package de.skuzzle.polly.core.parser.ast.lang; import java.util.Arrays; import java.util.Collection; import de.skuzzle.polly.core.parser.Position; import de.skuzzle.polly.core.parser.ast.ResolvableIdentifier; import de.skuzzle.polly.core.parser.ast.declarations.Declaration; import de.skuzzle.polly.core.parser.ast.declarations.Namespace; import de.skuzzle.polly.core.parser.ast.declarations.types.ProductType; import de.skuzzle.polly.core.parser.ast.declarations.types.Type; import de.skuzzle.polly.core.parser.ast.expressions.Expression; import de.skuzzle.polly.core.parser.ast.expressions.literals.FunctionLiteral; import de.skuzzle.polly.core.parser.ast.expressions.literals.Literal; import de.skuzzle.polly.core.parser.ast.visitor.ASTTraversalException; import de.skuzzle.polly.core.parser.ast.visitor.ExecutionVisitor; import de.skuzzle.polly.core.parser.ast.visitor.resolving.AbstractTypeResolver; import de.skuzzle.polly.tools.collections.Stack; public abstract class UnaryOperator<O extends Literal> extends Operator { protected final static ResolvableIdentifier PARAM_NAME = new ResolvableIdentifier(Position.NONE, "$param"); protected Type operandType; public UnaryOperator(OpType op) { super(op); } /** * Initializes the result- and operand types for this operator. * * @param resultType The type of the value that this operator returns. * @param operandType Type of the operand. */ protected final void initTypes(Type resultType, Type operandType) { this.addType(resultType); this.setUnique(resultType); this.operandType = operandType; } @Override protected FunctionLiteral createFunction() { Collection<Declaration> p = Arrays.asList(new Declaration[] { this.typeToParameter(this.operandType, PARAM_NAME)}); final FunctionLiteral func = new FunctionLiteral(Position.NONE, p, this); func.setUnique( new ProductType(this.operandType).mapTo(this.getUnique())); return func; } @Override public final void resolveType(Namespace ns, AbstractTypeResolver typeResolver) throws ASTTraversalException { final Expression param = ns.resolveFirst(PARAM_NAME).getExpression(); this.resolve(param, ns, typeResolver); } /** * Called to context check this operator. Default implementation does nothing. * * @param param The operand of the operator call. * @param ns The current namespace. * @param typeResolver The {@link TypeResolver}. * @throws ASTTraversalException If context checking fails. */ protected void resolve(Expression param, Namespace ns, AbstractTypeResolver typeResolver) throws ASTTraversalException { } @Override @SuppressWarnings("unchecked") public void execute(Stack<Literal> stack, Namespace ns, ExecutionVisitor execVisitor) throws ASTTraversalException { final O operand = (O) ns.resolveFirst(PARAM_NAME).getExpression(); this.exec(stack, ns, operand, operand.getPosition(), execVisitor); } /** * Called to generate the result of this operator on the stack. * * @param stack The current execution stack. * @param ns The current execution namespace. * @param operand Operand literal of this operator. * @param resultPos Position that can be used as position for the result literal. * @param execVisitor The visitor that is responsible for the execution of the AST. * @throws ASTTraversalException If executing fails for any reason. */ protected abstract void exec(Stack<Literal> stack, Namespace ns, O operand, Position resultPos, ExecutionVisitor execVisitor) throws ASTTraversalException; }