Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/java/suite/funp/P0.java
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,7 @@ public enum Fct { // function capture type
MANUAL, // capture the variables and allocate a capture frame, to be uncaptured (freed) manually
NOSCOP, // no access to variables of outer scope
ONCE__, // capture the variables and allocate a capture frame, which is to be freed after first call; lambda cannot be called twice
SINGLE, // pass one variable
STACKF, // pass the stack frame, no need to capture; lambda lifetime equals to stack frame lifetime
}

Expand Down
32 changes: 28 additions & 4 deletions src/main/java/suite/funp/P2.java
Original file line number Diff line number Diff line change
Expand Up @@ -290,27 +290,51 @@ public <R> R apply(FixieFun5<Funp, Integer, Integer, Integer, Integer, R> fun) {
}
}

public static class FunpLambdaCapSingle implements Funp, P2.End {
public FunpVariable fpIn;
public FunpVariable frameVar;
public Funp frameValue;
public String vn;
public Funp expr;
public Fct fct;

public static FunpLambdaCapSingle of(FunpVariable fpIn, FunpVariable frameVar, Funp frameValue, String vn, Funp expr, Fct fct) {
var f = new FunpLambdaCapSingle();
f.fpIn = fpIn;
f.frameVar = frameVar;
f.frameValue = frameValue;
f.vn = vn;
f.expr = expr;
f.fct = fct;
return f;
}

public <R> R apply(FixieFun6<FunpVariable, FunpVariable, Funp, String, Funp, Fct, R> fun) {
return fun.apply(fpIn, frameVar, frameValue, vn, expr, fct);
}
}

public static class FunpLambdaCapture implements Funp, P2.End {
public FunpVariable fpIn;
public FunpVariable frameVar;
public Funp struct;
public Funp frameValue;
public String vn;
public Funp expr;
public Fct fct;

public static FunpLambdaCapture of(FunpVariable fpIn, FunpVariable frameVar, Funp struct, String vn, Funp expr, Fct fct) {
public static FunpLambdaCapture of(FunpVariable fpIn, FunpVariable frameVar, Funp frameValue, String vn, Funp expr, Fct fct) {
var f = new FunpLambdaCapture();
f.fpIn = fpIn;
f.frameVar = frameVar;
f.struct = struct;
f.frameValue = frameValue;
f.vn = vn;
f.expr = expr;
f.fct = fct;
return f;
}

public <R> R apply(FixieFun6<FunpVariable, FunpVariable, Funp, String, Funp, Fct, R> fun) {
return fun.apply(fpIn, frameVar, struct, vn, expr, fct);
return fun.apply(fpIn, frameVar, frameValue, vn, expr, fct);
}
}

Expand Down
13 changes: 13 additions & 0 deletions src/main/java/suite/funp/p2/P21CaptureLambda.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import suite.funp.P0.FunpReference;
import suite.funp.P0.FunpStruct;
import suite.funp.P0.FunpVariable;
import suite.funp.P2;
import suite.funp.P2.FunpLambdaCapSingle;
import suite.funp.P2.FunpLambdaCapture;
import suite.funp.P2.FunpTypeAssign;
import suite.inspect.Inspect;
Expand Down Expand Up @@ -120,6 +122,12 @@ else if (lambda.fct == Fct.MANUAL || lambda.fct == Fct.ONCE__) { // access from
if (li.captureSet.add(vn))
li.captures.add(Pair.of(vn, access(lambdaByFunp.get(lambda))));
return FunpField.of(FunpReference.of(li.cap), vn);
}
else if (lambda.fct == Fct.SINGLE) { // access from frame variable
var li = infoByLambda.get(lambda);
if (li.captureSet.add(vn))
li.captures.add(Pair.of(vn, access(lambdaByFunp.get(lambda))));
return li.cap;
} else if (lambda.fct == Fct.STACKF) // accessible through stack frame
return access(lambdaByFunp.get(lambda));
else
Expand Down Expand Up @@ -178,6 +186,11 @@ private Funp c_(Funp n) {
yield Funp_.fail(f, "scopeless lambda <" + vn + "> capturing variables " + li.captureSet);
}
case ONCE__ -> capturef.apply(false);
case SINGLE -> {
var capture = Read.from(captures).uniqueResult();
var pcap = FunpVariable.of(capture.k);
yield FunpLambdaCapSingle.of(pcap, li.cap, capture.v, vn, c(expr), fct);
}
case STACKF -> null;
default -> fail();
};
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/suite/funp/p2/P22InferType.java
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,9 @@ else if (coerce == Coerce.POINTER)
.fold(PerMap.empty(), (e, p) -> e.put(p.k, p.v));
var env2 = env1.replace(vn, Pair.of(Fdt.L_MONO, tv));
return typeLambdaOf(tv, new Infer(env2, checks0, checks1, me).infer(expr));
})).applyIf(FunpLambdaCapture.class, f -> f.apply((fpIn, frameVar, frame, vn, expr, fct) -> {
})).applyIf(FunpLambdaCapture.class, f -> f.apply((fpIn, frameVar, frameValue, vn, expr, fct) -> {
var tv = new Reference();
var tf = infer(frame);
var tf = infer(frameValue);
var tr = typeRefOf(tf);
unify(f, tr, infer(fpIn));
var env1 = PerMap //
Expand Down Expand Up @@ -674,8 +674,8 @@ else if (Fdt.isSubs(fdt)) {
var expr2 = isPassByReg ? FunpAllocReg.of(lt.is, FunpDontCare.of(), expr1, opArg) : expr1;
var expr3 = f.name != null ? FunpRemark.of(f.name, expr2) : expr2;
return eraseRoutine(lt, frame, expr3);
})).applyIf(FunpLambdaCapture.class, f -> f.apply((fp0, frameVar, frame, vn, expr, fct) -> {
var size = getTypeSize(typeOf(frame));
})).applyIf(FunpLambdaCapture.class, f -> f.apply((fp0, frameVar, frameValue, vn, expr, fct) -> {
var size = getTypeSize(typeOf(frameValue));
var b = ps + ps; // return address and EBP
var lt = new LambdaType(f);
var isPassByReg = lt.isPassByReg;
Expand All @@ -698,6 +698,8 @@ else if (fct == Fct.ONCE__)
// the capture would free itself upon first call, therefore should not be called
// for the second time
expr3 = FunpHeapDealloc.of(false, size, FunpMemory.of(FunpFramePointer.of(), 0, ps), expr2);
else if (fct == Fct.SINGLE)
expr3 = expr2;
else
return fail();

Expand Down
4 changes: 3 additions & 1 deletion src/main/resources/suite/funp/iter.fp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ define-global list-iter! list := do
type list = type-list ~
let { elems ~ size ~ } := list ~
let i := new! 0 ~
let has-next := () => capture (i* < size) ~
let cap := new! { elems, i, size, } ~
let has.next := () => capture (i* < size) ~
let next! := () => capture do
let i_ := i* ~
assign! i* := i_ + 1 ~
Expand All @@ -60,6 +61,7 @@ define-global list-iter! list := do
free! := () => capture1 do
uncapture has-next ~
uncapture next! ~
delete! cap ~
delete! i ~
()
~
Expand Down