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

org.protelis.lang.interpreter.util.Op1 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.util;

import static org.protelis.lang.interpreter.util.Bytecode.UNARY_MINUS;
import static org.protelis.lang.interpreter.util.Bytecode.UNARY_NOT;
import static org.protelis.lang.interpreter.util.OpUtils.unsupported;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.UnaryOperator;

import org.protelis.lang.datatype.Field;
import org.protelis.lang.datatype.Fields;

/**
 * Collection of functions and helper methods for unary operators.
 */
public enum Op1 implements WithBytecode {

    /**
     * Sign inversion.
     */
    MINUS(UNARY_MINUS, "-", Op1::minus),
    /**
     * Not.
     */
    NOT(UNARY_NOT, "!", Op1::not);

    private static final int[] FIELDS = { 0 };
    private static final Map MAP = new ConcurrentHashMap<>();
    private final Bytecode bytecode;
    private final UnaryOperation fun;
    private final String opName;

    Op1(final Bytecode bytecode, final String name, final UnaryOperation function) {
        fun = function;
        opName = name;
        this.bytecode = bytecode;
    }

    @Override
    public Bytecode getBytecode() {
        return bytecode;
    }

    /**
     * @param a
     *            the object on which the {@link Op1} should be run
     * @return the result of the evaluation
     */
    public Object run(final Object a) {
        if (a instanceof Field) {
            return Fields.applyWithSingleParam(fun, FIELDS, a);
        }
        return fun.apply(a);
    }

    @Override
    public String toString() {
        return opName;
    }

    /**
     * Translates a name into an operator.
     * 
     * @param name
     *            operator name
     * @return an {@link Op1}
     */
    public static Op1 getOp(final String name) {
        Op1 op = MAP.get(name);
        if (op == null) {
            op = Arrays.stream(values()).filter(o -> o.opName.equals(name)).findFirst().get();
            MAP.put(name, op);
        }
        return op;
    }

    private static double minus(final Object o) {
        if (o instanceof Number) {
            return -((Number) o).doubleValue();
        }
        return unsupported("-", o);
    }

    private static boolean not(final Object o) {
        if (o instanceof Boolean) {
            return !(Boolean) o;
        }
        return unsupported("!", o);
    }

    private interface UnaryOperation extends UnaryOperator, Serializable { }
}