more things!

This commit is contained in:
FelixBrendel
2018-10-09 00:06:28 +02:00
parent 905500ab98
commit 1ea4cf5213
8 changed files with 313 additions and 73 deletions
+2
View File
@@ -8,6 +8,8 @@ set binDir=bin
mkdir quickbuild 2>nul mkdir quickbuild 2>nul
pushd quickbuild pushd quickbuild
taskkill /F /IM %exeName% > NUL 2> NUL
echo ---------- Compiling ---------- echo ---------- Compiling ----------
call timecmd cl ../src/main.c /Fe%exeName% /W3 /TC /nologo /EHsc /Z7 /link /incremental /debug:fastlink call timecmd cl ../src/main.c /Fe%exeName% /W3 /TC /nologo /EHsc /Z7 /link /incremental /debug:fastlink
+9 -7
View File
@@ -1,11 +1,13 @@
void assert_type (Ast_Node* node, Ast_Node_Type type) { void assert_type (Ast_Node* node, Ast_Node_Type type) {
if (node->type == type) return; if (node->type == type) return;
char *wanted, *got, *message; /* char *wanted, *got, *message; */
wanted = Ast_Node_Type_to_string(type); /* wanted = Ast_Node_Type_to_string(type); */
got = Ast_Node_Type_to_string(node->type); /* got = Ast_Node_Type_to_string(node->type); */
asprintf(&message, "Type assertion failed:\n\t" /* asprintf(&message, "Type assertion failed:\n\t" */
"Wanted: %s\n\t" /* "Wanted: %s\n\t" */
"Got : %s\n", wanted, got); /* "Got : %s\n", wanted, got); */
panic(message); /* panic(message); */
create_error(Error_Type_Type_Missmatch, node);
} }
+71
View File
@@ -1,7 +1,66 @@
bool ast_node_equal(Ast_Node* n1, Ast_Node* n2) {
if (n1 == n2)
return true;
if (n1->type != n2->type)
return false;
switch (n1->type) {
case Ast_Node_Type_Built_In_Function:
return string_equal(
n1->value.built_in_function->identifier,
n2->value.built_in_function->identifier);
case Ast_Node_Type_Function:
// if they have the same pointer, true is
// returned a few lines above
return false;
case Ast_Node_Type_Keyword:
return string_equal(
n1->value.keyword->identifier,
n2->value.keyword->identifier);
case Ast_Node_Type_Nil:
return true;
case Ast_Node_Type_Number:
return
n1->value.number->value ==
n2->value.number->value;
case Ast_Node_Type_Pair:
create_error(Error_Type_Not_Yet_Implemented, n1);
return false;
case Ast_Node_Type_String:
return string_equal(
n1->value.string->value,
n2->value.string->value);
case Ast_Node_Type_Symbol:
return string_equal(
n1->value.symbol->identifier,
n2->value.symbol->identifier);
}
// we should never reach here
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))
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(Ast_Node* operands) {
double sum = 0; double sum = 0;
while (operands->type == Ast_Node_Type_Pair) { while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number); assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
sum += operands->value.pair->first->value.number->value; sum += operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest; operands = operands->value.pair->rest;
} }
@@ -10,12 +69,16 @@ Ast_Node* built_in_add(Ast_Node* operands) {
} }
Ast_Node* built_in_substract(Ast_Node* operands) { Ast_Node* built_in_substract(Ast_Node* operands) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number); assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
double difference = operands->value.pair->first->value.number->value; double difference = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest; operands = operands->value.pair->rest;
while (operands->type == Ast_Node_Type_Pair) { while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number); assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
difference -= operands->value.pair->first->value.number->value; difference -= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest; operands = operands->value.pair->rest;
@@ -24,12 +87,16 @@ Ast_Node* built_in_substract(Ast_Node* operands) {
} }
Ast_Node* built_in_multiply(Ast_Node* operands) { Ast_Node* built_in_multiply(Ast_Node* operands) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number); assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
double product = operands->value.pair->first->value.number->value; double product = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest; operands = operands->value.pair->rest;
while (operands->type == Ast_Node_Type_Pair) { while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number); assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
product *= operands->value.pair->first->value.number->value; product *= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest; operands = operands->value.pair->rest;
@@ -38,12 +105,16 @@ Ast_Node* built_in_multiply(Ast_Node* operands) {
} }
Ast_Node* built_in_divide(Ast_Node* operands) { Ast_Node* built_in_divide(Ast_Node* operands) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number); assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
double quotient = operands->value.pair->first->value.number->value; double quotient = operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest; operands = operands->value.pair->rest;
while (operands->type == Ast_Node_Type_Pair) { while (operands->type == Ast_Node_Type_Pair) {
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number); assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
quotient /= operands->value.pair->first->value.number->value; quotient /= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest; operands = operands->value.pair->rest;
+5 -5
View File
@@ -12,7 +12,7 @@ typedef struct Environment Environment;
Environment* create_empty_environment() { Environment* create_empty_environment() {
Environment* env = new(Environment); Environment* env = new(Environment);
int start_capacity = 1; int start_capacity = 16;
env->parent = nullptr; env->parent = nullptr;
env->capacity = start_capacity; env->capacity = start_capacity;
@@ -56,15 +56,15 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
// Conditional stuff // Conditional stuff
"if", "and", "or", "not", "if", "and", "or", "not",
// Cons stuff // Cons stuff
"first", "rest", "pair", "pair", "first", "rest",
// rest // rest
"load", "define", "load", "define",
"lambda", "progn", "lambda", "progn",
"eval", "quote", "eval", "quote", "prog", "list",
"print", "read", "print", "read",
"help", "exit" "info", "type", "exit"
}; };
int built_in_count = 26; int built_in_count = sizeof(built_in_names) / sizeof(char*);
for (int i = 0; i < built_in_count; ++i) { for (int i = 0; i < built_in_count; ++i) {
if (string_equal(built_in_names[i], sym->identifier)) { if (string_equal(built_in_names[i], sym->identifier)) {
+152 -32
View File
@@ -56,46 +56,84 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
case Ast_Node_Type_String: case Ast_Node_Type_String:
return node; return node;
case Ast_Node_Type_Pair: { case Ast_Node_Type_Pair: {
Ast_Node* operator = eval_expr(node->value.pair->first, env); Ast_Node* operator;
if (error) return nullptr; try {
operator = eval_expr(node->value.pair->first, env);
}
Ast_Node* operands = node->value.pair->rest; Ast_Node* operands = node->value.pair->rest;
int operands_length;
// check for built ins functions // check for built ins functions
if (operator->type == Ast_Node_Type_Built_In_Function) { if (operator->type == Ast_Node_Type_Built_In_Function) {
char* operator_name = operator->value.built_in_function->identifier; char* operator_name = operator->value.built_in_function->identifier;
if (string_equal("quote", operator_name)) { if (string_equal("quote", operator_name)) {
int operands_length = list_length(operands); operands_length = list_length(operands);
if (operands_length != 1) { if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments); report_error(Error_Type_Wrong_Number_Of_Arguments);
} }
return operands->value.pair->first; return operands->value.pair->first;
} else if (string_equal("eval", operator_name)) { } else if (string_equal("eval", operator_name)) {
int operands_length = list_length(operands); try {
operands_length = list_length(operands);
}
if (operands_length != 1) { if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments); report_error(Error_Type_Wrong_Number_Of_Arguments);
} }
if (error) return nullptr;
return eval_expr(operands->value.pair->first, env); return eval_expr(operands->value.pair->first, env);
} else if (string_equal("+", operator_name)) { } else if (string_equal("prog", operator_name)) {
if (operands->type == Ast_Node_Type_Nil)
return operands;
while (!error) {
try {
operands->value.pair->first = eval_expr(operands->value.pair->first, env);
}
if (operands->value.pair->rest->type == Ast_Node_Type_Pair)
operands = operands->value.pair->rest;
else {
if (operands->value.pair->rest->type != Ast_Node_Type_Nil)
report_error(Error_Type_Ill_Formed_List);
break;
}
}
return operands->value.pair->first;
} else if (string_equal("list", operator_name)) {
try {
eval_operands(operands, env); eval_operands(operands, env);
if (error) return nullptr; }
return operands;
} else if (string_equal("=", operator_name)) {
try {
eval_operands(operands, env);
}
return built_in_equals(operands);
} else if (string_equal("+", operator_name)) {
try {
eval_operands(operands, env);
}
return built_in_add(operands); return built_in_add(operands);
} else if (string_equal("-", operator_name)) { } else if (string_equal("-", operator_name)) {
try {
eval_operands(operands, env); eval_operands(operands, env);
if (error) return nullptr; }
return built_in_substract(operands); return built_in_substract(operands);
} else if (string_equal("*", operator_name)) { } else if (string_equal("*", operator_name)) {
try {
eval_operands(operands, env); eval_operands(operands, env);
if (error) return nullptr; }
return built_in_multiply(operands); return built_in_multiply(operands);
} else if (string_equal("/", operator_name)) { } else if (string_equal("/", operator_name)) {
try {
eval_operands(operands, env); eval_operands(operands, env);
if (error) return nullptr; }
return built_in_divide(operands); return built_in_divide(operands);
} else if (string_equal("define", operator_name)) { } else if (string_equal("define", operator_name)) {
int operands_length = list_length(operands); try {
if (error) return nullptr; operands_length = list_length(operands);
}
if (operands_length != 2) { if (operands_length != 2) {
report_error(Error_Type_Wrong_Number_Of_Arguments); report_error(Error_Type_Wrong_Number_Of_Arguments);
} }
@@ -110,14 +148,40 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
define_symbol(symbol, value, env); define_symbol(symbol, value, env);
return value; return value;
} else if (string_equal("type", operator_name)) {
try {
operands_length = list_length(operands);
}
if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
try {
eval_operands(operands, env);
}
Ast_Node_Type type = operands->value.pair->first->type;
switch (type) {
case Ast_Node_Type_Built_In_Function: return create_ast_node_keyword("built-in-function");
case Ast_Node_Type_Function: return create_ast_node_keyword("dynamic-function");
case Ast_Node_Type_Keyword: return create_ast_node_keyword("keyword");
case Ast_Node_Type_Nil: return create_ast_node_keyword("nil");
case Ast_Node_Type_Number: return create_ast_node_keyword("number");
case Ast_Node_Type_Pair: return create_ast_node_keyword("pair");
case Ast_Node_Type_String: return create_ast_node_keyword("string");
case Ast_Node_Type_Symbol: return create_ast_node_keyword("symbol");
}
} else if (string_equal("exit", operator_name)) { } else if (string_equal("exit", operator_name)) {
int operands_length = list_length(operands); try {
if (error) return nullptr; operands_length = list_length(operands);
}
if (operands_length > 1) { if (operands_length > 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments); report_error(Error_Type_Wrong_Number_Of_Arguments);
} }
if (operands_length == 1) { if (operands_length == 1) {
try {
eval_operands(operands, env);
}
Ast_Node* error_code = operands->value.pair->first; Ast_Node* error_code = operands->value.pair->first;
if (error_code->type != Ast_Node_Type_Number) if (error_code->type != Ast_Node_Type_Number)
report_error(Error_Type_Type_Missmatch); report_error(Error_Type_Type_Missmatch);
@@ -127,26 +191,30 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
exit(0); exit(0);
} else if (string_equal("print", operator_name)) { } else if (string_equal("print", operator_name)) {
int operands_length = list_length(operands); try {
if (error) return nullptr; operands_length = list_length(operands);
}
if (operands_length != 1) { if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments); report_error(Error_Type_Wrong_Number_Of_Arguments);
} }
try {
eval_operands(operands, env); eval_operands(operands, env);
if (error) return nullptr; }
print(operands->value.pair->first); print(operands->value.pair->first);
printf("\n"); printf("\n");
return operands->value.pair->first; return operands->value.pair->first;
} else if (string_equal("read", operator_name)) { } else if (string_equal("read", operator_name)) {
int operands_length = list_length(operands); try {
if (error) return nullptr; operands_length = list_length(operands);
}
if (operands_length > 1) { if (operands_length > 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments); report_error(Error_Type_Wrong_Number_Of_Arguments);
} }
if (operands_length == 1) { if (operands_length == 1) {
try {
eval_operands(operands, env); eval_operands(operands, env);
if (error) return nullptr; }
Ast_Node* prompt = operands->value.pair->first; Ast_Node* prompt = operands->value.pair->first;
if (prompt->type == Ast_Node_Type_String) if (prompt->type == Ast_Node_Type_String)
printf("%s", prompt->value.string->value); printf("%s", prompt->value.string->value);
@@ -155,9 +223,54 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
} }
char* line = read_line(); char* line = read_line();
return create_ast_node_string(line, (int)strlen(line)); return create_ast_node_string(line, (int)strlen(line));
} else if (string_equal("pair", operator_name)) {
try {
operands_length = list_length(operands);
}
if (operands_length != 2) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
try {
eval_operands(operands, env);
}
return create_ast_node_pair(operands->value.pair->first, operands->value.pair->rest->value.pair->first);
} else if (string_equal("first", operator_name)) {
try {
operands_length = list_length(operands);
}
if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
try {
eval_operands(operands, env);
}
if (operands->value.pair->first->type == Ast_Node_Type_Nil)
return create_ast_node_nil();
if (operands->value.pair->first->type != Ast_Node_Type_Pair)
report_error(Error_Type_Type_Missmatch);
return operands->value.pair->first->value.pair->first;
} else if (string_equal("rest", operator_name)) {
try {
operands_length = list_length(operands);
}
if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
try {
eval_operands(operands, env);
}
if (operands->value.pair->first->type == Ast_Node_Type_Nil)
return create_ast_node_nil();
if (operands->value.pair->first->type != Ast_Node_Type_Pair)
report_error(Error_Type_Type_Missmatch);
return operands->value.pair->first->value.pair->rest;
} else if (string_equal("if", operator_name)) { } else if (string_equal("if", operator_name)) {
int operands_length = list_length(operands); try {
if (error) return nullptr; operands_length = list_length(operands);
}
if (operands_length != 2 && operands_length != 3) { if (operands_length != 2 && operands_length != 3) {
report_error(Error_Type_Wrong_Number_Of_Arguments); report_error(Error_Type_Wrong_Number_Of_Arguments);
} }
@@ -166,8 +279,10 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
Ast_Node* then_part = operands->value.pair->rest; Ast_Node* then_part = operands->value.pair->rest;
Ast_Node* else_part = then_part->value.pair->rest; Ast_Node* else_part = then_part->value.pair->rest;
bool truthy = is_truthy(condition, env); bool truthy;
if (error) return nullptr; try {
truthy = is_truthy(condition, env);
}
if (truthy) if (truthy)
return eval_expr(then_part->value.pair->first, env); return eval_expr(then_part->value.pair->first, env);
else if (operands_length == 3) else if (operands_length == 3)
@@ -180,8 +295,9 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
if (operands->type != Ast_Node_Type_Pair) { if (operands->type != Ast_Node_Type_Pair) {
report_error(Error_Type_Ill_Formed_List); report_error(Error_Type_Ill_Formed_List);
} }
try {
result &= is_truthy(operands->value.pair->first, env); result &= is_truthy(operands->value.pair->first, env);
if (error) return nullptr; }
operands = operands->value.pair->rest; operands = operands->value.pair->rest;
if (!result) return create_ast_node_nil(); if (!result) return create_ast_node_nil();
@@ -195,8 +311,9 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
if (operands->type != Ast_Node_Type_Pair) { if (operands->type != Ast_Node_Type_Pair) {
report_error(Error_Type_Ill_Formed_List); report_error(Error_Type_Ill_Formed_List);
} }
try {
result |= is_truthy(operands->value.pair->first, env); result |= is_truthy(operands->value.pair->first, env);
if (error) return nullptr; }
operands = operands->value.pair->rest; operands = operands->value.pair->rest;
if (result) return create_ast_node_number(1);; if (result) return create_ast_node_number(1);;
@@ -204,13 +321,16 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
return create_ast_node_nil(); return create_ast_node_nil();
} else if (string_equal("not", operator_name)) { } else if (string_equal("not", operator_name)) {
if (list_length(operands) != 1) { try {
if (!error) operands_length = list_length(operands);
create_error(Error_Type_Wrong_Number_Of_Arguments, operands); }
return nullptr; if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
bool truthy;
try {
truthy = is_truthy(operands->value.pair->first, env);
} }
bool truthy = is_truthy(operands->value.pair->first, env);
if (error) return nullptr;
if (truthy) if (truthy)
return create_ast_node_nil(); return create_ast_node_nil();
return create_ast_node_number(1); return create_ast_node_number(1);
+14
View File
@@ -1,6 +1,19 @@
#define new(type) (type*)malloc(sizeof(type)) #define new(type) (type*)malloc(sizeof(type))
#define nullptr NULL #define nullptr NULL
#define concat_( a, b) a##b
#define label(prefix, lnum) concat_(prefix,lnum)
#define try \
if (1) \
goto label(body,__LINE__); \
else \
while (1) \
if (1) { \
if(error) return 0; \
break; \
} \
else label(body,__LINE__):
typedef enum { false, true } bool; typedef enum { false, true } bool;
int string_equal(char* a, char* b) { int string_equal(char* a, char* b) {
@@ -102,6 +115,7 @@ char* read_line() {
if((*line++ = c) == '\n') if((*line++ = c) == '\n')
break; break;
} }
*line--; // we dont want the \n actually
*line = '\0'; *line = '\0';
return linep; return linep;
} }
+4 -3
View File
@@ -250,9 +250,10 @@ Ast_Node_Array_List* parse_program(char* text) {
while (text[index_in_text] != '\0') { while (text[index_in_text] != '\0') {
switch (text[index_in_text]) { switch (text[index_in_text]) {
case '(': { case '(': {
Ast_Node* parsed = parse_expression(text, &index_in_text); Ast_Node* parsed;
if (error) try {
return nullptr; parsed = parse_expression(text, &index_in_text);
}
append_to_Ast_Node_Array_List(program, parsed); append_to_Ast_Node_Array_List(program, parsed);
} break; } break;
case ';': case ';':
+40 -10
View File
@@ -31,25 +31,53 @@
#+RESULTS: #+RESULTS:
: t : t
** TODO first (car) ** DONE first (car)
** TODO rest (cdr) CLOSED: [2018-10-08 Mo 20:28]
** TODO pair (cons) ** DONE rest (cdr)
CLOSED: [2018-10-08 Mo 20:28]
** DONE pair (cons)
CLOSED: [2018-10-08 Mo 20:28]
** TODO load (import) ** TODO load (import)
** TODO define ** DONE define
CLOSED: [2018-10-08 Mo 20:28]
** TODO lambda ** TODO lambda
** TODO progn ** TODO progn
** TODO eval ** DONE eval
** TODO quote CLOSED: [2018-10-08 Mo 20:28]
** TODO print ** DONE quote
** TODO read CLOSED: [2018-10-08 Mo 20:28]
** TODO help
** DONE list
CLOSED: [2018-10-08 Mo 21:06]
#+begin_src emacs-lisp
(quote (cons 2 (cons 3 (cons 4 ()))))
;; (cons 2 (cons 3 (cons 4 nil)))
(quote (2 . (3 . (4 . ()))))
;; (2 3 4)
#+end_src
#+begin_src emacs-lisp
(list (cons 2 (cons 3 (cons 4 ()))))
;; ((2 3 4))
(list (quote(2 . (3 . (4 . ())))))
#+end_src
** DONE print
CLOSED: [2018-10-08 Mo 20:28]
** DONE read
CLOSED: [2018-10-08 Mo 20:28]
** DONE type
CLOSED: [2018-10-08 Mo 21:30]
** TODO info
* Types * Types
- Symbol - Symbol
- Number - Number
- String - String
- Cons-cell (list) - pair (cons-cell)
- lambda function lambda - lambda function lambda
- built-in function - built-in function
@@ -63,3 +91,5 @@
variable within an upper namespace it should variable within an upper namespace it should
infact change the environment even if the infact change the environment even if the
function exited function exited
(progn (setq x 4)(* x 2))