From 8c2519aec367ac0f5ae2be33cb320ec5efadd803 Mon Sep 17 00:00:00 2001 From: ywsing Date: Sun, 25 Oct 2020 20:07:04 +0800 Subject: [PATCH 1/2] add single-capture lambda --- src/main/java/suite/funp/P0.java | 1 + src/main/java/suite/funp/P2.java | 22 +++++++++++++++++++ .../java/suite/funp/p2/P21CaptureLambda.java | 8 +++++++ src/main/java/suite/funp/p2/P22InferType.java | 2 ++ src/main/resources/suite/funp/iter.fp | 4 +++- 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/main/java/suite/funp/P0.java b/src/main/java/suite/funp/P0.java index fe1317d03b..f4c6cbf59c 100644 --- a/src/main/java/suite/funp/P0.java +++ b/src/main/java/suite/funp/P0.java @@ -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 } diff --git a/src/main/java/suite/funp/P2.java b/src/main/java/suite/funp/P2.java index 8f945473a1..0516ef81d3 100644 --- a/src/main/java/suite/funp/P2.java +++ b/src/main/java/suite/funp/P2.java @@ -290,6 +290,28 @@ public R apply(FixieFun5 fun) { } } + public static class FunpLambdaCapSingle implements Funp, P2.End { + public FunpVariable fpIn; + public FunpVariable frameVar; + public String vn; + public Funp expr; + public Fct fct; + + public static FunpLambdaCapSingle of(FunpVariable fpIn, FunpVariable frameVar, String vn, Funp expr, Fct fct) { + var f = new FunpLambdaCapSingle(); + f.fpIn = fpIn; + f.frameVar = frameVar; + f.vn = vn; + f.expr = expr; + f.fct = fct; + return f; + } + + public R apply(FixieFun5 fun) { + return fun.apply(fpIn, frameVar, vn, expr, fct); + } + } + public static class FunpLambdaCapture implements Funp, P2.End { public FunpVariable fpIn; public FunpVariable frameVar; diff --git a/src/main/java/suite/funp/p2/P21CaptureLambda.java b/src/main/java/suite/funp/p2/P21CaptureLambda.java index 038ae96381..fc3a19ae5b 100644 --- a/src/main/java/suite/funp/p2/P21CaptureLambda.java +++ b/src/main/java/suite/funp/p2/P21CaptureLambda.java @@ -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; @@ -178,6 +180,12 @@ 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 pcapn = capture.k; + var pcap = FunpVariable.of(pcapn); + yield FunpLambdaCapSingle.of(pcap, li.cap, vn, c(expr), fct); + } case STACKF -> null; default -> fail(); }; diff --git a/src/main/java/suite/funp/p2/P22InferType.java b/src/main/java/suite/funp/p2/P22InferType.java index dfde9dcab1..f6bcdfe239 100644 --- a/src/main/java/suite/funp/p2/P22InferType.java +++ b/src/main/java/suite/funp/p2/P22InferType.java @@ -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(); diff --git a/src/main/resources/suite/funp/iter.fp b/src/main/resources/suite/funp/iter.fp index 866a2b7a9c..b309320869 100644 --- a/src/main/resources/suite/funp/iter.fp +++ b/src/main/resources/suite/funp/iter.fp @@ -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 ~ @@ -60,6 +61,7 @@ define-global list-iter! list := do free! := () => capture1 do uncapture has-next ~ uncapture next! ~ + delete! cap ~ delete! i ~ () ~ From f72bccdcb089b8b7bb38f4728a013ac9664e8dac Mon Sep 17 00:00:00 2001 From: ywsing Date: Sun, 25 Oct 2020 22:03:09 +0800 Subject: [PATCH 2/2] - --- src/main/java/suite/funp/P2.java | 16 +++++++++------- .../java/suite/funp/p2/P21CaptureLambda.java | 11 ++++++++--- src/main/java/suite/funp/p2/P22InferType.java | 8 ++++---- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/main/java/suite/funp/P2.java b/src/main/java/suite/funp/P2.java index 0516ef81d3..8cf7626376 100644 --- a/src/main/java/suite/funp/P2.java +++ b/src/main/java/suite/funp/P2.java @@ -293,38 +293,40 @@ public R apply(FixieFun5 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, String vn, Funp expr, 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 apply(FixieFun5 fun) { - return fun.apply(fpIn, frameVar, vn, expr, fct); + public R apply(FixieFun6 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; @@ -332,7 +334,7 @@ public static FunpLambdaCapture of(FunpVariable fpIn, FunpVariable frameVar, Fun } public R apply(FixieFun6 fun) { - return fun.apply(fpIn, frameVar, struct, vn, expr, fct); + return fun.apply(fpIn, frameVar, frameValue, vn, expr, fct); } } diff --git a/src/main/java/suite/funp/p2/P21CaptureLambda.java b/src/main/java/suite/funp/p2/P21CaptureLambda.java index fc3a19ae5b..5632989cbb 100644 --- a/src/main/java/suite/funp/p2/P21CaptureLambda.java +++ b/src/main/java/suite/funp/p2/P21CaptureLambda.java @@ -122,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 @@ -182,9 +188,8 @@ private Funp c_(Funp n) { case ONCE__ -> capturef.apply(false); case SINGLE -> { var capture = Read.from(captures).uniqueResult(); - var pcapn = capture.k; - var pcap = FunpVariable.of(pcapn); - yield FunpLambdaCapSingle.of(pcap, li.cap, vn, c(expr), fct); + var pcap = FunpVariable.of(capture.k); + yield FunpLambdaCapSingle.of(pcap, li.cap, capture.v, vn, c(expr), fct); } case STACKF -> null; default -> fail(); diff --git a/src/main/java/suite/funp/p2/P22InferType.java b/src/main/java/suite/funp/p2/P22InferType.java index f6bcdfe239..109f50490f 100644 --- a/src/main/java/suite/funp/p2/P22InferType.java +++ b/src/main/java/suite/funp/p2/P22InferType.java @@ -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 // @@ -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;