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