twostroke 0.0.4 → 0.1.0

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.
Files changed (80) hide show
  1. data/lib/twostroke/ast/array.rb +8 -0
  2. data/lib/twostroke/ast/assignment.rb +7 -0
  3. data/lib/twostroke/ast/binary_operators.rb +7 -0
  4. data/lib/twostroke/ast/body.rb +6 -0
  5. data/lib/twostroke/ast/break.rb +4 -0
  6. data/lib/twostroke/ast/call.rb +7 -0
  7. data/lib/twostroke/ast/case.rb +9 -1
  8. data/lib/twostroke/ast/continue.rb +11 -0
  9. data/lib/twostroke/ast/declaration.rb +4 -0
  10. data/lib/twostroke/ast/delete.rb +6 -0
  11. data/lib/twostroke/ast/do_while.rb +7 -0
  12. data/lib/twostroke/ast/false.rb +11 -0
  13. data/lib/twostroke/ast/for_in.rb +8 -0
  14. data/lib/twostroke/ast/for_loop.rb +10 -1
  15. data/lib/twostroke/ast/function.rb +6 -0
  16. data/lib/twostroke/ast/if.rb +8 -0
  17. data/lib/twostroke/ast/index.rb +7 -0
  18. data/lib/twostroke/ast/member_access.rb +6 -0
  19. data/lib/twostroke/ast/multi_expression.rb +7 -0
  20. data/lib/twostroke/ast/new.rb +7 -0
  21. data/lib/twostroke/ast/null.rb +4 -0
  22. data/lib/twostroke/ast/number.rb +4 -0
  23. data/lib/twostroke/ast/object_literal.rb +6 -0
  24. data/lib/twostroke/ast/regexp.rb +4 -0
  25. data/lib/twostroke/ast/return.rb +6 -0
  26. data/lib/twostroke/ast/string.rb +4 -0
  27. data/lib/twostroke/ast/switch.rb +7 -0
  28. data/lib/twostroke/ast/ternary.rb +8 -0
  29. data/lib/twostroke/ast/this.rb +4 -0
  30. data/lib/twostroke/ast/throw.rb +6 -0
  31. data/lib/twostroke/ast/true.rb +11 -0
  32. data/lib/twostroke/ast/try.rb +8 -0
  33. data/lib/twostroke/ast/unary_operators.rb +7 -1
  34. data/lib/twostroke/ast/variable.rb +4 -0
  35. data/lib/twostroke/ast/while.rb +8 -1
  36. data/lib/twostroke/ast/with.rb +16 -0
  37. data/lib/twostroke/compiler/javascript.rb +396 -0
  38. data/lib/twostroke/compiler/tsasm.rb +595 -0
  39. data/lib/twostroke/compiler.rb +8 -0
  40. data/lib/twostroke/parser.rb +47 -9
  41. data/lib/twostroke/runtime/lib/array.js +144 -0
  42. data/lib/twostroke/runtime/lib/array.rb +71 -0
  43. data/lib/twostroke/runtime/lib/boolean.rb +23 -0
  44. data/lib/twostroke/runtime/lib/console.rb +13 -0
  45. data/lib/twostroke/runtime/lib/date.rb +65 -0
  46. data/lib/twostroke/runtime/lib/error.rb +36 -0
  47. data/lib/twostroke/runtime/lib/function.js +0 -0
  48. data/lib/twostroke/runtime/lib/function.rb +45 -0
  49. data/lib/twostroke/runtime/lib/math.rb +36 -0
  50. data/lib/twostroke/runtime/lib/number.rb +65 -0
  51. data/lib/twostroke/runtime/lib/object.js +0 -0
  52. data/lib/twostroke/runtime/lib/object.rb +55 -0
  53. data/lib/twostroke/runtime/lib/regexp.rb +28 -0
  54. data/lib/twostroke/runtime/lib/string.rb +86 -0
  55. data/lib/twostroke/runtime/lib/undefined.rb +7 -0
  56. data/lib/twostroke/runtime/lib.rb +42 -0
  57. data/lib/twostroke/runtime/scope.rb +120 -0
  58. data/lib/twostroke/runtime/types/array.rb +79 -0
  59. data/lib/twostroke/runtime/types/boolean.rb +23 -0
  60. data/lib/twostroke/runtime/types/boolean_object.rb +25 -0
  61. data/lib/twostroke/runtime/types/function.rb +83 -0
  62. data/lib/twostroke/runtime/types/null.rb +11 -3
  63. data/lib/twostroke/runtime/types/number.rb +31 -0
  64. data/lib/twostroke/runtime/types/number_object.rb +25 -0
  65. data/lib/twostroke/runtime/types/object.rb +169 -20
  66. data/lib/twostroke/runtime/types/regexp.rb +31 -0
  67. data/lib/twostroke/runtime/types/string.rb +16 -0
  68. data/lib/twostroke/runtime/types/string_object.rb +52 -0
  69. data/lib/twostroke/runtime/types/undefined.rb +11 -3
  70. data/lib/twostroke/runtime/types/value.rb +14 -0
  71. data/lib/twostroke/runtime/types.rb +133 -4
  72. data/lib/twostroke/runtime/vm.rb +25 -0
  73. data/lib/twostroke/runtime/vm_frame.rb +459 -0
  74. data/lib/twostroke/runtime.rb +6 -5
  75. data/lib/twostroke/tokens.rb +20 -8
  76. data/lib/twostroke.rb +3 -1
  77. metadata +41 -7
  78. data/lib/twostroke/runtime/context.rb +0 -33
  79. data/lib/twostroke/runtime/environment.rb +0 -13
  80. data/lib/twostroke/runtime/types/basic_type.rb +0 -5
