|
|
@@ -1,10 +1,33 @@ |
|
|
|
|
|
Ast_Node* eval_expr(Ast_Node* node, Environment* env); |
|
|
|
|
|
|
|
|
|
|
|
Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, Environment* parent) { |
|
|
|
|
|
Environment* new_env = create_child_environment(parent); |
|
|
|
|
|
|
|
|
|
|
|
// positional arguments |
|
|
|
|
|
for (int i = 0; i < function->positional_arguments->next_index; ++i) { |
|
|
|
|
|
if (arguments->type == Ast_Node_Type_Pair) { |
|
|
|
|
|
define_symbol( |
|
|
|
|
|
create_ast_node_symbol(function->positional_arguments->identifiers[i]), |
|
|
|
|
|
arguments->value.pair->first, new_env); |
|
|
|
|
|
} else { |
|
|
|
|
|
// not enough arguments given |
|
|
|
|
|
create_error(Error_Type_Ill_Formed_Arguments, arguments); |
|
|
|
|
|
return nullptr; |
|
|
|
|
|
} |
|
|
|
|
|
arguments = arguments->value.pair->rest; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Ast_Node* apply_arguments_to_function (Ast_Node* arguments, Ast_Node* function) { |
|
|
|
|
|
printf("calling function, yey\n"); |
|
|
|
|
|
|
|
|
Ast_Node* result; |
|
|
|
|
|
|
|
|
return create_ast_node_nil(); |
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
result = eval_expr(function->body, new_env); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* (define type (lambda (e) (if (and (= (old-type e) :pair) (= (first e) :my-type)) :my-type (old-type e)))) */ |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
This parses the argument specification of funcitons into their |
|
|
This parses the argument specification of funcitons into their |
|
|
Function struct. It dois this by allocating new |
|
|
Function struct. It dois this by allocating new |
|
|
@@ -189,59 +212,8 @@ Ast_Node* copy_list(Ast_Node* node) { |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Ast_Node* eval_expr(Ast_Node* node, Environment* env); |
|
|
|
|
|
bool is_truthy (Ast_Node* expression, Environment* env); |
|
|
bool is_truthy (Ast_Node* expression, Environment* env); |
|
|
|
|
|
|
|
|
Parsed_Arguments* eval_and_parse_arguments(Ast_Node* arguments, Environment* env) { |
|
|
|
|
|
// TODO(Felix): if arguments is nil then maybe return a constant |
|
|
|
|
|
// Parsed_Arguments_nil? |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef enum { |
|
|
|
|
|
Expecting_Anything, |
|
|
|
|
|
Expecting_Keyword_Key, |
|
|
|
|
|
Expecting_Keyword_Value |
|
|
|
|
|
} Parse_State; |
|
|
|
|
|
|
|
|
|
|
|
Parse_State parse_state = Expecting_Anything; |
|
|
|
|
|
|
|
|
|
|
|
Parsed_Arguments* result = new(Parsed_Arguments); |
|
|
|
|
|
result->positional_arguments = create_Ast_Node_Array_List(16); |
|
|
|
|
|
result->keyword_keys = create_Ast_Node_Array_List(16); |
|
|
|
|
|
result->keyword_values = create_Ast_Node_Array_List(16); |
|
|
|
|
|
|
|
|
|
|
|
Ast_Node* current_head = copy_list(arguments); |
|
|
|
|
|
Ast_Node* current_evaluated_head; |
|
|
|
|
|
while (current_head->type == Ast_Node_Type_Pair) { |
|
|
|
|
|
try { |
|
|
|
|
|
current_evaluated_head = eval_expr(current_head->value.pair->first, env); |
|
|
|
|
|
} |
|
|
|
|
|
if (current_evaluated_head->type == Ast_Node_Type_Keyword) { |
|
|
|
|
|
if (parse_state == Expecting_Anything || Expecting_Keyword_Key) { |
|
|
|
|
|
append_to_Ast_Node_Array_List(result->keyword_keys, current_evaluated_head); |
|
|
|
|
|
parse_state = Expecting_Keyword_Value; |
|
|
|
|
|
} else { |
|
|
|
|
|
create_error(Error_Type_Ill_Formed_Arguments, arguments); |
|
|
|
|
|
return nullptr; |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
if (parse_state == Expecting_Anything) |
|
|
|
|
|
append_to_Ast_Node_Array_List(result->positional_arguments, current_evaluated_head); |
|
|
|
|
|
else if (parse_state == Expecting_Keyword_Value) { |
|
|
|
|
|
append_to_Ast_Node_Array_List(result->keyword_values, current_evaluated_head); |
|
|
|
|
|
parse_state = Expecting_Keyword_Key; |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
create_error(Error_Type_Ill_Formed_Arguments, arguments); |
|
|
|
|
|
return nullptr; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
current_head = current_head->value.pair->rest; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Ast_Node* extract_keyword_value(char* keyword, Parsed_Arguments* args) { |
|
|
Ast_Node* extract_keyword_value(char* keyword, Parsed_Arguments* args) { |
|
|
// NOTE(Felix): This will be a hashmap lookup later |
|
|
// NOTE(Felix): This will be a hashmap lookup later |
|
|
for (int i = 0; i < args->keyword_keys->next_index; ++i) { |
|
|
for (int i = 0; i < args->keyword_keys->next_index; ++i) { |
|
|
@@ -257,16 +229,27 @@ Ast_Node* eval_arguments(Ast_Node* arguments, Environment* env, int *out_argumen |
|
|
return arguments; |
|
|
return arguments; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// NOTE(Felix): Instead of copying and then mutating it, we could |
|
|
|
|
|
// just build the resulting list on the fly |
|
|
|
|
|
Ast_Node* evaluated_arguments = copy_list(arguments); |
|
|
|
|
|
Ast_Node* current_head = evaluated_arguments; |
|
|
|
|
|
|
|
|
Ast_Node* evaluated_arguments = create_ast_node_pair(nullptr, nullptr); |
|
|
|
|
|
Ast_Node* evaluated_arguments_head = evaluated_arguments; |
|
|
|
|
|
Ast_Node* current_head = arguments; |
|
|
while (current_head->type == Ast_Node_Type_Pair) { |
|
|
while (current_head->type == Ast_Node_Type_Pair) { |
|
|
try { |
|
|
try { |
|
|
current_head->value.pair->first = |
|
|
|
|
|
|
|
|
evaluated_arguments_head->value.pair->first = |
|
|
eval_expr(current_head->value.pair->first, env); |
|
|
eval_expr(current_head->value.pair->first, env); |
|
|
} |
|
|
} |
|
|
current_head = current_head->value.pair->rest; |
|
|
current_head = current_head->value.pair->rest; |
|
|
|
|
|
|
|
|
|
|
|
if (current_head->type == Ast_Node_Type_Pair) { |
|
|
|
|
|
evaluated_arguments_head->value.pair->rest = create_ast_node_pair(nullptr, nullptr); |
|
|
|
|
|
evaluated_arguments_head = evaluated_arguments_head->value.pair->rest; |
|
|
|
|
|
} |
|
|
|
|
|
else if (current_head->type == Ast_Node_Type_Nil) { |
|
|
|
|
|
evaluated_arguments_head->value.pair->rest = current_head; |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
create_error(Error_Type_Ill_Formed_Arguments, arguments); |
|
|
|
|
|
return nullptr; |
|
|
|
|
|
} |
|
|
++(*out_arguments_length); |
|
|
++(*out_arguments_length); |
|
|
} |
|
|
} |
|
|
return evaluated_arguments; |
|
|
return evaluated_arguments; |
|
|
@@ -298,8 +281,12 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
return node; |
|
|
return node; |
|
|
case Ast_Node_Type_Pair: { |
|
|
case Ast_Node_Type_Pair: { |
|
|
Ast_Node* operator; |
|
|
Ast_Node* operator; |
|
|
try { |
|
|
|
|
|
operator = eval_expr(node->value.pair->first, env); |
|
|
|
|
|
|
|
|
if (node->value.pair->first->type != Ast_Node_Type_Built_In_Function) { |
|
|
|
|
|
try { |
|
|
|
|
|
operator = eval_expr(node->value.pair->first, env); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
operator = node->value.pair->first; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Ast_Node* arguments = node->value.pair->rest; |
|
|
Ast_Node* arguments = node->value.pair->rest; |
|
|
@@ -458,27 +445,25 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
// to evaluate the arguments; eval_arguments will also tell |
|
|
// to evaluate the arguments; eval_arguments will also tell |
|
|
// us the arguments_length. |
|
|
// us the arguments_length. |
|
|
Ast_Node* evaluated_arguments; |
|
|
Ast_Node* evaluated_arguments; |
|
|
Parsed_Arguments* evaluated_and_parsed_arguments; |
|
|
|
|
|
try { |
|
|
try { |
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
evaluated_arguments = eval_arguments(arguments, env, &arguments_length); |
|
|
evaluated_and_parsed_arguments = eval_and_parse_arguments(arguments, env); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
switch (operator->value.built_in_function->type) { |
|
|
switch (operator->value.built_in_function->type) { |
|
|
case Built_In_Addition: { |
|
|
case Built_In_Addition: { |
|
|
return built_in_add(evaluated_and_parsed_arguments); |
|
|
|
|
|
|
|
|
return built_in_add(evaluated_arguments); |
|
|
} |
|
|
} |
|
|
case Built_In_Subtraction: { |
|
|
case Built_In_Subtraction: { |
|
|
return built_in_substract(evaluated_and_parsed_arguments); |
|
|
|
|
|
|
|
|
return built_in_substract(evaluated_arguments); |
|
|
} |
|
|
} |
|
|
case Built_In_Multiplication: { |
|
|
case Built_In_Multiplication: { |
|
|
return built_in_multiply(evaluated_and_parsed_arguments); |
|
|
|
|
|
|
|
|
return built_in_multiply(evaluated_arguments); |
|
|
} |
|
|
} |
|
|
case Built_In_Division: { |
|
|
case Built_In_Division: { |
|
|
return built_in_divide(evaluated_and_parsed_arguments); |
|
|
|
|
|
|
|
|
return built_in_divide(evaluated_arguments); |
|
|
} |
|
|
} |
|
|
case Built_In_Equal: { |
|
|
case Built_In_Equal: { |
|
|
return built_in_equals(evaluated_and_parsed_arguments); |
|
|
|
|
|
|
|
|
return built_in_equals(evaluated_arguments); |
|
|
} |
|
|
} |
|
|
case Built_In_Pair: { |
|
|
case Built_In_Pair: { |
|
|
if (arguments_length != 2) { |
|
|
if (arguments_length != 2) { |
|
|
@@ -536,46 +521,12 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
return evaluated_arguments; |
|
|
return evaluated_arguments; |
|
|
} |
|
|
} |
|
|
case Built_In_Print: { |
|
|
case Built_In_Print: { |
|
|
/* if (arguments_length != 1) { */ |
|
|
|
|
|
/* report_error(Error_Type_Wrong_Number_Of_Arguments); */ |
|
|
|
|
|
/* } */ |
|
|
|
|
|
/* print(evaluated_arguments->value.pair->first); */ |
|
|
|
|
|
/* printf("\n"); */ |
|
|
|
|
|
/* return arguments->value.pair->first; */ |
|
|
|
|
|
|
|
|
|
|
|
if (evaluated_and_parsed_arguments->positional_arguments->next_index == 0) { |
|
|
|
|
|
|
|
|
if (arguments_length != 1) { |
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
report_error(Error_Type_Wrong_Number_Of_Arguments); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
char* sep = " "; |
|
|
|
|
|
char* end = "\n"; |
|
|
|
|
|
|
|
|
|
|
|
Ast_Node* temp = extract_keyword_value("sep", evaluated_and_parsed_arguments); |
|
|
|
|
|
if (temp) { |
|
|
|
|
|
try { |
|
|
|
|
|
assert_type(temp, Ast_Node_Type_String); |
|
|
|
|
|
} |
|
|
|
|
|
sep = temp->value.string->value; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
temp = extract_keyword_value("end", evaluated_and_parsed_arguments); |
|
|
|
|
|
if (temp) { |
|
|
|
|
|
try { |
|
|
|
|
|
assert_type(temp, Ast_Node_Type_String); |
|
|
|
|
|
} |
|
|
|
|
|
end = temp->value.string->value; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
print(*evaluated_and_parsed_arguments->positional_arguments->data); |
|
|
|
|
|
for (int i = 1; i < evaluated_and_parsed_arguments->positional_arguments->next_index; ++i) { |
|
|
|
|
|
printf("%s", sep); |
|
|
|
|
|
print(*(evaluated_and_parsed_arguments->positional_arguments->data+i)); |
|
|
|
|
|
} |
|
|
|
|
|
printf("%s", end); |
|
|
|
|
|
|
|
|
|
|
|
// return last positional argument |
|
|
|
|
|
return *(evaluated_and_parsed_arguments->positional_arguments->data+ |
|
|
|
|
|
(evaluated_and_parsed_arguments->positional_arguments->next_index-1)); |
|
|
|
|
|
|
|
|
print(evaluated_arguments->value.pair->first); |
|
|
|
|
|
printf("\n"); |
|
|
|
|
|
return arguments->value.pair->first; |
|
|
} |
|
|
} |
|
|
case Built_In_Read: { |
|
|
case Built_In_Read: { |
|
|
if (arguments_length > 1) { |
|
|
if (arguments_length > 1) { |
|
|
@@ -635,7 +586,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { |
|
|
if (operator->type == Ast_Node_Type_Function) { |
|
|
if (operator->type == Ast_Node_Type_Function) { |
|
|
Ast_Node* result; |
|
|
Ast_Node* result; |
|
|
try { |
|
|
try { |
|
|
result = apply_arguments_to_function(arguments, operator); |
|
|
|
|
|
|
|
|
result = apply_arguments_to_function(arguments, operator->value.function, env); |
|
|
} |
|
|
} |
|
|
return result; |
|
|
return result; |
|
|
} |
|
|
} |
|
|
|