Quellcode durchsuchen

more things!

master
FelixBrendel vor 7 Jahren
Ursprung
Commit
1ea4cf5213
8 geänderte Dateien mit 313 neuen und 73 gelöschten Zeilen
  1. +2
    -0
      build.bat
  2. +9
    -7
      src/assert.c
  3. +78
    -7
      src/built_ins.c
  4. +6
    -6
      src/env.c
  5. +159
    -39
      src/eval.c
  6. +15
    -1
      src/helpers.c
  7. +4
    -3
      src/parse.c
  8. +40
    -10
      todo.org

+ 2
- 0
build.bat Datei anzeigen

@@ -8,6 +8,8 @@ set binDir=bin
mkdir quickbuild 2>nul
pushd quickbuild

taskkill /F /IM %exeName% > NUL 2> NUL

echo ---------- Compiling ----------
call timecmd cl ../src/main.c /Fe%exeName% /W3 /TC /nologo /EHsc /Z7 /link /incremental /debug:fastlink



+ 9
- 7
src/assert.c Datei anzeigen

@@ -1,11 +1,13 @@
void assert_type (Ast_Node* node, Ast_Node_Type type) {
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);
/* 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);
}

+ 78
- 7
src/built_ins.c Datei anzeigen

@@ -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) {
double sum = 0;
while (operands->type == Ast_Node_Type_Pair) {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}
sum += operands->value.pair->first->value.number->value;
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) {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
try {
assert_type(operands->value.pair->first, 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) {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}

difference -= operands->value.pair->first->value.number->value;
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) {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
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) {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}

product *= operands->value.pair->first->value.number->value;
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) {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
try {
assert_type(operands->value.pair->first, 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) {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
try {
assert_type(operands->value.pair->first, Ast_Node_Type_Number);
}

quotient /= operands->value.pair->first->value.number->value;
operands = operands->value.pair->rest;


+ 6
- 6
src/env.c Datei anzeigen

@@ -12,7 +12,7 @@ typedef struct Environment Environment;
Environment* create_empty_environment() {
Environment* env = new(Environment);

int start_capacity = 1;
int start_capacity = 16;

env->parent = nullptr;
env->capacity = start_capacity;
@@ -54,17 +54,17 @@ Ast_Node* lookup_symbol(Symbol* sym, Environment* env) {
"+", "-", "*", "/",
">", "<", "=", "<=", ">=",
// Conditional stuff
"if", "and", "or", "not",
"if", "and", "or", "not",
// Cons stuff
"first", "rest", "pair",
"pair", "first", "rest",
// rest
"load", "define",
"lambda", "progn",
"eval", "quote",
"eval", "quote", "prog", "list",
"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) {
if (string_equal(built_in_names[i], sym->identifier)) {


+ 159
- 39
src/eval.c Datei anzeigen

@@ -56,46 +56,84 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
case Ast_Node_Type_String:
return node;
case Ast_Node_Type_Pair: {
Ast_Node* operator = eval_expr(node->value.pair->first, env);
if (error) return nullptr;
Ast_Node* operator;
try {
operator = eval_expr(node->value.pair->first, env);
}

Ast_Node* operands = node->value.pair->rest;
int operands_length;


// check for built ins functions
if (operator->type == Ast_Node_Type_Built_In_Function) {
char* operator_name = operator->value.built_in_function->identifier;
if (string_equal("quote", operator_name)) {
int operands_length = list_length(operands);
operands_length = list_length(operands);
if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
return operands->value.pair->first;
} else if (string_equal("eval", operator_name)) {
int operands_length = list_length(operands);
try {
operands_length = list_length(operands);
}
if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
if (error) return nullptr;
return eval_expr(operands->value.pair->first, env);
} 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);
}
return operands;
} else if (string_equal("=", operator_name)) {
try {
eval_operands(operands, env);
}
return built_in_equals(operands);
} else if (string_equal("+", operator_name)) {
eval_operands(operands, env);
if (error) return nullptr;
try {
eval_operands(operands, env);
}
return built_in_add(operands);
} else if (string_equal("-", operator_name)) {
eval_operands(operands, env);
if (error) return nullptr;
try {
eval_operands(operands, env);
}
return built_in_substract(operands);
} else if (string_equal("*", operator_name)) {
eval_operands(operands, env);
if (error) return nullptr;
try {
eval_operands(operands, env);
}
return built_in_multiply(operands);
} else if (string_equal("/", operator_name)) {
eval_operands(operands, env);
if (error) return nullptr;
try {
eval_operands(operands, env);
}
return built_in_divide(operands);
} else if (string_equal("define", operator_name)) {
int operands_length = list_length(operands);
if (error) return nullptr;
try {
operands_length = list_length(operands);
}
if (operands_length != 2) {
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);

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)) {
int operands_length = list_length(operands);
if (error) return nullptr;
try {
operands_length = list_length(operands);
}
if (operands_length > 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}

if (operands_length == 1) {
try {
eval_operands(operands, env);
}
Ast_Node* error_code = operands->value.pair->first;
if (error_code->type != Ast_Node_Type_Number)
report_error(Error_Type_Type_Missmatch);
@@ -127,26 +191,30 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
exit(0);

} else if (string_equal("print", operator_name)) {
int operands_length = list_length(operands);
if (error) return nullptr;
try {
operands_length = list_length(operands);
}
if (operands_length != 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}
eval_operands(operands, env);
if (error) return nullptr;
try {
eval_operands(operands, env);
}
print(operands->value.pair->first);
printf("\n");
return operands->value.pair->first;
} else if (string_equal("read", operator_name)) {
int operands_length = list_length(operands);
if (error) return nullptr;
try {
operands_length = list_length(operands);
}
if (operands_length > 1) {
report_error(Error_Type_Wrong_Number_Of_Arguments);
}

if (operands_length == 1) {
eval_operands(operands, env);
if (error) return nullptr;
try {
eval_operands(operands, env);
}
Ast_Node* prompt = operands->value.pair->first;
if (prompt->type == Ast_Node_Type_String)
printf("%s", prompt->value.string->value);
@@ -155,9 +223,54 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) {
}
char* line = read_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)) {
int operands_length = list_length(operands);
if (error) return nullptr;
try {
operands_length = list_length(operands);
}
if (operands_length != 2 && operands_length != 3) {
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* else_part = then_part->value.pair->rest;

bool truthy = is_truthy(condition, env);
if (error) return nullptr;
bool truthy;
try {
truthy = is_truthy(condition, env);
}
if (truthy)
return eval_expr(then_part->value.pair->first, env);
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) {
report_error(Error_Type_Ill_Formed_List);
}
result &= is_truthy(operands->value.pair->first, env);
if (error) return nullptr;
try {
result &= is_truthy(operands->value.pair->first, env);
}
operands = operands->value.pair->rest;

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) {
report_error(Error_Type_Ill_Formed_List);
}
result |= is_truthy(operands->value.pair->first, env);
if (error) return nullptr;
try {
result |= is_truthy(operands->value.pair->first, env);
}
operands = operands->value.pair->rest;

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();
} else if (string_equal("not", operator_name)) {
if (list_length(operands) != 1) {
if (!error)
create_error(Error_Type_Wrong_Number_Of_Arguments, operands);
return nullptr;
try {
operands_length = list_length(operands);
}
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)
return create_ast_node_nil();
return create_ast_node_number(1);


+ 15
- 1
src/helpers.c Datei anzeigen

@@ -1,6 +1,19 @@
#define new(type) (type*)malloc(sizeof(type))
#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;

int string_equal(char* a, char* b) {
@@ -75,7 +88,7 @@ char* read_entire_file (char* filename) {
}

char* read_line() {
char * line = malloc(100), * linep = line;
char* line = malloc(100), * linep = line;
size_t lenmax = 100, len = lenmax;
int c;

@@ -102,6 +115,7 @@ char* read_line() {
if((*line++ = c) == '\n')
break;
}
*line--; // we dont want the \n actually
*line = '\0';
return linep;
}

+ 4
- 3
src/parse.c Datei anzeigen

@@ -250,9 +250,10 @@ Ast_Node_Array_List* parse_program(char* text) {
while (text[index_in_text] != '\0') {
switch (text[index_in_text]) {
case '(': {
Ast_Node* parsed = parse_expression(text, &index_in_text);
if (error)
return nullptr;
Ast_Node* parsed;
try {
parsed = parse_expression(text, &index_in_text);
}
append_to_Ast_Node_Array_List(program, parsed);
} break;
case ';':


+ 40
- 10
todo.org Datei anzeigen

@@ -31,25 +31,53 @@
#+RESULTS:
: t

** TODO first (car)
** TODO rest (cdr)
** TODO pair (cons)
** DONE first (car)
CLOSED: [2018-10-08 Mo 20:28]
** DONE rest (cdr)
CLOSED: [2018-10-08 Mo 20:28]
** DONE pair (cons)
CLOSED: [2018-10-08 Mo 20:28]

** TODO load (import)
** TODO define
** DONE define
CLOSED: [2018-10-08 Mo 20:28]
** TODO lambda
** TODO progn
** TODO eval
** TODO quote
** TODO print
** TODO read
** TODO help
** DONE eval
CLOSED: [2018-10-08 Mo 20:28]
** DONE quote
CLOSED: [2018-10-08 Mo 20:28]

** 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
- Symbol
- Number
- String
- Cons-cell (list)
- pair (cons-cell)
- lambda function lambda
- built-in function

@@ -63,3 +91,5 @@
variable within an upper namespace it should
infact change the environment even if the
function exited

(progn (setq x 4)(* x 2))

Laden…
Abbrechen
Speichern