com.synflow.core.transformations.AbstractExpressionTransformer.java Source code

Java tutorial

Introduction

Here is the source code for com.synflow.core.transformations.AbstractExpressionTransformer.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Synflow SAS.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Matthieu Wipliez - initial API and implementation and/or initial documentation
 *******************************************************************************/
package com.synflow.core.transformations;

import java.util.Iterator;

import org.eclipse.emf.common.util.EList;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.synflow.models.ir.ExprBinary;
import com.synflow.models.ir.ExprList;
import com.synflow.models.ir.ExprResize;
import com.synflow.models.ir.ExprTypeConv;
import com.synflow.models.ir.ExprUnary;
import com.synflow.models.ir.Expression;
import com.synflow.models.ir.Procedure;
import com.synflow.models.ir.Type;
import com.synflow.models.ir.util.IrSwitch;
import com.synflow.models.ir.util.TypeUtil;

/**
 * This interface defines an IR visitor that transforms expressions to match the type system of the
 * target code.
 * 
 * @author Matthieu Wipliez
 * 
 */
public abstract class AbstractExpressionTransformer extends IrSwitch<Expression> {

    private Procedure procedure;

    private Type target;

    @Override
    public Expression caseExprBinary(ExprBinary expr) {
        Type parent = TypeUtil.getType(expr);
        expr.setE1(transform(parent, expr.getE1()));
        expr.setE2(transform(parent, expr.getE2()));
        return expr;
    }

    @Override
    public Expression caseExpression(Expression expr) {
        return expr;
    }

    @Override
    public Expression caseExprList(ExprList expr) {
        visitExprList(expr.getValue());
        return expr;
    }

    @Override
    public Expression caseExprResize(ExprResize resize) {
        Type type = TypeUtil.getType(resize);
        resize.setExpr(transform(type, resize.getExpr()));
        return resize;
    }

    @Override
    public Expression caseExprTypeConv(ExprTypeConv typeConv) {
        Type type = TypeUtil.getType(typeConv);
        typeConv.setExpr(transform(type, typeConv.getExpr()));
        return typeConv;
    }

    @Override
    public Expression caseExprUnary(ExprUnary expr) {
        expr.setExpr(transform(getTarget(), expr.getExpr()));
        return expr;
    }

    protected Procedure getProcedure() {
        return procedure;
    }

    protected Type getTarget() {
        return target;
    }

    public void setProcedure(Procedure procedure) {
        this.procedure = procedure;
    }

    public Expression transform(Type target, Expression expression) {
        Type oldTarget = this.target;
        this.target = target;
        Expression result = doSwitch(expression);
        this.target = oldTarget;
        return result;
    }

    private void visitExprList(EList<Expression> indexes) {
        visitExprList(Functions.constant(target), indexes);
    }

    private void visitExprList(Function<Object, Type> fun, EList<Expression> indexes) {
        int i = 0;
        while (i < indexes.size()) {
            final Expression expr = indexes.get(i);
            final Expression res = transform(fun.apply(null), expr);
            if (res != expr) {
                // remove expr (expr may already have been removed if it is contained in res)
                indexes.remove(expr);

                // add res to the list
                // we need to use "add" and not "set" because "expr" was removed from the list
                // so the list might not be big enough
                indexes.add(i, res);
            }
            i++;
        }
    }

    protected void visitExprList(Iterable<? extends Type> types, EList<Expression> indexes) {
        final Iterator<? extends Type> it = types.iterator();
        visitExprList(new Function<Object, Type>() {
            @Override
            public Type apply(Object arg0) {
                return it.next();
            }
        }, indexes);
    }

}