Removed parsed arguments again because it was super slow, also
implemented positional aguments
This commit is contained in:
+47
-47
@@ -39,84 +39,84 @@ bool ast_node_equal(Ast_Node* n1, Ast_Node* n2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Ast_Node* built_in_equals(Parsed_Arguments* arguments) {
|
||||
for (int i = 0; i < arguments->positional_arguments->next_index-1; ++i) {
|
||||
if (!ast_node_equal(
|
||||
arguments->positional_arguments->data[i],
|
||||
arguments->positional_arguments->data[i+1]))
|
||||
Ast_Node* built_in_equals(Ast_Node* operands) {
|
||||
if (operands->type == Ast_Node_Type_Nil)
|
||||
return create_ast_node_number(1);
|
||||
|
||||
Ast_Node* first = operands->value.pair->first;
|
||||
|
||||
while (operands->type == Ast_Node_Type_Pair) {
|
||||
if (!ast_node_equal(operands->value.pair->first, first))
|
||||
return create_ast_node_nil();
|
||||
operands = operands->value.pair->rest;
|
||||
}
|
||||
|
||||
return create_ast_node_number(1);
|
||||
}
|
||||
|
||||
Ast_Node* built_in_add(Parsed_Arguments* arguments) {
|
||||
Ast_Node* built_in_add(Ast_Node* operands) {
|
||||
double sum = 0;
|
||||
for (int i = 0; i < arguments->positional_arguments->next_index; ++i) {
|
||||
while (operands->type == Ast_Node_Type_Pair) {
|
||||
try {
|
||||
assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number);
|
||||
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
|
||||
}
|
||||
sum += arguments->positional_arguments->data[i]->value.number->value;
|
||||
sum += operands->value.pair->first->value.number->value;
|
||||
operands = operands->value.pair->rest;
|
||||
}
|
||||
|
||||
return create_ast_node_number(sum);
|
||||
}
|
||||
|
||||
Ast_Node* built_in_substract(Parsed_Arguments* arguments) {
|
||||
if (arguments->positional_arguments->next_index == 0)
|
||||
return create_ast_node_number(0);
|
||||
|
||||
Ast_Node* built_in_substract(Ast_Node* operands) {
|
||||
try {
|
||||
assert_type(*arguments->positional_arguments->data, Ast_Node_Type_Number);
|
||||
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
|
||||
}
|
||||
double difference = operands->value.pair->first->value.number->value;
|
||||
|
||||
if (arguments->positional_arguments->next_index == 1) {
|
||||
return create_ast_node_number(-(*arguments->positional_arguments->data)->value.number->value);
|
||||
}
|
||||
|
||||
// okay we have at least 2 arguments
|
||||
double difference = (*arguments->positional_arguments->data)->value.number->value;
|
||||
for (int i = 1; i < arguments->positional_arguments->next_index; ++i) {
|
||||
operands = operands->value.pair->rest;
|
||||
while (operands->type == Ast_Node_Type_Pair) {
|
||||
try {
|
||||
assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number);
|
||||
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
|
||||
}
|
||||
difference -= arguments->positional_arguments->data[i]->value.number->value;
|
||||
}
|
||||
|
||||
difference -= operands->value.pair->first->value.number->value;
|
||||
operands = operands->value.pair->rest;
|
||||
}
|
||||
return create_ast_node_number(difference);
|
||||
}
|
||||
|
||||
Ast_Node* built_in_multiply(Parsed_Arguments* arguments) {
|
||||
double product = 1;
|
||||
for (int i = 0; i < arguments->positional_arguments->next_index; ++i) {
|
||||
try {
|
||||
assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number);
|
||||
}
|
||||
product *= arguments->positional_arguments->data[i]->value.number->value;
|
||||
Ast_Node* built_in_multiply(Ast_Node* operands) {
|
||||
try {
|
||||
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
|
||||
}
|
||||
double product = operands->value.pair->first->value.number->value;
|
||||
|
||||
operands = operands->value.pair->rest;
|
||||
while (operands->type == Ast_Node_Type_Pair) {
|
||||
try {
|
||||
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
|
||||
}
|
||||
|
||||
product *= operands->value.pair->first->value.number->value;
|
||||
operands = operands->value.pair->rest;
|
||||
}
|
||||
return create_ast_node_number(product);
|
||||
}
|
||||
|
||||
Ast_Node* built_in_divide(Parsed_Arguments* arguments) {
|
||||
if (arguments->positional_arguments->next_index == 0)
|
||||
return create_ast_node_number(1);
|
||||
|
||||
Ast_Node* built_in_divide(Ast_Node* operands) {
|
||||
try {
|
||||
assert_type(*arguments->positional_arguments->data, Ast_Node_Type_Number);
|
||||
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
|
||||
}
|
||||
double quotient = operands->value.pair->first->value.number->value;
|
||||
|
||||
if (arguments->positional_arguments->next_index == 1) {
|
||||
return create_ast_node_number((*arguments->positional_arguments->data)->value.number->value);
|
||||
}
|
||||
|
||||
// okay we have at least 2 arguments
|
||||
double difference = (*arguments->positional_arguments->data)->value.number->value;
|
||||
for (int i = 1; i < arguments->positional_arguments->next_index; ++i) {
|
||||
operands = operands->value.pair->rest;
|
||||
while (operands->type == Ast_Node_Type_Pair) {
|
||||
try {
|
||||
assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number);
|
||||
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
|
||||
}
|
||||
difference /= arguments->positional_arguments->data[i]->value.number->value;
|
||||
}
|
||||
|
||||
return create_ast_node_number(difference);
|
||||
quotient /= operands->value.pair->first->value.number->value;
|
||||
operands = operands->value.pair->rest;
|
||||
}
|
||||
return create_ast_node_number(quotient);
|
||||
}
|
||||
|
||||
@@ -10,12 +10,13 @@ struct Environment {
|
||||
|
||||
typedef struct Environment Environment;
|
||||
|
||||
Environment* create_empty_environment() {
|
||||
|
||||
Environment* create_child_environment(Environment* parent) {
|
||||
Environment* env = new(Environment);
|
||||
|
||||
int start_capacity = 16;
|
||||
|
||||
env->parent = nullptr;
|
||||
env->parent = parent;
|
||||
env->capacity = start_capacity;
|
||||
env->next_index = 0;
|
||||
env->keys = (char**)malloc(start_capacity * sizeof(char*));
|
||||
@@ -24,6 +25,10 @@ Environment* create_empty_environment() {
|
||||
return env;
|
||||
}
|
||||
|
||||
Environment* create_empty_environment() {
|
||||
return create_child_environment(nullptr);
|
||||
}
|
||||
|
||||
void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) {
|
||||
// NOTE(Felix): right now we are simmply adding the symol at the
|
||||
// back of the list without checking if it already exists but are
|
||||
|
||||
+58
-107
@@ -1,10 +1,33 @@
|
||||
Ast_Node* eval_expr(Ast_Node* node, Environment* env);
|
||||
|
||||
Ast_Node* apply_arguments_to_function (Ast_Node* arguments, Ast_Node* function) {
|
||||
printf("calling function, yey\n");
|
||||
Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, Environment* parent) {
|
||||
Environment* new_env = create_child_environment(parent);
|
||||
|
||||
return create_ast_node_nil();
|
||||
// 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* result;
|
||||
|
||||
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
|
||||
Function struct. It dois this by allocating new
|
||||
@@ -189,59 +212,8 @@ Ast_Node* copy_list(Ast_Node* node) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Ast_Node* eval_expr(Ast_Node* node, 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) {
|
||||
// NOTE(Felix): This will be a hashmap lookup later
|
||||
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;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
try {
|
||||
current_head->value.pair->first =
|
||||
evaluated_arguments_head->value.pair->first =
|
||||
eval_expr(current_head->value.pair->first, env);
|
||||
}
|
||||
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);
|
||||
}
|
||||
return evaluated_arguments;
|
||||
@@ -298,8 +281,12 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
||||
return node;
|
||||
case Ast_Node_Type_Pair: {
|
||||
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;
|
||||
@@ -458,27 +445,25 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
||||
// to evaluate the arguments; eval_arguments will also tell
|
||||
// us the arguments_length.
|
||||
Ast_Node* evaluated_arguments;
|
||||
Parsed_Arguments* evaluated_and_parsed_arguments;
|
||||
try {
|
||||
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) {
|
||||
case Built_In_Addition: {
|
||||
return built_in_add(evaluated_and_parsed_arguments);
|
||||
return built_in_add(evaluated_arguments);
|
||||
}
|
||||
case Built_In_Subtraction: {
|
||||
return built_in_substract(evaluated_and_parsed_arguments);
|
||||
return built_in_substract(evaluated_arguments);
|
||||
}
|
||||
case Built_In_Multiplication: {
|
||||
return built_in_multiply(evaluated_and_parsed_arguments);
|
||||
return built_in_multiply(evaluated_arguments);
|
||||
}
|
||||
case Built_In_Division: {
|
||||
return built_in_divide(evaluated_and_parsed_arguments);
|
||||
return built_in_divide(evaluated_arguments);
|
||||
}
|
||||
case Built_In_Equal: {
|
||||
return built_in_equals(evaluated_and_parsed_arguments);
|
||||
return built_in_equals(evaluated_arguments);
|
||||
}
|
||||
case Built_In_Pair: {
|
||||
if (arguments_length != 2) {
|
||||
@@ -536,46 +521,12 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
||||
return evaluated_arguments;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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: {
|
||||
if (arguments_length > 1) {
|
||||
@@ -635,7 +586,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
|
||||
if (operator->type == Ast_Node_Type_Function) {
|
||||
Ast_Node* result;
|
||||
try {
|
||||
result = apply_arguments_to_function(arguments, operator);
|
||||
result = apply_arguments_to_function(arguments, operator->value.function, env);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user