@@ -0,0 +1,459 @@
1
+ module Twostroke::Runtime
2
+ class VM::Frame
3
+ attr_reader :vm, :insns, :stack, :sp_stack, :catch_stack, :finally_stack, :enum_stack, :exception, :ip, :scope
4
+
5
+ def initialize(vm, section, callee = nil)
6
+ @vm = vm
7
+ @section = section
8
+ @insns = vm.bytecode[section]
9
+ @callee = callee
10
+ end
11
+
12
+ def arguments_object
13
+ arguments = Types::Object.new
14
+ @args.each_with_index { |arg,i| arguments.put i.to_s, arg }
15
+ arguments.put "length", Types::Number.new(@args.size)
16
+ arguments.put "callee", @callee
17
+ arguments
18
+ end
19
+
20
+ def execute(scope, this = nil, args = [])
21
+ @scope = scope || Scope.new(vm.global_scope)
22
+ @stack = []
23
+ @sp_stack = []
24
+ @catch_stack = []
25
+ @finally_stack = []
26
+ @enum_stack = []
27
+ @ip = 0
28
+ @return = false
29
+ @this = this || @scope.global_scope.root_object
30
+ @args = args
31
+ if @callee
32
+ # the arguments object is only available within functions
33
+ scope.declare :arguments
34
+ scope.set_var :arguments, arguments_object
35
+ end
36
+
37
+ until @return
38
+ ins, arg = *insns[ip]
39
+ st = @stack.size
40
+ @ip += 1
41
+ if respond_to? ins
42
+ if @exception = catch(:exception) { public_send ins, arg; nil }
43
+ throw :exception, @exception if catch_stack.empty?
44
+ @ip = catch_stack.last
45
+ end
46
+ else
47
+ error! "unknown instruction #{ins}"
48
+ end
49
+ end
50
+
51
+ stack.last
52
+ end
53
+
54
+ define_method ".name" do |arg|
55
+ scope.declare arg.intern
56
+ scope.set_var arg.intern, @callee
57
+ end
58
+
59
+ define_method ".local" do |arg|
60
+ scope.declare arg.intern
61
+ end
62
+
63
+ define_method ".arg" do |arg|
64
+ scope.declare arg.intern
65
+ scope.set_var arg.intern, @args.shift || Types::Undefined.new
66
+ end
67
+
68
+ define_method ".catch" do |arg|
69
+ scope.declare arg.intern
70
+ scope.set_var arg.intern, @exception
71
+ end
72
+
73
+ ## instructions
74
+
75
+ def push(arg)
76
+ if arg.is_a? Symbol
77
+ stack.push scope.get_var(arg)
78
+ elsif arg.is_a?(Fixnum) || arg.is_a?(Float)
79
+ stack.push Types::Number.new(arg)
80
+ elsif arg.is_a?(Bignum)
81
+ stack.push Types::Number.new(arg.to_f)
82
+ elsif arg.is_a?(String)
83
+ stack.push Types::String.new(arg)
84
+ else
85
+ error! "bad argument to push instruction"
86
+ end
87
+ end
88
+
89
+ def call(arg)
90
+ args = []
91
+ arg.times { args.unshift @stack.pop }
92
+ fun = stack.pop
93
+ Lib.throw_type_error "called non callable" unless fun.respond_to?(:call)
94
+ stack.push fun.call(scope, scope.global_scope.root_object, args)
95
+ end
96
+
97
+ def thiscall(arg)
98
+ args = []
99
+ arg.times { args.unshift stack.pop }
100
+ fun = stack.pop
101
+ Lib.throw_type_error "called non callable" unless fun.respond_to?(:call)
102
+ stack.push fun.call(scope, Types.to_object(stack.pop), args)
103
+ end
104
+
105
+ def newcall(arg)
106
+ args = []
107
+ arg.times { args.unshift @stack.pop }
108
+ fun = stack.pop
109
+ Lib.throw_type_error "called non callable" unless fun.respond_to?(:call)
110
+ obj = Types::Object.new
111
+ obj.construct prototype: fun.get("prototype"), _class: fun do
112
+ retn = fun.call(scope, obj, args)
113
+ if retn.is_a?(Types::Undefined)
114
+ stack.push obj
115
+ else
116
+ stack.push retn
117
+ end
118
+ end
119
+ end
120
+
121
+ def dup(arg)
122
+ n = arg || 1
123
+ stack.push *stack[-n..-1]
124
+ end
125
+
126
+ def member(arg)
127
+ stack.push Types.to_object(stack.pop).get(arg.to_s)
128
+ end
129
+
130
+ def deleteg(arg)
131
+ scope.global_scope.root_object.delete arg.to_s
132
+ end
133
+
134
+ def delete(arg)
135
+ Types.to_object(stack.pop).delete arg.to_s
136
+ end
137
+
138
+ def in(arg)
139
+ obj = Types.to_object stack.pop
140
+ idx = Types.to_string stack.pop
141
+ stack.push Types::Boolean.new(obj.has_property idx.string)
142
+ end
143
+
144
+ def enum(arg)
145
+ props = []
146
+ obj = stack.pop
147
+ Types.to_object(obj).each_enumerable_property { |p| props.push p } unless obj.is_a?(Types::Null) || obj.is_a?(Types::Undefined)
148
+ @enum_stack.push [props, 0]
149
+ end
150
+
151
+ def enumnext(arg)
152
+ enum = @enum_stack.last
153
+ stack.push Types::String.new(enum[0][enum[1]])
154
+ enum[1] += 1
155
+ end
156
+
157
+ def jiee(arg)
158
+ enum = @enum_stack.last
159
+ @ip = arg if enum[1] >= enum[0].size
160
+ end
161
+
162
+ def popenum(arg)
163
+ @enum_stack.pop
164
+ end
165
+
166
+ def set(arg)
167
+ scope.set_var arg, stack.last
168
+ end
169
+
170
+ def setprop(arg)
171
+ val = stack.pop
172
+ obj = stack.pop
173
+ obj.put arg.to_s, val
174
+ stack.push val
175
+ end
176
+
177
+ def ret(arg)
178
+ if finally_stack.empty?
179
+ @return = true
180
+ else
181
+ @ip = finally_stack.last
182
+ end
183
+ end
184
+
185
+ def _throw(arg)
186
+ throw :exception, stack.pop
187
+ end
188
+
189
+ def eq(arg)
190
+ b = stack.pop
191
+ a = stack.pop
192
+ stack.push Types::Boolean.new(Types.eq(a, b))
193
+ end
194
+
195
+ def seq(arg)
196
+ b = stack.pop
197
+ a = stack.pop
198
+ stack.push Types::Boolean.new(Types.seq(a, b))
199
+ end
200
+
201
+ def null(arg)
202
+ stack.push Types::Null.new
203
+ end
204
+
205
+ def true(arg)
206
+ stack.push Types::Boolean.new(true)
207
+ end
208
+
209
+ def false(arg)
210
+ stack.push Types::Boolean.new(false)
211
+ end
212
+
213
+ def jmp(arg)
214
+ @ip = arg.to_i
215
+ end
216
+
217
+ def jif(arg)
218
+ if Types.is_falsy stack.pop
219
+ @ip = arg.to_i
220
+ end
221
+ end
222
+
223
+ def jit(arg)
224
+ if Types.is_truthy stack.pop
225
+ @ip = arg.to_i
226
+ end
227
+ end
228
+
229
+ def not(arg)
230
+ stack.push Types::Boolean.new(Types.is_falsy(stack.pop))
231
+ end
232
+
233
+ def inc(arg)
234
+ stack.push Types::Number.new(Types.to_number(stack.pop).number + 1)
235
+ end
236
+
237
+ def dec(arg)
238
+ stack.push Types::Number.new(Types.to_number(stack.pop).number - 1)
239
+ end
240
+
241
+ def pop(arg)
242
+ stack.pop
243
+ end
244
+
245
+ def index(arg)
246
+ index = Types.to_string(stack.pop).string
247
+ stack.push(Types.to_object(stack.pop).get(index) || Types::Undefined.new)
248
+ end
249
+
250
+ def array(arg)
251
+ args = []
252
+ arg.times { args.unshift stack.pop }
253
+ stack.push Types::Array.new(args)
254
+ end
255
+
256
+ def undefined(arg)
257
+ stack.push Types::Undefined.new
258
+ end
259
+
260
+ def number(arg)
261
+ stack.push Types.to_number(stack.pop)
262
+ end
263
+
264
+ def regexp(arg)
265
+ stack.push Types::RegExp.new(*arg)
266
+ end
267
+
268
+ def sal(arg)
269
+ r = Types.to_uint32(stack.pop) & 31
270
+ l = Types.to_int32 stack.pop
271
+ stack.push Types::Number.new(l << r)
272
+ end
273
+
274
+ def sar(arg)
275
+ r = Types.to_uint32(stack.pop) & 31
276
+ l = Types.to_int32 stack.pop
277
+ stack.push Types::Number.new(l >> r)
278
+ end
279
+
280
+ def slr(arg)
281
+ r = Types.to_uint32(stack.pop) & 31
282
+ l = Types.to_uint32 stack.pop
283
+ stack.push Types::Number.new(l >> r)
284
+ end
285
+
286
+ def add(arg)
287
+ r = stack.pop
288
+ l = stack.pop
289
+ right = Types.to_primitive r
290
+ left = Types.to_primitive l
291
+
292
+ if left.is_a?(Types::String) || right.is_a?(Types::String)
293
+ stack.push Types::String.new(Types.to_string(left).string + Types.to_string(right).string)
294
+ else
295
+ stack.push Types::Number.new(Types.to_number(left).number + Types.to_number(right).number)
296
+ end
297
+ end
298
+
299
+ def sub(arg)
300
+ right = Types.to_number(stack.pop).number
301
+ left = Types.to_number(stack.pop).number
302
+ stack.push Types::Number.new(left - right)
303
+ end
304
+
305
+ def mul(arg)
306
+ right = Types.to_number(stack.pop).number
307
+ left = Types.to_number(stack.pop).number
308
+ stack.push Types::Number.new(left * right)
309
+ end
310
+
311
+ def div(arg)
312
+ right = Types.to_number(stack.pop).number
313
+ left = Types.to_number(stack.pop).number
314
+ stack.push Types::Number.new(left / right.to_f)
315
+ end
316
+
317
+ def mod(arg)
318
+ right = Types.to_number(stack.pop).number
319
+ left = Types.to_number(stack.pop).number
320
+ stack.push Types::Number.new(left % right)
321
+ end
322
+
323
+ def and(arg)
324
+ right = Types.to_int32 stack.pop
325
+ left = Types.to_int32 stack.pop
326
+ stack.push Types::Number.new(left & right)
327
+ end
328
+
329
+ def or(arg)
330
+ right = Types.to_int32 stack.pop
331
+ left = Types.to_int32 stack.pop
332
+ stack.push Types::Number.new(left | right)
333
+ end
334
+
335
+ def xor(arg)
336
+ right = Types.to_int32 stack.pop
337
+ left = Types.to_int32 stack.pop
338
+ stack.push Types::Number.new(left ^ right)
339
+ end
340
+
341
+ def setindex(arg)
342
+ val = stack.pop
343
+ index = Types.to_string(stack.pop).string
344
+ Types.to_object(stack.pop).put index, val
345
+ stack.push val
346
+ end
347
+
348
+ def lt(arg)
349
+ comparison_oper :<
350
+ end
351
+
352
+ def lte(arg)
353
+ comparison_oper :<=
354
+ end
355
+
356
+ def gt(arg)
357
+ comparison_oper :>
358
+ end
359
+
360
+ def gte(arg)
361
+ comparison_oper :>=
362
+ end
363
+
364
+ def typeof(arg)
365
+ if arg
366
+ stack.push Types::String.new(scope.has_var(arg) ? scope.get_var(arg).typeof : "undefined")
367
+ else
368
+ stack.push Types::String.new(stack.pop.typeof)
369
+ end
370
+ end
371
+
372
+ def instanceof(arg)
373
+ r = stack.pop
374
+ l = stack.pop
375
+ stack.push Types::Boolean.new(r.has_instance l)
376
+ end
377
+
378
+ def close(arg)
379
+ name = vm.bytecode[arg].select { |ins,arg| ins == :".name" }.map { |ins,arg| arg }.first
380
+ arguments = vm.bytecode[arg].select { |ins,arg| ins == :".arg" }.map(&:last).map(&:to_s)
381
+ scope = @scope
382
+ fun = Types::Function.new(->(outer_scope, this, args) { VM::Frame.new(vm, arg, fun).execute(scope.close, this, args) }, "...", name || "", arguments)
383
+ stack.push fun
384
+ end
385
+
386
+ def callee(arg)
387
+ stack.push @callee
388
+ end
389
+
390
+ def object(arg)
391
+ obj = Types::Object.new
392
+ kvs = []
393
+ arg.reverse_each { |a| kvs << [a, stack.pop] }
394
+ kvs.reverse_each { |kv| obj.put kv[0].to_s, kv[1] }
395
+ stack.push obj
396
+ end
397
+
398
+ def negate(arg)
399
+ n = Types.to_number(stack.pop).number
400
+ if n.zero?
401
+ stack.push Types::Number.new(-n.to_f) # to preserve javascript's 0/-0 semantics
402
+ else
403
+ stack.push Types::Number.new(-n)
404
+ end
405
+ end
406
+
407
+ def with(arg)
408
+ @scope = ObjectScope.new stack.pop, @scope
409
+ end
410
+
411
+ def popscope(arg)
412
+ @scope = @scope.parent
413
+ end
414
+
415
+ def pushsp(arg)
416
+ sp_stack.push stack.size
417
+ end
418
+
419
+ def popsp(arg)
420
+ @stack = stack[0...sp_stack.pop]
421
+ end
422
+
423
+ def pushcatch(arg)
424
+ catch_stack.push arg
425
+ end
426
+
427
+ def popcatch(arg)
428
+ catch_stack.pop
429
+ end
430
+
431
+ def pushfinally(arg)
432
+ finally_stack.push arg
433
+ end
434
+
435
+ def popfinally(arg)
436
+ finally_stack.pop
437
+ end
438
+
439
+ def this(arg)
440
+ stack.push @this
441
+ end
442
+
443
+ private
444
+ def comparison_oper(op)
445
+ right = Types.to_primitive stack.pop
446
+ left = Types.to_primitive stack.pop
447
+
448
+ if left.is_a?(Types::String) && right.is_a?(Types::String)
449
+ stack.push Types::Boolean.new(left.string.send op, right.string)
450
+ else
451
+ stack.push Types::Boolean.new(Types.to_number(left).number.send op, Types.to_number(right).number)
452
+ end
453
+ end
454
+
455
+ def error!(msg)
456
+ vm.send :error!, "#{msg} (at #{@section}+#{@ip - 1})"
457
+ end
458
+ end
459
+ end
@@ -1,7 +1,8 @@
1
- module Twostroke
2
- module Runtime
3
- Dir.glob File.expand_path("../runtime/*", __FILE__) do |f|
4
- require f
5
- end
1
+ module Twostroke::Runtime
2
+ class RuntimeError < Twostroke::Error
3
+ end
4
+
5
+ Dir.glob File.expand_path("../runtime/*.rb", __FILE__) do |f|
6
+ require f
6
7
  end
7
8
  end
@@ -1,33 +1,45 @@
1
1
  module Twostroke
2
2
  class Lexer
3
- RESERVED = %w(function var if instanceof in else for while do this return throw typeof try catch finally void null new delete switch case break)
3
+ RESERVED = %w(
4
+ function var if instanceof in else for while do this return
5
+ throw typeof try catch finally void null new delete switch
6
+ case break continue default true false with)
4
7
  TOKENS = [
5
8
 
6
9
  [ :MULTI_COMMENT, %r{/\*.*?\*/} ],
7
10
  [ :SINGLE_COMMENT, /\/\/.*?$/ ],
8
11
 
9
12
  [ :WHITESPACE, /\s+/ ],
10
- [ :NUMBER, /((?<oct>0[0-7]+)|(?<hex>0x[A-Fa-f0-9]+)|(?<to_f>(\d+(\.?\d*([eE][+-]?\d+)?)?|\.\d+([eE][+-]?\d+)?)))/, ->m { m[0].send m.names.first } ],
13
+ [ :NUMBER, /((?<oct>0[0-7]+)|(?<hex>0x[A-Fa-f0-9]+)|(?<to_f>(\d+(\.?\d*([eE][+-]?\d+)?)?|\.\d+([eE][+-]?\d+)?)))/, ->m do
14
+ method, number = m.names.zip(m.captures).select { |k,v| v }.first
15
+ n = number.send method
16
+ if (n % 1).zero?
17
+ n.to_i
18
+ else
19
+ n
20
+ end
21
+ end ],
11
22
 
12
23
  *RESERVED.map do |w|
13
24
  [ w.upcase.intern, /#{w}(?=[^a-zA-Z_0-9])/ ]
14
25
  end,
15
26
  [ :BAREWORD, /[a-zA-Z_\$][\$a-zA-Z_0-9]*/, ->m { m[0] } ],
16
27
 
17
- [ :STRING, /(["'])((\\.|[^\1])*?[^\1\\]?)\1/, ->m do
18
- m[2].gsub(/\\([bfnrt])/) { |m|
28
+ [ :STRING, /(["'])((\\\n|\\.|[^\1])*?[^\1\\]?)\1/, ->m do
29
+ m[2]
30
+ .gsub(/\\([0-6]{1,3})/) { |m| m[1].to_i(7).chr }
31
+ .gsub(/\\x([a-f0-9]{2})/i) { |m| m[1].to_i(16).chr }
32
+ .gsub(/\\u([a-f0-9]{4})/i) { |m| m[1].to_i(16).chr }
33
+ .gsub(/\\(.)/m) { |m|
19
34
  case m[1]
20
35
  when "b"; "\b"
21
36
  when "n"; "\n"
22
37
  when "f"; "\f"
23
38
  when "r"; "\r"
24
39
  when "t"; "\t"
40
+ else; m[1]
25
41
  end
26
42
  }
27
- .gsub(/\\([0-6]{1,3})/) { |m| m[1].to_i(7).chr }
28
- .gsub(/\\x([a-f0-9]{2})/i) { |m| m[1].to_i(16).chr }
29
- .gsub(/\\u([a-f0-9]{4})/i) { |m| m[1].to_i(16).chr }
30
- .gsub(/\\(.)/) { |m| m[1] }
31
43
  end ],
32
44
 
33
45
  [ :REGEXP, %r{/(?<src>(\\.|[^\1])*?[^\1\\]?)/(?<opts>[gim]+)?}, ->m { [m[:src], m[:opts]] } ],
data/lib/twostroke.rb CHANGED
@@ -2,4 +2,6 @@ require "twostroke/error"
2
2
  require "twostroke/tokens"
3
3
  require "twostroke/lexer"
4
4
  require "twostroke/parser"
5
- require "twostroke/ast"
5
+ require "twostroke/ast"
6
+ require "twostroke/compiler"
7
+ require "twostroke/runtime"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twostroke
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-15 00:00:00.000000000Z
12
+ date: 2011-11-09 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: An implementation of Javascript written in pure Ruby. This project currently
15
- includes a WIP parser, and will include a runtime.
14
+ description: An implementation of Javascript written in pure Ruby. Twostroke contains
15
+ a parser, a bytecode compiler, a VM, and a minimal implementation of the Javascript
16
+ standard library.
16
17
  email:
17
18
  - charlie@charliesomerville.com
18
19
  executables: []
@@ -26,9 +27,11 @@ files:
26
27
  - lib/twostroke/ast/break.rb
27
28
  - lib/twostroke/ast/call.rb
28
29
  - lib/twostroke/ast/case.rb
30
+ - lib/twostroke/ast/continue.rb
29
31
  - lib/twostroke/ast/declaration.rb
30
32
  - lib/twostroke/ast/delete.rb
31
33
  - lib/twostroke/ast/do_while.rb
34
+ - lib/twostroke/ast/false.rb
32
35
  - lib/twostroke/ast/for_in.rb
33
36
  - lib/twostroke/ast/for_loop.rb
34
37
  - lib/twostroke/ast/function.rb
@@ -47,22 +50,53 @@ files:
47
50
  - lib/twostroke/ast/ternary.rb
48
51
  - lib/twostroke/ast/this.rb
49
52
  - lib/twostroke/ast/throw.rb
53
+ - lib/twostroke/ast/true.rb
50
54
  - lib/twostroke/ast/try.rb
51
55
  - lib/twostroke/ast/unary_operators.rb
52
56
  - lib/twostroke/ast/unsorted_binop.rb
53
57
  - lib/twostroke/ast/variable.rb
54
58
  - lib/twostroke/ast/while.rb
59
+ - lib/twostroke/ast/with.rb
55
60
  - lib/twostroke/ast.rb
61
+ - lib/twostroke/compiler/javascript.rb
62
+ - lib/twostroke/compiler/tsasm.rb
63
+ - lib/twostroke/compiler.rb
56
64
  - lib/twostroke/error.rb
57
65
  - lib/twostroke/lexer.rb
58
66
  - lib/twostroke/parser.rb
59
- - lib/twostroke/runtime/context.rb
60
- - lib/twostroke/runtime/environment.rb
61
- - lib/twostroke/runtime/types/basic_type.rb
67
+ - lib/twostroke/runtime/lib/array.js
68
+ - lib/twostroke/runtime/lib/array.rb
69
+ - lib/twostroke/runtime/lib/boolean.rb
70
+ - lib/twostroke/runtime/lib/console.rb
71
+ - lib/twostroke/runtime/lib/date.rb
72
+ - lib/twostroke/runtime/lib/error.rb
73
+ - lib/twostroke/runtime/lib/function.js
74
+ - lib/twostroke/runtime/lib/function.rb
75
+ - lib/twostroke/runtime/lib/math.rb
76
+ - lib/twostroke/runtime/lib/number.rb
77
+ - lib/twostroke/runtime/lib/object.js
78
+ - lib/twostroke/runtime/lib/object.rb
79
+ - lib/twostroke/runtime/lib/regexp.rb
80
+ - lib/twostroke/runtime/lib/string.rb
81
+ - lib/twostroke/runtime/lib/undefined.rb
82
+ - lib/twostroke/runtime/lib.rb
83
+ - lib/twostroke/runtime/scope.rb
84
+ - lib/twostroke/runtime/types/array.rb
85
+ - lib/twostroke/runtime/types/boolean.rb
86
+ - lib/twostroke/runtime/types/boolean_object.rb
87
+ - lib/twostroke/runtime/types/function.rb
62
88
  - lib/twostroke/runtime/types/null.rb
89
+ - lib/twostroke/runtime/types/number.rb
90
+ - lib/twostroke/runtime/types/number_object.rb
63
91
  - lib/twostroke/runtime/types/object.rb
92
+ - lib/twostroke/runtime/types/regexp.rb
93
+ - lib/twostroke/runtime/types/string.rb
94
+ - lib/twostroke/runtime/types/string_object.rb
64
95
  - lib/twostroke/runtime/types/undefined.rb
96
+ - lib/twostroke/runtime/types/value.rb
65
97
  - lib/twostroke/runtime/types.rb
98
+ - lib/twostroke/runtime/vm.rb
99
+ - lib/twostroke/runtime/vm_frame.rb
66
100
  - lib/twostroke/runtime.rb
67
101
  - lib/twostroke/tokens.rb
68
102
  - lib/twostroke.rb
@@ -1,33 +0,0 @@
1
- module Twostroke::Runtime
2
- class Context
3
- attr_accessor :variables, :parent
4
-
5
- def initialize
6
- variables = {}
7
- end
8
-
9
- def [](var)
10
- if variables.key? var
11
- variables[var]
12
- elsif parent
13
- parent[var]
14
- else
15
- raise "ReferenceError" # TODO
16
- end
17
- end
18
-
19
- def []=(var, val)
20
- if variables.key?(var) || parent.nil?
21
- variables[var] = val
22
- else
23
- parent[var] = val
24
- end
25
- end
26
-
27
- def create_context
28
- context = Context.new
29
- context.parent = self
30
- context
31
- end
32
- end
33
- end
@@ -1,13 +0,0 @@
1
- module Twostroke::Runtime
2
- class Environment
3
- attr_accessor :root_context, :root_object
4
-
5
- def initialize(root_name)
6
- @root_object = Types::Object.new
7
- @root_context = Context.new
8
- @root_contect.variables = @root_object
9
-
10
-
11
- end
12
- end
13
- end
@@ -1,5 +0,0 @@
1
- module Twostroke::Runtime::Types
2
- class BasicType
3
- #
4
- end
5
- end