/* Ast_Node* apply_to_lambda () {} */ /* Ast_Node* apply_to_built_in (Ast_Node* function, Ast_Node* arguments) { */ /* } */ Ast_Node* eval_expr(Ast_Node* node, Environment* env); int is_truthy (Ast_Node* expression, Environment* env); void eval_operands(Ast_Node* operands, Environment* env) { while (!error) { if (operands->type == Ast_Node_Type_Cons_Cell) { operands->value.cons_cell->first = eval_expr(operands->value.cons_cell->first, env); operands = operands->value.cons_cell->rest; } else { return; } } // if we reach here we got an error log_error("An error occurred while evaluating operands to a function:"); } Ast_Node* eval_expr(Ast_Node* node, Environment* env) { #define report_error(_message) \ error = new(Error); \ error->message = _message; \ error->location = node; \ return NULL Ast_Node* ret = new(Ast_Node); switch (node->type) { case Ast_Node_Type_Nil: ret->type = Ast_Node_Type_Nil; return ret; case Ast_Node_Type_Symbol: return lookup_symbol(node->value.symbol, env); case Ast_Node_Type_Number: case Ast_Node_Type_String: return node; case Ast_Node_Type_Cons_Cell: { Ast_Node* operator = eval_expr(node->value.cons_cell->first, env); Ast_Node* operands = node->value.cons_cell->rest; // check for built ins functions if (operator->type == Ast_Node_Type_Built_In_Function) { char* operator_name = operator->value.built_in_function->identifier; if (string_equal("quote", operator_name)) { return node->value.cons_cell->rest; } else if (string_equal("+", operator_name)) { eval_operands(operands, env); return built_in_add(operands); } else if (string_equal("-", operator_name)) { eval_operands(operands, env); return built_in_substract(operands); } else if (string_equal("*", operator_name)) { eval_operands(operands, env); return built_in_multiply(operands); } else if (string_equal("/", operator_name)) { eval_operands(operands, env); return built_in_divide(operands); } else if (string_equal("if", operator_name)) { if (Ast_Node_Type_Cons_Cell != operands->value.cons_cell->rest->type || Ast_Node_Type_Cons_Cell != operands->value.cons_cell->rest->value.cons_cell->rest->type || Ast_Node_Type_Nil != operands->value.cons_cell->rest->value.cons_cell->rest->value.cons_cell->rest->type) { report_error("Ill formed if statement"); } Ast_Node* then_part = operands->value.cons_cell->rest; Ast_Node* else_part = then_part->value.cons_cell->rest; if (is_truthy(operands->value.cons_cell->first, env)) return eval_expr(then_part->value.cons_cell->first, env); else return eval_expr(else_part->value.cons_cell->first, env); } else if (string_equal("not", operator_name)) { } else if (string_equal("and", operator_name)) { } else if (string_equal("or", operator_name)) { } else { report_error("The operator is not yet implemented"); } } // assume it's lambda function and evaluate the operands in // place eval_operands(operands, env); } default: report_error("Unknown error"); } #undef report_error } int is_truthy (Ast_Node* expression, Environment* env) { Ast_Node* result = eval_expr(expression, env); switch (result->type) { case Ast_Node_Type_Nil: return 0; case Ast_Node_Type_Number: return result->value.number->value != 0; default: return 1; } }