java-commons/muscript/src/main/java/io/gitlab/jfronny/muscript/ast/dynamic/Call.java

97 lines
3.2 KiB
Java

package io.gitlab.jfronny.muscript.ast.dynamic;
import io.gitlab.jfronny.muscript.ast.DynamicExpr;
import io.gitlab.jfronny.muscript.annotations.CanThrow;
import io.gitlab.jfronny.muscript.annotations.UncheckedDynamic;
import io.gitlab.jfronny.muscript.compiler.ExprWriter;
import io.gitlab.jfronny.muscript.compiler.Order;
import io.gitlab.jfronny.muscript.data.Scope;
import io.gitlab.jfronny.muscript.data.dynamic.*;
import io.gitlab.jfronny.muscript.data.dynamic.additional.DFinal;
import io.gitlab.jfronny.muscript.error.LocationalException;
import java.io.IOException;
import java.util.*;
import java.util.stream.Stream;
@CanThrow
@UncheckedDynamic
public class Call extends DynamicExpr {
private final DynamicExpr left;
private final List<Arg> args;
public Call(int chStart, int chEnd, DynamicExpr left, List<Arg> args) {
super(Order.Call, chStart, chEnd);
this.left = left;
this.args = args;
}
@Override
public Dynamic<?> get(Scope dataRoot) {
try {
return left.get(dataRoot)
.asCallable()
.getValue()
.apply(DFinal.of(args.stream().flatMap(e -> e.get(dataRoot)).toArray(Dynamic[]::new)));
} catch (DynamicTypeConversionException e) {
throw e.locational(chStart, chEnd);
} catch (RuntimeException e) {
throw new LocationalException(chStart, chEnd, "Could not perform call successfully", e);
}
}
@Override
public DynamicExpr optimize() {
List<Arg> args = new ArrayList<>();
DynamicExpr left = this.left.optimize();
if (left instanceof Bind bind) {
left = bind.callable;
args.add(new Arg(bind.parameter, false));
}
for (Arg arg : this.args) args.add(arg.optimize());
return new Call(chStart, chEnd, left, args);
}
@Override
public void decompile(ExprWriter writer) throws IOException {
parenthesize(left, writer, false);
if (args.size() > 3) {
writer.increaseIndent();
writer.append("(\n");
boolean first = true;
for (Arg arg : args) {
if (!first) writer.append(",\n");
first = false;
arg.expr.decompile(writer);
if (arg.variadic) writer.append("...");
}
writer.decreaseIndent();
writer.append("\n)");
} else {
writer.append("(");
boolean first = true;
for (Arg arg : args) {
if (!first) writer.append(", ");
first = false;
arg.expr.decompile(writer);
if (arg.variadic) writer.append("...");
}
}
}
@Override
public boolean equals(Object obj) {
return obj instanceof Call call && left.equals(call.left) && args.equals(call.args);
}
public record Arg(DynamicExpr expr, boolean variadic) {
public Stream<Dynamic<?>> get(Scope dataRoot) {
return variadic ? expr.get(dataRoot).asList().getValue().stream() : Stream.of(expr.get(dataRoot));
}
public Arg optimize() {
return new Arg(expr.optimize(), variadic);
}
}
}