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

main.io.github.moonlightsuite.moonlight.script.ParametricExpressionEvaluator Maven / Gradle / Ivy

package io.github.moonlightsuite.moonlight.script;

import io.github.moonlightsuite.moonlight.core.base.MoonLightRecord;
import io.github.moonlightsuite.moonlight.offline.signal.RecordHandler;
import org.antlr.v4.runtime.ParserRuleContext;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;

public class ParametricExpressionEvaluator extends MoonLightScriptBaseVisitor> {

    private static final Map> binaryFunctionMap = new HashMap<>();

    static {
        binaryFunctionMap.put("atan2", Math::atan2);
        binaryFunctionMap.put("hypot", Math::hypot);
        binaryFunctionMap.put("max", Math::max);
        binaryFunctionMap.put("min", Math::min);
        binaryFunctionMap.put("pow", Math::pow);
    }

    private static final Map> unaryFunctionMap = new HashMap<>();

    static {
        unaryFunctionMap.put("abs", Math::abs);
        unaryFunctionMap.put("acos", Math::acos);
        unaryFunctionMap.put("asin", Math::asin);
        unaryFunctionMap.put("atan", Math::atan);
        unaryFunctionMap.put("cbrt", Math::cbrt);
        unaryFunctionMap.put("ceil", Math::ceil);
        unaryFunctionMap.put("cos", Math::cos);
        unaryFunctionMap.put("cosh", Math::cosh);
        unaryFunctionMap.put("exp", Math::exp);
        unaryFunctionMap.put("expm1", Math::expm1);
        unaryFunctionMap.put("floor", Math::floor);
        unaryFunctionMap.put("log", Math::log);
        unaryFunctionMap.put("log10", Math::log10);
        unaryFunctionMap.put("log1p", Math::log1p);
        unaryFunctionMap.put("signum", Math::signum);
        unaryFunctionMap.put("sin", Math::sin);
        unaryFunctionMap.put("sqrt", Math::sqrt);
        unaryFunctionMap.put("sinh", Math::sinh);
        unaryFunctionMap.put("tan", Math::tan);
    }

    private final List errors;

    private final NameResolver      nameResolver;
    private final RecordHandler     inputHandler;

    private ParametricBooleanExpressionEvaluator booleanExpressionEvaluator ;

    public ParametricExpressionEvaluator(List errors, NameResolver nameResolver, RecordHandler inputHandler) {
        this.errors = errors;
        this.nameResolver = nameResolver;
        this.inputHandler = inputHandler;
    }
    public ParametricExpressionEvaluator(NameResolver nameResolver, RecordHandler inputHandler) {
        this(new LinkedList<>(), nameResolver, inputHandler);
    }

    public ParametricExpressionEvaluator(NameResolver nameResolver) {
        this(nameResolver, new RecordHandler());
    }

    @Override
    protected Function defaultResult() {
        return r -> Double.NaN;
    }

    @Override
    public Function visitBinaryMathCallExpression(MoonLightScriptParser.BinaryMathCallExpressionContext ctx) {
        BiFunction opFunction = getBinaryFunction(ctx.binaryMathFunction());
        return doApply(ctx,opFunction,ctx.left.accept(this),ctx.right.accept(this));
    }

    private BiFunction getBinaryFunction(MoonLightScriptParser.BinaryMathFunctionContext binaryMathFunction) {
        String funName = binaryMathFunction.getText();
        BiFunction fun = binaryFunctionMap.get(funName);
        if (fun == null) {
            errors.add(MoonLightParseError.illegalFunctionName(funName,binaryMathFunction.start));
            return (x,y) -> Double.NaN;
        }
        return fun;
    }

    private Function doApply(ParserRuleContext ctx, BiFunction fun, Function arg1, Function arg2) {
        return r -> fun.apply(arg1.apply(r),arg2.apply(r));
    }


    @Override
    public Function visitBracketExpression(MoonLightScriptParser.BracketExpressionContext ctx) {
        return ctx.expression().accept(this);
    }

    @Override
    public Function visitUnaryMathCallExpression(MoonLightScriptParser.UnaryMathCallExpressionContext ctx) {
        Function fun = getUnaryFunction(ctx.fun);
        return doApply(ctx,fun,ctx.argument.accept(this));
    }

    private Function doApply(ParserRuleContext ctx, Function fun, Function arg) {
        return r -> fun.apply(arg.apply(r));
    }

    private Function getUnaryFunction(MoonLightScriptParser.UnaryMathFunctionContext unaryMathFunction) {
        String funName = unaryMathFunction.getText();
        Function fun = unaryFunctionMap.get(funName);
        if (fun == null) {
            errors.add(MoonLightParseError.illegalFunctionName(funName,unaryMathFunction.start));
            return x -> Double.NaN;
        }
        return fun;

    }

    @Override
    public Function visitRealExpression(MoonLightScriptParser.RealExpressionContext ctx) {
        double v = Double.parseDouble(ctx.getText());
        return r  -> v;
    }

    @Override
    public Function visitUnaryExpression(MoonLightScriptParser.UnaryExpressionContext ctx) {
        if (ctx.op.getText().equals("-")) {
            return doApply(ctx,x -> -x,ctx.arg.accept(this));
        } else {
            return ctx.arg.accept(this);
        }
    }

    @Override
    public Function visitReferenceExpression(MoonLightScriptParser.ReferenceExpressionContext ctx) {
        String name = ctx.name.getText();
        double value = nameResolver.get(name);
        if (!Double.isNaN(value)) {
            return r -> value;
        }
        if (inputHandler.isAVariable(name)) {
            int idx = inputHandler.getVariableIndex(name);
            return r -> r.getDoubleOf(idx);
        }
        return r -> Double.NaN;
    }

    @Override
    public Function  visitIntExpression(MoonLightScriptParser.IntExpressionContext ctx) {
        double value = Integer.parseInt(ctx.getText());
        return r -> value;
    }

    @Override
    public Function visitIfThenElseExpression(MoonLightScriptParser.IfThenElseExpressionContext ctx) {
        ParametricBooleanExpressionEvaluator booleanEvaluator = getParametricBooleanExpressionEvaluator();
        if (booleanEvaluator.eval(ctx.guard)) {
            return ctx.thenExpression.accept(this);
        } else {
            return ctx.elseExpression.accept(this);
        }
    }

    private synchronized ParametricBooleanExpressionEvaluator getParametricBooleanExpressionEvaluator() {
        if (booleanExpressionEvaluator == null) {
            booleanExpressionEvaluator = new ParametricBooleanExpressionEvaluator(this);
        }
        return booleanExpressionEvaluator;
    }

    @Override
    public Function visitMulDivExpression(MoonLightScriptParser.MulDivExpressionContext ctx) {
        BiFunction fun;
        if (ctx.op.getText().equals("*")) {
            fun = (x,y) -> x*y;
        } else {
            fun = (x,y) -> x/y;
        }
        return doApply(ctx,fun,ctx.left.accept(this),ctx.right.accept(this));
    }

    @Override
    public Function visitSumDifExpression(MoonLightScriptParser.SumDifExpressionContext ctx) {
        BiFunction fun;
        if (ctx.op.getText().equals("+")) {
            fun = Double::sum;
        } else {
            if (ctx.op.getText().equals("-")) {
                fun = (x,y) -> x-y;
            } else {
                fun = (x,y) -> x%y;
            }
        }
        return doApply(ctx,fun,ctx.left.accept(this),ctx.right.accept(this));
    }

    @Override
    public Function visitInfinityExpression(MoonLightScriptParser.InfinityExpressionContext ctx) {
        return r -> Double.POSITIVE_INFINITY;
    }

    public Function eval(MoonLightScriptParser.ExpressionContext value) {
        return value.accept(this);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy