You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2014/11/14 15:05:03 UTC

svn commit: r1639641 [3/15] - in /sling/trunk/contrib/scripting/sightly: ./ engine/ engine/src/ engine/src/main/ engine/src/main/antlr4/ engine/src/main/antlr4/org/ engine/src/main/antlr4/org/apache/ engine/src/main/antlr4/org/apache/sling/ engine/src/...

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/CodeGenVisitor.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/CodeGenVisitor.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/CodeGenVisitor.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/CodeGenVisitor.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.compiled;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Stack;
+
+import org.apache.sling.scripting.sightly.api.ObjectModel;
+import org.apache.sling.scripting.sightly.compiler.api.ris.CommandVisitor;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.BufferControl;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Conditional;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Loop;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutText;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutVariable;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Procedure;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.visitor.StateControl;
+import org.apache.sling.scripting.sightly.compiler.api.ris.CommandVisitor;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutText;
+import org.apache.sling.scripting.sightly.compiler.visitor.StateControl;
+
+/**
+ * Java code generator
+ */
+class CodeGenVisitor implements CommandVisitor {
+
+    private final JavaSource source;
+    private final UnitBuilder unitBuilder;
+    private final Stack<String> loopStatusStack = new Stack<String>();
+    private final VariableAnalyzer analyzer = new VariableAnalyzer();
+    private final StateControl control;
+    private final Set<String> unitParameters;
+
+    public CodeGenVisitor(UnitBuilder unitBuilder, StateControl control) {
+        this.unitBuilder = unitBuilder;
+        this.source = unitBuilder.getSource();
+        this.control = control;
+        this.unitParameters = new HashSet<String>();
+        for (String param : unitBuilder.getParameters()) {
+            this.unitParameters.add(param.toLowerCase());
+        }
+    }
+
+    /**
+     * Complete building the source
+     */
+    public void finish() {
+        source.prepend(initializations());
+    }
+
+    private String initializations() {
+        JavaSource initSource = new JavaSource();
+        for (VariableDescriptor descriptor : analyzer.allVariables()) {
+            initVariable(descriptor, initSource);
+        }
+        return initSource.toString();
+    }
+
+    private void initVariable(VariableDescriptor descriptor, JavaSource initSource) {
+        switch (descriptor.getScope()) {
+            case DYNAMIC:
+                initSource.beginAssignment(descriptor.getAssignedName());
+                if (descriptor.isTemplateVariable()) {
+                    initSource.startCall(SourceGenConstants.OBJ_GET);
+                } else if (unitParameters.contains(descriptor.getOriginalName().toLowerCase())) {
+                    initSource.startMethodCall(SourceGenConstants.ARGUMENTS_FIELD, SourceGenConstants.BINDINGS_GET_METHOD);
+                } else {
+                    initSource.startMethodCall(SourceGenConstants.BINDINGS_FIELD, SourceGenConstants.BINDINGS_GET_METHOD);
+                }
+                initSource.stringLiteral(descriptor.getOriginalName())
+                        .endCall()
+                        .endStatement();
+                break;
+            case GLOBAL:
+                initSource.beginAssignment(descriptor.getAssignedName())
+                        .nullLiteral()
+                        .endStatement();
+                break;
+        }
+        String listCoercionVar = descriptor.getListCoercion();
+        if (listCoercionVar != null) {
+            //need to initialize the list coercion to null
+            initSource.beginAssignment(listCoercionVar, SourceGenConstants.COLLECTION_TYPE)
+                    .nullLiteral().endStatement();
+        }
+    }
+
+    @Override
+    public void visit(Conditional.Start conditional) {
+        VariableDescriptor descriptor = analyzer.descriptor(conditional.getVariable());
+        boolean negate = !conditional.getExpectedTruthValue();
+        source.beginIf();
+        if (negate) {
+            source.negation();
+        }
+        if (descriptor.getType() == Type.BOOLEAN) {
+            source.append(descriptor.getAssignedName());
+        } else {
+            source.startMethodCall(SourceGenConstants.OBJ_MODEL_INSTANCE, ObjectModel.BOOLEAN_COERCE)
+                    .append(descriptor.getAssignedName())
+                    .endCall();
+        }
+        source.completeIf();
+    }
+
+    @Override
+    public void visit(Conditional.End conditionalEnd) {
+        source.endIf();
+    }
+
+    @Override
+    public void visit(VariableBinding.Start variableBinding) {
+        source.startBlock();
+        TypeInfo typeInfo = TypeInference.inferTypes(variableBinding.getExpression(), analyzer);
+        Type type = typeInfo.typeOf(variableBinding.getExpression());
+        String properName = declare(variableBinding.getVariableName(), type);
+        source.beginAssignment(properName, type.getNativeClass());
+        ExpressionTranslator.buildExpression(
+                variableBinding.getExpression(),
+                source,
+                analyzer,
+                typeInfo);
+        source.endStatement();
+    }
+
+    @Override
+    public void visit(VariableBinding.End variableBindingEnd) {
+        VariableDescriptor descriptor = analyzer.endVariable();
+        String listCoercionVar = descriptor.getListCoercion();
+        if (listCoercionVar != null) {
+            //this variable was coerced to list at some point
+            generateCoercionClearing(listCoercionVar);
+        }
+        source.endBlock();
+    }
+
+    @Override
+    public void visit(VariableBinding.Global globalAssignment) {
+        TypeInfo typeInfo = TypeInference.inferTypes(globalAssignment.getExpression(), analyzer);
+        VariableDescriptor descriptor = analyzer.declareGlobal(globalAssignment.getVariableName());
+        String name = descriptor.getAssignedName();
+        source.append(name).assign();
+        ExpressionTranslator.buildExpression(
+                globalAssignment.getExpression(),
+                source,
+                analyzer,
+                typeInfo);
+        source.endStatement();
+        String listCoercionVar = descriptor.getListCoercion();
+        if (listCoercionVar != null) {
+            //variable was used for list coercion. Generating a coercion clearing
+            generateCoercionClearing(listCoercionVar);
+        }
+    }
+
+    @Override
+    public void visit(OutVariable outVariable) {
+        String variable = analyzer.assignedName(outVariable.getVariableName());
+        source.startStatement()
+                .startMethodCall(SourceGenConstants.OUT_BUFFER, SourceGenConstants.WRITE_METHOD)
+                .startMethodCall(SourceGenConstants.OBJ_MODEL_INSTANCE, ObjectModel.STRING_COERCE)
+                .append(variable)
+                .endCall()
+                .endCall()
+                .endStatement();
+    }
+
+    @Override
+    public void visit(OutText outText) {
+        source.startStatement()
+                .startMethodCall(SourceGenConstants.OUT_BUFFER, SourceGenConstants.WRITE_METHOD)
+                .stringLiteral(outText.getText())
+                .endCall()
+                .endStatement();
+    }
+
+    @Override
+    public void visit(Loop.Start loop) {
+        VariableDescriptor descriptor = analyzer.descriptor(loop.getListVariable());
+        String listVariable = descriptor.getAssignedName();
+        String collectionVar = descriptor.requireListCoercion();
+        source.beginIf().append(collectionVar).equality().nullLiteral().completeIf()
+                .startStatement()
+                .append(collectionVar)
+                .assign()
+                .startMethodCall(SourceGenConstants.OBJ_MODEL_INSTANCE, ObjectModel.COLLECTION_COERCE)
+                .append(listVariable)
+                .endCall()
+                .endStatement()
+                .endIf();
+        String indexVar = declare(loop.getIndexVariable(), Type.LONG);
+        source.beginAssignment(indexVar, Type.LONG.getNativeClass()).number(0).endStatement();
+        String itemVar = declare(loop.getItemVariable(), Type.UNKNOWN);
+        source.beginFor(itemVar, collectionVar);
+        loopStatusStack.push(indexVar);
+    }
+
+    @Override
+    public void visit(Loop.End loopEnd) {
+        String indexVar = loopStatusStack.pop();
+        source.startStatement().append(indexVar).increment().endStatement();
+        source.endFor();
+        analyzer.endVariable();
+        analyzer.endVariable();
+    }
+
+    @Override
+    public void visit(BufferControl.Push bufferPush) {
+        source.startStatement()
+                .startMethodCall(SourceGenConstants.OUT_BUFFER, SourceGenConstants.PUSH_BUFFER_METHOD)
+                .endCall()
+                .endStatement();
+    }
+
+    @Override
+    public void visit(BufferControl.Pop bufferPop) {
+        source.startBlock();
+        String outputVar = declare(bufferPop.getVariableName(), Type.STRING);
+        source.beginAssignment(outputVar, Type.STRING.getNativeClass())
+                .startMethodCall(SourceGenConstants.OUT_BUFFER, SourceGenConstants.POP_BUFFER_METHOD)
+                .endCall()
+                .endStatement();
+    }
+
+    @Override
+    public void visit(Procedure.Start startProcedure) {
+        UnitBuilder subTemplateUnit = unitBuilder.newSubBuilder(startProcedure.getName(), startProcedure.getParameters());
+        analyzer.declareTemplate(startProcedure.getName());
+        control.push(new CodeGenVisitor(subTemplateUnit, control));
+    }
+
+    @Override
+    public void visit(Procedure.End endProcedure) {
+        CodeGenVisitor previous = (CodeGenVisitor) control.pop();
+        previous.finish();
+    }
+
+    @Override
+    public void visit(Procedure.Call procedureCall) {
+        String templateVar = analyzer.assignedName(procedureCall.getTemplateVariable());
+        String argVar = analyzer.assignedName(procedureCall.getArgumentsVariable());
+        source.startStatement()
+                .startCall(SourceGenConstants.CALL_UNIT_METHOD, false)
+                .append(SourceGenConstants.RENDER_CONTEXT_INSTANCE)
+                .separateArgument()
+                .append(templateVar)
+                .separateArgument()
+                .append(argVar)
+                .endCall()
+                .endStatement();
+    }
+
+    private String declare(String originalName, Type type) {
+        return analyzer.declareVariable(originalName, type).getAssignedName();
+    }
+
+    private void generateCoercionClearing(String coercionVariableName) {
+        source.startStatement().append(coercionVariableName).assign().nullLiteral().endStatement();
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/CompilationOutput.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/CompilationOutput.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/CompilationOutput.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/CompilationOutput.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled;
+
+import java.util.Map;
+
+/**
+ * Result from compilation
+ */
+public class CompilationOutput {
+
+    private final String mainBody;
+    private final Map<String, CompilationOutput> subTemplates;
+
+    public CompilationOutput(String mainBody, Map<String, CompilationOutput> subTemplates) {
+        this.mainBody = mainBody;
+        this.subTemplates = subTemplates;
+    }
+
+    public String getMainBody() {
+        return mainBody;
+    }
+
+    public Map<String, CompilationOutput> getSubTemplates() {
+        return subTemplates;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/ExpressionTranslator.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/ExpressionTranslator.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/ExpressionTranslator.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/ExpressionTranslator.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.compiled;
+
+import java.util.Map;
+
+import org.apache.sling.scripting.sightly.api.ObjectModel;
+import org.apache.sling.scripting.sightly.compiled.operator.BinaryOpGen;
+import org.apache.sling.scripting.sightly.compiled.operator.Operators;
+import org.apache.sling.scripting.sightly.compiled.operator.UnaryOpGen;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.ArrayLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperation;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.BooleanConstant;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.Identifier;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.NullLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.NumericConstant;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.PropertyAccess;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.RuntimeCall;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.StringConstant;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.TernaryOperator;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.UnaryOperation;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.UnaryOperator;
+import org.apache.sling.scripting.sightly.compiler.util.expression.SideEffectVisitor;
+import org.apache.sling.scripting.sightly.api.ObjectModel;
+import org.apache.sling.scripting.sightly.compiled.operator.BinaryOpGen;
+import org.apache.sling.scripting.sightly.compiled.operator.Operators;
+import org.apache.sling.scripting.sightly.compiled.operator.UnaryOpGen;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.*;
+import org.apache.sling.scripting.sightly.compiler.util.expression.SideEffectVisitor;
+
+
+/**
+ * Builds expressions within a sling source file.
+ */
+public final class ExpressionTranslator extends SideEffectVisitor {
+
+    private final JavaSource source;
+    private final VariableAnalyzer analyzer;
+    private final TypeInfo typeInfo;
+
+    private ExpressionTranslator(JavaSource source, VariableAnalyzer analyzer, TypeInfo typeInfo) {
+        this.source = source;
+        this.analyzer = analyzer;
+        this.typeInfo= typeInfo;
+    }
+
+    public static void buildExpression(ExpressionNode node,
+                                       JavaSource source,
+                                       VariableAnalyzer analyzer,
+                                       TypeInfo typeInfo) {
+        ExpressionTranslator builder = new ExpressionTranslator(source, analyzer, typeInfo);
+        builder.traverse(node);
+    }
+
+    public void traverse(ExpressionNode node) {
+        visit(node);
+    }
+
+    private void visit(ExpressionNode node) {
+        node.accept(this);
+    }
+
+    @Override
+    public void visit(PropertyAccess propertyAccess) {
+        if (typeInfo.typeOf(propertyAccess.getTarget()) == Type.MAP) {
+            //Special optimization for maps
+            visit(propertyAccess.getTarget());
+            source.startCall(SourceGenConstants.MAP_GET, true);
+            visit(propertyAccess.getProperty());
+            source.endCall();
+        } else {
+            source.startMethodCall(SourceGenConstants.OBJ_MODEL_INSTANCE, ObjectModel.PROPERTY_ACCESS);
+            visit(propertyAccess.getTarget());
+            source.separateArgument();
+            visit(propertyAccess.getProperty());
+            source.endCall();
+        }
+    }
+
+    @Override
+    public void visit(Identifier identifier) {
+        String safeName = analyzer.assignedName(identifier.getName());
+        source.append(safeName);
+    }
+
+    @Override
+    public void visit(StringConstant text) {
+        source.stringLiteral(text.getText());
+    }
+
+    @Override
+    public void visit(BinaryOperation binaryOperation) {
+        BinaryOpGen opGen = Operators.generatorFor(binaryOperation.getOperator());
+        source.startExpression();
+        opGen.generate(source, this,
+                typeInfo.getTyped(binaryOperation.getLeftOperand()),
+                typeInfo.getTyped(binaryOperation.getRightOperand()));
+        source.endExpression();
+    }
+
+    @Override
+    public void visit(BooleanConstant booleanConstant) {
+        source.append(Boolean.toString(booleanConstant.getValue()));
+    }
+
+    @Override
+    public void visit(NumericConstant numericConstant) {
+        source.append(numericConstant.getValue().toString()); //todo: check correctness
+    }
+
+    @Override
+    public void visit(UnaryOperation unaryOperation) {
+        UnaryOperator operator = unaryOperation.getOperator();
+        ExpressionNode operand = unaryOperation.getTarget();
+        UnaryOpGen unaryOpGen = Operators.generatorFor(operator);
+        source.startExpression();
+        unaryOpGen.generate(source, this, typeInfo.getTyped(operand));
+        source.endExpression();
+    }
+
+    @Override
+    public void visit(TernaryOperator ternaryOperator) {
+        GenHelper.generateTernary(source, this,
+                typeInfo.getTyped(ternaryOperator.getCondition()),
+                typeInfo.getTyped(ternaryOperator.getThenBranch()),
+                typeInfo.getTyped(ternaryOperator.getElseBranch()));
+    }
+
+    @Override
+    public void visit(RuntimeCall runtimeCall) {
+        source.startMethodCall(SourceGenConstants.RUNTIME_INSTANCE, SourceGenConstants.RUNTIME_CALL_METHOD)
+                .stringLiteral(runtimeCall.getFunctionName());
+        for (ExpressionNode arg : runtimeCall.getArguments()) {
+            source.separateArgument();
+            visit(arg);
+        }
+        source.endCall();
+    }
+
+    @Override
+    public void visit(MapLiteral mapLiteral) {
+        source.startCall(SourceGenConstants.START_MAP_METHOD).endCall();
+        for (Map.Entry<String, ExpressionNode> entry : mapLiteral.getMap().entrySet()) {
+            source.startCall(SourceGenConstants.MAP_TYPE_ADD, true)
+                    .stringLiteral(entry.getKey())
+                    .separateArgument();
+            visit(entry.getValue());
+            source.endCall();
+        }
+    }
+
+    @Override
+    public void visit(ArrayLiteral arrayLiteral) {
+        source.startExpression().startArray();
+        boolean needsComma = false;
+        for (ExpressionNode node : arrayLiteral.getItems()) {
+            if (needsComma) {
+                source.separateArgument();
+            }
+            visit(node);
+            needsComma = true;
+        }
+        source.endArray().endExpression();
+    }
+
+    @Override
+    public void visit(NullLiteral nullLiteral) {
+        source.nullLiteral();
+    }
+
+    public VariableAnalyzer getAnalyzer() {
+        return analyzer;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/GenHelper.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/GenHelper.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/GenHelper.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/GenHelper.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.scripting.sightly.api.ObjectModel;
+import org.apache.sling.scripting.sightly.compiled.operator.TypedNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.Identifier;
+import org.apache.sling.scripting.sightly.compiler.util.expression.SideEffectVisitor;
+import org.apache.sling.scripting.sightly.api.ObjectModel;
+import org.apache.sling.scripting.sightly.compiled.operator.TypedNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.Identifier;
+import org.apache.sling.scripting.sightly.compiler.util.expression.SideEffectVisitor;
+
+/**
+ * Helper for code generation
+ */
+public class GenHelper {
+
+    public static void generateTernary(JavaSource source, SideEffectVisitor visitor,
+                                TypedNode condition, TypedNode thenBranch, TypedNode elseBranch) {
+        source.startExpression();
+        typeCoercion(source, visitor, condition, Type.BOOLEAN);
+        source.conditional();
+        thenBranch.getNode().accept(visitor);
+        source.conditionalBranchSep();
+        elseBranch.getNode().accept(visitor);
+        source.endExpression();
+    }
+
+    public static void typeCoercion(JavaSource source, SideEffectVisitor visitor, TypedNode node, Type type) {
+        if (type == node.getType() || type == Type.UNKNOWN) {
+            node.getNode().accept(visitor);
+        } else if (type == Type.LONG && node.getType() == Type.DOUBLE) {
+            callLongCoercion(source, visitor, node.getNode());
+        } else {
+            String coercionMethod = dynamicCoercions.get(type);
+            if (coercionMethod == null) {
+                throw new UnsupportedOperationException("Cannot generate coercion to type " + type);
+            }
+            callDynamicCoercion(source, visitor, node.getNode(), dynamicCoercions.get(type));
+        }
+    }
+
+    public static void listCoercion(JavaSource source, ExpressionTranslator visitor, TypedNode typedNode) {
+        ExpressionNode node = typedNode.getNode();
+        if (node instanceof Identifier) {
+            //using list coercion caching optimization
+            VariableDescriptor descriptor = visitor.getAnalyzer().descriptor(((Identifier) node).getName());
+            String listCoercionVar = descriptor.requireListCoercion();
+            source.startExpression()
+                    .append(listCoercionVar)
+                    .equality()
+                    .nullLiteral()
+                    .conditional()
+                    .startExpression()
+                    .append(listCoercionVar)
+                    .assign()
+                    .startMethodCall(SourceGenConstants.OBJ_MODEL_INSTANCE, ObjectModel.COLLECTION_COERCE);
+            node.accept(visitor);
+            source
+                    .endCall()
+                    .endExpression()
+                    .conditionalBranchSep()
+                    .append(listCoercionVar)
+                    .endExpression();
+        } else {
+            source.startMethodCall(SourceGenConstants.OBJ_MODEL_INSTANCE, ObjectModel.COLLECTION_COERCE);
+            typedNode.getNode().accept(visitor);
+            source.endCall();
+        }
+    }
+
+    private static void callLongCoercion(JavaSource source, SideEffectVisitor visitor, ExpressionNode node) {
+        source.cast(Type.LONG.getNativeClass());
+        source.startExpression();
+        node.accept(visitor);
+        source.endExpression();
+    }
+
+    private static void callDynamicCoercion(JavaSource source, SideEffectVisitor visitor, ExpressionNode node, String methodName) {
+        source.startMethodCall(SourceGenConstants.OBJ_MODEL_INSTANCE, methodName);
+        node.accept(visitor);
+        source.endCall();
+    }
+
+    private static final Map<Type, String> dynamicCoercions = new HashMap<Type, String>();
+
+    static {
+        dynamicCoercions.put(Type.STRING, ObjectModel.STRING_COERCE);
+        dynamicCoercions.put(Type.BOOLEAN, ObjectModel.BOOLEAN_COERCE);
+        dynamicCoercions.put(Type.LONG, ObjectModel.NUMERIC_COERCE);
+        dynamicCoercions.put(Type.DOUBLE, ObjectModel.NUMERIC_COERCE);
+    }
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/JavaClassBackend.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/JavaClassBackend.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/JavaClassBackend.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/JavaClassBackend.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.compiled;
+
+import org.apache.sling.scripting.sightly.compiler.CompilerBackend;
+import org.apache.sling.scripting.sightly.compiler.api.ris.CommandStream;
+import org.apache.sling.scripting.sightly.compiler.util.stream.VisitorHandler;
+import org.apache.sling.scripting.sightly.compiler.visitor.StatefulVisitor;
+import org.apache.sling.scripting.sightly.compiler.visitor.StatefulVisitor;
+
+/**
+ * Backend which generates a Java class.
+ */
+public class JavaClassBackend implements CompilerBackend {
+
+    private UnitBuilder unitBuilder = new UnitBuilder();
+
+    @Override
+    public void handle(CommandStream stream) {
+        StatefulVisitor statefulVisitor = new StatefulVisitor();
+        final CodeGenVisitor visitor = new CodeGenVisitor(unitBuilder, statefulVisitor.getControl());
+        statefulVisitor.initializeWith(visitor);
+        stream.addHandler(new VisitorHandler(statefulVisitor) {
+            @Override
+            public void onDone() {
+                super.onDone();
+                visitor.finish();
+            }
+        });
+    }
+
+    public CompilationOutput build() {
+        return this.unitBuilder.build();
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/JavaSource.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/JavaSource.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/JavaSource.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/JavaSource.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.compiled;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+/**
+ * Builder object for a Java class printing method.
+ */
+public class JavaSource {
+
+    private static final String INDENT = "    ";
+
+    private int indentLevel;
+    private final StringBuilder builder = new StringBuilder();
+
+    public JavaSource prepend(String str) {
+        builder.insert(0, str);
+        return this;
+    }
+
+    public JavaSource beginIf() {
+        indent().append("if (");
+        return this;
+    }
+
+    public JavaSource completeIf() {
+        append(") {\n");
+        incIndent();
+        return this;
+    }
+
+    public JavaSource endBlock() {
+        decIndent();
+        indent().append("}\n");
+        return this;
+    }
+
+    public JavaSource comment(String text) {
+        indent().append("//").append(text).append("\n");
+        return this;
+    }
+
+    public JavaSource assign() {
+        return append(" = ");
+    }
+
+    public JavaSource number(int value) {
+        return append(Integer.toString(value));
+    }
+
+    public JavaSource increment() {
+        return append("++");
+    }
+
+    public JavaSource beginAssignment(String variable, String type) {
+        return declare(variable, type).assign();
+    }
+
+    public JavaSource beginAssignment(String variable) {
+        return beginAssignment(variable, "Object");
+    }
+
+    public JavaSource declare(String variable, String type) {
+        return startStatement().append(type).append(" ").append(variable);
+    }
+
+    public JavaSource declare(String variable) {
+        return declare(variable, "Object");
+    }
+
+    public JavaSource equality() {
+        return append(" == ");
+    }
+
+    public JavaSource startCall(String methodName, boolean useDot) {
+        if (useDot) {
+            builder.append('.');
+        }
+        builder.append(methodName).append('(');
+        return this;
+    }
+
+    public JavaSource startCall(String methodName) {
+        return startCall(methodName, false);
+    }
+
+    public JavaSource startMethodCall(String target, String method) {
+        return append(target).startCall(method, true);
+    }
+
+    public JavaSource startArray() {
+        return append("new Object[] {");
+    }
+
+    public JavaSource endArray() {
+        return append("}");
+    }
+
+    public JavaSource startStatement() {
+        indent();
+        return this;
+    }
+
+    public JavaSource nullLiteral() {
+        return append("null");
+    }
+
+    public JavaSource separateArgument() {
+        builder.append(", ");
+        return this;
+    }
+
+    public JavaSource stringLiteral(String text) {
+        builder.append('"')
+                .append(StringEscapeUtils.escapeJava(text))
+                .append('"');
+        return this;
+    }
+
+    public JavaSource startExpression() {
+        builder.append('(');
+        return this;
+    }
+
+    public JavaSource endExpression() {
+        builder.append(')');
+        return this;
+    }
+
+    public JavaSource endCall() {
+        builder.append(')');
+        return this;
+    }
+
+    public JavaSource startBlock() {
+        indent().append("{\n");
+        incIndent();
+        return this;
+    }
+
+    public JavaSource beginFor(String itemVariable, String listVariable) {
+        startStatement()
+                .append("for (Object ")
+                .append(itemVariable)
+                .append(" : ")
+                .append(listVariable)
+                .append(") {\n");
+        incIndent();
+        return this;
+    }
+
+    public JavaSource endFor() {
+        return endBlock();
+    }
+
+    public JavaSource endIf() {
+        return endBlock();
+    }
+
+    public JavaSource beginNewInstanceCall(String className) {
+        return append("new ").append(className).append("(");
+    }
+
+    public JavaSource append(String str) {
+        builder.append(str);
+        return this;
+    }
+
+    public JavaSource endStatement() {
+        builder.append(";\n");
+        return this;
+    }
+
+    public JavaSource cast(String type) {
+        return append("(").append(type).append(")");
+    }
+
+    public JavaSource operator(String op) {
+        return append(" ").append(op).append(" ");
+    }
+
+    public JavaSource beginAnonymousInstance(String className) {
+        append("new ").append(className).append("() {\n");
+        incIndent();
+        return this;
+    }
+
+    public JavaSource endAnonymousInstance() {
+        decIndent();
+        append("}");
+        return this;
+    }
+
+    public JavaSource beginMethod(String name, String returnType) {
+        return startStatement().append("public ").append(returnType).append(" ").append(name).append("(");
+    }
+
+    public JavaSource methodParameter(String name, String type) {
+        return append(type).append(" ").append(name);
+    }
+
+    public JavaSource completeMethodSignature() {
+        append(") {\n");
+        incIndent();
+        return this;
+    }
+
+    public JavaSource endMethod() {
+        return endBlock();
+    }
+
+    public JavaSource conditional() {
+        return append(" ? ");
+    }
+
+    public JavaSource conditionalBranchSep() {
+        return append(" : ");
+    }
+
+    public JavaSource negation() {
+        return append("!");
+    }
+
+    public JavaSource newLine() {
+        return append("\n");
+    }
+
+    private StringBuilder indent() {
+        for (int i = 0; i < indentLevel; i++) {
+            builder.append(INDENT);
+        }
+        return builder;
+    }
+
+    private void incIndent() {
+        indentLevel++;
+    }
+
+    private void decIndent() {
+        indentLevel--;
+    }
+
+    @Override
+    public String toString() {
+        return builder.toString();
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/SourceGenConstants.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/SourceGenConstants.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/SourceGenConstants.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/SourceGenConstants.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.compiled;
+
+/**
+ * Names related to Java source generation.
+ */
+public class SourceGenConstants {
+
+    public static final String OUT_BUFFER = "out";
+
+    public static final String WRITE_METHOD = "write";
+
+    public static final String COLLECTION_TYPE = "Collection";
+
+    public static final String BINDINGS_FIELD = "bindings";
+
+    public static final String BINDINGS_GET_METHOD = "get";
+
+    public static final String PUSH_BUFFER_METHOD = "push";
+
+    public static final String POP_BUFFER_METHOD = "pop";
+
+    public static final String START_MAP_METHOD = "obj";
+
+    public static final String MAP_TYPE_ADD = "with";
+
+    public static final String CALL_UNIT_METHOD = "callUnit";
+
+    public static final String RENDER_CONTEXT_INSTANCE = "renderContext";
+
+    public static final String OBJ_MODEL_INSTANCE = "objectModel";
+
+    public static final String RUNTIME_INSTANCE = "runtime";
+
+    public static final String RUNTIME_CALL_METHOD = "call";
+
+    public static final String COLLECTION_LENGTH_METHOD = "size";
+
+    public static final String MAP_GET = "get";
+    public static final String TRIM_METHOD = "trim";
+    public static final String STRING_EMPTY = "isEmpty";
+    public static final String OBJ_GET = "get";
+    public static final String ARGUMENTS_FIELD = "arguments";
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/Type.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/Type.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/Type.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/Type.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled;
+
+/**
+ * Type inferred for an expression
+ */
+public enum Type {
+    UNKNOWN("Object", false),
+    STRING("String", false),
+    LONG("long", true),
+    DOUBLE("double", true),
+    BOOLEAN("boolean", true),
+    MAP("java.util.Map", false);
+
+    private final String nativeClass;
+    private final boolean isPrimitive;
+
+    Type(String nativeClass, boolean isPrimitive) {
+        this.nativeClass = nativeClass;
+        this.isPrimitive = isPrimitive;
+    }
+
+    public String getNativeClass() {
+        return nativeClass;
+    }
+
+    public boolean isPrimitive() {
+        return isPrimitive;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/TypeInference.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/TypeInference.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/TypeInference.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/TypeInference.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled;
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+import org.apache.sling.scripting.sightly.compiled.operator.BinaryOpGen;
+import org.apache.sling.scripting.sightly.compiled.operator.Operators;
+import org.apache.sling.scripting.sightly.compiled.operator.UnaryOpGen;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.NodeVisitor;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.ArrayLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperation;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.BooleanConstant;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.Identifier;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.NullLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.NumericConstant;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.PropertyAccess;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.RuntimeCall;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.StringConstant;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.TernaryOperator;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.UnaryOperation;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.UnaryOperation;
+
+/**
+ * Expression translator which uses type information
+ */
+public final class TypeInference implements NodeVisitor<Type> {
+
+    private final VariableAnalyzer analyzer;
+    private final Map<ExpressionNode, Type> inferMap = new IdentityHashMap<ExpressionNode, Type>();
+
+
+    public static TypeInfo inferTypes(ExpressionNode node, VariableAnalyzer analyzer) {
+        TypeInference typeInference = new TypeInference(analyzer);
+        typeInference.infer(node);
+        return new TypeInfo(typeInference.inferMap);
+    }
+
+    private TypeInference(VariableAnalyzer analyzer) {
+        this.analyzer = analyzer;
+    }
+
+
+
+    private Type infer(ExpressionNode node) {
+        Type type = node.accept(this);
+        inferMap.put(node, type);
+        return type;
+    }
+
+    @Override
+    public Type evaluate(PropertyAccess propertyAccess) {
+        infer(propertyAccess.getTarget());
+        infer(propertyAccess.getProperty());
+        return Type.UNKNOWN;
+    }
+
+    @Override
+    public Type evaluate(Identifier identifier) {
+        return analyzer.descriptor(identifier.getName()).getType();
+    }
+
+    @Override
+    public Type evaluate(StringConstant text) {
+        return Type.STRING;
+    }
+
+    @Override
+    public Type evaluate(BinaryOperation binaryOperation) {
+        Type leftType = infer(binaryOperation.getLeftOperand());
+        Type rightType = infer(binaryOperation.getRightOperand());
+        BinaryOpGen opGen = Operators.generatorFor(binaryOperation.getOperator());
+        return opGen.returnType(leftType, rightType);
+    }
+
+    @Override
+    public Type evaluate(BooleanConstant booleanConstant) {
+        return Type.BOOLEAN;
+    }
+
+    @Override
+    public Type evaluate(NumericConstant numericConstant) {
+        Number number = numericConstant.getValue();
+        if (number instanceof Integer || number instanceof Long) {
+            return Type.LONG;
+        }
+        if (number instanceof Float || number instanceof Double) {
+            return Type.DOUBLE;
+        }
+        return Type.UNKNOWN;
+    }
+
+    @Override
+    public Type evaluate(UnaryOperation unaryOperation) {
+        infer(unaryOperation.getTarget());
+        UnaryOpGen opGen = Operators.generatorFor(unaryOperation.getOperator());
+        return opGen.returnType(infer(unaryOperation.getTarget()));
+    }
+
+    @Override
+    public Type evaluate(TernaryOperator ternaryOperator) {
+        infer(ternaryOperator.getCondition());
+        Type thenType = infer(ternaryOperator.getThenBranch());
+        Type elseType = infer(ternaryOperator.getElseBranch());
+        if (thenType.equals(elseType)) {
+            return thenType;
+        }
+        return Type.UNKNOWN;
+    }
+
+    @Override
+    public Type evaluate(RuntimeCall runtimeCall) {
+        inferAll(runtimeCall.getArguments());
+        return Type.UNKNOWN;
+    }
+
+    @Override
+    public Type evaluate(MapLiteral mapLiteral) {
+        inferAll(mapLiteral.getMap().values());
+        return Type.MAP;
+    }
+
+    @Override
+    public Type evaluate(ArrayLiteral arrayLiteral) {
+        inferAll(arrayLiteral.getItems());
+        return Type.UNKNOWN;
+    }
+
+    @Override
+    public Type evaluate(NullLiteral nullLiteral) {
+        return Type.UNKNOWN;
+    }
+
+    private void inferAll(Iterable<ExpressionNode> nodes) {
+        for (ExpressionNode node : nodes) {
+            infer(node);
+        }
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/TypeInfo.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/TypeInfo.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/TypeInfo.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/TypeInfo.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled;
+
+import java.util.Map;
+
+import org.apache.sling.scripting.sightly.compiled.operator.TypedNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiled.operator.TypedNode;
+
+/**
+ * Provide type information for expressions
+ */
+public class TypeInfo {
+
+    private final Map<ExpressionNode, Type> typeMap;
+
+    public TypeInfo(Map<ExpressionNode, Type> typeMap) {
+        this.typeMap = typeMap;
+    }
+
+    public Type typeOf(ExpressionNode node) {
+        Type type = typeMap.get(node);
+        if (type == null) {
+            return Type.UNKNOWN;
+        }
+        return type;
+    }
+
+    public TypedNode getTyped(ExpressionNode expressionNode) {
+        return new TypedNode(expressionNode, typeOf(expressionNode));
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/UnitBuilder.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/UnitBuilder.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/UnitBuilder.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/UnitBuilder.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Builder for compiled sources
+ */
+public class UnitBuilder {
+
+    private final JavaSource source = new JavaSource();
+    private final Set<String> parameters;
+    private final Map<String, UnitBuilder> subTemplates = new HashMap<String, UnitBuilder>();
+
+    public UnitBuilder() {
+        this(Collections.<String>emptySet());
+    }
+
+    public UnitBuilder(Set<String> parameters) {
+        this.parameters = parameters;
+    }
+
+    public UnitBuilder newSubBuilder(String name, Set<String> parameters) {
+        UnitBuilder unitBuilder = new UnitBuilder(parameters);
+        subTemplates.put(name, unitBuilder);
+        return unitBuilder;
+    }
+
+    public JavaSource getSource() {
+        return source;
+    }
+
+    public Set<String> getParameters() {
+        return parameters;
+    }
+
+    public CompilationOutput build() {
+        Map<String, CompilationOutput> map = new HashMap<String, CompilationOutput>();
+        for (Map.Entry<String, UnitBuilder> entry : subTemplates.entrySet()) {
+            map.put(entry.getKey(), entry.getValue().build());
+        }
+        return new CompilationOutput(source.toString(), map);
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableAnalyzer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableAnalyzer.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableAnalyzer.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableAnalyzer.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.sling.scripting.sightly.compiler.util.VariableTracker;
+import org.apache.sling.scripting.sightly.compiler.util.VariableTracker;
+
+/**
+ * Data structure used in the analysis of variables
+ * during the compilation process
+ */
+class VariableAnalyzer {
+
+    private static final HashSet<String> javaKeywords = new HashSet<String>();
+    private final VariableTracker<VariableDescriptor> tracker = new VariableTracker<VariableDescriptor>();
+    private final List<VariableDescriptor> variables = new ArrayList<VariableDescriptor>();
+    private final HashMap<String, VariableDescriptor> dynamicVariables = new HashMap<String, VariableDescriptor>();
+    private final HashMap<String, VariableDescriptor> staticVariables = new HashMap<String, VariableDescriptor>();
+    private static final String DYNAMIC_PREFIX = "_dynamic_";
+    private static final String GLOBAL_PREFIX = "_global_";
+
+    /**
+     * Mark the declaration of a variable in the Java code
+     * @param originalName - the original name of the variable
+     * @return - a variable descriptor uniquely assigned to this variable
+     */
+    public VariableDescriptor declareVariable(String originalName, Type type) {
+        originalName = originalName.toLowerCase();
+        String assignedName = findSafeName(originalName);
+        VariableDescriptor descriptor = new VariableDescriptor(originalName, assignedName, type, VariableScope.SCOPED);
+        tracker.pushVariable(originalName, descriptor);
+        variables.add(descriptor);
+        return descriptor;
+    }
+
+    /**
+     * Declare a global variable. Redundant declarations are ignored
+     * @param originalName - the original name of the variable
+     * @return a variable descriptor
+     */
+    public VariableDescriptor declareGlobal(String originalName) {
+        originalName = originalName.toLowerCase();
+        VariableDescriptor descriptor = staticVariables.get(originalName);
+        if (descriptor == null) {
+            String assignedName = findGlobalName(originalName);
+            descriptor = new VariableDescriptor(originalName, assignedName, Type.UNKNOWN, VariableScope.GLOBAL);
+            variables.add(descriptor);
+            staticVariables.put(originalName, descriptor);
+        }
+        return descriptor;
+    }
+
+    /**
+     * Mark this variable as a template
+     * @param originalName - the original name of the variable
+     * @return a variable descriptor
+     */
+    public VariableDescriptor declareTemplate(String originalName) {
+        originalName = originalName.toLowerCase();
+        VariableDescriptor descriptor = dynamicDescriptor(originalName);
+        descriptor.markAsTemplate();
+        return descriptor;
+    }
+
+    /**
+     * Mark the end of a variable scope
+     */
+    public VariableDescriptor endVariable() {
+        VariableDescriptor descriptor = tracker.peek().getValue();
+        tracker.popVariable();
+        return descriptor;
+    }
+
+    /**
+     * Get a the descriptor for the given variable
+     * @param name the original lowerName of the variable
+     * @return the variable descriptor. If the variable is not in scope,
+     * then a dynamic variable descriptor is provided
+     */
+    public VariableDescriptor descriptor(String name) {
+        String lowerName = name.toLowerCase();
+        VariableDescriptor descriptor = tracker.get(lowerName);
+        if (descriptor == null) {
+            descriptor = staticVariables.get(lowerName);
+        }
+        if (descriptor == null) {
+            descriptor = dynamicDescriptor(lowerName);
+        }
+        return descriptor;
+    }
+
+    /**
+     * Get the collection of all the variables encountered so far
+     * @return an unmodifiable list of all the variables tracked by this analyzer
+     */
+    public Collection<VariableDescriptor> allVariables() {
+        return Collections.unmodifiableList(variables);
+    }
+
+    /**
+     * Shortcut method that returns the assigned name for the given
+     * variable
+     * @param original the original variable name
+     * @return the assigned name for this compilation process
+     */
+    public String assignedName(String original) {
+        return descriptor(original).getAssignedName();
+    }
+
+    private VariableDescriptor dynamicDescriptor(String original) {
+        VariableDescriptor descriptor = dynamicVariables.get(original);
+        if (descriptor == null) {
+            String dynamicName = findDynamicName(original);
+            descriptor = new VariableDescriptor(original, dynamicName, Type.UNKNOWN, VariableScope.DYNAMIC);
+            dynamicVariables.put(original, descriptor);
+            variables.add(descriptor);
+        }
+        return descriptor;
+    }
+
+    private String findDynamicName(String original) {
+        return DYNAMIC_PREFIX + original;
+    }
+
+    private String findGlobalName(String original) {
+        return GLOBAL_PREFIX + syntaxSafeName(original);
+    }
+
+    private String findSafeName(String original) {
+        int occurrenceCount = tracker.getOccurrenceCount(original);
+        String syntaxSafe = syntaxSafeName(original);
+        if (occurrenceCount == 0) {
+            return syntaxSafe; //no other declarations in scope. Use this very name
+        } else {
+            return original + "_" + occurrenceCount;
+        }
+    }
+
+    private String syntaxSafeName(String original) {
+        if (javaKeywords.contains(original)) {
+            return "_" + original;
+        }
+        return original.replaceAll("-", "_");
+    }
+
+    static {
+        javaKeywords.add("abstract");
+        javaKeywords.add("continue");
+        javaKeywords.add("for");
+        javaKeywords.add("new");
+        javaKeywords.add("switch");
+        javaKeywords.add("assert");
+        javaKeywords.add("default");
+        javaKeywords.add("goto");
+        javaKeywords.add("package");
+        javaKeywords.add("synchronized");
+        javaKeywords.add("boolean");
+        javaKeywords.add("do");
+        javaKeywords.add("if");
+        javaKeywords.add("private");
+        javaKeywords.add("this");
+        javaKeywords.add("break");
+        javaKeywords.add("double");
+        javaKeywords.add("implements");
+        javaKeywords.add("protected");
+        javaKeywords.add("throw");
+        javaKeywords.add("byte");
+        javaKeywords.add("else");
+        javaKeywords.add("import");
+        javaKeywords.add("public");
+        javaKeywords.add("throws");
+        javaKeywords.add("case");
+        javaKeywords.add("enum");
+        javaKeywords.add("instanceof");
+        javaKeywords.add("return");
+        javaKeywords.add("transient");
+        javaKeywords.add("catch");
+        javaKeywords.add("extends");
+        javaKeywords.add("int");
+        javaKeywords.add("short");
+        javaKeywords.add("try");
+        javaKeywords.add("char");
+        javaKeywords.add("final");
+        javaKeywords.add("interface");
+        javaKeywords.add("static");
+        javaKeywords.add("void");
+        javaKeywords.add("class");
+        javaKeywords.add("finally");
+        javaKeywords.add("long");
+        javaKeywords.add("strictfp");
+        javaKeywords.add("volatile");
+        javaKeywords.add("const");
+        javaKeywords.add("float");
+        javaKeywords.add("native");
+        javaKeywords.add("super");
+        javaKeywords.add("while");
+    }
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableDescriptor.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableDescriptor.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableDescriptor.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableDescriptor.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled;
+
+/**
+ * Information about a variable during the compilation process
+ */
+public class VariableDescriptor {
+
+    private final String originalName;
+    private final String assignedName;
+    private VariableScope scope;
+    private String listCoercion;
+    private final Type type;
+    private boolean templateVariable;
+
+    public VariableDescriptor(String originalName, String assignedName, Type type, VariableScope scope) {
+        this.originalName = originalName;
+        this.assignedName = assignedName;
+        this.scope = scope;
+        this.type = type;
+    }
+
+    /**
+     * The name of the list coercion variable
+     * @return - the variable that will hold the list coercion
+     */
+    public String requireListCoercion() {
+        if (listCoercion == null) {
+            listCoercion = assignedName + "_list_coerced$";
+        }
+        return listCoercion;
+    }
+
+    public String getListCoercion() {
+        return listCoercion;
+    }
+
+    /**
+     * Get the original name of the variable, as it was provided
+     * by the command that introduced the variable
+     * @return - the original variable name
+     */
+    public String getOriginalName() {
+        return originalName;
+    }
+
+    /**
+     * Get the assigned name for the variable - the name that will
+     * actually be used during compilation
+     * @return - the assigned variable name
+     */
+    public String getAssignedName() {
+        return assignedName;
+    }
+
+    /**
+     * Get the scope of this variable
+     * @return the variable scope
+     */
+    public VariableScope getScope() {
+        return scope;
+    }
+
+    /**
+     * Get the inferred type fot this variable
+     * @return - the class of the variable
+     */
+    public Type getType() {
+        return type;
+    }
+
+    /**
+     * Check whether this is a template variable
+     * @return true if it is a template variable
+     */
+    public boolean isTemplateVariable() {
+        return templateVariable;
+    }
+
+    /**
+     * Signal that this variable stands for a template
+     */
+    public void markAsTemplate() {
+        if (scope != VariableScope.DYNAMIC) {
+            throw new UnsupportedOperationException("Only dynamic variables can be marked as templates");
+        }
+        templateVariable = true;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableScope.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableScope.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableScope.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/VariableScope.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled;
+
+/**
+ * The scope of a variable in a Sightly script
+ */
+public enum VariableScope {
+    DYNAMIC, SCOPED, GLOBAL
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/BinaryOpGen.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/BinaryOpGen.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/BinaryOpGen.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/BinaryOpGen.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled.operator;
+
+import org.apache.sling.scripting.sightly.compiled.ExpressionTranslator;
+import org.apache.sling.scripting.sightly.compiled.JavaSource;
+import org.apache.sling.scripting.sightly.compiled.Type;
+import org.apache.sling.scripting.sightly.compiled.Type;
+
+/**
+ * Generator for a binary operator
+ */
+public interface BinaryOpGen {
+
+    Type returnType(Type leftType, Type rightType);
+
+    void generate(JavaSource source, ExpressionTranslator visitor, TypedNode left, TypedNode right);
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/ComparisonOpGen.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/ComparisonOpGen.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/ComparisonOpGen.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/ComparisonOpGen.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled.operator;
+
+import org.apache.sling.scripting.sightly.api.ObjectModel;
+import org.apache.sling.scripting.sightly.compiled.ExpressionTranslator;
+import org.apache.sling.scripting.sightly.compiled.JavaSource;
+import org.apache.sling.scripting.sightly.compiled.SourceGenConstants;
+import org.apache.sling.scripting.sightly.compiled.Type;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperator;
+import org.apache.sling.scripting.sightly.compiler.util.expression.SideEffectVisitor;
+import org.apache.sling.scripting.sightly.compiled.SourceGenConstants;
+
+/**
+ * Generator for logical operators
+ */
+public class ComparisonOpGen implements BinaryOpGen {
+
+    private final String javaOperator;
+    private final boolean inverted;
+    private final String runtimeMethod;
+
+    public ComparisonOpGen(BinaryOperator operator) {
+        switch (operator) {
+            case LT: runtimeMethod = ObjectModel.LT; inverted = false; javaOperator = "<"; break;
+            case GT: runtimeMethod = ObjectModel.LEQ; inverted = true; javaOperator = ">"; break;
+            case LEQ: runtimeMethod = ObjectModel.LEQ; inverted = false; javaOperator = "<="; break;
+            case GEQ: runtimeMethod = ObjectModel.LT; inverted = true; javaOperator = ">="; break;
+            default: throw new IllegalArgumentException("Operator is not a comparison operator: " + operator);
+        }
+    }
+
+    @Override
+    public Type returnType(Type left, Type right) {
+        return Type.BOOLEAN;
+    }
+
+    @Override
+    public void generate(JavaSource source, ExpressionTranslator visitor, TypedNode left, TypedNode right) {
+        Type type = OpHelper.sameType(left, right);
+        if (OpHelper.isNumericType(type)) {
+            generateWithOperator(source, visitor, left.getNode(), right.getNode());
+        } else {
+            generateGeneric(source, visitor, left.getNode(), right.getNode());
+        }
+    }
+
+    private void generateGeneric(JavaSource source, SideEffectVisitor visitor, ExpressionNode leftNode, ExpressionNode rightNode) {
+        if (inverted) {
+            source.negation().startExpression();
+        }
+        source.startMethodCall(SourceGenConstants.OBJ_MODEL_INSTANCE, runtimeMethod);
+        leftNode.accept(visitor);
+        source.separateArgument();
+        rightNode.accept(visitor);
+        source.endCall();
+        if (inverted) {
+            source.endExpression();
+        }
+    }
+
+    private void generateWithOperator(JavaSource source, SideEffectVisitor visitor,
+                                      ExpressionNode leftNode, ExpressionNode rightNode) {
+        leftNode.accept(visitor);
+        source.append(javaOperator);
+        rightNode.accept(visitor);
+    }
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/ConcatenateOpGen.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/ConcatenateOpGen.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/ConcatenateOpGen.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/ConcatenateOpGen.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled.operator;
+
+import org.apache.sling.scripting.sightly.compiled.ExpressionTranslator;
+import org.apache.sling.scripting.sightly.compiled.GenHelper;
+import org.apache.sling.scripting.sightly.compiled.JavaSource;
+import org.apache.sling.scripting.sightly.compiled.Type;
+
+/**
+ * Concatenation operator generation
+ */
+public final class ConcatenateOpGen implements BinaryOpGen {
+
+    public static final ConcatenateOpGen INSTANCE = new ConcatenateOpGen();
+
+    private ConcatenateOpGen() {
+    }
+
+    @Override
+    public Type returnType(Type leftType, Type rightType) {
+        return Type.STRING;
+    }
+
+    @Override
+    public void generate(JavaSource source, ExpressionTranslator visitor, TypedNode left, TypedNode right) {
+        GenHelper.typeCoercion(source, visitor, left, Type.STRING);
+        source.append("+");
+        GenHelper.typeCoercion(source, visitor, right, Type.STRING);
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/EquivalenceOpGen.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/EquivalenceOpGen.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/EquivalenceOpGen.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/compiled/operator/EquivalenceOpGen.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.compiled.operator;
+
+import org.apache.sling.scripting.sightly.compiled.ExpressionTranslator;
+import org.apache.sling.scripting.sightly.compiled.JavaSource;
+import org.apache.sling.scripting.sightly.compiled.Type;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.util.expression.SideEffectVisitor;
+
+/**
+ * Generator for logical operators
+ */
+public class EquivalenceOpGen implements BinaryOpGen {
+
+    private final boolean negated;
+
+    public EquivalenceOpGen(boolean negated) {
+        this.negated = negated;
+    }
+
+    @Override
+    public Type returnType(Type left, Type right) {
+        return Type.BOOLEAN;
+    }
+
+    @Override
+    public void generate(JavaSource source, ExpressionTranslator visitor, TypedNode left, TypedNode right) {
+        Type type = OpHelper.sameType(left, right);
+        if (type != null && OpHelper.isNumericType(type) || type == Type.BOOLEAN) {
+            generateEqualsOperator(source, visitor, left.getNode(), right.getNode());
+        } else if (type != Type.UNKNOWN) {
+            generateEqualsMethod(source, visitor, left, right);
+        } else {
+            generateCheckedEquals(source, visitor, left, right);
+        }
+    }
+
+    private void generateCheckedEquals(JavaSource source, SideEffectVisitor visitor, TypedNode leftNode, TypedNode rightNode) {
+        source.startExpression();
+        leftNode.getNode().accept(visitor);
+        source.equality().nullLiteral().conditional();
+        rightNode.getNode().accept(visitor);
+        source.equality().nullLiteral();
+        source.conditionalBranchSep();
+        generateEqualsMethod(source, visitor, leftNode, rightNode);
+    }
+
+    private void generateEqualsMethod(JavaSource source, SideEffectVisitor visitor, TypedNode leftNode, TypedNode rightNode) {
+        boolean performCast = leftNode.getType().isPrimitive();
+        if (performCast) {
+            source.startExpression();
+            source.cast(Type.UNKNOWN.getNativeClass());
+        }
+        leftNode.getNode().accept(visitor);
+        if (performCast) {
+            source.endExpression();
+        }
+        source.startCall("equals", true);
+        rightNode.getNode().accept(visitor);
+        source.endCall();
+    }
+
+    private void generateEqualsOperator(JavaSource source, SideEffectVisitor visitor, ExpressionNode leftNode, ExpressionNode rightNode) {
+        leftNode.accept(visitor);
+        source.append(operator());
+        rightNode.accept(visitor);
+    }
+
+    private String operator() {
+        return (negated) ? "!=" : "==";
+    }
+
+}