Removed parsed arguments again because it was super slow, also
implemented positional aguments
This commit is contained in:
@@ -5,3 +5,5 @@
|
|||||||
*.user
|
*.user
|
||||||
/vs/*/*
|
/vs/*/*
|
||||||
/bin/slime
|
/bin/slime
|
||||||
|
*.psess
|
||||||
|
*.vspx
|
||||||
|
|||||||
+47
-47
@@ -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;
|
try {
|
||||||
for (int i = 0; i < arguments->positional_arguments->next_index; ++i) {
|
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
|
||||||
try {
|
|
||||||
assert_type(arguments->positional_arguments->data[i], 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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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) {
|
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
|
||||||
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
|
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,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 {
|
if (node->value.pair->first->type != Ast_Node_Type_Built_In_Function) {
|
||||||
operator = eval_expr(node->value.pair->first, env);
|
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) { */
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user