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.
- data/lib/twostroke/ast/array.rb +8 -0
- data/lib/twostroke/ast/assignment.rb +7 -0
- data/lib/twostroke/ast/binary_operators.rb +7 -0
- data/lib/twostroke/ast/body.rb +6 -0
- data/lib/twostroke/ast/break.rb +4 -0
- data/lib/twostroke/ast/call.rb +7 -0
- data/lib/twostroke/ast/case.rb +9 -1
- data/lib/twostroke/ast/continue.rb +11 -0
- data/lib/twostroke/ast/declaration.rb +4 -0
- data/lib/twostroke/ast/delete.rb +6 -0
- data/lib/twostroke/ast/do_while.rb +7 -0
- data/lib/twostroke/ast/false.rb +11 -0
- data/lib/twostroke/ast/for_in.rb +8 -0
- data/lib/twostroke/ast/for_loop.rb +10 -1
- data/lib/twostroke/ast/function.rb +6 -0
- data/lib/twostroke/ast/if.rb +8 -0
- data/lib/twostroke/ast/index.rb +7 -0
- data/lib/twostroke/ast/member_access.rb +6 -0
- data/lib/twostroke/ast/multi_expression.rb +7 -0
- data/lib/twostroke/ast/new.rb +7 -0
- data/lib/twostroke/ast/null.rb +4 -0
- data/lib/twostroke/ast/number.rb +4 -0
- data/lib/twostroke/ast/object_literal.rb +6 -0
- data/lib/twostroke/ast/regexp.rb +4 -0
- data/lib/twostroke/ast/return.rb +6 -0
- data/lib/twostroke/ast/string.rb +4 -0
- data/lib/twostroke/ast/switch.rb +7 -0
- data/lib/twostroke/ast/ternary.rb +8 -0
- data/lib/twostroke/ast/this.rb +4 -0
- data/lib/twostroke/ast/throw.rb +6 -0
- data/lib/twostroke/ast/true.rb +11 -0
- data/lib/twostroke/ast/try.rb +8 -0
- data/lib/twostroke/ast/unary_operators.rb +7 -1
- data/lib/twostroke/ast/variable.rb +4 -0
- data/lib/twostroke/ast/while.rb +8 -1
- data/lib/twostroke/ast/with.rb +16 -0
- data/lib/twostroke/compiler/javascript.rb +396 -0
- data/lib/twostroke/compiler/tsasm.rb +595 -0
- data/lib/twostroke/compiler.rb +8 -0
- data/lib/twostroke/parser.rb +47 -9
- data/lib/twostroke/runtime/lib/array.js +144 -0
- data/lib/twostroke/runtime/lib/array.rb +71 -0
- data/lib/twostroke/runtime/lib/boolean.rb +23 -0
- data/lib/twostroke/runtime/lib/console.rb +13 -0
- data/lib/twostroke/runtime/lib/date.rb +65 -0
- data/lib/twostroke/runtime/lib/error.rb +36 -0
- data/lib/twostroke/runtime/lib/function.js +0 -0
- data/lib/twostroke/runtime/lib/function.rb +45 -0
- data/lib/twostroke/runtime/lib/math.rb +36 -0
- data/lib/twostroke/runtime/lib/number.rb +65 -0
- data/lib/twostroke/runtime/lib/object.js +0 -0
- data/lib/twostroke/runtime/lib/object.rb +55 -0
- data/lib/twostroke/runtime/lib/regexp.rb +28 -0
- data/lib/twostroke/runtime/lib/string.rb +86 -0
- data/lib/twostroke/runtime/lib/undefined.rb +7 -0
- data/lib/twostroke/runtime/lib.rb +42 -0
- data/lib/twostroke/runtime/scope.rb +120 -0
- data/lib/twostroke/runtime/types/array.rb +79 -0
- data/lib/twostroke/runtime/types/boolean.rb +23 -0
- data/lib/twostroke/runtime/types/boolean_object.rb +25 -0
- data/lib/twostroke/runtime/types/function.rb +83 -0
- data/lib/twostroke/runtime/types/null.rb +11 -3
- data/lib/twostroke/runtime/types/number.rb +31 -0
- data/lib/twostroke/runtime/types/number_object.rb +25 -0
- data/lib/twostroke/runtime/types/object.rb +169 -20
- data/lib/twostroke/runtime/types/regexp.rb +31 -0
- data/lib/twostroke/runtime/types/string.rb +16 -0
- data/lib/twostroke/runtime/types/string_object.rb +52 -0
- data/lib/twostroke/runtime/types/undefined.rb +11 -3
- data/lib/twostroke/runtime/types/value.rb +14 -0
- data/lib/twostroke/runtime/types.rb +133 -4
- data/lib/twostroke/runtime/vm.rb +25 -0
- data/lib/twostroke/runtime/vm_frame.rb +459 -0
- data/lib/twostroke/runtime.rb +6 -5
- data/lib/twostroke/tokens.rb +20 -8
- data/lib/twostroke.rb +3 -1
- metadata +41 -7
- data/lib/twostroke/runtime/context.rb +0 -33
- data/lib/twostroke/runtime/environment.rb +0 -13
- data/lib/twostroke/runtime/types/basic_type.rb +0 -5
@@ -1,33 +1,182 @@
|
|
1
1
|
module Twostroke::Runtime::Types
|
2
|
-
class Object <
|
3
|
-
attr_accessor :
|
4
|
-
|
5
|
-
|
2
|
+
class Object < Value
|
3
|
+
attr_accessor :_class, :prototype
|
4
|
+
attr_reader :accessors, :properties, :extensible, :data
|
5
|
+
private :accessors, :properties
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@extensible = true
|
6
9
|
@properties = {}
|
7
|
-
@
|
8
|
-
|
10
|
+
@accessors = {}
|
11
|
+
@prototype ||= defined?(@@_prototype) ? @@_prototype : Null.new
|
12
|
+
@_class = self.class.constructor_function if !defined?(@_class) && self.class.respond_to?(:constructor_function)
|
13
|
+
@data = {} # for abitrary data not safe to store as a property
|
14
|
+
proto_put "constructor", @_class
|
15
|
+
end
|
16
|
+
|
17
|
+
def _class=(c)
|
18
|
+
proto_put "constructor", (@_class = c)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.set_global_prototype(proto)
|
22
|
+
@@_prototype = proto
|
23
|
+
end
|
24
|
+
|
25
|
+
def typeof
|
26
|
+
"object"
|
27
|
+
end
|
28
|
+
|
29
|
+
def constructing?
|
30
|
+
@constructing
|
31
|
+
end
|
32
|
+
|
33
|
+
# this allows us to treat the object like a generic array.
|
34
|
+
# the value of this method is not memoized, so call sparingly
|
35
|
+
def generic_items
|
36
|
+
return items if respond_to? :items
|
37
|
+
len = Twostroke::Runtime::Types.to_number(get "length").number
|
38
|
+
return [] if (len.is_a?(Float) && (len.nan? || len.infinite?)) || len < 0
|
39
|
+
len = len.to_i
|
40
|
+
(0...len).map { |i| get i.to_s }
|
41
|
+
end
|
42
|
+
|
43
|
+
def construct(opts = {})
|
44
|
+
@constructing = true
|
45
|
+
opts.each do |k,v|
|
46
|
+
if respond_to? "#{k}="
|
47
|
+
send "#{k}=", v
|
48
|
+
else
|
49
|
+
instance_variable_set "@#{k}", v
|
50
|
+
end
|
51
|
+
end
|
52
|
+
yield
|
53
|
+
@constructing = false
|
54
|
+
end
|
55
|
+
|
56
|
+
def get(prop, this = self)
|
57
|
+
if accessors.has_key? prop
|
58
|
+
accessors[prop][:get].(this)
|
59
|
+
elsif properties.has_key? prop
|
60
|
+
properties[prop]
|
61
|
+
else
|
62
|
+
prototype && prototype.is_a?(Object) ? prototype.get(prop, this) : Undefined.new
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_own_property(prop)
|
67
|
+
if accessors.has_key? prop
|
68
|
+
accessors[prop][:get] ? accessors[prop][:get].(this) : Undefined.new
|
69
|
+
elsif properties.has_key? prop
|
70
|
+
properties[prop]
|
71
|
+
else
|
72
|
+
Undefined.new
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_property(prop)
|
77
|
+
# @TODO?
|
9
78
|
end
|
10
79
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
80
|
+
def each_enumerable_property(&bk)
|
81
|
+
accessors.select { |k,v| v[:enumerable] }.each { |k,v| yield k }
|
82
|
+
properties.reject { |k,v| accessors[k] }.each { |k,v| yield k }
|
83
|
+
if prototype && prototype.is_a?(Object)
|
84
|
+
prototype.each_enumerable_property &bk
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def put(prop, value, this = self)
|
89
|
+
if accessors.has_key? prop
|
90
|
+
accessors[prop][:set].(this, value) if accessors[prop][:set] && accessors[prop][:writable]
|
91
|
+
elsif properties.has_key? prop
|
92
|
+
properties[prop] = value
|
93
|
+
#elsif prototype && prototype.is_a?(Object) && prototype.has_accessor(prop)
|
94
|
+
# prototype.put prop, value, this
|
95
|
+
else
|
96
|
+
properties[prop] = value
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# puts prop as a non-enumerable property
|
101
|
+
def proto_put(prop, value)
|
102
|
+
define_own_property prop, value: value, enumerable: false
|
103
|
+
end
|
104
|
+
|
105
|
+
def can_put(prop)
|
106
|
+
extensible && (!accessors.has_key?(prop) || accessors[prop][:configurable])
|
107
|
+
end
|
108
|
+
|
109
|
+
def has_property(prop)
|
110
|
+
accessors.has_key?(prop) || properties.has_key?(prop) || (prototype && prototype.is_a?(Object) && prototype.has_property(prop))
|
111
|
+
end
|
112
|
+
|
113
|
+
def has_accessor(prop)
|
114
|
+
accessors.has_key?(prop)
|
115
|
+
end
|
116
|
+
|
117
|
+
def has_own_property(prop)
|
118
|
+
accessors.has_key?(prop) || properties.has_key?(prop)
|
119
|
+
end
|
120
|
+
|
121
|
+
def delete(prop)
|
122
|
+
if accessors.has_key? prop
|
123
|
+
accessors.delete prop if accessors[prop][:configurable]
|
124
|
+
elsif prop != "prototype"
|
125
|
+
properties.delete prop
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def delete!(prop)
|
130
|
+
if accessors.has_key? prop
|
131
|
+
accessors.delete prop if accessors[prop][:configurable]
|
18
132
|
else
|
19
|
-
|
133
|
+
properties.delete prop
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def default_value(hint = nil)
|
138
|
+
if hint.nil?
|
139
|
+
# @TODO
|
140
|
+
# hint = is_a?(Date) ? "String" : "Number"
|
141
|
+
hint = "Number"
|
142
|
+
end
|
143
|
+
|
144
|
+
if hint == "String"
|
145
|
+
toString = get "toString"
|
146
|
+
if toString.respond_to? :call
|
147
|
+
str = toString.call(nil, self, [])
|
148
|
+
return str if str.is_a? Primitive
|
149
|
+
end
|
150
|
+
valueOf = get "valueOf"
|
151
|
+
if valueOf.respond_to? :call
|
152
|
+
val = valueOf.call(nil, self, [])
|
153
|
+
return val if val.is_a? Primitive
|
154
|
+
end
|
155
|
+
Twostroke::Runtime::Lib.throw_type_error "could not convert object to string"
|
156
|
+
elsif hint == "Number"
|
157
|
+
valueOf = get "valueOf"
|
158
|
+
if valueOf.respond_to? :call
|
159
|
+
val = valueOf.call(nil, self, [])
|
160
|
+
return val if val.is_a? Primitive
|
161
|
+
end
|
162
|
+
toString = get "toString"
|
163
|
+
if toString.respond_to? :call
|
164
|
+
str = toString.call(nil, self, [])
|
165
|
+
return str if str.is_a? Primitive
|
166
|
+
end
|
167
|
+
Twostroke::Runtime::Lib.throw_type_error "could not convert object to string"
|
20
168
|
end
|
21
169
|
end
|
22
170
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
171
|
+
def define_own_property(prop, descriptor)
|
172
|
+
unless descriptor.has_key?(:get) || descriptor.has_key?(:set)
|
173
|
+
descriptor[:get] = ->(this) { descriptor[:value] }
|
174
|
+
descriptor[:set] = ->(this, value) { descriptor[:value] = value }
|
175
|
+
descriptor[:value] ||= Undefined.new
|
28
176
|
else
|
29
|
-
|
177
|
+
descriptor[:writable] = true if descriptor.has_key?(:set)
|
30
178
|
end
|
179
|
+
accessors[prop] = descriptor
|
31
180
|
end
|
32
181
|
end
|
33
182
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Twostroke::Runtime::Types
|
2
|
+
class RegExp < Object
|
3
|
+
def self.constructor_function
|
4
|
+
@@constructor_function ||=
|
5
|
+
Function.new(->(scope, this, args) {
|
6
|
+
RegExp.new Twostroke::Runtime::Types.to_string(args[0] || Undefined.new).string, args[1] && Twostroke::Runtime::Types.to_string(args[1]).string
|
7
|
+
}, nil, "RegExp", [])
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :regexp
|
11
|
+
attr_reader :global
|
12
|
+
def initialize(regexp_source, options)
|
13
|
+
opts = 0
|
14
|
+
(options ||= "").each_char do |opt|
|
15
|
+
opts |= case opt
|
16
|
+
when "m"; Regexp::MULTILINE
|
17
|
+
when "i"; Regexp::IGNORECASE
|
18
|
+
else; 0
|
19
|
+
end
|
20
|
+
end
|
21
|
+
@regexp = Regexp.new regexp_source, opts
|
22
|
+
@global = options.include? "g"
|
23
|
+
@prototype = RegExp.constructor_function.get("prototype")
|
24
|
+
super()
|
25
|
+
end
|
26
|
+
|
27
|
+
def primitive_value
|
28
|
+
String.new(regexp.inspect + (@global ? "g" : ""))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Twostroke::Runtime::Types
|
2
|
+
class String < Primitive
|
3
|
+
attr_reader :string
|
4
|
+
def initialize(string)
|
5
|
+
@string = string
|
6
|
+
end
|
7
|
+
|
8
|
+
def ===(other)
|
9
|
+
other.is_a?(String) && string == other.string
|
10
|
+
end
|
11
|
+
|
12
|
+
def typeof
|
13
|
+
"string"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Twostroke::Runtime
|
2
|
+
module Types
|
3
|
+
class StringObject < Object
|
4
|
+
def self.constructor_function
|
5
|
+
@@constructor_function ||=
|
6
|
+
Function.new(->(scope, this, args) { this.constructing? ? Types.to_object(Types.to_string(args[0] || Undefined.new)) : Types.to_string(args[0]) }, nil, "String", [])
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :string
|
10
|
+
def initialize(string)
|
11
|
+
@prototype = StringObject.constructor_function.get("prototype")
|
12
|
+
@string = string
|
13
|
+
super()
|
14
|
+
end
|
15
|
+
|
16
|
+
def primitive_value
|
17
|
+
String.new string
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(prop, this = self)
|
21
|
+
if prop =~ /\A\d+\z/
|
22
|
+
String.new string[prop.to_i]
|
23
|
+
else
|
24
|
+
super prop, this
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def has_property(prop)
|
29
|
+
if prop =~ /\A\d+\z/
|
30
|
+
i = prop.to_i
|
31
|
+
i >= 0 && i < string.size
|
32
|
+
else
|
33
|
+
super prop
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def has_own_property(prop)
|
38
|
+
if prop =~ /\A\d+\z/
|
39
|
+
i = prop.to_i
|
40
|
+
i >= 0 && i < string.size
|
41
|
+
else
|
42
|
+
super prop
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def each_enumerable_property(&bk)
|
47
|
+
(0...string.length).map(&:to_s).each &bk
|
48
|
+
super &bk
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,7 +1,15 @@
|
|
1
1
|
module Twostroke::Runtime::Types
|
2
|
-
class Undefined <
|
3
|
-
def self.
|
4
|
-
@@undefined ||= Undefined.
|
2
|
+
class Undefined < Primitive
|
3
|
+
def self.new
|
4
|
+
@@undefined ||= Undefined.allocate
|
5
|
+
end
|
6
|
+
|
7
|
+
def ===(other)
|
8
|
+
other.is_a?(Undefined)
|
9
|
+
end
|
10
|
+
|
11
|
+
def typeof
|
12
|
+
"undefined"
|
5
13
|
end
|
6
14
|
end
|
7
15
|
end
|
@@ -1,7 +1,136 @@
|
|
1
|
-
module Twostroke::Runtime
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Twostroke::Runtime::Types
|
2
|
+
def self.to_primitive(object, preferred_type = nil)
|
3
|
+
if object.is_a? Primitive
|
4
|
+
object
|
5
|
+
else
|
6
|
+
object.default_value preferred_type
|
5
7
|
end
|
6
8
|
end
|
9
|
+
|
10
|
+
def self.to_boolean(object)
|
11
|
+
b = if object.is_a?(Boolean)
|
12
|
+
object.boolean
|
13
|
+
elsif object.is_a?(Undefined) || object.is_a?(Null)
|
14
|
+
false
|
15
|
+
elsif object.is_a?(Number)
|
16
|
+
!object.zero? && !object.nan?
|
17
|
+
elsif object.is_a?(String)
|
18
|
+
object.string != ""
|
19
|
+
else
|
20
|
+
true
|
21
|
+
end
|
22
|
+
Boolean.new b
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.to_number(object)
|
26
|
+
if object.is_a?(Undefined)
|
27
|
+
Number.new Float::NAN
|
28
|
+
elsif object.is_a?(Null)
|
29
|
+
Number.new 0
|
30
|
+
elsif object.is_a?(Boolean)
|
31
|
+
Number.new(object.boolean ? 1 : 0)
|
32
|
+
elsif object.is_a?(Number)
|
33
|
+
object
|
34
|
+
elsif object.is_a?(String)
|
35
|
+
Number.new(Float(object.string)) rescue Number.new(Float::NAN)
|
36
|
+
else # object is Object
|
37
|
+
to_number to_primitive(object)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.to_int32(object)
|
42
|
+
num = to_number object
|
43
|
+
if num.nan? || num.infinite?
|
44
|
+
0
|
45
|
+
else
|
46
|
+
int32 = num.number.to_i & 0xffff_ffff
|
47
|
+
int32 -= 2 ** 31 if int32 >= 2 ** 31
|
48
|
+
int32
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.to_uint32(object)
|
53
|
+
num = to_number object
|
54
|
+
if num.nan? || num.infinite?
|
55
|
+
0
|
56
|
+
else
|
57
|
+
num.number.to_i & 0xffff_ffff
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.to_string(object)
|
62
|
+
if object.is_a?(Undefined)
|
63
|
+
String.new "undefined"
|
64
|
+
elsif object.is_a?(Null)
|
65
|
+
String.new "null"
|
66
|
+
elsif object.is_a?(Boolean)
|
67
|
+
String.new object.boolean.to_s
|
68
|
+
elsif object.is_a?(Number)
|
69
|
+
String.new object.number.to_s
|
70
|
+
elsif object.is_a?(String)
|
71
|
+
object
|
72
|
+
else
|
73
|
+
to_string to_primitive(object)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.to_object(object)
|
78
|
+
if object.is_a?(Undefined) || object.is_a?(Null)
|
79
|
+
Twostroke::Runtime::Lib.throw_type_error "cannot convert null or undefined to object"
|
80
|
+
elsif object.is_a?(Boolean)
|
81
|
+
BooleanObject.new object.boolean
|
82
|
+
elsif object.is_a?(Number)
|
83
|
+
NumberObject.new object.number
|
84
|
+
elsif object.is_a?(String)
|
85
|
+
StringObject.new object.string
|
86
|
+
else
|
87
|
+
object
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.is_falsy(object)
|
92
|
+
!is_truthy(object)
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.is_truthy(object)
|
96
|
+
to_boolean(object).boolean
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.eq(a, b)
|
100
|
+
if a.class == b.class
|
101
|
+
a === b
|
102
|
+
elsif a.is_a?(Null) && b.is_a?(Undefined)
|
103
|
+
true
|
104
|
+
elsif a.is_a?(Undefined) && b.is_a?(Null)
|
105
|
+
true
|
106
|
+
elsif a.is_a?(Number) && b.is_a?(String)
|
107
|
+
eq(a, to_number(b))
|
108
|
+
elsif a.is_a?(String) && b.is_a?(Number)
|
109
|
+
eq(to_number(a), b)
|
110
|
+
elsif a.is_a?(Boolean)
|
111
|
+
eq(to_number(a), b)
|
112
|
+
elsif b.is_a?(Boolean)
|
113
|
+
eq(a, to_number(b))
|
114
|
+
elsif (a.is_a?(String) || b.is_a?(Number)) && b.is_a?(Object)
|
115
|
+
eq(a, to_primitive(b))
|
116
|
+
elsif a.is_a?(Object) && (b.is_a?(String) || b.is_a?(Number))
|
117
|
+
eq(to_primitive(a), b)
|
118
|
+
else
|
119
|
+
false
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.seq(a, b)
|
124
|
+
if a.class == b.class
|
125
|
+
a === b
|
126
|
+
else
|
127
|
+
false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
require File.expand_path("../types/value.rb", __FILE__)
|
132
|
+
require File.expand_path("../types/object.rb", __FILE__)
|
133
|
+
Dir.glob(File.expand_path("../types/*", __FILE__)).each do |f|
|
134
|
+
require f
|
135
|
+
end
|
7
136
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Twostroke::Runtime
|
2
|
+
class VM
|
3
|
+
attr_accessor :bytecode
|
4
|
+
attr_reader :global_scope, :lib
|
5
|
+
|
6
|
+
def initialize(bytecode)
|
7
|
+
@bytecode = bytecode
|
8
|
+
@global_scope = GlobalScope.new self
|
9
|
+
@lib = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute(section = :main, scope = nil)
|
13
|
+
Frame.new(self, section).execute scope
|
14
|
+
end
|
15
|
+
|
16
|
+
def throw_error(type, message)
|
17
|
+
throw :exception, lib[type].(nil, global_scope.root_object, [Types::String.new(message)])
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def error!(msg)
|
22
|
+
raise RuntimeError, msg
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|