Use the parse arguments
This commit is contained in:
+2
-9
@@ -1,13 +1,6 @@
|
|||||||
void assert_type (Ast_Node* node, Ast_Node_Type type) {
|
void assert_type (Ast_Node* node, Ast_Node_Type type) {
|
||||||
|
if (!node)
|
||||||
|
create_error(Error_Type_Unknown_Error, node);
|
||||||
if (node->type == type) return;
|
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);
|
create_error(Error_Type_Type_Missmatch, node);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,6 +134,19 @@ struct Ast_Node {
|
|||||||
// was forward declarated
|
// was forward declarated
|
||||||
typedef struct Ast_Node Ast_Node;
|
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* create_ast_node_nil() {
|
||||||
Ast_Node* node = new(Ast_Node);
|
Ast_Node* node = new(Ast_Node);
|
||||||
|
|||||||
+46
-46
@@ -39,84 +39,84 @@ bool ast_node_equal(Ast_Node* n1, Ast_Node* n2) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Node* built_in_equals(Ast_Node* operands) {
|
Ast_Node* built_in_equals(Parsed_Arguments* arguments) {
|
||||||
if (operands->type == Ast_Node_Type_Nil)
|
for (int i = 0; i < arguments->positional_arguments->next_index-1; ++i) {
|
||||||
return create_ast_node_number(1);
|
if (!ast_node_equal(
|
||||||
|
arguments->positional_arguments->data[i],
|
||||||
Ast_Node* first = operands->value.pair->first;
|
arguments->positional_arguments->data[i+1]))
|
||||||
|
|
||||||
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(Ast_Node* operands) {
|
Ast_Node* built_in_add(Parsed_Arguments* arguments) {
|
||||||
double sum = 0;
|
double sum = 0;
|
||||||
while (operands->type == Ast_Node_Type_Pair) {
|
for (int i = 0; i < arguments->positional_arguments->next_index; ++i) {
|
||||||
try {
|
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;
|
sum += arguments->positional_arguments->data[i]->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(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 {
|
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;
|
if (arguments->positional_arguments->next_index == 1) {
|
||||||
while (operands->type == Ast_Node_Type_Pair) {
|
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 {
|
try {
|
||||||
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
|
assert_type(arguments->positional_arguments->data[i], 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(Ast_Node* operands) {
|
Ast_Node* built_in_multiply(Parsed_Arguments* arguments) {
|
||||||
try {
|
double product = 1;
|
||||||
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
|
for (int i = 0; i < arguments->positional_arguments->next_index; ++i) {
|
||||||
}
|
|
||||||
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(operands->value.pair->first, Ast_Node_Type_Number);
|
assert_type(arguments->positional_arguments->data[i], 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(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 {
|
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;
|
if (arguments->positional_arguments->next_index == 1) {
|
||||||
while (operands->type == Ast_Node_Type_Pair) {
|
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 {
|
try {
|
||||||
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
|
assert_type(arguments->positional_arguments->data[i], Ast_Node_Type_Number);
|
||||||
}
|
}
|
||||||
|
difference /= arguments->positional_arguments->data[i]->value.number->value;
|
||||||
quotient /= operands->value.pair->first->value.number->value;
|
|
||||||
operands = operands->value.pair->rest;
|
|
||||||
}
|
}
|
||||||
return create_ast_node_number(quotient);
|
|
||||||
|
return create_ast_node_number(difference);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ typedef enum {
|
|||||||
Error_Type_Ill_Formed_List,
|
Error_Type_Ill_Formed_List,
|
||||||
Error_Type_Ill_Formed_Arguments,
|
Error_Type_Ill_Formed_Arguments,
|
||||||
Error_Type_Wrong_Number_Of_Arguments,
|
Error_Type_Wrong_Number_Of_Arguments,
|
||||||
|
Error_Type_Unknown_Keyword_Argument,
|
||||||
Error_Type_Type_Missmatch,
|
Error_Type_Type_Missmatch,
|
||||||
Error_Type_Symbol_Not_Defined,
|
Error_Type_Symbol_Not_Defined,
|
||||||
Error_Type_Not_A_Function,
|
Error_Type_Not_A_Function,
|
||||||
@@ -39,6 +40,7 @@ char* Error_Type_to_string(Error_Type type) {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case Error_Type_Ill_Formed_List: return "Evaluation-error: Ill formed list";
|
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_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_Not_A_Function: return "Evaluation-error: Not a function";
|
||||||
case Error_Type_Symbol_Not_Defined: return "Evaluation-error: Symbol not defined";
|
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";
|
case Error_Type_Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments";
|
||||||
|
|||||||
+54
-17
@@ -56,14 +56,6 @@ Ast_Node* copy_list(Ast_Node* node) {
|
|||||||
return result;
|
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) {
|
Parsed_Arguments* eval_and_parse_arguments(Ast_Node* arguments, Environment* env) {
|
||||||
// TODO(Felix): if arguments is nil then maybe return a constant
|
// TODO(Felix): if arguments is nil then maybe return a constant
|
||||||
// Parsed_Arguments_nil?
|
// Parsed_Arguments_nil?
|
||||||
@@ -114,6 +106,15 @@ Parsed_Arguments* eval_and_parse_arguments(Ast_Node* arguments, Environment* env
|
|||||||
return result;
|
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) {
|
Ast_Node* eval_arguments(Ast_Node* arguments, Environment* env, int *out_arguments_length) {
|
||||||
*out_arguments_length = 0;
|
*out_arguments_length = 0;
|
||||||
if (arguments->type == Ast_Node_Type_Nil) {
|
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
|
// 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_arguments);
|
return built_in_add(evaluated_and_parsed_arguments);
|
||||||
}
|
}
|
||||||
case Built_In_Subtraction: {
|
case Built_In_Subtraction: {
|
||||||
return built_in_substract(evaluated_arguments);
|
return built_in_substract(evaluated_and_parsed_arguments);
|
||||||
}
|
}
|
||||||
case Built_In_Multiplication: {
|
case Built_In_Multiplication: {
|
||||||
return built_in_multiply(evaluated_arguments);
|
return built_in_multiply(evaluated_and_parsed_arguments);
|
||||||
}
|
}
|
||||||
case Built_In_Division: {
|
case Built_In_Division: {
|
||||||
return built_in_divide(evaluated_arguments);
|
return built_in_divide(evaluated_and_parsed_arguments);
|
||||||
}
|
}
|
||||||
case Built_In_Equal: {
|
case Built_In_Equal: {
|
||||||
return built_in_equals(evaluated_arguments);
|
return built_in_equals(evaluated_and_parsed_arguments);
|
||||||
}
|
}
|
||||||
case Built_In_Pair: {
|
case Built_In_Pair: {
|
||||||
if (arguments_length != 2) {
|
if (arguments_length != 2) {
|
||||||
@@ -355,12 +358,46 @@ 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);
|
|
||||||
printf("\n");
|
char* sep = " ";
|
||||||
return arguments->value.pair->first;
|
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: {
|
case Built_In_Read: {
|
||||||
if (arguments_length > 1) {
|
if (arguments_length > 1) {
|
||||||
|
|||||||
+18
@@ -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
@@ -15,6 +15,7 @@
|
|||||||
#include "./built_ins.c"
|
#include "./built_ins.c"
|
||||||
#include "./eval.c"
|
#include "./eval.c"
|
||||||
#include "./testing.c"
|
#include "./testing.c"
|
||||||
|
#include "./init.c"
|
||||||
|
|
||||||
int interprete_file (char* file_content) {
|
int interprete_file (char* file_content) {
|
||||||
Ast_Node_Array_List* program = parse_program(file_content);
|
Ast_Node_Array_List* program = parse_program(file_content);
|
||||||
@@ -62,8 +63,9 @@ int interprete_stdin () {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main (int argc, char *argv[]) {
|
int main (int argc, char *argv[]) {
|
||||||
|
init();
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
char* file_content = read_entire_file(argv[1]);
|
char* file_content = read_entire_file(argv[1]);
|
||||||
if (file_content) {
|
if (file_content) {
|
||||||
|
|||||||
@@ -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* create_Ast_Node_Array_List() {
|
||||||
Ast_Node_Array_List* ret = new (Ast_Node_Array_List);
|
Ast_Node_Array_List* ret = new (Ast_Node_Array_List);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user