rsense-core 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +1 -0
  5. data/README.md +35 -0
  6. data/Rakefile +84 -0
  7. data/TypeAnnotation.tokens +41 -0
  8. data/build.xml +84 -0
  9. data/build_lib/antlr-3.2.jar +0 -0
  10. data/lib/jars/ant-1.7.0.jar +0 -0
  11. data/lib/jars/ant-launcher-1.7.0.jar +0 -0
  12. data/lib/jars/antlr-runtime-3.2.jar +0 -0
  13. data/lib/jars/bsf-2.3.0.jar +0 -0
  14. data/lib/rsense-core.rb +28 -0
  15. data/lib/rsense.jar +0 -0
  16. data/lib/rsense/core.rb +5 -0
  17. data/lib/rsense/core/version.rb +5 -0
  18. data/lib/rsense/parser.rb +6 -0
  19. data/lib/rsense/ruby.rb +19 -0
  20. data/lib/rsense/typing.rb +13 -0
  21. data/lib/rsense/typing/annotation.rb +20 -0
  22. data/lib/rsense/typing/runtime.rb +23 -0
  23. data/lib/rsense/typing/vertex.rb +15 -0
  24. data/lib/rsense/util.rb +9 -0
  25. data/rsense-core.gemspec +30 -0
  26. data/src/org/cx4a/rsense/CodeAssist.java +744 -0
  27. data/src/org/cx4a/rsense/CodeAssistError.java +31 -0
  28. data/src/org/cx4a/rsense/CodeAssistResult.java +42 -0
  29. data/src/org/cx4a/rsense/CodeCompletionResult.java +65 -0
  30. data/src/org/cx4a/rsense/FindDefinitionResult.java +24 -0
  31. data/src/org/cx4a/rsense/LoadResult.java +19 -0
  32. data/src/org/cx4a/rsense/Main.java +916 -0
  33. data/src/org/cx4a/rsense/Options.java +353 -0
  34. data/src/org/cx4a/rsense/Project.java +103 -0
  35. data/src/org/cx4a/rsense/TypeInferenceResult.java +25 -0
  36. data/src/org/cx4a/rsense/WhereResult.java +19 -0
  37. data/src/org/cx4a/rsense/parser/TypeAnnotation.g +221 -0
  38. data/src/org/cx4a/rsense/parser/TypeAnnotationLexer.java +1759 -0
  39. data/src/org/cx4a/rsense/parser/TypeAnnotationParser.java +2025 -0
  40. data/src/org/cx4a/rsense/ruby/Block.java +10 -0
  41. data/src/org/cx4a/rsense/ruby/Context.java +75 -0
  42. data/src/org/cx4a/rsense/ruby/DynamicMethod.java +10 -0
  43. data/src/org/cx4a/rsense/ruby/DynamicScope.java +51 -0
  44. data/src/org/cx4a/rsense/ruby/Frame.java +95 -0
  45. data/src/org/cx4a/rsense/ruby/IRubyObject.java +17 -0
  46. data/src/org/cx4a/rsense/ruby/LocalScope.java +43 -0
  47. data/src/org/cx4a/rsense/ruby/MetaClass.java +50 -0
  48. data/src/org/cx4a/rsense/ruby/Ruby.java +242 -0
  49. data/src/org/cx4a/rsense/ruby/RubyClass.java +146 -0
  50. data/src/org/cx4a/rsense/ruby/RubyModule.java +255 -0
  51. data/src/org/cx4a/rsense/ruby/RubyObject.java +94 -0
  52. data/src/org/cx4a/rsense/ruby/Scope.java +7 -0
  53. data/src/org/cx4a/rsense/ruby/SpecialObject.java +15 -0
  54. data/src/org/cx4a/rsense/ruby/Visibility.java +17 -0
  55. data/src/org/cx4a/rsense/typing/Graph.java +1690 -0
  56. data/src/org/cx4a/rsense/typing/Propagation.java +73 -0
  57. data/src/org/cx4a/rsense/typing/Template.java +84 -0
  58. data/src/org/cx4a/rsense/typing/TemplateAttribute.java +158 -0
  59. data/src/org/cx4a/rsense/typing/TypeSet.java +48 -0
  60. data/src/org/cx4a/rsense/typing/annotation/ClassType.java +57 -0
  61. data/src/org/cx4a/rsense/typing/annotation/MethodType.java +79 -0
  62. data/src/org/cx4a/rsense/typing/annotation/TypeAnnotation.java +4 -0
  63. data/src/org/cx4a/rsense/typing/annotation/TypeAny.java +7 -0
  64. data/src/org/cx4a/rsense/typing/annotation/TypeApplication.java +37 -0
  65. data/src/org/cx4a/rsense/typing/annotation/TypeConstraint.java +29 -0
  66. data/src/org/cx4a/rsense/typing/annotation/TypeExpression.java +11 -0
  67. data/src/org/cx4a/rsense/typing/annotation/TypeIdentity.java +59 -0
  68. data/src/org/cx4a/rsense/typing/annotation/TypeOptional.java +22 -0
  69. data/src/org/cx4a/rsense/typing/annotation/TypePragma.java +22 -0
  70. data/src/org/cx4a/rsense/typing/annotation/TypeSplat.java +22 -0
  71. data/src/org/cx4a/rsense/typing/annotation/TypeTuple.java +35 -0
  72. data/src/org/cx4a/rsense/typing/annotation/TypeUnion.java +23 -0
  73. data/src/org/cx4a/rsense/typing/annotation/TypeVariable.java +44 -0
  74. data/src/org/cx4a/rsense/typing/runtime/AliasMethod.java +94 -0
  75. data/src/org/cx4a/rsense/typing/runtime/AnnotationHelper.java +69 -0
  76. data/src/org/cx4a/rsense/typing/runtime/AnnotationResolver.java +523 -0
  77. data/src/org/cx4a/rsense/typing/runtime/Array.java +84 -0
  78. data/src/org/cx4a/rsense/typing/runtime/ClassTag.java +27 -0
  79. data/src/org/cx4a/rsense/typing/runtime/DefaultMethod.java +115 -0
  80. data/src/org/cx4a/rsense/typing/runtime/Hash.java +131 -0
  81. data/src/org/cx4a/rsense/typing/runtime/LoopTag.java +21 -0
  82. data/src/org/cx4a/rsense/typing/runtime/Method.java +32 -0
  83. data/src/org/cx4a/rsense/typing/runtime/MonomorphicObject.java +77 -0
  84. data/src/org/cx4a/rsense/typing/runtime/ObjectAllocator.java +40 -0
  85. data/src/org/cx4a/rsense/typing/runtime/PolymorphicObject.java +90 -0
  86. data/src/org/cx4a/rsense/typing/runtime/Proc.java +100 -0
  87. data/src/org/cx4a/rsense/typing/runtime/RuntimeHelper.java +1339 -0
  88. data/src/org/cx4a/rsense/typing/runtime/SpecialMethod.java +119 -0
  89. data/src/org/cx4a/rsense/typing/runtime/TypeVarMap.java +112 -0
  90. data/src/org/cx4a/rsense/typing/runtime/VertexHolder.java +48 -0
  91. data/src/org/cx4a/rsense/typing/vertex/CallVertex.java +122 -0
  92. data/src/org/cx4a/rsense/typing/vertex/MultipleAsgnVertex.java +23 -0
  93. data/src/org/cx4a/rsense/typing/vertex/PassThroughVertex.java +20 -0
  94. data/src/org/cx4a/rsense/typing/vertex/SValueVertex.java +24 -0
  95. data/src/org/cx4a/rsense/typing/vertex/SplatVertex.java +24 -0
  96. data/src/org/cx4a/rsense/typing/vertex/ToAryVertex.java +24 -0
  97. data/src/org/cx4a/rsense/typing/vertex/TypeVarVertex.java +22 -0
  98. data/src/org/cx4a/rsense/typing/vertex/Vertex.java +221 -0
  99. data/src/org/cx4a/rsense/typing/vertex/YieldVertex.java +70 -0
  100. data/src/org/cx4a/rsense/util/HereDocReader.java +48 -0
  101. data/src/org/cx4a/rsense/util/Logger.java +111 -0
  102. data/src/org/cx4a/rsense/util/NodeUtil.java +198 -0
  103. data/src/org/cx4a/rsense/util/SourceLocation.java +70 -0
  104. data/src/org/cx4a/rsense/util/StringUtil.java +63 -0
  105. data/src/resources/org/cx4a/rsense/rsense.properties +1 -0
  106. data/stubs/1.8/_builtin.rb +3006 -0
  107. data/stubs/1.8/bigdecimal.rb +131 -0
  108. data/stubs/1.8/cgi.rb +257 -0
  109. data/stubs/1.8/date.rb +147 -0
  110. data/stubs/1.8/optparse.rb +113 -0
  111. data/stubs/1.8/rational.rb +47 -0
  112. data/stubs/1.8/set.rb +94 -0
  113. data/stubs/1.8/socket.rb +461 -0
  114. data/stubs/1.8/stringio.rb +129 -0
  115. data/test/data/a file.rb +1 -0
  116. data/test/data/benchmark.rb +12 -0
  117. data/test/data/crlf.rb +5 -0
  118. data/test/data/test.rb +19 -0
  119. data/test/script/all.rsense +2 -0
  120. data/test/script/array_dynamic.rsense +25 -0
  121. data/test/script/block_nested.rsense +7 -0
  122. data/test/script/builtin.rsense +785 -0
  123. data/test/script/class_method_partial_update.rsense +52 -0
  124. data/test/script/class_partial_update.rsense +17 -0
  125. data/test/script/find-definition.rsense +72 -0
  126. data/test/script/method_arg_onearg.rsense +6 -0
  127. data/test/script/method_arg_optional.rsense +7 -0
  128. data/test/script/method_partial_update.rsense +14 -0
  129. data/test/script/method_yield_arrayarg.rsense +8 -0
  130. data/test/script/method_yield_arrayarg_expand.rsense +8 -0
  131. data/test/script/method_yield_arrayarg_splat.rsense +17 -0
  132. data/test/script/misc.rsense +2 -0
  133. data/test/script/proc_higher_order.rsense +22 -0
  134. data/test/script/regression.rsense +95 -0
  135. data/test/script/stdlib.rsense +66 -0
  136. data/test/script/where.rsense +41 -0
  137. metadata +315 -0
