From 20d1fa909e9ddb8c049b77c08162ded3738275d6 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Mon, 11 Sep 2023 15:14:29 +0800 Subject: [PATCH 01/37] adding optional flag to FldFlags --- .../src/main/scala/mlscript/JSBackend.scala | 4 +- shared/src/main/scala/mlscript/MLParser.scala | 12 ++--- .../src/main/scala/mlscript/NewParser.scala | 36 ++++++++------- .../src/main/scala/mlscript/NuTypeDefs.scala | 4 +- shared/src/main/scala/mlscript/Parser.scala | 2 +- shared/src/main/scala/mlscript/Typer.scala | 16 +++---- shared/src/main/scala/mlscript/helpers.scala | 26 +++++------ shared/src/main/scala/mlscript/syntax.scala | 2 +- .../src/main/scala/mlscript/ucs/helpers.scala | 2 +- shared/src/test/diff/nu/OptionalArgs.mls | 45 +++++++++++++++++++ 10 files changed, 100 insertions(+), 49 deletions(-) create mode 100644 shared/src/test/diff/nu/OptionalArgs.mls diff --git a/shared/src/main/scala/mlscript/JSBackend.scala b/shared/src/main/scala/mlscript/JSBackend.scala index 64cdddb56..966dfae03 100644 --- a/shared/src/main/scala/mlscript/JSBackend.scala +++ b/shared/src/main/scala/mlscript/JSBackend.scala @@ -934,10 +934,10 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { def prepare(nme: Str, fs: Ls[Opt[Var] -> Fld], pars: Ls[Term], unit: TypingUnit) = { val params = fs.map { - case (S(nme), Fld(FldFlags(mut, spec), trm)) => + case (S(nme), Fld(FldFlags(mut, spec, opt), trm)) => val ty = tt(trm) nme -> Field(if (mut) S(ty) else N, ty) - case (N, Fld(FldFlags(mut, spec), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top) + case (N, Fld(FldFlags(mut, spec, opt), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top) case _ => die } val body = pars.map(tt).foldRight(Record(params): Type)(Inter) diff --git a/shared/src/main/scala/mlscript/MLParser.scala b/shared/src/main/scala/mlscript/MLParser.scala index ac0a6e22c..c22a12ff4 100644 --- a/shared/src/main/scala/mlscript/MLParser.scala +++ b/shared/src/main/scala/mlscript/MLParser.scala @@ -23,7 +23,7 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) { } def toParam(t: Term): Tup = - Tup((N, Fld(FldFlags(false, false), t)) :: Nil) + Tup((N, Fld(FldFlags(false, false, false), t)) :: Nil) def toParams(t: Term): Tup = t match { case t: Tup => t @@ -67,14 +67,14 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) { def parens[p: P]: P[Term] = locate(P( "(" ~/ parenCell.rep(0, ",") ~ ",".!.? ~ ")" ).map { case (Seq(Right(t -> false)), N) => Bra(false, t) - case (Seq(Right(t -> true)), N) => Tup(N -> Fld(FldFlags(true, false), t) :: Nil) // ? single tuple with mutable + case (Seq(Right(t -> true)), N) => Tup(N -> Fld(FldFlags(true, false, false), t) :: Nil) // ? single tuple with mutable case (ts, _) => if (ts.forall(_.isRight)) Tup(ts.iterator.map { - case R(f) => N -> Fld(FldFlags(f._2, false), f._1) + case R(f) => N -> Fld(FldFlags(f._2, false, false), f._1) case _ => die // left unreachable }.toList) else Splc(ts.map { - case R((v, m)) => R(Fld(FldFlags(m, false), v)) + case R((v, m)) => R(Fld(FldFlags(m, false, false), v)) case L(spl) => L(spl) }.toList) }) @@ -104,8 +104,8 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) { "{" ~/ (kw("mut").!.? ~ variable ~ "=" ~ term map L.apply).|(kw("mut").!.? ~ variable map R.apply).rep(sep = ";" | ",") ~ "}" ).map { fs => Rcd(fs.map{ - case L((mut, v, t)) => v -> Fld(FldFlags(mut.isDefined, false), t) - case R(mut -> id) => id -> Fld(FldFlags(mut.isDefined, false), id) }.toList)}) + case L((mut, v, t)) => v -> Fld(FldFlags(mut.isDefined, false, false), t) + case R(mut -> id) => id -> Fld(FldFlags(mut.isDefined, false, false), id) }.toList)}) def fun[p: P]: P[Term] = locate(P( kw("fun") ~/ term ~ "->" ~ term ).map(nb => Lam(toParams(nb._1), nb._2))) diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index 501d25315..cfdfcf4d9 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -245,7 +245,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D final def toParams(t: Term): Tup = t match { case t: Tup => t case Bra(false, t: Tup) => t - case _ => Tup((N, Fld(FldFlags(false, false), t)) :: Nil) + case _ => Tup((N, Fld(FldFlags(false, false, false), t)) :: Nil) } final def toParamsTy(t: Type): Tuple = t match { case t: Tuple => t @@ -436,7 +436,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D case (br @ BRACKETS(Angle | Square, toks), loc) :: _ => consume val ts = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()).map { - case (N, Fld(FldFlags(false, false), v @ Var(nme))) => + case (N, Fld(FldFlags(false, false, false), v @ Var(nme))) => TypeName(nme).withLocOf(v) case _ => ??? } @@ -447,11 +447,11 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D case (br @ BRACKETS(Round, Spaces(cons, (KEYWORD("override"), ovLoc) :: rest)), loc) :: rest2 => resetCur(BRACKETS(Round, rest)(br.innerLoc) -> loc :: rest2) funParams match { - case ps @ Tup(N -> Fld(FldFlags(false, false), pat) :: Nil) :: Nil => + case ps @ Tup(N -> Fld(FldFlags(false, false, false), pat) :: Nil) :: Nil => val fv = freshVar - (Tup(N -> Fld(FldFlags(false, false), fv) :: Nil) :: Nil, S( + (Tup(N -> Fld(FldFlags(false, false, false), fv) :: Nil) :: Nil, S( (body: Term) => If(IfOpApp(fv, Var("is"), IfThen(pat, body)), S( - App(Sel(Super().withLoc(S(ovLoc)), v), Tup(N -> Fld(FldFlags(false, false), fv) :: Nil)) + App(Sel(Super().withLoc(S(ovLoc)), v), Tup(N -> Fld(FldFlags(false, false, false), fv) :: Nil)) )) )) case r => @@ -587,7 +587,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D msg"Record field should have a name" -> fld.value.toLoc :: Nil)) Var("") -> fld })) - case (Round, (N, Fld(FldFlags(false, false), elt)) :: Nil) => + case (Round, (N, Fld(FldFlags(false, false, false), elt)) :: Nil) => Bra(false, elt) case _ => // TODO actually reject round tuples? (except for function arg lists) @@ -605,7 +605,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D // } val e = expr(0) R(Forall(as.flatMap { - case N -> Fld(FldFlags(false, false), v: Var) => + case N -> Fld(FldFlags(false, false, false), v: Var) => TypeVar(R(v.name), N).withLocOf(v) :: Nil case v -> f => err(msg"illegal `forall` quantifier body" -> f.value.toLoc :: Nil) @@ -634,7 +634,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D val head = body match { case Var(clsNme) => S(TypeName(clsNme).withLocOf(body) -> Tup(Nil)) - case App(Var(clsNme), Tup(N -> Fld(FldFlags(false, false), UnitLit(true)) :: Nil)) => + case App(Var(clsNme), Tup(N -> Fld(FldFlags(false, false, false), UnitLit(true)) :: Nil)) => S(TypeName(clsNme).withLocOf(body) -> Tup(Nil)) case App(Var(clsNme), arg) => S(TypeName(clsNme).withLocOf(body) -> arg) @@ -847,7 +847,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()) // val res = TyApp(acc, as.map(_.mapSecond.to)) val res = TyApp(acc, as.map { - case (N, Fld(FldFlags(false, false), trm)) => trm.toType match { + case (N, Fld(FldFlags(false, false, false), trm)) => trm.toType match { case L(d) => raise(d); Top // TODO better case R(ty) => ty } @@ -1016,7 +1016,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D // argsOrIf(Nil).map{case (_, L(x))=> ???; case (n, R(x))=>n->x} // TODO argsOrIf(Nil, Nil, allowNewlines, prec).flatMap{case (n, L(x))=> err(msg"Unexpected 'then'/'else' clause" -> x.toLoc :: Nil) - n->Fld(FldFlags(false, false), errExpr)::Nil + n->Fld(FldFlags(false, false, false), errExpr)::Nil case (n, R(x))=>n->x::Nil} // TODO /* final def argsOrIf2()(implicit fe: FoundErr, et: ExpectThen): IfBlock \/ Ls[Opt[Var] -> Fld] = { @@ -1037,7 +1037,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D case Nil => seqAcc match { case res :: seqAcc => - (N -> R(Fld(FldFlags(false, false), Blk((res :: seqAcc).reverse))) :: acc).reverse + (N -> R(Fld(FldFlags(false, false, false), Blk((res :: seqAcc).reverse))) :: acc).reverse case Nil => acc.reverse } @@ -1063,6 +1063,12 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D S(l0) case _ => N } + val argOpt = yeetSpaces match { + case (KEYWORD("?"), l0) :: _ => + consume + S(l0) + case _ => N + } val argName = yeetSpaces match { case (IDENT(idStr, false), l0) :: (KEYWORD(":"), _) :: _ => // TODO: | ... consume @@ -1071,12 +1077,12 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D case _ => N } // val e = expr(NoElsePrec) -> argMut.isDefined - val e = exprOrIf(prec).map(Fld(FldFlags(argMut.isDefined, argSpec.isDefined), _)) + val e = exprOrIf(prec).map(Fld(FldFlags(argMut.isDefined, argSpec.isDefined, argOpt.isDefined), _)) def mkSeq = if (seqAcc.isEmpty) argName -> e else e match { case L(_) => ??? - case R(Fld(FldFlags(m, s), res)) => - argName -> R(Fld(FldFlags(m, s), Blk((res :: seqAcc).reverse))) + case R(Fld(FldFlags(m, s, o), res)) => + argName -> R(Fld(FldFlags(m, s, o), Blk((res :: seqAcc).reverse))) } cur match { @@ -1096,7 +1102,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D } e match { case L(_) => ??? - case R(Fld(FldFlags(false, false), res)) => + case R(Fld(FldFlags(false, false, false), res)) => argsOrIf(acc, res :: seqAcc, allowNewlines) case R(_) => ??? } diff --git a/shared/src/main/scala/mlscript/NuTypeDefs.scala b/shared/src/main/scala/mlscript/NuTypeDefs.scala index 811ece8f4..ca3a27082 100644 --- a/shared/src/main/scala/mlscript/NuTypeDefs.scala +++ b/shared/src/main/scala/mlscript/NuTypeDefs.scala @@ -807,7 +807,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => decl match { case td: NuTypeDef => td.params.getOrElse(Tup(Nil)).fields.map { - case (S(nme), Fld(FldFlags(mut, spec), value)) => + case (S(nme), Fld(FldFlags(mut, spec, opt), value)) => assert(!mut && !spec, "TODO") // TODO value.toType match { case R(tpe) => @@ -816,7 +816,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => nme -> FieldType(N, ty)(provTODO) case _ => ??? } - case (N, Fld(FldFlags(mut, spec), nme: Var)) => + case (N, Fld(FldFlags(mut, spec, opt), nme: Var)) => // assert(!mut && !spec, "TODO") // TODO // nme -> FieldType(N, freshVar(ttp(nme), N, S(nme.name)))(provTODO) nme -> FieldType(N, err(msg"${td.kind.str.capitalize} parameters currently need type annotations", diff --git a/shared/src/main/scala/mlscript/Parser.scala b/shared/src/main/scala/mlscript/Parser.scala index b88874a7a..9595ccb71 100644 --- a/shared/src/main/scala/mlscript/Parser.scala +++ b/shared/src/main/scala/mlscript/Parser.scala @@ -101,7 +101,7 @@ class Parser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) { Index ~~ (NAME ~ ":" ~ (noCommas | suite) | noCommas.map(Var("") -> _)).rep(1, ",").map(_.toList) ~ ",".!.? ~~ Index ).map { case (_, (Var(""), x) :: Nil, N, _) => x - case (i0, xs, _, i1) => Tup(xs.map { case (n, t) => (n optionIf (_.name.nonEmpty), Fld(FldFlags(false, false), t)) }).withLoc(i0, i1, origin) + case (i0, xs, _, i1) => Tup(xs.map { case (n, t) => (n optionIf (_.name.nonEmpty), Fld(FldFlags(false, false, false), t)) }).withLoc(i0, i1, origin) } def booleans[p: P]: P[Term] = P(binops rep (1, kw("and")) rep (1, kw("or"))) // TODO locs diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index 795cf3022..fb9737f3a 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -874,7 +874,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne :: fieldNames.map(tp => msg"Declared at" -> tp.toLoc))(raise) case _ => } - RecordType.mk(fs.map { case (n, Fld(FldFlags(mut, _), t)) => + RecordType.mk(fs.map { case (n, Fld(FldFlags(mut, _, _), t)) => if (n.name.isCapitalized) err(msg"Field identifiers must start with a small letter", term.toLoc)(raise) val tym = typePolymorphicTerm(t) @@ -895,7 +895,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne Asc(v, t.toTypeRaise).withLoc(v.toLoc.fold(t.toLoc)(_ ++ t.toLoc |> some)))) case _ => e } - }.map { case (n, Fld(FldFlags(mut, _), t)) => + }.map { case (n, Fld(FldFlags(mut, _, _), t)) => val tym = typePolymorphicTerm(t) // val tym = if (n.isDefined) typeType(t.toTypeRaise) // else typePolymorphicTerm(t) @@ -957,7 +957,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne val t_a = ArrayType(freshVar(prov, N).toUpper(prov))(prov) con(t_l, t_a, t_l) }) - case R(Fld(FldFlags(mt, sp), r)) => { + case R(Fld(FldFlags(mt, sp, op), r)) => { val t = typeMonomorphicTerm(r) if (mt) { R(FieldType(Some(t), t)(t.prov)) } else {R(t.toUpper(t.prov))} } @@ -1005,7 +1005,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne else ctx.poly { implicit ctx => typePolymorphicTerm(a) } a match { case tup @ Tup(as) => - TupleType(as.map { case (n, Fld(FldFlags(mut, spec), a)) => // TODO handle mut? + TupleType(as.map { case (n, Fld(FldFlags(mut, spec, opt), a)) => // TODO handle mut? // assert(!mut) val fprov = tp(a.toLoc, "argument") val tym = typeArg(a) @@ -1412,10 +1412,10 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne (implicit ctx: Ctx, raise: Raise, prov: TypeProvenance, vars: Map[Str, SimpleType], genLambdas: GenLambdas): SimpleType = term match { case (trm @ Var(nme)) :: sts if rcd => // field punning - typeTerms(Tup(S(trm) -> Fld(FldFlags(false, false), trm) :: Nil) :: sts, rcd, fields) + typeTerms(Tup(S(trm) -> Fld(FldFlags(false, false, false), trm) :: Nil) :: sts, rcd, fields) case Blk(sts0) :: sts1 => typeTerms(sts0 ::: sts1, rcd, fields) case Tup(Nil) :: sts => typeTerms(sts, rcd, fields) - case Tup((no, Fld(FldFlags(tmut, _), trm)) :: ofs) :: sts => + case Tup((no, Fld(FldFlags(tmut, _, _), trm)) :: ofs) :: sts => val ty = { trm match { case Bra(false, t) if ctx.inPattern => // we use syntax `(x: (p))` to type `p` as a pattern and not a type... @@ -1520,7 +1520,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne case TypedNuMxn(level, td, thisTy, superTy, tparams, params, members) => ectx(tparams) |> { implicit ectx => NuTypeDef(td.kind, td.nme, td.tparams, - S(Tup(params.map(p => N -> Fld(FldFlags(false, false), Asc(p._1, go(p._2.ub)))))), + S(Tup(params.map(p => N -> Fld(FldFlags(false, false, false), Asc(p._1, go(p._2.ub)))))), N,//TODO N, Nil, // TODO mixin parents? @@ -1531,7 +1531,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne case TypedNuCls(level, td, tparams, params, members, thisTy, sign, ihtags, ptps) => ectx(tparams) |> { implicit ectx => NuTypeDef(td.kind, td.nme, td.tparams, - Opt.when(td.params.isDefined)(Tup(params.map(p => N -> Fld(FldFlags(false, false), Asc(p._1, go(p._2.ub)))))), + Opt.when(td.params.isDefined)(Tup(params.map(p => N -> Fld(FldFlags(false, false, false), Asc(p._1, go(p._2.ub)))))), td.ctor, Option.when(!(TopType <:< sign))(go(sign)), ihtags.toList.sorted.map(_.toVar), // TODO provide targs/args diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index 30e91ba11..08b4f5501 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -533,7 +533,7 @@ trait TermImpl extends StatementImpl { self: Term => }.mkString(" ") |> bra case Splc(fields) => fields.map{ case L(l) => s"...$l" - case R(Fld(FldFlags(m, s), r)) => (if (m) "mut " else "") + (if (s) "#" else "") + r + case R(Fld(FldFlags(m, s, o), r)) => (if (m) "mut " else "") + (if (s) "#" else "") + r + (if (o) "?" else "") }.mkString("(", ", ", ")") case Bind(l, r) => s"$l as $r" |> bra case Test(l, r) => s"$l is $r" |> bra @@ -569,11 +569,11 @@ 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("|"), 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 ty @ App(App(v @ Var("\\"), Tup(N -> Fld(FldFlags(false, false, _), lhs) :: Nil)), Tup(N -> Fld(FldFlags(false, false, _), rhs) :: Nil)) => 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_!) @@ -585,7 +585,7 @@ trait TermImpl extends StatementImpl { self: Term => 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) + case Fld(FldFlags(m, s, _), v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty) }))) case Bra(rcd, trm) => trm match { case _: Rcd => if (rcd) trm.toType_! else throw new NotAType(this) @@ -596,7 +596,7 @@ trait TermImpl extends StatementImpl { self: Term => case _ => throw new NotAType(this) } case Rcd(fields) => Record(fields.map(fld => (fld._1, fld._2 match { - case Fld(FldFlags(m, s), v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty) + case Fld(FldFlags(m, s, _), v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty) }))) case Where(body, where) => Constrained(body.toType_!, Nil, where.map { @@ -772,17 +772,17 @@ trait StatementImpl extends Located { self: Statement => case R(ty) => ty } val params = fs.map { - case (S(nme), Fld(FldFlags(mut, spec), trm)) => + case (S(nme), Fld(FldFlags(mut, spec, _), trm)) => val ty = tt(trm) nme -> Field(if (mut) S(ty) else N, ty) - case (N, Fld(FldFlags(mut, spec), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top) + case (N, Fld(FldFlags(mut, spec, _), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top) case _ => die } val pos = params.unzip._1 val bod = pars.map(tt).foldRight(Record(params): Type)(Inter) val termName = Var(nme.name).withLocOf(nme) - val ctor = Def(false, termName, L(Lam(tup, App(termName, Tup(N -> Fld(FldFlags(false, false), Rcd(fs.map { - case (S(nme), fld) => nme -> Fld(FldFlags(false, false), nme) + val ctor = Def(false, termName, L(Lam(tup, App(termName, Tup(N -> Fld(FldFlags(false, false, false), Rcd(fs.map { + case (S(nme), fld) => nme -> Fld(FldFlags(false, false, false), nme) case (N, fld @ Fld(_, nme: Var)) => nme -> fld case _ => die })) :: Nil)))), true) @@ -830,7 +830,7 @@ trait StatementImpl extends Located { self: Statement => case Bra(false, t) => getFields(t) case Bra(true, Tup(fs)) => Record(fs.map { - case (S(n) -> Fld(FldFlags(mut, _), t)) => + case (S(n) -> Fld(FldFlags(mut, _, _), t)) => val ty = t.toType match { case L(d) => allDiags += d; Top case R(t) => t @@ -842,7 +842,7 @@ trait StatementImpl extends Located { self: Statement => case Bra(true, t) => lastWords(s"$t ${t.getClass}") case Tup(fs) => // TODO factor with case Bra(true, Tup(fs)) above Tuple(fs.map { - case (S(n) -> Fld(FldFlags(tmut, _), t)) => + case (S(n) -> Fld(FldFlags(tmut, _, _), t)) => val ty = t.toType match { case L(d) => allDiags += d; Top case R(t) => t diff --git a/shared/src/main/scala/mlscript/syntax.scala b/shared/src/main/scala/mlscript/syntax.scala index fe9aa373d..d0575bea0 100644 --- a/shared/src/main/scala/mlscript/syntax.scala +++ b/shared/src/main/scala/mlscript/syntax.scala @@ -102,7 +102,7 @@ final case class IfOpsApp(lhs: Term, opsRhss: Ls[Var -> IfBody]) extends IfBody final case class IfBlock(lines: Ls[IfBody \/ Statement]) extends IfBody // final case class IfApp(fun: Term, opsRhss: Ls[Var -> IfBody]) extends IfBody -final case class FldFlags(mut: Bool, spec: Bool) +final case class FldFlags(mut: Bool, spec: Bool, opt: Bool) final case class Fld(flags: FldFlags, value: Term) extends FldImpl sealed abstract class CaseBranches extends CaseBranchesImpl diff --git a/shared/src/main/scala/mlscript/ucs/helpers.scala b/shared/src/main/scala/mlscript/ucs/helpers.scala index df86f28c3..cc3046c82 100644 --- a/shared/src/main/scala/mlscript/ucs/helpers.scala +++ b/shared/src/main/scala/mlscript/ucs/helpers.scala @@ -16,7 +16,7 @@ object helpers { * @param t the sole element * @return a tuple term with the only element */ - def mkMonuple(t: Term): Tup = Tup(N -> Fld(FldFlags(false, false), t) :: Nil) + def mkMonuple(t: Term): Tup = Tup(N -> Fld(FldFlags(false, false, false), t) :: Nil) /** * Make a binary operation. diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls new file mode 100644 index 000000000..a4c173486 --- /dev/null +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -0,0 +1,45 @@ +:NewDefs + +:p +fun x(a? : Int, b? : Int) = a + b +//│ |#fun| |x|(|a|?| |#:| |Int|,| |b|?| |#:| |Int|)| |#=| |a| |+| |b| +//│ ╔══[PARSE ERROR] Unexpected ':' in expression position +//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b +//│ ╙── ^ +//│ ╔══[PARSE ERROR] Unexpected ':' in expression position +//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b +//│ ╙── ^ +//│ AST: TypingUnit(NuFunDef(None, x, [], Lam(Tup(_: App(App(Var(?), Tup(_: Var(a))), Tup(_: Var(Int))), _: App(App(Var(?), Tup(_: Var(b))), Tup(_: Var(Int)))), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b)))))) +//│ Parsed: fun x = (? (a,) (Int,), ? (b,) (Int,),) => + (a,) (b,); +//│ ╔══[ERROR] Unsupported pattern shape: +//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b +//│ ╙── ^^^^^^^^ +//│ ╔══[ERROR] Unsupported pattern shape: +//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b +//│ ╙── ^^^^^^^^ +//│ ╔══[ERROR] identifier not found: a +//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b +//│ ╙── ^ +//│ ╔══[ERROR] identifier not found: b +//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b +//│ ╙── ^ +//│ fun x: (error, error,) -> Int +//│ Code generation encountered an error: +//│ term App(App(Var(?), Tup(_: Var(a))), Tup(_: Var(Int))) is not a valid pattern + + +:p +fun f1(a : Int, b : Int) = a + b +//│ |#fun| |f1|(|a| |#:| |Int|,| |b| |#:| |Int|)| |#=| |a| |+| |b| +//│ AST: TypingUnit(NuFunDef(None, f1, [], Lam(Tup(_: Asc(Var(a), TypeName(Int)), _: Asc(Var(b), TypeName(Int))), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b)))))) +//│ Parsed: fun f1 = (a : Int, b : Int,) => + (a,) (b,); +//│ fun f1: (Int, Int,) -> Int + +:p +f1(1, 2) +//│ |f1|(|1|,| |2|)| +//│ AST: TypingUnit(App(Var(f1), Tup(_: IntLit(1), _: IntLit(2)))) +//│ Parsed: f1 (1, 2,); +//│ Int +//│ res +//│ = 3 From 0316ade81713017ffad12eca69f11d38545b09e8 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Tue, 12 Sep 2023 18:20:14 +0800 Subject: [PATCH 02/37] lexing ? char in args NewLexer --- shared/src/main/scala/mlscript/NewLexer.scala | 3 + .../src/main/scala/mlscript/NewParser.scala | 51 ++++++-- shared/src/test/diff/nu/OptionalArgs.mls | 109 +++++++++++++----- 3 files changed, 123 insertions(+), 40 deletions(-) diff --git a/shared/src/main/scala/mlscript/NewLexer.scala b/shared/src/main/scala/mlscript/NewLexer.scala index 191d408ab..7f9f1bf97 100644 --- a/shared/src/main/scala/mlscript/NewLexer.scala +++ b/shared/src/main/scala/mlscript/NewLexer.scala @@ -163,6 +163,9 @@ class NewLexer(origin: Origin, raise: Diagnostic => Unit, dbg: Bool) { // go(j, if (keywords.contains(n)) KEYWORD(n) else IDENT(n, isAlphaOp(n))) lex(j, ind, next(j, if (keywords.contains(n)) KEYWORD(n) else IDENT(n, isAlphaOp(n)))) case _ if isOpChar(c) => + if (c === '?') { + lex(i + 1, ind, next(i, IDENT(c.toString(), true))) + } else if (c === '-' && isDigit(bytes(i + 1))) { val (str, j) = takeWhile(i + 1)(isDigit) lex(j, ind, next(j, LITVAL(IntLit(-BigInt(str))))) diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index cfdfcf4d9..089dcc38f 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -7,6 +7,7 @@ import sourcecode.{Name, Line} import utils._, shorthands._ import mlscript.Message._ import BracketKind._ +import mlscript.codegen.Helpers object NewParser { @@ -216,6 +217,8 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D */ final def typingUnit: TypingUnit = { + printDbg("At MM") + val ts = block(false, false) val es = ts.map { case L(t) => @@ -409,6 +412,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D R(res.withLoc(S(l0 ++ res.getLoc))) case ModifierSet(mods, (KEYWORD(kwStr @ ("fun" | "val" | "let")), l0) :: c) => // TODO support rec? + printDbg("At MM2") consume val (isDecl, mods2) = mods.handle("declare") mods2.done @@ -431,6 +435,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D // R(errExpr) (Var("").withLoc(curLoc.map(_.left)), false) } + printDbg(s"foundErr => ${foundErr} ${success}") foundErr || !success pipe { implicit fe => val tparams = if (kwStr === "let") Ls[TypeName]() else yeetSpaces match { case (br @ BRACKETS(Angle | Square, toks), loc) :: _ => @@ -443,8 +448,10 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D ts case _ => Nil } + printDbg("HERE1") val (ps, transformBody) = yeetSpaces match { case (br @ BRACKETS(Round, Spaces(cons, (KEYWORD("override"), ovLoc) :: rest)), loc) :: rest2 => + printDbg("case 1") resetCur(BRACKETS(Round, rest)(br.innerLoc) -> loc :: rest2) funParams match { case ps @ Tup(N -> Fld(FldFlags(false, false, false), pat) :: Nil) :: Nil => @@ -459,8 +466,15 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D (r, N) } case _ => + val res = funParams + res match { + case x :: _ => printDbg(s"head => ${x.fields}") + case Nil => printDbg(s"list is empty") + } + printDbg(s"case 2${res}") // important (funParams, N) } + printDbg(s"ps and transformBody => ${ps} ${transformBody}") val asc = yeetSpaces match { case (KEYWORD(":"), _) :: _ => consume @@ -513,7 +527,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D cur.dropWhile(_._1 === SPACE && { consume; true }) final def funParams(implicit et: ExpectThen, fe: FoundErr, l: Line): Ls[Tup] = wrap(()) { l => - yeetSpaces match { + val res = yeetSpaces match { case (KEYWORD("=" | ":"), _) :: _ => Nil case Nil => Nil case (KEYWORD("of"), _) :: _ => @@ -523,6 +537,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D case (br @ BRACKETS(Round, toks), loc) :: _ => consume val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()) // TODO + printDbg(s"Okkkkk as => ${as}") Tup(as).withLoc(S(loc)) :: funParams case (tk, l0) :: _ => err(( @@ -531,6 +546,13 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D consume Nil } + res match { + case x :: _ => + printDbg(s"Here, creating the params! ${res} ${Helpers.inspect(x)}" ) + case Nil => + printDbg(s"Here, creating the params! ${res}") + } + res } final def expr(prec: Int, allowSpace: Bool = true)(implicit fe: FoundErr, l: Line): Term = wrap(prec,allowSpace) { l => @@ -1032,7 +1054,6 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D final def argsOrIf(acc: Ls[Opt[Var] -> (IfBody \/ Fld)], seqAcc: Ls[Statement], allowNewlines: Bool, prec: Int = NoElsePrec) (implicit fe: FoundErr, et: ExpectThen): Ls[Opt[Var] -> (IfBody \/ Fld)] = wrap(acc, seqAcc) { l => - cur match { case Nil => seqAcc match { @@ -1063,19 +1084,27 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D S(l0) case _ => N } - val argOpt = yeetSpaces match { - case (KEYWORD("?"), l0) :: _ => - consume - S(l0) - case _ => N + yeetSpaces match { + case x1 :: x2 :: x3 :: xs => + printDbg(s"good! ${x1} ${x2} ${x3}" ) + case _ => + printDbg("not-good!") } - val argName = yeetSpaces match { - case (IDENT(idStr, false), l0) :: (KEYWORD(":"), _) :: _ => // TODO: | ... + val (argName, argOpt) = yeetSpaces match { + case (IDENT(idStr, false), l0) :: (IDENT("?", true), l1) :: (KEYWORD(":"), _) :: _ => // TODO: | ... consume consume - S(Var(idStr).withLoc(S(l0))) - case _ => N + consume + printDbg("case #3") + (S(Var(idStr).withLoc(S(l0))), S(l1)) + case (IDENT(idStr, false), l0) :: (KEYWORD(":"), _) :: _ => + consume + consume + printDbg("case #2") + (S(Var(idStr).withLoc(S(l0))), N) + case _ => (N, N) } + printDbg(s"flags => ${argMut} ${argSpec} ${argOpt}") // val e = expr(NoElsePrec) -> argMut.isDefined val e = exprOrIf(prec).map(Fld(FldFlags(argMut.isDefined, argSpec.isDefined, argOpt.isDefined), _)) diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index a4c173486..2ae6346bc 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -1,45 +1,96 @@ :NewDefs + +// TODO: there is problem when the is SPACE after '?' + +:p +fun f1(a?: Int, b?: Int) = a + b +//│ tokens here => List((KEYWORD(fun),Loc(0,3,nu/OptionalArgs:+7)), (SPACE,Loc(3,4,nu/OptionalArgs:+7)), (IDENT(f1,false),Loc(4,6,nu/OptionalArgs:+7)), (BRACKETS(Round,List((IDENT(a,false),Loc(7,8,nu/OptionalArgs:+7)), (IDENT(?,true),Loc(8,8,nu/OptionalArgs:+7)), (KEYWORD(:),Loc(9,10,nu/OptionalArgs:+7)), (SPACE,Loc(10,11,nu/OptionalArgs:+7)), (IDENT(Int,false),Loc(11,14,nu/OptionalArgs:+7)), (COMMA,Loc(14,15,nu/OptionalArgs:+7)), (SPACE,Loc(15,16,nu/OptionalArgs:+7)), (IDENT(b,false),Loc(16,17,nu/OptionalArgs:+7)), (IDENT(?,true),Loc(17,17,nu/OptionalArgs:+7)), (KEYWORD(:),Loc(18,19,nu/OptionalArgs:+7)), (SPACE,Loc(19,20,nu/OptionalArgs:+7)), (IDENT(Int,false),Loc(20,23,nu/OptionalArgs:+7)))),Loc(6,24,nu/OptionalArgs:+7)), (SPACE,Loc(24,25,nu/OptionalArgs:+7)), (KEYWORD(=),Loc(25,26,nu/OptionalArgs:+7)), (SPACE,Loc(26,27,nu/OptionalArgs:+7)), (IDENT(a,false),Loc(27,28,nu/OptionalArgs:+7)), (SPACE,Loc(28,29,nu/OptionalArgs:+7)), (IDENT(+,true),Loc(29,30,nu/OptionalArgs:+7)), (SPACE,Loc(30,31,nu/OptionalArgs:+7)), (IDENT(b,false),Loc(31,32,nu/OptionalArgs:+7))) +//│ printtokens? |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a| |+| |b| +//│ |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a| |+| |b| +//│ AST: TypingUnit(NuFunDef(None, f1, [], App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))) +//│ Parsed: fun f1 = + (a,) (b,); +//│ ╔══[ERROR] identifier not found: a +//│ ║ l.7: fun f1(a?: Int, b?: Int) = a + b +//│ ╙── ^ +//│ ╔══[ERROR] identifier not found: b +//│ ║ l.7: fun f1(a?: Int, b?: Int) = a + b +//│ ╙── ^ +//│ fun f1: Int +//│ Code generation encountered an error: +//│ unresolved symbol a + + +// using space, creates ASC in AST. :p -fun x(a? : Int, b? : Int) = a + b -//│ |#fun| |x|(|a|?| |#:| |Int|,| |b|?| |#:| |Int|)| |#=| |a| |+| |b| -//│ ╔══[PARSE ERROR] Unexpected ':' in expression position -//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b -//│ ╙── ^ -//│ ╔══[PARSE ERROR] Unexpected ':' in expression position -//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b -//│ ╙── ^ -//│ AST: TypingUnit(NuFunDef(None, x, [], Lam(Tup(_: App(App(Var(?), Tup(_: Var(a))), Tup(_: Var(Int))), _: App(App(Var(?), Tup(_: Var(b))), Tup(_: Var(Int)))), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b)))))) -//│ Parsed: fun x = (? (a,) (Int,), ? (b,) (Int,),) => + (a,) (b,); -//│ ╔══[ERROR] Unsupported pattern shape: -//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b -//│ ╙── ^^^^^^^^ -//│ ╔══[ERROR] Unsupported pattern shape: -//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b -//│ ╙── ^^^^^^^^ +fun f1(a: Int, b: Int) = a + b +//│ tokens here => List((KEYWORD(fun),Loc(0,3,nu/OptionalArgs:+26)), (SPACE,Loc(3,4,nu/OptionalArgs:+26)), (IDENT(f1,false),Loc(4,6,nu/OptionalArgs:+26)), (BRACKETS(Round,List((IDENT(a,false),Loc(7,8,nu/OptionalArgs:+26)), (KEYWORD(:),Loc(8,9,nu/OptionalArgs:+26)), (SPACE,Loc(9,10,nu/OptionalArgs:+26)), (IDENT(Int,false),Loc(10,13,nu/OptionalArgs:+26)), (COMMA,Loc(13,14,nu/OptionalArgs:+26)), (SPACE,Loc(14,15,nu/OptionalArgs:+26)), (IDENT(b,false),Loc(15,16,nu/OptionalArgs:+26)), (KEYWORD(:),Loc(16,17,nu/OptionalArgs:+26)), (SPACE,Loc(17,18,nu/OptionalArgs:+26)), (IDENT(Int,false),Loc(18,21,nu/OptionalArgs:+26)))),Loc(6,22,nu/OptionalArgs:+26)), (SPACE,Loc(22,23,nu/OptionalArgs:+26)), (KEYWORD(=),Loc(23,24,nu/OptionalArgs:+26)), (SPACE,Loc(24,25,nu/OptionalArgs:+26)), (IDENT(a,false),Loc(25,26,nu/OptionalArgs:+26)), (SPACE,Loc(26,27,nu/OptionalArgs:+26)), (IDENT(+,true),Loc(27,28,nu/OptionalArgs:+26)), (SPACE,Loc(28,29,nu/OptionalArgs:+26)), (IDENT(b,false),Loc(29,30,nu/OptionalArgs:+26))) +//│ printtokens? |#fun| |f1|(|a|#:| |Int|,| |b|#:| |Int|)| |#=| |a| |+| |b| +//│ |#fun| |f1|(|a|#:| |Int|,| |b|#:| |Int|)| |#=| |a| |+| |b| +//│ AST: TypingUnit(NuFunDef(None, f1, [], App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))) +//│ Parsed: fun f1 = + (a,) (b,); //│ ╔══[ERROR] identifier not found: a -//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b -//│ ╙── ^ +//│ ║ l.26: fun f1(a: Int, b: Int) = a + b +//│ ╙── ^ //│ ╔══[ERROR] identifier not found: b -//│ ║ l.4: fun x(a? : Int, b? : Int) = a + b -//│ ╙── ^ -//│ fun x: (error, error,) -> Int +//│ ║ l.26: fun f1(a: Int, b: Int) = a + b +//│ ╙── ^ +//│ fun f1: Int //│ Code generation encountered an error: -//│ term App(App(Var(?), Tup(_: Var(a))), Tup(_: Var(Int))) is not a valid pattern +//│ unresolved symbol a +f1(1, 2) +//│ tokens here => List((IDENT(f1,false),Loc(0,2,nu/OptionalArgs:+42)), (BRACKETS(Round,List((LITVAL(1),Loc(3,4,nu/OptionalArgs:+42)), (COMMA,Loc(4,5,nu/OptionalArgs:+42)), (SPACE,Loc(5,6,nu/OptionalArgs:+42)), (LITVAL(2),Loc(6,7,nu/OptionalArgs:+42)))),Loc(2,8,nu/OptionalArgs:+42))) +//│ printtokens? |f1|(|1|,| |2|)| +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.42: f1(1, 2) +//│ ║ ^^^^^^^^ +//│ ╟── operator application of type `Int` is not a function +//│ ║ l.26: fun f1(a: Int, b: Int) = a + b +//│ ║ ^^^^^ +//│ ╟── but it flows into reference with expected type `(1, 2,) -> ?a` +//│ ║ l.42: f1(1, 2) +//│ ╙── ^^ +//│ error +//│ res +//│ Runtime error: +//│ ReferenceError: f11 is not defined :p -fun f1(a : Int, b : Int) = a + b -//│ |#fun| |f1|(|a| |#:| |Int|,| |b| |#:| |Int|)| |#=| |a| |+| |b| -//│ AST: TypingUnit(NuFunDef(None, f1, [], Lam(Tup(_: Asc(Var(a), TypeName(Int)), _: Asc(Var(b), TypeName(Int))), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b)))))) -//│ Parsed: fun f1 = (a : Int, b : Int,) => + (a,) (b,); -//│ fun f1: (Int, Int,) -> Int +fun f1(a, b) = a + b +//│ tokens here => List((KEYWORD(fun),Loc(0,3,nu/OptionalArgs:+60)), (SPACE,Loc(3,4,nu/OptionalArgs:+60)), (IDENT(f1,false),Loc(4,6,nu/OptionalArgs:+60)), (BRACKETS(Round,List((IDENT(a,false),Loc(7,8,nu/OptionalArgs:+60)), (COMMA,Loc(8,9,nu/OptionalArgs:+60)), (SPACE,Loc(9,10,nu/OptionalArgs:+60)), (IDENT(b,false),Loc(10,11,nu/OptionalArgs:+60)))),Loc(6,12,nu/OptionalArgs:+60)), (SPACE,Loc(12,13,nu/OptionalArgs:+60)), (KEYWORD(=),Loc(13,14,nu/OptionalArgs:+60)), (SPACE,Loc(14,15,nu/OptionalArgs:+60)), (IDENT(a,false),Loc(15,16,nu/OptionalArgs:+60)), (SPACE,Loc(16,17,nu/OptionalArgs:+60)), (IDENT(+,true),Loc(17,18,nu/OptionalArgs:+60)), (SPACE,Loc(18,19,nu/OptionalArgs:+60)), (IDENT(b,false),Loc(19,20,nu/OptionalArgs:+60))) +//│ printtokens? |#fun| |f1|(|a|,| |b|)| |#=| |a| |+| |b| +//│ |#fun| |f1|(|a|,| |b|)| |#=| |a| |+| |b| +//│ AST: TypingUnit(NuFunDef(None, f1, [], App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))) +//│ Parsed: fun f1 = + (a,) (b,); +//│ ╔══[ERROR] identifier not found: a +//│ ║ l.60: fun f1(a, b) = a + b +//│ ╙── ^ +//│ ╔══[ERROR] identifier not found: b +//│ ║ l.60: fun f1(a, b) = a + b +//│ ╙── ^ +//│ fun f1: Int +//│ Code generation encountered an error: +//│ unresolved symbol a + :p f1(1, 2) +//│ tokens here => List((IDENT(f1,false),Loc(0,2,nu/OptionalArgs:+78)), (BRACKETS(Round,List((LITVAL(1),Loc(3,4,nu/OptionalArgs:+78)), (COMMA,Loc(4,5,nu/OptionalArgs:+78)), (SPACE,Loc(5,6,nu/OptionalArgs:+78)), (LITVAL(2),Loc(6,7,nu/OptionalArgs:+78)))),Loc(2,8,nu/OptionalArgs:+78))) +//│ printtokens? |f1|(|1|,| |2|)| //│ |f1|(|1|,| |2|)| //│ AST: TypingUnit(App(Var(f1), Tup(_: IntLit(1), _: IntLit(2)))) //│ Parsed: f1 (1, 2,); -//│ Int +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.78: f1(1, 2) +//│ ║ ^^^^^^^^ +//│ ╟── operator application of type `Int` is not a function +//│ ║ l.60: fun f1(a, b) = a + b +//│ ║ ^^^^^ +//│ ╟── but it flows into reference with expected type `(1, 2,) -> ?a` +//│ ║ l.78: f1(1, 2) +//│ ╙── ^^ +//│ error //│ res -//│ = 3 +//│ Runtime error: +//│ ReferenceError: f12 is not defined From 3b036b346c88edf1e8dd1b17d6b1c1ea80fa2b32 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Tue, 12 Sep 2023 18:25:12 +0800 Subject: [PATCH 03/37] show parser debug in test --- shared/src/test/diff/nu/OptionalArgs.mls | 180 +++++++++++++++++++---- 1 file changed, 148 insertions(+), 32 deletions(-) diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 2ae6346bc..f811fe0b6 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -3,12 +3,136 @@ // TODO: there is problem when the is SPACE after '?' -:p +:dp fun f1(a?: Int, b?: Int) = a + b -//│ tokens here => List((KEYWORD(fun),Loc(0,3,nu/OptionalArgs:+7)), (SPACE,Loc(3,4,nu/OptionalArgs:+7)), (IDENT(f1,false),Loc(4,6,nu/OptionalArgs:+7)), (BRACKETS(Round,List((IDENT(a,false),Loc(7,8,nu/OptionalArgs:+7)), (IDENT(?,true),Loc(8,8,nu/OptionalArgs:+7)), (KEYWORD(:),Loc(9,10,nu/OptionalArgs:+7)), (SPACE,Loc(10,11,nu/OptionalArgs:+7)), (IDENT(Int,false),Loc(11,14,nu/OptionalArgs:+7)), (COMMA,Loc(14,15,nu/OptionalArgs:+7)), (SPACE,Loc(15,16,nu/OptionalArgs:+7)), (IDENT(b,false),Loc(16,17,nu/OptionalArgs:+7)), (IDENT(?,true),Loc(17,17,nu/OptionalArgs:+7)), (KEYWORD(:),Loc(18,19,nu/OptionalArgs:+7)), (SPACE,Loc(19,20,nu/OptionalArgs:+7)), (IDENT(Int,false),Loc(20,23,nu/OptionalArgs:+7)))),Loc(6,24,nu/OptionalArgs:+7)), (SPACE,Loc(24,25,nu/OptionalArgs:+7)), (KEYWORD(=),Loc(25,26,nu/OptionalArgs:+7)), (SPACE,Loc(26,27,nu/OptionalArgs:+7)), (IDENT(a,false),Loc(27,28,nu/OptionalArgs:+7)), (SPACE,Loc(28,29,nu/OptionalArgs:+7)), (IDENT(+,true),Loc(29,30,nu/OptionalArgs:+7)), (SPACE,Loc(30,31,nu/OptionalArgs:+7)), (IDENT(b,false),Loc(31,32,nu/OptionalArgs:+7))) -//│ printtokens? |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a| |+| |b| //│ |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a| |+| |b| -//│ AST: TypingUnit(NuFunDef(None, f1, [], App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))) +//│ At MM +//│ ? block inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.301] +//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.270] +//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.270] +//│ At MM2 +//│ ! t consumes |#fun| [at l.416] +//│ ? yeetSpaces inspects | |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=|... [at l.527] +//│ ! yeetSpaces consumes | | [at l.527] +//│ ? yeetSpaces inspects |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |... [at l.527] +//│ ! x$29 consumes |f1| [at l.427] +//│ foundErr => false true +//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.527] +//│ HERE1 +//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.527] +//│ @ funParams(()) [at l.469] +//│ │ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.527] +//│ │ ! res consumes |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| [at l.538] +//│ │ > ? maybeIndented inspects |a|?|#:| |Int|... [at l.1013] +//│ │ > @ argsOrIf(List(),List()) [at l.1056] +//│ │ > │ ? argsOrIf inspects |a|?|#:| |Int|... [at l.1057] +//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.527] +//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.527] +//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.527] +//│ │ > │ good! (IDENT(a,false),Loc(7,8,nu/OptionalArgs:+7)) (IDENT(?,true),Loc(8,8,nu/OptionalArgs:+7)) (KEYWORD(:),Loc(9,10,nu/OptionalArgs:+7)) +//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.527] +//│ │ > │ ! x$60 consumes |a| [at l.1095] +//│ │ > │ ! x$60 consumes |?| [at l.1096] +//│ │ > │ ! x$60 consumes |#:| [at l.1097] +//│ │ > │ case #3 +//│ │ > │ flags => None None Some(Loc(8,8,nu/OptionalArgs:+7)) +//│ │ > │ @ exprOrIf(1,true) [at l.1109] +//│ │ > │ │ ? exprOrIf inspects | |Int|,| |b|... [at l.571] +//│ │ > │ │ ! exprOrIf consumes | | [at l.573] +//│ │ > │ │ @ exprOrIf(1,true) [at l.574] +//│ │ > │ │ │ ? exprOrIf inspects |Int|,| |b|?|... [at l.571] +//│ │ > │ │ │ ! exprOrIf consumes |Int| [at l.590] +//│ │ > │ │ │ @ exprCont(1,`Int`,false) [at l.591] +//│ │ > │ │ │ │ ? exprCont inspects |,| |b|?|#:|... [at l.747] +//│ │ > │ │ │ = Right(Int) +//│ │ > │ │ = Right(Int) +//│ │ > │ = Right(Int) +//│ │ > │ ? argsOrIf inspects |,| |b|?|#:|... [at l.1117] +//│ │ > │ ! argsOrIf consumes |,| [at l.1123] +//│ │ > │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1056] +//│ │ > │ │ ? argsOrIf inspects | |b|?|#:| |... [at l.1057] +//│ │ > │ │ ! argsOrIf consumes | | [at l.1066] +//│ │ > │ │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1056] +//│ │ > │ │ │ ? argsOrIf inspects |b|?|#:| |Int| [at l.1057] +//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.527] +//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.527] +//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.527] +//│ │ > │ │ │ good! (IDENT(b,false),Loc(16,17,nu/OptionalArgs:+7)) (IDENT(?,true),Loc(17,17,nu/OptionalArgs:+7)) (KEYWORD(:),Loc(18,19,nu/OptionalArgs:+7)) +//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.527] +//│ │ > │ │ │ ! x$60 consumes |b| [at l.1095] +//│ │ > │ │ │ ! x$60 consumes |?| [at l.1096] +//│ │ > │ │ │ ! x$60 consumes |#:| [at l.1097] +//│ │ > │ │ │ case #3 +//│ │ > │ │ │ flags => None None Some(Loc(17,17,nu/OptionalArgs:+7)) +//│ │ > │ │ │ @ exprOrIf(1,true) [at l.1109] +//│ │ > │ │ │ │ ? exprOrIf inspects | |Int| [at l.571] +//│ │ > │ │ │ │ ! exprOrIf consumes | | [at l.573] +//│ │ > │ │ │ │ @ exprOrIf(1,true) [at l.574] +//│ │ > │ │ │ │ │ ? exprOrIf inspects |Int| [at l.571] +//│ │ > │ │ │ │ │ ! exprOrIf consumes |Int| [at l.590] +//│ │ > │ │ │ │ │ @ exprCont(1,`Int`,false) [at l.591] +//│ │ > │ │ │ │ │ │ ? exprCont inspects || [at l.747] +//│ │ > │ │ │ │ │ = Right(Int) +//│ │ > │ │ │ │ = Right(Int) +//│ │ > │ │ │ = Right(Int) +//│ │ > │ │ │ ? argsOrIf inspects || [at l.1117] +//│ │ > │ │ = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) +//│ │ > │ = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) +//│ │ > = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) +//│ │ > ? concludeWith inspects || [at l.86] +//│ │ > Concluded with List((Some(a),Fld(FldFlags(false,false,true),Int)), (Some(b),Fld(FldFlags(false,false,true),Int))) +//│ │ Okkkkk as => List((Some(a),Fld(FldFlags(false,false,true),Int)), (Some(b),Fld(FldFlags(false,false,true),Int))) +//│ │ @ funParams(()) [at l.541] +//│ │ │ ? yeetSpaces inspects | |#=| |a| |... [at l.527] +//│ │ │ ! yeetSpaces consumes | | [at l.527] +//│ │ │ Here, creating the params! List() +//│ │ = List() +//│ │ Here, creating the params! List(a: Int, b: Int,) Tup(a: Var(Int), b: Var(Int)) +//│ = List(a: Int, b: Int,) +//│ head => List((Some(a),Fld(FldFlags(false,false,true),Int)), (Some(b),Fld(FldFlags(false,false,true),Int))) +//│ case 2List(a: Int, b: Int,) +//│ @ funParams(()) [at l.475] +//│ │ ? yeetSpaces inspects |#=| |a| |+|... [at l.527] +//│ │ Here, creating the params! List() +//│ = List() +//│ ps and transformBody => List() None +//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.527] +//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.527] +//│ ! t consumes |#=| [at l.487] +//│ @ expr(0,true) [at l.488] +//│ │ @ exprOrIf(0,true) [at l.559] +//│ │ │ ? exprOrIf inspects | |a| |+| |... [at l.571] +//│ │ │ ! exprOrIf consumes | | [at l.573] +//│ │ │ @ exprOrIf(0,true) [at l.574] +//│ │ │ │ ? exprOrIf inspects |a| |+| |b| [at l.571] +//│ │ │ │ ! exprOrIf consumes |a| [at l.590] +//│ │ │ │ @ exprCont(0,`a`,false) [at l.591] +//│ │ │ │ │ ? exprCont inspects | |+| |b| [at l.747] +//│ │ │ │ │ ! exprCont consumes | | [at l.791] +//│ │ │ │ │ @ exprCont(0,`a`,false) [at l.792] +//│ │ │ │ │ │ ? exprCont inspects |+| |b| [at l.747] +//│ │ │ │ │ │ ! exprCont consumes |+| [at l.756] +//│ │ │ │ │ │ @ exprOrIf(18,true) [at l.759] +//│ │ │ │ │ │ │ ? exprOrIf inspects | |b| [at l.571] +//│ │ │ │ │ │ │ ! exprOrIf consumes | | [at l.573] +//│ │ │ │ │ │ │ @ exprOrIf(18,true) [at l.574] +//│ │ │ │ │ │ │ │ ? exprOrIf inspects |b| [at l.571] +//│ │ │ │ │ │ │ │ ! exprOrIf consumes |b| [at l.590] +//│ │ │ │ │ │ │ │ @ exprCont(18,`b`,false) [at l.591] +//│ │ │ │ │ │ │ │ │ ? exprCont inspects || [at l.747] +//│ │ │ │ │ │ │ │ = Right(b) +//│ │ │ │ │ │ │ = Right(b) +//│ │ │ │ │ │ = Right(b) +//│ │ │ │ │ │ @ exprCont(0,`+ (a,) (b,)`,false) [at l.763] +//│ │ │ │ │ │ │ ? exprCont inspects || [at l.747] +//│ │ │ │ │ │ = Right(+ (a,) (b,)) +//│ │ │ │ │ = Right(+ (a,) (b,)) +//│ │ │ │ = Right(+ (a,) (b,)) +//│ │ │ = Right(+ (a,) (b,)) +//│ │ = Right(+ (a,) (b,)) +//│ = + (a,) (b,) +//│ ? yeetSpaces inspects || [at l.527] +//│ ? parseAll inspects || [at l.75] //│ Parsed: fun f1 = + (a,) (b,); //│ ╔══[ERROR] identifier not found: a //│ ║ l.7: fun f1(a?: Int, b?: Int) = a + b @@ -24,33 +148,29 @@ fun f1(a?: Int, b?: Int) = a + b // using space, creates ASC in AST. :p fun f1(a: Int, b: Int) = a + b -//│ tokens here => List((KEYWORD(fun),Loc(0,3,nu/OptionalArgs:+26)), (SPACE,Loc(3,4,nu/OptionalArgs:+26)), (IDENT(f1,false),Loc(4,6,nu/OptionalArgs:+26)), (BRACKETS(Round,List((IDENT(a,false),Loc(7,8,nu/OptionalArgs:+26)), (KEYWORD(:),Loc(8,9,nu/OptionalArgs:+26)), (SPACE,Loc(9,10,nu/OptionalArgs:+26)), (IDENT(Int,false),Loc(10,13,nu/OptionalArgs:+26)), (COMMA,Loc(13,14,nu/OptionalArgs:+26)), (SPACE,Loc(14,15,nu/OptionalArgs:+26)), (IDENT(b,false),Loc(15,16,nu/OptionalArgs:+26)), (KEYWORD(:),Loc(16,17,nu/OptionalArgs:+26)), (SPACE,Loc(17,18,nu/OptionalArgs:+26)), (IDENT(Int,false),Loc(18,21,nu/OptionalArgs:+26)))),Loc(6,22,nu/OptionalArgs:+26)), (SPACE,Loc(22,23,nu/OptionalArgs:+26)), (KEYWORD(=),Loc(23,24,nu/OptionalArgs:+26)), (SPACE,Loc(24,25,nu/OptionalArgs:+26)), (IDENT(a,false),Loc(25,26,nu/OptionalArgs:+26)), (SPACE,Loc(26,27,nu/OptionalArgs:+26)), (IDENT(+,true),Loc(27,28,nu/OptionalArgs:+26)), (SPACE,Loc(28,29,nu/OptionalArgs:+26)), (IDENT(b,false),Loc(29,30,nu/OptionalArgs:+26))) -//│ printtokens? |#fun| |f1|(|a|#:| |Int|,| |b|#:| |Int|)| |#=| |a| |+| |b| //│ |#fun| |f1|(|a|#:| |Int|,| |b|#:| |Int|)| |#=| |a| |+| |b| //│ AST: TypingUnit(NuFunDef(None, f1, [], App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))) //│ Parsed: fun f1 = + (a,) (b,); //│ ╔══[ERROR] identifier not found: a -//│ ║ l.26: fun f1(a: Int, b: Int) = a + b -//│ ╙── ^ +//│ ║ l.150: fun f1(a: Int, b: Int) = a + b +//│ ╙── ^ //│ ╔══[ERROR] identifier not found: b -//│ ║ l.26: fun f1(a: Int, b: Int) = a + b -//│ ╙── ^ +//│ ║ l.150: fun f1(a: Int, b: Int) = a + b +//│ ╙── ^ //│ fun f1: Int //│ Code generation encountered an error: //│ unresolved symbol a f1(1, 2) -//│ tokens here => List((IDENT(f1,false),Loc(0,2,nu/OptionalArgs:+42)), (BRACKETS(Round,List((LITVAL(1),Loc(3,4,nu/OptionalArgs:+42)), (COMMA,Loc(4,5,nu/OptionalArgs:+42)), (SPACE,Loc(5,6,nu/OptionalArgs:+42)), (LITVAL(2),Loc(6,7,nu/OptionalArgs:+42)))),Loc(2,8,nu/OptionalArgs:+42))) -//│ printtokens? |f1|(|1|,| |2|)| //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.42: f1(1, 2) -//│ ║ ^^^^^^^^ +//│ ║ l.164: f1(1, 2) +//│ ║ ^^^^^^^^ //│ ╟── operator application of type `Int` is not a function -//│ ║ l.26: fun f1(a: Int, b: Int) = a + b -//│ ║ ^^^^^ +//│ ║ l.150: fun f1(a: Int, b: Int) = a + b +//│ ║ ^^^^^ //│ ╟── but it flows into reference with expected type `(1, 2,) -> ?a` -//│ ║ l.42: f1(1, 2) -//│ ╙── ^^ +//│ ║ l.164: f1(1, 2) +//│ ╙── ^^ //│ error //│ res //│ Runtime error: @@ -58,17 +178,15 @@ f1(1, 2) :p fun f1(a, b) = a + b -//│ tokens here => List((KEYWORD(fun),Loc(0,3,nu/OptionalArgs:+60)), (SPACE,Loc(3,4,nu/OptionalArgs:+60)), (IDENT(f1,false),Loc(4,6,nu/OptionalArgs:+60)), (BRACKETS(Round,List((IDENT(a,false),Loc(7,8,nu/OptionalArgs:+60)), (COMMA,Loc(8,9,nu/OptionalArgs:+60)), (SPACE,Loc(9,10,nu/OptionalArgs:+60)), (IDENT(b,false),Loc(10,11,nu/OptionalArgs:+60)))),Loc(6,12,nu/OptionalArgs:+60)), (SPACE,Loc(12,13,nu/OptionalArgs:+60)), (KEYWORD(=),Loc(13,14,nu/OptionalArgs:+60)), (SPACE,Loc(14,15,nu/OptionalArgs:+60)), (IDENT(a,false),Loc(15,16,nu/OptionalArgs:+60)), (SPACE,Loc(16,17,nu/OptionalArgs:+60)), (IDENT(+,true),Loc(17,18,nu/OptionalArgs:+60)), (SPACE,Loc(18,19,nu/OptionalArgs:+60)), (IDENT(b,false),Loc(19,20,nu/OptionalArgs:+60))) -//│ printtokens? |#fun| |f1|(|a|,| |b|)| |#=| |a| |+| |b| //│ |#fun| |f1|(|a|,| |b|)| |#=| |a| |+| |b| //│ AST: TypingUnit(NuFunDef(None, f1, [], App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))) //│ Parsed: fun f1 = + (a,) (b,); //│ ╔══[ERROR] identifier not found: a -//│ ║ l.60: fun f1(a, b) = a + b -//│ ╙── ^ +//│ ║ l.180: fun f1(a, b) = a + b +//│ ╙── ^ //│ ╔══[ERROR] identifier not found: b -//│ ║ l.60: fun f1(a, b) = a + b -//│ ╙── ^ +//│ ║ l.180: fun f1(a, b) = a + b +//│ ╙── ^ //│ fun f1: Int //│ Code generation encountered an error: //│ unresolved symbol a @@ -76,20 +194,18 @@ fun f1(a, b) = a + b :p f1(1, 2) -//│ tokens here => List((IDENT(f1,false),Loc(0,2,nu/OptionalArgs:+78)), (BRACKETS(Round,List((LITVAL(1),Loc(3,4,nu/OptionalArgs:+78)), (COMMA,Loc(4,5,nu/OptionalArgs:+78)), (SPACE,Loc(5,6,nu/OptionalArgs:+78)), (LITVAL(2),Loc(6,7,nu/OptionalArgs:+78)))),Loc(2,8,nu/OptionalArgs:+78))) -//│ printtokens? |f1|(|1|,| |2|)| //│ |f1|(|1|,| |2|)| //│ AST: TypingUnit(App(Var(f1), Tup(_: IntLit(1), _: IntLit(2)))) //│ Parsed: f1 (1, 2,); //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.78: f1(1, 2) -//│ ║ ^^^^^^^^ +//│ ║ l.196: f1(1, 2) +//│ ║ ^^^^^^^^ //│ ╟── operator application of type `Int` is not a function -//│ ║ l.60: fun f1(a, b) = a + b -//│ ║ ^^^^^ +//│ ║ l.180: fun f1(a, b) = a + b +//│ ║ ^^^^^ //│ ╟── but it flows into reference with expected type `(1, 2,) -> ?a` -//│ ║ l.78: f1(1, 2) -//│ ╙── ^^ +//│ ║ l.196: f1(1, 2) +//│ ╙── ^^ //│ error //│ res //│ Runtime error: From 5bd936514ec9a1b7cea60cf6c0457b53b621e39a Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Wed, 13 Sep 2023 15:29:28 +0800 Subject: [PATCH 04/37] fix in parsing --- .../src/main/scala/mlscript/NewParser.scala | 2 +- shared/src/test/diff/nu/OptionalArgs.mls | 74 ++++--------------- 2 files changed, 14 insertions(+), 62 deletions(-) diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index 089dcc38f..290d692d9 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -472,7 +472,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D case Nil => printDbg(s"list is empty") } printDbg(s"case 2${res}") // important - (funParams, N) + (res, N) } printDbg(s"ps and transformBody => ${ps} ${transformBody}") val asc = yeetSpaces match { diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index f811fe0b6..7d3bea4a6 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -91,11 +91,7 @@ fun f1(a?: Int, b?: Int) = a + b //│ = List(a: Int, b: Int,) //│ head => List((Some(a),Fld(FldFlags(false,false,true),Int)), (Some(b),Fld(FldFlags(false,false,true),Int))) //│ case 2List(a: Int, b: Int,) -//│ @ funParams(()) [at l.475] -//│ │ ? yeetSpaces inspects |#=| |a| |+|... [at l.527] -//│ │ Here, creating the params! List() -//│ = List() -//│ ps and transformBody => List() None +//│ ps and transformBody => List(a: Int, b: Int,) None //│ ? yeetSpaces inspects |#=| |a| |+|... [at l.527] //│ ? yeetSpaces inspects |#=| |a| |+|... [at l.527] //│ ! t consumes |#=| [at l.487] @@ -133,63 +129,29 @@ fun f1(a?: Int, b?: Int) = a + b //│ = + (a,) (b,) //│ ? yeetSpaces inspects || [at l.527] //│ ? parseAll inspects || [at l.75] -//│ Parsed: fun f1 = + (a,) (b,); -//│ ╔══[ERROR] identifier not found: a -//│ ║ l.7: fun f1(a?: Int, b?: Int) = a + b -//│ ╙── ^ -//│ ╔══[ERROR] identifier not found: b -//│ ║ l.7: fun f1(a?: Int, b?: Int) = a + b -//│ ╙── ^ -//│ fun f1: Int -//│ Code generation encountered an error: -//│ unresolved symbol a +//│ Parsed: fun f1 = (a: Int, b: Int,) => + (a,) (b,); +//│ fun f1: (a: Int, b: Int,) -> Int // using space, creates ASC in AST. :p fun f1(a: Int, b: Int) = a + b //│ |#fun| |f1|(|a|#:| |Int|,| |b|#:| |Int|)| |#=| |a| |+| |b| -//│ AST: TypingUnit(NuFunDef(None, f1, [], App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))) -//│ Parsed: fun f1 = + (a,) (b,); -//│ ╔══[ERROR] identifier not found: a -//│ ║ l.150: fun f1(a: Int, b: Int) = a + b -//│ ╙── ^ -//│ ╔══[ERROR] identifier not found: b -//│ ║ l.150: fun f1(a: Int, b: Int) = a + b -//│ ╙── ^ -//│ fun f1: Int -//│ Code generation encountered an error: -//│ unresolved symbol a +//│ AST: TypingUnit(NuFunDef(None, f1, [], Lam(Tup(a: Var(Int), b: Var(Int)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b)))))) +//│ Parsed: fun f1 = (a: Int, b: Int,) => + (a,) (b,); +//│ fun f1: (a: Int, b: Int,) -> Int f1(1, 2) -//│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.164: f1(1, 2) -//│ ║ ^^^^^^^^ -//│ ╟── operator application of type `Int` is not a function -//│ ║ l.150: fun f1(a: Int, b: Int) = a + b -//│ ║ ^^^^^ -//│ ╟── but it flows into reference with expected type `(1, 2,) -> ?a` -//│ ║ l.164: f1(1, 2) -//│ ╙── ^^ -//│ error +//│ Int //│ res -//│ Runtime error: -//│ ReferenceError: f11 is not defined +//│ = 3 :p fun f1(a, b) = a + b //│ |#fun| |f1|(|a|,| |b|)| |#=| |a| |+| |b| -//│ AST: TypingUnit(NuFunDef(None, f1, [], App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))) -//│ Parsed: fun f1 = + (a,) (b,); -//│ ╔══[ERROR] identifier not found: a -//│ ║ l.180: fun f1(a, b) = a + b -//│ ╙── ^ -//│ ╔══[ERROR] identifier not found: b -//│ ║ l.180: fun f1(a, b) = a + b -//│ ╙── ^ -//│ fun f1: Int -//│ Code generation encountered an error: -//│ unresolved symbol a +//│ AST: TypingUnit(NuFunDef(None, f1, [], Lam(Tup(_: Var(a), _: Var(b)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b)))))) +//│ Parsed: fun f1 = (a, b,) => + (a,) (b,); +//│ fun f1: (Int, Int,) -> Int :p @@ -197,16 +159,6 @@ f1(1, 2) //│ |f1|(|1|,| |2|)| //│ AST: TypingUnit(App(Var(f1), Tup(_: IntLit(1), _: IntLit(2)))) //│ Parsed: f1 (1, 2,); -//│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.196: f1(1, 2) -//│ ║ ^^^^^^^^ -//│ ╟── operator application of type `Int` is not a function -//│ ║ l.180: fun f1(a, b) = a + b -//│ ║ ^^^^^ -//│ ╟── but it flows into reference with expected type `(1, 2,) -> ?a` -//│ ║ l.196: f1(1, 2) -//│ ╙── ^^ -//│ error +//│ Int //│ res -//│ Runtime error: -//│ ReferenceError: f12 is not defined +//│ = 3 From a2ad510eb47065c6fef564792e5c7a5151dce266 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Wed, 13 Sep 2023 15:36:53 +0800 Subject: [PATCH 05/37] delete redundant prints --- .../src/main/scala/mlscript/NewParser.scala | 24 +-- shared/src/test/diff/nu/OptionalArgs.mls | 178 ++++++++---------- 2 files changed, 83 insertions(+), 119 deletions(-) diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index 290d692d9..e6dc3bda1 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -217,8 +217,6 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D */ final def typingUnit: TypingUnit = { - printDbg("At MM") - val ts = block(false, false) val es = ts.map { case L(t) => @@ -412,7 +410,6 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D R(res.withLoc(S(l0 ++ res.getLoc))) case ModifierSet(mods, (KEYWORD(kwStr @ ("fun" | "val" | "let")), l0) :: c) => // TODO support rec? - printDbg("At MM2") consume val (isDecl, mods2) = mods.handle("declare") mods2.done @@ -435,7 +432,6 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D // R(errExpr) (Var("").withLoc(curLoc.map(_.left)), false) } - printDbg(s"foundErr => ${foundErr} ${success}") foundErr || !success pipe { implicit fe => val tparams = if (kwStr === "let") Ls[TypeName]() else yeetSpaces match { case (br @ BRACKETS(Angle | Square, toks), loc) :: _ => @@ -448,10 +444,8 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D ts case _ => Nil } - printDbg("HERE1") val (ps, transformBody) = yeetSpaces match { case (br @ BRACKETS(Round, Spaces(cons, (KEYWORD("override"), ovLoc) :: rest)), loc) :: rest2 => - printDbg("case 1") resetCur(BRACKETS(Round, rest)(br.innerLoc) -> loc :: rest2) funParams match { case ps @ Tup(N -> Fld(FldFlags(false, false, false), pat) :: Nil) :: Nil => @@ -466,15 +460,8 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D (r, N) } case _ => - val res = funParams - res match { - case x :: _ => printDbg(s"head => ${x.fields}") - case Nil => printDbg(s"list is empty") - } - printDbg(s"case 2${res}") // important - (res, N) + (funParams, N) } - printDbg(s"ps and transformBody => ${ps} ${transformBody}") val asc = yeetSpaces match { case (KEYWORD(":"), _) :: _ => consume @@ -537,7 +524,6 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D case (br @ BRACKETS(Round, toks), loc) :: _ => consume val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()) // TODO - printDbg(s"Okkkkk as => ${as}") Tup(as).withLoc(S(loc)) :: funParams case (tk, l0) :: _ => err(( @@ -1084,23 +1070,15 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D S(l0) case _ => N } - yeetSpaces match { - case x1 :: x2 :: x3 :: xs => - printDbg(s"good! ${x1} ${x2} ${x3}" ) - case _ => - printDbg("not-good!") - } val (argName, argOpt) = yeetSpaces match { case (IDENT(idStr, false), l0) :: (IDENT("?", true), l1) :: (KEYWORD(":"), _) :: _ => // TODO: | ... consume consume consume - printDbg("case #3") (S(Var(idStr).withLoc(S(l0))), S(l1)) case (IDENT(idStr, false), l0) :: (KEYWORD(":"), _) :: _ => consume consume - printDbg("case #2") (S(Var(idStr).withLoc(S(l0))), N) case _ => (N, N) } diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 7d3bea4a6..9e6997daf 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -6,128 +6,114 @@ :dp fun f1(a?: Int, b?: Int) = a + b //│ |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a| |+| |b| -//│ At MM -//│ ? block inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.301] -//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.270] -//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.270] -//│ At MM2 -//│ ! t consumes |#fun| [at l.416] -//│ ? yeetSpaces inspects | |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=|... [at l.527] -//│ ! yeetSpaces consumes | | [at l.527] -//│ ? yeetSpaces inspects |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |... [at l.527] -//│ ! x$29 consumes |f1| [at l.427] -//│ foundErr => false true -//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.527] -//│ HERE1 -//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.527] -//│ @ funParams(()) [at l.469] -//│ │ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.527] -//│ │ ! res consumes |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| [at l.538] -//│ │ > ? maybeIndented inspects |a|?|#:| |Int|... [at l.1013] -//│ │ > @ argsOrIf(List(),List()) [at l.1056] -//│ │ > │ ? argsOrIf inspects |a|?|#:| |Int|... [at l.1057] -//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.527] -//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.527] -//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.527] -//│ │ > │ good! (IDENT(a,false),Loc(7,8,nu/OptionalArgs:+7)) (IDENT(?,true),Loc(8,8,nu/OptionalArgs:+7)) (KEYWORD(:),Loc(9,10,nu/OptionalArgs:+7)) -//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.527] -//│ │ > │ ! x$60 consumes |a| [at l.1095] -//│ │ > │ ! x$60 consumes |?| [at l.1096] -//│ │ > │ ! x$60 consumes |#:| [at l.1097] -//│ │ > │ case #3 +//│ ? block inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.299] +//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.268] +//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.268] +//│ ! t consumes |#fun| [at l.413] +//│ ? yeetSpaces inspects | |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=|... [at l.514] +//│ ! yeetSpaces consumes | | [at l.514] +//│ ? yeetSpaces inspects |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |... [at l.514] +//│ ! x$29 consumes |f1| [at l.424] +//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.514] +//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.514] +//│ @ funParams(()) [at l.463] +//│ │ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.514] +//│ │ ! res consumes |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| [at l.525] +//│ │ > ? maybeIndented inspects |a|?|#:| |Int|... [at l.999] +//│ │ > @ argsOrIf(List(),List()) [at l.1042] +//│ │ > │ ? argsOrIf inspects |a|?|#:| |Int|... [at l.1043] +//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.514] +//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.514] +//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.514] +//│ │ > │ ! x$60 consumes |a| [at l.1075] +//│ │ > │ ! x$60 consumes |?| [at l.1076] +//│ │ > │ ! x$60 consumes |#:| [at l.1077] //│ │ > │ flags => None None Some(Loc(8,8,nu/OptionalArgs:+7)) -//│ │ > │ @ exprOrIf(1,true) [at l.1109] -//│ │ > │ │ ? exprOrIf inspects | |Int|,| |b|... [at l.571] -//│ │ > │ │ ! exprOrIf consumes | | [at l.573] -//│ │ > │ │ @ exprOrIf(1,true) [at l.574] -//│ │ > │ │ │ ? exprOrIf inspects |Int|,| |b|?|... [at l.571] -//│ │ > │ │ │ ! exprOrIf consumes |Int| [at l.590] -//│ │ > │ │ │ @ exprCont(1,`Int`,false) [at l.591] -//│ │ > │ │ │ │ ? exprCont inspects |,| |b|?|#:|... [at l.747] +//│ │ > │ @ exprOrIf(1,true) [at l.1087] +//│ │ > │ │ ? exprOrIf inspects | |Int|,| |b|... [at l.557] +//│ │ > │ │ ! exprOrIf consumes | | [at l.559] +//│ │ > │ │ @ exprOrIf(1,true) [at l.560] +//│ │ > │ │ │ ? exprOrIf inspects |Int|,| |b|?|... [at l.557] +//│ │ > │ │ │ ! exprOrIf consumes |Int| [at l.576] +//│ │ > │ │ │ @ exprCont(1,`Int`,false) [at l.577] +//│ │ > │ │ │ │ ? exprCont inspects |,| |b|?|#:|... [at l.733] //│ │ > │ │ │ = Right(Int) //│ │ > │ │ = Right(Int) //│ │ > │ = Right(Int) -//│ │ > │ ? argsOrIf inspects |,| |b|?|#:|... [at l.1117] -//│ │ > │ ! argsOrIf consumes |,| [at l.1123] -//│ │ > │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1056] -//│ │ > │ │ ? argsOrIf inspects | |b|?|#:| |... [at l.1057] -//│ │ > │ │ ! argsOrIf consumes | | [at l.1066] -//│ │ > │ │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1056] -//│ │ > │ │ │ ? argsOrIf inspects |b|?|#:| |Int| [at l.1057] -//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.527] -//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.527] -//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.527] -//│ │ > │ │ │ good! (IDENT(b,false),Loc(16,17,nu/OptionalArgs:+7)) (IDENT(?,true),Loc(17,17,nu/OptionalArgs:+7)) (KEYWORD(:),Loc(18,19,nu/OptionalArgs:+7)) -//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.527] -//│ │ > │ │ │ ! x$60 consumes |b| [at l.1095] -//│ │ > │ │ │ ! x$60 consumes |?| [at l.1096] -//│ │ > │ │ │ ! x$60 consumes |#:| [at l.1097] -//│ │ > │ │ │ case #3 +//│ │ > │ ? argsOrIf inspects |,| |b|?|#:|... [at l.1095] +//│ │ > │ ! argsOrIf consumes |,| [at l.1101] +//│ │ > │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1042] +//│ │ > │ │ ? argsOrIf inspects | |b|?|#:| |... [at l.1043] +//│ │ > │ │ ! argsOrIf consumes | | [at l.1052] +//│ │ > │ │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1042] +//│ │ > │ │ │ ? argsOrIf inspects |b|?|#:| |Int| [at l.1043] +//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.514] +//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.514] +//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.514] +//│ │ > │ │ │ ! x$60 consumes |b| [at l.1075] +//│ │ > │ │ │ ! x$60 consumes |?| [at l.1076] +//│ │ > │ │ │ ! x$60 consumes |#:| [at l.1077] //│ │ > │ │ │ flags => None None Some(Loc(17,17,nu/OptionalArgs:+7)) -//│ │ > │ │ │ @ exprOrIf(1,true) [at l.1109] -//│ │ > │ │ │ │ ? exprOrIf inspects | |Int| [at l.571] -//│ │ > │ │ │ │ ! exprOrIf consumes | | [at l.573] -//│ │ > │ │ │ │ @ exprOrIf(1,true) [at l.574] -//│ │ > │ │ │ │ │ ? exprOrIf inspects |Int| [at l.571] -//│ │ > │ │ │ │ │ ! exprOrIf consumes |Int| [at l.590] -//│ │ > │ │ │ │ │ @ exprCont(1,`Int`,false) [at l.591] -//│ │ > │ │ │ │ │ │ ? exprCont inspects || [at l.747] +//│ │ > │ │ │ @ exprOrIf(1,true) [at l.1087] +//│ │ > │ │ │ │ ? exprOrIf inspects | |Int| [at l.557] +//│ │ > │ │ │ │ ! exprOrIf consumes | | [at l.559] +//│ │ > │ │ │ │ @ exprOrIf(1,true) [at l.560] +//│ │ > │ │ │ │ │ ? exprOrIf inspects |Int| [at l.557] +//│ │ > │ │ │ │ │ ! exprOrIf consumes |Int| [at l.576] +//│ │ > │ │ │ │ │ @ exprCont(1,`Int`,false) [at l.577] +//│ │ > │ │ │ │ │ │ ? exprCont inspects || [at l.733] //│ │ > │ │ │ │ │ = Right(Int) //│ │ > │ │ │ │ = Right(Int) //│ │ > │ │ │ = Right(Int) -//│ │ > │ │ │ ? argsOrIf inspects || [at l.1117] +//│ │ > │ │ │ ? argsOrIf inspects || [at l.1095] //│ │ > │ │ = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) //│ │ > │ = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) //│ │ > = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) //│ │ > ? concludeWith inspects || [at l.86] //│ │ > Concluded with List((Some(a),Fld(FldFlags(false,false,true),Int)), (Some(b),Fld(FldFlags(false,false,true),Int))) -//│ │ Okkkkk as => List((Some(a),Fld(FldFlags(false,false,true),Int)), (Some(b),Fld(FldFlags(false,false,true),Int))) -//│ │ @ funParams(()) [at l.541] -//│ │ │ ? yeetSpaces inspects | |#=| |a| |... [at l.527] -//│ │ │ ! yeetSpaces consumes | | [at l.527] +//│ │ @ funParams(()) [at l.527] +//│ │ │ ? yeetSpaces inspects | |#=| |a| |... [at l.514] +//│ │ │ ! yeetSpaces consumes | | [at l.514] //│ │ │ Here, creating the params! List() //│ │ = List() //│ │ Here, creating the params! List(a: Int, b: Int,) Tup(a: Var(Int), b: Var(Int)) //│ = List(a: Int, b: Int,) -//│ head => List((Some(a),Fld(FldFlags(false,false,true),Int)), (Some(b),Fld(FldFlags(false,false,true),Int))) -//│ case 2List(a: Int, b: Int,) -//│ ps and transformBody => List(a: Int, b: Int,) None -//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.527] -//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.527] -//│ ! t consumes |#=| [at l.487] -//│ @ expr(0,true) [at l.488] -//│ │ @ exprOrIf(0,true) [at l.559] -//│ │ │ ? exprOrIf inspects | |a| |+| |... [at l.571] -//│ │ │ ! exprOrIf consumes | | [at l.573] -//│ │ │ @ exprOrIf(0,true) [at l.574] -//│ │ │ │ ? exprOrIf inspects |a| |+| |b| [at l.571] -//│ │ │ │ ! exprOrIf consumes |a| [at l.590] -//│ │ │ │ @ exprCont(0,`a`,false) [at l.591] -//│ │ │ │ │ ? exprCont inspects | |+| |b| [at l.747] -//│ │ │ │ │ ! exprCont consumes | | [at l.791] -//│ │ │ │ │ @ exprCont(0,`a`,false) [at l.792] -//│ │ │ │ │ │ ? exprCont inspects |+| |b| [at l.747] -//│ │ │ │ │ │ ! exprCont consumes |+| [at l.756] -//│ │ │ │ │ │ @ exprOrIf(18,true) [at l.759] -//│ │ │ │ │ │ │ ? exprOrIf inspects | |b| [at l.571] -//│ │ │ │ │ │ │ ! exprOrIf consumes | | [at l.573] -//│ │ │ │ │ │ │ @ exprOrIf(18,true) [at l.574] -//│ │ │ │ │ │ │ │ ? exprOrIf inspects |b| [at l.571] -//│ │ │ │ │ │ │ │ ! exprOrIf consumes |b| [at l.590] -//│ │ │ │ │ │ │ │ @ exprCont(18,`b`,false) [at l.591] -//│ │ │ │ │ │ │ │ │ ? exprCont inspects || [at l.747] +//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.514] +//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.514] +//│ ! t consumes |#=| [at l.474] +//│ @ expr(0,true) [at l.475] +//│ │ @ exprOrIf(0,true) [at l.545] +//│ │ │ ? exprOrIf inspects | |a| |+| |... [at l.557] +//│ │ │ ! exprOrIf consumes | | [at l.559] +//│ │ │ @ exprOrIf(0,true) [at l.560] +//│ │ │ │ ? exprOrIf inspects |a| |+| |b| [at l.557] +//│ │ │ │ ! exprOrIf consumes |a| [at l.576] +//│ │ │ │ @ exprCont(0,`a`,false) [at l.577] +//│ │ │ │ │ ? exprCont inspects | |+| |b| [at l.733] +//│ │ │ │ │ ! exprCont consumes | | [at l.777] +//│ │ │ │ │ @ exprCont(0,`a`,false) [at l.778] +//│ │ │ │ │ │ ? exprCont inspects |+| |b| [at l.733] +//│ │ │ │ │ │ ! exprCont consumes |+| [at l.742] +//│ │ │ │ │ │ @ exprOrIf(18,true) [at l.745] +//│ │ │ │ │ │ │ ? exprOrIf inspects | |b| [at l.557] +//│ │ │ │ │ │ │ ! exprOrIf consumes | | [at l.559] +//│ │ │ │ │ │ │ @ exprOrIf(18,true) [at l.560] +//│ │ │ │ │ │ │ │ ? exprOrIf inspects |b| [at l.557] +//│ │ │ │ │ │ │ │ ! exprOrIf consumes |b| [at l.576] +//│ │ │ │ │ │ │ │ @ exprCont(18,`b`,false) [at l.577] +//│ │ │ │ │ │ │ │ │ ? exprCont inspects || [at l.733] //│ │ │ │ │ │ │ │ = Right(b) //│ │ │ │ │ │ │ = Right(b) //│ │ │ │ │ │ = Right(b) -//│ │ │ │ │ │ @ exprCont(0,`+ (a,) (b,)`,false) [at l.763] -//│ │ │ │ │ │ │ ? exprCont inspects || [at l.747] +//│ │ │ │ │ │ @ exprCont(0,`+ (a,) (b,)`,false) [at l.749] +//│ │ │ │ │ │ │ ? exprCont inspects || [at l.733] //│ │ │ │ │ │ = Right(+ (a,) (b,)) //│ │ │ │ │ = Right(+ (a,) (b,)) //│ │ │ │ = Right(+ (a,) (b,)) //│ │ │ = Right(+ (a,) (b,)) //│ │ = Right(+ (a,) (b,)) //│ = + (a,) (b,) -//│ ? yeetSpaces inspects || [at l.527] +//│ ? yeetSpaces inspects || [at l.514] //│ ? parseAll inspects || [at l.75] //│ Parsed: fun f1 = (a: Int, b: Int,) => + (a,) (b,); //│ fun f1: (a: Int, b: Int,) -> Int From 4e795d27b83c60801a0492b07672164b82efefbf Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Tue, 19 Sep 2023 18:26:56 +0800 Subject: [PATCH 06/37] add opt field in Field node, and parse correctly --- .../src/main/scala/mlscript/JSBackend.scala | 4 +- shared/src/main/scala/mlscript/MLParser.scala | 16 +- .../src/main/scala/mlscript/NewParser.scala | 39 +- shared/src/main/scala/mlscript/Typer.scala | 6 +- shared/src/main/scala/mlscript/helpers.scala | 36 +- shared/src/main/scala/mlscript/syntax.scala | 2 +- shared/src/test/diff/nu/OptionalArgs.mls | 535 +++++++++++++++--- 7 files changed, 514 insertions(+), 124 deletions(-) diff --git a/shared/src/main/scala/mlscript/JSBackend.scala b/shared/src/main/scala/mlscript/JSBackend.scala index 966dfae03..1735ab37f 100644 --- a/shared/src/main/scala/mlscript/JSBackend.scala +++ b/shared/src/main/scala/mlscript/JSBackend.scala @@ -936,8 +936,8 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { val params = fs.map { case (S(nme), Fld(FldFlags(mut, spec, opt), trm)) => val ty = tt(trm) - nme -> Field(if (mut) S(ty) else N, ty) - case (N, Fld(FldFlags(mut, spec, opt), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top) + nme -> Field(if (mut) S(ty) else N, ty, false) + case (N, Fld(FldFlags(mut, spec, opt), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top, false) case _ => die } val body = pars.map(tt).foldRight(Record(params): Type)(Inter) diff --git a/shared/src/main/scala/mlscript/MLParser.scala b/shared/src/main/scala/mlscript/MLParser.scala index c22a12ff4..4870e6880 100644 --- a/shared/src/main/scala/mlscript/MLParser.scala +++ b/shared/src/main/scala/mlscript/MLParser.scala @@ -31,7 +31,7 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) { } def toParamsTy(t: Type): Tuple = t match { case t: Tuple => t - case _ => Tuple((N, Field(None, t)) :: Nil) + case _ => Tuple((N, Field(None, t, false)) :: Nil) } def letter[p: P] = P( lowercase | uppercase ) @@ -272,8 +272,8 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) { def rcd[p: P]: P[Record] = locate(P( "{" ~/ ( kw("mut").!.? ~ variable ~ ":" ~ ty).rep(sep = ";") ~ "}" ) .map(_.toList.map { - case (None, v, t) => v -> Field(None, t) - case (Some(_), v, t) => v -> Field(Some(t), t) + case (None, v, t) => v -> Field(None, t, false) + case (Some(_), v, t) => v -> Field(Some(t), t, false) } pipe Record)) def parTyCell[p: P]: P[Either[Type, (Type, Boolean)]] = (("..." | kw("mut")).!.? ~ ty). map { @@ -287,14 +287,14 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) { case (fs, _) => if (fs.forall(_._2.isRight)) Tuple(fs.map { - case (l, Right(t -> false)) => l -> Field(None, t) - case (l, Right(t -> true)) => l -> Field(Some(t), t) + case (l, Right(t -> false)) => l -> Field(None, t, false) + case (l, Right(t -> true)) => l -> Field(Some(t), t, false) case _ => ??? // unreachable }) else Splice(fs.map{ _._2 match { case L(l) => L(l) - case R(r -> true) => R(Field(Some(r), r)) - case R(r -> false) => R(Field(None, r)) + case R(r -> true) => R(Field(Some(r), r, false)) + case R(r -> false) => R(Field(None, r, false)) } }) }) def litTy[p: P]: P[Type] = P( lit.map(l => Literal(l).withLocOf(l)) ) @@ -325,7 +325,7 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) { } def tup = parTy.map { case t: Tuple => t - case t => Tuple(N -> Field(N, t) :: Nil) + case t => Tuple(N -> Field(N, t, false) :: Nil) } P((ctorName ~ tup.?).map { case (id, S(body: Tuple)) => diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index e6dc3bda1..a75653061 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -8,6 +8,7 @@ import utils._, shorthands._ import mlscript.Message._ import BracketKind._ import mlscript.codegen.Helpers +import mlscript.ucs.helpers object NewParser { @@ -250,7 +251,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D } final def toParamsTy(t: Type): Tuple = t match { case t: Tuple => t - case _ => Tuple((N, Field(None, t)) :: Nil) + case _ => Tuple((N, Field(None, t, false)) :: Nil) } final def typ(prec: Int = 0)(implicit fe: FoundErr, l: Line): Type = mkType(expr(prec)) @@ -542,12 +543,15 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D } final def expr(prec: Int, allowSpace: Bool = true)(implicit fe: FoundErr, l: Line): Term = wrap(prec,allowSpace) { l => - exprOrIf(prec, allowSpace)(et = false, fe = fe, l = implicitly) match { + val result = exprOrIf(prec, allowSpace)(et = false, fe = fe, l = implicitly) match { case R(e) => e case L(e) => err(msg"Expected an expression; found a 'then'/'else' clause instead" -> e.toLoc :: Nil) errExpr } + printDbg(s"result => ${result} ## ${Helpers.inspect(result)}") + printDbg(s"result toType => ${result.toType}") + result } private def warnDbg(msg: Any, loco: Opt[Loc] = curLoc): Unit = @@ -738,7 +742,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D .concludeWith(_.expr(0, allowSpace = true)) val newAcc = Subs(acc, idx).withLoc(S(l0 ++ l1 ++ idx.toLoc)) exprCont(newAcc, prec, allowNewlines) - case (IDENT(opStr, true), l0) :: _ if /* isInfix(opStr) && */ opPrec(opStr)._1 > prec => + case (IDENT(opStr, true), l0) :: _ if /* isInfix(opStr) && */ opPrec(opStr)._1 > prec && opStr =/= "?" => consume val v = Var(opStr).withLoc(S(l0)) // printDbg(s">>> $opStr ${opPrec(opStr)}") @@ -765,7 +769,9 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D } case (KEYWORD(":"), l0) :: _ => consume - R(Asc(acc, typ(0))) + val asc = Asc(acc, typ(0)) + printDbg(s"asc => ${asc}") + R(asc) // case (KEYWORD(":"), _) :: _ if prec <= 1 => // consume // R(Asc(acc, typ(1))) @@ -1082,9 +1088,30 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D (S(Var(idStr).withLoc(S(l0))), N) case _ => (N, N) } - printDbg(s"flags => ${argMut} ${argSpec} ${argOpt}") // val e = expr(NoElsePrec) -> argMut.isDefined - val e = exprOrIf(prec).map(Fld(FldFlags(argMut.isDefined, argSpec.isDefined, argOpt.isDefined), _)) + val body = exprOrIf(prec) + cur match { + case x :: _ => + printDbg(s"nexttoken => ${x}") + case _ => () + } + val isOptinoal = cur match { + case (IDENT("?", true), l0) :: _ => + consume + true + case _ => + false + } + val e = body.map(Fld(FldFlags(argMut.isDefined, argSpec.isDefined, argOpt.isDefined || isOptinoal), _)) + printDbg(s"flags => ${argMut} ${argSpec} ${argOpt}") + printDbg(s"e => ${e}") + + body match { + case Right(value) => + printDbg(s"body => ${value} ${Helpers.inspect(value)}") + case _ => () + } + def mkSeq = if (seqAcc.isEmpty) argName -> e else e match { case L(_) => ??? diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index fb9737f3a..0a11e93c6 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -1494,9 +1494,9 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne def field(ft: FieldType)(implicit ectx: ExpCtx): Field = ft match { case FieldType(S(l: TV), u: TV) if l === u => val res = go(u) - Field(S(res), res) // TODO improve Field + Field(S(res), res, false) // TODO improve Field case f => - Field(f.lb.map(go), go(f.ub)) + Field(f.lb.map(go), go(f.ub), false) } class ExpCtx(val tps: Map[TV, TN]) { @@ -1602,7 +1602,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne AppliedType(TypeName("MutArray"), Bounds(f2.in.getOrElse(Bot), f2.out) :: Nil) case SpliceType(elems) => Splice(elems.map { case L(l) => L(go(l)) - case R(v) => R(Field(v.lb.map(go(_)), go(v.ub))) }) + case R(v) => R(Field(v.lb.map(go(_)), go(v.ub), false)) }) case NegType(t) => Neg(go(t)) case ExtrType(true) => Bot case ExtrType(false) => Top diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index 08b4f5501..6676cc72c 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -22,11 +22,11 @@ trait TypeLikeImpl extends Located { self: TypeLike => private def parensIf(str: Str, cnd: Boolean): Str = if (cnd) "(" + str + ")" else str private def showField(f: Field, ctx: ShowCtx): Str = f match { - case Field(N, ub) => ub.showIn(ctx, 0) - case Field(S(lb), ub) if lb === ub => ub.showIn(ctx, 0) - case Field(S(Bot), ub) => s"out ${ub.showIn(ctx, 0)}" - case Field(S(lb), Top) => s"in ${lb.showIn(ctx, 0)}" - case Field(S(lb), ub) => s"in ${lb.showIn(ctx, 0)} out ${ub.showIn(ctx, 0)}" + case Field(N, ub, _) => ub.showIn(ctx, 0) + case Field(S(lb), ub, _) if lb === ub => ub.showIn(ctx, 0) + case Field(S(Bot), ub, _) => s"out ${ub.showIn(ctx, 0)}" + case Field(S(lb), Top, _) => s"in ${lb.showIn(ctx, 0)}" + case Field(S(lb), ub, _) => s"in ${lb.showIn(ctx, 0)} out ${ub.showIn(ctx, 0)}" } def showIn(ctx: ShowCtx, outerPrec: Int): Str = this match { // TODO remove obsolete pretty-printing hacks @@ -38,17 +38,17 @@ trait TypeLikeImpl extends Located { self: TypeLike => case uv: TypeVar => ctx.vs(uv) case Recursive(n, b) => parensIf(s"${b.showIn(ctx, 2)} as ${ctx.vs(n)}", outerPrec > 1) case WithExtension(b, r) => parensIf(s"${b.showIn(ctx, 2)} with ${r.showIn(ctx, 0)}", outerPrec > 1) - case Function(Tuple((N,Field(N,l)) :: Nil), r) => Function(l, r).showIn(ctx, outerPrec) + case Function(Tuple((N,Field(N,l, _)) :: Nil), r) => Function(l, r).showIn(ctx, outerPrec) case Function(l, r) => parensIf(l.showIn(ctx, 31) + " -> " + r.showIn(ctx, 30), outerPrec > 30) case Neg(t) => s"~${t.showIn(ctx, 100)}" case Record(fs) => fs.map { nt => val nme = nt._1.name if (nme.isCapitalized) nt._2 match { - case Field(N | S(Bot), Top) => s"$nme" - case Field(S(lb), ub) if lb === ub => s"$nme = ${ub.showIn(ctx, 0)}" - case Field(N | S(Bot), ub) => s"$nme <: ${ub.showIn(ctx, 0)}" - case Field(S(lb), Top) => s"$nme :> ${lb.showIn(ctx, 0)}" - case Field(S(lb), ub) => s"$nme :> ${lb.showIn(ctx, 0)} <: ${ub.showIn(ctx, 0)}" + case Field(N | S(Bot), Top, _) => s"$nme" + case Field(S(lb), ub, _) if lb === ub => s"$nme = ${ub.showIn(ctx, 0)}" + case Field(N | S(Bot), ub, _) => s"$nme <: ${ub.showIn(ctx, 0)}" + case Field(S(lb), Top, _) => s"$nme :> ${lb.showIn(ctx, 0)}" + case Field(S(lb), ub, _) => s"$nme :> ${lb.showIn(ctx, 0)} <: ${ub.showIn(ctx, 0)}" } else s"${nt._2.mutStr}${nme}: ${showField(nt._2, ctx)}" }.mkString("{", ", ", "}") @@ -585,7 +585,7 @@ trait TermImpl extends StatementImpl { self: Term => 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) + case Fld(FldFlags(m, s, o), v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty, o) }))) case Bra(rcd, trm) => trm match { case _: Rcd => if (rcd) trm.toType_! else throw new NotAType(this) @@ -596,7 +596,7 @@ trait TermImpl extends StatementImpl { self: Term => case _ => throw new NotAType(this) } case Rcd(fields) => Record(fields.map(fld => (fld._1, fld._2 match { - case Fld(FldFlags(m, s, _), v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty) + case Fld(FldFlags(m, s, _), v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty, false) }))) case Where(body, where) => Constrained(body.toType_!, Nil, where.map { @@ -774,8 +774,8 @@ trait StatementImpl extends Located { self: Statement => val params = fs.map { case (S(nme), Fld(FldFlags(mut, spec, _), trm)) => val ty = tt(trm) - nme -> Field(if (mut) S(ty) else N, ty) - case (N, Fld(FldFlags(mut, spec, _), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top) + nme -> Field(if (mut) S(ty) else N, ty, false) + case (N, Fld(FldFlags(mut, spec, _), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top, false) case _ => die } val pos = params.unzip._1 @@ -836,7 +836,7 @@ trait StatementImpl extends Located { self: Statement => case R(t) => t } fields += n -> ty - n -> Field(None, ty) + n -> Field(None, ty, false) case _ => ??? }) :: Nil case Bra(true, t) => lastWords(s"$t ${t.getClass}") @@ -848,7 +848,7 @@ trait StatementImpl extends Located { self: Statement => case R(t) => t } fields += n -> ty - S(n) -> Field(None, ty) + S(n) -> Field(None, ty, false) case _ => ??? }) :: Nil case _ => ??? // TODO proper error @@ -858,7 +858,7 @@ trait StatementImpl extends Located { self: Statement => val tps = tparams.toList val ctor = Def(false, v, R(PolyType(tps.map(L(_)), params.foldRight(AppliedType(clsNme, tps):Type)(Function(_, _)))), true).withLocOf(stmt) - val td = TypeDef(Cls, clsNme, tps, Record(fields.toList.mapValues(Field(None, _))), Nil, Nil, Nil, N).withLocOf(stmt) + val td = TypeDef(Cls, clsNme, tps, Record(fields.toList.mapValues(Field(None, _, false))), Nil, Nil, Nil, N).withLocOf(stmt) td :: ctor :: cs case _ => ??? // TODO methods in data type defs? nested data type defs? } diff --git a/shared/src/main/scala/mlscript/syntax.scala b/shared/src/main/scala/mlscript/syntax.scala index d0575bea0..dfcf2f0b2 100644 --- a/shared/src/main/scala/mlscript/syntax.scala +++ b/shared/src/main/scala/mlscript/syntax.scala @@ -156,7 +156,7 @@ final case class Splice(fields: Ls[Either[Type, Field]]) extends Type final case class Constrained(base: TypeLike, tvBounds: Ls[TypeVar -> Bounds], where: Ls[Bounds]) extends Type // final case class FirstClassDefn(defn: NuTypeDef) extends Type // TODO -final case class Field(in: Opt[Type], out: Type) extends FieldImpl +final case class Field(in: Opt[Type], out: Type, opt: Boolean) extends FieldImpl sealed abstract class NullaryType extends Type diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 9e6997daf..a6a5de3a1 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -4,117 +4,130 @@ // TODO: there is problem when the is SPACE after '?' :dp +:p fun f1(a?: Int, b?: Int) = a + b //│ |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a| |+| |b| -//│ ? block inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.299] -//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.268] -//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.268] -//│ ! t consumes |#fun| [at l.413] -//│ ? yeetSpaces inspects | |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=|... [at l.514] -//│ ! yeetSpaces consumes | | [at l.514] -//│ ? yeetSpaces inspects |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |... [at l.514] -//│ ! x$29 consumes |f1| [at l.424] -//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.514] -//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.514] -//│ @ funParams(()) [at l.463] -//│ │ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.514] -//│ │ ! res consumes |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| [at l.525] -//│ │ > ? maybeIndented inspects |a|?|#:| |Int|... [at l.999] -//│ │ > @ argsOrIf(List(),List()) [at l.1042] -//│ │ > │ ? argsOrIf inspects |a|?|#:| |Int|... [at l.1043] -//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.514] -//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.514] -//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.514] -//│ │ > │ ! x$60 consumes |a| [at l.1075] -//│ │ > │ ! x$60 consumes |?| [at l.1076] -//│ │ > │ ! x$60 consumes |#:| [at l.1077] -//│ │ > │ flags => None None Some(Loc(8,8,nu/OptionalArgs:+7)) -//│ │ > │ @ exprOrIf(1,true) [at l.1087] -//│ │ > │ │ ? exprOrIf inspects | |Int|,| |b|... [at l.557] -//│ │ > │ │ ! exprOrIf consumes | | [at l.559] -//│ │ > │ │ @ exprOrIf(1,true) [at l.560] -//│ │ > │ │ │ ? exprOrIf inspects |Int|,| |b|?|... [at l.557] -//│ │ > │ │ │ ! exprOrIf consumes |Int| [at l.576] -//│ │ > │ │ │ @ exprCont(1,`Int`,false) [at l.577] -//│ │ > │ │ │ │ ? exprCont inspects |,| |b|?|#:|... [at l.733] +//│ ? block inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.300] +//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.269] +//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.269] +//│ ! t consumes |#fun| [at l.414] +//│ ? yeetSpaces inspects | |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=|... [at l.515] +//│ ! yeetSpaces consumes | | [at l.515] +//│ ? yeetSpaces inspects |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |... [at l.515] +//│ ! x$29 consumes |f1| [at l.425] +//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.515] +//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.515] +//│ @ funParams(()) [at l.464] +//│ │ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.515] +//│ │ ! res consumes |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| [at l.526] +//│ │ > ? maybeIndented inspects |a|?|#:| |Int|... [at l.1005] +//│ │ > @ argsOrIf(List(),List()) [at l.1048] +//│ │ > │ ? argsOrIf inspects |a|?|#:| |Int|... [at l.1049] +//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.515] +//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.515] +//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.515] +//│ │ > │ ! x$60 consumes |a| [at l.1081] +//│ │ > │ ! x$60 consumes |?| [at l.1082] +//│ │ > │ ! x$60 consumes |#:| [at l.1083] +//│ │ > │ @ exprOrIf(1,true) [at l.1092] +//│ │ > │ │ ? exprOrIf inspects | |Int|,| |b|... [at l.561] +//│ │ > │ │ ! exprOrIf consumes | | [at l.563] +//│ │ > │ │ @ exprOrIf(1,true) [at l.564] +//│ │ > │ │ │ ? exprOrIf inspects |Int|,| |b|?|... [at l.561] +//│ │ > │ │ │ ! exprOrIf consumes |Int| [at l.580] +//│ │ > │ │ │ @ exprCont(1,`Int`,false) [at l.581] +//│ │ > │ │ │ │ ? exprCont inspects |,| |b|?|#:|... [at l.737] //│ │ > │ │ │ = Right(Int) //│ │ > │ │ = Right(Int) //│ │ > │ = Right(Int) -//│ │ > │ ? argsOrIf inspects |,| |b|?|#:|... [at l.1095] -//│ │ > │ ! argsOrIf consumes |,| [at l.1101] -//│ │ > │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1042] -//│ │ > │ │ ? argsOrIf inspects | |b|?|#:| |... [at l.1043] -//│ │ > │ │ ! argsOrIf consumes | | [at l.1052] -//│ │ > │ │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1042] -//│ │ > │ │ │ ? argsOrIf inspects |b|?|#:| |Int| [at l.1043] -//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.514] -//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.514] -//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.514] -//│ │ > │ │ │ ! x$60 consumes |b| [at l.1075] -//│ │ > │ │ │ ! x$60 consumes |?| [at l.1076] -//│ │ > │ │ │ ! x$60 consumes |#:| [at l.1077] -//│ │ > │ │ │ flags => None None Some(Loc(17,17,nu/OptionalArgs:+7)) -//│ │ > │ │ │ @ exprOrIf(1,true) [at l.1087] -//│ │ > │ │ │ │ ? exprOrIf inspects | |Int| [at l.557] -//│ │ > │ │ │ │ ! exprOrIf consumes | | [at l.559] -//│ │ > │ │ │ │ @ exprOrIf(1,true) [at l.560] -//│ │ > │ │ │ │ │ ? exprOrIf inspects |Int| [at l.557] -//│ │ > │ │ │ │ │ ! exprOrIf consumes |Int| [at l.576] -//│ │ > │ │ │ │ │ @ exprCont(1,`Int`,false) [at l.577] -//│ │ > │ │ │ │ │ │ ? exprCont inspects || [at l.733] +//│ │ > │ ? argsOrIf inspects |,| |b|?|#:|... [at l.1093] +//│ │ > │ nexttoken => (COMMA,Loc(14,15,nu/OptionalArgs:+8)) +//│ │ > │ ? isOptinoal inspects |,| |b|?|#:|... [at l.1098] +//│ │ > │ flags => None None Some(Loc(8,8,nu/OptionalArgs:+8)) +//│ │ > │ e => Right(Fld(FldFlags(false,false,true),Int)) +//│ │ > │ body => Int Var(Int) +//│ │ > │ ? argsOrIf inspects |,| |b|?|#:|... [at l.1122] +//│ │ > │ ! argsOrIf consumes |,| [at l.1128] +//│ │ > │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1048] +//│ │ > │ │ ? argsOrIf inspects | |b|?|#:| |... [at l.1049] +//│ │ > │ │ ! argsOrIf consumes | | [at l.1058] +//│ │ > │ │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1048] +//│ │ > │ │ │ ? argsOrIf inspects |b|?|#:| |Int| [at l.1049] +//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.515] +//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.515] +//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.515] +//│ │ > │ │ │ ! x$60 consumes |b| [at l.1081] +//│ │ > │ │ │ ! x$60 consumes |?| [at l.1082] +//│ │ > │ │ │ ! x$60 consumes |#:| [at l.1083] +//│ │ > │ │ │ @ exprOrIf(1,true) [at l.1092] +//│ │ > │ │ │ │ ? exprOrIf inspects | |Int| [at l.561] +//│ │ > │ │ │ │ ! exprOrIf consumes | | [at l.563] +//│ │ > │ │ │ │ @ exprOrIf(1,true) [at l.564] +//│ │ > │ │ │ │ │ ? exprOrIf inspects |Int| [at l.561] +//│ │ > │ │ │ │ │ ! exprOrIf consumes |Int| [at l.580] +//│ │ > │ │ │ │ │ @ exprCont(1,`Int`,false) [at l.581] +//│ │ > │ │ │ │ │ │ ? exprCont inspects || [at l.737] //│ │ > │ │ │ │ │ = Right(Int) //│ │ > │ │ │ │ = Right(Int) //│ │ > │ │ │ = Right(Int) -//│ │ > │ │ │ ? argsOrIf inspects || [at l.1095] +//│ │ > │ │ │ ? argsOrIf inspects || [at l.1093] +//│ │ > │ │ │ ? isOptinoal inspects || [at l.1098] +//│ │ > │ │ │ flags => None None Some(Loc(17,17,nu/OptionalArgs:+8)) +//│ │ > │ │ │ e => Right(Fld(FldFlags(false,false,true),Int)) +//│ │ > │ │ │ body => Int Var(Int) +//│ │ > │ │ │ ? argsOrIf inspects || [at l.1122] //│ │ > │ │ = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) //│ │ > │ = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) //│ │ > = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) -//│ │ > ? concludeWith inspects || [at l.86] +//│ │ > ? concludeWith inspects || [at l.87] //│ │ > Concluded with List((Some(a),Fld(FldFlags(false,false,true),Int)), (Some(b),Fld(FldFlags(false,false,true),Int))) -//│ │ @ funParams(()) [at l.527] -//│ │ │ ? yeetSpaces inspects | |#=| |a| |... [at l.514] -//│ │ │ ! yeetSpaces consumes | | [at l.514] +//│ │ @ funParams(()) [at l.528] +//│ │ │ ? yeetSpaces inspects | |#=| |a| |... [at l.515] +//│ │ │ ! yeetSpaces consumes | | [at l.515] //│ │ │ Here, creating the params! List() //│ │ = List() //│ │ Here, creating the params! List(a: Int, b: Int,) Tup(a: Var(Int), b: Var(Int)) //│ = List(a: Int, b: Int,) -//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.514] -//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.514] -//│ ! t consumes |#=| [at l.474] -//│ @ expr(0,true) [at l.475] -//│ │ @ exprOrIf(0,true) [at l.545] -//│ │ │ ? exprOrIf inspects | |a| |+| |... [at l.557] -//│ │ │ ! exprOrIf consumes | | [at l.559] -//│ │ │ @ exprOrIf(0,true) [at l.560] -//│ │ │ │ ? exprOrIf inspects |a| |+| |b| [at l.557] -//│ │ │ │ ! exprOrIf consumes |a| [at l.576] -//│ │ │ │ @ exprCont(0,`a`,false) [at l.577] -//│ │ │ │ │ ? exprCont inspects | |+| |b| [at l.733] -//│ │ │ │ │ ! exprCont consumes | | [at l.777] -//│ │ │ │ │ @ exprCont(0,`a`,false) [at l.778] -//│ │ │ │ │ │ ? exprCont inspects |+| |b| [at l.733] -//│ │ │ │ │ │ ! exprCont consumes |+| [at l.742] -//│ │ │ │ │ │ @ exprOrIf(18,true) [at l.745] -//│ │ │ │ │ │ │ ? exprOrIf inspects | |b| [at l.557] -//│ │ │ │ │ │ │ ! exprOrIf consumes | | [at l.559] -//│ │ │ │ │ │ │ @ exprOrIf(18,true) [at l.560] -//│ │ │ │ │ │ │ │ ? exprOrIf inspects |b| [at l.557] -//│ │ │ │ │ │ │ │ ! exprOrIf consumes |b| [at l.576] -//│ │ │ │ │ │ │ │ @ exprCont(18,`b`,false) [at l.577] -//│ │ │ │ │ │ │ │ │ ? exprCont inspects || [at l.733] +//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.515] +//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.515] +//│ ! t consumes |#=| [at l.475] +//│ @ expr(0,true) [at l.476] +//│ │ @ exprOrIf(0,true) [at l.546] +//│ │ │ ? exprOrIf inspects | |a| |+| |... [at l.561] +//│ │ │ ! exprOrIf consumes | | [at l.563] +//│ │ │ @ exprOrIf(0,true) [at l.564] +//│ │ │ │ ? exprOrIf inspects |a| |+| |b| [at l.561] +//│ │ │ │ ! exprOrIf consumes |a| [at l.580] +//│ │ │ │ @ exprCont(0,`a`,false) [at l.581] +//│ │ │ │ │ ? exprCont inspects | |+| |b| [at l.737] +//│ │ │ │ │ ! exprCont consumes | | [at l.783] +//│ │ │ │ │ @ exprCont(0,`a`,false) [at l.784] +//│ │ │ │ │ │ ? exprCont inspects |+| |b| [at l.737] +//│ │ │ │ │ │ ! exprCont consumes |+| [at l.746] +//│ │ │ │ │ │ @ exprOrIf(18,true) [at l.749] +//│ │ │ │ │ │ │ ? exprOrIf inspects | |b| [at l.561] +//│ │ │ │ │ │ │ ! exprOrIf consumes | | [at l.563] +//│ │ │ │ │ │ │ @ exprOrIf(18,true) [at l.564] +//│ │ │ │ │ │ │ │ ? exprOrIf inspects |b| [at l.561] +//│ │ │ │ │ │ │ │ ! exprOrIf consumes |b| [at l.580] +//│ │ │ │ │ │ │ │ @ exprCont(18,`b`,false) [at l.581] +//│ │ │ │ │ │ │ │ │ ? exprCont inspects || [at l.737] //│ │ │ │ │ │ │ │ = Right(b) //│ │ │ │ │ │ │ = Right(b) //│ │ │ │ │ │ = Right(b) -//│ │ │ │ │ │ @ exprCont(0,`+ (a,) (b,)`,false) [at l.749] -//│ │ │ │ │ │ │ ? exprCont inspects || [at l.733] +//│ │ │ │ │ │ @ exprCont(0,`+ (a,) (b,)`,false) [at l.753] +//│ │ │ │ │ │ │ ? exprCont inspects || [at l.737] //│ │ │ │ │ │ = Right(+ (a,) (b,)) //│ │ │ │ │ = Right(+ (a,) (b,)) //│ │ │ │ = Right(+ (a,) (b,)) //│ │ │ = Right(+ (a,) (b,)) //│ │ = Right(+ (a,) (b,)) +//│ │ result => + (a,) (b,) ## App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))) +//│ │ result toType => Right(AppliedType(TypeName(+),List(Tuple(List((None,Field(None,TypeName(a),false)))), Tuple(List((None,Field(None,TypeName(b),false))))))) //│ = + (a,) (b,) -//│ ? yeetSpaces inspects || [at l.514] -//│ ? parseAll inspects || [at l.75] +//│ ? yeetSpaces inspects || [at l.515] +//│ ? parseAll inspects || [at l.76] +//│ AST: TypingUnit(NuFunDef(None, f1, [], Lam(Tup(a: Var(Int), b: Var(Int)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b)))))) //│ Parsed: fun f1 = (a: Int, b: Int,) => + (a,) (b,); //│ fun f1: (a: Int, b: Int,) -> Int @@ -148,3 +161,353 @@ f1(1, 2) //│ Int //│ res //│ = 3 + +// checking how typer works. +let x = [1, 2] : [Int, Int] +//│ let x: (Int, Int,) +//│ x +//│ = [ 1, 2 ] + +let f = ([a, b]) => a - b +//│ let f: (Int, Int,) -> Int +//│ f +//│ = [Function: f] + +f(x) +//│ Int +//│ res +//│ = -1 + +[1, 2, 3]: [Int, Int, Int] +//│ (Int, Int, Int,) +//│ res +//│ = [ 1, 2, 3 ] + +[1] +//│ (1,) +//│ res +//│ = [ 1 ] + +class C1 +class C2 extends C1 +let x = new C2() +let y: C1 = x +//│ class C1 +//│ class C2 extends C1 +//│ let x: C2 +//│ let y: C1 +//│ x +//│ = C2 {} +//│ y +//│ = C2 {} + +[x, y]: [C1, C1] +//│ (C1, C1,) +//│ res +//│ = [ C2 {}, C2 {} ] + + +[1, 2, 3]: [Int, Int, Int] +//│ (Int, Int, Int,) +//│ res +//│ = [ 1, 2, 3 ] + +:dp +:p +[1, 2]: [Int, Int] +//│ |[|1|,| |2|]|#:| |[|Int|,| |Int|]| +//│ ? block inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|]| [at l.300] +//│ ? go inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|]| [at l.269] +//│ ? go inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|]| [at l.269] +//│ @ exprOrIf(0,false) [at l.499] +//│ │ ? exprOrIf inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|]| [at l.561] +//│ │ ! exprOrIf consumes |[|1|,| |2|]| [at l.590] +//│ │ > ? maybeIndented inspects |1|,| |2| [at l.1005] +//│ │ > @ argsOrIf(List(),List()) [at l.1048] +//│ │ > │ ? argsOrIf inspects |1|,| |2| [at l.1049] +//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] +//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] +//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] +//│ │ > │ @ exprOrIf(1,true) [at l.1092] +//│ │ > │ │ ? exprOrIf inspects |1|,| |2| [at l.561] +//│ │ > │ │ ! exprOrIf consumes |1| [at l.574] +//│ │ > │ │ @ exprCont(1,`1`,false) [at l.575] +//│ │ > │ │ │ ? exprCont inspects |,| |2| [at l.737] +//│ │ > │ │ = Right(1) +//│ │ > │ = Right(1) +//│ │ > │ ? argsOrIf inspects |,| |2| [at l.1093] +//│ │ > │ nexttoken => (COMMA,Loc(2,3,nu/OptionalArgs:+217)) +//│ │ > │ ? isOptinoal inspects |,| |2| [at l.1098] +//│ │ > │ flags => None None None +//│ │ > │ e => Right(Fld(FldFlags(false,false,false),1)) +//│ │ > │ body => 1 IntLit(1) +//│ │ > │ ? argsOrIf inspects |,| |2| [at l.1122] +//│ │ > │ ! argsOrIf consumes |,| [at l.1128] +//│ │ > │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),1)))),List()) [at l.1048] +//│ │ > │ │ ? argsOrIf inspects | |2| [at l.1049] +//│ │ > │ │ ! argsOrIf consumes | | [at l.1058] +//│ │ > │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),1)))),List()) [at l.1048] +//│ │ > │ │ │ ? argsOrIf inspects |2| [at l.1049] +//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] +//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] +//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] +//│ │ > │ │ │ @ exprOrIf(1,true) [at l.1092] +//│ │ > │ │ │ │ ? exprOrIf inspects |2| [at l.561] +//│ │ > │ │ │ │ ! exprOrIf consumes |2| [at l.574] +//│ │ > │ │ │ │ @ exprCont(1,`2`,false) [at l.575] +//│ │ > │ │ │ │ │ ? exprCont inspects || [at l.737] +//│ │ > │ │ │ │ = Right(2) +//│ │ > │ │ │ = Right(2) +//│ │ > │ │ │ ? argsOrIf inspects || [at l.1093] +//│ │ > │ │ │ ? isOptinoal inspects || [at l.1098] +//│ │ > │ │ │ flags => None None None +//│ │ > │ │ │ e => Right(Fld(FldFlags(false,false,false),2)) +//│ │ > │ │ │ body => 2 IntLit(2) +//│ │ > │ │ │ ? argsOrIf inspects || [at l.1122] +//│ │ > │ │ = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) +//│ │ > │ = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) +//│ │ > = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) +//│ │ > ? concludeWith inspects || [at l.87] +//│ │ > Concluded with List((None,Fld(FldFlags(false,false,false),1)), (None,Fld(FldFlags(false,false,false),2))) +//│ │ @ exprCont(0,`'(' 1, 2, ')'`,false) [at l.608] +//│ │ │ ? exprCont inspects |#:| |[|Int|,| |Int|]| [at l.737] +//│ │ │ ! exprCont consumes |#:| [at l.771] +//│ │ │ @ expr(0,true) [at l.772] +//│ │ │ │ @ exprOrIf(0,true) [at l.546] +//│ │ │ │ │ ? exprOrIf inspects | |[|Int|,| |Int|]| [at l.561] +//│ │ │ │ │ ! exprOrIf consumes | | [at l.563] +//│ │ │ │ │ @ exprOrIf(0,true) [at l.564] +//│ │ │ │ │ │ ? exprOrIf inspects |[|Int|,| |Int|]| [at l.561] +//│ │ │ │ │ │ ! exprOrIf consumes |[|Int|,| |Int|]| [at l.590] +//│ │ │ │ │ │ > ? maybeIndented inspects |Int|,| |Int| [at l.1005] +//│ │ │ │ │ │ > @ argsOrIf(List(),List()) [at l.1048] +//│ │ │ │ │ │ > │ ? argsOrIf inspects |Int|,| |Int| [at l.1049] +//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int| [at l.515] +//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int| [at l.515] +//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int| [at l.515] +//│ │ │ │ │ │ > │ @ exprOrIf(1,true) [at l.1092] +//│ │ │ │ │ │ > │ │ ? exprOrIf inspects |Int|,| |Int| [at l.561] +//│ │ │ │ │ │ > │ │ ! exprOrIf consumes |Int| [at l.580] +//│ │ │ │ │ │ > │ │ @ exprCont(1,`Int`,false) [at l.581] +//│ │ │ │ │ │ > │ │ │ ? exprCont inspects |,| |Int| [at l.737] +//│ │ │ │ │ │ > │ │ = Right(Int) +//│ │ │ │ │ │ > │ = Right(Int) +//│ │ │ │ │ │ > │ ? argsOrIf inspects |,| |Int| [at l.1093] +//│ │ │ │ │ │ > │ nexttoken => (COMMA,Loc(12,13,nu/OptionalArgs:+217)) +//│ │ │ │ │ │ > │ ? isOptinoal inspects |,| |Int| [at l.1098] +//│ │ │ │ │ │ > │ flags => None None None +//│ │ │ │ │ │ > │ e => Right(Fld(FldFlags(false,false,false),Int)) +//│ │ │ │ │ │ > │ body => Int Var(Int) +//│ │ │ │ │ │ > │ ? argsOrIf inspects |,| |Int| [at l.1122] +//│ │ │ │ │ │ > │ ! argsOrIf consumes |,| [at l.1128] +//│ │ │ │ │ │ > │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] +//│ │ │ │ │ │ > │ │ ? argsOrIf inspects | |Int| [at l.1049] +//│ │ │ │ │ │ > │ │ ! argsOrIf consumes | | [at l.1058] +//│ │ │ │ │ │ > │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] +//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects |Int| [at l.1049] +//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int| [at l.515] +//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int| [at l.515] +//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int| [at l.515] +//│ │ │ │ │ │ > │ │ │ @ exprOrIf(1,true) [at l.1092] +//│ │ │ │ │ │ > │ │ │ │ ? exprOrIf inspects |Int| [at l.561] +//│ │ │ │ │ │ > │ │ │ │ ! exprOrIf consumes |Int| [at l.580] +//│ │ │ │ │ │ > │ │ │ │ @ exprCont(1,`Int`,false) [at l.581] +//│ │ │ │ │ │ > │ │ │ │ │ ? exprCont inspects || [at l.737] +//│ │ │ │ │ │ > │ │ │ │ = Right(Int) +//│ │ │ │ │ │ > │ │ │ = Right(Int) +//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects || [at l.1093] +//│ │ │ │ │ │ > │ │ │ ? isOptinoal inspects || [at l.1098] +//│ │ │ │ │ │ > │ │ │ flags => None None None +//│ │ │ │ │ │ > │ │ │ e => Right(Fld(FldFlags(false,false,false),Int)) +//│ │ │ │ │ │ > │ │ │ body => Int Var(Int) +//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects || [at l.1122] +//│ │ │ │ │ │ > │ │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int)))) +//│ │ │ │ │ │ > │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int)))) +//│ │ │ │ │ │ > = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int)))) +//│ │ │ │ │ │ > ? concludeWith inspects || [at l.87] +//│ │ │ │ │ │ > Concluded with List((None,Fld(FldFlags(false,false,false),Int)), (None,Fld(FldFlags(false,false,false),Int))) +//│ │ │ │ │ │ @ exprCont(0,`'(' Int, Int, ')'`,false) [at l.608] +//│ │ │ │ │ │ │ ? exprCont inspects || [at l.737] +//│ │ │ │ │ │ = Right('(' Int, Int, ')') +//│ │ │ │ │ = Right('(' Int, Int, ')') +//│ │ │ │ = Right('(' Int, Int, ')') +//│ │ │ │ result => '(' Int, Int, ')' ## Bra(rcd = false, Tup(_: Var(Int), _: Var(Int))) +//│ │ │ │ result toType => Right(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) +//│ │ │ = '(' Int, Int, ')' +//│ │ │ asc => '(' 1, 2, ')' : (Int, Int,) +//│ │ = Right('(' 1, 2, ')' : (Int, Int,)) +//│ = Right('(' 1, 2, ')' : (Int, Int,)) +//│ ? yeetSpaces inspects || [at l.515] +//│ ? parseAll inspects || [at l.76] +//│ AST: TypingUnit(Asc(Bra(rcd = false, Tup(_: IntLit(1), _: IntLit(2))), Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)))))) +//│ Parsed: '(' 1, 2, ')' : (Int, Int,); +//│ (Int, Int,) +//│ res +//│ = [ 1, 2 ] + +:dp +[1, 2]: [Int, Int, Int?] +//│ |[|1|,| |2|]|#:| |[|Int|,| |Int|,| |Int|?|]| +//│ ? block inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|,| |Int|?|]| [at l.300] +//│ ? go inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|,| |Int|?|]| [at l.269] +//│ ? go inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|,| |Int|?|]| [at l.269] +//│ @ exprOrIf(0,false) [at l.499] +//│ │ ? exprOrIf inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|,| |Int|?|]| [at l.561] +//│ │ ! exprOrIf consumes |[|1|,| |2|]| [at l.590] +//│ │ > ? maybeIndented inspects |1|,| |2| [at l.1005] +//│ │ > @ argsOrIf(List(),List()) [at l.1048] +//│ │ > │ ? argsOrIf inspects |1|,| |2| [at l.1049] +//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] +//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] +//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] +//│ │ > │ @ exprOrIf(1,true) [at l.1092] +//│ │ > │ │ ? exprOrIf inspects |1|,| |2| [at l.561] +//│ │ > │ │ ! exprOrIf consumes |1| [at l.574] +//│ │ > │ │ @ exprCont(1,`1`,false) [at l.575] +//│ │ > │ │ │ ? exprCont inspects |,| |2| [at l.737] +//│ │ > │ │ = Right(1) +//│ │ > │ = Right(1) +//│ │ > │ ? argsOrIf inspects |,| |2| [at l.1093] +//│ │ > │ nexttoken => (COMMA,Loc(2,3,nu/OptionalArgs:+349)) +//│ │ > │ ? isOptinoal inspects |,| |2| [at l.1098] +//│ │ > │ flags => None None None +//│ │ > │ e => Right(Fld(FldFlags(false,false,false),1)) +//│ │ > │ body => 1 IntLit(1) +//│ │ > │ ? argsOrIf inspects |,| |2| [at l.1122] +//│ │ > │ ! argsOrIf consumes |,| [at l.1128] +//│ │ > │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),1)))),List()) [at l.1048] +//│ │ > │ │ ? argsOrIf inspects | |2| [at l.1049] +//│ │ > │ │ ! argsOrIf consumes | | [at l.1058] +//│ │ > │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),1)))),List()) [at l.1048] +//│ │ > │ │ │ ? argsOrIf inspects |2| [at l.1049] +//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] +//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] +//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] +//│ │ > │ │ │ @ exprOrIf(1,true) [at l.1092] +//│ │ > │ │ │ │ ? exprOrIf inspects |2| [at l.561] +//│ │ > │ │ │ │ ! exprOrIf consumes |2| [at l.574] +//│ │ > │ │ │ │ @ exprCont(1,`2`,false) [at l.575] +//│ │ > │ │ │ │ │ ? exprCont inspects || [at l.737] +//│ │ > │ │ │ │ = Right(2) +//│ │ > │ │ │ = Right(2) +//│ │ > │ │ │ ? argsOrIf inspects || [at l.1093] +//│ │ > │ │ │ ? isOptinoal inspects || [at l.1098] +//│ │ > │ │ │ flags => None None None +//│ │ > │ │ │ e => Right(Fld(FldFlags(false,false,false),2)) +//│ │ > │ │ │ body => 2 IntLit(2) +//│ │ > │ │ │ ? argsOrIf inspects || [at l.1122] +//│ │ > │ │ = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) +//│ │ > │ = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) +//│ │ > = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) +//│ │ > ? concludeWith inspects || [at l.87] +//│ │ > Concluded with List((None,Fld(FldFlags(false,false,false),1)), (None,Fld(FldFlags(false,false,false),2))) +//│ │ @ exprCont(0,`'(' 1, 2, ')'`,false) [at l.608] +//│ │ │ ? exprCont inspects |#:| |[|Int|,| |Int|,| |Int|?|]| [at l.737] +//│ │ │ ! exprCont consumes |#:| [at l.771] +//│ │ │ @ expr(0,true) [at l.772] +//│ │ │ │ @ exprOrIf(0,true) [at l.546] +//│ │ │ │ │ ? exprOrIf inspects | |[|Int|,| |Int|,| |Int|?|]| [at l.561] +//│ │ │ │ │ ! exprOrIf consumes | | [at l.563] +//│ │ │ │ │ @ exprOrIf(0,true) [at l.564] +//│ │ │ │ │ │ ? exprOrIf inspects |[|Int|,| |Int|,| |Int|?|]| [at l.561] +//│ │ │ │ │ │ ! exprOrIf consumes |[|Int|,| |Int|,| |Int|?|]| [at l.590] +//│ │ │ │ │ │ > ? maybeIndented inspects |Int|,| |Int|,|... [at l.1005] +//│ │ │ │ │ │ > @ argsOrIf(List(),List()) [at l.1048] +//│ │ │ │ │ │ > │ ? argsOrIf inspects |Int|,| |Int|,|... [at l.1049] +//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int|,|... [at l.515] +//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int|,|... [at l.515] +//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int|,|... [at l.515] +//│ │ │ │ │ │ > │ @ exprOrIf(1,true) [at l.1092] +//│ │ │ │ │ │ > │ │ ? exprOrIf inspects |Int|,| |Int|,|... [at l.561] +//│ │ │ │ │ │ > │ │ ! exprOrIf consumes |Int| [at l.580] +//│ │ │ │ │ │ > │ │ @ exprCont(1,`Int`,false) [at l.581] +//│ │ │ │ │ │ > │ │ │ ? exprCont inspects |,| |Int|,| |... [at l.737] +//│ │ │ │ │ │ > │ │ = Right(Int) +//│ │ │ │ │ │ > │ = Right(Int) +//│ │ │ │ │ │ > │ ? argsOrIf inspects |,| |Int|,| |... [at l.1093] +//│ │ │ │ │ │ > │ nexttoken => (COMMA,Loc(12,13,nu/OptionalArgs:+349)) +//│ │ │ │ │ │ > │ ? isOptinoal inspects |,| |Int|,| |... [at l.1098] +//│ │ │ │ │ │ > │ flags => None None None +//│ │ │ │ │ │ > │ e => Right(Fld(FldFlags(false,false,false),Int)) +//│ │ │ │ │ │ > │ body => Int Var(Int) +//│ │ │ │ │ │ > │ ? argsOrIf inspects |,| |Int|,| |... [at l.1122] +//│ │ │ │ │ │ > │ ! argsOrIf consumes |,| [at l.1128] +//│ │ │ │ │ │ > │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] +//│ │ │ │ │ │ > │ │ ? argsOrIf inspects | |Int|,| |Int|... [at l.1049] +//│ │ │ │ │ │ > │ │ ! argsOrIf consumes | | [at l.1058] +//│ │ │ │ │ │ > │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] +//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects |Int|,| |Int|?| [at l.1049] +//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int|,| |Int|?| [at l.515] +//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int|,| |Int|?| [at l.515] +//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int|,| |Int|?| [at l.515] +//│ │ │ │ │ │ > │ │ │ @ exprOrIf(1,true) [at l.1092] +//│ │ │ │ │ │ > │ │ │ │ ? exprOrIf inspects |Int|,| |Int|?| [at l.561] +//│ │ │ │ │ │ > │ │ │ │ ! exprOrIf consumes |Int| [at l.580] +//│ │ │ │ │ │ > │ │ │ │ @ exprCont(1,`Int`,false) [at l.581] +//│ │ │ │ │ │ > │ │ │ │ │ ? exprCont inspects |,| |Int|?| [at l.737] +//│ │ │ │ │ │ > │ │ │ │ = Right(Int) +//│ │ │ │ │ │ > │ │ │ = Right(Int) +//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects |,| |Int|?| [at l.1093] +//│ │ │ │ │ │ > │ │ │ nexttoken => (COMMA,Loc(17,18,nu/OptionalArgs:+349)) +//│ │ │ │ │ │ > │ │ │ ? isOptinoal inspects |,| |Int|?| [at l.1098] +//│ │ │ │ │ │ > │ │ │ flags => None None None +//│ │ │ │ │ │ > │ │ │ e => Right(Fld(FldFlags(false,false,false),Int)) +//│ │ │ │ │ │ > │ │ │ body => Int Var(Int) +//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects |,| |Int|?| [at l.1122] +//│ │ │ │ │ │ > │ │ │ ! argsOrIf consumes |,| [at l.1128] +//│ │ │ │ │ │ > │ │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] +//│ │ │ │ │ │ > │ │ │ │ ? argsOrIf inspects | |Int|?| [at l.1049] +//│ │ │ │ │ │ > │ │ │ │ ! argsOrIf consumes | | [at l.1058] +//│ │ │ │ │ │ > │ │ │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] +//│ │ │ │ │ │ > │ │ │ │ │ ? argsOrIf inspects |Int|?| [at l.1049] +//│ │ │ │ │ │ > │ │ │ │ │ ? yeetSpaces inspects |Int|?| [at l.515] +//│ │ │ │ │ │ > │ │ │ │ │ ? yeetSpaces inspects |Int|?| [at l.515] +//│ │ │ │ │ │ > │ │ │ │ │ ? yeetSpaces inspects |Int|?| [at l.515] +//│ │ │ │ │ │ > │ │ │ │ │ @ exprOrIf(1,true) [at l.1092] +//│ │ │ │ │ │ > │ │ │ │ │ │ ? exprOrIf inspects |Int|?| [at l.561] +//│ │ │ │ │ │ > │ │ │ │ │ │ ! exprOrIf consumes |Int| [at l.580] +//│ │ │ │ │ │ > │ │ │ │ │ │ @ exprCont(1,`Int`,false) [at l.581] +//│ │ │ │ │ │ > │ │ │ │ │ │ │ ? exprCont inspects |?| [at l.737] +//│ │ │ │ │ │ > │ │ │ │ │ │ = Right(Int) +//│ │ │ │ │ │ > │ │ │ │ │ = Right(Int) +//│ │ │ │ │ │ > │ │ │ │ │ ? argsOrIf inspects |?| [at l.1093] +//│ │ │ │ │ │ > │ │ │ │ │ nexttoken => (IDENT(?,true),Loc(22,22,nu/OptionalArgs:+349)) +//│ │ │ │ │ │ > │ │ │ │ │ ? isOptinoal inspects |?| [at l.1098] +//│ │ │ │ │ │ > │ │ │ │ │ ! isOptinoal consumes |?| [at l.1100] +//│ │ │ │ │ │ > │ │ │ │ │ flags => None None None +//│ │ │ │ │ │ > │ │ │ │ │ e => Right(Fld(FldFlags(false,false,true),Int)) +//│ │ │ │ │ │ > │ │ │ │ │ body => Int Var(Int) +//│ │ │ │ │ │ > │ │ │ │ │ ? argsOrIf inspects || [at l.1122] +//│ │ │ │ │ │ > │ │ │ │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) +//│ │ │ │ │ │ > │ │ │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) +//│ │ │ │ │ │ > │ │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) +//│ │ │ │ │ │ > │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) +//│ │ │ │ │ │ > = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) +//│ │ │ │ │ │ > ? concludeWith inspects || [at l.87] +//│ │ │ │ │ │ > Concluded with List((None,Fld(FldFlags(false,false,false),Int)), (None,Fld(FldFlags(false,false,false),Int)), (None,Fld(FldFlags(false,false,true),Int))) +//│ │ │ │ │ │ @ exprCont(0,`'(' Int, Int, Int, ')'`,false) [at l.608] +//│ │ │ │ │ │ │ ? exprCont inspects || [at l.737] +//│ │ │ │ │ │ = Right('(' Int, Int, Int, ')') +//│ │ │ │ │ = Right('(' Int, Int, Int, ')') +//│ │ │ │ = Right('(' Int, Int, Int, ')') +//│ │ │ │ result => '(' Int, Int, Int, ')' ## Bra(rcd = false, Tup(_: Var(Int), _: Var(Int), _: Var(Int))) +//│ │ │ │ result toType => Right(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) +//│ │ │ = '(' Int, Int, Int, ')' +//│ │ │ asc => '(' 1, 2, ')' : (Int, Int, Int,) +//│ │ = Right('(' 1, 2, ')' : (Int, Int, Int,)) +//│ = Right('(' 1, 2, ')' : (Int, Int, Int,)) +//│ ? yeetSpaces inspects || [at l.515] +//│ ? parseAll inspects || [at l.76] +//│ Parsed: '(' 1, 2, ')' : (Int, Int, Int,); +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.349: [1, 2]: [Int, Int, Int?] +//│ ║ ^^^^^^ +//│ ╟── tuple literal of type `(1, 2,)` does not match type `(Int, Int, Int,)` +//│ ║ l.349: [1, 2]: [Int, Int, Int?] +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from tuple type: +//│ ║ l.349: [1, 2]: [Int, Int, Int?] +//│ ╙── ^^^^^^^^^^^^^^^^ +//│ (Int, Int, Int,) +//│ res +//│ = [ 1, 2 ] From e6e4ae360873b69db7e1110982730abe8b602828 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Tue, 19 Sep 2023 21:22:40 +0800 Subject: [PATCH 07/37] add opt field for FieldType --- .../src/main/scala/mlscript/NuTypeDefs.scala | 18 +-- shared/src/main/scala/mlscript/TypeDefs.scala | 6 +- .../main/scala/mlscript/TypeSimplifier.scala | 24 ++-- shared/src/main/scala/mlscript/Typer.scala | 30 ++-- .../main/scala/mlscript/TyperDatatypes.scala | 16 +-- .../main/scala/mlscript/TyperHelpers.scala | 6 +- shared/src/test/diff/basics/Data.fun | 2 +- shared/src/test/diff/basics/Datatypes.fun | 2 +- shared/src/test/diff/fcp/Church_CT.mls | 130 +++++++++--------- .../src/test/diff/fcp/ConstrainedTypes2.mls | 10 +- shared/src/test/diff/fcp/NestedDataTypes.mls | 8 +- .../test/diff/fcp/QML_exist_Classes_CT.mls | 4 +- shared/src/test/diff/fcp/SystemF_2.mls | 104 +++++++------- .../diff/mlf-examples/ex_casparticuliers.mls | 8 +- shared/src/test/diff/mlf-examples/ex_demo.mls | 16 +-- shared/src/test/diff/typegen/TypegenTerms.mls | 4 +- 16 files changed, 194 insertions(+), 194 deletions(-) diff --git a/shared/src/main/scala/mlscript/NuTypeDefs.scala b/shared/src/main/scala/mlscript/NuTypeDefs.scala index ca3a27082..9cbe9eead 100644 --- a/shared/src/main/scala/mlscript/NuTypeDefs.scala +++ b/shared/src/main/scala/mlscript/NuTypeDefs.scala @@ -167,7 +167,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => lazy val virtualMembers: Map[Str, NuMember] = members ++ tparams.map { case (nme @ TypeName(name), tv, _) => - td.nme.name+"#"+name -> NuParam(nme, FieldType(S(tv), tv)(provTODO))(level) + td.nme.name+"#"+name -> NuParam(nme, FieldType(S(tv), tv, false)(provTODO))(level) } ++ parentTP def freshenAbove(lim: Int, rigidify: Bool) @@ -229,7 +229,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => /** Includes class-name-coded type parameter fields. */ lazy val virtualMembers: Map[Str, NuMember] = members ++ tparams.map { case (nme @ TypeName(name), tv, _) => - td.nme.name+"#"+name -> NuParam(nme, FieldType(S(tv), tv)(provTODO))(level) + td.nme.name+"#"+name -> NuParam(nme, FieldType(S(tv), tv, false)(provTODO))(level) } ++ parentTP // TODO @@ -338,7 +338,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => lazy val virtualMembers: Map[Str, NuMember] = members ++ tparams.map { case (nme @ TypeName(name), tv, _) => - td.nme.name+"#"+name -> NuParam(nme, FieldType(S(tv), tv)(provTODO))(level) + td.nme.name+"#"+name -> NuParam(nme, FieldType(S(tv), tv, false)(provTODO))(level) } def freshenAbove(lim: Int, rigidify: Bool) @@ -677,7 +677,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => val a_ty = typeTerm(a) p.lb.foreach(constrain(_, a_ty)) constrain(a_ty, p.ub) - NuParam(nme, FieldType(p.lb, a_ty)(provTODO))(lvl) + NuParam(nme, FieldType(p.lb, a_ty, false)(provTODO))(lvl) } paramMems //++ mxn.members.valuesIterator @@ -728,7 +728,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => val a_ty = typeTerm(a) p.lb.foreach(constrain(_, a_ty)) constrain(a_ty, p.ub) - NuParam(nme, FieldType(p.lb, a_ty)(provTODO))(lvl) + NuParam(nme, FieldType(p.lb, a_ty, false)(provTODO))(lvl) } S((cls, paramMems, ptp ++ cls.parentTP, p.toLoc)) @@ -813,14 +813,14 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => case R(tpe) => implicit val newDefsInfo: Map[Str, (TypeDefKind, Int)] = Map.empty // TODO? val ty = typeType(tpe) - nme -> FieldType(N, ty)(provTODO) + nme -> FieldType(N, ty, false)(provTODO) case _ => ??? } case (N, Fld(FldFlags(mut, spec, opt), nme: Var)) => // assert(!mut && !spec, "TODO") // TODO // nme -> FieldType(N, freshVar(ttp(nme), N, S(nme.name)))(provTODO) nme -> FieldType(N, err(msg"${td.kind.str.capitalize} parameters currently need type annotations", - nme.toLoc))(provTODO) + nme.toLoc), false)(provTODO) case _ => ??? } case fd: NuFunDef => Nil @@ -1213,7 +1213,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => val tparamMems = tparams.map { case (tp, tv, vi) => // TODO use vi val fldNme = td.nme.name + "#" + tp.name - NuParam(TypeName(fldNme).withLocOf(tp), FieldType(S(tv), tv)(tv.prov))(lvl) + NuParam(TypeName(fldNme).withLocOf(tp), FieldType(S(tv), tv, false)(tv.prov))(lvl) } val tparamFields = tparamMems.map(p => p.nme.toVar -> p.ty) assert(!typedParams.keys.exists(tparamFields.keys.toSet), ???) @@ -1452,7 +1452,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => tv }) freshened += _tv -> tv - rawName+"#"+tn.name -> NuParam(tn, FieldType(S(tv), tv)(provTODO))(ctx.lvl) + rawName+"#"+tn.name -> NuParam(tn, FieldType(S(tv), tv, false)(provTODO))(ctx.lvl) } freshened -> parTP.toMap diff --git a/shared/src/main/scala/mlscript/TypeDefs.scala b/shared/src/main/scala/mlscript/TypeDefs.scala index 1ffc4bb33..41a3905ed 100644 --- a/shared/src/main/scala/mlscript/TypeDefs.scala +++ b/shared/src/main/scala/mlscript/TypeDefs.scala @@ -333,7 +333,7 @@ class TypeDefs extends NuTypeDefs { self: Typer => // * This is not actually necessary for soundness // * (if they aren't, the object type just won't be instantiable), // * but will help report inheritance errors earlier (see test BadInherit2). - case (nme, FieldType(S(lb), ub)) => constrain(lb, ub) + case (nme, FieldType(S(lb), ub, false)) => constrain(lb, ub) case _ => () } (decls -- defns) match { @@ -343,7 +343,7 @@ class TypeDefs extends NuTypeDefs { self: Typer => case _ => val fields = fieldsOf(td.bodyTy, paramTags = true) val tparamTags = td.tparamsargs.map { case (tp, tv) => - tparamField(td.nme, tp) -> FieldType(Some(tv), tv)(tv.prov) } + tparamField(td.nme, tp) -> FieldType(Some(tv), tv, false)(tv.prov) } val ctor = k match { case Cls => val nomTag = clsNameToNomTag(td)(originProv(td.nme.toLoc, "class", td.nme.name), ctx) @@ -354,7 +354,7 @@ class TypeDefs extends NuTypeDefs { self: Typer => S(f._1.name.drop(f._1.name.indexOf('#') + 1)) // strip any "...#" prefix )(1).tap(_.upperBounds ::= f._2.ub) f._1 -> ( - if (f._2.lb.isDefined) FieldType(Some(fv), fv)(f._2.prov) + if (f._2.lb.isDefined) FieldType(Some(fv), fv, false)(f._2.prov) else fv.toUpper(f._2.prov) ) }).toList diff --git a/shared/src/main/scala/mlscript/TypeSimplifier.scala b/shared/src/main/scala/mlscript/TypeSimplifier.scala index bb88bfa12..4c7ea6e27 100644 --- a/shared/src/main/scala/mlscript/TypeSimplifier.scala +++ b/shared/src/main/scala/mlscript/TypeSimplifier.scala @@ -106,8 +106,8 @@ trait TypeSimplifier { self: Typer => tvv(td.tparamsargs.find(_._1.name === postfix).getOrElse(die)._2) match { case VarianceInfo(true, true) => Nil case VarianceInfo(co, contra) => - if (co) v -> FieldType(S(BotType), process(fty.ub, N))(fty.prov) :: Nil - else if (contra) v -> FieldType(fty.lb.map(process(_, N)), TopType)(fty.prov) :: Nil + if (co) v -> FieldType(S(BotType), process(fty.ub, N), false)(fty.prov) :: Nil + else if (contra) v -> FieldType(fty.lb.map(process(_, N)), TopType, false)(fty.prov) :: Nil else v -> default :: Nil }) case N => @@ -119,8 +119,8 @@ trait TypeSimplifier { self: Typer => cls.varianceOf(cls.tparams.find(_._1.name === postfix).getOrElse(die)._2) match { case VarianceInfo(true, true) => Nil case VarianceInfo(co, contra) => - if (co) v -> FieldType(S(BotType), process(fty.ub, N))(fty.prov) :: Nil - else if (contra) v -> FieldType(fty.lb.map(process(_, N)), TopType)(fty.prov) :: Nil + if (co) v -> FieldType(S(BotType), process(fty.ub, N), false)(fty.prov) :: Nil + else if (contra) v -> FieldType(fty.lb.map(process(_, N)), TopType, false)(fty.prov) :: Nil else v -> default :: Nil } case S(_) => ??? // TODO: @@ -238,10 +238,10 @@ trait TypeSimplifier { self: Typer => // * Reconstruct a TypeRef from its current structural components val typeRef = TypeRef(td.nme, td.tparamsargs.zipWithIndex.map { case ((tp, tv), tpidx) => val fieldTagNme = tparamField(clsTyNme, tp) - val fromTyRef = trs2.get(clsTyNme).map(_.targs(tpidx) |> { ta => FieldType(S(ta), ta)(noProv) }) + val fromTyRef = trs2.get(clsTyNme).map(_.targs(tpidx) |> { ta => FieldType(S(ta), ta, false)(noProv) }) fromTyRef.++(rcd2.fields.iterator.filter(_._1 === fieldTagNme).map(_._2)) .foldLeft((BotType: ST, TopType: ST)) { - case ((acc_lb, acc_ub), FieldType(lb, ub)) => + case ((acc_lb, acc_ub), FieldType(lb, ub, _)) => (acc_lb | lb.getOrElse(BotType), acc_ub & ub) }.pipe { case (lb, ub) => @@ -348,10 +348,10 @@ trait TypeSimplifier { self: Typer => // * Reconstruct a TypeRef from its current structural components val typeRef = TypeRef(cls.td.nme, cls.tparams.zipWithIndex.map { case ((tp, tv, vi), tpidx) => val fieldTagNme = tparamField(clsTyNme, tp) - val fromTyRef = trs2.get(clsTyNme).map(_.targs(tpidx) |> { ta => FieldType(S(ta), ta)(noProv) }) + val fromTyRef = trs2.get(clsTyNme).map(_.targs(tpidx) |> { ta => FieldType(S(ta), ta, false)(noProv) }) fromTyRef.++(rcd2.fields.iterator.filter(_._1 === fieldTagNme).map(_._2)) .foldLeft((BotType: ST, TopType: ST)) { - case ((acc_lb, acc_ub), FieldType(lb, ub)) => + case ((acc_lb, acc_ub), FieldType(lb, ub, _)) => (acc_lb | lb.getOrElse(BotType), acc_ub & ub) }.pipe { case (lb, ub) => @@ -936,9 +936,9 @@ trait TypeSimplifier { self: Typer => def transform(st: SimpleType, pol: PolMap, parents: Set[TV], canDistribForall: Opt[Level] = N): SimpleType = trace(s"transform[${printPol(pol)}] $st (${parents.mkString(", ")}) $pol $canDistribForall") { def transformField(f: FieldType): FieldType = f match { - case FieldType(S(lb), ub) if lb === ub => + case FieldType(S(lb), ub, _) if lb === ub => val b = transform(ub, pol.invar, semp) - FieldType(S(b), b)(f.prov) + FieldType(S(b), b, false)(f.prov) case _ => f.update(transform(_, pol.contravar, semp), transform(_, pol, semp)) } st match { @@ -1200,8 +1200,8 @@ trait TypeSimplifier { self: Typer => def nope: false = { println(s"Nope(${ty1.getClass.getSimpleName}): $ty1 ~ $ty2"); false } def unifyF(f1: FieldType, f2: FieldType): Bool = (f1, f2) match { - case (FieldType(S(l1), u1), FieldType(S(l2), u2)) => unify(l1, l2) && unify(u1, u2) - case (FieldType(N, u1), FieldType(N, u2)) => unify(u1, u2) + case (FieldType(S(l1), u1, _), FieldType(S(l2), u2, _)) => unify(l1, l2) && unify(u1, u2) + case (FieldType(N, u1, _), FieldType(N, u2, _)) => unify(u1, u2) case _ => nope } diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index 0a11e93c6..a11efc991 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -253,7 +253,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne { val tv = freshVar(noTyProv, N)(1) val tyDef = TypeDef(Als, TN("Array"), List(TN("A") -> tv), - ArrayType(FieldType(None, tv)(noTyProv))(noTyProv), Nil, Nil, semp, N, Nil) + ArrayType(FieldType(None, tv, false)(noTyProv))(noTyProv), Nil, Nil, semp, N, Nil) // * ^ Note that the `noTyProv` here is kind of a problem // * since we currently expand primitive types eagerly in DNFs. // * For instance, see `inn2 v1` in test `Yicong.mls`. @@ -266,7 +266,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne { val tv = freshVar(noTyProv, N)(1) val tyDef = TypeDef(Als, TN("MutArray"), List(TN("A") -> tv), - ArrayType(FieldType(Some(tv), tv)(noTyProv))(noTyProv), Nil, Nil, semp, N, Nil) + ArrayType(FieldType(Some(tv), tv, false)(noTyProv))(noTyProv), Nil, Nil, semp, N, Nil) tyDef.tvarVariances = S(MutMap(tv -> VarianceInfo.in)) tyDef } :: @@ -352,7 +352,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne }, "emptyArray" -> { val v = freshVar(noProv, N)(1) - PolymorphicType(0, ArrayType(FieldType(S(v), v)(noProv))(noProv)) + PolymorphicType(0, ArrayType(FieldType(S(v), v, false)(noProv))(noProv)) }, ) ++ primTypes ++ primTypes.map(p => "" + p._1.capitalize -> p._2) // TODO settle on naming convention... } @@ -426,7 +426,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne TypeBounds(lb_ty, ub_ty)(prov) case Tuple(fields) => TupleType(fields.mapValues(f => - FieldType(f.in.map(rec), rec(f.out))(tp(f.toLoc, "tuple field")) + FieldType(f.in.map(rec), rec(f.out), false)(tp(f.toLoc, "tuple field")) ))(tyTp(ty.toLoc, "tuple type")) case Splice(fields) => SpliceType(fields.map{ @@ -437,7 +437,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne L(t) } case R(f) => { - R(FieldType(f.in.map(rec), rec(f.out))(tp(f.toLoc, "splice field"))) + R(FieldType(f.in.map(rec), rec(f.out), false)(tp(f.toLoc, "splice field"))) } })(tyTp(ty.toLoc, "splice type")) case Inter(lhs, rhs) => (if (simplify) rec(lhs) & (rec(rhs), _: TypeProvenance) @@ -457,14 +457,14 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne RecordType.mk(fs.map { nt => if (nt._1.name.isCapitalized) err(msg"Field identifiers must start with a small letter", nt._1.toLoc)(raise) - nt._1 -> FieldType(nt._2.in.map(rec), rec(nt._2.out))( + nt._1 -> FieldType(nt._2.in.map(rec), rec(nt._2.out), false)( tp(App(nt._1, Var("").withLocOf(nt._2)).toCoveringLoc, (if (nt._2.in.isDefined) "mutable " else "") + "record field")) })(prov) case Function(lhs, rhs) => FunctionType(rec(lhs), rec(rhs))(tyTp(ty.toLoc, "function type")) case WithExtension(b, r) => WithType(rec(b), RecordType( - r.fields.map { case (n, f) => n -> FieldType(f.in.map(rec), rec(f.out))( + r.fields.map { case (n, f) => n -> FieldType(f.in.map(rec), rec(f.out), false)( tyTp(App(n, Var("").withLocOf(f)).toCoveringLoc, "extension field")) } )(tyTp(r.toLoc, "extension record")))(tyTp(ty.toLoc, "extension type")) case Literal(lit) => @@ -882,7 +882,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne if (mut) { val res = freshVar(fprov, N, S(n.name)) val rs = con(tym, res, res) - (n, FieldType(Some(rs), rs)(fprov)) + (n, FieldType(Some(rs), rs, false)(fprov)) } else (n, tym.toUpper(fprov)) })(prov) case tup: Tup if funkyTuples => @@ -903,7 +903,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne if (mut) { val res = freshVar(fprov, N, n.map(_.name)) val rs = con(tym, res, res) - (n, FieldType(Some(rs), rs)(fprov)) + (n, FieldType(Some(rs), rs, false)(fprov)) } else (n, tym.toUpper(fprov)) })(fs match { case Nil | ((N, _) :: Nil) => noProv // TODO rm? @@ -930,7 +930,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne val obj_ty = // Note: this proxy does not seem to make any difference: mkProxy(o_ty, tp(r.toCoveringLoc, "receiver")) - con(obj_ty, RecordType.mk((f, FieldType(Some(fieldType), TopType)( + con(obj_ty, RecordType.mk((f, FieldType(Some(fieldType), TopType, false)( tp(f.toLoc, "assigned field") )) :: Nil)(sprov), fieldType) val vl = typeMonomorphicTerm(rhs) @@ -942,7 +942,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne val arr_ty = // Note: this proxy does not seem to make any difference: mkProxy(a_ty, tp(a.toCoveringLoc, "receiver")) - con(arr_ty, ArrayType(FieldType(Some(elemType), elemType)(sprov))(prov), TopType) + con(arr_ty, ArrayType(FieldType(Some(elemType), elemType, false)(sprov))(prov), TopType) val i_ty = typeMonomorphicTerm(i) con(i_ty, IntType, TopType) val vl = typeMonomorphicTerm(rhs) @@ -959,7 +959,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne }) case R(Fld(FldFlags(mt, sp, op), r)) => { val t = typeMonomorphicTerm(r) - if (mt) { R(FieldType(Some(t), t)(t.prov)) } else {R(t.toUpper(t.prov))} + if (mt) { R(FieldType(Some(t), t, false)(t.prov)) } else {R(t.toUpper(t.prov))} } })(prov) case Bra(false, trm: Blk) => typeTerm(trm) @@ -1192,7 +1192,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne fs.map(_ => freshVar(noProv, N)) // ) - val fld_ty = tupArgs.map(elem => N -> FieldType(N, elem)(elem.prov)) + val fld_ty = tupArgs.map(elem => N -> FieldType(N, elem, false)(elem.prov)) val caseAdtTyp = TypeProvenance(tup.toLoc, "pattern") val adt_ty = TupleType(fld_ty)(caseAdtTyp) .withProv(TypeProvenance(cond.toLoc, "match `condition`")) @@ -1492,7 +1492,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne val seenVars = mutable.Set.empty[TV] def field(ft: FieldType)(implicit ectx: ExpCtx): Field = ft match { - case FieldType(S(l: TV), u: TV) if l === u => + case FieldType(S(l: TV), u: TV, _) if l === u => val res = go(u) Field(S(res), res, false) // TODO improve Field case f => @@ -1596,7 +1596,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne case ComposedType(false, l, r) => Inter(go(l), go(r)) case RecordType(fs) => Record(fs.mapValues(field)) case TupleType(fs) => Tuple(fs.mapValues(field)) - case ArrayType(FieldType(None, ub)) => AppliedType(TypeName("Array"), go(ub) :: Nil) + case ArrayType(FieldType(None, ub, _)) => AppliedType(TypeName("Array"), go(ub) :: Nil) case ArrayType(f) => val f2 = field(f) AppliedType(TypeName("MutArray"), Bounds(f2.in.getOrElse(Bot), f2.out) :: Nil) diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala index 23bdf851a..00cfa7575 100644 --- a/shared/src/main/scala/mlscript/TyperDatatypes.scala +++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala @@ -472,18 +472,18 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => } } - case class FieldType(lb: Option[SimpleType], ub: SimpleType)(val prov: TypeProvenance) { + case class FieldType(lb: Option[SimpleType], ub: SimpleType, opt: Boolean)(val prov: TypeProvenance) { def level: Int = lb.map(_.level).getOrElse(ub.level) max ub.level def levelBelow(ubLvl: Level)(implicit cache: MutSet[TV]): Level = lb.fold(MinLevel)(_.levelBelow(ubLvl)) max ub.levelBelow(ubLvl) def <:< (that: FieldType)(implicit ctx: Ctx, cache: MutMap[ST -> ST, Bool] = MutMap.empty): Bool = (that.lb.getOrElse(BotType) <:< this.lb.getOrElse(BotType)) && (this.ub <:< that.ub) def && (that: FieldType, prov: TypeProvenance = noProv): FieldType = - FieldType(lb.fold(that.lb)(l => Some(that.lb.fold(l)(l | _))), ub & that.ub)(prov) + FieldType(lb.fold(that.lb)(l => Some(that.lb.fold(l)(l | _))), ub & that.ub, false)(prov) def || (that: FieldType, prov: TypeProvenance = noProv): FieldType = - FieldType(for {l <- lb; r <- that.lb} yield (l & r), ub | that.ub)(prov) + FieldType(for {l <- lb; r <- that.lb} yield (l & r), ub | that.ub, false)(prov) def update(lb: SimpleType => SimpleType, ub: SimpleType => SimpleType): FieldType = - FieldType(this.lb.map(lb), ub(this.ub))(prov) + FieldType(this.lb.map(lb), ub(this.ub), false)(prov) def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): FieldType = update(_.freshenAbove(lim, rigidify), _.freshenAbove(lim, rigidify)) override def toString = @@ -491,10 +491,10 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => } object FieldType { def mk(vi: VarianceInfo, lb: ST, ub: ST)(prov: TP): FieldType = vi match { - case VarianceInfo(true, true) => FieldType(N, TopType)(prov) - case VarianceInfo(true, false) => FieldType(N, ub)(prov) - case VarianceInfo(false, true) => FieldType(S(lb), TopType)(prov) - case VarianceInfo(false, false) => FieldType(S(lb), ub)(prov) + case VarianceInfo(true, true) => FieldType(N, TopType, false)(prov) + case VarianceInfo(true, false) => FieldType(N, ub, false)(prov) + case VarianceInfo(false, true) => FieldType(S(lb), TopType, false)(prov) + case VarianceInfo(false, false) => FieldType(S(lb), ub, false)(prov) } } diff --git a/shared/src/main/scala/mlscript/TyperHelpers.scala b/shared/src/main/scala/mlscript/TyperHelpers.scala index 21edc1b25..fcfba6562 100644 --- a/shared/src/main/scala/mlscript/TyperHelpers.scala +++ b/shared/src/main/scala/mlscript/TyperHelpers.scala @@ -374,8 +374,8 @@ abstract class TyperHelpers { Typer: Typer => case _: TypeVariable | _: TypeTag | _: ExtrType => this } - def toUpper(prov: TypeProvenance): FieldType = FieldType(None, this)(prov) - def toLower(prov: TypeProvenance): FieldType = FieldType(Some(this), TopType)(prov) + def toUpper(prov: TypeProvenance): FieldType = FieldType(None, this, false)(prov) + def toLower(prov: TypeProvenance): FieldType = FieldType(Some(this), TopType, false)(prov) def | (that: SimpleType, prov: TypeProvenance = noProv, swapped: Bool = false): SimpleType = (this, that) match { case (TopType, _) => this @@ -1158,7 +1158,7 @@ abstract class TyperHelpers { Typer: Typer => val tvv = td.getVariancesOrDefault tparamField(defn, tp) -> FieldType( Some(if (tvv(tv).isCovariant) BotType else tv), - if (tvv(tv).isContravariant) TopType else tv)(prov) + if (tvv(tv).isContravariant) TopType else tv, false)(prov) })(noProv) else TopType subst(td.kind match { diff --git a/shared/src/test/diff/basics/Data.fun b/shared/src/test/diff/basics/Data.fun index a8279c9e1..95dce1e25 100644 --- a/shared/src/test/diff/basics/Data.fun +++ b/shared/src/test/diff/basics/Data.fun @@ -13,7 +13,7 @@ data Person(name: string, age: int) //│ Parsed: data Person '(' {name: string, age: int,} ')'; //│ Desugared: class Person: {age: int, name: string} //│ Desugared: def Person: (name: string, age: int,) -> Person[] -//│ AST: Def(false, Person, PolyType(List(),Function(Tuple(List((Some(name),Field(None,TypeName(string))), (Some(age),Field(None,TypeName(int))))),AppliedType(TypeName(Person),List()))), true) +//│ AST: Def(false, Person, PolyType(List(),Function(Tuple(List((Some(name),Field(None,TypeName(string),false)), (Some(age),Field(None,TypeName(int),false)))),AppliedType(TypeName(Person),List()))), true) //│ Defined class Person //│ Person: (name: string, age: int,) -> Person diff --git a/shared/src/test/diff/basics/Datatypes.fun b/shared/src/test/diff/basics/Datatypes.fun index 32d443036..4646eea51 100644 --- a/shared/src/test/diff/basics/Datatypes.fun +++ b/shared/src/test/diff/basics/Datatypes.fun @@ -120,7 +120,7 @@ data type List a of //│ 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) +//│ AST: Def(false, Cons, PolyType(List(Left(TypeName(a))),Function(Tuple(List((Some(head),Field(None,TypeName(a),false)))),Function(Tuple(List((Some(tail),Field(None,AppliedType(TypeName(List),List(TypeName(a))),false)))),AppliedType(TypeName(Cons),List(TypeName(a)))))), true) //│ Defined type alias List[+a] //│ Defined class Nil[±a] //│ Defined class Cons[+a] diff --git a/shared/src/test/diff/fcp/Church_CT.mls b/shared/src/test/diff/fcp/Church_CT.mls index 1f279fcf2..55907289c 100644 --- a/shared/src/test/diff/fcp/Church_CT.mls +++ b/shared/src/test/diff/fcp/Church_CT.mls @@ -39,8 +39,8 @@ def succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M def succ n f x = f (n f x) //│ 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'd -> 'c //│ where -//│ 'a <: 'b -> 'd -> 'e -//│ 'b <: 'e -> 'c)) +//│ 'b <: 'e -> 'c +//│ 'a <: 'b -> 'd -> 'e)) //│ <: succ: //│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M) //│ ╔══[ERROR] Type error in def definition @@ -69,8 +69,8 @@ def succ: ChurchInt -> ChurchInt def succ n f x = f (n f x) //│ 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'e -> 'd //│ where -//│ 'b <: 'c -> 'd -//│ 'a <: 'b -> 'e -> 'c)) +//│ 'a <: 'b -> 'e -> 'c +//│ 'b <: 'c -> 'd)) //│ <: succ: //│ ChurchInt -> ChurchInt //│ ╔══[ERROR] Type error in def definition @@ -340,8 +340,8 @@ zero = z succ = s //│ 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e //│ where -//│ 'b <: 'd -> 'e -//│ 'a <: 'b -> 'c -> 'd)) +//│ 'a <: 'b -> 'c -> 'd +//│ 'b <: 'd -> 'e)) //│ <: succ: //│ ChurchInt -> ChurchInt //│ ╔══[ERROR] Type error in def definition @@ -410,24 +410,24 @@ n1 = s z n2 = s (s z) //│ n2: 'a -> (forall 'b 'c 'd. 'b -> 'd //│ where -//│ 'a <: 'c -> 'd //│ forall 'e. 'e -> (forall 'f 'g 'h. 'f -> 'h //│ where //│ anything -> (forall 'i. 'i -> 'i) <: 'e -> 'f -> 'g -//│ 'e <: 'g -> 'h) <: 'a -> 'b -> 'c) +//│ 'e <: 'g -> 'h) <: 'a -> 'b -> 'c +//│ 'a <: 'c -> 'd) //│ = [Function (anonymous)] n3 = s (s (s z)) //│ n3: 'a -> (forall 'b 'c 'd. 'c -> 'b //│ where +//│ 'a <: 'd -> 'b //│ forall 'e. 'e -> (forall 'f 'g 'h. 'f -> 'h //│ where +//│ 'e <: 'g -> 'h //│ forall 'i. 'i -> (forall 'j 'k 'l. 'j -> 'l //│ where -//│ 'i <: 'k -> 'l -//│ anything -> (forall 'm. 'm -> 'm) <: 'i -> 'j -> 'k) <: 'e -> 'f -> 'g -//│ 'e <: 'g -> 'h) <: 'a -> 'c -> 'd -//│ 'a <: 'd -> 'b) +//│ anything -> (forall 'm. 'm -> 'm) <: 'i -> 'j -> 'k +//│ 'i <: 'k -> 'l) <: 'e -> 'f -> 'g) <: 'a -> 'c -> 'd) //│ = [Function (anonymous)] @@ -438,8 +438,8 @@ wrap x = { x } n1w = n1 wrap //│ n1w: 'a -> 'b //│ where -//│ anything -> (forall 'c. 'c -> 'c) <: (forall 'd. 'd -> {x: 'd}) -> 'a -> 'e -//│ forall 'd. 'd -> {x: 'd} <: 'e -> 'b +//│ forall 'c. 'c -> {x: 'c} <: 'd -> 'b +//│ anything -> (forall 'e. 'e -> 'e) <: (forall 'c. 'c -> {x: 'c}) -> 'a -> 'd //│ = [Function (anonymous)] n1w 0 @@ -484,8 +484,8 @@ wrap_ty = wrap n1w = n1 wrap_ty //│ n1w: 'b -> 'c //│ where -//│ forall 'a. 'a -> {x: 'a} <: 'd -> 'c -//│ anything -> (forall 'e. 'e -> 'e) <: (forall 'a. 'a -> {x: 'a}) -> 'b -> 'd +//│ anything -> (forall 'd. 'd -> 'd) <: (forall 'a. 'a -> {x: 'a}) -> 'b -> 'e +//│ forall 'a. 'a -> {x: 'a} <: 'e -> 'c //│ = [Function (anonymous)] n1w 0 @@ -520,8 +520,8 @@ res.x.x.x + 1 sz = s zero //│ sz: 'a -> (forall 'b 'c 'd. 'd -> 'c //│ where -//│ ChurchInt <: 'a -> 'd -> 'b -//│ 'a <: 'b -> 'c) +//│ 'a <: 'b -> 'c +//│ ChurchInt <: 'a -> 'd -> 'b) //│ = [Function (anonymous)] :ns @@ -559,8 +559,8 @@ s zero : ChurchInt sz1 = sz 1 //│ sz1: 'a -> 'b //│ where -//│ ChurchInt <: 1 -> 'a -> 'c //│ 1 <: 'c -> 'b +//│ ChurchInt <: 1 -> 'a -> 'c //│ = [Function (anonymous)] :ns @@ -569,11 +569,11 @@ sz1 //│ where //│ 'b :> forall 'd 'e 'f 'g. 'e -> 'g //│ where -//│ 'a <: 'f -> 'g //│ 'c <: 'a -> 'd +//│ 'a <: 'f -> 'g //│ 'd <: 'e -> 'f -//│ 'c :> ChurchInt //│ 'a :> 1 +//│ 'c :> ChurchInt //│ = [Function (anonymous)] :e // * Since inconsistent constrained types (delayed error from above) @@ -633,15 +633,15 @@ rec def to_ch_s n = //│ where //│ 'a :> forall 'b. (? & 'b) -> (forall 'b 'c 'd 'e 'f. ('c & 'f) -> ('c | 'e) //│ where -//│ 'b <: 'd -> 'e -//│ 'a <: 'b -> 'f -> 'd) +//│ 'a <: 'b -> 'f -> 'd +//│ 'b <: 'd -> 'e) //│ ╙── //│ to_ch_s: int -> 'a //│ where //│ 'a :> forall 'b. 'b -> (forall 'c 'b 'd 'e 'f. ('d & 'c) -> ('d | 'e) //│ where -//│ 'b <: 'f -> 'e -//│ 'a <: 'b -> 'c -> 'f) +//│ 'a <: 'b -> 'c -> 'f +//│ 'b <: 'f -> 'e) //│ = [Function: to_ch_s] :e @@ -652,15 +652,15 @@ rec def to_ch n = //│ where //│ 'a :> forall 'b. (? & 'b) -> (forall 'c 'd 'e 'b 'f. ('f & 'e) -> ('f | 'c) //│ where -//│ 'a <: 'b -> 'e -> 'd -//│ 'b <: 'd -> 'c) +//│ 'b <: 'd -> 'c +//│ 'a <: 'b -> 'e -> 'd) //│ ╙── //│ to_ch: int -> 'a //│ where //│ 'a :> forall 'b. 'b -> (forall 'c 'd 'b 'e 'f. ('c & 'f) -> ('c | 'd) //│ where -//│ 'a <: 'b -> 'f -> 'e -//│ 'b <: 'e -> 'd) +//│ 'b <: 'e -> 'd +//│ 'a <: 'b -> 'f -> 'e) //│ = [Function: to_ch] :e // * Needs distrib (see below) @@ -692,15 +692,15 @@ rec def to_ch_simplif n = s (to_ch_simplif n) //│ where //│ 'a :> forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e //│ where -//│ 'a <: 'b -> 'c -> 'd -//│ 'b <: 'd -> 'e) +//│ 'b <: 'd -> 'e +//│ 'a <: 'b -> 'c -> 'd) //│ ╙── //│ to_ch_simplif: anything -> 'a //│ where //│ 'a :> forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e //│ where -//│ 'a <: 'b -> 'c -> 'd -//│ 'b <: 'd -> 'e) +//│ 'b <: 'd -> 'e +//│ 'a <: 'b -> 'c -> 'd) //│ = [Function: to_ch_simplif] :e @@ -716,8 +716,8 @@ to_church_ty = to_ch_simplif //│ where //│ 'a :> forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e //│ where -//│ 'a <: 'b -> 'c -> 'd -//│ 'b <: 'd -> 'e) +//│ 'b <: 'd -> 'e +//│ 'a <: 'b -> 'c -> 'd) //│ <: to_church_ty: //│ int -> ChurchInt //│ ╔══[ERROR] Subtyping constraint of the form `forall ?to_ch_simplif. ?to_ch_simplif <: int -> ChurchInt` exceeded recursion depth limit (250) @@ -792,8 +792,8 @@ rec def to_ch_A1 n = //│ ╙── ^^^^^ //│ to_ch_A1: int -> (forall 'a. 'a -> (forall 'b 'a 'c 'd 'e. ('b & 'c) -> ('c | 'd) //│ where -//│ ChurchInt <: 'a -> 'b -> 'e -//│ 'a <: 'e -> 'd)) +//│ 'a <: 'e -> 'd +//│ ChurchInt <: 'a -> 'b -> 'e)) //│ = [Function: to_ch_A1] :precise-rec-typing @@ -814,8 +814,8 @@ rec def to_ch_A1 n = //│ where //│ 'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('b & 'c) -> ('c | 'd) //│ where -//│ 'a <: 'e -> 'd -//│ ChurchInt <: 'a -> 'b -> 'e)) +//│ ChurchInt <: 'a -> 'b -> 'e +//│ 'a <: 'e -> 'd)) //│ where //│ 'to_ch_A1 <: int -> ChurchInt //│ = [Function: to_ch_A11] @@ -836,8 +836,8 @@ to_church_ty = to_ch_A1 //│ where //│ 'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('e & 'b) -> ('b | 'c) //│ where -//│ ChurchInt <: 'a -> 'e -> 'd -//│ 'a <: 'd -> 'c)) +//│ 'a <: 'd -> 'c +//│ ChurchInt <: 'a -> 'e -> 'd)) //│ where //│ 'to_ch_A1 <: int -> ChurchInt //│ <: to_church_ty: @@ -970,8 +970,8 @@ def to_church_mix n = else s (to_church (n - 1)) //│ to_church_mix: int -> (forall 'a. 'a -> (forall 'b 'c 'a 'd 'e. ('e & 'd) -> ('d | 'c) //│ where -//│ 'a <: 'b -> 'c -//│ ChurchInt <: 'a -> 'e -> 'b)) +//│ ChurchInt <: 'a -> 'e -> 'b +//│ 'a <: 'b -> 'c)) //│ = [Function: to_church_mix] :e @@ -1037,8 +1037,8 @@ rec def to_chD n = succ = s //│ 'a -> 'b -> ('c -> 'd //│ where -//│ 'b <: 'e -> 'd -//│ 'a <: 'b -> 'c -> 'e) +//│ 'a <: 'b -> 'c -> 'e +//│ 'b <: 'e -> 'd) //│ <: succ: //│ ChurchInt -> ChurchInt //│ = [Function: s] @@ -1062,18 +1062,18 @@ to_church_ty = to_ch //│ where //│ 'a :> forall 'b 'c 'd 'e 'f. (? & 'c) -> (('d & 'b) -> ('d | 'e) //│ where -//│ 'a <: 'c -> 'b -> 'f -//│ 'c <: 'f -> 'e) +//│ 'c <: 'f -> 'e +//│ 'a <: 'c -> 'b -> 'f) //│ ╙── //│ int -> 'a -> ('b -> ('b | 'c) //│ where -//│ 'd <: 'a -> 'b -> 'e -//│ 'a <: 'e -> 'c) +//│ 'a <: 'd -> 'c +//│ 'e <: 'a -> 'b -> 'd) //│ where -//│ 'd :> forall 'f 'g 'h 'i 'j. 'f -> (('i & 'j) -> ('i | 'g) +//│ 'e :> forall 'f 'g 'h 'i 'j. 'f -> (('i & 'j) -> ('i | 'g) //│ where //│ 'f <: 'h -> 'g -//│ 'd <: 'f -> 'j -> 'h) +//│ 'e <: 'f -> 'j -> 'h) //│ <: to_church_ty: //│ int -> ChurchInt //│ ╔══[ERROR] Subtyping constraint of the form `forall ?to_ch. ?to_ch <: int -> ChurchInt` exceeded recursion depth limit (250) @@ -1088,8 +1088,8 @@ to_church_ty = to_ch_simplif //│ where //│ 'a :> forall 'b 'c 'd 'e. 'b -> ('c -> 'e //│ where -//│ 'a <: 'b -> 'c -> 'd -//│ 'b <: 'd -> 'e) +//│ 'b <: 'd -> 'e +//│ 'a <: 'b -> 'c -> 'd) //│ ╙── //│ anything -> 'a -> ('b -> 'c //│ where @@ -1098,8 +1098,8 @@ to_church_ty = to_ch_simplif //│ where //│ 'e :> forall 'f 'g 'h 'i. 'f -> ('g -> 'i //│ where -//│ 'f <: 'h -> 'i -//│ 'e <: 'f -> 'g -> 'h) +//│ 'e <: 'f -> 'g -> 'h +//│ 'f <: 'h -> 'i) //│ <: to_church_ty: //│ int -> ChurchInt //│ ╔══[ERROR] Subtyping constraint of the form `forall ?to_ch_simplif. ?to_ch_simplif <: int -> ChurchInt` exceeded recursion depth limit (250) @@ -1120,13 +1120,13 @@ rec def to_ch_simplif n = s (to_ch_simplif n) //│ ╙── //│ to_ch_simplif: anything -> 'a -> ('b -> 'c //│ where -//│ 'd <: 'a -> 'b -> 'e -//│ 'a <: 'e -> 'c) +//│ 'a <: 'd -> 'c +//│ 'e <: 'a -> 'b -> 'd) //│ where -//│ 'd :> forall 'f 'g 'h 'i. 'f -> ('g -> 'i +//│ 'e :> forall 'f 'g 'h 'i. 'f -> ('g -> 'i //│ where //│ 'f <: 'h -> 'i -//│ 'd <: 'f -> 'g -> 'h) +//│ 'e <: 'f -> 'g -> 'h) //│ = [Function: to_ch_simplif1] :e // * Since the removal of "recursive definition hacks" @@ -1135,8 +1135,8 @@ to_church_ty = to_ch_simplif //│ where //│ 'a :> forall 'b 'c 'd 'e. 'b -> ('c -> 'e //│ where -//│ 'b <: 'd -> 'e -//│ 'a <: 'b -> 'c -> 'd) +//│ 'a <: 'b -> 'c -> 'd +//│ 'b <: 'd -> 'e) //│ ╙── //│ anything -> 'a -> ('b -> 'c //│ where @@ -1162,8 +1162,8 @@ to_church_ty = to_ch_A1 //│ where //│ 'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a 'b 'c 'd 'e. (? & 'e) -> (('a & 'c) -> ('c | 'd) //│ where -//│ ChurchInt <: 'e -> 'a -> 'b -//│ 'e <: 'b -> 'd)) +//│ 'e <: 'b -> 'd +//│ ChurchInt <: 'e -> 'a -> 'b)) //│ where //│ 'to_ch_A1 <: int -> ChurchInt //│ ╙── @@ -1187,8 +1187,8 @@ to_church_ty = to_ch_A1 to_church_ty = to_church_mix //│ int -> 'a -> ('b -> ('b | 'c) //│ where -//│ 'a <: 'd -> 'c -//│ ChurchInt <: 'a -> 'b -> 'd) +//│ ChurchInt <: 'a -> 'b -> 'd +//│ 'a <: 'd -> 'c) //│ <: to_church_ty: //│ int -> ChurchInt //│ = [Function: to_church_mix] diff --git a/shared/src/test/diff/fcp/ConstrainedTypes2.mls b/shared/src/test/diff/fcp/ConstrainedTypes2.mls index acdf742ce..e4a633763 100644 --- a/shared/src/test/diff/fcp/ConstrainedTypes2.mls +++ b/shared/src/test/diff/fcp/ConstrainedTypes2.mls @@ -128,8 +128,8 @@ test 0 //│ ╙── ^^^^^^ //│ res: error | 'a -> (anything -> 'b //│ where -//│ 'a <: 'c -> 'b -//│ 0 <: 0 -> 'c) +//│ 0 <: 0 -> 'c +//│ 'a <: 'c -> 'b) //│ = [Function (anonymous)] def test extr x = @@ -137,16 +137,16 @@ def test extr x = in f 0 //│ test: anything -> 'a -> (anything -> 'b //│ where -//│ 'a <: 'c -> 'b -//│ 0 <: 0 -> 'c) +//│ 0 <: 0 -> 'c +//│ 'a <: 'c -> 'b) //│ = [Function: test2] // Error delayed by inconsistent constrained types test 0 1 //│ res: anything -> 'a //│ where -//│ 0 <: 0 -> 'b //│ 1 <: 'b -> 'a +//│ 0 <: 0 -> 'b //│ = [Function (anonymous)] :e diff --git a/shared/src/test/diff/fcp/NestedDataTypes.mls b/shared/src/test/diff/fcp/NestedDataTypes.mls index 57cf354a8..20a46fb88 100644 --- a/shared/src/test/diff/fcp/NestedDataTypes.mls +++ b/shared/src/test/diff/fcp/NestedDataTypes.mls @@ -238,19 +238,19 @@ rec def map f tree = case tree of { //│ where //│ 'map :> forall 'A 'subTree 'value 'value0 'a 'subTree0. 'a -> ((Leaf[?] & {value: 'value} | (Node[?] with {subTree: 'subTree0})) -> (Leaf['value0] | (Node['A] with {subTree: 'subTree})) //│ where +//│ 'a <: 'value -> 'value0 //│ 'map <: (forall 'b 'c 'd 'e. ('b, 'd,) -> ('c, 'e,) //│ where -//│ 'a <: 'b -> 'c & 'd -> 'e) -> 'subTree0 -> (PerfectTree[Two['A]] & 'subTree) -//│ 'a <: 'value -> 'value0) +//│ 'a <: 'b -> 'c & 'd -> 'e) -> 'subTree0 -> (PerfectTree[Two['A]] & 'subTree)) //│ ╙── //│ map: 'map //│ where //│ 'map :> forall 'subTree 'value 'value0 'subTree0 'a 'A. 'a -> ((Leaf[?] & {value: 'value} | (Node[?] with {subTree: 'subTree0})) -> (Leaf['value0] | (Node['A] with {subTree: 'subTree})) //│ where +//│ 'a <: 'value -> 'value0 //│ 'map <: (forall 'b 'c 'd 'e. ('b, 'd,) -> ('c, 'e,) //│ where -//│ 'a <: 'b -> 'c & 'd -> 'e) -> 'subTree0 -> (PerfectTree[Two['A]] & 'subTree) -//│ 'a <: 'value -> 'value0) +//│ 'a <: 'b -> 'c & 'd -> 'e) -> 'subTree0 -> (PerfectTree[Two['A]] & 'subTree)) //│ = [Function: map1] :e diff --git a/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls b/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls index b6689a9b0..454f22488 100644 --- a/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls +++ b/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls @@ -182,8 +182,8 @@ def simpleStep arr f = f (simpleStepImpl2 arr) //│ where //│ 'a <: (forall 'A 'e 'f 'Rep. (ArraysRep['A, 'e] & 'f) -> (ArraysImpl['A, 'Rep] with {fold: forall 'g 'b 'A0 'Rep0. 'g -> 'b -> (('Rep0, anything,) -> 'b //│ where -//│ 'f <: ArraysRep['A0, 'Rep0] -//│ 'g <: 'A0 -> 'b -> 'b), init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) +//│ 'g <: 'A0 -> 'b -> 'b +//│ 'f <: ArraysRep['A0, 'Rep0]), init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) //│ where //│ 'f <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. ('Rep2, anything,) -> (int -> 'A2 //│ where diff --git a/shared/src/test/diff/fcp/SystemF_2.mls b/shared/src/test/diff/fcp/SystemF_2.mls index 932b3da42..87f5a763e 100644 --- a/shared/src/test/diff/fcp/SystemF_2.mls +++ b/shared/src/test/diff/fcp/SystemF_2.mls @@ -291,8 +291,8 @@ def succ: (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X. ('X -> 'X) -> 'X -> succ = succ_ //│ 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e //│ where -//│ 'b <: 'd -> 'e -//│ 'a <: 'b -> 'c -> 'd)) +//│ 'a <: 'b -> 'c -> 'd +//│ 'b <: 'd -> 'e)) //│ <: succ: //│ (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X0. ('X0 -> 'X0) -> 'X0 -> 'X0) //│ ╔══[ERROR] Type error in def definition @@ -344,23 +344,23 @@ c2_ = succ_ (succ_ n0) c2_ c2_ //│ res: 'a -> 'b //│ where -//│ forall 'c. 'c -> (forall 'd 'e 'f. 'd -> 'f -//│ where -//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'c -> 'd -> 'e -//│ 'c <: 'e -> 'f) <: (forall 'g. 'g -> (forall 'h 'i 'j. 'j -> 'i +//│ forall 'c. 'c -> (forall 'd 'e 'f. 'f -> 'e //│ where -//│ 'g <: 'h -> 'i -//│ forall 'k. 'k -> (forall 'l 'm 'n. 'l -> 'n +//│ 'c <: 'd -> 'e +//│ forall 'g. 'g -> (forall 'h 'i 'j. 'h -> 'j //│ where -//│ 'k <: 'm -> 'n -//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'k -> 'l -> 'm) <: 'g -> 'j -> 'h)) -> 'a -> 'o -//│ forall 'g. 'g -> (forall 'h 'i 'j. 'j -> 'i +//│ 'g <: 'i -> 'j +//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'g -> 'h -> 'i) <: 'c -> 'f -> 'd) <: 'k -> 'b +//│ forall 'l. 'l -> (forall 'm 'n 'o. 'm -> 'o +//│ where +//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'l -> 'm -> 'n +//│ 'l <: 'n -> 'o) <: (forall 'c. 'c -> (forall 'd 'e 'f. 'f -> 'e //│ where -//│ 'g <: 'h -> 'i -//│ forall 'k. 'k -> (forall 'l 'm 'n. 'l -> 'n +//│ 'c <: 'd -> 'e +//│ forall 'g. 'g -> (forall 'h 'i 'j. 'h -> 'j //│ where -//│ 'k <: 'm -> 'n -//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'k -> 'l -> 'm) <: 'g -> 'j -> 'h) <: 'o -> 'b +//│ 'g <: 'i -> 'j +//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'g -> 'h -> 'i) <: 'c -> 'f -> 'd)) -> 'a -> 'k //│ = [Function (anonymous)] :e @@ -372,8 +372,8 @@ c2_ c2_ K //│ 'a <: 'c -> 'd //│ forall 'f. 'f -> (forall 'g 'h 'i. 'g -> 'i //│ where -//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'f -> 'g -> 'h -//│ 'f <: 'h -> 'i) <: 'a -> 'b -> 'c +//│ 'f <: 'h -> 'i +//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'f -> 'g -> 'h) <: 'a -> 'b -> 'c //│ ╙── //│ res: 'a -> 'b //│ where @@ -382,36 +382,36 @@ c2_ c2_ K //│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'c -> 'f -> 'd //│ 'c <: 'd -> 'e) <: (forall 'g 'h 'i. 'i -> 'h //│ where -//│ 'j <: 'g -> 'h -//│ forall 'k. 'k -> (forall 'l 'm 'n. 'l -> 'n +//│ forall 'j. 'j -> (forall 'k 'l 'm. 'k -> 'm //│ where -//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'k -> 'l -> 'm -//│ 'k <: 'm -> 'n) <: 'j -> 'i -> 'g) -> 'a -> 'o +//│ 'j <: 'l -> 'm +//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'j -> 'k -> 'l) <: 'n -> 'i -> 'g +//│ 'n <: 'g -> 'h) -> 'a -> 'o //│ forall 'g 'h 'i. 'i -> 'h //│ where -//│ 'j <: 'g -> 'h -//│ forall 'k. 'k -> (forall 'l 'm 'n. 'l -> 'n +//│ forall 'j. 'j -> (forall 'k 'l 'm. 'k -> 'm //│ where -//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'k -> 'l -> 'm -//│ 'k <: 'm -> 'n) <: 'j -> 'i -> 'g <: 'o -> 'b +//│ 'j <: 'l -> 'm +//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 'j -> 'k -> 'l) <: 'n -> 'i -> 'g +//│ 'n <: 'g -> 'h <: 'o -> 'b //│ where -//│ 'j :> forall 'p 'q 'r 's. ('p & 's) -> (anything -> 's | 'r) +//│ 'n :> forall 'p 'q 'r 's. ('p & 's) -> (anything -> 's | 'r) //│ where //│ forall 't. 't -> (forall 'u 'v 'w. 'u -> 'w //│ where -//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 't -> 'u -> 'v -//│ 't <: 'v -> 'w) <: 'j -> 'p -> 'q -//│ 'j <: 'q -> 'r +//│ 't <: 'v -> 'w +//│ forall 'X. ('X -> 'X) -> 'X -> 'X <: 't -> 'u -> 'v) <: 'n -> 'p -> 'q +//│ 'n <: 'q -> 'r //│ = [Function (anonymous)] c2__ = succ_ (succ_ n0_) //│ c2__: 'a -> (forall 'b 'c 'd. 'b -> 'd //│ where -//│ 'a <: 'c -> 'd //│ forall 'e. 'e -> (forall 'f 'g 'h. 'f -> 'h //│ where //│ anything -> (forall 'i. 'i -> 'i) <: 'e -> 'f -> 'g -//│ 'e <: 'g -> 'h) <: 'a -> 'b -> 'c) +//│ 'e <: 'g -> 'h) <: 'a -> 'b -> 'c +//│ 'a <: 'c -> 'd) //│ = [Function (anonymous)] c2__ c2__ @@ -419,43 +419,43 @@ c2__ c2__ //│ where //│ forall 'c. 'c -> (forall 'd 'e 'f. 'd -> 'f //│ where +//│ 'c <: 'e -> 'f //│ forall 'g. 'g -> (forall 'h 'i 'j. 'h -> 'j //│ where -//│ 'g <: 'i -> 'j -//│ anything -> (forall 'k. 'k -> 'k) <: 'g -> 'h -> 'i) <: 'c -> 'd -> 'e -//│ 'c <: 'e -> 'f) <: 'l -> 'b +//│ anything -> (forall 'k. 'k -> 'k) <: 'g -> 'h -> 'i +//│ 'g <: 'i -> 'j) <: 'c -> 'd -> 'e) <: 'l -> 'b //│ forall 'm. 'm -> (forall 'n 'o 'p. 'n -> 'p //│ where -//│ anything -> (forall 'k. 'k -> 'k) <: 'm -> 'n -> 'o -//│ 'm <: 'o -> 'p) <: (forall 'c. 'c -> (forall 'd 'e 'f. 'd -> 'f +//│ 'm <: 'o -> 'p +//│ anything -> (forall 'k. 'k -> 'k) <: 'm -> 'n -> 'o) <: (forall 'c. 'c -> (forall 'd 'e 'f. 'd -> 'f //│ where +//│ 'c <: 'e -> 'f //│ forall 'g. 'g -> (forall 'h 'i 'j. 'h -> 'j //│ where -//│ 'g <: 'i -> 'j -//│ anything -> (forall 'k. 'k -> 'k) <: 'g -> 'h -> 'i) <: 'c -> 'd -> 'e -//│ 'c <: 'e -> 'f)) -> 'a -> 'l +//│ anything -> (forall 'k. 'k -> 'k) <: 'g -> 'h -> 'i +//│ 'g <: 'i -> 'j) <: 'c -> 'd -> 'e)) -> 'a -> 'l //│ = [Function (anonymous)] c2__ c2__ K //│ res: 'a -> 'b //│ where -//│ forall 'c. 'c -> (forall 'd 'e 'f. 'd -> 'f -//│ where -//│ anything -> (forall 'g. 'g -> 'g) <: 'c -> 'd -> 'e -//│ 'c <: 'e -> 'f) <: (forall 'h 'i 'j. 'h -> 'j +//│ forall 'c 'd 'e. 'c -> 'e //│ where -//│ forall 'k. 'k -> (forall 'l 'm 'n. 'l -> 'n +//│ forall 'f. 'f -> (forall 'g 'h 'i. 'g -> 'i //│ where -//│ anything -> (forall 'g. 'g -> 'g) <: 'k -> 'l -> 'm -//│ 'k <: 'm -> 'n) <: (forall 'o. 'o -> anything -> 'o) -> 'h -> 'i -//│ forall 'o. 'o -> anything -> 'o <: 'i -> 'j) -> 'a -> 'p -//│ forall 'h 'i 'j. 'h -> 'j +//│ anything -> (forall 'j. 'j -> 'j) <: 'f -> 'g -> 'h +//│ 'f <: 'h -> 'i) <: (forall 'k. 'k -> anything -> 'k) -> 'c -> 'd +//│ forall 'k. 'k -> anything -> 'k <: 'd -> 'e <: 'l -> 'b +//│ forall 'm. 'm -> (forall 'n 'o 'p. 'n -> 'p //│ where -//│ forall 'k. 'k -> (forall 'l 'm 'n. 'l -> 'n +//│ 'm <: 'o -> 'p +//│ anything -> (forall 'j. 'j -> 'j) <: 'm -> 'n -> 'o) <: (forall 'c 'd 'e. 'c -> 'e +//│ where +//│ forall 'f. 'f -> (forall 'g 'h 'i. 'g -> 'i //│ where -//│ anything -> (forall 'g. 'g -> 'g) <: 'k -> 'l -> 'm -//│ 'k <: 'm -> 'n) <: (forall 'o. 'o -> anything -> 'o) -> 'h -> 'i -//│ forall 'o. 'o -> anything -> 'o <: 'i -> 'j <: 'p -> 'b +//│ anything -> (forall 'j. 'j -> 'j) <: 'f -> 'g -> 'h +//│ 'f <: 'h -> 'i) <: (forall 'k. 'k -> anything -> 'k) -> 'c -> 'd +//│ forall 'k. 'k -> anything -> 'k <: 'd -> 'e) -> 'a -> 'l //│ = [Function (anonymous)] diff --git a/shared/src/test/diff/mlf-examples/ex_casparticuliers.mls b/shared/src/test/diff/mlf-examples/ex_casparticuliers.mls index 6dbbf0de8..82c34baa4 100644 --- a/shared/src/test/diff/mlf-examples/ex_casparticuliers.mls +++ b/shared/src/test/diff/mlf-examples/ex_casparticuliers.mls @@ -550,8 +550,8 @@ succ_ty = succ succ_ty = succ' //│ 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e //│ where -//│ 'b <: 'd -> 'e -//│ 'a <: 'b -> 'c -> 'd)) +//│ 'a <: 'b -> 'c -> 'd +//│ 'b <: 'd -> 'e)) //│ <: succ_ty: //│ ChurchInt -> ChurchInt //│ ╔══[ERROR] Type error in def definition @@ -593,8 +593,8 @@ succ' succ' {} //│ res: 'a -> (forall 'b 'c 'd. 'b -> 'd //│ where -//│ 'a <: 'c -> 'd -//│ anything <: 'a -> 'b -> 'c) +//│ anything <: 'a -> 'b -> 'c +//│ 'a <: 'c -> 'd) //│ = [Function (anonymous)] // :e // * Error delayed by inconsistent constrained types diff --git a/shared/src/test/diff/mlf-examples/ex_demo.mls b/shared/src/test/diff/mlf-examples/ex_demo.mls index 5f9950dc3..5fb32fbc0 100644 --- a/shared/src/test/diff/mlf-examples/ex_demo.mls +++ b/shared/src/test/diff/mlf-examples/ex_demo.mls @@ -1401,8 +1401,8 @@ def c_succ_ n = fun f -> fun x -> n f (f x) def c_add_ n m = m c_succ_ n //│ c_add_: 'a -> (forall 'b. ((forall 'c. 'c -> (forall 'd. 'd -> (forall 'e 'f 'g. 'g -> 'f //│ where -//│ 'd <: 'g -> 'e -//│ 'c <: 'd -> 'e -> 'f))) -> 'a -> 'b) -> 'b) +//│ 'c <: 'd -> 'e -> 'f +//│ 'd <: 'g -> 'e))) -> 'a -> 'b) -> 'b) //│ = [Function: c_add_1] // let c_i1 = fun f x -> f x @@ -1421,10 +1421,10 @@ def c_i2_ = c_succ_ c_i1 //│ = [Function: c_i22] //│ c_i2_: 'a -> (forall 'b 'c 'd. 'd -> 'c //│ where -//│ 'a <: 'd -> 'b //│ forall 'e. 'e -> (forall 'f 'g. 'f -> 'g //│ where -//│ 'e <: 'f -> 'g) <: 'a -> 'b -> 'c) +//│ 'e <: 'f -> 'g) <: 'a -> 'b -> 'c +//│ 'a <: 'd -> 'b) //│ = [Function: c_i2_1] // let c_i3 = c_succ c_i2 @@ -1450,26 +1450,26 @@ c_i5_ = c_add_ c_i3_ c_i2 //│ 'b :> forall 'c. 'c -> (forall 'd 'e 'f 'g. 'g -> 'f //│ where //│ 'c <: 'g -> 'e & 'g -> 'd -//│ 'b <: 'c -> 'e -> 'f //│ forall 'h. 'h -> (forall 'i 'j 'k. 'k -> 'j //│ where //│ 'h <: 'k -> 'i //│ forall 'l. 'l -> (forall 'a 'm. 'm -> 'a //│ where -//│ 'l <: 'a -> 'a & 'm -> 'a) <: 'h -> 'i -> 'j) <: 'c -> 'd -> 'f) +//│ 'l <: 'a -> 'a & 'm -> 'a) <: 'h -> 'i -> 'j) <: 'c -> 'd -> 'f +//│ 'b <: 'c -> 'e -> 'f) //│ ╙── //│ c_i5_: 'b //│ where //│ 'b :> forall 'c. 'c -> (forall 'd 'e 'f 'g. 'f -> 'e //│ where //│ 'c <: 'f -> 'd & 'f -> 'g +//│ 'b <: 'c -> 'd -> 'e //│ forall 'h. 'h -> (forall 'i 'j 'k. 'k -> 'j //│ where //│ 'h <: 'k -> 'i //│ forall 'l. 'l -> (forall 'a 'm. 'm -> 'a //│ where -//│ 'l <: 'a -> 'a & 'm -> 'a) <: 'h -> 'i -> 'j) <: 'c -> 'g -> 'e -//│ 'b <: 'c -> 'd -> 'e) +//│ 'l <: 'a -> 'a & 'm -> 'a) <: 'h -> 'i -> 'j) <: 'c -> 'g -> 'e) //│ = [Function (anonymous)] //│ constrain calls : 140 //│ annoying calls : 0 diff --git a/shared/src/test/diff/typegen/TypegenTerms.mls b/shared/src/test/diff/typegen/TypegenTerms.mls index e628ca0fc..eebe45ecc 100644 --- a/shared/src/test/diff/typegen/TypegenTerms.mls +++ b/shared/src/test/diff/typegen/TypegenTerms.mls @@ -66,7 +66,7 @@ rec def l (a: int) = l rec def m (a: int) (b: int) = m def f: ('c -> 'a as 'a) -> 'c -> int // recursion type functions -//│ /!!!\ Uncaught error: mlscript.codegen.CodeGenError: Cannot generate type for `where` clause List((α95,Bounds(Function(Tuple(List((None,Field(None,TypeName(int))))),α95),Top))) List() +//│ /!!!\ Uncaught error: mlscript.codegen.CodeGenError: Cannot generate type for `where` clause List((α95,Bounds(Function(Tuple(List((None,Field(None,TypeName(int),false)))),α95),Top))) List() :ts :e @@ -152,6 +152,6 @@ def weird: ((int, int) -> 'a) as 'a def weird: ('a -> (int, int)) as 'a def weird: ((int, 'a) as 'a) -> int def weird: ((int, bool) | 'a) -> 'a -//│ /!!!\ Uncaught error: mlscript.codegen.CodeGenError: Cannot generate type for `where` clause List((α218,Bounds(Function(Tuple(List((None,Field(None,TypeName(int))), (None,Field(None,TypeName(int))))),α218),Top))) List() +//│ /!!!\ Uncaught error: mlscript.codegen.CodeGenError: Cannot generate type for `where` clause List((α218,Bounds(Function(Tuple(List((None,Field(None,TypeName(int),false)), (None,Field(None,TypeName(int),false)))),α218),Top))) List() From fec99d8c181b4cd9d2ee93cea1cdce6f6c6b0758 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Wed, 20 Sep 2023 15:15:04 +0800 Subject: [PATCH 08/37] adding opt field for FieldType --- .../src/main/scala/mlscript/NewParser.scala | 2 +- shared/src/main/scala/mlscript/Typer.scala | 14 +- .../main/scala/mlscript/TyperDatatypes.scala | 2 +- shared/src/main/scala/mlscript/helpers.scala | 3 +- shared/src/test/diff/nu/OptionalArgs.mls | 215 +++++------------- 5 files changed, 78 insertions(+), 158 deletions(-) diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index a75653061..1c9d4c9c6 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -537,7 +537,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D case x :: _ => printDbg(s"Here, creating the params! ${res} ${Helpers.inspect(x)}" ) case Nil => - printDbg(s"Here, creating the params! ${res}") + printDbg(s"Here, (not) creating the params! ${res}") } res } diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index a11efc991..825d47a62 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -424,10 +424,12 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne implicit val prov: TP = tyTp(ty.toLoc, "type bounds") constrain(lb_ty, ub_ty) TypeBounds(lb_ty, ub_ty)(prov) - case Tuple(fields) => + case Tuple(fields) => { + println("typing tuple!!!") TupleType(fields.mapValues(f => - FieldType(f.in.map(rec), rec(f.out), false)(tp(f.toLoc, "tuple field")) + FieldType(f.in.map(rec), rec(f.out), f.opt)(tp(f.toLoc, "tuple field")) ))(tyTp(ty.toLoc, "tuple type")) + } case Splice(fields) => SpliceType(fields.map{ case L(l) => { @@ -479,6 +481,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne case tn @ TypeTag(name) => rec(TypeName(name.decapitalize)) // TODO rm this hack // case tn @ TypeTag(name) => rec(TypeName(name)) case tn @ TypeName(name) => + println("typename case??") val tyLoc = ty.toLoc val tpr = tyTp(tyLoc, "type reference") vars.getOrElse(name, { @@ -802,10 +805,15 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne } case Asc(trm, ty) => + println(s"typing-trm-here!!! ${trm}") val trm_ty = typePolymorphicTerm(trm) + println(s"typing-ty-here!!! ${ty}") val ty_ty = typeType(ty)(ctx.copy(inPattern = false), raise, vars) if (ctx.inPattern) { unify(trm_ty, ty_ty); ty_ty } // * In patterns, we actually _unify_ the pattern and ascribed type - else con(trm_ty, ty_ty, ty_ty) + else { + println("constraining!!!") + con(trm_ty, ty_ty, ty_ty) + } case (v @ ValidPatVar(nme)) => val prov = tp(if (verboseConstraintProvenanceHints) v.toLoc else N, "variable") // * Note: only look at ctx.env, and not the outer ones! diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala index 00cfa7575..94a7a9eda 100644 --- a/shared/src/main/scala/mlscript/TyperDatatypes.scala +++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala @@ -487,7 +487,7 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): FieldType = update(_.freshenAbove(lim, rigidify), _.freshenAbove(lim, rigidify)) override def toString = - lb.fold(s"$ub")(lb => s"mut ${if (lb === BotType) "" else lb}..$ub") + lb.fold(s"$ub${if (opt) "?" else ""}")(lb => s"mut ${if (lb === BotType) "" else lb}..$ub") } object FieldType { def mk(vi: VarianceInfo, lb: ST, ub: ST)(prov: TP): FieldType = vi match { diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index 6676cc72c..189c56819 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -528,7 +528,8 @@ trait TermImpl extends StatementImpl { self: Term => s"let${if (isRec) " rec" else ""} $name = $rhs in $body" |> bra case Tup(xs) => xs.iterator.map { case (n, t) => - (if (t.flags.mut) "mut " else "") + (if (t.flags.spec) "#" else "") + n.fold("")(_.name + ": ") + t.value + "," + (if (t.flags.mut) "mut " else "") + (if (t.flags.spec) "#" else "") + n.fold("")(_.name + ": ") + t.value + "," + + (if (t.flags.opt) "?" else "") // }.mkString("(", " ", ")") }.mkString(" ") |> bra case Splc(fields) => fields.map{ diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index a6a5de3a1..e62fdaf41 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -4,7 +4,6 @@ // TODO: there is problem when the is SPACE after '?' :dp -:p fun f1(a?: Int, b?: Int) = a + b //│ |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a| |+| |b| //│ ? block inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.300] @@ -41,9 +40,9 @@ fun f1(a?: Int, b?: Int) = a + b //│ │ > │ │ = Right(Int) //│ │ > │ = Right(Int) //│ │ > │ ? argsOrIf inspects |,| |b|?|#:|... [at l.1093] -//│ │ > │ nexttoken => (COMMA,Loc(14,15,nu/OptionalArgs:+8)) +//│ │ > │ nexttoken => (COMMA,Loc(14,15,nu/OptionalArgs:+7)) //│ │ > │ ? isOptinoal inspects |,| |b|?|#:|... [at l.1098] -//│ │ > │ flags => None None Some(Loc(8,8,nu/OptionalArgs:+8)) +//│ │ > │ flags => None None Some(Loc(8,8,nu/OptionalArgs:+7)) //│ │ > │ e => Right(Fld(FldFlags(false,false,true),Int)) //│ │ > │ body => Int Var(Int) //│ │ > │ ? argsOrIf inspects |,| |b|?|#:|... [at l.1122] @@ -72,7 +71,7 @@ fun f1(a?: Int, b?: Int) = a + b //│ │ > │ │ │ = Right(Int) //│ │ > │ │ │ ? argsOrIf inspects || [at l.1093] //│ │ > │ │ │ ? isOptinoal inspects || [at l.1098] -//│ │ > │ │ │ flags => None None Some(Loc(17,17,nu/OptionalArgs:+8)) +//│ │ > │ │ │ flags => None None Some(Loc(17,17,nu/OptionalArgs:+7)) //│ │ > │ │ │ e => Right(Fld(FldFlags(false,false,true),Int)) //│ │ > │ │ │ body => Int Var(Int) //│ │ > │ │ │ ? argsOrIf inspects || [at l.1122] @@ -84,10 +83,10 @@ fun f1(a?: Int, b?: Int) = a + b //│ │ @ funParams(()) [at l.528] //│ │ │ ? yeetSpaces inspects | |#=| |a| |... [at l.515] //│ │ │ ! yeetSpaces consumes | | [at l.515] -//│ │ │ Here, creating the params! List() +//│ │ │ Here, (not) creating the params! List() //│ │ = List() -//│ │ Here, creating the params! List(a: Int, b: Int,) Tup(a: Var(Int), b: Var(Int)) -//│ = List(a: Int, b: Int,) +//│ │ Here, creating the params! List(a: Int,? b: Int,?) Tup(a: Var(Int), b: Var(Int)) +//│ = List(a: Int,? b: Int,?) //│ ? yeetSpaces inspects |#=| |a| |+|... [at l.515] //│ ? yeetSpaces inspects |#=| |a| |+|... [at l.515] //│ ! t consumes |#=| [at l.475] @@ -127,11 +126,11 @@ fun f1(a?: Int, b?: Int) = a + b //│ = + (a,) (b,) //│ ? yeetSpaces inspects || [at l.515] //│ ? parseAll inspects || [at l.76] -//│ AST: TypingUnit(NuFunDef(None, f1, [], Lam(Tup(a: Var(Int), b: Var(Int)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b)))))) -//│ Parsed: fun f1 = (a: Int, b: Int,) => + (a,) (b,); +//│ Parsed: fun f1 = (a: Int,? b: Int,?) => + (a,) (b,); //│ fun f1: (a: Int, b: Int,) -> Int + // using space, creates ASC in AST. :p fun f1(a: Int, b: Int) = a + b @@ -212,136 +211,48 @@ let y: C1 = x //│ res //│ = [ 1, 2, 3 ] -:dp -:p -[1, 2]: [Int, Int] -//│ |[|1|,| |2|]|#:| |[|Int|,| |Int|]| -//│ ? block inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|]| [at l.300] -//│ ? go inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|]| [at l.269] -//│ ? go inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|]| [at l.269] -//│ @ exprOrIf(0,false) [at l.499] -//│ │ ? exprOrIf inspects |[|1|,| |2|]|#:| |[|Int|,| |Int|]| [at l.561] -//│ │ ! exprOrIf consumes |[|1|,| |2|]| [at l.590] -//│ │ > ? maybeIndented inspects |1|,| |2| [at l.1005] -//│ │ > @ argsOrIf(List(),List()) [at l.1048] -//│ │ > │ ? argsOrIf inspects |1|,| |2| [at l.1049] -//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] -//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] -//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] -//│ │ > │ @ exprOrIf(1,true) [at l.1092] -//│ │ > │ │ ? exprOrIf inspects |1|,| |2| [at l.561] -//│ │ > │ │ ! exprOrIf consumes |1| [at l.574] -//│ │ > │ │ @ exprCont(1,`1`,false) [at l.575] -//│ │ > │ │ │ ? exprCont inspects |,| |2| [at l.737] -//│ │ > │ │ = Right(1) -//│ │ > │ = Right(1) -//│ │ > │ ? argsOrIf inspects |,| |2| [at l.1093] -//│ │ > │ nexttoken => (COMMA,Loc(2,3,nu/OptionalArgs:+217)) -//│ │ > │ ? isOptinoal inspects |,| |2| [at l.1098] -//│ │ > │ flags => None None None -//│ │ > │ e => Right(Fld(FldFlags(false,false,false),1)) -//│ │ > │ body => 1 IntLit(1) -//│ │ > │ ? argsOrIf inspects |,| |2| [at l.1122] -//│ │ > │ ! argsOrIf consumes |,| [at l.1128] -//│ │ > │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),1)))),List()) [at l.1048] -//│ │ > │ │ ? argsOrIf inspects | |2| [at l.1049] -//│ │ > │ │ ! argsOrIf consumes | | [at l.1058] -//│ │ > │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),1)))),List()) [at l.1048] -//│ │ > │ │ │ ? argsOrIf inspects |2| [at l.1049] -//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] -//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] -//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] -//│ │ > │ │ │ @ exprOrIf(1,true) [at l.1092] -//│ │ > │ │ │ │ ? exprOrIf inspects |2| [at l.561] -//│ │ > │ │ │ │ ! exprOrIf consumes |2| [at l.574] -//│ │ > │ │ │ │ @ exprCont(1,`2`,false) [at l.575] -//│ │ > │ │ │ │ │ ? exprCont inspects || [at l.737] -//│ │ > │ │ │ │ = Right(2) -//│ │ > │ │ │ = Right(2) -//│ │ > │ │ │ ? argsOrIf inspects || [at l.1093] -//│ │ > │ │ │ ? isOptinoal inspects || [at l.1098] -//│ │ > │ │ │ flags => None None None -//│ │ > │ │ │ e => Right(Fld(FldFlags(false,false,false),2)) -//│ │ > │ │ │ body => 2 IntLit(2) -//│ │ > │ │ │ ? argsOrIf inspects || [at l.1122] -//│ │ > │ │ = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) -//│ │ > │ = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) -//│ │ > = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) -//│ │ > ? concludeWith inspects || [at l.87] -//│ │ > Concluded with List((None,Fld(FldFlags(false,false,false),1)), (None,Fld(FldFlags(false,false,false),2))) -//│ │ @ exprCont(0,`'(' 1, 2, ')'`,false) [at l.608] -//│ │ │ ? exprCont inspects |#:| |[|Int|,| |Int|]| [at l.737] -//│ │ │ ! exprCont consumes |#:| [at l.771] -//│ │ │ @ expr(0,true) [at l.772] -//│ │ │ │ @ exprOrIf(0,true) [at l.546] -//│ │ │ │ │ ? exprOrIf inspects | |[|Int|,| |Int|]| [at l.561] -//│ │ │ │ │ ! exprOrIf consumes | | [at l.563] -//│ │ │ │ │ @ exprOrIf(0,true) [at l.564] -//│ │ │ │ │ │ ? exprOrIf inspects |[|Int|,| |Int|]| [at l.561] -//│ │ │ │ │ │ ! exprOrIf consumes |[|Int|,| |Int|]| [at l.590] -//│ │ │ │ │ │ > ? maybeIndented inspects |Int|,| |Int| [at l.1005] -//│ │ │ │ │ │ > @ argsOrIf(List(),List()) [at l.1048] -//│ │ │ │ │ │ > │ ? argsOrIf inspects |Int|,| |Int| [at l.1049] -//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int| [at l.515] -//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int| [at l.515] -//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int| [at l.515] -//│ │ │ │ │ │ > │ @ exprOrIf(1,true) [at l.1092] -//│ │ │ │ │ │ > │ │ ? exprOrIf inspects |Int|,| |Int| [at l.561] -//│ │ │ │ │ │ > │ │ ! exprOrIf consumes |Int| [at l.580] -//│ │ │ │ │ │ > │ │ @ exprCont(1,`Int`,false) [at l.581] -//│ │ │ │ │ │ > │ │ │ ? exprCont inspects |,| |Int| [at l.737] -//│ │ │ │ │ │ > │ │ = Right(Int) -//│ │ │ │ │ │ > │ = Right(Int) -//│ │ │ │ │ │ > │ ? argsOrIf inspects |,| |Int| [at l.1093] -//│ │ │ │ │ │ > │ nexttoken => (COMMA,Loc(12,13,nu/OptionalArgs:+217)) -//│ │ │ │ │ │ > │ ? isOptinoal inspects |,| |Int| [at l.1098] -//│ │ │ │ │ │ > │ flags => None None None -//│ │ │ │ │ │ > │ e => Right(Fld(FldFlags(false,false,false),Int)) -//│ │ │ │ │ │ > │ body => Int Var(Int) -//│ │ │ │ │ │ > │ ? argsOrIf inspects |,| |Int| [at l.1122] -//│ │ │ │ │ │ > │ ! argsOrIf consumes |,| [at l.1128] -//│ │ │ │ │ │ > │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] -//│ │ │ │ │ │ > │ │ ? argsOrIf inspects | |Int| [at l.1049] -//│ │ │ │ │ │ > │ │ ! argsOrIf consumes | | [at l.1058] -//│ │ │ │ │ │ > │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] -//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects |Int| [at l.1049] -//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int| [at l.515] -//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int| [at l.515] -//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int| [at l.515] -//│ │ │ │ │ │ > │ │ │ @ exprOrIf(1,true) [at l.1092] -//│ │ │ │ │ │ > │ │ │ │ ? exprOrIf inspects |Int| [at l.561] -//│ │ │ │ │ │ > │ │ │ │ ! exprOrIf consumes |Int| [at l.580] -//│ │ │ │ │ │ > │ │ │ │ @ exprCont(1,`Int`,false) [at l.581] -//│ │ │ │ │ │ > │ │ │ │ │ ? exprCont inspects || [at l.737] -//│ │ │ │ │ │ > │ │ │ │ = Right(Int) -//│ │ │ │ │ │ > │ │ │ = Right(Int) -//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects || [at l.1093] -//│ │ │ │ │ │ > │ │ │ ? isOptinoal inspects || [at l.1098] -//│ │ │ │ │ │ > │ │ │ flags => None None None -//│ │ │ │ │ │ > │ │ │ e => Right(Fld(FldFlags(false,false,false),Int)) -//│ │ │ │ │ │ > │ │ │ body => Int Var(Int) -//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects || [at l.1122] -//│ │ │ │ │ │ > │ │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int)))) -//│ │ │ │ │ │ > │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int)))) -//│ │ │ │ │ │ > = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int)))) -//│ │ │ │ │ │ > ? concludeWith inspects || [at l.87] -//│ │ │ │ │ │ > Concluded with List((None,Fld(FldFlags(false,false,false),Int)), (None,Fld(FldFlags(false,false,false),Int))) -//│ │ │ │ │ │ @ exprCont(0,`'(' Int, Int, ')'`,false) [at l.608] -//│ │ │ │ │ │ │ ? exprCont inspects || [at l.737] -//│ │ │ │ │ │ = Right('(' Int, Int, ')') -//│ │ │ │ │ = Right('(' Int, Int, ')') -//│ │ │ │ = Right('(' Int, Int, ')') -//│ │ │ │ result => '(' Int, Int, ')' ## Bra(rcd = false, Tup(_: Var(Int), _: Var(Int))) -//│ │ │ │ result toType => Right(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) -//│ │ │ = '(' Int, Int, ')' -//│ │ │ asc => '(' 1, 2, ')' : (Int, Int,) -//│ │ = Right('(' 1, 2, ')' : (Int, Int,)) -//│ = Right('(' 1, 2, ')' : (Int, Int,)) -//│ ? yeetSpaces inspects || [at l.515] -//│ ? parseAll inspects || [at l.76] -//│ AST: TypingUnit(Asc(Bra(rcd = false, Tup(_: IntLit(1), _: IntLit(2))), Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)))))) -//│ Parsed: '(' 1, 2, ')' : (Int, Int,); -//│ (Int, Int,) +:d +[1, 2]: [Int, (Int | C1)?] +//│ 0. Typing TypingUnit(List('(' 1, 2, ')' : (Int, Int | C1,))) +//│ | Typing unit statements +//│ | | 0. Typing term '(' 1, 2, ')' : (Int, Int | C1,) +//│ | | | typing-trm-here!!! '(' 1, 2, ')' +//│ | | | 0. Typing term '(' 1, 2, ')' +//│ | | | | 0. Typing term 1, 2, +//│ | | | | | 0. Typing term 1 +//│ | | | | | 0. : #1 +//│ | | | | | 0. Typing term 2 +//│ | | | | | 0. : #2 +//│ | | | | 0. : (#1, #2,) +//│ | | | 0. : (#1, #2,) +//│ | | | typing-ty-here!!! Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,Union(TypeName(Int),TypeName(C1)),true)))) +//│ | | | Typing type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,Union(TypeName(Int),TypeName(C1)),true)))) +//│ | | | | vars=Map() newDefsInfo=Map() +//│ | | | | 0. type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,Union(TypeName(Int),TypeName(C1)),true)))) +//│ | | | | | typing tuple!!! +//│ | | | | | 0. type TypeName(Int) +//│ | | | | | | typename case?? +//│ | | | | | => Int +//│ | | | | | 0. type Union(TypeName(Int),TypeName(C1)) +//│ | | | | | | 0. type TypeName(Int) +//│ | | | | | | | typename case?? +//│ | | | | | | => Int +//│ | | | | | | 0. type TypeName(C1) +//│ | | | | | | | typename case?? +//│ | | | | | | => C1 +//│ | | | | | => (Int | C1) +//│ | | | | => (Int, (Int | C1)?,) +//│ | | | => (Int, (Int | C1)?,) ——— +//│ | | | constraining!!! +//│ | | | CONSTRAIN (#1, #2,) , #2,) │ │ = Right(1) //│ │ > │ = Right(1) //│ │ > │ ? argsOrIf inspects |,| |2| [at l.1093] -//│ │ > │ nexttoken => (COMMA,Loc(2,3,nu/OptionalArgs:+349)) +//│ │ > │ nexttoken => (COMMA,Loc(2,3,nu/OptionalArgs:+260)) //│ │ > │ ? isOptinoal inspects |,| |2| [at l.1098] //│ │ > │ flags => None None None //│ │ > │ e => Right(Fld(FldFlags(false,false,false),1)) @@ -425,7 +336,7 @@ let y: C1 = x //│ │ │ │ │ │ > │ │ = Right(Int) //│ │ │ │ │ │ > │ = Right(Int) //│ │ │ │ │ │ > │ ? argsOrIf inspects |,| |Int|,| |... [at l.1093] -//│ │ │ │ │ │ > │ nexttoken => (COMMA,Loc(12,13,nu/OptionalArgs:+349)) +//│ │ │ │ │ │ > │ nexttoken => (COMMA,Loc(12,13,nu/OptionalArgs:+260)) //│ │ │ │ │ │ > │ ? isOptinoal inspects |,| |Int|,| |... [at l.1098] //│ │ │ │ │ │ > │ flags => None None None //│ │ │ │ │ │ > │ e => Right(Fld(FldFlags(false,false,false),Int)) @@ -448,7 +359,7 @@ let y: C1 = x //│ │ │ │ │ │ > │ │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects |,| |Int|?| [at l.1093] -//│ │ │ │ │ │ > │ │ │ nexttoken => (COMMA,Loc(17,18,nu/OptionalArgs:+349)) +//│ │ │ │ │ │ > │ │ │ nexttoken => (COMMA,Loc(17,18,nu/OptionalArgs:+260)) //│ │ │ │ │ │ > │ │ │ ? isOptinoal inspects |,| |Int|?| [at l.1098] //│ │ │ │ │ │ > │ │ │ flags => None None None //│ │ │ │ │ │ > │ │ │ e => Right(Fld(FldFlags(false,false,false),Int)) @@ -471,7 +382,7 @@ let y: C1 = x //│ │ │ │ │ │ > │ │ │ │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ │ │ ? argsOrIf inspects |?| [at l.1093] -//│ │ │ │ │ │ > │ │ │ │ │ nexttoken => (IDENT(?,true),Loc(22,22,nu/OptionalArgs:+349)) +//│ │ │ │ │ │ > │ │ │ │ │ nexttoken => (IDENT(?,true),Loc(22,22,nu/OptionalArgs:+260)) //│ │ │ │ │ │ > │ │ │ │ │ ? isOptinoal inspects |?| [at l.1098] //│ │ │ │ │ │ > │ │ │ │ │ ! isOptinoal consumes |?| [at l.1100] //│ │ │ │ │ │ > │ │ │ │ │ flags => None None None @@ -485,14 +396,14 @@ let y: C1 = x //│ │ │ │ │ │ > = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) //│ │ │ │ │ │ > ? concludeWith inspects || [at l.87] //│ │ │ │ │ │ > Concluded with List((None,Fld(FldFlags(false,false,false),Int)), (None,Fld(FldFlags(false,false,false),Int)), (None,Fld(FldFlags(false,false,true),Int))) -//│ │ │ │ │ │ @ exprCont(0,`'(' Int, Int, Int, ')'`,false) [at l.608] +//│ │ │ │ │ │ @ exprCont(0,`'(' Int, Int, Int,? ')'`,false) [at l.608] //│ │ │ │ │ │ │ ? exprCont inspects || [at l.737] -//│ │ │ │ │ │ = Right('(' Int, Int, Int, ')') -//│ │ │ │ │ = Right('(' Int, Int, Int, ')') -//│ │ │ │ = Right('(' Int, Int, Int, ')') -//│ │ │ │ result => '(' Int, Int, Int, ')' ## Bra(rcd = false, Tup(_: Var(Int), _: Var(Int), _: Var(Int))) +//│ │ │ │ │ │ = Right('(' Int, Int, Int,? ')') +//│ │ │ │ │ = Right('(' Int, Int, Int,? ')') +//│ │ │ │ = Right('(' Int, Int, Int,? ')') +//│ │ │ │ result => '(' Int, Int, Int,? ')' ## Bra(rcd = false, Tup(_: Var(Int), _: Var(Int), _: Var(Int))) //│ │ │ │ result toType => Right(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) -//│ │ │ = '(' Int, Int, Int, ')' +//│ │ │ = '(' Int, Int, Int,? ')' //│ │ │ asc => '(' 1, 2, ')' : (Int, Int, Int,) //│ │ = Right('(' 1, 2, ')' : (Int, Int, Int,)) //│ = Right('(' 1, 2, ')' : (Int, Int, Int,)) @@ -500,13 +411,13 @@ let y: C1 = x //│ ? parseAll inspects || [at l.76] //│ Parsed: '(' 1, 2, ')' : (Int, Int, Int,); //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.349: [1, 2]: [Int, Int, Int?] +//│ ║ l.260: [1, 2]: [Int, Int, Int?] //│ ║ ^^^^^^ //│ ╟── tuple literal of type `(1, 2,)` does not match type `(Int, Int, Int,)` -//│ ║ l.349: [1, 2]: [Int, Int, Int?] +//│ ║ l.260: [1, 2]: [Int, Int, Int?] //│ ║ ^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.349: [1, 2]: [Int, Int, Int?] +//│ ║ l.260: [1, 2]: [Int, Int, Int?] //│ ╙── ^^^^^^^^^^^^^^^^ //│ (Int, Int, Int,) //│ res From 0a653b214c5d6cb3bb3ca62bf898d3c879b39890 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Wed, 20 Sep 2023 16:50:56 +0800 Subject: [PATCH 09/37] fix typing of funparams --- shared/src/main/scala/mlscript/Typer.scala | 17 +- shared/src/main/scala/mlscript/helpers.scala | 4 +- shared/src/test/diff/nu/OptionalArgs.mls | 270 ++++++++----------- 3 files changed, 127 insertions(+), 164 deletions(-) diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index 825d47a62..6869a3527 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -895,7 +895,8 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne })(prov) case tup: Tup if funkyTuples => typeTerms(tup :: Nil, false, Nil) - case Tup(fs) => + case Tup(fs) => { + println("HERE, good!") TupleType(fs.mapConserve { case e @ (n, Fld(flags, t)) => n match { case S(v) if ctx.inPattern => @@ -903,20 +904,28 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne Asc(v, t.toTypeRaise).withLoc(v.toLoc.fold(t.toLoc)(_ ++ t.toLoc |> some)))) case _ => e } - }.map { case (n, Fld(FldFlags(mut, _, _), t)) => + }.map { case (n, Fld(FldFlags(mut, _, opt), t)) => val tym = typePolymorphicTerm(t) // val tym = if (n.isDefined) typeType(t.toTypeRaise) // else typePolymorphicTerm(t) val fprov = tp(t.toLoc, (if (mut) "mutable " else "") + "tuple field") + println(s"opt is => ${opt}") if (mut) { + println("case #1") val res = freshVar(fprov, N, n.map(_.name)) val rs = con(tym, res, res) - (n, FieldType(Some(rs), rs, false)(fprov)) - } else (n, tym.toUpper(fprov)) + (n, FieldType(Some(rs), rs, opt)(fprov)) + } else { + println("case #2") + val ty = tym.toUpper(fprov) + val tres = FieldType(ty.lb, ty.ub, opt)(ty.prov) + (n, tres) + } })(fs match { case Nil | ((N, _) :: Nil) => noProv // TODO rm? case _ => tp(term.toLoc, "tuple literal") }) + } case Subs(a, i) => val t_a = typeMonomorphicTerm(a) val t_i = typeMonomorphicTerm(i) diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index 189c56819..b47d640e0 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -528,8 +528,8 @@ trait TermImpl extends StatementImpl { self: Term => s"let${if (isRec) " rec" else ""} $name = $rhs in $body" |> bra case Tup(xs) => xs.iterator.map { case (n, t) => - (if (t.flags.mut) "mut " else "") + (if (t.flags.spec) "#" else "") + n.fold("")(_.name + ": ") + t.value + "," + - (if (t.flags.opt) "?" else "") + (if (t.flags.mut) "mut " else "") + (if (t.flags.spec) "#" else "") + n.fold("")(_.name + ": ") + t.value + + (if (t.flags.opt) "?" else "") + "," // }.mkString("(", " ", ")") }.mkString(" ") |> bra case Splc(fields) => fields.map{ diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index e62fdaf41..91161986d 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -3,130 +3,82 @@ // TODO: there is problem when the is SPACE after '?' -:dp +// Typing of (a?: Int, b?: Int) is ok, but constraining is not +:d fun f1(a?: Int, b?: Int) = a + b -//│ |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a| |+| |b| -//│ ? block inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.300] -//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.269] -//│ ? go inspects |#fun| |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |... [at l.269] -//│ ! t consumes |#fun| [at l.414] -//│ ? yeetSpaces inspects | |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=|... [at l.515] -//│ ! yeetSpaces consumes | | [at l.515] -//│ ? yeetSpaces inspects |f1|(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |... [at l.515] -//│ ! x$29 consumes |f1| [at l.425] -//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.515] -//│ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.515] -//│ @ funParams(()) [at l.464] -//│ │ ? yeetSpaces inspects |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| |#=| |a|... [at l.515] -//│ │ ! res consumes |(|a|?|#:| |Int|,| |b|?|#:| |Int|)| [at l.526] -//│ │ > ? maybeIndented inspects |a|?|#:| |Int|... [at l.1005] -//│ │ > @ argsOrIf(List(),List()) [at l.1048] -//│ │ > │ ? argsOrIf inspects |a|?|#:| |Int|... [at l.1049] -//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.515] -//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.515] -//│ │ > │ ? yeetSpaces inspects |a|?|#:| |Int|... [at l.515] -//│ │ > │ ! x$60 consumes |a| [at l.1081] -//│ │ > │ ! x$60 consumes |?| [at l.1082] -//│ │ > │ ! x$60 consumes |#:| [at l.1083] -//│ │ > │ @ exprOrIf(1,true) [at l.1092] -//│ │ > │ │ ? exprOrIf inspects | |Int|,| |b|... [at l.561] -//│ │ > │ │ ! exprOrIf consumes | | [at l.563] -//│ │ > │ │ @ exprOrIf(1,true) [at l.564] -//│ │ > │ │ │ ? exprOrIf inspects |Int|,| |b|?|... [at l.561] -//│ │ > │ │ │ ! exprOrIf consumes |Int| [at l.580] -//│ │ > │ │ │ @ exprCont(1,`Int`,false) [at l.581] -//│ │ > │ │ │ │ ? exprCont inspects |,| |b|?|#:|... [at l.737] -//│ │ > │ │ │ = Right(Int) -//│ │ > │ │ = Right(Int) -//│ │ > │ = Right(Int) -//│ │ > │ ? argsOrIf inspects |,| |b|?|#:|... [at l.1093] -//│ │ > │ nexttoken => (COMMA,Loc(14,15,nu/OptionalArgs:+7)) -//│ │ > │ ? isOptinoal inspects |,| |b|?|#:|... [at l.1098] -//│ │ > │ flags => None None Some(Loc(8,8,nu/OptionalArgs:+7)) -//│ │ > │ e => Right(Fld(FldFlags(false,false,true),Int)) -//│ │ > │ body => Int Var(Int) -//│ │ > │ ? argsOrIf inspects |,| |b|?|#:|... [at l.1122] -//│ │ > │ ! argsOrIf consumes |,| [at l.1128] -//│ │ > │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1048] -//│ │ > │ │ ? argsOrIf inspects | |b|?|#:| |... [at l.1049] -//│ │ > │ │ ! argsOrIf consumes | | [at l.1058] -//│ │ > │ │ @ argsOrIf(List((Some(a),Right(Fld(FldFlags(false,false,true),Int)))),List()) [at l.1048] -//│ │ > │ │ │ ? argsOrIf inspects |b|?|#:| |Int| [at l.1049] -//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.515] -//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.515] -//│ │ > │ │ │ ? yeetSpaces inspects |b|?|#:| |Int| [at l.515] -//│ │ > │ │ │ ! x$60 consumes |b| [at l.1081] -//│ │ > │ │ │ ! x$60 consumes |?| [at l.1082] -//│ │ > │ │ │ ! x$60 consumes |#:| [at l.1083] -//│ │ > │ │ │ @ exprOrIf(1,true) [at l.1092] -//│ │ > │ │ │ │ ? exprOrIf inspects | |Int| [at l.561] -//│ │ > │ │ │ │ ! exprOrIf consumes | | [at l.563] -//│ │ > │ │ │ │ @ exprOrIf(1,true) [at l.564] -//│ │ > │ │ │ │ │ ? exprOrIf inspects |Int| [at l.561] -//│ │ > │ │ │ │ │ ! exprOrIf consumes |Int| [at l.580] -//│ │ > │ │ │ │ │ @ exprCont(1,`Int`,false) [at l.581] -//│ │ > │ │ │ │ │ │ ? exprCont inspects || [at l.737] -//│ │ > │ │ │ │ │ = Right(Int) -//│ │ > │ │ │ │ = Right(Int) -//│ │ > │ │ │ = Right(Int) -//│ │ > │ │ │ ? argsOrIf inspects || [at l.1093] -//│ │ > │ │ │ ? isOptinoal inspects || [at l.1098] -//│ │ > │ │ │ flags => None None Some(Loc(17,17,nu/OptionalArgs:+7)) -//│ │ > │ │ │ e => Right(Fld(FldFlags(false,false,true),Int)) -//│ │ > │ │ │ body => Int Var(Int) -//│ │ > │ │ │ ? argsOrIf inspects || [at l.1122] -//│ │ > │ │ = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) -//│ │ > │ = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) -//│ │ > = List((Some(a),Right(Fld(FldFlags(false,false,true),Int))), (Some(b),Right(Fld(FldFlags(false,false,true),Int)))) -//│ │ > ? concludeWith inspects || [at l.87] -//│ │ > Concluded with List((Some(a),Fld(FldFlags(false,false,true),Int)), (Some(b),Fld(FldFlags(false,false,true),Int))) -//│ │ @ funParams(()) [at l.528] -//│ │ │ ? yeetSpaces inspects | |#=| |a| |... [at l.515] -//│ │ │ ! yeetSpaces consumes | | [at l.515] -//│ │ │ Here, (not) creating the params! List() -//│ │ = List() -//│ │ Here, creating the params! List(a: Int,? b: Int,?) Tup(a: Var(Int), b: Var(Int)) -//│ = List(a: Int,? b: Int,?) -//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.515] -//│ ? yeetSpaces inspects |#=| |a| |+|... [at l.515] -//│ ! t consumes |#=| [at l.475] -//│ @ expr(0,true) [at l.476] -//│ │ @ exprOrIf(0,true) [at l.546] -//│ │ │ ? exprOrIf inspects | |a| |+| |... [at l.561] -//│ │ │ ! exprOrIf consumes | | [at l.563] -//│ │ │ @ exprOrIf(0,true) [at l.564] -//│ │ │ │ ? exprOrIf inspects |a| |+| |b| [at l.561] -//│ │ │ │ ! exprOrIf consumes |a| [at l.580] -//│ │ │ │ @ exprCont(0,`a`,false) [at l.581] -//│ │ │ │ │ ? exprCont inspects | |+| |b| [at l.737] -//│ │ │ │ │ ! exprCont consumes | | [at l.783] -//│ │ │ │ │ @ exprCont(0,`a`,false) [at l.784] -//│ │ │ │ │ │ ? exprCont inspects |+| |b| [at l.737] -//│ │ │ │ │ │ ! exprCont consumes |+| [at l.746] -//│ │ │ │ │ │ @ exprOrIf(18,true) [at l.749] -//│ │ │ │ │ │ │ ? exprOrIf inspects | |b| [at l.561] -//│ │ │ │ │ │ │ ! exprOrIf consumes | | [at l.563] -//│ │ │ │ │ │ │ @ exprOrIf(18,true) [at l.564] -//│ │ │ │ │ │ │ │ ? exprOrIf inspects |b| [at l.561] -//│ │ │ │ │ │ │ │ ! exprOrIf consumes |b| [at l.580] -//│ │ │ │ │ │ │ │ @ exprCont(18,`b`,false) [at l.581] -//│ │ │ │ │ │ │ │ │ ? exprCont inspects || [at l.737] -//│ │ │ │ │ │ │ │ = Right(b) -//│ │ │ │ │ │ │ = Right(b) -//│ │ │ │ │ │ = Right(b) -//│ │ │ │ │ │ @ exprCont(0,`+ (a,) (b,)`,false) [at l.753] -//│ │ │ │ │ │ │ ? exprCont inspects || [at l.737] -//│ │ │ │ │ │ = Right(+ (a,) (b,)) -//│ │ │ │ │ = Right(+ (a,) (b,)) -//│ │ │ │ = Right(+ (a,) (b,)) -//│ │ │ = Right(+ (a,) (b,)) -//│ │ = Right(+ (a,) (b,)) -//│ │ result => + (a,) (b,) ## App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))) -//│ │ result toType => Right(AppliedType(TypeName(+),List(Tuple(List((None,Field(None,TypeName(a),false)))), Tuple(List((None,Field(None,TypeName(b),false))))))) -//│ = + (a,) (b,) -//│ ? yeetSpaces inspects || [at l.515] -//│ ? parseAll inspects || [at l.76] -//│ Parsed: fun f1 = (a: Int,? b: Int,?) => + (a,) (b,); +//│ 0. Typing TypingUnit(List(fun f1 = (a: Int?, b: Int?,) => + (a,) (b,))) +//│ | 0. Created lazy type info for fun f1 = (a: Int?, b: Int?,) => + (a,) (b,) +//│ | Completing fun f1 = (a: Int?, b: Int?,) => + (a,) (b,) +//│ | | UNSTASHING... (out) +//│ | | Type params +//│ | | UNSTASHING... (out) +//│ | | Params +//│ | | 1. Typing term (a: Int?, b: Int?,) => + (a,) (b,) +//│ | | | 1. Typing pattern a: Int?, b: Int?, +//│ | | | | HERE, good! +//│ | | | | 1. Typing pattern a : Int +//│ | | | | | Typing type TypeName(Int) +//│ | | | | | | vars=Map() newDefsInfo=Map() +//│ | | | | | | 1. type TypeName(Int) +//│ | | | | | | | typename case?? +//│ | | | | | | => Int +//│ | | | | | => Int ——— +//│ | | | | 1. : Int +//│ | | | | opt is => true +//│ | | | | case #2 +//│ | | | | 1. Typing pattern b : Int +//│ | | | | | Typing type TypeName(Int) +//│ | | | | | | vars=Map() newDefsInfo=Map() +//│ | | | | | | 1. type TypeName(Int) +//│ | | | | | | | typename case?? +//│ | | | | | | => Int +//│ | | | | | => Int ——— +//│ | | | | 1. : Int +//│ | | | | opt is => true +//│ | | | | case #2 +//│ | | | 1. : (a: Int?, b: Int?,) +//│ | | | 1. Typing term + (a,) (b,) +//│ | | | | 1. Typing term + (a,) +//│ | | | | | 1. Typing term + +//│ | | | | | 1. : (Int -> (Int -> Int)) +//│ | | | | | 1. Typing term a +//│ | | | | | 1. : Int +//│ | | | | | CONSTRAIN (Int -> (Int -> Int)) α29') +//│ | | | | | where +//│ | | | | | 1. C (Int -> (Int -> Int)) α29') (0) +//│ | | | | | | 1. C (Int,) Int) α30') +//│ | | | | where +//│ α29' :> (Int -> Int) +//│ | | | | 1. C α29' α30') (0) +//│ | | | | | NEW α29' UB (1) +//│ | | | | | 1. C (Int -> Int) α30') (2) +//│ | | | | | | 1. C (Int,) α30') +//│ | | UNSTASHING... (out) +//│ | | CONSTRAIN ((a: Int?, b: Int?,) -> α30') Int +//│ | | 1. C ((a: Int?, b: Int?,) -> α30') + (a,) (b,),((a: Int?, b: Int?,) -> α30')) where +//│ α30' :> Int +//│ | Typing unit statements +//│ | : None +//│ ======== TYPED ======== +//│ fun f1: ‹∀ 0. ((a: Int?, b: Int?,) -> α30')› where +//│ | α30' :> Int //│ fun f1: (a: Int, b: Int,) -> Int @@ -211,48 +163,49 @@ let y: C1 = x //│ res //│ = [ 1, 2, 3 ] +// Typing of [Int, Int?] is ok, but constraining is not :d -[1, 2]: [Int, (Int | C1)?] -//│ 0. Typing TypingUnit(List('(' 1, 2, ')' : (Int, Int | C1,))) +[1, 2]: [Int, Int?] +//│ 0. Typing TypingUnit(List('(' 1, 2, ')' : (Int, Int,))) //│ | Typing unit statements -//│ | | 0. Typing term '(' 1, 2, ')' : (Int, Int | C1,) +//│ | | 0. Typing term '(' 1, 2, ')' : (Int, Int,) //│ | | | typing-trm-here!!! '(' 1, 2, ')' //│ | | | 0. Typing term '(' 1, 2, ')' //│ | | | | 0. Typing term 1, 2, +//│ | | | | | HERE, good! //│ | | | | | 0. Typing term 1 //│ | | | | | 0. : #1 +//│ | | | | | opt is => false +//│ | | | | | case #2 //│ | | | | | 0. Typing term 2 //│ | | | | | 0. : #2 +//│ | | | | | opt is => false +//│ | | | | | case #2 //│ | | | | 0. : (#1, #2,) //│ | | | 0. : (#1, #2,) -//│ | | | typing-ty-here!!! Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,Union(TypeName(Int),TypeName(C1)),true)))) -//│ | | | Typing type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,Union(TypeName(Int),TypeName(C1)),true)))) +//│ | | | typing-ty-here!!! Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) +//│ | | | Typing type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) //│ | | | | vars=Map() newDefsInfo=Map() -//│ | | | | 0. type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,Union(TypeName(Int),TypeName(C1)),true)))) +//│ | | | | 0. type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) //│ | | | | | typing tuple!!! //│ | | | | | 0. type TypeName(Int) //│ | | | | | | typename case?? //│ | | | | | => Int -//│ | | | | | 0. type Union(TypeName(Int),TypeName(C1)) -//│ | | | | | | 0. type TypeName(Int) -//│ | | | | | | | typename case?? -//│ | | | | | | => Int -//│ | | | | | | 0. type TypeName(C1) -//│ | | | | | | | typename case?? -//│ | | | | | | => C1 -//│ | | | | | => (Int | C1) -//│ | | | | => (Int, (Int | C1)?,) -//│ | | | => (Int, (Int | C1)?,) ——— +//│ | | | | | 0. type TypeName(Int) +//│ | | | | | | typename case?? +//│ | | | | | => Int +//│ | | | | => (Int, Int?,) +//│ | | | => (Int, Int?,) ——— //│ | | | constraining!!! -//│ | | | CONSTRAIN (#1, #2,) , #2,) , #2,) , #2,) │ │ = Right(1) //│ │ > │ = Right(1) //│ │ > │ ? argsOrIf inspects |,| |2| [at l.1093] -//│ │ > │ nexttoken => (COMMA,Loc(2,3,nu/OptionalArgs:+260)) +//│ │ > │ nexttoken => (COMMA,Loc(2,3,nu/OptionalArgs:+213)) //│ │ > │ ? isOptinoal inspects |,| |2| [at l.1098] //│ │ > │ flags => None None None //│ │ > │ e => Right(Fld(FldFlags(false,false,false),1)) @@ -336,7 +289,7 @@ let y: C1 = x //│ │ │ │ │ │ > │ │ = Right(Int) //│ │ │ │ │ │ > │ = Right(Int) //│ │ │ │ │ │ > │ ? argsOrIf inspects |,| |Int|,| |... [at l.1093] -//│ │ │ │ │ │ > │ nexttoken => (COMMA,Loc(12,13,nu/OptionalArgs:+260)) +//│ │ │ │ │ │ > │ nexttoken => (COMMA,Loc(12,13,nu/OptionalArgs:+213)) //│ │ │ │ │ │ > │ ? isOptinoal inspects |,| |Int|,| |... [at l.1098] //│ │ │ │ │ │ > │ flags => None None None //│ │ │ │ │ │ > │ e => Right(Fld(FldFlags(false,false,false),Int)) @@ -359,7 +312,7 @@ let y: C1 = x //│ │ │ │ │ │ > │ │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects |,| |Int|?| [at l.1093] -//│ │ │ │ │ │ > │ │ │ nexttoken => (COMMA,Loc(17,18,nu/OptionalArgs:+260)) +//│ │ │ │ │ │ > │ │ │ nexttoken => (COMMA,Loc(17,18,nu/OptionalArgs:+213)) //│ │ │ │ │ │ > │ │ │ ? isOptinoal inspects |,| |Int|?| [at l.1098] //│ │ │ │ │ │ > │ │ │ flags => None None None //│ │ │ │ │ │ > │ │ │ e => Right(Fld(FldFlags(false,false,false),Int)) @@ -382,7 +335,7 @@ let y: C1 = x //│ │ │ │ │ │ > │ │ │ │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ │ │ ? argsOrIf inspects |?| [at l.1093] -//│ │ │ │ │ │ > │ │ │ │ │ nexttoken => (IDENT(?,true),Loc(22,22,nu/OptionalArgs:+260)) +//│ │ │ │ │ │ > │ │ │ │ │ nexttoken => (IDENT(?,true),Loc(22,22,nu/OptionalArgs:+213)) //│ │ │ │ │ │ > │ │ │ │ │ ? isOptinoal inspects |?| [at l.1098] //│ │ │ │ │ │ > │ │ │ │ │ ! isOptinoal consumes |?| [at l.1100] //│ │ │ │ │ │ > │ │ │ │ │ flags => None None None @@ -396,14 +349,14 @@ let y: C1 = x //│ │ │ │ │ │ > = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) //│ │ │ │ │ │ > ? concludeWith inspects || [at l.87] //│ │ │ │ │ │ > Concluded with List((None,Fld(FldFlags(false,false,false),Int)), (None,Fld(FldFlags(false,false,false),Int)), (None,Fld(FldFlags(false,false,true),Int))) -//│ │ │ │ │ │ @ exprCont(0,`'(' Int, Int, Int,? ')'`,false) [at l.608] +//│ │ │ │ │ │ @ exprCont(0,`'(' Int, Int, Int?, ')'`,false) [at l.608] //│ │ │ │ │ │ │ ? exprCont inspects || [at l.737] -//│ │ │ │ │ │ = Right('(' Int, Int, Int,? ')') -//│ │ │ │ │ = Right('(' Int, Int, Int,? ')') -//│ │ │ │ = Right('(' Int, Int, Int,? ')') -//│ │ │ │ result => '(' Int, Int, Int,? ')' ## Bra(rcd = false, Tup(_: Var(Int), _: Var(Int), _: Var(Int))) +//│ │ │ │ │ │ = Right('(' Int, Int, Int?, ')') +//│ │ │ │ │ = Right('(' Int, Int, Int?, ')') +//│ │ │ │ = Right('(' Int, Int, Int?, ')') +//│ │ │ │ result => '(' Int, Int, Int?, ')' ## Bra(rcd = false, Tup(_: Var(Int), _: Var(Int), _: Var(Int))) //│ │ │ │ result toType => Right(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) -//│ │ │ = '(' Int, Int, Int,? ')' +//│ │ │ = '(' Int, Int, Int?, ')' //│ │ │ asc => '(' 1, 2, ')' : (Int, Int, Int,) //│ │ = Right('(' 1, 2, ')' : (Int, Int, Int,)) //│ = Right('(' 1, 2, ')' : (Int, Int, Int,)) @@ -411,14 +364,15 @@ let y: C1 = x //│ ? parseAll inspects || [at l.76] //│ Parsed: '(' 1, 2, ')' : (Int, Int, Int,); //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.260: [1, 2]: [Int, Int, Int?] +//│ ║ l.213: [1, 2]: [Int, Int, Int?] //│ ║ ^^^^^^ //│ ╟── tuple literal of type `(1, 2,)` does not match type `(Int, Int, Int,)` -//│ ║ l.260: [1, 2]: [Int, Int, Int?] +//│ ║ l.213: [1, 2]: [Int, Int, Int?] //│ ║ ^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.260: [1, 2]: [Int, Int, Int?] +//│ ║ l.213: [1, 2]: [Int, Int, Int?] //│ ╙── ^^^^^^^^^^^^^^^^ //│ (Int, Int, Int,) //│ res //│ = [ 1, 2 ] + From 723a9a587dbde0b67c47f82a5bedc96f90f64719 Mon Sep 17 00:00:00 2001 From: Lionel Parreaux Date: Fri, 22 Sep 2023 12:55:32 +0800 Subject: [PATCH 10/37] WIP Add helpful test cases --- .../scala/mlscript/ConstraintSolver.scala | 2 +- .../main/scala/mlscript/TyperHelpers.scala | 2 + shared/src/test/diff/nu/OptionalArgs.mls | 406 ++++++++++++++---- 3 files changed, 329 insertions(+), 81 deletions(-) diff --git a/shared/src/main/scala/mlscript/ConstraintSolver.scala b/shared/src/main/scala/mlscript/ConstraintSolver.scala index c25076bd3..c91946ce1 100644 --- a/shared/src/main/scala/mlscript/ConstraintSolver.scala +++ b/shared/src/main/scala/mlscript/ConstraintSolver.scala @@ -845,7 +845,7 @@ class ConstraintSolver extends NormalForms { self: Typer => } - case (TupleType(fs0), TupleType(fs1)) if fs0.size === fs1.size => // TODO generalize (coerce compatible tuples) + case (TupleType(fs0), TupleType(fs1)) if fs0.size === fs1.size => // TODO[optional-fields] generalize (coerce compatible tuples) fs0.lazyZip(fs1).foreach { case ((ln, l), (rn, r)) => ln.foreach { ln => rn.foreach { rn => if (ln =/= rn) err( diff --git a/shared/src/main/scala/mlscript/TyperHelpers.scala b/shared/src/main/scala/mlscript/TyperHelpers.scala index fcfba6562..d9096fcf5 100644 --- a/shared/src/main/scala/mlscript/TyperHelpers.scala +++ b/shared/src/main/scala/mlscript/TyperHelpers.scala @@ -427,6 +427,7 @@ abstract class TyperHelpers { Typer: Typer => case (RecordType(fs1), RecordType(fs2)) => RecordType(mergeSortedMap(fs1, fs2)(_ && _).toList)(prov) case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) => + // TODO[optional-fields] update this condition if (fs0.sizeCompare(fs1) =/= 0) BotType else TupleType(tupleIntersection(fs0, fs1))(t0.prov) case _ if !swapped => that & (this, prov, swapped = true) @@ -488,6 +489,7 @@ abstract class TyperHelpers { Typer: Typer => case (_: TypeTag, _: TypeTag) | (_: TV, _: TV) if this === that => true case (ab: ArrayBase, at: ArrayType) => ab.inner <:< at.inner case (TupleType(fs1), TupleType(fs2)) => + // TODO[optional-fields] generalize: handle optionality; eg: [Int] <:< [Int, Int?] fs1.sizeCompare(fs2) === 0 && fs1.lazyZip(fs2).forall { case ((_, ty1), (_, ty2)) => ty1 <:< ty2 } diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 91161986d..9f56a7065 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -4,81 +4,145 @@ // TODO: there is problem when the is SPACE after '?' // Typing of (a?: Int, b?: Int) is ok, but constraining is not -:d +// :d +:ds fun f1(a?: Int, b?: Int) = a + b -//│ 0. Typing TypingUnit(List(fun f1 = (a: Int?, b: Int?,) => + (a,) (b,))) -//│ | 0. Created lazy type info for fun f1 = (a: Int?, b: Int?,) => + (a,) (b,) -//│ | Completing fun f1 = (a: Int?, b: Int?,) => + (a,) (b,) -//│ | | UNSTASHING... (out) -//│ | | Type params -//│ | | UNSTASHING... (out) -//│ | | Params -//│ | | 1. Typing term (a: Int?, b: Int?,) => + (a,) (b,) -//│ | | | 1. Typing pattern a: Int?, b: Int?, -//│ | | | | HERE, good! -//│ | | | | 1. Typing pattern a : Int -//│ | | | | | Typing type TypeName(Int) -//│ | | | | | | vars=Map() newDefsInfo=Map() -//│ | | | | | | 1. type TypeName(Int) -//│ | | | | | | | typename case?? -//│ | | | | | | => Int -//│ | | | | | => Int ——— -//│ | | | | 1. : Int -//│ | | | | opt is => true -//│ | | | | case #2 -//│ | | | | 1. Typing pattern b : Int -//│ | | | | | Typing type TypeName(Int) -//│ | | | | | | vars=Map() newDefsInfo=Map() -//│ | | | | | | 1. type TypeName(Int) -//│ | | | | | | | typename case?? -//│ | | | | | | => Int -//│ | | | | | => Int ——— -//│ | | | | 1. : Int -//│ | | | | opt is => true -//│ | | | | case #2 -//│ | | | 1. : (a: Int?, b: Int?,) -//│ | | | 1. Typing term + (a,) (b,) -//│ | | | | 1. Typing term + (a,) -//│ | | | | | 1. Typing term + -//│ | | | | | 1. : (Int -> (Int -> Int)) -//│ | | | | | 1. Typing term a -//│ | | | | | 1. : Int -//│ | | | | | CONSTRAIN (Int -> (Int -> Int)) α29') -//│ | | | | | where -//│ | | | | | 1. C (Int -> (Int -> Int)) α29') (0) -//│ | | | | | | 1. C (Int,) Int) α30') -//│ | | | | where -//│ α29' :> (Int -> Int) -//│ | | | | 1. C α29' α30') (0) -//│ | | | | | NEW α29' UB (1) -//│ | | | | | 1. C (Int -> Int) α30') (2) -//│ | | | | | | 1. C (Int,) α30') -//│ | | UNSTASHING... (out) -//│ | | CONSTRAIN ((a: Int?, b: Int?,) -> α30') + (a,) (b,),((a: Int?, b: Int?,) -> α30')) +//│ None) +//│ where: //│ α30' :> Int -//│ | | 1. C ((a: Int?, b: Int?,) -> α30') + (a,) (b,),((a: Int?, b: Int?,) -> α30')) where -//│ α30' :> Int -//│ | Typing unit statements -//│ | : None -//│ ======== TYPED ======== -//│ fun f1: ‹∀ 0. ((a: Int?, b: Int?,) -> α30')› where -//│ | α30' :> Int +//│ allVarPols: +α30' +//│ Renewed α30' ~> α30_32' +//│ ⬤ Cleaned up: TypedTypingUnit( +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int, b: Int,) -> α30_32')) +//│ None) +//│ where: +//│ α30_32' :> Int +//│ allVarPols: +α30_32' +//│ consed: Map((true,Int) -> α30_32') +//│ ⬤ Unskid: TypedTypingUnit( +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int, b: Int,) -> α30_32')) +//│ None) +//│ where: +//│ α30_32' :> Int +//│ analyze1[+] ((a: Int, b: Int,) -> α30_32') +//│ | analyze1[+;-] (a: Int, b: Int,) +//│ | | analyze1[+;-] Int +//│ | | analyze1[+;-] Int +//│ | analyze1[+] α30_32' +//│ | | analyze1[+;@[+](0)] Int +//│ [inv] +//│ [nums] +α30_32' 1 +//│ analyze2[+] ((a: Int, b: Int,) -> α30_32') +//│ | analyze2[+;-] (a: Int, b: Int,) +//│ | | analyze2[+;-] Int +//│ | | analyze2[+;-] Int +//│ | analyze2[+] α30_32' +//│ | | >> Processing α30_32' at [+] +//│ | | go α30_32' () +//│ | | | go Int (α30_32') +//│ | | >> Occurrences HashSet(α30_32', Int) +//│ | | >>>> occs[+α30_32'] := HashSet(α30_32', Int) <~ None +//│ | | analyze2[+] Int +//│ [occs] +α30_32' {α30_32',Int} +//│ [vars] TreeSet(α30_32') +//│ [rec] Set() +//│ 0[1] α30_32' +//│ 1[!] α30_32' +//│ [sub] α30_32' -> None +//│ [bounds] +//│ α30_32' :> Int +//│ [rec] Set() +//│ transform[+] ((a: Int, b: Int,) -> α30_32') () + None +//│ | transform[-] (a: Int, b: Int,) () +;- None +//│ | | transform[-] Int () +;- None +//│ | | ~> Int +//│ | | transform[-] Int () +;- None +//│ | | ~> Int +//│ | ~> (a: Int, b: Int,) +//│ | transform[+] α30_32' () + None +//│ | | -> bound Some(true) +//│ | | transform[+] Int (α30_32') +;@[+](0) None +//│ | | ~> Int +//│ | ~> Int +//│ ~> ((a: Int, b: Int,) -> Int) +//│ ⬤ Type after simplification: TypedTypingUnit( +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int, b: Int,) -> Int)) +//│ None) +//│ where: +//│ allVarPols: +//│ normLike[+] TypedTypingUnit( +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int, b: Int,) -> Int)) +//│ None) +//│ | norm[+] ((a: Int, b: Int,) -> Int) +//│ | | DNF: DNF(0, ((a: Int, b: Int,) -> Int){}) +//│ | | norm[-] (a: Int, b: Int,) +//│ | | | DNF: DNF(0, (a: Int, b: Int,){}) +//│ | | | norm[-] Int +//│ | | | | DNF: DNF(0, #Int{}) +//│ | | | ~> #Int +//│ | | | norm[-] Int +//│ | | | | DNF: DNF(0, #Int{}) +//│ | | | ~> #Int +//│ | | ~> (a: #Int, b: #Int,) +//│ | | norm[+] Int +//│ | | | DNF: DNF(0, #Int{}) +//│ | | ~> #Int +//│ | ~> ((a: #Int, b: #Int,) -> #Int) +//│ ⬤ Normalized: TypedTypingUnit( +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ None) +//│ where: +//│ allVarPols: +//│ ⬤ Cleaned up: TypedTypingUnit( +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ None) +//│ where: +//│ allVarPols: +//│ consed: Map() +//│ ⬤ Unskid: TypedTypingUnit( +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ None) +//│ where: +//│ analyze1[+] ((a: #Int, b: #Int,) -> #Int) +//│ | analyze1[+;-] (a: #Int, b: #Int,) +//│ | | analyze1[+;-] #Int +//│ | | analyze1[+;-] #Int +//│ | analyze1[+] #Int +//│ [inv] +//│ [nums] +//│ analyze2[+] ((a: #Int, b: #Int,) -> #Int) +//│ | analyze2[+;-] (a: #Int, b: #Int,) +//│ | | analyze2[+;-] #Int +//│ | | analyze2[+;-] #Int +//│ | analyze2[+] #Int +//│ [occs] +//│ [vars] TreeSet() +//│ [rec] Set() +//│ [sub] +//│ [bounds] +//│ [rec] Set() +//│ transform[+] ((a: #Int, b: #Int,) -> #Int) () + None +//│ | transform[-] (a: #Int, b: #Int,) () +;- None +//│ | | transform[-] #Int () +;- None +//│ | | ~> #Int +//│ | | transform[-] #Int () +;- None +//│ | | ~> #Int +//│ | ~> (a: #Int, b: #Int,) +//│ | transform[+] #Int () + None +//│ | ~> #Int +//│ ~> ((a: #Int, b: #Int,) -> #Int) +//│ ⬤ Resim: TypedTypingUnit( +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ None) +//│ where: +//│ allVarPols: +//│ [subs] HashMap() +//│ ⬤ Factored: TypedTypingUnit( +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ None) +//│ where: //│ fun f1: (a: Int, b: Int,) -> Int @@ -209,6 +273,104 @@ let y: C1 = x //│ res //│ = [ 1, 2 ] +:d +[1]: [Int, Int?] +//│ 0. Typing TypingUnit(List('(' 1, ')' : (Int, Int,))) +//│ | Typing unit statements +//│ | | 0. Typing term '(' 1, ')' : (Int, Int,) +//│ | | | typing-trm-here!!! '(' 1, ')' +//│ | | | 0. Typing term '(' 1, ')' +//│ | | | | 0. Typing term 1, +//│ | | | | | HERE, good! +//│ | | | | | 0. Typing term 1 +//│ | | | | | 0. : #1 +//│ | | | | | opt is => false +//│ | | | | | case #2 +//│ | | | | 0. : (#1,) +//│ | | | 0. : (#1,) +//│ | | | typing-ty-here!!! Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) +//│ | | | Typing type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) +//│ | | | | vars=Map() newDefsInfo=Map() +//│ | | | | 0. type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) +//│ | | | | | typing tuple!!! +//│ | | | | | 0. type TypeName(Int) +//│ | | | | | | typename case?? +//│ | | | | | => Int +//│ | | | | | 0. type TypeName(Int) +//│ | | | | | | typename case?? +//│ | | | | | => Int +//│ | | | | => (Int, Int?,) +//│ | | | => (Int, Int?,) ——— +//│ | | | constraining!!! +//│ | | | CONSTRAIN (#1,) ,) ,) <: (Int, Int?,) +//│ | | | | allVarPols: +//│ | | | | normLike[-] (Int, Int,) +//│ | | | | | norm[-] (Int, Int,) +//│ | | | | | | DNF: DNF(0, (Int, Int,){}) +//│ | | | | | | norm[-] Int +//│ | | | | | | | DNF: DNF(0, #Int{}) +//│ | | | | | | ~> #Int +//│ | | | | | | norm[-] Int +//│ | | | | | | | DNF: DNF(0, #Int{}) +//│ | | | | | | ~> #Int +//│ | | | | | ~> (#Int, #Int,) +//│ | | | | allVarPols: +//│ | | | | normLike[+] (#1,) +//│ | | | | | norm[+] (#1,) +//│ | | | | | | DNF: DNF(0, (#1,){}) +//│ | | | | | | norm[+] #1 +//│ | | | | | | | DNF: DNF(0, #1{}) +//│ | | | | | | ~> #1 +//│ | | | | | ~> (#1,) +//│ | | | | CONSTRAIN #error<> │ │ = Right(1) //│ │ > │ = Right(1) //│ │ > │ ? argsOrIf inspects |,| |2| [at l.1093] -//│ │ > │ nexttoken => (COMMA,Loc(2,3,nu/OptionalArgs:+213)) +//│ │ > │ nexttoken => (COMMA,Loc(2,3,nu/OptionalArgs:+375)) //│ │ > │ ? isOptinoal inspects |,| |2| [at l.1098] //│ │ > │ flags => None None None //│ │ > │ e => Right(Fld(FldFlags(false,false,false),1)) @@ -289,7 +451,7 @@ let y: C1 = x //│ │ │ │ │ │ > │ │ = Right(Int) //│ │ │ │ │ │ > │ = Right(Int) //│ │ │ │ │ │ > │ ? argsOrIf inspects |,| |Int|,| |... [at l.1093] -//│ │ │ │ │ │ > │ nexttoken => (COMMA,Loc(12,13,nu/OptionalArgs:+213)) +//│ │ │ │ │ │ > │ nexttoken => (COMMA,Loc(12,13,nu/OptionalArgs:+375)) //│ │ │ │ │ │ > │ ? isOptinoal inspects |,| |Int|,| |... [at l.1098] //│ │ │ │ │ │ > │ flags => None None None //│ │ │ │ │ │ > │ e => Right(Fld(FldFlags(false,false,false),Int)) @@ -312,7 +474,7 @@ let y: C1 = x //│ │ │ │ │ │ > │ │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects |,| |Int|?| [at l.1093] -//│ │ │ │ │ │ > │ │ │ nexttoken => (COMMA,Loc(17,18,nu/OptionalArgs:+213)) +//│ │ │ │ │ │ > │ │ │ nexttoken => (COMMA,Loc(17,18,nu/OptionalArgs:+375)) //│ │ │ │ │ │ > │ │ │ ? isOptinoal inspects |,| |Int|?| [at l.1098] //│ │ │ │ │ │ > │ │ │ flags => None None None //│ │ │ │ │ │ > │ │ │ e => Right(Fld(FldFlags(false,false,false),Int)) @@ -335,7 +497,7 @@ let y: C1 = x //│ │ │ │ │ │ > │ │ │ │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ │ │ = Right(Int) //│ │ │ │ │ │ > │ │ │ │ │ ? argsOrIf inspects |?| [at l.1093] -//│ │ │ │ │ │ > │ │ │ │ │ nexttoken => (IDENT(?,true),Loc(22,22,nu/OptionalArgs:+213)) +//│ │ │ │ │ │ > │ │ │ │ │ nexttoken => (IDENT(?,true),Loc(22,22,nu/OptionalArgs:+375)) //│ │ │ │ │ │ > │ │ │ │ │ ? isOptinoal inspects |?| [at l.1098] //│ │ │ │ │ │ > │ │ │ │ │ ! isOptinoal consumes |?| [at l.1100] //│ │ │ │ │ │ > │ │ │ │ │ flags => None None None @@ -364,15 +526,99 @@ let y: C1 = x //│ ? parseAll inspects || [at l.76] //│ Parsed: '(' 1, 2, ')' : (Int, Int, Int,); //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.213: [1, 2]: [Int, Int, Int?] +//│ ║ l.375: [1, 2]: [Int, Int, Int?] //│ ║ ^^^^^^ //│ ╟── tuple literal of type `(1, 2,)` does not match type `(Int, Int, Int,)` -//│ ║ l.213: [1, 2]: [Int, Int, Int?] +//│ ║ l.375: [1, 2]: [Int, Int, Int?] //│ ║ ^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.213: [1, 2]: [Int, Int, Int?] +//│ ║ l.375: [1, 2]: [Int, Int, Int?] //│ ╙── ^^^^^^^^^^^^^^^^ //│ (Int, Int, Int,) //│ res //│ = [ 1, 2 ] + +// * Harder case: + +:d +fun foo(xs: [Int] & 'a) = xs : [Int, Int?] +//│ 0. Typing TypingUnit(List(fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int,))) +//│ | 0. Created lazy type info for fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int,) +//│ | Completing fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int,) +//│ | | UNSTASHING... (out) +//│ | | Type params +//│ | | UNSTASHING... (out) +//│ | | Params +//│ | | 1. Typing term (xs: & (Int,) ('a,),) => xs : (Int, Int,) +//│ | | | 1. Typing pattern xs: & (Int,) ('a,), +//│ | | | | HERE, good! +//│ | | | | 1. Typing pattern xs : Int & 'a +//│ | | | | | Typing type Inter(TypeName(Int),'a) +//│ | | | | | | vars=Map() newDefsInfo=Map() +//│ | | | | | | 1. type Inter(TypeName(Int),'a) +//│ | | | | | | | 1. type TypeName(Int) +//│ | | | | | | | | typename case?? +//│ | | | | | | | => Int +//│ | | | | | | | 1. type 'a +//│ | | | | | | | => 'a75' +//│ | | | | | | => (Int & 'a75') +//│ | | | | | => (Int & 'a75') ——— 'a75' +//│ | | | | 1. : (Int & 'a75') +//│ | | | | opt is => false +//│ | | | | case #2 +//│ | | | 1. : (xs: (Int & 'a75'),) +//│ | | | 1. Typing term xs : (Int, Int,) +//│ | | | | typing-trm-here!!! xs +//│ | | | | 1. Typing term xs +//│ | | | | 1. : (Int & 'a75') +//│ | | | | typing-ty-here!!! Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) +//│ | | | | Typing type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) +//│ | | | | | vars=Map() newDefsInfo=Map() +//│ | | | | | 1. type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) +//│ | | | | | | typing tuple!!! +//│ | | | | | | 1. type TypeName(Int) +//│ | | | | | | | typename case?? +//│ | | | | | | => Int +//│ | | | | | | 1. type TypeName(Int) +//│ | | | | | | | typename case?? +//│ | | | | | | => Int +//│ | | | | | => (Int, Int?,) +//│ | | | | => (Int, Int?,) ——— +//│ | | | | constraining!!! +//│ | | | | CONSTRAIN (Int & 'a75') {}∧'a75') , #Int,){_2: #Int, _1: #Int}) +//│ | | | | | | DNF DISCHARGE CONSTRAINTS +//│ | | | | | | 1. C 'a75' , #Int,) & {_2: #Int, _1: #Int}) | ~(#Int)) (3) +//│ | | | | | | | NEW 'a75' UB (0) +//│ | | | 1. : (Int, Int?,) +//│ | | 1. : ((xs: (Int & 'a75'),) -> (Int, Int?,)) +//│ | | UNSTASHING... (out) +//│ | | CONSTRAIN ((xs: (Int & 'a75'),) -> (Int, Int?,)) , #Int,) & {_2: #Int, _1: #Int}) | ~(#Int)) +//│ | | 1. C ((xs: (Int & 'a75'),) -> (Int, Int?,)) xs : (Int, Int,),((xs: (Int & 'a75'),) -> (Int, Int?,))) where +//│ 'a75' <: (((#Int, #Int,) & {_2: #Int, _1: #Int}) | ~(#Int)) +//│ | Typing unit statements +//│ | : None +//│ ======== TYPED ======== +//│ fun foo: ‹∀ 0. ((xs: (Int & 'a75'),) -> (Int, Int?,))› where +//│ | 'a75' <: (((#Int, #Int,) & {_2: #Int, _1: #Int}) | ~(#Int)) +//│ fun foo: (xs: nothing,) -> (Int, Int,) + + + +// TODO later: update normal form construction + +fun foo: [Int] | [Int, Int?] +//│ fun foo: Array[Int] & {_1: Int} + +fun foo: [Int] & [Int, Int?] +//│ fun foo: nothing + + From 5f5fdfd0cde71e191d741194a3bfe18ec8cf395f Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Sat, 23 Sep 2023 13:31:10 +0800 Subject: [PATCH 11/37] fix type show --- shared/src/main/scala/mlscript/helpers.scala | 2 +- shared/src/test/diff/nu/OptionalArgs.mls | 28 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index b47d640e0..457fa8bde 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -55,7 +55,7 @@ trait TypeLikeImpl extends Located { self: TypeLike => case Splice(fs) => fs.map{case L(l) => s"...${l.showIn(ctx, 0)}" case R(r) => s"${showField(r, ctx)}"}.mkString("(", ", ", ")") case Tuple(fs) => - fs.map(nt => s"${nt._2.mutStr}${nt._1.fold("")(_.name + ": ")}${showField(nt._2, ctx)},").mkString("(", " ", ")") + fs.map(nt => s"${nt._2.mutStr}${nt._1.fold("")(_.name + ": ")}${showField(nt._2, ctx)}${if (nt._2.opt) "?" else ""},").mkString("(", " ", ")") case Union(TypeName("true"), TypeName("false")) | Union(TypeName("false"), TypeName("true")) => TypeName("bool").showIn(ctx, 0) // case Union(l, r) => parensIf(l.showIn(ctx, 20) + " | " + r.showIn(ctx, 20), outerPrec > 20) diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 9f56a7065..43872ba58 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -230,9 +230,9 @@ let y: C1 = x // Typing of [Int, Int?] is ok, but constraining is not :d [1, 2]: [Int, Int?] -//│ 0. Typing TypingUnit(List('(' 1, 2, ')' : (Int, Int,))) +//│ 0. Typing TypingUnit(List('(' 1, 2, ')' : (Int, Int?,))) //│ | Typing unit statements -//│ | | 0. Typing term '(' 1, 2, ')' : (Int, Int,) +//│ | | 0. Typing term '(' 1, 2, ')' : (Int, Int?,) //│ | | | typing-trm-here!!! '(' 1, 2, ')' //│ | | | 0. Typing term '(' 1, 2, ')' //│ | | | | 0. Typing term 1, 2, @@ -275,9 +275,9 @@ let y: C1 = x :d [1]: [Int, Int?] -//│ 0. Typing TypingUnit(List('(' 1, ')' : (Int, Int,))) +//│ 0. Typing TypingUnit(List('(' 1, ')' : (Int, Int?,))) //│ | Typing unit statements -//│ | | 0. Typing term '(' 1, ')' : (Int, Int,) +//│ | | 0. Typing term '(' 1, ')' : (Int, Int?,) //│ | | | typing-trm-here!!! '(' 1, ')' //│ | | | 0. Typing term '(' 1, ')' //│ | | | | 0. Typing term 1, @@ -519,12 +519,12 @@ let y: C1 = x //│ │ │ │ result => '(' Int, Int, Int?, ')' ## Bra(rcd = false, Tup(_: Var(Int), _: Var(Int), _: Var(Int))) //│ │ │ │ result toType => Right(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) //│ │ │ = '(' Int, Int, Int?, ')' -//│ │ │ asc => '(' 1, 2, ')' : (Int, Int, Int,) -//│ │ = Right('(' 1, 2, ')' : (Int, Int, Int,)) -//│ = Right('(' 1, 2, ')' : (Int, Int, Int,)) +//│ │ │ asc => '(' 1, 2, ')' : (Int, Int, Int?,) +//│ │ = Right('(' 1, 2, ')' : (Int, Int, Int?,)) +//│ = Right('(' 1, 2, ')' : (Int, Int, Int?,)) //│ ? yeetSpaces inspects || [at l.515] //│ ? parseAll inspects || [at l.76] -//│ Parsed: '(' 1, 2, ')' : (Int, Int, Int,); +//│ Parsed: '(' 1, 2, ')' : (Int, Int, Int?,); //│ ╔══[ERROR] Type mismatch in type ascription: //│ ║ l.375: [1, 2]: [Int, Int, Int?] //│ ║ ^^^^^^ @@ -543,14 +543,14 @@ let y: C1 = x :d fun foo(xs: [Int] & 'a) = xs : [Int, Int?] -//│ 0. Typing TypingUnit(List(fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int,))) -//│ | 0. Created lazy type info for fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int,) -//│ | Completing fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int,) +//│ 0. Typing TypingUnit(List(fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,))) +//│ | 0. Created lazy type info for fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,) +//│ | Completing fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,) //│ | | UNSTASHING... (out) //│ | | Type params //│ | | UNSTASHING... (out) //│ | | Params -//│ | | 1. Typing term (xs: & (Int,) ('a,),) => xs : (Int, Int,) +//│ | | 1. Typing term (xs: & (Int,) ('a,),) => xs : (Int, Int?,) //│ | | | 1. Typing pattern xs: & (Int,) ('a,), //│ | | | | HERE, good! //│ | | | | 1. Typing pattern xs : Int & 'a @@ -568,7 +568,7 @@ fun foo(xs: [Int] & 'a) = xs : [Int, Int?] //│ | | | | opt is => false //│ | | | | case #2 //│ | | | 1. : (xs: (Int & 'a75'),) -//│ | | | 1. Typing term xs : (Int, Int,) +//│ | | | 1. Typing term xs : (Int, Int?,) //│ | | | | typing-trm-here!!! xs //│ | | | | 1. Typing term xs //│ | | | | 1. : (Int & 'a75') @@ -602,7 +602,7 @@ fun foo(xs: [Int] & 'a) = xs : [Int, Int?] //│ | | 1. C ((xs: (Int & 'a75'),) -> (Int, Int?,)) xs : (Int, Int,),((xs: (Int & 'a75'),) -> (Int, Int?,))) where +//│ | Completed TypedNuFun(0,fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,),((xs: (Int & 'a75'),) -> (Int, Int?,))) where //│ 'a75' <: (((#Int, #Int,) & {_2: #Int, _1: #Int}) | ~(#Int)) //│ | Typing unit statements //│ | : None From d8a8ed4879df8af9265e0f8469cdfd01c970b559 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Sat, 23 Sep 2023 14:04:35 +0800 Subject: [PATCH 12/37] add subtype check for subtyping with <:< --- .../scala/mlscript/ConstraintSolver.scala | 5 +- .../main/scala/mlscript/TyperHelpers.scala | 11 +- shared/src/test/diff/nu/OptionalArgs.mls | 355 +----------------- 3 files changed, 22 insertions(+), 349 deletions(-) diff --git a/shared/src/main/scala/mlscript/ConstraintSolver.scala b/shared/src/main/scala/mlscript/ConstraintSolver.scala index c91946ce1..c50775997 100644 --- a/shared/src/main/scala/mlscript/ConstraintSolver.scala +++ b/shared/src/main/scala/mlscript/ConstraintSolver.scala @@ -845,7 +845,9 @@ class ConstraintSolver extends NormalForms { self: Typer => } - case (TupleType(fs0), TupleType(fs1)) if fs0.size === fs1.size => // TODO[optional-fields] generalize (coerce compatible tuples) + case (TupleType(fs0), TupleType(fs1)) if fs0.size === fs1.size => { // TODO[optional-fields] generalize (coerce compatible tuples) + println("case #1") + fs0.lazyZip(fs1).foreach { case ((ln, l), (rn, r)) => ln.foreach { ln => rn.foreach { rn => if (ln =/= rn) err( @@ -855,6 +857,7 @@ class ConstraintSolver extends NormalForms { self: Typer => recLb(r, l) rec(l.ub, r.ub, false) } + } case (t: ArrayBase, a: ArrayType) => recLb(a.inner, t.inner) rec(t.inner.ub, a.inner.ub, false) diff --git a/shared/src/main/scala/mlscript/TyperHelpers.scala b/shared/src/main/scala/mlscript/TyperHelpers.scala index d9096fcf5..795a52895 100644 --- a/shared/src/main/scala/mlscript/TyperHelpers.scala +++ b/shared/src/main/scala/mlscript/TyperHelpers.scala @@ -426,10 +426,13 @@ abstract class TyperHelpers { Typer: Typer => case (_: ClassTag, _: FunctionType) => BotType case (RecordType(fs1), RecordType(fs2)) => RecordType(mergeSortedMap(fs1, fs2)(_ && _).toList)(prov) - case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) => + case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) => { + println("case #2") + // TODO[optional-fields] update this condition if (fs0.sizeCompare(fs1) =/= 0) BotType else TupleType(tupleIntersection(fs0, fs1))(t0.prov) + } case _ if !swapped => that & (this, prov, swapped = true) case (`that`, _) => this case _ if !swapped => that & (this, prov, swapped = true) @@ -488,11 +491,13 @@ abstract class TyperHelpers { Typer: Typer => // case (ClassTag(ErrTypeId, _), _) | (_, ClassTag(ErrTypeId, _)) => true case (_: TypeTag, _: TypeTag) | (_: TV, _: TV) if this === that => true case (ab: ArrayBase, at: ArrayType) => ab.inner <:< at.inner - case (TupleType(fs1), TupleType(fs2)) => + case (TupleType(fs1), TupleType(fs2)) => { // TODO[optional-fields] generalize: handle optionality; eg: [Int] <:< [Int, Int?] - fs1.sizeCompare(fs2) === 0 && fs1.lazyZip(fs2).forall { + println(s"case #3 ${fs1} ${fs2}") + fs1.sizeCompare(fs2) <= 0 && fs1.sizeCompare(fs2.filter(x => !x._2.opt)) >= 0 && fs1.lazyZip(fs2).forall { case ((_, ty1), (_, ty2)) => ty1 <:< ty2 } + } case (RecordType(Nil), _) => TopType <:< that case (_, RecordType(Nil)) => this <:< TopType case (pt1 @ ClassTag(id1, ps1), pt2 @ ClassTag(id2, ps2)) => (id1 === id2) || pt1.parentsST(id2) diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 43872ba58..e7e7ce5f0 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -1,8 +1,5 @@ :NewDefs - -// TODO: there is problem when the is SPACE after '?' - // Typing of (a?: Int, b?: Int) is ok, but constraining is not // :d :ds @@ -146,7 +143,6 @@ fun f1(a?: Int, b?: Int) = a + b //│ fun f1: (a: Int, b: Int,) -> Int - // using space, creates ASC in AST. :p fun f1(a: Int, b: Int) = a + b @@ -177,7 +173,6 @@ f1(1, 2) //│ res //│ = 3 -// checking how typer works. let x = [1, 2] : [Int, Int] //│ let x: (Int, Int,) //│ x @@ -227,118 +222,12 @@ let y: C1 = x //│ res //│ = [ 1, 2, 3 ] -// Typing of [Int, Int?] is ok, but constraining is not -:d [1, 2]: [Int, Int?] -//│ 0. Typing TypingUnit(List('(' 1, 2, ')' : (Int, Int?,))) -//│ | Typing unit statements -//│ | | 0. Typing term '(' 1, 2, ')' : (Int, Int?,) -//│ | | | typing-trm-here!!! '(' 1, 2, ')' -//│ | | | 0. Typing term '(' 1, 2, ')' -//│ | | | | 0. Typing term 1, 2, -//│ | | | | | HERE, good! -//│ | | | | | 0. Typing term 1 -//│ | | | | | 0. : #1 -//│ | | | | | opt is => false -//│ | | | | | case #2 -//│ | | | | | 0. Typing term 2 -//│ | | | | | 0. : #2 -//│ | | | | | opt is => false -//│ | | | | | case #2 -//│ | | | | 0. : (#1, #2,) -//│ | | | 0. : (#1, #2,) -//│ | | | typing-ty-here!!! Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) -//│ | | | Typing type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) -//│ | | | | vars=Map() newDefsInfo=Map() -//│ | | | | 0. type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) -//│ | | | | | typing tuple!!! -//│ | | | | | 0. type TypeName(Int) -//│ | | | | | | typename case?? -//│ | | | | | => Int -//│ | | | | | 0. type TypeName(Int) -//│ | | | | | | typename case?? -//│ | | | | | => Int -//│ | | | | => (Int, Int?,) -//│ | | | => (Int, Int?,) ——— -//│ | | | constraining!!! -//│ | | | CONSTRAIN (#1, #2,) , #2,) -//│ | | | | | opt is => false -//│ | | | | | case #2 -//│ | | | | 0. : (#1,) -//│ | | | 0. : (#1,) -//│ | | | typing-ty-here!!! Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) -//│ | | | Typing type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) -//│ | | | | vars=Map() newDefsInfo=Map() -//│ | | | | 0. type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) -//│ | | | | | typing tuple!!! -//│ | | | | | 0. type TypeName(Int) -//│ | | | | | | typename case?? -//│ | | | | | => Int -//│ | | | | | 0. type TypeName(Int) -//│ | | | | | | typename case?? -//│ | | | | | => Int -//│ | | | | => (Int, Int?,) -//│ | | | => (Int, Int?,) ——— -//│ | | | constraining!!! -//│ | | | CONSTRAIN (#1,) ,) ,) <: (Int, Int?,) -//│ | | | | allVarPols: -//│ | | | | normLike[-] (Int, Int,) -//│ | | | | | norm[-] (Int, Int,) -//│ | | | | | | DNF: DNF(0, (Int, Int,){}) -//│ | | | | | | norm[-] Int -//│ | | | | | | | DNF: DNF(0, #Int{}) -//│ | | | | | | ~> #Int -//│ | | | | | | norm[-] Int -//│ | | | | | | | DNF: DNF(0, #Int{}) -//│ | | | | | | ~> #Int -//│ | | | | | ~> (#Int, #Int,) -//│ | | | | allVarPols: -//│ | | | | normLike[+] (#1,) -//│ | | | | | norm[+] (#1,) -//│ | | | | | | DNF: DNF(0, (#1,){}) -//│ | | | | | | norm[+] #1 -//│ | | | | | | | DNF: DNF(0, #1{}) -//│ | | | | | | ~> #1 -//│ | | | | | ~> (#1,) -//│ | | | | CONSTRAIN #error<> ? maybeIndented inspects |1|,| |2| [at l.1005] -//│ │ > @ argsOrIf(List(),List()) [at l.1048] -//│ │ > │ ? argsOrIf inspects |1|,| |2| [at l.1049] -//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] -//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] -//│ │ > │ ? yeetSpaces inspects |1|,| |2| [at l.515] -//│ │ > │ @ exprOrIf(1,true) [at l.1092] -//│ │ > │ │ ? exprOrIf inspects |1|,| |2| [at l.561] -//│ │ > │ │ ! exprOrIf consumes |1| [at l.574] -//│ │ > │ │ @ exprCont(1,`1`,false) [at l.575] -//│ │ > │ │ │ ? exprCont inspects |,| |2| [at l.737] -//│ │ > │ │ = Right(1) -//│ │ > │ = Right(1) -//│ │ > │ ? argsOrIf inspects |,| |2| [at l.1093] -//│ │ > │ nexttoken => (COMMA,Loc(2,3,nu/OptionalArgs:+375)) -//│ │ > │ ? isOptinoal inspects |,| |2| [at l.1098] -//│ │ > │ flags => None None None -//│ │ > │ e => Right(Fld(FldFlags(false,false,false),1)) -//│ │ > │ body => 1 IntLit(1) -//│ │ > │ ? argsOrIf inspects |,| |2| [at l.1122] -//│ │ > │ ! argsOrIf consumes |,| [at l.1128] -//│ │ > │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),1)))),List()) [at l.1048] -//│ │ > │ │ ? argsOrIf inspects | |2| [at l.1049] -//│ │ > │ │ ! argsOrIf consumes | | [at l.1058] -//│ │ > │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),1)))),List()) [at l.1048] -//│ │ > │ │ │ ? argsOrIf inspects |2| [at l.1049] -//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] -//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] -//│ │ > │ │ │ ? yeetSpaces inspects |2| [at l.515] -//│ │ > │ │ │ @ exprOrIf(1,true) [at l.1092] -//│ │ > │ │ │ │ ? exprOrIf inspects |2| [at l.561] -//│ │ > │ │ │ │ ! exprOrIf consumes |2| [at l.574] -//│ │ > │ │ │ │ @ exprCont(1,`2`,false) [at l.575] -//│ │ > │ │ │ │ │ ? exprCont inspects || [at l.737] -//│ │ > │ │ │ │ = Right(2) -//│ │ > │ │ │ = Right(2) -//│ │ > │ │ │ ? argsOrIf inspects || [at l.1093] -//│ │ > │ │ │ ? isOptinoal inspects || [at l.1098] -//│ │ > │ │ │ flags => None None None -//│ │ > │ │ │ e => Right(Fld(FldFlags(false,false,false),2)) -//│ │ > │ │ │ body => 2 IntLit(2) -//│ │ > │ │ │ ? argsOrIf inspects || [at l.1122] -//│ │ > │ │ = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) -//│ │ > │ = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) -//│ │ > = List((None,Right(Fld(FldFlags(false,false,false),1))), (None,Right(Fld(FldFlags(false,false,false),2)))) -//│ │ > ? concludeWith inspects || [at l.87] -//│ │ > Concluded with List((None,Fld(FldFlags(false,false,false),1)), (None,Fld(FldFlags(false,false,false),2))) -//│ │ @ exprCont(0,`'(' 1, 2, ')'`,false) [at l.608] -//│ │ │ ? exprCont inspects |#:| |[|Int|,| |Int|,| |Int|?|]| [at l.737] -//│ │ │ ! exprCont consumes |#:| [at l.771] -//│ │ │ @ expr(0,true) [at l.772] -//│ │ │ │ @ exprOrIf(0,true) [at l.546] -//│ │ │ │ │ ? exprOrIf inspects | |[|Int|,| |Int|,| |Int|?|]| [at l.561] -//│ │ │ │ │ ! exprOrIf consumes | | [at l.563] -//│ │ │ │ │ @ exprOrIf(0,true) [at l.564] -//│ │ │ │ │ │ ? exprOrIf inspects |[|Int|,| |Int|,| |Int|?|]| [at l.561] -//│ │ │ │ │ │ ! exprOrIf consumes |[|Int|,| |Int|,| |Int|?|]| [at l.590] -//│ │ │ │ │ │ > ? maybeIndented inspects |Int|,| |Int|,|... [at l.1005] -//│ │ │ │ │ │ > @ argsOrIf(List(),List()) [at l.1048] -//│ │ │ │ │ │ > │ ? argsOrIf inspects |Int|,| |Int|,|... [at l.1049] -//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int|,|... [at l.515] -//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int|,|... [at l.515] -//│ │ │ │ │ │ > │ ? yeetSpaces inspects |Int|,| |Int|,|... [at l.515] -//│ │ │ │ │ │ > │ @ exprOrIf(1,true) [at l.1092] -//│ │ │ │ │ │ > │ │ ? exprOrIf inspects |Int|,| |Int|,|... [at l.561] -//│ │ │ │ │ │ > │ │ ! exprOrIf consumes |Int| [at l.580] -//│ │ │ │ │ │ > │ │ @ exprCont(1,`Int`,false) [at l.581] -//│ │ │ │ │ │ > │ │ │ ? exprCont inspects |,| |Int|,| |... [at l.737] -//│ │ │ │ │ │ > │ │ = Right(Int) -//│ │ │ │ │ │ > │ = Right(Int) -//│ │ │ │ │ │ > │ ? argsOrIf inspects |,| |Int|,| |... [at l.1093] -//│ │ │ │ │ │ > │ nexttoken => (COMMA,Loc(12,13,nu/OptionalArgs:+375)) -//│ │ │ │ │ │ > │ ? isOptinoal inspects |,| |Int|,| |... [at l.1098] -//│ │ │ │ │ │ > │ flags => None None None -//│ │ │ │ │ │ > │ e => Right(Fld(FldFlags(false,false,false),Int)) -//│ │ │ │ │ │ > │ body => Int Var(Int) -//│ │ │ │ │ │ > │ ? argsOrIf inspects |,| |Int|,| |... [at l.1122] -//│ │ │ │ │ │ > │ ! argsOrIf consumes |,| [at l.1128] -//│ │ │ │ │ │ > │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] -//│ │ │ │ │ │ > │ │ ? argsOrIf inspects | |Int|,| |Int|... [at l.1049] -//│ │ │ │ │ │ > │ │ ! argsOrIf consumes | | [at l.1058] -//│ │ │ │ │ │ > │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] -//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects |Int|,| |Int|?| [at l.1049] -//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int|,| |Int|?| [at l.515] -//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int|,| |Int|?| [at l.515] -//│ │ │ │ │ │ > │ │ │ ? yeetSpaces inspects |Int|,| |Int|?| [at l.515] -//│ │ │ │ │ │ > │ │ │ @ exprOrIf(1,true) [at l.1092] -//│ │ │ │ │ │ > │ │ │ │ ? exprOrIf inspects |Int|,| |Int|?| [at l.561] -//│ │ │ │ │ │ > │ │ │ │ ! exprOrIf consumes |Int| [at l.580] -//│ │ │ │ │ │ > │ │ │ │ @ exprCont(1,`Int`,false) [at l.581] -//│ │ │ │ │ │ > │ │ │ │ │ ? exprCont inspects |,| |Int|?| [at l.737] -//│ │ │ │ │ │ > │ │ │ │ = Right(Int) -//│ │ │ │ │ │ > │ │ │ = Right(Int) -//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects |,| |Int|?| [at l.1093] -//│ │ │ │ │ │ > │ │ │ nexttoken => (COMMA,Loc(17,18,nu/OptionalArgs:+375)) -//│ │ │ │ │ │ > │ │ │ ? isOptinoal inspects |,| |Int|?| [at l.1098] -//│ │ │ │ │ │ > │ │ │ flags => None None None -//│ │ │ │ │ │ > │ │ │ e => Right(Fld(FldFlags(false,false,false),Int)) -//│ │ │ │ │ │ > │ │ │ body => Int Var(Int) -//│ │ │ │ │ │ > │ │ │ ? argsOrIf inspects |,| |Int|?| [at l.1122] -//│ │ │ │ │ │ > │ │ │ ! argsOrIf consumes |,| [at l.1128] -//│ │ │ │ │ │ > │ │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] -//│ │ │ │ │ │ > │ │ │ │ ? argsOrIf inspects | |Int|?| [at l.1049] -//│ │ │ │ │ │ > │ │ │ │ ! argsOrIf consumes | | [at l.1058] -//│ │ │ │ │ │ > │ │ │ │ @ argsOrIf(List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int)))),List()) [at l.1048] -//│ │ │ │ │ │ > │ │ │ │ │ ? argsOrIf inspects |Int|?| [at l.1049] -//│ │ │ │ │ │ > │ │ │ │ │ ? yeetSpaces inspects |Int|?| [at l.515] -//│ │ │ │ │ │ > │ │ │ │ │ ? yeetSpaces inspects |Int|?| [at l.515] -//│ │ │ │ │ │ > │ │ │ │ │ ? yeetSpaces inspects |Int|?| [at l.515] -//│ │ │ │ │ │ > │ │ │ │ │ @ exprOrIf(1,true) [at l.1092] -//│ │ │ │ │ │ > │ │ │ │ │ │ ? exprOrIf inspects |Int|?| [at l.561] -//│ │ │ │ │ │ > │ │ │ │ │ │ ! exprOrIf consumes |Int| [at l.580] -//│ │ │ │ │ │ > │ │ │ │ │ │ @ exprCont(1,`Int`,false) [at l.581] -//│ │ │ │ │ │ > │ │ │ │ │ │ │ ? exprCont inspects |?| [at l.737] -//│ │ │ │ │ │ > │ │ │ │ │ │ = Right(Int) -//│ │ │ │ │ │ > │ │ │ │ │ = Right(Int) -//│ │ │ │ │ │ > │ │ │ │ │ ? argsOrIf inspects |?| [at l.1093] -//│ │ │ │ │ │ > │ │ │ │ │ nexttoken => (IDENT(?,true),Loc(22,22,nu/OptionalArgs:+375)) -//│ │ │ │ │ │ > │ │ │ │ │ ? isOptinoal inspects |?| [at l.1098] -//│ │ │ │ │ │ > │ │ │ │ │ ! isOptinoal consumes |?| [at l.1100] -//│ │ │ │ │ │ > │ │ │ │ │ flags => None None None -//│ │ │ │ │ │ > │ │ │ │ │ e => Right(Fld(FldFlags(false,false,true),Int)) -//│ │ │ │ │ │ > │ │ │ │ │ body => Int Var(Int) -//│ │ │ │ │ │ > │ │ │ │ │ ? argsOrIf inspects || [at l.1122] -//│ │ │ │ │ │ > │ │ │ │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) -//│ │ │ │ │ │ > │ │ │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) -//│ │ │ │ │ │ > │ │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) -//│ │ │ │ │ │ > │ = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) -//│ │ │ │ │ │ > = List((None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,false),Int))), (None,Right(Fld(FldFlags(false,false,true),Int)))) -//│ │ │ │ │ │ > ? concludeWith inspects || [at l.87] -//│ │ │ │ │ │ > Concluded with List((None,Fld(FldFlags(false,false,false),Int)), (None,Fld(FldFlags(false,false,false),Int)), (None,Fld(FldFlags(false,false,true),Int))) -//│ │ │ │ │ │ @ exprCont(0,`'(' Int, Int, Int?, ')'`,false) [at l.608] -//│ │ │ │ │ │ │ ? exprCont inspects || [at l.737] -//│ │ │ │ │ │ = Right('(' Int, Int, Int?, ')') -//│ │ │ │ │ = Right('(' Int, Int, Int?, ')') -//│ │ │ │ = Right('(' Int, Int, Int?, ')') -//│ │ │ │ result => '(' Int, Int, Int?, ')' ## Bra(rcd = false, Tup(_: Var(Int), _: Var(Int), _: Var(Int))) -//│ │ │ │ result toType => Right(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) -//│ │ │ = '(' Int, Int, Int?, ')' -//│ │ │ asc => '(' 1, 2, ')' : (Int, Int, Int?,) -//│ │ = Right('(' 1, 2, ')' : (Int, Int, Int?,)) -//│ = Right('(' 1, 2, ')' : (Int, Int, Int?,)) -//│ ? yeetSpaces inspects || [at l.515] -//│ ? parseAll inspects || [at l.76] -//│ Parsed: '(' 1, 2, ')' : (Int, Int, Int?,); -//│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.375: [1, 2]: [Int, Int, Int?] -//│ ║ ^^^^^^ -//│ ╟── tuple literal of type `(1, 2,)` does not match type `(Int, Int, Int,)` -//│ ║ l.375: [1, 2]: [Int, Int, Int?] -//│ ║ ^^^^ -//│ ╟── Note: constraint arises from tuple type: -//│ ║ l.375: [1, 2]: [Int, Int, Int?] -//│ ╙── ^^^^^^^^^^^^^^^^ //│ (Int, Int, Int,) //│ res //│ = [ 1, 2 ] @@ -541,74 +268,12 @@ let y: C1 = x // * Harder case: -:d +// why xs type is `nothing` ? +:p fun foo(xs: [Int] & 'a) = xs : [Int, Int?] -//│ 0. Typing TypingUnit(List(fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,))) -//│ | 0. Created lazy type info for fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,) -//│ | Completing fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,) -//│ | | UNSTASHING... (out) -//│ | | Type params -//│ | | UNSTASHING... (out) -//│ | | Params -//│ | | 1. Typing term (xs: & (Int,) ('a,),) => xs : (Int, Int?,) -//│ | | | 1. Typing pattern xs: & (Int,) ('a,), -//│ | | | | HERE, good! -//│ | | | | 1. Typing pattern xs : Int & 'a -//│ | | | | | Typing type Inter(TypeName(Int),'a) -//│ | | | | | | vars=Map() newDefsInfo=Map() -//│ | | | | | | 1. type Inter(TypeName(Int),'a) -//│ | | | | | | | 1. type TypeName(Int) -//│ | | | | | | | | typename case?? -//│ | | | | | | | => Int -//│ | | | | | | | 1. type 'a -//│ | | | | | | | => 'a75' -//│ | | | | | | => (Int & 'a75') -//│ | | | | | => (Int & 'a75') ——— 'a75' -//│ | | | | 1. : (Int & 'a75') -//│ | | | | opt is => false -//│ | | | | case #2 -//│ | | | 1. : (xs: (Int & 'a75'),) -//│ | | | 1. Typing term xs : (Int, Int?,) -//│ | | | | typing-trm-here!!! xs -//│ | | | | 1. Typing term xs -//│ | | | | 1. : (Int & 'a75') -//│ | | | | typing-ty-here!!! Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) -//│ | | | | Typing type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) -//│ | | | | | vars=Map() newDefsInfo=Map() -//│ | | | | | 1. type Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))) -//│ | | | | | | typing tuple!!! -//│ | | | | | | 1. type TypeName(Int) -//│ | | | | | | | typename case?? -//│ | | | | | | => Int -//│ | | | | | | 1. type TypeName(Int) -//│ | | | | | | | typename case?? -//│ | | | | | | => Int -//│ | | | | | => (Int, Int?,) -//│ | | | | => (Int, Int?,) ——— -//│ | | | | constraining!!! -//│ | | | | CONSTRAIN (Int & 'a75') {}∧'a75') , #Int,){_2: #Int, _1: #Int}) -//│ | | | | | | DNF DISCHARGE CONSTRAINTS -//│ | | | | | | 1. C 'a75' , #Int,) & {_2: #Int, _1: #Int}) | ~(#Int)) (3) -//│ | | | | | | | NEW 'a75' UB (0) -//│ | | | 1. : (Int, Int?,) -//│ | | 1. : ((xs: (Int & 'a75'),) -> (Int, Int?,)) -//│ | | UNSTASHING... (out) -//│ | | CONSTRAIN ((xs: (Int & 'a75'),) -> (Int, Int?,)) , #Int,) & {_2: #Int, _1: #Int}) | ~(#Int)) -//│ | | 1. C ((xs: (Int & 'a75'),) -> (Int, Int?,)) xs : (Int, Int?,),((xs: (Int & 'a75'),) -> (Int, Int?,))) where -//│ 'a75' <: (((#Int, #Int,) & {_2: #Int, _1: #Int}) | ~(#Int)) -//│ | Typing unit statements -//│ | : None -//│ ======== TYPED ======== -//│ fun foo: ‹∀ 0. ((xs: (Int & 'a75'),) -> (Int, Int?,))› where -//│ | 'a75' <: (((#Int, #Int,) & {_2: #Int, _1: #Int}) | ~(#Int)) +//│ |#fun| |foo|(|xs|#:| |[|Int|]| |&| |'a|)| |#=| |xs| |#:| |[|Int|,| |Int|?|]| +//│ AST: TypingUnit(NuFunDef(None, foo, [], Lam(Tup(xs: App(App(Var(&), Tup(_: Var(Int))), Tup(_: Var('a)))), Asc(Var(xs), Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))))))) +//│ Parsed: fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,); //│ fun foo: (xs: nothing,) -> (Int, Int,) From b432dc4aa03988ea2bdea9ea6e3b782b806bc5f3 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Mon, 25 Sep 2023 09:41:07 +0800 Subject: [PATCH 13/37] add 2 other field size member checks --- .../src/main/scala/mlscript/ConstraintSolver.scala | 2 +- shared/src/main/scala/mlscript/TyperHelpers.scala | 2 +- shared/src/main/scala/mlscript/helpers.scala | 10 ++++++++-- shared/src/test/diff/nu/OptionalArgs.mls | 13 ++++++++++++- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/shared/src/main/scala/mlscript/ConstraintSolver.scala b/shared/src/main/scala/mlscript/ConstraintSolver.scala index c50775997..004ac7872 100644 --- a/shared/src/main/scala/mlscript/ConstraintSolver.scala +++ b/shared/src/main/scala/mlscript/ConstraintSolver.scala @@ -845,7 +845,7 @@ class ConstraintSolver extends NormalForms { self: Typer => } - case (TupleType(fs0), TupleType(fs1)) if fs0.size === fs1.size => { // TODO[optional-fields] generalize (coerce compatible tuples) + case (TupleType(fs0), TupleType(fs1)) if fs0.sizeCompare(fs1) <= 0 && fs0.sizeCompare(fs1.filter(x => !x._2.opt)) >= 0 => { // TODO[optional-fields] generalize (coerce compatible tuples) println("case #1") fs0.lazyZip(fs1).foreach { case ((ln, l), (rn, r)) => diff --git a/shared/src/main/scala/mlscript/TyperHelpers.scala b/shared/src/main/scala/mlscript/TyperHelpers.scala index 795a52895..f19831878 100644 --- a/shared/src/main/scala/mlscript/TyperHelpers.scala +++ b/shared/src/main/scala/mlscript/TyperHelpers.scala @@ -430,7 +430,7 @@ abstract class TyperHelpers { Typer: Typer => println("case #2") // TODO[optional-fields] update this condition - if (fs0.sizeCompare(fs1) =/= 0) BotType + if (fs0.sizeCompare(fs1) > 0 || fs0.sizeCompare(fs1.filter(x => !x._2.opt)) < 0) BotType else TupleType(tupleIntersection(fs0, fs1))(t0.prov) } case _ if !swapped => that & (this, prov, swapped = true) diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index 457fa8bde..16b246505 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -43,14 +43,20 @@ trait TypeLikeImpl extends Located { self: TypeLike => case Neg(t) => s"~${t.showIn(ctx, 100)}" case Record(fs) => fs.map { nt => val nme = nt._1.name - if (nme.isCapitalized) nt._2 match { + val opt = nt._2 match { + case Field(_, _, true) => "?" + case Field(_, _, false) => "" + } + val res = if (nme.isCapitalized) nt._2 match { case Field(N | S(Bot), Top, _) => s"$nme" case Field(S(lb), ub, _) if lb === ub => s"$nme = ${ub.showIn(ctx, 0)}" case Field(N | S(Bot), ub, _) => s"$nme <: ${ub.showIn(ctx, 0)}" case Field(S(lb), Top, _) => s"$nme :> ${lb.showIn(ctx, 0)}" case Field(S(lb), ub, _) => s"$nme :> ${lb.showIn(ctx, 0)} <: ${ub.showIn(ctx, 0)}" } - else s"${nt._2.mutStr}${nme}: ${showField(nt._2, ctx)}" + else + s"${nt._2.mutStr}${nme}: ${showField(nt._2, ctx)}" + res + opt }.mkString("{", ", ", "}") case Splice(fs) => fs.map{case L(l) => s"...${l.showIn(ctx, 0)}" case R(r) => s"${showField(r, ctx)}"}.mkString("(", ", ", ")") diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index e7e7ce5f0..4a14e8ddc 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -260,6 +260,7 @@ let y: C1 = x //│ res //│ = [ 1, 2, 3 ] +// FIXME [1, 2]: [Int, Int, Int?] //│ (Int, Int, Int,) //│ res @@ -284,6 +285,16 @@ fun foo: [Int] | [Int, Int?] //│ fun foo: Array[Int] & {_1: Int} fun foo: [Int] & [Int, Int?] -//│ fun foo: nothing +//│ /!!!\ Uncaught error: java.lang.IllegalArgumentException: requirement failed +//│ at: scala.Predef$.require(Predef.scala:324) +//│ at: mlscript.TyperHelpers.tupleIntersection(TyperHelpers.scala:135) +//│ at: mlscript.TyperHelpers$SimpleTypeImpl.$amp(TyperHelpers.scala:434) +//│ at: mlscript.TyperHelpers$SimpleTypeImpl.$amp$(TyperHelpers.scala:411) +//│ at: mlscript.TyperDatatypes$SimpleType.$amp(TyperDatatypes.scala:155) +//│ at: mlscript.Typer.$anonfun$typeType2$17(Typer.scala:445) +//│ at: mlscript.Typer.$anonfun$typeType2$11(Typer.scala:447) +//│ at: mlscript.TyperHelpers.trace(TyperHelpers.scala:32) +//│ at: mlscript.Typer.rec$1(Typer.scala:604) +//│ at: mlscript.Typer.$anonfun$typeType2$2(Typer.scala:605) From ed457490d06d5f192d8471ac5fcca337a69118a9 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Tue, 26 Sep 2023 10:00:00 +0800 Subject: [PATCH 14/37] fix problem in field type show --- shared/src/main/scala/mlscript/helpers.scala | 24 ++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index 16b246505..606fa2bfd 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -21,12 +21,19 @@ trait TypeLikeImpl extends Located { self: TypeLike => def show: Str = showIn(ShowCtx.mk(this :: Nil), 0) private def parensIf(str: Str, cnd: Boolean): Str = if (cnd) "(" + str + ")" else str - private def showField(f: Field, ctx: ShowCtx): Str = f match { + private def showField(f: Field, ctx: ShowCtx): Str = { + val res = f match { case Field(N, ub, _) => ub.showIn(ctx, 0) case Field(S(lb), ub, _) if lb === ub => ub.showIn(ctx, 0) case Field(S(Bot), ub, _) => s"out ${ub.showIn(ctx, 0)}" case Field(S(lb), Top, _) => s"in ${lb.showIn(ctx, 0)}" case Field(S(lb), ub, _) => s"in ${lb.showIn(ctx, 0)} out ${ub.showIn(ctx, 0)}" + } + val opt = f match { + case Field(_, _, true) => "?" + case Field(_, _, false)=> "" + } + res + opt } def showIn(ctx: ShowCtx, outerPrec: Int): Str = this match { // TODO remove obsolete pretty-printing hacks @@ -47,21 +54,20 @@ trait TypeLikeImpl extends Located { self: TypeLike => case Field(_, _, true) => "?" case Field(_, _, false) => "" } - val res = if (nme.isCapitalized) nt._2 match { - case Field(N | S(Bot), Top, _) => s"$nme" - case Field(S(lb), ub, _) if lb === ub => s"$nme = ${ub.showIn(ctx, 0)}" - case Field(N | S(Bot), ub, _) => s"$nme <: ${ub.showIn(ctx, 0)}" - case Field(S(lb), Top, _) => s"$nme :> ${lb.showIn(ctx, 0)}" - case Field(S(lb), ub, _) => s"$nme :> ${lb.showIn(ctx, 0)} <: ${ub.showIn(ctx, 0)}" + if (nme.isCapitalized) nt._2 match { + case Field(N | S(Bot), Top, _) => s"$nme" + opt + case Field(S(lb), ub, _) if lb === ub => s"$nme = ${ub.showIn(ctx, 0)}" + opt + case Field(N | S(Bot), ub, _) => s"$nme <: ${ub.showIn(ctx, 0)}" + opt + case Field(S(lb), Top, _) => s"$nme :> ${lb.showIn(ctx, 0)}" + opt + case Field(S(lb), ub, _) => s"$nme :> ${lb.showIn(ctx, 0)} <: ${ub.showIn(ctx, 0)}" + opt } else s"${nt._2.mutStr}${nme}: ${showField(nt._2, ctx)}" - res + opt }.mkString("{", ", ", "}") case Splice(fs) => fs.map{case L(l) => s"...${l.showIn(ctx, 0)}" case R(r) => s"${showField(r, ctx)}"}.mkString("(", ", ", ")") case Tuple(fs) => - fs.map(nt => s"${nt._2.mutStr}${nt._1.fold("")(_.name + ": ")}${showField(nt._2, ctx)}${if (nt._2.opt) "?" else ""},").mkString("(", " ", ")") + fs.map(nt => s"${nt._2.mutStr}${nt._1.fold("")(_.name + ": ")}${showField(nt._2, ctx)},").mkString("(", " ", ")") case Union(TypeName("true"), TypeName("false")) | Union(TypeName("false"), TypeName("true")) => TypeName("bool").showIn(ctx, 0) // case Union(l, r) => parensIf(l.showIn(ctx, 20) + " | " + r.showIn(ctx, 20), outerPrec > 20) From ea729b57022153b1ecf8fc13c84b0eba0036bcfb Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Tue, 26 Sep 2023 10:39:10 +0800 Subject: [PATCH 15/37] add some debugs --- shared/src/main/scala/mlscript/Typer.scala | 6 +- shared/src/test/diff/nu/OptionalArgs.mls | 160 ++++++++++++------ .../src/test/scala/mlscript/DiffTests.scala | 9 + 3 files changed, 121 insertions(+), 54 deletions(-) diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index 6869a3527..24083ef6a 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -1509,11 +1509,11 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne val seenVars = mutable.Set.empty[TV] def field(ft: FieldType)(implicit ectx: ExpCtx): Field = ft match { - case FieldType(S(l: TV), u: TV, _) if l === u => + case FieldType(S(l: TV), u: TV, opt) if l === u => val res = go(u) - Field(S(res), res, false) // TODO improve Field + Field(S(res), res, opt) // TODO improve Field case f => - Field(f.lb.map(go), go(f.ub), false) + Field(f.lb.map(go), go(f.ub), f.opt) } class ExpCtx(val tps: Map[TV, TN]) { diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 4a14e8ddc..b47864d32 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -2,6 +2,7 @@ // Typing of (a?: Int, b?: Int) is ok, but constraining is not // :d +// :ds :ds fun f1(a?: Int, b?: Int) = a + b //│ ⬤ Initial: TypedTypingUnit( @@ -140,6 +141,12 @@ fun f1(a?: Int, b?: Int) = a + b //│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) //│ None) //│ where: +//│ sim => TypedTypingUnit( +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ None) +//│ exp => class mlscript.Signature +//│ members => List(fun f1: (a: Int, b: Int,) -> Int) +//│ result => None //│ fun f1: (a: Int, b: Int,) -> Int @@ -149,59 +156,36 @@ fun f1(a: Int, b: Int) = a + b //│ |#fun| |f1|(|a|#:| |Int|,| |b|#:| |Int|)| |#=| |a| |+| |b| //│ AST: TypingUnit(NuFunDef(None, f1, [], Lam(Tup(a: Var(Int), b: Var(Int)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b)))))) //│ Parsed: fun f1 = (a: Int, b: Int,) => + (a,) (b,); +//│ sim => TypedTypingUnit( +//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ None) +//│ exp => class mlscript.Signature +//│ members => List(fun f1: (a: Int, b: Int,) -> Int) +//│ result => None //│ fun f1: (a: Int, b: Int,) -> Int -f1(1, 2) -//│ Int -//│ res -//│ = 3 - -:p -fun f1(a, b) = a + b -//│ |#fun| |f1|(|a|,| |b|)| |#=| |a| |+| |b| -//│ AST: TypingUnit(NuFunDef(None, f1, [], Lam(Tup(_: Var(a), _: Var(b)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b)))))) -//│ Parsed: fun f1 = (a, b,) => + (a,) (b,); -//│ fun f1: (Int, Int,) -> Int - - -:p -f1(1, 2) -//│ |f1|(|1|,| |2|)| -//│ AST: TypingUnit(App(Var(f1), Tup(_: IntLit(1), _: IntLit(2)))) -//│ Parsed: f1 (1, 2,); -//│ Int -//│ res -//│ = 3 - -let x = [1, 2] : [Int, Int] -//│ let x: (Int, Int,) -//│ x -//│ = [ 1, 2 ] - -let f = ([a, b]) => a - b -//│ let f: (Int, Int,) -> Int -//│ f -//│ = [Function: f] - -f(x) -//│ Int -//│ res -//│ = -1 - -[1, 2, 3]: [Int, Int, Int] -//│ (Int, Int, Int,) -//│ res -//│ = [ 1, 2, 3 ] - -[1] -//│ (1,) -//│ res -//│ = [ 1 ] class C1 class C2 extends C1 let x = new C2() let y: C1 = x +//│ sim => TypedTypingUnit( +//│ TypedNuCls(0, TypeName(C1), +//│ List(), +//│ List(), +//│ this: ⊤, , +//│ : ⊤, Set(), Map()) +//│ TypedNuCls(0, TypeName(C2), +//│ List(), +//│ List(), +//│ this: ⊤, , +//│ : ⊤, Set(TypeName(C1)), Map()) +//│ TypedNuFun(0,let x = new C2() {},C2) +//│ TypedNuFun(0,let y = x : C1,C1) +//│ None) +//│ exp => class mlscript.Signature +//│ members => List(class C1() {}, class C2(): C1 {}, let x: C2, let y: C1) +//│ result => None //│ class C1 //│ class C2 extends C1 //│ let x: C2 @@ -212,22 +196,69 @@ let y: C1 = x //│ = C2 {} [x, y]: [C1, C1] +//│ sim => TypedTypingUnit( +//│ Some((C1, C1,))) +//│ exp => class mlscript.Signature +//│ members => List() +//│ result => Some(Tuple(List((None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false))))) //│ (C1, C1,) //│ res //│ = [ C2 {}, C2 {} ] +[x, y]: [C1, C1, C1?] +//│ sim => TypedTypingUnit( +//│ Some((C1, C1, C1,))) +//│ exp => class mlscript.Signature +//│ members => List() +//│ result => Some(Tuple(List((None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false))))) +//│ (C1, C1, C1,) +//│ res +//│ = [ C2 {}, C2 {} ] + +:e +[x]: [C1, C1, C1?] +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.218: [x]: [C1, C1, C1?] +//│ ║ ^^^ +//│ ╟── expression of type `(?a,)` does not match type `(C1, C1, C1,)` +//│ ╟── Note: constraint arises from tuple type: +//│ ║ l.218: [x]: [C1, C1, C1?] +//│ ╙── ^^^^^^^^^^^^^ +//│ sim => TypedTypingUnit( +//│ Some((C1, C1, C1,))) +//│ exp => class mlscript.Signature +//│ members => List() +//│ result => Some(Tuple(List((None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false))))) +//│ (C1, C1, C1,) +//│ res +//│ = [ C2 {} ] [1, 2, 3]: [Int, Int, Int] +//│ sim => TypedTypingUnit( +//│ Some((#Int, #Int, #Int,))) +//│ exp => class mlscript.Signature +//│ members => List() +//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) //│ (Int, Int, Int,) //│ res //│ = [ 1, 2, 3 ] [1, 2]: [Int, Int?] +//│ sim => TypedTypingUnit( +//│ Some((#Int, #Int,))) +//│ exp => class mlscript.Signature +//│ members => List() +//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) //│ (Int, Int,) //│ res //│ = [ 1, 2 ] [1]: [Int, Int?] +//│ sim => TypedTypingUnit( +//│ Some((#Int, #Int,))) +//│ exp => class mlscript.Signature +//│ members => List() +//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) //│ (Int, Int,) //│ res //│ = [ 1 ] @@ -235,12 +266,17 @@ let y: C1 = x :e []: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.236: []: [Int, Int?] +//│ ║ l.267: []: [Int, Int?] //│ ║ ^^ //│ ╟── expression of type `()` does not match type `(Int, Int,)` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.236: []: [Int, Int?] +//│ ║ l.267: []: [Int, Int?] //│ ╙── ^^^^^^^^^^^ +//│ sim => TypedTypingUnit( +//│ Some((#Int, #Int,))) +//│ exp => class mlscript.Signature +//│ members => List() +//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) //│ (Int, Int,) //│ res //│ = [] @@ -248,20 +284,30 @@ let y: C1 = x :e [1, 2, 3]: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.249: [1, 2, 3]: [Int, Int?] +//│ ║ l.285: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^^^ //│ ╟── tuple literal of type `(1, 2, 3,)` does not match type `(Int, Int,)` -//│ ║ l.249: [1, 2, 3]: [Int, Int?] +//│ ║ l.285: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.249: [1, 2, 3]: [Int, Int?] +//│ ║ l.285: [1, 2, 3]: [Int, Int?] //│ ╙── ^^^^^^^^^^^ +//│ sim => TypedTypingUnit( +//│ Some((#Int, #Int,))) +//│ exp => class mlscript.Signature +//│ members => List() +//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) //│ (Int, Int,) //│ res //│ = [ 1, 2, 3 ] // FIXME [1, 2]: [Int, Int, Int?] +//│ sim => TypedTypingUnit( +//│ Some((#Int, #Int, #Int,))) +//│ exp => class mlscript.Signature +//│ members => List() +//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) //│ (Int, Int, Int,) //│ res //│ = [ 1, 2 ] @@ -275,6 +321,12 @@ fun foo(xs: [Int] & 'a) = xs : [Int, Int?] //│ |#fun| |foo|(|xs|#:| |[|Int|]| |&| |'a|)| |#=| |xs| |#:| |[|Int|,| |Int|?|]| //│ AST: TypingUnit(NuFunDef(None, foo, [], Lam(Tup(xs: App(App(Var(&), Tup(_: Var(Int))), Tup(_: Var('a)))), Asc(Var(xs), Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))))))) //│ Parsed: fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,); +//│ sim => TypedTypingUnit( +//│ TypedNuFun(0,fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,),((xs: ⊥,) -> (#Int, #Int,))) +//│ None) +//│ exp => class mlscript.Signature +//│ members => List(fun foo: (xs: nothing,) -> (Int, Int,)) +//│ result => None //│ fun foo: (xs: nothing,) -> (Int, Int,) @@ -282,6 +334,12 @@ fun foo(xs: [Int] & 'a) = xs : [Int, Int?] // TODO later: update normal form construction fun foo: [Int] | [Int, Int?] +//│ sim => TypedTypingUnit( +//│ TypedNuFun(0,fun foo: (Int,) | (Int, Int?,),(Array‹#Int› & {_1: #Int})) +//│ None) +//│ exp => class mlscript.Signature +//│ members => List(fun foo: Array[Int] & {_1: Int}) +//│ result => None //│ fun foo: Array[Int] & {_1: Int} fun foo: [Int] & [Int, Int?] diff --git a/shared/src/test/scala/mlscript/DiffTests.scala b/shared/src/test/scala/mlscript/DiffTests.scala index 61c3f32b2..c1de81206 100644 --- a/shared/src/test/scala/mlscript/DiffTests.scala +++ b/shared/src/test/scala/mlscript/DiffTests.scala @@ -567,8 +567,17 @@ class DiffTests SimplifyPipeline(tpd, pol = S(true))(ctx) } finally typer.dbg = oldDbg + output(s"sim => ${sim}") + val exp = typer.expandType(sim)(ctx) + output(s"exp => ${exp.getClass()}") + exp match { + case Signature(members, result) => + output(s"members => ${members}") + output(s"result => ${result}") + } + val expStr = exp.showIn(ShowCtx.mk(exp :: Nil) // .copy(newDefs = true) // TODO later From 1819d2528c9e6c56726a78b6879ffda8494d3f85 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Wed, 27 Sep 2023 16:45:26 +0800 Subject: [PATCH 16/37] debug the place error happens --- shared/src/main/scala/mlscript/Typer.scala | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index 24083ef6a..a7cdbc9e0 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -1567,8 +1567,15 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne Option.when(!(TopType <:< thisTy))(go(thisTy)), 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) + case tf @ TypedNuFun(level, fd, bodyTy) => { + println(s"tf => $tf \n######\n fd => $fd \n######\n bodyTy => $bodyTy") // (problem) bodyTy type dosen't have the opt field, so tf.typeSignature(which + // uses the bodyTy fails. + println(s"typeSignature => ${tf.typeSignature}") + val res = NuFunDef(fd.isLetRec, fd.nme, Nil, R(go(tf.typeSignature)))(fd.declareLoc, fd.signature, fd.outer) + // res.toString() + println(s"ress(problem)!! $res ## ${res.rhs}") + res + } case p: NuParam => ??? // TODO case TypedNuDummy(d) => @@ -1580,9 +1587,13 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, var ne // if (bounds.isEmpty) res // else Constrained(res, bounds, Nil) res - case OtherTypeLike(tu) => + case OtherTypeLike(tu) => { val mems = tu.implementedMembers.map(goDecl) - Signature(mems, tu.result.map(go)) + val res = Signature(mems, tu.result.map(go)) + println(s"tu => $tu") + println(s"resss => $res") + res + } } def go(st: SimpleType)(implicit ectx: ExpCtx): Type = From b924f800535bbf54d6e2999fec22bf01c9ac92ae Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 10:30:15 +0800 Subject: [PATCH 17/37] fix operations defined on FieldType --- .../main/scala/mlscript/TypeSimplifier.scala | 2 +- .../main/scala/mlscript/TyperDatatypes.scala | 8 +- .../main/scala/mlscript/TyperHelpers.scala | 2 +- shared/src/test/diff/nu/OptionalArgs.mls | 227 +++++++++++++----- 4 files changed, 169 insertions(+), 70 deletions(-) diff --git a/shared/src/main/scala/mlscript/TypeSimplifier.scala b/shared/src/main/scala/mlscript/TypeSimplifier.scala index 4c7ea6e27..a113c98d8 100644 --- a/shared/src/main/scala/mlscript/TypeSimplifier.scala +++ b/shared/src/main/scala/mlscript/TypeSimplifier.scala @@ -416,7 +416,7 @@ trait TypeSimplifier { self: Typer => ) val componentFieldsMap = componentFields.toMap val tupleComponents = fs.iterator.zipWithIndex.map { case ((nme, ty), i) => - nme -> (ty && componentFieldsMap.getOrElse(i + 1, TopType.toUpper(noProv))).update(go(_, pol.map(!_)), go(_, pol)) + nme -> (ty && componentFieldsMap.getOrElse(i + 1, TopType.toUpper(noProv, true))).update(go(_, pol.map(!_)), go(_, pol)) }.toList S(TupleType(tupleComponents)(tt.prov)) -> rcdFields.mapValues(_.update(go(_, pol.map(!_)), go(_, pol))) case S(ct: ClassTag) => S(ct) -> nFields diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala index 94a7a9eda..85502c17f 100644 --- a/shared/src/main/scala/mlscript/TyperDatatypes.scala +++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala @@ -479,17 +479,17 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => def <:< (that: FieldType)(implicit ctx: Ctx, cache: MutMap[ST -> ST, Bool] = MutMap.empty): Bool = (that.lb.getOrElse(BotType) <:< this.lb.getOrElse(BotType)) && (this.ub <:< that.ub) def && (that: FieldType, prov: TypeProvenance = noProv): FieldType = - FieldType(lb.fold(that.lb)(l => Some(that.lb.fold(l)(l | _))), ub & that.ub, false)(prov) + FieldType(lb.fold(that.lb)(l => Some(that.lb.fold(l)(l | _))), ub & that.ub, opt && that.opt)(prov) def || (that: FieldType, prov: TypeProvenance = noProv): FieldType = - FieldType(for {l <- lb; r <- that.lb} yield (l & r), ub | that.ub, false)(prov) + FieldType(for {l <- lb; r <- that.lb} yield (l & r), ub | that.ub, opt || that.opt)(prov) def update(lb: SimpleType => SimpleType, ub: SimpleType => SimpleType): FieldType = - FieldType(this.lb.map(lb), ub(this.ub), false)(prov) + FieldType(this.lb.map(lb), ub(this.ub), opt)(prov) def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): FieldType = update(_.freshenAbove(lim, rigidify), _.freshenAbove(lim, rigidify)) override def toString = lb.fold(s"$ub${if (opt) "?" else ""}")(lb => s"mut ${if (lb === BotType) "" else lb}..$ub") } - object FieldType { + object FieldType { //TODO def mk(vi: VarianceInfo, lb: ST, ub: ST)(prov: TP): FieldType = vi match { case VarianceInfo(true, true) => FieldType(N, TopType, false)(prov) case VarianceInfo(true, false) => FieldType(N, ub, false)(prov) diff --git a/shared/src/main/scala/mlscript/TyperHelpers.scala b/shared/src/main/scala/mlscript/TyperHelpers.scala index f19831878..98184cab8 100644 --- a/shared/src/main/scala/mlscript/TyperHelpers.scala +++ b/shared/src/main/scala/mlscript/TyperHelpers.scala @@ -374,7 +374,7 @@ abstract class TyperHelpers { Typer: Typer => case _: TypeVariable | _: TypeTag | _: ExtrType => this } - def toUpper(prov: TypeProvenance): FieldType = FieldType(None, this, false)(prov) + def toUpper(prov: TypeProvenance, opt: Bool = false): FieldType = FieldType(None, this, opt)(prov) def toLower(prov: TypeProvenance): FieldType = FieldType(Some(this), TopType, false)(prov) def | (that: SimpleType, prov: TypeProvenance = noProv, swapped: Bool = false): SimpleType = (this, that) match { diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index b47864d32..c069a0afb 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -13,27 +13,27 @@ fun f1(a?: Int, b?: Int) = a + b //│ allVarPols: +α30' //│ Renewed α30' ~> α30_32' //│ ⬤ Cleaned up: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int, b: Int,) -> α30_32')) +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int?, b: Int?,) -> α30_32')) //│ None) //│ where: //│ α30_32' :> Int //│ allVarPols: +α30_32' //│ consed: Map((true,Int) -> α30_32') //│ ⬤ Unskid: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int, b: Int,) -> α30_32')) +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int?, b: Int?,) -> α30_32')) //│ None) //│ where: //│ α30_32' :> Int -//│ analyze1[+] ((a: Int, b: Int,) -> α30_32') -//│ | analyze1[+;-] (a: Int, b: Int,) +//│ analyze1[+] ((a: Int?, b: Int?,) -> α30_32') +//│ | analyze1[+;-] (a: Int?, b: Int?,) //│ | | analyze1[+;-] Int //│ | | analyze1[+;-] Int //│ | analyze1[+] α30_32' //│ | | analyze1[+;@[+](0)] Int //│ [inv] //│ [nums] +α30_32' 1 -//│ analyze2[+] ((a: Int, b: Int,) -> α30_32') -//│ | analyze2[+;-] (a: Int, b: Int,) +//│ analyze2[+] ((a: Int?, b: Int?,) -> α30_32') +//│ | analyze2[+;-] (a: Int?, b: Int?,) //│ | | analyze2[+;-] Int //│ | | analyze2[+;-] Int //│ | analyze2[+] α30_32' @@ -52,66 +52,66 @@ fun f1(a?: Int, b?: Int) = a + b //│ [bounds] //│ α30_32' :> Int //│ [rec] Set() -//│ transform[+] ((a: Int, b: Int,) -> α30_32') () + None -//│ | transform[-] (a: Int, b: Int,) () +;- None +//│ transform[+] ((a: Int?, b: Int?,) -> α30_32') () + None +//│ | transform[-] (a: Int?, b: Int?,) () +;- None //│ | | transform[-] Int () +;- None //│ | | ~> Int //│ | | transform[-] Int () +;- None //│ | | ~> Int -//│ | ~> (a: Int, b: Int,) +//│ | ~> (a: Int?, b: Int?,) //│ | transform[+] α30_32' () + None //│ | | -> bound Some(true) //│ | | transform[+] Int (α30_32') +;@[+](0) None //│ | | ~> Int //│ | ~> Int -//│ ~> ((a: Int, b: Int,) -> Int) +//│ ~> ((a: Int?, b: Int?,) -> Int) //│ ⬤ Type after simplification: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int, b: Int,) -> Int)) +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int?, b: Int?,) -> Int)) //│ None) //│ where: //│ allVarPols: //│ normLike[+] TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int, b: Int,) -> Int)) +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: Int?, b: Int?,) -> Int)) //│ None) -//│ | norm[+] ((a: Int, b: Int,) -> Int) -//│ | | DNF: DNF(0, ((a: Int, b: Int,) -> Int){}) -//│ | | norm[-] (a: Int, b: Int,) -//│ | | | DNF: DNF(0, (a: Int, b: Int,){}) +//│ | norm[+] ((a: Int?, b: Int?,) -> Int) +//│ | | DNF: DNF(0, ((a: Int?, b: Int?,) -> Int){}) +//│ | | norm[-] (a: Int?, b: Int?,) +//│ | | | DNF: DNF(0, (a: Int?, b: Int?,){}) //│ | | | norm[-] Int //│ | | | | DNF: DNF(0, #Int{}) //│ | | | ~> #Int //│ | | | norm[-] Int //│ | | | | DNF: DNF(0, #Int{}) //│ | | | ~> #Int -//│ | | ~> (a: #Int, b: #Int,) +//│ | | ~> (a: #Int?, b: #Int?,) //│ | | norm[+] Int //│ | | | DNF: DNF(0, #Int{}) //│ | | ~> #Int -//│ | ~> ((a: #Int, b: #Int,) -> #Int) +//│ | ~> ((a: #Int?, b: #Int?,) -> #Int) //│ ⬤ Normalized: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ where: //│ allVarPols: //│ ⬤ Cleaned up: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ where: //│ allVarPols: //│ consed: Map() //│ ⬤ Unskid: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ where: -//│ analyze1[+] ((a: #Int, b: #Int,) -> #Int) -//│ | analyze1[+;-] (a: #Int, b: #Int,) +//│ analyze1[+] ((a: #Int?, b: #Int?,) -> #Int) +//│ | analyze1[+;-] (a: #Int?, b: #Int?,) //│ | | analyze1[+;-] #Int //│ | | analyze1[+;-] #Int //│ | analyze1[+] #Int //│ [inv] //│ [nums] -//│ analyze2[+] ((a: #Int, b: #Int,) -> #Int) -//│ | analyze2[+;-] (a: #Int, b: #Int,) +//│ analyze2[+] ((a: #Int?, b: #Int?,) -> #Int) +//│ | analyze2[+;-] (a: #Int?, b: #Int?,) //│ | | analyze2[+;-] #Int //│ | | analyze2[+;-] #Int //│ | analyze2[+] #Int @@ -121,33 +121,33 @@ fun f1(a?: Int, b?: Int) = a + b //│ [sub] //│ [bounds] //│ [rec] Set() -//│ transform[+] ((a: #Int, b: #Int,) -> #Int) () + None -//│ | transform[-] (a: #Int, b: #Int,) () +;- None +//│ transform[+] ((a: #Int?, b: #Int?,) -> #Int) () + None +//│ | transform[-] (a: #Int?, b: #Int?,) () +;- None //│ | | transform[-] #Int () +;- None //│ | | ~> #Int //│ | | transform[-] #Int () +;- None //│ | | ~> #Int -//│ | ~> (a: #Int, b: #Int,) +//│ | ~> (a: #Int?, b: #Int?,) //│ | transform[+] #Int () + None //│ | ~> #Int -//│ ~> ((a: #Int, b: #Int,) -> #Int) +//│ ~> ((a: #Int?, b: #Int?,) -> #Int) //│ ⬤ Resim: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ where: //│ allVarPols: //│ [subs] HashMap() //│ ⬤ Factored: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ where: //│ sim => TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int, b: #Int,) -> #Int)) +//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a,) (b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ exp => class mlscript.Signature -//│ members => List(fun f1: (a: Int, b: Int,) -> Int) +//│ members => List(fun f1: (a: Int?, b: Int?,) -> Int) //│ result => None -//│ fun f1: (a: Int, b: Int,) -> Int +//│ fun f1: (a: Int?, b: Int?,) -> Int // using space, creates ASC in AST. @@ -206,11 +206,11 @@ let y: C1 = x //│ = [ C2 {}, C2 {} ] [x, y]: [C1, C1, C1?] //│ sim => TypedTypingUnit( -//│ Some((C1, C1, C1,))) +//│ Some((C1, C1, C1?,))) //│ exp => class mlscript.Signature //│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false))))) -//│ (C1, C1, C1,) +//│ result => Some(Tuple(List((None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),true))))) +//│ (C1, C1, C1?,) //│ res //│ = [ C2 {}, C2 {} ] @@ -219,16 +219,16 @@ let y: C1 = x //│ ╔══[ERROR] Type mismatch in type ascription: //│ ║ l.218: [x]: [C1, C1, C1?] //│ ║ ^^^ -//│ ╟── expression of type `(?a,)` does not match type `(C1, C1, C1,)` +//│ ╟── expression of type `(?a,)` does not match type `(C1, C1, C1?,)` //│ ╟── Note: constraint arises from tuple type: //│ ║ l.218: [x]: [C1, C1, C1?] //│ ╙── ^^^^^^^^^^^^^ //│ sim => TypedTypingUnit( -//│ Some((C1, C1, C1,))) +//│ Some((C1, C1, C1?,))) //│ exp => class mlscript.Signature //│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false))))) -//│ (C1, C1, C1,) +//│ result => Some(Tuple(List((None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),true))))) +//│ (C1, C1, C1?,) //│ res //│ = [ C2 {} ] @@ -245,21 +245,21 @@ let y: C1 = x [1, 2]: [Int, Int?] //│ sim => TypedTypingUnit( -//│ Some((#Int, #Int,))) +//│ Some((#Int, #Int?,))) //│ exp => class mlscript.Signature //│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) -//│ (Int, Int,) +//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) +//│ (Int, Int?,) //│ res //│ = [ 1, 2 ] [1]: [Int, Int?] //│ sim => TypedTypingUnit( -//│ Some((#Int, #Int,))) +//│ Some((#Int, #Int?,))) //│ exp => class mlscript.Signature //│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) -//│ (Int, Int,) +//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) +//│ (Int, Int?,) //│ res //│ = [ 1 ] @@ -268,16 +268,16 @@ let y: C1 = x //│ ╔══[ERROR] Type mismatch in type ascription: //│ ║ l.267: []: [Int, Int?] //│ ║ ^^ -//│ ╟── expression of type `()` does not match type `(Int, Int,)` +//│ ╟── expression of type `()` does not match type `(Int, Int?,)` //│ ╟── Note: constraint arises from tuple type: //│ ║ l.267: []: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ sim => TypedTypingUnit( -//│ Some((#Int, #Int,))) +//│ Some((#Int, #Int?,))) //│ exp => class mlscript.Signature //│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) -//│ (Int, Int,) +//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) +//│ (Int, Int?,) //│ res //│ = [] @@ -286,29 +286,128 @@ let y: C1 = x //│ ╔══[ERROR] Type mismatch in type ascription: //│ ║ l.285: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^^^ -//│ ╟── tuple literal of type `(1, 2, 3,)` does not match type `(Int, Int,)` +//│ ╟── tuple literal of type `(1, 2, 3,)` does not match type `(Int, Int?,)` //│ ║ l.285: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: //│ ║ l.285: [1, 2, 3]: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ sim => TypedTypingUnit( -//│ Some((#Int, #Int,))) +//│ Some((#Int, #Int?,))) //│ exp => class mlscript.Signature //│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) -//│ (Int, Int,) +//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) +//│ (Int, Int?,) //│ res //│ = [ 1, 2, 3 ] // FIXME +:ds [1, 2]: [Int, Int, Int?] +//│ ⬤ Initial: TypedTypingUnit( +//│ Some((Int, Int, Int?,))) +//│ where: +//│ allVarPols: +//│ ⬤ Cleaned up: TypedTypingUnit( +//│ Some((Int, Int, Int?,))) +//│ where: +//│ allVarPols: +//│ consed: Map() +//│ ⬤ Unskid: TypedTypingUnit( +//│ Some((Int, Int, Int?,))) +//│ where: +//│ analyze1[+] (Int, Int, Int?,) +//│ | analyze1[+] Int +//│ | analyze1[+] Int +//│ | analyze1[+] Int +//│ [inv] +//│ [nums] +//│ analyze2[+] (Int, Int, Int?,) +//│ | analyze2[+] Int +//│ | analyze2[+] Int +//│ | analyze2[+] Int +//│ [occs] +//│ [vars] TreeSet() +//│ [rec] Set() +//│ [sub] +//│ [bounds] +//│ [rec] Set() +//│ transform[+] (Int, Int, Int?,) () + None +//│ | transform[+] Int () + None +//│ | ~> Int +//│ | transform[+] Int () + None +//│ | ~> Int +//│ | transform[+] Int () + None +//│ | ~> Int +//│ ~> (Int, Int, Int?,) +//│ ⬤ Type after simplification: TypedTypingUnit( +//│ Some((Int, Int, Int?,))) +//│ where: +//│ allVarPols: +//│ normLike[+] TypedTypingUnit( +//│ Some((Int, Int, Int?,))) +//│ | norm[+] (Int, Int, Int?,) +//│ | | DNF: DNF(0, (Int, Int, Int?,){}) +//│ | | norm[+] Int +//│ | | | DNF: DNF(0, #Int{}) +//│ | | ~> #Int +//│ | | norm[+] Int +//│ | | | DNF: DNF(0, #Int{}) +//│ | | ~> #Int +//│ | | norm[+] Int +//│ | | | DNF: DNF(0, #Int{}) +//│ | | ~> #Int +//│ | ~> (#Int, #Int, #Int?,) +//│ ⬤ Normalized: TypedTypingUnit( +//│ Some((#Int, #Int, #Int?,))) +//│ where: +//│ allVarPols: +//│ ⬤ Cleaned up: TypedTypingUnit( +//│ Some((#Int, #Int, #Int?,))) +//│ where: +//│ allVarPols: +//│ consed: Map() +//│ ⬤ Unskid: TypedTypingUnit( +//│ Some((#Int, #Int, #Int?,))) +//│ where: +//│ analyze1[+] (#Int, #Int, #Int?,) +//│ | analyze1[+] #Int +//│ | analyze1[+] #Int +//│ | analyze1[+] #Int +//│ [inv] +//│ [nums] +//│ analyze2[+] (#Int, #Int, #Int?,) +//│ | analyze2[+] #Int +//│ | analyze2[+] #Int +//│ | analyze2[+] #Int +//│ [occs] +//│ [vars] TreeSet() +//│ [rec] Set() +//│ [sub] +//│ [bounds] +//│ [rec] Set() +//│ transform[+] (#Int, #Int, #Int?,) () + None +//│ | transform[+] #Int () + None +//│ | ~> #Int +//│ | transform[+] #Int () + None +//│ | ~> #Int +//│ | transform[+] #Int () + None +//│ | ~> #Int +//│ ~> (#Int, #Int, #Int?,) +//│ ⬤ Resim: TypedTypingUnit( +//│ Some((#Int, #Int, #Int?,))) +//│ where: +//│ allVarPols: +//│ [subs] HashMap() +//│ ⬤ Factored: TypedTypingUnit( +//│ Some((#Int, #Int, #Int?,))) +//│ where: //│ sim => TypedTypingUnit( -//│ Some((#Int, #Int, #Int,))) +//│ Some((#Int, #Int, #Int?,))) //│ exp => class mlscript.Signature //│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) -//│ (Int, Int, Int,) +//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) +//│ (Int, Int, Int?,) //│ res //│ = [ 1, 2 ] @@ -322,12 +421,12 @@ fun foo(xs: [Int] & 'a) = xs : [Int, Int?] //│ AST: TypingUnit(NuFunDef(None, foo, [], Lam(Tup(xs: App(App(Var(&), Tup(_: Var(Int))), Tup(_: Var('a)))), Asc(Var(xs), Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))))))) //│ Parsed: fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,); //│ sim => TypedTypingUnit( -//│ TypedNuFun(0,fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,),((xs: ⊥,) -> (#Int, #Int,))) +//│ TypedNuFun(0,fun foo = (xs: & (Int,) ('a,),) => xs : (Int, Int?,),((xs: ⊥,) -> (#Int, #Int?,))) //│ None) //│ exp => class mlscript.Signature -//│ members => List(fun foo: (xs: nothing,) -> (Int, Int,)) +//│ members => List(fun foo: (xs: nothing,) -> (Int, Int?,)) //│ result => None -//│ fun foo: (xs: nothing,) -> (Int, Int,) +//│ fun foo: (xs: nothing,) -> (Int, Int?,) @@ -335,12 +434,12 @@ fun foo(xs: [Int] & 'a) = xs : [Int, Int?] fun foo: [Int] | [Int, Int?] //│ sim => TypedTypingUnit( -//│ TypedNuFun(0,fun foo: (Int,) | (Int, Int?,),(Array‹#Int› & {_1: #Int})) +//│ TypedNuFun(0,fun foo: (Int,) | (Int, Int?,),(#Int, #Int?,)) //│ None) //│ exp => class mlscript.Signature -//│ members => List(fun foo: Array[Int] & {_1: Int}) +//│ members => List(fun foo: (Int, Int?,)) //│ result => None -//│ fun foo: Array[Int] & {_1: Int} +//│ fun foo: (Int, Int?,) fun foo: [Int] & [Int, Int?] //│ /!!!\ Uncaught error: java.lang.IllegalArgumentException: requirement failed From 4a6c2e7c32b513c737d4f9b12cea400745879ec6 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 11:13:52 +0800 Subject: [PATCH 18/37] add new require for intersection --- .../main/scala/mlscript/TyperHelpers.scala | 2 +- shared/src/test/diff/nu/OptionalArgs.mls | 98 +++++++++++++++---- 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/shared/src/main/scala/mlscript/TyperHelpers.scala b/shared/src/main/scala/mlscript/TyperHelpers.scala index 98184cab8..fd16d1326 100644 --- a/shared/src/main/scala/mlscript/TyperHelpers.scala +++ b/shared/src/main/scala/mlscript/TyperHelpers.scala @@ -132,7 +132,7 @@ abstract class TyperHelpers { Typer: Typer => // }(r => s"=> $r") def tupleIntersection(fs1: Ls[Opt[Var] -> FieldType], fs2: Ls[Opt[Var] -> FieldType]): Ls[Opt[Var] -> FieldType] = { - require(fs1.size === fs2.size) + require(fs1.sizeCompare(fs2) <= 0 && fs1.sizeCompare(fs2.filter(x => !x._2.opt)) >= 0) (fs1 lazyZip fs2).map { case ((S(n1), t1), (S(n2), t2)) if n1 =/= n2 => (N, t1 && t2) case ((no1, t1), (no2, t2)) => (no1 orElse no2, t1 && t2) diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index e5ebdb773..e503c2e4b 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -1,4 +1,5 @@ :NewDefs +// TODO add check two compatible fields // Typing of (a?: Int, b?: Int) is ok, but constraining is not // :d @@ -217,11 +218,11 @@ let y: C1 = x :e [x]: [C1, C1, C1?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.218: [x]: [C1, C1, C1?] +//│ ║ l.219: [x]: [C1, C1, C1?] //│ ║ ^^^ //│ ╟── expression of type `[?a]` does not match type `[C1, C1, C1?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.218: [x]: [C1, C1, C1?] +//│ ║ l.219: [x]: [C1, C1, C1?] //│ ╙── ^^^^^^^^^^^^^ //│ sim => TypedTypingUnit( //│ Some((C1, C1, C1?,))) @@ -266,11 +267,11 @@ let y: C1 = x :e []: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.267: []: [Int, Int?] +//│ ║ l.268: []: [Int, Int?] //│ ║ ^^ //│ ╟── expression of type `[]` does not match type `[Int, Int?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.267: []: [Int, Int?] +//│ ║ l.268: []: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ sim => TypedTypingUnit( //│ Some((#Int, #Int?,))) @@ -284,13 +285,13 @@ let y: C1 = x :e [1, 2, 3]: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.285: [1, 2, 3]: [Int, Int?] +//│ ║ l.286: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^^^ //│ ╟── tuple literal of type `[1, 2, 3]` does not match type `[Int, Int?]` -//│ ║ l.285: [1, 2, 3]: [Int, Int?] +//│ ║ l.286: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.285: [1, 2, 3]: [Int, Int?] +//│ ║ l.286: [1, 2, 3]: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ sim => TypedTypingUnit( //│ Some((#Int, #Int?,))) @@ -428,6 +429,15 @@ fun foo(xs: [Int] & 'a) = xs : [Int, Int?] //│ result => None //│ fun foo: (xs: [Int]) -> [Int, Int?] +fun foo(xs: [Int] & 'a) = [xs : [Int, Int?], xs] +//│ sim => TypedTypingUnit( +//│ TypedNuFun(0,fun foo = (xs: & ('(' Int, ')', 'a,),) => '(' xs : [Int, Int?], xs, ')',((xs: ((#Int,) & 'a45_49'),) -> ((#Int, #Int?,), ((#Int,) & 'a45_49'),))) +//│ None) +//│ exp => class mlscript.Signature +//│ members => List(fun foo: forall 'a. (xs: [Int] & 'a) -> [[Int, Int?], [Int] & 'a]) +//│ result => None +//│ fun foo: forall 'a. (xs: [Int] & 'a) -> [[Int, Int?], [Int] & 'a] + // TODO later: update normal form construction @@ -442,16 +452,68 @@ fun foo: [Int] | [Int, Int?] //│ fun foo: [Int, Int?] fun foo: [Int] & [Int, Int?] -//│ /!!!\ Uncaught error: java.lang.IllegalArgumentException: requirement failed -//│ at: scala.Predef$.require(Predef.scala:324) -//│ at: mlscript.TyperHelpers.tupleIntersection(TyperHelpers.scala:135) -//│ at: mlscript.TyperHelpers$SimpleTypeImpl.$amp(TyperHelpers.scala:434) -//│ at: mlscript.TyperHelpers$SimpleTypeImpl.$amp$(TyperHelpers.scala:411) -//│ at: mlscript.TyperDatatypes$SimpleType.$amp(TyperDatatypes.scala:155) -//│ at: mlscript.Typer.$anonfun$typeType2$17(Typer.scala:462) -//│ at: mlscript.Typer.$anonfun$typeType2$11(Typer.scala:464) -//│ at: mlscript.TyperHelpers.trace(TyperHelpers.scala:32) -//│ at: mlscript.Typer.rec$1(Typer.scala:621) -//│ at: mlscript.Typer.$anonfun$typeType2$2(Typer.scala:622) +//│ sim => TypedTypingUnit( +//│ TypedNuFun(0,fun foo: [Int] & [Int, Int?],(#Int,)) +//│ None) +//│ exp => class mlscript.Signature +//│ members => List(fun foo: [Int]) +//│ result => None +//│ fun foo: [Int] + +fun foo: ([Int] & [Int, Int?]) -> Int +//│ sim => TypedTypingUnit( +//│ TypedNuFun(0,fun foo: ([Int] & [Int, Int?]) -> Int,([#Int,] -> #Int)) +//│ None) +//│ exp => class mlscript.Signature +//│ members => List(fun foo: ([Int]) -> Int) +//│ result => None +//│ fun foo: ([Int]) -> Int + +foo([1, true]) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.472: foo([1, true]) +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── tuple literal of type `[1, true]` does not match type `[Int]` +//│ ║ l.472: foo([1, true]) +//│ ║ ^^^^^^^ +//│ ╟── Note: constraint arises from tuple type: +//│ ║ l.463: fun foo: ([Int] & [Int, Int?]) -> Int +//│ ╙── ^^^^^ +//│ sim => TypedTypingUnit( +//│ Some((#Int | #error<>))) +//│ exp => class mlscript.Signature +//│ members => List() +//│ result => Some(Union(TypeName(Int),TypeName(error))) +//│ Int | error +//│ res +//│ = +//│ foo is not implemented + + +fun foo: ([Int] | [Int, Int?]) -> Int +//│ sim => TypedTypingUnit( +//│ TypedNuFun(0,fun foo: ([Int] | [Int, Int?]) -> Int,([#Int, #Int?,] -> #Int)) +//│ None) +//│ exp => class mlscript.Signature +//│ members => List(fun foo: ([Int, Int?]) -> Int) +//│ result => None +//│ fun foo: ([Int, Int?]) -> Int + +foo([1, true]) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.502: foo([1, true]) +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── reference of type `true` is not an instance of type `Int` +//│ ║ l.502: foo([1, true]) +//│ ╙── ^^^^ +//│ sim => TypedTypingUnit( +//│ Some((#Int | #error<>))) +//│ exp => class mlscript.Signature +//│ members => List() +//│ result => Some(Union(TypeName(Int),TypeName(error))) +//│ Int | error +//│ res +//│ = +//│ foo is not implemented From b81c5b4510c2e7a161f86bb82ae5d976414c6bf8 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 16:25:37 +0800 Subject: [PATCH 19/37] Fix minor things in test --- shared/src/test/diff/nu/OptionalArgs.mls | 34 +++++++++--------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index e503c2e4b..b27b7b90c 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -1,9 +1,6 @@ :NewDefs // TODO add check two compatible fields -// Typing of (a?: Int, b?: Int) is ok, but constraining is not -// :d -// :ds :ds fun f1(a?: Int, b?: Int) = a + b //│ ⬤ Initial: TypedTypingUnit( @@ -151,7 +148,6 @@ fun f1(a?: Int, b?: Int) = a + b //│ fun f1: (a: Int?, b: Int?) -> Int -// using space, creates ASC in AST. :p fun f1(a: Int, b: Int) = a + b //│ |#fun| |f1|(|a|#:| |Int|,| |b|#:| |Int|)| |#=| |a| |+| |b| @@ -205,6 +201,7 @@ let y: C1 = x //│ [C1, C1] //│ res //│ = [ C2 {}, C2 {} ] + [x, y]: [C1, C1, C1?] //│ sim => TypedTypingUnit( //│ Some((C1, C1, C1?,))) @@ -218,11 +215,11 @@ let y: C1 = x :e [x]: [C1, C1, C1?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.219: [x]: [C1, C1, C1?] +//│ ║ l.216: [x]: [C1, C1, C1?] //│ ║ ^^^ //│ ╟── expression of type `[?a]` does not match type `[C1, C1, C1?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.219: [x]: [C1, C1, C1?] +//│ ║ l.216: [x]: [C1, C1, C1?] //│ ╙── ^^^^^^^^^^^^^ //│ sim => TypedTypingUnit( //│ Some((C1, C1, C1?,))) @@ -267,11 +264,11 @@ let y: C1 = x :e []: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.268: []: [Int, Int?] +//│ ║ l.265: []: [Int, Int?] //│ ║ ^^ //│ ╟── expression of type `[]` does not match type `[Int, Int?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.268: []: [Int, Int?] +//│ ║ l.265: []: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ sim => TypedTypingUnit( //│ Some((#Int, #Int?,))) @@ -285,13 +282,13 @@ let y: C1 = x :e [1, 2, 3]: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.286: [1, 2, 3]: [Int, Int?] +//│ ║ l.283: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^^^ //│ ╟── tuple literal of type `[1, 2, 3]` does not match type `[Int, Int?]` -//│ ║ l.286: [1, 2, 3]: [Int, Int?] +//│ ║ l.283: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.286: [1, 2, 3]: [Int, Int?] +//│ ║ l.283: [1, 2, 3]: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ sim => TypedTypingUnit( //│ Some((#Int, #Int?,))) @@ -302,7 +299,6 @@ let y: C1 = x //│ res //│ = [ 1, 2, 3 ] -// FIXME :ds [1, 2]: [Int, Int, Int?] //│ ⬤ Initial: TypedTypingUnit( @@ -414,8 +410,6 @@ let y: C1 = x // * Harder case: - -// why xs type is `nothing` ? :p fun foo(xs: [Int] & 'a) = xs : [Int, Int?] //│ |#fun| |foo|(|xs|#:| |[|Int|]| |&| |'a|)| |#=| |xs| |#:| |[|Int|,| |Int|?|]| @@ -471,13 +465,13 @@ fun foo: ([Int] & [Int, Int?]) -> Int foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.472: foo([1, true]) +//│ ║ l.466: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── tuple literal of type `[1, true]` does not match type `[Int]` -//│ ║ l.472: foo([1, true]) +//│ ║ l.466: foo([1, true]) //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.463: fun foo: ([Int] & [Int, Int?]) -> Int +//│ ║ l.457: fun foo: ([Int] & [Int, Int?]) -> Int //│ ╙── ^^^^^ //│ sim => TypedTypingUnit( //│ Some((#Int | #error<>))) @@ -501,10 +495,10 @@ fun foo: ([Int] | [Int, Int?]) -> Int foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.502: foo([1, true]) +//│ ║ l.496: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── reference of type `true` is not an instance of type `Int` -//│ ║ l.502: foo([1, true]) +//│ ║ l.496: foo([1, true]) //│ ╙── ^^^^ //│ sim => TypedTypingUnit( //│ Some((#Int | #error<>))) @@ -515,5 +509,3 @@ foo([1, true]) //│ res //│ = //│ foo is not implemented - - From e511ce1419436cfb425a21348cc99bfb915761a8 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 17:24:07 +0800 Subject: [PATCH 20/37] Add isSubtype for TupleTypes --- .../src/main/scala/mlscript/ConstraintSolver.scala | 4 +--- shared/src/main/scala/mlscript/TyperDatatypes.scala | 1 + shared/src/main/scala/mlscript/TyperHelpers.scala | 12 +++--------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/shared/src/main/scala/mlscript/ConstraintSolver.scala b/shared/src/main/scala/mlscript/ConstraintSolver.scala index 47ba54448..a60fa0115 100644 --- a/shared/src/main/scala/mlscript/ConstraintSolver.scala +++ b/shared/src/main/scala/mlscript/ConstraintSolver.scala @@ -846,9 +846,7 @@ class ConstraintSolver extends NormalForms { self: Typer => } - case (TupleType(fs0), TupleType(fs1)) if fs0.sizeCompare(fs1) <= 0 && fs0.sizeCompare(fs1.filter(x => !x._2.opt)) >= 0 => { // TODO[optional-fields] generalize (coerce compatible tuples) - println("case #1") - + case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) if t0.isSubtype(t1) => { fs0.lazyZip(fs1).foreach { case ((ln, l), (rn, r)) => ln.foreach { ln => rn.foreach { rn => if (ln =/= rn) err( diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala index 700611bbc..97181695d 100644 --- a/shared/src/main/scala/mlscript/TyperDatatypes.scala +++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala @@ -274,6 +274,7 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => fields.map(f => s"${f._1.fold("")(_.name+": ")}${f._2},").mkString(" ") override def toString = s"($showInner)" // override def toString = s"(${fields.map(f => s"${f._1.fold("")(_+": ")}${f._2},").mkString(" ")})" + def isSubtype(that: TupleType): Boolean = fields.sizeCompare(that.fields) <= 0 && fields.sizeCompare(that.fields.filter(x => !x._2.opt)) >= 0 } case class SpliceType(elems: Ls[Either[SimpleType, FieldType]])(val prov: TypeProvenance) extends ArrayBase { diff --git a/shared/src/main/scala/mlscript/TyperHelpers.scala b/shared/src/main/scala/mlscript/TyperHelpers.scala index fd16d1326..f40769b69 100644 --- a/shared/src/main/scala/mlscript/TyperHelpers.scala +++ b/shared/src/main/scala/mlscript/TyperHelpers.scala @@ -427,10 +427,7 @@ abstract class TyperHelpers { Typer: Typer => case (RecordType(fs1), RecordType(fs2)) => RecordType(mergeSortedMap(fs1, fs2)(_ && _).toList)(prov) case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) => { - println("case #2") - - // TODO[optional-fields] update this condition - if (fs0.sizeCompare(fs1) > 0 || fs0.sizeCompare(fs1.filter(x => !x._2.opt)) < 0) BotType + if (!t0.isSubtype(t1)) BotType else TupleType(tupleIntersection(fs0, fs1))(t0.prov) } case _ if !swapped => that & (this, prov, swapped = true) @@ -491,13 +488,10 @@ abstract class TyperHelpers { Typer: Typer => // case (ClassTag(ErrTypeId, _), _) | (_, ClassTag(ErrTypeId, _)) => true case (_: TypeTag, _: TypeTag) | (_: TV, _: TV) if this === that => true case (ab: ArrayBase, at: ArrayType) => ab.inner <:< at.inner - case (TupleType(fs1), TupleType(fs2)) => { - // TODO[optional-fields] generalize: handle optionality; eg: [Int] <:< [Int, Int?] - println(s"case #3 ${fs1} ${fs2}") - fs1.sizeCompare(fs2) <= 0 && fs1.sizeCompare(fs2.filter(x => !x._2.opt)) >= 0 && fs1.lazyZip(fs2).forall { + case (t1 @ TupleType(fs1), t2 @ TupleType(fs2)) => + t1.isSubtype(t2) && fs1.lazyZip(fs2).forall { case ((_, ty1), (_, ty2)) => ty1 <:< ty2 } - } case (RecordType(Nil), _) => TopType <:< that case (_, RecordType(Nil)) => this <:< TopType case (pt1 @ ClassTag(id1, ps1), pt2 @ ClassTag(id2, ps2)) => (id1 === id2) || pt1.parentsST(id2) From 33fc41fd2270e129acc2e3cde8506b7267f25bd8 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 17:27:00 +0800 Subject: [PATCH 21/37] Add error flag for some tests --- shared/src/test/diff/nu/OptionalArgs.mls | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index b27b7b90c..2182074e6 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -463,12 +463,13 @@ fun foo: ([Int] & [Int, Int?]) -> Int //│ result => None //│ fun foo: ([Int]) -> Int +:e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.466: foo([1, true]) +//│ ║ l.467: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── tuple literal of type `[1, true]` does not match type `[Int]` -//│ ║ l.466: foo([1, true]) +//│ ║ l.467: foo([1, true]) //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: //│ ║ l.457: fun foo: ([Int] & [Int, Int?]) -> Int @@ -493,12 +494,13 @@ fun foo: ([Int] | [Int, Int?]) -> Int //│ result => None //│ fun foo: ([Int, Int?]) -> Int +:e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.496: foo([1, true]) +//│ ║ l.498: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── reference of type `true` is not an instance of type `Int` -//│ ║ l.496: foo([1, true]) +//│ ║ l.498: foo([1, true]) //│ ╙── ^^^^ //│ sim => TypedTypingUnit( //│ Some((#Int | #error<>))) From 79a51a058cd11ec592f0e4fd053a750f3a778c6b Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 17:33:31 +0800 Subject: [PATCH 22/37] Delete some extra debugs --- shared/src/main/scala/mlscript/JSBackend.scala | 2 +- shared/src/main/scala/mlscript/NewParser.scala | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/shared/src/main/scala/mlscript/JSBackend.scala b/shared/src/main/scala/mlscript/JSBackend.scala index 11b069753..d0806f9b3 100644 --- a/shared/src/main/scala/mlscript/JSBackend.scala +++ b/shared/src/main/scala/mlscript/JSBackend.scala @@ -953,7 +953,7 @@ class JSBackend(allowUnresolvedSymbols: Boolean) { case (S(nme), Fld(FldFlags(mut, spec, opt), trm)) => val ty = tt(trm) nme -> Field(if (mut) S(ty) else N, ty, false) - case (N, Fld(FldFlags(mut, spec, opt), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top, false) + case (N, Fld(FldFlags(mut, spec, opt), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top, opt) case _ => die } val body = pars.map(tt).foldRight(Record(params): Type)(Inter) diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index f9d27f118..2768d2dea 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -541,7 +541,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo cur.dropWhile(_._1 === SPACE && { consume; true }) final def funParams(implicit et: ExpectThen, fe: FoundErr, l: Line): Ls[Tup] = wrap(()) { l => - val res = yeetSpaces match { + yeetSpaces match { case (KEYWORD("=" | ":"), _) :: _ => Nil case Nil => Nil case (KEYWORD("of"), _) :: _ => @@ -559,13 +559,6 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo consume Nil } - res match { - case x :: _ => - printDbg(s"Here, creating the params! ${res} ${Helpers.inspect(x)}" ) - case Nil => - printDbg(s"Here, (not) creating the params! ${res}") - } - res } final def expr(prec: Int, allowSpace: Bool = true)(implicit fe: FoundErr, l: Line): Term = wrap(prec,allowSpace) { l => From a190864c7713086936ebbc35789bc6e00fedd694 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 17:34:41 +0800 Subject: [PATCH 23/37] Delete some extra debugs --- shared/src/main/scala/mlscript/NewParser.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index 2768d2dea..67fd7c6d8 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -562,15 +562,12 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo } final def expr(prec: Int, allowSpace: Bool = true)(implicit fe: FoundErr, l: Line): Term = wrap(prec,allowSpace) { l => - val result = exprOrIf(prec, allowSpace)(et = false, fe = fe, l = implicitly) match { + exprOrIf(prec, allowSpace)(et = false, fe = fe, l = implicitly) match { case R(e) => e case L(e) => err(msg"Expected an expression; found a 'then'/'else' clause instead" -> e.toLoc :: Nil) errExpr } - printDbg(s"result => ${result} ## ${Helpers.inspect(result)}") - printDbg(s"result toType => ${result.toType}") - result } private def warnDbg(msg: Any, loco: Opt[Loc] = curLoc): Unit = From e882b7c168d3afb153b226e4d24bb3048f8ae493 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 17:38:42 +0800 Subject: [PATCH 24/37] Delete some extra debugs --- shared/src/main/scala/mlscript/NewParser.scala | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index 67fd7c6d8..045386f82 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -1116,11 +1116,6 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo } // val e = expr(NoElsePrec) -> argMut.isDefined val body = exprOrIf(prec) - cur match { - case x :: _ => - printDbg(s"nexttoken => ${x}") - case _ => () - } val isOptinoal = cur match { case (IDENT("?", true), l0) :: _ => consume @@ -1129,15 +1124,6 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo false } val e = body.map(Fld(FldFlags(argMut.isDefined, argSpec.isDefined, argOpt.isDefined || isOptinoal), _)) - printDbg(s"flags => ${argMut} ${argSpec} ${argOpt}") - printDbg(s"e => ${e}") - - body match { - case Right(value) => - printDbg(s"body => ${value} ${Helpers.inspect(value)}") - case _ => () - } - def mkSeq = if (seqAcc.isEmpty) argName -> e else e match { case L(_) => ??? From 01ddc6607f7b0a86b3f55dcbfb679ab755b9cffe Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 17:46:52 +0800 Subject: [PATCH 25/37] Fix some possible? bugs --- shared/src/main/scala/mlscript/NuTypeDefs.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shared/src/main/scala/mlscript/NuTypeDefs.scala b/shared/src/main/scala/mlscript/NuTypeDefs.scala index 4af240adb..0d4a42d25 100644 --- a/shared/src/main/scala/mlscript/NuTypeDefs.scala +++ b/shared/src/main/scala/mlscript/NuTypeDefs.scala @@ -680,12 +680,12 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => mxn.params.size.toString} parameter(s); got ${parArgs.size.toString}", Loc(v :: parArgs.unzip._2)) val paramMems = mxn.params.lazyZip(parArgs).map { - case (nme -> p, _ -> Fld(_, a)) => // TODO check name, mut, spec + case (nme -> p, _ -> Fld(flags, a)) => // TODO check name, mut, spec implicit val genLambdas: GenLambdas = true val a_ty = typeTerm(a) p.lb.foreach(constrain(_, a_ty)) constrain(a_ty, p.ub) - NuParam(nme, FieldType(p.lb, a_ty, false)(provTODO))(lvl) + NuParam(nme, FieldType(p.lb, a_ty, flags.opt)(provTODO))(lvl) } paramMems //++ mxn.members.valuesIterator @@ -731,12 +731,12 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => err(msg"class $parNme expects ${ cls.params.size.toString} parameter(s); got ${parArgs.size.toString}", Loc(v :: parArgs.unzip._2)) - val paramMems = cls.params.lazyZip(parArgs).map { case (nme -> p, _ -> Fld(_, a)) => // TODO check name, mut, spec + val paramMems = cls.params.lazyZip(parArgs).map { case (nme -> p, _ -> Fld(flags, a)) => // TODO check name, mut, spec implicit val genLambdas: GenLambdas = true val a_ty = typeTerm(a) p.lb.foreach(constrain(_, a_ty)) constrain(a_ty, p.ub) - NuParam(nme, FieldType(p.lb, a_ty, false)(provTODO))(lvl) + NuParam(nme, FieldType(p.lb, a_ty, flags.opt)(provTODO))(lvl) } S((cls, paramMems, ptp ++ cls.parentTP, p.toLoc)) @@ -821,14 +821,14 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => case R(tpe) => implicit val newDefsInfo: Map[Str, (TypeDefKind, Int)] = Map.empty // TODO? val ty = typeType(tpe) - nme -> FieldType(N, ty, false)(provTODO) + nme -> FieldType(N, ty, opt)(provTODO) case _ => ??? } case (N, Fld(FldFlags(mut, spec, opt), nme: Var)) => // assert(!mut && !spec, "TODO") // TODO // nme -> FieldType(N, freshVar(ttp(nme), N, S(nme.name)))(provTODO) nme -> FieldType(N, err(msg"${td.kind.str.capitalize} parameters currently need type annotations", - nme.toLoc), false)(provTODO) + nme.toLoc), opt)(provTODO) case _ => ??? } case fd: NuFunDef => Nil From 8383e097936db45afd92690db9634b2333bbf58b Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 18:03:17 +0800 Subject: [PATCH 26/37] Delete extra log in DiffTests --- shared/src/test/diff/basics/Data.fun | 10 +- shared/src/test/diff/basics/Datatypes.fun | 10 +- shared/src/test/diff/codegen/SymbolicOps.mls | 78 ++++++---- shared/src/test/diff/fcp/NestedDataTypes.mls | 12 -- .../test/diff/fcp/QML_exist_Classes_CT.mls | 48 +++--- shared/src/test/diff/nu/OptionalArgs.mls | 144 ++---------------- .../src/test/scala/mlscript/DiffTests.scala | 9 -- 7 files changed, 88 insertions(+), 223 deletions(-) diff --git a/shared/src/test/diff/basics/Data.fun b/shared/src/test/diff/basics/Data.fun index cacd50e91..5efdd5722 100644 --- a/shared/src/test/diff/basics/Data.fun +++ b/shared/src/test/diff/basics/Data.fun @@ -12,16 +12,8 @@ data Test a b data Person(name: string, age: int) //│ Parsed: data Person '(' {name: string, age: int,} ')'; //│ Desugared: class Person: {age: int, name: string} -<<<<<<< HEAD -//│ Desugared: def Person: (name: string, age: int,) -> Person[] -//│ AST: Def(false, Person, PolyType(List(),Function(Tuple(List((Some(name),Field(None,TypeName(string),false)), (Some(age),Field(None,TypeName(int),false)))),AppliedType(TypeName(Person),List()))), true) -||||||| a0084daf -//│ Desugared: def Person: (name: string, age: int,) -> Person[] -//│ AST: Def(false, Person, PolyType(List(),Function(Tuple(List((Some(name),Field(None,TypeName(string))), (Some(age),Field(None,TypeName(int))))),AppliedType(TypeName(Person),List()))), true) -======= //│ Desugared: def Person: (name: string, age: int) -> Person[] -//│ AST: Def(false, Person, PolyType(List(),Function(Tuple(List((Some(name),Field(None,TypeName(string))), (Some(age),Field(None,TypeName(int))))),AppliedType(TypeName(Person),List()))), true) ->>>>>>> new-definition-typing +//│ AST: Def(false, Person, PolyType(List(),Function(Tuple(List((Some(name),Field(None,TypeName(string),false)), (Some(age),Field(None,TypeName(int),false)))),AppliedType(TypeName(Person),List()))), true) //│ Defined class Person //│ Person: (name: string, age: int,) -> Person diff --git a/shared/src/test/diff/basics/Datatypes.fun b/shared/src/test/diff/basics/Datatypes.fun index ec0e3497a..c4440f47c 100644 --- a/shared/src/test/diff/basics/Datatypes.fun +++ b/shared/src/test/diff/basics/Datatypes.fun @@ -123,16 +123,8 @@ data type List a of //│ 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) -<<<<<<< HEAD -//│ 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),false)))),Function(Tuple(List((Some(tail),Field(None,AppliedType(TypeName(List),List(TypeName(a))),false)))),AppliedType(TypeName(Cons),List(TypeName(a)))))), true) -||||||| a0084daf -//│ 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) ->>>>>>> new-definition-typing +//│ AST: Def(false, Cons, PolyType(List(Left(TypeName(a))),Function(Tuple(List((Some(head),Field(None,TypeName(a),false)))),Function(Tuple(List((Some(tail),Field(None,Top,false)))),AppliedType(TypeName(Cons),List(TypeName(a)))))), true) //│ Defined type alias List[+a] //│ Defined class Nil[±a] //│ Defined class Cons[+a] diff --git a/shared/src/test/diff/codegen/SymbolicOps.mls b/shared/src/test/diff/codegen/SymbolicOps.mls index c2e09605e..aead38fc1 100644 --- a/shared/src/test/diff/codegen/SymbolicOps.mls +++ b/shared/src/test/diff/codegen/SymbolicOps.mls @@ -160,45 +160,67 @@ abstract class Nested { fun (??) oops: (Int, Int) => Int -//│ fun (??) oops: (Int, Int) -> Int +//│ ╔══[PARSE ERROR] Unexpected operator after symbolic name +//│ ║ l.162: fun (??) oops: (Int, Int) => Int +//│ ╙── ^ +//│ fun (?) oops: (Int, Int) -> Int 1 ?? 2 -//│ Int +//│ ╔══[PARSE ERROR] Expected end of input; found operator instead +//│ ║ l.168: 1 ?? 2 +//│ ╙── ^ +//│ 1 //│ res -//│ = -//│ ?? is not implemented +//│ = 1 fun (??) oops: (Int, Int) => Int fun oops(a, b) = a + b +//│ ╔══[PARSE ERROR] Unexpected operator after symbolic name +//│ ║ l.176: fun (??) oops: (Int, Int) => Int +//│ ╙── ^ //│ fun oops: (Int, Int) -> Int -//│ fun (??) oops: (Int, Int) -> Int +//│ fun (?) oops: (Int, Int) -> Int // FIXME-later (stub symbols) This is actually implemented... 1 ?? 2 -//│ Int +//│ ╔══[PARSE ERROR] Expected end of input; found operator instead +//│ ║ l.185: 1 ?? 2 +//│ ╙── ^ +//│ 1 //│ res -//│ = -//│ ?? is not implemented +//│ = 1 fun oops: (Int, Int) => Int fun (??) oops(a, b) = a + b -//│ fun (??) oops: (Int, Int) -> Int +//│ ╔══[PARSE ERROR] Unexpected operator after symbolic name +//│ ║ l.194: fun (??) oops(a, b) = a + b +//│ ╙── ^ +//│ fun (?) oops: (Int, Int) -> Int //│ fun oops: (Int, Int) -> Int 1 ?? 2 -//│ Int +//│ ╔══[PARSE ERROR] Expected end of input; found operator instead +//│ ║ l.201: 1 ?? 2 +//│ ╙── ^ +//│ 1 //│ res -//│ = 3 +//│ = 1 fun (!?) oops: (Int, Int) => Int fun (??) oops(a, b) = a + b -//│ fun (??) oops: (Int, Int) -> Int +//│ ╔══[PARSE ERROR] Unexpected operator after symbolic name +//│ ║ l.210: fun (??) oops(a, b) = a + b +//│ ╙── ^ +//│ fun (?) oops: (Int, Int) -> Int //│ fun (!?) oops: (Int, Int) -> Int 1 ?? 2 -//│ Int +//│ ╔══[PARSE ERROR] Expected end of input; found operator instead +//│ ║ l.217: 1 ?? 2 +//│ ╙── ^ +//│ 1 //│ res -//│ = 3 +//│ = 1 1 !? 2 //│ Int @@ -214,16 +236,16 @@ fun (??) oops(a, b) = a + b :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)) +//│ ║ l.237: fun (>>)(f, g) = x => g(f(x)) //│ ╙── ^^^^^^ //│ ╔══[ERROR] identifier not found: g -//│ ║ l.215: fun (>>)(f, g) = x => g(f(x)) +//│ ║ l.237: fun (>>)(f, g) = x => g(f(x)) //│ ╙── ^ //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.215: fun (>>)(f, g) = x => g(f(x)) +//│ ║ l.237: 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)) +//│ ║ l.237: fun (>>)(f, g) = x => g(f(x)) //│ ║ ^^^ //│ ╟── Note: constraint arises from tuple literal: //│ ║ l.4: fun (>>) compose(f, g) = x => g(f(x)) @@ -235,7 +257,7 @@ fun (>>)(f, g) = x => g(f(x)) :pe fun compose(>>)(f, g) = x => g(f(x)) //│ ╔══[PARSE ERROR] Unexpected operator here -//│ ║ l.236: fun compose(>>)(f, g) = x => g(f(x)) +//│ ║ l.258: fun compose(>>)(f, g) = x => g(f(x)) //│ ╙── ^^ //│ fun compose: forall 'a 'b 'c. () -> ('a -> 'b, 'b -> 'c) -> 'a -> 'c @@ -243,14 +265,14 @@ fun compose(>>)(f, g) = x => g(f(x)) :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 +//│ ║ l.266: 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 +//│ ║ l.273: fun ( ) foo(a, b) = a + b //│ ╙── ^^^ //│ fun foo: (Int, Int) -> Int @@ -258,30 +280,30 @@ fun ( ) foo(a, b) = a + b fun ( ) foo(a, b) = a + b //│ ╔══[PARSE ERROR] Expected a symbolic name, found newline instead -//│ ║ l.258: fun ( +//│ ║ l.280: fun ( //│ ║ ^ -//│ ║ l.259: ) foo(a, b) = a + b +//│ ║ l.281: ) 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 +//│ ║ l.290: 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 +//│ ║ l.297: 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 +//│ ║ l.304: fun (a ++ 1) foo(a, b) = a + b //│ ╙── ^ //│ fun foo: (Int, Int) -> Int // should be `<<|+_+|>>`, but we got `<<|+` @@ -290,7 +312,7 @@ fun (a ++ 1) foo(a, b) = a + b :pe fun (<<|+_+|>>) robot(a, b) = a + b //│ ╔══[PARSE ERROR] Unexpected identifier after symbolic name -//│ ║ l.291: fun (<<|+_+|>>) robot(a, b) = a + b +//│ ║ l.313: fun (<<|+_+|>>) robot(a, b) = a + b //│ ╙── ^ //│ fun (<<|+) robot: (Int, Int) -> Int @@ -306,7 +328,7 @@ fun (<<|+-+|>>) robot(a, b) = a + b :pe fun (:-D) dd(a, b) = a + b //│ ╔══[PARSE ERROR] Unexpected identifier after symbolic name -//│ ║ l.307: fun (:-D) dd(a, b) = a + b +//│ ║ l.329: fun (:-D) dd(a, b) = a + b //│ ╙── ^ //│ fun (:-) dd: (Int, Int) -> Int // should be `:-D`, but we got `:-` diff --git a/shared/src/test/diff/fcp/NestedDataTypes.mls b/shared/src/test/diff/fcp/NestedDataTypes.mls index 2a2712d6e..aeeb2a8a3 100644 --- a/shared/src/test/diff/fcp/NestedDataTypes.mls +++ b/shared/src/test/diff/fcp/NestedDataTypes.mls @@ -238,14 +238,8 @@ rec def map f tree = case tree of { //│ where //│ 'map :> forall 'A 'subTree 'value 'value0 'a 'subTree0. 'a -> ((Leaf[?] & {value: 'value} | (Node[?] with {subTree: 'subTree0})) -> (Leaf['value0] | (Node['A] with {subTree: 'subTree})) //│ where -<<<<<<< HEAD //│ 'a <: 'value -> 'value0 -//│ 'map <: (forall 'b 'c 'd 'e. ('b, 'd,) -> ('c, 'e,) -||||||| a0084daf -//│ 'map <: (forall 'b 'c 'd 'e. ('b, 'd,) -> ('c, 'e,) -======= //│ 'map <: (forall 'b 'c 'd 'e. (('b, 'd,),) -> ('c, 'e,) ->>>>>>> new-definition-typing //│ where //│ 'a <: 'b -> 'c & 'd -> 'e) -> 'subTree0 -> (PerfectTree[Two['A]] & 'subTree)) //│ ╙── @@ -253,14 +247,8 @@ rec def map f tree = case tree of { //│ where //│ 'map :> forall 'subTree 'value 'value0 'subTree0 'a 'A. 'a -> ((Leaf[?] & {value: 'value} | (Node[?] with {subTree: 'subTree0})) -> (Leaf['value0] | (Node['A] with {subTree: 'subTree})) //│ where -<<<<<<< HEAD //│ 'a <: 'value -> 'value0 -//│ 'map <: (forall 'b 'c 'd 'e. ('b, 'd,) -> ('c, 'e,) -||||||| a0084daf -//│ 'map <: (forall 'b 'c 'd 'e. ('b, 'd,) -> ('c, 'e,) -======= //│ 'map <: (forall 'b 'c 'd 'e. (('b, 'd,),) -> ('c, 'e,) ->>>>>>> new-definition-typing //│ where //│ 'a <: 'b -> 'c & 'd -> 'e) -> 'subTree0 -> (PerfectTree[Two['A]] & 'subTree)) //│ = [Function: map1] diff --git a/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls b/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls index 454f22488..7845ef46b 100644 --- a/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls +++ b/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls @@ -77,14 +77,14 @@ def simpleStepImpl arrImpl = ArraysImpl { update = fun ((r0, r1)) -> fun i -> fun a -> (arrImpl.Update r0 i a, "updated"); fold = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.Fold f b r0 } -//│ simpleStepImpl: (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with {fold: forall 'b 'A0 'Rep0 'd. 'd -> 'b -> (('Rep0, anything,) -> 'b +//│ simpleStepImpl: (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with {fold: forall 'b 'A0 'Rep0 'd. 'd -> 'b -> ((('Rep0, anything,),) -> 'b //│ where //│ 'd <: 'A0 -> 'b -> 'b //│ 'c <: ArraysRep['A0, 'Rep0]), init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) //│ where -//│ 'c <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. ('Rep2, anything,) -> (int -> 'A2 +//│ 'c <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 //│ where -//│ 'c <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. ('Rep3, anything,) -> int -> ('A3 -> ('Rep3, "updated",) +//│ 'c <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) //│ where //│ 'c <: ArraysRep['A3, 'Rep3])}) //│ where @@ -106,14 +106,14 @@ def simpleStepImpl2_ty: (forall 'r. (ArraysRep['A, 'Rep] -> 'r) -> 'r) -> Arrays def simpleStepImpl2 arr = arr simpleStepImpl -//│ simpleStepImpl2: ((forall 'A 'a 'c 'Rep. (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with {fold: forall 'd 'b 'A0 'Rep0. 'd -> 'b -> (('Rep0, anything,) -> 'b +//│ simpleStepImpl2: ((forall 'A 'a 'c 'Rep. (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with {fold: forall 'd 'b 'A0 'Rep0. 'd -> 'b -> ((('Rep0, anything,),) -> 'b //│ where //│ 'd <: 'A0 -> 'b -> 'b //│ 'c <: ArraysRep['A0, 'Rep0]), init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) //│ where -//│ 'c <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. ('Rep2, anything,) -> (int -> 'A2 +//│ 'c <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 //│ where -//│ 'c <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. ('Rep3, anything,) -> int -> ('A3 -> ('Rep3, "updated",) +//│ 'c <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) //│ where //│ 'c <: ArraysRep['A3, 'Rep3])})) -> 'e) -> 'e //│ where @@ -122,14 +122,14 @@ def simpleStepImpl2 arr = arr simpleStepImpl //│ = [Function: simpleStepImpl2] simpleStepImpl2_ty = simpleStepImpl2 -//│ ((forall 'A 'a 'c 'Rep. (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with {fold: forall 'd 'b 'A0 'Rep0. 'd -> 'b -> (('Rep0, anything,) -> 'b +//│ ((forall 'A 'a 'c 'Rep. (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with {fold: forall 'd 'b 'A0 'Rep0. 'd -> 'b -> ((('Rep0, anything,),) -> 'b //│ where //│ 'd <: 'A0 -> 'b -> 'b //│ 'c <: ArraysRep['A0, 'Rep0]), init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) //│ where -//│ 'c <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. ('Rep2, anything,) -> (int -> 'A2 +//│ 'c <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 //│ where -//│ 'c <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. ('Rep3, anything,) -> int -> ('A3 -> ('Rep3, "updated",) +//│ 'c <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) //│ where //│ 'c <: ArraysRep['A3, 'Rep3])})) -> 'e) -> 'e //│ where @@ -180,14 +180,14 @@ def simpleStep: Arrays['a] -> Arrays['a] def simpleStep arr f = f (simpleStepImpl2 arr) //│ 'a -> (('c -> 'd) -> 'd //│ where -//│ 'a <: (forall 'A 'e 'f 'Rep. (ArraysRep['A, 'e] & 'f) -> (ArraysImpl['A, 'Rep] with {fold: forall 'g 'b 'A0 'Rep0. 'g -> 'b -> (('Rep0, anything,) -> 'b +//│ 'a <: (forall 'A 'e 'f 'Rep. (ArraysRep['A, 'e] & 'f) -> (ArraysImpl['A, 'Rep] with {fold: forall 'g 'b 'A0 'Rep0. 'g -> 'b -> ((('Rep0, anything,),) -> 'b //│ where //│ 'g <: 'A0 -> 'b -> 'b //│ 'f <: ArraysRep['A0, 'Rep0]), init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) //│ where -//│ 'f <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. ('Rep2, anything,) -> (int -> 'A2 +//│ 'f <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 //│ where -//│ 'f <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. ('Rep3, anything,) -> int -> ('A3 -> ('Rep3, "updated",) +//│ 'f <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) //│ where //│ 'f <: ArraysRep['A3, 'Rep3])})) -> 'c) //│ where @@ -351,14 +351,14 @@ def stepImpl arrImpl = ArraysImpl { else (r0, arrImpl.Update r1 (div i 2) a); fold = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.Fold f (arrImpl.Fold f b r0) r1 } -//│ stepImpl: (ArraysRep['A, in 'a & 'c out 'a | 'c] & 'd) -> (ArraysImpl['A, 'Rep] with {fold: forall 'Rep0 'Rep1 'e 'A0 'b 'f 'b0 'A1. 'e -> 'f -> (('Rep0, 'Rep1,) -> ('f | 'b0) +//│ stepImpl: (ArraysRep['A, in 'a & 'c out 'a | 'c] & 'd) -> (ArraysImpl['A, 'Rep] with {fold: forall 'Rep0 'Rep1 'e 'A0 'b 'f 'b0 'A1. 'e -> 'f -> ((('Rep0, 'Rep1,),) -> ('f | 'b0) //│ where //│ 'd <: ArraysRep['A1, 'Rep1] & ArraysRep['A0, 'Rep0] //│ 'e <: 'A1 -> ('f | 'b0) -> 'b0 & 'A0 -> ('b | 'f) -> ('b0 & 'b)), init: forall 'A2 'Rep2 'A3 'Rep3. ('A3 & 'A2) -> ('Rep3, 'Rep2,) //│ where -//│ 'd <: ArraysRep['A3, 'Rep3] & ArraysRep['A2, 'Rep2], sub: forall 'A4 'g 'Rep4 'A5 'Rep5. ('Rep4, 'Rep5,) -> (int -> 'g +//│ 'd <: ArraysRep['A3, 'Rep3] & ArraysRep['A2, 'Rep2], sub: forall 'A4 'g 'Rep4 'A5 'Rep5. (('Rep4, 'Rep5,),) -> (int -> 'g //│ where -//│ 'd <: ArraysRep['A4, 'Rep4] & ArraysRep['A5, 'Rep5]), update: forall 'Rep6 'Rep7 'A6 'A7. ('Rep6, 'Rep7,) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) +//│ 'd <: ArraysRep['A4, 'Rep4] & ArraysRep['A5, 'Rep5]), update: forall 'Rep6 'Rep7 'A6 'A7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) //│ where //│ 'd <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7])}) //│ where @@ -372,14 +372,14 @@ def stepImpl2_ty: (forall 'r. (ArraysRep['A, 'Rep] -> 'r) -> 'r) -> ArraysImpl[' //│ = def stepImpl2 arr = arr stepImpl -//│ stepImpl2: ((forall 'a 'c 'A 'Rep 'd. (ArraysRep['A, in 'c & 'a out 'c | 'a] & 'd) -> (ArraysImpl['A, 'Rep] with {fold: forall 'Rep0 'A0 'Rep1 'e 'b 'A1 'f 'b0. 'e -> 'f -> (('Rep0, 'Rep1,) -> ('f | 'b0) +//│ stepImpl2: ((forall 'a 'c 'A 'Rep 'd. (ArraysRep['A, in 'c & 'a out 'c | 'a] & 'd) -> (ArraysImpl['A, 'Rep] with {fold: forall 'Rep0 'A0 'Rep1 'e 'b 'A1 'f 'b0. 'e -> 'f -> ((('Rep0, 'Rep1,),) -> ('f | 'b0) //│ where //│ 'e <: 'A0 -> ('f | 'b0) -> 'b0 & 'A1 -> ('b | 'f) -> ('b0 & 'b) //│ 'd <: ArraysRep['A0, 'Rep1] & ArraysRep['A1, 'Rep0]), init: forall 'A2 'Rep2 'A3 'Rep3. ('A2 & 'A3) -> ('Rep2, 'Rep3,) //│ where -//│ 'd <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], sub: forall 'Rep4 'A4 'Rep5 'A5 'g. ('Rep4, 'Rep5,) -> (int -> 'g +//│ 'd <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], sub: forall 'Rep4 'A4 'Rep5 'A5 'g. (('Rep4, 'Rep5,),) -> (int -> 'g //│ where -//│ 'd <: ArraysRep['A5, 'Rep4] & ArraysRep['A4, 'Rep5]), update: forall 'Rep6 'Rep7 'A6 'A7. ('Rep6, 'Rep7,) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) +//│ 'd <: ArraysRep['A5, 'Rep4] & ArraysRep['A4, 'Rep5]), update: forall 'Rep6 'Rep7 'A6 'A7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) //│ where //│ 'd <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7])})) -> 'h) -> 'h //│ where @@ -389,14 +389,14 @@ def stepImpl2 arr = arr stepImpl //│ = [Function: stepImpl2] stepImpl2_ty = stepImpl2 -//│ ((forall 'a 'Rep 'A 'c 'd. (ArraysRep['A, in 'c & 'd out 'c | 'd] & 'a) -> (ArraysImpl['A, 'Rep] with {fold: forall 'b 'Rep0 'e 'A0 'Rep1 'f 'b0 'A1. 'e -> 'f -> (('Rep0, 'Rep1,) -> ('f | 'b) +//│ ((forall 'a 'Rep 'A 'c 'd. (ArraysRep['A, in 'c & 'd out 'c | 'd] & 'a) -> (ArraysImpl['A, 'Rep] with {fold: forall 'b 'Rep0 'e 'A0 'Rep1 'f 'b0 'A1. 'e -> 'f -> ((('Rep0, 'Rep1,),) -> ('f | 'b) //│ where //│ 'a <: ArraysRep['A1, 'Rep1] & ArraysRep['A0, 'Rep0] //│ 'e <: 'A1 -> ('f | 'b) -> 'b & 'A0 -> ('b0 | 'f) -> ('b & 'b0)), init: forall 'A2 'Rep2 'A3 'Rep3. ('A2 & 'A3) -> ('Rep2, 'Rep3,) //│ where -//│ 'a <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], sub: forall 'Rep4 'A4 'g 'A5 'Rep5. ('Rep5, 'Rep4,) -> (int -> 'g +//│ 'a <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], sub: forall 'Rep4 'A4 'g 'A5 'Rep5. (('Rep5, 'Rep4,),) -> (int -> 'g //│ where -//│ 'a <: ArraysRep['A4, 'Rep5] & ArraysRep['A5, 'Rep4]), update: forall 'Rep6 'Rep7 'A6 'A7. ('Rep6, 'Rep7,) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) +//│ 'a <: ArraysRep['A4, 'Rep5] & ArraysRep['A5, 'Rep4]), update: forall 'Rep6 'Rep7 'A6 'A7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) //│ where //│ 'a <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7])})) -> 'h) -> 'h //│ where @@ -416,14 +416,14 @@ def step: Arrays['a] -> Arrays['a] def step arr f = f (stepImpl2 arr) //│ 'a -> (('c -> 'd) -> 'd //│ where -//│ 'a <: (forall 'e 'Rep 'A 'f 'g. (ArraysRep['A, in 'g & 'f out 'g | 'f] & 'e) -> (ArraysImpl['A, 'Rep] with {fold: forall 'h 'Rep0 'b 'Rep1 'i 'A0 'b0 'A1. 'h -> 'i -> (('Rep0, 'Rep1,) -> ('i | 'b) +//│ 'a <: (forall 'e 'Rep 'A 'f 'g. (ArraysRep['A, in 'g & 'f out 'g | 'f] & 'e) -> (ArraysImpl['A, 'Rep] with {fold: forall 'h 'Rep0 'b 'Rep1 'i 'A0 'b0 'A1. 'h -> 'i -> ((('Rep0, 'Rep1,),) -> ('i | 'b) //│ where //│ 'e <: ArraysRep['A1, 'Rep1] & ArraysRep['A0, 'Rep0] //│ 'h <: 'A1 -> ('i | 'b) -> 'b & 'A0 -> ('b0 | 'i) -> ('b & 'b0)), init: forall 'A2 'Rep2 'A3 'Rep3. ('A2 & 'A3) -> ('Rep2, 'Rep3,) //│ where -//│ 'e <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], sub: forall 'j 'Rep4 'A4 'Rep5 'A5. ('Rep5, 'Rep4,) -> (int -> 'j +//│ 'e <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], sub: forall 'j 'Rep4 'A4 'Rep5 'A5. (('Rep5, 'Rep4,),) -> (int -> 'j //│ where -//│ 'e <: ArraysRep['A4, 'Rep5] & ArraysRep['A5, 'Rep4]), update: forall 'A6 'A7 'Rep6 'Rep7. ('Rep6, 'Rep7,) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) +//│ 'e <: ArraysRep['A4, 'Rep5] & ArraysRep['A5, 'Rep4]), update: forall 'A6 'A7 'Rep6 'Rep7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) //│ where //│ 'e <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7])})) -> 'c) //│ where diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 2182074e6..48ead5849 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -139,12 +139,6 @@ fun f1(a?: Int, b?: Int) = a + b //│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ where: -//│ sim => TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: #Int?, b: #Int?,) -> #Int)) -//│ None) -//│ exp => class mlscript.Signature -//│ members => List(fun f1: (a: Int?, b: Int?) -> Int) -//│ result => None //│ fun f1: (a: Int?, b: Int?) -> Int @@ -153,12 +147,6 @@ fun f1(a: Int, b: Int) = a + b //│ |#fun| |f1|(|a|#:| |Int|,| |b|#:| |Int|)| |#=| |a| |+| |b| //│ AST: TypingUnit(NuFunDef(None, f1, None, [], Lam(Tup(a: Var(Int), b: Var(Int)), App(Var(+), Tup(_: Var(a), _: Var(b)))))) //│ Parsed: fun f1 = (a: Int, b: Int,) => + (a, b,); -//│ sim => TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => + (a, b,),((a: #Int, b: #Int,) -> #Int)) -//│ None) -//│ exp => class mlscript.Signature -//│ members => List(fun f1: (a: Int, b: Int) -> Int) -//│ result => None //│ fun f1: (a: Int, b: Int) -> Int @@ -166,23 +154,6 @@ class C1 class C2 extends C1 let x = new C2() let y: C1 = x -//│ sim => TypedTypingUnit( -//│ TypedNuCls(0, TypeName(C1), -//│ List(), -//│ List(), -//│ this: ⊤, , -//│ : ⊤, Set(), Map()) -//│ TypedNuCls(0, TypeName(C2), -//│ List(), -//│ List(), -//│ this: ⊤, , -//│ : ⊤, Set(TypeName(C1)), Map()) -//│ TypedNuFun(0,let x = new C2() {},C2) -//│ TypedNuFun(0,let y = x : C1,C1) -//│ None) -//│ exp => class mlscript.Signature -//│ members => List(class C1() {}, class C2(): C1 {}, let x: C2, let y: C1) -//│ result => None //│ class C1 //│ class C2 extends C1 //│ let x: C2 @@ -193,21 +164,11 @@ let y: C1 = x //│ = C2 {} [x, y]: [C1, C1] -//│ sim => TypedTypingUnit( -//│ Some((C1, C1,))) -//│ exp => class mlscript.Signature -//│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false))))) //│ [C1, C1] //│ res //│ = [ C2 {}, C2 {} ] [x, y]: [C1, C1, C1?] -//│ sim => TypedTypingUnit( -//│ Some((C1, C1, C1?,))) -//│ exp => class mlscript.Signature -//│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),true))))) //│ [C1, C1, C1?] //│ res //│ = [ C2 {}, C2 {} ] @@ -215,48 +176,28 @@ let y: C1 = x :e [x]: [C1, C1, C1?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.216: [x]: [C1, C1, C1?] +//│ ║ l.177: [x]: [C1, C1, C1?] //│ ║ ^^^ //│ ╟── expression of type `[?a]` does not match type `[C1, C1, C1?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.216: [x]: [C1, C1, C1?] +//│ ║ l.177: [x]: [C1, C1, C1?] //│ ╙── ^^^^^^^^^^^^^ -//│ sim => TypedTypingUnit( -//│ Some((C1, C1, C1?,))) -//│ exp => class mlscript.Signature -//│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),false)), (None,Field(None,TypeName(C1),true))))) //│ [C1, C1, C1?] //│ res //│ = [ C2 {} ] [1, 2, 3]: [Int, Int, Int] -//│ sim => TypedTypingUnit( -//│ Some((#Int, #Int, #Int,))) -//│ exp => class mlscript.Signature -//│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false))))) //│ [Int, Int, Int] //│ res //│ = [ 1, 2, 3 ] [1, 2]: [Int, Int?] -//│ sim => TypedTypingUnit( -//│ Some((#Int, #Int?,))) -//│ exp => class mlscript.Signature -//│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) //│ [Int, Int?] //│ res //│ = [ 1, 2 ] [1]: [Int, Int?] -//│ sim => TypedTypingUnit( -//│ Some((#Int, #Int?,))) -//│ exp => class mlscript.Signature -//│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) //│ [Int, Int?] //│ res //│ = [ 1 ] @@ -264,17 +205,12 @@ let y: C1 = x :e []: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.265: []: [Int, Int?] +//│ ║ l.206: []: [Int, Int?] //│ ║ ^^ //│ ╟── expression of type `[]` does not match type `[Int, Int?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.265: []: [Int, Int?] +//│ ║ l.206: []: [Int, Int?] //│ ╙── ^^^^^^^^^^^ -//│ sim => TypedTypingUnit( -//│ Some((#Int, #Int?,))) -//│ exp => class mlscript.Signature -//│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) //│ [Int, Int?] //│ res //│ = [] @@ -282,19 +218,14 @@ let y: C1 = x :e [1, 2, 3]: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.283: [1, 2, 3]: [Int, Int?] +//│ ║ l.219: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^^^ //│ ╟── tuple literal of type `[1, 2, 3]` does not match type `[Int, Int?]` -//│ ║ l.283: [1, 2, 3]: [Int, Int?] +//│ ║ l.219: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.283: [1, 2, 3]: [Int, Int?] +//│ ║ l.219: [1, 2, 3]: [Int, Int?] //│ ╙── ^^^^^^^^^^^ -//│ sim => TypedTypingUnit( -//│ Some((#Int, #Int?,))) -//│ exp => class mlscript.Signature -//│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) //│ [Int, Int?] //│ res //│ = [ 1, 2, 3 ] @@ -399,11 +330,6 @@ let y: C1 = x //│ ⬤ Factored: TypedTypingUnit( //│ Some((#Int, #Int, #Int?,))) //│ where: -//│ sim => TypedTypingUnit( -//│ Some((#Int, #Int, #Int?,))) -//│ exp => class mlscript.Signature -//│ members => List() -//│ result => Some(Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true))))) //│ [Int, Int, Int?] //│ res //│ = [ 1, 2 ] @@ -415,21 +341,9 @@ fun foo(xs: [Int] & 'a) = xs : [Int, Int?] //│ |#fun| |foo|(|xs|#:| |[|Int|]| |&| |'a|)| |#=| |xs| |#:| |[|Int|,| |Int|?|]| //│ AST: TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(xs: App(Var(&), Tup(_: Bra(rcd = false, Tup(_: Var(Int))), _: Var('a)))), Asc(Var(xs), Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))))))) //│ Parsed: fun foo = (xs: & ('(' Int, ')', 'a,),) => xs : [Int, Int?]; -//│ sim => TypedTypingUnit( -//│ TypedNuFun(0,fun foo = (xs: & ('(' Int, ')', 'a,),) => xs : [Int, Int?],((xs: (#Int,),) -> (#Int, #Int?,))) -//│ None) -//│ exp => class mlscript.Signature -//│ members => List(fun foo: (xs: [Int]) -> [Int, Int?]) -//│ result => None //│ fun foo: (xs: [Int]) -> [Int, Int?] fun foo(xs: [Int] & 'a) = [xs : [Int, Int?], xs] -//│ sim => TypedTypingUnit( -//│ TypedNuFun(0,fun foo = (xs: & ('(' Int, ')', 'a,),) => '(' xs : [Int, Int?], xs, ')',((xs: ((#Int,) & 'a45_49'),) -> ((#Int, #Int?,), ((#Int,) & 'a45_49'),))) -//│ None) -//│ exp => class mlscript.Signature -//│ members => List(fun foo: forall 'a. (xs: [Int] & 'a) -> [[Int, Int?], [Int] & 'a]) -//│ result => None //│ fun foo: forall 'a. (xs: [Int] & 'a) -> [[Int, Int?], [Int] & 'a] @@ -437,48 +351,25 @@ fun foo(xs: [Int] & 'a) = [xs : [Int, Int?], xs] // TODO later: update normal form construction fun foo: [Int] | [Int, Int?] -//│ sim => TypedTypingUnit( -//│ TypedNuFun(0,fun foo: [Int] | [Int, Int?],(#Int, #Int?,)) -//│ None) -//│ exp => class mlscript.Signature -//│ members => List(fun foo: [Int, Int?]) -//│ result => None //│ fun foo: [Int, Int?] fun foo: [Int] & [Int, Int?] -//│ sim => TypedTypingUnit( -//│ TypedNuFun(0,fun foo: [Int] & [Int, Int?],(#Int,)) -//│ None) -//│ exp => class mlscript.Signature -//│ members => List(fun foo: [Int]) -//│ result => None //│ fun foo: [Int] fun foo: ([Int] & [Int, Int?]) -> Int -//│ sim => TypedTypingUnit( -//│ TypedNuFun(0,fun foo: ([Int] & [Int, Int?]) -> Int,([#Int,] -> #Int)) -//│ None) -//│ exp => class mlscript.Signature -//│ members => List(fun foo: ([Int]) -> Int) -//│ result => None //│ fun foo: ([Int]) -> Int :e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.467: foo([1, true]) +//│ ║ l.363: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── tuple literal of type `[1, true]` does not match type `[Int]` -//│ ║ l.467: foo([1, true]) +//│ ║ l.363: foo([1, true]) //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.457: fun foo: ([Int] & [Int, Int?]) -> Int +//│ ║ l.359: fun foo: ([Int] & [Int, Int?]) -> Int //│ ╙── ^^^^^ -//│ sim => TypedTypingUnit( -//│ Some((#Int | #error<>))) -//│ exp => class mlscript.Signature -//│ members => List() -//│ result => Some(Union(TypeName(Int),TypeName(error))) //│ Int | error //│ res //│ = @@ -486,27 +377,16 @@ foo([1, true]) fun foo: ([Int] | [Int, Int?]) -> Int -//│ sim => TypedTypingUnit( -//│ TypedNuFun(0,fun foo: ([Int] | [Int, Int?]) -> Int,([#Int, #Int?,] -> #Int)) -//│ None) -//│ exp => class mlscript.Signature -//│ members => List(fun foo: ([Int, Int?]) -> Int) -//│ result => None //│ fun foo: ([Int, Int?]) -> Int :e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.498: foo([1, true]) +//│ ║ l.383: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── reference of type `true` is not an instance of type `Int` -//│ ║ l.498: foo([1, true]) +//│ ║ l.383: foo([1, true]) //│ ╙── ^^^^ -//│ sim => TypedTypingUnit( -//│ Some((#Int | #error<>))) -//│ exp => class mlscript.Signature -//│ members => List() -//│ result => Some(Union(TypeName(Int),TypeName(error))) //│ Int | error //│ res //│ = diff --git a/shared/src/test/scala/mlscript/DiffTests.scala b/shared/src/test/scala/mlscript/DiffTests.scala index f99ad574f..e51791629 100644 --- a/shared/src/test/scala/mlscript/DiffTests.scala +++ b/shared/src/test/scala/mlscript/DiffTests.scala @@ -566,17 +566,8 @@ class DiffTests SimplifyPipeline(tpd, pol = S(true))(ctx) } finally typer.dbg = oldDbg - output(s"sim => ${sim}") - val exp = typer.expandType(sim)(ctx) - output(s"exp => ${exp.getClass()}") - exp match { - case Signature(members, result) => - output(s"members => ${members}") - output(s"result => ${result}") - } - val expStr = exp.showIn(ShowCtx.mk(exp :: Nil, newDefs) // .copy(newDefs = true) // TODO later From 27bfae90e594e46d259b7ccc2b4a721c3873f9c8 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 18:30:52 +0800 Subject: [PATCH 27/37] Fix some possible future? bugs --- shared/src/main/scala/mlscript/TypeDefs.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/src/main/scala/mlscript/TypeDefs.scala b/shared/src/main/scala/mlscript/TypeDefs.scala index 856084c1b..5b5baf3bf 100644 --- a/shared/src/main/scala/mlscript/TypeDefs.scala +++ b/shared/src/main/scala/mlscript/TypeDefs.scala @@ -333,7 +333,7 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => // * This is not actually necessary for soundness // * (if they aren't, the object type just won't be instantiable), // * but will help report inheritance errors earlier (see test BadInherit2). - case (nme, FieldType(S(lb), ub, false)) => constrain(lb, ub) + case (nme, FieldType(S(lb), ub, _)) => constrain(lb, ub) case _ => () } (decls -- defns) match { @@ -354,7 +354,7 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => S(f._1.name.drop(f._1.name.indexOf('#') + 1)) // strip any "...#" prefix )(1).tap(_.upperBounds ::= f._2.ub) f._1 -> ( - if (f._2.lb.isDefined) FieldType(Some(fv), fv, false)(f._2.prov) + if (f._2.lb.isDefined) FieldType(Some(fv), fv, f._2.opt)(f._2.prov) else fv.toUpper(f._2.prov) ) }).toList From a136b37cb7f4407d2fe93d5debd29d857f1a85f7 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 18:58:50 +0800 Subject: [PATCH 28/37] Fix some possible future? bugs --- shared/src/main/scala/mlscript/Typer.scala | 35 +++++++--------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index 73c481b5f..d73b3276e 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -441,12 +441,10 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne implicit val prov: TP = tyTp(ty.toLoc, "type bounds") constrain(lb_ty, ub_ty) TypeBounds(lb_ty, ub_ty)(prov) - case Tuple(fields) => { - println("typing tuple!!!") + case Tuple(fields) => TupleType(fields.mapValues(f => FieldType(f.in.map(rec), rec(f.out), f.opt)(tp(f.toLoc, "tuple field")) ))(tyTp(ty.toLoc, "tuple type")) - } case Splice(fields) => SpliceType(fields.map{ case L(l) => { @@ -498,7 +496,6 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne case tn @ TypeTag(name) => rec(TypeName(name.decapitalize)) // TODO rm this hack // case tn @ TypeTag(name) => rec(TypeName(name)) case tn @ TypeName(name) => - println("typename case??") val tyLoc = ty.toLoc val tpr = tyTp(tyLoc, "type reference") vars.getOrElse(name, { @@ -822,15 +819,11 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne } case Asc(trm, ty) => - println(s"typing-trm-here!!! ${trm}") val trm_ty = typePolymorphicTerm(trm) - println(s"typing-ty-here!!! ${ty}") val ty_ty = typeType(ty)(ctx.copy(inPattern = false), raise, vars) if (ctx.inPattern) { unify(trm_ty, ty_ty); ty_ty } // * In patterns, we actually _unify_ the pattern and ascribed type - else { - println("constraining!!!") + else con(trm_ty, ty_ty, ty_ty) - } case (v @ ValidPatVar(nme)) => val prov = tp(if (verboseConstraintProvenanceHints) v.toLoc else N, "variable") // * Note: only look at ctx.env, and not the outer ones! @@ -899,7 +892,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne :: fieldNames.map(tp => msg"Declared at" -> tp.toLoc))(raise) case _ => } - RecordType.mk(fs.map { case (n, Fld(FldFlags(mut, _, _), t)) => + RecordType.mk(fs.map { case (n, Fld(FldFlags(mut, _, opt), t)) => if (n.name.isCapitalized) err(msg"Field identifiers must start with a small letter", term.toLoc)(raise) val tym = typePolymorphicTerm(t) @@ -907,13 +900,12 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne if (mut) { val res = freshVar(fprov, N, S(n.name)) val rs = con(tym, res, res) - (n, FieldType(Some(rs), rs, false)(fprov)) - } else (n, tym.toUpper(fprov)) + (n, FieldType(Some(rs), rs, opt)(fprov)) + } else (n, tym.toUpper(fprov)) // TODO[optional-fields]: should send opt in toUpper? })(prov) case tup: Tup if funkyTuples => typeTerms(tup :: Nil, false, Nil) - case Tup(fs) => { - println("HERE, good!") + case Tup(fs) => TupleType(fs.mapConserve { case e @ (n, Fld(flags, t)) => n match { case S(v) if ctx.inPattern => @@ -926,15 +918,12 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne // val tym = if (n.isDefined) typeType(t.toTypeRaise) // else typePolymorphicTerm(t) val fprov = tp(t.toLoc, (if (mut) "mutable " else "") + "tuple field") - println(s"opt is => ${opt}") if (mut) { - println("case #1") val res = freshVar(fprov, N, n.map(_.name)) val rs = con(tym, res, res) (n, FieldType(Some(rs), rs, opt)(fprov)) } else { - println("case #2") - val ty = tym.toUpper(fprov) + val ty = tym.toUpper(fprov) // TODO[optional-fields]: should send opt in toUpper? val tres = FieldType(ty.lb, ty.ub, opt)(ty.prov) (n, tres) } @@ -942,7 +931,6 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne case Nil | ((N, _) :: Nil) => noProv // TODO rm? case _ => tp(term.toLoc, "tuple literal") }) - } case Subs(a, i) => val t_a = typeMonomorphicTerm(a) val t_i = typeMonomorphicTerm(i) @@ -993,7 +981,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne }) case R(Fld(FldFlags(mt, sp, op), r)) => { val t = typeMonomorphicTerm(r) - if (mt) { R(FieldType(Some(t), t, false)(t.prov)) } else {R(t.toUpper(t.prov))} + if (mt) { R(FieldType(Some(t), t, op)(t.prov)) } else {R(t.toUpper(t.prov))} // TODO[optional-fields]: should send opt in toUpper? } })(prov) case Bra(false, trm: Blk) => typeTerm(trm) @@ -1051,7 +1039,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne // assert(!mut) val fprov = tp(a.toLoc, "argument") val tym = typeArg(a) - (n, tym.toUpper(fprov)) + (n, tym.toUpper(fprov)) // TODO[optional-fields]: should send opt in toUpper? })(as match { // TODO dedup w/ general Tup case case Nil | ((N, _) :: Nil) => noProv case _ => tp(tup.toLoc, "argument list") @@ -1607,10 +1595,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne res case OtherTypeLike(tu) => { val mems = tu.implementedMembers.map(goDecl) - val res = Signature(mems, tu.result.map(go)) - println(s"tu => $tu") - println(s"resss => $res") - res + Signature(mems, tu.result.map(go)) } } From 12b3dc5ed6c79c1dc5164d9080101c785b781008 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Thu, 28 Sep 2023 19:08:12 +0800 Subject: [PATCH 29/37] Fix some possible future? bugs --- shared/src/main/scala/mlscript/helpers.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index 5eb32a06f..b39045ff5 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -627,7 +627,7 @@ trait TermImpl extends StatementImpl { self: Term => case _ => throw new NotAType(this) } case Rcd(fields) => Record(fields.map(fld => (fld._1, fld._2 match { - case Fld(FldFlags(m, s, _), v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty, false) + case Fld(FldFlags(m, s, o), v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty, o) }))) case Where(body, where) => Constrained(body.toType_!, Nil, where.map { @@ -811,10 +811,10 @@ trait StatementImpl extends Located { self: Statement => case R(ty) => ty } val params = fs.map { - case (S(nme), Fld(FldFlags(mut, spec, _), trm)) => + case (S(nme), Fld(FldFlags(mut, spec, opt), trm)) => val ty = tt(trm) - nme -> Field(if (mut) S(ty) else N, ty, false) - case (N, Fld(FldFlags(mut, spec, _), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top, false) + nme -> Field(if (mut) S(ty) else N, ty, opt) + case (N, Fld(FldFlags(mut, spec, opt), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top, opt) case _ => die } val pos = params.unzip._1 @@ -869,13 +869,13 @@ trait StatementImpl extends Located { self: Statement => case Bra(false, t) => getFields(t) case Bra(true, Tup(fs)) => Record(fs.map { - case (S(n) -> Fld(FldFlags(mut, _, _), t)) => + case (S(n) -> Fld(FldFlags(mut, _, opt), t)) => val ty = t.toType match { case L(d) => allDiags += d; Top case R(t) => t } fields += n -> ty - n -> Field(None, ty, false) + n -> Field(None, ty, opt) case _ => ??? }) :: Nil case Bra(true, t) => lastWords(s"$t ${t.getClass}") From e2df709c0b47512add57389835dab637c7f9df99 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Fri, 29 Sep 2023 12:07:38 +0800 Subject: [PATCH 30/37] Rename fields compatible checker --- shared/src/main/scala/mlscript/ConstraintSolver.scala | 2 +- shared/src/main/scala/mlscript/TyperDatatypes.scala | 2 +- shared/src/main/scala/mlscript/TyperHelpers.scala | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/shared/src/main/scala/mlscript/ConstraintSolver.scala b/shared/src/main/scala/mlscript/ConstraintSolver.scala index a60fa0115..5faa3f4db 100644 --- a/shared/src/main/scala/mlscript/ConstraintSolver.scala +++ b/shared/src/main/scala/mlscript/ConstraintSolver.scala @@ -846,7 +846,7 @@ class ConstraintSolver extends NormalForms { self: Typer => } - case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) if t0.isSubtype(t1) => { + case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) if t0.isLengthCompatibleWith(t1) => { fs0.lazyZip(fs1).foreach { case ((ln, l), (rn, r)) => ln.foreach { ln => rn.foreach { rn => if (ln =/= rn) err( diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala index 97181695d..f4f2e74e6 100644 --- a/shared/src/main/scala/mlscript/TyperDatatypes.scala +++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala @@ -274,7 +274,7 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => fields.map(f => s"${f._1.fold("")(_.name+": ")}${f._2},").mkString(" ") override def toString = s"($showInner)" // override def toString = s"(${fields.map(f => s"${f._1.fold("")(_+": ")}${f._2},").mkString(" ")})" - def isSubtype(that: TupleType): Boolean = fields.sizeCompare(that.fields) <= 0 && fields.sizeCompare(that.fields.filter(x => !x._2.opt)) >= 0 + def isLengthCompatibleWith(that: TupleType): Boolean = fields.sizeCompare(that.fields) <= 0 && fields.sizeCompare(that.fields.filter(x => !x._2.opt)) >= 0 } case class SpliceType(elems: Ls[Either[SimpleType, FieldType]])(val prov: TypeProvenance) extends ArrayBase { diff --git a/shared/src/main/scala/mlscript/TyperHelpers.scala b/shared/src/main/scala/mlscript/TyperHelpers.scala index f40769b69..3165b2138 100644 --- a/shared/src/main/scala/mlscript/TyperHelpers.scala +++ b/shared/src/main/scala/mlscript/TyperHelpers.scala @@ -427,7 +427,7 @@ abstract class TyperHelpers { Typer: Typer => case (RecordType(fs1), RecordType(fs2)) => RecordType(mergeSortedMap(fs1, fs2)(_ && _).toList)(prov) case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) => { - if (!t0.isSubtype(t1)) BotType + if (!t0.isLengthCompatibleWith(t1)) BotType else TupleType(tupleIntersection(fs0, fs1))(t0.prov) } case _ if !swapped => that & (this, prov, swapped = true) @@ -489,7 +489,7 @@ abstract class TyperHelpers { Typer: Typer => case (_: TypeTag, _: TypeTag) | (_: TV, _: TV) if this === that => true case (ab: ArrayBase, at: ArrayType) => ab.inner <:< at.inner case (t1 @ TupleType(fs1), t2 @ TupleType(fs2)) => - t1.isSubtype(t2) && fs1.lazyZip(fs2).forall { + t1.isLengthCompatibleWith(t2) && fs1.lazyZip(fs2).forall { case ((_, ty1), (_, ty2)) => ty1 <:< ty2 } case (RecordType(Nil), _) => TopType <:< that From 5c6f3c5b038d41698dee6df51c732a0c47cd4acd Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Fri, 29 Sep 2023 13:08:59 +0800 Subject: [PATCH 31/37] Fix syntax problem in helper --- shared/src/main/scala/mlscript/helpers.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index da8c5c51d..17f853638 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -63,9 +63,12 @@ trait TypeLikeImpl extends Located { self: TypeLike => case Record(fs) => val strs = fs.map { nt => val nme = nt._1.name - val opt = nt._2 match { - case Field(_, _, true) => "?" - case Field(_, _, false) => "" + if (nme.isCapitalized) nt._2 match { + case Field(N | S(Bot), Top, _) => s"$nme" + case Field(S(lb), ub, _) if lb === ub => s"$nme = ${ub.showIn(ctx, 0)}" + case Field(N | S(Bot), ub, _) => s"$nme <: ${ub.showIn(ctx, 0)}" + case Field(S(lb), Top, _) => s"$nme :> ${lb.showIn(ctx, 0)}" + case Field(S(lb), ub, _) => s"$nme :> ${lb.showIn(ctx, 0)} <: ${ub.showIn(ctx, 0)}" } else s"${nt._2.mutStr}${nme}: ${showField(nt._2, ctx)}" } From a92fc4e99c6664a0e3b2bccf03de05c159da2cc3 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Fri, 29 Sep 2023 13:21:02 +0800 Subject: [PATCH 32/37] Fix syntax errors --- shared/src/main/scala/mlscript/MLParser.scala | 10 +- .../src/main/scala/mlscript/NuTypeDefs.scala | 10 +- .../main/scala/mlscript/TypeSimplifier.scala | 6 +- shared/src/main/scala/mlscript/Typer.scala | 2 +- shared/src/main/scala/mlscript/helpers.scala | 2 +- .../test/diff/fcp/QML_exist_Classes_CT.mls | 222 +++++++++++------- shared/src/test/diff/nu/OptionalArgs.mls | 56 +++-- 7 files changed, 181 insertions(+), 127 deletions(-) diff --git a/shared/src/main/scala/mlscript/MLParser.scala b/shared/src/main/scala/mlscript/MLParser.scala index ec10a441b..586666bcc 100644 --- a/shared/src/main/scala/mlscript/MLParser.scala +++ b/shared/src/main/scala/mlscript/MLParser.scala @@ -67,14 +67,14 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) { def parens[p: P]: P[Term] = locate(P( "(" ~/ parenCell.rep(0, ",") ~ ",".!.? ~ ")" ).map { case (Seq(Right(t -> false)), N) => Bra(false, t) - case (Seq(Right(t -> true)), N) => Tup(N -> Fld(FldFlags(true, false, false), t) :: Nil) // ? single tuple with mutable + case (Seq(Right(t -> true)), N) => Tup(N -> Fld(FldFlags(true, false, false, false), t) :: Nil) // ? single tuple with mutable case (ts, _) => if (ts.forall(_.isRight)) Tup(ts.iterator.map { - case R(f) => N -> Fld(FldFlags(f._2, false, false), f._1) + case R(f) => N -> Fld(FldFlags(f._2, false, false, false), f._1) case _ => die // left unreachable }.toList) else Splc(ts.map { - case R((v, m)) => R(Fld(FldFlags(m, false, false), v)) + case R((v, m)) => R(Fld(FldFlags(m, false, false, false), v)) case L(spl) => L(spl) }.toList) }) @@ -104,8 +104,8 @@ class MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) { "{" ~/ (kw("mut").!.? ~ variable ~ "=" ~ term map L.apply).|(kw("mut").!.? ~ variable map R.apply).rep(sep = ";" | ",") ~ "}" ).map { fs => Rcd(fs.map{ - case L((mut, v, t)) => v -> Fld(FldFlags(mut.isDefined, false, false), t) - case R(mut -> id) => id -> Fld(FldFlags(mut.isDefined, false, false), id) }.toList)}) + case L((mut, v, t)) => v -> Fld(FldFlags(mut.isDefined, false, false, false), t) + case R(mut -> id) => id -> Fld(FldFlags(mut.isDefined, false, false, false), id) }.toList)}) def fun[p: P]: P[Term] = locate(P( kw("fun") ~/ term ~ "->" ~ term ).map(nb => Lam(toParams(nb._1), nb._2))) diff --git a/shared/src/main/scala/mlscript/NuTypeDefs.scala b/shared/src/main/scala/mlscript/NuTypeDefs.scala index ac6baab66..c75ac2f88 100644 --- a/shared/src/main/scala/mlscript/NuTypeDefs.scala +++ b/shared/src/main/scala/mlscript/NuTypeDefs.scala @@ -824,7 +824,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => case S(ps) => checkArgsNum(ps.size) ps.lazyZip(parArgs).flatMap { - case (nme -> p, _ -> Fld(FldFlags(mut, spec, _, get), a)) => + case (nme -> p, _ -> Fld(FldFlags(mut, spec, opt, get), a)) => assert(!mut && !spec && !get, "TODO") // TODO check mut, spec, get val a_ty = typeTerm(a) p.lb.foreach(constrain(_, a_ty)) @@ -832,8 +832,8 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => val isPublic = cls.members(nme.name).isPublic val fty = if (p.lb.isDefined) // * We don't refine the field type when it's mutable as that could lead to muable updates being rejected - FieldType(p.lb, p.ub)(provTODO) - else FieldType(p.lb, a_ty)(provTODO) + FieldType(p.lb, p.ub, opt)(provTODO) + else FieldType(p.lb, a_ty, opt)(provTODO) Option.when(isPublic)(NuParam(nme, fty, isPublic = isPublic)(lvl)) } case N => @@ -1629,7 +1629,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => def getterError(loco: Opt[Loc]) = err(msg"Cannot use `val` in constructor parameters", loco) val res = ps.fields.map { - case (S(nme), Fld(FldFlags(mut, spec, getter), value)) => + case (S(nme), Fld(FldFlags(mut, spec, _, getter), value)) => assert(!mut && !spec, "TODO") // TODO if (getter) // TODO we could support this to some extent @@ -1641,7 +1641,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => nme -> ty case _ => ??? } - case (N, Fld(FldFlags(mut, spec, getter), nme: Var)) => + case (N, Fld(FldFlags(mut, spec, _, getter), nme: Var)) => assert(!mut && !spec, "TODO") // TODO if (getter) getterError(nme.toLoc) diff --git a/shared/src/main/scala/mlscript/TypeSimplifier.scala b/shared/src/main/scala/mlscript/TypeSimplifier.scala index dcd25e54c..c358d432c 100644 --- a/shared/src/main/scala/mlscript/TypeSimplifier.scala +++ b/shared/src/main/scala/mlscript/TypeSimplifier.scala @@ -107,7 +107,7 @@ trait TypeSimplifier { self: Typer => case VarianceInfo(true, true) => Nil case VarianceInfo(co, contra) => if (co) v -> FieldType(S(BotType), process(fty.ub, N), false)(fty.prov) :: Nil - else if (contra) v -> FieldType(fty.lb.map(process(_, N)), TopType)(fty.prov) :: Nil + else if (contra) v -> FieldType(fty.lb.map(process(_, N)), TopType, false)(fty.prov) :: Nil else v -> default :: Nil }) case N => @@ -119,8 +119,8 @@ trait TypeSimplifier { self: Typer => cls.varianceOf(cls.tparams.find(_._1.name === postfix).getOrElse(die)._2) match { case VarianceInfo(true, true) => Nil case VarianceInfo(co, contra) => - if (co) v -> FieldType(S(BotType), process(fty.ub, N))(fty.prov) :: Nil - else if (contra) v -> FieldType(fty.lb.map(process(_, N)), TopType)(fty.prov) :: Nil + if (co) v -> FieldType(S(BotType), process(fty.ub, N), false)(fty.prov) :: Nil + else if (contra) v -> FieldType(fty.lb.map(process(_, N)), TopType, false)(fty.prov) :: Nil else v -> default :: Nil } case S(trt: TypedNuTrt) => // TODO factor w/ above & generalize diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index 44a027b82..04af49176 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -1493,7 +1493,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne typeTerms(Tup(S(trm) -> Fld(FldFlags.empty, trm) :: Nil) :: sts, rcd, fields) case Blk(sts0) :: sts1 => typeTerms(sts0 ::: sts1, rcd, fields) case Tup(Nil) :: sts => typeTerms(sts, rcd, fields) - case Tup((no, Fld(FldFlags(tmut, _, _), trm)) :: ofs) :: sts => + case Tup((no, Fld(FldFlags(tmut, _, _, _), trm)) :: ofs) :: sts => val ty = { trm match { case Bra(false, t) if ctx.inPattern => // we use syntax `(x: (p))` to type `p` as a pattern and not a type... diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index 17f853638..d26f9c380 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -921,7 +921,7 @@ trait StatementImpl extends Located { self: Statement => case Bra(true, t) => lastWords(s"$t ${t.getClass}") case Tup(fs) => // TODO factor with case Bra(true, Tup(fs)) above Tuple(fs.map { - case (S(n) -> Fld(FldFlags(tmut, _, _), t)) => + case (S(n) -> Fld(FldFlags(tmut, _, _, _), t)) => val ty = t.toType match { case L(d) => allDiags += d; Top case R(t) => t diff --git a/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls b/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls index 7845ef46b..6cef46cca 100644 --- a/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls +++ b/shared/src/test/diff/fcp/QML_exist_Classes_CT.mls @@ -48,9 +48,14 @@ baseImpl = ArraysImpl { update = fun r -> fun (i : int) -> fun a -> a; fold = fun f -> fun b -> fun r -> f r b } -//│ baseImpl: ArraysImpl['Rep, 'Rep] with {fold: forall 'a 'b 'c 'd. 'd -> 'a -> ('b -> 'c -//│ where -//│ 'd <: 'b -> 'a -> 'c), init: forall 'e. 'e -> 'e, sub: forall 'f. 'f -> int -> 'f, update: forall 'g. anything -> int -> 'g -> 'g} +//│ baseImpl: ArraysImpl['Rep, 'Rep] with { +//│ fold: forall 'a 'b 'c 'd. 'd -> 'a -> ('b -> 'c +//│ where +//│ 'd <: 'b -> 'a -> 'c), +//│ init: forall 'e. 'e -> 'e, +//│ sub: forall 'f. 'f -> int -> 'f, +//│ update: forall 'g. anything -> int -> 'g -> 'g +//│ } //│ = ArraysImpl { //│ init: [Function: init], //│ sub: [Function: sub], @@ -62,9 +67,14 @@ def base: Arrays['a] def base f = f baseImpl //│ base: Arrays['a] //│ = -//│ ((forall 'Rep. ArraysImpl['Rep, 'Rep] with {fold: forall 'a 'b 'c 'd. 'a -> 'b -> ('c -> 'd -//│ where -//│ 'a <: 'c -> 'b -> 'd), init: forall 'e. 'e -> 'e, sub: forall 'f. 'f -> int -> 'f, update: forall 'g. anything -> int -> 'g -> 'g}) -> 'h) -> 'h +//│ ((forall 'Rep. ArraysImpl['Rep, 'Rep] with { +//│ fold: forall 'a 'b 'c 'd. 'a -> 'b -> ('c -> 'd +//│ where +//│ 'a <: 'c -> 'b -> 'd), +//│ init: forall 'e. 'e -> 'e, +//│ sub: forall 'f. 'f -> int -> 'f, +//│ update: forall 'g. anything -> int -> 'g -> 'g +//│ }) -> 'h) -> 'h //│ <: base: //│ Arrays['a] //│ = [Function: base] @@ -77,16 +87,21 @@ def simpleStepImpl arrImpl = ArraysImpl { update = fun ((r0, r1)) -> fun i -> fun a -> (arrImpl.Update r0 i a, "updated"); fold = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.Fold f b r0 } -//│ simpleStepImpl: (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with {fold: forall 'b 'A0 'Rep0 'd. 'd -> 'b -> ((('Rep0, anything,),) -> 'b -//│ where -//│ 'd <: 'A0 -> 'b -> 'b -//│ 'c <: ArraysRep['A0, 'Rep0]), init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) -//│ where -//│ 'c <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 -//│ where -//│ 'c <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) -//│ where -//│ 'c <: ArraysRep['A3, 'Rep3])}) +//│ simpleStepImpl: (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with { +//│ fold: forall 'b 'A0 'Rep0 'd. 'd -> 'b -> ((('Rep0, anything,),) -> 'b +//│ where +//│ 'd <: 'A0 -> 'b -> 'b +//│ 'c <: ArraysRep['A0, 'Rep0]), +//│ init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) +//│ where +//│ 'c <: ArraysRep['A1, 'Rep1], +//│ sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 +//│ where +//│ 'c <: ArraysRep['A2, 'Rep2]), +//│ update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) +//│ where +//│ 'c <: ArraysRep['A3, 'Rep3]) +//│ }) //│ where //│ 'Rep :> ('a, "initialized" | "updated",) //│ <: ('a, anything,) @@ -106,32 +121,42 @@ def simpleStepImpl2_ty: (forall 'r. (ArraysRep['A, 'Rep] -> 'r) -> 'r) -> Arrays def simpleStepImpl2 arr = arr simpleStepImpl -//│ simpleStepImpl2: ((forall 'A 'a 'c 'Rep. (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with {fold: forall 'd 'b 'A0 'Rep0. 'd -> 'b -> ((('Rep0, anything,),) -> 'b -//│ where -//│ 'd <: 'A0 -> 'b -> 'b -//│ 'c <: ArraysRep['A0, 'Rep0]), init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) -//│ where -//│ 'c <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 -//│ where -//│ 'c <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) -//│ where -//│ 'c <: ArraysRep['A3, 'Rep3])})) -> 'e) -> 'e +//│ simpleStepImpl2: ((forall 'A 'a 'c 'Rep. (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with { +//│ fold: forall 'd 'b 'A0 'Rep0. 'd -> 'b -> ((('Rep0, anything,),) -> 'b +//│ where +//│ 'd <: 'A0 -> 'b -> 'b +//│ 'c <: ArraysRep['A0, 'Rep0]), +//│ init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) +//│ where +//│ 'c <: ArraysRep['A1, 'Rep1], +//│ sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 +//│ where +//│ 'c <: ArraysRep['A2, 'Rep2]), +//│ update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) +//│ where +//│ 'c <: ArraysRep['A3, 'Rep3]) +//│ })) -> 'e) -> 'e //│ where //│ 'Rep :> ('a, "initialized" | "updated",) //│ <: ('a, anything,) //│ = [Function: simpleStepImpl2] simpleStepImpl2_ty = simpleStepImpl2 -//│ ((forall 'A 'a 'c 'Rep. (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with {fold: forall 'd 'b 'A0 'Rep0. 'd -> 'b -> ((('Rep0, anything,),) -> 'b -//│ where -//│ 'd <: 'A0 -> 'b -> 'b -//│ 'c <: ArraysRep['A0, 'Rep0]), init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) -//│ where -//│ 'c <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 -//│ where -//│ 'c <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) -//│ where -//│ 'c <: ArraysRep['A3, 'Rep3])})) -> 'e) -> 'e +//│ ((forall 'A 'a 'c 'Rep. (ArraysRep['A, 'a] & 'c) -> (ArraysImpl['A, 'Rep] with { +//│ fold: forall 'd 'b 'A0 'Rep0. 'd -> 'b -> ((('Rep0, anything,),) -> 'b +//│ where +//│ 'd <: 'A0 -> 'b -> 'b +//│ 'c <: ArraysRep['A0, 'Rep0]), +//│ init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) +//│ where +//│ 'c <: ArraysRep['A1, 'Rep1], +//│ sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 +//│ where +//│ 'c <: ArraysRep['A2, 'Rep2]), +//│ update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) +//│ where +//│ 'c <: ArraysRep['A3, 'Rep3]) +//│ })) -> 'e) -> 'e //│ where //│ 'Rep :> ('a, "initialized" | "updated",) //│ <: ('a, anything,) @@ -180,16 +205,21 @@ def simpleStep: Arrays['a] -> Arrays['a] def simpleStep arr f = f (simpleStepImpl2 arr) //│ 'a -> (('c -> 'd) -> 'd //│ where -//│ 'a <: (forall 'A 'e 'f 'Rep. (ArraysRep['A, 'e] & 'f) -> (ArraysImpl['A, 'Rep] with {fold: forall 'g 'b 'A0 'Rep0. 'g -> 'b -> ((('Rep0, anything,),) -> 'b -//│ where -//│ 'g <: 'A0 -> 'b -> 'b -//│ 'f <: ArraysRep['A0, 'Rep0]), init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) -//│ where -//│ 'f <: ArraysRep['A1, 'Rep1], sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 -//│ where -//│ 'f <: ArraysRep['A2, 'Rep2]), update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) -//│ where -//│ 'f <: ArraysRep['A3, 'Rep3])})) -> 'c) +//│ 'a <: (forall 'A 'e 'f 'Rep. (ArraysRep['A, 'e] & 'f) -> (ArraysImpl['A, 'Rep] with { +//│ fold: forall 'g 'b 'A0 'Rep0. 'g -> 'b -> ((('Rep0, anything,),) -> 'b +//│ where +//│ 'g <: 'A0 -> 'b -> 'b +//│ 'f <: ArraysRep['A0, 'Rep0]), +//│ init: forall 'A1 'Rep1. 'A1 -> ('Rep1, "initialized",) +//│ where +//│ 'f <: ArraysRep['A1, 'Rep1], +//│ sub: forall 'Rep2 'A2. (('Rep2, anything,),) -> (int -> 'A2 +//│ where +//│ 'f <: ArraysRep['A2, 'Rep2]), +//│ update: forall 'Rep3 'A3. (('Rep3, anything,),) -> int -> ('A3 -> ('Rep3, "updated",) +//│ where +//│ 'f <: ArraysRep['A3, 'Rep3]) +//│ })) -> 'c) //│ where //│ 'Rep :> ('e, "initialized" | "updated",) //│ <: ('e, anything,) @@ -351,16 +381,21 @@ def stepImpl arrImpl = ArraysImpl { else (r0, arrImpl.Update r1 (div i 2) a); fold = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.Fold f (arrImpl.Fold f b r0) r1 } -//│ stepImpl: (ArraysRep['A, in 'a & 'c out 'a | 'c] & 'd) -> (ArraysImpl['A, 'Rep] with {fold: forall 'Rep0 'Rep1 'e 'A0 'b 'f 'b0 'A1. 'e -> 'f -> ((('Rep0, 'Rep1,),) -> ('f | 'b0) -//│ where -//│ 'd <: ArraysRep['A1, 'Rep1] & ArraysRep['A0, 'Rep0] -//│ 'e <: 'A1 -> ('f | 'b0) -> 'b0 & 'A0 -> ('b | 'f) -> ('b0 & 'b)), init: forall 'A2 'Rep2 'A3 'Rep3. ('A3 & 'A2) -> ('Rep3, 'Rep2,) -//│ where -//│ 'd <: ArraysRep['A3, 'Rep3] & ArraysRep['A2, 'Rep2], sub: forall 'A4 'g 'Rep4 'A5 'Rep5. (('Rep4, 'Rep5,),) -> (int -> 'g -//│ where -//│ 'd <: ArraysRep['A4, 'Rep4] & ArraysRep['A5, 'Rep5]), update: forall 'Rep6 'Rep7 'A6 'A7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) -//│ where -//│ 'd <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7])}) +//│ stepImpl: (ArraysRep['A, in 'a & 'c out 'a | 'c] & 'd) -> (ArraysImpl['A, 'Rep] with { +//│ fold: forall 'Rep0 'Rep1 'e 'A0 'b 'f 'b0 'A1. 'e -> 'f -> ((('Rep0, 'Rep1,),) -> ('f | 'b0) +//│ where +//│ 'd <: ArraysRep['A1, 'Rep1] & ArraysRep['A0, 'Rep0] +//│ 'e <: 'A1 -> ('f | 'b0) -> 'b0 & 'A0 -> ('b | 'f) -> ('b0 & 'b)), +//│ init: forall 'A2 'Rep2 'A3 'Rep3. ('A3 & 'A2) -> ('Rep3, 'Rep2,) +//│ where +//│ 'd <: ArraysRep['A3, 'Rep3] & ArraysRep['A2, 'Rep2], +//│ sub: forall 'A4 'g 'Rep4 'A5 'Rep5. (('Rep4, 'Rep5,),) -> (int -> 'g +//│ where +//│ 'd <: ArraysRep['A4, 'Rep4] & ArraysRep['A5, 'Rep5]), +//│ update: forall 'Rep6 'Rep7 'A6 'A7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) +//│ where +//│ 'd <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7]) +//│ }) //│ where //│ 'A5 <: 'g //│ 'A4 <: 'g @@ -372,16 +407,21 @@ def stepImpl2_ty: (forall 'r. (ArraysRep['A, 'Rep] -> 'r) -> 'r) -> ArraysImpl[' //│ = def stepImpl2 arr = arr stepImpl -//│ stepImpl2: ((forall 'a 'c 'A 'Rep 'd. (ArraysRep['A, in 'c & 'a out 'c | 'a] & 'd) -> (ArraysImpl['A, 'Rep] with {fold: forall 'Rep0 'A0 'Rep1 'e 'b 'A1 'f 'b0. 'e -> 'f -> ((('Rep0, 'Rep1,),) -> ('f | 'b0) -//│ where -//│ 'e <: 'A0 -> ('f | 'b0) -> 'b0 & 'A1 -> ('b | 'f) -> ('b0 & 'b) -//│ 'd <: ArraysRep['A0, 'Rep1] & ArraysRep['A1, 'Rep0]), init: forall 'A2 'Rep2 'A3 'Rep3. ('A2 & 'A3) -> ('Rep2, 'Rep3,) -//│ where -//│ 'd <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], sub: forall 'Rep4 'A4 'Rep5 'A5 'g. (('Rep4, 'Rep5,),) -> (int -> 'g -//│ where -//│ 'd <: ArraysRep['A5, 'Rep4] & ArraysRep['A4, 'Rep5]), update: forall 'Rep6 'Rep7 'A6 'A7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) -//│ where -//│ 'd <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7])})) -> 'h) -> 'h +//│ stepImpl2: ((forall 'a 'c 'A 'Rep 'd. (ArraysRep['A, in 'c & 'a out 'c | 'a] & 'd) -> (ArraysImpl['A, 'Rep] with { +//│ fold: forall 'Rep0 'A0 'Rep1 'e 'b 'A1 'f 'b0. 'e -> 'f -> ((('Rep0, 'Rep1,),) -> ('f | 'b0) +//│ where +//│ 'e <: 'A0 -> ('f | 'b0) -> 'b0 & 'A1 -> ('b | 'f) -> ('b0 & 'b) +//│ 'd <: ArraysRep['A0, 'Rep1] & ArraysRep['A1, 'Rep0]), +//│ init: forall 'A2 'Rep2 'A3 'Rep3. ('A2 & 'A3) -> ('Rep2, 'Rep3,) +//│ where +//│ 'd <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], +//│ sub: forall 'Rep4 'A4 'Rep5 'A5 'g. (('Rep4, 'Rep5,),) -> (int -> 'g +//│ where +//│ 'd <: ArraysRep['A5, 'Rep4] & ArraysRep['A4, 'Rep5]), +//│ update: forall 'Rep6 'Rep7 'A6 'A7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) +//│ where +//│ 'd <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7]) +//│ })) -> 'h) -> 'h //│ where //│ 'A4 <: 'g //│ 'A5 <: 'g @@ -389,16 +429,21 @@ def stepImpl2 arr = arr stepImpl //│ = [Function: stepImpl2] stepImpl2_ty = stepImpl2 -//│ ((forall 'a 'Rep 'A 'c 'd. (ArraysRep['A, in 'c & 'd out 'c | 'd] & 'a) -> (ArraysImpl['A, 'Rep] with {fold: forall 'b 'Rep0 'e 'A0 'Rep1 'f 'b0 'A1. 'e -> 'f -> ((('Rep0, 'Rep1,),) -> ('f | 'b) -//│ where -//│ 'a <: ArraysRep['A1, 'Rep1] & ArraysRep['A0, 'Rep0] -//│ 'e <: 'A1 -> ('f | 'b) -> 'b & 'A0 -> ('b0 | 'f) -> ('b & 'b0)), init: forall 'A2 'Rep2 'A3 'Rep3. ('A2 & 'A3) -> ('Rep2, 'Rep3,) -//│ where -//│ 'a <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], sub: forall 'Rep4 'A4 'g 'A5 'Rep5. (('Rep5, 'Rep4,),) -> (int -> 'g -//│ where -//│ 'a <: ArraysRep['A4, 'Rep5] & ArraysRep['A5, 'Rep4]), update: forall 'Rep6 'Rep7 'A6 'A7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) -//│ where -//│ 'a <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7])})) -> 'h) -> 'h +//│ ((forall 'a 'Rep 'A 'c 'd. (ArraysRep['A, in 'c & 'd out 'c | 'd] & 'a) -> (ArraysImpl['A, 'Rep] with { +//│ fold: forall 'b 'Rep0 'e 'A0 'Rep1 'f 'b0 'A1. 'e -> 'f -> ((('Rep0, 'Rep1,),) -> ('f | 'b) +//│ where +//│ 'a <: ArraysRep['A1, 'Rep1] & ArraysRep['A0, 'Rep0] +//│ 'e <: 'A1 -> ('f | 'b) -> 'b & 'A0 -> ('b0 | 'f) -> ('b & 'b0)), +//│ init: forall 'A2 'Rep2 'A3 'Rep3. ('A2 & 'A3) -> ('Rep2, 'Rep3,) +//│ where +//│ 'a <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], +//│ sub: forall 'Rep4 'A4 'g 'A5 'Rep5. (('Rep5, 'Rep4,),) -> (int -> 'g +//│ where +//│ 'a <: ArraysRep['A4, 'Rep5] & ArraysRep['A5, 'Rep4]), +//│ update: forall 'Rep6 'Rep7 'A6 'A7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) +//│ where +//│ 'a <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7]) +//│ })) -> 'h) -> 'h //│ where //│ 'A5 <: 'g //│ 'A4 <: 'g @@ -416,16 +461,21 @@ def step: Arrays['a] -> Arrays['a] def step arr f = f (stepImpl2 arr) //│ 'a -> (('c -> 'd) -> 'd //│ where -//│ 'a <: (forall 'e 'Rep 'A 'f 'g. (ArraysRep['A, in 'g & 'f out 'g | 'f] & 'e) -> (ArraysImpl['A, 'Rep] with {fold: forall 'h 'Rep0 'b 'Rep1 'i 'A0 'b0 'A1. 'h -> 'i -> ((('Rep0, 'Rep1,),) -> ('i | 'b) -//│ where -//│ 'e <: ArraysRep['A1, 'Rep1] & ArraysRep['A0, 'Rep0] -//│ 'h <: 'A1 -> ('i | 'b) -> 'b & 'A0 -> ('b0 | 'i) -> ('b & 'b0)), init: forall 'A2 'Rep2 'A3 'Rep3. ('A2 & 'A3) -> ('Rep2, 'Rep3,) -//│ where -//│ 'e <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], sub: forall 'j 'Rep4 'A4 'Rep5 'A5. (('Rep5, 'Rep4,),) -> (int -> 'j -//│ where -//│ 'e <: ArraysRep['A4, 'Rep5] & ArraysRep['A5, 'Rep4]), update: forall 'A6 'A7 'Rep6 'Rep7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) -//│ where -//│ 'e <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7])})) -> 'c) +//│ 'a <: (forall 'e 'Rep 'A 'f 'g. (ArraysRep['A, in 'g & 'f out 'g | 'f] & 'e) -> (ArraysImpl['A, 'Rep] with { +//│ fold: forall 'h 'Rep0 'b 'Rep1 'i 'A0 'b0 'A1. 'h -> 'i -> ((('Rep0, 'Rep1,),) -> ('i | 'b) +//│ where +//│ 'e <: ArraysRep['A1, 'Rep1] & ArraysRep['A0, 'Rep0] +//│ 'h <: 'A1 -> ('i | 'b) -> 'b & 'A0 -> ('b0 | 'i) -> ('b & 'b0)), +//│ init: forall 'A2 'Rep2 'A3 'Rep3. ('A2 & 'A3) -> ('Rep2, 'Rep3,) +//│ where +//│ 'e <: ArraysRep['A2, 'Rep2] & ArraysRep['A3, 'Rep3], +//│ sub: forall 'j 'Rep4 'A4 'Rep5 'A5. (('Rep5, 'Rep4,),) -> (int -> 'j +//│ where +//│ 'e <: ArraysRep['A4, 'Rep5] & ArraysRep['A5, 'Rep4]), +//│ update: forall 'A6 'A7 'Rep6 'Rep7. (('Rep6, 'Rep7,),) -> int -> (('A6 & 'A7) -> ('Rep6, 'Rep7,) +//│ where +//│ 'e <: ArraysRep['A6, 'Rep6] & ArraysRep['A7, 'Rep7]) +//│ })) -> 'c) //│ where //│ 'A5 <: 'j //│ 'A4 <: 'j diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 48ead5849..366701bcc 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -4,21 +4,21 @@ :ds fun f1(a?: Int, b?: Int) = a + b //│ ⬤ Initial: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: Int?, b: Int?,) -> α29')) +//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: Int?, b: Int?,) -> α29')) //│ None) //│ where: //│ α29' :> Int //│ allVarPols: +α29' //│ Renewed α29' ~> α29_31' //│ ⬤ Cleaned up: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: Int?, b: Int?,) -> α29_31')) +//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: Int?, b: Int?,) -> α29_31')) //│ None) //│ where: //│ α29_31' :> Int //│ allVarPols: +α29_31' //│ consed: Map((true,Int) -> α29_31') //│ ⬤ Unskid: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: Int?, b: Int?,) -> α29_31')) +//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: Int?, b: Int?,) -> α29_31')) //│ None) //│ where: //│ α29_31' :> Int @@ -64,12 +64,12 @@ fun f1(a?: Int, b?: Int) = a + b //│ | ~> Int //│ ~> ((a: Int?, b: Int?,) -> Int) //│ ⬤ Type after simplification: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: Int?, b: Int?,) -> Int)) +//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: Int?, b: Int?,) -> Int)) //│ None) //│ where: //│ allVarPols: //│ normLike[+] TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: Int?, b: Int?,) -> Int)) +//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: Int?, b: Int?,) -> Int)) //│ None) //│ | norm[+] ((a: Int?, b: Int?,) -> Int) //│ | | DNF: DNF(0, ((a: Int?, b: Int?,) -> Int){}) @@ -87,18 +87,18 @@ fun f1(a?: Int, b?: Int) = a + b //│ | | ~> #Int //│ | ~> ((a: #Int?, b: #Int?,) -> #Int) //│ ⬤ Normalized: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: #Int?, b: #Int?,) -> #Int)) +//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ where: //│ allVarPols: //│ ⬤ Cleaned up: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: #Int?, b: #Int?,) -> #Int)) +//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ where: //│ allVarPols: //│ consed: Map() //│ ⬤ Unskid: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: #Int?, b: #Int?,) -> #Int)) +//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ where: //│ analyze1[+] ((a: #Int?, b: #Int?,) -> #Int) @@ -130,13 +130,13 @@ fun f1(a?: Int, b?: Int) = a + b //│ | ~> #Int //│ ~> ((a: #Int?, b: #Int?,) -> #Int) //│ ⬤ Resim: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: #Int?, b: #Int?,) -> #Int)) +//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ where: //│ allVarPols: //│ [subs] HashMap() //│ ⬤ Factored: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int?, b: Int?,) => + (a, b,),((a: #Int?, b: #Int?,) -> #Int)) +//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: #Int?, b: #Int?,) -> #Int)) //│ None) //│ where: //│ fun f1: (a: Int?, b: Int?) -> Int @@ -146,7 +146,7 @@ fun f1(a?: Int, b?: Int) = a + b fun f1(a: Int, b: Int) = a + b //│ |#fun| |f1|(|a|#:| |Int|,| |b|#:| |Int|)| |#=| |a| |+| |b| //│ AST: TypingUnit(NuFunDef(None, f1, None, [], Lam(Tup(a: Var(Int), b: Var(Int)), App(Var(+), Tup(_: Var(a), _: Var(b)))))) -//│ Parsed: fun f1 = (a: Int, b: Int,) => + (a, b,); +//│ Parsed: fun f1 = (a: Int, b: Int,) => +(a, b,); //│ fun f1: (a: Int, b: Int) -> Int @@ -154,8 +154,12 @@ class C1 class C2 extends C1 let x = new C2() let y: C1 = x -//│ class C1 -//│ class C2 extends C1 +//│ class C1 { +//│ constructor() +//│ } +//│ class C2 extends C1 { +//│ constructor() +//│ } //│ let x: C2 //│ let y: C1 //│ x @@ -176,11 +180,11 @@ let y: C1 = x :e [x]: [C1, C1, C1?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.177: [x]: [C1, C1, C1?] +//│ ║ l.181: [x]: [C1, C1, C1?] //│ ║ ^^^ //│ ╟── expression of type `[?a]` does not match type `[C1, C1, C1?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.177: [x]: [C1, C1, C1?] +//│ ║ l.181: [x]: [C1, C1, C1?] //│ ╙── ^^^^^^^^^^^^^ //│ [C1, C1, C1?] //│ res @@ -205,11 +209,11 @@ let y: C1 = x :e []: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.206: []: [Int, Int?] +//│ ║ l.210: []: [Int, Int?] //│ ║ ^^ //│ ╟── expression of type `[]` does not match type `[Int, Int?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.206: []: [Int, Int?] +//│ ║ l.210: []: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ [Int, Int?] //│ res @@ -218,13 +222,13 @@ let y: C1 = x :e [1, 2, 3]: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.219: [1, 2, 3]: [Int, Int?] +//│ ║ l.223: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^^^ //│ ╟── tuple literal of type `[1, 2, 3]` does not match type `[Int, Int?]` -//│ ║ l.219: [1, 2, 3]: [Int, Int?] +//│ ║ l.223: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.219: [1, 2, 3]: [Int, Int?] +//│ ║ l.223: [1, 2, 3]: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ [Int, Int?] //│ res @@ -340,7 +344,7 @@ let y: C1 = x fun foo(xs: [Int] & 'a) = xs : [Int, Int?] //│ |#fun| |foo|(|xs|#:| |[|Int|]| |&| |'a|)| |#=| |xs| |#:| |[|Int|,| |Int|?|]| //│ AST: TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(xs: App(Var(&), Tup(_: Bra(rcd = false, Tup(_: Var(Int))), _: Var('a)))), Asc(Var(xs), Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))))))) -//│ Parsed: fun foo = (xs: & ('(' Int, ')', 'a,),) => xs : [Int, Int?]; +//│ Parsed: fun foo = (xs: &('(' [Int,] ')', 'a,),) => xs : [Int, Int?]; //│ fun foo: (xs: [Int]) -> [Int, Int?] fun foo(xs: [Int] & 'a) = [xs : [Int, Int?], xs] @@ -362,13 +366,13 @@ fun foo: ([Int] & [Int, Int?]) -> Int :e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.363: foo([1, true]) +//│ ║ l.367: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── tuple literal of type `[1, true]` does not match type `[Int]` -//│ ║ l.363: foo([1, true]) +//│ ║ l.367: foo([1, true]) //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.359: fun foo: ([Int] & [Int, Int?]) -> Int +//│ ║ l.363: fun foo: ([Int] & [Int, Int?]) -> Int //│ ╙── ^^^^^ //│ Int | error //│ res @@ -382,10 +386,10 @@ fun foo: ([Int] | [Int, Int?]) -> Int :e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.383: foo([1, true]) +//│ ║ l.387: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── reference of type `true` is not an instance of type `Int` -//│ ║ l.383: foo([1, true]) +//│ ║ l.387: foo([1, true]) //│ ╙── ^^^^ //│ Int | error //│ res From 31b3eddbc11f6e02a089457fcf6c32a6a2bab2df Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Sat, 30 Sep 2023 21:33:38 +0800 Subject: [PATCH 33/37] Add some notes --- .../main/scala/mlscript/TyperHelpers.scala | 22 +++-- shared/src/test/diff/nu/OptionalArgs.mls | 83 ++++++++++++++++--- 2 files changed, 85 insertions(+), 20 deletions(-) diff --git a/shared/src/main/scala/mlscript/TyperHelpers.scala b/shared/src/main/scala/mlscript/TyperHelpers.scala index e8ff60fc4..f71772d5a 100644 --- a/shared/src/main/scala/mlscript/TyperHelpers.scala +++ b/shared/src/main/scala/mlscript/TyperHelpers.scala @@ -139,7 +139,7 @@ abstract class TyperHelpers { Typer: Typer => } } def tupleUnion(fs1: Ls[Opt[Var] -> FieldType], fs2: Ls[Opt[Var] -> FieldType]): Ls[Opt[Var] -> FieldType] = { - require(fs1.size === fs2.size) + require(fs1.sizeCompare(fs2) <= 0 && fs1.sizeCompare(fs2.filter(x => !x._2.opt)) >= 0) (fs1 lazyZip fs2).map { case ((S(n1), t1), (S(n2), t2)) => (Option.when(n1 === n2)(n1), t1 || t2) case ((no1, t1), (no2, t2)) => (N, t1 || t2) @@ -377,7 +377,10 @@ abstract class TyperHelpers { Typer: Typer => def toUpper(prov: TypeProvenance, opt: Bool = false): FieldType = FieldType(None, this, opt)(prov) def toLower(prov: TypeProvenance): FieldType = FieldType(Some(this), TopType, false)(prov) - def | (that: SimpleType, prov: TypeProvenance = noProv, swapped: Bool = false): SimpleType = (this, that) match { + def | (that: SimpleType, prov: TypeProvenance = noProv, swapped: Bool = false): SimpleType = + { + println("SHIT!") + (this, that) match { case (TopType, _) => this case (BotType, _) => that @@ -388,16 +391,20 @@ abstract class TyperHelpers { Typer: Typer => case (_: RecordType, _: FunctionType) => TopType case (RecordType(fs1), RecordType(fs2)) => RecordType(recordUnion(fs1, fs2))(prov) - case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) + case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) if (fs0.sizeCompare(fs1) === 0) => // TODO[optional-fields]: check size is ok? // If the sizes are different, to merge these we'd have to return // the awkward `t0.toArray & t0.toRecord | t1.toArray & t1.toRecord` - if fs0.sizeCompare(fs1) === 0 => + if (!t0.isLengthCompatibleWith(t1)) BotType + println("HERE, UNION") TupleType(tupleUnion(fs0, fs1))(t0.prov) case _ if !swapped => that | (this, prov, swapped = true) case (`that`, _) => this case (NegType(`that`), _) => TopType - case _ => ComposedType(true, that, this)(prov) - } + case _ => { + println("COMPOSDED!!!") + ComposedType(true, that, this)(prov) + } + }} /** This is to intersect two types that occur in negative position, * where it may be sound to perform some online simplifications/approximations. */ @@ -426,10 +433,9 @@ abstract class TyperHelpers { Typer: Typer => case (_: ClassTag, _: FunctionType) => BotType case (RecordType(fs1), RecordType(fs2)) => RecordType(mergeSortedMap(fs1, fs2)(_ && _).toList)(prov) - case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) => { + case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) => if (!t0.isLengthCompatibleWith(t1)) BotType else TupleType(tupleIntersection(fs0, fs1))(t0.prov) - } case _ if !swapped => that & (this, prov, swapped = true) case (`that`, _) => this case _ if !swapped => that & (this, prov, swapped = true) diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 366701bcc..0f2ab56e6 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -16,6 +16,7 @@ fun f1(a?: Int, b?: Int) = a + b //│ where: //│ α29_31' :> Int //│ allVarPols: +α29_31' +//│ SHIT! //│ consed: Map((true,Int) -> α29_31') //│ ⬤ Unskid: TypedTypingUnit( //│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: Int?, b: Int?,) -> α29_31')) @@ -42,6 +43,7 @@ fun f1(a?: Int, b?: Int) = a + b //│ | | >>>> occs[+α29_31'] := HashSet(Int, α29_31') <~ None //│ | | analyze2[+] Int //│ [occs] +α29_31' {Int,α29_31'} +//│ SHIT! //│ [vars] TreeSet(α29_31') //│ [rec] Set() //│ 0[1] α29_31' @@ -59,6 +61,7 @@ fun f1(a?: Int, b?: Int) = a + b //│ | ~> (a: Int?, b: Int?,) //│ | transform[+] α29_31' () + None //│ | | -> bound Some(true) +//│ | | SHIT! //│ | | transform[+] Int (α29_31') +;@[+](0) None //│ | | ~> Int //│ | ~> Int @@ -77,14 +80,29 @@ fun f1(a?: Int, b?: Int) = a + b //│ | | | DNF: DNF(0, (a: Int?, b: Int?,){}) //│ | | | norm[-] Int //│ | | | | DNF: DNF(0, #Int{}) +//│ | | | | SHIT! +//│ | | | | SHIT! +//│ | | | | SHIT! //│ | | | ~> #Int //│ | | | norm[-] Int //│ | | | | DNF: DNF(0, #Int{}) +//│ | | | | SHIT! +//│ | | | | SHIT! +//│ | | | | SHIT! //│ | | | ~> #Int +//│ | | | SHIT! +//│ | | | SHIT! +//│ | | | SHIT! //│ | | ~> (a: #Int?, b: #Int?,) //│ | | norm[+] Int //│ | | | DNF: DNF(0, #Int{}) +//│ | | | SHIT! +//│ | | | SHIT! +//│ | | | SHIT! //│ | | ~> #Int +//│ | | SHIT! +//│ | | SHIT! +//│ | | SHIT! //│ | ~> ((a: #Int?, b: #Int?,) -> #Int) //│ ⬤ Normalized: TypedTypingUnit( //│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: #Int?, b: #Int?,) -> #Int)) @@ -180,11 +198,11 @@ let y: C1 = x :e [x]: [C1, C1, C1?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.181: [x]: [C1, C1, C1?] +//│ ║ l.199: [x]: [C1, C1, C1?] //│ ║ ^^^ //│ ╟── expression of type `[?a]` does not match type `[C1, C1, C1?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.181: [x]: [C1, C1, C1?] +//│ ║ l.199: [x]: [C1, C1, C1?] //│ ╙── ^^^^^^^^^^^^^ //│ [C1, C1, C1?] //│ res @@ -209,11 +227,11 @@ let y: C1 = x :e []: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.210: []: [Int, Int?] +//│ ║ l.228: []: [Int, Int?] //│ ║ ^^ //│ ╟── expression of type `[]` does not match type `[Int, Int?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.210: []: [Int, Int?] +//│ ║ l.228: []: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ [Int, Int?] //│ res @@ -222,13 +240,13 @@ let y: C1 = x :e [1, 2, 3]: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.223: [1, 2, 3]: [Int, Int?] +//│ ║ l.241: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^^^ //│ ╟── tuple literal of type `[1, 2, 3]` does not match type `[Int, Int?]` -//│ ║ l.223: [1, 2, 3]: [Int, Int?] +//│ ║ l.241: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.223: [1, 2, 3]: [Int, Int?] +//│ ║ l.241: [1, 2, 3]: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ [Int, Int?] //│ res @@ -282,13 +300,25 @@ let y: C1 = x //│ | | DNF: DNF(0, (Int, Int, Int?,){}) //│ | | norm[+] Int //│ | | | DNF: DNF(0, #Int{}) +//│ | | | SHIT! +//│ | | | SHIT! +//│ | | | SHIT! //│ | | ~> #Int //│ | | norm[+] Int //│ | | | DNF: DNF(0, #Int{}) +//│ | | | SHIT! +//│ | | | SHIT! +//│ | | | SHIT! //│ | | ~> #Int //│ | | norm[+] Int //│ | | | DNF: DNF(0, #Int{}) +//│ | | | SHIT! +//│ | | | SHIT! +//│ | | | SHIT! //│ | | ~> #Int +//│ | | SHIT! +//│ | | SHIT! +//│ | | SHIT! //│ | ~> (#Int, #Int, #Int?,) //│ ⬤ Normalized: TypedTypingUnit( //│ Some((#Int, #Int, #Int?,))) @@ -354,6 +384,12 @@ fun foo(xs: [Int] & 'a) = [xs : [Int, Int?], xs] // TODO later: update normal form construction +fun foo: [Int] | [Int?] +//│ fun foo: [Int?] + +fun foo: [Int] & [Int?] +//│ fun foo: [Int] + fun foo: [Int] | [Int, Int?] //│ fun foo: [Int, Int?] @@ -363,16 +399,17 @@ fun foo: [Int] & [Int, Int?] fun foo: ([Int] & [Int, Int?]) -> Int //│ fun foo: ([Int]) -> Int + :e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.367: foo([1, true]) +//│ ║ l.404: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── tuple literal of type `[1, true]` does not match type `[Int]` -//│ ║ l.367: foo([1, true]) +//│ ║ l.404: foo([1, true]) //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.363: fun foo: ([Int] & [Int, Int?]) -> Int +//│ ║ l.399: fun foo: ([Int] & [Int, Int?]) -> Int //│ ╙── ^^^^^ //│ Int | error //│ res @@ -386,12 +423,34 @@ fun foo: ([Int] | [Int, Int?]) -> Int :e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.387: foo([1, true]) +//│ ║ l.424: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── reference of type `true` is not an instance of type `Int` -//│ ║ l.387: foo([1, true]) +//│ ║ l.424: foo([1, true]) //│ ╙── ^^^^ //│ Int | error //│ res //│ = //│ foo is not implemented + +// check check check +let x = [1, 2, 3]: [Int, Int, Int] +//│ let x: [Int, Int, Int] +//│ x +//│ = [ 1, 2, 3 ] + + +fun foo0(x: Int?) = if x is undefined then 0 else x + 1 +//│ fun foo0: (x: Int?) -> Int + +fun foo1(x?) = if x is undefined then 0 else x + 1 +//│ fun foo1: (Int | undefined?) -> Int + +:e +fun foo0(x: Int?) = x + 1 +//│ fun foo0: (x: Int?) -> Int + +:e +fun foo1(x?) = x + 1 +//│ fun foo1: (Int?) -> Int + From b299e54c7a20ae7037e647865b47bb7df49b2803 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Mon, 2 Oct 2023 13:04:12 +0800 Subject: [PATCH 34/37] Using composed type instead of field opt --- shared/src/main/scala/mlscript/Typer.scala | 16 +- shared/src/test/diff/nu/OptionalArgs.mls | 321 ++------------------- 2 files changed, 36 insertions(+), 301 deletions(-) diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index ccef8a8c7..8127a5388 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -916,17 +916,25 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne }.map { case (n, Fld(FldFlags(mut, spec, opt, getter), t)) => if (getter) err(msg"Cannot use `val` in this position", Loc(t :: n.toList)) - val tym = typePolymorphicTerm(t) + val fprov = tp(t.toLoc, (if (mut) "mutable " else "") + "tuple field") + val tym = if (opt) { + println(s"opt val => $opt") + // (typePolymorphicTerm(t) | BotType) + ComposedType(true, + typePolymorphicTerm(t), + TypeRef(TypeName("undefined"), Nil)(noProv))(fprov) + } else { + typePolymorphicTerm(t) + } // val tym = if (n.isDefined) typeType(t.toTypeRaise) // else typePolymorphicTerm(t) - val fprov = tp(t.toLoc, (if (mut) "mutable " else "") + "tuple field") if (mut) { val res = freshVar(fprov, N, n.map(_.name)) val rs = con(tym, res, res) - (n, FieldType(Some(rs), rs, opt)(fprov)) + (n, FieldType(Some(rs), rs, false)(fprov)) } else { val ty = tym.toUpper(fprov) // TODO[optional-fields]: should send opt in toUpper? - val tres = FieldType(ty.lb, ty.ub, opt)(ty.prov) + val tres = FieldType(ty.lb, ty.ub, false)(ty.prov) (n, tres) } })(fs match { diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 0f2ab56e6..594d705fa 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -1,170 +1,10 @@ :NewDefs // TODO add check two compatible fields -:ds fun f1(a?: Int, b?: Int) = a + b -//│ ⬤ Initial: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: Int?, b: Int?,) -> α29')) -//│ None) -//│ where: -//│ α29' :> Int -//│ allVarPols: +α29' -//│ Renewed α29' ~> α29_31' -//│ ⬤ Cleaned up: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: Int?, b: Int?,) -> α29_31')) -//│ None) -//│ where: -//│ α29_31' :> Int -//│ allVarPols: +α29_31' -//│ SHIT! -//│ consed: Map((true,Int) -> α29_31') -//│ ⬤ Unskid: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: Int?, b: Int?,) -> α29_31')) -//│ None) -//│ where: -//│ α29_31' :> Int -//│ analyze1[+] ((a: Int?, b: Int?,) -> α29_31') -//│ | analyze1[+;-] (a: Int?, b: Int?,) -//│ | | analyze1[+;-] Int -//│ | | analyze1[+;-] Int -//│ | analyze1[+] α29_31' -//│ | | analyze1[+;@[+](0)] Int -//│ [inv] -//│ [nums] +α29_31' 1 -//│ analyze2[+] ((a: Int?, b: Int?,) -> α29_31') -//│ | analyze2[+;-] (a: Int?, b: Int?,) -//│ | | analyze2[+;-] Int -//│ | | analyze2[+;-] Int -//│ | analyze2[+] α29_31' -//│ | | >> Processing α29_31' at [+] -//│ | | go α29_31' () -//│ | | | go Int (α29_31') -//│ | | >> Occurrences HashSet(Int, α29_31') -//│ | | >>>> occs[+α29_31'] := HashSet(Int, α29_31') <~ None -//│ | | analyze2[+] Int -//│ [occs] +α29_31' {Int,α29_31'} -//│ SHIT! -//│ [vars] TreeSet(α29_31') -//│ [rec] Set() -//│ 0[1] α29_31' -//│ 1[!] α29_31' -//│ [sub] α29_31' -> None -//│ [bounds] -//│ α29_31' :> Int -//│ [rec] Set() -//│ transform[+] ((a: Int?, b: Int?,) -> α29_31') () + None -//│ | transform[-] (a: Int?, b: Int?,) () +;- None -//│ | | transform[-] Int () +;- None -//│ | | ~> Int -//│ | | transform[-] Int () +;- None -//│ | | ~> Int -//│ | ~> (a: Int?, b: Int?,) -//│ | transform[+] α29_31' () + None -//│ | | -> bound Some(true) -//│ | | SHIT! -//│ | | transform[+] Int (α29_31') +;@[+](0) None -//│ | | ~> Int -//│ | ~> Int -//│ ~> ((a: Int?, b: Int?,) -> Int) -//│ ⬤ Type after simplification: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: Int?, b: Int?,) -> Int)) -//│ None) -//│ where: -//│ allVarPols: -//│ normLike[+] TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: Int?, b: Int?,) -> Int)) -//│ None) -//│ | norm[+] ((a: Int?, b: Int?,) -> Int) -//│ | | DNF: DNF(0, ((a: Int?, b: Int?,) -> Int){}) -//│ | | norm[-] (a: Int?, b: Int?,) -//│ | | | DNF: DNF(0, (a: Int?, b: Int?,){}) -//│ | | | norm[-] Int -//│ | | | | DNF: DNF(0, #Int{}) -//│ | | | | SHIT! -//│ | | | | SHIT! -//│ | | | | SHIT! -//│ | | | ~> #Int -//│ | | | norm[-] Int -//│ | | | | DNF: DNF(0, #Int{}) -//│ | | | | SHIT! -//│ | | | | SHIT! -//│ | | | | SHIT! -//│ | | | ~> #Int -//│ | | | SHIT! -//│ | | | SHIT! -//│ | | | SHIT! -//│ | | ~> (a: #Int?, b: #Int?,) -//│ | | norm[+] Int -//│ | | | DNF: DNF(0, #Int{}) -//│ | | | SHIT! -//│ | | | SHIT! -//│ | | | SHIT! -//│ | | ~> #Int -//│ | | SHIT! -//│ | | SHIT! -//│ | | SHIT! -//│ | ~> ((a: #Int?, b: #Int?,) -> #Int) -//│ ⬤ Normalized: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: #Int?, b: #Int?,) -> #Int)) -//│ None) -//│ where: -//│ allVarPols: -//│ ⬤ Cleaned up: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: #Int?, b: #Int?,) -> #Int)) -//│ None) -//│ where: -//│ allVarPols: -//│ consed: Map() -//│ ⬤ Unskid: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: #Int?, b: #Int?,) -> #Int)) -//│ None) -//│ where: -//│ analyze1[+] ((a: #Int?, b: #Int?,) -> #Int) -//│ | analyze1[+;-] (a: #Int?, b: #Int?,) -//│ | | analyze1[+;-] #Int -//│ | | analyze1[+;-] #Int -//│ | analyze1[+] #Int -//│ [inv] -//│ [nums] -//│ analyze2[+] ((a: #Int?, b: #Int?,) -> #Int) -//│ | analyze2[+;-] (a: #Int?, b: #Int?,) -//│ | | analyze2[+;-] #Int -//│ | | analyze2[+;-] #Int -//│ | analyze2[+] #Int -//│ [occs] -//│ [vars] TreeSet() -//│ [rec] Set() -//│ [sub] -//│ [bounds] -//│ [rec] Set() -//│ transform[+] ((a: #Int?, b: #Int?,) -> #Int) () + None -//│ | transform[-] (a: #Int?, b: #Int?,) () +;- None -//│ | | transform[-] #Int () +;- None -//│ | | ~> #Int -//│ | | transform[-] #Int () +;- None -//│ | | ~> #Int -//│ | ~> (a: #Int?, b: #Int?,) -//│ | transform[+] #Int () + None -//│ | ~> #Int -//│ ~> ((a: #Int?, b: #Int?,) -> #Int) -//│ ⬤ Resim: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: #Int?, b: #Int?,) -> #Int)) -//│ None) -//│ where: -//│ allVarPols: -//│ [subs] HashMap() -//│ ⬤ Factored: TypedTypingUnit( -//│ TypedNuFun(0,fun f1 = (a: Int, b: Int,) => +(a, b,),((a: #Int?, b: #Int?,) -> #Int)) -//│ None) -//│ where: -//│ fun f1: (a: Int?, b: Int?) -> Int +//│ fun f1: (a: Int | undefined, b: Int | undefined) -> Int - -:p fun f1(a: Int, b: Int) = a + b -//│ |#fun| |f1|(|a|#:| |Int|,| |b|#:| |Int|)| |#=| |a| |+| |b| -//│ AST: TypingUnit(NuFunDef(None, f1, None, [], Lam(Tup(a: Var(Int), b: Var(Int)), App(Var(+), Tup(_: Var(a), _: Var(b)))))) -//│ Parsed: fun f1 = (a: Int, b: Int,) => +(a, b,); //│ fun f1: (a: Int, b: Int) -> Int @@ -198,12 +38,12 @@ let y: C1 = x :e [x]: [C1, C1, C1?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.199: [x]: [C1, C1, C1?] -//│ ║ ^^^ +//│ ║ l.39: [x]: [C1, C1, C1?] +//│ ║ ^^^ //│ ╟── expression of type `[?a]` does not match type `[C1, C1, C1?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.199: [x]: [C1, C1, C1?] -//│ ╙── ^^^^^^^^^^^^^ +//│ ║ l.39: [x]: [C1, C1, C1?] +//│ ╙── ^^^^^^^^^^^^^ //│ [C1, C1, C1?] //│ res //│ = [ C2 {} ] @@ -227,12 +67,12 @@ let y: C1 = x :e []: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.228: []: [Int, Int?] -//│ ║ ^^ +//│ ║ l.68: []: [Int, Int?] +//│ ║ ^^ //│ ╟── expression of type `[]` does not match type `[Int, Int?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.228: []: [Int, Int?] -//│ ╙── ^^^^^^^^^^^ +//│ ║ l.68: []: [Int, Int?] +//│ ╙── ^^^^^^^^^^^ //│ [Int, Int?] //│ res //│ = [] @@ -240,130 +80,19 @@ let y: C1 = x :e [1, 2, 3]: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.241: [1, 2, 3]: [Int, Int?] -//│ ║ ^^^^^^^^^ +//│ ║ l.81: [1, 2, 3]: [Int, Int?] +//│ ║ ^^^^^^^^^ //│ ╟── tuple literal of type `[1, 2, 3]` does not match type `[Int, Int?]` -//│ ║ l.241: [1, 2, 3]: [Int, Int?] -//│ ║ ^^^^^^^ +//│ ║ l.81: [1, 2, 3]: [Int, Int?] +//│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.241: [1, 2, 3]: [Int, Int?] -//│ ╙── ^^^^^^^^^^^ +//│ ║ l.81: [1, 2, 3]: [Int, Int?] +//│ ╙── ^^^^^^^^^^^ //│ [Int, Int?] //│ res //│ = [ 1, 2, 3 ] -:ds [1, 2]: [Int, Int, Int?] -//│ ⬤ Initial: TypedTypingUnit( -//│ Some((Int, Int, Int?,))) -//│ where: -//│ allVarPols: -//│ ⬤ Cleaned up: TypedTypingUnit( -//│ Some((Int, Int, Int?,))) -//│ where: -//│ allVarPols: -//│ consed: Map() -//│ ⬤ Unskid: TypedTypingUnit( -//│ Some((Int, Int, Int?,))) -//│ where: -//│ analyze1[+] (Int, Int, Int?,) -//│ | analyze1[+] Int -//│ | analyze1[+] Int -//│ | analyze1[+] Int -//│ [inv] -//│ [nums] -//│ analyze2[+] (Int, Int, Int?,) -//│ | analyze2[+] Int -//│ | analyze2[+] Int -//│ | analyze2[+] Int -//│ [occs] -//│ [vars] TreeSet() -//│ [rec] Set() -//│ [sub] -//│ [bounds] -//│ [rec] Set() -//│ transform[+] (Int, Int, Int?,) () + None -//│ | transform[+] Int () + None -//│ | ~> Int -//│ | transform[+] Int () + None -//│ | ~> Int -//│ | transform[+] Int () + None -//│ | ~> Int -//│ ~> (Int, Int, Int?,) -//│ ⬤ Type after simplification: TypedTypingUnit( -//│ Some((Int, Int, Int?,))) -//│ where: -//│ allVarPols: -//│ normLike[+] TypedTypingUnit( -//│ Some((Int, Int, Int?,))) -//│ | norm[+] (Int, Int, Int?,) -//│ | | DNF: DNF(0, (Int, Int, Int?,){}) -//│ | | norm[+] Int -//│ | | | DNF: DNF(0, #Int{}) -//│ | | | SHIT! -//│ | | | SHIT! -//│ | | | SHIT! -//│ | | ~> #Int -//│ | | norm[+] Int -//│ | | | DNF: DNF(0, #Int{}) -//│ | | | SHIT! -//│ | | | SHIT! -//│ | | | SHIT! -//│ | | ~> #Int -//│ | | norm[+] Int -//│ | | | DNF: DNF(0, #Int{}) -//│ | | | SHIT! -//│ | | | SHIT! -//│ | | | SHIT! -//│ | | ~> #Int -//│ | | SHIT! -//│ | | SHIT! -//│ | | SHIT! -//│ | ~> (#Int, #Int, #Int?,) -//│ ⬤ Normalized: TypedTypingUnit( -//│ Some((#Int, #Int, #Int?,))) -//│ where: -//│ allVarPols: -//│ ⬤ Cleaned up: TypedTypingUnit( -//│ Some((#Int, #Int, #Int?,))) -//│ where: -//│ allVarPols: -//│ consed: Map() -//│ ⬤ Unskid: TypedTypingUnit( -//│ Some((#Int, #Int, #Int?,))) -//│ where: -//│ analyze1[+] (#Int, #Int, #Int?,) -//│ | analyze1[+] #Int -//│ | analyze1[+] #Int -//│ | analyze1[+] #Int -//│ [inv] -//│ [nums] -//│ analyze2[+] (#Int, #Int, #Int?,) -//│ | analyze2[+] #Int -//│ | analyze2[+] #Int -//│ | analyze2[+] #Int -//│ [occs] -//│ [vars] TreeSet() -//│ [rec] Set() -//│ [sub] -//│ [bounds] -//│ [rec] Set() -//│ transform[+] (#Int, #Int, #Int?,) () + None -//│ | transform[+] #Int () + None -//│ | ~> #Int -//│ | transform[+] #Int () + None -//│ | ~> #Int -//│ | transform[+] #Int () + None -//│ | ~> #Int -//│ ~> (#Int, #Int, #Int?,) -//│ ⬤ Resim: TypedTypingUnit( -//│ Some((#Int, #Int, #Int?,))) -//│ where: -//│ allVarPols: -//│ [subs] HashMap() -//│ ⬤ Factored: TypedTypingUnit( -//│ Some((#Int, #Int, #Int?,))) -//│ where: //│ [Int, Int, Int?] //│ res //│ = [ 1, 2 ] @@ -403,13 +132,13 @@ fun foo: ([Int] & [Int, Int?]) -> Int :e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.404: foo([1, true]) +//│ ║ l.133: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── tuple literal of type `[1, true]` does not match type `[Int]` -//│ ║ l.404: foo([1, true]) +//│ ║ l.133: foo([1, true]) //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.399: fun foo: ([Int] & [Int, Int?]) -> Int +//│ ║ l.128: fun foo: ([Int] & [Int, Int?]) -> Int //│ ╙── ^^^^^ //│ Int | error //│ res @@ -423,10 +152,10 @@ fun foo: ([Int] | [Int, Int?]) -> Int :e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.424: foo([1, true]) +//│ ║ l.153: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── reference of type `true` is not an instance of type `Int` -//│ ║ l.424: foo([1, true]) +//│ ║ l.153: foo([1, true]) //│ ╙── ^^^^ //│ Int | error //│ res @@ -439,18 +168,16 @@ let x = [1, 2, 3]: [Int, Int, Int] //│ x //│ = [ 1, 2, 3 ] - fun foo0(x: Int?) = if x is undefined then 0 else x + 1 -//│ fun foo0: (x: Int?) -> Int +//│ fun foo0: (x: Int | undefined) -> Int fun foo1(x?) = if x is undefined then 0 else x + 1 -//│ fun foo1: (Int | undefined?) -> Int +//│ fun foo1: (Int | undefined) -> Int :e fun foo0(x: Int?) = x + 1 -//│ fun foo0: (x: Int?) -> Int +//│ fun foo0: (x: Int | undefined) -> Int :e fun foo1(x?) = x + 1 -//│ fun foo1: (Int?) -> Int - +//│ fun foo1: (Int | undefined) -> Int From 25d776484e9b32c99d4346086b25509765b72aa6 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Mon, 2 Oct 2023 20:15:17 +0800 Subject: [PATCH 35/37] Revert to opt + show bracketed --- shared/src/main/scala/mlscript/Typer.scala | 22 ++++---- shared/src/main/scala/mlscript/helpers.scala | 13 ++++- shared/src/test/diff/nu/OptionalArgs.mls | 59 +++++++++++++------- 3 files changed, 59 insertions(+), 35 deletions(-) diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index 8127a5388..36399da62 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -917,24 +917,24 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne if (getter) err(msg"Cannot use `val` in this position", Loc(t :: n.toList)) val fprov = tp(t.toLoc, (if (mut) "mutable " else "") + "tuple field") - val tym = if (opt) { - println(s"opt val => $opt") - // (typePolymorphicTerm(t) | BotType) - ComposedType(true, - typePolymorphicTerm(t), - TypeRef(TypeName("undefined"), Nil)(noProv))(fprov) - } else { - typePolymorphicTerm(t) - } + // val tym = if (opt) { + // println(s"opt val => $opt") + // ComposedType(true, + // typePolymorphicTerm(t), + // TypeRef(TypeName("undefined"), Nil)(noProv))(fprov) + // } else { + // typePolymorphicTerm(t) + // } + val tym = typePolymorphicTerm(t) // val tym = if (n.isDefined) typeType(t.toTypeRaise) // else typePolymorphicTerm(t) if (mut) { val res = freshVar(fprov, N, n.map(_.name)) val rs = con(tym, res, res) - (n, FieldType(Some(rs), rs, false)(fprov)) + (n, FieldType(Some(rs), rs, opt)(fprov)) } else { val ty = tym.toUpper(fprov) // TODO[optional-fields]: should send opt in toUpper? - val tres = FieldType(ty.lb, ty.ub, false)(ty.prov) + val tres = FieldType(ty.lb, ty.ub, opt)(ty.prov) (n, tres) } })(fs match { diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index d26f9c380..997793ba0 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -22,6 +22,7 @@ trait TypeLikeImpl extends Located { self: TypeLike => private def parensIf(str: Str, cnd: Boolean): Str = if (cnd) "(" + str + ")" else str private def showField(f: Field, ctx: ShowCtx): Str = { + // println(s"OK $f") val res = f match { case Field(N, ub, _) => ub.showIn(ctx, 0) case Field(S(lb), ub, _) if lb === ub => ub.showIn(ctx, 0) @@ -30,10 +31,16 @@ trait TypeLikeImpl extends Located { self: TypeLike => case Field(S(lb), ub, _) => s"in ${lb.showIn(ctx, 0)} out ${ub.showIn(ctx, 0)}" } val opt = f match { - case Field(_, _, true) => "?" - case Field(_, _, false)=> "" + case Field(_, _, true) => true + case Field(_, _, false)=> false } - res + opt + println(s"OK $f ### ${res + opt}" ) + if (opt) { + "(" + res + ")" + "?" + } else { + res + } + // res + opt } private def showFields(fs: Ls[Opt[Var] -> Field], ctx: ShowCtx): Ls[Str] = fs.map(nt => s"${nt._2.mutStr}${nt._1.fold("")(_.name + ": ")}${showField(nt._2, ctx)}") diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 594d705fa..5b121d830 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -2,7 +2,7 @@ // TODO add check two compatible fields fun f1(a?: Int, b?: Int) = a + b -//│ fun f1: (a: Int | undefined, b: Int | undefined) -> Int +//│ fun f1: (a: (Int)?, b: (Int)?) -> Int fun f1(a: Int, b: Int) = a + b //│ fun f1: (a: Int, b: Int) -> Int @@ -31,7 +31,7 @@ let y: C1 = x //│ = [ C2 {}, C2 {} ] [x, y]: [C1, C1, C1?] -//│ [C1, C1, C1?] +//│ [C1, C1, (C1)?] //│ res //│ = [ C2 {}, C2 {} ] @@ -40,11 +40,11 @@ let y: C1 = x //│ ╔══[ERROR] Type mismatch in type ascription: //│ ║ l.39: [x]: [C1, C1, C1?] //│ ║ ^^^ -//│ ╟── expression of type `[?a]` does not match type `[C1, C1, C1?]` +//│ ╟── expression of type `[?a]` does not match type `[C1, C1, (C1)?]` //│ ╟── Note: constraint arises from tuple type: //│ ║ l.39: [x]: [C1, C1, C1?] //│ ╙── ^^^^^^^^^^^^^ -//│ [C1, C1, C1?] +//│ [C1, C1, (C1)?] //│ res //│ = [ C2 {} ] @@ -55,12 +55,12 @@ let y: C1 = x //│ = [ 1, 2, 3 ] [1, 2]: [Int, Int?] -//│ [Int, Int?] +//│ [Int, (Int)?] //│ res //│ = [ 1, 2 ] [1]: [Int, Int?] -//│ [Int, Int?] +//│ [Int, (Int)?] //│ res //│ = [ 1 ] @@ -69,11 +69,11 @@ let y: C1 = x //│ ╔══[ERROR] Type mismatch in type ascription: //│ ║ l.68: []: [Int, Int?] //│ ║ ^^ -//│ ╟── expression of type `[]` does not match type `[Int, Int?]` +//│ ╟── expression of type `[]` does not match type `[Int, (Int)?]` //│ ╟── Note: constraint arises from tuple type: //│ ║ l.68: []: [Int, Int?] //│ ╙── ^^^^^^^^^^^ -//│ [Int, Int?] +//│ [Int, (Int)?] //│ res //│ = [] @@ -82,18 +82,18 @@ let y: C1 = x //│ ╔══[ERROR] Type mismatch in type ascription: //│ ║ l.81: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^^^ -//│ ╟── tuple literal of type `[1, 2, 3]` does not match type `[Int, Int?]` +//│ ╟── tuple literal of type `[1, 2, 3]` does not match type `[Int, (Int)?]` //│ ║ l.81: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: //│ ║ l.81: [1, 2, 3]: [Int, Int?] //│ ╙── ^^^^^^^^^^^ -//│ [Int, Int?] +//│ [Int, (Int)?] //│ res //│ = [ 1, 2, 3 ] [1, 2]: [Int, Int, Int?] -//│ [Int, Int, Int?] +//│ [Int, Int, (Int)?] //│ res //│ = [ 1, 2 ] @@ -103,24 +103,24 @@ let y: C1 = x fun foo(xs: [Int] & 'a) = xs : [Int, Int?] //│ |#fun| |foo|(|xs|#:| |[|Int|]| |&| |'a|)| |#=| |xs| |#:| |[|Int|,| |Int|?|]| //│ AST: TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(xs: App(Var(&), Tup(_: Bra(rcd = false, Tup(_: Var(Int))), _: Var('a)))), Asc(Var(xs), Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))))))) -//│ Parsed: fun foo = (xs: &('(' [Int,] ')', 'a,),) => xs : [Int, Int?]; -//│ fun foo: (xs: [Int]) -> [Int, Int?] +//│ Parsed: fun foo = (xs: &('(' [Int,] ')', 'a,),) => xs : [Int, (Int)?]; +//│ fun foo: (xs: [Int]) -> [Int, (Int)?] fun foo(xs: [Int] & 'a) = [xs : [Int, Int?], xs] -//│ fun foo: forall 'a. (xs: [Int] & 'a) -> [[Int, Int?], [Int] & 'a] +//│ fun foo: forall 'a. (xs: [Int] & 'a) -> [[Int, (Int)?], [Int] & 'a] // TODO later: update normal form construction fun foo: [Int] | [Int?] -//│ fun foo: [Int?] +//│ fun foo: [(Int)?] fun foo: [Int] & [Int?] //│ fun foo: [Int] fun foo: [Int] | [Int, Int?] -//│ fun foo: [Int, Int?] +//│ fun foo: [Int, (Int)?] fun foo: [Int] & [Int, Int?] //│ fun foo: [Int] @@ -147,7 +147,7 @@ foo([1, true]) fun foo: ([Int] | [Int, Int?]) -> Int -//│ fun foo: ([Int, Int?]) -> Int +//│ fun foo: ([Int, (Int)?]) -> Int :e foo([1, true]) @@ -169,15 +169,32 @@ let x = [1, 2, 3]: [Int, Int, Int] //│ = [ 1, 2, 3 ] fun foo0(x: Int?) = if x is undefined then 0 else x + 1 -//│ fun foo0: (x: Int | undefined) -> Int +//│ fun foo0: (x: (Int)?) -> Int fun foo1(x?) = if x is undefined then 0 else x + 1 -//│ fun foo1: (Int | undefined) -> Int +//│ fun foo1: ((Int | undefined)?) -> Int :e fun foo0(x: Int?) = x + 1 -//│ fun foo0: (x: Int | undefined) -> Int +//│ fun foo0: (x: (Int)?) -> Int :e fun foo1(x?) = x + 1 -//│ fun foo1: (Int | undefined) -> Int +//│ fun foo1: ((Int)?) -> Int + +:e +fun ff(x: Int?) = x + 1 +//│ fun ff: (x: (Int)?) -> Int + +:e +fun ff(x: Int | undefined) = x + 1 +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.190: fun ff(x: Int | undefined) = x + 1 +//│ ║ ^^^^^ +//│ ╟── type `undefined` is not an instance of type `Int` +//│ ║ l.190: fun ff(x: Int | undefined) = x + 1 +//│ ║ ^^^^^^^^^ +//│ ╟── but it flows into reference with expected type `Int` +//│ ║ l.190: fun ff(x: Int | undefined) = x + 1 +//│ ╙── ^ +//│ fun ff: (x: Int | undefined) -> (Int | error) From 59814ac0c0cd0e0e29496954b832ac3aa6a511da Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Tue, 3 Oct 2023 09:03:40 +0800 Subject: [PATCH 36/37] . --- .../main/scala/mlscript/TyperHelpers.scala | 7 +- shared/src/test/diff/nu/OptionalArgs.mls | 170 +++++++++++++++++- 2 files changed, 167 insertions(+), 10 deletions(-) diff --git a/shared/src/main/scala/mlscript/TyperHelpers.scala b/shared/src/main/scala/mlscript/TyperHelpers.scala index f71772d5a..19dc2e092 100644 --- a/shared/src/main/scala/mlscript/TyperHelpers.scala +++ b/shared/src/main/scala/mlscript/TyperHelpers.scala @@ -377,10 +377,7 @@ abstract class TyperHelpers { Typer: Typer => def toUpper(prov: TypeProvenance, opt: Bool = false): FieldType = FieldType(None, this, opt)(prov) def toLower(prov: TypeProvenance): FieldType = FieldType(Some(this), TopType, false)(prov) - def | (that: SimpleType, prov: TypeProvenance = noProv, swapped: Bool = false): SimpleType = - { - println("SHIT!") - (this, that) match { + def | (that: SimpleType, prov: TypeProvenance = noProv, swapped: Bool = false): SimpleType = (this, that) match { case (TopType, _) => this case (BotType, _) => that @@ -404,7 +401,7 @@ abstract class TyperHelpers { Typer: Typer => println("COMPOSDED!!!") ComposedType(true, that, this)(prov) } - }} + } /** This is to intersect two types that occur in negative position, * where it may be sound to perform some online simplifications/approximations. */ diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 5b121d830..567cecef2 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -186,15 +186,175 @@ fun foo1(x?) = x + 1 fun ff(x: Int?) = x + 1 //│ fun ff: (x: (Int)?) -> Int -:e +:d fun ff(x: Int | undefined) = x + 1 +//│ 0. Typing ‹fun ff = (x: |(Int, undefined,),) => +(x, 1,)› +//│ | 0. Created lazy type info for fun ff = (x: |(Int, undefined,),) => +(x, 1,) +//│ | Completing fun ff = (x: |(Int, undefined,),) => +(x, 1,) +//│ | | Type params +//│ | | Params +//│ | | 1. Typing term (x: |(Int, undefined,),) => +(x, 1,) +//│ | | | 1. Typing pattern [x: |(Int, undefined,),] +//│ | | | | 1. Typing pattern x : Int | undefined +//│ | | | | | Typing type Union(TypeName(Int),Literal(undefined)) +//│ | | | | | | vars=Map() newDefsInfo=Map() +//│ | | | | | | 1. type Union(TypeName(Int),Literal(undefined)) +//│ | | | | | | | 1. type TypeName(Int) +//│ | | | | | | | => Int +//│ | | | | | | | 1. type Literal(undefined) +//│ | | | | | | | => #undefined +//│ | | | | | | | COMPOSDED!!! +//│ | | | | | | => (Int | #undefined) +//│ | | | | | => (Int | #undefined) ——— +//│ | | | | 1. : (Int | #undefined) +//│ | | | 1. : (x: (Int | #undefined),) +//│ | | | 1. Typing term +(x, 1,) +//│ | | | | 1. Typing term + +//│ | | | | 1. : ((Int, Int,) -> Int) +//│ | | | | 1. Typing term x +//│ | | | | 1. : (Int | #undefined) +//│ | | | | 1. Typing term 1 +//│ | | | | 1. : #1 +//│ | | | | CONSTRAIN ((Int, Int,) -> Int) ), #1,) -> α83') +//│ | | | | where +//│ | | | | 1. C ((Int, Int,) -> Int) ), #1,) -> α83') (0) +//│ | | | | | 1. C ((Int | #undefined), #1,) ) (6) +//│ | | | | | | | | | CONSTRAINT FAILURE: #undefined <: #Int +//│ | | | | | | | | | allVarPols: +//│ | | | | | | | | | normLike[+] #undefined +//│ | | | | | | | | | | norm[+] #undefined +//│ | | | | | | | | | | | DNF: DNF(0, #undefined{}) +//│ | | | | | | | | | | ~> #undefined +//│ | | | | | | | | | CONSTRAIN #error<> ),) -> α83') +//│ | | CONSTRAIN ((x: (Int | #undefined),) -> α83') Int | #error<> +//│ | | 1. C ((x: (Int | #undefined),) -> α83') +(x, 1,),((x: (Int | #undefined),) -> α83')) where +//│ α83' :> Int | #error<> +//│ | Typing unit statements +//│ | : None +//│ ======== TYPED ======== +//│ fun ff: ‹∀ 0. ((x: (Int | #undefined),) -> α83')› where +//│ | α83' :> Int | #error<> +//│ COMPOSDED!!! +//│ COMPOSDED!!! //│ fun ff: (x: Int | undefined) -> (Int | error) + +:d +fun ff(x: Int | undefined) = if x is undefined then 0 else x + 1 +//│ 0. Typing ‹fun ff = (x: |(Int, undefined,),) => if (is(x, undefined,)) then 0 else +(x, 1,)› +//│ | 0. Created lazy type info for fun ff = (x: |(Int, undefined,),) => if (is(x, undefined,)) then 0 else +(x, 1,) +//│ | Completing fun ff = (x: |(Int, undefined,),) => if (is(x, undefined,)) then 0 else +(x, 1,) +//│ | | Type params +//│ | | Params +//│ | | 1. Typing term (x: |(Int, undefined,),) => if (is(x, undefined,)) then 0 else +(x, 1,) +//│ | | | 1. Typing pattern [x: |(Int, undefined,),] +//│ | | | | 1. Typing pattern x : Int | undefined +//│ | | | | | Typing type Union(TypeName(Int),Literal(undefined)) +//│ | | | | | | vars=Map() newDefsInfo=Map() +//│ | | | | | | 1. type Union(TypeName(Int),Literal(undefined)) +//│ | | | | | | | 1. type TypeName(Int) +//│ | | | | | | | => Int +//│ | | | | | | | 1. type Literal(undefined) +//│ | | | | | | | => #undefined +//│ | | | | | | | COMPOSDED!!! +//│ | | | | | | => (Int | #undefined) +//│ | | | | | => (Int | #undefined) ——— +//│ | | | | 1. : (Int | #undefined) +//│ | | | 1. : (x: (Int | #undefined),) +//│ | | | 1. Typing term if (is(x, undefined,)) then 0 else +(x, 1,) +//│ | | | | [Desugarer.destructPattern] scrutinee = x; pattern = undefined +//│ | | | | [Desugarer.destructPattern] Result: «x is undefined +//│ | | | | Desugared term: case x of { undefined => 0; _ => +(x, 1,) } +//│ | | | | 1. Typing term case x of { undefined => 0; _ => +(x, 1,) } +//│ | | | | | 1. Typing term x +//│ | | | | | 1. : (Int | #undefined) +//│ | | | | | CONSTRAIN (Int | #undefined) ) +//│ | | | | | 1. Typing term +(x, 1,) +//│ | | | | | | 1. Typing term + +//│ | | | | | | 1. : ((Int, Int,) -> Int) +//│ | | | | | | 1. Typing term x +//│ | | | | | | 1. : α86' +//│ | | | | | | 1. Typing term 1 +//│ | | | | | | 1. : #1 +//│ | | | | | | CONSTRAIN ((Int, Int,) -> Int) ,) -> α87') +//│ | | | | | | where +//│ | | | | | | 1. C ((Int, Int,) -> Int) ,) -> α87') (0) +//│ | | | | | | | 1. C (α86', #1,) ) | (α86' & ~(#undefined))) +//│ | | | | | where +//│ α86' <: Int +//│ | | | | | 1. C (Int | #undefined) | (α86' & ~(#undefined))) (0) +//│ | | | | | | 1. C Int | (α86' & ~(#undefined))) (2) +//│ | | | | | | | 1. C #Int | (α86' & ~(#undefined))) (4) +//│ | | | | | | | | COMPOSDED!!! +//│ | | | | | | | | 1. ARGH DNF(0, #Int{}) {} | α86'∧~(#undefined)) +//│ | | | | | | | | | DNF DISCHARGE CONSTRAINTS +//│ | | | | | | | | | Consider #Int{} <: DNF(1, #undefined{} | α86'∧~(#undefined)) +//│ | | | | | | | | | Possible: List(α86'∧~(#undefined)) +//│ | | | | | | | | | 1. A #Int{} % List() ))) % ⊥ +//│ | | | | | | | | | | Case.1 +//│ | | | | | | | | | | 1. A #Int{} % List() {} % List() )) % ⊥ +//│ | | | | | | | | | | | 1. A #Int{} % List(#undefined) {} & #undefined =:= ⊥ +//│ | | | | | | 1. C #undefined | (α86' & ~(#undefined))) (2) +//│ | | | | | | | Already a subtype by <:< +//│ | | | | 1. : (#0 | α87') +//│ | | | 1. : (#0 | α87') +//│ | | 1. : ((x: (Int | #undefined),) -> (#0 | α87')) +//│ | | CONSTRAIN ((x: (Int | #undefined),) -> (#0 | α87')) Int +//│ | | 1. C ((x: (Int | #undefined),) -> (#0 | α87')) if (is(x, undefined,)) then 0 else +(x, 1,),((x: (Int | #undefined),) -> (#0 | α87'))) where +//│ α87' :> Int +//│ | Typing unit statements +//│ | : None +//│ ======== TYPED ======== +//│ fun ff: ‹∀ 0. ((x: (Int | #undefined),) -> (#0 | α87'))› where +//│ | α87' :> Int +//│ COMPOSDED!!! +//│ fun ff: (x: Int | undefined) -> Int From 028a5b59ba86bb262199bbd33665a191c334bbe8 Mon Sep 17 00:00:00 2001 From: Mohammad Broughani Date: Tue, 3 Oct 2023 11:02:50 +0800 Subject: [PATCH 37/37] Add ascribing for pattern match on optional fields --- shared/src/main/scala/mlscript/Typer.scala | 15 +- .../main/scala/mlscript/TyperDatatypes.scala | 4 +- shared/src/test/diff/nu/OptionalArgs.mls | 298 +++++++----------- 3 files changed, 127 insertions(+), 190 deletions(-) diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index 36399da62..dfc3712a3 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -906,11 +906,22 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne case tup: Tup if funkyTuples => typeTerms(tup :: Nil, false, Nil) case Tup(fs) => - TupleType(fs.mapConserve { case e @ (n, Fld(flags, t)) => + TupleType(fs.mapConserve { case e @ (n, f @ Fld(flags, t)) => n match { case S(v) if ctx.inPattern => (n, Fld(flags, - Asc(v, t.toTypeRaise).withLoc(v.toLoc.fold(t.toLoc)(_ ++ t.toLoc |> some)))) + Asc(v, Union(t.toTypeRaise,Literal(UnitLit(true)))).withLoc(v.toLoc.fold(t.toLoc)(_ ++ t.toLoc |> some)))) + case N if flags.opt => + t match { + case v: Var if ctx.inPattern => + (n, Fld(flags, + Asc(v, Union(TypeVar(R(""), N),Literal(UnitLit(true)))).withLoc(v.toLoc.fold(t.toLoc)(_ ++ t.toLoc |> some)))) + case _ => + // if ctx.inPattern // TODO + err("Error here", f.toLoc) // TODO[optional-fields] + e + } + case _ => e } }.map { case (n, Fld(FldFlags(mut, spec, opt, getter), t)) => diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala index cbf49aa3f..2adace13a 100644 --- a/shared/src/main/scala/mlscript/TyperDatatypes.scala +++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala @@ -184,7 +184,7 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => def freshenAboveImpl(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): FunctionType = FunctionType(lhs.freshenAbove(lim, rigidify), rhs.freshenAbove(lim, rigidify))(prov) override def toString = s"(${lhs match { - case TupleType((N, FieldType(N, f: TupleType, false)) :: Nil) => "[" + f.showInner + "]" + case TupleType((N, FieldType(N, f: TupleType, _)) :: Nil) => "[" + f.showInner + "]" case TupleType((N, f) :: Nil) => f.toString case lhs => lhs }} -> $rhs)" @@ -492,7 +492,7 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): FieldType = update(_.freshenAbove(lim, rigidify), _.freshenAbove(lim, rigidify)) override def toString = - lb.fold(s"$ub${if (opt) "?" else ""}")(lb => s"mut ${if (lb === BotType) "" else lb}..$ub") + lb.fold(s"$ub")(lb => s"mut ${if (lb === BotType) "" else lb}..$ub") + (if (opt) "?" else "") } object FieldType { //TODO def mk(vi: VarianceInfo, lb: ST, ub: ST)(prov: TP): FieldType = vi match { diff --git a/shared/src/test/diff/nu/OptionalArgs.mls b/shared/src/test/diff/nu/OptionalArgs.mls index 567cecef2..aeff8950f 100644 --- a/shared/src/test/diff/nu/OptionalArgs.mls +++ b/shared/src/test/diff/nu/OptionalArgs.mls @@ -2,10 +2,28 @@ // TODO add check two compatible fields fun f1(a?: Int, b?: Int) = a + b -//│ fun f1: (a: (Int)?, b: (Int)?) -> Int +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.4: fun f1(a?: Int, b?: Int) = a + b +//│ ║ ^^^^^ +//│ ╟── type `undefined` is not an instance of type `Int` +//│ ║ l.4: fun f1(a?: Int, b?: Int) = a + b +//│ ║ ^^^ +//│ ╟── but it flows into reference with expected type `Int` +//│ ║ l.4: fun f1(a?: Int, b?: Int) = a + b +//│ ╙── ^ +//│ fun f1: (a: (Int | undefined)?, b: (Int | undefined)?) -> (Int | error) fun f1(a: Int, b: Int) = a + b -//│ fun f1: (a: Int, b: Int) -> Int +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.16: fun f1(a: Int, b: Int) = a + b +//│ ║ ^^^^^ +//│ ╟── type `undefined` is not an instance of type `Int` +//│ ║ l.16: fun f1(a: Int, b: Int) = a + b +//│ ║ ^^^ +//│ ╟── but it flows into reference with expected type `Int` +//│ ║ l.16: fun f1(a: Int, b: Int) = a + b +//│ ╙── ^ +//│ fun f1: (a: Int | undefined, b: Int | undefined) -> (Int | error) class C1 @@ -38,11 +56,11 @@ let y: C1 = x :e [x]: [C1, C1, C1?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.39: [x]: [C1, C1, C1?] +//│ ║ l.57: [x]: [C1, C1, C1?] //│ ║ ^^^ //│ ╟── expression of type `[?a]` does not match type `[C1, C1, (C1)?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.39: [x]: [C1, C1, C1?] +//│ ║ l.57: [x]: [C1, C1, C1?] //│ ╙── ^^^^^^^^^^^^^ //│ [C1, C1, (C1)?] //│ res @@ -67,11 +85,11 @@ let y: C1 = x :e []: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.68: []: [Int, Int?] +//│ ║ l.86: []: [Int, Int?] //│ ║ ^^ //│ ╟── expression of type `[]` does not match type `[Int, (Int)?]` //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.68: []: [Int, Int?] +//│ ║ l.86: []: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ [Int, (Int)?] //│ res @@ -80,13 +98,13 @@ let y: C1 = x :e [1, 2, 3]: [Int, Int?] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.81: [1, 2, 3]: [Int, Int?] +//│ ║ l.99: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^^^ //│ ╟── tuple literal of type `[1, 2, 3]` does not match type `[Int, (Int)?]` -//│ ║ l.81: [1, 2, 3]: [Int, Int?] +//│ ║ l.99: [1, 2, 3]: [Int, Int?] //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.81: [1, 2, 3]: [Int, Int?] +//│ ║ l.99: [1, 2, 3]: [Int, Int?] //│ ╙── ^^^^^^^^^^^ //│ [Int, (Int)?] //│ res @@ -104,10 +122,34 @@ fun foo(xs: [Int] & 'a) = xs : [Int, Int?] //│ |#fun| |foo|(|xs|#:| |[|Int|]| |&| |'a|)| |#=| |xs| |#:| |[|Int|,| |Int|?|]| //│ AST: TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(xs: App(Var(&), Tup(_: Bra(rcd = false, Tup(_: Var(Int))), _: Var('a)))), Asc(Var(xs), Tuple(List((None,Field(None,TypeName(Int),false)), (None,Field(None,TypeName(Int),true)))))))) //│ Parsed: fun foo = (xs: &('(' [Int,] ')', 'a,),) => xs : [Int, (Int)?]; -//│ fun foo: (xs: [Int]) -> [Int, (Int)?] +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.121: fun foo(xs: [Int] & 'a) = xs : [Int, Int?] +//│ ║ ^^ +//│ ╟── type `undefined` is not a 2-element tuple +//│ ║ l.121: fun foo(xs: [Int] & 'a) = xs : [Int, Int?] +//│ ║ ^^^^^^^^^^ +//│ ╟── but it flows into reference with expected type `[Int, (Int)?]` +//│ ║ l.121: fun foo(xs: [Int] & 'a) = xs : [Int, Int?] +//│ ║ ^^ +//│ ╟── Note: constraint arises from tuple type: +//│ ║ l.121: fun foo(xs: [Int] & 'a) = xs : [Int, Int?] +//│ ╙── ^^^^^^^^^^^ +//│ fun foo: (xs: undefined | [Int]) -> [Int, (Int)?] fun foo(xs: [Int] & 'a) = [xs : [Int, Int?], xs] -//│ fun foo: forall 'a. (xs: [Int] & 'a) -> [[Int, (Int)?], [Int] & 'a] +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.139: fun foo(xs: [Int] & 'a) = [xs : [Int, Int?], xs] +//│ ║ ^^ +//│ ╟── type `undefined` is not a 2-element tuple +//│ ║ l.139: fun foo(xs: [Int] & 'a) = [xs : [Int, Int?], xs] +//│ ║ ^^^^^^^^^^ +//│ ╟── but it flows into reference with expected type `[Int, (Int)?]` +//│ ║ l.139: fun foo(xs: [Int] & 'a) = [xs : [Int, Int?], xs] +//│ ║ ^^ +//│ ╟── Note: constraint arises from tuple type: +//│ ║ l.139: fun foo(xs: [Int] & 'a) = [xs : [Int, Int?], xs] +//│ ╙── ^^^^^^^^^^^ +//│ fun foo: (xs: undefined | [Int]) -> [[Int, (Int)?], undefined] @@ -132,13 +174,13 @@ fun foo: ([Int] & [Int, Int?]) -> Int :e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.133: foo([1, true]) +//│ ║ l.175: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── tuple literal of type `[1, true]` does not match type `[Int]` -//│ ║ l.133: foo([1, true]) +//│ ║ l.175: foo([1, true]) //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from tuple type: -//│ ║ l.128: fun foo: ([Int] & [Int, Int?]) -> Int +//│ ║ l.170: fun foo: ([Int] & [Int, Int?]) -> Int //│ ╙── ^^^^^ //│ Int | error //│ res @@ -152,10 +194,10 @@ fun foo: ([Int] | [Int, Int?]) -> Int :e foo([1, true]) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.153: foo([1, true]) +//│ ║ l.195: foo([1, true]) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── reference of type `true` is not an instance of type `Int` -//│ ║ l.153: foo([1, true]) +//│ ║ l.195: foo([1, true]) //│ ╙── ^^^^ //│ Int | error //│ res @@ -169,192 +211,76 @@ let x = [1, 2, 3]: [Int, Int, Int] //│ = [ 1, 2, 3 ] fun foo0(x: Int?) = if x is undefined then 0 else x + 1 -//│ fun foo0: (x: (Int)?) -> Int +//│ fun foo0: (x: (Int | undefined)?) -> Int fun foo1(x?) = if x is undefined then 0 else x + 1 //│ fun foo1: ((Int | undefined)?) -> Int :e fun foo0(x: Int?) = x + 1 -//│ fun foo0: (x: (Int)?) -> Int +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.220: fun foo0(x: Int?) = x + 1 +//│ ║ ^^^^^ +//│ ╟── type `undefined` is not an instance of type `Int` +//│ ║ l.220: fun foo0(x: Int?) = x + 1 +//│ ║ ^^^ +//│ ╟── but it flows into reference with expected type `Int` +//│ ║ l.220: fun foo0(x: Int?) = x + 1 +//│ ╙── ^ +//│ fun foo0: (x: (Int | undefined)?) -> (Int | error) :e fun foo1(x?) = x + 1 -//│ fun foo1: ((Int)?) -> Int +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.233: fun foo1(x?) = x + 1 +//│ ║ ^^^^^ +//│ ╟── reference of type `undefined` is not an instance of type `Int` +//│ ║ l.233: fun foo1(x?) = x + 1 +//│ ╙── ^ +//│ fun foo1: ((Int | undefined)?) -> (Int | error) :e fun ff(x: Int?) = x + 1 -//│ fun ff: (x: (Int)?) -> Int +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.243: fun ff(x: Int?) = x + 1 +//│ ║ ^^^^^ +//│ ╟── type `undefined` is not an instance of type `Int` +//│ ║ l.243: fun ff(x: Int?) = x + 1 +//│ ║ ^^^ +//│ ╟── but it flows into reference with expected type `Int` +//│ ║ l.243: fun ff(x: Int?) = x + 1 +//│ ╙── ^ +//│ fun ff: (x: (Int | undefined)?) -> (Int | error) + -:d fun ff(x: Int | undefined) = x + 1 -//│ 0. Typing ‹fun ff = (x: |(Int, undefined,),) => +(x, 1,)› -//│ | 0. Created lazy type info for fun ff = (x: |(Int, undefined,),) => +(x, 1,) -//│ | Completing fun ff = (x: |(Int, undefined,),) => +(x, 1,) -//│ | | Type params -//│ | | Params -//│ | | 1. Typing term (x: |(Int, undefined,),) => +(x, 1,) -//│ | | | 1. Typing pattern [x: |(Int, undefined,),] -//│ | | | | 1. Typing pattern x : Int | undefined -//│ | | | | | Typing type Union(TypeName(Int),Literal(undefined)) -//│ | | | | | | vars=Map() newDefsInfo=Map() -//│ | | | | | | 1. type Union(TypeName(Int),Literal(undefined)) -//│ | | | | | | | 1. type TypeName(Int) -//│ | | | | | | | => Int -//│ | | | | | | | 1. type Literal(undefined) -//│ | | | | | | | => #undefined -//│ | | | | | | | COMPOSDED!!! -//│ | | | | | | => (Int | #undefined) -//│ | | | | | => (Int | #undefined) ——— -//│ | | | | 1. : (Int | #undefined) -//│ | | | 1. : (x: (Int | #undefined),) -//│ | | | 1. Typing term +(x, 1,) -//│ | | | | 1. Typing term + -//│ | | | | 1. : ((Int, Int,) -> Int) -//│ | | | | 1. Typing term x -//│ | | | | 1. : (Int | #undefined) -//│ | | | | 1. Typing term 1 -//│ | | | | 1. : #1 -//│ | | | | CONSTRAIN ((Int, Int,) -> Int) ), #1,) -> α83') -//│ | | | | where -//│ | | | | 1. C ((Int, Int,) -> Int) ), #1,) -> α83') (0) -//│ | | | | | 1. C ((Int | #undefined), #1,) ) (6) -//│ | | | | | | | | | CONSTRAINT FAILURE: #undefined <: #Int -//│ | | | | | | | | | allVarPols: -//│ | | | | | | | | | normLike[+] #undefined -//│ | | | | | | | | | | norm[+] #undefined -//│ | | | | | | | | | | | DNF: DNF(0, #undefined{}) -//│ | | | | | | | | | | ~> #undefined -//│ | | | | | | | | | CONSTRAIN #error<> ),) -> α83') -//│ | | CONSTRAIN ((x: (Int | #undefined),) -> α83') Int | #error<> -//│ | | 1. C ((x: (Int | #undefined),) -> α83') +(x, 1,),((x: (Int | #undefined),) -> α83')) where -//│ α83' :> Int | #error<> -//│ | Typing unit statements -//│ | : None -//│ ======== TYPED ======== -//│ fun ff: ‹∀ 0. ((x: (Int | #undefined),) -> α83')› where -//│ | α83' :> Int | #error<> -//│ COMPOSDED!!! -//│ COMPOSDED!!! +//│ ║ l.256: fun ff(x: Int | undefined) = x + 1 +//│ ║ ^^^^^^^^^ +//│ ╟── but it flows into reference with expected type `Int` +//│ ║ l.256: fun ff(x: Int | undefined) = x + 1 +//│ ╙── ^ //│ fun ff: (x: Int | undefined) -> (Int | error) -:d -fun ff(x: Int | undefined) = if x is undefined then 0 else x + 1 -//│ 0. Typing ‹fun ff = (x: |(Int, undefined,),) => if (is(x, undefined,)) then 0 else +(x, 1,)› -//│ | 0. Created lazy type info for fun ff = (x: |(Int, undefined,),) => if (is(x, undefined,)) then 0 else +(x, 1,) -//│ | Completing fun ff = (x: |(Int, undefined,),) => if (is(x, undefined,)) then 0 else +(x, 1,) -//│ | | Type params -//│ | | Params -//│ | | 1. Typing term (x: |(Int, undefined,),) => if (is(x, undefined,)) then 0 else +(x, 1,) -//│ | | | 1. Typing pattern [x: |(Int, undefined,),] -//│ | | | | 1. Typing pattern x : Int | undefined -//│ | | | | | Typing type Union(TypeName(Int),Literal(undefined)) -//│ | | | | | | vars=Map() newDefsInfo=Map() -//│ | | | | | | 1. type Union(TypeName(Int),Literal(undefined)) -//│ | | | | | | | 1. type TypeName(Int) -//│ | | | | | | | => Int -//│ | | | | | | | 1. type Literal(undefined) -//│ | | | | | | | => #undefined -//│ | | | | | | | COMPOSDED!!! -//│ | | | | | | => (Int | #undefined) -//│ | | | | | => (Int | #undefined) ——— -//│ | | | | 1. : (Int | #undefined) -//│ | | | 1. : (x: (Int | #undefined),) -//│ | | | 1. Typing term if (is(x, undefined,)) then 0 else +(x, 1,) -//│ | | | | [Desugarer.destructPattern] scrutinee = x; pattern = undefined -//│ | | | | [Desugarer.destructPattern] Result: «x is undefined -//│ | | | | Desugared term: case x of { undefined => 0; _ => +(x, 1,) } -//│ | | | | 1. Typing term case x of { undefined => 0; _ => +(x, 1,) } -//│ | | | | | 1. Typing term x -//│ | | | | | 1. : (Int | #undefined) -//│ | | | | | CONSTRAIN (Int | #undefined) ) -//│ | | | | | 1. Typing term +(x, 1,) -//│ | | | | | | 1. Typing term + -//│ | | | | | | 1. : ((Int, Int,) -> Int) -//│ | | | | | | 1. Typing term x -//│ | | | | | | 1. : α86' -//│ | | | | | | 1. Typing term 1 -//│ | | | | | | 1. : #1 -//│ | | | | | | CONSTRAIN ((Int, Int,) -> Int) ,) -> α87') -//│ | | | | | | where -//│ | | | | | | 1. C ((Int, Int,) -> Int) ,) -> α87') (0) -//│ | | | | | | | 1. C (α86', #1,) ) | (α86' & ~(#undefined))) -//│ | | | | | where -//│ α86' <: Int -//│ | | | | | 1. C (Int | #undefined) | (α86' & ~(#undefined))) (0) -//│ | | | | | | 1. C Int | (α86' & ~(#undefined))) (2) -//│ | | | | | | | 1. C #Int | (α86' & ~(#undefined))) (4) -//│ | | | | | | | | COMPOSDED!!! -//│ | | | | | | | | 1. ARGH DNF(0, #Int{}) {} | α86'∧~(#undefined)) -//│ | | | | | | | | | DNF DISCHARGE CONSTRAINTS -//│ | | | | | | | | | Consider #Int{} <: DNF(1, #undefined{} | α86'∧~(#undefined)) -//│ | | | | | | | | | Possible: List(α86'∧~(#undefined)) -//│ | | | | | | | | | 1. A #Int{} % List() ))) % ⊥ -//│ | | | | | | | | | | Case.1 -//│ | | | | | | | | | | 1. A #Int{} % List() {} % List() )) % ⊥ -//│ | | | | | | | | | | | 1. A #Int{} % List(#undefined) {} & #undefined =:= ⊥ -//│ | | | | | | 1. C #undefined | (α86' & ~(#undefined))) (2) -//│ | | | | | | | Already a subtype by <:< -//│ | | | | 1. : (#0 | α87') -//│ | | | 1. : (#0 | α87') -//│ | | 1. : ((x: (Int | #undefined),) -> (#0 | α87')) -//│ | | CONSTRAIN ((x: (Int | #undefined),) -> (#0 | α87')) Int -//│ | | 1. C ((x: (Int | #undefined),) -> (#0 | α87')) if (is(x, undefined,)) then 0 else +(x, 1,),((x: (Int | #undefined),) -> (#0 | α87'))) where -//│ α87' :> Int -//│ | Typing unit statements -//│ | : None -//│ ======== TYPED ======== -//│ fun ff: ‹∀ 0. ((x: (Int | #undefined),) -> (#0 | α87'))› where -//│ | α87' :> Int -//│ COMPOSDED!!! -//│ fun ff: (x: Int | undefined) -> Int + +:e +fun foo1([x, y]?) = x + y +//│ ╔══[ERROR] Error here +//│ ║ l.270: fun foo1([x, y]?) = x + y +//│ ╙── ^^^^^^ +//│ fun foo1: (([Int, Int])?) -> Int + + +[123?] +//│ ╔══[ERROR] Error here +//│ ║ l.277: [123?] +//│ ╙── ^^^ +//│ [(123)?] +//│ res +//│ = [ 123 ] + + +