use of suite.funp.Funp_.Funp in project suite by stupidsing.
the class P2InferType method captureLambdas.
private Funp captureLambdas(Funp node0) {
class Capture {
private Fun<String, Funp> accesses;
private ISet<String> locals;
private ISet<String> globals;
private Capture(Fun<String, Funp> accesses, ISet<String> locals, ISet<String> globals) {
this.accesses = accesses;
this.locals = locals;
this.globals = globals;
}
private Funp capture(Funp n) {
return inspect.rewrite(Funp.class, this::capture_, n);
}
private Funp capture_(Funp n) {
return //
n.<//
Funp>switch_().applyIf(FunpDefine.class, f -> f.apply((isPolyType, var, value, expr) -> {
Capture c1 = new Capture(accesses, locals.add(var), globals);
return FunpDefine.of(isPolyType, var, capture(value), c1.capture(expr));
})).applyIf(FunpDefineRec.class, f -> f.apply((vars, expr) -> {
List<Pair<String, Funp>> vars1 = new ArrayList<>();
ISet<String> locals1 = locals;
for (Pair<String, Funp> pair : vars) {
locals1 = locals1.add(pair.t0);
vars1.add(Pair.of(pair.t0, capture(pair.t1)));
}
Capture c1 = new Capture(accesses, locals1, globals);
return FunpDefineRec.of(vars1, c1.capture(expr));
})).applyIf(FunpGlobal.class, f -> f.apply((var, value, expr) -> {
Capture c1 = new Capture(accesses, locals, globals.add(var));
return FunpGlobal.of(var, capture(value), c1.capture(expr));
})).applyIf(FunpIterate.class, f -> f.apply((var, init, cond, iterate) -> {
Capture c1 = new Capture(accesses, locals.add(var), globals);
return FunpIterate.of(var, capture(init), c1.capture(cond), c1.capture(iterate));
})).applyIf(FunpLambda.class, f -> f.apply((var, expr) -> {
ISet<String> locals1 = ISet.empty();
String capn = "cap" + Util.temp();
FunpVariable cap = FunpVariable.of(capn);
FunpReference ref = FunpReference.of(cap);
Set<String> set = new HashSet<>();
List<Pair<String, Funp>> list = new ArrayList<>();
FunpStruct struct = FunpStruct.of(list);
Capture c1 = new Capture(v -> {
if (set.add(v))
list.add(Pair.of(v, FunpVariable.of(v)));
return FunpField.of(ref, v);
}, locals1.add(capn).add(var), globals);
return FunpGlobal.of(capn, struct, FunpLambdaCapture.of(var, capn, cap, c1.capture(expr)));
// TODO allocate cap on heap
// TODO free cap after use
})).applyIf(FunpVariable.class, f -> f.apply(var -> {
return locals.contains(var) || globals.contains(var) ? f : accesses.apply(var);
})).result();
}
}
return new Capture(v -> Fail.t(), ISet.empty(), ISet.empty()).capture(node0);
}
use of suite.funp.Funp_.Funp in project suite by stupidsing.
the class P2InferType method infer.
public Funp infer(Funp n0) {
UnNode<Type> t = unify.newRef();
Funp n1 = extractPredefine(n0);
Funp n2 = Boolean.FALSE ? captureLambdas(n1) : n1;
if (unify.unify(t, new Infer(IMap.empty()).infer(n2)))
return new Erase(0, IMap.empty()).erase(n2);
else
return Fail.t("cannot infer type for " + n0);
}
use of suite.funp.Funp_.Funp in project suite by stupidsing.
the class P3Optimize method optimize_.
private Funp optimize_(Funp n) {
return //
n.<//
Funp>switch_().applyIf(FunpCoerce.class, f -> f.apply((coerce, expr) -> {
return !(expr instanceof FunpDontCare) ? n : optimize(expr);
})).applyIf(FunpData.class, f -> f.apply(pairs -> {
return FunpData.of(Read.from2(pairs).concatMap((expr, range) -> {
Funp expr1 = optimize(expr);
int start = range.t0;
Streamlet<Pair<Funp, IntIntPair>> pairsx = new //
Switch<Streamlet<Pair<Funp, IntIntPair>>>(//
expr1).applyIf(FunpData.class, g -> g.apply(pairs1 -> {
return //
Read.from2(//
pairs1).map((exprc, range1) -> Pair.of(optimize(exprc), IntIntPair.of(start + range1.t0, start + range1.t1)));
})).result();
return pairsx != null ? pairsx : Read.each(Pair.of(expr1, range));
}).toList());
})).applyIf(FunpDeref.class, f -> f.apply(pointer -> {
return optimize(pointer).<Funp>switch_().applyIf(FunpReference.class, g -> g.expr).result();
})).applyIf(FunpIf.class, f -> f.apply((if_, then, else_) -> {
return //
optimize(if_).<Funp>switch_().applyIf(FunpBoolean.class, g -> g.apply(b -> {
return b ? then : else_;
})).result();
})).applyIf(FunpMemory.class, f -> f.apply((pointer, start, end) -> {
return //
optimize(pointer).<Funp>switch_().applyIf(FunpData.class, g -> g.apply(pairs -> {
for (Pair<Funp, IntIntPair> pair : pairs) {
IntIntPair range = pair.t1;
if (start == range.t0 && end == range.t1)
return pair.t0;
}
return null;
})).applyIf(FunpReference.class, g -> {
return FunpTree.of(TermOp.PLUS__, g.expr, FunpNumber.ofNumber(start));
}).result();
})).applyIf(FunpReference.class, f -> f.apply(expr -> {
return optimize(expr).<Funp>switch_().applyIf(FunpMemory.class, g -> g.pointer).result();
})).applyIf(FunpTree.class, f -> f.apply((operator, lhs, rhs) -> {
IntInt_Bool iib = TreeUtil.boolOperations.get(operator);
IntInt_Int iii = TreeUtil.intOperations.get(operator);
if (iib != null)
return evaluate(iib, lhs, rhs);
else if (iii != null)
return evaluate(iii, lhs, rhs);
else
return null;
})).applyIf(FunpTree2.class, f -> f.apply((operator, lhs, rhs) -> {
return evaluate(TreeUtil.tupleOperations.get(operator), lhs, rhs);
})).applyIf(FunpWhile.class, f -> f.apply((while_, do_, expr) -> {
return //
optimize(while_).<Funp>switch_().applyIf(FunpBoolean.class, g -> g.apply(b -> {
return b ? null : expr;
})).result();
})).result();
}
use of suite.funp.Funp_.Funp in project suite by stupidsing.
the class P2InferType method extractPredefine.
private Funp extractPredefine(Funp node0) {
List<Pair<String, Funp>> evs = new ArrayList<>();
Funp node1 = new Object() {
private Funp extract_(Funp n) {
return inspect.rewrite(Funp.class, n_ -> {
return //
n_.<//
Funp>switch_().applyIf(FunpDefine.class, f -> f.apply((isPolyType, var, value, expr) -> {
return FunpDefine.of(isPolyType, var, extractPredefine(value), extract_(expr));
})).applyIf(FunpDefineRec.class, f -> f.apply((pairs0, expr) -> {
List<Pair<String, Funp>> pairs1 = Read.from2(pairs0).mapValue(P2InferType.this::extractPredefine).toList();
return FunpDefineRec.of(pairs1, extract_(expr));
})).applyIf(FunpGlobal.class, f -> f.apply((var, value, expr) -> {
return FunpGlobal.of(var, extractPredefine(value), extract_(expr));
})).applyIf(FunpLambda.class, f -> f.apply((var, expr) -> {
return FunpLambda.of(var, extractPredefine(expr));
})).applyIf(FunpPredefine.class, f -> f.apply(expr -> {
String ev = "ev" + Util.temp();
evs.add(Pair.of(ev, expr));
Funp var = FunpVariable.of(ev);
return FunpAssignReference.of(FunpReference.of(var), expr, var);
})).result();
}, n);
}
}.extract_(node0);
for (Pair<String, Funp> pair : evs) node1 = FunpDefine.of(false, pair.t0, FunpDontCare.of(), node1);
return node1;
}
use of suite.funp.Funp_.Funp in project suite by stupidsing.
the class P4DecomposeOperand method decomposeOpMem.
public OpMem decomposeOpMem(int fd, Funp n0, int disp0, int size) {
class Decompose {
private Operator operator;
private List<Funp> nodes = new ArrayList<>();
private Decompose(Operator operator) {
this.operator = operator;
}
private void decompose(Funp n_) {
FunpTree tree;
if (n_ instanceof FunpTree && (tree = (FunpTree) n_).operator == operator) {
decompose(tree.left);
decompose(tree.right);
} else
nodes.add(n_);
}
}
Fun2<Operator, Funp, List<Funp>> decompose = (operator, n_) -> {
Decompose dec = new Decompose(operator);
dec.decompose(n_);
return dec.nodes;
};
class DecomposeMult {
private long scale = 1;
private OpReg reg;
private List<Funp> mults = new ArrayList<>();
private void decompose(Funp n0) {
FunpTree2 tree;
Funp r;
for (Funp n1 : decompose.apply(TermOp.MULT__, n0)) if (n1 instanceof FunpFramePointer && isUseEbp && reg == null)
reg = amd64.ebp;
else if (n1 instanceof FunpNumber)
scale *= ((FunpNumber) n1).i.get();
else if (//
n1 instanceof FunpTree2 && //
(tree = (FunpTree2) n1).operator == TreeUtil.SHL && (r = tree.right) instanceof FunpNumber) {
decompose(tree.left);
scale <<= ((FunpNumber) r).i.get();
} else
mults.add(n1);
}
}
class DecomposePlus {
private OpReg baseReg = null, indexReg = null;
private int scale = 1, disp = disp0;
private boolean ok = is124(size);
private DecomposePlus(Funp n0) {
for (Funp n1 : decompose.apply(TermOp.PLUS__, n0)) if (n1 instanceof FunpFramePointer && !isUseEbp) {
addReg(amd64.esp, 1);
disp -= fd;
} else {
DecomposeMult dec = new DecomposeMult();
dec.decompose(n1);
if (dec.mults.isEmpty()) {
OpReg reg_ = dec.reg;
long scale_ = dec.scale;
if (reg_ != null)
addReg(reg_, scale_);
else
disp += scale_;
} else
ok = false;
}
}
private void addReg(OpReg reg_, long scale_) {
if (scale_ == 1 && baseReg == null)
baseReg = reg_;
else if (is1248(scale_) && indexReg == null) {
indexReg = reg_;
scale = (int) scale_;
} else
ok = false;
}
private OpMem op() {
return ok ? amd64.mem(baseReg, indexReg, scale, disp, size) : null;
}
}
return new DecomposePlus(n0).op();
}
Aggregations