msi.gaml.expressions.PrimitiveOperator.java Source code

Java tutorial

Introduction

Here is the source code for msi.gaml.expressions.PrimitiveOperator.java

Source

/*******************************************************************************************************
 *
 * msi.gaml.expressions.PrimitiveOperator.java, in plugin msi.gama.core,
 * is part of the source code of the GAMA modeling and simulation platform (v. 1.8)
 * 
 * (c) 2007-2018 UMI 209 UMMISCO IRD/SU & Partners
 *
 * Visit https://github.com/gama-platform/gama for license information and contacts.
 * 
 ********************************************************************************************************/
package msi.gaml.expressions;

import java.util.Map;

import com.google.common.collect.Iterables;

import msi.gama.metamodel.agent.IAgent;
import msi.gama.runtime.IScope;
import msi.gama.runtime.exceptions.GamaRuntimeException;
import msi.gama.util.ICollector;
import msi.gaml.descriptions.IDescription;
import msi.gaml.descriptions.IExpressionDescription;
import msi.gaml.descriptions.OperatorProto;
import msi.gaml.descriptions.SpeciesDescription;
import msi.gaml.descriptions.StatementDescription;
import msi.gaml.descriptions.VariableDescription;
import msi.gaml.operators.Cast;
import msi.gaml.operators.Strings;
import msi.gaml.species.ISpecies;
import msi.gaml.statements.Arguments;
import msi.gaml.statements.IStatement;
import msi.gaml.types.IType;

/**
 * PrimitiveOperator. An operator that wraps a primitive or an action.
 *
 * @author drogoul 4 sept. 07
 */

public class PrimitiveOperator implements IExpression, IOperator {

    final Arguments parameters;
    final IExpression target;
    final StatementDescription action;
    final boolean isSuper;

    public PrimitiveOperator(final IDescription callerContext, final StatementDescription action,
            final IExpression target, final Arguments args, final boolean superInvocation) {
        this.target = target;
        this.action = action;
        isSuper = superInvocation;
        parameters = args;

    }

    @Override
    public String getName() {
        return action.getName();
    }

    @Override
    public Object value(final IScope scope) throws GamaRuntimeException {
        if (scope == null) {
            return null;
        }
        final IAgent target = this.target == null ? scope.getAgent()
                : Cast.asAgent(scope, this.target.value(scope));
        if (target == null) {
            return null;
        }
        // AD 13/05/13 The target should not be pushed so early to the scope, as
        // the arguments will be (incorrectly)
        // evaluated in its context, but how to prevent it ? See Issue 401.
        // One way is (1) to gather the executer
        final ISpecies species = isSuper ? target.getSpecies().getParentSpecies() : target.getSpecies();
        final IStatement.WithArgs executer = species.getAction(getName());
        // Then, (2) to set the caller to the actual agent on the scope (in the
        // context of which the arguments need to
        // be evaluated
        if (executer != null) {
            // And finally, (3) to execute the executer on the target (it will
            // be pushed in the scope)
            return scope.execute(executer, target, parameters).getValue();
        }
        return null;
    }

    @Override
    public boolean isConst() {
        return false;
    }

    @Override
    public String getTitle() {
        final StringBuilder sb = new StringBuilder(50);
        sb.append("action ").append(getName()).append(" defined in species ")
                .append(target.getGamlType().getSpeciesName()).append(" returns ").append(getGamlType().getTitle());
        return sb.toString();

    }

    @Override
    public String getDocumentation() {
        return action.getDocumentation();
    }

    @Override
    public String getDefiningPlugin() {
        return action.getDefiningPlugin();
    }

    @Override
    public String serialize(final boolean includingBuiltIn) {
        final StringBuilder sb = new StringBuilder();
        if (target != null) {
            AbstractExpression.parenthesize(sb, target);
            sb.append(".");
        }
        sb.append(literalValue()).append("(");
        argsToGaml(sb, includingBuiltIn);
        sb.append(")");
        return sb.toString();
    }

    protected String argsToGaml(final StringBuilder sb, final boolean includingBuiltIn) {
        if (parameters == null || parameters.isEmpty()) {
            return "";
        }
        for (final Map.Entry<String, IExpressionDescription> entry : parameters.entrySet()) {
            final String name = entry.getKey();
            final IExpressionDescription expr = entry.getValue();
            if (Strings.isGamaNumber(name)) {
                sb.append(expr.serialize(false));
            } else {
                sb.append(name).append(":").append(expr.serialize(includingBuiltIn));
            }
            sb.append(", ");
        }
        if (sb.length() > 0) {
            sb.setLength(sb.length() - 2);
        }
        return sb.toString();
    }

    /**
     * Method collectPlugins()
     * 
     * @see msi.gama.common.interfaces.IGamlDescription#collectPlugins(java.util.Set)
     */
    // @Override
    // public void collectMetaInformation(final GamlProperties meta) {
    // meta.put(GamlProperties.PLUGINS, action.getDefiningPlugin());
    // if (action.isBuiltIn()) {
    // meta.put(GamlProperties.ACTIONS, action.getName());
    // }
    // if (parameters != null) {
    // parameters.forEachValue(exp -> {
    // exp.collectMetaInformation(meta);
    // return true;
    // });
    // }
    // }

    @Override
    public void collectUsedVarsOf(final SpeciesDescription species, final ICollector<VariableDescription> result) {
        if (parameters != null) {
            parameters.forEachEntry((name, exp) -> {
                final IExpression expression = exp.getExpression();
                if (expression != null) {
                    expression.collectUsedVarsOf(species, result);
                }
                return true;

            });
        }
    }

    @Override
    public void setName(final String newName) {
    }

    @Override
    public IType<?> getGamlType() {
        return action.getGamlType();
    }

    @Override
    public void dispose() {
        if (parameters != null) {
            parameters.dispose();
        }
    }

    @Override
    public String literalValue() {
        return action.getName();
    }

    @Override
    public IExpression resolveAgainst(final IScope scope) {
        return this;
    }

    @Override
    public boolean shouldBeParenthesized() {
        return true;
    }

    @Override
    public void visitSuboperators(final IOperatorVisitor visitor) {
        if (parameters != null) {
            parameters.forEach((name, exp) -> {
                final IExpression expr = exp.getExpression();
                if (expr instanceof IOperator) {
                    visitor.visit((IOperator) expr);
                }
            });
        }

    }

    // TODO The arguments are not ordered...
    @Override
    public IExpression arg(final int i) {
        if (i < 0 || i > parameters.size()) {
            return null;
        }
        return Iterables.get(parameters.values(), i).getExpression();
    }

    @Override
    public OperatorProto getPrototype() {
        return null;
    }

}