Quellcode durchsuchen

Use the parse arguments

master
FelixBrendel vor 7 Jahren
Ursprung
Commit
2006e3b45c
8 geänderte Dateien mit 139 neuen und 80 gelöschten Zeilen
  1. +2
    -9
      src/assert.c
  2. +13
    -0
      src/ast.c
  3. +46
    -46
      src/built_ins.c
  4. +2
    -0
      src/error.c
  5. +55
    -18
      src/eval.c
  6. +18
    -0
      src/init.c
  7. +3
    -1
      src/main.c
  8. +0
    -6
      src/parse.c

+ 2
- 9
src/assert.c Datei anzeigen

@@ -1,13 +1,6 @@
void assert_type (Ast_Node* node, Ast_Node_Type type) {
if (!node)
create_error(Error_Type_Unknown_Error, node);
if (node->type == type) return;

/* char *wanted, *got, *message; */
/* wanted = Ast_Node_Type_to_string(type); */
/* got = Ast_Node_Type_to_string(node->type); */
/* asprintf(&message, "Type assertion failed:\n\t" */
/* "Wanted: %s\n\t" */
/* "Got : %s\n", wanted, got); */
/* panic(message); */

create_error(Error_Type_Type_Missmatch, node);
}

+ 13
- 0
src/ast.c Datei anzeigen

@@ -134,6 +134,19 @@ struct Ast_Node {
// was forward declarated
typedef struct Ast_Node Ast_Node;

typedef struct {
Ast_Node** data;
int length;
int next_index;
} Ast_Node_Array_List;

typedef struct {
Ast_Node_Array_List* positional_arguments;
// TODO(Felix): Really use hashmap (keyword[sting] ->
// value[Ast_Node*]) here
Ast_Node_Array_List* keyword_keys;
Ast_Node_Array_List* keyword_values;
} Parsed_Arguments;

Ast_Node* create_ast_node_nil() {
Ast_Node* node = new(Ast_Node);


+ 46
- 46
src/built_ins.c Datei anzeigen

@@ -39,84 +39,84 @@ bool ast_node_equal(Ast_Node* n1, Ast_Node* n2) {
return false;
}

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))
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]))
return create_ast_node_nil();
operands = operands->value.pair->rest;
}

return create_ast_node_number(1);
}

Ast_Node* built_in_add(Ast_Node* operands) {
Ast_Node* built_in_add(Parsed_Arguments* arguments) {
double sum = 0;
while (operands->type == Ast_Node_Type_Pair) {
for (int i = 0; i < arguments->positional_arguments->next_index; ++i) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number);
}
sum += operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
sum += arguments->positional_arguments->data[i]->value.number->value;
}

return create_ast_node_number(sum);
}

Ast_Node* built_in_substract(Ast_Node* operands) {
Ast_Node* built_in_substract(Parsed_Arguments* arguments) {
if (arguments->positional_arguments->next_index == 0)
return create_ast_node_number(0);

try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
assert_type(*arguments->positional_arguments->data, Ast_Node_Type_Number);
}
double difference = operands->value.pair->first->value.number->value;

operands = operands->value.pair->rest;
while (operands->type == Ast_Node_Type_Pair) {
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) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number);
}

difference -= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
difference -= arguments->positional_arguments->data[i]->value.number->value;
}

return create_ast_node_number(difference);
}

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) {
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(operands->value.pair->first, Ast_Node_Type_Number);
assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number);
}

product *= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
product *= arguments->positional_arguments->data[i]->value.number->value;
}

return create_ast_node_number(product);
}

Ast_Node* built_in_divide(Ast_Node* operands) {
Ast_Node* built_in_divide(Parsed_Arguments* arguments) {
if (arguments->positional_arguments->next_index == 0)
return create_ast_node_number(1);

try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
assert_type(*arguments->positional_arguments->data, Ast_Node_Type_Number);
}
double quotient = operands->value.pair->first->value.number->value;

operands = operands->value.pair->rest;
while (operands->type == Ast_Node_Type_Pair) {
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) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number);
}

quotient /= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;
difference /= arguments->positional_arguments->data[i]->value.number->value;
}
return create_ast_node_number(quotient);

return create_ast_node_number(difference);
}

+ 2
- 0
src/error.c Datei anzeigen

