aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-23 18:19:14 +0200
committerBad Diode <bd@badd10de.dev>2021-10-23 18:19:14 +0200
commitb07ece568d8d62ca80a8ba3b43fb46a98e117d5a (patch)
tree1b52b7c3c4d73d154ca565e57cf5e062d4495a2a /src
parentc3fe9367986520b08a36bf693e6c74eb309377c5 (diff)
downloadbdl-b07ece568d8d62ca80a8ba3b43fb46a98e117d5a.tar.gz
bdl-b07ece568d8d62ca80a8ba3b43fb46a98e117d5a.zip
Add logic operations
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bytecode/compiler.h88
-rwxr-xr-xsrc/bytecode/lexer.c16
-rwxr-xr-xsrc/bytecode/lexer.h8
-rwxr-xr-xsrc/bytecode/ops.h8
-rwxr-xr-xsrc/bytecode/vm.h43
5 files changed, 137 insertions, 26 deletions
diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h
index fd5cdbc..6f43416 100755
--- a/src/bytecode/compiler.h
+++ b/src/bytecode/compiler.h
@@ -58,7 +58,7 @@ parse_fixnum(Chunk *chunk, Token tok) {
58void parse_tree(Chunk *chunk, Visitor *vs); 58void parse_tree(Chunk *chunk, Visitor *vs);
59 59
60void 60void
61compile_list_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) { 61compile_list_binary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) {
62 size_t n = 0; 62 size_t n = 0;
63 while (has_next_token(vs)) { 63 while (has_next_token(vs)) {
64 Token tok = peek_token(vs); 64 Token tok = peek_token(vs);
@@ -73,7 +73,15 @@ compile_list_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) {
73 } 73 }
74 if (tok.type == TOKEN_RPAREN) { 74 if (tok.type == TOKEN_RPAREN) {
75 next_token(vs); 75 next_token(vs);
76 break; 76 if (n <= 1) {
77 error_push((Error){
78 .type = ERR_TYPE_COMPILER,
79 .value = ERR_NOT_ENOUGH_ARGS,
80 .line = list_start.line,
81 .col = list_start.column,
82 });
83 }
84 return;
77 } 85 }
78 parse_tree(chunk, vs); 86 parse_tree(chunk, vs);
79 n++; 87 n++;
@@ -81,14 +89,58 @@ compile_list_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) {
81 add_code(chunk, op, list_start.line, list_start.column); 89 add_code(chunk, op, list_start.line, list_start.column);
82 } 90 }
83 } 91 }
84 if (n == 0) { 92 error_push((Error){
85 error_push((Error){ 93 .type = ERR_TYPE_COMPILER,
86 .type = ERR_TYPE_COMPILER, 94 .value = ERR_NOT_ENOUGH_ARGS,
87 .value = ERR_NOT_ENOUGH_ARGS, 95 .line = list_start.line,
88 .line = list_start.line, 96 .col = list_start.column,
89 .col = list_start.column, 97 });
90 }); 98}
99
100void
101compile_list_unary_op(Chunk *chunk, Visitor *vs, Token list_start, Ops op) {
102 size_t n = 0;
103 while (has_next_token(vs)) {
104 Token tok = peek_token(vs);
105 if (tok.type == TOKEN_EOF) {
106 error_push((Error){
107 .type = ERR_TYPE_COMPILER,
108 .value = ERR_UNBALANCED_PAREN,
109 .line = list_start.line,
110 .col = list_start.column,
111 });
112 return;
113 }
114 if (tok.type == TOKEN_RPAREN) {
115 next_token(vs);
116 if (n == 0) {
117 error_push((Error){
118 .type = ERR_TYPE_COMPILER,
119 .value = ERR_NOT_ENOUGH_ARGS,
120 .line = list_start.line,
121 .col = list_start.column,
122 });
123 }
124 return;
125 }
126 parse_tree(chunk, vs);
127 add_code(chunk, op, list_start.line, list_start.column);
128 n++;
129 if (n > 1) {
130 error_push((Error){
131 .type = ERR_TYPE_COMPILER,
132 .value = ERR_TOO_MANY_ARGS,
133 .line = list_start.line,
134 .col = list_start.column,
135 });
136 }
91 } 137 }
138 error_push((Error){
139 .type = ERR_TYPE_COMPILER,
140 .value = ERR_UNBALANCED_PAREN,
141 .line = list_start.line,
142 .col = list_start.column,
143 });
92} 144}
93 145
94void 146void
@@ -103,11 +155,19 @@ parse_list(Chunk *chunk, Visitor *vs, Token list_start) {
103 } 155 }
104 Token tok = next_token(vs); 156 Token tok = next_token(vs);
105 switch (tok.type) { 157 switch (tok.type) {
106 case TOKEN_ADD: { compile_list_op(chunk, vs, list_start, OP_SUM); } break; 158 case TOKEN_ADD: { compile_list_binary_op(chunk, vs, list_start, OP_SUM); } break;
107 case TOKEN_SUB: { compile_list_op(chunk, vs, list_start, OP_SUB); } break; 159 case TOKEN_SUB: { compile_list_binary_op(chunk, vs, list_start, OP_SUB); } break;
108 case TOKEN_MUL: { compile_list_op(chunk, vs, list_start, OP_MUL); } break; 160 case TOKEN_MUL: { compile_list_binary_op(chunk, vs, list_start, OP_MUL); } break;
109 case TOKEN_DIV: { compile_list_op(chunk, vs, list_start, OP_DIV); } break; 161 case TOKEN_DIV: { compile_list_binary_op(chunk, vs, list_start, OP_DIV); } break;
110 case TOKEN_MOD: { compile_list_op(chunk, vs, list_start, OP_MOD); } break; 162 case TOKEN_MOD: { compile_list_binary_op(chunk, vs, list_start, OP_MOD); } break;
163 case TOKEN_NOT: { compile_list_unary_op(chunk, vs, list_start, OP_NOT); } break;
164 case TOKEN_AND: { compile_list_binary_op(chunk, vs, list_start, OP_AND); } break;
165 case TOKEN_OR: { compile_list_binary_op(chunk, vs, list_start, OP_OR); } break;
166 case TOKEN_EQUAL: { compile_list_binary_op(chunk, vs, list_start, OP_EQUAL); } break;
167 case TOKEN_LESS: { compile_list_binary_op(chunk, vs, list_start, OP_LESS); } break;
168 case TOKEN_GREATER: { compile_list_binary_op(chunk, vs, list_start, OP_GREATER); } break;
169 case TOKEN_LESS_EQUAL: { compile_list_binary_op(chunk, vs, list_start, OP_LESS_EQUAL); } break;
170 case TOKEN_GREATER_EQUAL: { compile_list_binary_op(chunk, vs, list_start, OP_GREATER_EQUAL); } break;
111 default: { 171 default: {
112 error_push((Error){ 172 error_push((Error){
113 .type = ERR_TYPE_COMPILER, 173 .type = ERR_TYPE_COMPILER,
diff --git a/src/bytecode/lexer.c b/src/bytecode/lexer.c
index bc2dd9d..207cebb 100755
--- a/src/bytecode/lexer.c
+++ b/src/bytecode/lexer.c
@@ -25,10 +25,10 @@ static const char* token_str[] = {
25 [TOKEN_AND] = "TOKEN_AND", 25 [TOKEN_AND] = "TOKEN_AND",
26 [TOKEN_OR] = "TOKEN_OR", 26 [TOKEN_OR] = "TOKEN_OR",
27 [TOKEN_EQUAL] = "TOKEN_EQUAL", 27 [TOKEN_EQUAL] = "TOKEN_EQUAL",
28 [TOKEN_LESS_THAN] = "TOKEN_LESS_THAN", 28 [TOKEN_LESS] = "TOKEN_LESS",
29 [TOKEN_GREATER_THAN] = "TOKEN_GREATER_THAN", 29 [TOKEN_GREATER] = "TOKEN_GREATER",
30 [TOKEN_LESS_EQUAL_THAN] = "TOKEN_LESS_EQUAL_THAN", 30 [TOKEN_LESS_EQUAL] = "TOKEN_LESS_EQUAL",
31 [TOKEN_GREATER_EQUAL_THAN] = "TOKEN_GREATER_EQUAL_THAN", 31 [TOKEN_GREATER_EQUAL] = "TOKEN_GREATER_EQUAL",
32 [TOKEN_EOF] = "TOKEN_EOF", 32 [TOKEN_EOF] = "TOKEN_EOF",
33}; 33};
34 34
@@ -155,10 +155,10 @@ find_primitive_type(const StringView value) {
155 if (TOKEN_IS_KEYWORD(value, "and")) { return TOKEN_AND; } 155 if (TOKEN_IS_KEYWORD(value, "and")) { return TOKEN_AND; }
156 if (TOKEN_IS_KEYWORD(value, "or")) { return TOKEN_OR; } 156 if (TOKEN_IS_KEYWORD(value, "or")) { return TOKEN_OR; }
157 if (TOKEN_IS_KEYWORD(value, "=")) { return TOKEN_EQUAL; } 157 if (TOKEN_IS_KEYWORD(value, "=")) { return TOKEN_EQUAL; }
158 if (TOKEN_IS_KEYWORD(value, "<")) { return TOKEN_LESS_THAN; } 158 if (TOKEN_IS_KEYWORD(value, "<")) { return TOKEN_LESS; }
159 if (TOKEN_IS_KEYWORD(value, ">")) { return TOKEN_GREATER_THAN; } 159 if (TOKEN_IS_KEYWORD(value, ">")) { return TOKEN_GREATER; }
160 if (TOKEN_IS_KEYWORD(value, "<=")) { return TOKEN_LESS_EQUAL_THAN; } 160 if (TOKEN_IS_KEYWORD(value, "<=")) { return TOKEN_LESS_EQUAL; }
161 if (TOKEN_IS_KEYWORD(value, ">=")) { return TOKEN_GREATER_EQUAL_THAN; } 161 if (TOKEN_IS_KEYWORD(value, ">=")) { return TOKEN_GREATER_EQUAL; }
162 162
163 return TOKEN_SYMBOL; 163 return TOKEN_SYMBOL;
164} 164}
diff --git a/src/bytecode/lexer.h b/src/bytecode/lexer.h
index 47fd384..cee2915 100755
--- a/src/bytecode/lexer.h
+++ b/src/bytecode/lexer.h
@@ -38,10 +38,10 @@ typedef enum TokenType {
38 TOKEN_AND, 38 TOKEN_AND,
39 TOKEN_OR, 39 TOKEN_OR,
40 TOKEN_EQUAL, 40 TOKEN_EQUAL,
41 TOKEN_LESS_THAN, 41 TOKEN_LESS,
42 TOKEN_GREATER_THAN, 42 TOKEN_GREATER,
43 TOKEN_LESS_EQUAL_THAN, 43 TOKEN_LESS_EQUAL,
44 TOKEN_GREATER_EQUAL_THAN, 44 TOKEN_GREATER_EQUAL,
45 45
46 TOKEN_EOF, 46 TOKEN_EOF,
47} TokenType; 47} TokenType;
diff --git a/src/bytecode/ops.h b/src/bytecode/ops.h
index b58631f..b59d65a 100755
--- a/src/bytecode/ops.h
+++ b/src/bytecode/ops.h
@@ -8,6 +8,14 @@ typedef enum Ops {
8 OP_MUL, 8 OP_MUL,
9 OP_DIV, 9 OP_DIV,
10 OP_MOD, 10 OP_MOD,
11 OP_NOT,
12 OP_AND,
13 OP_OR,
14 OP_EQUAL,
15 OP_LESS,
16 OP_GREATER,
17 OP_LESS_EQUAL,
18 OP_GREATER_EQUAL,
11 OP_RETURN, 19 OP_RETURN,
12} Ops; 20} Ops;
13 21
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h
index 9b68fc1..c94e22b 100755
--- a/src/bytecode/vm.h
+++ b/src/bytecode/vm.h
@@ -59,6 +59,35 @@ vm_reset(VM *vm) {
59 array_push(vm->stack, FIXNUM_VAL(y OP x)); \ 59 array_push(vm->stack, FIXNUM_VAL(y OP x)); \
60 } while (false) 60 } while (false)
61 61
62#define FIXNUM_CMP_OP(OP) \
63 do { \
64 Object a = array_pop(vm->stack); \
65 Object b = array_pop(vm->stack); \
66 if (!IS_FIXNUM(a) || !IS_FIXNUM(b)) { \
67 error_push((Error){ \
68 .type = ERR_TYPE_RUNTIME, \
69 .value = ERR_WRONG_ARG_TYPE, \
70 .line = vm->chunk->lines[vm->pc - vm->chunk->code - 1].line, \
71 .col = vm->chunk->lines[vm->pc - vm->chunk->code - 1].col, \
72 }); \
73 return; \
74 } \
75 ssize_t x = AS_FIXNUM(a); \
76 ssize_t y = AS_FIXNUM(b); \
77 Object result = y OP x ? TRUE_VAL : FALSE_VAL; \
78 array_push(vm->stack, result); \
79 } while (false)
80
81#define LOGIC_OP(OP) \
82 do { \
83 Object a = array_pop(vm->stack); \
84 Object b = array_pop(vm->stack); \
85 bool x = IS_TRUE(a); \
86 bool y = IS_TRUE(b); \
87 Object result = y OP x ? TRUE_VAL : FALSE_VAL; \
88 array_push(vm->stack, result); \
89 } while (false)
90
62void 91void
63vm_interpret(VM *vm, Chunk *chunk) { 92vm_interpret(VM *vm, Chunk *chunk) {
64 vm->chunk = chunk; 93 vm->chunk = chunk;
@@ -97,6 +126,18 @@ vm_interpret(VM *vm, Chunk *chunk) {
97 case OP_MUL: { FIXNUM_BINARY_OP(*); } break; 126 case OP_MUL: { FIXNUM_BINARY_OP(*); } break;
98 case OP_DIV: { FIXNUM_BINARY_OP(/); } break; 127 case OP_DIV: { FIXNUM_BINARY_OP(/); } break;
99 case OP_MOD: { FIXNUM_BINARY_OP(%); } break; 128 case OP_MOD: { FIXNUM_BINARY_OP(%); } break;
129 case OP_NOT: {
130 Object prev = array_pop(vm->stack);
131 Object new = IS_TRUE(prev) ? FALSE_VAL : TRUE_VAL;
132 array_push(vm->stack, new);
133 } break;
134 case OP_AND: { LOGIC_OP(&&); } break;
135 case OP_OR: { LOGIC_OP(||); } break;
136 case OP_EQUAL: { FIXNUM_CMP_OP(==); } break;
137 case OP_LESS: { FIXNUM_CMP_OP(<); } break;
138 case OP_GREATER: { FIXNUM_CMP_OP(>); } break;
139 case OP_LESS_EQUAL: { FIXNUM_CMP_OP(<=); } break;
140 case OP_GREATER_EQUAL: { FIXNUM_CMP_OP(>=); } break;
100 case OP_RETURN: { 141 case OP_RETURN: {
101 display(array_pop(vm->stack)); 142 display(array_pop(vm->stack));
102 printf("\n"); 143 printf("\n");
@@ -123,5 +164,7 @@ vm_interpret(VM *vm, Chunk *chunk) {
123} 164}
124 165
125#undef FIXNUM_BINARY_OP 166#undef FIXNUM_BINARY_OP
167#undef FIXNUM_CMP_OP
168#undef LOGIC_OP
126 169
127#endif // BDL_VM_H 170#endif // BDL_VM_H