Procházet zdrojové kódy

Removed parsed arguments again because it was super slow, also

implemented positional aguments
master
FelixBrendel před 7 roky
rodič
revize
42d64a0743
5 změnil soubory, kde provedl 116 přidání a 155 odebrání
  1. +2
    -0
      .gitignore
  2. +46
    -46
      src/built_ins.c
  3. +7
    -2
      src/env.c
  4. +58
    -107
      src/eval.c
  5. +3
    -0
      vs/slime.sln

+ 2
- 0
.gitignore Zobrazit soubor

@@ -5,3 +5,5 @@
*.user *.user
/vs/*/* /vs/*/*
/bin/slime /bin/slime
*.psess
*.vspx

+ 46
- 46
src/built_ins.c Zobrazit soubor

@@ -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) {
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(); 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) {
if (arguments->positional_arguments->next_index == 0)
return create_ast_node_number(0);

Ast_Node* built_in_substract(Ast_Node* operands) {
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) {
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 { 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) {
double product = 1;
for (int i = 0; i < arguments->positional_arguments->next_index; ++i) {
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 { 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;
}


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) {
if (arguments->positional_arguments->next_index == 0)
return create_ast_node_number(1);

Ast_Node* built_in_divide(Ast_Node* operands) {
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) {
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 { 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
src/env.c Zobrazit soubor

@@ -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


+ 58
- 107
src/eval.c Zobrazit soubor

@@ -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;
} }


+ 3
- 0
vs/slime.sln Zobrazit soubor

@@ -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


Načítá se…
Zrušit
Uložit