twostroke 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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