13514
|
1 /*
|
|
2 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
|
|
3 * code is released under a tri EPL/GPL/LGPL license. You can use it,
|
|
4 * redistribute it and/or modify it under the terms of the:
|
|
5 *
|
|
6 * Eclipse Public License version 1.0
|
|
7 * GNU General Public License version 2
|
|
8 * GNU Lesser General Public License version 2.1
|
|
9 */
|
|
10 package com.oracle.truffle.ruby.parser;
|
|
11
|
|
12 import java.util.*;
|
|
13
|
|
14 import com.oracle.truffle.api.*;
|
|
15 import com.oracle.truffle.api.frame.*;
|
|
16 import com.oracle.truffle.ruby.nodes.*;
|
|
17 import com.oracle.truffle.ruby.nodes.methods.locals.*;
|
|
18 import com.oracle.truffle.ruby.runtime.*;
|
|
19 import com.oracle.truffle.ruby.runtime.core.*;
|
|
20 import com.oracle.truffle.ruby.runtime.methods.*;
|
|
21
|
|
22 public class TranslatorEnvironment {
|
|
23
|
|
24 private final RubyContext context;
|
|
25
|
|
26 private final FrameDescriptor frameDescriptor;
|
|
27
|
|
28 private final List<FrameSlot> preParameters = new ArrayList<>();
|
|
29
|
|
30 private final List<FrameSlot> optionalParameters = new ArrayList<>();
|
|
31 private final Map<FrameSlot, RubyNode> optionalParametersDefaultValues = new HashMap<>();
|
|
32
|
|
33 private final List<FrameSlot> postParameters = new ArrayList<>();
|
|
34
|
|
35 private final List<FrameSlot> flipFlopStates = new ArrayList<>();
|
|
36
|
|
37 private FrameSlot restParameter = null;
|
|
38
|
|
39 private FrameSlot blockParameter = null;
|
|
40
|
|
41 private JRubyParser parser;
|
|
42 private final long returnID;
|
|
43
|
|
44 private final boolean ownScopeForAssignments;
|
|
45 private final boolean neverAssignInParentScope;
|
|
46
|
|
47 protected final TranslatorEnvironment parent;
|
|
48 private String methodName = "";
|
|
49 private boolean needsDeclarationFrame = false;
|
|
50 private UniqueMethodIdentifier methodIdentifier;
|
|
51
|
|
52 private int tempIndex;
|
|
53
|
|
54 public TranslatorEnvironment(RubyContext context, TranslatorEnvironment parent, FrameDescriptor frameDescriptor, JRubyParser parser, long returnID, boolean ownScopeForAssignments,
|
|
55 boolean neverAssignInParentScope, UniqueMethodIdentifier methodIdentifier) {
|
|
56 this.context = context;
|
|
57 this.parent = parent;
|
|
58 this.frameDescriptor = frameDescriptor;
|
|
59 this.parser = parser;
|
|
60 this.returnID = returnID;
|
|
61 this.ownScopeForAssignments = ownScopeForAssignments;
|
|
62 this.neverAssignInParentScope = neverAssignInParentScope;
|
|
63 this.methodIdentifier = methodIdentifier;
|
|
64 }
|
|
65
|
|
66 public TranslatorEnvironment(RubyContext context, TranslatorEnvironment parent, JRubyParser parser, long returnID, boolean ownScopeForAssignments, boolean neverAssignInParentScope,
|
|
67 UniqueMethodIdentifier methodIdentifier) {
|
|
68 this(context, parent, new FrameDescriptor(RubyFrameTypeConversion.getInstance()), parser, returnID, ownScopeForAssignments, neverAssignInParentScope, methodIdentifier);
|
|
69 }
|
|
70
|
|
71 public int getLocalVarCount() {
|
|
72 return getFrameDescriptor().getSize();
|
|
73 }
|
|
74
|
|
75 public TranslatorEnvironment getParent() {
|
|
76 return parent;
|
|
77 }
|
|
78
|
|
79 public List<FrameSlot> getPreParameters() {
|
|
80 return preParameters;
|
|
81 }
|
|
82
|
|
83 public List<FrameSlot> getOptionalParameters() {
|
|
84 return optionalParameters;
|
|
85 }
|
|
86
|
|
87 public Map<FrameSlot, RubyNode> getOptionalParametersDefaultValues() {
|
|
88 return optionalParametersDefaultValues;
|
|
89 }
|
|
90
|
|
91 public List<FrameSlot> getPostParameters() {
|
|
92 return postParameters;
|
|
93 }
|
|
94
|
|
95 public TranslatorEnvironment getParent(int level) {
|
|
96 assert level >= 0;
|
|
97 if (level == 0) {
|
|
98 return this;
|
|
99 } else {
|
|
100 return parent.getParent(level - 1);
|
|
101 }
|
|
102 }
|
|
103
|
|
104 public FrameSlot declareVar(String name) {
|
|
105 return getFrameDescriptor().findOrAddFrameSlot(name);
|
|
106 }
|
|
107
|
|
108 public UniqueMethodIdentifier findMethodForLocalVar(String name) {
|
|
109 TranslatorEnvironment current = this;
|
|
110 do {
|
|
111 FrameSlot slot = current.getFrameDescriptor().findFrameSlot(name);
|
|
112 if (slot != null) {
|
|
113 return current.methodIdentifier;
|
|
114 }
|
|
115
|
|
116 current = current.parent;
|
|
117 } while (current != null);
|
|
118
|
|
119 return null;
|
|
120 }
|
|
121
|
|
122 public RubyNode findLocalVarNode(String name, SourceSection sourceSection) {
|
|
123 TranslatorEnvironment current = this;
|
|
124 int level = -1;
|
|
125 try {
|
|
126 do {
|
|
127 level++;
|
|
128 FrameSlot slot = current.getFrameDescriptor().findFrameSlot(name);
|
|
129 if (slot != null) {
|
|
130 if (level == 0) {
|
|
131 return ReadLocalVariableNodeFactory.create(context, sourceSection, slot);
|
|
132 } else {
|
|
133 return ReadLevelVariableNodeFactory.create(context, sourceSection, slot, level);
|
|
134 }
|
|
135 }
|
|
136
|
|
137 current = current.parent;
|
|
138 } while (current != null);
|
|
139 } finally {
|
|
140 if (current != null) {
|
|
141 current = this;
|
|
142 while (level-- > 0) {
|
|
143 current.needsDeclarationFrame = true;
|
|
144 current = current.parent;
|
|
145 }
|
|
146 }
|
|
147 }
|
|
148
|
|
149 return null;
|
|
150 }
|
|
151
|
|
152 public void setRestParameter(FrameSlot restParameter) {
|
|
153 this.restParameter = restParameter;
|
|
154 }
|
|
155
|
|
156 public FrameSlot getRestParameter() {
|
|
157 return restParameter;
|
|
158 }
|
|
159
|
|
160 public void setBlockParameter(FrameSlot blockParameter) {
|
|
161 this.blockParameter = blockParameter;
|
|
162 }
|
|
163
|
|
164 public FrameSlot getBlockParameter() {
|
|
165 return blockParameter;
|
|
166 }
|
|
167
|
|
168 public void declareFunction(String name) {
|
|
169 declareVar(name);
|
|
170 }
|
|
171
|
|
172 public String getMethodName() {
|
|
173 return methodName;
|
|
174 }
|
|
175
|
|
176 public void setMethodName(String methodName) {
|
|
177 this.methodName = methodName;
|
|
178 }
|
|
179
|
|
180 public void setNeedsDeclarationFrame() {
|
|
181 needsDeclarationFrame = true;
|
|
182 }
|
|
183
|
|
184 public boolean needsDeclarationFrame() {
|
|
185 return needsDeclarationFrame;
|
|
186 }
|
|
187
|
|
188 public FrameDescriptor getFrameDescriptor() {
|
|
189 return frameDescriptor;
|
|
190 }
|
|
191
|
|
192 public String allocateLocalTemp() {
|
|
193 final String name = "rubytruffle_temp" + tempIndex;
|
|
194 tempIndex++;
|
|
195 declareVar(name);
|
|
196 return name;
|
|
197 }
|
|
198
|
|
199 public long getReturnID() {
|
|
200 return returnID;
|
|
201 }
|
|
202
|
|
203 public JRubyParser getParser() {
|
|
204 return parser;
|
|
205 }
|
|
206
|
|
207 public boolean hasOwnScopeForAssignments() {
|
|
208 return ownScopeForAssignments;
|
|
209 }
|
|
210
|
|
211 public boolean getNeverAssignInParentScope() {
|
|
212 return neverAssignInParentScope;
|
|
213 }
|
|
214
|
|
215 public void addMethodDeclarationSlots() {
|
|
216 frameDescriptor.addFrameSlot(RubyModule.VISIBILITY_FRAME_SLOT_ID);
|
|
217 frameDescriptor.addFrameSlot(RubyModule.MODULE_FUNCTION_FLAG_FRAME_SLOT_ID);
|
|
218 }
|
|
219
|
|
220 public UniqueMethodIdentifier getUniqueMethodIdentifier() {
|
|
221 return methodIdentifier;
|
|
222 }
|
|
223
|
|
224 public List<FrameSlot> getFlipFlopStates() {
|
|
225 return flipFlopStates;
|
|
226 }
|
|
227 }
|