Просмотр исходного кода

Removed parsed arguments again because it was super slow, also

implemented positional aguments
master
FelixBrendel 7 лет назад
Родитель
Сommit
42d64a0743
5 измененных файлов: 116 добавлений и 155 удалений
  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 Просмотреть файл

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

+ 46
- 46
src/built_ins.c Просмотреть файл

@@ -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) {
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(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);
}

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

+ 7
- 2
src/env.c Просмотреть файл

@@ -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
src/eval.c Просмотреть файл

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


+ 3
- 0
vs/slime.sln Просмотреть файл

@@ -6,6 +6,9 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slime", "slime.vcxproj", "{1A47A3ED-871F-4CB4-875B-8CAA385B1771}"
EndProject
Global
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86


Загрузка…
Отмена
Сохранить