Value * visit(And const * e) { return eval_and(e->left->accept(*this), e->right->accept(*this)); }
ast_t* eval_expression(env_t* env, ast_t* ast) { switch(ast->type) { /* valid */ case at_call: return eval_call(env,ast); case at_identifier: return get_ast_by_id(env, ast->data.id); case at_expression: { ast_t* result = NULL; ast_t* left = eval_expression(env, ast->data.expression.left); ast_t* right = eval_expression(env, ast->data.expression.right); inc_ref(left); inc_ref(right); switch(ast->data.expression.op) { case op_add: result = eval_add(env, left, right); break; case op_mul: result = eval_mul(env, left, right); break; case op_div: result = eval_div(env, left, right); break; case op_sub: result = eval_sub(env, left, right); break; case op_mod: result = eval_mod(env, left, right); break; case op_and: result = eval_and(env, left, right); break; case op_or: result = eval_or(env, left, right); break; case op_gt: result = eval_gt(env, left, right); break; case op_ge: result = eval_ge(env, left, right); break; case op_lt: result = eval_lt(env, left, right); break; case op_le: result = eval_le(env, left, right); break; case op_eq: result = eval_eq(env, left, right); break; case op_neq: result = eval_neq(env, left, right); break; case op_cat: result = eval_cat(env, left, right); break; case op_deref: { ast_t* index = eval_expression(env, right); if (index->type != at_integer) { // TODO: error -> index must be an integer! } else { switch(left->type) { case at_list: result = left->data.list.elements[index->data.i]; } } } } result->ref_count = 0; dec_ref(left); dec_ref(right); return result; } /* no need to evaluate */ case at_integer: case at_bool: case at_double: case at_string: case at_function: case at_statements: case at_list: return ast; /* invalid */ case at_assignment: case at_callargs: case at_conditional: case at_dowhile: case at_elif: case at_if: case at_params: case at_while: case at_builtin: error_expected(NULL,"expression",get_ast_type_name(ast->type)); } return NULL; /* this should never happen */ }
/////////////////////////////////////////////////////////////////// //eval //requires two arguments:exp & tail_context /////////////////////////////////////////////////////////////////// cellpoint eval(void) { if (is_true(is_self_evaluating(args_ref(1)))){ reg = args_ref(1); }else if (is_true(is_variable(args_ref(1)))){ reg = args_ref(1); args_push(current_env); args_push(reg); reg = lookup_var_val(); }else if (is_true(is_quoted(args_ref(1)))){ args_push(args_ref(1)); reg = quotation_text(); }else if (is_true(is_assignment(args_ref(1)))){ args_push(args_ref(1)); reg = eval_assignment(); }else if (is_true(is_definition(args_ref(1)))){ args_push(args_ref(1)); reg = eval_definition(); }else if (is_true(is_if(args_ref(1)))){ //eval if expression with the second argument (tail_context) reg = args_ref(1); args_push(args_ref(2)); args_push(reg); reg = eval_if(); }else if (is_true(is_lambda(args_ref(1)))){ args_push(args_ref(1)); reg = eval_lambda(); }else if (is_true(is_begin(args_ref(1)))){ args_push(args_ref(1)); reg = begin_actions(); //eval the actions of begin exp with the second argument (tail_context) args_push(args_ref(2)); args_push(reg); reg = eval_sequence(); }else if (is_true(is_cond(args_ref(1)))){ args_push(args_ref(1)); reg = cond_2_if(); //eval the exp with the second argument (tail_context) args_push(args_ref(2)); args_push(reg); reg = eval(); }else if (is_true(is_and(args_ref(1)))){ reg = args_ref(1); args_push(args_ref(2)); args_push(reg); reg = eval_and(); }else if (is_true(is_or(args_ref(1)))){ reg = args_ref(1); args_push(args_ref(2)); args_push(reg); reg = eval_or(); }else if (is_true(is_let(args_ref(1)))){ //convert let to combination args_push(args_ref(1)); reg = let_2_combination(); //evals the combination args_push(args_ref(2)); args_push(reg); reg = eval(); }else if (is_true(is_letstar(args_ref(1)))){ //convert let* to nested lets args_push(args_ref(1)); reg = letstar_2_nested_lets(); //evals the nested lets args_push(args_ref(2)); args_push(reg); reg = eval(); }else if (is_true(is_application(args_ref(1)))){ //computes operator args_push(args_ref(1)); reg = operator(); args_push(a_false); args_push(reg); reg = eval(); stack_push(&vars_stack, reg); //computes operands args_push(args_ref(1)); reg = operands(); args_push(reg); reg = list_of_values(); //calls apply with the second argument (tail_context) args_push(args_ref(2)); args_push(reg); args_push(stack_pop(&vars_stack)); reg = apply(); }else { printf("Unknown expression type -- EVAL\n"); error_handler(); } args_pop(2); return reg; }