diff options
-rw-r--r-- | src/bytecode/lexer.c | 93 | ||||
-rw-r--r-- | src/bytecode/lexer.h | 38 | ||||
-rw-r--r-- | src/bytecode/main.c | 4 | ||||
-rw-r--r-- | src/bytecode/vm.h | 4 |
4 files changed, 100 insertions, 39 deletions
diff --git a/src/bytecode/lexer.c b/src/bytecode/lexer.c index 38ca37c..82cdf22 100644 --- a/src/bytecode/lexer.c +++ b/src/bytecode/lexer.c | |||
@@ -1,44 +1,55 @@ | |||
1 | #include "lexer.h" | 1 | #include "lexer.h" |
2 | 2 | ||
3 | static const char* token_str[] = { | ||
4 | [TOKEN_UNKNOWN] = "TOKEN_UNKNOWN", | ||
5 | [TOKEN_LPAREN] = "TOKEN_LPAREN", | ||
6 | [TOKEN_RPAREN] = "TOKEN_RPAREN", | ||
7 | [TOKEN_FIXNUM] = "TOKEN_FIXNUM", | ||
8 | [TOKEN_SYMBOL] = "TOKEN_SYMBOL", | ||
9 | [TOKEN_STRING] = "TOKEN_STRING", | ||
10 | [TOKEN_NIL] = "TOKEN_NIL", | ||
11 | [TOKEN_QUOTE] = "TOKEN_QUOTE", | ||
12 | [TOKEN_TRUE] = "TOKEN_TRUE", | ||
13 | [TOKEN_FALSE] = "TOKEN_FALSE", | ||
14 | [TOKEN_IF] = "TOKEN_IF", | ||
15 | [TOKEN_ELSE] = "TOKEN_ELSE", | ||
16 | [TOKEN_DEF] = "TOKEN_DEF", | ||
17 | [TOKEN_FUN] = "TOKEN_FUN", | ||
18 | [TOKEN_LAMBDA] = "TOKEN_LAMBDA", | ||
19 | [TOKEN_ADD] = "TOKEN_ADD", | ||
20 | [TOKEN_MIN] = "TOKEN_MIN", | ||
21 | [TOKEN_MUL] = "TOKEN_MUL", | ||
22 | [TOKEN_DIV] = "TOKEN_DIV", | ||
23 | [TOKEN_MOD] = "TOKEN_MOD", | ||
24 | [TOKEN_NOT] = "TOKEN_NOT", | ||
25 | [TOKEN_AND] = "TOKEN_AND", | ||
26 | [TOKEN_OR] = "TOKEN_OR", | ||
27 | [TOKEN_EQUAL] = "TOKEN_EQUAL", | ||
28 | [TOKEN_LESS_THAN] = "TOKEN_LESS_THAN", | ||
29 | [TOKEN_GREATER_THAN] = "TOKEN_GREATER_THAN", | ||
30 | [TOKEN_LESS_EQUAL_THAN] = "TOKEN_LESS_EQUAL_THAN", | ||
31 | [TOKEN_GREATER_EQUAL_THAN] = "TOKEN_GREATER_EQUAL_THAN", | ||
32 | [TOKEN_EOF] = "TOKEN_EOF", | ||
33 | }; | ||
34 | |||
3 | void | 35 | void |
4 | print_token(Token tok) { | 36 | print_token(Token tok) { |
5 | printf("LINE: %3ld COL: %3ld ", tok.line, tok.column); | 37 | printf("LINE: %3ld COL: %3ld ", tok.line, tok.column); |
38 | printf("%s", token_str[tok.type]); | ||
6 | switch (tok.type) { | 39 | switch (tok.type) { |
7 | case TOKEN_LPAREN: { | ||
8 | printf("TOKEN_LPAREN"); | ||
9 | } break; | ||
10 | case TOKEN_RPAREN: { | ||
11 | printf("TOKEN_RPAREN"); | ||
12 | } break; | ||
13 | case TOKEN_QUOTE: { | ||
14 | printf("TOKEN_QUOTE"); | ||
15 | } break; | ||
16 | case TOKEN_TRUE: { | ||
17 | printf("TOKEN_TRUE"); | ||
18 | } break; | ||
19 | case TOKEN_FALSE: { | ||
20 | printf("TOKEN_FALSE"); | ||
21 | } break; | ||
22 | case TOKEN_NIL: { | ||
23 | printf("TOKEN_NIL"); | ||
24 | } break; | ||
25 | case TOKEN_FIXNUM: { | 40 | case TOKEN_FIXNUM: { |
26 | printf("TOKEN_FIXNUM -> "); | 41 | printf(" -> "); |
27 | sv_write(&tok.value, stdout); | 42 | sv_write(&tok.value, stdout); |
28 | } break; | 43 | } break; |
29 | case TOKEN_SYMBOL: { | 44 | case TOKEN_SYMBOL: { |
30 | printf("TOKEN_SYMBOL -> "); | 45 | printf(" -> "); |
31 | sv_write(&tok.value, stdout); | 46 | sv_write(&tok.value, stdout); |
32 | } break; | 47 | } break; |
33 | case TOKEN_STRING: { | 48 | case TOKEN_STRING: { |
34 | printf("TOKEN_STRING -> "); | 49 | printf(" -> "); |
35 | sv_write(&tok.value, stdout); | 50 | sv_write(&tok.value, stdout); |
36 | } break; | 51 | } break; |
37 | case TOKEN_EOF: { | 52 | default: { |
38 | printf("TOKEN_EOF"); | ||
39 | } break; | ||
40 | case TOKEN_UNKNOWN: { | ||
41 | printf("TOKEN_UNKNOWN"); | ||
42 | } break; | 53 | } break; |
43 | } | 54 | } |
44 | printf("\n"); | 55 | printf("\n"); |
@@ -109,6 +120,9 @@ is_delimiter(char c) { | |||
109 | return false; | 120 | return false; |
110 | } | 121 | } |
111 | 122 | ||
123 | #define TOKEN_IS_KEYWORD(VAL, KEYWORD) \ | ||
124 | sv_equal(&(VAL), &(StringView){(KEYWORD), sizeof(KEYWORD) - 1}) | ||
125 | |||
112 | TokenType | 126 | TokenType |
113 | find_primitive_type(const StringView value) { | 127 | find_primitive_type(const StringView value) { |
114 | bool is_fixnum = true; | 128 | bool is_fixnum = true; |
@@ -125,12 +139,27 @@ find_primitive_type(const StringView value) { | |||
125 | if (is_fixnum) { | 139 | if (is_fixnum) { |
126 | return TOKEN_FIXNUM; | 140 | return TOKEN_FIXNUM; |
127 | } | 141 | } |
128 | if (sv_equal(&value, &(StringView){"true", 4})) { | 142 | if (TOKEN_IS_KEYWORD(value, "true")) { return TOKEN_TRUE; } |
129 | return TOKEN_TRUE; | 143 | if (TOKEN_IS_KEYWORD(value, "false")) { return TOKEN_FALSE; } |
130 | } | 144 | if (TOKEN_IS_KEYWORD(value, "if")) { return TOKEN_IF; } |
131 | if (sv_equal(&value, &(StringView){"false", 5})) { | 145 | if (TOKEN_IS_KEYWORD(value, "else")) { return TOKEN_ELSE; } |
132 | return TOKEN_FALSE; | 146 | if (TOKEN_IS_KEYWORD(value, "def")) { return TOKEN_DEF; } |
133 | } | 147 | if (TOKEN_IS_KEYWORD(value, "fun")) { return TOKEN_FUN; } |
148 | if (TOKEN_IS_KEYWORD(value, "lambda")) { return TOKEN_LAMBDA; } | ||
149 | if (TOKEN_IS_KEYWORD(value, "+")) { return TOKEN_ADD; } | ||
150 | if (TOKEN_IS_KEYWORD(value, "-")) { return TOKEN_MIN; } | ||
151 | if (TOKEN_IS_KEYWORD(value, "*")) { return TOKEN_MUL; } | ||
152 | if (TOKEN_IS_KEYWORD(value, "/")) { return TOKEN_DIV; } | ||
153 | if (TOKEN_IS_KEYWORD(value, "%")) { return TOKEN_MOD; } | ||
154 | if (TOKEN_IS_KEYWORD(value, "not")) { return TOKEN_NOT; } | ||
155 | if (TOKEN_IS_KEYWORD(value, "and")) { return TOKEN_AND; } | ||
156 | if (TOKEN_IS_KEYWORD(value, "or")) { return TOKEN_OR; } | ||
157 | if (TOKEN_IS_KEYWORD(value, "=")) { return TOKEN_EQUAL; } | ||
158 | if (TOKEN_IS_KEYWORD(value, "<")) { return TOKEN_LESS_THAN; } | ||
159 | if (TOKEN_IS_KEYWORD(value, ">")) { return TOKEN_GREATER_THAN; } | ||
160 | if (TOKEN_IS_KEYWORD(value, "<=")) { return TOKEN_LESS_EQUAL_THAN; } | ||
161 | if (TOKEN_IS_KEYWORD(value, ">=")) { return TOKEN_GREATER_EQUAL_THAN; } | ||
162 | |||
134 | return TOKEN_SYMBOL; | 163 | return TOKEN_SYMBOL; |
135 | } | 164 | } |
136 | 165 | ||
diff --git a/src/bytecode/lexer.h b/src/bytecode/lexer.h index e58dd05..a19ac11 100644 --- a/src/bytecode/lexer.h +++ b/src/bytecode/lexer.h | |||
@@ -3,18 +3,46 @@ | |||
3 | 3 | ||
4 | #include "string_view.h" | 4 | #include "string_view.h" |
5 | 5 | ||
6 | |||
7 | typedef enum TokenType { | 6 | typedef enum TokenType { |
8 | TOKEN_UNKNOWN = 0, | 7 | TOKEN_UNKNOWN = 0, |
8 | |||
9 | // Parentheses. | ||
9 | TOKEN_LPAREN, | 10 | TOKEN_LPAREN, |
10 | TOKEN_RPAREN, | 11 | TOKEN_RPAREN, |
11 | TOKEN_QUOTE, | 12 | |
12 | TOKEN_TRUE, | 13 | // Primitive types. |
13 | TOKEN_FALSE, | ||
14 | TOKEN_NIL, | ||
15 | TOKEN_FIXNUM, | 14 | TOKEN_FIXNUM, |
16 | TOKEN_SYMBOL, | 15 | TOKEN_SYMBOL, |
17 | TOKEN_STRING, | 16 | TOKEN_STRING, |
17 | |||
18 | // Keywords. | ||
19 | TOKEN_NIL, | ||
20 | TOKEN_QUOTE, | ||
21 | TOKEN_TRUE, | ||
22 | TOKEN_FALSE, | ||
23 | TOKEN_IF, | ||
24 | TOKEN_ELSE, | ||
25 | TOKEN_DEF, | ||
26 | TOKEN_FUN, | ||
27 | TOKEN_LAMBDA, | ||
28 | |||
29 | // Arithmetic. | ||
30 | TOKEN_ADD, | ||
31 | TOKEN_MIN, | ||
32 | TOKEN_MUL, | ||
33 | TOKEN_DIV, | ||
34 | TOKEN_MOD, | ||
35 | |||
36 | // Boolean comparisons. | ||
37 | TOKEN_NOT, | ||
38 | TOKEN_AND, | ||
39 | TOKEN_OR, | ||
40 | TOKEN_EQUAL, | ||
41 | TOKEN_LESS_THAN, | ||
42 | TOKEN_GREATER_THAN, | ||
43 | TOKEN_LESS_EQUAL_THAN, | ||
44 | TOKEN_GREATER_EQUAL_THAN, | ||
45 | |||
18 | TOKEN_EOF, | 46 | TOKEN_EOF, |
19 | } TokenType; | 47 | } TokenType; |
20 | 48 | ||
diff --git a/src/bytecode/main.c b/src/bytecode/main.c index 66089c0..5661747 100644 --- a/src/bytecode/main.c +++ b/src/bytecode/main.c | |||
@@ -38,6 +38,10 @@ process_source(const StringView *source) { | |||
38 | return; | 38 | return; |
39 | } | 39 | } |
40 | 40 | ||
41 | for (size_t i = 0; i < array_size(tokens); i++) { | ||
42 | print_token(tokens[i]); | ||
43 | } | ||
44 | |||
41 | size_t const_a = add_constant(vm.chunk, 7); | 45 | size_t const_a = add_constant(vm.chunk, 7); |
42 | add_code(vm.chunk, OP_CONSTANT, 1, 1); | 46 | add_code(vm.chunk, OP_CONSTANT, 1, 1); |
43 | add_code(vm.chunk, const_a, 1, 1); | 47 | add_code(vm.chunk, const_a, 1, 1); |
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index cc9f846..6c5dfa7 100644 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h | |||
@@ -102,8 +102,8 @@ vm_interpret(VM vm) { | |||
102 | error_push((Error){ | 102 | error_push((Error){ |
103 | .type = ERR_TYPE_RUNTIME, | 103 | .type = ERR_TYPE_RUNTIME, |
104 | .value = ERR_NOT_IMPLEMENTED, | 104 | .value = ERR_NOT_IMPLEMENTED, |
105 | .line = vm.chunk->lines[0].line, | 105 | .line = vm.chunk->lines[(vm.pc - vm.chunk->code) - 1].line, |
106 | .col = vm.chunk->lines[0].col, | 106 | .col = vm.chunk->lines[(vm.pc - vm.chunk->code) - 1].col, |
107 | }); | 107 | }); |
108 | return; | 108 | return; |
109 | } break; | 109 | } break; |