j2s/src/main/java/me/topchetoeu/jscript/compilation/CompileResult.java

140 lines
4.4 KiB
Java

package me.topchetoeu.jscript.compilation;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.function.Consumer;
import java.util.function.IntFunction;
import me.topchetoeu.jscript.common.FunctionBody;
import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.common.environment.Environment;
import me.topchetoeu.jscript.common.mapping.FunctionMap;
import me.topchetoeu.jscript.common.mapping.FunctionMap.FunctionMapBuilder;
import me.topchetoeu.jscript.common.parsing.Location;
import me.topchetoeu.jscript.compilation.scope.Scope;
public final class CompileResult {
public static final class ChildData {
public final int id;
public final CompileResult result;
public ChildData(int id, CompileResult result) {
this.result = result;
this.id = id;
}
}
public final List<IntFunction<Instruction>> instructions;
public final List<CompileResult> children;
public final FunctionMapBuilder map;
public final Environment env;
public int length;
public Runnable buildTask = () -> {
throw new IllegalStateException("Compile result is not ready to be built");
};
public final Scope scope;
public int temp() {
instructions.add(null);
return instructions.size() - 1;
}
public CompileResult add(Instruction instr) {
instructions.add(i -> instr);
return this;
}
public CompileResult add(IntFunction<Instruction> instr) {
instructions.add(instr);
return this;
}
public CompileResult set(int i, Instruction instr) {
instructions.set(i, _i -> instr);
return this;
}
public CompileResult set(int i, IntFunction<Instruction>instr) {
instructions.set(i, instr);
return this;
}
public int size() { return instructions.size(); }
public void setDebug(Location loc, BreakpointType type) {
map.setDebug(loc, type);
}
public void setLocation(int i, Location loc) {
map.setLocation(i, loc);
}
public void setLocationAndDebug(int i, Location loc, BreakpointType type) {
map.setLocationAndDebug(i, loc, type);
}
public void setDebug(BreakpointType type) {
setDebug(map.last(), type);
}
public void setLocation(Location type) {
setLocation(instructions.size() - 1, type);
}
public void setLocationAndDebug(Location loc, BreakpointType type) {
setLocationAndDebug(instructions.size() - 1, loc, type);
}
public int addChild(CompileResult res) {
this.children.add(res);
return this.children.size() - 1;
}
public Instruction[] instructions() {
var res = new Instruction[instructions.size()];
var i = 0;
for (var suppl : instructions) {
res[i] = suppl.apply(i);
i++;
}
return res;
}
public FunctionMap map() {
return map.build(scope);
}
public FunctionBody body() {
var builtChildren = new FunctionBody[children.size()];
for (var i = 0; i < children.size(); i++) builtChildren[i] = children.get(i).body();
var instrRes = new Instruction[instructions.size()];
var i = 0;
for (var suppl : instructions) {
instrRes[i] = suppl.apply(i);
// System.out.println(instrRes[i]);
i++;
}
return new FunctionBody(
scope.localsCount() + scope.allocCount(), scope.capturesCount(),
length, instrRes, builtChildren
);
}
public CompileResult subtarget() {
return new CompileResult(new Scope(scope), this);
}
public CompileResult(Environment env, Scope scope, int length, Consumer<CompileResult> task) {
this.scope = scope;
this.instructions = new ArrayList<>();
this.children = new LinkedList<>();
this.map = FunctionMap.builder();
this.env = env;
this.length = length;
this.buildTask = () -> task.accept(this);
}
private CompileResult(Scope scope, CompileResult parent) {
this.scope = scope;
this.instructions = parent.instructions;
this.children = parent.children;
this.map = parent.map;
this.env = parent.env;
}
}