@@ -0,0 +1,7 @@
1
+ package org.cx4a.rsense.ruby;
2
+
3
+ public interface Scope {
4
+ public RubyModule getModule();
5
+ public IRubyObject getValue(String name);
6
+ public void setValue(String name, IRubyObject value);
7
+ }
@@ -0,0 +1,15 @@
1
+ package org.cx4a.rsense.ruby;
2
+
3
+ public class SpecialObject extends RubyObject {
4
+ private String displayValue;
5
+
6
+ public SpecialObject(Ruby runtime, RubyClass metaClass, String displayValue) {
7
+ super(runtime, metaClass);
8
+ this.displayValue = displayValue;
9
+ }
10
+
11
+ @Override
12
+ public String toString() {
13
+ return displayValue;
14
+ }
15
+ }
@@ -0,0 +1,17 @@
1
+ package org.cx4a.rsense.ruby;
2
+
3
+ public enum Visibility {
4
+ PUBLIC, PROTECTED, PRIVATE, MODULE_FUNCTION;
5
+
6
+ public boolean isPublic() {
7
+ return this == PUBLIC;
8
+ }
9
+
10
+ public boolean isPrivate() {
11
+ return this == PRIVATE;
12
+ }
13
+
14
+ public boolean isProtected() {
15
+ return this == PROTECTED;
16
+ }
17
+ }
@@ -0,0 +1,1690 @@
1
+ package org.cx4a.rsense.typing;
2
+
3
+ import java.util.ArrayList;
4
+ import java.util.Arrays;
5
+ import java.util.Collection;
6
+ import java.util.HashMap;
7
+ import java.util.LinkedList;
8
+ import java.util.List;
9
+ import java.util.Map;
10
+ import java.util.Queue;
11
+
12
+ import org.cx4a.rsense.CodeAssist;
13
+ import org.jrubyparser.ast.*;
14
+
15
+ import org.jrubyparser.NodeVisitor;
16
+
17
+ import org.cx4a.rsense.ruby.Block;
18
+ import org.cx4a.rsense.ruby.Context;
19
+ import org.cx4a.rsense.ruby.DynamicMethod;
20
+ import org.cx4a.rsense.ruby.Frame;
21
+ import org.cx4a.rsense.ruby.IRubyObject;
22
+ import org.cx4a.rsense.ruby.LocalScope;
23
+ import org.cx4a.rsense.ruby.MetaClass;
24
+ import org.cx4a.rsense.ruby.Ruby;
25
+ import org.cx4a.rsense.ruby.RubyClass;
26
+ import org.cx4a.rsense.ruby.RubyModule;
27
+ import org.cx4a.rsense.ruby.Visibility;
28
+ import org.cx4a.rsense.typing.annotation.TypeVariable;
29
+ import org.cx4a.rsense.typing.runtime.AliasMethod;
30
+ import org.cx4a.rsense.typing.runtime.AnnotationHelper;
31
+ import org.cx4a.rsense.typing.runtime.Array;
32
+ import org.cx4a.rsense.typing.runtime.DefaultMethod;
33
+ import org.cx4a.rsense.typing.runtime.Hash;
34
+ import org.cx4a.rsense.typing.runtime.LoopTag;
35
+ import org.cx4a.rsense.typing.runtime.Method;
36
+ import org.cx4a.rsense.typing.runtime.ObjectAllocator;
37
+ import org.cx4a.rsense.typing.runtime.Proc;
38
+ import org.cx4a.rsense.typing.runtime.RuntimeHelper;
39
+ import org.cx4a.rsense.typing.runtime.SpecialMethod;
40
+ import org.cx4a.rsense.typing.runtime.TypeVarMap;
41
+ import org.cx4a.rsense.typing.runtime.VertexHolder;
42
+ import org.cx4a.rsense.typing.vertex.CallVertex;
43
+ import org.cx4a.rsense.typing.vertex.MultipleAsgnVertex;
44
+ import org.cx4a.rsense.typing.vertex.PassThroughVertex;
45
+ import org.cx4a.rsense.typing.vertex.SValueVertex;
46
+ import org.cx4a.rsense.typing.vertex.SplatVertex;
47
+ import org.cx4a.rsense.typing.vertex.ToAryVertex;
48
+ import org.cx4a.rsense.typing.vertex.TypeVarVertex;
49
+ import org.cx4a.rsense.typing.vertex.Vertex;
50
+ import org.cx4a.rsense.typing.vertex.YieldVertex;
51
+ import org.cx4a.rsense.util.Logger;
52
+ import org.cx4a.rsense.util.SourceLocation;
53
+
54
+ public class Graph implements NodeVisitor {
55
+ public interface EventListener {
56
+ public enum EventType { DEFINE, CLASS, MODULE, METHOD_MISSING }
57
+
58
+ public static class Event {
59
+ public final EventType type;
60
+
61
+ // TODO divide into classes
62
+ public final String name;
63
+ public final Node node;
64
+ public final Vertex vertex;
65
+
66
+ public Event(EventType type, String name, Node node) {
67
+ this.type = type;
68
+ this.name = name;
69
+ this.node = node;
70
+ this.vertex = null;
71
+ }
72
+
73
+ public Event(EventType type, Vertex vertex) {
74
+ this.type = type;
75
+ this.name = null;
76
+ this.node = null;
77
+ this.vertex = vertex;
78
+ }
79
+ }
80
+
81
+ public void update(Event event);
82
+ }
83
+
84
+ protected static class DummyCall {
85
+ private MethodDefNode node;
86
+ private Method newMethod;
87
+ private Method oldMethod;
88
+ private IRubyObject receiver;
89
+
90
+ public DummyCall(MethodDefNode node, Method newMethod, Method oldMethod, IRubyObject receiver) {
91
+ this.node = node;
92
+ this.newMethod = newMethod;
93
+ this.oldMethod = oldMethod;
94
+ this.receiver = receiver;
95
+ }
96
+
97
+ public void force(Graph graph) {
98
+ if (!newMethod.isTemplatesShared()) {
99
+ Collection<TemplateAttribute> templateAttributes = oldMethod != null ? oldMethod.getTemplates().keySet() : null;
100
+ if (templateAttributes != null && !templateAttributes.isEmpty()) {
101
+ RuntimeHelper.dummyCallForTemplates(graph, node, newMethod, templateAttributes);
102
+ } else {
103
+ RuntimeHelper.dummyCall(graph, node, newMethod, receiver);
104
+ }
105
+ }
106
+ }
107
+ }
108
+
109
+ protected Ruby runtime;
110
+ protected Context context;
111
+ protected Map<String, SpecialMethod> specialMethods;
112
+ protected Queue<DummyCall> dummyCallQueue = new LinkedList<DummyCall>();
113
+ protected List<EventListener> eventListeners;
114
+
115
+ public Graph() {
116
+ this.runtime = new Ruby();
117
+ this.runtime.setObjectAllocator(new ObjectAllocator());
118
+ this.context = runtime.getContext();
119
+ this.specialMethods = new HashMap<String, SpecialMethod>();
120
+ this.eventListeners = new ArrayList<EventListener>();
121
+ init();
122
+ }
123
+
124
+ public Ruby getRuntime() {
125
+ return runtime;
126
+ }
127
+
128
+ public Map<String, SpecialMethod> getSpecialMethods() {
129
+ return specialMethods;
130
+ }
131
+
132
+ public SpecialMethod getSpecialMethod(String name) {
133
+ return specialMethods.get(name);
134
+ }
135
+
136
+ public void addSpecialMethod(String name, SpecialMethod method) {
137
+ specialMethods.put(name, method);
138
+ }
139
+
140
+ public void addEventListener(EventListener eventListener) {
141
+ eventListeners.add(eventListener);
142
+ }
143
+
144
+ public void removeEventListener(EventListener eventListener) {
145
+ eventListeners.remove(eventListener);
146
+ }
147
+
148
+ public void notifyDefineEvent(Node node, Method method) {
149
+ for (EventListener eventListener : eventListeners)
150
+ eventListener.update(new EventListener.Event(EventListener.EventType.DEFINE,
151
+ method.toString(),
152
+ node));
153
+ }
154
+
155
+ public void notifyClassEvent(Node node, RubyModule klass) {
156
+ for (EventListener eventListener : eventListeners)
157
+ eventListener.update(new EventListener.Event(EventListener.EventType.CLASS,
158
+ klass.toString(),
159
+ node));
160
+ }
161
+
162
+ public void notifyModuleEvent(Node node, RubyModule module) {
163
+ for (EventListener eventListener : eventListeners)
164
+ eventListener.update(new EventListener.Event(EventListener.EventType.MODULE,
165
+ module.toString(),
166
+ node));
167
+ }
168
+
169
+ public void notifyMethodMissingEvent(CallVertex vertex) {
170
+ for (EventListener eventListener : eventListeners)
171
+ eventListener.update(new EventListener.Event(EventListener.EventType.METHOD_MISSING,
172
+ vertex));
173
+ }
174
+
175
+ private void init() {
176
+ addSpecialMethod("new", new SpecialMethod() {
177
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
178
+ TypeSet accumulator = result.getAccumulator();
179
+ if (result.getPrevious() == null) {
180
+ TypeSet resultTypeSet = accumulator = new TypeSet();
181
+ TypeSet newReceivers = new TypeSet();
182
+ for (IRubyObject receiver : receivers) {
183
+ if (receiver instanceof RubyClass) {
184
+ RubyClass klass = (RubyClass) receiver;
185
+ if (klass.getMetaClass().searchMethod("new") == null) {
186
+ if (klass == runtime.getProc()) {
187
+ // Proc.new {}
188
+ if (block instanceof Proc)
189
+ resultTypeSet.add((Proc) block);
190
+ else
191
+ Logger.debug("Proc.new for no block is not supported yet");
192
+ } else
193
+ resultTypeSet.add(newInstanceOf((RubyClass) receiver));
194
+ } else {
195
+ newReceivers.add(receiver);
196
+ }
197
+ }
198
+ }
199
+ if (!newReceivers.isEmpty()) {
200
+ result
201
+ .setResultTypeSet(resultTypeSet)
202
+ .setCallNextMethod(true)
203
+ .setNextMethodChange(true)
204
+ .setNextMethodName("new")
205
+ .setNextMethodReceivers(newReceivers)
206
+ .setNextMethodBlock(block);
207
+ return;
208
+ }
209
+ }
210
+ result
211
+ .setResultTypeSet(accumulator)
212
+ .setCallNextMethod(true)
213
+ .setNextMethodChange(true)
214
+ .setNextMethodName("initialize")
215
+ .setNextMethodReceivers(accumulator)
216
+ .setNextMethodBlock(block)
217
+ .setNextMethodNoReturn(true)
218
+ .setPrivateVisibility(true);
219
+ }
220
+ });
221
+
222
+ addSpecialMethod("include", new SpecialMethod() {
223
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
224
+ boolean included = false;
225
+ if (args != null) {
226
+ for (Vertex arg : args) {
227
+ for (IRubyObject receiver : receivers) {
228
+ // FIXME log message
229
+ if (!(receiver instanceof RubyModule)) {
230
+ // FIXME toplevel
231
+ receiver = receiver.getMetaClass();
232
+ }
233
+ if (receiver instanceof RubyModule) {
234
+ RubyModule module = (RubyModule) receiver;
235
+ for (IRubyObject target : arg.getTypeSet()) {
236
+ if (target instanceof RubyModule) {
237
+ module.includeModule((RubyModule) target);
238
+ included = true;
239
+ }
240
+ }
241
+ }
242
+ }
243
+ }
244
+ }
245
+ if (!included) {
246
+ result.setCallNextMethod(true);
247
+ }
248
+ }
249
+ });
250
+
251
+ addSpecialMethod("[]", new SpecialMethod() {
252
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
253
+ Collection<IRubyObject> arg = null;
254
+ TypeSet ts = new TypeSet();
255
+ for (IRubyObject receiver : receivers) {
256
+ if (receiver instanceof Hash) {
257
+ if (args != null && args.length > 0) {
258
+ Hash hash = (Hash) receiver;
259
+ Object key = Hash.getRealKey(args[0].getNode());
260
+ if (!hash.isModified() && key != null) {
261
+ Vertex v = hash.get(key);
262
+ if (v != null) {
263
+ ts.addAll(v.getTypeSet());
264
+ }
265
+ }
266
+ }
267
+ } else if (receiver instanceof Array) {
268
+ if (args != null && args.length > 0) {
269
+ Array array = (Array) receiver;
270
+ Integer n = Vertex.getFixnum(args[0]);
271
+ if (!array.isModified() && n != null) {
272
+ Vertex v = array.getElement(n);
273
+ if (v != null) {
274
+ ts.addAll(v.getTypeSet());
275
+ }
276
+ }
277
+ }
278
+ } else if (receiver instanceof Proc) {
279
+ if (arg == null) {
280
+ if (args == null) {
281
+ arg = Arrays.asList((IRubyObject) RuntimeHelper.createArray(Graph.this, new Vertex[0]));
282
+ } else if (args.length == 1) {
283
+ arg = args[0].getTypeSet();
284
+ } else { arg = Arrays.asList((IRubyObject) RuntimeHelper.createArray(Graph.this, args));
285
+ }
286
+ }
287
+ Vertex returnVertex = createFreeVertex();
288
+ RuntimeHelper.yield(Graph.this, (Proc) receiver, arg, true, returnVertex);
289
+ ts.addAll(returnVertex.getTypeSet());
290
+ }
291
+ }
292
+
293
+ if (ts.isEmpty()) {
294
+ result.setCallNextMethod(true);
295
+ } else {
296
+ result.setResultTypeSet(ts);
297
+ }
298
+ }
299
+ });
300
+
301
+ addSpecialMethod("private", new SpecialMethod() {
302
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
303
+ RuntimeHelper.setMethodsVisibility(Graph.this, receivers, args, Visibility.PRIVATE);
304
+ }
305
+ });
306
+
307
+ addSpecialMethod("protected", new SpecialMethod() {
308
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
309
+ RuntimeHelper.setMethodsVisibility(Graph.this, receivers, args, Visibility.PROTECTED);
310
+ }
311
+ });
312
+
313
+ addSpecialMethod("public", new SpecialMethod() {
314
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
315
+ RuntimeHelper.setMethodsVisibility(Graph.this, receivers, args, Visibility.PUBLIC);
316
+ }
317
+ });
318
+
319
+ addSpecialMethod("module_function", new SpecialMethod() {
320
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
321
+ RuntimeHelper.setMethodsVisibility(Graph.this, receivers, args, Visibility.MODULE_FUNCTION);
322
+ }
323
+ });
324
+
325
+ addSpecialMethod("attr", new SpecialMethod() {
326
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
327
+ if (args != null && args.length > 0) {
328
+ RuntimeHelper.defineAttrs(Graph.this, receivers, new Vertex[] { args[0] }, true, args.length > 1);
329
+ }
330
+ }
331
+ });
332
+
333
+ addSpecialMethod("attr_reader", new SpecialMethod() {
334
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
335
+ RuntimeHelper.defineAttrs(Graph.this, receivers, args, true, false);
336
+ }
337
+ });
338
+
339
+ addSpecialMethod("attr_writer", new SpecialMethod() {
340
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
341
+ RuntimeHelper.defineAttrs(Graph.this, receivers, args, false, true);
342
+ }
343
+ });
344
+
345
+ addSpecialMethod("attr_accessor", new SpecialMethod() {
346
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
347
+ RuntimeHelper.defineAttrs(Graph.this, receivers, args, true, true);
348
+ }
349
+ });
350
+
351
+ addSpecialMethod("alias_method", new SpecialMethod() {
352
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
353
+ boolean callNextMethod = true;
354
+ if (args != null && args.length == 2) {
355
+ for (IRubyObject receiver : receivers) {
356
+ if (receiver instanceof RubyModule) {
357
+ callNextMethod = false;
358
+ String newName = Vertex.getStringOrSymbol(args[0]);
359
+ String oldName = Vertex.getStringOrSymbol(args[1]);
360
+ if (newName != null && oldName != null) {
361
+ RubyModule module = (RubyModule) receiver;
362
+ DynamicMethod method = module.getMethod(oldName);
363
+ if (method instanceof Method)
364
+ module.addMethod(newName, new AliasMethod(newName, (Method) method));
365
+ }
366
+ }
367
+ }
368
+ }
369
+ result.setCallNextMethod(callNextMethod);
370
+ }
371
+ });
372
+
373
+ addSpecialMethod("unpack", new SpecialMethod() {
374
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
375
+ if (args != null && args.length > 0) {
376
+ String template = Vertex.getString(args[0]);
377
+ if (template != null) {
378
+ TypeSet ts = new TypeSet();
379
+ for (IRubyObject object : receivers) {
380
+ if (object.isKindOf(runtime.getString())) {
381
+ List<Vertex> elements = new ArrayList<Vertex>();
382
+ for (char c : template.toCharArray()) {
383
+ RubyClass type = null;
384
+ switch (c) {
385
+ case 'a': case 'A': case 'Z': case 'b':
386
+ case 'B': case 'h': case 'H': case 'm':
387
+ case 'M': case 'p': case 'P': case 'u':
388
+ case 'U':
389
+ type = runtime.getString();
390
+ break;
391
+ case 'c': case 'C': case 's': case 'S':
392
+ case 'i': case 'I': case 'l': case 'L':
393
+ case 'q': case 'Q': case 'n': case 'N':
394
+ case 'v': case 'V': case 'w': case 'x':
395
+ case 'X':
396
+ type = runtime.getInteger();
397
+ break;
398
+ case 'f': case 'd': case 'e': case 'E':
399
+ case 'g': case 'G':
400
+ type = runtime.getFloat();
401
+ break;
402
+ }
403
+ if (type != null) {
404
+ elements.add(createFreeSingleTypeVertex(newInstanceOf(type)));
405
+ }
406
+ }
407
+ ts.add(RuntimeHelper.createArray(Graph.this, elements.toArray(new Vertex[0])));
408
+ }
409
+ }
410
+ if (ts.isEmpty()) {
411
+ result.setCallNextMethod(true);
412
+ } else {
413
+ result.setResultTypeSet(ts);
414
+ }
415
+ }
416
+ }
417
+ }
418
+ });
419
+
420
+ addSpecialMethod("proc", new SpecialMethod() {
421
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
422
+ TypeSet ts = new TypeSet();
423
+ for (IRubyObject receiver : receivers) {
424
+ DynamicMethod method = receiver.getMetaClass().searchMethod("proc");
425
+ if (method != null && method.getModule() == runtime.getKernel()) {
426
+ if (block instanceof Proc)
427
+ ts.add((Proc) block);
428
+ else
429
+ Logger.debug("proc for no block is not supported yet");
430
+ }
431
+ }
432
+ if (ts.isEmpty())
433
+ result.setCallNextMethod(true);
434
+ else
435
+ result.setResultTypeSet(ts);
436
+ }
437
+ });
438
+
439
+ addSpecialMethod("lambda", new SpecialMethod() {
440
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
441
+ TypeSet ts = new TypeSet();
442
+ for (IRubyObject receiver : receivers) {
443
+ DynamicMethod method = receiver.getMetaClass().searchMethod("lambda");
444
+ if (method != null && method.getModule() == runtime.getKernel()) {
445
+ if (block instanceof Proc)
446
+ ts.add((Proc) block);
447
+ else
448
+ Logger.debug("lambda for no block is not supported yet");
449
+ }
450
+ }
451
+ if (ts.isEmpty())
452
+ result.setCallNextMethod(true);
453
+ else
454
+ result.setResultTypeSet(ts);
455
+ }
456
+ });
457
+
458
+ addSpecialMethod("call", new SpecialMethod() {
459
+ public void call(Ruby runtime, TypeSet receivers, Vertex[] args, Block block, Result result) {
460
+ TypeSet ts = new TypeSet();
461
+ Vertex argVertex = null;
462
+ for (IRubyObject receiver : receivers) {
463
+ if (receiver instanceof Proc) {
464
+ if (argVertex == null) {
465
+ TypeSet argts;
466
+ if (args == null) {
467
+ argts = new TypeSet();
468
+ argts.add(RuntimeHelper.createArray(Graph.this, new Vertex[0]));
469
+ } else if (args.length == 1) {
470
+ argts = args[0].getTypeSet();
471
+ } else {
472
+ argts = new TypeSet();
473
+ argts.add(RuntimeHelper.createArray(Graph.this, args));
474
+ }
475
+ argVertex = createFreeVertex(argts);
476
+ argVertex.markUnchanged();
477
+ }
478
+ YieldVertex vertex = new YieldVertex(null,
479
+ RuntimeHelper.getFrameTemplate(runtime.getContext().getCurrentFrame()),
480
+ (Proc) receiver,
481
+ argVertex,
482
+ true);
483
+ RuntimeHelper.yield(Graph.this, vertex);
484
+ ts.addAll(vertex.getTypeSet());
485
+ }
486
+ }
487
+ if (ts.isEmpty()) {
488
+ result.setCallNextMethod(true);
489
+ } else {
490
+ result.setResultTypeSet(ts);
491
+ }
492
+ }
493
+ });
494
+
495
+ RubyClass objectClass = runtime.getObject();
496
+ RubyClass classClass = runtime.getClassClass();
497
+ RubyClass procClass = runtime.getProc();
498
+
499
+ objectClass.addMethod("class", new DefaultMethod(objectClass, "class", null, null, Visibility.PUBLIC, null) {
500
+ public Vertex call(Graph graph, Template template, IRubyObject receiver, IRubyObject[] args, Vertex[] argVertices, Block block) {
501
+ return graph.createFreeSingleTypeVertex(receiver.getMetaClass());
502
+ }
503
+ });
504
+
505
+ classClass.addMethod("superclass", new DefaultMethod(classClass, "superclass", null, null, Visibility.PUBLIC, null) {
506
+ public Vertex call(Graph graph, Template template, IRubyObject receiver, IRubyObject[] args, Vertex[] argVertices, Block block) {
507
+ if (receiver instanceof RubyClass) {
508
+ return graph.createFreeSingleTypeVertex(((RubyClass) receiver).getSuperClass());
509
+ } else {
510
+ return null;
511
+ }
512
+ }
513
+ });
514
+ }
515
+
516
+ public void load(Node newAST) {
517
+ load(newAST, null);
518
+ }
519
+
520
+ public void load(Node newAST, Node oldAST) {
521
+ context.pushMain();
522
+
523
+ // List<Node> partialDiff = null;
524
+ // if (oldAST != null && nodeDiff != null) {
525
+ // partialDiff = nodeDiff.diff(newAST, oldAST);
526
+ // if (partialDiff != null) {
527
+ // Logger.debug("partial load: %s", partialDiff.size());
528
+ // for (Node dirty : partialDiff) {
529
+ // createVertex(dirty);
530
+ // }
531
+ // }
532
+ // }
533
+ // if (partialDiff == null) {
534
+ // createVertex(newAST);
535
+ // }
536
+ createVertex(newAST);
537
+ DummyCall entry;
538
+ while ((entry = dummyCallQueue.poll()) != null) {
539
+ entry.force(this);
540
+ }
541
+
542
+ context.popMain();
543
+ }
544
+
545
+ public Vertex createVertex(Node node) {
546
+ if (node != null) {
547
+ return (Vertex) node.accept(this);
548
+ } else {
549
+ return null;
550
+ }
551
+ }
552
+
553
+ public Vertex createFreeVertex() {
554
+ return new Vertex();
555
+ }
556
+
557
+ public Vertex createFreeVertex(TypeSet typeSet) {
558
+ return new Vertex(null, typeSet);
559
+ }
560
+
561
+ public Vertex createFreeSingleTypeVertex(IRubyObject type) {
562
+ Vertex vertex = createFreeVertex();
563
+ vertex.addType(type);
564
+ return vertex;
565
+ }
566
+
567
+ public VertexHolder createVertexHolder(Vertex vertex) {
568
+ return new VertexHolder(runtime, vertex);
569
+ }
570
+
571
+ public VertexHolder createFreeVertexHolder() {
572
+ return new VertexHolder(runtime, createFreeVertex());
573
+ }
574
+
575
+ public Vertex createEmptyVertex(Node node) {
576
+ return new Vertex(node);
577
+ }
578
+
579
+ public Vertex createSingleTypeVertex(Node node, IRubyObject type) {
580
+ Vertex vertex = new Vertex(node, 2);
581
+ vertex.addType(type);
582
+ return vertex;
583
+ }
584
+
585
+ public void addEdgeAndPropagate(Vertex src, Vertex dest) {
586
+ src.addEdge(dest);
587
+ propagate(src, dest);
588
+ }
589
+
590
+ public void addEdgeAndUpdate(Vertex src, Vertex dest) {
591
+ src.addEdge(dest);
592
+ dest.update(src);
593
+ }
594
+
595
+ private Propagation propagation;
596
+
597
+ public boolean propagate(Vertex src, Vertex dest) {
598
+ startPropagation();
599
+ boolean result = dest.accept(propagation, src);
600
+ endPropagation();
601
+ return result;
602
+ }
603
+
604
+ public boolean propagateEdges(Vertex src) {
605
+ startPropagation();
606
+ boolean result = propagateEdges(propagation, src);
607
+ endPropagation();
608
+ return result;
609
+ }
610
+
611
+ public boolean propagateEdges(Propagation propagation, Vertex src) {
612
+ // Edges may change during propagation
613
+ int size = src.getEdges().size();
614
+ for (int i = 0; i < size; i++) {
615
+ Vertex edge = src.getEdges().get(i);
616
+ if (!propagation.visit(edge, src)) {
617
+ return false;
618
+ }
619
+ }
620
+ return true;
621
+ }
622
+
623
+ public boolean propagateEdge(Vertex src, Vertex dest) {
624
+ startPropagation();
625
+ boolean result = propagateEdge(propagation, src, dest);
626
+ endPropagation();
627
+ return result;
628
+ }
629
+
630
+ public boolean propagateEdge(Propagation propagation, Vertex src, Vertex dest) {
631
+ src.addEdge(dest);
632
+ return dest.accept(propagation, src);
633
+ }
634
+
635
+ private void startPropagation() {
636
+ if (propagation == null) {
637
+ propagation = new Propagation(this);
638
+ }
639
+ propagation.retain();
640
+ }
641
+
642
+ private void endPropagation() {
643
+ if (propagation.release()) {
644
+ propagation = null;
645
+ }
646
+ }
647
+
648
+ public IRubyObject newInstanceOf(RubyClass klass) {
649
+ return runtime.newInstance(klass);
650
+ }
651
+
652
+ public Object visitAliasNode(AliasNode node) {
653
+ RubyModule module = context.getFrameModule();
654
+ DynamicMethod method = module.getMethod(node.getOldNameString());
655
+ if (method instanceof Method)
656
+ module.addMethod(node.getNewNameString(), new AliasMethod(node.getNewNameString(), (Method) method));
657
+ return Vertex.EMPTY;
658
+ }
659
+ public Object visitAndNode(AndNode node) {
660
+ Vertex vertex = createEmptyVertex(node);
661
+ Vertex firstVertex = createVertex(node.getFirst());
662
+ Vertex secondVertex = createVertex(node.getSecond());
663
+ addEdgeAndUpdate(secondVertex, vertex);
664
+ return vertex;
665
+ }
666
+
667
+ public Object visitArgsNode(ArgsNode node) {
668
+ unsupportedNode(node);
669
+ return Vertex.EMPTY;
670
+ }
671
+
672
+ public Object visitArgsCatNode(ArgsCatNode node) {
673
+ Vertex vertex = createEmptyVertex(node);
674
+ Vertex first = createVertex(node.getFirst());
675
+ SplatVertex second = new SplatVertex(node, createVertex(node.getSecond()));
676
+ RuntimeHelper.splatValue(this, second);
677
+ for (IRubyObject a : first.getTypeSet()) {
678
+ List<Vertex> elements = new ArrayList<Vertex>();
679
+ if (a instanceof Array) {
680
+ Array array = (Array) a;
681
+ if (array.getElements() != null) {
682
+ elements.addAll(Arrays.asList(array.getElements()));
683
+ }
684
+ } else {
685
+ elements.add(createFreeSingleTypeVertex(a));
686
+ }
687
+ for (IRubyObject b : second.getTypeSet()) {
688
+ if (b instanceof Array) {
689
+ Array array = (Array) b;
690
+ if (array.getElements() != null) {
691
+ elements.addAll(Arrays.asList(array.getElements()));
692
+ }
693
+ } else {
694
+ elements.add(createFreeSingleTypeVertex(a));
695
+ }
696
+ }
697
+ vertex.addType(RuntimeHelper.createArray(this, elements.toArray(new Vertex[0])));
698
+ }
699
+ return vertex;
700
+ }
701
+
702
+ public Object visitArgsPushNode(ArgsPushNode node) {
703
+ unsupportedNode(node);
704
+ return Vertex.EMPTY;
705
+ }
706
+
707
+ public Object visitArgumentNode(ArgumentNode node) {
708
+ return createEmptyVertex(node);
709
+ }
710
+
711
+ public Object visitArrayNode(ArrayNode node) {
712
+ return RuntimeHelper.createArrayVertex(this, node, RuntimeHelper.toVertices(this, node));
713
+ }
714
+
715
+ public Object visitAttrAssignNode(AttrAssignNode node) {
716
+ Vertex receiverVertex = createVertex(node.getReceiver());
717
+ Vertex[] argVertices = null;
718
+ if (node.getArgs() != null) {
719
+ List<Node> argNodes = node.getArgs().childNodes();
720
+ argVertices = new Vertex[argNodes.size()];
721
+ for (int i = 0; i < argVertices.length; i++) {
722
+ argVertices[i] = createVertex(argNodes.get(i));
723
+ }
724
+ }
725
+
726
+ CallVertex vertex = new CallVertex(node, receiverVertex, argVertices, null);
727
+ return RuntimeHelper.call(this, vertex);
728
+ }
729
+
730
+ public Object visitBackRefNode(BackRefNode node) {
731
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getString()));
732
+ }
733
+
734
+ public Object visitBeginNode(BeginNode node) {
735
+ return createVertex(node.getBody());
736
+ }
737
+
738
+ public Object visitBignumNode(BignumNode node) {
739
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getBignum()));
740
+ }
741
+
742
+ public Object visitBlockArgNode(BlockArgNode node) {
743
+ unsupportedNode(node);
744
+ return Vertex.EMPTY;
745
+ }
746
+
747
+ public Object visitBlockArg18Node(BlockArg18Node node) {
748
+ unsupportedNode(node);
749
+ return Vertex.EMPTY;
750
+ }
751
+
752
+ public Object visitBlockNode(BlockNode node) {
753
+ Object result = null;
754
+ for (Node child : node.childNodes()) {
755
+ result = createVertex(child);
756
+ }
757
+ return result;
758
+ }
759
+
760
+ public Object visitBlockPassNode(BlockPassNode node) {
761
+ // Never reach here
762
+ unsupportedNode(node);
763
+ return Vertex.EMPTY;
764
+ }
765
+
766
+ public Object visitBreakNode(BreakNode node) {
767
+ Frame frame = context.getCurrentFrame();
768
+ LoopTag loopTag = RuntimeHelper.getFrameLoopTag(frame);
769
+ if (loopTag != null) {
770
+ Vertex vertex;
771
+ if (node.getValue() != null) {
772
+ vertex = createVertex(node.getValue());
773
+ } else {
774
+ vertex = createEmptyVertex(node);
775
+ }
776
+
777
+ if (loopTag.getYieldVertex() != null)
778
+ addEdgeAndPropagate(vertex, loopTag.getYieldVertex());
779
+ else
780
+
781
+
782
+ Logger.debug("no yield vertex");
783
+ return vertex;
784
+ }
785
+ return Vertex.EMPTY;
786
+ }
787
+
788
+ public Object visitCommentNode(CommentNode node) {
789
+ return Vertex.EMPTY;
790
+ }
791
+
792
+ public Object visitConstDeclNode(ConstDeclNode node) {
793
+ return RuntimeHelper.constDeclaration(this, node);
794
+ }
795
+
796
+ public Object visitClassVarAsgnNode(ClassVarAsgnNode node) {
797
+ return RuntimeHelper.classVarAssign(this, node);
798
+ }
799
+
800
+ public Object visitClassVarDeclNode(ClassVarDeclNode node) {
801
+ return RuntimeHelper.classVarDeclaration(this, node);
802
+ }
803
+
804
+ public Object visitClassVarNode(ClassVarNode node) {
805
+ return RuntimeHelper.classVariable(this, node);
806
+ }
807
+
808
+ public Object visitCallNode(CallNode node) {
809
+ Vertex receiverVertex = createVertex(node.getReceiver());
810
+ Vertex[] argVertices = RuntimeHelper.setupCallArgs(this, node.getArgs());
811
+ Block block = RuntimeHelper.setupCallBlock(this, node.getIter());
812
+ CallVertex vertex = new CallVertex(node, receiverVertex, argVertices, block);
813
+ return RuntimeHelper.call(this, vertex);
814
+ }
815
+
816
+ public Object visitCaseNode(CaseNode node) {
817
+ // FIXME eval ===
818
+ Vertex vertex = createEmptyVertex(node);
819
+ if (node.getCase() != null) {
820
+ createVertex(node.getCase());
821
+ }
822
+ ListNode cases = node.getCases();
823
+ if (cases != null) {
824
+ for (int i = 0; i < cases.size(); i++) {
825
+ WhenNode when = (WhenNode) cases.get(i);
826
+ if (when.getBody() != null) {
827
+ Vertex v = createVertex(when.getBody());
828
+ addEdgeAndUpdate(v, vertex);
829
+ }
830
+ }
831
+ }
832
+ if (node.getElse() != null) {
833
+ Vertex v = createVertex(node.getElse());
834
+ addEdgeAndUpdate(v, vertex);
835
+ }
836
+ return vertex;
837
+ }
838
+
839
+ public Object visitClassNode(ClassNode node) {
840
+ Colon3Node cpath = node.getCPath();
841
+ String name = cpath.getName();
842
+ RubyModule module = RuntimeHelper.getNamespace(this, cpath);
843
+ if (module == null) {
844
+ Logger.error(SourceLocation.of(node), "namespace unresolved: %s", cpath);
845
+ return Vertex.EMPTY;
846
+ }
847
+
848
+ RubyClass superClass = null;
849
+ if (node.getSuper() != null) {
850
+ Vertex v = createVertex(node.getSuper());
851
+ if (v != null) {
852
+ IRubyObject superObj = v.singleType();
853
+ if (superObj instanceof RubyClass) {
854
+ superClass = (RubyClass) superObj;
855
+ }
856
+ }
857
+ if (superClass == null) {
858
+ Logger.error("superclass not found: %s", cpath.getName());
859
+ }
860
+ }
861
+
862
+ RubyModule klass = module.defineOrGetClassUnder(name, superClass, SourceLocation.of(node));
863
+
864
+ if (klass != null) {
865
+ context.pushFrame(klass, name, klass, null, Visibility.PUBLIC);
866
+ context.pushScope(new LocalScope(klass));
867
+
868
+ RuntimeHelper.classPartialUpdate(this, klass, node.getBody());
869
+
870
+ context.popScope();
871
+ context.popFrame();
872
+
873
+ RuntimeHelper.setClassTag(klass, node.getBody(),
874
+ AnnotationHelper.parseAnnotations(node.getPreviousComments(), node.getPosition().getStartLine()));
875
+
876
+ notifyClassEvent(node, klass);
877
+ }
878
+
879
+ return Vertex.EMPTY;
880
+ }
881
+
882
+ public Object visitColon2Node(Colon2Node node) {
883
+ RubyModule target = RuntimeHelper.getNamespace(this, node);
884
+ if (target != null) {
885
+ IRubyObject value = target.getConstant(node.getName());
886
+ if (value instanceof VertexHolder) {
887
+ return ((VertexHolder) value).getVertex();
888
+ } else if (value != null) {
889
+ return createSingleTypeVertex(node, value);
890
+ } else {
891
+ return Vertex.EMPTY;
892
+ }
893
+ } else {
894
+ return Vertex.EMPTY;
895
+ }
896
+ }
897
+
898
+ public Object visitColon3Node(Colon3Node node) {
899
+ IRubyObject value = runtime.getObject().getConstant(node.getName());
900
+ if (value instanceof VertexHolder) {
901
+ return ((VertexHolder) value).getVertex();
902
+ } else if (value != null) {
903
+ return createSingleTypeVertex(node, value);
904
+ } else {
905
+ return Vertex.EMPTY;
906
+ }
907
+ }
908
+
909
+ public Object visitConstNode(ConstNode node) {
910
+ IRubyObject value = context.getConstant(node.getName());
911
+ if (value instanceof VertexHolder) {
912
+ return ((VertexHolder) value).getVertex();
913
+ } else if (value != null) {
914
+ return createSingleTypeVertex(node, value);
915
+ } else {
916
+ return Vertex.EMPTY;
917
+ }
918
+ }
919
+
920
+ public Object visitDAsgnNode(DAsgnNode node) {
921
+ return RuntimeHelper.dynamicAssign(this, node);
922
+ }
923
+
924
+ public Object visitDRegxNode(DRegexpNode node) {
925
+ // FIXME eval
926
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getRegexp()));
927
+ }
928
+
929
+ public Object visitDStrNode(DStrNode node) {
930
+ // FIXME eval
931
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getString()));
932
+ }
933
+
934
+ public Object visitDSymbolNode(DSymbolNode node) {
935
+ // FIXME eval
936
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getSymbol()));
937
+ }
938
+
939
+ public Object visitDVarNode(DVarNode node) {
940
+ VertexHolder holder = (VertexHolder) runtime.getContext().getCurrentScope().getValue(node.getName());
941
+ return holder != null ? holder.getVertex() : Vertex.EMPTY;
942
+ }
943
+
944
+ public Object visitDXStrNode(DXStrNode node) {
945
+ // FIXME eval `
946
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getString()));
947
+ }
948
+
949
+ public Object visitDefinedNode(DefinedNode node) {
950
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getString()));
951
+ }
952
+
953
+ public Object visitDefnNode(DefnNode node) {
954
+ RubyModule cbase = context.getCurrentScope().getModule();
955
+ RubyModule klass = context.getFrameModule();
956
+ String name = node.getName();
957
+ Node bodyNode = node.getBody();
958
+ Node argsNode = node.getArgs();
959
+ Visibility visibility = context.getFrameVisibility();
960
+ boolean moduleFunction = visibility == Visibility.MODULE_FUNCTION;
961
+ if (name == "initialize" || name == "initialize_copy" || moduleFunction) {
962
+ visibility = Visibility.PRIVATE;
963
+ }
964
+
965
+ Method oldMethod = (Method) klass.getMethod(name);
966
+ Method newMethod = new DefaultMethod(cbase, name, bodyNode, argsNode, visibility, SourceLocation.of(node));
967
+ klass.addMethod(name, newMethod);
968
+
969
+ if (moduleFunction) {
970
+ Method singletonMethod = new DefaultMethod(cbase, name, bodyNode, argsNode, visibility, SourceLocation.of(node));
971
+ singletonMethod.setVisibility(Visibility.PUBLIC);
972
+ klass.getSingletonClass().addMethod(name, singletonMethod);
973
+ }
974
+
975
+ IRubyObject receiver = newInstanceOf((klass instanceof RubyClass) ? (RubyClass) klass : runtime.getObject());
976
+
977
+ RuntimeHelper.methodPartialUpdate(this, node, newMethod, oldMethod, receiver);
978
+ RuntimeHelper.setMethodTag(newMethod, node,
979
+ AnnotationHelper.parseAnnotations(node.getPreviousComments(), node.getPosition().getStartLine()));
980
+
981
+ dummyCallQueue.offer(new DummyCall(node, newMethod, oldMethod, receiver));
982
+
983
+ notifyDefineEvent(node, newMethod);
984
+
985
+ return Vertex.EMPTY;
986
+ }
987
+
988
+ public Object visitDefsNode(DefsNode node) {
989
+ Vertex receiverVertex = createVertex(node.getReceiver());
990
+ if (receiverVertex.isEmpty()) {
991
+ Logger.error(SourceLocation.of(node), "null receiver for defs: %s", node.getName());
992
+ return Vertex.EMPTY;
993
+ }
994
+
995
+ RubyModule cbase = context.getCurrentScope().getModule();
996
+ String name = node.getName();
997
+ for (IRubyObject receiver : receiverVertex.getTypeSet()) {
998
+ if (receiver instanceof RubyModule) {
999
+ RubyClass rubyClass = receiver.getSingletonClass();
1000
+ Node bodyNode = node.getBody();
1001
+ Node argsNode = node.getArgs();
1002
+
1003
+ Method oldMethod = (Method) rubyClass.getMethod(name);
1004
+ Method newMethod = new DefaultMethod(cbase, name, bodyNode, argsNode, Visibility.PUBLIC, SourceLocation.of(node));
1005
+ rubyClass.addMethod(name, newMethod);
1006
+
1007
+ RuntimeHelper.methodPartialUpdate(this, node, newMethod, oldMethod, receiver);
1008
+ RuntimeHelper.setMethodTag(newMethod, node,
1009
+ AnnotationHelper.parseAnnotations(node.getPreviousComments(), node.getPosition().getStartLine()));
1010
+
1011
+ dummyCallQueue.offer(new DummyCall(node, newMethod, oldMethod, receiver));
1012
+
1013
+ notifyDefineEvent(node, newMethod);
1014
+ } else
1015
+ Logger.warn(SourceLocation.of(node), "cannot define singleton method for individual object: %s", name);
1016
+ }
1017
+
1018
+ return Vertex.EMPTY;
1019
+ }
1020
+
1021
+ public Object visitDotNode(DotNode node) {
1022
+ // FIXME propagation
1023
+ IRubyObject range = newInstanceOf(runtime.getRange());
1024
+ Vertex beginVertex = createVertex(node.getBegin());
1025
+ Vertex endVertex = createVertex(node.getEnd());
1026
+ TypeVarMap typeVarMap = RuntimeHelper.getTypeVarMap(range);
1027
+ if (typeVarMap != null && beginVertex != null && endVertex != null) {
1028
+ Vertex t = createFreeVertex();
1029
+ t.update(beginVertex);
1030
+ t.update(endVertex);
1031
+ typeVarMap.put(TypeVariable.valueOf("t"), t);
1032
+ }
1033
+ return createSingleTypeVertex(node, range);
1034
+ }
1035
+
1036
+ public Object visitEncodingNode(EncodingNode node) {
1037
+ unsupportedNode(node);
1038
+ return Vertex.EMPTY;
1039
+ }
1040
+
1041
+ public Object visitEnsureNode(EnsureNode node) {
1042
+ // FIXME
1043
+ if (node.getEnsure() != null) {
1044
+ createVertex(node.getEnsure());
1045
+ }
1046
+ return createVertex(node.getBody());
1047
+ }
1048
+
1049
+ public Object visitEvStrNode(EvStrNode node) {
1050
+ // never reach here
1051
+ unsupportedNode(node);
1052
+ return Vertex.EMPTY;
1053
+ }
1054
+
1055
+ public Object visitFCallNode(FCallNode node) {
1056
+ Vertex[] argVertices;
1057
+ Block block;
1058
+
1059
+ if (node.getArgs() != null && node.getArgs().getNodeType() == NodeType.BLOCKPASSNODE) {
1060
+ BlockPassNode block_pass = (BlockPassNode) node.getArgs();
1061
+ argVertices = RuntimeHelper.setupCallArgs(this, block_pass.getArgs());
1062
+ block = RuntimeHelper.setupCallBlock(this, block_pass);
1063
+ } else {
1064
+ argVertices = RuntimeHelper.setupCallArgs(this, node.getArgs());
1065
+ block = RuntimeHelper.setupCallBlock(this, node.getIter());
1066
+ }
1067
+
1068
+ CallVertex vertex = new CallVertex(node, createFreeSingleTypeVertex(context.getFrameSelf()), argVertices, block);
1069
+ vertex.setPrivateVisibility(true);
1070
+ return RuntimeHelper.call(this, vertex);
1071
+ }
1072
+
1073
+ public Object visitFalseNode(FalseNode node) {
1074
+ return createSingleTypeVertex(node, runtime.getFalse());
1075
+ }
1076
+
1077
+ public Object visitFixnumNode(FixnumNode node) {
1078
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getFixnum()));
1079
+ }
1080
+
1081
+ public Object visitFlipNode(FlipNode node) {
1082
+ // FIXME check booleans (new vertex)
1083
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getBoolean()));
1084
+ }
1085
+
1086
+ public Object visitFloatNode(FloatNode node) {
1087
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getFloat()));
1088
+ }
1089
+
1090
+ public Object visitForNode(ForNode node) {
1091
+ Vertex vertex = createEmptyVertex(node);
1092
+ Vertex receiverVertex = createVertex(node.getIter());
1093
+ Block block = new Proc(runtime, node.getVar(), node.getBody(), context.getCurrentFrame(), context.getCurrentScope());
1094
+ CallVertex callVertex = new CallVertex(node, "each", receiverVertex, null, block);
1095
+ RuntimeHelper.call(this, callVertex);
1096
+ addEdgeAndUpdate(vertex, callVertex);
1097
+ return vertex;
1098
+ }
1099
+
1100
+ public Object visitGlobalAsgnNode(GlobalAsgnNode node) {
1101
+ return RuntimeHelper.globalAssign(this, node);
1102
+ }
1103
+
1104
+ public Object visitGlobalVarNode(GlobalVarNode node) {
1105
+ return RuntimeHelper.globalVariable(this, node);
1106
+ }
1107
+
1108
+ public Object visitHashNode(HashNode node) {
1109
+ return RuntimeHelper.createHashVertex(this, node, RuntimeHelper.toVertices(this, node.getListNode()));
1110
+ }
1111
+
1112
+ @Override
1113
+ public Object visitImplicitNilNode(ImplicitNilNode node) {
1114
+ Vertex vertex = createEmptyVertex(node);
1115
+ return vertex;
1116
+ }
1117
+
1118
+ public Object visitInstAsgnNode(InstAsgnNode node) {
1119
+ return RuntimeHelper.instanceAssign(this, node);
1120
+ }
1121
+
1122
+ public Object visitInstVarNode(InstVarNode node) {
1123
+ return RuntimeHelper.instanceVariable(this, node);
1124
+ }
1125
+
1126
+ public Object visitIfNode(IfNode node) {
1127
+ Vertex vertex = createEmptyVertex(node);
1128
+ createVertex(node.getCondition());
1129
+ Vertex thenBodyVertex = null;
1130
+ if (node.getThenBody() != null) {
1131
+ thenBodyVertex = createVertex(node.getThenBody());
1132
+ addEdgeAndUpdate(thenBodyVertex, vertex);
1133
+ }
1134
+ Vertex elseBodyVertex = null;
1135
+ if (node.getElseBody() != null) {
1136
+ elseBodyVertex = createVertex(node.getElseBody());
1137
+ addEdgeAndUpdate(elseBodyVertex, vertex);
1138
+
1139
+ }
1140
+ return vertex;
1141
+ }
1142
+
1143
+ public Object visitIterNode(IterNode node) {
1144
+ unsupportedNode(node);
1145
+ return Vertex.EMPTY;
1146
+ }
1147
+
1148
+ @Override
1149
+ public Object visitKeywordArgNode(KeywordArgNode node) {
1150
+ throw new UnsupportedOperationException("Not supported yet.");
1151
+ }
1152
+
1153
+ @Override
1154
+ public Object visitKeywordRestArgNode(KeywordRestArgNode node) {
1155
+ throw new UnsupportedOperationException("Not supported yet.");
1156
+ }
1157
+
1158
+ @Override
1159
+ public Object visitLambdaNode(LambdaNode node) {
1160
+ Vertex vertex = createEmptyVertex(node);
1161
+ return vertex;
1162
+ }
1163
+
1164
+ public Object visitListNode(ListNode node) {
1165
+ Vertex vertex = createEmptyVertex(node);
1166
+ return vertex;
1167
+ }
1168
+
1169
+ public Object visitLiteralNode(LiteralNode node) {
1170
+ unsupportedNode(node);
1171
+ return Vertex.EMPTY;
1172
+ }
1173
+
1174
+ public Object visitLocalAsgnNode(LocalAsgnNode node) {
1175
+ return RuntimeHelper.localAssign(this, node);
1176
+ }
1177
+
1178
+ public Object visitLocalVarNode(LocalVarNode node) {
1179
+ VertexHolder holder = (VertexHolder) runtime.getContext().getCurrentScope().getValue(node.getName());
1180
+ return holder != null ? holder.getVertex() : Vertex.EMPTY;
1181
+ }
1182
+
1183
+ @Override
1184
+ public Object visitMethodNameNode(MethodNameNode node) { // Earlier versions of jruby-parser had this an ArgsNode
1185
+ unsupportedNode(node);
1186
+ return Vertex.EMPTY;
1187
+ }
1188
+
1189
+ public Object visitMultipleAsgnNode(MultipleAsgnNode node) {
1190
+ return RuntimeHelper.multipleAssign(this, node);
1191
+ }
1192
+
1193
+ public Object visitMatch2Node(Match2Node node) {
1194
+ // FIXME speedup node
1195
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getMatchData()));
1196
+ }
1197
+
1198
+ public Object visitMatch3Node(Match3Node node) {
1199
+ // FIXME speedup node
1200
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getMatchData()));
1201
+ }
1202
+
1203
+ public Object visitMatchNode(MatchNode node) {
1204
+ // FIXME speedup node
1205
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getMatchData()));
1206
+ }
1207
+
1208
+ public Object visitModuleNode(ModuleNode node) {
1209
+ Colon3Node cpath = node.getCPath();
1210
+ String name = cpath.getName();
1211
+ RubyModule enclosingModule = RuntimeHelper.getNamespace(this, cpath);
1212
+ if (enclosingModule == null) {
1213
+ Logger.error(SourceLocation.of(node), "namespace unresolved: %s", name);
1214
+ return Vertex.EMPTY;
1215
+ }
1216
+
1217
+ RubyModule module = enclosingModule.defineOrGetModuleUnder(name, SourceLocation.of(node));
1218
+
1219
+ if (module != null) {
1220
+ context.pushFrame(module, name, module, null, Visibility.PUBLIC);
1221
+ context.pushScope(new LocalScope(module));
1222
+
1223
+ RuntimeHelper.classPartialUpdate(this, module, node.getBody());
1224
+
1225
+ context.popScope();
1226
+ context.popFrame();
1227
+
1228
+ RuntimeHelper.setClassTag(module, node.getBody(),
1229
+ AnnotationHelper.parseAnnotations(node.getPreviousComments(), node.getPosition().getStartLine()));
1230
+
1231
+ notifyModuleEvent(node, module);
1232
+ }
1233
+
1234
+ return Vertex.EMPTY;
1235
+ }
1236
+
1237
+ public Object visitNewlineNode(NewlineNode node) {
1238
+ return createVertex(node.getNextNode());
1239
+ }
1240
+
1241
+ public Object visitNextNode(NextNode node) {
1242
+ Frame frame = context.getCurrentFrame();
1243
+ LoopTag loopTag = RuntimeHelper.getFrameLoopTag(frame);
1244
+ if (loopTag != null && loopTag.getYieldVertex() != null) {
1245
+ Vertex vertex;
1246
+ if (node.getValue() != null) {
1247
+ vertex = createVertex(node.getValue());
1248
+ } else {
1249
+ vertex = createEmptyVertex(node);
1250
+ }
1251
+
1252
+ if (loopTag.getYieldVertex() != null)
1253
+ addEdgeAndPropagate(vertex, loopTag.getYieldVertex());
1254
+ else
1255
+ Logger.debug("no yield vertex");
1256
+ return vertex;
1257
+ }
1258
+ return Vertex.EMPTY;
1259
+ }
1260
+
1261
+ public Object visitNilNode(NilNode node) {
1262
+ return createSingleTypeVertex(node, runtime.getNil());
1263
+ }
1264
+
1265
+ public Object visitNotNode(NotNode node) {
1266
+ createVertex(node.getCondition());
1267
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getBoolean()));
1268
+ }
1269
+
1270
+ public Object visitNthRefNode(NthRefNode node) {
1271
+ // FIXME
1272
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getString()));
1273
+ }
1274
+
1275
+ public Object visitOpElementAsgnNode(OpElementAsgnNode node) {
1276
+ String operator = node.getOperatorName();
1277
+ Vertex receiverVertex = createVertex(node.getReceiver());
1278
+ Vertex[] argVertices = null;
1279
+ if (node.getArgs() != null) {
1280
+ List<Node> argNodes = node.getArgs().childNodes();
1281
+ argVertices = new Vertex[argNodes.size()];
1282
+ for (int i = 0; i < argVertices.length; i++) {
1283
+ argVertices[i] = createVertex(argNodes.get(i));
1284
+ }
1285
+ }
1286
+ Vertex src = createVertex(node.getValue());
1287
+ Vertex value;
1288
+
1289
+ if (operator.equals("||") || operator.equals("&&")) {
1290
+ // do nothing
1291
+ value = src;
1292
+ } else {
1293
+ CallVertex getter = new CallVertex(node.getReceiver(), "[]", receiverVertex, argVertices, null);
1294
+ CallVertex op = new CallVertex(node, operator, RuntimeHelper.call(this, getter), new Vertex[] {src}, null);
1295
+ value = RuntimeHelper.call(this, op);
1296
+ }
1297
+
1298
+ Vertex[] expandedArgs = new Vertex[argVertices.length + 1];
1299
+ System.arraycopy(argVertices, 0, expandedArgs, 0, argVertices.length);
1300
+ expandedArgs[expandedArgs.length - 1] = value;
1301
+ CallVertex setter = new CallVertex(node, "[]=", receiverVertex, expandedArgs, null);
1302
+ return RuntimeHelper.call(this, setter);
1303
+ }
1304
+
1305
+ public Object visitOpAsgnNode(OpAsgnNode node) {
1306
+ String operator = node.getOperatorName();
1307
+ String var = node.getVariableName();
1308
+ String varAsgn = (node.getVariableName() + "=");
1309
+ Vertex receiverVertex = createVertex(node.getReceiver());
1310
+ Vertex src = createVertex(node.getValue());
1311
+ Vertex value;
1312
+ if (operator.equals("||") || operator.equals("&&")) {
1313
+ // do nothing
1314
+ value = src;
1315
+ } else {
1316
+ CallVertex getter = new CallVertex(node.getValue(), var, receiverVertex, null, null);
1317
+ CallVertex op = new CallVertex(node.getValue(), operator, RuntimeHelper.call(this, getter), new Vertex[] {src}, null);
1318
+ value = RuntimeHelper.call(this, op);
1319
+ }
1320
+
1321
+ CallVertex setter = new CallVertex(node.getValue(), varAsgn, receiverVertex, new Vertex[] {value}, null);
1322
+ return RuntimeHelper.call(this, setter);
1323
+ }
1324
+
1325
+ public Object visitOpAsgnAndNode(OpAsgnAndNode node) {
1326
+ Vertex vertex = createEmptyVertex(node);
1327
+ Vertex firstVertex = createVertex(node.getFirst());
1328
+ Vertex secondVertex = createVertex(node.getSecond());
1329
+ addEdgeAndUpdate(firstVertex, vertex);
1330
+ addEdgeAndUpdate(secondVertex, vertex);
1331
+ return vertex;
1332
+ }
1333
+
1334
+ public Object visitOpAsgnOrNode(OpAsgnOrNode node) {
1335
+ Vertex vertex = createEmptyVertex(node);
1336
+ Vertex firstVertex = createVertex(node.getFirst());
1337
+ Vertex secondVertex = createVertex(node.getSecond());
1338
+ addEdgeAndUpdate(firstVertex, vertex);
1339
+ addEdgeAndUpdate(secondVertex, vertex);
1340
+ return vertex;
1341
+ }
1342
+
1343
+ public Object visitOptArgNode(OptArgNode node) {
1344
+ Vertex vertex = createEmptyVertex(node);
1345
+ return vertex;
1346
+ }
1347
+
1348
+ public Object visitOrNode(OrNode node) {
1349
+ Vertex vertex = createEmptyVertex(node);
1350
+ Vertex firstVertex = createVertex(node.getFirst());
1351
+ Vertex secondVertex = createVertex(node.getSecond());
1352
+ addEdgeAndUpdate(firstVertex, vertex);
1353
+ addEdgeAndUpdate(secondVertex, vertex);
1354
+ return vertex;
1355
+ }
1356
+
1357
+ public Object visitPreExeNode(PreExeNode node) {
1358
+ unsupportedNode(node);
1359
+ return Vertex.EMPTY;
1360
+ }
1361
+
1362
+ public Object visitPostExeNode(PostExeNode node) {
1363
+ unsupportedNode(node);
1364
+ return Vertex.EMPTY;
1365
+ }
1366
+
1367
+ public Object visitRedoNode(RedoNode node) {
1368
+ return Vertex.EMPTY;
1369
+ }
1370
+
1371
+ public Object visitRegexpNode(RegexpNode node) {
1372
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getRegexp()));
1373
+ }
1374
+
1375
+ public Object visitRescueBodyNode(RescueBodyNode node) {
1376
+ if (node.getBody() != null) {
1377
+ return createVertex(node.getBody());
1378
+ }
1379
+ return Vertex.EMPTY;
1380
+ }
1381
+
1382
+ public Object visitRescueNode(RescueNode node) {
1383
+ Vertex result = Vertex.EMPTY;
1384
+ if (node.getBody() != null) {
1385
+ result = createVertex(node.getBody());
1386
+ }
1387
+ if (node.getRescue() != null) {
1388
+ createVertex(node.getRescue());
1389
+ }
1390
+ if (node.getElse() != null) {
1391
+ result = createVertex(node.getElse());
1392
+ }
1393
+ return result;
1394
+ }
1395
+
1396
+ public Object visitRestArgNode(RestArgNode node) {
1397
+ unsupportedNode(node);
1398
+ return Vertex.EMPTY;
1399
+ }
1400
+
1401
+ public Object visitRetryNode(RetryNode node) {
1402
+ return Vertex.EMPTY;
1403
+ }
1404
+
1405
+ public Object visitReturnNode(ReturnNode node) {
1406
+ Frame frame = context.getCurrentFrame();
1407
+ Template template = RuntimeHelper.getFrameTemplate(frame);
1408
+ if (template != null) {
1409
+
1410
+ Vertex vertex;
1411
+ if (node.getValue() != null) {
1412
+ vertex = createVertex(node.getValue());
1413
+ } else {
1414
+ vertex = createEmptyVertex(node);
1415
+ }
1416
+
1417
+ addEdgeAndPropagate(vertex, template.getReturnVertex());
1418
+ return vertex;
1419
+ }
1420
+ return Vertex.EMPTY;
1421
+ }
1422
+
1423
+ public Object visitRootNode(RootNode node) {
1424
+ return createVertex(node.getBody());
1425
+ }
1426
+
1427
+ public Object visitSClassNode(SClassNode node) {
1428
+ Vertex receiverVertex = createVertex(node.getReceiver());
1429
+
1430
+ if (receiverVertex != null) {
1431
+ for (IRubyObject object : receiverVertex.getTypeSet()) {
1432
+ RubyClass klass = object.getMetaClass();
1433
+ if (klass.isSingleton()) {
1434
+ MetaClass metaClass = (MetaClass) klass;
1435
+ if (metaClass.getAttached() instanceof RubyModule) {
1436
+ context.pushFrame(klass, "sclass", klass, null, Visibility.PUBLIC);
1437
+ context.pushScope(new LocalScope((RubyModule) metaClass.getAttached()));
1438
+
1439
+ if (node.getBody() != null) {
1440
+ createVertex(node.getBody());
1441
+ }
1442
+
1443
+ context.popScope();
1444
+ context.popFrame();
1445
+ }
1446
+
1447
+ return Vertex.EMPTY;
1448
+ } else {
1449
+ Logger.warn(SourceLocation.of(node), "singleton class of objects is not supported.");
1450
+ }
1451
+ }
1452
+ }
1453
+
1454
+ return Vertex.EMPTY;
1455
+ }
1456
+
1457
+ public Object visitSelfNode(SelfNode node) {
1458
+ IRubyObject self = context.getFrameSelf();
1459
+ if (self == null) {
1460
+ Logger.error(SourceLocation.of(node), "self unresolved");
1461
+ return Vertex.EMPTY;
1462
+ } else
1463
+ return createSingleTypeVertex(node, self);
1464
+ }
1465
+
1466
+ public Object visitSplatNode(SplatNode node) {
1467
+ Vertex valueVertex = createVertex(node.getValue());
1468
+ SplatVertex vertex = new SplatVertex(node, valueVertex);
1469
+ RuntimeHelper.splatValue(this, vertex);
1470
+ return vertex;
1471
+ }
1472
+
1473
+ public Object visitStrNode(StrNode node) {
1474
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getString()));
1475
+ }
1476
+
1477
+ public Object visitSyntaxNode(SyntaxNode node) {
1478
+ return Vertex.EMPTY;
1479
+ }
1480
+
1481
+ public Object visitSuperNode(SuperNode node) {
1482
+ Vertex receiverVertex = createFreeSingleTypeVertex(context.getFrameSelf());
1483
+ Vertex[] argVertices = null;
1484
+ if (node.getArgs() != null) {
1485
+ List<Node> argNodes = node.getArgs().childNodes();
1486
+ argVertices = new Vertex[argNodes.size()];
1487
+ for (int i = 0; i < argVertices.length; i++) {
1488
+ argVertices[i] = createVertex(argNodes.get(i));
1489
+ }
1490
+ }
1491
+
1492
+ Block block = RuntimeHelper.setupCallBlock(this, node.getIter());
1493
+ CallVertex vertex = new CallVertex(node, context.getCurrentFrame().getName(), receiverVertex, argVertices, block);
1494
+ vertex.setPrivateVisibility(true);
1495
+ return RuntimeHelper.callSuper(this, vertex);
1496
+ }
1497
+
1498
+ public Object visitSValueNode(SValueNode node) {
1499
+ SValueVertex vertex = new SValueVertex(node, createVertex(node.getValue()));
1500
+ RuntimeHelper.aValueSplat(this, vertex);
1501
+ return vertex;
1502
+ }
1503
+
1504
+ public Object visitSymbolNode(SymbolNode node) {
1505
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getSymbol()));
1506
+ }
1507
+
1508
+ public Object visitToAryNode(ToAryNode node) {
1509
+ Vertex valueVertex = createVertex(node.getValue());
1510
+ ToAryVertex vertex = new ToAryVertex(node, valueVertex);
1511
+ RuntimeHelper.toAryValue(this, vertex);
1512
+ return vertex;
1513
+ }
1514
+
1515
+ public Object visitTrueNode(TrueNode node) {
1516
+ return createSingleTypeVertex(node, runtime.getTrue());
1517
+ }
1518
+
1519
+ @Override
1520
+ public Object visitUnaryCallNode(UnaryCallNode node) {
1521
+ return createVertex(node.getReceiver());
1522
+ }
1523
+
1524
+ public Object visitUndefNode(UndefNode node) {
1525
+ Logger.warn("undef is not supported yet.");
1526
+ return Vertex.EMPTY;
1527
+ }
1528
+
1529
+ public Object visitUntilNode(UntilNode node) {
1530
+ Vertex vertex = createEmptyVertex(node);
1531
+ createVertex(node.getCondition());
1532
+ RuntimeHelper.pushLoopFrame(context, vertex, null);
1533
+ createVertex(node.getBody());
1534
+ RuntimeHelper.popLoopFrame(context);
1535
+ return vertex;
1536
+ }
1537
+
1538
+ public Object visitVAliasNode(VAliasNode node) {
1539
+ RuntimeHelper.aliasGlobalVariables(this, node.getNewName(), node.getOldName());
1540
+ return Vertex.EMPTY;
1541
+ }
1542
+
1543
+ public Object visitVCallNode(VCallNode node) {
1544
+ CallVertex vertex = new CallVertex(node, createFreeSingleTypeVertex(context.getFrameSelf()), null, null);
1545
+ vertex.setPrivateVisibility(true);
1546
+ return RuntimeHelper.call(this, vertex);
1547
+ }
1548
+
1549
+ public Object visitWhenNode(WhenNode node) {
1550
+ // never reach here
1551
+ unsupportedNode(node);
1552
+ return Vertex.EMPTY;
1553
+ }
1554
+
1555
+ public Object visitWhileNode(WhileNode node) {
1556
+ Vertex vertex = createEmptyVertex(node);
1557
+ createVertex(node.getCondition());
1558
+ RuntimeHelper.pushLoopFrame(context, vertex, null);
1559
+ createVertex(node.getBody());
1560
+ RuntimeHelper.popLoopFrame(context);
1561
+ return vertex;
1562
+ }
1563
+
1564
+ public Object visitXStrNode(XStrNode node) {
1565
+ // FIXME eval `
1566
+ return createSingleTypeVertex(node, newInstanceOf(runtime.getString()));
1567
+ }
1568
+
1569
+ public Object visitYieldNode(YieldNode node) {
1570
+ Vertex argsVertex = null;
1571
+ if (node.getArgs() != null) {
1572
+ argsVertex = createVertex(node.getArgs());
1573
+ }
1574
+ YieldVertex vertex = new YieldVertex(node, RuntimeHelper.getFrameTemplate(context.getCurrentFrame()), context.getFrameBlock(), argsVertex, node.getExpandArguments());
1575
+ return RuntimeHelper.yield(this, vertex);
1576
+ }
1577
+
1578
+ public Object visitZArrayNode(ZArrayNode node) {
1579
+ return RuntimeHelper.createArrayVertex(this, node, null);
1580
+ }
1581
+
1582
+ public Object visitZSuperNode(ZSuperNode node) {
1583
+ Template template = RuntimeHelper.getFrameTemplate(context.getCurrentFrame());
1584
+ if (template != null) {
1585
+ // FIXME more efficient way
1586
+ TemplateAttribute attr = template.getAttribute();
1587
+ IRubyObject[] args = attr.getArgs();
1588
+
1589
+ Vertex receiverVertex = createFreeSingleTypeVertex(context.getFrameSelf());
1590
+ Vertex[] argVertices = new Vertex[args.length];
1591
+ for (int i = 0; i < args.length; i++) {
1592
+ argVertices[i] = createFreeSingleTypeVertex(args[i]);
1593
+ }
1594
+
1595
+ Block block = RuntimeHelper.setupCallBlock(this, node.getIter());
1596
+ CallVertex vertex = new CallVertex(node, context.getCurrentFrame().getName(), receiverVertex, argVertices, block);
1597
+ vertex.setPrivateVisibility(true);
1598
+ return RuntimeHelper.callSuper(this, vertex);
1599
+ }
1600
+ return Vertex.EMPTY;
1601
+ }
1602
+
1603
+ public boolean propagateVertex(Propagation propagation, Vertex dest, Vertex src) {
1604
+ // copy first to make sure variable assign can be revisited
1605
+ dest.update(src);
1606
+
1607
+ if (propagation.checkVisited(dest)) {
1608
+ return true;
1609
+ }
1610
+
1611
+ return propagateEdges(propagation, dest);
1612
+ }
1613
+
1614
+ public boolean propagateCallVertex(Propagation propagation, CallVertex dest, Vertex src) {
1615
+ if (propagation.checkVisited(dest)) { return true; }
1616
+
1617
+ RuntimeHelper.call(this, dest);
1618
+ return propagateEdges(propagation, dest);
1619
+ }
1620
+
1621
+ public boolean propagateMultipleAsgnVertex(Propagation propagation, MultipleAsgnVertex dest, Vertex src) {
1622
+ if (propagation.checkVisited(dest)) { return true; }
1623
+
1624
+ if (dest.isChanged()) {
1625
+ dest.markUnchanged();
1626
+
1627
+ for (IRubyObject object : RuntimeHelper.arrayValue(propagation.getGraph(), dest.getValueVertex())) {
1628
+ RuntimeHelper.multipleAssign(this, (MultipleAsgnNode) dest.getNode(), object);
1629
+ }
1630
+ }
1631
+
1632
+ // FIXME no need to propagate?
1633
+ return true;
1634
+ }
1635
+
1636
+ public boolean propagateSplatVertex(Propagation propagation, SplatVertex dest, Vertex src) {
1637
+ if (propagation.checkVisited(dest)) { return true; }
1638
+
1639
+ if (dest.isChanged()) {
1640
+ dest.markUnchanged();
1641
+ RuntimeHelper.splatValue(this, dest);
1642
+ }
1643
+ return propagateEdges(propagation, dest);
1644
+ }
1645
+
1646
+ public boolean propagateToAryVertex(Propagation propagation, ToAryVertex dest, Vertex src) {
1647
+ if (propagation.checkVisited(dest)) { return true; }
1648
+
1649
+ if (dest.isChanged()) {
1650
+ dest.markUnchanged();
1651
+ RuntimeHelper.toAryValue(this, dest);
1652
+ }
1653
+ return propagateEdges(propagation, dest);
1654
+ }
1655
+
1656
+ public boolean propagateSValueVertex(Propagation propagation, SValueVertex dest, Vertex src) {
1657
+ if (propagation.checkVisited(dest)) { return true; }
1658
+
1659
+ if (dest.isChanged()) {
1660
+ dest.markUnchanged();
1661
+ RuntimeHelper.aValueSplat(this, dest);
1662
+ }
1663
+ return propagateEdges(propagation, dest);
1664
+ }
1665
+
1666
+ public boolean propagateYieldVertex(Propagation propagation, YieldVertex dest, Vertex src) {
1667
+ if (propagation.checkVisited(dest)) { return true; }
1668
+
1669
+ RuntimeHelper.yield(this, dest);
1670
+ return propagateEdges(propagation, dest);
1671
+ }
1672
+
1673
+ public boolean propagatePassThroughVertex(Propagation propagation, PassThroughVertex dest, Vertex src) {
1674
+ if (propagation.checkVisited(dest)) { return true; }
1675
+
1676
+ return propagateEdges(propagation, dest);
1677
+ }
1678
+
1679
+ public boolean propagateTypeVarVertex(Propagation propagation, TypeVarVertex dest, Vertex src) {
1680
+ if (propagation.checkVisited(dest)) { return true; }
1681
+
1682
+ dest.getObject().setModified(true);
1683
+ dest.update(src);
1684
+ return propagateEdges(propagation, dest);
1685
+ }
1686
+
1687
+ private void unsupportedNode(Node node) {
1688
+ Logger.fixme("unsupported node: %s", node);
1689
+ }
1690
+ }