rsense-core 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }