aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-12-22 18:07:53 +0100
committerBad Diode <bd@badd10de.dev>2021-12-22 18:07:53 +0100
commit7ad32a2a907150e3ce71e89f126ca2a530550158 (patch)
tree2c5db028cd7e5b5244db3d43f7561d7a8327f07a
parentfd65adf81f6c3e7e94755a83e22f7e0a19f8bd99 (diff)
downloadbdl-7ad32a2a907150e3ce71e89f126ca2a530550158.tar.gz
bdl-7ad32a2a907150e3ce71e89f126ca2a530550158.zip
Add builtin object type
-rw-r--r--src/ir.h53
-rw-r--r--src/parser.c62
-rw-r--r--src/parser.h31
3 files changed, 108 insertions, 38 deletions
diff --git a/src/ir.h b/src/ir.h
index b42e02f..a42cd48 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -115,34 +115,43 @@ proc_alloc(ProgramIr *program, StringView name) {
115void compile_object(ProgramIr *program, Procedure *proc, Object *obj); 115void compile_object(ProgramIr *program, Procedure *proc, Object *obj);
116 116
117void 117void
118compile_arithmetic_list(ProgramIr *program, Procedure *proc, Op op, Object *obj) { 118compile_arithmetic(ProgramIr *program, Procedure *proc, Op op,
119 size_t op_line = obj->head->line; 119 size_t line, size_t col, Object *args) {
120 size_t op_col = obj->head->col; 120 compile_object(program, proc, args->head);
121 obj = obj->tail; 121 args = args->tail;
122 122 while (args != NULL) {
123 compile_object(program, proc, obj->head); 123 compile_object(program, proc, args->head);
124 obj = obj->tail; 124 args = args->tail;
125 while (obj != NULL) { 125 Instruction inst = (Instruction){op, NULL, line, col};
126 compile_object(program, proc, obj->head);
127 obj = obj->tail;
128 Instruction inst = (Instruction){op, NULL, op_line, op_col};
129 array_push(proc->instructions, inst); 126 array_push(proc->instructions, inst);
130 } 127 }
131} 128}
132 129
133void 130void
134compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) { 131compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) {
135 // TODO: Handle this on the parser? 132 size_t line = obj->line;
136 if (sv_equal(&obj->head->text, &STRING("+"))) { 133 size_t col = obj->col;
137 compile_arithmetic_list(program, proc, OP_ADD, obj); 134 if (obj->head->type == OBJ_TYPE_BUILTIN) {
138 } else if (sv_equal(&obj->head->text, &STRING("-"))) { 135 switch (obj->head->builtin) {
139 compile_arithmetic_list(program, proc, OP_SUB, obj); 136 case BUILTIN_ADD: {
140 } else if (sv_equal(&obj->head->text, &STRING("*"))) { 137 compile_arithmetic(program, proc, OP_ADD, line, col, obj->tail);
141 compile_arithmetic_list(program, proc, OP_MUL, obj); 138 } break;
142 } else if (sv_equal(&obj->head->text, &STRING("/"))) { 139 case BUILTIN_SUB: {
143 compile_arithmetic_list(program, proc, OP_DIV, obj); 140 compile_arithmetic(program, proc, OP_SUB, line, col, obj->tail);
144 } else if (sv_equal(&obj->head->text, &STRING("%"))) { 141 } break;
145 compile_arithmetic_list(program, proc, OP_MOD, obj); 142 case BUILTIN_MUL: {
143 compile_arithmetic(program, proc, OP_MUL, line, col, obj->tail);
144 } break;
145 case BUILTIN_DIV: {
146 compile_arithmetic(program, proc, OP_DIV, line, col, obj->tail);
147 } break;
148 case BUILTIN_MOD: {
149 compile_arithmetic(program, proc, OP_MOD, line, col, obj->tail);
150 } break;
151 default: {
152 assert(false && "builtin not implemented");
153 } break;
154 }
146 } else { 155 } else {
147 assert(false && "compile_proc_call: not implemented"); 156 assert(false && "compile_proc_call: not implemented");
148 } 157 }
diff --git a/src/parser.c b/src/parser.c
index e72675f..298220a 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -5,7 +5,7 @@ static Object **objects = NULL;
5static Root *roots = NULL; 5static Root *roots = NULL;
6static Environment **environments = NULL; 6static Environment **environments = NULL;
7 7
8static char *builtins [] = { 8static char *builtin_names[] = {
9 "+", "-", "*", "/", "%", 9 "+", "-", "*", "/", "%",
10 "=", "<", ">", "<=", ">=", 10 "=", "<", ">", "<=", ">=",
11 "not", "and", "or", 11 "not", "and", "or",
@@ -14,6 +14,30 @@ static char *builtins [] = {
14 "cons", "car", "cdr", 14 "cons", "car", "cdr",
15}; 15};
16 16
17static Object builtins[] = {
18 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_ADD } ,
19 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_SUB } ,
20 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_MUL } ,
21 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_DIV } ,
22 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_MOD } ,
23 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_EQ } ,
24 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_LT } ,
25 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_GT } ,
26 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_LE } ,
27 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_GE } ,
28 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_NOT } ,
29 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_AND } ,
30 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_OR } ,
31 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_IS_NIL } ,
32 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_IS_ZERO } ,
33 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_IS_FIXNUM } ,
34 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_IS_BOOL } ,
35 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_IS_PRINT } ,
36 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_IS_CONS } ,
37 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_IS_CAR } ,
38 { .type = OBJ_TYPE_BUILTIN, .builtin = BUILTIN_IS_CDR } ,
39};
40
17Token 41Token
18peek_token(const Parser *parser) { 42peek_token(const Parser *parser) {
19 if (parser->current >= array_size(parser->tokens)) { 43 if (parser->current >= array_size(parser->tokens)) {
@@ -79,6 +103,16 @@ parse_string(Token tok) {
79 103
80Object * 104Object *
81parse_symbol(Token tok) { 105parse_symbol(Token tok) {
106 // Check if symbol is a builtin procedure.
107 size_t n_builtins = sizeof(builtin_names) / sizeof(char*);
108 for (size_t i = 0; i < n_builtins; ++i) {
109 char *str = builtin_names[i];
110 size_t str_n = strlen(str);
111 if (sv_equal(&tok.value, &(StringView){str, str_n})) {
112 return &builtins[i];
113 }
114 }
115
82 Object *ret = object_alloc(tok, OBJ_TYPE_SYMBOL); 116 Object *ret = object_alloc(tok, OBJ_TYPE_SYMBOL);
83 ret->text = tok.value; 117 ret->text = tok.value;
84 return ret; 118 return ret;
@@ -352,7 +386,9 @@ parse_list(Parser *parser, Errors *errors) {
352 } 386 }
353 387
354 if (first) { 388 if (first) {
355 if (!IS_SYMBOL(current->head) && !IS_LAMBDA(current->head)) { 389 if (!IS_SYMBOL(current->head) &&
390 !IS_LAMBDA(current->head) &&
391 !IS_BUILTIN(current->head)) {
356 error_push(errors, (Error){ 392 error_push(errors, (Error){
357 .type = ERR_TYPE_PARSER, 393 .type = ERR_TYPE_PARSER,
358 .value = ERR_NOT_CALLABLE, 394 .value = ERR_NOT_CALLABLE,
@@ -613,20 +649,8 @@ parse(Token *tokens, Errors *errors) {
613 array_push(roots, root); 649 array_push(roots, root);
614 } 650 }
615 651
616 // Prepare global environment of builtin functions. 652 // Prepare global environment.
617 Environment *global_env = env_alloc(NULL); 653 Environment *env = env_alloc(NULL);
618 Environment *env = env_alloc(global_env);
619 size_t n_builtins = sizeof(builtins) / sizeof(char*);
620 for (size_t i = 0; i < n_builtins; i++) {
621 // Prepare builtin symbol.
622 char *str = builtins[i];
623 size_t str_n = strlen(str);
624 Object *symbol = object_alloc((Token){0}, OBJ_TYPE_SYMBOL);
625 symbol->text = (StringView){str, str_n};
626
627 // Insert in global table.
628 insert_local(global_env, symbol, symbol);
629 }
630 654
631 // Perform semantic analysis: 655 // Perform semantic analysis:
632 // 1. Populate symbol tables and ensure symbols are in scope when used. 656 // 1. Populate symbol tables and ensure symbols are in scope when used.
@@ -807,6 +831,9 @@ object_display(Object *obj) {
807 object_display(obj->var_expr); 831 object_display(obj->var_expr);
808 printf(" }"); 832 printf(" }");
809 } break; 833 } break;
834 case OBJ_TYPE_BUILTIN: {
835 printf("%s", builtin_names[obj->builtin]);
836 } break;
810 } 837 }
811 return; 838 return;
812} 839}
@@ -828,6 +855,9 @@ object_equal(Object *a, Object *b) {
828 case OBJ_TYPE_STRING: { 855 case OBJ_TYPE_STRING: {
829 return sv_equal(&a->text, &b->text); 856 return sv_equal(&a->text, &b->text);
830 } break; 857 } break;
858 case OBJ_TYPE_BUILTIN: {
859 return a->builtin = b->builtin;
860 } break;
831 default: break; 861 default: break;
832 } 862 }
833 return false; 863 return false;
diff --git a/src/parser.h b/src/parser.h
index 60a307c..41f1fc1 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -23,8 +23,33 @@ typedef enum ObjectType {
23 OBJ_TYPE_IF, 23 OBJ_TYPE_IF,
24 OBJ_TYPE_DEF, 24 OBJ_TYPE_DEF,
25 OBJ_TYPE_SET, 25 OBJ_TYPE_SET,
26 OBJ_TYPE_BUILTIN,
26} ObjectType; 27} ObjectType;
27 28
29typedef enum Builtin {
30 BUILTIN_ADD,
31 BUILTIN_SUB,
32 BUILTIN_MUL,
33 BUILTIN_DIV,
34 BUILTIN_MOD,
35 BUILTIN_EQ,
36 BUILTIN_LT,
37 BUILTIN_GT,
38 BUILTIN_LE,
39 BUILTIN_GE,
40 BUILTIN_NOT,
41 BUILTIN_AND,
42 BUILTIN_OR,
43 BUILTIN_IS_NIL,
44 BUILTIN_IS_ZERO,
45 BUILTIN_IS_FIXNUM,
46 BUILTIN_IS_BOOL,
47 BUILTIN_IS_PRINT,
48 BUILTIN_IS_CONS,
49 BUILTIN_IS_CAR,
50 BUILTIN_IS_CDR,
51} Builtin;
52
28typedef struct Object { 53typedef struct Object {
29 ObjectType type; 54 ObjectType type;
30 union { 55 union {
@@ -62,6 +87,11 @@ typedef struct Object {
62 struct Object *var_name; 87 struct Object *var_name;
63 struct Object *var_expr; 88 struct Object *var_expr;
64 }; 89 };
90
91 // OBJ_TYPE_BUILTIN
92 struct {
93 Builtin builtin;
94 };
65 }; 95 };
66 96
67 bool visited; 97 bool visited;
@@ -125,6 +155,7 @@ void free_objects(void);
125#define IS_SYMBOL(VAL) ((VAL)->type == OBJ_TYPE_SYMBOL) 155#define IS_SYMBOL(VAL) ((VAL)->type == OBJ_TYPE_SYMBOL)
126#define IS_PAIR(VAL) ((VAL)->type == OBJ_TYPE_PAIR) 156#define IS_PAIR(VAL) ((VAL)->type == OBJ_TYPE_PAIR)
127#define IS_LAMBDA(VAL) ((VAL)->type == OBJ_TYPE_LAMBDA) 157#define IS_LAMBDA(VAL) ((VAL)->type == OBJ_TYPE_LAMBDA)
158#define IS_BUILTIN(VAL) ((VAL)->type == OBJ_TYPE_BUILTIN)
128 159
129// Debug. 160// Debug.
130#define OBJ_PRINT(OBJ) object_display(OBJ); printf("\n"); 161#define OBJ_PRINT(OBJ) object_display(OBJ); printf("\n");