@@ -2,6 +2,7 @@ typedef enum {
Error_Type_Ill_Formed_List,
Error_Type_Ill_Formed_Arguments,
Error_Type_Wrong_Number_Of_Arguments,
Error_Type_Unknown_Keyword_Argument,
Error_Type_Type_Missmatch,
Error_Type_Symbol_Not_Defined,
Error_Type_Not_A_Function,
@@ -39,6 +40,7 @@ char* Error_Type_to_string(Error_Type type) {
switch (type) {
case Error_Type_Ill_Formed_List: return "Evaluation-error: Ill formed list";
case Error_Type_Ill_Formed_Arguments: return "Evaluation-error: Ill formed arguments";
case Error_Type_Unknown_Keyword_Argument: return "Evaluation-error: Unknown keyword argument";
case Error_Type_Not_A_Function: return "Evaluation-error: Not a function";
case Error_Type_Symbol_Not_Defined: return "Evaluation-error: Symbol not defined";
case Error_Type_Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments";


+ 55
- 18
src/eval.c Datei anzeigen

@@ -56,14 +56,6 @@ Ast_Node* copy_list(Ast_Node* node) {
return result;
}

typedef struct {
Ast_Node_Array_List* positional_arguments;
// TODO(Felix): Really use hashmap (keyword[sting] ->
// value[Ast_Node*]) here
Ast_Node_Array_List* keyword_keys;
Ast_Node_Array_List* keyword_values;
} Parsed_Arguments;

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?
@@ -114,6 +106,15 @@ Parsed_Arguments* eval_and_parse_arguments(Ast_Node* arguments, Environment* env
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) {
if (string_equal(args->keyword_keys->data[i]->value.keyword->identifier, keyword))
return args->keyword_values->data[i];
}
return nullptr;
}

Ast_Node* eval_arguments(Ast_Node* arguments, Environment* env, int *out_arguments_length) {
*out_arguments_length = 0;
if (arguments->type == Ast_Node_Type_Nil) {
@@ -279,25 +280,27 @@ 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_arguments);
return built_in_add(evaluated_and_parsed_arguments);
}
case Built_In_Subtraction: {
return built_in_substract(evaluated_arguments);
return built_in_substract(evaluated_and_parsed_arguments);
}
case Built_In_Multiplication: {
return built_in_multiply(evaluated_arguments);
return built_in_multiply(evaluated_and_parsed_arguments);
}
case Built_In_Division: {
return built_in_divide(evaluated_arguments);
return built_in_divide(evaluated_and_parsed_arguments);
}
case Built_In_Equal: {
return built_in_equals(evaluated_arguments);
return built_in_equals(evaluated_and_parsed_arguments);
}
case Built_In_Pair: {
if (arguments_length != 2) {
@@ -355,12 +358,46 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
return evaluated_arguments;
}
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);
}
print(evaluated_arguments->value.pair->first);
printf("\n");
return arguments->value.pair->first;

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));
}
case Built_In_Read: {
if (arguments_length > 1) {
@@ -415,7 +452,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {

}

// assume it's lambda function and evaluate the arguments
// assume it's lambda function and evaluate the arguments
arguments = eval_arguments(arguments, env, &arguments_length);
}



+ 18
- 0
src/init.c Datei anzeigen

@@ -0,0 +1,18 @@
// for colored console output
#ifdef _WIN32
#include <windows.h>
#pragma comment(lib, "Kernel32.lib")
#endif

void init () {
// On Windows: manually enable colored console output
#ifdef _WIN32
SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE),
ENABLE_PROCESSED_OUTPUT |
ENABLE_WRAP_AT_EOL_OUTPUT |
ENABLE_VIRTUAL_TERMINAL_PROCESSING);
#endif

// TODO(Felix): Init the constants here (Bulit-in function
// ast_nodes, nil, ..more?)
}

+ 3
- 1
src/main.c Datei anzeigen

@@ -15,6 +15,7 @@
#include "./built_ins.c"
#include "./eval.c"
#include "./testing.c"
#include "./init.c"

int interprete_file (char* file_content) {
Ast_Node_Array_List* program = parse_program(file_content);
@@ -62,8 +63,9 @@ int interprete_stdin () {
return 0;
}


int main (int argc, char *argv[]) {
init();

if (argc > 1) {
char* file_content = read_entire_file(argv[1]);
if (file_content) {


+ 0
- 6
src/parse.c Datei anzeigen

@@ -1,9 +1,3 @@
typedef struct {
Ast_Node** data;
int length;
int next_index;
} Ast_Node_Array_List;

Ast_Node_Array_List* create_Ast_Node_Array_List() {
Ast_Node_Array_List* ret = new (Ast_Node_Array_List);



Laden…
Abbrechen
Speichern