Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Oh my god

  • Loading branch information...
commit 2aead052c6f656fc9ca23a4c9d51e8a92e1ca303 1 parent 93f95ed
Josep M. Bach authored
3  bin/fxvm.c
@@ -7,7 +7,6 @@ int
7 7 main(int argc, char *argv[])
8 8 {
9 9 bstring filename = bfromcstr(argv[1]);
10   - BytecodeFile *file = BytecodeFile_new(filename);
11   - VM_start(file);
  10 + VM_start(filename);
12 11 return 0;
13 12 }
2  compiler/examples/functions.rb
... ... @@ -1 +1 @@
1   --> { 3 }
  1 +puts -> a { a + 3 }.apply(nil, 123)
4 compiler/examples/primitives.rb
... ... @@ -1,4 +0,0 @@
1   -puts VM.primitives[:+].apply(3, 4)
2   -puts VM.primitives[:-].apply(4, 3)
3   -puts VM.primitives[:*].apply(4, 3)
4   -puts VM.primitives[:/].apply(4, 2)
1  compiler/examples/vm.rb
... ... @@ -1 +0,0 @@
1   -puts VM.primitives
13 compiler/kernel/prelude.rb
... ... @@ -1,2 +1,11 @@
1   -self.print = VM.primitives[:print]
2   -self.puts = VM.primitives[:puts]
  1 +VM.types[:object].clone = VM.primitives[:clone]
  2 +VM.types[:object].print = VM.primitives[:print]
  3 +VM.types[:object].puts = VM.primitives[:puts]
  4 +
  5 +VM.types[:integer][:+] = VM.primitives[:'integer_+']
  6 +VM.types[:integer][:-] = VM.primitives[:'integer_-']
  7 +VM.types[:integer][:/] = VM.primitives[:'integer_/']
  8 +VM.types[:integer][:*] = VM.primitives[:'integer_*']
  9 +
  10 +VM.types[:vector][:[]] = VM.primitives[:'vector_[]']
  11 +VM.types[:vector][:to_map] = VM.primitives[:vector_to_map]
17 compiler/lib/terror/visitor.rb
@@ -115,7 +115,7 @@ def slot_retrieval(node, parent)
115 115
116 116 def attribute_assignment(node, parent)
117 117 receiver_name = if node.receiver.is_a?(Rubinius::AST::Self)
118   - 'self'
  118 + :self
119 119 else
120 120 node.receiver.name
121 121 end
@@ -128,6 +128,21 @@ def attribute_assignment(node, parent)
128 128 g.setslot attribute_name
129 129 end
130 130
  131 + def element_assignment(node, parent)
  132 + receiver_name = if node.receiver.is_a?(Rubinius::AST::Self)
  133 + :self
  134 + else
  135 + node.receiver.name
  136 + end
  137 + attribute_name = node.arguments.array.first.value
  138 + @slots[receiver_name] ||= []
  139 + @slots[receiver_name] << attribute_name
  140 +
  141 + node.receiver.lazy_visit self
  142 + node.arguments.array[1].lazy_visit self
  143 + g.setslot attribute_name
  144 + end
  145 +
131 146 def array_literal(node, parent)
132 147 node.body.reverse.each do |element|
133 148 element.lazy_visit self
32 compiler/test/terror/visitor_test.rb
@@ -124,23 +124,6 @@ def compiles(code, &block)
124 124 _setslot 2
125 125 end
126 126 end
127   -
128   - it 'compiles objects with getters and setters' do
129   - compiles("a = 3; a.foo = 9; a.foo") do
130   - # a = 3
131   - _push 0
132   - _setlocal 0
133   -
134   - # a.foo = 9
135   - _pushlocal 0
136   - _push 1
137   - _setslot 2
138   -
139   - # a.foo
140   - _pushlocal 0
141   - _getslot 2
142   - end
143   - end
144 127 end
145 128
146 129 describe 'constants' do
@@ -194,6 +177,21 @@ def compiles(code, &block)
194 177 _setslot 1
195 178 end
196 179 end
  180 +
  181 + it 'is compiled with hash syntax' do
  182 + compiles("a = 2; a[:foo] = 'bar'; a[:foo]") do
  183 + _push 0
  184 + _setlocal 0
  185 +
  186 + _pushlocal 0
  187 + _push 1
  188 + _setslot 2
  189 +
  190 + _pushlocal 0
  191 + _push 1
  192 + _send 2, 1
  193 + end
  194 + end
197 195 end
198 196 end
199 197 end
23 examples/functions.tvm
... ... @@ -1,14 +1,33 @@
1 1 _main
2   -:1:4
  2 +:4:14
3 3 "block_508
  4 +123
  5 +"apply
  6 +"puts
  7 +16 PUSHSELF
4 8 67 DEFN
5 9 0
6 10 20 PUSHNIL
  11 +17 PUSH
  12 +1
  13 +128 SEND
  14 +2
  15 +2
  16 +128 SEND
  17 +3
  18 +1
  19 +20 PUSHNIL
7 20 144 RET
8 21 _block_508
9   -:1:3
  22 +:2:8
10 23 3
  24 +"+
  25 +32 PUSHLOCAL
  26 +0
11 27 17 PUSH
12 28 0
  29 +128 SEND
  30 +1
  31 +1
13 32 144 RET
14 33
56 examples/objects.tvm
... ... @@ -1,7 +1,6 @@
1 1 _main
2   -:14:92
3   -"Object
4   -"new
  2 +:13:91
  3 +"to_map
5 4 50
6 5 "age
7 6 1000
@@ -14,95 +13,94 @@ _main
14 13 "Parent money:
15 14 "Child age:
16 15 "Child money:
17   -16 PUSHSELF
18   -64 GETSLOT
  16 +68 MAKEVEC
19 17 0
20 18 128 SEND
21   -1
  19 +0
22 20 0
23 21 33 SETLOCAL
24 22 0
25 23 32 PUSHLOCAL
26 24 0
27 25 17 PUSH
28   -2
  26 +1
29 27 65 SETSLOT
30   -3
  28 +2
31 29 32 PUSHLOCAL
32 30 0
33 31 17 PUSH
34   -4
  32 +3
35 33 65 SETSLOT
36   -5
  34 +4
37 35 32 PUSHLOCAL
38 36 0
39 37 128 SEND
40   -6
  38 +5
41 39 0
42 40 33 SETLOCAL
43 41 1
44 42 32 PUSHLOCAL
45 43 1
46 44 17 PUSH
47   -7
  45 +6
48 46 65 SETSLOT
49   -3
  47 +2
50 48 16 PUSHSELF
51 49 17 PUSH
52   -8
  50 +7
53 51 128 SEND
54   -9
  52 +8
55 53 1
56 54 16 PUSHSELF
57 55 32 PUSHLOCAL
58 56 0
59 57 64 GETSLOT
60   -3
  58 +2
61 59 128 SEND
62   -10
  60 +9
63 61 1
64 62 16 PUSHSELF
65 63 17 PUSH
66   -11
  64 +10
67 65 128 SEND
68   -9
  66 +8
69 67 1
70 68 16 PUSHSELF
71 69 32 PUSHLOCAL
72 70 0
73 71 64 GETSLOT
74   -5
  72 +4
75 73 128 SEND
76   -10
  74 +9
77 75 1
78 76 16 PUSHSELF
79 77 17 PUSH
80   -12
  78 +11
81 79 128 SEND
82   -9
  80 +8
83 81 1
84 82 16 PUSHSELF
85 83 32 PUSHLOCAL
86 84 1
87 85 64 GETSLOT
88   -3
  86 +2
89 87 128 SEND
90   -10
  88 +9
91 89 1
92 90 16 PUSHSELF
93 91 17 PUSH
94   -13
  92 +12
95 93 128 SEND
96   -9
  94 +8
97 95 1
98 96 16 PUSHSELF
99 97 32 PUSHLOCAL
100 98 1
101 99 128 SEND
102   -5
  100 +4
103 101 0
104 102 128 SEND
105   -10
  103 +9
106 104 1
107 105 20 PUSHNIL
108 106 144 RET
105 examples/primitives.tvm
... ... @@ -1,105 +0,0 @@
1   -_main
2   -:12:90
3   -"VM
4   -"primitives
5   -"+
6   -"[]
7   -3
8   -4
9   -"apply
10   -"puts
11   -"-
12   -"*
13   -"/
14   -2
15   -16 PUSHSELF
16   -16 PUSHSELF
17   -64 GETSLOT
18   -0
19   -128 SEND
20   -1
21   -0
22   -17 PUSH
23   -2
24   -128 SEND
25   -3
26   -1
27   -17 PUSH
28   -4
29   -17 PUSH
30   -5
31   -128 SEND
32   -6
33   -2
34   -128 SEND
35   -7
36   -1
37   -16 PUSHSELF
38   -16 PUSHSELF
39   -64 GETSLOT
40   -0
41   -128 SEND
42   -1
43   -0
44   -17 PUSH
45   -8
46   -128 SEND
47   -3
48   -1
49   -17 PUSH
50   -5
51   -17 PUSH
52   -4
53   -128 SEND
54   -6
55   -2
56   -128 SEND
57   -7
58   -1
59   -16 PUSHSELF
60   -16 PUSHSELF
61   -64 GETSLOT
62   -0
63   -128 SEND
64   -1
65   -0
66   -17 PUSH
67   -9
68   -128 SEND
69   -3
70   -1
71   -17 PUSH
72   -5
73   -17 PUSH
74   -4
75   -128 SEND
76   -6
77   -2
78   -128 SEND
79   -7
80   -1
81   -16 PUSHSELF
82   -16 PUSHSELF
83   -64 GETSLOT
84   -0
85   -128 SEND
86   -1
87   -0
88   -17 PUSH
89   -10
90   -128 SEND
91   -3
92   -1
93   -17 PUSH
94   -5
95   -17 PUSH
96   -11
97   -128 SEND
98   -6
99   -2
100   -128 SEND
101   -7
102   -1
103   -20 PUSHNIL
104   -144 RET
105   -
18 examples/vm.tvm
... ... @@ -1,18 +0,0 @@
1   -_main
2   -:3:12
3   -"VM
4   -"primitives
5   -"puts
6   -16 PUSHSELF
7   -16 PUSHSELF
8   -64 GETSLOT
9   -0
10   -128 SEND
11   -1
12   -0
13   -128 SEND
14   -2
15   -1
16   -20 PUSHNIL
17   -144 RET
18   -
208 kernel/prelude.tvm
... ... @@ -1,11 +1,50 @@
1 1 _main
2   -:5:30
  2 +:21:218
3 3 "VM
  4 +"types
  5 +"object
  6 +"[]
4 7 "primitives
  8 +"clone
5 9 "print
6   -"[]
7 10 "puts
  11 +"integer
  12 +"integer_+
  13 +"+
  14 +"integer_-
  15 +"-
  16 +"integer_/
  17 +"/
  18 +"integer_*
  19 +"*
  20 +"vector
  21 +"vector_[]
  22 +"vector_to_map
  23 +"to_map
8 24 16 PUSHSELF
  25 +64 GETSLOT
  26 +0
  27 +128 SEND
  28 +1
  29 +0
  30 +17 PUSH
  31 +2
  32 +128 SEND
  33 +3
  34 +1
  35 +16 PUSHSELF
  36 +64 GETSLOT
  37 +0
  38 +128 SEND
  39 +4
  40 +0
  41 +17 PUSH
  42 +5
  43 +128 SEND
  44 +3
  45 +1
  46 +65 SETSLOT
  47 +5
9 48 16 PUSHSELF
10 49 64 GETSLOT
11 50 0
@@ -17,9 +56,43 @@ _main
17 56 128 SEND
18 57 3
19 58 1
  59 +16 PUSHSELF
  60 +64 GETSLOT
  61 +0
  62 +128 SEND
  63 +4
  64 +0
  65 +17 PUSH
  66 +6
  67 +128 SEND
  68 +3
  69 +1
20 70 65 SETSLOT
  71 +6
  72 +16 PUSHSELF
  73 +64 GETSLOT
  74 +0
  75 +128 SEND
  76 +1
  77 +0
  78 +17 PUSH
21 79 2
  80 +128 SEND
  81 +3
  82 +1
22 83 16 PUSHSELF
  84 +64 GETSLOT
  85 +0
  86 +128 SEND
  87 +4
  88 +0
  89 +17 PUSH
  90 +7
  91 +128 SEND
  92 +3
  93 +1
  94 +65 SETSLOT
  95 +7
23 96 16 PUSHSELF
24 97 64 GETSLOT
25 98 0
@@ -27,12 +100,143 @@ _main
27 100 1
28 101 0
29 102 17 PUSH
  103 +8
  104 +128 SEND
  105 +3
  106 +1
  107 +16 PUSHSELF
  108 +64 GETSLOT
  109 +0
  110 +128 SEND
30 111 4
  112 +0
  113 +17 PUSH
  114 +9
31 115 128 SEND
32 116 3
33 117 1
34 118 65 SETSLOT
  119 +10
  120 +16 PUSHSELF
  121 +64 GETSLOT
  122 +0
  123 +128 SEND
  124 +1
  125 +0
  126 +17 PUSH
  127 +8
  128 +128 SEND
  129 +3
  130 +1
  131 +16 PUSHSELF
  132 +64 GETSLOT
  133 +0
  134 +128 SEND
35 135 4
  136 +0
  137 +17 PUSH
  138 +11
  139 +128 SEND
  140 +3
  141 +1
  142 +65 SETSLOT
  143 +12
  144 +16 PUSHSELF
  145 +64 GETSLOT
  146 +0
  147 +128 SEND
  148 +1
  149 +0
  150 +17 PUSH
  151 +8
  152 +128 SEND
  153 +3
  154 +1
  155 +16 PUSHSELF
  156 +64 GETSLOT
  157 +0
  158 +128 SEND
  159 +4
  160 +0
  161 +17 PUSH
  162 +13
  163 +128 SEND
  164 +3
  165 +1
  166 +65 SETSLOT
  167 +14
  168 +16 PUSHSELF
  169 +64 GETSLOT
  170 +0
  171 +128 SEND
  172 +1
  173 +0
  174 +17 PUSH
  175 +8
  176 +128 SEND
  177 +3
  178 +1
  179 +16 PUSHSELF
  180 +64 GETSLOT
  181 +0
  182 +128 SEND
  183 +4
  184 +0
  185 +17 PUSH
  186 +15
  187 +128 SEND
  188 +3
  189 +1
  190 +65 SETSLOT
  191 +16
  192 +16 PUSHSELF
  193 +64 GETSLOT
  194 +0
  195 +128 SEND
  196 +1
  197 +0
  198 +17 PUSH
  199 +17
  200 +128 SEND
  201 +3
  202 +1
  203 +16 PUSHSELF
  204 +64 GETSLOT
  205 +0
  206 +128 SEND
  207 +4
  208 +0
  209 +17 PUSH
  210 +18
  211 +128 SEND
  212 +3
  213 +1
  214 +65 SETSLOT
  215 +3
  216 +16 PUSHSELF
  217 +64 GETSLOT
  218 +0
  219 +128 SEND
  220 +1
  221 +0
  222 +17 PUSH
  223 +17
  224 +128 SEND
  225 +3
  226 +1
  227 +16 PUSHSELF
  228 +64 GETSLOT
  229 +0
  230 +128 SEND
  231 +4
  232 +0
  233 +17 PUSH
  234 +19
  235 +128 SEND
  236 +3
  237 +1
  238 +65 SETSLOT
  239 +20
36 240 20 PUSHNIL
37 241 144 RET
38 242
16 src/forkix/bootstrap.c
@@ -41,22 +41,35 @@ expose_VM(VALUE lobby)
41 41 // VM.primitives map
42 42 DArray *primitives = DArray_create(sizeof(VALUE), 10);
43 43
  44 + // Object
44 45 DEFPRIM(primitives, "print", Primitive_print);
45 46 DEFPRIM(primitives, "puts", Primitive_puts);
46 47 DEFPRIM(primitives, "require", Primitive_require);
  48 + DEFPRIM(primitives, "clone", Primitive_clone);
  49 +
  50 + // Vector
  51 + DEFPRIM(primitives, "vector_[]", Primitive_Vector_at);
  52 + DEFPRIM(primitives, "vector_to_map", Primitive_Vector_to_map);
  53 +
  54 + // Integer
  55 + DEFPRIM(primitives, "integer_+", Primitive_Integer_add);
  56 + DEFPRIM(primitives, "integer_-", Primitive_Integer_sub);
  57 + DEFPRIM(primitives, "integer_*", Primitive_Integer_mul);
  58 + DEFPRIM(primitives, "integer_/", Primitive_Integer_div);
47 59
48 60 Value_set(vm, "primitives", Map_new(primitives));
49 61
50 62 // VM.types map
51 63 DArray *types = DArray_create(sizeof(VALUE), 10);
52 64
  65 + DEFVALUE(types, "object", Object_bp);
53 66 DEFVALUE(types, "integer", Integer_bp);
54 67 DEFVALUE(types, "string", String_bp);
55 68 DEFVALUE(types, "vector", Vector_bp);
56 69 DEFVALUE(types, "map", Map_bp);
57 70 DEFVALUE(types, "closure", Closure_bp);
58 71
59   - Value_set(vm, "types", Map_new(primitives));
  72 + Value_set(vm, "types", Map_new(types));
60 73 }
61 74
62 75 void
@@ -76,4 +89,5 @@ State_bootstrap(STATE)
76 89 debug("[BOOTSTRAP] Loading %s...", bdata(path));
77 90 Primitive_require(state, String_new(bdata(path)), NULL, NULL);
78 91 }
  92 + debug("[BOOTSTRAP] Done!");
79 93 }
3  src/forkix/gc.c
@@ -5,7 +5,10 @@ VALUE
5 5 gc_alloc(size_t size)
6 6 {
7 7 VALUE val = calloc(1, size);
  8 + check(val, "Out of memory.");
8 9 return val;
  10 +error:
  11 + return NULL;
9 12 }
10 13
11 14 void
14 src/forkix/primitives.c
@@ -12,6 +12,13 @@
12 12 */
13 13
14 14 VALUE
  15 +Primitive_clone(STATE, void *a, void *_, void *__)
  16 +{
  17 + VALUE obj = (VALUE)a;
  18 + return Value_from_prototype(obj->type, obj);
  19 +}
  20 +
  21 +VALUE
15 22 Primitive_print(STATE, void *_, void *b, void *__)
16 23 {
17 24 Value_print((VALUE)b);
@@ -149,13 +156,15 @@ Primitive_Map_get(STATE, void *a, void *b, void *_)
149 156 VALUE map = (VALUE)a;
150 157 VALUE key = (VALUE)b;
151 158
152   - CHECK_TYPE(map, MapType);
153 159 CHECK_TYPE(key, StringType);
154 160
155 161 VALUE result = Value_get(map, VAL2STR(key));
156   - if(!result) result = NilObject;
  162 + check(result, "No member named %s.", VAL2STR(key));
157 163
158 164 return result;
  165 +
  166 +error:
  167 + return NULL;
159 168 }
160 169
161 170 VALUE
@@ -165,7 +174,6 @@ Primitive_Map_set(STATE, void *a, void *b, void *c)
165 174 VALUE key = (VALUE)b;
166 175 VALUE value = (VALUE)c;
167 176
168   - CHECK_TYPE(map, MapType);
169 177 CHECK_TYPE(key, StringType);
170 178 CHECK_PRESENCE(value);
171 179
1  src/forkix/primitives.h
@@ -10,6 +10,7 @@
10 10
11 11 #define PRIMITIVE_ARGS STATE, void*, void*, void*
12 12 // Generic primitive methods
  13 +VALUE Primitive_clone(PRIMITIVE_ARGS);
13 14 VALUE Primitive_print(PRIMITIVE_ARGS);
14 15 VALUE Primitive_puts(PRIMITIVE_ARGS);
15 16 VALUE Primitive_require(PRIMITIVE_ARGS);
24 src/forkix/runtime.c
... ... @@ -1,6 +1,10 @@
1 1 #include <forkix/runtime.h>
  2 +#include <forkix/value.h>
  3 +#include <forkix/function.h>
  4 +#include <forkix/primitives.h>
2 5
3 6 // Blueprints
  7 +VALUE Object_bp = NULL;
4 8 VALUE Integer_bp = NULL;
5 9 VALUE String_bp = NULL;
6 10 VALUE Vector_bp = NULL;
@@ -12,12 +16,20 @@ VALUE TrueObject = NULL;
12 16 VALUE FalseObject = NULL;
13 17 VALUE NilObject = NULL;
14 18
  19 +#define DEFNATIVE(V, N, F) Value_set((V), (N), Closure_new(Function_native_new((F))))
  20 +
15 21 void Runtime_init() {
16   - Integer_bp = Value_new(ObjectType);
17   - String_bp = Value_new(ObjectType);
18   - Vector_bp = Value_new(ObjectType);
19   - Map_bp = Value_new(ObjectType);
20   - Closure_bp = Value_new(ObjectType);
  22 + Object_bp = Value_new(ObjectType);
  23 +
  24 + // These primitives cannot go in the prelude because they are used there.
  25 + DEFNATIVE(Object_bp, "[]", Primitive_Map_get);
  26 + DEFNATIVE(Object_bp, "[]=", Primitive_Map_set);
  27 +
  28 + Integer_bp = Value_from_prototype(IntegerType, Object_bp);
  29 + String_bp = Value_from_prototype(StringType, Object_bp);
  30 + Vector_bp = Value_from_prototype(VectorType, Object_bp);
  31 + Map_bp = Value_from_prototype(MapType, Object_bp);
  32 + Closure_bp = Value_from_prototype(ClosureType, Object_bp);
21 33
22 34 // Init extern constants
23 35 TrueObject = Value_new(TrueType);
@@ -31,11 +43,13 @@ void Runtime_destroy() {
31 43 Value_destroy(Vector_bp);
32 44 Value_destroy(Map_bp);
33 45 Value_destroy(Closure_bp);
  46 + Value_destroy(Object_bp);
34 47 Integer_bp = NULL;
35 48 String_bp = NULL;
36 49 Vector_bp = NULL;
37 50 Map_bp = NULL;
38 51 Closure_bp = NULL;
  52 + Object_bp = NULL;
39 53
40 54 Value_destroy(TrueObject);
41 55 TrueObject = NULL;
1  src/forkix/runtime.h
@@ -3,6 +3,7 @@
3 3
4 4 #include <forkix/value.h>
5 5
  6 +extern VALUE Object_bp;
6 7 extern VALUE Integer_bp;
7 8 extern VALUE String_bp;
8 9 extern VALUE Vector_bp;
109 src/forkix/value.c
@@ -5,6 +5,13 @@
5 5 #include <forkix/primitives.h>
6 6 #include <forkix/gc.h>
7 7
  8 +VALUE Object_bp;
  9 +VALUE Integer_bp;
  10 +VALUE String_bp;
  11 +VALUE Vector_bp;
  12 +VALUE Map_bp;
  13 +VALUE Closure_bp;
  14 +
8 15 VALUE NilObject;
9 16
10 17 VALUE
@@ -13,59 +20,108 @@ Value_new(ValueType type)
13 20 VALUE val = gc_alloc(sizeof(val_t));
14 21 val->type = type;
15 22 val->table = Hashmap_create(NULL, NULL);
  23 + val->prototype = Object_bp;
16 24 return val;
17 25 };
18 26
  27 +VALUE
  28 +Value_from_prototype(ValueType type, VALUE prototype)
  29 +{
  30 + VALUE val = Value_new(type);
  31 + val->prototype = prototype;
  32 + return val;
  33 +}
  34 +
19 35 void
20 36 Value_destroy(VALUE o)
21 37 {
22 38 gc_dealloc(o);
23 39 }
24 40
25   -void
26   -Value_print(VALUE o)
  41 +static inline int
  42 +Hashmap_print_cb(HashmapNode *node) {
  43 + char *name = bdata((bstring)(node->key));
  44 + VALUE obj = (VALUE)(node->data);
  45 + Value_print(String_new(name));
  46 + printf(" => ");
  47 + Value_print(obj);
  48 + printf(", ");
  49 + return 0;
  50 +}
  51 +
  52 +static inline void
  53 +__Value_print(VALUE o)
27 54 {
  55 + check(o, "Cannot print NULL value");
  56 +
  57 + // Blueprints
  58 + if(o == Object_bp) { printf("Object"); return;
  59 + } else if (o == Integer_bp) { printf("Integer"); return;
  60 + } else if (o == String_bp) { printf("String"); return;
  61 + } else if (o == Closure_bp) { printf("Closure"); return;
  62 + } else if (o == Vector_bp) { printf("Vector"); return;
  63 + } else if (o == Map_bp) { printf("Map"); return;
  64 + }
  65 +
28 66 switch(o->type) {
29 67 case IntegerType: {
30   - printf("%i\n", VAL2INT(o));
  68 + printf("%i", VAL2INT(o));
31 69 break;
32 70 }
33 71 case StringType: {
34   - printf("\"%s\"\n", VAL2STR(o));
  72 + printf("\"%s\"", VAL2STR(o));
35 73 break;
36 74 }
37 75 case TrueType: {
38   - printf("true\n");
  76 + printf("true");
39 77 break;
40 78 }
41 79 case FalseType: {
42   - printf("false\n");
  80 + printf("false");
43 81 break;
44 82 }
45 83 case NilType: {
46   - printf("nil\n");
  84 + printf("nil");
47 85 break;
48 86 }
49 87 case ClosureType: {
50   - printf("#<Closure %p>\n", o);
  88 + printf("#<Closure %p>", o);
51 89 break;
52 90 }
53 91 case VectorType: {
54   - printf("#<Vector %p>\n", o);
  92 + printf("#<Vector %p>", o);
55 93 break;
56 94 }
57 95 case MapType: {
58   - printf("#<Map %p>\n", o);
  96 + printf("{");
  97 + Hashmap_traverse(o->table, Hashmap_print_cb);
  98 + printf("}");
59 99 break;
60 100 }
61 101 default: {
62   - printf("#<Object %p>\n", o);
  102 + printf("#<Object %p ", o);
  103 + printf("{");
  104 + Hashmap_traverse(o->table, Hashmap_print_cb);
  105 + printf("}>");
63 106 break;
64 107 }
65 108 }
  109 +error:
  110 + return;
66 111 }
67 112
68   -#define DEFNATIVE(V, N, F) Value_set((V), (N), Closure_new(Function_native_new((F))))
  113 +void
  114 +Value_print(VALUE o)
  115 +{
  116 + __Value_print(o);
  117 +
  118 + return; // for now
  119 + if(o->prototype) {
  120 + printf(" (");
  121 + __Value_print(o->prototype);
  122 + printf(")");
  123 + }
  124 +}
69 125
70 126 VALUE
71 127 Lobby_new()
@@ -77,21 +133,16 @@ Lobby_new()
77 133 VALUE
78 134 Integer_new(int num)
79 135 {
80   - VALUE val = Value_new(IntegerType);
  136 + VALUE val = Value_from_prototype(IntegerType, Integer_bp);
81 137 val->data.as_int = num;
82 138
83   - DEFNATIVE(val, "+", Primitive_Integer_add);
84   - DEFNATIVE(val, "-", Primitive_Integer_sub);
85   - DEFNATIVE(val, "*", Primitive_Integer_mul);
86   - DEFNATIVE(val, "/", Primitive_Integer_div);
87   -
88 139 return val;
89 140 }
90 141
91 142 VALUE
92 143 String_new(char* value)
93 144 {
94   - VALUE val = Value_new(StringType);
  145 + VALUE val = Value_from_prototype(StringType, String_bp);
95 146 val->data.as_str = value;
96 147 return val;
97 148 }
@@ -99,7 +150,7 @@ String_new(char* value)
99 150 VALUE
100 151 Closure_new(Function *fn)
101 152 {
102   - VALUE val = Value_new(ClosureType);
  153 + VALUE val = Value_from_prototype(ClosureType, Closure_bp);
103 154 val->data.as_data = fn;
104 155 return val;
105 156 }
@@ -107,19 +158,16 @@ Closure_new(Function *fn)
107 158 VALUE
108 159 Vector_new(DArray *array)
109 160 {
110   - VALUE val = Value_new(VectorType);
  161 + VALUE val = Value_from_prototype(VectorType, Vector_bp);
111 162 val->data.as_data = array;
112 163
113   - DEFNATIVE(val, "[]", Primitive_Vector_at);
114   - DEFNATIVE(val, "to_map", Primitive_Vector_to_map);
115   -
116 164 return val;
117 165 }
118 166
119 167 VALUE
120 168 Map_new(DArray *array)
121 169 {
122   - VALUE val = Value_new(MapType);
  170 + VALUE val = Value_from_prototype(MapType, Map_bp);
123 171
124 172 int count = DArray_count(array);
125 173 assert(count % 2 == 0 && "Map element count must be even.");
@@ -136,9 +184,6 @@ Map_new(DArray *array)
136 184 Hashmap_set(hash, bfromcstr(VAL2STR(key)), value);
137 185 }
138 186
139   - DEFNATIVE(val, "[]", Primitive_Map_get);
140   - DEFNATIVE(val, "[]=", Primitive_Map_set);
141   -
142 187 return val;
143 188 };
144 189
@@ -153,6 +198,12 @@ Value_set(VALUE receiver, char *key, VALUE value)
153 198 VALUE
154 199 Value_get(VALUE receiver, char *key)
155 200 {
156   - return (VALUE)Hashmap_get(receiver->table, bfromcstr(key));
  201 + VALUE result = (VALUE)Hashmap_get(receiver->table, bfromcstr(key));
  202 +
  203 + if(!result && receiver->prototype) {
  204 + result = Value_get(receiver->prototype, key);
  205 + }
  206 +
  207 + return result;
157 208 }
158 209
2  src/forkix/value.h
@@ -15,12 +15,14 @@ struct val_s {
15 15 void *as_data;
16 16 } data;
17 17 Hashmap *table;
  18 + struct val_s *prototype;
18 19 };
19 20
20 21 typedef struct val_s val_t;
21 22 #define VALUE val_t*
22 23
23 24 VALUE Value_new(ValueType);
  25 +VALUE Value_from_prototype(ValueType, VALUE);
24 26 void Value_destroy(VALUE);
25 27 void Value_print(VALUE);
26 28
52 src/forkix/vm.c
@@ -35,14 +35,16 @@ static inline void dump(Stack* stack)
35 35 #define LOCAL(A) (VALUE)DArray_at(CURR_FRAME->locals, (A))
36 36 #define LOCALSET(A, B) DArray_set(CURR_FRAME->locals, (A), (B))
37 37
38   -void VM_start(BytecodeFile *file)
  38 +void VM_start(bstring filename)
39 39 {
  40 + Runtime_init();
  41 +
  42 + BytecodeFile *file = BytecodeFile_new(filename);
  43 +
40 44 STATE = State_new(file->functions);
41 45
42 46 VALUE lobby = Lobby_new(); // toplevel object
43 47 state->lobby = lobby;
44   -
45   - Runtime_init();
46 48 CallFrame *top_frame = CallFrame_new(lobby, STATE_FN("main"), NULL);
47 49
48 50 Stack_push(FRAMES, top_frame);
@@ -129,10 +131,11 @@ VALUE VM_run(STATE)
129 131 VALUE receiver = Stack_pop(STACK);
130 132 VALUE slot = LITERAL(*ip);
131 133
  134 + check(receiver->type != NilType, "Tried to get a slot from nil.");
132 135 check(slot->type == StringType, "Slot name must be a String.");
133 136
134 137 VALUE value = Value_get(receiver, VAL2STR(slot));
135   - check(value, "Undefined slot %s.", VAL2STR(slot));
  138 + check(value, "Undefined slot %s on object type %i.", VAL2STR(slot), receiver->type);
136 139
137 140 Stack_push(STACK, value);
138 141 break;
@@ -144,6 +147,7 @@ VALUE VM_run(STATE)
144 147 VALUE receiver = Stack_pop(STACK);
145 148 VALUE slot = LITERAL(*ip);
146 149
  150 + check(receiver->type != NilType, "Tried to set a slot on nil.");
147 151 check(slot->type == StringType, "Slot name must be a String.");
148 152
149 153 Value_set(receiver, VAL2STR(slot), value);
@@ -196,20 +200,16 @@ VALUE VM_run(STATE)
196 200 if(receiver->type == ClosureType &&
197 201 strcmp(VAL2STR(name), "apply") == 0) {
198 202
199   - DArray *apply_locals = DArray_create(sizeof(VALUE), op2 + 1);
200   - int argc = op2;
201   - VALUE rcv = DArray_at(locals, 0);
202   - for(int i=0; i < argc; i++) {
203   - DArray_push(apply_locals, DArray_at(locals, i+1));
204   - }
205 203 state->ret = ip; // save where we want to return
206   - ip = Function_call(state, VAL2FN(receiver), rcv, apply_locals);
  204 + ip = Function_call(state, VAL2FN(receiver), CURR_FRAME->self, locals);
207 205 ip--;
208 206 break;
209 207 }
210 208
  209 + /* printf("Trying to get slot %s.", VAL2STR(name)); */
211 210 VALUE closure = Value_get(receiver, VAL2STR(name));
212   - check(closure, "Undefined slot %s.", VAL2STR(name));
  211 + /* printf("Tried to get slot %s.", VAL2STR(name)); */
  212 + check(closure, "Undefined slot %s on object type %i.", VAL2STR(name), receiver->type);
213 213
214 214 if (op2 == 0 && closure->type != ClosureType && closure != NilObject) {
215 215 // GETSLOT
@@ -217,6 +217,34 @@ VALUE VM_run(STATE)
217 217 break;
218 218 }
219 219
  220 + /* if(op2 == 1 && strcmp(VAL2STR(name), "[]") == 0) { // getslot */
  221 + /* VALUE key = (VALUE)DArray_at(locals, 0); */
  222 + /* Stack_push(STACK, Value_get(receiver, VAL2STR(key))); */
  223 + /* break; */
  224 + /* } */
  225 +
  226 + /* if(op2 == 2 && strcmp(VAL2STR(name), "[]=") == 0) { // setslot */
  227 + /* VALUE key = (VALUE)DArray_at(locals, 0); */
  228 + /* VALUE value = (VALUE)DArray_at(locals, 1); */
  229 + /* Value_set(receiver, VAL2STR(key), value); */
  230 + /* Stack_push(STACK, value); */
  231 + /* break; */
  232 + /* } */
  233 +
  234 + if(closure->type == StringType) {
  235 + printf("BUG\n");
  236 +
  237 + assert(receiver == Integer_bp && "Not the droids we're looking for");
  238 + VALUE cls = Value_get(receiver, "[]");
  239 + printf("SEND: Integer#[]\n\t");
  240 + Value_print(cls);
  241 + printf("\n");
  242 +
  243 + printf("Calling %s on ", VAL2STR(name));
  244 + Value_print(receiver);
  245 + printf(". The closure is a string: %s.\n", VAL2STR(closure));
  246 + }
  247 +
220 248 state->ret = ip; // save where we want to return
221 249 ip = Function_call(state, VAL2FN(closure), receiver, locals);
222 250 ip--; // because we increment after each while cycle
2  src/forkix/vm.h
@@ -7,6 +7,6 @@
7 7 #include <forkix/input_reader.h>
8 8
9 9 VALUE VM_run(STATE);
10   -void VM_start(BytecodeFile *file);
  10 +void VM_start(bstring filename);
11 11
12 12 #endif
5 tests/value_tests.c
@@ -72,8 +72,9 @@ char *test_destroy()
72 72 char *test_get()
73 73 {
74 74 VALUE obj = Integer_new(123);
75   - VALUE closure = Value_get(obj, "+");
76   - mu_assert(closure->type == ClosureType, "failed getting closure");
  75 + Value_set(obj, "foo", Integer_new(99));
  76 + VALUE number = Value_get(obj, "foo");
  77 + mu_assert(number->type == IntegerType, "failed getting member of integer");
77 78
78 79 return NULL;
79 80 }
2  tests/vm_tests.c
@@ -324,7 +324,7 @@ char *test_send_apply()
324 324
325 325 DEFN(
326 326 "echo",
327   - PUSHSELF,
  327 + PUSHLOCAL, 0,
328 328 RET
329 329 );
330 330

0 comments on commit 2aead05

Please sign in to comment.
Something went wrong with that request. Please try again.