sardonyx 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/sdx +32 -0
- data/lib/sdx/compiler/compiler.rb +183 -0
- data/lib/sdx/compiler/parser.rb +522 -0
- data/lib/sdx/vm/datatypes.rb +410 -0
- data/lib/sdx/vm/scope.rb +60 -0
- data/lib/sdx/vm/variables.rb +19 -0
- data/lib/sdx/vm/vm.rb +385 -0
- metadata +51 -0
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
require "sdx/vm/vm"
|
|
2
|
+
require "sdx/vm/variables"
|
|
3
|
+
require "stringio"
|
|
4
|
+
|
|
5
|
+
class DataType
|
|
6
|
+
attr_reader :internal
|
|
7
|
+
attr_reader :fields
|
|
8
|
+
|
|
9
|
+
@fields
|
|
10
|
+
def initialize(val=nil)
|
|
11
|
+
@internal = val
|
|
12
|
+
@fields = {}
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class NativeFnInternal
|
|
17
|
+
attr_reader :arity
|
|
18
|
+
|
|
19
|
+
def initialize(val=nil)
|
|
20
|
+
@internal = val
|
|
21
|
+
@arity = IntInternal.new val.arity
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def call(*args)
|
|
25
|
+
@internal.call *args
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class IntInternal < DataType
|
|
30
|
+
def initialize(val)
|
|
31
|
+
@internal = val
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class NativeFn < DataType
|
|
36
|
+
def initialize(arity, val)
|
|
37
|
+
@internal = val
|
|
38
|
+
@fields = {
|
|
39
|
+
"__call" => (NativeFnInternal.new (Proc.new do |args|
|
|
40
|
+
args.reverse!
|
|
41
|
+
@internal.call *args
|
|
42
|
+
end)),
|
|
43
|
+
"__arity" => (Int.new arity)
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class Bool < DataType
|
|
49
|
+
def initialize(val=nil)
|
|
50
|
+
if val
|
|
51
|
+
@internal = true
|
|
52
|
+
else
|
|
53
|
+
@internal = false
|
|
54
|
+
end
|
|
55
|
+
@fields = {
|
|
56
|
+
"__as_string" => (NativeFn.new 0, (Proc.new do
|
|
57
|
+
as_string
|
|
58
|
+
end)),
|
|
59
|
+
"__as_code_string" => (NativeFn.new 0, (Proc.new do
|
|
60
|
+
as_string
|
|
61
|
+
end))
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def as_string
|
|
66
|
+
Str.new ({ true => "true", false => "false" }[@internal])
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class Int < DataType
|
|
71
|
+
def initialize(val=nil)
|
|
72
|
+
if val != nil
|
|
73
|
+
@internal = val
|
|
74
|
+
end
|
|
75
|
+
@fields = {
|
|
76
|
+
"__as_string" => (NativeFnInternal.new (Proc.new do
|
|
77
|
+
as_string
|
|
78
|
+
end)),
|
|
79
|
+
"__as_code_string" => (NativeFnInternal.new (Proc.new do
|
|
80
|
+
as_string
|
|
81
|
+
end)),
|
|
82
|
+
"__as_bool" => (NativeFnInternal.new (Proc.new do
|
|
83
|
+
as_bool
|
|
84
|
+
end)),
|
|
85
|
+
"__add" => (NativeFnInternal.new (Proc.new do |other|
|
|
86
|
+
add other
|
|
87
|
+
end)),
|
|
88
|
+
"__sub" => (NativeFnInternal.new (Proc.new do |other|
|
|
89
|
+
sub other
|
|
90
|
+
end)),
|
|
91
|
+
"__mul" => (NativeFnInternal.new (Proc.new do |other|
|
|
92
|
+
mul other
|
|
93
|
+
end)),
|
|
94
|
+
"__div" => (NativeFnInternal.new (Proc.new do |other|
|
|
95
|
+
div other
|
|
96
|
+
end)),
|
|
97
|
+
"__mod" => (NativeFnInternal.new (Proc.new do |other|
|
|
98
|
+
mod other
|
|
99
|
+
end)),
|
|
100
|
+
"__pow" => (NativeFnInternal.new (Proc.new do |other|
|
|
101
|
+
pow other
|
|
102
|
+
end))
|
|
103
|
+
}
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def as_string
|
|
107
|
+
Str.new @internal.to_s
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def as_bool
|
|
111
|
+
Bool.new true
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def add(other)
|
|
115
|
+
Int.new @internal + other.internal
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def sub(other)
|
|
119
|
+
Int.new @internal - other.internal
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def mul(other)
|
|
123
|
+
Int.new @internal * other.internal
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def div(other)
|
|
127
|
+
Int.new @internal / other.internal
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def mod(other)
|
|
131
|
+
Int.new @internal % other.internal
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def pow(other)
|
|
135
|
+
Int.new @internal ** other.internal
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
class Str < DataType
|
|
140
|
+
def initialize(val=nil)
|
|
141
|
+
if val != nil
|
|
142
|
+
@internal = val
|
|
143
|
+
end
|
|
144
|
+
@fields = {
|
|
145
|
+
"__as_string" => (NativeFnInternal.new (Proc.new do
|
|
146
|
+
as_string
|
|
147
|
+
end)),
|
|
148
|
+
"__as_code_string" => (NativeFnInternal.new (Proc.new do
|
|
149
|
+
as_code_string
|
|
150
|
+
end)),
|
|
151
|
+
"__add" => (NativeFnInternal.new (Proc.new do |other|
|
|
152
|
+
add other
|
|
153
|
+
end)),
|
|
154
|
+
"__mul" => (NativeFnInternal.new (Proc.new do |other|
|
|
155
|
+
mul other
|
|
156
|
+
end))
|
|
157
|
+
}
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def as_string
|
|
161
|
+
(Str.new @internal)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def as_code_string
|
|
165
|
+
(Str.new "\"#{@internal}\"")
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def add(other)
|
|
169
|
+
Str.new @internal + other.internal
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def mul(other)
|
|
173
|
+
Str.new @internal * other.internal
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
class Num < DataType
|
|
178
|
+
def initialize(val=nil)
|
|
179
|
+
if val != nil
|
|
180
|
+
@internal = val
|
|
181
|
+
end
|
|
182
|
+
@fields = {
|
|
183
|
+
"__as_string" => (NativeFnInternal.new (Proc.new do
|
|
184
|
+
as_string
|
|
185
|
+
end)),
|
|
186
|
+
"__as_code_string" => (NativeFnInternal.new (Proc.new do
|
|
187
|
+
as_string
|
|
188
|
+
end)),
|
|
189
|
+
"__as_bool" => (NativeFnInternal.new (Proc.new do
|
|
190
|
+
as_bool
|
|
191
|
+
end)),
|
|
192
|
+
"__add" => (NativeFnInternal.new (Proc.new do |other|
|
|
193
|
+
add other
|
|
194
|
+
end)),
|
|
195
|
+
"__sub" => (NativeFnInternal.new (Proc.new do |other|
|
|
196
|
+
sub other
|
|
197
|
+
end)),
|
|
198
|
+
"__mul" => (NativeFnInternal.new (Proc.new do |other|
|
|
199
|
+
mul other
|
|
200
|
+
end)),
|
|
201
|
+
"__div" => (NativeFnInternal.new (Proc.new do |other|
|
|
202
|
+
div other
|
|
203
|
+
end)),
|
|
204
|
+
"__mod" => (NativeFnInternal.new (Proc.new do |other|
|
|
205
|
+
mod other
|
|
206
|
+
end)),
|
|
207
|
+
"__pow" => (NativeFnInternal.new (Proc.new do |other|
|
|
208
|
+
pow other
|
|
209
|
+
end))
|
|
210
|
+
}
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def as_string
|
|
214
|
+
Str.new @internal.to_s
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def as_bool
|
|
218
|
+
Bool.new true
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def add(other)
|
|
222
|
+
Num.new @internal + other.internal
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def sub(other)
|
|
226
|
+
Num.new @internal - other.internal
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def mul(other)
|
|
230
|
+
Num.new @internal * other.internal
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def div(other)
|
|
234
|
+
Num.new @internal / other.internal
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def mod(other)
|
|
238
|
+
Num.new @internal % other.internal
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def pow(other)
|
|
242
|
+
Num.new @internal ** other.internal
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
class Nil < DataType
|
|
247
|
+
def initialize
|
|
248
|
+
@internal = nil
|
|
249
|
+
@fields = {
|
|
250
|
+
"__as_bool" => (NativeFnInternal.new (Proc.new do
|
|
251
|
+
Bool.new false
|
|
252
|
+
end))
|
|
253
|
+
}
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
class List < DataType
|
|
258
|
+
def initialize(val)
|
|
259
|
+
@internal = val
|
|
260
|
+
@pos = 0
|
|
261
|
+
@fields = {
|
|
262
|
+
"__as_string" => (NativeFnInternal.new (Proc.new do
|
|
263
|
+
as_string
|
|
264
|
+
end)),
|
|
265
|
+
"__as_code_string" => (NativeFnInternal.new (Proc.new do
|
|
266
|
+
as_code_string
|
|
267
|
+
end)),
|
|
268
|
+
"__reset" => (NativeFnInternal.new (Proc.new do
|
|
269
|
+
reset
|
|
270
|
+
end)),
|
|
271
|
+
"__iter" => (NativeFnInternal.new (Proc.new do
|
|
272
|
+
iter
|
|
273
|
+
end)),
|
|
274
|
+
"__add" => (NativeFnInternal.new (Proc.new do |other|
|
|
275
|
+
add other
|
|
276
|
+
end)),
|
|
277
|
+
"__mul" => (NativeFnInternal.new (Proc.new do |other|
|
|
278
|
+
mul other
|
|
279
|
+
end))
|
|
280
|
+
}
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def as_string
|
|
284
|
+
s = "["
|
|
285
|
+
@internal.each do |item|
|
|
286
|
+
s += (stringify item) + ", "
|
|
287
|
+
end
|
|
288
|
+
s = s[0..-3]
|
|
289
|
+
s += "]"
|
|
290
|
+
Str.new s
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def as_code_string
|
|
294
|
+
s = "["
|
|
295
|
+
@internal.each do |item|
|
|
296
|
+
s += (codify item) + ", "
|
|
297
|
+
end
|
|
298
|
+
s = s[0..-3]
|
|
299
|
+
s += "]"
|
|
300
|
+
Str.new s
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def reset
|
|
304
|
+
@pos = 0
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def iter
|
|
308
|
+
val = @internal[@pos]
|
|
309
|
+
@pos += 1
|
|
310
|
+
if val
|
|
311
|
+
return val
|
|
312
|
+
else
|
|
313
|
+
return Variable.new Nil.new
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def add(other)
|
|
318
|
+
return List.new [*@internal, other]
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def mul(other)
|
|
322
|
+
return List.new @internal * other.internal
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def get_type(x)
|
|
327
|
+
case x
|
|
328
|
+
when Int
|
|
329
|
+
:int
|
|
330
|
+
when Str
|
|
331
|
+
:str
|
|
332
|
+
when Bool
|
|
333
|
+
:bool
|
|
334
|
+
when Function
|
|
335
|
+
:fn
|
|
336
|
+
when List
|
|
337
|
+
:list
|
|
338
|
+
when Nil
|
|
339
|
+
:nil
|
|
340
|
+
when Num
|
|
341
|
+
:num
|
|
342
|
+
when Obj
|
|
343
|
+
:object
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
class Function < DataType
|
|
348
|
+
attr_reader :args
|
|
349
|
+
|
|
350
|
+
def initialize(args, body)
|
|
351
|
+
@args = args
|
|
352
|
+
@internal = body
|
|
353
|
+
|
|
354
|
+
@fields = {
|
|
355
|
+
"__call" => (NativeFnInternal.new (Proc.new do |args, scope|
|
|
356
|
+
call args, scope
|
|
357
|
+
end)),
|
|
358
|
+
"__arity" => (Int.new args.size)
|
|
359
|
+
}
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def call(passed, scope)
|
|
363
|
+
passed.reverse!
|
|
364
|
+
vm = VM.new StringIO.new @internal
|
|
365
|
+
scope.variables.each do |k|
|
|
366
|
+
vm.global.add_var k[0], (scope.get_var k[0])
|
|
367
|
+
end
|
|
368
|
+
args.each_with_index do |arg, i|
|
|
369
|
+
vm.global.add_var arg, passed[i]
|
|
370
|
+
end
|
|
371
|
+
vm.interpret
|
|
372
|
+
vm.stack[-1]
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
class Obj < DataType
|
|
377
|
+
attr_reader :args
|
|
378
|
+
|
|
379
|
+
def initialize(args, body)
|
|
380
|
+
@args = args
|
|
381
|
+
@internal = body
|
|
382
|
+
|
|
383
|
+
@fields = {
|
|
384
|
+
"__new" => (NativeFnInternal.new (Proc.new do |args, scope|
|
|
385
|
+
_new args, scope
|
|
386
|
+
end)),
|
|
387
|
+
"__arity" => (Int.new args.size)
|
|
388
|
+
}
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def _new(passed, scope)
|
|
392
|
+
passed.reverse!
|
|
393
|
+
vm = VM.new StringIO.new @internal
|
|
394
|
+
scope.variables.each do |k|
|
|
395
|
+
vm.global.add_var k[0], (scope.get_var k[0])
|
|
396
|
+
end
|
|
397
|
+
args.each_with_index do |arg, i|
|
|
398
|
+
vm.global.add_var arg, passed[i]
|
|
399
|
+
end
|
|
400
|
+
vm.interpret
|
|
401
|
+
vm.global
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
class InstantiatedObj < DataType
|
|
406
|
+
def initialize(scope)
|
|
407
|
+
@internal = scope
|
|
408
|
+
@fields = scope.variables
|
|
409
|
+
end
|
|
410
|
+
end
|
data/lib/sdx/vm/scope.rb
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
class GLOBAL_SCOPE
|
|
2
|
+
attr_reader :variables
|
|
3
|
+
|
|
4
|
+
def error(msg)
|
|
5
|
+
puts "\x1b[0;31mError in VM: #{msg}\x1b[0;0m"
|
|
6
|
+
exit 1
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize(variables={})
|
|
10
|
+
@variables = variables
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def add_var(var_name, var_class)
|
|
14
|
+
@variables[var_name] = var_class
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def add_fn(fn_name, fn_class)
|
|
18
|
+
@variables[fn_name] = fn_class
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def get_var(var_name)
|
|
22
|
+
scope = self
|
|
23
|
+
val = nil
|
|
24
|
+
name = var_name.split "."
|
|
25
|
+
name.each do |part|
|
|
26
|
+
val = scope.variables[part]
|
|
27
|
+
unless val
|
|
28
|
+
error "No such variable #{part}"
|
|
29
|
+
end
|
|
30
|
+
case val.value
|
|
31
|
+
when InstantiatedObj
|
|
32
|
+
scope = val.value.internal
|
|
33
|
+
else
|
|
34
|
+
fields = {}
|
|
35
|
+
if val.value.respond_to? :fields
|
|
36
|
+
val.value.fields.each do |k, v|
|
|
37
|
+
fields[k] = Variable.new v, (get_type v), self
|
|
38
|
+
end
|
|
39
|
+
scope = GLOBAL_SCOPE.new fields
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
return val
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def get_fn(fn_name)
|
|
47
|
+
@variables[fn_name]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def add_obj(obj_name, obj_class)
|
|
51
|
+
if obj_class.value.args.size == 0
|
|
52
|
+
scope = obj_class.value.fields["__new"].call [], self
|
|
53
|
+
scope.variables.each do |k, v|
|
|
54
|
+
add_var "#{obj_name}:#{k}", scope.variables[k]
|
|
55
|
+
end
|
|
56
|
+
else
|
|
57
|
+
@variables[obj_name] = obj_class
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|