|
|
|
@@ -56,46 +56,84 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
|
case Ast_Node_Type_String: |
|
|
|
return node; |
|
|
|
case Ast_Node_Type_Pair: { |
|
|
|
Ast_Node* operator = eval_expr(node->value.pair->first, env); |
|
|
|
if (error) return nullptr; |
|
|
|
Ast_Node* operator; |
|
|
|
try { |
|
|
|
operator = eval_expr(node->value.pair->first, env); |
|
|
|
} |
|
|
|
|
|
|
|
Ast_Node* operands = node->value.pair->rest; |
|
|
|
int operands_length; |
|
|
|
|
|
|
|
|
|
|
|
// 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)) { |
|
|
|
int operands_length = list_length(operands); |
|
|
|
operands_length = list_length(operands); |
|
|
|
if (operands_length != 1) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
return operands->value.pair->first; |
|
|
|
} else if (string_equal("eval", operator_name)) { |
|
|
|
int operands_length = list_length(operands); |
|
|
|
try { |
|
|
|
operands_length = list_length(operands); |
|
|
|
} |
|
|
|
if (operands_length != 1) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
if (error) return nullptr; |
|
|
|
|
|
|
|
return eval_expr(operands->value.pair->first, env); |
|
|
|
} else if (string_equal("prog", operator_name)) { |
|
|
|
if (operands->type == Ast_Node_Type_Nil) |
|
|
|
return operands; |
|
|
|
while (!error) { |
|
|
|
try { |
|
|
|
operands->value.pair->first = eval_expr(operands->value.pair->first, env); |
|
|
|
} |
|
|
|
|
|
|
|
if (operands->value.pair->rest->type == Ast_Node_Type_Pair) |
|
|
|
operands = operands->value.pair->rest; |
|
|
|
else { |
|
|
|
if (operands->value.pair->rest->type != Ast_Node_Type_Nil) |
|
|
|
report_error(Error_Type_Ill_Formed_List); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
return operands->value.pair->first; |
|
|
|
} else if (string_equal("list", operator_name)) { |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
return operands; |
|
|
|
} else if (string_equal("=", operator_name)) { |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
return built_in_equals(operands); |
|
|
|
} else if (string_equal("+", operator_name)) { |
|
|
|
eval_operands(operands, env); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
return built_in_add(operands); |
|
|
|
} else if (string_equal("-", operator_name)) { |
|
|
|
eval_operands(operands, env); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
return built_in_substract(operands); |
|
|
|
} else if (string_equal("*", operator_name)) { |
|
|
|
eval_operands(operands, env); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
return built_in_multiply(operands); |
|
|
|
} else if (string_equal("/", operator_name)) { |
|
|
|
eval_operands(operands, env); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
return built_in_divide(operands); |
|
|
|
} else if (string_equal("define", operator_name)) { |
|
|
|
int operands_length = list_length(operands); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
operands_length = list_length(operands); |
|
|
|
} |
|
|
|
if (operands_length != 2) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
@@ -110,14 +148,40 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
|
define_symbol(symbol, value, env); |
|
|
|
|
|
|
|
return value; |
|
|
|
} else if (string_equal("type", operator_name)) { |
|
|
|
try { |
|
|
|
operands_length = list_length(operands); |
|
|
|
} |
|
|
|
if (operands_length != 1) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
Ast_Node_Type type = operands->value.pair->first->type; |
|
|
|
switch (type) { |
|
|
|
case Ast_Node_Type_Built_In_Function: return create_ast_node_keyword("built-in-function"); |
|
|
|
case Ast_Node_Type_Function: return create_ast_node_keyword("dynamic-function"); |
|
|
|
case Ast_Node_Type_Keyword: return create_ast_node_keyword("keyword"); |
|
|
|
case Ast_Node_Type_Nil: return create_ast_node_keyword("nil"); |
|
|
|
case Ast_Node_Type_Number: return create_ast_node_keyword("number"); |
|
|
|
case Ast_Node_Type_Pair: return create_ast_node_keyword("pair"); |
|
|
|
case Ast_Node_Type_String: return create_ast_node_keyword("string"); |
|
|
|
case Ast_Node_Type_Symbol: return create_ast_node_keyword("symbol"); |
|
|
|
} |
|
|
|
|
|
|
|
} else if (string_equal("exit", operator_name)) { |
|
|
|
int operands_length = list_length(operands); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
operands_length = list_length(operands); |
|
|
|
} |
|
|
|
if (operands_length > 1) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
|
|
|
|
if (operands_length == 1) { |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
Ast_Node* error_code = operands->value.pair->first; |
|
|
|
if (error_code->type != Ast_Node_Type_Number) |
|
|
|
report_error(Error_Type_Type_Missmatch); |
|
|
|
@@ -127,26 +191,30 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
|
exit(0); |
|
|
|
|
|
|
|
} else if (string_equal("print", operator_name)) { |
|
|
|
int operands_length = list_length(operands); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
operands_length = list_length(operands); |
|
|
|
} |
|
|
|
if (operands_length != 1) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
eval_operands(operands, env); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
print(operands->value.pair->first); |
|
|
|
printf("\n"); |
|
|
|
return operands->value.pair->first; |
|
|
|
} else if (string_equal("read", operator_name)) { |
|
|
|
int operands_length = list_length(operands); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
operands_length = list_length(operands); |
|
|
|
} |
|
|
|
if (operands_length > 1) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
|
|
|
|
if (operands_length == 1) { |
|
|
|
eval_operands(operands, env); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
Ast_Node* prompt = operands->value.pair->first; |
|
|
|
if (prompt->type == Ast_Node_Type_String) |
|
|
|
printf("%s", prompt->value.string->value); |
|
|
|
@@ -155,9 +223,54 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
|
} |
|
|
|
char* line = read_line(); |
|
|
|
return create_ast_node_string(line, (int)strlen(line)); |
|
|
|
} else if (string_equal("pair", operator_name)) { |
|
|
|
try { |
|
|
|
operands_length = list_length(operands); |
|
|
|
} |
|
|
|
if (operands_length != 2) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
|
|
|
|
return create_ast_node_pair(operands->value.pair->first, operands->value.pair->rest->value.pair->first); |
|
|
|
} else if (string_equal("first", operator_name)) { |
|
|
|
try { |
|
|
|
operands_length = list_length(operands); |
|
|
|
} |
|
|
|
if (operands_length != 1) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
if (operands->value.pair->first->type == Ast_Node_Type_Nil) |
|
|
|
return create_ast_node_nil(); |
|
|
|
if (operands->value.pair->first->type != Ast_Node_Type_Pair) |
|
|
|
report_error(Error_Type_Type_Missmatch); |
|
|
|
|
|
|
|
return operands->value.pair->first->value.pair->first; |
|
|
|
} else if (string_equal("rest", operator_name)) { |
|
|
|
try { |
|
|
|
operands_length = list_length(operands); |
|
|
|
} |
|
|
|
if (operands_length != 1) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
try { |
|
|
|
eval_operands(operands, env); |
|
|
|
} |
|
|
|
if (operands->value.pair->first->type == Ast_Node_Type_Nil) |
|
|
|
return create_ast_node_nil(); |
|
|
|
if (operands->value.pair->first->type != Ast_Node_Type_Pair) |
|
|
|
report_error(Error_Type_Type_Missmatch); |
|
|
|
|
|
|
|
return operands->value.pair->first->value.pair->rest; |
|
|
|
} else if (string_equal("if", operator_name)) { |
|
|
|
int operands_length = list_length(operands); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
operands_length = list_length(operands); |
|
|
|
} |
|
|
|
if (operands_length != 2 && operands_length != 3) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
@@ -166,8 +279,10 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
|
Ast_Node* then_part = operands->value.pair->rest; |
|
|
|
Ast_Node* else_part = then_part->value.pair->rest; |
|
|
|
|
|
|
|
bool truthy = is_truthy(condition, env); |
|
|
|
if (error) return nullptr; |
|
|
|
bool truthy; |
|
|
|
try { |
|
|
|
truthy = is_truthy(condition, env); |
|
|
|
} |
|
|
|
if (truthy) |
|
|
|
return eval_expr(then_part->value.pair->first, env); |
|
|
|
else if (operands_length == 3) |
|
|
|
@@ -180,8 +295,9 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
|
if (operands->type != Ast_Node_Type_Pair) { |
|
|
|
report_error(Error_Type_Ill_Formed_List); |
|
|
|
} |
|
|
|
result &= is_truthy(operands->value.pair->first, env); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
result &= is_truthy(operands->value.pair->first, env); |
|
|
|
} |
|
|
|
operands = operands->value.pair->rest; |
|
|
|
|
|
|
|
if (!result) return create_ast_node_nil(); |
|
|
|
@@ -195,8 +311,9 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
|
if (operands->type != Ast_Node_Type_Pair) { |
|
|
|
report_error(Error_Type_Ill_Formed_List); |
|
|
|
} |
|
|
|
result |= is_truthy(operands->value.pair->first, env); |
|
|
|
if (error) return nullptr; |
|
|
|
try { |
|
|
|
result |= is_truthy(operands->value.pair->first, env); |
|
|
|
} |
|
|
|
operands = operands->value.pair->rest; |
|
|
|
|
|
|
|
if (result) return create_ast_node_number(1);; |
|
|
|
@@ -204,13 +321,16 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
|
|
|
|
|
return create_ast_node_nil(); |
|
|
|
} else if (string_equal("not", operator_name)) { |
|
|
|
if (list_length(operands) != 1) { |
|
|
|
if (!error) |
|
|
|
create_error(Error_Type_Wrong_Number_Of_Arguments, operands); |
|
|
|
return nullptr; |
|
|
|
try { |
|
|
|
operands_length = list_length(operands); |
|
|
|
} |
|
|
|
if (operands_length != 1) { |
|
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
|
} |
|
|
|
bool truthy; |
|
|
|
try { |
|
|
|
truthy = is_truthy(operands->value.pair->first, env); |
|
|
|
} |
|
|
|
bool truthy = is_truthy(operands->value.pair->first, env); |
|
|
|
if (error) return nullptr; |
|
|
|
if (truthy) |
|
|
|
return create_ast_node_nil(); |
|
|
|
return create_ast_node_number(1); |
|
|
|
|