diff --git a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala index c5b212628a..3f130bb0c5 100644 --- a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala +++ b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala @@ -58,7 +58,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { var anonymCnt: Int = 0 var clsCnt: Int = 0 val logOutput: StringBuilder = new StringBuilder - val primiTypes = new mlscript.Typer(false, false, false).primitiveTypes + val primiTypes = new mlscript.Typer(false, false, false, true).primitiveTypes private def log(str: String): Unit = { logOutput.append(str) @@ -88,7 +88,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { private def getFields(etts: List[Statement]): Set[Var] = { etts.flatMap{ - case NuFunDef(_, nm, _, _) => Some(nm) + case NuFunDef(_, nm, _, _, _) => Some(nm) case nuty: NuTypeDef => Some(Var(nuty.name)) case Let(_, name, _, _) => Some(name) case _ => None @@ -163,7 +163,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { case Lam(lhs, rhs) => val lhsVs = getFreeVars(lhs) getFreeVars(rhs)(using ctx ++ lhsVs) -+ lhsVs - case NuFunDef(_, vm, tps, Left(trm)) => + case NuFunDef(_, vm, _, tps, Left(trm)) => getFreeVars(trm).extV(vm).extT(tps) case OpApp(_, trm) => getFreeVars(trm) case Sel(trm, _) => getFreeVars(trm) @@ -542,7 +542,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { private def liftFunc(func: NuFunDef)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (NuFunDef, LocalContext) = { log(s"liftFunc $func under $ctx # $cache # $outer") - val NuFunDef(rec, nm, tpVs, body) = func + val NuFunDef(rec, nm, sn, tpVs, body) = func body match { case Left(value) => val ret = liftTerm(value)(using ctx.addV(nm).addT(tpVs)) diff --git a/compiler/shared/test/diff/LiftType.mls b/compiler/shared/test/diff/LiftType.mls index 99221caca9..f6dcc38185 100644 --- a/compiler/shared/test/diff/LiftType.mls +++ b/compiler/shared/test/diff/LiftType.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly class CTX{ @@ -8,7 +8,7 @@ class CTX{ //│ |#class| |CTX|{|→|#class| |A| |{||}|↵|#fun| |foo|(|f|#:| |A| |=>| |A|)|#:| |(|A| |=>| |A|)| |=>| |A| |#=| |f|(|#new| |A|)|←|↵|}| //│ Parsed: {class CTX() {class A() {}; fun foo = (f: (A,) => A,) => f (new A() {},) : (A -> A) -> A}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(), (), None, None, TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit()), NuFunDef(None, foo, [], Lam(Tup(f: Lam(Tup(_: Var(A)), Var(A))), Asc(App(Var(f), Tup(_: New(Some((TypeName(A),)), TypingUnit(List())))), Function(Tuple(List((None,Field(None,Function(Tuple(List((None,Field(None,TypeName(A))))),TypeName(A)))))),TypeName(A)))))))) +//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(), (), None, None, TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit()), NuFunDef(None, foo, None, [], Lam(Tup(f: Lam(Tup(_: Var(A)), Var(A))), Asc(App(Var(f), Tup(_: New(Some((TypeName(A),)), TypingUnit(List())))), Function(Tuple(List((None,Field(None,Function(Tuple(List((None,Field(None,TypeName(A))))),TypeName(A)))))),TypeName(A)))))))) //│ Lifted: //│ TypingUnit { //│ class CTX$1_A$2(par$CTX$1,) {} @@ -16,6 +16,7 @@ class CTX{ //│ fun foo = (f: (CTX$1_A$2,) => CTX$1_A$2,) => f (new CTX$1_A$2(this,) {},) : (CTX$1_A$2 -> CTX$1_A$2) -> CTX$1_A$2 //│ } //│ } +//│ class CTX(x, y){ class A{ fun foo = x} @@ -25,7 +26,7 @@ class CTX(x, y){ //│ |#class| |CTX|(|x|,| |y|)|{|→|#class| |A|{| |#fun| |foo| |#=| |x|}|↵|#class| |B|#:| |A| |{| |#fun| |foo| |#=| |y|}|↵|#fun| |foo|(|any|#:| |(|A|,| |B|)|)|#:| |(|B|,| |A|)| |#=| |(|any|._2|,| |any|._1|)|←|↵|}| //│ Parsed: {class CTX(x, y,) {class A() {fun foo = x}; class B(): A {fun foo = y}; fun foo = (any: '(' A, B, ')',) => '(' (any)._2, (any)._1, ')' : [B, A]}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(_: Var(x), _: Var(y)), (), None, None, TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, [], Var(x)))), NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, [], Var(y)))), NuFunDef(None, foo, [], Lam(Tup(any: Bra(rcd = false, Tup(_: Var(A), _: Var(B)))), Asc(Bra(rcd = false, Tup(_: Sel(Var(any), _2), _: Sel(Var(any), _1))), Tuple(List((None,Field(None,TypeName(B))), (None,Field(None,TypeName(A))))))))))) +//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(_: Var(x), _: Var(y)), (), None, None, TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Var(x)))), NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Var(y)))), NuFunDef(None, foo, None, [], Lam(Tup(any: Bra(rcd = false, Tup(_: Var(A), _: Var(B)))), Asc(Bra(rcd = false, Tup(_: Sel(Var(any), _2), _: Sel(Var(any), _1))), Tuple(List((None,Field(None,TypeName(B))), (None,Field(None,TypeName(A))))))))))) //│ Lifted: //│ TypingUnit { //│ class CTX$1_A$2(par$CTX$1,) {fun foo = ((this).par$CTX$1).x} @@ -34,6 +35,7 @@ class CTX(x, y){ //│ fun foo = (any: '(' CTX$1_A$2, CTX$1_B$3, ')',) => '(' (any)._2, (any)._1, ')' : [CTX$1_B$3, CTX$1_A$2] //│ } //│ } +//│ class CTX(x, y){ class A{ fun foo = x} @@ -43,7 +45,7 @@ class CTX(x, y){ //│ |#class| |CTX|(|x|,| |y|)|{|→|#class| |A|{| |#fun| |foo| |#=| |x|}|↵|#class| |B|#:| |A| |{| |#fun| |foo| |#=| |y|}|↵|#fun| |foo|(|any|#:| |{|p1|#:| |A|,| |p2|#:| |B|}|)|#:| |(|B|,| |A|)| |#=| |(|any|.p2|,| |any|.p1|)|←|↵|}| //│ Parsed: {class CTX(x, y,) {class A() {fun foo = x}; class B(): A {fun foo = y}; fun foo = (any: '{' {p1: A, p2: B} '}',) => '(' (any).p2, (any).p1, ')' : [B, A]}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(_: Var(x), _: Var(y)), (), None, None, TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, [], Var(x)))), NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, [], Var(y)))), NuFunDef(None, foo, [], Lam(Tup(any: Bra(rcd = true, Rcd(Var(p1) = Var(A), Var(p2) = Var(B)))), Asc(Bra(rcd = false, Tup(_: Sel(Var(any), p2), _: Sel(Var(any), p1))), Tuple(List((None,Field(None,TypeName(B))), (None,Field(None,TypeName(A))))))))))) +//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(_: Var(x), _: Var(y)), (), None, None, TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Var(x)))), NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Var(y)))), NuFunDef(None, foo, None, [], Lam(Tup(any: Bra(rcd = true, Rcd(Var(p1) = Var(A), Var(p2) = Var(B)))), Asc(Bra(rcd = false, Tup(_: Sel(Var(any), p2), _: Sel(Var(any), p1))), Tuple(List((None,Field(None,TypeName(B))), (None,Field(None,TypeName(A))))))))))) //│ Lifted: //│ TypingUnit { //│ class CTX$1_A$2(par$CTX$1,) {fun foo = ((this).par$CTX$1).x} @@ -52,6 +54,7 @@ class CTX(x, y){ //│ fun foo = (any: '{' {p1: CTX$1_A$2, p2: CTX$1_B$3} '}',) => '(' (any).p2, (any).p1, ')' : [CTX$1_B$3, CTX$1_A$2] //│ } //│ } +//│ class CTX(x, y){ class A{ fun foo = x} @@ -61,7 +64,7 @@ class CTX(x, y){ //│ |#class| |CTX|(|x|,| |y|)|{|→|#class| |A|{| |#fun| |foo| |#=| |x|}|↵|#class| |B|‹|T|›| |{| |#fun| |foo| |#=| |y|}|↵|#fun| |foo|(|any|#:| |(|A|,| |B|‹|A|›|)|)|#:| |(|(|B|‹|A|›|,| |A|)|,| |A|)| |#=| |(|any|,| |any|._1|)|←|↵|}| //│ Parsed: {class CTX(x, y,) {class A() {fun foo = x}; class B‹T›() {fun foo = y}; fun foo = (any: '(' A, B‹A›, ')',) => '(' any, (any)._1, ')' : [[B[A], A], A]}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(_: Var(x), _: Var(y)), (), None, None, TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, [], Var(x)))), NuTypeDef(class, B, ((None,TypeName(T))), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, [], Var(y)))), NuFunDef(None, foo, [], Lam(Tup(any: Bra(rcd = false, Tup(_: Var(A), _: TyApp(Var(B), List(TypeName(A)))))), Asc(Bra(rcd = false, Tup(_: Var(any), _: Sel(Var(any), _1))), Tuple(List((None,Field(None,Tuple(List((None,Field(None,AppliedType(TypeName(B),List(TypeName(A))))), (None,Field(None,TypeName(A))))))), (None,Field(None,TypeName(A))))))))))) +//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(_: Var(x), _: Var(y)), (), None, None, TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Var(x)))), NuTypeDef(class, B, ((None,TypeName(T))), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Var(y)))), NuFunDef(None, foo, None, [], Lam(Tup(any: Bra(rcd = false, Tup(_: Var(A), _: TyApp(Var(B), List(TypeName(A)))))), Asc(Bra(rcd = false, Tup(_: Var(any), _: Sel(Var(any), _1))), Tuple(List((None,Field(None,Tuple(List((None,Field(None,AppliedType(TypeName(B),List(TypeName(A))))), (None,Field(None,TypeName(A))))))), (None,Field(None,TypeName(A))))))))))) //│ Lifted: //│ TypingUnit { //│ class CTX$1_A$2(par$CTX$1,) {fun foo = ((this).par$CTX$1).x} @@ -70,6 +73,7 @@ class CTX(x, y){ //│ fun foo = (any: '(' CTX$1_A$2, CTX$1_B$3‹CTX$1_A$2›, ')',) => '(' any, (any)._1, ')' : [[CTX$1_B$3[CTX$1_A$2], CTX$1_A$2], CTX$1_A$2] //│ } //│ } +//│ class CTX{ fun ctx(x,y) = @@ -82,7 +86,8 @@ class CTX{ //│ |#class| |CTX|{|→|#fun| |ctx|(|x|,|y|)| |#=| |→|#class| |A|{| |#fun| |foo| |#=| |x| |}|↵|#fun| |bar|‹|T|›|(|any|#:| |T|)|#:| |A| |#=| |→|#let| |x| |#=| |#new| |T|↵|#new| |A|←|↵|(|#new| |CTX|)|.bar|‹|CTX|›|←|←|↵|}| //│ Parsed: {class CTX() {fun ctx = (x, y,) => {class A() {fun foo = x}; fun bar = (any: T,) => {let x = new T() {}; new A() {}} : A; ('(' new CTX() {} ')').bar‹CTX›}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, ctx, [], Lam(Tup(_: Var(x), _: Var(y)), Blk(...)))))) +//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, ctx, None, [], Lam(Tup(_: Var(x), _: Var(y)), Blk(...)))))) //│ Lifted: //│ Lifting failed: mlscript.codegen.CodeGenError: Cannot find type T. Class values are not supported in lifter. +//│ diff --git a/compiler/shared/test/diff/Lifter.mls b/compiler/shared/test/diff/Lifter.mls index 862c4f91a5..0d4b717ab9 100644 --- a/compiler/shared/test/diff/Lifter.mls +++ b/compiler/shared/test/diff/Lifter.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly class A(x) { @@ -26,13 +26,13 @@ class A(x) { fun getA = A(x) } //│ |#class| |A|(|x|)| |{|→|#class| |B|(|y|)| |{|→|#fun| |getX| |#=| |x|↵|#fun| |getB1| |#=| |B1|(|y|)|↵|#class| |C|(|z|)| |{|→|#fun| |inc|(||)| |#=| |x| |+| |1|↵|#fun| |getY| |#=| |y|↵|#fun| |getA| |#=| |A|(|z|)|↵|#fun| |getB|(|w|)| |#=| |B|(|w|)|↵|#fun| |getC| |#=| |#new| |C|(|inc|(||)|)|↵|#fun| |getSelf| |#=| |this|←|↵|}|←|↵|}|↵|#class| |B1|(|y|)| |{|→|#fun| |getX| |#=| |x|↵|#fun| |getY| |#=| |y|↵|#fun| |getB| |#=| |#new| |B|(|y|)|↵|#fun| |getB1| |#=| |#new| |B1|(|y|)|←|↵|}|↵|#fun| |getB| |#=| |#new| |B|(|x|)|↵|#fun| |getB2|(|y|)| |#=| |B1|(|y|)|↵|#fun| |getB3|(|z|)| |#=| |getB2|(|z|)|↵|#fun| |getA| |#=| |A|(|x|)|←|↵|}| -//│ Parsed: {class A(x,) {class B(y,) {fun getX = x; fun getB1 = B1 (y,); class C(z,) {fun inc = () => + (x,) (1,); fun getY = y; fun getA = A (z,); fun getB = (w,) => B (w,); fun getC = new C(inc (),) {}; fun getSelf = this}}; class B1(y,) {fun getX = x; fun getY = y; fun getB = new B(y,) {}; fun getB1 = new B1(y,) {}}; fun getB = new B(x,) {}; fun getB2 = (y,) => B1 (y,); fun getB3 = (z,) => getB2 (z,); fun getA = A (x,)}} +//│ Parsed: {class A(x,) {class B(y,) {fun getX = x; fun getB1 = B1 (y,); class C(z,) {fun inc = () => + (x, 1,); fun getY = y; fun getA = A (z,); fun getB = (w,) => B (w,); fun getC = new C(inc (),) {}; fun getSelf = this}}; class B1(y,) {fun getX = x; fun getY = y; fun getB = new B(y,) {}; fun getB1 = new B1(y,) {}}; fun getB = new B(x,) {}; fun getB2 = (y,) => B1 (y,); fun getB3 = (z,) => getB2 (z,); fun getA = A (x,)}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(_: Var(y)), (), None, None, TypingUnit(NuFunDef(None, getX, [], Var(x)), NuFunDef(None, getB1, [], App(Var(B1), Tup(_: Var(y)))), NuTypeDef(class, C, (), Tup(_: Var(z)), (), None, None, TypingUnit(NuFunDef(None, inc, [], Lam(Tup(), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1))))), NuFunDef(None, getY, [], Var(y)), NuFunDef(None, getA, [], App(Var(A), Tup(_: Var(z)))), NuFunDef(None, getB, [], Lam(Tup(_: Var(w)), App(Var(B), Tup(_: Var(w))))), NuFunDef(None, getC, [], New(Some((TypeName(C),inc (),)), TypingUnit(List()))), NuFunDef(None, getSelf, [], Var(this)))))), NuTypeDef(class, B1, (), Tup(_: Var(y)), (), None, None, TypingUnit(NuFunDef(None, getX, [], Var(x)), NuFunDef(None, getY, [], Var(y)), NuFunDef(None, getB, [], New(Some((TypeName(B),y,)), TypingUnit(List()))), NuFunDef(None, getB1, [], New(Some((TypeName(B1),y,)), TypingUnit(List()))))), NuFunDef(None, getB, [], New(Some((TypeName(B),x,)), TypingUnit(List()))), NuFunDef(None, getB2, [], Lam(Tup(_: Var(y)), App(Var(B1), Tup(_: Var(y))))), NuFunDef(None, getB3, [], Lam(Tup(_: Var(z)), App(Var(getB2), Tup(_: Var(z))))), NuFunDef(None, getA, [], App(Var(A), Tup(_: Var(x))))))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(_: Var(y)), (), None, None, TypingUnit(NuFunDef(None, getX, None, [], Var(x)), NuFunDef(None, getB1, None, [], App(Var(B1), Tup(_: Var(y)))), NuTypeDef(class, C, (), Tup(_: Var(z)), (), None, None, TypingUnit(NuFunDef(None, inc, None, [], Lam(Tup(), App(Var(+), Tup(_: Var(x), _: IntLit(1))))), NuFunDef(None, getY, None, [], Var(y)), NuFunDef(None, getA, None, [], App(Var(A), Tup(_: Var(z)))), NuFunDef(None, getB, None, [], Lam(Tup(_: Var(w)), App(Var(B), Tup(_: Var(w))))), NuFunDef(None, getC, None, [], New(Some((TypeName(C),inc (),)), TypingUnit(List()))), NuFunDef(None, getSelf, None, [], Var(this)))))), NuTypeDef(class, B1, (), Tup(_: Var(y)), (), None, None, TypingUnit(NuFunDef(None, getX, None, [], Var(x)), NuFunDef(None, getY, None, [], Var(y)), NuFunDef(None, getB, None, [], New(Some((TypeName(B),y,)), TypingUnit(List()))), NuFunDef(None, getB1, None, [], New(Some((TypeName(B1),y,)), TypingUnit(List()))))), NuFunDef(None, getB, None, [], New(Some((TypeName(B),x,)), TypingUnit(List()))), NuFunDef(None, getB2, None, [], Lam(Tup(_: Var(y)), App(Var(B1), Tup(_: Var(y))))), NuFunDef(None, getB3, None, [], Lam(Tup(_: Var(z)), App(Var(getB2), Tup(_: Var(z))))), NuFunDef(None, getA, None, [], App(Var(A), Tup(_: Var(x))))))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2_C$4(par$A$1_B$2, z,) { -//│ fun inc = () => + ((((this).par$A$1_B$2).par$A$1).x,) (1,) +//│ fun inc = () => + ((((this).par$A$1_B$2).par$A$1).x, 1,) //│ fun getY = ((this).par$A$1_B$2).y //│ fun getA = A$1 ((this).z,) //│ fun getB = (w,) => A$1_B$2 (((this).par$A$1_B$2).par$A$1, w,) @@ -56,6 +56,7 @@ class A(x) { //│ fun getA = A$1 ((this).x,) //│ } //│ } +//│ class A(x) { class B(y) { @@ -65,17 +66,18 @@ class A(x) { } } //│ |#class| |A|(|x|)| |{|→|#class| |B|(|y|)| |{|→|#class| |C|(|z|)| |{|→|#fun| |sum| |#=| |x| |+| |y| |+| |z|←|↵|}|←|↵|}|←|↵|}| -//│ Parsed: {class A(x,) {class B(y,) {class C(z,) {fun sum = + (+ (x,) (y,),) (z,)}}}} +//│ Parsed: {class A(x,) {class B(y,) {class C(z,) {fun sum = + (+ (x, y,), z,)}}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(_: Var(y)), (), None, None, TypingUnit(NuTypeDef(class, C, (), Tup(_: Var(z)), (), None, None, TypingUnit(NuFunDef(None, sum, [], App(App(Var(+), Tup(_: App(App(Var(+), Tup(_: Var(x))), Tup(_: Var(y))))), Tup(_: Var(z))))))))))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(_: Var(y)), (), None, None, TypingUnit(NuTypeDef(class, C, (), Tup(_: Var(z)), (), None, None, TypingUnit(NuFunDef(None, sum, None, [], App(Var(+), Tup(_: App(Var(+), Tup(_: Var(x), _: Var(y))), _: Var(z))))))))))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2_C$3(par$A$1_B$2, z,) { -//│ fun sum = + (+ ((((this).par$A$1_B$2).par$A$1).x,) (((this).par$A$1_B$2).y,),) ((this).z,) +//│ fun sum = + (+ ((((this).par$A$1_B$2).par$A$1).x, ((this).par$A$1_B$2).y,), (this).z,) //│ } //│ class A$1_B$2(par$A$1, y,) {} //│ class A$1(x,) {} //│ } +//│ class A(x) { @@ -106,9 +108,10 @@ new C{ //│ |#class| |A|(|x|)| |{|→|#class| |B|{|→|#fun| |foo| |#=| |1|↵|#fun| |bar| |#=| |11|←|↵|}|↵|#fun| |getB| |#=| |#new| |B|{|→|#fun| |foo| |#=| |2|↵|#fun| |bar| |#=| |12|←|↵|}|↵|#fun| |bar| |#=| |13|←|↵|}|↵|#class| |C|#:| |A|{|→|#fun| |getB| |#=| |#new| |B|{|→|#fun| |foo| |#=| |3|↵|#fun| |bar| |#=| |14|←|↵|}|↵|#fun| |bar| |#=| |15|←|↵|}|↵|#new| |C|{|→|#fun| |getB| |#=| |#new| |B|{|→|#fun| |foo| |#=| |4|↵|#fun| |bar| |#=| |16|←|↵|}|↵|#fun| |bar| |#=| |17|←|↵|}| //│ Parsed: {class A(x,) {class B() {fun foo = 1; fun bar = 11}; fun getB = new B() {fun foo = 2; fun bar = 12}; fun bar = 13}; class C(): A {fun getB = new B() {fun foo = 3; fun bar = 14}; fun bar = 15}; new C() {fun getB = new B() {fun foo = 4; fun bar = 16}; fun bar = 17}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, [], IntLit(1)), NuFunDef(None, bar, [], IntLit(11)))), NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(List(fun foo = 2, fun bar = 12)))), NuFunDef(None, bar, [], IntLit(13)))), NuTypeDef(class, C, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(List(fun foo = 3, fun bar = 14)))), NuFunDef(None, bar, [], IntLit(15)))), New(Some((TypeName(C),)), TypingUnit(List(fun getB = new B() {fun foo = 4; fun bar = 16}, fun bar = 17)))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], IntLit(1)), NuFunDef(None, bar, None, [], IntLit(11)))), NuFunDef(None, getB, None, [], New(Some((TypeName(B),)), TypingUnit(List(fun foo = 2, fun bar = 12)))), NuFunDef(None, bar, None, [], IntLit(13)))), NuTypeDef(class, C, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, getB, None, [], New(Some((TypeName(B),)), TypingUnit(List(fun foo = 3, fun bar = 14)))), NuFunDef(None, bar, None, [], IntLit(15)))), New(Some((TypeName(C),)), TypingUnit(List(fun getB = new B() {fun foo = 4; fun bar = 16}, fun bar = 17)))) //│ Lifted: //│ Lifting failed: java.util.NoSuchElementException: None.get +//│ @@ -120,17 +123,18 @@ class Parent(x) { } } //│ |#class| |Parent|‹|T|,| |U|,| |V|›|(|x|)| |{| |→|#fun| |foo|(|x|#:| |Int|)|#:| |T| |#=| |x|+|1|↵|#class| |Inner|‹|W|›|(|y|#:| |Int|)|{|→|#fun| |bar|(|z|#:| |U|)| |#=| |foo|(|y|)|↵|#fun| |boo|(|z|#:| |W|)| |#=| |z|←|↵|}|←|↵|}| -//│ Parsed: {class Parent‹T, U, V›(x,) {fun foo = (x: Int,) => + (x,) (1,) : T; class Inner‹W›(y: Int,) {fun bar = (z: U,) => foo (y,); fun boo = (z: W,) => z}}} +//│ Parsed: {class Parent‹T, U, V›(x,) {fun foo = (x: Int,) => + (x, 1,) : T; class Inner‹W›(y: Int,) {fun bar = (z: U,) => foo (y,); fun boo = (z: W,) => z}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Parent, ((None,TypeName(T)), (None,TypeName(U)), (None,TypeName(V))), Tup(_: Var(x)), (), None, None, TypingUnit(NuFunDef(None, foo, [], Lam(Tup(x: Var(Int)), Asc(App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1))), TypeName(T)))), NuTypeDef(class, Inner, ((None,TypeName(W))), Tup(y: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, bar, [], Lam(Tup(z: Var(U)), App(Var(foo), Tup(_: Var(y))))), NuFunDef(None, boo, [], Lam(Tup(z: Var(W)), Var(z)))))))) +//│ TypingUnit(NuTypeDef(class, Parent, ((None,TypeName(T)), (None,TypeName(U)), (None,TypeName(V))), Tup(_: Var(x)), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(x: Var(Int)), Asc(App(Var(+), Tup(_: Var(x), _: IntLit(1))), TypeName(T)))), NuTypeDef(class, Inner, ((None,TypeName(W))), Tup(y: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, bar, None, [], Lam(Tup(z: Var(U)), App(Var(foo), Tup(_: Var(y))))), NuFunDef(None, boo, None, [], Lam(Tup(z: Var(W)), Var(z)))))))) //│ Lifted: //│ TypingUnit { //│ class Parent$1_Inner$2[W,U](par$Parent$1, y: Int,) { //│ fun bar = (z: U,) => ((this).par$Parent$1).foo ((this).y,) //│ fun boo = (z: W,) => z //│ } -//│ class Parent$1[T,U,V](x,) {fun foo = (x: Int,) => + (x,) (1,) : T} +//│ class Parent$1[T,U,V](x,) {fun foo = (x: Int,) => + (x, 1,) : T} //│ } +//│ class B {} @@ -142,9 +146,9 @@ class A(x: Int): {a1: Int} & B & D(x){ } } //│ |#class| |B|‹|T|›| |{||}|↵|#class| |C| |{||}|↵|#class| |D|(|y|#:| |Int|)| |{||}|↵|#class| |A|‹|T|,| |U|›|(|x|#:| |Int|)|#:| |{|a1|#:| |Int|}| |&| |B|‹|T|›| |&| |D|(|x|)|{|→|#fun| |getA|(||)| |#=| |#new| |C|{|→|#fun| |foo|(|x|#:| |T|)| |#=| |x|←|↵|}|←|↵|}| -//│ Parsed: {class B‹T›() {}; class C() {}; class D(y: Int,) {}; class A‹T, U›(x: Int,): {a1: Int} & B[T] & D[[x]] {fun getA = () => new C() {fun foo = (x: T,) => x}}} +//│ Parsed: {class B‹T›() {}; class C() {}; class D(y: Int,) {}; class A‹T, U›(x: Int,): {a1: Int} & B[T] & D[x] {fun getA = () => new C() {fun foo = (x: T,) => x}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, B, ((None,TypeName(T))), Tup(), (), None, None, TypingUnit()), NuTypeDef(class, C, (), Tup(), (), None, None, TypingUnit()), NuTypeDef(class, D, (), Tup(y: Var(Int)), (), None, None, TypingUnit()), NuTypeDef(class, A, ((None,TypeName(T)), (None,TypeName(U))), Tup(x: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = (x: T,) => x)))))))) +//│ TypingUnit(NuTypeDef(class, B, ((None,TypeName(T))), Tup(), (), None, None, TypingUnit()), NuTypeDef(class, C, (), Tup(), (), None, None, TypingUnit()), NuTypeDef(class, D, (), Tup(y: Var(Int)), (), None, None, TypingUnit()), NuTypeDef(class, A, ((None,TypeName(T)), (None,TypeName(U))), Tup(x: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, getA, None, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = (x: T,) => x)))))))) //│ Lifted: //│ TypingUnit { //│ class B$1[T]() {} @@ -153,6 +157,7 @@ class A(x: Int): {a1: Int} & B & D(x){ //│ class A$4_C$1$5[T](par$A$4,): C$2 () {fun foo = (x: T,) => x} //│ class A$4[T,U](x: Int,) {fun getA = () => {new A$4_C$1$5(this,) {}}} //│ } +//│ // │ TypingUnit(NuTypeDef(class, B, (TypeName(T)), Tup(), (), TypingUnit()), NuTypeDef(class, C, (), Tup(), (), TypingUnit()), NuTypeDef(class, A, (TypeName(T), TypeName(U)), Tup(x: Var(Int)), (App(App(Var(&), Tup(_: Bra(rcd = true, Rcd(Var(a1) = Var(Int)})))), Tup(_: TyApp(Var(B), List(TypeName(T)))))), TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = x: T, => x)))))))) class B {} @@ -166,7 +171,7 @@ class A(x: Int) extends {a1: Int}, B, D(x){ //│ |#class| |B|‹|T|›| |{||}|↵|#class| |C| |{||}|↵|#class| |D|(|y|#:| |Int|)| |{||}|↵|#class| |A|‹|T|,| |U|›|(|x|#:| |Int|)| |#extends| |{|a1|#:| |Int|}|,| |B|‹|T|›|,| |D|(|x|)|{|→|#fun| |getA|(||)| |#=| |#new| |C|{|→|#fun| |foo|(|x|)| |#=| |x|←|↵|}|←|↵|}| //│ Parsed: {class B‹T›() {}; class C() {}; class D(y: Int,) {}; class A‹T, U›(x: Int,): '{' {a1: Int} '}', B‹T›, D (x,) {fun getA = () => new C() {fun foo = (x,) => x}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, B, ((None,TypeName(T))), Tup(), (), None, None, TypingUnit()), NuTypeDef(class, C, (), Tup(), (), None, None, TypingUnit()), NuTypeDef(class, D, (), Tup(y: Var(Int)), (), None, None, TypingUnit()), NuTypeDef(class, A, ((None,TypeName(T)), (None,TypeName(U))), Tup(x: Var(Int)), (Bra(rcd = true, Rcd(Var(a1) = Var(Int))), TyApp(Var(B), List(TypeName(T))), App(Var(D), Tup(_: Var(x)))), None, None, TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = (x,) => x)))))))) +//│ TypingUnit(NuTypeDef(class, B, ((None,TypeName(T))), Tup(), (), None, None, TypingUnit()), NuTypeDef(class, C, (), Tup(), (), None, None, TypingUnit()), NuTypeDef(class, D, (), Tup(y: Var(Int)), (), None, None, TypingUnit()), NuTypeDef(class, A, ((None,TypeName(T)), (None,TypeName(U))), Tup(x: Var(Int)), (Bra(rcd = true, Rcd(Var(a1) = Var(Int))), TyApp(Var(B), List(TypeName(T))), App(Var(D), Tup(_: Var(x)))), None, None, TypingUnit(NuFunDef(None, getA, None, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = (x,) => x)))))))) //│ Lifted: //│ TypingUnit { //│ class B$1[T]() {} @@ -175,6 +180,7 @@ class A(x: Int) extends {a1: Int}, B, D(x){ //│ class A$4_C$1$5(par$A$4,): C$2 () {fun foo = (x,) => x} //│ class A$4[T,U](x: Int,): '{' {a1: Int} '}', B$1 ()‹T›, D$3 ((this).x,) {fun getA = () => {new A$4_C$1$5(this,) {}}} //│ } +//│ class Child(x): { age: T } & { name: String} { class Inner{ @@ -186,7 +192,7 @@ class Child(x): { age: T } & { name: String} { //│ |#class| |Child|‹|T|,| |U|›|(|x|)|#:| |{| |age|#:| |T| |}| |&| |{| |name|#:| |String|}| |{|→|#class| |Inner|{|→|#fun| |foo| |#=| |age|←|↵|}|↵|#fun| |bar| |#=| |age|↵|#fun| |boo| |#=| |#new| |Inner|←|↵|}| //│ Parsed: {class Child‹T, U›(x,): {age: T} & {name: String} {class Inner() {fun foo = age}; fun bar = age; fun boo = new Inner() {}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Child, ((None,TypeName(T)), (None,TypeName(U))), Tup(_: Var(x)), (), None, None, TypingUnit(NuTypeDef(class, Inner, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, [], Var(age)))), NuFunDef(None, bar, [], Var(age)), NuFunDef(None, boo, [], New(Some((TypeName(Inner),)), TypingUnit(List())))))) +//│ TypingUnit(NuTypeDef(class, Child, ((None,TypeName(T)), (None,TypeName(U))), Tup(_: Var(x)), (), None, None, TypingUnit(NuTypeDef(class, Inner, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Var(age)))), NuFunDef(None, bar, None, [], Var(age)), NuFunDef(None, boo, None, [], New(Some((TypeName(Inner),)), TypingUnit(List())))))) //│ Lifted: //│ TypingUnit { //│ class Child$1_Inner$2(par$Child$1, age,) {fun foo = (this).age} @@ -195,6 +201,7 @@ class Child(x): { age: T } & { name: String} { //│ fun boo = new Child$1_Inner$2(this, age,) {} //│ } //│ } +//│ class A(x: Int) { @@ -208,13 +215,14 @@ new A(0) { //│ |#class| |A|(|x|#:| |Int|)| |{|→|#fun| |getA|#:| |Int| |#=| |0|↵|#fun| |getA1| |#=| |1|←|↵|}|↵|#new| |A|(|0|)| |{|→|#fun| |getA| |#=| |3|↵|#fun| |getA2| |#=| |2|←|↵|}| //│ Parsed: {class A(x: Int,) {fun getA = 0 : Int; fun getA1 = 1}; new A(0,) {fun getA = 3; fun getA2 = 2}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(x: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, getA, [], Asc(IntLit(0), TypeName(Int))), NuFunDef(None, getA1, [], IntLit(1)))), New(Some((TypeName(A),0,)), TypingUnit(List(fun getA = 3, fun getA2 = 2)))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(x: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, getA, None, [], Asc(IntLit(0), TypeName(Int))), NuFunDef(None, getA1, None, [], IntLit(1)))), New(Some((TypeName(A),0,)), TypingUnit(List(fun getA = 3, fun getA2 = 2)))) //│ Lifted: //│ TypingUnit { //│ class A$1(x: Int,) {fun getA = 0 : Int; fun getA1 = 1} //│ class A$1$2(x: Int,): A$1 ((this).x,) {fun getA = 3; fun getA2 = 2} //│ Code(List({new A$1$2(0,) {}})) //│ } +//│ class A(x) { @@ -237,6 +245,7 @@ new A(1) { //│ class A$1$3(x,): A$1 ((this).x,) {fun getB = {new A$1$3_B$2$4(this, 2,) {}}} //│ Code(List({new A$1$3(1,) {}})) //│ } +//│ @@ -258,21 +267,22 @@ new B{ fun getA = funcB } //│ |#class| |A| |{|→|#fun| |getA| |#=| |0|↵|#fun| |funcA| |#=| |10|←|↵|}|↵|#class| |B|#:| |A|{|→|#fun| |getA| |#=| |1|↵|#fun| |funcB| |#=| |11|←|↵|}|↵|#new| |A|↵|#new| |B|↵|#fun| |f|(|x|)| |#=| |#if| |x| |is| |A| |#then| |0| |#else| |1|↵|f|(|#new| |A|{|→|#fun| |getA| |#=| |2|←|↵|}|)|↵|#new| |B|{|→|#fun| |getA| |#=| |funcB|←|↵|}| -//│ Parsed: {class A() {fun getA = 0; fun funcA = 10}; class B(): A {fun getA = 1; fun funcB = 11}; new A() {}; new B() {}; fun f = (x,) => if (is (x,) (A,)) then 0 else 1; f (new A() {fun getA = 2},); new B() {fun getA = funcB}} +//│ Parsed: {class A() {fun getA = 0; fun funcA = 10}; class B(): A {fun getA = 1; fun funcB = 11}; new A() {}; new B() {}; fun f = (x,) => if (is (x, A,)) then 0 else 1; f (new A() {fun getA = 2},); new B() {fun getA = funcB}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, getA, [], IntLit(0)), NuFunDef(None, funcA, [], IntLit(10)))), NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, getA, [], IntLit(1)), NuFunDef(None, funcB, [], IntLit(11)))), New(Some((TypeName(A),)), TypingUnit(List())), New(Some((TypeName(B),)), TypingUnit(List())), NuFunDef(None, f, [], Lam(Tup(_: Var(x)), If(IfThen(App(App(Var(is), Tup(_: Var(x))), Tup(_: Var(A))), IntLit(0), Some(IntLit(1))))), App(Var(f), Tup(_: New(Some((TypeName(A),)), TypingUnit(List(fun getA = 2))))), New(Some((TypeName(B),)), TypingUnit(List(fun getA = funcB)))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, getA, None, [], IntLit(0)), NuFunDef(None, funcA, None, [], IntLit(10)))), NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, getA, None, [], IntLit(1)), NuFunDef(None, funcB, None, [], IntLit(11)))), New(Some((TypeName(A),)), TypingUnit(List())), New(Some((TypeName(B),)), TypingUnit(List())), NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), If(IfThen(App(Var(is), Tup(_: Var(x), _: Var(A))), IntLit(0), Some(IntLit(1))))), App(Var(f), Tup(_: New(Some((TypeName(A),)), TypingUnit(List(fun getA = 2))))), New(Some((TypeName(B),)), TypingUnit(List(fun getA = funcB)))) //│ Lifted: //│ TypingUnit { //│ class A$1() {fun getA = 0; fun funcA = 10} //│ class B$2() {fun getA = 1; fun funcB = 11} //│ class A$1$3(): A$1 () {fun getA = 2} //│ class B$2$4(): B$2 () {fun getA = (this).funcB} -//│ fun f = (x,) => if (is (x,) (A$1 (),)) then 0 else 1 +//│ fun f = (x,) => if (is (x, A$1 (),)) then 0 else 1 //│ Code(List(new A$1() {})) //│ Code(List(new B$2() {})) //│ Code(List(f ({new A$1$3() {}},))) //│ Code(List({new B$2$4() {}})) //│ } +//│ class A{ @@ -300,7 +310,7 @@ class A{ //│ |#class| |A|{|→|#class| |B|{|→|#fun| |funB| |#=| |1|↵|#fun| |foo| |#=| |100|←|↵|}|↵|#class| |C|#:| |B|{|→|#fun| |funC| |#=| |2|↵|#fun| |foo| |#=| |1000|←|↵|}|↵|#class| |D|{|→|#fun| |funD| |#=| |3|↵|#fun| |foo| |#=| |10000| |↵|#class| |E|#:| |C|{|→|#fun| |funE| |#=| |4|↵|#fun| |foo| |#=| |100000|←|↵|}|↵|#class| |F|#:| |E|{|→|#fun| |funF| |#=| |5|↵|#fun| |foo| |#=| |1000000|←|↵|}|←|↵|}|←|↵|}| //│ Parsed: {class A() {class B() {fun funB = 1; fun foo = 100}; class C(): B {fun funC = 2; fun foo = 1000}; class D() {fun funD = 3; fun foo = 10000; class E(): C {fun funE = 4; fun foo = 100000}; class F(): E {fun funF = 5; fun foo = 1000000}}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funB, [], IntLit(1)), NuFunDef(None, foo, [], IntLit(100)))), NuTypeDef(class, C, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funC, [], IntLit(2)), NuFunDef(None, foo, [], IntLit(1000)))), NuTypeDef(class, D, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funD, [], IntLit(3)), NuFunDef(None, foo, [], IntLit(10000)), NuTypeDef(class, E, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funE, [], IntLit(4)), NuFunDef(None, foo, [], IntLit(100000)))), NuTypeDef(class, F, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funF, [], IntLit(5)), NuFunDef(None, foo, [], IntLit(1000000))))))))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funB, None, [], IntLit(1)), NuFunDef(None, foo, None, [], IntLit(100)))), NuTypeDef(class, C, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funC, None, [], IntLit(2)), NuFunDef(None, foo, None, [], IntLit(1000)))), NuTypeDef(class, D, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funD, None, [], IntLit(3)), NuFunDef(None, foo, None, [], IntLit(10000)), NuTypeDef(class, E, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funE, None, [], IntLit(4)), NuFunDef(None, foo, None, [], IntLit(100000)))), NuTypeDef(class, F, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funF, None, [], IntLit(5)), NuFunDef(None, foo, None, [], IntLit(1000000))))))))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2(par$A$1,) {fun funB = 1; fun foo = 100} @@ -310,6 +320,7 @@ class A{ //│ class A$1_D$4(par$A$1,) {fun funD = 3; fun foo = 10000} //│ class A$1() {} //│ } +//│ class A{ @@ -342,7 +353,7 @@ class A{ //│ |#class| |A|{|→|#class| |B|{|→|#fun| |funB| |#=| |1|↵|#fun| |foo| |#=| |100|←|↵|}|↵|#class| |C|#:| |B|{|→|#fun| |funC| |#=| |2|↵|#fun| |foo| |#=| |1000|↵|#fun| |getB| |#=| |#new| |B|←|↵|}|↵|#class| |D|{|→|#fun| |funD| |#=| |3|↵|#fun| |foo| |#=| |10000| |↵|#class| |E|#:| |C|{|→|#fun| |funE| |#=| |4|↵|#fun| |foo| |#=| |100000|↵|#fun| |getD| |#=| |#new| |D|←|↵|}|↵|#class| |F|#:| |E|{|→|#fun| |funF| |#=| |5|↵|#fun| |foo| |#=| |1000000|↵|#fun| |getE| |#=| |#new| |E|{|→|#fun| |foo| |#=| |0|←|↵|}|←|↵|}|←|↵|}|←|↵|}| //│ Parsed: {class A() {class B() {fun funB = 1; fun foo = 100}; class C(): B {fun funC = 2; fun foo = 1000; fun getB = new B() {}}; class D() {fun funD = 3; fun foo = 10000; class E(): C {fun funE = 4; fun foo = 100000; fun getD = new D() {}}; class F(): E {fun funF = 5; fun foo = 1000000; fun getE = new E() {fun foo = 0}}}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funB, [], IntLit(1)), NuFunDef(None, foo, [], IntLit(100)))), NuTypeDef(class, C, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funC, [], IntLit(2)), NuFunDef(None, foo, [], IntLit(1000)), NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(List()))))), NuTypeDef(class, D, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funD, [], IntLit(3)), NuFunDef(None, foo, [], IntLit(10000)), NuTypeDef(class, E, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funE, [], IntLit(4)), NuFunDef(None, foo, [], IntLit(100000)), NuFunDef(None, getD, [], New(Some((TypeName(D),)), TypingUnit(List()))))), NuTypeDef(class, F, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funF, [], IntLit(5)), NuFunDef(None, foo, [], IntLit(1000000)), NuFunDef(None, getE, [], New(Some((TypeName(E),)), TypingUnit(List(fun foo = 0))))))))))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funB, None, [], IntLit(1)), NuFunDef(None, foo, None, [], IntLit(100)))), NuTypeDef(class, C, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funC, None, [], IntLit(2)), NuFunDef(None, foo, None, [], IntLit(1000)), NuFunDef(None, getB, None, [], New(Some((TypeName(B),)), TypingUnit(List()))))), NuTypeDef(class, D, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funD, None, [], IntLit(3)), NuFunDef(None, foo, None, [], IntLit(10000)), NuTypeDef(class, E, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funE, None, [], IntLit(4)), NuFunDef(None, foo, None, [], IntLit(100000)), NuFunDef(None, getD, None, [], New(Some((TypeName(D),)), TypingUnit(List()))))), NuTypeDef(class, F, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, funF, None, [], IntLit(5)), NuFunDef(None, foo, None, [], IntLit(1000000)), NuFunDef(None, getE, None, [], New(Some((TypeName(E),)), TypingUnit(List(fun foo = 0))))))))))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2(par$A$1,) {fun funB = 1; fun foo = 100} @@ -365,6 +376,7 @@ class A{ //│ class A$1_D$4(par$A$1,) {fun funD = 3; fun foo = 10000} //│ class A$1() {} //│ } +//│ class A{ @@ -377,13 +389,14 @@ new A //│ |#class| |A|{|→|#class| |B|{|→|#fun| |foo| |#=| |1|←|↵|}|↵|#fun| |bar| |#=| |#new| |B|←|↵|}|↵|#new| |A| //│ Parsed: {class A() {class B() {fun foo = 1}; fun bar = new B() {}}; new A() {}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, [], IntLit(1)))), NuFunDef(None, bar, [], New(Some((TypeName(B),)), TypingUnit(List()))))), New(Some((TypeName(A),)), TypingUnit(List()))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], IntLit(1)))), NuFunDef(None, bar, None, [], New(Some((TypeName(B),)), TypingUnit(List()))))), New(Some((TypeName(A),)), TypingUnit(List()))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2(par$A$1,) {fun foo = 1} //│ class A$1() {fun bar = new A$1_B$2(this,) {}} //│ Code(List(new A$1() {})) //│ } +//│ class A(x) { @@ -399,15 +412,15 @@ let x = new A{ } } //│ |#class| |A|(|x|)| |{|→|#fun| |foo| |#=| |0|↵|#fun| |bar| |#=| |x|←|↵|}|↵|#let| |x| |#=| |#new| |A|{|→|#fun| |foo| |#=| |1|↵|#fun| |newFun| |#=| |2|↵|#fun| |bar| |#=| |#new| |A|(|foo|)|{|→|#fun| |foo| |#=| |bar| |+| |1|↵|#fun| |bar2| |#=| |newFun| |+| |1|←|↵|}|←|↵|}| -//│ Parsed: {class A(x,) {fun foo = 0; fun bar = x}; let x = new A() {fun foo = 1; fun newFun = 2; fun bar = new A(foo,) {fun foo = + (bar,) (1,); fun bar2 = + (newFun,) (1,)}}} +//│ Parsed: {class A(x,) {fun foo = 0; fun bar = x}; let x = new A() {fun foo = 1; fun newFun = 2; fun bar = new A(foo,) {fun foo = + (bar, 1,); fun bar2 = + (newFun, 1,)}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), None, None, TypingUnit(NuFunDef(None, foo, [], IntLit(0)), NuFunDef(None, bar, [], Var(x)))), NuFunDef(Some(false), x, [], New(Some((TypeName(A),)), TypingUnit(List(fun foo = 1, fun newFun = 2, fun bar = new A(foo,) {fun foo = + (bar,) (1,); fun bar2 = + (newFun,) (1,)}))))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], IntLit(0)), NuFunDef(None, bar, None, [], Var(x)))), NuFunDef(Some(false), x, None, [], New(Some((TypeName(A),)), TypingUnit(List(fun foo = 1, fun newFun = 2, fun bar = new A(foo,) {fun foo = + (bar, 1,); fun bar2 = + (newFun, 1,)}))))) //│ Lifted: //│ TypingUnit { //│ class A$1(x,) {fun foo = 0; fun bar = (this).x} //│ class A$1$2_A$2$3(par$A$1$2, x,): A$1 ((this).x,) { -//│ fun foo = + ((this).bar,) (1,) -//│ fun bar2 = + (((this).par$A$1$2).newFun,) (1,) +//│ fun foo = + ((this).bar, 1,) +//│ fun bar2 = + (((this).par$A$1$2).newFun, 1,) //│ } //│ class A$1$2(x,): A$1 ((this).x,) { //│ fun foo = 1 @@ -416,6 +429,7 @@ let x = new A{ //│ } //│ let x = {new A$1$2() {}} //│ } +//│ class A {} new A{ @@ -460,4 +474,5 @@ new A{ //│ class A$1$2(): A$1 () {fun foo = 1; fun bar = {new A$1$2_A$2$3(this,) {}}} //│ Code(List({new A$1$2() {}})) //│ } +//│ diff --git a/compiler/shared/test/diff/LifterBlks.mls b/compiler/shared/test/diff/LifterBlks.mls index 6089f19262..bc45be8120 100644 --- a/compiler/shared/test/diff/LifterBlks.mls +++ b/compiler/shared/test/diff/LifterBlks.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly fun foo = @@ -7,9 +7,10 @@ fun foo = //│ |#fun| |foo| |#=|→|print|(|"ok"|)|↵|print|(|"ko"|)|←| //│ Parsed: {fun foo = {print ("ok",); print ("ko",)}} //│ Parsed: -//│ TypingUnit(NuFunDef(None, foo, [], Blk(...))) +//│ TypingUnit(NuFunDef(None, foo, None, [], Blk(...))) //│ Lifted: //│ TypingUnit {fun foo = {print ("ok",); print ("ko",)}} +//│ class A{ class B {} @@ -18,12 +19,13 @@ class A{ //│ |#class| |A|{|→|#class| |B| |{||}|↵|#fun| |foo|(|x|#:| |B|)| |#=| |(|x|#:|B|)|←|↵|}| //│ Parsed: {class A() {class B() {}; fun foo = (x: B,) => '(' x: B, ')'}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit()), NuFunDef(None, foo, [], Lam(Tup(x: Var(B)), Bra(rcd = false, Tup(x: Var(B)))))))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit()), NuFunDef(None, foo, None, [], Lam(Tup(x: Var(B)), Bra(rcd = false, Tup(x: Var(B)))))))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2(par$A$1,) {} //│ class A$1() {fun foo = (x: A$1_B$2,) => '(' x: A$1_B$2, ')'} //│ } +//│ fun foo = fun local(x) = @@ -37,29 +39,31 @@ fun foo = print of local of 0 + local of 1 fun tmp = 2 //│ |#fun| |foo| |#=|→|#fun| |local|(|x|)| |#=|→|#class| |Foo| |{|→|#fun| |bar| |#=| |x| |+| |1|←|↵|}|↵|Foo|(||)|.bar|←|↵|print| |#of| |local|(|0|)| |+| |local|(|1|)|↵|print| |#of| |(|local| |#of| |0|)| |+| |local| |#of| |1|↵|#fun| |tmp| |#=| |1|↵|print| |#of| |local| |#of| |0| |+| |local| |#of| |1|↵|#fun| |tmp| |#=| |2|←| -//│ Parsed: {fun foo = {fun local = (x,) => {class Foo() {fun bar = + (x,) (1,)}; (Foo ()).bar}; print (+ (local (0,),) (local (1,),),); print (+ ('(' local (0,) ')',) (local (1,),),); fun tmp = 1; print (local (+ (0,) (local (1,),),),); fun tmp = 2}} +//│ Parsed: {fun foo = {fun local = (x,) => {class Foo() {fun bar = + (x, 1,)}; (Foo ()).bar}; print (+ (local (0,), local (1,),),); print (+ ('(' local (0,) ')', local (1,),),); fun tmp = 1; print (local (+ (0, local (1,),),),); fun tmp = 2}} //│ Parsed: -//│ TypingUnit(NuFunDef(None, foo, [], Blk(...))) +//│ TypingUnit(NuFunDef(None, foo, None, [], Blk(...))) //│ Lifted: //│ TypingUnit { -//│ class Foo$1(x,) {fun bar = + ((this).x,) (1,)} -//│ fun foo = {fun local = (x,) => {(Foo$1 (x,)).bar}; fun tmp = 1; fun tmp = 2; print (+ (local (0,),) (local (1,),),); print (+ ('(' local (0,) ')',) (local (1,),),); print (local (+ (0,) (local (1,),),),)} +//│ class Foo$1(x,) {fun bar = + ((this).x, 1,)} +//│ fun foo = {fun local = (x,) => {(Foo$1 (x,)).bar}; fun tmp = 1; fun tmp = 2; print (+ (local (0,), local (1,),),); print (+ ('(' local (0,) ')', local (1,),),); print (local (+ (0, local (1,),),),)} //│ } +//│ class A(y){} let f = x => new A(0){fun bar = x+y} f(0) //│ |#class| |A|(|y|)|{||}|↵|#let| |f| |#=| |x| |=>| |#new| |A|(|0|)|{|#fun| |bar| |#=| |x|+|y|}|↵|f|(|0|)| -//│ Parsed: {class A(y,) {}; let f = (x,) => new A(0,) {fun bar = + (x,) (y,)}; f (0,)} +//│ Parsed: {class A(y,) {}; let f = (x,) => new A(0,) {fun bar = + (x, y,)}; f (0,)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(y)), (), None, None, TypingUnit()), NuFunDef(Some(false), f, [], Lam(Tup(_: Var(x)), New(Some((TypeName(A),0,)), TypingUnit(List(fun bar = + (x,) (y,)))))), App(Var(f), Tup(_: IntLit(0)))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(y)), (), None, None, TypingUnit()), NuFunDef(Some(false), f, None, [], Lam(Tup(_: Var(x)), New(Some((TypeName(A),0,)), TypingUnit(List(fun bar = + (x, y,)))))), App(Var(f), Tup(_: IntLit(0)))) //│ Lifted: //│ TypingUnit { //│ class A$1(y,) {} -//│ class A$1$2(y, x,): A$1 ((this).y,) {fun bar = + ((this).x,) ((this).y,)} +//│ class A$1$2(y, x,): A$1 ((this).y,) {fun bar = + ((this).x, (this).y,)} //│ let f = (x,) => {new A$1$2(0, x,) {}} //│ Code(List(f (0,))) //│ } +//│ class A(x){ fun w = x @@ -72,22 +76,23 @@ class A(x){ } } //│ |#class| |A|(|x|)|{|→|#fun| |w| |#=| |x|↵|#fun| |foo|(|y|)| |#=| |→|#class| |B|(|z|)|{|→|#fun| |bar| |#=| |x|+|y|+|z|←|↵|}|↵|#new| |B|(|0|)|{|→|#fun| |bar| |#=| |w|+|y|+|z|←|↵|}|←|←|↵|}| -//│ Parsed: {class A(x,) {fun w = x; fun foo = (y,) => {class B(z,) {fun bar = + (+ (x,) (y,),) (z,)}; new B(0,) {fun bar = + (+ (w,) (y,),) (z,)}}}} +//│ Parsed: {class A(x,) {fun w = x; fun foo = (y,) => {class B(z,) {fun bar = + (+ (x, y,), z,)}; new B(0,) {fun bar = + (+ (w, y,), z,)}}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), None, None, TypingUnit(NuFunDef(None, w, [], Var(x)), NuFunDef(None, foo, [], Lam(Tup(_: Var(y)), Blk(...)))))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), None, None, TypingUnit(NuFunDef(None, w, None, [], Var(x)), NuFunDef(None, foo, None, [], Lam(Tup(_: Var(y)), Blk(...)))))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2(par$A$1, z, y,) { -//│ fun bar = + (+ (((this).par$A$1).x,) ((this).y,),) ((this).z,) +//│ fun bar = + (+ (((this).par$A$1).x, (this).y,), (this).z,) //│ } //│ class A$1_B$1$3(par$A$1, z, y,): A$1_B$2 ((this).par$A$1, (this).z, (this).y,) { -//│ fun bar = + (+ (((this).par$A$1).w,) ((this).y,),) ((this).z,) +//│ fun bar = + (+ (((this).par$A$1).w, (this).y,), (this).z,) //│ } //│ class A$1(x,) { //│ fun w = (this).x //│ fun foo = (y,) => {{new A$1_B$1$3(this, 0, y,) {}}} //│ } //│ } +//│ fun f(x,y,z) = class A{ @@ -102,9 +107,9 @@ fun f(x,y,z) = fun bar = bar1 + bar2 } //│ |#fun| |f|(|x|,|y|,|z|)| |#=| |→|#class| |A|{|→|#fun| |foo| |#=| |#new| |B|↵|#fun| |bar1| |#=| |x|←|↵|}|↵|#class| |B|{|→|#fun| |foo| |#=| |#new| |A|↵|#fun| |bar2| |#=| |y|←|↵|}|↵|#class| |C| |#extends| |A|,| |B| |{|→|#fun| |bar| |#=| |bar1| |+| |bar2|←|↵|}|←| -//│ Parsed: {fun f = (x, y, z,) => {class A() {fun foo = new B() {}; fun bar1 = x}; class B() {fun foo = new A() {}; fun bar2 = y}; class C(): A, B {fun bar = + (bar1,) (bar2,)}}} +//│ Parsed: {fun f = (x, y, z,) => {class A() {fun foo = new B() {}; fun bar1 = x}; class B() {fun foo = new A() {}; fun bar2 = y}; class C(): A, B {fun bar = + (bar1, bar2,)}}} //│ Parsed: -//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x), _: Var(y), _: Var(z)), Blk(...)))) +//│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x), _: Var(y), _: Var(z)), Blk(...)))) //│ Lifted: //│ TypingUnit { //│ class A$1(x, y,) { @@ -115,9 +120,10 @@ fun f(x,y,z) = //│ fun foo = new A$1((this).x, (this).y,) {} //│ fun bar2 = (this).y //│ } -//│ class C$3(x, y,): A$1 ((this).x, (this).y,), B$2 ((this).y, (this).x,) {fun bar = + ((this).bar1,) ((this).bar2,)} +//│ class C$3(x, y,): A$1 ((this).x, (this).y,), B$2 ((this).y, (this).x,) {fun bar = + ((this).bar1, (this).bar2,)} //│ fun f = (x, y, z,) => {} //│ } +//│ fun f(x,y,z) = class C{ @@ -132,9 +138,9 @@ fun f(x,y,z) = fun boo = (new A).bar1 + B().bar2 + z } //│ |#fun| |f|(|x|,|y|,|z|)| |#=| |→|#class| |C|{|→|#class| |A|{|→|#fun| |foo| |#=| |#new| |B|↵|#fun| |bar1| |#=| |x|←|↵|}|↵|#class| |B|{|→|#fun| |foo| |#=| |#new| |A|↵|#fun| |bar2| |#=| |y|←|↵|}|↵|#fun| |boo| |#=| |(|#new| |A|)|.bar1| |+| |B|(||)|.bar2| |+| |z|←|↵|}|←| -//│ Parsed: {fun f = (x, y, z,) => {class C() {class A() {fun foo = new B() {}; fun bar1 = x}; class B() {fun foo = new A() {}; fun bar2 = y}; fun boo = + (+ (('(' new A() {} ')').bar1,) ((B ()).bar2,),) (z,)}}} +//│ Parsed: {fun f = (x, y, z,) => {class C() {class A() {fun foo = new B() {}; fun bar1 = x}; class B() {fun foo = new A() {}; fun bar2 = y}; fun boo = + (+ (('(' new A() {} ')').bar1, (B ()).bar2,), z,)}}} //│ Parsed: -//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x), _: Var(y), _: Var(z)), Blk(...)))) +//│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x), _: Var(y), _: Var(z)), Blk(...)))) //│ Lifted: //│ TypingUnit { //│ class C$1_A$2(par$C$1,) { @@ -146,10 +152,11 @@ fun f(x,y,z) = //│ fun bar2 = ((this).par$C$1).y //│ } //│ class C$1(x, y, z,) { -//│ fun boo = + (+ (('(' new C$1_A$2(this,) {} ')').bar1,) ((C$1_B$3 (this,)).bar2,),) ((this).z,) +//│ fun boo = + (+ (('(' new C$1_A$2(this,) {} ')').bar1, (C$1_B$3 (this,)).bar2,), (this).z,) //│ } //│ fun f = (x, y, z,) => {} //│ } +//│ fun f(x) = let g(x) = x + 1 @@ -158,14 +165,15 @@ fun f(x) = } Foo(x).h //│ |#fun| |f|(|x|)| |#=|→|#let| |g|(|x|)| |#=| |x| |+| |1|↵|#class| |Foo|(|x|)| |{|→|#fun| |h| |#=| |g|(|x|)|←|↵|}|↵|Foo|(|x|)|.h|←| -//│ Parsed: {fun f = (x,) => {let g = (x,) => + (x,) (1,); class Foo(x,) {fun h = g (x,)}; (Foo (x,)).h}} +//│ Parsed: {fun f = (x,) => {let g = (x,) => + (x, 1,); class Foo(x,) {fun h = g (x,)}; (Foo (x,)).h}} //│ Parsed: -//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Blk(...)))) +//│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), Blk(...)))) //│ Lifted: //│ TypingUnit { //│ class Foo$1(x, g,) {fun h = (this).g ((this).x,)} -//│ fun f = (x,) => {let g = (x,) => + (x,) (1,); (Foo$1 (x, g,)).h} +//│ fun f = (x,) => {let g = (x,) => + (x, 1,); (Foo$1 (x, g,)).h} //│ } +//│ fun f(x) = let g(x) = @@ -176,24 +184,26 @@ fun f(x) = } Foo(x, x).bar //│ |#fun| |f|(|x|)| |#=|→|#let| |g|(|x|)| |#=| |→|#let| |h|(|x|)| |#=| |x| |+| |2|↵|Foo|(|h|(|x|)|,| |x|)|.bar|←|↵|#class| |Foo|(|x|,| |y|)| |{|→|#fun| |bar| |#=| |g|(|x|)|+|y|←|↵|}|↵|Foo|(|x|,| |x|)|.bar|←| -//│ Parsed: {fun f = (x,) => {let g = (x,) => {let h = (x,) => + (x,) (2,); (Foo (h (x,), x,)).bar}; class Foo(x, y,) {fun bar = + (g (x,),) (y,)}; (Foo (x, x,)).bar}} +//│ Parsed: {fun f = (x,) => {let g = (x,) => {let h = (x,) => + (x, 2,); (Foo (h (x,), x,)).bar}; class Foo(x, y,) {fun bar = + (g (x,), y,)}; (Foo (x, x,)).bar}} //│ Parsed: -//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Blk(...)))) +//│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), Blk(...)))) //│ Lifted: //│ TypingUnit { -//│ class Foo$1(x, y, g,) {fun bar = + ((this).g ((this).x,),) ((this).y,)} -//│ fun f = (x,) => {let g = (x,) => {let h = (x,) => + (x,) (2,); (Foo$1 (h (x,), x, g,)).bar}; (Foo$1 (x, x, g,)).bar} +//│ class Foo$1(x, y, g,) {fun bar = + ((this).g ((this).x,), (this).y,)} +//│ fun f = (x,) => {let g = (x,) => {let h = (x,) => + (x, 2,); (Foo$1 (h (x,), x, g,)).bar}; (Foo$1 (x, x, g,)).bar} //│ } +//│ class Foo(x, y) extends Bar(y, x), Baz(x + y) //│ |#class| |Foo|(|x|,| |y|)| |#extends| |Bar|(|y|,| |x|)|,| |Baz|(|x| |+| |y|)| -//│ Parsed: {class Foo(x, y,): Bar (y, x,), Baz (+ (x,) (y,),) {}} +//│ Parsed: {class Foo(x, y,): Bar (y, x,), Baz (+ (x, y,),) {}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(_: Var(x), _: Var(y)), (App(Var(Bar), Tup(_: Var(y), _: Var(x))), App(Var(Baz), Tup(_: App(App(Var(+), Tup(_: Var(x))), Tup(_: Var(y)))))), None, None, TypingUnit())) +//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(_: Var(x), _: Var(y)), (App(Var(Bar), Tup(_: Var(y), _: Var(x))), App(Var(Baz), Tup(_: App(Var(+), Tup(_: Var(x), _: Var(y)))))), None, None, TypingUnit())) //│ Lifted: //│ TypingUnit { -//│ class Foo$1(x, y,): Bar ((this).y, (this).x,), Baz (+ ((this).x,) ((this).y,),) {} +//│ class Foo$1(x, y,): Bar ((this).y, (this).x,), Baz (+ ((this).x, (this).y,),) {} //│ } +//│ fun foo(x: T): string = class A(y) extends B, C(y: U) { @@ -203,12 +213,13 @@ fun foo(x: T): string = //│ |#fun| |foo|‹|T|,| |U|›|(|x|#:| |T|)|#:| |string| |#=| |→|#class| |A|(|y|)| |#extends| |B|‹|T|›|,| |C|(|y|#:| |U|)| |{|→|#fun| |bar| |#=| |this|←|↵|}|↵|"rua"|←| //│ Parsed: {fun foo = (x: T,) => {class A(y,): B‹T›, C (y: U,) {fun bar = this}; "rua"} : string} //│ Parsed: -//│ TypingUnit(NuFunDef(None, foo, [TypeName(T), TypeName(U)], Lam(Tup(x: Var(T)), Asc(Blk(...), TypeName(string))))) +//│ TypingUnit(NuFunDef(None, foo, None, [TypeName(T), TypeName(U)], Lam(Tup(x: Var(T)), Asc(Blk(...), TypeName(string))))) //│ Lifted: //│ TypingUnit { //│ class A$1[T,U](y,): B‹T›, C (y: U,) {fun bar = this} //│ fun foo[T, U] = (x: T,) => {"rua"} : string //│ } +//│ class A{ class B{ @@ -219,7 +230,7 @@ class A{ //│ |#class| |A|‹|T|›|{|→|#class| |B|{|→|#fun| |f|#:| |T| |=>| |B| |=>| |T| |#=| |x| |=>| |y| |=>| |x|↵|#fun| |g|#:| |T| |=>| |B| |=>| |T|←|↵|}|←|↵|}| //│ Parsed: {class A‹T›() {class B() {fun f = (x,) => (y,) => x : T -> B -> T; fun g: T -> B -> T}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, ((None,TypeName(T))), Tup(), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, f, [], Asc(Lam(Tup(_: Var(x)), Lam(Tup(_: Var(y)), Var(x))), Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T))))), NuFunDef(None, g, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T)))))))))) +//│ TypingUnit(NuTypeDef(class, A, ((None,TypeName(T))), Tup(), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, f, None, [], Asc(Lam(Tup(_: Var(x)), Lam(Tup(_: Var(y)), Var(x))), Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T))))), NuFunDef(None, g, None, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T)))))))))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2[T](par$A$1,) { @@ -228,6 +239,7 @@ class A{ //│ } //│ class A$1[T]() {} //│ } +//│ class Foo{ class RectangleBox: Box & { breadth: T } @@ -245,6 +257,7 @@ class Foo{ //│ class Foo$1_Bar$4(par$Foo$1,) {} //│ class Foo$1[T]() {} //│ } +//│ class Func { fun apply: T => U @@ -257,16 +270,17 @@ fun ctx(a,b) = fun apply(x) = a+x }, b) //│ |#class| |Func|‹|T|,| |U|›| |{|→|#fun| |apply|#:| |T| |=>| |U|←|↵|}|↵|#class| |Lambda|‹|T|,| |U|›| |#:| |Func|‹|T|,| |U|›| |{||}|↵|#fun| |ctx|(|a|,|b|)| |#=|→|#fun| |foo|(|f|#:| |Func|,| |x|)| |#=| |→|f|.apply|(|x|)|←|↵|foo|(|#new| |Lambda|{|→|#fun| |apply|(|x|)| |#=| |a|+|x|←|↵|}|,| |b|)|←| -//│ Parsed: {class Func‹T, U›() {fun apply: T -> U}; class Lambda‹T, U›(): Func[T, U] {}; fun ctx = (a, b,) => {fun foo = (f: Func, x,) => {(f).apply (x,)}; foo (new Lambda() {fun apply = (x,) => + (a,) (x,)}, b,)}} +//│ Parsed: {class Func‹T, U›() {fun apply: T -> U}; class Lambda‹T, U›(): Func[T, U] {}; fun ctx = (a, b,) => {fun foo = (f: Func, x,) => {(f).apply (x,)}; foo (new Lambda() {fun apply = (x,) => + (a, x,)}, b,)}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Func, ((None,TypeName(T)), (None,TypeName(U))), Tup(), (), None, None, TypingUnit(NuFunDef(None, apply, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(T))))),TypeName(U)))))), NuTypeDef(class, Lambda, ((None,TypeName(T)), (None,TypeName(U))), Tup(), (), None, None, TypingUnit()), NuFunDef(None, ctx, [], Lam(Tup(_: Var(a), _: Var(b)), Blk(...)))) +//│ TypingUnit(NuTypeDef(class, Func, ((None,TypeName(T)), (None,TypeName(U))), Tup(), (), None, None, TypingUnit(NuFunDef(None, apply, None, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(T))))),TypeName(U)))))), NuTypeDef(class, Lambda, ((None,TypeName(T)), (None,TypeName(U))), Tup(), (), None, None, TypingUnit()), NuFunDef(None, ctx, None, [], Lam(Tup(_: Var(a), _: Var(b)), Blk(...)))) //│ Lifted: //│ TypingUnit { //│ class Func$1[T,U]() {fun apply = T -> U} //│ class Lambda$2[T,U]() {} -//│ class Lambda$1$3(a,): Lambda$2 () {fun apply = (x,) => + ((this).a,) (x,)} +//│ class Lambda$1$3(a,): Lambda$2 () {fun apply = (x,) => + ((this).a, x,)} //│ fun ctx = (a, b,) => {fun foo = (f: Func$1, x,) => {(f).apply (x,)}; foo ({new Lambda$1$3(a,) {}}, b,)} //│ } +//│ fun f(T) = new T() @@ -274,6 +288,7 @@ f(MyClass) //│ |#fun| |f|(|T|)| |#=| |→|#new| |T|(||)|←|↵|f|(|MyClass|)| //│ Parsed: {fun f = (T,) => {new T() {}}; f (MyClass,)} //│ Parsed: -//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(T)), Blk(...))), App(Var(f), Tup(_: Var(MyClass)))) +//│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(T)), Blk(...))), App(Var(f), Tup(_: Var(MyClass)))) //│ Lifted: //│ Lifting failed: mlscript.codegen.CodeGenError: Cannot find type T. Class values are not supported in lifter. +//│ diff --git a/js/src/main/scala/Main.scala b/js/src/main/scala/Main.scala index abf39dc6b8..deba214668 100644 --- a/js/src/main/scala/Main.scala +++ b/js/src/main/scala/Main.scala @@ -110,7 +110,7 @@ object Main { val origin = Origin("", 1, fph) val lexer = new NewLexer(origin, throw _, dbg = false) val tokens = lexer.bracketedTokens - val parser = new NewParser(origin, tokens, throw _, dbg = false, N) { + val parser = new NewParser(origin, tokens, newDefs = true, throw _, dbg = false, N) { def doPrintDbg(msg: => Str): Unit = if (dbg) println(msg) } parser.parseAll(parser.typingUnit) match { diff --git a/shared/src/main/scala/mlscript/JSBackend.scala b/shared/src/main/scala/mlscript/JSBackend.scala index 64cdddb562..9bec911ccb 100644 --- a/shared/src/main/scala/mlscript/JSBackend.scala +++ b/shared/src/main/scala/mlscript/JSBackend.scala @@ -93,7 +93,12 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { JSIdent(sym.outsiderSym.runtimeName).member(sym.actualSym.lexicalName) protected def translateVar(name: Str, isCallee: Bool)(implicit scope: Scope): JSExpr = - scope.resolveValue(name) match { + translateVarImpl(name, isCallee).fold(throw _, identity) + + /** Try to retrieve a name from the scope, returning a Left value if the name is not found, + * a Right value if it is found, and throwing an exception in case of unrecoverable error. */ + protected def translateVarImpl(name: Str, isCallee: Bool)(implicit scope: Scope): Either[CodeGenError, JSExpr] = + Right(scope.resolveValue(name) match { case S(sym: BuiltinSymbol) => sym.accessed = true if (!polyfill.used(sym.feature)) @@ -106,7 +111,9 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { else throw new UnimplementedError(sym) case S(sym: ValueSymbol) => - if (sym.isByvalueRec.getOrElse(false) && !sym.isLam) throw CodeGenError(s"unguarded recursive use of by-value binding $name") + if (sym.isByvalueRec.getOrElse(false) && !sym.isLam) + // * Note that this represents an illegal reference, which should throw an error in all cases + throw CodeGenError(s"unguarded recursive use of by-value binding $name") visitedSymbols += sym val ident = JSIdent(sym.runtimeName) if (sym.isByvalueRec.isEmpty && !sym.isLam) ident() else ident @@ -114,7 +121,9 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { if (sym.isPlainJSClass || !isCallee) translateNuTypeSymbol(sym) else translateNuTypeSymbol(sym).member("class") case S(sym: NewClassMemberSymbol) => - if (sym.isByvalueRec.getOrElse(false) && !sym.isLam) throw CodeGenError(s"unguarded recursive use of by-value binding $name") + if (sym.isByvalueRec.getOrElse(false) && !sym.isLam) + // * Note that this represents an illegal reference, which should throw an error in all cases + throw CodeGenError(s"unguarded recursive use of by-value binding $name") scope.resolveValue("this") match { case Some(selfSymbol) => visitedSymbols += selfSymbol @@ -133,15 +142,15 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { JSIdent(sym.lexicalName)("build") case N => scope.getType(name) match { case S(sym: TypeAliasSymbol) => - throw CodeGenError(s"type alias ${name} is not a valid expression") - case S(_) => throw new Exception("register mismatch in scope") + return Left(CodeGenError(s"type alias ${name} is not a valid expression")) + case S(_) => lastWords("register mismatch in scope") case N => if (allowUnresolvedSymbols) JSIdent(name) else - throw CodeGenError(s"unresolved symbol ${name}") + return Left(CodeGenError(s"unresolved symbol ${name}")) } - } + }) /** * Handle all possible cases of MLscript function applications. We extract @@ -152,6 +161,10 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { case App(App(Var(op), Tup((N -> Fld(_, lhs)) :: Nil)), Tup((N -> Fld(_, rhs)) :: Nil)) if JSBinary.operators contains op => JSBinary(op, translateTerm(lhs), translateTerm(rhs)) + // Binary expressions with new-definitions + case App(Var(op), Tup(N -> Fld(_, lhs) :: N -> Fld(_, rhs) :: Nil)) + if JSBinary.operators.contains(op) && !translateVarImpl(op, isCallee = true).isRight => + JSBinary(op, translateTerm(lhs), translateTerm(rhs)) // If-expressions case App(App(App(Var("if"), Tup((_, Fld(_, tst)) :: Nil)), Tup((_, Fld(_, con)) :: Nil)), Tup((_, Fld(_, alt)) :: Nil)) => JSTenary(translateTerm(tst), translateTerm(con), translateTerm(alt)) @@ -219,8 +232,9 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { val blkScope = scope.derive("Blk") val flattened = stmts.iterator.flatMap { case nt: NuTypeDef => nt :: Nil - case nf @ NuFunDef(_, Var(nme), _, _) => - blkScope.declareStubValue(nme)(true) + case nf @ NuFunDef(_, Var(nme), symNme, _, _) => + val symb = symNme.map(_.name) + blkScope.declareStubValue(nme, symb)(true) nf.desugared._2 case other => other.desugared._2 }.toList @@ -230,10 +244,10 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { R(blkScope.tempVars `with` (flattened.iterator.zipWithIndex.map { case (t: Term, index) if index + 1 == flattened.length => translateTerm(t)(blkScope).`return` case (t: Term, index) => JSExprStmt(translateTerm(t)(blkScope)) - case (NuFunDef(isLetRec, Var(nme), _, L(rhs)), _) => { - val pat = blkScope.declareValue(nme, isLetRec, isLetRec.isEmpty) + case (NuFunDef(isLetRec, Var(nme), symNme, _, L(rhs)), _) => + val symb = symNme.map(_.name) + val pat = blkScope.declareValue(nme, isLetRec, isLetRec.isEmpty, symb) JSLetDecl(Ls(pat.runtimeName -> S(translateTerm(rhs)(blkScope)))) - } case (nt: NuTypeDef, _) => translateLocalNewType(nt)(blkScope) // TODO: find out if we need to support this. case (_: Def | _: TypeDef | _: NuFunDef | _: DataDefn | _: DatatypeDefn | _: LetS | _: Constructor, _) => @@ -382,7 +396,7 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { case Lam(params, body) => val methodScope = scope.derive(s"Method $name") val methodParams = translateParams(params)(methodScope) - methodScope.declareValue("this", Some(false), false) + methodScope.declareValue("this", Some(false), false, N) instance(name) := JSFuncExpr( N, methodParams, @@ -391,7 +405,7 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { // Define getters for pure expressions. case term => val getterScope = scope.derive(s"Getter $name") - getterScope.declareValue("this", Some(false), false) + getterScope.declareValue("this", Some(false), false, N) id("Object")("defineProperty")( instance, JSExpr(name), @@ -533,7 +547,7 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { case S(sym: NewClassSymbol) => val localScope = scope.derive(s"local ${sym.lexicalName}") val nd = translateNewTypeDefinition(sym, N, false)(localScope) - val ctorMth = localScope.declareValue("ctor", Some(false), false).runtimeName + val ctorMth = localScope.declareValue("ctor", Some(false), false, N).runtimeName val (constructor, params) = translateNewClassParameters(nd) val initList = if (sym.isPlainJSClass) @@ -550,7 +564,7 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { )) case S(sym: MixinSymbol) => val localScope = scope.derive(s"local ${sym.lexicalName}") - val base = localScope.declareValue("base", Some(false), false) + val base = localScope.declareValue("base", Some(false), false, N) val nd = translateNewTypeDefinition(sym, S(base), false)(localScope) JSConstDecl(sym.lexicalName, JSArrowFn( Ls(JSNamePattern(base.runtimeName)), R(Ls( @@ -560,7 +574,7 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { case S(sym: ModuleSymbol) => val localScope = scope.derive(s"local ${sym.lexicalName}") val nd = translateNewTypeDefinition(sym, N, false)(localScope) - val ins = localScope.declareValue("ins", Some(false), false).runtimeName + val ins = localScope.declareValue("ins", Some(false), false, N).runtimeName JSConstDecl(sym.lexicalName, JSImmEvalFn( N, Nil, R(Ls( nd, JSLetDecl.from(Ls(ins)), @@ -578,7 +592,7 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { siblingsMembers: Ls[RuntimeSymbol] )(implicit scope: Scope): JSClassMethod = { val getterScope = scope.derive(s"getter ${mixinSymbol.lexicalName}") - val base = getterScope.declareValue("base", Some(false), false) + val base = getterScope.declareValue("base", Some(false), false, N) val outerSymbol = getterScope.declareOuterSymbol() siblingsMembers.foreach(getterScope.captureSymbol(outerSymbol, _)) @@ -723,17 +737,17 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { val ctorParams = sym.ctorParams.fold( fields.map { f => memberList += NewClassMemberSymbol(f, Some(false), false).tap(nuTypeScope.register) - constructorScope.declareValue(f, Some(false), false).runtimeName + constructorScope.declareValue(f, Some(false), false, N).runtimeName } )(lst => lst.map { p => - constructorScope.declareValue(p, Some(false), false).runtimeName + constructorScope.declareValue(p, Some(false), false, N).runtimeName }) sym.methods.foreach { case MethodDef(_, _, Var(nme), _, _) => memberList += NewClassMemberSymbol(nme, N, true).tap(nuTypeScope.register) } sym.ctor.foreach { - case NuFunDef(rec, Var(nme), _, _) => memberList += NewClassMemberSymbol(nme, rec, false).tap(nuTypeScope.register) + case NuFunDef(rec, Var(nme), _, _, _) => memberList += NewClassMemberSymbol(nme, rec, false).tap(nuTypeScope.register) case _ => () } @@ -770,7 +784,7 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { } val (superParameters, rest) = if (baseSym.isDefined) { - val rest = constructorScope.declareValue("rest", Some(false), false) + val rest = constructorScope.declareValue("rest", Some(false), false, N) (Ls(JSIdent(s"...${rest.runtimeName}")), S(rest.runtimeName)) } else @@ -785,12 +799,12 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { val stmts = sym.ctor.flatMap { case Eqn(Var(name), rhs) => Ls( JSAssignExpr(JSIdent(s"this.#$name"), translateTerm(rhs)(constructorScope)).stmt, - JSConstDecl(constructorScope.declareValue(name, S(false), false).runtimeName, JSIdent(s"this.#$name")) + JSConstDecl(constructorScope.declareValue(name, S(false), false, N).runtimeName, JSIdent(s"this.#$name")) ) case s: Term => JSExprStmt(translateTerm(s)(constructorScope)) :: Nil - case NuFunDef(_, Var(nme), _, Left(rhs)) => getters += nme; Ls[JSStmt]( + case NuFunDef(_, Var(nme), _, _, Left(rhs)) => getters += nme; Ls[JSStmt]( JSExprStmt(JSAssignExpr(JSIdent(s"this.#$nme"), translateTerm(rhs)(constructorScope))), - JSConstDecl(constructorScope.declareValue(nme, S(false), false).runtimeName, JSIdent(s"this.#$nme")) + JSConstDecl(constructorScope.declareValue(nme, S(false), false, N).runtimeName, JSIdent(s"this.#$nme")) ) case _ => Nil } @@ -868,7 +882,7 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { // Declare the alias for `this` before declaring parameters. val selfSymbol = memberScope.declareThisAlias() val preDecs = props.map(p => { - val runtime = memberScope.declareValue(p, Some(false), false) + val runtime = memberScope.declareValue(p, Some(false), false, N) JSConstDecl(runtime.runtimeName, JSIdent(s"this.#$p")) }) // Declare parameters. @@ -923,10 +937,12 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { protected def declareNewTypeDefs(typeDefs: Ls[NuTypeDef], isNested: Bool)(implicit scope: Scope): (Ls[TraitSymbol], Ls[NewClassSymbol], Ls[MixinSymbol], Ls[ModuleSymbol]) = { + val traits = new ListBuffer[TraitSymbol]() val classes = new ListBuffer[NewClassSymbol]() val mixins = new ListBuffer[MixinSymbol]() val modules = new ListBuffer[ModuleSymbol]() + def tt(trm: Term): Type = trm.toType match { case L(ds) => Top case R(ty) => ty @@ -942,14 +958,14 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { } val body = pars.map(tt).foldRight(Record(params): Type)(Inter) val members = unit.entities.collect { - case NuFunDef(isLetRec, mnme, tys, Left(rhs)) if (isLetRec.isEmpty || isLetRec.getOrElse(false)) => + case NuFunDef(isLetRec, mnme, _, tys, Left(rhs)) if (isLetRec.isEmpty || isLetRec.getOrElse(false)) => MethodDef[Left[Term, Type]](isLetRec.getOrElse(false), TypeName(nme), mnme, tys, Left(rhs)) } val stmts = unit.entities.filter { case Asc(Var("this"), _) => false case Asc(Super(), _) => false - case NuFunDef(S(false), _, _, Left(rhs)) => true + case NuFunDef(S(false), _, _, _, Left(rhs)) => true case _: Term => true case _ => false } @@ -1088,17 +1104,18 @@ class JSWebBackend extends JSBackend(allowUnresolvedSymbols = true) { // ``` .concat(otherStmts.flatMap { case Def(recursive, Var(name), L(body), isByname) => + val isLam = body.isInstanceOf[Lam] val (originalExpr, sym) = if (recursive) { val isByvalueRecIn = if (isByname) None else Some(true) - val sym = topLevelScope.declareValue(name, isByvalueRecIn, body.isInstanceOf[Lam]) + val sym = topLevelScope.declareValue(name, isByvalueRecIn, isLam, N) val translated = translateTerm(body)(topLevelScope) topLevelScope.unregisterSymbol(sym) val isByvalueRecOut = if (isByname) None else Some(false) - (translated, topLevelScope.declareValue(name, isByvalueRecOut, body.isInstanceOf[Lam])) + (translated, topLevelScope.declareValue(name, isByvalueRecOut, isLam, N)) } else { val translatedBody = translateTerm(body)(topLevelScope) val isByvalueRec = if (isByname) None else Some(false) - (translatedBody, topLevelScope.declareValue(name, isByvalueRec, body.isInstanceOf[Lam])) + (translatedBody, topLevelScope.declareValue(name, isByvalueRec, isLam, N)) } val translatedBody = if (sym.isByvalueRec.isEmpty && !sym.isLam) JSArrowFn(Nil, L(originalExpr)) else originalExpr topLevelScope.tempVars `with` JSConstDecl(sym.runtimeName, translatedBody) :: @@ -1117,6 +1134,7 @@ class JSWebBackend extends JSBackend(allowUnresolvedSymbols = true) { } private def generateNewDef(pgrm: Pgrm): (Ls[Str], Ls[Str]) = { + val (typeDefs, otherStmts) = pgrm.tops.partitionMap { case ot: Terms => R(ot) case fd: NuFunDef => R(fd) @@ -1126,7 +1144,7 @@ class JSWebBackend extends JSBackend(allowUnresolvedSymbols = true) { // don't pass `otherStmts` to the top-level module, because we need to execute them one by one later val topModule = topLevelScope.declareTopModule("TypingUnit", Nil, typeDefs, true) - val moduleIns = topLevelScope.declareValue("typing_unit", Some(false), false) + val moduleIns = topLevelScope.declareValue("typing_unit", Some(false), false, N) val moduleDecl = translateTopModuleDeclaration(topModule, true)(topLevelScope) val insDecl = JSConstDecl(moduleIns.runtimeName, JSNew(JSIdent(topModule.runtimeName))) @@ -1144,27 +1162,31 @@ class JSWebBackend extends JSBackend(allowUnresolvedSymbols = true) { // .push(); // ``` .concat(otherStmts.flatMap { - case NuFunDef(isLetRec, nme @ Var(name), tys, rhs @ L(body)) => + case NuFunDef(isLetRec, nme @ Var(name), symNme, tys, rhs @ L(body)) => val recursive = isLetRec.getOrElse(true) val isByname = isLetRec.isEmpty val bodyIsLam = body match { case _: Lam => true case _ => false } + val symb = symNme.map(_.name) val (originalExpr, sym) = (if (recursive) { val isByvalueRecIn = if (isByname) None else Some(true) - val sym = topLevelScope.declareValue(name, isByvalueRecIn, bodyIsLam) + + // TODO Improve: (Lionel) what?! + val sym = topLevelScope.declareValue(name, isByvalueRecIn, bodyIsLam, N) val translated = translateTerm(body)(topLevelScope) topLevelScope.unregisterSymbol(sym) + val isByvalueRecOut = if (isByname) None else Some(false) - (translated, topLevelScope.declareValue(name, isByvalueRecOut, bodyIsLam)) + (translated, topLevelScope.declareValue(name, isByvalueRecOut, bodyIsLam, symb)) } else { val translated = translateTerm(body)(topLevelScope) val isByvalueRec = if (isByname) None else Some(false) - (translated, topLevelScope.declareValue(name, isByvalueRec, bodyIsLam)) + (translated, topLevelScope.declareValue(name, isByvalueRec, bodyIsLam, symb)) }) val translatedBody = if (sym.isByvalueRec.isEmpty && !sym.isLam) JSArrowFn(Nil, L(originalExpr)) else originalExpr resultNames += sym.runtimeName topLevelScope.tempVars `with` JSConstDecl(sym.runtimeName, translatedBody) :: JSInvoke(resultsIdent("push"), JSIdent(sym.runtimeName) :: Nil).stmt :: Nil - case fd @ NuFunDef(isLetRec, Var(name), tys, R(ty)) => + case fd @ NuFunDef(isLetRec, Var(name), _, tys, R(ty)) => Nil case _: Def | _: TypeDef => throw CodeGenError("Def and TypeDef are not supported in NewDef files.") @@ -1185,7 +1207,7 @@ class JSWebBackend extends JSBackend(allowUnresolvedSymbols = true) { } class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) { - private val lastResultSymbol = topLevelScope.declareValue("res", Some(false), false) + private val lastResultSymbol = topLevelScope.declareValue("res", Some(false), false, N) private val resultIdent = JSIdent(lastResultSymbol.runtimeName) private var numRun = 0 @@ -1198,13 +1220,13 @@ class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) { try generate(pgrm)(topLevelScope, allowEscape) catch { case e: CodeGenError => JSTestBackend.IllFormedCode(e.getMessage()) case e: UnimplementedError => JSTestBackend.Unimplemented(e.getMessage()) - // case e: Throwable => JSTestBackend.UnexpectedCrash(e.getClass().getName, e.getMessage()) + // case NonFatal(e) => JSTestBackend.UnexpectedCrash(e.getClass().getName, e.getMessage()) } else try generateNewDef(pgrm)(topLevelScope, allowEscape) catch { case e: CodeGenError => JSTestBackend.IllFormedCode(e.getMessage()) case e: UnimplementedError => JSTestBackend.Unimplemented(e.getMessage()) - // case e: Throwable => JSTestBackend.UnexpectedCrash(e.getClass().getName, e.getMessage()) + // case NonFatal(e) => JSTestBackend.UnexpectedCrash(e.getClass().getName, e.getMessage()) } // generate(pgrm)(topLevelScope, allowEscape) @@ -1238,31 +1260,30 @@ class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) { val bodyIsLam = body match { case _: Lam => true case _ => false } (if (recursive) { val isByvalueRecIn = if (isByname) None else Some(true) - val sym = scope.declareValue(name, isByvalueRecIn, bodyIsLam) + val sym = scope.declareValue(name, isByvalueRecIn, bodyIsLam, N) try { val translated = translateTerm(body) scope.unregisterSymbol(sym) val isByvalueRecOut = if (isByname) None else Some(false) - R((translated, scope.declareValue(name, isByvalueRecOut, bodyIsLam))) + R((translated, scope.declareValue(name, isByvalueRecOut, bodyIsLam, N))) } catch { case e: UnimplementedError => scope.stubize(sym, e.symbol) L(e.getMessage()) - case e: Throwable => + case NonFatal(e) => scope.unregisterSymbol(sym) val isByvalueRecOut = if (isByname) None else Some(false) - scope.declareValue(name, isByvalueRecOut, bodyIsLam) + scope.declareValue(name, isByvalueRecOut, bodyIsLam, N) throw e } } else { (try R(translateTerm(body)) catch { case e: UnimplementedError => - scope.declareStubValue(name, e.symbol) + scope.declareStubValue(name, e.symbol, N) L(e.getMessage()) - case e: Throwable => throw e }) map { val isByvalueRec = if (isByname) None else Some(false) - expr => (expr, scope.declareValue(name, isByvalueRec, bodyIsLam)) + expr => (expr, scope.declareValue(name, isByvalueRec, bodyIsLam, N)) } }) match { case R((originalExpr, sym)) => @@ -1282,7 +1303,7 @@ class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) { case L(reason) => JSTestBackend.AbortedQuery(reason) } case Def(_, Var(name), _, _) => - scope.declareStubValue(name) + scope.declareStubValue(name, N) JSTestBackend.EmptyQuery case term: Term => try { @@ -1292,7 +1313,6 @@ class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) { res } catch { case e: UnimplementedError => JSTestBackend.AbortedQuery(e.getMessage()) - case e: Throwable => throw e } } @@ -1308,6 +1328,7 @@ class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) { } private def generateNewDef(pgrm: Pgrm)(implicit scope: Scope, allowEscape: Bool): JSTestBackend.TestCode = { + val (typeDefs, otherStmts) = pgrm.tops.partitionMap { case _: Constructor => throw CodeGenError("unexpected constructor.") case ot: Terms => R(ot) @@ -1318,7 +1339,7 @@ class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) { // don't pass `otherStmts` to the top-level module, because we need to execute them one by one later val topModule = topLevelScope.declareTopModule("TypingUnit", Nil, typeDefs, true) - val moduleIns = topLevelScope.declareValue("typing_unit", Some(false), false) + val moduleIns = topLevelScope.declareValue("typing_unit", Some(false), false, N) val moduleDecl = translateTopModuleDeclaration(topModule, true) val insDecl = JSConstDecl(moduleIns.runtimeName, JSNew(JSIdent(topModule.runtimeName))) @@ -1332,50 +1353,54 @@ class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) { ) otherStmts.foreach { - case fd @ NuFunDef(isLetRec, Var(nme), _, L(body)) if (isLetRec.isEmpty || isLetRec.getOrElse(false)) => + case fd @ NuFunDef(isLetRec, Var(nme), symNme, _, L(body)) if isLetRec.getOrElse(true) => val isByname = isLetRec.isEmpty val isByvalueRecIn = if (isByname) None else Some(true) val bodyIsLam = body match { case _: Lam => true case _ => false } - scope.declareValue(nme, isByvalueRecIn, bodyIsLam) + val symb = symNme.map(_.name) + scope.declareValue(nme, isByvalueRecIn, bodyIsLam, symb) case _ => () } + // TODO Improve: (Lionel) I find this logic very strange! What's going on here? + // Why are we declaring some things above AND below? + // Why does the fact that a binding is recursive affect its declaration in the OUTER scope? + // Generate statements. val queries = otherStmts.map { - case NuFunDef(isLetRec, nme @ Var(name), tys, rhs @ L(body)) => + case NuFunDef(isLetRec, nme @ Var(name), symNme, tys, rhs @ L(body)) => val recursive = isLetRec.getOrElse(true) val isByname = isLetRec.isEmpty val bodyIsLam = body match { case _: Lam => true case _ => false } + val symb = symNme.map(_.name) (if (recursive) { val isByvalueRecIn = if (isByname) None else Some(true) val sym = scope.resolveValue(name) match { case Some(s: ValueSymbol) => s - case _ => scope.declareValue(name, isByvalueRecIn, bodyIsLam) + case _ => scope.declareValue(name, isByvalueRecIn, bodyIsLam, symb) } + val isByvalueRecOut = if (isByname) None else Some(false) try { - val translated = translateTerm(body) - scope.unregisterSymbol(sym) - val isByvalueRecOut = if (isByname) None else Some(false) - R((translated, scope.declareValue(name, isByvalueRecOut, bodyIsLam))) + val translated = translateTerm(body) // TODO Improve: (Lionel) Why are the bodies translated in the SAME scope?! + scope.unregisterSymbol(sym) // TODO Improve: (Lionel) ??? + R((translated, scope.declareValue(name, isByvalueRecOut, bodyIsLam, symb))) } catch { case e: UnimplementedError => scope.stubize(sym, e.symbol) L(e.getMessage()) - case e: Throwable => - scope.unregisterSymbol(sym) - val isByvalueRecOut = if (isByname) None else Some(false) - scope.declareValue(name, isByvalueRecOut, bodyIsLam) + case NonFatal(e) => + scope.unregisterSymbol(sym) // TODO Improve: (Lionel) You should only try/catch around the part that may actually fail, and if `unregisterSymbol` should always be called, that should be done in `finally`... but the very logic of calling `unregisterSymbol` is very fishy, to say the least + scope.declareValue(name, isByvalueRecOut, bodyIsLam, symb) throw e } } else { - (try R(translateTerm(body)) catch { + (try R(translateTerm(body)) catch { // TODO Improve: Why are the bodies translated in the SAME scope?! case e: UnimplementedError => - scope.declareStubValue(name, e.symbol) + scope.declareStubValue(name, e.symbol, symb) L(e.getMessage()) - case e: Throwable => throw e }) map { val isByvalueRec = if (isByname) None else Some(false) - expr => (expr, scope.declareValue(name, isByvalueRec, bodyIsLam)) + expr => (expr, scope.declareValue(name, isByvalueRec, bodyIsLam, symb)) } }) match { case R((originalExpr, sym)) => @@ -1394,8 +1419,9 @@ class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) { ) case L(reason) => JSTestBackend.AbortedQuery(reason) } - case fd @ NuFunDef(isLetRec, Var(name), tys, R(ty)) => - scope.declareStubValue(name)(allowEscape || fd.isDecl) + case fd @ NuFunDef(isLetRec, Var(name), symNme, tys, R(ty)) => + val symb = symNme.map(_.name) + scope.declareStubValue(name, symb)(allowEscape || fd.isDecl) JSTestBackend.EmptyQuery case term: Term => try { @@ -1405,7 +1431,6 @@ class JSTestBackend extends JSBackend(allowUnresolvedSymbols = false) { res } catch { case e: UnimplementedError => JSTestBackend.AbortedQuery(e.getMessage()) - case e: Throwable => throw e } case _: Def | _: TypeDef => throw CodeGenError("Def and TypeDef are not supported in NewDef files.") diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index 10b7a940f1..f2dfdb676c 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -19,7 +19,7 @@ object NewParser { } import NewParser._ -abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: Diagnostic => Unit, val dbg: Bool, fallbackLoc: Opt[Loc], description: Str = "input") { +abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bool, raiseFun: Diagnostic => Unit, val dbg: Bool, fallbackLoc: Opt[Loc], description: Str = "input") { outer => private var freshCnt: Int = 0 @@ -37,7 +37,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D } final def rec(tokens: Ls[Stroken -> Loc], fallbackLoc: Opt[Loc], description: Str): NewParser = - new NewParser(origin, tokens, raiseFun, dbg, fallbackLoc, description) { + new NewParser(origin, tokens, newDefs, raiseFun, dbg, fallbackLoc, description) { def doPrintDbg(msg: => Str): Unit = outer.printDbg("> " + msg) } @@ -135,8 +135,14 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D case "and" => (3, 3) case "or" => (2, 2) case "=>" => - val eqPrec = prec('=') - (eqPrec, eqPrec - 1) + // * The lambda operator is special: + // * it should associate veyr strongly on the left and very loosely on the right + // * so that we can write things like `f() |> x => x is 0` ie `(f()) |> (x => (x is 0))` + val eqPrec = prec('.') // * We pick the tightest precedence + (eqPrec, 1) + // * Note: we used to do this instead which broke the example above on both sides: + // val eqPrec = prec('=') + // (eqPrec, eqPrec - 1) case _ if opStr.exists(_.isLetter) => (5, 5) case _ => @@ -418,15 +424,35 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D S(true) case c => if (kwStr === "fun") N else S(false) } + val opStr = yeetSpaces match { + case (BRACKETS(Round, ts), brackloc) :: _ => + ts match { + case (IDENT(opStr, true), l1) :: rest => + consume + rest.dropWhile(_._1 === SPACE) match { + case Nil => + case (tok, loc) :: ts => + err((msg"Unexpected ${tok.describe} after symbolic name" -> S(loc) :: Nil)) + } + S(Var(opStr).withLoc(S(l1))) + case (tok, loc) :: _ => + consume + err((msg"Expected a symbolic name, found ${tok.describe} instead" -> S(loc) :: Nil)) + N + case Nil => + consume + err((msg"Expected a symbolic name between brackets, found nothing" -> S(brackloc) :: Nil)) + N + } + case _ => N + } val (v, success) = yeetSpaces match { case (IDENT(idStr, false), l1) :: _ => consume (Var(idStr).withLoc(S(l1)), true) case c => val (tkstr, loc) = c.headOption.fold(("end of input", lastLoc))(_.mapFirst(_.describe).mapSecond(some)) - err(( - // msg"Expected a function name; found ${"[TODO]"} instead" -> N :: Nil)) - msg"Expected a function name; found ${tkstr} instead" -> loc :: Nil)) + err((msg"Expected a function name; found ${tkstr} instead" -> loc :: Nil)) consume // R(errExpr) (Var("").withLoc(curLoc.map(_.left)), false) @@ -474,12 +500,12 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D val body = expr(0) val newBody = transformBody.fold(body)(_(body)) val annotatedBody = asc.fold(newBody)(ty => Asc(newBody, ty)) - R(NuFunDef(isLetRec, v, tparams, L(ps.foldRight(annotatedBody)((i, acc) => Lam(i, acc))))(isDecl, N, N)) + R(NuFunDef(isLetRec, v, opStr, tparams, L(ps.foldRight(annotatedBody)((i, acc) => Lam(i, acc))))(isDecl, N, N)) case c => asc match { case S(ty) => if (transformBody.nonEmpty) die // TODO - R(NuFunDef(isLetRec, v, tparams, R(PolyType(Nil, ps.foldRight(ty)((p, r) => Function(p.toType match { + R(NuFunDef(isLetRec, v, opStr, tparams, R(PolyType(Nil, ps.foldRight(ty)((p, r) => Function(p.toType match { case L(diag) => raise(diag); Top // TODO better case R(tp) => tp }, r)))))(isDecl, N, N)) // TODO rm PolyType after FCP is merged @@ -489,7 +515,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D err(( msg"Expected ':' or '=' followed by a function body or signature; found ${tkstr} instead" -> loc :: Nil)) consume - R(NuFunDef(isLetRec, v, Nil, L(ps.foldRight(errExpr: Term)((i, acc) => Lam(i, acc))))(isDecl, N, N)) + R(NuFunDef(isLetRec, v, opStr, Nil, L(ps.foldRight(errExpr: Term)((i, acc) => Lam(i, acc))))(isDecl, N, N)) } } } @@ -575,6 +601,9 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D consume val rest = expr(prec, allowSpace = true) exprCont(App(Var("~").withLoc(S(l0)), rest).withLoc(S(l0 ++ rest.toLoc)), prec, allowNewlines = false) + case (BRACKETS(Round, (IDENT(opStr, true), l1) :: Nil), l0) :: _ => + consume + exprCont(Var(opStr).withLoc(S(l1)), prec, allowNewlines = false) case (br @ BRACKETS(bk @ (Round | Square | Curly), toks), loc) :: _ => consume val res = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()) // TODO @@ -758,7 +787,8 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D case "=>" => Lam(toParams(acc), rhs) case _ => - App(App(v, toParams(acc)), toParams(rhs)) + if (newDefs) App(v, PlainTup(acc, rhs)) + else App(App(v, toParams(acc)), toParams(rhs)) }, prec, allowNewlines) } case (KEYWORD(":"), l0) :: _ => diff --git a/shared/src/main/scala/mlscript/NuTypeDefs.scala b/shared/src/main/scala/mlscript/NuTypeDefs.scala index ba9ac806e5..c97a1084ad 100644 --- a/shared/src/main/scala/mlscript/NuTypeDefs.scala +++ b/shared/src/main/scala/mlscript/NuTypeDefs.scala @@ -484,7 +484,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => } val funSigs = MutMap.empty[Str, NuFunDef] val implems = decls.filter { - case fd @ NuFunDef(N, nme, tparams, R(rhs)) => + case fd @ NuFunDef(N, nme, snme, tparams, R(rhs)) => funSigs.updateWith(nme.name) { case S(s) => err(s"A type signature for '$nme' was already given", fd.toLoc) @@ -497,8 +497,13 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => val sigInfos = if (topLevel) funSigs.map { case (nme, decl) => val lti = new DelayedTypeInfo(decl, implicitly) + + // TODO check against duplicated symbolic names in same scope... + decl.symbolicNme.foreach(snme => ctx += snme.name -> lti) + decl.name -> lti } else Nil + val infos = implems.map { case _decl: NuDecl => val decl = _decl match { @@ -519,12 +524,14 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => decl match { case td: NuTypeDef => ctx.tyDefs2 += td.nme.name -> lti - case _: NuFunDef => + case fd: NuFunDef => + // TODO check against duplicated symbolic names in same scope... + fd.symbolicNme.foreach(snme => ctx += snme.name -> lti) } named.updateWith(decl.name) { case sv @ S(v) => decl match { - case NuFunDef(S(_), _, _, _) => () + case NuFunDef(S(_), _, _, _, _) => () case _ => err(msg"Refininition of '${decl.name}'", decl.toLoc) } @@ -534,6 +541,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => } decl.name -> lti } + ctx ++= infos ctx ++= sigInfos @@ -833,12 +841,12 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => lazy val (typedSignatures, funImplems) : (Ls[(NuFunDef, ST)], Ls[NuFunDef]) = decl match { case td: NuTypeDef => ctx.nest.nextLevel { implicit ctx => val (signatures, rest) = td.body.entities.partitionMap { - case fd @ NuFunDef(N | S(false), nme, tparams, R(rhs)) => // currently `val`s are encoded with `S(false)` + case fd @ NuFunDef(N | S(false), nme, snme, tparams, R(rhs)) => // currently `val`s are encoded with `S(false)` L((fd, rhs)) // TODO also pick up signature off implems with typed params/results case s => R(s) } - val implems = rest.collect { case fd @ NuFunDef(N | S(false), nme, tparams, L(rhs)) => fd } + val implems = rest.collect { case fd @ NuFunDef(N | S(false), nme, snme, tparams, L(rhs)) => fd } ctx ++= paramSymbols @@ -1054,7 +1062,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => val fd = NuFunDef((a.fd.isLetRec, b.fd.isLetRec) match { case (S(a), S(b)) => S(a || b) case _ => N // if one is fun, then it will be fun - }, a.fd.nme, a.fd.tparams, a.fd.rhs)(a.fd.declareLoc, N, a.fd.outer orElse b.fd.outer) + }, a.fd.nme, N/*no sym name?*/, a.fd.tparams, a.fd.rhs)(a.fd.declareLoc, N, a.fd.outer orElse b.fd.outer) S(TypedNuFun(a.level, fd, a.bodyType & b.bodyType)(a.isImplemented || b.isImplemented)) case (a: NuParam, S(b: NuParam)) => S(NuParam(a.nme, a.ty && b.ty)(a.level)) @@ -1150,7 +1158,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => inherit(typedParents, trtNameToNomTag(td)(noProv, ctx), Nil, Map.empty) td.body.entities.foreach { - case fd @ NuFunDef(_, _, _, L(_)) => + case fd @ NuFunDef(_, _, _, _, L(_)) => err(msg"Method implementations in traits are not yet supported", fd.toLoc) case _ => } diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index f6f41f5a1d..35538d7428 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -14,7 +14,7 @@ import mlscript.Message._ * Inferred SimpleType values are then turned into CompactType values for simplification. * In order to turn the resulting CompactType into a mlscript.Type, we use `expandCompactType`. */ -class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var newDefs: Bool = false) +class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val newDefs: Bool) extends ucs.Desugarer with TypeSimplifier { def funkyTuples: Bool = false @@ -162,7 +162,11 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne }), ) implicit val raise: Raise = throw _ - res.tyDefs2.valuesIterator.foreach(_.complete()) + res.tyDefs2.valuesIterator.foreach { dti => + val mem = dti.complete() + // * Not strictly necessary, but it makes sense to use the completed member symbols: + res.env += mem.name -> CompletedTypeInfo(mem) + } res } val empty: Ctx = init @@ -277,13 +281,23 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne val reservedTypeNames: Set[Str] = primitiveTypes + "Eql" def singleTup(ty: ST): ST = if (funkyTuples) ty else TupleType((N, ty.toUpper(ty.prov) ) :: Nil)(noProv) + def pair(ty1: ST, ty2: ST): ST = + TupleType(N -> ty1.toUpper(ty1.prov) :: N -> ty2.toUpper(ty2.prov) :: Nil)(noProv) val builtinBindings: Bindings = { val tv = freshVar(noProv, N)(1) import FunctionType.{ apply => fun } - val intBinOpTy = fun(singleTup(IntType), fun(singleTup(IntType), IntType)(noProv))(noProv) - val numberBinOpTy = fun(singleTup(DecType), fun(singleTup(DecType), DecType)(noProv))(noProv) - val numberBinPred = fun(singleTup(DecType), fun(singleTup(DecType), BoolType)(noProv))(noProv) - val stringBinPred = fun(singleTup(StrType), fun(singleTup(StrType), BoolType)(noProv))(noProv) + val (intBinOpTy, numberBinOpTy, numberBinPred, stringBinPred) = if (newDefs) ( + fun(pair(IntType, IntType), IntType)(noProv), + fun(pair(DecType, DecType), DecType)(noProv), + fun(pair(DecType, DecType), BoolType)(noProv), + fun(pair(StrType, StrType), BoolType)(noProv), + ) + else ( + fun(singleTup(IntType), fun(singleTup(IntType), IntType)(noProv))(noProv), + fun(singleTup(DecType), fun(singleTup(DecType), DecType)(noProv))(noProv), + fun(singleTup(DecType), fun(singleTup(DecType), BoolType)(noProv))(noProv), + fun(singleTup(StrType), fun(singleTup(StrType), BoolType)(noProv))(noProv), + ) Map( "true" -> TrueType, "false" -> FalseType, @@ -337,11 +351,13 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne "===" -> { val v = freshVar(noProv, N)(1) val eq = TypeRef(TypeName("Eql"), v :: Nil)(noProv) - PolymorphicType(MinLevel, fun(singleTup(eq), fun(singleTup(v), BoolType)(noProv))(noProv)) + PolymorphicType(MinLevel, fun(pair(eq, v), BoolType)(noProv)) }, "<>" -> numberBinPred, - "&&" -> fun(singleTup(BoolType), fun(singleTup(BoolType), BoolType)(noProv))(noProv), - "||" -> fun(singleTup(BoolType), fun(singleTup(BoolType), BoolType)(noProv))(noProv), + "&&" -> (if (newDefs) fun(pair(BoolType, BoolType), BoolType)(noProv) + else fun(singleTup(BoolType), fun(singleTup(BoolType), BoolType)(noProv))(noProv)), + "||" -> (if (newDefs) fun(pair(BoolType, BoolType), BoolType)(noProv) + else fun(singleTup(BoolType), fun(singleTup(BoolType), BoolType)(noProv))(noProv)), "id" -> { val v = freshVar(noProv, N)(1) PolymorphicType(MinLevel, fun(singleTup(v), v)(noProv)) @@ -354,7 +370,8 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne val v = freshVar(noProv, N)(1) PolymorphicType(0, ArrayType(FieldType(S(v), v)(noProv))(noProv)) }, - ) ++ primTypes ++ primTypes.map(p => "" + p._1.capitalize -> p._2) // TODO settle on naming convention... + ) ++ (if (!newDefs) primTypes ++ primTypes.map(p => p._1.capitalize -> p._2) // TODO settle on naming convention... + else Nil) } @@ -986,11 +1003,19 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne val body_ty = typeTerm(body)(newCtx, raise, vars, generalizeCurriedFunctions || doGenLambdas) FunctionType(param_ty, body_ty)(tp(term.toLoc, "function")) - case App(App(Var("is"), _), _) => + case App(App(Var("is"), _), _) => // * Old-style operators val desug = If(IfThen(term, Var("true")), S(Var("false"))) term.desugaredTerm = S(desug) typeTerm(desug) - case App(App(Var("and"), Tup(_ -> Fld(_, lhs) :: Nil)), Tup(_ -> Fld(_, rhs) :: Nil)) => + case App(Var("is"), _) => + val desug = If(IfThen(term, Var("true")), S(Var("false"))) + term.desugaredTerm = S(desug) + typeTerm(desug) + case App(App(Var("and"), PlainTup(lhs)), PlainTup(rhs)) => // * Old-style operators + val desug = If(IfThen(lhs, rhs), S(Var("false"))) + term.desugaredTerm = S(desug) + typeTerm(desug) + case App(Var("and"), PlainTup(lhs, rhs)) => val desug = If(IfThen(lhs, rhs), S(Var("false"))) term.desugaredTerm = S(desug) typeTerm(desug) @@ -1551,7 +1576,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne mkTypingUnit(thisTy, members))(td.declareLoc, td.abstractLoc) } case tf @ TypedNuFun(level, fd, bodyTy) => - NuFunDef(fd.isLetRec, fd.nme, Nil, R(go(tf.typeSignature)))(fd.declareLoc, fd.signature, fd.outer) + NuFunDef(fd.isLetRec, fd.nme, fd.symbolicNme, Nil, R(go(tf.typeSignature)))(fd.declareLoc, fd.signature, fd.outer) case p: NuParam => ??? // TODO case TypedNuDummy(d) => diff --git a/shared/src/main/scala/mlscript/codegen/Helpers.scala b/shared/src/main/scala/mlscript/codegen/Helpers.scala index 5c466acf41..f5eca10462 100644 --- a/shared/src/main/scala/mlscript/codegen/Helpers.scala +++ b/shared/src/main/scala/mlscript/codegen/Helpers.scala @@ -68,7 +68,7 @@ object Helpers { case IfBlock(lines) => s"IfBlock(${ lines.iterator.map { case L(body) => inspect(body) - case R(NuFunDef(S(isRec), nme, _, L(rhs))) => + case R(NuFunDef(S(isRec), nme, _, _, L(rhs))) => s"Let($isRec, ${nme.name}, ${inspect(rhs)})" case R(_) => ??? }.mkString(";") @@ -85,10 +85,10 @@ object Helpers { def inspect(t: TypingUnit): Str = t.entities.iterator .map { case term: Term => inspect(term) - case NuFunDef(lt, nme, targs, L(term)) => - s"NuFunDef(${lt}, ${nme.name}, ${targs.mkString("[", ", ", "]")}, ${inspect(term)})" - case NuFunDef(lt, nme, targs, R(ty)) => - s"NuFunDef(${lt}, ${nme.name}, ${targs.mkString("[", ", ", "]")}, $ty)" + case NuFunDef(lt, nme, symNme, targs, L(term)) => + s"NuFunDef(${lt}, ${nme.name}, $symNme, ${targs.mkString("[", ", ", "]")}, ${inspect(term)})" + case NuFunDef(lt, nme, symNme, targs, R(ty)) => + s"NuFunDef(${lt}, ${nme.name}, $symNme, ${targs.mkString("[", ", ", "]")}, $ty)" case NuTypeDef(kind, nme, tparams, params, ctor, sig, parents, sup, ths, body) => s"NuTypeDef(${kind.str}, ${nme.name}, ${tparams.mkString("(", ", ", ")")}, ${ inspect(params.getOrElse(Tup(Nil)))}, ${parents.map(inspect).mkString("(", ", ", ")")}, $sup, $ths, ${inspect(body)})" diff --git a/shared/src/main/scala/mlscript/codegen/Scope.scala b/shared/src/main/scala/mlscript/codegen/Scope.scala index 015030de6a..a49b5d963a 100644 --- a/shared/src/main/scala/mlscript/codegen/Scope.scala +++ b/shared/src/main/scala/mlscript/codegen/Scope.scala @@ -262,7 +262,7 @@ class Scope(name: Str, enclosing: Opt[Scope]) { val finalName = if (allowRenaming) allocateRuntimeName(lexicalName) else lexicalName val (ctor, mths) = stmts.partitionMap { - case NuFunDef(isLetRec, Var(nme), tys, Left(rhs)) if (isLetRec.isEmpty || isLetRec.getOrElse(false)) => + case NuFunDef(isLetRec, Var(nme), _, tys, Left(rhs)) if (isLetRec.isEmpty || isLetRec.getOrElse(false)) => Right(MethodDef[Left[Term, Type]](isLetRec.getOrElse(false), TypeName(finalName), Var(nme), tys, Left(rhs))) case s => Left(s) } @@ -315,7 +315,7 @@ class Scope(name: Str, enclosing: Opt[Scope]) { symbol } - def declareValue(lexicalName: Str, isByvalueRec: Option[Boolean], isLam: Boolean): ValueSymbol = { + def declareValue(lexicalName: Str, isByvalueRec: Option[Boolean], isLam: Boolean, symbolicName: Opt[Str]): ValueSymbol = { val runtimeName = lexicalValueSymbols.get(lexicalName) match { // If we are implementing a stub symbol and the stub symbol did not shadow any other // symbols, it is safe to reuse its `runtimeName`. @@ -325,28 +325,30 @@ class Scope(name: Str, enclosing: Opt[Scope]) { } val symbol = ValueSymbol(lexicalName, runtimeName, isByvalueRec, isLam) register(symbol) + symbolicName.foreach { symbolicName => + register(ValueSymbol(symbolicName, runtimeName, isByvalueRec, isLam)) + } symbol } def declareOuterSymbol(): ValueSymbol = { val lexicalName = "outer" - val symbol = declareValue(lexicalName, Some(false), false) + val symbol = declareValue(lexicalName, Some(false), false, N) outerSymbols += symbol.runtimeName symbol } - def declareStubValue(lexicalName: Str)(implicit allowEscape: Bool): StubValueSymbol = - declareStubValue(lexicalName, N) + def declareStubValue(lexicalName: Str, symbolicName: Opt[Str])(implicit allowEscape: Bool): StubValueSymbol = + declareStubValue(lexicalName, N, symbolicName) - def declareStubValue(lexicalName: Str, previous: StubValueSymbol)(implicit + def declareStubValue(lexicalName: Str, previous: StubValueSymbol, symbolicName: Opt[Str])(implicit allowEscape: Bool ): StubValueSymbol = - declareStubValue(lexicalName, S(previous)) + declareStubValue(lexicalName, S(previous), symbolicName) - private def declareStubValue(lexicalName: Str, previous: Opt[StubValueSymbol])(implicit + private def declareStubValue(lexicalName: Str, previous: Opt[StubValueSymbol], symbolicName: Opt[Str])(implicit allowEscape: Bool ): StubValueSymbol = { - val symbol = lexicalValueSymbols.get(lexicalName) match { // If a stub with the same name has been defined, use the name. case S(value) => StubValueSymbol(lexicalName, value.runtimeName, true, previous) @@ -354,6 +356,9 @@ class Scope(name: Str, enclosing: Opt[Scope]) { case N => StubValueSymbol(lexicalName, allocateRuntimeName(lexicalName), false, previous) } register(symbol) + symbolicName.foreach { symbolicName => + register(StubValueSymbol(symbolicName, symbol.runtimeName, false, previous)) + } symbol } @@ -361,7 +366,7 @@ class Scope(name: Str, enclosing: Opt[Scope]) { allowEscape: Bool ): StubValueSymbol = { unregister(sym) - declareStubValue(sym.lexicalName, S(previous)) + declareStubValue(sym.lexicalName, S(previous), N) } def declareRuntimeSymbol(): Str = { diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index f8f7314aa8..eaca44bf7f 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -130,12 +130,13 @@ trait TypeLikeImpl extends Located { self: TypeLike => case Bounds(lo, hi) => s"\n${ctx.indStr}${lo.showIn(ctx, 0)} <: ${hi.showIn(ctx, 0)}" // TODO print differently from bs? }.mkString}" }, outerPrec > 0) - case NuFunDef(isLetRec, nme, targs, rhs) => + case NuFunDef(isLetRec, nme, snme, targs, rhs) => s"${isLetRec match { case S(false) => "let" case S(true) => "let rec" case N => "fun" - }} ${nme.name}${targs.map(_.showIn(ctx, 0)).mkStringOr(", ", "[", "]")}${rhs match { + }}${snme.fold("")(" (" + _.name + ")") + } ${nme.name}${targs.map(_.showIn(ctx, 0)).mkStringOr(", ", "[", "]")}${rhs match { case L(trm) => " = ..." case R(ty) => ": " + ty.showIn(ctx, 0) }}" @@ -190,7 +191,7 @@ trait TypeLikeImpl extends Located { self: TypeLike => case Splice(fs) => fs.flatMap{ case L(l) => l :: Nil case R(r) => r.in.toList ++ (r.out :: Nil) } case Constrained(b, bs, ws) => b :: bs.flatMap(c => c._1 :: c._2 :: Nil) ::: ws.flatMap(c => c.lb :: c.ub :: Nil) case Signature(xs, res) => xs ::: res.toList - case NuFunDef(isLetRec, nme, targs, rhs) => targs ::: rhs.toOption.toList + case NuFunDef(isLetRec, nme, snme, targs, rhs) => targs ::: rhs.toOption.toList case NuTypeDef(kind, nme, tparams, params, ctor, sig, parents, sup, ths, body) => // TODO improve this mess tparams.map(_._2) ::: params.getOrElse(Tup(Nil)).fields.collect { @@ -362,7 +363,7 @@ trait PgrmImpl { self: Pgrm => }.partitionMap { case td: TypeDef => L(td) case ot: Terms => R(ot) - case NuFunDef(isLetRec, nme, tys, rhs) => + case NuFunDef(isLetRec, nme, _, tys, rhs) => R(Def(isLetRec.getOrElse(true), nme, rhs, isLetRec.isEmpty)) } diags.toList -> res @@ -415,7 +416,7 @@ trait NuDeclImpl extends Located { self: NuDecl => } def name: Str = nameVar.name def showBody: Str = this match { - case NuFunDef(_, _, _, rhs) => rhs.fold(_.toString, _.showDbg2) + case NuFunDef(_, _, _, _, rhs) => rhs.fold(_.toString, _.showDbg2) case td: NuTypeDef => td.body.showDbg } def describe: Str = this match { @@ -423,14 +424,14 @@ trait NuDeclImpl extends Located { self: NuDecl => case _: NuTypeDef => "type declaration" } def showDbg: Str = showHead + (this match { - case NuFunDef(_, _, _, L(_)) => " = " - case NuFunDef(_, _, _, R(_)) => ": " + case NuFunDef(_, _, _, _, L(_)) => " = " + case NuFunDef(_, _, _, _, R(_)) => ": " case _: NuTypeDef => " " }) + showBody def showHead: Str = this match { - case NuFunDef(N, n, _, b) => s"fun $n" - case NuFunDef(S(false), n, _, b) => s"let $n" - case NuFunDef(S(true), n, _, b) => s"let rec $n" + case NuFunDef(N, n, snme, _, b) => s"fun${snme.fold("")(" ("+_+")")} $n" + case NuFunDef(S(false), n, snme, _, b) => s"let${snme.fold("")(" "+_+")")} $n" + case NuFunDef(S(true), n, snme, _, b) => s"let rec${snme.fold("")(" "+_+")")} $n" case NuTypeDef(k, n, tps, sps, ctor, sig, parents, sup, ths, bod) => s"${k.str} ${n.name}${if (tps.isEmpty) "" else tps.map(_._2.name).mkString("‹", ", ", "›")}(${ // sps.mkString("(",",",")") @@ -583,21 +584,24 @@ trait TermImpl extends StatementImpl { self: Term => case Var(name) if name.startsWith("'") => TypeVar(R(name), N) case Var(name) => TypeName(name) case lit: Lit => Literal(lit) - case App(App(Var("|"), Tup(N -> Fld(FldFlags(false, false), lhs) :: Nil)), Tup(N -> Fld(FldFlags(false, false), rhs) :: Nil)) => Union(lhs.toType_!, rhs.toType_!) - case App(App(Var("&"), Tup(N -> Fld(FldFlags(false, false), lhs) :: Nil)), Tup(N -> Fld(FldFlags(false, false), rhs) :: Nil)) => Inter(lhs.toType_!, rhs.toType_!) - case App(App(Var("->"), lhs), Tup(N -> Fld(FldFlags(false, false), rhs) :: Nil)) => Function(lhs.toType_!, rhs.toType_!) - case App(App(Var("->"), lhs), tup: Tup) => Function(lhs.toType_!, tup.toType_!) - case ty @ App(App(v @ Var("\\"), Tup(N -> Fld(FldFlags(false, false), lhs) :: Nil)), Tup(N -> Fld(FldFlags(false, false), rhs) :: Nil)) => + case App(Var("->"), PlainTup(lhs @ (_: Tup | Bra(false, _: Tup)), rhs)) => + // * ^ Note: don't think the plain _: Tup without a Bra can actually occur + Function(lhs.toType_!, rhs.toType_!) + case App(Var("->"), PlainTup(lhs, rhs)) => + Function(Tuple(N -> Field(N, lhs.toType_!) :: Nil), rhs.toType_!) + case App(Var("|"), PlainTup(lhs, rhs)) => + Union(lhs.toType_!, rhs.toType_!) + case App(Var("&"), PlainTup(lhs, rhs)) => + Inter(lhs.toType_!, rhs.toType_!) + case ty @ App(v @ Var("\\"), PlainTup(lhs, rhs)) => Inter(lhs.toType_!, Neg(rhs.toType_!).withLoc(Loc(v :: rhs :: Nil))).withLoc(ty.toCoveringLoc) - case App(App(Var("|"), lhs), rhs) => Union(lhs.toType_!, rhs.toType_!) - case App(App(Var("&"), lhs), rhs) => Inter(lhs.toType_!, rhs.toType_!) case App(Var("~"), rhs) => Neg(rhs.toType_!) case Lam(lhs, rhs) => Function(lhs.toType_!, rhs.toType_!) - case App(lhs, rhs) => lhs.toType_! match { - case AppliedType(base, targs) => AppliedType(base, targs :+ rhs.toType_!) - case p: TypeName => AppliedType(p, rhs.toType_! :: Nil) - case _ => throw new NotAType(this) - } + case App(lhs, PlainTup(fs @ _*)) => + lhs.toType_! match { + case tn: TypeName => AppliedType(tn, fs.iterator.map(_.toType_!).toList) + case _ => throw new NotAType(this) + } case Tup(fields) => Tuple(fields.map(fld => (fld._1, fld._2 match { case Fld(FldFlags(m, s), v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty) }))) @@ -634,15 +638,23 @@ trait TermImpl extends StatementImpl { self: Term => // case Test(trm, ty) => ??? // case With(trm, fieldNme, fieldVal) => ??? // case CaseOf(trm, cases) => ??? - // case IntLit(value) => ??? - // case DecLit(value) => ??? - // case StrLit(value) => ??? case _ => throw new NotAType(this) }).withLocOf(this) } private class NotAType(val trm: Statement) extends Throwable +object PlainTup { + def apply(fields: Term*): Term = + Tup(fields.iterator.map(t => (N, Fld(FldFlags(false, false), t))).toList) + def unapplySeq(trm: Term): Opt[List[Term]] = trm match { + case Tup(fields) if fields.forall(f => + f._1.isEmpty && f._2.flags.mut === false && f._2.flags.spec === false + ) => S(fields.map(_._2.value)) + case _ => N + } +} + trait LitImpl { self: Lit => def baseClassesOld: Set[TypeName] = this match { case _: IntLit => Set.single(TypeName("int")) + TypeName("number") @@ -906,7 +918,7 @@ trait StatementImpl extends Located { self: Statement => case Assign(lhs, rhs) => lhs :: rhs :: Nil case Splc(fields) => fields.map{case L(l) => l case R(r) => r.value} case If(body, els) => body :: els.toList - case d @ NuFunDef(_, v, ts, rhs) => v :: ts ::: d.body :: Nil + case d @ NuFunDef(_, v, v2, ts, rhs) => v :: v2.toList ::: ts ::: d.body :: Nil case TyApp(lhs, targs) => lhs :: targs case New(base, bod) => base.toList.flatMap(ab => ab._1 :: ab._2 :: Nil) ::: bod :: Nil case Where(bod, wh) => bod :: wh diff --git a/shared/src/main/scala/mlscript/syntax.scala b/shared/src/main/scala/mlscript/syntax.scala index fe9aa373d5..bc72cda3d2 100644 --- a/shared/src/main/scala/mlscript/syntax.scala +++ b/shared/src/main/scala/mlscript/syntax.scala @@ -105,6 +105,8 @@ final case class IfBlock(lines: Ls[IfBody \/ Statement]) extends IfBody final case class FldFlags(mut: Bool, spec: Bool) final case class Fld(flags: FldFlags, value: Term) extends FldImpl +object FldFlags { val empty: FldFlags = FldFlags(false, false) } + sealed abstract class CaseBranches extends CaseBranchesImpl final case class Case(pat: SimpleTerm, body: Term, rest: CaseBranches) extends CaseBranches final case class Wildcard(body: Term) extends CaseBranches @@ -209,6 +211,7 @@ final case class NuTypeDef( final case class NuFunDef( isLetRec: Opt[Bool], // None means it's a `fun`, which is always recursive; Some means it's a `let` nme: Var, + symbolicNme: Opt[Var], tparams: Ls[TypeName], rhs: Term \/ Type, )(val declareLoc: Opt[Loc], val signature: Opt[NuFunDef], val outer: Opt[Outer]) extends NuDecl with DesugaredStatement { diff --git a/shared/src/main/scala/mlscript/ucs/Desugarer.scala b/shared/src/main/scala/mlscript/ucs/Desugarer.scala index 837c821dab..cb80af3fc4 100644 --- a/shared/src/main/scala/mlscript/ucs/Desugarer.scala +++ b/shared/src/main/scala/mlscript/ucs/Desugarer.scala @@ -420,7 +420,12 @@ class Desugarer extends TypeDefs { self: Typer => App(Var("is"), Tup(_ -> Fld(_, scrutinee) :: Nil)), Tup(_ -> Fld(_, pattern) :: Nil) - ) => + ) if !newDefs => // * Old-style operators + // This is an inline `x is Class` match test. + val inlineMatchLoc = isApp.toLoc + val inlineScrutinee = makeScrutinee(scrutinee, inlineMatchLoc) + destructPattern(inlineScrutinee, pattern, true)(ctx, raise, exhaustivenessMap, scrutineeFieldAliasMap) + case isApp @ App(Var("is"), PlainTup(scrutinee, pattern)) => // This is an inline `x is Class` match test. val inlineMatchLoc = isApp.toLoc val inlineScrutinee = makeScrutinee(scrutinee, inlineMatchLoc) @@ -468,8 +473,8 @@ class Desugarer extends TypeDefs { self: Typer => // A(...) then ... // Case 1: no conjunctions // B(...) and ... then ... // Case 2: more conjunctions case L(IfThen(patTest, consequent)) => - val (patternPart, extraTestOpt) = separatePattern(patTest) - val clauses = destructPattern(scrutinee, partialPattern.addTerm(patternPart).term, true) + val (patternPart, extraTestOpt) = separatePattern(patTest, newDefs) + val clauses = destructPattern(scrutinee, partialPattern.addTerm(patternPart, newDefs).term, true) val conditions = collectedConditions + Conjunction(clauses, Nil).withBindings printlnUCS(s"Result: " + conditions.clauses.mkString(", ")) extraTestOpt match { @@ -488,14 +493,14 @@ class Desugarer extends TypeDefs { self: Typer => // B(...) then ... // B(...) then ... case L(IfOpApp(patLhs, Var("and"), consequent)) => - val (pattern, optTests) = separatePattern(patLhs) + val (pattern, optTests) = separatePattern(patLhs, newDefs) val patternConditions = destructPattern(scrutinee, pattern, true) val tailTestConditions = optTests.fold(Nil: Ls[Clause])(x => desugarConditions(splitAnd(x))) val conditions = collectedConditions + Conjunction(patternConditions ::: tailTestConditions, Nil).withBindings desugarIfBody(consequent, PartialTerm.Empty, conditions) case L(IfOpApp(patLhs, op, consequent)) => - separatePattern(patLhs) match { + separatePattern(patLhs, newDefs) match { // Case 1. // The pattern is completed. There is also a conjunction. // So, we need to separate the pattern from remaining parts. @@ -512,17 +517,17 @@ class Desugarer extends TypeDefs { self: Typer => // Nil then ... // do something with head // tail then ... // do something with head and tail case (patternPart, N) => - desugarMatchBranch(scrutinee, L(consequent), partialPattern.addTermOp(patternPart, op), collectedConditions) + desugarMatchBranch(scrutinee, L(consequent), partialPattern.addTermOp(patternPart, op, newDefs), collectedConditions) } case L(IfOpsApp(patLhs, opsRhss)) => - separatePattern(patLhs) match { + separatePattern(patLhs, newDefs) match { case (patternPart, N) => - val partialPattern2 = partialPattern.addTerm(patternPart) + val partialPattern2 = partialPattern.addTerm(patternPart, newDefs) opsRhss.foreach { case op -> consequent => desugarMatchBranch(scrutinee, L(consequent), partialPattern2.addOp(op), collectedConditions) } case (patternPart, S(extraTests)) => - val patternConditions = destructPattern(scrutinee, partialPattern.addTerm(patternPart).term, true) + val patternConditions = destructPattern(scrutinee, partialPattern.addTerm(patternPart, newDefs).term, true) val testTerms = splitAnd(extraTests) val middleConditions = desugarConditions(testTerms.init) val conditions = @@ -541,7 +546,7 @@ class Desugarer extends TypeDefs { self: Typer => case L(IfLet(_, _, _, _)) => TODO("please add this rare case to test files") // This case handles interleaved lets. - case R(NuFunDef(S(isRec), nameVar, _, L(term))) => + case R(NuFunDef(S(isRec), nameVar, _, _, L(term))) => interleavedLets += (LetBinding(LetBinding.Kind.InterleavedLet, isRec, nameVar, term)) // Other statements are considered to be ill-formed. case R(statement) => throw new DesugaringException({ @@ -556,7 +561,7 @@ class Desugarer extends TypeDefs { self: Typer => : Unit = traceUCS[Unit]("[desugarIfBody]") { body match { case IfOpsApp(exprPart, opsRhss) => - val exprStart = expr.addTerm(exprPart) + val exprStart = expr.addTerm(exprPart, newDefs) opsRhss.foreach { case opVar -> contBody => desugarIfBody(contBody, exprStart.addOp(opVar), acc) } @@ -564,7 +569,7 @@ class Desugarer extends TypeDefs { self: Typer => branches += (acc -> consequent) // The termination case. case IfThen(term, consequent) => - val totalTerm = expr.addTerm(term) + val totalTerm = expr.addTerm(term, newDefs) // “Atomic” means terms that do not contain `and`. val atomicTerms = splitAnd(totalTerm.term) val fragments = atomicTerms ::: totalTerm.fragments @@ -574,7 +579,7 @@ class Desugarer extends TypeDefs { self: Typer => case IfOpApp(scrutineePart, isVar @ Var("is"), IfBlock(lines)) => // Create a synthetic scrutinee term by combining accumulated partial // term with the new part. - val scrutineeTerm = expr.addTerm(scrutineePart).term + val scrutineeTerm = expr.addTerm(scrutineePart, newDefs).term // We don't need to include the entire `IfOpApp` because it might be // very long... Indicating the beginning of the match is enough. val matchRootLoc = (scrutineeTerm.toLoc, isVar.toLoc) match { @@ -596,12 +601,12 @@ class Desugarer extends TypeDefs { self: Typer => } // For example: "if x == 0 and y is \n ..." case IfOpApp(testPart, Var("and"), consequent) => - val conditions = acc + (desugarConditions(expr.addTerm(testPart).term :: Nil)) + val conditions = acc + (desugarConditions(expr.addTerm(testPart, newDefs).term :: Nil)) desugarIfBody(consequent, PartialTerm.Empty, conditions) // Otherwise, this is not a pattern matching. // We create a partial term from `lhs` and `op` and dive deeper. case IfOpApp(lhs, op, body) => - desugarIfBody(body, expr.addTermOp(lhs, op), acc) + desugarIfBody(body, expr.addTermOp(lhs, op, newDefs), acc) // This case is rare. Let's put it aside. case IfLet(isRec, name, rhs, body) => TODO("please add this rare case to test files") @@ -611,7 +616,7 @@ class Desugarer extends TypeDefs { self: Typer => case IfBlock(lines) => lines.foreach { case L(subBody) => desugarIfBody(subBody, expr, acc) - case R(NuFunDef(S(isRec), nameVar, _, L(term))) => + case R(NuFunDef(S(isRec), nameVar, _, _, L(term))) => printlnUCS(s"Found interleaved binding ${nameVar.name}") interleavedLets += LetBinding(LetBinding.Kind.InterleavedLet, isRec, nameVar, term) case R(_) => diff --git a/shared/src/main/scala/mlscript/ucs/PartialTerm.scala b/shared/src/main/scala/mlscript/ucs/PartialTerm.scala index 3726d7a56a..7ce2d6a001 100644 --- a/shared/src/main/scala/mlscript/ucs/PartialTerm.scala +++ b/shared/src/main/scala/mlscript/ucs/PartialTerm.scala @@ -15,33 +15,33 @@ class PartialTermError(term: PartialTerm, message: Str) extends Error(message) */ sealed abstract class PartialTerm { val fragments: Ls[Term] - def addTerm(term: Term): PartialTerm.Total + def addTerm(term: Term, newDefs: Bool): PartialTerm.Total def addOp(op: Var): PartialTerm.Half - def addTermOp(term: Term, op: Var): PartialTerm.Half = - this.addTerm(term).addOp(op) + def addTermOp(term: Term, op: Var, newDefs: Bool): PartialTerm.Half = + this.addTerm(term, newDefs).addOp(op) } object PartialTerm { final case object Empty extends PartialTerm { val fragments: Ls[Term] = Nil - def addTerm(term: Term): Total = Total(term, term :: Nil) + def addTerm(term: Term, newDefs: Bool): Total = Total(term, term :: Nil) def addOp(op: Var): Half = throw new PartialTermError(this, s"expect a term but operator $op was given") } final case class Total(term: Term, fragments: Ls[Term]) extends PartialTerm { - def addTerm(term: Term): Total = + def addTerm(term: Term, newDefs: Bool): Total = throw new PartialTermError(this, s"expect an operator but term $term was given") def addOp(op: Var): Half = Half(term, op, op :: fragments) } final case class Half(lhs: Term, op: Var, fragments: Ls[Term]) extends PartialTerm { - def addTerm(rhs: Term): Total = { - val (realRhs, extraExprOpt) = separatePattern(rhs) - val leftmost = mkBinOp(lhs, op, realRhs) + def addTerm(rhs: Term, newDefs: Bool): Total = { + val (realRhs, extraExprOpt) = separatePattern(rhs, newDefs) + val leftmost = mkBinOp(lhs, op, realRhs, newDefs) extraExprOpt match { case N => Total(leftmost, fragments) - case S(extraExpr) => Total(mkBinOp(leftmost, Var("and"), extraExpr), extraExpr :: fragments) + case S(extraExpr) => Total(mkBinOp(leftmost, Var("and"), extraExpr, newDefs), extraExpr :: fragments) } } def addOp(op: Var): Half = diff --git a/shared/src/main/scala/mlscript/ucs/helpers.scala b/shared/src/main/scala/mlscript/ucs/helpers.scala index df86f28c3f..e4ab4597bf 100644 --- a/shared/src/main/scala/mlscript/ucs/helpers.scala +++ b/shared/src/main/scala/mlscript/ucs/helpers.scala @@ -26,8 +26,9 @@ object helpers { * @param rhs the right-hand side term * @return something like `App(App(op, lhs), rhs)` */ - def mkBinOp(lhs: Term, op: Var, rhs: Term): Term = - App(App(op, mkMonuple(lhs)), mkMonuple(rhs)) + def mkBinOp(lhs: Term, op: Var, rhs: Term, newDefs: Bool): Term = + if (newDefs) App(op, PlainTup(lhs, rhs)) + else App(App(op, mkMonuple(lhs)), mkMonuple(rhs)) /** * Split a term joined by `and` into a list of terms. @@ -41,7 +42,9 @@ object helpers { App(Var("and"), Tup((_ -> Fld(_, lhs)) :: Nil)), Tup((_ -> Fld(_, rhs)) :: Nil) - ) => + ) => // * Old-style operators + splitAnd(lhs) :+ rhs + case App(Var("and"), PlainTup(lhs, rhs)) => splitAnd(lhs) :+ rhs case _ => t :: Nil } @@ -64,16 +67,21 @@ object helpers { * @return a tuple, whose the first element is the pattern and the second * element is the extra test */ - def separatePattern(term: Term): (Term, Opt[Term]) = + def separatePattern(term: Term, newDefs: Bool): (Term, Opt[Term]) = term match { case App( App(and @ Var("and"), Tup((_ -> Fld(_, lhs)) :: Nil)), Tup((_ -> Fld(_, rhs)) :: Nil) - ) => - separatePattern(lhs) match { + ) => // * Old-style operators + separatePattern(lhs, newDefs) match { + case (pattern, N) => (pattern, S(rhs)) + case (pattern, S(lshRhs)) => (pattern, S(mkBinOp(lshRhs, and, rhs, newDefs))) + } + case App(and @ Var("and"), PlainTup(lhs, rhs)) => + separatePattern(lhs, newDefs) match { case (pattern, N) => (pattern, S(rhs)) - case (pattern, S(lshRhs)) => (pattern, S(mkBinOp(lshRhs, and, rhs))) + case (pattern, S(lshRhs)) => (pattern, S(mkBinOp(lshRhs, and, rhs, newDefs))) } case _ => (term, N) } diff --git a/shared/src/test/diff/basics/Datatypes.fun b/shared/src/test/diff/basics/Datatypes.fun index 86d9a89fde..1bb3531674 100644 --- a/shared/src/test/diff/basics/Datatypes.fun +++ b/shared/src/test/diff/basics/Datatypes.fun @@ -110,28 +110,32 @@ Tru : Boolean :p :w +:e data type List a of Nil Cons (head: a) (tail: List a) //│ Parsed: data type List a of {Nil; Cons '(' {head: a,} ')' '(' {tail: List a,} ')'}; +//│ ╔══[ERROR] not a recognized type +//│ ║ l.116: Cons (head: a) (tail: List a) +//│ ╙── ^^^^^^ //│ Desugared: type alias List[a] = Nil[a] | Cons[a] //│ Desugared: class Nil[a]: {} -//│ Desugared: class Cons[a]: {head: a, tail: List[a]} +//│ Desugared: class Cons[a]: {head: a, tail: anything} //│ Desugared: def Nil: forall a. Nil[a] //│ AST: Def(false, Nil, PolyType(List(Left(TypeName(a))),AppliedType(TypeName(Nil),List(TypeName(a)))), true) -//│ Desugared: def Cons: forall a. (head: a) -> (tail: List[a]) -> Cons[a] -//│ AST: Def(false, Cons, PolyType(List(Left(TypeName(a))),Function(Tuple(List((Some(head),Field(None,TypeName(a))))),Function(Tuple(List((Some(tail),Field(None,AppliedType(TypeName(List),List(TypeName(a))))))),AppliedType(TypeName(Cons),List(TypeName(a)))))), true) +//│ Desugared: def Cons: forall a. (head: a) -> (tail: anything) -> Cons[a] +//│ AST: Def(false, Cons, PolyType(List(Left(TypeName(a))),Function(Tuple(List((Some(head),Field(None,TypeName(a))))),Function(Tuple(List((Some(tail),Field(None,Top)))),AppliedType(TypeName(Cons),List(TypeName(a)))))), true) //│ Defined type alias List[+a] //│ Defined class Nil[±a] //│ Defined class Cons[+a] //│ ╔══[WARNING] Type definition Nil has bivariant type parameters: -//│ ║ l.114: Nil +//│ ║ l.115: Nil //│ ║ ^^^ //│ ╟── a is irrelevant and may be removed -//│ ║ l.113: data type List a of +//│ ║ l.114: data type List a of //│ ╙── ^ //│ Nil: Nil[?] -//│ Cons: (head: 'a,) -> (tail: List['a],) -> Cons['a] +//│ Cons: (head: 'a,) -> (tail: anything,) -> Cons['a] // TODO interpret as free type variable? :p @@ -142,7 +146,7 @@ data type Ls of LsA a //│ Desugared: def LsA: forall a. (...a) -> LsA[a] //│ AST: Def(false, LsA, PolyType(List(Left(TypeName(a))),Function(TypeName(a),AppliedType(TypeName(LsA),List(TypeName(a))))), true) //│ ╔══[ERROR] type identifier not found: a -//│ ║ l.138: data type Ls of LsA a +//│ ║ l.142: data type Ls of LsA a //│ ╙── ^ //│ Defined type alias Ls //│ Defined class LsA[+a] @@ -157,7 +161,7 @@ data type Ls2 of LsA2 `a //│ Desugared: def LsA2: (...'a) -> LsA2[] //│ AST: Def(false, LsA2, PolyType(List(),Function(a,AppliedType(TypeName(LsA2),List()))), true) //│ ╔══[ERROR] cannot inherit from a polymorphic type -//│ ║ l.153: data type Ls2 of LsA2 `a +//│ ║ l.157: data type Ls2 of LsA2 `a //│ ╙── ^^^^^^^ //│ ╔══[ERROR] type identifier not found: LsA2 //│ ╙── @@ -172,10 +176,10 @@ Cons 1 Cons 2 Nil Cons 1 (Cons 2 Nil) //│ res: Nil[?] -//│ res: (head: 'a,) -> (tail: List['a],) -> Cons['a] -//│ res: (tail: List['a],) -> Cons[1 | 'a] +//│ res: (head: 'a,) -> (tail: anything,) -> Cons['a] +//│ res: (tail: anything,) -> Cons[1] //│ res: Cons[2] -//│ res: Cons[1 | 2] +//│ res: Cons[1] (Cons 3 Nil).head succ (Cons 3 Nil).head @@ -187,54 +191,38 @@ not (Cons false Nil).head :e not (Cons 42 Nil).head //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.188: not (Cons 42 Nil).head +//│ ║ l.192: not (Cons 42 Nil).head //│ ║ ^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── integer literal of type `42` is not an instance of type `bool` -//│ ║ l.188: not (Cons 42 Nil).head +//│ ║ l.192: not (Cons 42 Nil).head //│ ║ ^^ //│ ╟── but it flows into field selection with expected type `bool` -//│ ║ l.188: not (Cons 42 Nil).head +//│ ║ l.192: not (Cons 42 Nil).head //│ ╙── ^^^^^ //│ res: bool | error :e (Cons 4).head //│ ╔══[ERROR] Type mismatch in field selection: -//│ ║ l.201: (Cons 4).head +//│ ║ l.205: (Cons 4).head //│ ║ ^^^^^ -//│ ╟── type `(tail: List[?a],) -> Cons[?a]` does not have field 'head' -//│ ║ l.113: data type List a of -//│ ║ ^^^^ -//│ ║ l.114: Nil -//│ ║ ^^^^^ -//│ ║ l.115: Cons (head: a) (tail: List a) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `(tail: anything,) -> Cons[?a]` does not have field 'head' +//│ ║ l.114: data type List a of +//│ ║ ^ //│ ╟── but it flows into receiver with expected type `{head: ?head}` -//│ ║ l.201: (Cons 4).head +//│ ║ l.205: (Cons 4).head //│ ╙── ^^^^^^^^ //│ res: error -:e +// :e Cons 1 2 -//│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.218: Cons 1 2 -//│ ║ ^^^^^^^^ -//│ ╟── integer literal of type `2` does not match type `Cons[?a] | Nil[?]` -//│ ║ l.218: Cons 1 2 -//│ ║ ^ -//│ ╟── Note: constraint arises from union type: -//│ ║ l.113: data type List a of -//│ ║ ^ -//│ ╟── from tuple type: -//│ ║ l.115: Cons (head: a) (tail: List a) -//│ ╙── ^^^^^^ -//│ res: Cons[1] | error +//│ res: Cons[1] // TODO Allow method/field defintions in the same file (lose the let?): :e let List.head = () // ... //│ ╔══[ERROR] Unsupported pattern shape -//│ ║ l.235: let List.head = () // ... +//│ ║ l.223: let List.head = () // ... //│ ╙── ^^^^^ //│ : () diff --git a/shared/src/test/diff/codegen/SymbolicOps.mls b/shared/src/test/diff/codegen/SymbolicOps.mls new file mode 100644 index 0000000000..c2e09605e4 --- /dev/null +++ b/shared/src/test/diff/codegen/SymbolicOps.mls @@ -0,0 +1,343 @@ +:NewDefs + + +fun (>>) compose(f, g) = x => g(f(x)) +//│ fun (>>) compose: forall 'a 'b 'c. ('a -> 'b, 'b -> 'c) -> 'a -> 'c + +:js +let r = succ >> succ +//│ let r: Int -> Int +//│ // Prelude +//│ function succ(x) { +//│ return x + 1; +//│ } +//│ class TypingUnit1 {} +//│ const typing_unit1 = new TypingUnit1; +//│ // Query 1 +//│ globalThis.r = compose(succ, succ); +//│ // End of generated code +//│ r +//│ = [Function (anonymous)] + +r(3) +//│ Int +//│ res +//│ = 5 + +compose(succ, succ)(3) +//│ Int +//│ res +//│ = 5 + +(succ >> succ)(3) +//│ Int +//│ res +//│ = 5 + +(succ >> succ) of 3 +//│ Int +//│ res +//│ = 5 + +// * Note the high left-precedence of `of` +:e +succ >> succ of 3 +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.44: succ >> succ of 3 +//│ ║ ^^^^^^^^^^^^^^^^^ +//│ ╟── application of type `Int` is not a function +//│ ║ l.44: succ >> succ of 3 +//│ ║ ^^^^^^^^^ +//│ ╟── Note: constraint arises from application: +//│ ║ l.4: fun (>>) compose(f, g) = x => g(f(x)) +//│ ║ ^^^^^^^ +//│ ╟── from reference: +//│ ║ l.4: fun (>>) compose(f, g) = x => g(f(x)) +//│ ╙── ^ +//│ error | Int -> Int +//│ res +//│ = [Function (anonymous)] + +:js +let f = (>>) +//│ let f: forall 'a 'b. ((3 | 'a) -> Int, Int -> 'b) -> (Int & 'a) -> (Int | 'b) +//│ // Prelude +//│ class TypingUnit7 {} +//│ const typing_unit7 = new TypingUnit7; +//│ // Query 1 +//│ globalThis.f = compose; +//│ // End of generated code +//│ f +//│ = [Function: compose] + +f(succ, succ)(3) +//│ Int +//│ res +//│ = 5 + +(>>)(succ, succ)(3) +//│ Int +//│ res +//│ = 5 + +(>>) of succ, succ +//│ Int -> Int +//│ res +//│ = [Function (anonymous)] + +((>>) of succ, succ) of 3 +//│ Int +//│ res +//│ = 5 + +:e // TODO parse this differently? +(>>) of succ, succ + of 3 +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.94: (>>) of succ, succ +//│ ║ ^^^^^^^^^^^^^^^^^ +//│ ║ l.95: of 3 +//│ ║ ^^^^^^ +//│ ╟── application of type `Int` is not a function +//│ ║ l.94: (>>) of succ, succ +//│ ║ ^^^^ +//│ ║ l.95: of 3 +//│ ║ ^^^^^^ +//│ ╟── Note: constraint arises from application: +//│ ║ l.4: fun (>>) compose(f, g) = x => g(f(x)) +//│ ║ ^^^^^^^ +//│ ╟── from reference: +//│ ║ l.4: fun (>>) compose(f, g) = x => g(f(x)) +//│ ╙── ^ +//│ error | Int -> Int +//│ res +//│ = [Function (anonymous)] + + +:ge // TODO support this syntax for builtin operators +fun oops = (+) +//│ fun oops: (Int, Int) -> Int +//│ Code generation encountered an error: +//│ unresolved symbol + + + +fun (%) mod = div +//│ fun (%) mod: (Int, Int) -> Int + +// TODO builtin `div` should compute *integer* division +12 % 5 +//│ Int +//│ res +//│ = 2.4 + + + +// TODO support code-gen for non-top-level operator definitions +module Nested { + fun (++) conc(a, b) = concat(a)(b) + log("abc" ++ "def") +} +//│ module Nested { +//│ fun (++) conc: (Str, Str) -> Str +//│ } +//│ Code generation encountered an error: +//│ unresolved symbol ++ + +// TODO +abstract class Nested { + fun (++) conc: (Int, Int) -> Int + log("abc" ++ "def") +} +//│ ╔══[ERROR] identifier not found: ++ +//│ ║ l.149: log("abc" ++ "def") +//│ ╙── ^^ +//│ abstract class Nested { +//│ fun (++) conc: (Int, Int) -> Int +//│ } +//│ Code generation encountered an error: +//│ unresolved symbol ++ + + + +fun (??) oops: (Int, Int) => Int +//│ fun (??) oops: (Int, Int) -> Int + +1 ?? 2 +//│ Int +//│ res +//│ = +//│ ?? is not implemented + +fun (??) oops: (Int, Int) => Int +fun oops(a, b) = a + b +//│ fun oops: (Int, Int) -> Int +//│ fun (??) oops: (Int, Int) -> Int + +// FIXME-later (stub symbols) This is actually implemented... +1 ?? 2 +//│ Int +//│ res +//│ = +//│ ?? is not implemented + +fun oops: (Int, Int) => Int +fun (??) oops(a, b) = a + b +//│ fun (??) oops: (Int, Int) -> Int +//│ fun oops: (Int, Int) -> Int + +1 ?? 2 +//│ Int +//│ res +//│ = 3 + +fun (!?) oops: (Int, Int) => Int +fun (??) oops(a, b) = a + b +//│ fun (??) oops: (Int, Int) -> Int +//│ fun (!?) oops: (Int, Int) -> Int + +1 ?? 2 +//│ Int +//│ res +//│ = 3 + +1 !? 2 +//│ Int +//│ res +//│ = +//│ !? is not implemented + + + +// * Note: some malformed definitions + +:pe +:e +fun (>>)(f, g) = x => g(f(x)) +//│ ╔══[PARSE ERROR] Expected a function name; found parenthesis section instead +//│ ║ l.215: fun (>>)(f, g) = x => g(f(x)) +//│ ╙── ^^^^^^ +//│ ╔══[ERROR] identifier not found: g +//│ ║ l.215: fun (>>)(f, g) = x => g(f(x)) +//│ ╙── ^ +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.215: fun (>>)(f, g) = x => g(f(x)) +//│ ║ ^^^^ +//│ ╟── argument of type `[?a]` does not match type `[?b, ?c]` +//│ ║ l.215: fun (>>)(f, g) = x => g(f(x)) +//│ ║ ^^^ +//│ ╟── Note: constraint arises from tuple literal: +//│ ║ l.4: fun (>>) compose(f, g) = x => g(f(x)) +//│ ╙── ^^^^^^ +//│ fun (>>) : anything -> error +//│ Code generation encountered an error: +//│ unresolved symbol g + +:pe +fun compose(>>)(f, g) = x => g(f(x)) +//│ ╔══[PARSE ERROR] Unexpected operator here +//│ ║ l.236: fun compose(>>)(f, g) = x => g(f(x)) +//│ ╙── ^^ +//│ fun compose: forall 'a 'b 'c. () -> ('a -> 'b, 'b -> 'c) -> 'a -> 'c + + +:pe +fun () foo(a, b) = a + b +//│ ╔══[PARSE ERROR] Expected a symbolic name between brackets, found nothing +//│ ║ l.244: fun () foo(a, b) = a + b +//│ ╙── ^^ +//│ fun foo: (Int, Int) -> Int + +:pe +fun ( ) foo(a, b) = a + b +//│ ╔══[PARSE ERROR] Expected a symbolic name, found space instead +//│ ║ l.251: fun ( ) foo(a, b) = a + b +//│ ╙── ^^^ +//│ fun foo: (Int, Int) -> Int + +:pe +fun ( +) foo(a, b) = a + b +//│ ╔══[PARSE ERROR] Expected a symbolic name, found newline instead +//│ ║ l.258: fun ( +//│ ║ ^ +//│ ║ l.259: ) foo(a, b) = a + b +//│ ╙── +//│ fun foo: (Int, Int) -> Int + +:pe +fun (1) foo(a, b) = a + b +//│ ╔══[PARSE ERROR] Expected a symbolic name, found literal instead +//│ ║ l.268: fun (1) foo(a, b) = a + b +//│ ╙── ^ +//│ fun foo: (Int, Int) -> Int + +:pe +fun (++ 1) foo(a, b) = a + b +//│ ╔══[PARSE ERROR] Unexpected literal after symbolic name +//│ ║ l.275: fun (++ 1) foo(a, b) = a + b +//│ ╙── ^ +//│ fun (++) foo: (Int, Int) -> Int + +:pe +fun (a ++ 1) foo(a, b) = a + b +//│ ╔══[PARSE ERROR] Expected a symbolic name, found identifier instead +//│ ║ l.282: fun (a ++ 1) foo(a, b) = a + b +//│ ╙── ^ +//│ fun foo: (Int, Int) -> Int +// should be `<<|+_+|>>`, but we got `<<|+` + + +:pe +fun (<<|+_+|>>) robot(a, b) = a + b +//│ ╔══[PARSE ERROR] Unexpected identifier after symbolic name +//│ ║ l.291: fun (<<|+_+|>>) robot(a, b) = a + b +//│ ╙── ^ +//│ fun (<<|+) robot: (Int, Int) -> Int + +fun (<<|+-+|>>) robot(a, b) = a + b +//│ fun (<<|+-+|>>) robot: (Int, Int) -> Int + +2 <<|+-+|>> 2 +//│ Int +//│ res +//│ = 4 + + +:pe +fun (:-D) dd(a, b) = a + b +//│ ╔══[PARSE ERROR] Unexpected identifier after symbolic name +//│ ║ l.307: fun (:-D) dd(a, b) = a + b +//│ ╙── ^ +//│ fun (:-) dd: (Int, Int) -> Int +// should be `:-D`, but we got `:-` + + +val (->) f(x, y) = [x, y] +//│ let (->) f: forall 'a 'b. ('a, 'b) -> ['a, 'b] +//│ f +//│ = [Function: f1] + +12 -> 34 +//│ [12, 34] +//│ res +//│ = [ 12, 34 ] + + +let (->) _ = f +//│ let (->) _: forall 'a 'b. ('a, 'b) -> ['a, 'b] +//│ _ +//│ = [Function: f1] + +:js +12 -> 34 +//│ [12, 34] +//│ // Prelude +//│ class TypingUnit42 {} +//│ const typing_unit42 = new TypingUnit42; +//│ // Query 1 +//│ res = _(12, 34); +//│ // End of generated code +//│ res +//│ = [ 12, 34 ] + + diff --git a/shared/src/test/diff/ecoop23/PolymorphicVariants.mls b/shared/src/test/diff/ecoop23/PolymorphicVariants.mls index 964fc4f580..952b76ee69 100644 --- a/shared/src/test/diff/ecoop23/PolymorphicVariants.mls +++ b/shared/src/test/diff/ecoop23/PolymorphicVariants.mls @@ -113,7 +113,7 @@ Test1.eval(Cons(("c", Var("d")), Nil), App(Abs("b", Var("b")), Var("c"))) Test1.eval(Cons(("c", Abs("d", Var("d"))), Nil), App(Abs("b", Var("b")), Var("c"))) //│ forall 'a. 'A | 'a //│ where -//│ 'A :> 'a | Abs[Var] | Var +//│ 'A :> Abs[Var] | Var | 'a //│ 'a :> App['A] | Abs['A] //│ res //│ = Var {} @@ -131,7 +131,7 @@ fun map_expr(f, v) = Numb then v Add(l, r) then Add(f(l), f(r)) Mul(l, r) then Mul(f(l), f(r)) -//│ fun map_expr: forall 'A 'l 'A0 'l0. ('l -> 'A0 & 'l0 -> 'A, Add['l] | Mul['l0] | Numb | Var) -> (Add['A0] | Mul['A] | Numb | Var) +//│ fun map_expr: forall 'l 'A 'l0 'A0. ('l -> 'A & 'l0 -> 'A0, Add['l] | Mul['l0] | Numb | Var) -> (Add['A] | Mul['A0] | Numb | Var) mixin EvalExpr { fun eval(sub, v) = @@ -198,7 +198,7 @@ Test2.eval(Cons(("a", Abs("d", Var("d"))), Nil), Add(Numb(1), Var("a"))) module Test3 extends EvalVar, EvalExpr, EvalLambda //│ module Test3 { -//│ fun eval: forall 'a 'A. (Cons[{_1: anything, _2: 'result}] | Nil, Abs['b] | App['A] | Object & 'c & ~#Abs & ~#App) -> ('A0 | 'a) +//│ fun eval: forall 'A 'a. (Cons[{_1: anything, _2: 'result}] | Nil, Abs['b] | App['A] | Object & 'c & ~#Abs & ~#App) -> ('A0 | 'a) //│ } //│ where //│ 'result :> 'A0 @@ -220,7 +220,7 @@ Test3.eval(Cons(("c", Abs("d", Var("d"))), Nil), Abs("a", Var("a"))) Test3.eval(Cons(("c", Abs("d", Var("d"))), Nil), App(Abs("a", Var("a")), Add(Numb(1), Var("c")))) //│ forall 'a. 'A | 'a //│ where -//│ 'A :> Abs[Var] | Add[Numb | Var] | Numb | Var | 'a +//│ 'A :> 'a | Abs[Var] | Add[Numb | Var] | Numb | Var //│ 'a :> App['A] | Abs['A] //│ res //│ = Var {} diff --git a/shared/src/test/diff/ecoop23/SimpleRegionDSL.mls b/shared/src/test/diff/ecoop23/SimpleRegionDSL.mls index 541923f8b6..92e12f840f 100644 --- a/shared/src/test/diff/ecoop23/SimpleRegionDSL.mls +++ b/shared/src/test/diff/ecoop23/SimpleRegionDSL.mls @@ -302,7 +302,7 @@ module TestElim extends Eliminate //│ where //│ 'b <: Intersect['b] | Object & 'c & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['b & (Object & ~#Outside | Outside['b])] | Scale['b] | Translate['b] | Union['b] //│ 'c :> 'a -//│ 'a :> Outside['c] | Translate['c] | Scale['c] | Union['c] | Intersect['c] +//│ 'a :> Outside['c] | Union['c] | Intersect['c] | Translate['c] | Scale['c] TestElim.eliminate(Outside(Outside(Univ()))) //│ forall 'a. 'b | 'a @@ -336,7 +336,7 @@ fun mk(n) = if n is TestElim.eliminate(mk(100)) //│ forall 'a. 'a //│ where -//│ 'a :> Outside['Region] | Union['Region] | Intersect['Region] | Translate['Region] | Scale['Region] +//│ 'a :> Outside['Region] | Translate['Region] | Scale['Region] | Union['Region] | Intersect['Region] //│ 'Region :> 'a //│ res //│ Runtime error: diff --git a/shared/src/test/diff/gadt/ThisMatching.mls b/shared/src/test/diff/gadt/ThisMatching.mls index 1b24d1d92e..d15c22d9ad 100644 --- a/shared/src/test/diff/gadt/ThisMatching.mls +++ b/shared/src/test/diff/gadt/ThisMatching.mls @@ -33,7 +33,7 @@ class Funny: Int { fun test = this + 1 } class Unfunny { fun test = this + 1 } //│ ╔══[ERROR] Type mismatch in operator application: //│ ║ l.33: class Unfunny { fun test = this + 1 } -//│ ║ ^^^^^^ +//│ ║ ^^^^^^^^ //│ ╟── reference of type `#Unfunny` is not an instance of type `Int` //│ ║ l.33: class Unfunny { fun test = this + 1 } //│ ╙── ^^^^ diff --git a/shared/src/test/diff/nu/ArrayProg.mls b/shared/src/test/diff/nu/ArrayProg.mls index f2d122415e..7302d16a34 100644 --- a/shared/src/test/diff/nu/ArrayProg.mls +++ b/shared/src/test/diff/nu/ArrayProg.mls @@ -174,7 +174,7 @@ s([Numbr(0),Numbr(0)]) //│ ║ ^^^^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from tuple type: //│ ║ l.136: fun s: ([Numbr,Numbr] -> Int) & ([Vectr,Vectr] -> Int) -//│ ╙── ^^^^^^^^^^^ +//│ ╙── ^^^^^^^^^^^^^ //│ Int | error :e diff --git a/shared/src/test/diff/nu/EqlClasses.mls b/shared/src/test/diff/nu/EqlClasses.mls index dd4c6663b5..82be4b683d 100644 --- a/shared/src/test/diff/nu/EqlClasses.mls +++ b/shared/src/test/diff/nu/EqlClasses.mls @@ -64,7 +64,7 @@ p === { fst: 1, snd: 2 } { fst: 1, snd: 2 } === p //│ ╔══[ERROR] Type mismatch in operator application: //│ ║ l.64: { fst: 1, snd: 2 } === p -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── record literal of type `{fst: 1, snd: 2}` is not an instance of type `Eql` //│ ║ l.64: { fst: 1, snd: 2 } === p //│ ╙── ^^^^^^^^^ @@ -87,7 +87,7 @@ r : {x: Int} x => { a: 0 } === x //│ ╔══[ERROR] Type mismatch in operator application: //│ ║ l.87: x => { a: 0 } === x -//│ ║ ^^^^^^^^^^^^ +//│ ║ ^^^^^^^^^^^^^^ //│ ╟── record literal of type `{a: 0}` is not an instance of type `Eql` //│ ║ l.87: x => { a: 0 } === x //│ ╙── ^ diff --git a/shared/src/test/diff/nu/FlatMonads.mls b/shared/src/test/diff/nu/FlatMonads.mls index cd869c7a44..d2eb8d2fa2 100644 --- a/shared/src/test/diff/nu/FlatMonads.mls +++ b/shared/src/test/diff/nu/FlatMonads.mls @@ -112,13 +112,167 @@ printLine("").bind of [] => error //│ = Bind {} +// * Using a shortand operator for `bind` + +fun (|>=) bindOp[A, B](x: IO[A], f: A -> IO[B]): IO[B] = x.bind(f) +//│ fun (|>=) bindOp: forall 'A 'B. (x: IO['A], f: 'A -> IO['B]) -> IO['B] + +:e // FIXME why the errors? +val main = + printLine("Hi! Input two numbers: ") |>= _ => + readInt |>= n => + readInt |>= m => + val sum = n + m + printLine(concat("The sum is: ")(String of sum)) |>= _ => + Pure(sum) +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.124: readInt |>= m => +//│ ║ ^^^^^^^^^^^^^^^^ +//│ ║ l.125: val sum = n + m +//│ ║ ^^^^^^^^^^^^^^^^^ +//│ ║ l.126: printLine(concat("The sum is: ")(String of sum)) |>= _ => +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.127: Pure(sum) +//│ ║ ^^^^^^^^^^^ +//│ ╟── type `Int` does not match type `undefined` +//│ ║ l.32: module readInt extends IO[Int] { fun run = 42 } +//│ ║ ^^^ +//│ ╟── Note: constraint arises from literal type: +//│ ║ l.33: class printLine(str: Str) extends IO[undefined] { fun run = log(str) } +//│ ║ ^^^^^^^^^ +//│ ╟── Note: method type parameter A is defined at: +//│ ║ l.117: fun (|>=) bindOp[A, B](x: IO[A], f: A -> IO[B]): IO[B] = x.bind(f) +//│ ╙── ^ +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.123: readInt |>= n => +//│ ║ ^^^^^^^^^^^^^^^^ +//│ ║ l.124: readInt |>= m => +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ║ l.125: val sum = n + m +//│ ║ ^^^^^^^^^^^^^^^^^ +//│ ║ l.126: printLine(concat("The sum is: ")(String of sum)) |>= _ => +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.127: Pure(sum) +//│ ║ ^^^^^^^^^^^ +//│ ╟── type `Int` does not match type `undefined` +//│ ║ l.32: module readInt extends IO[Int] { fun run = 42 } +//│ ║ ^^^ +//│ ╟── Note: constraint arises from literal type: +//│ ║ l.33: class printLine(str: Str) extends IO[undefined] { fun run = log(str) } +//│ ║ ^^^^^^^^^ +//│ ╟── Note: method type parameter A is defined at: +//│ ║ l.117: fun (|>=) bindOp[A, B](x: IO[A], f: A -> IO[B]): IO[B] = x.bind(f) +//│ ╙── ^ +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.122: printLine("Hi! Input two numbers: ") |>= _ => +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.123: readInt |>= n => +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ║ l.124: readInt |>= m => +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ║ l.125: val sum = n + m +//│ ║ ^^^^^^^^^^^^^^^^^ +//│ ║ l.126: printLine(concat("The sum is: ")(String of sum)) |>= _ => +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.127: Pure(sum) +//│ ║ ^^^^^^^^^^^ +//│ ╟── type `undefined` is not an instance of type `Int` +//│ ║ l.33: class printLine(str: Str) extends IO[undefined] { fun run = log(str) } +//│ ║ ^^^^^^^^^ +//│ ╟── Note: constraint arises from reference: +//│ ║ l.125: val sum = n + m +//│ ╙── ^ +//│ let main: IO['B] | error +//│ main +//│ = Bind {} + + +// * With no type annotations: + +fun (|>=) bindOp(x, f) = x.bind(f) +//│ fun (|>=) bindOp: forall 'a 'b. ({bind: 'a -> 'b}, 'a) -> 'b + +// FIXME why `nothing`? +val main = + printLine("Hi! Input two numbers: ") |>= _ => + readInt |>= n => + readInt |>= m => + val sum = n + m + printLine(concat("The sum is: ")(String of sum)) |>= _ => + Pure(sum) +//│ let main: Bind[nothing, 'B] +//│ where +//│ 'B :> Int +//│ main +//│ = Bind {} + +main.run +//│ Int +//│ res +//│ = 84 +//│ // Output +//│ Hi! Input two numbers: +//│ The sum is: 84 + + +// * Abstracting over the monad: + +fun (|>=) bindOp(x, f) = x.bind(f) +//│ fun (|>=) bindOp: forall 'a 'b. ({bind: 'a -> 'b}, 'a) -> 'b + +fun main(ctx) = + ctx.printLine("Hi! Input two numbers: ") |>= _ => + ctx.readInt |>= n => + ctx.readInt |>= m => + val sum = n + m + ctx.printLine(concat("The sum is: ")(String of sum)) |>= _ => + ctx.pure(sum) +//│ fun main: forall 'a 'b. {printLine: Str -> {bind: (Int -> ('a | 'b)) -> 'a}, pure: Int -> 'b, readInt: {bind: (Int -> ('a | 'b)) -> 'a}} -> 'a + +val defaultCtx = {printLine, readInt, pure: Pure} +//│ let defaultCtx: {printLine: (str: Str) -> printLine, pure: forall 'A. (value: 'A) -> Pure['A], readInt: readInt} +//│ defaultCtx +//│ = { +//│ printLine: [Function (anonymous)] { class: [class printLine extends IO] }, +//│ readInt: readInt { class: [class readInt extends IO] }, +//│ pure: [Function (anonymous)] { class: [class Pure extends IO] } +//│ } + +main(defaultCtx).run +//│ Int +//│ res +//│ = 84 +//│ // Output +//│ Hi! Input two numbers: +//│ The sum is: 84 + +fun loop(ctx) = + ctx.printLine("Input a positive number: ") |>= _ => + ctx.readInt |>= n => + if n < 0 then loop(ctx) else ctx.pure(n) +//│ fun loop: forall 'a 'b 'c. {printLine: "Input a positive number: " -> {bind: ((Int & 'a) -> ('b | 'c)) -> 'b}, pure: 'a -> 'c, readInt: {bind: ((Int & 'a) -> ('b | 'c)) -> 'b}} -> 'b + +// FIXME why `nothing`? +let r = loop(defaultCtx).run +//│ let r: nothing +//│ r +//│ = 42 +//│ // Output +//│ Input a positive number: + +not(r) +//│ Bool +//│ res +//│ = false + + // * Note: using inferred type parent arguments module readInt extends IO { fun run = 42 } class printLine(str: Str) extends IO { fun run = log(str) } declare fun String: anything -> Str //│ module readInt extends IO { -//│ fun bind: forall 'B 'A. ('A -> IO['B]) -> Bind['A, 'B] +//│ fun bind: forall 'A 'B. ('A -> IO['B]) -> Bind['A, 'B] //│ fun run: 42 //│ } //│ class printLine(str: Str) extends IO { diff --git a/shared/src/test/diff/nu/GenericClasses.mls b/shared/src/test/diff/nu/GenericClasses.mls index 1894ec53d5..3d0e6705fd 100644 --- a/shared/src/test/diff/nu/GenericClasses.mls +++ b/shared/src/test/diff/nu/GenericClasses.mls @@ -214,7 +214,7 @@ class Test(n: A) { } //│ ╔══[ERROR] Type mismatch in operator application: //│ ║ l.213: fun foo = n + 1 -//│ ║ ^^^ +//│ ║ ^^^^^ //│ ╟── reference of type `A` is not an instance of type `Int` //│ ║ l.213: fun foo = n + 1 //│ ║ ^ @@ -297,7 +297,7 @@ class TestBad() { } //│ ╔══[ERROR] Type mismatch in operator application: //│ ║ l.296: fun foo2(x: A) = x + 1 -//│ ║ ^^^ +//│ ║ ^^^^^ //│ ╟── reference of type `A` is not an instance of type `Int` //│ ║ l.296: fun foo2(x: A) = x + 1 //│ ║ ^ diff --git a/shared/src/test/diff/nu/GenericMethods.mls b/shared/src/test/diff/nu/GenericMethods.mls index 379ff0c9ab..04115b3d8c 100644 --- a/shared/src/test/diff/nu/GenericMethods.mls +++ b/shared/src/test/diff/nu/GenericMethods.mls @@ -85,15 +85,21 @@ fun bar: A => A //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword //│ ║ l.77: fun bar: A => A //│ ╙── ^^^^^^^^^^^^^^ -//│ ╔══[ERROR] Unsupported pattern shape: +//│ ╔══[ERROR] identifier not found: >: //│ ║ l.77: fun bar: A => A -//│ ╙── ^^^^^ +//│ ╙── ^^ +//│ ╔══[ERROR] identifier not found: A +//│ ║ l.77: fun bar: A => A +//│ ╙── ^ +//│ ╔══[ERROR] identifier not found: A +//│ ║ l.77: fun bar: A => A +//│ ╙── ^ //│ ╔══[ERROR] identifier not found: A //│ ║ l.77: fun bar: A => A //│ ╙── ^ -//│ error -> error +//│ error //│ Code generation encountered an error: -//│ term App(App(Var(>:), Tup(_: Var(A))), Tup(_: Var(A))) is not a valid pattern +//│ unresolved symbol >: :e @@ -103,16 +109,16 @@ module Test { fun test(x: A) = x } //│ ╔══[ERROR] Member `foo` is declared in parent but not implemented in `Test` -//│ ║ l.100: module Test { +//│ ║ l.106: module Test { //│ ║ ^^^^ //│ ╟── Declared here: -//│ ║ l.101: fun foo: 'A => 'A +//│ ║ l.107: fun foo: 'A => 'A //│ ╙── ^^^^^^^^^^^^^ //│ ╔══[ERROR] Member `bar` is declared in parent but not implemented in `Test` -//│ ║ l.100: module Test { +//│ ║ l.106: module Test { //│ ║ ^^^^ //│ ╟── Declared here: -//│ ║ l.102: fun bar: 'A +//│ ║ l.108: fun bar: 'A //│ ╙── ^^^^^^^ //│ module Test { //│ fun bar: nothing diff --git a/shared/src/test/diff/nu/GenericModules.mls b/shared/src/test/diff/nu/GenericModules.mls index 057dae7500..6ec4a734f2 100644 --- a/shared/src/test/diff/nu/GenericModules.mls +++ b/shared/src/test/diff/nu/GenericModules.mls @@ -84,7 +84,7 @@ Test.foo(1) Test.foo(error) + 1 //│ ╔══[ERROR] Type error in operator application //│ ║ l.84: Test.foo(error) + 1 -//│ ║ ^^^^^^^^^^^^^^^^^ +//│ ║ ^^^^^^^^^^^^^^^^^^^ //│ ╟── type variable `A` leaks out of its scope //│ ║ l.84: Test.foo(error) + 1 //│ ║ ^^^^^^^^^^^^^^^ diff --git a/shared/src/test/diff/nu/LamPatterns.mls b/shared/src/test/diff/nu/LamPatterns.mls new file mode 100644 index 0000000000..58aa85eb8e --- /dev/null +++ b/shared/src/test/diff/nu/LamPatterns.mls @@ -0,0 +1,62 @@ +:NewDefs + + +class Some(value: Int) +//│ class Some(value: Int) + +:e // TODO +Some(x) => x +//│ ╔══[ERROR] Unsupported pattern shape: +//│ ║ l.8: Some(x) => x +//│ ╙── ^^^^^^^ +//│ ╔══[ERROR] identifier not found: x +//│ ║ l.8: Some(x) => x +//│ ╙── ^ +//│ error -> error +//│ Code generation encountered an error: +//│ term App(Var(Some), Tup(_: Var(x))) is not a valid pattern + +:js +// FIXME type +let f = Some => 0 +//│ let f: ((value: Int) -> Some) -> 0 +//│ // Prelude +//│ class TypingUnit2 {} +//│ const typing_unit2 = new TypingUnit2; +//│ // Query 1 +//│ globalThis.f = function f(Some) { +//│ return 0; +//│ }; +//│ // End of generated code +//│ f +//│ = [Function: f] + +// :e // TODO +f(Some) +//│ 0 +//│ res +//│ = 0 + +// :e // TODO +f(_ => error) +//│ 0 +//│ res +//│ = 0 + +:e // TODO +f(Some(0)) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.47: f(Some(0)) +//│ ║ ^^^^^^^^^^ +//│ ╟── application of type `Some` is not a function +//│ ║ l.47: f(Some(0)) +//│ ║ ^^^^^^^ +//│ ╟── Note: constraint arises from reference: +//│ ║ l.21: let f = Some => 0 +//│ ╙── ^^^^ +//│ 0 | error +//│ res +//│ = 0 + + + diff --git a/shared/src/test/diff/nu/LetRec.mls b/shared/src/test/diff/nu/LetRec.mls index 38afe236f5..d7f7adad37 100644 --- a/shared/src/test/diff/nu/LetRec.mls +++ b/shared/src/test/diff/nu/LetRec.mls @@ -88,7 +88,7 @@ f :p let rec f = 1 //│ |#let| |#rec| |f| |#=| |1| -//│ AST: TypingUnit(NuFunDef(Some(true), f, [], IntLit(1))) +//│ AST: TypingUnit(NuFunDef(Some(true), f, None, [], IntLit(1))) //│ Parsed: let rec f = 1; //│ let rec f: 1 //│ f diff --git a/shared/src/test/diff/nu/NuScratch.mls b/shared/src/test/diff/nu/NuScratch.mls index 539c23787c..fbbd9ffb3f 100644 --- a/shared/src/test/diff/nu/NuScratch.mls +++ b/shared/src/test/diff/nu/NuScratch.mls @@ -1,3 +1,37 @@ :NewDefs + + +declare fun String: nothing +//│ fun String: nothing + +let makeString: anything => { length: Int, charCodeAt: Int => Int } = String +let StringInstance: { fromCharCode: Int => Str } = String +//│ let makeString: anything -> {charCodeAt: Int -> Int, length: Int} +//│ let StringInstance: {fromCharCode: Int -> Str} +//│ makeString +//│ = [Function: String] +//│ StringInstance +//│ = [Function: String] + +// * Why do we get below and not above?? + +declare fun String: nothing +let makeString: anything => { length: Int, charCodeAt: Int => Int } = String +let StringInstance: { fromCharCode: Int => Str } = String +//│ let makeString: anything -> {charCodeAt: Int -> Int, length: Int} +//│ let StringInstance: {fromCharCode: Int -> Str} +//│ fun String: nothing +//│ makeString +//│ = +//│ StringInstance +//│ = [Function: String] + + + + + + + + diff --git a/shared/src/test/diff/nu/Numbers.mls b/shared/src/test/diff/nu/Numbers.mls index ed817f72de..4543e1746d 100644 --- a/shared/src/test/diff/nu/Numbers.mls +++ b/shared/src/test/diff/nu/Numbers.mls @@ -40,7 +40,7 @@ let x = NaN x + 1 //│ ╔══[ERROR] Type mismatch in operator application: //│ ║ l.40: x + 1 -//│ ║ ^^^ +//│ ║ ^^^^^ //│ ╟── reference of type `Num` is not an instance of `Int` //│ ║ l.34: let x = NaN //│ ║ ^^^ diff --git a/shared/src/test/diff/nu/OpLam.mls b/shared/src/test/diff/nu/OpLam.mls new file mode 100644 index 0000000000..c481673bca --- /dev/null +++ b/shared/src/test/diff/nu/OpLam.mls @@ -0,0 +1,89 @@ +:NewDefs + + +x => x is 42 +//│ Object -> Bool +//│ res +//│ = [Function: res] + + +fun (|>;) foo(a, b) = [a, b] +//│ fun (|>;) foo: forall 'a 'b. ('a, 'b) -> ['a, 'b] + +42 |>; x => x +//│ [42, forall 'a. 'a -> 'a] +//│ res +//│ = [ 42, [Function (anonymous)] ] + + +fun (>>) compose(f, g) = x => g(f(x)) +//│ fun (>>) compose: forall 'a 'b 'c. ('a -> 'b, 'b -> 'c) -> 'a -> 'c + +succ >> x => x + 2 +//│ Int -> Int +//│ res +//│ = [Function (anonymous)] + +:e +x => x + 2 >> succ +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.28: x => x + 2 >> succ +//│ ║ ^^^^^^^^^^^^^ +//│ ╟── operator application of type `Int` is not a function +//│ ║ l.28: x => x + 2 >> succ +//│ ║ ^^^^^ +//│ ╟── Note: constraint arises from application: +//│ ║ l.19: fun (>>) compose(f, g) = x => g(f(x)) +//│ ║ ^^^^ +//│ ╟── from reference: +//│ ║ l.19: fun (>>) compose(f, g) = x => g(f(x)) +//│ ╙── ^ +//│ Int -> (error | Int -> Int) +//│ res +//│ = [Function: res] + +(x => x + 2) >> succ +//│ Int -> Int +//│ res +//│ = [Function (anonymous)] + +:e // FIXME parsing +x => x + 2 + >> succ +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.51: x => x + 2 +//│ ║ ^ +//│ ║ l.52: >> succ +//│ ║ ^^^^ +//│ ╟── integer literal of type `2` is not a 2-element tuple +//│ ║ l.51: x => x + 2 +//│ ║ ^ +//│ ╟── Note: constraint arises from tuple literal: +//│ ║ l.19: fun (>>) compose(f, g) = x => g(f(x)) +//│ ╙── ^^^^^^ +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.51: x => x + 2 +//│ ║ ^ +//│ ║ l.52: >> succ +//│ ║ ^^^^^^^^^^ +//│ ╟── reference of type `Int -> Int` is not a 1-element tuple +//│ ║ l.52: >> succ +//│ ╙── ^^^^ +//│ Int -> Int +//│ Code generation encountered an error: +//│ ill-formed application App(App(Var(>>), IntLit(2)), Var(succ)) + + +:e +x => x.y => y +//│ ╔══[ERROR] Unsupported pattern shape: +//│ ║ l.78: x => x.y => y +//│ ╙── ^^^ +//│ ╔══[ERROR] identifier not found: y +//│ ║ l.78: x => x.y => y +//│ ╙── ^ +//│ anything -> error -> error +//│ Code generation encountered an error: +//│ term Sel(Var(x), y) is not a valid pattern + + diff --git a/shared/src/test/diff/nu/OverrideShorthand.mls b/shared/src/test/diff/nu/OverrideShorthand.mls index 249d928a69..c7d2b71693 100644 --- a/shared/src/test/diff/nu/OverrideShorthand.mls +++ b/shared/src/test/diff/nu/OverrideShorthand.mls @@ -10,8 +10,8 @@ class Pair(lhs: Int, rhs: Int) :e fun f(override Pair(x, y)) = x + y //│ |#fun| |f|(|#override| |Pair|(|x|,| |y|)|)| |#=| |x| |+| |y| -//│ AST: TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(_$0)), If(IfOpApp(Var(_$0), Var(is), IfThen(App(Var(Pair), Tup(_: Var(x), _: Var(y))), App(App(Var(+), Tup(_: Var(x))), Tup(_: Var(y))), Some(App(Sel(Super(), f), Tup(_: Var(_$0)))))))) -//│ Parsed: fun f = (_$0,) => if _$0 is (Pair (x, y,)) then + (x,) (y,) else (super).f (_$0,); +//│ AST: TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(_$0)), If(IfOpApp(Var(_$0), Var(is), IfThen(App(Var(Pair), Tup(_: Var(x), _: Var(y))), App(Var(+), Tup(_: Var(x), _: Var(y))), Some(App(Sel(Super(), f), Tup(_: Var(_$0)))))))) +//│ Parsed: fun f = (_$0,) => if _$0 is (Pair (x, y,)) then + (x, y,) else (super).f (_$0,); //│ ╔══[ERROR] identifier not found: super //│ ║ l.11: fun f(override Pair(x, y)) = x + y //│ ╙── ^^^^^^^^ diff --git a/shared/src/test/diff/nu/Subscripts.mls b/shared/src/test/diff/nu/Subscripts.mls index d3d082361a..49c60d0089 100644 --- a/shared/src/test/diff/nu/Subscripts.mls +++ b/shared/src/test/diff/nu/Subscripts.mls @@ -18,7 +18,7 @@ if xs.[0] is xs.[0] + 1 //│ ╔══[ERROR] Type mismatch in operator application: //│ ║ l.18: xs.[0] + 1 -//│ ║ ^^^^^^ +//│ ║ ^^^^^^^^ //│ ╟── possibly-undefined array access of type `undefined` is not an instance of type `Int` //│ ║ l.18: xs.[0] + 1 //│ ╙── ^^^^ diff --git a/shared/src/test/diff/nu/TypeOps.mls b/shared/src/test/diff/nu/TypeOps.mls index c867f6bf84..6f2363088c 100644 --- a/shared/src/test/diff/nu/TypeOps.mls +++ b/shared/src/test/diff/nu/TypeOps.mls @@ -5,19 +5,36 @@ type *[A, B] = [A, B] //│ type *[A, B] = [A, B] -:e // FIXME parsing of type operators fun x : Int * Int fun x = [0, 1] -//│ ╔══[ERROR] Type mismatch in definition: -//│ ║ l.10: fun x = [0, 1] -//│ ║ ^^^^^^^^^^ -//│ ╟── integer literal of type `0` is not a 1-element tuple -//│ ║ l.10: fun x = [0, 1] -//│ ║ ^ -//│ ╟── Note: constraint arises from tuple type: -//│ ║ l.9: fun x : Int * Int -//│ ╙── ^^^ //│ fun x: [0, 1] -//│ fun x: *[[Int], [Int]] +//│ fun x: *[Int, Int] + +fun x : Int * [Int] +fun x = [0, [1]] +//│ fun x: [0, [1]] +//│ fun x: *[Int, [Int]] + +fun x : [Int] * Int +fun x = [[0], 1] +//│ fun x: [[0], 1] +//│ fun x: *[[Int], Int] + + +type Id[A] = A +//│ type Id[A] = A + +:e +fun x: Id[Int, Int] +//│ ╔══[ERROR] Wrong number of type arguments – expected 1, found 2 +//│ ║ l.28: fun x: Id[Int, Int] +//│ ╙── ^^^^^^^^^^^^ +//│ fun x: Id[Int] + +fun x: Id[[Int, Int]] +//│ fun x: Id[[Int, Int]] + +fun x: Id[[[Int, Int]]] +//│ fun x: Id[[[Int, Int]]] diff --git a/shared/src/test/diff/nu/Vals.mls b/shared/src/test/diff/nu/Vals.mls index 4377d8b517..14602aa1a5 100644 --- a/shared/src/test/diff/nu/Vals.mls +++ b/shared/src/test/diff/nu/Vals.mls @@ -28,4 +28,29 @@ val a = a //│ = 1 +val f(x) = x +//│ let f: forall 'a. 'a -> 'a +//│ f +//│ = [Function: f] + +f(123) +//│ 123 +//│ res +//│ = 123 + + +module M { + let tmp = 2 + val f(x) = x + tmp +} +//│ module M { +//│ let f: Int -> Int +//│ let tmp: 2 +//│ } + +M.f(123) +//│ Int +//│ res +//│ = 125 + diff --git a/shared/src/test/diff/nu/WeirdUnions.mls b/shared/src/test/diff/nu/WeirdUnions.mls index f3f631b372..b81b6fbe27 100644 --- a/shared/src/test/diff/nu/WeirdUnions.mls +++ b/shared/src/test/diff/nu/WeirdUnions.mls @@ -2,21 +2,17 @@ -// * There are strange parsing quirks here - fun f: Str | [Str, Int] -//│ fun f: Array[Int | Str] & {_1: Str} - -// * ^ parses as: +//│ fun f: Str | [Str, Int] fun f: [Str] | [Str, Int] //│ fun f: Array[Int | Str] & {_1: Str} fun f: (Str | [Str, Int]) -//│ fun f: Array[Int | Str] & {_1: Str} +//│ fun f: Str | [Str, Int] fun f: Str | (Str, Int) -//│ fun f: Array[Int | Str] & {_1: Str} +//│ fun f: Str | [Str, Int] fun f: Str | ([Str, Int]) @@ -46,10 +42,10 @@ fun f: (Str => Str) & ((Str, Int) => Int) :e f("abc", "abc") //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.47: f("abc", "abc") +//│ ║ l.43: f("abc", "abc") //│ ║ ^^^^^^^^^^^^^^^ //│ ╟── argument list of type `["abc", "abc"]` does not match type `nothing` -//│ ║ l.47: f("abc", "abc") +//│ ║ l.43: f("abc", "abc") //│ ╙── ^^^^^^^^^^^^^^ //│ Int | Str | error //│ res @@ -68,19 +64,19 @@ let r = if true then id else [x, y] => [y, x] r(error) r(error, error) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.68: r(error) +//│ ║ l.64: r(error) //│ ║ ^^^^^^^^ //│ ╟── argument of type `[nothing]` does not match type `[?a, ?b]` -//│ ║ l.68: r(error) +//│ ║ l.64: r(error) //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple literal: -//│ ║ l.62: let r = if true then id else [x, y] => [y, x] +//│ ║ l.58: let r = if true then id else [x, y] => [y, x] //│ ╙── ^^^^ //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.69: r(error, error) +//│ ║ l.65: r(error, error) //│ ║ ^^^^^^^^^^^^^^^ //│ ╟── argument list of type `[nothing, nothing]` does not match type `[?a]` -//│ ║ l.69: r(error, error) +//│ ║ l.65: r(error, error) //│ ╙── ^^^^^^^^^^^^^^ //│ error | [nothing, nothing] //│ res diff --git a/shared/src/test/diff/parser/Classes.mls b/shared/src/test/diff/parser/Classes.mls index c25e1f0c4b..cd53006828 100644 --- a/shared/src/test/diff/parser/Classes.mls +++ b/shared/src/test/diff/parser/Classes.mls @@ -124,13 +124,13 @@ class Foo(x, y, z) class Foo(x, y, z): Bar(z, x) //│ |#class| |Foo|(|x|,| |y|,| |z|)|#:| |Bar|(|z|,| |x|)| -//│ Parsed: {class Foo(x, y, z,): Bar[[z, x]] {}} +//│ Parsed: {class Foo(x, y, z,): Bar[z, x] {}} class Foo(x, y, z): Bar(z, x) { fun blah(x) = x + y } //│ |#class| |Foo|(|x|,| |y|,| |z|)|#:| |Bar|(|z|,| |x|)| |{|→|#fun| |blah|(|x|)| |#=| |x| |+| |y|←|↵|}| -//│ Parsed: {class Foo(x, y, z,): Bar[[z, x]] {fun blah = (x,) => + (x,) (y,)}} +//│ Parsed: {class Foo(x, y, z,): Bar[z, x] {fun blah = (x,) => + (x,) (y,)}} class Foo(x, y) extends Bar(y, x), Baz(x + y) //│ |#class| |Foo|(|x|,| |y|)| |#extends| |Bar|(|y|,| |x|)|,| |Baz|(|x| |+| |y|)| diff --git a/shared/src/test/diff/parser/Lambdas.mls b/shared/src/test/diff/parser/Lambdas.mls index 90d8a80a64..89240fd873 100644 --- a/shared/src/test/diff/parser/Lambdas.mls +++ b/shared/src/test/diff/parser/Lambdas.mls @@ -113,5 +113,5 @@ id + of x => x + 1 //│ ╔══[PARSE ERROR] Unexpected 'of' keyword in expression position //│ ║ l.111: id + of x => x + 1 //│ ╙── ^^ -//│ Parsed: {(+ (id,) (x,),) => + (x,) (1,)} +//│ Parsed: {+ (id,) ((x,) => + (x,) (1,),)} diff --git a/shared/src/test/diff/parser/Select.mls b/shared/src/test/diff/parser/Select.mls index e370e2a359..b1a7ae70bd 100644 --- a/shared/src/test/diff/parser/Select.mls +++ b/shared/src/test/diff/parser/Select.mls @@ -84,19 +84,15 @@ x //│ ╙── ^ //│ Parsed: {undefined} -:pe (.) //│ |(|.|)| -//│ ╔══[PARSE ERROR] Unexpected operator here -//│ ║ l.88: (.) -//│ ╙── ^ -//│ Parsed: {'(' ')'} +//│ Parsed: {.} :pe a, b //│ |a|,| |b| //│ ╔══[PARSE ERROR] Expected end of input; found comma instead -//│ ║ l.96: a, b +//│ ║ l.92: a, b //│ ╙── ^ //│ Parsed: {a} @@ -140,10 +136,10 @@ a + .c //│ |a| |+|→|b|↵|.c|←| //│ ╔══[PARSE ERROR] Unexpected selector in expression position -//│ ║ l.140: .c +//│ ║ l.136: .c //│ ╙── ^^ //│ ╔══[PARSE ERROR] Unexpected end of indented block; an expression was expected here -//│ ║ l.140: .c +//│ ║ l.136: .c //│ ╙── ^ //│ Parsed: {+ (a,) ({b; undefined},)} @@ -191,7 +187,7 @@ a of c //│ |a|→|.b| |+|→|1|↵|#of| |c|←|←| //│ ╔══[PARSE ERROR] Unexpected 'of' keyword in expression position -//│ ║ l.191: of c +//│ ║ l.187: of c //│ ╙── ^^ //│ Parsed: {+ ((a).b,) ({1; c},)} @@ -230,7 +226,7 @@ a .b //│ |a|→|+|1|↵|*|2|↵|.b|←| //│ ╔══[PARSE ERROR] Unexpected selector in operator block -//│ ║ l.230: .b +//│ ║ l.226: .b //│ ╙── ^^ //│ Parsed: {* (+ a 1) 2} @@ -255,7 +251,7 @@ a 1 .+a 2 //│ |1| |.+|a| |2| //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword -//│ ║ l.255: 1 .+a 2 +//│ ║ l.251: 1 .+a 2 //│ ╙── ^^^ //│ Parsed: {.+ (1,) (a (2,),)} diff --git a/shared/src/test/diff/parser/Where.mls b/shared/src/test/diff/parser/Where.mls index 0bb203fe69..90e4d15342 100644 --- a/shared/src/test/diff/parser/Where.mls +++ b/shared/src/test/diff/parser/Where.mls @@ -13,19 +13,23 @@ a + 1 where let a = 1 fun foo: 'a => 'a => 'a where 'a : int //│ |#fun| |foo|#:| |'a| |=>| |'a| |=>| |'a| |#where| |'a| |#:| |int| -//│ Parsed: {fun foo: 'a -> 'a -> 'a +//│ Parsed: {fun foo: 'a -> 'a -> ('a //│ where -//│ 'a <: int} +//│ 'a <: int)} +:e fun foo: 'a + 'a + 'a where 'a : int //│ |#fun| |foo|#:| |'a| |+| |'a| |+| |'a| |#where| |'a| |#:| |int| -//│ Parsed: {fun foo: +[[+[['a], ['a]]], ['a]] -//│ where -//│ 'a <: int} +//│ ╔══[ERROR] not a recognized type +//│ ║ l.21: fun foo: 'a + 'a + 'a where 'a : int +//│ ╙── ^^^^^^^ +//│ Parsed: {fun foo: anything} +:e fun foo: 'a -> 'a -> 'a where 'a : int //│ |#fun| |foo|#:| |'a| |->| |'a| |->| |'a| |#where| |'a| |#:| |int| -//│ Parsed: {fun foo: 'a -> 'a -> 'a -//│ where -//│ 'a <: int} +//│ ╔══[ERROR] not a recognized type +//│ ║ l.29: fun foo: 'a -> 'a -> 'a where 'a : int +//│ ╙── ^^^^^^^^^^^^^^ +//│ Parsed: {fun foo: anything} diff --git a/shared/src/test/diff/tapl/NuSimplyTyped.mls b/shared/src/test/diff/tapl/NuSimplyTyped.mls index 37ed119e8a..bc71deb00d 100644 --- a/shared/src/test/diff/tapl/NuSimplyTyped.mls +++ b/shared/src/test/diff/tapl/NuSimplyTyped.mls @@ -1,26 +1,11 @@ :NewParser :NewDefs -let str = toString -fun concat2(a, b) = concat(a)(b) -fun concat3(a, b, c) = concat2(a, concat2(b, c)) -fun concat4(a, b, c, d) = concat2(a, concat3(b, c, d)) -fun concat5(a, b, c, d, e) = concat2(a, concat4(b, c, d, e)) -fun concat6(a, b, c, d, e, f) = concat2(a, concat5(b, c, d, e, f)) -fun concat7(a, b, c, d, e, f, g) = concat2(a, concat6(b, c, d, e, f, g)) -fun concat8(a, b, c, d, e, f, g, h) = concat2(a, concat7(b, c, d, e, f, g, h)) -fun par(a) = concat3("(", a, ")") -//│ let str: anything -> Str -//│ fun concat2: (Str, Str) -> Str -//│ fun concat3: (Str, Str, Str) -> Str -//│ fun concat4: (Str, Str, Str, Str) -> Str -//│ fun concat5: (Str, Str, Str, Str, Str) -> Str -//│ fun concat6: (Str, Str, Str, Str, Str, Str) -> Str -//│ fun concat7: (Str, Str, Str, Str, Str, Str, Str) -> Str -//│ fun concat8: (Str, Str, Str, Str, Str, Str, Str, Str) -> Str +fun (++) concatOp(a, b) = concat(a)(b) +//│ fun (++) concatOp: (Str, Str) -> Str + +fun par(a) = "(" ++ a ++ ")" //│ fun par: Str -> Str -//│ str -//│ = [Function: toString] type Option[A] = Some[A] | None class Some[A](value: A) @@ -71,15 +56,15 @@ module Empty fun insert(t, k, v) = if t is Node(k', _, l, r) and - slt(k)(k') then Node(k', v, insert(l, k, v), r) - sgt(k)(k') then Node(k', v, l, insert(r, k, v)) + slt(k, k') then Node(k', v, insert(l, k, v), r) + sgt(k, k') then Node(k', v, l, insert(r, k, v)) _ then Node(k, v, l, r) Empty then Node(k, v, Empty, Empty) fun find(t, k) = if t is Node(k', v, l, r) and - slt(k)(k') then find(l, k) - sgt(k)(k') then find(r, k) + slt(k, k') then find(l, k) + sgt(k, k') then find(r, k) _ then Some(v) Empty then None //│ fun insert: forall 'A. (Empty | Node['A], Str, 'A) -> Node['A] @@ -87,8 +72,8 @@ fun find(t, k) = fun showType(ty) = if ty is - FunctionType(PrimitiveType(name), rhs) then concat3(name, " -> ", showType(rhs)) - FunctionType(lhs, rhs) then concat4("(", showType(lhs), ") -> ", showType(rhs)) + FunctionType(PrimitiveType(name), rhs) then name ++ " -> " ++ showType(rhs) + FunctionType(lhs, rhs) then "(" ++ showType(lhs) ++ ") -> " ++ showType(rhs) PrimitiveType(name) then name //│ fun showType: (FunctionType | PrimitiveType) -> Str @@ -116,12 +101,12 @@ fun typeEqual(t1, t2) = fun showTerm(t) = if t is - Lit(tag, _) then toString(tag) - Var(name) then toString(name) - Abs(lhs, ty, rhs) then concat6("&", showTerm(lhs), ": ", showType(ty), " => ", showTerm(rhs)) + Lit(tag, _) then tag + Var(name) then name + Abs(lhs, ty, rhs) then "&" ++ showTerm(lhs) ++ ": " ++ showType(ty) ++ " => " ++ showTerm(rhs) App(Abs(lhs0, ty, lhs1), rhs) then - concat5("((", showTerm(Abs(lhs0, ty, rhs)), ") ", showTerm(rhs), ")") - App(lhs, rhs) then par(concat3(showTerm(lhs), " ", showTerm(rhs))) + "((" ++ showTerm(Abs(lhs0, ty, rhs)) ++ ") " ++ showTerm(rhs) ++ ")" + App(lhs, rhs) then par(showTerm(lhs) ++ " " ++ showTerm(rhs)) //│ fun showTerm: (Abs | App | Lit | Var) -> Str showTerm(Var("x")) @@ -144,7 +129,7 @@ fun typeTerm(t: Term, ctx: TreeMap[Type]): Result[Type, Str] = Lit(_, ty) then Ok(ty) Var(name) and find(ctx, name) is Some(ty) then Ok(ty) - None then Err(concat3("unbound variable `", name, "`")) + None then Err("unbound variable `" ++ name ++ "`") Abs(Var(name), ty, body) and typeTerm(body, insert(ctx, name, ty)) is Ok(resTy) then Ok(FunctionType(ty, resTy)) Err(message) then Err(message) @@ -152,16 +137,16 @@ fun typeTerm(t: Term, ctx: TreeMap[Type]): Result[Type, Str] = Ok(FunctionType(pTy, resTy)) and typeTerm(rhs, ctx) is Ok(aTy) and typeEqual(pTy, aTy) then Ok(resTy) - else Err(concat5("expect the argument to be of type `", showType(pTy), "` but found `", showType(aTy), "`")) + else Err("expect the argument to be of type `" ++ showType(pTy) ++ "` but found `" ++ showType(aTy) ++ "`") Err(message) then Err(message) - Ok(PrimitiveType(name)) then Err(concat3("cannot apply primitive type `", name, "`")) + Ok(PrimitiveType(name)) then Err("cannot apply primitive type `" ++ name ++ "`") Err(message) then Err(message) //│ fun typeTerm: (t: Term, ctx: TreeMap[Type]) -> Result[Type, Str] fun showTypeTerm(t, ctx) = if typeTerm(t, ctx) is - Ok(ty) then concat3(showTerm(t), " : ", showType(ty)) - Err(message) then concat2("Type error: ", message) + Ok(ty) then showTerm(t) ++ " : " ++ showType(ty) + Err(message) then "Type error: " ++ message //│ fun showTypeTerm: (Term, TreeMap[Type]) -> Str showTypeTerm(Var("x"), Empty) diff --git a/shared/src/test/diff/tapl/NuUntyped.mls b/shared/src/test/diff/tapl/NuUntyped.mls index bf789ea85f..df42332b85 100644 --- a/shared/src/test/diff/tapl/NuUntyped.mls +++ b/shared/src/test/diff/tapl/NuUntyped.mls @@ -1,38 +1,23 @@ -:NewParser :NewDefs -fun concat2(a, b) = concat(a)(b) -fun concat3(a, b, c) = concat2(a, concat2(b, c)) -fun concat4(a, b, c, d) = concat2(a, concat3(b, c, d)) -fun concat5(a, b, c, d, e) = concat2(a, concat4(b, c, d, e)) -fun concat6(a, b, c, d, e, f) = concat2(a, concat5(b, c, d, e, f)) -fun concat7(a, b, c, d, e, f, g) = concat2(a, concat6(b, c, d, e, f, g)) -fun concat8(a, b, c, d, e, f, g, h) = concat2(a, concat7(b, c, d, e, f, g, h)) -fun par(a) = concat3("(", a, ")") -//│ fun concat2: (Str, Str) -> Str -//│ fun concat3: (Str, Str, Str) -> Str -//│ fun concat4: (Str, Str, Str, Str) -> Str -//│ fun concat5: (Str, Str, Str, Str, Str) -> Str -//│ fun concat6: (Str, Str, Str, Str, Str, Str) -> Str -//│ fun concat7: (Str, Str, Str, Str, Str, Str, Str) -> Str -//│ fun concat8: (Str, Str, Str, Str, Str, Str, Str, Str) -> Str +fun (++) concatOp(a, b) = concat(a)(b) +//│ fun (++) concatOp: (Str, Str) -> Str + +fun par(a) = "(" ++ a ++ ")" //│ fun par: Str -> Str -:escape -let String: nothing +declare fun String: nothing +//│ fun String: nothing + let makeString: anything => { length: Int, charCodeAt: Int => Int } = String let StringInstance: { fromCharCode: Int => Str } = String -//│ let String: nothing //│ let makeString: anything -> {charCodeAt: Int -> Int, length: Int} //│ let StringInstance: {fromCharCode: Int -> Str} -//│ String -//│ = //│ makeString //│ = [Function: String] //│ StringInstance //│ = [Function: String] - let anythingToString = toString fun fromCharCode(n: Int) = StringInstance.fromCharCode(n) fun stringCharCodeAt(s: Str, i) = makeString(s).charCodeAt(i) @@ -46,7 +31,7 @@ fun stringLength(s: Str) = makeString(s).length type Option[A] = Some[A] | None class Some[A](value: A) { - fun toString() = concat3("Some(", anythingToString(value), ")") + fun toString() = "Some(" ++ anythingToString(value) ++ ")" } module None { fun toString() = "None" @@ -66,6 +51,7 @@ module Nil //│ class Cons[A](head: A, tail: List[A]) //│ module Nil +// * We could define a shorthand for these, but let's leave them as useful tests fun list1(x) = Cons(x, Nil) fun list2(x, y) = Cons(x, list1(y)) fun list3(x, y, z) = Cons(x, list2(y, z)) @@ -118,18 +104,21 @@ fun listWithout(xs, x) = //│ where //│ 'A <: 'A0 -// fix this: -// fun listJoin(xs, sep) = -// if xs is -// Nil then "" -// Cons(x, Nil) then toString(x) -// Cons(x, xs') then concat3(toString(x), sep, listJoin(xs', sep)) + +// * FIXME? +fun listJoin(xs, sep) = + if xs is + Nil then "" + Cons(x, Nil) then toString(x) + Cons(x, xs') then toString(x) ++ sep ++ listJoin(xs', sep) +//│ fun listJoin: forall 'A. (Cons['A] | Nil, Str) -> Str + fun listJoin(xs, sep) = if xs is Nil then "" Cons(x, xs') and xs' is Nil then toString(x) - _ then concat3(toString(x), sep, listJoin(xs', sep)) + _ then toString(x) ++ sep ++ listJoin(xs', sep) //│ fun listJoin: forall 'A. (Cons['A] | Nil, Str) -> Str listJoin(list3("x", "y", "z"), ", ") @@ -149,10 +138,10 @@ class App(lhs: Term, rhs: Term) fun showTerm(t) = if t is Var(name) then toString(name) - Abs(lhs, rhs) then concat4("&", showTerm(lhs), ". ", showTerm(rhs)) + Abs(lhs, rhs) then "&" ++ showTerm(lhs) ++ ". " ++ showTerm(rhs) App(Abs(lhs0, lhs1), rhs) then - concat8("((", "&", showTerm(lhs0), ". ", showTerm(lhs1), ") ", showTerm(rhs), ")") - App(lhs, rhs) then par(concat3(showTerm(lhs), " ", showTerm(rhs))) + "((" ++ "&" ++ showTerm(lhs0) ++ ". " ++ showTerm(lhs1) ++ ") " ++ showTerm(rhs) ++ ")" + App(lhs, rhs) then par(showTerm(lhs) ++ " " ++ showTerm(rhs)) //│ fun showTerm: (Abs | App | Var) -> Str showTerm(Var("x")) @@ -198,7 +187,7 @@ fun hasFree(t, n) = //│ fun hasFree: (Object, anything) -> Bool fun showHasFree(t, n) = - concat4(showTerm(t), if hasFree(t, n) then " has " else " DOES NOT have ", "free variable ", n) + showTerm(t) ++ (if hasFree(t, n) then " has " else " DOES NOT have ") ++ "free variable " ++ n //│ fun showHasFree: (Abs | App | Var, Str) -> Str showHasFree(Var("x"), "x") @@ -249,10 +238,9 @@ fun fv(t) = //│ 'A :> Str fun showFv(t) = - concat2(showTerm(t), if fv(t) is + showTerm(t) ++ if fv(t) is Nil then " DOES NOT have free variables" - _ then concat2(" has free variables: ", listJoin(fv(t), ", ")) - ) + _ then " has free variables: " ++ listJoin(fv(t), ", ") //│ fun showFv: (Abs | App | Var) -> Str showFv(Var("x")) @@ -282,11 +270,11 @@ fun tryNextAlphabet(initialCode, currentCode, freeNames) = _ then Some(name) //│ fun tryNextAlphabet: forall 'A. (Num, Int, Cons['A] | Nil) -> (None | Some[Str]) -toString(tryNextAlphabet(97, 97, list1("a"))) -toString(tryNextAlphabet(97, 98, list1("a"))) -toString(tryNextAlphabet(97, 98, list2("a", "b"))) -toString(tryNextAlphabet(121, 122, list1("y"))) -toString(tryNextAlphabet(121, 122, list2("y", "z"))) +tryNextAlphabet(97, 97, list1("a")).toString() +tryNextAlphabet(97, 98, list1("a")).toString() +tryNextAlphabet(97, 98, list2("a", "b")).toString() +tryNextAlphabet(121, 122, list1("y")).toString() +tryNextAlphabet(121, 122, list2("y", "z")).toString() //│ Str //│ res //│ = 'None' @@ -301,7 +289,7 @@ toString(tryNextAlphabet(121, 122, list2("y", "z"))) fun tryAppendDigits(name, index, freeNames) = if - let currentName = concat2(name, toString(index)) + let currentName = name ++ toString(index) listContains(freeNames, currentName) then tryAppendDigits(name, index + 1, freeNames) _ then currentName @@ -334,7 +322,7 @@ fun subst(t, n, v) = //│ fun subst: forall 'a. (Abs | App | Term & Object & 'a & ~#Abs & ~#App & ~#Var | Var, anything, Term & Object & 'a) -> (Abs | App | Var | 'a) fun showSubst(t, n, v) = - concat8(showTerm(t), " [", n, " / ", showTerm(v), "]", " => ", showTerm(subst(t, n, v))) + showTerm(t) ++ " [" ++ n ++ " / " ++ showTerm(v) ++ "]" ++ " => " ++ showTerm(subst(t, n, v)) //│ fun showSubst: (Abs | App | Var, Str, Abs & Term | App & Term | Var & Term) -> Str showSubst(Var("x"), "x", Var("y")) @@ -359,13 +347,13 @@ showSubst(Abs(Var("z"), Abs(Var("x"), App(Var("z"), App(Var("x"), Var("y"))))), type Result = Normal | Stuck | Stepped class Normal(term: Term) { - fun toString() = concat2("Normal form: ", showTerm(term)) + fun toString() = "Normal form: " ++ showTerm(term) } class Stuck(term: Term, part: Term) { - fun toString() = concat4("Stuck: ", showTerm(part), " in ", showTerm(term)) + fun toString() = "Stuck: " ++ showTerm(part) ++ " in " ++ showTerm(term) } class Stepped(from: Term, to: Term) { - fun toString() = concat3(showTerm(from), " => ", showTerm(to)) + fun toString() = showTerm(from) ++ " => " ++ showTerm(to) } //│ type Result = Normal | Stepped | Stuck //│ class Normal(term: Term) { diff --git a/shared/src/test/diff/ucs/Exhaustiveness.mls b/shared/src/test/diff/ucs/Exhaustiveness.mls index c5a88c54be..b335ba7e08 100644 --- a/shared/src/test/diff/ucs/Exhaustiveness.mls +++ b/shared/src/test/diff/ucs/Exhaustiveness.mls @@ -48,7 +48,7 @@ class Node[A](value: int, left: Tree[A], right: Tree[A]) { >= value then right.find(wanted) == value then true } -//│ ╔══[ERROR] The case when this is false is not handled: == (wanted,) (value,) +//│ ╔══[ERROR] The case when this is false is not handled: == (wanted, value,) //│ ║ l.46: fun contains(wanted) = if wanted //│ ║ ^^^^^^ //│ ║ l.47: <= value then left.find(wanted) diff --git a/shared/src/test/diff/ucs/JSON.mls b/shared/src/test/diff/ucs/JSON.mls index ed321cf2b3..12cfaa332d 100644 --- a/shared/src/test/diff/ucs/JSON.mls +++ b/shared/src/test/diff/ucs/JSON.mls @@ -115,15 +115,15 @@ class Node[A](key: Str, value: A, left: TreeMap[A], right: TreeMap[A]) fun insert(t, k, v) = if t is Node(k', _, l, r) and - slt(k)(k') then Node(k', v, insert(l, k, v), r) - sgt(k)(k') then Node(k', v, l, insert(r, k, v)) + slt(k, k') then Node(k', v, insert(l, k, v), r) + sgt(k, k') then Node(k', v, l, insert(r, k, v)) _ then Node(k, v, l, r) Empty then Node(k, v, Empty, Empty) fun find(t, k) = if t is Node(k', v, l, r) and - slt(k)(k') then find(l, k) - sgt(k)(k') then find(r, k) + slt(k, k') then find(l, k) + sgt(k, k') then find(r, k) _ then Some(v) Empty then None fun traverse(t, f) = diff --git a/shared/src/test/diff/ucs/LeadingAnd.mls b/shared/src/test/diff/ucs/LeadingAnd.mls index b5eb7c202b..f052cd41a1 100644 --- a/shared/src/test/diff/ucs/LeadingAnd.mls +++ b/shared/src/test/diff/ucs/LeadingAnd.mls @@ -11,7 +11,7 @@ class Some[T](value: T) fun f(a, b) = if a is Some(av) and b is Some(bv) then av + bv -//│ ╔══[ERROR] Cannot find operator `and` in the context +//│ ╔══[ERROR] Illegal pattern `and` //│ ║ l.13: and b is Some(bv) then av + bv //│ ╙── ^^^ //│ fun f: (anything, anything) -> error @@ -23,8 +23,8 @@ fun f(a, b) = if a is Some(av) and b is Some(bv) then av + bv //│ |#fun| |f|(|a|,| |b|)| |#=| |#if| |a| |is| |Some|(|av|)|→|and| |b| |is| |Some|(|bv|)|↵|#then| |av| |+| |bv|←| -//│ AST: TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(a), _: Var(b)), If(IfOpApp(Var(a), Var(is), I; f; O; p; s; A; p; p; (; A; p; p; (; V; a; r; (; S; o; m; e; ); ,; ; T; u; p; (; _; :; ; V; a; r; (; a; v; ); ); ); ,; ; <; i; t; e; r; a; t; o; r; >, None)))) -//│ Parsed: fun f = (a, b,) => if a is Some (av,) ‹· and (is (b,) (Some (bv,),)) then + (av,) (bv,)›; +//│ AST: TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(a), _: Var(b)), If(IfOpApp(Var(a), Var(is), I; f; O; p; s; A; p; p; (; A; p; p; (; V; a; r; (; S; o; m; e; ); ,; ; T; u; p; (; _; :; ; V; a; r; (; a; v; ); ); ); ,; ; <; i; t; e; r; a; t; o; r; >, None)))) +//│ Parsed: fun f = (a, b,) => if a is Some (av,) ‹· and (is (b, Some (bv,),)) then + (av, bv,)›; //│ fun f: (Some[Int], Some[Int]) -> Int // TODO @@ -34,9 +34,9 @@ fun f(a, b) = if a is and b is Some(bv) then av + bv //│ |#fun| |f|(|a|,| |b|)| |#=| |#if| |a| |is|→|Some|(|av|)|→|and| |b| |is| |Some|(|bv|)|↵|#then| |av| |+| |bv|←|←| -//│ AST: TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(a), _: Var(b)), If(IfOpApp(Var(a), Var(is), IfBlock(I; f; O; p; s; A; p; p; (; A; p; p; (; V; a; r; (; S; o; m; e; ); ,; ; T; u; p; (; _; :; ; V; a; r; (; a; v; ); ); ); ,; ; <; i; t; e; r; a; t; o; r; >), None)))) -//│ Parsed: fun f = (a, b,) => if a is ‹Some (av,) ‹· and (is (b,) (Some (bv,),)) then + (av,) (bv,)››; -//│ ╔══[ERROR] Cannot find operator `and` in the context +//│ AST: TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(a), _: Var(b)), If(IfOpApp(Var(a), Var(is), IfBlock(I; f; O; p; s; A; p; p; (; A; p; p; (; V; a; r; (; S; o; m; e; ); ,; ; T; u; p; (; _; :; ; V; a; r; (; a; v; ); ); ); ,; ; <; i; t; e; r; a; t; o; r; >), None)))) +//│ Parsed: fun f = (a, b,) => if a is ‹Some (av,) ‹· and (is (b, Some (bv,),)) then + (av, bv,)››; +//│ ╔══[ERROR] Illegal pattern `and` //│ ║ l.34: and b is Some(bv) //│ ╙── ^^^ //│ fun f: (anything, anything) -> error diff --git a/shared/src/test/diff/ucs/NestedBranches.mls b/shared/src/test/diff/ucs/NestedBranches.mls index c0a80a0d34..a25252c6f0 100644 --- a/shared/src/test/diff/ucs/NestedBranches.mls +++ b/shared/src/test/diff/ucs/NestedBranches.mls @@ -101,16 +101,39 @@ fun mapPartition(f, xs) = if xs is Cons(x, xs) and mapPartition(f, xs) is (l, r) and f(x) is Left(v) then (Cons(v, l), r) Right(v) then (l, Cons(v, r)) -//│ ╔══[ERROR] The case when this is false is not handled: is (mapPartition (f, xs,),) (l, r,) +//│ ╔══[ERROR] type identifier not found: Tuple#2 +//│ ╙── +//│ ╔══[ERROR] Type mismatch in definition: +//│ ║ l.99: fun mapPartition(f, xs) = if xs is +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.100: Nil then (Nil, Nil) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^ //│ ║ l.101: Cons(x, xs) and mapPartition(f, xs) is (l, r) and f(x) is -//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ fun mapPartition: (anything, anything) -> error +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.102: Left(v) then (Cons(v, l), r) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.103: Right(v) then (l, Cons(v, r)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── tuple literal of type `[Nil, Nil]` is not an instance of type `Object` +//│ ║ l.100: Nil then (Nil, Nil) +//│ ║ ^^^^^^^^ +//│ ╟── Note: constraint arises from `case` expression: +//│ ║ l.101: Cons(x, xs) and mapPartition(f, xs) is (l, r) and f(x) is +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.102: Left(v) then (Cons(v, l), r) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.103: Right(v) then (l, Cons(v, r)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── from application: +//│ ║ l.101: Cons(x, xs) and mapPartition(f, xs) is (l, r) and f(x) is +//│ ╙── ^^^^^^^^^^^^^^^^^^^ +//│ fun mapPartition: forall 'A. (anything, Cons['A] | Nil) -> (error | [Nil, Nil]) //│ Code generation encountered an error: -//│ if expression was not desugared +//│ unknown match case: Tuple#2 // TODO mapPartition(f, zeroToThree) -//│ error +//│ error | [Nil, Nil] //│ res //│ Runtime error: //│ ReferenceError: mapPartition3 is not defined @@ -127,38 +150,38 @@ fun mapPartition(f, xs) = if xs is and f(x) is Left(v) then (Cons(v, l), r) Right(v) then (l, Cons(v, r)) //│ ╔══[PARSE ERROR] Unexpected 'then' keyword here -//│ ║ l.128: Right(v) then (l, Cons(v, r)) +//│ ║ l.151: Right(v) then (l, Cons(v, r)) //│ ╙── ^^^^ //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword -//│ ║ l.127: and f(x) is Left(v) then (Cons(v, l), r) +//│ ║ l.150: and f(x) is Left(v) then (Cons(v, l), r) //│ ║ ^^^^^^^^^^^^^^^ -//│ ║ l.128: Right(v) then (l, Cons(v, r)) +//│ ║ l.151: Right(v) then (l, Cons(v, r)) //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╔══[ERROR] type identifier not found: Tuple#2 //│ ╙── //│ ╔══[ERROR] Type mismatch in definition: -//│ ║ l.124: fun mapPartition(f, xs) = if xs is +//│ ║ l.147: fun mapPartition(f, xs) = if xs is //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.125: Nil then (Nil, Nil) +//│ ║ l.148: Nil then (Nil, Nil) //│ ║ ^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.126: Cons(x, xs) and mapPartition(f, xs) is (l, r) +//│ ║ l.149: Cons(x, xs) and mapPartition(f, xs) is (l, r) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.127: and f(x) is Left(v) then (Cons(v, l), r) +//│ ║ l.150: and f(x) is Left(v) then (Cons(v, l), r) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.128: Right(v) then (l, Cons(v, r)) +//│ ║ l.151: Right(v) then (l, Cons(v, r)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── tuple literal of type `[Nil, Nil]` is not an instance of type `Object` -//│ ║ l.125: Nil then (Nil, Nil) +//│ ║ l.148: Nil then (Nil, Nil) //│ ║ ^^^^^^^^ //│ ╟── Note: constraint arises from `case` expression: -//│ ║ l.126: Cons(x, xs) and mapPartition(f, xs) is (l, r) +//│ ║ l.149: Cons(x, xs) and mapPartition(f, xs) is (l, r) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.127: and f(x) is Left(v) then (Cons(v, l), r) +//│ ║ l.150: and f(x) is Left(v) then (Cons(v, l), r) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.128: Right(v) then (l, Cons(v, r)) +//│ ║ l.151: Right(v) then (l, Cons(v, r)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── from application: -//│ ║ l.126: Cons(x, xs) and mapPartition(f, xs) is (l, r) +//│ ║ l.149: Cons(x, xs) and mapPartition(f, xs) is (l, r) //│ ╙── ^^^^^^^^^^^^^^^^^^^ //│ fun mapPartition: forall 'A. (anything, Cons['A] | Nil) -> (error | [Nil, Nil]) //│ Code generation encountered an error: diff --git a/shared/src/test/diff/ucs/NestedOpSplits.mls b/shared/src/test/diff/ucs/NestedOpSplits.mls index ec2c20b5d7..bb716281c1 100644 --- a/shared/src/test/diff/ucs/NestedOpSplits.mls +++ b/shared/src/test/diff/ucs/NestedOpSplits.mls @@ -13,6 +13,8 @@ fun f(x) = //│ ║ ^^^^ //│ ║ l.8: 1 + //│ ║ ^^^^^^^ +//│ ║ l.9: 2 then 0 +//│ ║ ^^^^^^^ //│ ╟── operator application of type `Bool` is not an instance of `Int` //│ ║ l.7: if x == //│ ║ ^^^^ diff --git a/shared/src/test/diff/ucs/NuPlainConditionals.mls b/shared/src/test/diff/ucs/NuPlainConditionals.mls new file mode 100644 index 0000000000..328fbf5c57 --- /dev/null +++ b/shared/src/test/diff/ucs/NuPlainConditionals.mls @@ -0,0 +1,103 @@ +:NewDefs + + +class Pair[A](fst: A, snd: A) +//│ class Pair[A](fst: A, snd: A) + + + +Pair(0, 1) is Pair +//│ Bool +//│ res +//│ = true + +Pair(0, 1) is Pair(a, b) +//│ Bool +//│ res +//│ = true + +Pair(0, 1) is Pair(0, _) +//│ Bool +//│ res +//│ = true + +if Pair(0, 1) is Pair(a, b) then true else false +//│ Bool +//│ res +//│ = true + + +fun foo(x) = x is Pair(a, b) +//│ fun foo: (Object & ~#Pair | Pair[anything]) -> Bool + + +Pair(0, 1) is Pair(a, b) and a > b +//│ Bool +//│ res +//│ = false + +if Pair(0, 1) is Pair(a, b) then a > b else false +//│ Bool +//│ res +//│ = false + + +fun foo(x) = x is Pair(a, b) and a > b +//│ fun foo: (Object & ~#Pair | Pair[Num]) -> Bool + +fun foo(x) = if x is Pair(a, b) then a > b else false +//│ fun foo: (Object & ~#Pair | Pair[Num]) -> Bool + + +// TODO proper error +fun foo(x) = x is + Pair + Int +//│ ╔══[ERROR] illegal pattern +//│ ║ l.54: Pair +//│ ║ ^^^^ +//│ ║ l.55: Int +//│ ╙── ^^^^^ +//│ fun foo: anything -> error +//│ Code generation encountered an error: +//│ if expression was not desugared + +// TODO proper error +fun foo(x) = x is + Pair(a, b) and a > b + Int +//│ ╔══[ERROR] illegal pattern +//│ ║ l.67: Pair(a, b) and a > b +//│ ║ ^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.68: Int +//│ ╙── ^^^^^ +//│ fun foo: anything -> error +//│ Code generation encountered an error: +//│ if expression was not desugared + +// TODO support `|` +fun foo1(x) = x is Pair(a, b) | Int +fun foo2(x) = x is (Pair(a, b) and a > b) | Int +//│ ╔══[ERROR] Illegal pattern `|` +//│ ║ l.79: fun foo1(x) = x is Pair(a, b) | Int +//│ ╙── ^ +//│ ╔══[ERROR] Illegal pattern `|` +//│ ║ l.80: fun foo2(x) = x is (Pair(a, b) and a > b) | Int +//│ ╙── ^ +//│ fun foo1: anything -> error +//│ fun foo2: anything -> error +//│ Code generation encountered an error: +//│ if expression was not desugared + + + +class A(arg: Int) +//│ class A(arg: Int) + +// TODO make `is` lower precedence than `=>` +x => (x is A(_)) +//│ Object -> Bool +//│ res +//│ = [Function: res] + + diff --git a/shared/src/test/diff/ucs/Or.mls b/shared/src/test/diff/ucs/Or.mls index 7d6a8af491..066a382e2b 100644 --- a/shared/src/test/diff/ucs/Or.mls +++ b/shared/src/test/diff/ucs/Or.mls @@ -11,7 +11,7 @@ fun f(a, b) = if a is and b is Some(v') then v + v' or b is Some(v) then v else 0 -//│ ╔══[ERROR] Cannot find operator `and` in the context +//│ ╔══[ERROR] Illegal pattern `and` //│ ║ l.11: and b is Some(v') then v + v' //│ ╙── ^^^ //│ fun f: (anything, anything) -> error diff --git a/shared/src/test/diff/ucs/SplitAroundOp.mls b/shared/src/test/diff/ucs/SplitAroundOp.mls index 13cb1fb17b..198590fa4d 100644 --- a/shared/src/test/diff/ucs/SplitAroundOp.mls +++ b/shared/src/test/diff/ucs/SplitAroundOp.mls @@ -35,16 +35,14 @@ fun f(x) = B() then 1 //│ fun f: (A | B) -> (0 | 1) -// It fails because we interpret == as a constructor. -:e -:ge +:e // FIXME if x is A() === 0 then 0 > 0 then 1 < 0 then 2 -//│ ╔══[ERROR] Cannot find operator `===` in the context -//│ ║ l.43: === 0 then 0 +//│ ╔══[ERROR] Illegal pattern `===` +//│ ║ l.41: === 0 then 0 //│ ╙── ^^^ //│ error //│ Code generation encountered an error: diff --git a/shared/src/test/diff/ucs/SplitBeforeOp.mls b/shared/src/test/diff/ucs/SplitBeforeOp.mls index 9e32ae567d..15b69a053c 100644 --- a/shared/src/test/diff/ucs/SplitBeforeOp.mls +++ b/shared/src/test/diff/ucs/SplitBeforeOp.mls @@ -4,7 +4,7 @@ :ge if x == 0 then 0 -//│ ╔══[ERROR] The case when this is false is not handled: == (x,) (0,) +//│ ╔══[ERROR] The case when this is false is not handled: == (x, 0,) //│ ║ l.5: if x //│ ║ ^ //│ ║ l.6: == 0 then 0 diff --git a/shared/src/test/diff/ucs/SplitOps.mls b/shared/src/test/diff/ucs/SplitOps.mls index 203953c89b..5e44153648 100644 --- a/shared/src/test/diff/ucs/SplitOps.mls +++ b/shared/src/test/diff/ucs/SplitOps.mls @@ -93,7 +93,7 @@ fun f(a, b, c) = if a == 0 and b is B() and c is C() then 0 //│ |#fun| |f|(|a|,| |b|,| |c|)| |#=|→|#if| |a|→|==| |0| |and| |b| |is| |B|(||)| |and| |c| |is| |C|(||)| |#then| |0|←|←| -//│ AST: TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(a), _: Var(b), _: Var(c)), Blk(...)))) +//│ AST: TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(a), _: Var(b), _: Var(c)), Blk(...)))) //│ Parsed: fun f = (a, b, c,) => {if a ‹· == (and (and (0,) (is (b,) (B (),),),) (is (c,) (C (),),)) then 0›}; //│ Desugared: rec def f: (a, b, c,) => {if a ‹· == (and (and (0,) (is (b,) (B (),),),) (is (c,) (C (),),)) then 0›} //│ AST: Def(true, f, Lam(Tup(_: Var(a), _: Var(b), _: Var(c)), Blk(...)), true) diff --git a/shared/src/test/diff/ucs/WeirdIf.mls b/shared/src/test/diff/ucs/WeirdIf.mls index c094ec36f5..864e50a136 100644 --- a/shared/src/test/diff/ucs/WeirdIf.mls +++ b/shared/src/test/diff/ucs/WeirdIf.mls @@ -83,7 +83,7 @@ fun f(x) = //│ ╟── Note: 'if' expression started here: //│ ║ l.70: if x === //│ ╙── ^^ -//│ ╔══[ERROR] The case when this is false is not handled: === (x,) (undefined,) +//│ ╔══[ERROR] The case when this is false is not handled: === (x, undefined,) //│ ║ l.70: if x === //│ ║ ^^^^^ //│ ║ l.71: else "bruh" diff --git a/shared/src/test/scala/mlscript/DiffTests.scala b/shared/src/test/scala/mlscript/DiffTests.scala index bb095a1fad..e51791629b 100644 --- a/shared/src/test/scala/mlscript/DiffTests.scala +++ b/shared/src/test/scala/mlscript/DiffTests.scala @@ -415,7 +415,7 @@ class DiffTests if (mode.showParse || mode.dbgParsing || parseOnly) output(NewLexer.printTokens(tokens)) - val p = new NewParser(origin, tokens, raise, dbg = mode.dbgParsing, N) { + val p = new NewParser(origin, tokens, newDefs, raise, dbg = mode.dbgParsing, N) { def doPrintDbg(msg: => Str): Unit = if (dbg) output(msg) } val res = p.parseAll(p.typingUnit) @@ -458,7 +458,6 @@ class DiffTests if (mode.stats) typer.resetStats() typer.dbg = mode.dbg typer.dbgUCS = mode.dbgUCS - typer.newDefs = newDefs // typer.recordProvenances = !noProvs typer.recordProvenances = !noProvs && !mode.dbg && !mode.dbgSimplif || mode.explainErrors typer.generalizeCurriedFunctions = generalizeCurriedFunctions @@ -603,7 +602,7 @@ class DiffTests // (Nil, Nil, N) (Nil, Nil, S(p.tops.collect { // case LetS(isRec, pat, bod) => ("res", Nil, Nil, false) - case NuFunDef(isLet @ S(_), nme, tparams, bod) => + case NuFunDef(isLet @ S(_), nme, snme, tparams, bod) => (nme.name + " ", nme.name :: Nil, Nil, false) case t: Term => ("res ", "res" :: Nil, Nil, false) })) diff --git a/ts2mls/js/src/main/scala/ts2mls/JSWriter.scala b/ts2mls/js/src/main/scala/ts2mls/JSWriter.scala index ad84615473..b448bbcbf0 100644 --- a/ts2mls/js/src/main/scala/ts2mls/JSWriter.scala +++ b/ts2mls/js/src/main/scala/ts2mls/JSWriter.scala @@ -18,7 +18,7 @@ class JSWriter(filename: String) { private var fileSize = 0 // how many bytes we've written in the file private var needTruncate = false - writeln(":NewParser\n:ParseOnly") + writeln(":NewDefs\n:ParseOnly") def writeln(str: String) = { val strln = str + "\n" diff --git a/ts2mls/js/src/test/diff/Array.d.mls b/ts2mls/js/src/test/diff/Array.d.mls index c7a81b0051..446fb8f8f4 100644 --- a/ts2mls/js/src/test/diff/Array.d.mls +++ b/ts2mls/js/src/test/diff/Array.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly fun first(x: MutArray): string fun getZero3(): MutArray @@ -21,3 +21,4 @@ fun ta(ts: MutArray>): MutArray> fun tat(ts: MutArray>): MutArray> //│ |#fun| |first|(|x|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |getZero3|(||)|#:| |MutArray|‹|number|›|↵|#fun| |first2|(|fs|#:| |MutArray|‹|(|number|)| |=>| |number|›|)|#:| |(|number|)| |=>| |number|↵|#fun| |doEs|(|e|#:| |MutArray|‹|int|›|)|#:| |MutArray|‹|int|›|↵|#class| |C|(||)| |{||}|↵|#trait| |I|(||)| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|(|c|#:| |MutArray|‹|C|›|)|#:| |MutArray|‹|C|›|↵|#fun| |doIs|(|i|#:| |MutArray|‹|I|›|)|#:| |MutArray|‹|I|›|↵|#fun| |inter|‹|U|,| |T|›|(|x|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|)|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|(|x|#:| |MutArray|‹|(|string|,| |number|,| |)|›|)|#:| |MutArray|‹|(|string|,| |number|,| |)|›|↵|#fun| |translate|‹|T|,| |U|›|(|x|#:| |MutArray|‹|T|›|)|#:| |MutArray|‹|U|›|↵|#fun| |uu|(|x|#:| |MutArray|‹|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|›|)|#:| |MutArray|‹|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|›|↵|#class| |Temp|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|(|ts|#:| |MutArray|‹|Temp|‹|(|false|)| ||| |(|true|)|›|›|)|#:| |MutArray|‹|Temp|‹|(|false|)| ||| |(|true|)|›|›|↵|#fun| |tat|‹|T|›|(|ts|#:| |MutArray|‹|Temp|‹|T|›|›|)|#:| |MutArray|‹|Temp|‹|T|›|›| //│ Parsed: {fun first: (x: MutArray[string]) -> string; fun getZero3: () -> MutArray[number]; fun first2: (fs: MutArray[number -> number]) -> number -> number; fun doEs: (e: MutArray[int]) -> MutArray[int]; class C() {}; trait I() {let i: number}; fun doCs: (c: MutArray[C]) -> MutArray[C]; fun doIs: (i: MutArray[I]) -> MutArray[I]; fun inter: (x: MutArray[U & T]) -> MutArray[U & T]; fun clean: (x: MutArray[[string, number]]) -> MutArray[[string, number]]; fun translate: (x: MutArray[T]) -> MutArray[U]; fun uu: (x: MutArray[number | false | true]) -> MutArray[number | false | true]; class Temp‹T›() {let x: T}; fun ta: (ts: MutArray[Temp[bool]]) -> MutArray[Temp[bool]]; fun tat: (ts: MutArray[Temp[T]]) -> MutArray[Temp[T]]} +//│ diff --git a/ts2mls/js/src/test/diff/BasicFunctions.d.mls b/ts2mls/js/src/test/diff/BasicFunctions.d.mls index 6199bc42ac..b4ef115545 100644 --- a/ts2mls/js/src/test/diff/BasicFunctions.d.mls +++ b/ts2mls/js/src/test/diff/BasicFunctions.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly fun hello(): unit fun add(x: number, y: number): number @@ -26,3 +26,4 @@ fun inn2(b: Barrrrrrrrr): unit fun out2(): Barrrrrrrrr //│ |#fun| |hello|(||)|#:| |unit|↵|#fun| |add|(|x|#:| |number|,| |y|#:| |number|)|#:| |number|↵|#fun| |sub|(|x|#:| |number|,| |y|#:| |number|)|#:| |number|↵|#fun| |foo|(||)|#:| |number|↵|#fun| |id|(|x|#:| |anything|)|#:| |anything|↵|#fun| |odd|(|x|#:| |number|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |isnull|(|x|#:| |anything|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |bar|(||)|#:| |anything|↵|#fun| |nu|(|n|#:| |#null|)|#:| |#null|↵|#fun| |un|(|n|#:| |#undefined|)|#:| |#undefined|↵|#fun| |fail|(||)|#:| |nothing|↵|#fun| |create|(||)|#:| |object|↵|#fun| |pa|(|x|#:| |number|)|#:| |number|↵|#fun| |wtf|(|x|#:| |anything|)|#:| |unit|↵|#class| |Foooooo|(||)| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|(|f|#:| |Foooooo|)|#:| |unit|↵|#fun| |out1|(||)|#:| |Foooooo|↵|#trait| |Barrrrrrrrr|(||)| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|(|b|#:| |Barrrrrrrrr|)|#:| |unit|↵|#fun| |out2|(||)|#:| |Barrrrrrrrr| //│ Parsed: {fun hello: () -> unit; fun add: (x: number, y: number) -> number; fun sub: (x: number, y: number) -> number; fun foo: () -> number; fun id: (x: anything) -> anything; fun odd: (x: number) -> bool; fun isnull: (x: anything) -> bool; fun bar: () -> anything; fun nu: (n: null) -> null; fun un: (n: undefined) -> undefined; fun fail: () -> nothing; fun create: () -> object; fun pa: (x: number) -> number; fun wtf: (x: anything) -> unit; class Foooooo() {let ooooooo: number}; fun inn: (f: Foooooo) -> unit; fun out1: () -> Foooooo; trait Barrrrrrrrr() {let rrrrrrr: number}; fun inn2: (b: Barrrrrrrrr) -> unit; fun out2: () -> Barrrrrrrrr} +//│ diff --git a/ts2mls/js/src/test/diff/ClassMember.d.mls b/ts2mls/js/src/test/diff/ClassMember.d.mls index 9324c2f013..03848dcb26 100644 --- a/ts2mls/js/src/test/diff/ClassMember.d.mls +++ b/ts2mls/js/src/test/diff/ClassMember.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly class Student(s: string, age: number) { let name: string @@ -23,3 +23,4 @@ class TTT() { } //│ |#class| |Student|(|s|#:| |string|,| |age|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|(|other|#:| |Student|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |addScore|(|sub|#:| |string|,| |score|#:| |number|)|#:| |unit|↵|#fun| |getID|(||)|#:| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|(|x|#:| |T|)|#:| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|(|x|#:| |number|)|#:| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|x|#:| |T|)|#:| |T|↵|#fun| |ttt2|(|x|#:| |T|)|#:| |T|←|↵|}| //│ Parsed: {class Student(s: string, age: number,) {let name: string; fun isFriend: (other: Student) -> bool; fun addScore: (sub: string, score: number) -> unit; fun getID: () -> number}; class Foo‹T›() {fun bar: (x: T) -> unit}; class EZ() {fun inc: (x: number) -> number}; class Outer() {class Inner() {let a: number}}; class TTT‹T›() {fun ttt: (x: T) -> T; fun ttt2: (x: T) -> T}} +//│ diff --git a/ts2mls/js/src/test/diff/Dec.d.mls b/ts2mls/js/src/test/diff/Dec.d.mls index bac5a6b3eb..2976186b91 100644 --- a/ts2mls/js/src/test/diff/Dec.d.mls +++ b/ts2mls/js/src/test/diff/Dec.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly fun getName(id: (string) | (number)): string fun render(callback: (unit => unit) | (undefined)): string @@ -12,3 +12,4 @@ module OOO { } //│ |#fun| |getName|(|id|#:| |(|string|)| ||| |(|number|)|)|#:| |string|↵|#fun| |render|(|callback|#:| |(|unit| |=>| |unit|)| ||| |(|#undefined|)|)|#:| |string|↵|#trait| |Get|(||)| |{|→|#fun| |__call|(|id|#:| |string|)|#:| |string|←|↵|}|↵|#class| |Person|(|name|#:| |string|,| |age|#:| |number|)| |{|→|#fun| |getName|(|id|#:| |number|)|#:| |string|←|↵|}|↵|#module| |OOO| |{|↵|}| //│ Parsed: {fun getName: (id: string | number) -> string; fun render: (callback: unit -> unit | undefined) -> string; trait Get() {fun __call: (id: string) -> string}; class Person(name: string, age: number,) {fun getName: (id: number) -> string}; module OOO() {}} +//│ diff --git a/ts2mls/js/src/test/diff/Enum.d.mls b/ts2mls/js/src/test/diff/Enum.d.mls index 64e979cd72..75e68ab29e 100644 --- a/ts2mls/js/src/test/diff/Enum.d.mls +++ b/ts2mls/js/src/test/diff/Enum.d.mls @@ -1,7 +1,8 @@ -:NewParser +:NewDefs :ParseOnly fun pass(c: int): (false) | (true) fun stop(): int fun g(x: int): int //│ |#fun| |pass|(|c|#:| |int|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|x|#:| |int|)|#:| |int| //│ Parsed: {fun pass: (c: int) -> bool; fun stop: () -> int; fun g: (x: int) -> int} +//│ diff --git a/ts2mls/js/src/test/diff/Heritage.d.mls b/ts2mls/js/src/test/diff/Heritage.d.mls index 2a6bb2fdbb..a90d7822eb 100644 --- a/ts2mls/js/src/test/diff/Heritage.d.mls +++ b/ts2mls/js/src/test/diff/Heritage.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly class A() { fun foo(): unit @@ -42,3 +42,4 @@ module Five { class Y(): Five.ROTK {} //│ |#class| |A|(||)| |{|→|#fun| |foo|(||)|#:| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›|(||)| |{|→|#fun| |set|(|x|#:| |T|)|#:| |unit|↵|#fun| |get|(||)|#:| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu|(||)| |{|→|#let| |x|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|(||)|#:| |nothing|←|↵|}|↵|#class| |VG|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›|(||)| |{|→|#fun| |xx|(|x|#:| |I|)|#:| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|(|x|#:| |R|)|#:| |R|←|↵|}|↵|#module| |Five| |{|→|#class| |ROTK|(||)| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five|.ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five|.ROTK| |{||}| //│ Parsed: {class A() {fun foo: () -> unit}; class B(): A {}; class C‹T›() {fun set: (x: T) -> unit; fun get: () -> T}; class D(): C[number] {}; trait Wu() {let x: bool}; class WuWu(): Wu {let y: bool}; trait WuWuWu(): WuWu {let z: bool}; trait Never(): WuWuWu {fun w: () -> nothing}; class VG‹T›() {let x: T}; class Home‹T›(): VG[string] {let y: T}; trait O‹I›() {fun xx: (x: I) -> I}; class OR‹R›(): O[R] {fun xx: (x: R) -> R}; module Five() {class ROTK() {let wu: string}; class Y(): Five.ROTK {}}; class Y(): Five.ROTK {}} +//│ diff --git a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls index afe851ebc9..ec24d7bef6 100644 --- a/ts2mls/js/src/test/diff/HighOrderFunc.d.mls +++ b/ts2mls/js/src/test/diff/HighOrderFunc.d.mls @@ -1,7 +1,8 @@ -:NewParser +:NewDefs :ParseOnly fun h1(inc: (number) => number, num: number): number fun h2(hint: string): unit => string fun h3(f: (number) => number, g: (number) => number): (number) => number //│ |#fun| |h1|(|inc|#:| |(|number|)| |=>| |number|,| |num|#:| |number|)|#:| |number|↵|#fun| |h2|(|hint|#:| |string|)|#:| |unit| |=>| |string|↵|#fun| |h3|(|f|#:| |(|number|)| |=>| |number|,| |g|#:| |(|number|)| |=>| |number|)|#:| |(|number|)| |=>| |number| //│ Parsed: {fun h1: (inc: number -> number, num: number) -> number; fun h2: (hint: string) -> unit -> string; fun h3: (f: number -> number, g: number -> number) -> number -> number} +//│ diff --git a/ts2mls/js/src/test/diff/InterfaceMember.d.mls b/ts2mls/js/src/test/diff/InterfaceMember.d.mls index e572de4d21..53a5e69d1d 100644 --- a/ts2mls/js/src/test/diff/InterfaceMember.d.mls +++ b/ts2mls/js/src/test/diff/InterfaceMember.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly trait IFoo() { let a: string @@ -38,3 +38,4 @@ trait TTT() { } //│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|(|x|#:| |number|)|#:| |number|↵|#fun| |c|(||)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |d|(|x|#:| |string|)|#:| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|(|x|#:| |T|)|#:| |number|←|↵|}|↵|#fun| |create|(||)|#:| |{|v|#:| |number|,|}|↵|#fun| |get|(|x|#:| |{|t|#:| |string|,|}|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|(||)|#:| |(|number|)| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|(|source|#:| |string|,| |subString|#:| |string|)|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|(|index|#:| |number|)|#:| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|(|start|#:| |number|)|#:| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|(||)|#:| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|x|#:| |T|)|#:| |T|←|↵|}| //│ Parsed: {trait IFoo() {let a: string; fun b: (x: number) -> number; fun c: () -> bool; fun d: (x: string) -> unit}; trait II‹T›() {fun test: (x: T) -> number}; fun create: () -> {v: number}; fun get: (x: {t: string}) -> string; trait IEvent() {fun callback: () -> number -> unit}; trait SearchFunc() {fun __call: (source: string, subString: string) -> bool}; trait StringArray() {fun __index: (index: number) -> string}; trait Counter() {fun __call: (start: number) -> string; let interval: number; fun reset: () -> unit}; trait Simple() {let a: number; fun b: (x: bool) -> string}; trait Simple2‹T›() {let abc: T}; trait Next(): Simple {}; trait TTT‹T›() {fun ttt: (x: T) -> T}} +//│ diff --git a/ts2mls/js/src/test/diff/Intersection.d.mls b/ts2mls/js/src/test/diff/Intersection.d.mls index 7205c79e52..50d28c76b4 100644 --- a/ts2mls/js/src/test/diff/Intersection.d.mls +++ b/ts2mls/js/src/test/diff/Intersection.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly fun extend(first: T, second: U): (T) & (U) fun foo(x: (T) & (U)): unit @@ -19,3 +19,4 @@ class B() {} fun inter(c: (A) & (B)): (A) & (B) //│ |#fun| |extend|‹|T|,| |U|›|(|first|#:| |T|,| |second|#:| |U|)|#:| |(|T|)| |&| |(|U|)|↵|#fun| |foo|‹|T|,| |U|›|(|x|#:| |(|T|)| |&| |(|U|)|)|#:| |unit|↵|#fun| |over|(|f|#:| |(|(|number|)| |=>| |string|)| |&| |(|(|object|)| |=>| |string|)|)|#:| |string|↵|#trait| |IA|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB|(||)| |{|→|#let| |y|#:| |number|←|↵|}|↵|#fun| |iii|(|x|#:| |(|IA|)| |&| |(|IB|)|)|#:| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|‹|U|,| |V|,| |T|,| |P|›|(|x|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|‹|U|,| |T|,| |V|›|(|x|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|‹|U|,| |T|›|(|a|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|‹|U|,| |T|,| |V|›|(|x|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|)|#:| |(|(|U|,| |T|,| |)|)| |&| |(|(|V|,| |V|,| |)|)|↵|#class| |A|(||)| |{||}|↵|#class| |B|(||)| |{||}|↵|#fun| |inter|(|c|#:| |(|A|)| |&| |(|B|)|)|#:| |(|A|)| |&| |(|B|)| //│ Parsed: {fun extend: (first: T, second: U) -> (T & U); fun foo: (x: T & U) -> unit; fun over: (f: number -> string & object -> string) -> string; trait IA() {let x: number}; trait IB() {let y: number}; fun iii: (x: IA & IB) -> (IA & IB); fun uu: (x: U & T | U & P | V & T | V & P) -> (U & T | U & P | V & T | V & P); fun iiii: (x: U & T & V) -> (U & T & V); fun arr: (a: MutArray[U] & MutArray[T]) -> (MutArray[U] & MutArray[T]); fun tt: (x: [U, T] & [V, V]) -> ([U, T] & [V, V]); class A() {}; class B() {}; fun inter: (c: A & B) -> (A & B)} +//│ diff --git a/ts2mls/js/src/test/diff/Literal.d.mls b/ts2mls/js/src/test/diff/Literal.d.mls index cf8e30d9b6..1ff16c9da3 100644 --- a/ts2mls/js/src/test/diff/Literal.d.mls +++ b/ts2mls/js/src/test/diff/Literal.d.mls @@ -1,7 +1,8 @@ -:NewParser +:NewDefs :ParseOnly let a: {a: "A",b: "B",} let num: {y: 114,} fun foo(x: {xx: "X",}): {yy: "Y",} //│ |#let| |a|#:| |{|a|#:| |"A"|,|b|#:| |"B"|,|}|↵|#let| |num|#:| |{|y|#:| |114|,|}|↵|#fun| |foo|(|x|#:| |{|xx|#:| |"X"|,|}|)|#:| |{|yy|#:| |"Y"|,|}| //│ Parsed: {let a: {a: "A", b: "B"}; let num: {y: 114}; fun foo: (x: {xx: "X"}) -> {yy: "Y"}} +//│ diff --git a/ts2mls/js/src/test/diff/MultiFiles.d.mls b/ts2mls/js/src/test/diff/MultiFiles.d.mls index 2ec00f63bb..f6719e1656 100644 --- a/ts2mls/js/src/test/diff/MultiFiles.d.mls +++ b/ts2mls/js/src/test/diff/MultiFiles.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly fun multi1(x: number): number fun multi3(): unit @@ -20,3 +20,4 @@ class AnotherFoo(): AnotherBase {} fun multi5(): unit //│ |#fun| |multi1|(|x|#:| |number|)|#:| |number|↵|#fun| |multi3|(||)|#:| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase|(||)| |{|→|#let| |y|#:| |string|←|↵|}|↵|#module| |N| |{|→|#fun| |f|(||)|#:| |unit|↵|#fun| |g|(||)|#:| |unit|↵|#fun| |h|(||)|#:| |unit|←|↵|}|↵|#fun| |multi2|(|x|#:| |string|)|#:| |string|↵|#fun| |multi4|(||)|#:| |unit|↵|#trait| |Base|(||)| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|(||)|#:| |unit| //│ Parsed: {fun multi1: (x: number) -> number; fun multi3: () -> unit; class Foo(): Base {}; trait AnotherBase() {let y: string}; module N() {fun f: () -> unit; fun g: () -> unit; fun h: () -> unit}; fun multi2: (x: string) -> string; fun multi4: () -> unit; trait Base() {let a: number}; class AnotherFoo(): AnotherBase {}; fun multi5: () -> unit} +//│ diff --git a/ts2mls/js/src/test/diff/Namespace.d.mls b/ts2mls/js/src/test/diff/Namespace.d.mls index 00020a127e..4baef6fd28 100644 --- a/ts2mls/js/src/test/diff/Namespace.d.mls +++ b/ts2mls/js/src/test/diff/Namespace.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly module N1 { fun f(x: anything): number @@ -30,3 +30,4 @@ fun f1(x: N1.C): N1.C fun f2(x: AA.C): AA.C //│ |#module| |N1| |{|→|#fun| |f|(|x|#:| |anything|)|#:| |number|↵|#fun| |ff|(|y|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#module| |N2| |{|→|#fun| |fff|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |number|↵|#fun| |gg|(|c|#:| |N1|.C|)|#:| |N1|.C|↵|#class| |BBB|(||)|#:| |N1|.C| |{||}|←|↵|}|←|↵|}|↵|#module| |AA| |{|→|#fun| |f|(|x|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#module| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|x|#:| |N1|.C|)|#:| |N1|.C|↵|#fun| |f2|(|x|#:| |AA|.C|)|#:| |AA|.C| //│ Parsed: {module N1() {fun f: (x: anything) -> number; fun ff: (y: anything) -> number; class C() {fun f: () -> unit}; trait I() {fun f: () -> number}; module N2() {fun fff: (x: bool) -> number; fun gg: (c: N1.C) -> N1.C; class BBB(): N1.C {}}}; module AA() {fun f: (x: anything) -> string; class C() {fun f: () -> unit}; trait I() {fun f: () -> number}; module N2() {}}; fun f1: (x: N1.C) -> N1.C; fun f2: (x: AA.C) -> AA.C} +//│ diff --git a/ts2mls/js/src/test/diff/Optional.d.mls b/ts2mls/js/src/test/diff/Optional.d.mls index b2f2ad8df8..bacc22d276 100644 --- a/ts2mls/js/src/test/diff/Optional.d.mls +++ b/ts2mls/js/src/test/diff/Optional.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly fun buildName(firstName: string, lastName: (string) | (undefined)): string fun buildName2(firstName: string, lastName: (string) | (undefined)): string @@ -22,3 +22,4 @@ class B() { fun boom(b: (B) | (undefined)): anything //│ |#fun| |buildName|(|firstName|#:| |string|,| |lastName|#:| |(|string|)| ||| |(|#undefined|)|)|#:| |string|↵|#fun| |buildName2|(|firstName|#:| |string|,| |lastName|#:| |(|string|)| ||| |(|#undefined|)|)|#:| |string|↵|#fun| |buildName3|(|firstName|#:| |string|,| |lastName|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |buildName4|(|firstName|#:| |string|,| |lastName|#:| |MutArray|‹|anything|›|)|#:| |string|↵|#trait| |SquareConfig|(||)| |{|→|#let| |color|#:| |(|string|)| ||| |(|#undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|#undefined|)|←|↵|}|↵|#fun| |did|(|x|#:| |number|,| |f|#:| |(|(|number|)| |=>| |number|)| ||| |(|#undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|arr|#:| |(|MutArray|‹|object|›|)| ||| |(|#undefined|)|)|#:| |object|↵|#class| |ABC|(||)| |{||}|↵|#fun| |testABC|(|abc|#:| |(|ABC|)| ||| |(|#undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|conf|#:| |(|SquareConfig|)| ||| |(|#undefined|)|)|#:| |unit|↵|#fun| |err|(|msg|#:| |(|(|number|,| |string|,| |)|)| ||| |(|#undefined|)|)|#:| |unit|↵|#fun| |toStr|(|x|#:| |(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|)| ||| |(|#undefined|)|)|#:| |string|↵|#fun| |boo|‹|T|,| |U|›|(|x|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|#undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(||)| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|(|b|#:| |(|B|‹|nothing|›|)| ||| |(|#undefined|)|)|#:| |anything| //│ Parsed: {fun buildName: (firstName: string, lastName: string | undefined) -> string; fun buildName2: (firstName: string, lastName: string | undefined) -> string; fun buildName3: (firstName: string, lastName: MutArray[string]) -> string; fun buildName4: (firstName: string, lastName: MutArray[anything]) -> string; trait SquareConfig() {let color: string | undefined; let width: number | undefined}; fun did: (x: number, f: number -> number | undefined) -> number; fun getOrElse: (arr: MutArray[object] | undefined) -> object; class ABC() {}; fun testABC: (abc: ABC | undefined) -> unit; fun testSquareConfig: (conf: SquareConfig | undefined) -> unit; fun err: (msg: [number, string] | undefined) -> unit; fun toStr: (x: number | false | true | undefined) -> string; fun boo: (x: T & U | undefined) -> unit; class B‹T›() {let b: T}; fun boom: (b: B[nothing] | undefined) -> anything} +//│ diff --git a/ts2mls/js/src/test/diff/Overload.d.mls b/ts2mls/js/src/test/diff/Overload.d.mls index 9cd7cbdee3..3d9b91bfbe 100644 --- a/ts2mls/js/src/test/diff/Overload.d.mls +++ b/ts2mls/js/src/test/diff/Overload.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly fun f: ((number) => string) & ((string) => string) class M() { @@ -24,3 +24,4 @@ class WWW() { fun baz(): anything /* warning: the overload of function baz is not supported yet. */ //│ |#fun| |f|#:| |(|(|number|)| |=>| |string|)| |&| |(|(|string|)| |=>| |string|)|↵|#class| |M|(||)| |{|→|#let| |foo|#:| |(|(|number|)| |=>| |string|)| |&| |(|(|string|)| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|(|string|)| |=>| |unit|)| |=>| |(|number|)| |=>| |unit|)| |&| |(|(|(|string|)| |=>| |unit|)| |=>| |(|string|)| |=>| |unit|)|↵|#fun| |create|#:| |(|(|number|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)| |&| |(|(|(|false|)| ||| |(|true|)|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)|↵|#fun| |g0|#:| |(|(|MutArray|‹|string|›|)| |=>| |string|)| |&| |(|(|MutArray|‹|object|›|)| |=>| |string|)|↵|#fun| |db|#:| |(|(|number|)| |=>| |MutArray|‹|number|›|)| |&| |(|(|object|)| |=>| |MutArray|‹|number|›|)|↵|#class| |N|(||)| |{||}|↵|#fun| |id|#:| |(|(|M|)| |=>| |unit|)| |&| |(|(|N|)| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|{|z|#:| |number|,|}|)| |=>| |{|y|#:| |string|,|}|)| |&| |(|(|{|z|#:| |(|false|)| ||| |(|true|)|,|}|)| |=>| |{|y|#:| |string|,|}|)|↵|#fun| |op|#:| |(|(|number|)| |=>| |(|(|number|)| ||| |(|#undefined|)|)| |=>| |unit|)| |&| |(|(|number|)| |=>| |(|(|(|false|)| ||| |(|true|)|)| ||| |(|#undefined|)|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|(|number|,| |string|,| |)|)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|(|string|,| |number|,| |)|)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|)| |=>| |string|)| |&| |(|(|object|)| |=>| |string|)|↵|#fun| |doSome|‹|T|,| |U|›|(|x|#:| |anything|)|#:| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#module| |XX| |{|→|#fun| |f|‹|T|›|(|x|#:| |T|,| |n|#:| |anything|)|#:| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW|(||)| |{|→|#fun| |F|‹|T|›|(|x|#:| |T|)|#:| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|(||)|#:| |anything| |/* warning: the overload of function baz is not supported yet. */| //│ Parsed: {fun f: number -> string & string -> string; class M() {let foo: number -> string & string -> string}; fun app: (string -> unit) -> number -> unit & (string -> unit) -> string -> unit; fun create: number -> unit -> bool & bool -> unit -> bool; fun g0: MutArray[string] -> string & MutArray[object] -> string; fun db: number -> MutArray[number] & object -> MutArray[number]; class N() {}; fun id: M -> unit & N -> unit; fun tst: {z: number} -> {y: string} & {z: bool} -> {y: string}; fun op: number -> (number | undefined) -> unit & number -> (false | true | undefined) -> unit; fun swap: ([number, string]) -> [number, string] & ([string, number]) -> [number, string]; fun u: (number | false | true) -> string & object -> string; fun doSome: (x: anything) -> unit; module XX() {fun f: (x: T, n: anything) -> string}; class WWW() {fun F: (x: T) -> anything}; fun baz: () -> anything} +//│ diff --git a/ts2mls/js/src/test/diff/Tuple.d.mls b/ts2mls/js/src/test/diff/Tuple.d.mls index 82536060c5..73c4c9b167 100644 --- a/ts2mls/js/src/test/diff/Tuple.d.mls +++ b/ts2mls/js/src/test/diff/Tuple.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly fun key(x: (string, (false) | (true), )): string fun value(x: (string, (false) | (true), )): (false) | (true) @@ -18,3 +18,4 @@ class B() {} fun swap(x: (A, B, )): (B, A, ) //│ |#fun| |key|(|x|#:| |(|string|,| |(|false|)| ||| |(|true|)|,| |)|)|#:| |string|↵|#fun| |value|(|x|#:| |(|string|,| |(|false|)| ||| |(|true|)|,| |)|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |third|(|x|#:| |(|number|,| |number|,| |number|,| |)|)|#:| |number|↵|#fun| |vec2|(|x|#:| |number|,| |y|#:| |number|)|#:| |(|number|,| |number|,| |)|↵|#fun| |twoFunctions|(|ff|#:| |(|(|number|)| |=>| |number|,| |(|number|)| |=>| |number|,| |)|,| |x|#:| |number|)|#:| |number|↵|#fun| |tupleIt|(|x|#:| |string|)|#:| |(|unit| |=>| |string|,| |)|↵|#fun| |s|(|flag|#:| |(|false|)| ||| |(|true|)|)|#:| |(|(|string|)| ||| |(|number|)|,| |(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|,| |)|↵|#fun| |s2|(|t|#:| |(|(|false|)| ||| |(|true|)|,| |(|string|)| ||| |(|number|)|,| |)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |ex|‹|T|,| |U|›|(|x|#:| |T|,| |y|#:| |U|)|#:| |(|T|,| |U|,| |(|T|)| |&| |(|U|)|,| |)|↵|#fun| |foo|‹|T|,| |U|›|(|x|#:| |(|(|T|)| |&| |(|U|)|,| |)|)|#:| |unit|↵|#fun| |conv|(|x|#:| |{|y|#:| |number|,|}|)|#:| |(|{|y|#:| |number|,|}|,| |{|z|#:| |string|,|}|,| |)|↵|#class| |A|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B|(||)| |{||}|↵|#fun| |swap|(|x|#:| |(|A|,| |B|,| |)|)|#:| |(|B|,| |A|,| |)| //│ Parsed: {fun key: (x: [string, bool]) -> string; fun value: (x: [string, bool]) -> bool; fun third: (x: [number, number, number]) -> number; fun vec2: (x: number, y: number) -> [number, number]; fun twoFunctions: (ff: [number -> number, number -> number], x: number) -> number; fun tupleIt: (x: string) -> unit -> string; fun s: (flag: bool) -> [string | number, number | false | true]; fun s2: (t: [bool, string | number]) -> (string | number); fun ex: (x: T, y: U) -> [T, U, T & U]; fun foo: (x: T & U) -> unit; fun conv: (x: {y: number}) -> [{y: number}, {z: string}]; class A() {let x: number}; class B() {}; fun swap: (x: [A, B]) -> [B, A]} +//│ diff --git a/ts2mls/js/src/test/diff/Type.d.mls b/ts2mls/js/src/test/diff/Type.d.mls index bf576f0c35..cbfe6d7a62 100644 --- a/ts2mls/js/src/test/diff/Type.d.mls +++ b/ts2mls/js/src/test/diff/Type.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly trait None() { let _tag: "None" @@ -30,3 +30,4 @@ let none: {_tag: "None",} fun some(a: A): (None) | (Some) //│ |#trait| |None|(||)| |{|→|#let| |_tag|#:| |"None"|←|↵|}|↵|#trait| |Some|‹|A|›|(||)| |{|→|#let| |_tag|#:| |"Some"|↵|#let| |value|#:| |A|←|↵|}|↵|#type| |Option|‹|A|›| |#=| |(|None|)| ||| |(|Some|‹|A|›|)|↵|#type| |Func| |#=| |(|number|)| |=>| |number|↵|#type| |S2| |#=| |(|string|,| |string|,| |)|↵|#trait| |I1|(||)| |{||}|↵|#trait| |I2|(||)| |{||}|↵|#type| |I3| |#=| |(|I1|)| |&| |(|I2|)|↵|#type| |StringArray| |#=| |Array|‹|string|›|↵|#type| |SomeInterface| |#=| |{|x|#:| |number|,|y|#:| |number|,|}|↵|#class| |ABC|(||)| |{||}|↵|#type| |DEF| |#=| |ABC|↵|#type| |TP|‹|A|,| |B|,| |C|›| |#=| |(|A|,| |B|,| |C|,| |)|↵|#module| |NA| |{|→|#fun| |fb|(|b|#:| |string|)|#:| |unit|↵|#type| |B| |#=| |string|←|↵|}|↵|#class| |NC|(||)| |{|→|#let| |b|#:| |string|←|↵|}|↵|#type| |G| |#=| |ABC|↵|#let| |none|#:| |{|_tag|#:| |"None"|,|}|↵|#fun| |some|‹|A|›|(|a|#:| |A|)|#:| |(|None|)| ||| |(|Some|‹|A|›|)| //│ Parsed: {trait None() {let _tag: "None"}; trait Some‹A›() {let _tag: "Some"; let value: A}; type alias Option‹A›(): None | Some[A] {}; type alias Func(): number -> number {}; type alias S2(): [string, string] {}; trait I1() {}; trait I2() {}; type alias I3(): I1 & I2 {}; type alias StringArray(): Array[string] {}; type alias SomeInterface(): {x: number, y: number} {}; class ABC() {}; type alias DEF(): ABC {}; type alias TP‹A, B, C›(): [A, B, C] {}; module NA() {fun fb: (b: string) -> unit; type alias B(): string {}}; class NC() {let b: string}; type alias G(): ABC {}; let none: {_tag: "None"}; fun some: (a: A) -> (None | Some[A])} +//│ diff --git a/ts2mls/js/src/test/diff/TypeParameter.d.mls b/ts2mls/js/src/test/diff/TypeParameter.d.mls index 0cff4661d9..0f9147888a 100644 --- a/ts2mls/js/src/test/diff/TypeParameter.d.mls +++ b/ts2mls/js/src/test/diff/TypeParameter.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly fun inc(x: T): number class CC() { @@ -27,3 +27,4 @@ fun fff(p: FFF, s: string): unit fun getFFF(): FFF //│ |#fun| |inc|‹|T|›|(|x|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(||)| |{|→|#fun| |print|(|s|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |con|‹|U|,| |T|›|(|t|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(||)| |{|→|#fun| |print|(|t|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |setStringPrinter|(|p|#:| |Printer|‹|string|›|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|‹|string|›|↵|#fun| |foo|‹|T|›|(|p|#:| |Printer|‹|T|›|,| |x|#:| |T|)|#:| |T|↵|#fun| |foo2|‹|T|›|(|p|#:| |Printer|‹|T|›|,| |x|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|y|#:| |U|)|#:| |T|←|↵|}|↵|#trait| |I|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|y|#:| |U|)|#:| |T|←|↵|}|↵|#class| |FFF|‹|T|›|(||)| |{|→|#fun| |fff|(|x|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |fff|(|p|#:| |FFF|‹|string|›|,| |s|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|‹|number|›| //│ Parsed: {fun inc: (x: T) -> number; class CC‹T›() {fun print: (s: T) -> unit}; fun con: (t: T) -> U; class Printer‹T›() {fun print: (t: T) -> unit}; fun setStringPrinter: (p: Printer[string]) -> unit; fun getStringPrinter: () -> Printer[string]; fun foo: (p: Printer[T], x: T) -> T; fun foo2: (p: Printer[T], x: T) -> T; class F‹T›() {let x: T; fun GG: (y: U) -> T}; trait I‹T›() {let x: T; fun GG: (y: U) -> T}; class FFF‹T›() {fun fff: (x: T) -> unit}; fun fff: (p: FFF[string], s: string) -> unit; fun getFFF: () -> FFF[number]} +//│ diff --git a/ts2mls/js/src/test/diff/Union.d.mls b/ts2mls/js/src/test/diff/Union.d.mls index 9baedd5fdd..de8187d0da 100644 --- a/ts2mls/js/src/test/diff/Union.d.mls +++ b/ts2mls/js/src/test/diff/Union.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly fun getString(x: (((string) | (number)) | (false)) | (true)): string fun test(x: (false) | (true)): (string) | (number) @@ -9,3 +9,4 @@ fun typeVar(x: (T) | (U)): (T) | (U) fun uuuu(x: (((string) | (number)) | (false)) | (true)): (((string) | (number)) | (false)) | (true) //│ |#fun| |getString|(|x|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |string|↵|#fun| |test|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|f|#:| |(|(|number|)| |=>| |number|)| ||| |(|(|number|)| |=>| |string|)|)|#:| |anything|↵|#fun| |get|(|arr|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|t|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|‹|T|,| |U|›|(|x|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|x|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)| //│ Parsed: {fun getString: (x: string | number | false | true) -> string; fun test: (x: bool) -> (string | number); fun run: (f: number -> number | number -> string) -> anything; fun get: (arr: MutArray[number] | MutArray[string]) -> unit; fun get2: (t: [string, string] | [number, string]) -> string; fun typeVar: (x: T | U) -> (T | U); fun uuuu: (x: string | number | false | true) -> (string | number | false | true)} +//│ diff --git a/ts2mls/js/src/test/diff/Variables.d.mls b/ts2mls/js/src/test/diff/Variables.d.mls index 9e16907875..68c9994b23 100644 --- a/ts2mls/js/src/test/diff/Variables.d.mls +++ b/ts2mls/js/src/test/diff/Variables.d.mls @@ -1,4 +1,4 @@ -:NewParser +:NewDefs :ParseOnly let URI: string let URI2: string @@ -16,3 +16,4 @@ module DD { } //│ |#let| |URI|#:| |string|↵|#let| |URI2|#:| |string|↵|#let| |foo|#:| |number|↵|#let| |bar|#:| |false|↵|#class| |FooBar|(||)| |{||}|↵|#let| |fb|#:| |FooBar|↵|#module| |ABC| |{|→|#class| |DEF|(||)| |{||}|←|↵|}|↵|#let| |d|#:| |ABC|.DEF|↵|#module| |DD| |{|→|#let| |foo|#:| |number|↵|#let| |bar|#:| |number|←|↵|}| //│ Parsed: {let URI: string; let URI2: string; let foo: number; let bar: false; class FooBar() {}; let fb: FooBar; module ABC() {class DEF() {}}; let d: ABC.DEF; module DD() {let foo: number; let bar: number}} +//│