Removed parsed arguments again because it was super slow, also

implemented positional aguments
This commit is contained in:
FelixBrendel
2018-10-17 00:27:59 +02:00
parent bd0e541d80
commit 42d64a0743
5 changed files with 117 additions and 156 deletions
+2
View File
@@ -5,3 +5,5 @@
*.user *.user
/vs/*/* /vs/*/*
/bin/slime /bin/slime
*.psess
*.vspx
+45 -45
View File
@@ -39,84 +39,84 @@ bool ast_node_equal(Ast_Node* n1, Ast_Node* n2) {
return false; return false;
} }
Ast_Node* built_in_equals(Parsed_Arguments* arguments) { Ast_Node* built_in_equals(Ast_Node* operands) {
for (int i = 0; i < arguments->positional_arguments->next_index-1; ++i) { if (operands->type == Ast_Node_Type_Nil)
if (!ast_node_equal( return create_ast_node_number(1);
arguments->positional_arguments->data[i],
arguments->positional_arguments->data[i+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(); return create_ast_node_nil();
operands = operands->value.pair->rest;
} }
return create_ast_node_number(1); 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; double sum = 0;
for (int i = 0; i < arguments->positional_arguments->next_index; ++i) { while (operands->type == Ast_Node_Type_Pair) {
try { 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); return create_ast_node_number(sum);
} }
Ast_Node* built_in_substract(Parsed_Arguments* arguments) { Ast_Node* built_in_substract(Ast_Node* operands) {
if (arguments->positional_arguments->next_index == 0)
return create_ast_node_number(0);
try { 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) { operands = operands->value.pair->rest;
return create_ast_node_number(-(*arguments->positional_arguments->data)->value.number->value); while (operands->type == Ast_Node_Type_Pair) {
}
// 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) {
try { 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); return create_ast_node_number(difference);
} }
Ast_Node* built_in_multiply(Parsed_Arguments* arguments) { Ast_Node* built_in_multiply(Ast_Node* operands) {
double product = 1;
for (int i = 0; i < arguments->positional_arguments->next_index; ++i) {
try { try {
assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number); assert_type(operands->value.pair->first, Ast_Node_Type_Number);
} }
product *= arguments->positional_arguments->data[i]->value.number->value; 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); return create_ast_node_number(product);
} }
Ast_Node* built_in_divide(Parsed_Arguments* arguments) { Ast_Node* built_in_divide(Ast_Node* operands) {
if (arguments->positional_arguments->next_index == 0)
return create_ast_node_number(1);
try { 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) { operands = operands->value.pair->rest;
return create_ast_node_number((*arguments->positional_arguments->data)->value.number->value); while (operands->type == Ast_Node_Type_Pair) {
}
// 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) {
try { 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);
} }
+7 -2
View File
@@ -10,12 +10,13 @@ struct Environment {
typedef struct Environment Environment; typedef struct Environment Environment;
Environment* create_empty_environment() {
Environment* create_child_environment(Environment* parent) {
Environment* env = new(Environment); Environment* env = new(Environment);
int start_capacity = 16; int start_capacity = 16;
env->parent = nullptr; env->parent = parent;
env->capacity = start_capacity; env->capacity = start_capacity;
env->next_index = 0; env->next_index = 0;
env->keys = (char**)malloc(start_capacity * sizeof(char*)); env->keys = (char**)malloc(start_capacity * sizeof(char*));
@@ -24,6 +25,10 @@ Environment* create_empty_environment() {
return env; return env;
} }
Environment* create_empty_environment() {
return create_child_environment(nullptr);
}
void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) { void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) {
// NOTE(Felix): right now we are simmply adding the symol at the // NOTE(Felix): right now we are simmply adding the symol at the
// back of the list without checking if it already exists but are // back of the list without checking if it already exists but are
+56 -105
View File
@@ -1,9 +1,32 @@
Ast_Node* eval_expr(Ast_Node* node, Environment* env);
Ast_Node* apply_arguments_to_function (Ast_Node* arguments, Ast_Node* function) { Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function, Environment* parent) {
printf("calling function, yey\n"); 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 This parses the argument specification of funcitons into their
@@ -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 Ast_Node* evaluated_arguments = create_ast_node_pair(nullptr, nullptr);
// just build the resulting list on the fly Ast_Node* evaluated_arguments_head = evaluated_arguments;
Ast_Node* evaluated_arguments = copy_list(arguments); Ast_Node* current_head = arguments;
Ast_Node* current_head = evaluated_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,9 +281,13 @@ 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;
if (node->value.pair->first->type != Ast_Node_Type_Built_In_Function) {
try { try {
operator = eval_expr(node->value.pair->first, env); 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;
int arguments_length; int arguments_length;
@@ -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) { */ 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) {
report_error(Error_Type_Wrong_Number_Of_Arguments); report_error(Error_Type_Wrong_Number_Of_Arguments);
} }
print(evaluated_arguments->value.pair->first);
char* sep = " "; printf("\n");
char* end = "\n"; return arguments->value.pair->first;
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));
} }
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;
} }
+3
View File
@@ -6,6 +6,9 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slime", "slime.vcxproj", "{1A47A3ED-871F-4CB4-875B-8CAA385B1771}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slime", "slime.vcxproj", "{1A47A3ED-871F-4CB4-875B-8CAA385B1771}"
EndProject EndProject
Global Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
Debug|x86 = Debug|x86 Debug|x86 = Debug|x86