开发编程语言(七):运行execute.c

随笔 2016-10-27

起步

初步的可运行的已经在github上了:https://github.com/OriginUnion/origin,发现有bug可以留言,供学习而已。

上一篇已经介绍了语法分析并且创建了我们所需要的数据结构,运行函数从main.cORG_interpret(interpreter);开始。

入口运行函数

运行函数的结构如下:

void ORG_interpret(ORG_Interpreter *inter) {
    inter->execute_storage = MEM_open_storage(0);
    org_add_std_fp(inter);
    org_execute_statement_list(inter, NULL, inter->statement_list);
}

第一句创建一个存储器,第二句注册全局变量,STDIN STDOUT STDERR将他们与c语言的标准输入输出进行关联;第三句中,将解析的语句存在inter->statement_list,进行逐句执行。

void org_add_std_fp(ORG_Interpreter *inter) {
    ORG_Value fp_value;

    fp_value.type = ORG_NATIVE_POINTER_VALUE;
    fp_value.u.native_pointer.info = &st_native_lib_info;

    fp_value.u.native_pointer.pointer = stdin;
    ORG_add_global_variable(inter, "STDIN", &fp_value);

    fp_value.u.native_pointer.pointer = stdout;
    ORG_add_global_variable(inter, "STDOUT", &fp_value);

    fp_value.u.native_pointer.pointer = stderr;
    ORG_add_global_variable(inter, "STDERR", &fp_value);
}

执行函数

StatementResult org_execute_statement_list(ORG_Interpreter *inter, LocalEnvironment *env, StatementList *list) {
    StatementList *pos;
    StatementResult result;
    result.type = NORMAL_STATEMENT_RESULT;

    for (pos = list; pos; pos = pos->next) {
        result = execute_statement(inter, env, pos->statement);
        if (result.type != NORMAL_STATEMENT_RESULT) {
            return result;
        }
    }

    return result;
}

按照列表的顺序,调用execute_statement()函数。第二个参数LocalEnvironment保存了当前运行的函数的局部变量。

static StatementResult execute_statement(ORG_Interpreter *inter, LocalEnvironment *env, Statement *statement) {
    StatementResult result;
    result.type = NORMAL_STATEMENT_RESULT;
    switch (statement->type) {
        case EXPRESSION_STATEMENT:
            result = execute_expression_statement(inter, env, statement);
            break;
        case WHILE_STATEMENT:
            result = execute_while_statement(inter, env, statement);
            break;
        case FOR_STATEMENT:
            result = execute_for_statement(inter, env, statement);
            break;
        //....
    }
    return result;
}

根据不同的Statement类型执行不同的代码,采用switch处理,区分是算术表达式还是循环语句还是if语句等。然后再执行对应语句的执行函数,以下for语句为例子:

static StatementResult execute_for_statement(ORG_Interpreter *inter, LocalEnvironment *env, Statement *statement) {
    StatementResult result;
    ORG_Value cond;
    result.type = NORMAL_STATEMENT_RESULT;
    if (statement->u.for_s.init) {
        org_eval_expression(inter, env, statement->u.for_s.init);
    }
    for (;;) {
        //for的判断循环条件 
        if (statement->u.for_s.condition) {
            cond = org_eval_expression(inter, env, statement->u.for_s.condition);
            if (cond.type != ORG_BOOLEAN_VALUE) {
                //runtime error
                exit(1);
            }
            if (!cond.u.boolean_value) {
                break;
            }
        }

        result = org_execute_statement_list(inter, env, statement->u.for_s.block->statement_list);
        if (result.type == RETURN_STATEMENT_RESULT) {
            break;
        } else if (result.type == BREAK_STATEMENT_RESULT) {
            result.type = NORMAL_STATEMENT_RESULT;
            break;
        }

        if (statement->u.for_s.post) {
            org_eval_expression(inter, env, statement->u.for_s.post);
        }
    }
    return result;
}

for循环的形式为for(expression; expression; expression){block}的形式。其中循环体block中又是由语句列表组成,所以又调用org_execute_statement_list();上面的代码甚至处理break, continue, return的情况,跳出循环或返回上层循环。

表达式

其实最需要处理的是运行表达式,哪怕只有一条语句也可以用org_execute_statement_list执行,最后的问题都会归结到表达式的运行,execute_expression_statement(),表达式分为:字符串,函数表达式,二元表达式,布尔表达式等,表达式之间又可以嵌套func(4+8) || (a == 8 -3 && b != "s")总体这是一个布尔表达式,但包含的东西很多,下一节讲如何处理,eval.c


本文由 hongweipeng 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

赏个馒头吧