duby 0.0.2-java → 0.0.3-java
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/README.txt +18 -7
- data/Rakefile +72 -0
- data/examples/ant/example-build.xml +7 -0
- data/examples/appengine/Rakefile +8 -67
- data/examples/appengine/Readme +4 -3
- data/examples/appengine/lib/duby/appengine_tasks.rb +173 -0
- data/examples/appengine/lib/duby/plugin/datastore.rb +92 -31
- data/examples/appengine/lib/duby_task.rb +61 -0
- data/examples/appengine/src/com/ribrdb/DubyApp.duby +32 -6
- data/examples/appengine/src/com/ribrdb/list.dhtml +2 -2
- data/examples/appengine/{config.ru → src/config.ru} +0 -0
- data/examples/bintrees.duby +66 -0
- data/examples/dynamic.duby +17 -0
- data/examples/fib.duby +3 -11
- data/examples/fields.duby +3 -3
- data/examples/fractal.duby +1 -3
- data/examples/sort_closure.duby +7 -0
- data/examples/swing.duby +11 -11
- data/javalib/duby-bootstrap.jar +0 -0
- data/javalib/dynalang-invoke-0.1.jar +0 -0
- data/lib/duby.rb +168 -35
- data/lib/duby/ast.rb +224 -27
- data/lib/duby/ast/call.rb +85 -25
- data/lib/duby/ast/class.rb +112 -28
- data/lib/duby/ast/flow.rb +65 -44
- data/lib/duby/ast/intrinsics.rb +223 -21
- data/lib/duby/ast/literal.rb +67 -16
- data/lib/duby/ast/local.rb +36 -40
- data/lib/duby/ast/method.rb +83 -67
- data/lib/duby/ast/structure.rb +105 -23
- data/lib/duby/compiler.rb +83 -28
- data/lib/duby/env.rb +33 -0
- data/lib/duby/jvm/base.rb +210 -0
- data/lib/duby/jvm/compiler.rb +293 -219
- data/lib/duby/jvm/method_lookup.rb +77 -67
- data/lib/duby/jvm/source_compiler.rb +250 -157
- data/lib/duby/jvm/source_generator/builder.rb +53 -49
- data/lib/duby/jvm/source_generator/loops.rb +9 -9
- data/lib/duby/jvm/source_generator/precompile.rb +35 -25
- data/lib/duby/jvm/typer.rb +19 -10
- data/lib/duby/jvm/types.rb +127 -68
- data/lib/duby/jvm/types/basic_types.rb +26 -13
- data/lib/duby/jvm/types/enumerable.rb +6 -4
- data/lib/duby/jvm/types/factory.rb +49 -13
- data/lib/duby/jvm/types/floats.rb +16 -0
- data/lib/duby/jvm/types/integers.rb +63 -2
- data/lib/duby/jvm/types/intrinsics.rb +43 -21
- data/lib/duby/jvm/types/methods.rb +326 -86
- data/lib/duby/jvm/types/number.rb +3 -0
- data/lib/duby/nbcompiler.rb +1 -1
- data/lib/duby/plugin/edb.rb +1 -1
- data/lib/duby/plugin/java.rb +10 -1
- data/lib/duby/transform.rb +134 -46
- data/lib/duby/typer.rb +75 -50
- data/test/test_ast.rb +106 -106
- data/test/test_compilation.rb +46 -32
- data/test/test_env.rb +42 -0
- data/test/test_java_typer.rb +35 -51
- data/test/test_javac_compiler.rb +4 -1
- data/test/test_jvm_compiler.rb +564 -133
- data/test/test_typer.rb +68 -92
- metadata +37 -21
- data/examples/README +0 -16
- data/lib/duby/c/compiler.rb +0 -134
- data/lib/duby/old/compiler_old.rb +0 -845
- data/lib/duby/old/declaration.rb +0 -72
- data/lib/duby/old/mapper.rb +0 -72
- data/lib/duby/old/signature.rb +0 -52
- data/lib/duby/old/typer_old.rb +0 -163
- data/lib/duby/plugin/math.rb +0 -84
- data/test/test_math_plugin.rb +0 -87
data/lib/duby/ast/intrinsics.rb
CHANGED
@@ -1,54 +1,256 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
1
3
|
module Duby::AST
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
|
5
|
+
class MacroDefinition < Node
|
6
|
+
include Named
|
7
|
+
|
8
|
+
child :arguments
|
9
|
+
child :body
|
10
|
+
|
11
|
+
attr_accessor :proxy
|
12
|
+
|
13
|
+
def self.new(*args, &block)
|
14
|
+
real_node = super
|
15
|
+
real_node.proxy = NodeProxy.new(real_node)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(parent, line_number, name, &block)
|
7
19
|
super(parent, line_number, &block)
|
8
|
-
@
|
9
|
-
@println = println
|
20
|
+
@name = name
|
10
21
|
end
|
11
22
|
|
12
23
|
def infer(typer)
|
13
|
-
|
14
|
-
|
15
|
-
|
24
|
+
resolve_if(typer) do
|
25
|
+
self_type = typer.self_type
|
26
|
+
extension_name = "%s$%s" % [self_type.name,
|
27
|
+
typer.transformer.tmp("Extension%s")]
|
28
|
+
klass = build_and_load_extension(self_type,
|
29
|
+
extension_name,
|
30
|
+
typer.transformer.state)
|
31
|
+
|
32
|
+
# restore the self type since we're sharing a type factory
|
33
|
+
typer.known_types['self'] = self_type
|
34
|
+
|
35
|
+
arg_types = argument_types
|
36
|
+
macro = self_type.add_macro(name, *arg_types) do |duby, call|
|
37
|
+
expander = klass.constructors[0].newInstance(duby, call)
|
38
|
+
expander.expand
|
39
|
+
end
|
40
|
+
if arguments[-1].kind_of?(BlockArgument) && arguments[-1].optional?
|
41
|
+
arg_types.pop
|
42
|
+
typer.self_type.add_method(name, arg_types, macro)
|
43
|
+
end
|
44
|
+
proxy.__inline__(Noop.new(parent, position))
|
45
|
+
proxy.infer(typer)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def argument_types
|
50
|
+
arguments.map do |arg|
|
51
|
+
if arg.kind_of?(BlockArgument)
|
52
|
+
TypeReference::BlockType
|
53
|
+
else
|
54
|
+
# TODO support typed args. Also there should be a way
|
55
|
+
# to accept any AST node.
|
56
|
+
Duby::JVM::Types::Object
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def signature
|
62
|
+
args = argument_types
|
63
|
+
if args.size > 0 && args[-1].block?
|
64
|
+
args[-1] = BiteScript::ASM::Type.getObjectType('duby.lang.compiler.Block')
|
65
|
+
end
|
66
|
+
[nil] + args
|
67
|
+
end
|
68
|
+
|
69
|
+
def build_and_load_extension(parent, name, state)
|
70
|
+
transformer = Duby::Transform::Transformer.new(state)
|
71
|
+
ast = build_ast(name, parent, transformer)
|
72
|
+
puts ast.inspect if state.verbose
|
73
|
+
classes = compile_ast(name, ast, transformer)
|
74
|
+
loader = DubyClassLoader.new(
|
75
|
+
JRuby.runtime.jruby_class_loader, classes)
|
76
|
+
klass = loader.loadClass(name, true)
|
77
|
+
annotate(parent, name)
|
78
|
+
klass
|
79
|
+
end
|
80
|
+
|
81
|
+
def annotate(type, name)
|
82
|
+
node = type.unmeta.node
|
83
|
+
if node
|
84
|
+
extension = node.annotation('duby.anno.Extensions')
|
85
|
+
extension ||= begin
|
86
|
+
node.annotations << Annotation.new(
|
87
|
+
nil, nil, BiteScript::ASM::Type.getObjectType('duby/anno/Extensions'))
|
88
|
+
node.annotations[-1].runtime = false
|
89
|
+
node.annotations[-1]
|
90
|
+
end
|
91
|
+
extension['macros'] ||= []
|
92
|
+
macro = Annotation.new(nil, nil,
|
93
|
+
BiteScript::ASM::Type.getObjectType('duby/anno/Macro'))
|
94
|
+
macro['name'] = name
|
95
|
+
macro['signature'] = BiteScript::Signature.signature(*signature)
|
96
|
+
extension['macros'] << macro
|
16
97
|
else
|
17
|
-
|
98
|
+
puts "Warning: No ClassDefinition for #{type.name}. Macros can't be loaded from disk."
|
18
99
|
end
|
19
|
-
|
100
|
+
end
|
101
|
+
|
102
|
+
def compile_ast(name, ast, transformer)
|
103
|
+
filename = name.gsub(".", "/")
|
104
|
+
typer = Duby::Typer::JVM.new(filename, transformer)
|
105
|
+
typer.infer(ast)
|
106
|
+
typer.resolve(true)
|
107
|
+
compiler = Duby::Compiler::JVM.new(filename)
|
108
|
+
ast.compile(compiler, false)
|
109
|
+
class_map = {}
|
110
|
+
compiler.generate do |outfile, builder|
|
111
|
+
outfile = "#{transformer.destination}#{outfile}"
|
112
|
+
FileUtils.mkdir_p(File.dirname(outfile))
|
113
|
+
File.open(outfile, 'w') do |f|
|
114
|
+
bytes = builder.generate
|
115
|
+
name = builder.class_name.gsub(/\//, '.')
|
116
|
+
class_map[name] = bytes
|
117
|
+
f.write(bytes)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
class_map
|
121
|
+
end
|
122
|
+
|
123
|
+
def build_ast(name, parent, transformer)
|
124
|
+
# TODO should use a new type factory too.
|
125
|
+
ast = Duby::AST.parse_ruby("import duby.lang.compiler.Node")
|
126
|
+
ast = transformer.transform(ast, nil)
|
127
|
+
|
128
|
+
# Start building the extension class
|
129
|
+
extension = transformer.define_class(position, name)
|
130
|
+
#extension.superclass = Duby::AST.type('duby.lang.compiler.Macro')
|
131
|
+
extension.interfaces = [Duby::AST.type('duby.lang.compiler.Macro')]
|
132
|
+
|
133
|
+
# The constructor just saves the state
|
134
|
+
extension.define_constructor(
|
135
|
+
position,
|
136
|
+
['duby', Duby::AST.type('duby.lang.compiler.Compiler')],
|
137
|
+
['call', Duby::AST.type('duby.lang.compiler.Call')]) do |c|
|
138
|
+
transformer.eval("@duby = duby;@call = call", '-', c, 'duby', 'call')
|
139
|
+
end
|
140
|
+
|
141
|
+
node_type = Duby::AST.type('duby.lang.compiler.Node')
|
142
|
+
|
143
|
+
# expand() parses the arguments out of call and then passes them off to
|
144
|
+
# _expand
|
145
|
+
expand = extension.define_method(
|
146
|
+
position, 'expand', node_type)
|
147
|
+
args = []
|
148
|
+
arguments.each_with_index do |arg, i|
|
149
|
+
# TODO optional args
|
150
|
+
args << if arg.kind_of?(BlockArgument)
|
151
|
+
"@call.block"
|
152
|
+
else
|
153
|
+
"Node(args.get(#{i}))"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
expand.body = transformer.eval(<<-end)
|
157
|
+
args = @call.arguments
|
158
|
+
_expand(#{args.join(', ')})
|
159
|
+
end
|
160
|
+
actual_args = arguments.map do |arg|
|
161
|
+
[arg.name, node_type, arg.position]
|
162
|
+
end
|
163
|
+
m = extension.define_method(position, '_expand', node_type, *actual_args)
|
164
|
+
m.body = self.body
|
165
|
+
ast
|
20
166
|
end
|
21
167
|
end
|
22
|
-
|
168
|
+
|
169
|
+
defmacro('defmacro') do |duby, fcall, parent|
|
170
|
+
macro = fcall.args_node[0]
|
171
|
+
block_arg = nil
|
172
|
+
args_node = macro.args_node
|
173
|
+
body = macro.iter_node || fcall.iter_node
|
174
|
+
if args_node.respond_to? :getBodyNode
|
175
|
+
block_arg = args_node.body_node
|
176
|
+
args_node = args_node.args_node
|
177
|
+
body = fcall.iter_node
|
178
|
+
end
|
179
|
+
MacroDefinition.new(parent, fcall.position, macro.name) do |mdef|
|
180
|
+
# TODO optional args?
|
181
|
+
args = if args_node
|
182
|
+
args_node.map do |arg|
|
183
|
+
case arg
|
184
|
+
when JRubyAst::LocalAsgnNode
|
185
|
+
OptionalArgument.new(mdef, arg.position, arg.name) do |optarg|
|
186
|
+
# TODO check that they actually passed nil as the value
|
187
|
+
Null.new(parent, arg.value_node.position)
|
188
|
+
end
|
189
|
+
when JRubyAst::VCallNode, JRubyAst::LocalVarNode
|
190
|
+
RequiredArgument.new(mdef, arg.position, arg.name)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
else
|
194
|
+
[]
|
195
|
+
end
|
196
|
+
if block_arg
|
197
|
+
args << BlockArgument.new(mdef, block_arg.position, block_arg.name)
|
198
|
+
args[-1].optional = block_arg.kind_of?(JRubyAst::LocalAsgnNode)
|
199
|
+
end
|
200
|
+
body_node = duby.transform(body.body_node, mdef) if body.body_node
|
201
|
+
[args, body_node]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
23
205
|
defmacro('puts') do |transformer, fcall, parent|
|
24
|
-
|
25
|
-
if fcall.respond_to?(:args_node) && fcall.args_node
|
206
|
+
Call.new(parent, fcall.position, "println") do |x|
|
207
|
+
args = if fcall.respond_to?(:args_node) && fcall.args_node
|
26
208
|
fcall.args_node.child_nodes.map do |arg|
|
27
|
-
transformer.transform(arg,
|
209
|
+
transformer.transform(arg, x)
|
28
210
|
end
|
29
211
|
else
|
30
212
|
[]
|
31
213
|
end
|
214
|
+
[
|
215
|
+
Call.new(x, fcall.position, "out") do |y|
|
216
|
+
[
|
217
|
+
Constant.new(y, fcall.position, "System"),
|
218
|
+
[]
|
219
|
+
]
|
220
|
+
end,
|
221
|
+
args,
|
222
|
+
nil
|
223
|
+
]
|
32
224
|
end
|
33
225
|
end
|
34
226
|
|
35
227
|
defmacro('print') do |transformer, fcall, parent|
|
36
|
-
|
37
|
-
if fcall.respond_to?(:args_node) && fcall.args_node
|
228
|
+
Call.new(parent, fcall.position, "print") do |x|
|
229
|
+
args = if fcall.respond_to?(:args_node) && fcall.args_node
|
38
230
|
fcall.args_node.child_nodes.map do |arg|
|
39
|
-
transformer.transform(arg,
|
231
|
+
transformer.transform(arg, x)
|
40
232
|
end
|
41
233
|
else
|
42
234
|
[]
|
43
235
|
end
|
236
|
+
[
|
237
|
+
Call.new(x, fcall.position, "out") do |y|
|
238
|
+
[
|
239
|
+
Constant.new(y, fcall.position, "System"),
|
240
|
+
[]
|
241
|
+
]
|
242
|
+
end,
|
243
|
+
args,
|
244
|
+
nil
|
245
|
+
]
|
44
246
|
end
|
45
247
|
end
|
46
|
-
|
248
|
+
|
47
249
|
class InlineCode
|
48
250
|
def initialize(&block)
|
49
251
|
@block = block
|
50
252
|
end
|
51
|
-
|
253
|
+
|
52
254
|
def inline(transformer, call)
|
53
255
|
@block.call(transformer, call)
|
54
256
|
end
|
data/lib/duby/ast/literal.rb
CHANGED
@@ -5,75 +5,126 @@ module Duby::AST
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def infer(typer)
|
8
|
+
children.each do |kid|
|
9
|
+
kid.infer(typer)
|
10
|
+
end
|
8
11
|
@inferred_type = typer.array_type
|
9
12
|
end
|
10
13
|
end
|
11
|
-
|
14
|
+
|
12
15
|
class Fixnum < Node
|
13
16
|
include Literal
|
14
|
-
|
17
|
+
|
15
18
|
def initialize(parent, line_number, literal)
|
16
19
|
super(parent, line_number)
|
17
20
|
@literal = literal
|
18
21
|
end
|
19
|
-
|
22
|
+
|
20
23
|
def infer(typer)
|
21
24
|
return @inferred_type if resolved?
|
22
25
|
resolved!
|
23
26
|
@inferred_type = typer.fixnum_type
|
24
27
|
end
|
25
|
-
|
28
|
+
|
26
29
|
def ==(other)
|
27
30
|
@literal == other.literal
|
28
31
|
end
|
29
|
-
|
32
|
+
|
30
33
|
def eql?(other)
|
31
34
|
self.class == other.class && @literal.eql?(other.literal)
|
32
35
|
end
|
33
36
|
end
|
34
|
-
|
37
|
+
|
35
38
|
class Float < Node
|
36
39
|
include Literal
|
37
|
-
|
40
|
+
|
38
41
|
def initialize(parent, line_number, literal)
|
39
42
|
super(parent, line_number)
|
40
43
|
@literal = literal
|
41
44
|
end
|
42
|
-
|
45
|
+
|
43
46
|
def infer(typer)
|
44
47
|
return @inferred_type if resolved?
|
45
48
|
resolved!
|
46
49
|
@inferred_type = typer.float_type
|
47
50
|
end
|
48
51
|
end
|
49
|
-
|
52
|
+
|
50
53
|
class Hash < Node; end
|
51
|
-
|
54
|
+
|
55
|
+
class Regexp < Node
|
56
|
+
include Literal
|
57
|
+
|
58
|
+
def initialize(parent, line_number, literal)
|
59
|
+
super(parent, line_number)
|
60
|
+
@literal = literal
|
61
|
+
end
|
62
|
+
|
63
|
+
def infer(typer)
|
64
|
+
return @inferred_type if resolved?
|
65
|
+
resolved!
|
66
|
+
@inferred_type ||= typer.regexp_type
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
52
70
|
class String < Node
|
53
71
|
include Literal
|
54
|
-
|
72
|
+
|
55
73
|
def initialize(parent, line_number, literal)
|
56
74
|
super(parent, line_number)
|
57
75
|
@literal = literal
|
58
76
|
end
|
59
|
-
|
77
|
+
|
60
78
|
def infer(typer)
|
61
79
|
return @inferred_type if resolved?
|
62
80
|
resolved!
|
63
81
|
@inferred_type ||= typer.string_type
|
64
82
|
end
|
65
83
|
end
|
66
|
-
|
84
|
+
|
85
|
+
class StringConcat < Node
|
86
|
+
def initialize(parent, position, &block)
|
87
|
+
super(parent, position, &block)
|
88
|
+
end
|
89
|
+
|
90
|
+
def infer(typer)
|
91
|
+
unless resolved?
|
92
|
+
resolved = true
|
93
|
+
children.each {|node| node.infer(typer); resolved &&= node.resolved?}
|
94
|
+
resolved! if resolved
|
95
|
+
@inferred_type ||= typer.string_type
|
96
|
+
end
|
97
|
+
@inferred_type
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class ToString < Node
|
102
|
+
child :body
|
103
|
+
|
104
|
+
def initialize(parent, position)
|
105
|
+
super(parent, position)
|
106
|
+
end
|
107
|
+
|
108
|
+
def infer(typer)
|
109
|
+
unless resolved?
|
110
|
+
body.infer(typer)
|
111
|
+
resolved! if body.resolved?
|
112
|
+
@inferred_type ||= typer.string_type
|
113
|
+
end
|
114
|
+
@inferred_type
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
67
118
|
class Symbol < Node; end
|
68
|
-
|
119
|
+
|
69
120
|
class Boolean < Node
|
70
121
|
include Literal
|
71
|
-
|
122
|
+
|
72
123
|
def initialize(parent, line_number, literal)
|
73
124
|
super(parent, line_number)
|
74
125
|
@literal = literal
|
75
126
|
end
|
76
|
-
|
127
|
+
|
77
128
|
def infer(typer)
|
78
129
|
return @inferred_type if resolved?
|
79
130
|
resolved!
|
data/lib/duby/ast/local.rb
CHANGED
@@ -4,89 +4,85 @@ module Duby::AST
|
|
4
4
|
include Typed
|
5
5
|
include Scoped
|
6
6
|
|
7
|
-
|
7
|
+
child :type
|
8
|
+
|
9
|
+
def initialize(parent, line_number, name, &block)
|
8
10
|
super(parent, line_number, &block)
|
9
11
|
@name = name
|
10
|
-
@captured = captured
|
11
|
-
@type = children[0]
|
12
12
|
end
|
13
13
|
|
14
14
|
def captured?
|
15
|
-
|
15
|
+
scope.static_scope.captured?(name)
|
16
16
|
end
|
17
17
|
|
18
18
|
def infer(typer)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if @inferred_type
|
23
|
-
resolved!
|
24
|
-
typer.learn_local_type(scope, name, @inferred_type)
|
25
|
-
else
|
26
|
-
typer.defer(self)
|
27
|
-
end
|
19
|
+
resolve_if(typer) do
|
20
|
+
scope.static_scope << name
|
21
|
+
typer.known_types[type] || type
|
28
22
|
end
|
29
|
-
|
23
|
+
end
|
24
|
+
|
25
|
+
def resolved!(typer)
|
26
|
+
typer.learn_local_type(containing_scope, name, @inferred_type)
|
27
|
+
super
|
30
28
|
end
|
31
29
|
end
|
32
|
-
|
30
|
+
|
33
31
|
class LocalAssignment < Node
|
34
32
|
include Named
|
35
33
|
include Valued
|
36
34
|
include Scoped
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
|
36
|
+
child :value
|
37
|
+
|
38
|
+
def initialize(parent, line_number, name, &block)
|
39
|
+
super(parent, line_number, &block)
|
42
40
|
@name = name
|
43
41
|
end
|
44
42
|
|
45
43
|
def captured?
|
46
|
-
|
44
|
+
scope.static_scope.captured?(name)
|
47
45
|
end
|
48
46
|
|
49
47
|
def to_s
|
50
|
-
"LocalAssignment(name = #{name}, scope = #{scope}, captured = #{captured?})"
|
48
|
+
"LocalAssignment(name = #{name}, scope = #{scope}, captured = #{captured? == true})"
|
51
49
|
end
|
52
|
-
|
53
|
-
def infer(typer)
|
54
|
-
unless @inferred_type
|
55
|
-
@inferred_type = typer.learn_local_type(scope, name, typer.infer(value))
|
56
50
|
|
57
|
-
|
51
|
+
def infer(typer)
|
52
|
+
resolve_if(typer) do
|
53
|
+
scope.static_scope << name
|
54
|
+
typer.infer(value)
|
58
55
|
end
|
56
|
+
end
|
59
57
|
|
60
|
-
|
58
|
+
def resolved!(typer)
|
59
|
+
typer.learn_local_type(containing_scope, name, @inferred_type)
|
60
|
+
super
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
64
|
class Local < Node
|
65
65
|
include Named
|
66
66
|
include Scoped
|
67
|
-
|
68
|
-
def initialize(parent, line_number, name
|
67
|
+
|
68
|
+
def initialize(parent, line_number, name)
|
69
69
|
super(parent, line_number, [])
|
70
70
|
@name = name
|
71
|
-
@captured = captured
|
72
71
|
end
|
73
72
|
|
74
73
|
def captured?
|
75
|
-
|
74
|
+
scope.static_scope.captured?(name)
|
76
75
|
end
|
77
76
|
|
78
77
|
def to_s
|
79
|
-
"Local(name = #{name}, scope = #{scope}, captured = #{captured?})"
|
78
|
+
"Local(name = #{name}, scope = #{scope}, captured = #{captured? == true})"
|
80
79
|
end
|
81
|
-
|
82
|
-
def infer(typer)
|
83
|
-
unless @inferred_type
|
84
|
-
@inferred_type = typer.local_type(scope, name)
|
85
80
|
|
86
|
-
|
81
|
+
def infer(typer)
|
82
|
+
resolve_if(typer) do
|
83
|
+
scope.static_scope << name
|
84
|
+
typer.local_type(containing_scope, name)
|
87
85
|
end
|
88
|
-
|
89
|
-
@inferred_type
|
90
86
|
end
|
91
87
|
end
|
92
88
|
end
|