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 */ }
Value * visit(Mod const * e) { return eval_mod(e->left->accept(*this), e->right->accept(*this)); }