| /******************************************************************************* |
| * 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.java.compiler.impl; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.apache.sling.scripting.sightly.compiler.expression.ExpressionNode; |
| import org.apache.sling.scripting.sightly.compiler.expression.SideEffectVisitor; |
| import org.apache.sling.scripting.sightly.compiler.expression.nodes.Identifier; |
| import org.apache.sling.scripting.sightly.java.compiler.impl.operator.TypedNode; |
| |
| /** |
| * 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() |
| .objectModel().startCall(SourceGenConstants.ROM_TO_COLLECTION, true); |
| node.accept(visitor); |
| source |
| .endCall() |
| .endExpression() |
| .conditionalBranchSep() |
| .append(listCoercionVar) |
| .endExpression(); |
| } else { |
| source.objectModel().startCall(SourceGenConstants.ROM_TO_COLLECTION, true); |
| 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.objectModel().startCall(methodName, true); |
| node.accept(visitor); |
| source.endCall(); |
| } |
| |
| private static final Map<Type, String> dynamicCoercions = new HashMap<>(); |
| |
| static { |
| dynamicCoercions.put(Type.STRING, SourceGenConstants.ROM_TO_STRING); |
| dynamicCoercions.put(Type.BOOLEAN, SourceGenConstants.ROM_TO_BOOLEAN); |
| dynamicCoercions.put(Type.LONG, SourceGenConstants.ROM_TO_NUMBER); |
| dynamicCoercions.put(Type.DOUBLE, SourceGenConstants.ROM_TO_NUMBER); |
| } |
| |
| } |