mirah 0.0.12-java → 0.1.0-java
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/History.txt +372 -0
- data/README.txt +4 -5
- data/Rakefile +178 -55
- data/examples/appengine/Readme +3 -3
- data/examples/appengine/src/org/mirah/MirahApp.mirah +1 -1
- data/examples/appengine/src/org/mirah/list.dhtml +1 -1
- data/examples/bintrees.mirah +1 -1
- data/examples/edb.mirah +1 -1
- data/examples/fib.mirah +1 -1
- data/examples/interfaces.mirah +1 -1
- data/examples/macros/{string-each-char.mirah → string_each_char.mirah} +4 -5
- data/examples/maven/README.txt +1 -1
- data/examples/maven/src/main/mirah/hello_mirah.mirah +1 -1
- data/examples/plugins/appengine/Rakefile +1 -1
- data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/MetaModel.mirah +1 -1
- data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +1 -1
- data/examples/plugins/appengine/test/com/google/appengine/ext/duby/db/ModelTest.duby +1 -1
- data/examples/rosettacode/100-doors.mirah +6 -6
- data/examples/rosettacode/README.txt +3 -3
- data/examples/rosettacode/boolean-values.mirah +1 -1
- data/examples/rosettacode/comments.mirah +1 -1
- data/examples/rosettacode/count-occurrences-of-a-substring.mirah +1 -1
- data/examples/rosettacode/factorial.mirah +1 -1
- data/examples/rosettacode/fibonacci.mirah +1 -1
- data/examples/rosettacode/fizz-buzz.mirah +2 -2
- data/examples/rosettacode/flatten-a-list.mirah +4 -4
- data/examples/rosettacode/guess-the-number.mirah +2 -2
- data/examples/rosettacode/hamming-numbers.mirah +4 -4
- data/examples/rosettacode/is-string-numeric.mirah +22 -22
- data/examples/rosettacode/palindrome.mirah +2 -2
- data/examples/rosettacode/random-numbers.mirah +1 -1
- data/examples/rosettacode/repeat-a-string.mirah +1 -1
- data/examples/rosettacode/reverse-a-string.mirah +1 -1
- data/examples/rosettacode/rot-13.mirah +5 -5
- data/examples/rosettacode/secure-temporary-file.mirah +2 -2
- data/examples/rosettacode/sleep.mirah +1 -1
- data/examples/rosettacode/string-length.mirah +5 -5
- data/examples/swing.mirah +1 -1
- data/examples/test.edb +1 -1
- data/javalib/mirah-bootstrap.jar +0 -0
- data/javalib/mirah-builtins.jar +0 -0
- data/javalib/mirah-parser.jar +0 -0
- data/javalib/mirah-util.jar +0 -0
- data/lib/duby.rb +1 -1
- data/lib/mirah.rb +50 -28
- data/lib/mirah/ast.rb +15 -605
- data/lib/mirah/ast/scope.rb +98 -69
- data/lib/mirah/commands.rb +1 -1
- data/lib/mirah/commands/base.rb +7 -7
- data/lib/mirah/commands/compile.rb +3 -3
- data/lib/mirah/commands/parse.rb +7 -5
- data/lib/mirah/commands/run.rb +12 -19
- data/lib/mirah/compiler.rb +15 -23
- data/lib/mirah/errors.rb +16 -1
- data/lib/mirah/generator.rb +79 -39
- data/lib/mirah/jvm/compiler.rb +1 -19
- data/lib/mirah/jvm/compiler/base.rb +233 -90
- data/lib/mirah/jvm/compiler/jvm_bytecode.rb +675 -363
- data/lib/mirah/jvm/method_lookup.rb +134 -65
- data/lib/mirah/jvm/typer.rb +10 -5
- data/lib/mirah/jvm/types.rb +10 -2
- data/lib/mirah/jvm/types/array_type.rb +10 -12
- data/lib/mirah/{compiler/type.rb → jvm/types/ast_ext.rb} +12 -8
- data/lib/mirah/jvm/types/basic_types.rb +26 -33
- data/lib/mirah/jvm/types/bitescript_ext.rb +1 -1
- data/lib/mirah/jvm/types/block_type.rb +15 -0
- data/lib/mirah/jvm/types/boolean.rb +8 -4
- data/lib/mirah/jvm/types/dynamic_type.rb +12 -13
- data/lib/mirah/jvm/types/enumerable.rb +7 -7
- data/lib/mirah/jvm/types/extensions.rb +11 -6
- data/lib/mirah/jvm/types/factory.rb +624 -94
- data/lib/mirah/jvm/types/floats.rb +21 -15
- data/lib/mirah/jvm/types/generic_type.rb +72 -0
- data/lib/mirah/jvm/types/implicit_nil_type.rb +29 -0
- data/lib/mirah/jvm/types/integers.rb +26 -71
- data/lib/mirah/jvm/types/interface_definition.rb +3 -3
- data/lib/mirah/jvm/types/intrinsics.rb +203 -168
- data/lib/mirah/jvm/types/literals.rb +6 -6
- data/lib/mirah/jvm/types/meta_type.rb +13 -4
- data/lib/mirah/jvm/types/methods.rb +281 -93
- data/lib/mirah/jvm/types/null_type.rb +17 -5
- data/lib/mirah/jvm/types/number.rb +10 -7
- data/lib/mirah/jvm/types/primitive_type.rb +17 -6
- data/lib/mirah/jvm/types/source_mirror.rb +12 -7
- data/lib/mirah/jvm/types/type.rb +107 -23
- data/lib/mirah/jvm/types/type_definition.rb +25 -10
- data/lib/mirah/jvm/types/unreachable_type.rb +1 -1
- data/lib/mirah/jvm/types/void_type.rb +3 -3
- data/lib/mirah/parser.rb +154 -16
- data/lib/mirah/plugin/edb.rb +1 -1
- data/lib/mirah/transform.rb +1 -2
- data/lib/mirah/transform/ast_ext.rb +24 -43
- data/lib/mirah/transform/transformer.rb +29 -224
- data/lib/mirah/typer.rb +2 -16
- data/lib/mirah/util/argument_processor.rb +25 -10
- data/lib/mirah/util/class_loader.rb +1 -1
- data/lib/mirah/util/compilation_state.rb +16 -17
- data/lib/mirah/util/delegate.rb +2 -2
- data/lib/mirah/util/logging.rb +110 -0
- data/lib/mirah/util/process_errors.rb +69 -11
- data/lib/mirah/version.rb +1 -1
- data/test/core/commands_test.rb +6 -24
- data/test/core/env_test.rb +5 -5
- data/{lib/mirah/jvm/source_generator/typer.rb → test/core/generator_test.rb} +9 -9
- data/test/core/typer_test.rb +196 -158
- data/test/core/util/argument_processor_test.rb +10 -10
- data/test/core/util/class_loader_test.rb +6 -5
- data/test/fixtures/org/foo/LowerCaseInnerClass$inner.class +0 -0
- data/test/fixtures/org/foo/LowerCaseInnerClass.class +0 -0
- data/test/fixtures/org/foo/LowerCaseInnerClass.java +7 -0
- data/test/jvm/annotations_test.rb +5 -5
- data/test/jvm/blocks_test.rb +140 -88
- data/test/jvm/bytecode_test_helper.rb +112 -94
- data/test/jvm/cast_test.rb +162 -0
- data/test/jvm/constructors_test.rb +18 -8
- data/test/jvm/enumerable_test.rb +77 -44
- data/test/jvm/example_test.rb +53 -0
- data/test/jvm/factory_test.rb +7 -1
- data/test/jvm/generics_test.rb +57 -0
- data/test/jvm/hash_test.rb +106 -0
- data/test/jvm/import_test.rb +81 -0
- data/test/jvm/interface_test.rb +73 -0
- data/test/jvm/java_typer_test.rb +92 -66
- data/{lib/mirah/typer/base.rb → test/jvm/jvm_commands_test.rb} +6 -10
- data/test/jvm/jvm_compiler_test.rb +170 -604
- data/test/jvm/list_extensions_test.rb +23 -0
- data/test/jvm/macros_test.rb +197 -32
- data/test/jvm/main_method_test.rb +4 -4
- data/test/jvm/numeric_extensions_test.rb +13 -0
- data/test/jvm/rescue_test.rb +73 -16
- data/test/jvm/varargs_test.rb +65 -0
- data/test/test_helper.rb +1 -2
- metadata +234 -251
- data/examples/SortClosure$__xform_tmp_1.class +0 -0
- data/examples/SortClosure$__xform_tmp_2.class +0 -0
- data/examples/SortClosure.class +0 -0
- data/examples/macros/StringEachChar$Extension1.class +0 -0
- data/lib/mirah/ast/call.rb +0 -345
- data/lib/mirah/ast/class.rb +0 -359
- data/lib/mirah/ast/flow.rb +0 -381
- data/lib/mirah/ast/intrinsics.rb +0 -563
- data/lib/mirah/ast/literal.rb +0 -178
- data/lib/mirah/ast/local.rb +0 -112
- data/lib/mirah/ast/method.rb +0 -408
- data/lib/mirah/ast/structure.rb +0 -387
- data/lib/mirah/ast/type.rb +0 -146
- data/lib/mirah/commands/base.rb~ +0 -57
- data/lib/mirah/compiler/call.rb +0 -45
- data/lib/mirah/compiler/class.rb +0 -81
- data/lib/mirah/compiler/flow.rb +0 -109
- data/lib/mirah/compiler/literal.rb +0 -130
- data/lib/mirah/compiler/local.rb +0 -59
- data/lib/mirah/compiler/method.rb +0 -44
- data/lib/mirah/compiler/structure.rb +0 -65
- data/lib/mirah/jvm/compiler/java_source.rb +0 -787
- data/lib/mirah/jvm/method_lookup.rb~ +0 -247
- data/lib/mirah/jvm/source_generator/builder.rb +0 -468
- data/lib/mirah/jvm/source_generator/loops.rb +0 -131
- data/lib/mirah/jvm/source_generator/precompile.rb +0 -210
- data/lib/mirah/plugin/gwt.rb +0 -189
- data/lib/mirah/plugin/java.rb +0 -70
- data/lib/mirah/transform/error.rb +0 -13
- data/lib/mirah/transform/helper.rb +0 -765
- data/lib/mirah/typer/simple.rb +0 -384
- data/lib/mirah/version.rb~ +0 -18
- data/test/core/ast_test.rb +0 -382
- data/test/core/compilation_test.rb +0 -130
- data/test/core/macros_test.rb +0 -61
- data/test/jvm/javac_test_helper.rb +0 -89
- data/test/jvm/jvm_compiler_test.rb~ +0 -2181
- data/test/plugins/gwt_test.rb +0 -69
data/lib/mirah/typer/simple.rb
DELETED
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
|
|
2
|
-
# All contributing project authors may be found in the NOTICE file.
|
|
3
|
-
#
|
|
4
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
# you may not use this file except in compliance with the License.
|
|
6
|
-
# You may obtain a copy of the License at
|
|
7
|
-
#
|
|
8
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
#
|
|
10
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
# See the License for the specific language governing permissions and
|
|
14
|
-
# limitations under the License.
|
|
15
|
-
|
|
16
|
-
require 'mirah/ast'
|
|
17
|
-
require 'mirah/transform'
|
|
18
|
-
|
|
19
|
-
module Mirah
|
|
20
|
-
module Typer
|
|
21
|
-
class Simple < Base
|
|
22
|
-
attr_accessor :known_types, :errors, :last_chance
|
|
23
|
-
|
|
24
|
-
def initialize(self_type)
|
|
25
|
-
@known_types = {}
|
|
26
|
-
|
|
27
|
-
@known_types["self"] = type_reference(nil, self_type)
|
|
28
|
-
@known_types["fixnum"] = type_reference(nil, "fixnum")
|
|
29
|
-
@known_types["float"] = type_reference(nil, "float")
|
|
30
|
-
@known_types["string"] = type_reference(nil, "string")
|
|
31
|
-
@known_types["boolean"] = type_reference(nil, "boolean")
|
|
32
|
-
@errors = []
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def name
|
|
36
|
-
"Simple"
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def set_filename(scope, name); end
|
|
40
|
-
|
|
41
|
-
def self_type
|
|
42
|
-
known_types["self"]
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def default_type
|
|
46
|
-
nil
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def fixnum_type(value=0)
|
|
50
|
-
known_types["fixnum"]
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def float_type(value=0)
|
|
54
|
-
known_types["float"]
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def string_type
|
|
58
|
-
known_types["string"]
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def boolean_type
|
|
62
|
-
known_types["boolean"]
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def null_type
|
|
66
|
-
AST::TypeReference::NullType
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def no_type
|
|
70
|
-
AST::TypeReference::NoType
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# to be overridden
|
|
74
|
-
def array_type
|
|
75
|
-
AST::TypeReference::NullType
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# to be overridden
|
|
79
|
-
def hash_type
|
|
80
|
-
AST::TypeReference::NullType
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def known_type(scope, name)
|
|
84
|
-
@known_types[name]
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def define_type(scope, name, superclass, interfaces)
|
|
88
|
-
log "New type defined: '#{name}' < '#{superclass}'"
|
|
89
|
-
result = type_definition(scope, name, superclass, interfaces)
|
|
90
|
-
|
|
91
|
-
# TODO Get rid of known_types["self"]
|
|
92
|
-
old_self, known_types["self"] = known_types["self"], result
|
|
93
|
-
yield
|
|
94
|
-
known_types["self"] = old_self
|
|
95
|
-
|
|
96
|
-
result
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def learn_local_type(scope, name, type)
|
|
100
|
-
return if type.null? && !@last_chance
|
|
101
|
-
type = scope.learn_local_type(name, known_types[type] || type)
|
|
102
|
-
log "Learned local type under #{scope} : #{name} = #{type}" if type
|
|
103
|
-
type
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def local_type(scope, name)
|
|
107
|
-
type = scope.local_type(name)
|
|
108
|
-
log "Retrieved local type in #{scope} : #{name} = #{type}" if type
|
|
109
|
-
type
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def local_types
|
|
113
|
-
@local_types ||= {}
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def local_type_hash(scope)
|
|
117
|
-
local_types[scope] ||= {}
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def field_types
|
|
121
|
-
@field_types ||= {}
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def field_type_hash(cls)
|
|
125
|
-
field_types[cls] ||= {}
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def static_field_types
|
|
129
|
-
@static_field_types ||= {}
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def static_field_type_hash(cls)
|
|
133
|
-
static_field_types[cls] ||= {}
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def infer_signature(method_def)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def learn_field_type(cls, name, type)
|
|
140
|
-
log "Learned field type under #{cls} : #{name} = #{type}" if type
|
|
141
|
-
|
|
142
|
-
# TODO check for compatibility?
|
|
143
|
-
field_type_hash(cls)[name] ||= known_types[type] || type
|
|
144
|
-
|
|
145
|
-
type
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def field_type(cls, name)
|
|
149
|
-
field_type_hash(cls)[name]
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def learn_static_field_type(cls, name, type)
|
|
153
|
-
log "Learned field type under #{cls} : #{name} = #{type}" if type
|
|
154
|
-
|
|
155
|
-
# TODO check for compatibility?
|
|
156
|
-
static_field_type_hash(cls)[name] ||= known_types[type] || type
|
|
157
|
-
|
|
158
|
-
type
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def static_field_type(cls, name)
|
|
162
|
-
static_field_type_hash(cls)[name]
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def learn_method_type(target_type, name, parameter_types, type, exceptions)
|
|
166
|
-
log "Learned method #{name} (#{parameter_types}) on #{target_type} = #{type}" if type
|
|
167
|
-
|
|
168
|
-
get_method_type_hash(target_type, name, parameter_types)[:type] = known_types[type] || type
|
|
169
|
-
|
|
170
|
-
# if it's any args are imported types, also add a mapping for the expanded name
|
|
171
|
-
imported_types = parameter_types.map {|param| known_types[param] || param}
|
|
172
|
-
get_method_type_hash(target_type, name, imported_types)[:type] = type
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def method_type(target_type, name, parameter_types)
|
|
176
|
-
if (target_type && target_type.error?) ||
|
|
177
|
-
parameter_types.any? {|t| t && t.error?}
|
|
178
|
-
return AST.error_type
|
|
179
|
-
end
|
|
180
|
-
constructor = (name == 'new' && target_type && target_type.meta?)
|
|
181
|
-
|
|
182
|
-
if constructor
|
|
183
|
-
# constructor handled different from other methods
|
|
184
|
-
simple_type = get_method_type_hash(target_type.unmeta, 'initialize', parameter_types)[:type]
|
|
185
|
-
else
|
|
186
|
-
simple_type = get_method_type_hash(target_type, name, parameter_types)[:type]
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if !simple_type
|
|
191
|
-
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} not found."
|
|
192
|
-
|
|
193
|
-
# allow plugins a go if we're in the inference phase
|
|
194
|
-
simple_type = plugins do |plugin|
|
|
195
|
-
plugin.method_type(self, target_type, name, parameter_types)
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
return nil unless simple_type
|
|
200
|
-
|
|
201
|
-
if constructor
|
|
202
|
-
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} = #{target_type}"
|
|
203
|
-
target_type.unmeta
|
|
204
|
-
else
|
|
205
|
-
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} = #{simple_type}"
|
|
206
|
-
simple_type
|
|
207
|
-
end
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
def plugins
|
|
211
|
-
if cycling?
|
|
212
|
-
Mirah.typer_plugins.each do |plugin|
|
|
213
|
-
log "Invoking plugin: #{plugin}"
|
|
214
|
-
|
|
215
|
-
result = yield plugin
|
|
216
|
-
return result if result
|
|
217
|
-
end
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
nil
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
def cycling?
|
|
224
|
-
@cycling
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
def cycling=(c)
|
|
228
|
-
@cycling = c
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
def cycle(count)
|
|
232
|
-
@cycling = true
|
|
233
|
-
count.times do |i|
|
|
234
|
-
begin
|
|
235
|
-
log "[Cycle #{i}]: Started... (#{@deferred_nodes.size} nodes to resolve)"
|
|
236
|
-
yield i
|
|
237
|
-
ensure
|
|
238
|
-
log "[Cycle #{i}]: Complete!"
|
|
239
|
-
end
|
|
240
|
-
end
|
|
241
|
-
ensure
|
|
242
|
-
@cycling = false
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
def method_types
|
|
246
|
-
@method_types ||= {}
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
def get_method_type_hash(target_type, name, parameter_types)
|
|
250
|
-
method_types[target_type] ||= {}
|
|
251
|
-
method_types[target_type][name] ||= {}
|
|
252
|
-
method_types[target_type][name][parameter_types.size] ||= {}
|
|
253
|
-
|
|
254
|
-
current = method_types[target_type][name][parameter_types.size]
|
|
255
|
-
|
|
256
|
-
parameter_types.each {|type| current[type] ||= {}; current = current[type]}
|
|
257
|
-
|
|
258
|
-
current
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
def type_reference(scope, name, array=false, meta=false)
|
|
262
|
-
AST::TypeReference.new(name, array, meta)
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
def type_definition(scope, name, superclass, interfaces)
|
|
266
|
-
AST::TypeDefinition.new(name, AST::TypeReference.new(superclass), interfaces)
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
def deferred_nodes
|
|
270
|
-
@deferred_nodes ||= {}
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
def infer(node, expression=true)
|
|
274
|
-
begin
|
|
275
|
-
node.infer(self, expression)
|
|
276
|
-
rescue InferenceError => ex
|
|
277
|
-
ex.node ||= node
|
|
278
|
-
error(node, ex)
|
|
279
|
-
rescue Exception => ex
|
|
280
|
-
raise Mirah::InternalCompilerError.wrap(ex, node)
|
|
281
|
-
end
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
def error(node, error_or_msg=nil, backtrace=nil)
|
|
285
|
-
if error_or_msg.kind_of? InferenceError
|
|
286
|
-
error = error_or_msg
|
|
287
|
-
elsif error_or_msg
|
|
288
|
-
error = InferenceError.new(error_or_msg, node)
|
|
289
|
-
error.set_backtrace(backtrace) if backtrace
|
|
290
|
-
else
|
|
291
|
-
error = InferenceError.new("Unable to infer type.", node)
|
|
292
|
-
end
|
|
293
|
-
@errors << error
|
|
294
|
-
node.resolve_if(self) do
|
|
295
|
-
AST.error_type
|
|
296
|
-
end
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
def defer(node, error_message=nil)
|
|
300
|
-
if @error_next
|
|
301
|
-
log "Marking #{node} as an error"
|
|
302
|
-
@error_next = false
|
|
303
|
-
error(node, error_message)
|
|
304
|
-
else
|
|
305
|
-
raise "Can't defer nil" if node.nil?
|
|
306
|
-
return if deferred_nodes.include? node
|
|
307
|
-
log "Deferring inference for #{node}"
|
|
308
|
-
|
|
309
|
-
deferred_nodes[node] = self_type
|
|
310
|
-
end
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
def resolve(raise = false)
|
|
314
|
-
count = deferred_nodes.size + 1
|
|
315
|
-
|
|
316
|
-
log "Entering type inference cycle"
|
|
317
|
-
|
|
318
|
-
retried = false
|
|
319
|
-
cycle(count) do |i|
|
|
320
|
-
old_deferred = @deferred_nodes
|
|
321
|
-
@deferred_nodes = {}
|
|
322
|
-
old_deferred.each do |node, saved_type|
|
|
323
|
-
known_types["self"] = saved_type
|
|
324
|
-
type = infer(node)
|
|
325
|
-
|
|
326
|
-
log "[Cycle #{i}]: Inferred type for #{node}: #{type || 'FAILED'}"
|
|
327
|
-
|
|
328
|
-
if type == default_type
|
|
329
|
-
@deferred_nodes[node] = saved_type
|
|
330
|
-
end
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
if @deferred_nodes.empty?
|
|
334
|
-
log "[Cycle #{i}]: Resolved all types, exiting"
|
|
335
|
-
break
|
|
336
|
-
elsif old_deferred == @deferred_nodes
|
|
337
|
-
if @error_next || retried
|
|
338
|
-
log "[Cycle #{i}]: Made no progress, bailing out"
|
|
339
|
-
break
|
|
340
|
-
elsif @last_chance
|
|
341
|
-
break unless @errors.empty?
|
|
342
|
-
# Retry this iteration, and mark the first deferred
|
|
343
|
-
# type as an error.
|
|
344
|
-
retried = true
|
|
345
|
-
@error_next = true
|
|
346
|
-
redo
|
|
347
|
-
else
|
|
348
|
-
# This is a hack for default constructor support. The right fix
|
|
349
|
-
# is probably to check the AST for constructors. Instead we
|
|
350
|
-
# tell the plugins that we're near the end of inference so they
|
|
351
|
-
# can assume no new constructors are being added. You could
|
|
352
|
-
# easily write some circular constructors that would compile
|
|
353
|
-
# with this technique but fail to run.
|
|
354
|
-
@last_chance = true
|
|
355
|
-
redo
|
|
356
|
-
end
|
|
357
|
-
elsif @errors.size > 15
|
|
358
|
-
log "Too many errors, giving up"
|
|
359
|
-
break
|
|
360
|
-
end
|
|
361
|
-
retried = false
|
|
362
|
-
end
|
|
363
|
-
|
|
364
|
-
# done with n sweeps, if any remain mark them as errors
|
|
365
|
-
error_nodes = @errors.map {|e| e.node}
|
|
366
|
-
if error_nodes.empty?
|
|
367
|
-
(deferred_nodes.keys - error_nodes).each do |deferred_node|
|
|
368
|
-
break if @errors.size > 15
|
|
369
|
-
error_nodes << deferred_node
|
|
370
|
-
error(deferred_node)
|
|
371
|
-
end
|
|
372
|
-
end
|
|
373
|
-
if raise && !error_nodes.empty?
|
|
374
|
-
msg = "Could not infer typing for nodes:"
|
|
375
|
-
error_nodes.map do |e|
|
|
376
|
-
msg << "\n "
|
|
377
|
-
msg << "#{e.inspect} at line #{e.line_number} (child of #{e.parent})"
|
|
378
|
-
end
|
|
379
|
-
raise InferenceError.new(msg)
|
|
380
|
-
end
|
|
381
|
-
end
|
|
382
|
-
end
|
|
383
|
-
end
|
|
384
|
-
end
|
data/lib/mirah/version.rb~
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
|
|
2
|
-
# All contributing project authors may be found in the NOTICE file.
|
|
3
|
-
#
|
|
4
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
# you may not use this file except in compliance with the License.
|
|
6
|
-
# You may obtain a copy of the License at
|
|
7
|
-
#
|
|
8
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
#
|
|
10
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
# See the License for the specific language governing permissions and
|
|
14
|
-
# limitations under the License.
|
|
15
|
-
|
|
16
|
-
module Mirah
|
|
17
|
-
VERSION = "0.0.9"
|
|
18
|
-
end
|
data/test/core/ast_test.rb
DELETED
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2010 The Mirah project authors. All Rights Reserved.
|
|
2
|
-
# All contributing project authors may be found in the NOTICE file.
|
|
3
|
-
#
|
|
4
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
# you may not use this file except in compliance with the License.
|
|
6
|
-
# You may obtain a copy of the License at
|
|
7
|
-
#
|
|
8
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
#
|
|
10
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
# See the License for the specific language governing permissions and
|
|
14
|
-
# limitations under the License.
|
|
15
|
-
require 'test_helper'
|
|
16
|
-
|
|
17
|
-
class AstTest < Test::Unit::TestCase
|
|
18
|
-
include Mirah
|
|
19
|
-
|
|
20
|
-
def test_args
|
|
21
|
-
new_ast = AST.parse("def foo(a, *c, &d); end").body[0]
|
|
22
|
-
arguments = new_ast.arguments
|
|
23
|
-
|
|
24
|
-
assert_not_nil(arguments)
|
|
25
|
-
inspected = "Arguments\n RequiredArgument(a)\n RestArgument(c)\n BlockArgument(d)"
|
|
26
|
-
assert_equal(inspected, arguments.inspect)
|
|
27
|
-
|
|
28
|
-
assert(AST::Arguments === arguments)
|
|
29
|
-
children = arguments.children
|
|
30
|
-
assert_not_nil(children)
|
|
31
|
-
assert_equal(5, children.size)
|
|
32
|
-
assert(Array === children[0])
|
|
33
|
-
assert(AST::RequiredArgument === children[0][0])
|
|
34
|
-
assert_equal("a", children[0][0].name)
|
|
35
|
-
assert_equal(arguments, children[0][0].parent)
|
|
36
|
-
assert(AST::RestArgument === children[2])
|
|
37
|
-
assert_equal("c", children[2].name)
|
|
38
|
-
assert_equal(arguments, children[2].parent)
|
|
39
|
-
assert(AST::BlockArgument === children[4])
|
|
40
|
-
assert_equal("d", children[4].name)
|
|
41
|
-
assert_equal(arguments, children[4].parent)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def test_locals
|
|
45
|
-
new_ast = AST.parse("a = 1; a").body
|
|
46
|
-
|
|
47
|
-
assert_not_nil(new_ast)
|
|
48
|
-
assert(AST::Body === new_ast)
|
|
49
|
-
inspected = "Body\n LocalAssignment(name = a, scope = Script, captured = false)\n Fixnum(1)\n FunctionalCall(a)"
|
|
50
|
-
assert_equal(inspected, new_ast.inspect)
|
|
51
|
-
|
|
52
|
-
asgn = new_ast[0]
|
|
53
|
-
var = new_ast[1]
|
|
54
|
-
|
|
55
|
-
assert(AST::LocalAssignment === asgn)
|
|
56
|
-
assert_equal("a", asgn.name)
|
|
57
|
-
assert(AST::Fixnum === asgn.value)
|
|
58
|
-
assert(AST::FunctionalCall === var)
|
|
59
|
-
assert_equal("a", var.name)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def test_fields
|
|
63
|
-
new_ast = AST.parse("@a = 1; @a").body
|
|
64
|
-
|
|
65
|
-
assert_not_nil(new_ast)
|
|
66
|
-
assert(AST::Body === new_ast)
|
|
67
|
-
inspected = "Body\n FieldAssignment(a)\n Fixnum(1)\n Field(a)"
|
|
68
|
-
assert_equal(inspected, new_ast.inspect)
|
|
69
|
-
|
|
70
|
-
asgn = new_ast[0]
|
|
71
|
-
var = new_ast[1]
|
|
72
|
-
|
|
73
|
-
assert(AST::FieldAssignment === asgn)
|
|
74
|
-
assert_equal("a", asgn.name)
|
|
75
|
-
assert(AST::Fixnum === asgn.value)
|
|
76
|
-
assert(AST::Field === var)
|
|
77
|
-
assert_equal("a", var.name)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def test_array
|
|
81
|
-
new_ast = AST.parse("[a = 1, 1]").body[0]
|
|
82
|
-
|
|
83
|
-
assert_not_nil(new_ast)
|
|
84
|
-
assert(AST::Array === new_ast)
|
|
85
|
-
assert_equal("Array\n LocalAssignment(name = a, scope = Script, captured = false)\n Fixnum(1)\n Fixnum(1)", new_ast.inspect)
|
|
86
|
-
|
|
87
|
-
assert(AST::LocalAssignment === new_ast[0])
|
|
88
|
-
assert(AST::Fixnum === new_ast[1])
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def test_call
|
|
92
|
-
new_ast = AST.parse("1.foo(1)").body[0]
|
|
93
|
-
|
|
94
|
-
assert_not_nil(new_ast)
|
|
95
|
-
assert(AST::Call === new_ast)
|
|
96
|
-
assert_equal("Call(foo)\n Fixnum(1)\n Fixnum(1)", new_ast.inspect)
|
|
97
|
-
|
|
98
|
-
assert_equal("foo", new_ast.name)
|
|
99
|
-
assert(AST::Fixnum === new_ast.target)
|
|
100
|
-
assert_not_nil(new_ast.parameters)
|
|
101
|
-
assert_equal(1, new_ast.parameters.size)
|
|
102
|
-
assert(AST::Fixnum === new_ast.parameters[0])
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def test_fcall
|
|
106
|
-
new_ast = AST.parse("foo(1)").body[0]
|
|
107
|
-
|
|
108
|
-
assert_not_nil(new_ast)
|
|
109
|
-
assert(AST::FunctionalCall === new_ast)
|
|
110
|
-
assert_equal("FunctionalCall(foo)\n Fixnum(1)", new_ast.inspect)
|
|
111
|
-
|
|
112
|
-
assert_equal("foo", new_ast.name)
|
|
113
|
-
assert_not_nil(new_ast.parameters)
|
|
114
|
-
assert_equal(1, new_ast.parameters.size)
|
|
115
|
-
assert(AST::Fixnum === new_ast.parameters[0])
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def test_if
|
|
119
|
-
new_ast = AST.parse("if 1; 2; elsif 3; 4; else; 5; end").body[0]
|
|
120
|
-
|
|
121
|
-
assert_not_nil(new_ast)
|
|
122
|
-
assert(AST::If === new_ast)
|
|
123
|
-
assert_equal("If\n Condition\n Fixnum(1)\n Fixnum(2)\n If\n Condition\n Fixnum(3)\n Fixnum(4)\n Fixnum(5)", new_ast.inspect)
|
|
124
|
-
|
|
125
|
-
assert(AST::Condition === new_ast.condition)
|
|
126
|
-
assert(AST::Fixnum === new_ast.condition.predicate)
|
|
127
|
-
assert(AST::Fixnum === new_ast.body)
|
|
128
|
-
assert(AST::If === new_ast.else)
|
|
129
|
-
assert(AST::Condition === new_ast.else.condition)
|
|
130
|
-
assert(AST::Fixnum === new_ast.else.condition.predicate)
|
|
131
|
-
assert(AST::Fixnum === new_ast.else.body)
|
|
132
|
-
assert(AST::Fixnum === new_ast.else.else)
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def test_begin
|
|
136
|
-
new_ast = AST.parse("begin; 1; 2; end").body
|
|
137
|
-
|
|
138
|
-
assert_not_nil(new_ast)
|
|
139
|
-
assert_equal("Body\n Fixnum(1)\n Fixnum(2)", new_ast.inspect)
|
|
140
|
-
assert(AST::Body === new_ast)
|
|
141
|
-
assert(AST::Fixnum === new_ast[0])
|
|
142
|
-
|
|
143
|
-
new_ast = AST.parse("begin; 1; end").body[0]
|
|
144
|
-
assert(AST::Fixnum === new_ast)
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def test_block
|
|
148
|
-
new_ast = AST.parse("1; 2").body
|
|
149
|
-
|
|
150
|
-
assert_not_nil(new_ast)
|
|
151
|
-
assert_equal("Body\n Fixnum(1)\n Fixnum(2)", new_ast.inspect)
|
|
152
|
-
assert(AST::Body === new_ast)
|
|
153
|
-
assert(AST::Fixnum === new_ast[0])
|
|
154
|
-
|
|
155
|
-
new_ast = AST.parse("1").body[0]
|
|
156
|
-
assert(AST::Fixnum === new_ast)
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
def test_fixnum
|
|
160
|
-
new_ast = AST.parse("1").body[0]
|
|
161
|
-
|
|
162
|
-
assert_not_nil(new_ast)
|
|
163
|
-
assert_equal("Fixnum(1)", new_ast.inspect)
|
|
164
|
-
assert(AST::Fixnum === new_ast)
|
|
165
|
-
assert_equal(1, new_ast.literal)
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def test_float
|
|
169
|
-
new_ast = AST.parse("1.0").body[0]
|
|
170
|
-
|
|
171
|
-
assert_not_nil(new_ast)
|
|
172
|
-
assert_equal("Float(1.0)", new_ast.inspect)
|
|
173
|
-
assert(AST::Float === new_ast)
|
|
174
|
-
assert_equal(1.0, new_ast.literal)
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
def test_class
|
|
178
|
-
new_ast = AST.parse("class Foo < Bar; 1; 2; end").body[0]
|
|
179
|
-
|
|
180
|
-
assert_not_nil(new_ast)
|
|
181
|
-
assert_equal("ClassDefinition(Foo)\n Constant(Bar)\n Body\n Body\n Fixnum(1)\n Fixnum(2)", new_ast.inspect)
|
|
182
|
-
assert(AST::ClassDefinition === new_ast)
|
|
183
|
-
assert_equal("Foo", new_ast.name)
|
|
184
|
-
|
|
185
|
-
assert(AST::Body === new_ast.body)
|
|
186
|
-
assert(AST::Fixnum === new_ast.body[0][0])
|
|
187
|
-
|
|
188
|
-
new_ast = AST.parse("class Foo < Bar; def foo; end; end").body[0]
|
|
189
|
-
|
|
190
|
-
assert_not_nil(new_ast)
|
|
191
|
-
assert_equal("ClassDefinition(Foo)\n Constant(Bar)\n Body\n MethodDefinition(foo)\n {:return=>nil}\n Arguments\n Null(nil)", new_ast.inspect)
|
|
192
|
-
assert_equal(new_ast, new_ast.body.parent)
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
def test_defn
|
|
196
|
-
new_ast = AST.parse("def foo(a, b); 1; end").body[0]
|
|
197
|
-
|
|
198
|
-
assert_not_nil(new_ast)
|
|
199
|
-
assert_equal("MethodDefinition(foo)\n {:return=>nil}\n Arguments\n RequiredArgument(a)\n RequiredArgument(b)\n Fixnum(1)", new_ast.inspect)
|
|
200
|
-
assert(AST::MethodDefinition === new_ast)
|
|
201
|
-
assert_equal("foo", new_ast.name)
|
|
202
|
-
assert_not_nil(new_ast.signature)
|
|
203
|
-
assert_equal(1, new_ast.signature.size)
|
|
204
|
-
assert(nil === new_ast.signature[:return])
|
|
205
|
-
assert(AST::Arguments === new_ast.arguments)
|
|
206
|
-
assert(AST::Fixnum === new_ast.body)
|
|
207
|
-
|
|
208
|
-
new_ast = AST.parse("def foo; end").body[0]
|
|
209
|
-
|
|
210
|
-
assert_not_nil(new_ast)
|
|
211
|
-
assert_equal("MethodDefinition(foo)\n {:return=>nil}\n Arguments\n Null(nil)", new_ast.inspect)
|
|
212
|
-
assert_not_nil(new_ast.arguments)
|
|
213
|
-
assert_equal([], new_ast.arguments.args)
|
|
214
|
-
assert_equal(nil, new_ast.arguments.opt_args)
|
|
215
|
-
assert_equal(nil, new_ast.arguments.rest_arg)
|
|
216
|
-
assert_equal(nil, new_ast.arguments.block_arg)
|
|
217
|
-
|
|
218
|
-
new_ast = AST.parse("def foo(a, b):int; 1; end").body[0]
|
|
219
|
-
assert_equal("FunctionalCall(int)", new_ast.return_type.to_s)
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
def test_defs
|
|
223
|
-
new_ast = AST.parse("def self.foo(a, b); 1; end").body[0]
|
|
224
|
-
|
|
225
|
-
assert_not_nil(new_ast)
|
|
226
|
-
inspected = "StaticMethodDefinition(foo)\n {:return=>nil}\n Arguments\n RequiredArgument(a)\n RequiredArgument(b)\n Fixnum(1)"
|
|
227
|
-
assert_equal(inspected, new_ast.inspect)
|
|
228
|
-
assert(AST::StaticMethodDefinition === new_ast)
|
|
229
|
-
assert_equal("foo", new_ast.name)
|
|
230
|
-
assert_not_nil(new_ast.signature)
|
|
231
|
-
assert_equal(1, new_ast.signature.size)
|
|
232
|
-
assert(nil === new_ast.signature[:return])
|
|
233
|
-
assert(AST::Arguments === new_ast.arguments)
|
|
234
|
-
assert(AST::Fixnum === new_ast.body)
|
|
235
|
-
|
|
236
|
-
new_ast = AST.parse("def self.foo; end").body[0]
|
|
237
|
-
|
|
238
|
-
assert_not_nil(new_ast)
|
|
239
|
-
assert_equal("StaticMethodDefinition(foo)\n {:return=>nil}\n Arguments\n Null(nil)", new_ast.inspect)
|
|
240
|
-
assert_not_nil(new_ast.arguments)
|
|
241
|
-
assert_equal([], new_ast.arguments.args)
|
|
242
|
-
assert_equal(nil, new_ast.arguments.opt_args)
|
|
243
|
-
assert_equal(nil, new_ast.arguments.rest_arg)
|
|
244
|
-
assert_equal(nil, new_ast.arguments.block_arg)
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
def test_return
|
|
248
|
-
new_ast = AST.parse("return 1").body[0]
|
|
249
|
-
|
|
250
|
-
assert_not_nil(new_ast)
|
|
251
|
-
inspected = "Return\n Fixnum(1)"
|
|
252
|
-
assert_equal(inspected, new_ast.inspect)
|
|
253
|
-
assert(AST::Return === new_ast)
|
|
254
|
-
assert(AST::Fixnum === new_ast.value)
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
def test_vcall
|
|
258
|
-
new_ast = AST.parse("foo").body[0]
|
|
259
|
-
|
|
260
|
-
assert_not_nil(new_ast)
|
|
261
|
-
assert(AST::FunctionalCall === new_ast)
|
|
262
|
-
assert_equal("FunctionalCall(foo)", new_ast.inspect)
|
|
263
|
-
|
|
264
|
-
assert_equal("foo", new_ast.name)
|
|
265
|
-
assert_not_nil(new_ast.parameters)
|
|
266
|
-
assert_equal(0, new_ast.parameters.size)
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
def test_while
|
|
270
|
-
new_ast = AST.parse("while 1; 2; end").body[0]
|
|
271
|
-
|
|
272
|
-
assert_not_nil(new_ast)
|
|
273
|
-
assert(AST::Loop === new_ast)
|
|
274
|
-
assert_equal("Loop(check_first = true, negative = false)\n Body\n Condition\n Fixnum(1)\n Body\n Fixnum(2)\n Body", new_ast.inspect)
|
|
275
|
-
assert(new_ast.check_first?)
|
|
276
|
-
assert(!new_ast.negative?)
|
|
277
|
-
assert(AST::Condition === new_ast.condition)
|
|
278
|
-
assert(AST::Fixnum === new_ast.condition.predicate)
|
|
279
|
-
assert(AST::Fixnum === new_ast.body)
|
|
280
|
-
|
|
281
|
-
new_ast = AST.parse("begin; 2; end while 1").body[0]
|
|
282
|
-
|
|
283
|
-
assert_not_nil(new_ast)
|
|
284
|
-
assert(AST::Loop === new_ast)
|
|
285
|
-
assert_equal("Loop(check_first = false, negative = false)\n Body\n Condition\n Fixnum(1)\n Body\n Fixnum(2)\n Body", new_ast.inspect)
|
|
286
|
-
assert(!new_ast.check_first?)
|
|
287
|
-
assert(!new_ast.negative?)
|
|
288
|
-
assert(AST::Condition === new_ast.condition)
|
|
289
|
-
assert(AST::Fixnum === new_ast.condition.predicate)
|
|
290
|
-
assert(AST::Fixnum === new_ast.body)
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
def test_until
|
|
294
|
-
new_ast = AST.parse("until 1; 2; end").body[0]
|
|
295
|
-
|
|
296
|
-
assert_not_nil(new_ast)
|
|
297
|
-
assert(AST::Loop === new_ast)
|
|
298
|
-
assert_equal("Loop(check_first = true, negative = true)\n Body\n Condition\n Fixnum(1)\n Body\n Fixnum(2)\n Body", new_ast.inspect)
|
|
299
|
-
assert(new_ast.check_first?)
|
|
300
|
-
assert(new_ast.negative?)
|
|
301
|
-
assert(AST::Condition === new_ast.condition)
|
|
302
|
-
assert(AST::Fixnum === new_ast.condition.predicate)
|
|
303
|
-
assert(AST::Fixnum === new_ast.body)
|
|
304
|
-
|
|
305
|
-
new_ast = AST.parse("begin; 2; end until 1").body[0]
|
|
306
|
-
|
|
307
|
-
assert_not_nil(new_ast)
|
|
308
|
-
assert(AST::Loop === new_ast)
|
|
309
|
-
assert_equal("Loop(check_first = false, negative = true)\n Body\n Condition\n Fixnum(1)\n Body\n Fixnum(2)\n Body", new_ast.inspect)
|
|
310
|
-
assert(!new_ast.check_first?)
|
|
311
|
-
assert(new_ast.negative?)
|
|
312
|
-
assert(AST::Condition === new_ast.condition)
|
|
313
|
-
assert(AST::Fixnum === new_ast.condition.predicate)
|
|
314
|
-
assert(AST::Fixnum === new_ast.body)
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
def test_string
|
|
318
|
-
new_ast = AST.parse("'foo'").body[0]
|
|
319
|
-
|
|
320
|
-
assert_not_nil(new_ast)
|
|
321
|
-
assert(AST::String === new_ast)
|
|
322
|
-
assert_equal("String(\"foo\")", new_ast.inspect)
|
|
323
|
-
assert_equal("foo", new_ast.literal)
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
def test_root
|
|
327
|
-
new_ast = AST.parse("1").body[0]
|
|
328
|
-
|
|
329
|
-
assert_not_nil(new_ast)
|
|
330
|
-
assert(AST::Fixnum === new_ast)
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
def test_boolean
|
|
334
|
-
new_ast1 = AST.parse("true").body[0]
|
|
335
|
-
new_ast2 = AST.parse("false").body[0]
|
|
336
|
-
|
|
337
|
-
assert_not_nil(new_ast1)
|
|
338
|
-
assert_not_nil(new_ast2)
|
|
339
|
-
assert(AST::Boolean === new_ast1)
|
|
340
|
-
assert(AST::Boolean === new_ast2)
|
|
341
|
-
assert(new_ast1.literal)
|
|
342
|
-
assert(!new_ast2.literal)
|
|
343
|
-
end
|
|
344
|
-
|
|
345
|
-
def test_return
|
|
346
|
-
new_ast = AST.parse("return 1").body[0]
|
|
347
|
-
|
|
348
|
-
assert_not_nil(new_ast)
|
|
349
|
-
assert(AST::Return === new_ast)
|
|
350
|
-
assert(AST::Fixnum === new_ast.value)
|
|
351
|
-
assert(1, new_ast.value.literal)
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
def test_empty_array
|
|
355
|
-
new_ast = AST.parse("int[5]").body[0]
|
|
356
|
-
|
|
357
|
-
assert_not_nil(new_ast)
|
|
358
|
-
assert(AST::EmptyArray === new_ast)
|
|
359
|
-
assert_equal(5, new_ast.size.literal)
|
|
360
|
-
|
|
361
|
-
assert_equal("int", new_ast.type_node.name)
|
|
362
|
-
end
|
|
363
|
-
|
|
364
|
-
def test_block_comment
|
|
365
|
-
new_ast = AST.parse("/* foo\nbar*/1").body[0]
|
|
366
|
-
|
|
367
|
-
assert_not_nil(new_ast)
|
|
368
|
-
assert_equal("Fixnum(1)", new_ast.inspect)
|
|
369
|
-
assert(AST::Fixnum === new_ast)
|
|
370
|
-
assert_equal(1, new_ast.literal)
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
def test_incorrect_syntax_raises_syntax_error
|
|
374
|
-
assert_raises SyntaxError do
|
|
375
|
-
AST.parse("puts( 'aoue'")
|
|
376
|
-
end
|
|
377
|
-
end
|
|
378
|
-
|
|
379
|
-
def test_parsing_empty_string_raises_no_error
|
|
380
|
-
AST.parse("")
|
|
381
|
-
end
|
|
382
|
-
end
|