001: /***** BEGIN LICENSE BLOCK *****
002: * Version: CPL 1.0/GPL 2.0/LGPL 2.1
003: *
004: * The contents of this file are subject to the Common Public
005: * License Version 1.0 (the "License"); you may not use this file
006: * except in compliance with the License. You may obtain a copy of
007: * the License at http://www.eclipse.org/legal/cpl-v10.html
008: *
009: * Software distributed under the License is distributed on an "AS
010: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
011: * implied. See the License for the specific language governing
012: * rights and limitations under the License.
013: *
014: * Copyright (C) 2006 Charles O Nutter <headius@headius.com>
015: *
016: * Alternatively, the contents of this file may be used under the terms of
017: * either of the GNU General Public License Version 2 or later (the "GPL"),
018: * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
019: * in which case the provisions of the GPL or the LGPL are applicable instead
020: * of those above. If you wish to allow use of your version of this file only
021: * under the terms of either the GPL or the LGPL, and not to allow others to
022: * use your version of this file under the terms of the CPL, indicate your
023: * decision by deleting the provisions above and replace them with the notice
024: * and other provisions required by the GPL or the LGPL. If you do not delete
025: * the provisions above, a recipient may use your version of this file under
026: * the terms of any one of the CPL, the GPL or the LGPL.
027: ***** END LICENSE BLOCK *****/package org.jruby.compiler;
028:
029: import java.util.HashSet;
030: import java.util.Set;
031: import org.jruby.ast.ArgsNode;
032: import org.jruby.ast.LocalAsgnNode;
033: import org.jruby.ast.Node;
034: import org.jruby.ast.NodeTypes;
035:
036: /**
037: *
038: * @author headius
039: */
040: public class NodeCompilerFactory {
041: public static final boolean SAFE = System.getProperty(
042: "jruby.jit.safe", "true").equals("true");
043: public static final Set UNSAFE_CALLS;
044:
045: static {
046: UNSAFE_CALLS = new HashSet();
047: }
048:
049: public static YARVNodesCompiler getYARVCompiler() {
050: return new YARVNodesCompiler();
051: }
052:
053: public static NodeCompiler getCompiler(Node node) {
054: switch (node.nodeId) {
055: case NodeTypes.ALIASNODE:
056: // safe
057: return new AliasNodeCompiler();
058: case NodeTypes.ANDNODE:
059: // safe
060: return new AndNodeCompiler();
061: case NodeTypes.ARRAYNODE:
062: // safe
063: return new ArrayNodeCompiler();
064: case NodeTypes.ATTRASSIGNNODE:
065: // safe, I think :)
066: return new AttrAssignNodeCompiler();
067: case NodeTypes.BEGINNODE:
068: // safe
069: return new BeginNodeCompiler();
070: case NodeTypes.BIGNUMNODE:
071: // safe
072: return new BignumNodeCompiler();
073: case NodeTypes.BLOCKNODE:
074: // safe
075: return new BlockNodeCompiler();
076: case NodeTypes.BREAKNODE:
077: // Not safe yet; something weird with break-handling try/catch and calls like "foo bar {}"
078: if (SAFE)
079: throw new NotCompilableException(
080: "Can't compile node safely: " + node);
081: return new BreakNodeCompiler();
082: case NodeTypes.CALLNODE:
083: // safe; yield or block nodes that aren't should raise
084: return new CallNodeCompiler();
085: case NodeTypes.CLASSNODE:
086: if (SAFE)
087: throw new NotCompilableException(
088: "Can't compile class definitions safely: "
089: + node);
090: return new ClassNodeCompiler();
091: case NodeTypes.CLASSVARNODE:
092: return new ClassVarNodeCompiler();
093: case NodeTypes.CLASSVARASGNNODE:
094: return new ClassVarAsgnNodeCompiler();
095: case NodeTypes.CONSTDECLNODE:
096: // this should be safe as well with TC doing the right thing
097: return new ConstDeclNodeCompiler();
098: case NodeTypes.COLON2NODE:
099: return new Colon2NodeCompiler();
100: case NodeTypes.CONSTNODE:
101: // I think this is safe now that cref and class are being pushed on TC
102: return new ConstNodeCompiler();
103: case NodeTypes.DASGNNODE:
104: // safe
105: return new DAsgnNodeCompiler();
106: case NodeTypes.DEFNNODE:
107: // safe; it's primarily odd arg types that are problems, and defn compiler will catch those
108: return new DefnNodeCompiler();
109: case NodeTypes.DOTNODE:
110: // safe
111: return new DotNodeCompiler();
112: case NodeTypes.DSTRNODE:
113: // safe
114: return new DStrNodeCompiler();
115: case NodeTypes.DVARNODE:
116: // safe
117: return new DVarNodeCompiler();
118: case NodeTypes.EVSTRNODE:
119: // safe
120: return new EvStrNodeCompiler();
121: case NodeTypes.FALSENODE:
122: // safe
123: return new FalseNodeCompiler();
124: case NodeTypes.FCALLNODE:
125: // safe
126: return new FCallNodeCompiler();
127: case NodeTypes.FIXNUMNODE:
128: // safe
129: return new FixnumNodeCompiler();
130: case NodeTypes.FLOATNODE:
131: // safe
132: return new FloatNodeCompiler();
133: case NodeTypes.GLOBALASGNNODE:
134: // safe
135: return new GlobalAsgnNodeCompiler();
136: case NodeTypes.GLOBALVARNODE:
137: // safe
138: return new GlobalVarNodeCompiler();
139: case NodeTypes.HASHNODE:
140: // safe
141: return new HashNodeCompiler();
142: case NodeTypes.IFNODE:
143: // safe
144: return new IfNodeCompiler();
145: case NodeTypes.INSTASGNNODE:
146: // safe
147: return new InstAsgnNodeCompiler();
148: case NodeTypes.INSTVARNODE:
149: // safe
150: return new InstVarNodeCompiler();
151: case NodeTypes.ITERNODE:
152: return new IterNodeCompiler();
153: case NodeTypes.LOCALASGNNODE:
154: // safe
155: return new LocalAsgnNodeCompiler();
156: case NodeTypes.LOCALVARNODE:
157: // safe
158: return new LocalVarNodeCompiler();
159: case NodeTypes.MATCHNODE:
160: // safe
161: return new MatchNodeCompiler();
162: case NodeTypes.MATCH2NODE:
163: // safe
164: return new Match2NodeCompiler();
165: case NodeTypes.MATCH3NODE:
166: // safe
167: return new Match3NodeCompiler();
168: case NodeTypes.MODULENODE:
169: if (SAFE)
170: throw new NotCompilableException(
171: "Can't compile module definitions safely: "
172: + node);
173: return new ModuleNodeCompiler();
174: case NodeTypes.NEWLINENODE:
175: // safe
176: return new NewlineNodeCompiler();
177: case NodeTypes.NTHREFNODE:
178: // safe
179: return new NthRefNodeCompiler();
180: case NodeTypes.NILNODE:
181: // safe
182: return new NilNodeCompiler();
183: case NodeTypes.NOTNODE:
184: // safe
185: return new NotNodeCompiler();
186: case NodeTypes.OPASGNNODE:
187: // safe
188: return new OpAsgnNodeCompiler();
189: case NodeTypes.ORNODE:
190: // safe
191: return new OrNodeCompiler();
192: case NodeTypes.REGEXPNODE:
193: // safe
194: return new RegexpNodeCompiler();
195: case NodeTypes.RETURNNODE:
196: // safe; throws error if non-local
197: return new ReturnNodeCompiler();
198: case NodeTypes.ROOTNODE:
199: // safe
200: return new RootNodeCompiler();
201: case NodeTypes.SELFNODE:
202: // safe
203: return new SelfNodeCompiler();
204: case NodeTypes.SPLATNODE:
205: if (SAFE)
206: throw new NotCompilableException(
207: "Can't compile node safely: " + node);
208: return new SplatNodeCompiler();
209: case NodeTypes.STRNODE:
210: // safe
211: return new StringNodeCompiler();
212: case NodeTypes.SVALUENODE:
213: if (SAFE)
214: throw new NotCompilableException(
215: "Can't compile node safely: " + node);
216: return new SValueNodeCompiler();
217: case NodeTypes.SYMBOLNODE:
218: // safe
219: return new SymbolNodeCompiler();
220: case NodeTypes.TRUENODE:
221: // safe
222: return new TrueNodeCompiler();
223: case NodeTypes.VCALLNODE:
224: // safe
225: return new VCallNodeCompiler();
226: case NodeTypes.WHILENODE:
227: // safe; things like next and closures that aren't complete yet will fail to compile
228: return new WhileNodeCompiler();
229: case NodeTypes.YIELDNODE:
230: // safe; arg types that can't be handled will fail to compile, but yield logic is correct
231: return new YieldNodeCompiler();
232: case NodeTypes.ZARRAYNODE:
233: // safe
234: return new ZArrayNodeCompiler();
235: }
236:
237: throw new NotCompilableException("Can't compile node: " + node);
238: }
239:
240: public static NodeCompiler getArgumentsCompiler(Node node) {
241: switch (node.nodeId) {
242: case NodeTypes.ARRAYNODE:
243: return new ArrayNodeArgsCompiler();
244: }
245:
246: throw new NotCompilableException(
247: "Can't compile argument node: " + node);
248: }
249:
250: public static NodeCompiler getAssignmentCompiler(Node node) {
251: switch (node.nodeId) {
252: // disabled for now; incomplete
253: //case NodeTypes.MULTIPLEASGNNODE:
254: // return new MultipleAsgnNodeAsgnCompiler();
255: }
256:
257: throw new NotCompilableException(
258: "Can't compile assignment node: " + node);
259: }
260:
261: /**
262: * Check whether the target node can safely be compiled.
263: *
264: * @param node
265: */
266: public static void confirmNodeIsSafe(Node node) {
267: switch (node.nodeId) {
268: case NodeTypes.ARGSNODE:
269: ArgsNode argsNode = (ArgsNode) node;
270: // FIXME: We can't compile cases like def(a=(b=1)) because the variables
271: // in the arg list get ordered differently than you might expect (b comes first)
272: // So the code below searches through all opt args, ensuring none of them skip
273: // indicies. A skipped index means there's a hidden local var/arg like b above
274: // and so we shouldn't try to compile.
275: if (argsNode.getOptArgs() != null
276: && argsNode.getOptArgs().size() > 0) {
277: int index = argsNode.getArgsCount() - 1;
278:
279: for (int i = 0; i < argsNode.getOptArgs().size(); i++) {
280: int newIndex = ((LocalAsgnNode) argsNode
281: .getOptArgs().get(i)).getIndex() - 2;
282:
283: if (newIndex - index != 1) {
284: throw new NotCompilableException(
285: "Can't compile def with optional args that assign other variables at: "
286: + node.getPosition());
287: }
288: index = newIndex;
289: }
290: }
291:
292: // Also do not compile anything with a block argument or "rest" argument
293: if (argsNode.getBlockArgNode() != null)
294: throw new NotCompilableException(
295: "Can't compile def with block arg at: "
296: + node.getPosition());
297: if (argsNode.getRestArg() != -1)
298: throw new NotCompilableException(
299: "Can't compile def with rest arg at: "
300: + node.getPosition());
301: break;
302: }
303: }
304: }
|