diff options
-rw-r--r-- | src/bytecode/chunk.c | 43 | ||||
-rwxr-xr-x | src/bytecode/chunk.h | 43 | ||||
-rwxr-xr-x | src/bytecode/debug.h | 5 | ||||
-rwxr-xr-x | src/bytecode/main.c | 2 | ||||
-rw-r--r-- | src/bytecode/objects.c | 126 | ||||
-rwxr-xr-x | src/bytecode/objects.h | 124 | ||||
-rwxr-xr-x | src/bytecode/vm.h | 4 |
7 files changed, 190 insertions, 157 deletions
diff --git a/src/bytecode/chunk.c b/src/bytecode/chunk.c new file mode 100644 index 0000000..3dc2421 --- /dev/null +++ b/src/bytecode/chunk.c | |||
@@ -0,0 +1,43 @@ | |||
1 | #include "chunk.h" | ||
2 | #include "objects.h" | ||
3 | |||
4 | Chunk * | ||
5 | chunk_init(void) { | ||
6 | Chunk *chunk = malloc(sizeof(Chunk)); | ||
7 | array_init(chunk->code, 0); | ||
8 | array_init(chunk->constants, 0); | ||
9 | array_init(chunk->lines, 0); | ||
10 | return chunk; | ||
11 | } | ||
12 | |||
13 | void | ||
14 | chunk_free(Chunk *chunk) { | ||
15 | array_free(chunk->code); | ||
16 | for (size_t i = 0; i < array_size(chunk->constants); i++) { | ||
17 | Object obj = chunk->constants[i]; | ||
18 | object_free(obj); | ||
19 | } | ||
20 | array_free(chunk->constants); | ||
21 | array_free(chunk->lines); | ||
22 | free(chunk); | ||
23 | } | ||
24 | |||
25 | void | ||
26 | add_code(Chunk *chunk, u8 byte, size_t line, size_t col) { | ||
27 | array_push(chunk->code, byte); | ||
28 | LineInfo info = (LineInfo){line, col}; | ||
29 | array_push(chunk->lines, info); | ||
30 | } | ||
31 | |||
32 | size_t | ||
33 | add_constant(Chunk *chunk, Object obj) { | ||
34 | size_t pos = array_size(chunk->constants); | ||
35 | for (size_t i = 0; i < pos; i++) { | ||
36 | if (object_equal(obj, chunk->constants[i])) { | ||
37 | return i; | ||
38 | } | ||
39 | } | ||
40 | array_push(chunk->constants, obj); | ||
41 | return pos; | ||
42 | } | ||
43 | |||
diff --git a/src/bytecode/chunk.h b/src/bytecode/chunk.h index 5fbc000..3e1c005 100755 --- a/src/bytecode/chunk.h +++ b/src/bytecode/chunk.h | |||
@@ -1,9 +1,10 @@ | |||
1 | #ifndef BDL_CHUNK_H | 1 | #ifndef BDL_CHUNK_H |
2 | #define BDL_CHUNK_H | 2 | #define BDL_CHUNK_H |
3 | 3 | ||
4 | #include "objects.h" | ||
5 | #include "darray.h" | 4 | #include "darray.h" |
6 | 5 | ||
6 | typedef struct Object Object; | ||
7 | |||
7 | typedef struct LineInfo { | 8 | typedef struct LineInfo { |
8 | size_t line; | 9 | size_t line; |
9 | size_t col; | 10 | size_t col; |
@@ -20,44 +21,4 @@ void add_code(Chunk *chunk, u8 byte, size_t line, size_t col); | |||
20 | size_t add_constant(Chunk *chunk, Object obj); | 21 | size_t add_constant(Chunk *chunk, Object obj); |
21 | void chunk_free(Chunk *chunk); | 22 | void chunk_free(Chunk *chunk); |
22 | 23 | ||
23 | Chunk * | ||
24 | chunk_init(void) { | ||
25 | Chunk *chunk = malloc(sizeof(Chunk)); | ||
26 | array_init(chunk->code, 0); | ||
27 | array_init(chunk->constants, 0); | ||
28 | array_init(chunk->lines, 0); | ||
29 | return chunk; | ||
30 | } | ||
31 | |||
32 | void | ||
33 | chunk_free(Chunk *chunk) { | ||
34 | array_free(chunk->code); | ||
35 | for (size_t i = 0; i < array_size(chunk->constants); i++) { | ||
36 | Object obj = chunk->constants[i]; | ||
37 | object_free(obj); | ||
38 | } | ||
39 | array_free(chunk->constants); | ||
40 | array_free(chunk->lines); | ||
41 | free(chunk); | ||
42 | } | ||
43 | |||
44 | void | ||
45 | add_code(Chunk *chunk, u8 byte, size_t line, size_t col) { | ||
46 | array_push(chunk->code, byte); | ||
47 | LineInfo info = (LineInfo){line, col}; | ||
48 | array_push(chunk->lines, info); | ||
49 | } | ||
50 | |||
51 | size_t | ||
52 | add_constant(Chunk *chunk, Object obj) { | ||
53 | size_t pos = array_size(chunk->constants); | ||
54 | for (size_t i = 0; i < pos; i++) { | ||
55 | if (object_equal(obj, chunk->constants[i])) { | ||
56 | return i; | ||
57 | } | ||
58 | } | ||
59 | array_push(chunk->constants, obj); | ||
60 | return pos; | ||
61 | } | ||
62 | |||
63 | #endif // BDL_CHUNK_H | 24 | #endif // BDL_CHUNK_H |
diff --git a/src/bytecode/debug.h b/src/bytecode/debug.h index 6703e68..7673703 100755 --- a/src/bytecode/debug.h +++ b/src/bytecode/debug.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define BDL_DEBUG_H | 2 | #define BDL_DEBUG_H |
3 | 3 | ||
4 | #include "chunk.h" | 4 | #include "chunk.h" |
5 | #include "objects.h" | ||
5 | 6 | ||
6 | void disassemble_chunk(Chunk *chunk, const char *name); | 7 | void disassemble_chunk(Chunk *chunk, const char *name); |
7 | size_t disassemble_instruction(Chunk *chunk, size_t offset); | 8 | size_t disassemble_instruction(Chunk *chunk, size_t offset); |
@@ -51,7 +52,7 @@ disassemble_chunk(Chunk *chunk, const char *name) { | |||
51 | offset = 0; | 52 | offset = 0; |
52 | while (offset < array_size(chunk->constants)) { | 53 | while (offset < array_size(chunk->constants)) { |
53 | printf("\t%03ld -> ", offset); | 54 | printf("\t%03ld -> ", offset); |
54 | display(chunk->constants[offset]); | 55 | object_display(chunk->constants[offset]); |
55 | printf("\n"); | 56 | printf("\n"); |
56 | offset++; | 57 | offset++; |
57 | } | 58 | } |
@@ -72,7 +73,7 @@ disassemble_instruction(Chunk *chunk, size_t offset) { | |||
72 | case OP_CONSTANT: { | 73 | case OP_CONSTANT: { |
73 | u8 constant = chunk->code[offset + 1]; | 74 | u8 constant = chunk->code[offset + 1]; |
74 | printf("%-16s %4d -> ", ops_str[instruction], constant); | 75 | printf("%-16s %4d -> ", ops_str[instruction], constant); |
75 | display(chunk->constants[constant]); | 76 | object_display(chunk->constants[constant]); |
76 | printf("\n"); | 77 | printf("\n"); |
77 | return offset + 2; | 78 | return offset + 2; |
78 | } break; | 79 | } break; |
diff --git a/src/bytecode/main.c b/src/bytecode/main.c index 85882b3..f938e36 100755 --- a/src/bytecode/main.c +++ b/src/bytecode/main.c | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | #include "vm.h" | 15 | #include "vm.h" |
16 | #include "errors.c" | 16 | #include "errors.c" |
17 | #include "chunk.c" | ||
18 | #include "objects.c" | ||
17 | #include "compiler.h" | 19 | #include "compiler.h" |
18 | #include "ops.h" | 20 | #include "ops.h" |
19 | #include "debug.h" | 21 | #include "debug.h" |
diff --git a/src/bytecode/objects.c b/src/bytecode/objects.c new file mode 100644 index 0000000..515a19d --- /dev/null +++ b/src/bytecode/objects.c | |||
@@ -0,0 +1,126 @@ | |||
1 | #include "objects.h" | ||
2 | |||
3 | Object | ||
4 | make_string(StringView sv) { | ||
5 | Object obj = { | ||
6 | .type = OBJ_TYPE_STRING, | ||
7 | .text = NULL, | ||
8 | }; | ||
9 | array_init(obj.text, sv.n); | ||
10 | array_insert(obj.text, sv.start, sv.n); | ||
11 | return obj; | ||
12 | } | ||
13 | |||
14 | Object | ||
15 | make_symbol(StringView sv) { | ||
16 | Object obj = { | ||
17 | .type = OBJ_TYPE_SYMBOL, | ||
18 | .text = NULL, | ||
19 | }; | ||
20 | array_init(obj.text, sv.n); | ||
21 | array_insert(obj.text, sv.start, sv.n); | ||
22 | return obj; | ||
23 | } | ||
24 | |||
25 | Object | ||
26 | make_lambda(void) { | ||
27 | Object obj = { | ||
28 | .type = OBJ_TYPE_LAMBDA, | ||
29 | .chunk = chunk_init(), | ||
30 | }; | ||
31 | return obj; | ||
32 | } | ||
33 | |||
34 | void | ||
35 | object_display(Object obj) { | ||
36 | switch (obj.type) { | ||
37 | case OBJ_TYPE_FIXNUM: { | ||
38 | printf("%zd", obj.fixnum); | ||
39 | } break; | ||
40 | case OBJ_TYPE_TRUE: { | ||
41 | printf("true"); | ||
42 | } break; | ||
43 | case OBJ_TYPE_FALSE: { | ||
44 | printf("false"); | ||
45 | } break; | ||
46 | case OBJ_TYPE_NIL: { | ||
47 | printf("()"); | ||
48 | } break; | ||
49 | case OBJ_TYPE_STRING: { | ||
50 | printf("\"%.*s\"", (int)array_size(obj.text), obj.text); | ||
51 | } break; | ||
52 | case OBJ_TYPE_SYMBOL: { | ||
53 | printf(":%.*s", (int)array_size(obj.text), obj.text); | ||
54 | } break; | ||
55 | case OBJ_TYPE_PAIR: { | ||
56 | // printf("("); | ||
57 | // display_pair(obj); | ||
58 | // printf(")"); | ||
59 | } break; | ||
60 | case OBJ_TYPE_LAMBDA: { | ||
61 | printf("#{procedure}"); | ||
62 | } break; | ||
63 | case OBJ_TYPE_ERR: { | ||
64 | printf("#{error}"); | ||
65 | } break; | ||
66 | } | ||
67 | return; | ||
68 | } | ||
69 | |||
70 | void | ||
71 | object_free(Object obj) { | ||
72 | if (IS_STRING(obj) || IS_SYMBOL(obj)) { | ||
73 | array_free(obj.text); | ||
74 | return; | ||
75 | } | ||
76 | if (IS_LAMBDA(obj)) { | ||
77 | chunk_free(obj.chunk); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | bool | ||
82 | object_equal(Object a, Object b) { | ||
83 | if (a.type != b.type) { | ||
84 | return false; | ||
85 | } | ||
86 | switch (a.type) { | ||
87 | case OBJ_TYPE_TRUE: | ||
88 | case OBJ_TYPE_FALSE: { | ||
89 | return true; | ||
90 | } break; | ||
91 | case OBJ_TYPE_FIXNUM: { | ||
92 | return a.fixnum == b.fixnum; | ||
93 | } break; | ||
94 | case OBJ_TYPE_SYMBOL: | ||
95 | case OBJ_TYPE_STRING: { | ||
96 | if (array_size(a.text) != array_size(b.text)) { | ||
97 | return false; | ||
98 | } | ||
99 | for (size_t i = 0; i < array_size(a.text); i++) { | ||
100 | if (a.text[i] != b.text[i]) { | ||
101 | return false; | ||
102 | } | ||
103 | } | ||
104 | } break; | ||
105 | default: { | ||
106 | return false; | ||
107 | } break; | ||
108 | } | ||
109 | return true; | ||
110 | } | ||
111 | |||
112 | Object | ||
113 | object_copy(Object src) { | ||
114 | switch (src.type) { | ||
115 | case OBJ_TYPE_SYMBOL: | ||
116 | case OBJ_TYPE_STRING: { | ||
117 | Object copy = src; | ||
118 | copy.text = NULL; | ||
119 | array_init(copy.text, array_size(src.text)); | ||
120 | array_insert(copy.text, src.text, array_size(src.text)); | ||
121 | return copy; | ||
122 | } break; | ||
123 | default: { break; } break; | ||
124 | } | ||
125 | return src; | ||
126 | } | ||
diff --git a/src/bytecode/objects.h b/src/bytecode/objects.h index 9744071..72f7420 100755 --- a/src/bytecode/objects.h +++ b/src/bytecode/objects.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include "string_view.h" | 4 | #include "string_view.h" |
5 | #include "darray.h" | 5 | #include "darray.h" |
6 | #include "chunk.h" | ||
6 | 7 | ||
7 | typedef enum ObjectType { | 8 | typedef enum ObjectType { |
8 | OBJ_TYPE_NIL, | 9 | OBJ_TYPE_NIL, |
@@ -16,8 +17,6 @@ typedef enum ObjectType { | |||
16 | OBJ_TYPE_ERR, | 17 | OBJ_TYPE_ERR, |
17 | } ObjectType; | 18 | } ObjectType; |
18 | 19 | ||
19 | struct Environment; | ||
20 | |||
21 | typedef struct Object { | 20 | typedef struct Object { |
22 | ObjectType type; | 21 | ObjectType type; |
23 | bool marked; | 22 | bool marked; |
@@ -38,6 +37,9 @@ typedef struct Object { | |||
38 | // }; | 37 | // }; |
39 | 38 | ||
40 | // OBJ_TYPE_LAMBDA | 39 | // OBJ_TYPE_LAMBDA |
40 | struct { | ||
41 | Chunk *chunk; | ||
42 | }; | ||
41 | // struct { | 43 | // struct { |
42 | // struct Object *params; | 44 | // struct Object *params; |
43 | // struct Object *body; | 45 | // struct Object *body; |
@@ -46,7 +48,13 @@ typedef struct Object { | |||
46 | }; | 48 | }; |
47 | } Object; | 49 | } Object; |
48 | 50 | ||
49 | void display(Object obj); | 51 | Object make_string(StringView sv); |
52 | Object make_symbol(StringView sv); | ||
53 | Object make_lambda(void); | ||
54 | void object_display(Object obj); | ||
55 | void object_free(Object obj); | ||
56 | bool object_equal(Object a, Object b); | ||
57 | Object object_copy(Object src); | ||
50 | 58 | ||
51 | // Value initialization. | 59 | // Value initialization. |
52 | #define NIL_VAL ((Object){.type = OBJ_TYPE_NIL}) | 60 | #define NIL_VAL ((Object){.type = OBJ_TYPE_NIL}) |
@@ -64,115 +72,7 @@ void display(Object obj); | |||
64 | #define IS_FIXNUM(VAL) ((VAL).type == OBJ_TYPE_FIXNUM) | 72 | #define IS_FIXNUM(VAL) ((VAL).type == OBJ_TYPE_FIXNUM) |
65 | #define IS_STRING(VAL) ((VAL).type == OBJ_TYPE_STRING) | 73 | #define IS_STRING(VAL) ((VAL).type == OBJ_TYPE_STRING) |
66 | #define IS_SYMBOL(VAL) ((VAL).type == OBJ_TYPE_SYMBOL) | 74 | #define IS_SYMBOL(VAL) ((VAL).type == OBJ_TYPE_SYMBOL) |
75 | #define IS_LAMBDA(VAL) ((VAL).type == OBJ_TYPE_LAMBDA) | ||
67 | 76 | ||
68 | Object make_string(StringView sv) { | ||
69 | Object obj = { | ||
70 | .type = OBJ_TYPE_STRING, | ||
71 | .text = NULL, | ||
72 | }; | ||
73 | array_init(obj.text, sv.n); | ||
74 | array_insert(obj.text, sv.start, sv.n); | ||
75 | return obj; | ||
76 | } | ||
77 | |||
78 | Object make_symbol(StringView sv) { | ||
79 | Object obj = { | ||
80 | .type = OBJ_TYPE_SYMBOL, | ||
81 | .text = NULL, | ||
82 | }; | ||
83 | array_init(obj.text, sv.n); | ||
84 | array_insert(obj.text, sv.start, sv.n); | ||
85 | return obj; | ||
86 | } | ||
87 | |||
88 | void | ||
89 | display(Object obj) { | ||
90 | switch (obj.type) { | ||
91 | case OBJ_TYPE_FIXNUM: { | ||
92 | printf("%zd", obj.fixnum); | ||
93 | } break; | ||
94 | case OBJ_TYPE_TRUE: { | ||
95 | printf("true"); | ||
96 | } break; | ||
97 | case OBJ_TYPE_FALSE: { | ||
98 | printf("false"); | ||
99 | } break; | ||
100 | case OBJ_TYPE_NIL: { | ||
101 | printf("()"); | ||
102 | } break; | ||
103 | case OBJ_TYPE_STRING: { | ||
104 | printf("\"%.*s\"", (int)array_size(obj.text), obj.text); | ||
105 | } break; | ||
106 | case OBJ_TYPE_SYMBOL: { | ||
107 | printf(":%.*s", (int)array_size(obj.text), obj.text); | ||
108 | } break; | ||
109 | case OBJ_TYPE_PAIR: { | ||
110 | // printf("("); | ||
111 | // display_pair(obj); | ||
112 | // printf(")"); | ||
113 | } break; | ||
114 | case OBJ_TYPE_LAMBDA: { | ||
115 | printf("#{procedure}"); | ||
116 | } break; | ||
117 | case OBJ_TYPE_ERR: { | ||
118 | printf("#{error}"); | ||
119 | } break; | ||
120 | } | ||
121 | return; | ||
122 | } | ||
123 | |||
124 | void | ||
125 | object_free(Object obj) { | ||
126 | if (IS_STRING(obj) || IS_SYMBOL(obj)) { | ||
127 | array_free(obj.text); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | bool | ||
132 | object_equal(Object a, Object b) { | ||
133 | if (a.type != b.type) { | ||
134 | return false; | ||
135 | } | ||
136 | switch (a.type) { | ||
137 | case OBJ_TYPE_TRUE: | ||
138 | case OBJ_TYPE_FALSE: { | ||
139 | return true; | ||
140 | } break; | ||
141 | case OBJ_TYPE_FIXNUM: { | ||
142 | return a.fixnum == b.fixnum; | ||
143 | } break; | ||
144 | case OBJ_TYPE_SYMBOL: | ||
145 | case OBJ_TYPE_STRING: { | ||
146 | if (array_size(a.text) != array_size(b.text)) { | ||
147 | return false; | ||
148 | } | ||
149 | for (size_t i = 0; i < array_size(a.text); i++) { | ||
150 | if (a.text[i] != b.text[i]) { | ||
151 | return false; | ||
152 | } | ||
153 | } | ||
154 | } break; | ||
155 | default: { | ||
156 | return false; | ||
157 | } break; | ||
158 | } | ||
159 | return true; | ||
160 | } | ||
161 | |||
162 | Object | ||
163 | object_copy(Object src) { | ||
164 | switch (src.type) { | ||
165 | case OBJ_TYPE_SYMBOL: | ||
166 | case OBJ_TYPE_STRING: { | ||
167 | Object copy = src; | ||
168 | copy.text = NULL; | ||
169 | array_init(copy.text, array_size(src.text)); | ||
170 | array_insert(copy.text, src.text, array_size(src.text)); | ||
171 | return copy; | ||
172 | } break; | ||
173 | default: { break; } break; | ||
174 | } | ||
175 | return src; | ||
176 | } | ||
177 | 77 | ||
178 | #endif // BDL_OBJECTS_H | 78 | #endif // BDL_OBJECTS_H |
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index 96e36de..b6f9848 100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h | |||
@@ -140,7 +140,7 @@ vm_interpret(VM *vm, Chunk *chunk) { | |||
140 | #ifdef DEBUG_TRACE_EXECUTION | 140 | #ifdef DEBUG_TRACE_EXECUTION |
141 | printf("stack: [ "); | 141 | printf("stack: [ "); |
142 | for (size_t i = 0; i < array_size(vm->stack); i++) { | 142 | for (size_t i = 0; i < array_size(vm->stack); i++) { |
143 | display(vm->stack[i]); | 143 | object_display(vm->stack[i]); |
144 | if (i < array_size(vm->stack) - 1) { | 144 | if (i < array_size(vm->stack) - 1) { |
145 | printf(" | "); | 145 | printf(" | "); |
146 | } | 146 | } |
@@ -211,7 +211,7 @@ vm_interpret(VM *vm, Chunk *chunk) { | |||
211 | } | 211 | } |
212 | } break; | 212 | } break; |
213 | case OP_DISPLAY: { | 213 | case OP_DISPLAY: { |
214 | display(array_pop(vm->stack)); | 214 | object_display(array_pop(vm->stack)); |
215 | } break; | 215 | } break; |
216 | case OP_PRINT: { | 216 | case OP_PRINT: { |
217 | Object obj = array_pop(vm->stack); | 217 | Object obj = array_pop(vm->stack); |