Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   ***** BEGIN LICENSE BLOCK *****
   * Version: EPL 1.0/GPL 2.0/LGPL 2.1
   *
   * The contents of this file are subject to the Eclipse Public
   * License Version 1.0 (the "License"); you may not use this file
   * except in compliance with the License. You may obtain a copy of
   * the License at http://www.eclipse.org/legal/epl-v10.html
   *
  * Software distributed under the License is distributed on an "AS
  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  * implied. See the License for the specific language governing
  * rights and limitations under the License.
  *
  * Copyright (C) 2006 Charles O Nutter <headius@headius.com>
  *  
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the EPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the EPL, the GPL or the LGPL.
  ***** END LICENSE BLOCK *****/
 
 package org.jruby.compiler;
 

Author(s):
headius
 
 public class ASTCompiler19 extends ASTCompiler {
     @Override
     protected boolean is1_9() {
         return true;
     }
     
     @Override
     public void compile(Node nodeBodyCompiler contextboolean expr) {
         if (node == null) {
             if (exprcontext.loadNil();
             return;
         }
         switch (node.getNodeType()) {
         case :
             compileEncoding(nodecontextexpr);
             break;
         case :
             compileLambda(nodecontextexpr);
             break;
         case :
             compileMultipleAsgn19(nodecontextexpr);
             break;
         default:
             super.compile(nodecontextexpr);
         }
     }
 
     @Override
     public void compileArgs(Node nodeBodyCompiler contextboolean expr) {
         final ArgsNode argsNode = (ArgsNodenode;
 
         final int required = argsNode.getRequiredArgsCount();
         final int opt = argsNode.getOptionalArgsCount();
         final int rest = argsNode.getRestArg();
         
        context.getVariableCompiler().checkMethodArity(requiredoptrest);
        compileMethodArgs(nodecontextexpr);
    }
    @Override
    public void compileAssignment(Node nodeBodyCompiler context) {
        switch (node.getNodeType()) {
            case :
                compileMultipleAsgn19Assignment(nodecontextfalse);
                break;
            default:
                super.compileAssignment(nodecontext);
        }
    }
    @Override
    protected void compileDefinedAndOrDStrDRegexp(final Node nodeBodyCompiler context) {
    }
    @Override
    protected void compileDefinedBackref(final Node nodeBodyCompiler context) {
        context.backref();
        context.isInstanceOf(RubyMatchData.class,
                new BranchCallback() {
                    public void branch(BodyCompiler context) {
                        context.pushDefinedMessage(.);
                    }
                },
                new BranchCallback() {
                    public void branch(BodyCompiler context) {
                        context.pushNull();
                    }
                });
    }
    @Override
    protected void compileDefinedDVar(final Node nodeBodyCompiler context) {
    }
    @Override
    protected void compileDefinedNthref(final Node nodeBodyCompiler context) {
        context.isCaptured(((NthRefNodenode).getMatchNumber(),
                new BranchCallback() {
                    public void branch(BodyCompiler context) {
                        context.pushDefinedMessage(.);
                    }
                },
                new BranchCallback() {
                    public void branch(BodyCompiler context) {
                        context.pushNull();
                    }
                });
    }
    public void compileMethodArgs(Node nodeBodyCompiler contextboolean expr) {
        final ArgsNode argsNode = (ArgsNodenode;
        
        if (argsNode.getKeyRest() != null || argsNode.getKeywords() != null) {
            throw new NotCompilableException("keyword args not supported in JIT yet: " + argsNode);
        }
        final int required = argsNode.getRequiredArgsCount();
        final int opt = argsNode.getOptionalArgsCount();
        final int rest = argsNode.getRestArg();
        ArrayCallback requiredAssignment = null;
        ArrayCallback optionalGiven = null;
        ArrayCallback optionalNotGiven = null;
        CompilerCallback restAssignment = null;
        CompilerCallback blockAssignment = null;
        if (required > 0) {
            requiredAssignment = new ArrayCallback() {
                public void nextValue(BodyCompiler contextObject objectint index) {
                    ArrayNode arguments = (ArrayNode)object;
                    Node argNode = arguments.get(index);
                    switch (argNode.getNodeType()) {
                    case :
                        int varIndex = ((ArgumentNode)argNode).getIndex();
                        context.getVariableCompiler().assignLocalVariable(varIndexfalse);
                        break;
                    case :
                        compileMultipleAsgn19Assignment(argNodecontextfalse);
                        break;
                    default:
                        throw new NotCompilableException("unknown argument type: " + argNode);
                    }
                }
            };
        }
        if (opt > 0) {
            optionalGiven = new ArrayCallback() {
            public void nextValue(BodyCompiler contextObject objectint index) {
                    OptArgNode optArg = (OptArgNode)((ListNodeobject).get(index);
                    compileAssignment(optArg.getValue(), context);
                }
            };
            optionalNotGiven = new ArrayCallback() {
                public void nextValue(BodyCompiler contextObject objectint index) {
                    OptArgNode optArg = (OptArgNode)((ListNodeobject).get(index);
                    compile(optArg.getValue(), contextfalse);
                }
            };
        }
        if (rest > -1) {
            restAssignment = new CompilerCallback() {
                public void call(BodyCompiler context) {
                    context.getVariableCompiler().assignLocalVariable(argsNode.getRestArg(), false);
                }
            };
        }
        if (argsNode.getBlock() != null) {
            blockAssignment = new CompilerCallback() {
                public void call(BodyCompiler context) {
                    context.getVariableCompiler().assignLocalVariable(argsNode.getBlock().getCount(), false);
                }
            };
        }
                argsNode.getPre(),
                argsNode.getPreCount(),
                argsNode.getPost(),
                argsNode.getPostCount(),
                argsNode.getPostIndex(),
                argsNode.getOptArgs(),
                argsNode.getOptionalArgsCount(),
                requiredAssignment,
                optionalGiven,
                optionalNotGiven,
                restAssignment,
                blockAssignment);
        // TODO: don't require pop
        if (!exprcontext.consumeCurrentValue();
    }
    @Override
    public void compileArgsPush(Node nodeBodyCompiler contextboolean expr) {
        ArgsPushNode argsPush = (ArgsPushNodenode;
        compile(argsPush.getFirstNode(), context,true);
        compile(argsPush.getSecondNode(), context,true);
        context.argsPush();
        // TODO: don't require pop
        if (!exprcontext.consumeCurrentValue();
    }
    public void compileEncoding(Node nodeBodyCompiler contextboolean expr) {
        final EncodingNode encodingNode = (EncodingNode)node;
        if (expr) {
            context.loadEncoding(encodingNode.getEncoding());
        }
    }
    @Override
    public void compileIter(Node nodeBodyCompiler context) {
        final IterNode iterNode = (IterNode)node;
        final ArgsNode argsNode = (ArgsNode)iterNode.getVarNode();
        // create the closure class and instantiate it
        final CompilerCallback closureBody = new CompilerCallback() {
            public void call(BodyCompiler context) {
                if (iterNode.getBodyNode() != null) {
                    compile(iterNode.getBodyNode(), contexttrue);
                } else {
                    context.loadNil();
                }
            }
        };
        // create the closure class and instantiate it
        final CompilerCallback closureArgs = new CompilerCallback() {
            public void call(BodyCompiler context) {
                // FIXME: This is temporary since the variable compilers assume we want
                // args already on stack for assignment. We just pop and continue with
                // 1.9 args logic.
                context.consumeCurrentValue(); // args value
                context.consumeCurrentValue(); // passed block
                if (iterNode.getVarNode() != null) {
                    if (iterNode instanceof LambdaNode) {
                        final int required = argsNode.getRequiredArgsCount();
                        final int opt = argsNode.getOptionalArgsCount();
                        final int rest = argsNode.getRestArg();
                        context.getVariableCompiler().checkMethodArity(requiredoptrest);
                        compileMethodArgs(argsNodecontexttrue);
                    } else {
                        compileMethodArgs(argsNodecontexttrue);
                    }
                }
            }
        };
        boolean hasMultipleArgsHead = false;
        if (iterNode.getVarNode() instanceof MultipleAsgnNode) {
            hasMultipleArgsHead = ((MultipleAsgnNodeiterNode.getVarNode()).getHeadNode() != null;
        }
        NodeType argsNodeId = BlockBody.getArgumentTypeWackyHack(iterNode);
        ASTInspector inspector = new ASTInspector();
        inspector.inspect(iterNode.getBodyNode());
        inspector.inspect(iterNode.getVarNode());
        if (argsNodeId == null) {
            // no args, do not pass args processor
            context.createNewClosure19(iterNode.getPosition().getFile(), iterNode.getPosition().getStartLine(), iterNode.getScope(), Arity.procArityOf(iterNode.getVarNode()).getValue(),
                    closureBodynullhasMultipleArgsHeadargsNodeId, Helpers.encodeParameterList(argsNode), inspector);
        } else {
            context.createNewClosure19(iterNode.getPosition().getFile(), iterNode.getPosition().getStartLine(), iterNode.getScope(), Arity.procArityOf(iterNode.getVarNode()).getValue(),
                    closureBodyclosureArgshasMultipleArgsHeadargsNodeId, Helpers.encodeParameterList(argsNode), inspector);
        }
    }
    public void compileLambda(Node nodeBodyCompiler contextboolean expr) {
        final LambdaNode lambdaNode = (LambdaNode)node;
        if (expr) {
            context.createNewLambda(new CompilerCallback() {
                public void call(BodyCompiler context) {
                    compileIter(lambdaNodecontext);
                }
            });
        }
    }
    public void compileMultipleAsgn19(Node nodeBodyCompiler contextboolean expr) {
        MultipleAsgn19Node multipleAsgn19Node = (MultipleAsgn19Nodenode;
        if (expr) {
            // need the array, use unoptz version
            compileUnoptimizedMultipleAsgn19(multipleAsgn19Nodecontextexpr);
        } else {
            // try optz version
            compileOptimizedMultipleAsgn19(multipleAsgn19Nodecontextexpr);
        }
    }
    private void compileOptimizedMultipleAsgn19(MultipleAsgn19Node multipleAsgn19NodeBodyCompiler contextboolean expr) {
        // expect value to be an array of nodes
        if (multipleAsgn19Node.getValueNode() instanceof ArrayNode) {
            // head must not be null and there must be no "args" (like *arg)
            if (multipleAsgn19Node.getPreCount() > 0 && multipleAsgn19Node.getPostCount() == 0 && multipleAsgn19Node.getRest() == null) {
                // sizes must match
                if (multipleAsgn19Node.getPreCount() == ((ArrayNode)multipleAsgn19Node.getValueNode()).size()) {
                    // "head" must have no non-trivial assigns (array groupings, basically)
                    boolean normalAssigns = true;
                    for (Node asgn : multipleAsgn19Node.getPre().childNodes()) {
                        if (asgn instanceof ListNode) {
                            normalAssigns = false;
                            break;
                        }
                    }
                    if (normalAssigns) {
                        // only supports simple parallel assignment of up to 4 values to the same number of assignees
                        int size = multipleAsgn19Node.getPreCount();
                        if (size >= 2 && size <= 10) {
                            ArrayNode values = (ArrayNode)multipleAsgn19Node.getValueNode();
                            for (Node value : values.childNodes()) {
                                compile(valuecontexttrue);
                            }
                            context.reverseValues(size);
                            for (Node asgn : multipleAsgn19Node.getPre().childNodes()) {
                                compileAssignment(asgncontext);
                            }
                            return;
                        }
                    }
                }
            }
        }
        // if we get here, no optz cases work; fall back on unoptz.
        compileUnoptimizedMultipleAsgn19(multipleAsgn19Nodecontextexpr);
    }
    private void compileUnoptimizedMultipleAsgn19(MultipleAsgn19Node multipleAsgn19NodeBodyCompiler contextboolean expr) {
        compile(multipleAsgn19Node.getValueNode(), contexttrue);
        compileMultipleAsgn19Assignment(multipleAsgn19Nodecontextexpr);
    }
    public void compileMultipleAsgn19Assignment(Node nodeBodyCompiler contextboolean expr) {
        final MultipleAsgn19Node multipleAsgn19Node = (MultipleAsgn19Nodenode;
        // normal items at the front or back of the masgn
        ArrayCallback prePostAssignCallback = new ArrayCallback() {
                    public void nextValue(BodyCompiler contextObject sourceArray,
                            int index) {
                        ListNode nodes = (ListNodesourceArray;
                        Node assignNode = nodes.get(index);
                        // perform assignment for the next node
                        compileAssignment(assignNodecontext);
                    }
                };
        CompilerCallback restCallback = new CompilerCallback() {
                    public void call(BodyCompiler context) {
                        Node argsNode = multipleAsgn19Node.getRest();
                        if (argsNode instanceof StarNode) {
                            // done processing args
                            context.consumeCurrentValue();
                        } else {
                            // assign to appropriate variable
                            compileAssignment(argsNodecontext);
                        }
                    }
                };
        if (multipleAsgn19Node.getPreCount() == 0 && multipleAsgn19Node.getPostCount() == 0) {
            if (multipleAsgn19Node.getRest() == null) {
                throw new NotCompilableException("Something's wrong, multiple assignment with no head or args at: " + multipleAsgn19Node.getPosition());
            } else {
                if (multipleAsgn19Node.getRest() instanceof StarNode) {
                    // do nothing
                } else {
                    context.ensureMultipleAssignableRubyArray(multipleAsgn19Node.getPreCount() != 0 || multipleAsgn19Node.getPostCount() != 0);
                    context.forEachInValueArray(0, 0, nullnullrestCallback);
                }
            }
        } else {
            context.ensureMultipleAssignableRubyArray(multipleAsgn19Node.getPreCount() != 0 || multipleAsgn19Node.getPostCount() != 0);
            if (multipleAsgn19Node.getRest() == null) {
                context.forEachInValueArray(0, multipleAsgn19Node.getPreCount(), multipleAsgn19Node.getPre(), multipleAsgn19Node.getPostCount(), multipleAsgn19Node.getPost(), prePostAssignCallbacknull);
            } else {
                context.forEachInValueArray(0, multipleAsgn19Node.getPreCount(), multipleAsgn19Node.getPre(), multipleAsgn19Node.getPostCount(), multipleAsgn19Node.getPost(), prePostAssignCallbackrestCallback);
            }
        }
        // TODO: don't require pop
        if (!exprcontext.consumeCurrentValue();
    }
    
    @Override
    public void compileHash(Node nodeBodyCompiler contextboolean expr) {
        compileHashCommon((Hash19Nodenodecontextexpr);
    }
    
    @Override
    protected void createNewHash(BodyCompiler contextHashNode hashNodeArrayCallback hashCallback) {
        context.createNewHash19(hashNode.getListNode(), hashCallbackhashNode.getListNode().size() / 2);
    }
    public void compileMatch2(Node nodeBodyCompiler contextboolean expr) {
        if (!(node instanceof Match2CaptureNode)) {
            super.compileMatch2(nodecontextexpr);
            return;
        }
        // match with capture logic
        final Match2CaptureNode matchNode = (Match2CaptureNodenode;
        compile(matchNode.getReceiverNode(), context,true);
        CompilerCallback value = new CompilerCallback() {
            public void call(BodyCompiler context) {
                compile(matchNode.getValueNode(), context,true);
            }
        };
        context.match2Capture(valuematchNode.getScopeOffsets(), true);
        // TODO: don't require pop
        if (!exprcontext.consumeCurrentValue();
    }
    @Override
    public void compileSValue(Node nodeBodyCompiler contextboolean expr) {
        SValue19Node svalueNode = (SValue19Node)node;
        compile(svalueNode.getValue(), context,true);
        context.singlifySplattedValue19();
        // TODO: don't require pop
        if (!exprcontext.consumeCurrentValue();
    }
    @Override
    protected void splatCurrentValue(BodyCompiler context) {
        context.splatCurrentValue("splatValue19");
    }
    @Override
    public void compileArgsCatArguments(Node nodeBodyCompiler contextboolean expr) {
        ArgsCatNode argsCatNode = (ArgsCatNodenode;
        // arguments compilers always create IRubyObject[], but since we then combine
        // with another IRubyObject[] from coercing second node to array, this can
        // be inefficient. Escape analysis may help, though.
        compileArguments(argsCatNode.getFirstNode(), context);
        compile(argsCatNode.getSecondNode(), context,true);
        context.argsCatToArguments19();
        
        // TODO: don't require pop
        if (!exprcontext.consumeCurrentValue();
    }
    @Override
    public void compileSplatArguments(Node nodeBodyCompiler contextboolean expr) {
        SplatNode splatNode = (SplatNodenode;
        compile(splatNode.getValue(), context,true);
        context.splatToArguments19();
        // TODO: don't require pop
        if (!exprcontext.consumeCurrentValue();
    }
    public void compileDRegexp(Node nodeBodyCompiler contextboolean expr) {
        final DRegexpNode dregexpNode = (DRegexpNodenode;
        ArrayCallback dElementsCallback = new ArrayCallback() {
            public void nextValue(BodyCompiler contextObject sourceArrayint index) {
                compile((Node)((Object[])sourceArray)[index], contexttrue);
            }
        };
        if (expr) {
            context.createDRegexp19(dElementsCallbackdregexpNode.childNodes().toArray(), dregexpNode.getOptions().toEmbeddedOptions());
        } else {
            // not an expression, only compile the elements
            for (Node nextNode : dregexpNode.childNodes()) {
                compile(nextNodecontextfalse);
            }
        }
    }
    @Override
    public void compileYield(Node nodeBodyCompiler contextboolean expr) {
        if (!(node instanceof Yield19Node)) {
            super.compileYield(nodecontextexpr);
            return;
        }
        final Yield19Node yieldNode = (Yield19Nodenode;
        CompilerCallback argsCallback = new CompilerCallback() {
            public void call(BodyCompiler context) {
                compile(yieldNode.getArgsNode(), context,true);
            }
        };
        boolean unsplat = false;
        switch (yieldNode.getArgsNode().getNodeType()) {
            case :
            case :
            case :
                unsplat = true;
                break;
        }
        context.getInvocationCompiler().yield19(argsCallbackunsplat);
        // TODO: don't require pop
        if (!exprcontext.consumeCurrentValue();
    }
New to GrepCode? Check out our FAQ X