All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.protelis.lang.interpreter.impl.If Maven / Gradle / Ivy

There is a newer version: 17.6.0
Show newest version
/*
 * Copyright (C) 2021, Danilo Pianini and contributors listed in the project's build.gradle.kts or pom.xml file.
 *
 * This file is part of Protelis, and is distributed under the terms of the GNU General Public License,
 * with a linking exception, as described in the file LICENSE.txt in this project's top directory.
 */
package org.protelis.lang.interpreter.impl;

import org.protelis.lang.datatype.Field;
import org.protelis.lang.interpreter.ProtelisAST;
import org.protelis.lang.interpreter.util.Bytecode;
import org.protelis.lang.loading.Metadata;
import org.protelis.vm.ExecutionContext;

import javax.annotation.Nonnull;

import static org.protelis.lang.interpreter.util.Bytecode.IF_ELSE;
import static org.protelis.lang.interpreter.util.Bytecode.IF_THEN;

/**
 * Branch, restricting domain of true and false branches into their own aligned
 * subspaces.
 *
 * @param  the return type of this If
 */
public final class If extends AbstractProtelisAST {

    private static final long serialVersionUID = -4830593657731078743L;
    private final ProtelisAST conditionExpression;
    private final ProtelisAST elseExpression;
    private final ProtelisAST thenExpression;

    /**
     * @param metadata
     *            A {@link Metadata} object containing information about the code that generated this AST node.
     * @param cond
     *            condition
     * @param then
     *            branch to execute if condition is true (erase otherwise)
     * @param otherwise
     *            branch to execute if condition is false (erase otherwise)
     */
    public If(
            @Nonnull final Metadata metadata,
            @Nonnull final ProtelisAST cond,
            @Nonnull final ProtelisAST then,
            @Nonnull final ProtelisAST otherwise) {
        super(metadata);
        conditionExpression = cond;
        thenExpression = then;
        elseExpression = otherwise;
    }

    @SuppressWarnings("unchecked")
    @Override
    public T evaluate(final ExecutionContext context) {
        return ensureNotAField(
            conditionExpression.eval(context)
                ? context.runInNewStackFrame(IF_THEN.getCode(), thenExpression::eval)
                : context.runInNewStackFrame(IF_ELSE.getCode(), elseExpression::eval)
        );
    }

    private static  T ensureNotAField(final T in) {
        if (in instanceof Field) {
            throw new IllegalStateException("if statements cannot return a Field, consider using mux: " + in);
        }
        return in;
    }

    @Override
    public Bytecode getBytecode() {
        return Bytecode.IF;
    }

    /**
     * @return the {@link ProtelisAST} of the condition expression
     */
    public ProtelisAST getConditionExpression() {
        return conditionExpression;
    }

    /**
     * @return the {@link ProtelisAST} of the else expression
     */
    public ProtelisAST getElseExpression() {
        return elseExpression;
    }

    /**
     * @return the {@link ProtelisAST} of the then expression
     */
    public ProtelisAST getThenExpression() {
        return thenExpression;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return getName() + " (" + stringFor(conditionExpression) + ") { "
                + stringFor(thenExpression) + " } else { " + stringFor(thenExpression) + '}';
    }

    @Override
    protected boolean isNullable() {
        return elseExpression == null;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy