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

main.io.github.moonlightsuite.moonlight.script.BiParametricExpressionEvaluator 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.*;
import java.util.function.BiFunction;
import java.util.function.Function;

public class BiParametricExpressionEvaluator 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 resolver;
    private final RecordHandler firstGroupHandler; //Record handler for formula parameters;
    private final RecordHandler secondGroupHandler; //Record handler for signal expressions;

    private BiParametricBooleanExpressionEvaluator signalPredicateEvaluator ;

    public BiParametricExpressionEvaluator(
            List errors,
            NameResolver resolver,
            RecordHandler firstGroupHandler,
            RecordHandler secondGroupHandler) {
        this.errors = errors;
        this.resolver = resolver;
        this.firstGroupHandler = firstGroupHandler;
        this.secondGroupHandler = secondGroupHandler;
    }

    public BiParametricExpressionEvaluator(
            NameResolver resolver,
            RecordHandler firstGroupHandler,
            RecordHandler secondGroupHandler) {
        this(new LinkedList<>(),resolver, firstGroupHandler, secondGroupHandler);
    }

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

    @Override
    public BiFunction 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 BiFunction doApply(ParserRuleContext ctx, BiFunction fun, BiFunction arg1, BiFunction arg2) {
        return (r,s) -> fun.apply(arg1.apply(r,s), arg2.apply(r,s));
    }


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

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

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

    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 BiFunction visitRealExpression(MoonLightScriptParser.RealExpressionContext ctx) {
        return (r,s) -> Double.parseDouble(ctx.getText());
    }

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

    @Override
    public BiFunction visitReferenceExpression(MoonLightScriptParser.ReferenceExpressionContext ctx) {
        String name = ctx.name.getText();
        double value = resolver.get(name);
        if (!Double.isNaN(value)) {
            return (r,s) -> value;
        }
        if (firstGroupHandler.isAVariable(name)) {
            int idx = firstGroupHandler.getVariableIndex(name);
            return (r,s) -> r.getDoubleOf(idx);
        }
        if (secondGroupHandler.isAVariable(name)) {
            int vIndex = secondGroupHandler.getVariableIndex(name);
            return (r,s) -> s.getDoubleOf(vIndex);
        }
        errors.add(MoonLightParseError.useOfAnUnknownName(name,ctx));
        return (r,s) -> Double.NaN;
    }

    @Override
    public BiFunction  visitIntExpression(MoonLightScriptParser.IntExpressionContext ctx) {
        double i = (double) Integer.parseInt(ctx.getText());
        return (r,s) -> i;
    }

    @Override
    public BiFunction  visitIfThenElseExpression(MoonLightScriptParser.IfThenElseExpressionContext ctx) {
        BiParametricBooleanExpressionEvaluator signalPredicateEvaluator = getSignalPredicateEvaluator();
        BiFunction guard = ctx.guard.accept(signalPredicateEvaluator);
        BiFunction  thenBranch = ctx.thenExpression.accept(this);
        BiFunction  elseBranch = ctx.elseExpression.accept( this);
        return (r,s) -> (guard.apply(r,s)?thenBranch.apply(r,s):elseBranch.apply(r,s));
    }

    private synchronized BiParametricBooleanExpressionEvaluator getSignalPredicateEvaluator() {
        if (signalPredicateEvaluator == null) {
            signalPredicateEvaluator = new BiParametricBooleanExpressionEvaluator(this);
        }
        return signalPredicateEvaluator;
    }

    @Override
    public BiFunction 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 BiFunction 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 BiFunction  visitInfinityExpression(MoonLightScriptParser.InfinityExpressionContext ctx) {
        return (r,s) -> Double.POSITIVE_INFINITY;
    }

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy