com.synflow.cx.internal.compiler.ActorBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.synflow.cx.internal.compiler.ActorBuilder.java

Source

/*******************************************************************************
 * Copyright (c) 2013 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.cx.internal.compiler;

import static com.synflow.models.ir.IrFactory.eINSTANCE;

import java.util.List;

import org.eclipse.emf.ecore.EObject;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.synflow.cx.cx.VarRef;
import com.synflow.cx.instantiation.IInstantiator;
import com.synflow.cx.internal.compiler.helpers.AvailableRemover;
import com.synflow.cx.internal.services.Typer;
import com.synflow.models.dpn.Actor;
import com.synflow.models.dpn.Port;
import com.synflow.models.dpn.Transition;
import com.synflow.models.ir.Expression;
import com.synflow.models.ir.IrFactory;
import com.synflow.models.ir.OpBinary;
import com.synflow.models.ir.Type;
import com.synflow.models.ir.Var;

/**
 * This class defines a dataflow builder that inherits from the IR builder.
 * 
 * @author Matthieu Wipliez
 * 
 */
public class ActorBuilder extends IrBuilder {

    private ImmutableSet<String> existingSet;

    private boolean ignoreWrites;

    protected Integer line;

    private Transition transition;

    public ActorBuilder(IInstantiator instantiator, Typer typer, Actor actor) {
        super(instantiator, typer, actor);

        existingSet = ImmutableSet.copyOf(
                Iterables.transform(Iterables.concat(actor.getInputs(), actor.getOutputs(), actor.getVariables()),
                        new Function<Var, String>() {
                            @Override
                            public String apply(Var var) {
                                return var.getName();
                            }
                        }));
    }

    /**
     * Creates the body of the action associated with the given transition info. This method simply
     * uses the transformer to visit the objects associated with the info's body.
     * 
     * @param info
     *            transition info
     */
    private void createBody() {
        // use the 'body' procedure
        setProcedure(transition.getAction().getBody());
        for (EObject eObject : transition.getBody()) {
            transformer.doSwitch(eObject);
        }
    }

    /**
     * Creates the scheduler of the action associated with the given transition info.
     * 
     * @param info
     *            transition info
     */
    private void createScheduler() {
        // use the 'scheduler' procedure
        setProcedure(transition.getAction().getScheduler());

        // translate statements and condition
        ignoreWrites = true;
        Expression expr = null;
        List<EObject> eObjects = transition.getScheduler();
        for (EObject eObject : eObjects) {
            // translate object
            EObject irObject = transformer.doSwitch(eObject);
            if (irObject instanceof Expression) {
                expr = translateCondition(expr, (Expression) irObject);
            }
        }
        ignoreWrites = false;

        // adds a return if the expression is not null
        if (expr == null) {
            expr = IrFactory.eINSTANCE.createExprBool(true);
        }
        add(eINSTANCE.createInstReturn(expr));
    }

    /**
     * This overrides IrBuilder's implementation by also looking into an existing set of names
     * (including ports, state variables).
     */
    @Override
    public final Var createVar(int lineNumber, Type type, String hint) {
        String name = hint;
        boolean existing = existingSet.contains(name);
        int i = 0;
        while (existing) {
            name = hint + i;
            existing = existingSet.contains(name);
            i++;
        }

        return super.createVar(lineNumber, type, name);
    }

    final Actor getActor() {
        return (Actor) entity;
    }

    /**
     * Returns the IR port that corresponds to the given variable reference.
     * 
     * @param ref
     *            a variable reference
     * @return an IR port
     */
    public Port getPort(VarRef ref) {
        return instantiator.getPort(entity, ref);
    }

    /**
     * Returns true if writes should be ignored, which is the case when translating the scheduler.
     * 
     * @return
     */
    public boolean ignoreWrites() {
        return ignoreWrites;
    }

    private Expression translateCondition(Expression expr, Expression condition) {
        // remove calls to available
        condition = new AvailableRemover().visit(condition);
        if (condition == null) {
            return expr;
        }

        // assign to new 'cond' variable
        Var condVar = createVar(0, eINSTANCE.createTypeBool(), "cond");
        add(eINSTANCE.createInstAssign(condVar, condition));
        Expression cond = eINSTANCE.createExprVar(condVar);

        if (expr == null) {
            return cond;
        } else {
            return eINSTANCE.createExprBinary(expr, OpBinary.LOGIC_AND, cond);
        }
    }

    final void updateLineInfo(int lineNumber) {
        if (line == null) {
            transition.getLines().add(lineNumber);
        } else {
            transition.getLines().add(line);
        }
    }

    /**
     * Visits the given transition and creates the IR of the action associated with it.
     * 
     * @param transition
     *            a transition
     */
    public void visitTransition(Transition transition) {
        this.transition = transition;

        createScheduler();
        createBody();

        transition.getBody().clear();
        transition.getScheduler().clear();
    }

}