From 7ce59ab126371fb24d3214bc9b5e7cdb1300f825 Mon Sep 17 00:00:00 2001 From: YKY Date: Sat, 19 Nov 2022 22:02:03 +0800 Subject: [PATCH 01/13] current progress --- .../scala/mlscript/compiler/DataType.scala | 36 ++ .../mlscript/compiler/DataTypeInferer.scala | 18 + .../scala/mlscript/compiler/Helpers.scala | 30 + .../mlscript/compiler/mono/Monomorph.scala | 541 ++++++++++++++++++ .../compiler/mono/MonomorphContext.scala | 33 ++ .../compiler/mono/MonomorphError.scala | 3 + .../compiler/mono/specializer/Builtin.scala | 42 ++ .../compiler/mono/specializer/Context.scala | 15 + .../mono/specializer/Predicates.scala | 6 + .../mono/specializer/Specializer.scala | 5 + .../compiler/printer/ExprPrinter.scala | 110 ++++ .../main/scala/mlscript/compiler/syntax.scala | 187 ++++++ compiler/shared/test/diff/mono.mls | 198 +++++++ .../test/scala/mlscript/compiler/Test.scala | 19 +- .../src/test/scala/mlscript/DiffTests.scala | 9 +- 15 files changed, 1247 insertions(+), 5 deletions(-) create mode 100644 compiler/shared/main/scala/mlscript/compiler/DataType.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/DataTypeInferer.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/Helpers.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/mono/MonomorphContext.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/mono/MonomorphError.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/mono/specializer/Predicates.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/printer/ExprPrinter.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/syntax.scala create mode 100644 compiler/shared/test/diff/mono.mls diff --git a/compiler/shared/main/scala/mlscript/compiler/DataType.scala b/compiler/shared/main/scala/mlscript/compiler/DataType.scala new file mode 100644 index 000000000..ca3ba27b0 --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/DataType.scala @@ -0,0 +1,36 @@ +package mlscript.compiler + +abstract class DataType + +object DataType: + sealed class Singleton(value: Expr.Literal, dataType: DataType) extends DataType: + override def toString(): String = value.toString() + + enum Primitive(name: String) extends DataType: + case Integer extends Primitive("int") + case Decimal extends Primitive("real") + case Boolean extends Primitive("bool") + case String extends Primitive("str") + override def toString(): String = this.name + end Primitive + + sealed case class Tuple(elementTypes: List[DataType]) extends DataType: + override def toString(): String = elementTypes.mkString("(", ", ", ")") + + sealed case class Class(declaration: Item.TypeDecl) extends DataType: + override def toString(): String = s"class ${declaration.name.name}" + + sealed case class Function(parameterTypes: List[DataType], returnType: DataType) extends DataType: + def this(returnType: DataType, parameterTypes: DataType*) = + this(parameterTypes.toList, returnType) + override def toString(): String = + val parameterList = parameterTypes.mkString("(", ", ", ")") + s"$parameterList -> $returnType" + + sealed case class Record(fields: Map[String, DataType]) extends DataType: + def this(fields: (String, DataType)*) = this(Map.from(fields)) + override def toString(): String = + fields.iterator.map { (name, ty) => s"$name: $ty" }.mkString("{", ", ", "}") + + case object Unknown extends DataType: + override def toString(): String = "unknown" diff --git a/compiler/shared/main/scala/mlscript/compiler/DataTypeInferer.scala b/compiler/shared/main/scala/mlscript/compiler/DataTypeInferer.scala new file mode 100644 index 000000000..117a8a3b7 --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/DataTypeInferer.scala @@ -0,0 +1,18 @@ +package mlscript.compiler +import mlscript.compiler.mono.MonomorphError + +trait DataTypeInferer: + import DataType._ + + def findClassByName(name: String): Option[Item.TypeDecl] + + def infer(expr: Expr, compatiableType: Option[DataType]): DataType = + expr match + case Expr.Tuple(elements) => DataType.Tuple(elements.map(infer(_, None))) + case lit @ Expr.Literal(value: BigInt) => Singleton(lit, Primitive.Integer) + case lit @ Expr.Literal(value: BigDecimal) => Singleton(lit, Primitive.Decimal) + case lit @ Expr.Literal(value: String) => Singleton(lit, Primitive.String) + case lit @ Expr.Literal(value: Boolean) => Singleton(lit, Primitive.Boolean) + case Expr.Apply(Expr.Ref(name), args) => + findClassByName(name).fold(DataType.Unknown)(DataType.Class(_)) + case _ => throw MonomorphError(s"I can't infer the type of $expr now") \ No newline at end of file diff --git a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala new file mode 100644 index 000000000..764accf23 --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala @@ -0,0 +1,30 @@ +package mlscript.compiler + +import mlscript.{App, Asc, Assign, Bind, Blk, Bra, CaseOf, Lam, Let, Lit, + New, Rcd, Sel, Subs, Term, Test, Tup, With, Var, Fld, If} +import mlscript.{IfBody, IfThen, IfElse, IfLet, IfOpApp, IfOpsApp, IfBlock} +import mlscript.UnitLit +import mlscript.codegen.Helpers.inspect as showStructure +import mlscript.compiler.mono.MonomorphError + +object Helpers: + /** + * Extract parameters for monomorphization from a `Tup`. + */ + def toFuncParams(term: Term): Iterator[Parameter] = term match + case Tup(fields) => fields.iterator.flatMap { + // The new parser emits `Tup(_: UnitLit(true))` from `fun f() = x`. + case (_, Fld(_, _, UnitLit(true))) => None + case (_, Fld(_, spec, Var(name))) => Some((spec, Expr.Ref(name))) + case _ => throw new MonomorphError( + s"only `Var` can be parameters but we meet ${showStructure(term)}" + ) + } + case _ => throw MonomorphError("expect the list of parameters to be a `Tup`") + + def toFuncArgs(term: Term): IterableOnce[Term] = term match + // The new parser generates `(undefined, )` when no arguments. + // Let's do this temporary fix. + case Tup((_, Fld(_, _, UnitLit(true))) :: Nil) => Iterable.empty + case Tup(fields) => fields.iterator.map(_._2.value) + case _ => Some(term) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala new file mode 100644 index 000000000..b349593e1 --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala @@ -0,0 +1,541 @@ +package mlscript.compiler.mono + +import mlscript.compiler.debug.{Debug, DummyDebug} +import mlscript.{TypingUnit, NuTypeDef, NuFunDef} +import mlscript.{AppliedType, TypeName} +import mlscript.{App, Asc, Assign, Bind, Blk, Bra, CaseOf, Lam, Let, Lit, + New, Rcd, Sel, Subs, Term, Test, Tup, With, Var, Fld, If} +import mlscript.{IfThen, IfElse, IfLet, IfOpApp, IfOpsApp, IfBlock} +import mlscript.{IntLit, DecLit, StrLit, UnitLit} +import scala.collection.immutable.{HashMap} +import scala.collection.mutable.{Map as MutMap, Set as MutSet} +import scala.collection.mutable.ArrayBuffer +import mlscript.Cls +import mlscript.CaseBranches +import mlscript.TypeDefKind +import mlscript.AppliedType.apply +import mlscript.compiler.mono.specializer.Builtin +import mlscript.compiler.mono.specializer.Context +import mlscript.compiler.* + +import mlscript.compiler.printer.ExprPrinter + +class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: + import Helpers._ + import Monomorph._ + + /** + * Specialized implementations of function declarations. + */ + private val funImpls = MutMap[String, (Item.FuncDecl, MutMap[String, Item.FuncDecl])]() + private def allFunImpls: IterableOnce[(Item.FuncDecl, Item.FuncDecl)] = + funImpls.iterator.flatMap { case (name, (protoFunc, implFunc)) => + implFunc.values.map((protoFunc, _)) + } + + /** + * Specialized implementations of each type declarations. + */ + private val tyImpls = MutMap[String, SpecializationMap[Item.TypeDecl]]() + private val allTypeImpls = MutMap[String, Item.TypeDecl]() + /** + * Add a prototype type declaration. + */ + private def addPrototypeTypeDecl(typeDecl: Item.TypeDecl) = + tyImpls.addOne(typeDecl.name.name, SpecializationMap(typeDecl)) + /** + * An iterator going through all type declarations. + */ + private def allTypeDecls: IterableOnce[Item.TypeDecl] = + tyImpls.values.flatMap { _.iterator } + + /** + * A global store of monomorphized lambda classes. + */ + private val lamTyDefs = MutMap[String, Item.TypeDecl]() + /** + * A global store of anonymous classes. For example, `new { ... }`. + */ + private val anonymTyDefs = MutMap[String, Item.TypeDecl]() + + def findClassByName(name: String): Option[mlscript.compiler.Item.TypeDecl] = + allTypeImpls.get(name) + + /** + * This function monomorphizes the top-level `TypingUnit` into a `Module`. + */ + def monomorphize(tu: TypingUnit): Module = + debug.trace("MONO MODL", PrettyPrinter.show(tu)) { + mlscript.compiler.Module(tu.entities.iterator.flatMap[Expr | Item] { + case term: Term => + Some(monomorphizeTerm(term)(using MonomorphContext.empty)) + case tyDef: NuTypeDef => + monomorphizeTypeDef(tyDef) + None + case funDef: NuFunDef => + val funcItem = monomorphizeFunDef(funDef) + funcItem match + case funcDecl: Item.FuncDecl => + funImpls.addOne(funcDecl.name.name, (funcDecl, MutMap())) + case _ => () + Some(funcItem) + }.concat(allFunImpls.map(_._2)) + .concat(allTypeDecls) + .concat(lamTyDefs.values) + .concat(anonymTyDefs.values) + .toList) + }(identity) + + /** + * This function monomorphizes the nested `TypingUnit` into a `Isolation`. + */ + def monomorphizeBody(body: TypingUnit): Isolation = + debug.trace("MONO BODY", PrettyPrinter.show(body)) { + Isolation(body.entities.flatMap[Expr | Item.FuncDecl | Item.FuncDefn] { + case term: Term => + Some(monomorphizeTerm(term)(using MonomorphContext.empty)) + case tyDef: NuTypeDef => + monomorphizeTypeDef(tyDef) + None + case funDef: NuFunDef => + Some(monomorphizeFunDef(funDef)) + }) + }(identity) + + /** + * This function flattens a top-level type definition and returns the root + * type definition. There is a simple class lifting here. + */ + private def monomorphizeTypeDef(tyDef: NuTypeDef): Item.TypeDecl = + debug.trace("MONO TDEF", PrettyPrinter.show(tyDef)) { + /** + * The recursive function doing the real work. + * @param tyDef the type definition + * @param namePath enclosing class names and this class name + */ + def rec(tyDef: NuTypeDef, namePath: List[String]): Item.TypeDecl = + debug.trace[Item.TypeDecl]("LIFT", PrettyPrinter.show(tyDef)) { + val NuTypeDef(kind, _, tparams, params, parents, body) = tyDef + val isolation = Isolation(body.entities.flatMap { + // Question: Will there be pure terms in class body? + case term: Term => + Some(monomorphizeTerm(term)(using MonomorphContext.empty)) + case subTypeDef: NuTypeDef => + rec(subTypeDef, subTypeDef.nme.name :: namePath) + None + case subFunDef: NuFunDef => + Some(monomorphizeFunDef(subFunDef)) + }) + val className = namePath.reverseIterator.mkString("_") + val typeDecl: Item.TypeDecl = Item.TypeDecl( + className, // name + kind, // kind + tparams, // typeParams + toFuncParams(params).toList, // params + parents.map { + case Var(name) => (TypeName(name), Nil) + case App(Var(name), _) => (TypeName(name), Nil) + case _ => throw MonomorphError("unsupported parent term") + }, // parents + isolation // body + ) + addPrototypeTypeDecl(typeDecl) + typeDecl + }() + + rec(tyDef, tyDef.nme.name :: Nil) + }(identity) + + /** + * This function monomorphizes a function definition in smoe typing units. + * @param tyDecls the destination of nested type declarations + */ + private def monomorphizeFunDef(funDef: NuFunDef): Item.FuncDecl | Item.FuncDefn = + debug.trace[Item.FuncDecl | Item.FuncDefn]("MONO FUNC", PrettyPrinter.show(funDef)) { + val NuFunDef(_, nme, targs, rhs) = funDef + rhs match + case Left(Lam(params, body)) => + Item.FuncDecl(nme, toFuncParams(params).toList, monomorphizeTerm(body)(using MonomorphContext.empty)) + case Left(body: Term) => Item.FuncDecl(nme, Nil, monomorphizeTerm(body)(using MonomorphContext.empty)) + case Right(polyType) => Item.FuncDefn(nme, targs, polyType) + }(identity) + + /** + * This function monomophizes a `Term` into an `Expr`. + */ + def monomorphizeTerm(term: Term)(using context: MonomorphContext): Expr = + debug.trace[Expr]("MONO " + term.getClass.getSimpleName.toUpperCase, PrettyPrinter.show(term)) { + term match + case Var(name) => Expr.Ref(name) + case Lam(lhs, rhs) => monomorphizeLambda(lhs, rhs) + case App(App(Var("=>"), Bra(false, args: Tup)), body) => + monomorphizeLambda(args, body) + case App(App(Var("."), self), App(Var(method), args: Tup)) => + debug.log(s"meet a member method invocation") + Expr.Apply(Expr.Select(monomorphizeTerm(self), method), List.from(toFuncArgs(args).map(monomorphizeTerm))) + case App(lhs, rhs) => + debug.log("Monomorphizing the callee...") + val callee = monomorphizeTerm(lhs) + debug.log("Monomorphizing arguments...") + val arguments = toFuncArgs(rhs).map(monomorphizeTerm).toList + debug.log("Specializing the invocation...") + callee match + case Expr.Ref(name) => + specializeCall(name, arguments).fold(Expr.Apply(callee, arguments))(identity) + case _ => Expr.Apply(callee, arguments) + case Tup(fields) => + Expr.Tuple(fields.map { + case (_, Fld(mut, spec, value)) => monomorphizeTerm(value) + }) + case Rcd(fields) => + Expr.Record(fields.map { + case (name, Fld(mut, spec, value)) => (name, monomorphizeTerm(value)) + }) + case Sel(receiver, fieldName) => + Expr.Select(monomorphizeTerm(receiver), fieldName) + case Let(true, Var(name), rhs, body) => + val exprRhs = monomorphizeTerm(rhs)(using context + (name, DataType.Unknown)) + val exprBody = monomorphizeTerm(body)(using context + (name, infer(exprRhs, None))) + Expr.LetIn(true, name, exprRhs, exprBody) + case Let(false, Var(name), rhs, body) => + val exprRhs = monomorphizeTerm(rhs) + val exprBody = monomorphizeTerm(body)(using context + (name, infer(exprRhs, None))) + Expr.LetIn(false, name, exprRhs, exprBody) + case Blk(stmts) => Expr.Block(stmts.flatMap[Expr | Item.FuncDecl | Item.FuncDefn] { + case term: Term => Some(monomorphizeTerm(term)) + case tyDef: NuTypeDef => + monomorphizeTypeDef(tyDef) + None + case funDef: NuFunDef => Some(monomorphizeFunDef(funDef)) + case mlscript.DataDefn(_) => throw MonomorphError("unsupported DataDefn") + case mlscript.DatatypeDefn(_, _) => throw MonomorphError("unsupported DatatypeDefn") + case mlscript.TypeDef(_, _, _, _, _, _, _) => throw MonomorphError("unsupported TypeDef") + case mlscript.Def(_, _, _, _) => throw MonomorphError("unsupported Def") + case mlscript.LetS(_, _, _) => throw MonomorphError("unsupported LetS") + }) + case Bra(rcd, term) => monomorphizeTerm(term) + case Asc(term, ty) => Expr.As(monomorphizeTerm(term), ty) + case _: Bind => throw MonomorphError("cannot monomorphize `Bind`") + case _: Test => throw MonomorphError("cannot monomorphize `Test`") + case With(term, Rcd(fields)) => + Expr.With(monomorphizeTerm(term), Expr.Record(fields.map { + case (name, Fld(mut, spec, value)) => (name, monomorphizeTerm(term)) + })) + case CaseOf(term, cases) => ??? + case Subs(array, index) => + Expr.Subscript(monomorphizeTerm(array), monomorphizeTerm(index)) + case Assign(lhs, rhs) => + Expr.Assign(monomorphizeTerm(lhs), monomorphizeTerm(rhs)) + case New(None, body) => + val className = s"Anonym_${anonymTyDefs.size}" + val classDecl = Item.classDecl(className, Nil, monomorphizeBody(body)) + Expr.Apply(className, Nil) + case New(Some((constructor, args)), body) => + val typeName = constructor match + case AppliedType(TypeName(name), _) => name + case TypeName(name) => name + monomorphizeNew(typeName, toFuncArgs(args).toList, body) + // case Blk(unit) => Expr.Isolated(monomorphizeBody(TypingUnit(unit))) + case If(body, alternate) => body match + case IfThen(condition, consequent) => + Expr.IfThenElse( + monomorphizeTerm(condition), + monomorphizeTerm(consequent), + alternate.map(monomorphizeTerm) + ) + case term: IfElse => throw MonomorphError("unsupported IfElse") + case term: IfLet => throw MonomorphError("unsupported IfLet") + case term: IfOpApp => throw MonomorphError("unsupported IfOpApp") + case term: IfOpsApp => throw MonomorphError("unsupported IfOpsApp") + case term: IfBlock => throw MonomorphError("unsupported IfBlock") + case IntLit(value) => Expr.Literal(value) + case DecLit(value) => Expr.Literal(value) + case StrLit(value) => Expr.Literal(value) + case UnitLit(undefinedOrNull) => + Expr.Literal(if undefinedOrNull + then UnitValue.Undefined + else UnitValue.Null) + }(identity) + + def monomorphizeLambda(args: Term, body: Term): Expr = + debug.trace("MONO LAMBDA", args.toString + " => " + body) { + val params = toFuncParams(args).toList + // TODO: Capture variables referenced in the lambda body. + // We should capture: closure variables and referenced type variables. + val className = s"Lambda_${lamTyDefs.size}" + val applyMethod: Item.FuncDecl = + Item.FuncDecl("apply", toFuncParams(args).toList, monomorphizeTerm(body)(using MonomorphContext.empty)) + val classBody = Isolation(applyMethod :: Nil) + val classDecl = Item.classDecl(className, Nil, classBody) + // Add to the global store. + lamTyDefs.addOne((className, classDecl)) + // Returns a class construction. + Expr.Apply(Expr.Ref(className), Nil) + }(identity) + + /** + * `new C(...) { ... }` expressions are converted into + * `{ class CImpl extends C(...) { ... }; CImpl() }`. + * ~~This requires you to add a `LetClass` construct to `mlscript.Term`.~~ + */ + def monomorphizeNew(name: String, termArgs: List[Term], termBody: TypingUnit): Expr.Apply = + debug.trace[Expr.Apply]("MONO NEW", { + name + termArgs.iterator.map(_.toString).mkString("(", ", ", ")") + + " with " + PrettyPrinter.show(termBody) + }) { + val args = termArgs.map(monomorphizeTerm(_)(using MonomorphContext.empty)) + val body = monomorphizeBody(termBody) + val specTypeDecl = specializeTypeDef(name, args, body) + Expr.Apply(specTypeDecl.name, Nil) + }(identity) + + def specializeCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = + debug.trace("SPEC CALL", name + args.mkString(" with (", ", ", ")")) { + if tyImpls.contains(name) then specializeClassCall(name, args) + else if funImpls.contains(name) then specializeFunctionCall(name, args) + else { + debug.log(s"Not found: $name") + None + } + }() + + private def partitationArguments(name: String, params: List[Parameter], args: List[Expr]): (List[Expr], List[Expr]) = + if (args.length != params.length) { + debug.log("") + throw MonomorphError(s"$name expect ${params.length} arguments but ${args.length} were given") + } + val staticArguments = params.iterator.zip(args).flatMap({ + case ((true, _), value) => Some(value) + case _ => None + }).toList + val dynamicArguments = params.iterator.zip(args).flatMap({ + case ((false, _), value) => Some(value) + case _ => None + }).toList + (staticArguments, dynamicArguments) + + private def generateSignature(staticArguments: List[Expr])(using MonomorphContext): String = + staticArguments.iterator.map(infer(_, None)).mkString("__", "_", "") + + def specializeClassCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = + debug.trace("SPEC CALL", "class " + name + args.mkString(" with (", ", ", ")")) { + import TypeDeclKind._ + tyImpls.get(name).flatMap { specClassMap => specClassMap.prototype match + case Item.TypeDecl(Expr.Ref(name), Class, typeParams, params, parents, body) => + val (staticArguments, dynamicArguments) = partitationArguments(name, params, args) + val (staticParameters, dynamicParameters) = params.partition(_._1) + if (staticArguments.isEmpty) { + None + } else { + val signature = generateSignature(staticArguments) + val specClassDecl = specClassMap.getOrInsert(signature, { + specClassMap.base = Item.TypeDecl( + Expr.Ref(name), // name + Class, // kind + typeParams, // typeParams + dynamicParameters, // params + Nil, // parents + Isolation.empty // body + ) + val values = params.iterator.zip(args).flatMap({ + case ((true, Expr.Ref(name)), value) => Some((name, value)) + case ((false, _), _) => None + }) + val typeImpl: Item.TypeDecl = Item.TypeDecl( + Expr.Ref(s"${name}" + signature), // name + Class, // kind + typeParams, // typeParams + dynamicParameters, // params + (TypeName(name), dynamicParameters.map(_._2)) :: Nil, // parents + specializeClass(specClassMap.prototype)(using Context(values)) // body + ) + allTypeImpls += (typeImpl.name.name -> typeImpl) + typeImpl + }) + Some(Expr.Apply(specClassDecl.name, dynamicArguments)) + } + case Item.TypeDecl(_, Trait, _, _, _, _) => + throw new MonomorphError(s"cannot specialize trait $name") + case Item.TypeDecl(_, Alias, _, _, _, _) => + throw new MonomorphError(s"cannot specialize type alias $name") + } + }(_.fold(Debug.noPostTrace)(identity)) + + // TODO: Remove `Option[Expr]` by passing the callee. + def specializeFunctionCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = + debug.trace("SPEC CALL", "function " + name + args.mkString(" with (", ", ", ")")) { + funImpls.get(name).flatMap { case (Item.FuncDecl(ref, params, body), impls) => + val (staticArguments, dynamicArguments) = partitationArguments(name, params, args) + if (staticArguments.isEmpty) { + None + } else { + val signature = generateSignature(staticArguments) + val specFuncDecl = impls.get(signature).getOrElse[Item.FuncDecl] { + val values = params.iterator.zip(args).flatMap({ + case ((true, Expr.Ref(name)), value) => Some((name, value)) + case ((false, _), _) => None + }) + val specFuncBody = specializeExpr(body)(using Context(values)) + val staticParams = params.filter(!_._1) + val specFuncName = s"${name}" + signature + val funcDecl: Item.FuncDecl = Item.FuncDecl(specFuncName, staticParams, specFuncBody) + impls.addOne((specFuncName, funcDecl)) + funcDecl + } + Some(Expr.Apply(specFuncDecl.name, dynamicArguments)) + } + } + }(_.fold(Debug.noPostTrace)(identity)) + + def specializeExpr(expr: Expr)(using ctx: Context, typeContext: MonomorphContext): Expr = + debug.trace[Expr]("SPEC EXPR", expr, "in context", ctx) { + expr match + case Expr.Ref(name) => ctx.get(name) match + case Some(value) => value + case None => expr + case _: Expr.Lambda => expr + case Expr.Apply(Expr.Apply(ident @ Expr.Ref(name), lhsExpr :: Nil), rhsExpr :: Nil) + if Builtin.isBinaryOperator(name) => + val lhs = specializeExpr(lhsExpr) + val rhs = specializeExpr(rhsExpr) + Builtin.evalulateBinaryOperation(name, lhs, rhs) + .getOrElse(Expr.Apply(Expr.Apply(ident, lhs :: Nil), rhs :: Nil)) + case Expr.Apply(callee, arguments) => + val specCallee = specializeExpr(callee) + val specArgs = arguments.map(specializeExpr) + specCallee match + case Expr.Ref(name) => specializeCall(name, specArgs).getOrElse(expr) + case Expr.Lambda(params, body) => + // Same as `specializeFuncDecl` but I should extract some common stuffs. + ??? + case Expr.Select(receiver, Expr.Ref(fieldName)) => + infer(receiver, None) match + case DataType.Class(declaration) => declaration.body.get(fieldName) match + case Some(memberFuncDecl: Item.FuncDecl) => + // FIXME: the context should be from the class + val specFuncDecl = specializeFunction(memberFuncDecl) + val branches = ArrayBuffer[CaseBranch]() + val alias: Expr.Ref = Expr.Ref("alpha") // alpha conversion needed + branches += CaseBranch.Instance( + declaration.name, + alias, + Expr.Apply(Expr.Select(alias, specFuncDecl.name), specArgs) + ) + Expr.Match(receiver, branches) + case Some(memberFuncDefn: Item.FuncDefn) => + throw MonomorphError(s"class ${declaration.name.name}.$fieldName is not implemented") + case None => throw MonomorphError(s"class ${declaration.name.name} does not have $fieldName") + case other => throw MonomorphError(s"cannot select a non-class instance") + case other => throw MonomorphError(s"not a callable: $other") + case Expr.Tuple(elements) => Expr.Tuple(elements.map(specializeExpr)) + case Expr.Record(fields) => Expr.Record(fields.map { + case (key, value) => (key, specializeExpr(value)) + }) + case Expr.Select(receiver, field) => + // We can do more. + Expr.Select(specializeExpr(receiver), field) + case Expr.LetIn(true, name, Expr.Lambda(params, body), cont) => + // Create a callable entry in the context and recursively specialize + // the continuation. + throw MonomorphError(s"recursive local functions are not implemented") + case Expr.LetIn(true, _, _, _) => + throw MonomorphError(s"recursive non-function definition are not allowed") + case Expr.LetIn(false, Expr.Ref(name), rhs, body) => + val specRhs = specializeExpr(rhs) + specializeExpr(body)(using ctx + (name -> specRhs)) + case Expr.Block(items) => + val onlyExpressions = items.iterator.flatMap { + case expr: Expr => Some(expr) + case _ => None + } + onlyExpressions.map(specializeExpr).toList match + case Nil => Expr.Literal(UnitValue.Undefined) + case items => items.last + case expr: Expr.Literal => expr + case Expr.IfThenElse(condition, consequent, alternate) => + specializeExpr( + if specializeExpr(condition).asBoolean() + then consequent + else alternate.getOrElse(Expr.Literal(UnitValue.Undefined)) + ) + case _ => throw MonomorphError(s"unimplemented ${expr.getClass()}") + }(identity) + + /** + * This function monomorphizes the given class with given arguments. + * @return specialized class name and all included classes + */ + def specializeTypeDef( + name: String, + args: List[Expr], + body: Isolation + ): Item.TypeDecl = + debug.trace[Item.TypeDecl]("SPEC TDEF", name + args.mkString("(", ", ", ")") + " {\n" + body + "\n}") { + tyImpls.get(name) match { + case Some(classSpecMap) => + val Item.TypeDecl(_, kind, typeParams, params, parents, body) = classSpecMap.prototype + val implClassName: Expr.Ref = Expr.Ref(s"${name}_${classSpecMap.size}") + Item.TypeDecl(implClassName, kind, typeParams, params, parents, body) + // FIXME: Logic here does not work. + case None => throw new MonomorphError(s"cannot specialize undeclared type $name") + } + }(identity) + + def specializeFunction(funcProto: Item.FuncDecl)(using ctx: Context, typeContext: MonomorphContext): Item.FuncDecl = + Item.FuncDecl(funcProto.name, funcProto.params, specializeExpr(funcProto.body)) + + def specializeClass(classProto: Item.TypeDecl)(using ctx: Context, typeContext: MonomorphContext): Isolation = + debug.trace("SPEC CLASS", s"class ${classProto.name.name}", "in value context", ctx) { + Isolation(classProto.body.items.map { + case expr: Expr => specializeExpr(expr) + case funcDecl: Item.FuncDecl => specializeFunction(funcDecl) + case other => throw MonomorphError(s"$other is not supported") + }) + }(identity) + + def infer(expr: Expr, compatiableType: Option[DataType])(using context: MonomorphContext): DataType = + debug.trace("INFER", expr.toString) { + expr match + case Expr.Ref(name) => context.get(name).getOrElse(DataType.Unknown) + case other => super.infer(expr, compatiableType) + }(_.toString) + + // Shorthand implicit conversions. + + private given Conversion[String, Expr.Ref] with + def apply(name: String): Expr.Ref = Expr.Ref(name) + + private given Conversion[Var, Expr.Ref] with + def apply(nme: Var): Expr.Ref = Expr.Ref(nme.name) + + private given Conversion[TypeName, Expr.Ref] with + def apply(nme: TypeName): Expr.Ref = Expr.Ref(nme.name) + + private given Conversion[TypeDefKind, TypeDeclKind] with + import mlscript.{Als, Cls, Trt} + def apply(kind: TypeDefKind): TypeDeclKind = kind match + case Als => TypeDeclKind.Alias + case Cls => TypeDeclKind.Class + case Trt => TypeDeclKind.Trait + +object Monomorph: + class SpecializationMap[T <: Item](val prototype: T): + private var basePrototype: Option[T] = None + private val implementations = MutMap[String, T]() + + inline def getOrInsert(signature: String, op: => T): T = + implementations.getOrElseUpdate(signature, op) + inline def size: Int = implementations.size + // signature + item + inline def +=(entry: (String, T)): T = + implementations.addOne(entry) + entry._2 + inline def base: Option[T] = basePrototype + inline def base_=(op: => T): Unit = + basePrototype match + case None => basePrototype = Some(op) + case Some(_) => () + inline def isEmpty: Boolean = implementations.isEmpty + inline def iterator: Iterator[T] = + if implementations.isEmpty then Iterator.empty else + basePrototype.iterator.concat(implementations.values) \ No newline at end of file diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/MonomorphContext.scala b/compiler/shared/main/scala/mlscript/compiler/mono/MonomorphContext.scala new file mode 100644 index 000000000..d73292633 --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/mono/MonomorphContext.scala @@ -0,0 +1,33 @@ +package mlscript.compiler.mono + +import mlscript.compiler.debug.DebugOutput +import scala.collection.immutable.SeqMap +import mlscript.compiler.debug.Printable +import mlscript.compiler.* + +class MonomorphContext(context: List[Map[String, DataType]]) extends Printable: + def +(entry: (String, DataType)): MonomorphContext = + MonomorphContext(context match { + case Nil => Nil + case head :: tail => (head + entry) :: tail + }) + + def :+(entry: (String, DataType)): MonomorphContext = + MonomorphContext((Map.empty + entry) :: context) + + def unary_+(): MonomorphContext = + MonomorphContext(Map.empty :: context) + + def get(key: String): Option[DataType] = + context.iterator.flatMap(_.get(key)).nextOption() + + def getDebugOutput: DebugOutput = + DebugOutput.Map(context.foldRight(SeqMap.empty[String, String]) { (entries, map) => + entries.foldLeft(map) { (map, entry) => + map + (entry._1 -> entry._2.toString) + } + }.toList) + + +object MonomorphContext: + def empty: MonomorphContext = MonomorphContext(Nil) \ No newline at end of file diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/MonomorphError.scala b/compiler/shared/main/scala/mlscript/compiler/mono/MonomorphError.scala new file mode 100644 index 000000000..e7ef0305e --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/mono/MonomorphError.scala @@ -0,0 +1,3 @@ +package mlscript.compiler.mono + +class MonomorphError(message: String) extends Error(message) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala new file mode 100644 index 000000000..185d52949 --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala @@ -0,0 +1,42 @@ +package mlscript.compiler.mono.specializer + +import mlscript.compiler.Expr +import mlscript.compiler.mono.MonomorphError + +object Builtin: + private val builtinBinaryOperations = Map[String, (Expr, Expr) => Option[Expr]]( + (">", { + case (Expr.Literal(lhs: BigInt), Expr.Literal(rhs: BigInt)) => + Some(Expr.Literal(lhs > rhs)) + case (Expr.Literal(lhs: BigDecimal), Expr.Literal(rhs: BigDecimal)) => + Some(Expr.Literal(lhs > rhs)) + case (_, _) => None + }), + ("-", { + case (Expr.Literal(lhs: BigInt), Expr.Literal(rhs: BigInt)) => + Some(Expr.Literal(lhs - rhs)) + case (Expr.Literal(lhs: BigDecimal), Expr.Literal(rhs: BigDecimal)) => + Some(Expr.Literal(lhs - rhs)) + case (_, _) => None + }), + ("+", { + case (Expr.Literal(lhs: BigInt), Expr.Literal(rhs: BigInt)) => + Some(Expr.Literal(lhs + rhs)) + case (Expr.Literal(lhs: BigDecimal), Expr.Literal(rhs: BigDecimal)) => + Some(Expr.Literal(lhs + rhs)) + case (_, _) => None + }), + ("*", { + case (Expr.Literal(lhs: BigInt), Expr.Literal(rhs: BigInt)) => + Some(Expr.Literal(lhs * rhs)) + case (Expr.Literal(lhs: BigDecimal), Expr.Literal(rhs: BigDecimal)) => + Some(Expr.Literal(lhs * rhs)) + case (_, _) => None + }) + ) + + def isBinaryOperator(name: String): Boolean = + builtinBinaryOperations.contains(name) + + def evalulateBinaryOperation(name: String, lhs: Expr, rhs: Expr): Option[Expr] = + builtinBinaryOperations(name)(lhs, rhs) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala new file mode 100644 index 000000000..566b150ff --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala @@ -0,0 +1,15 @@ +package mlscript.compiler.mono.specializer + +import mlscript.compiler.Expr +import mlscript.compiler.debug.{DebugOutput, Printable} +import scala.collection.immutable.HashMap + +class Context(private val entries: HashMap[String, Expr]) extends Printable: + def this(entries: IterableOnce[(String, Expr)]) = this(HashMap.from(entries)) + inline def get(name: String): Option[Expr] = entries.get(name) + inline def +(entry: (String, Expr)): Context = Context(entries + entry) + inline def isEmpty: Boolean = entries.isEmpty + def getDebugOutput: DebugOutput = + DebugOutput.Map(entries.iterator.map { + (key, value) => (key, value.toString) + }.toList) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Predicates.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Predicates.scala new file mode 100644 index 000000000..80a75fa1a --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Predicates.scala @@ -0,0 +1,6 @@ +package mlscript.compiler.mono.specializer + +import mlscript.compiler.Expr + +object Predicates: + \ No newline at end of file diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala new file mode 100644 index 000000000..bfe09610a --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala @@ -0,0 +1,5 @@ +package mlscript.compiler.mono.specializer + +import mlscript.compiler.debug.Debug + +class Specializer(using debug: Debug) diff --git a/compiler/shared/main/scala/mlscript/compiler/printer/ExprPrinter.scala b/compiler/shared/main/scala/mlscript/compiler/printer/ExprPrinter.scala new file mode 100644 index 000000000..eddf97cd9 --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/printer/ExprPrinter.scala @@ -0,0 +1,110 @@ +package mlscript.compiler.printer + +import mlscript.compiler.{Expr, Isolation, Item, Module, Parameter} + +class ExprPrinter: + private val printer = BlockPrinter() + + import printer.{endLine, enter, leave, print} + + private def show(module: Module): Unit = module.items.foreach { + case expr: Expr => show(expr) + case item: Item => show(item) + } + + private def show(params: List[Parameter]): String = + params.iterator.map { + case (spec, Expr.Ref(name)) => (if spec then "#" else "") + name + }.mkString("(", ", ", ")") + + private def show(item: Item): Unit = item match + case Item.TypeDecl(Expr.Ref(name), kind, typeParams, params, parents, body) => + val typeParamsStr = if typeParams.isEmpty then "" + else typeParams.iterator.map(_.name).mkString("[", ", ", "]") + val reprParents = if parents.isEmpty then "" + else parents.iterator.map { case (parent, args) => + parent.show + args.iterator.mkString("(", ", ", ")") + }.mkString(": ", ", ", "") + print(s"$kind $name$typeParamsStr${show(params)}$reprParents ") + show(body) + case Item.FuncDecl(Expr.Ref(name), params, body) => + print(s"fun $name${show(params)} =") + enter() + show(body) + leave() + case Item.FuncDefn(Expr.Ref(name), typeParams, polyType) => + val reprTypeParams = if typeParams.isEmpty then "" else + s"${typeParams.mkString("[", ", ", "]")} => " + print(s"fun $name: $reprTypeParams${polyType.show}") + + private def show(isolation: Isolation): Unit = + enter("{", "}") + isolation.items.foreach { + case expr: Expr => show(expr) + case item: Item => show(item) + } + leave() + + private def show(expr: Expr) = + print(expr.toString) + endLine() + + def toLines: List[String] = printer.toLines + + override def toString(): String = printer.toString + + // private def show(expr: Expr): Unit = expr match + // case Expr.Ref(name) => name + // case Expr.Lambda(params, body) => + // val head = params.mkString("(", ", ", ")") + // s"(fun $head -> $body)" + // case Expr.Apply(Expr.Apply(Expr.Ref("."), lhs :: Nil), rhs :: Nil) => + // s"$lhs.$rhs" + // case Expr.Apply(Expr.Apply(Expr.Ref(op), lhs :: Nil), rhs :: Nil) + // if !op.headOption.forall(_.isLetter) => + // s"($lhs $op $rhs)" + // case Expr.Apply(callee, arguments) => + // val tail = arguments.mkString(", ") + // s"($callee $tail)" + // case Expr.Tuple(fields) => + // val inner = fields.mkString(", ") + // "(" + (if fields.length == 1 then inner + ", " else inner) + ")" + // case Expr.Record(fields) => + // "{" + fields.iterator.map { (name, value) => s"$name = $value" } + "}" + // case Expr.Select(receiver, field) => s"$receiver.$field" + // case Expr.LetIn(isRec, name, rhs, body) => s"let $name = $rhs in $body" + // case Expr.Block(items) => items.mkString(";") + // case Expr.As(value, toType) => s"$value as $toType" + // case Expr.Assign(assignee, value) => s"$assignee = $value" + // case Expr.With(value, fields) => s"$value with $fields" + // case Expr.Subscript(receiver, index) => s"$receiver[$index]" + // case Expr.Match(scrutinee, branches) => + // s"$scrutinee match " + branches.iterator.mkString("{", "; ", "}") + // case Expr.Literal(value) => value.toString + // case Expr.New(Some((callee, args)), body) => + // s"new ${callee.name}" + args.mkString(" (", ", ", ") ") + body.toString + // case Expr.New(None, body) => "new " + body.toString + // case Expr.IfThenElse(condition, consequent, None) => + // s"if $condition then $consequent" + // case Expr.IfThenElse(condition, consequent, Some(alternate)) => + // s"if $condition then $consequent else $alternate" + // case Expr.Isolated(isolation) => s"{\n$isolation\n}" + +object ExprPrinter: + def print(node: Module | Item | Isolation | Expr): String = + val printer = ExprPrinter() + node match + case module: Module => printer.show(module) + case item: Item => printer.show(item) + case isolation: Isolation => printer.show(isolation) + case expr: Expr => printer.show(expr) + printer.toString + + def printLines(node: Module | Item | Isolation | Expr): List[String] = + val printer = ExprPrinter() + node match + case module: Module => printer.show(module) + case item: Item => printer.show(item) + case isolation: Isolation => printer.show(isolation) + case expr: Expr => printer.show(expr) + printer.toLines diff --git a/compiler/shared/main/scala/mlscript/compiler/syntax.scala b/compiler/shared/main/scala/mlscript/compiler/syntax.scala new file mode 100644 index 000000000..89d80f01a --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/syntax.scala @@ -0,0 +1,187 @@ +package mlscript.compiler + +import mlscript.compiler.debug.{DebugOutput, Printable} +import mlscript.compiler.printer.ExprPrinter +import scala.collection.mutable.ArrayBuffer +import mlscript.{Type, Union, Inter, Function, Record, Tuple, Recursive, AppliedType, + Neg, Rem, Bounds, WithExtension, Constrained, Top, Bot, Literal, + TypeName, TypeVar, PolyType, NamedType} +import scala.collection.immutable.HashMap + +enum Expr extends Printable: + case Ref(name: String) + case Lambda(params: List[Ref], body: Expr) + case Apply(callee: Expr, arguments: List[Expr]) + case Tuple(fields: List[Expr]) + case Record(fields: List[(Ref, Expr)]) + case Select(receiver: Expr, field: Ref) + case LetIn(isRec: Boolean, name: Ref, rhs: Expr, body: Expr) + case Block(items: List[Expr | Item.FuncDecl | Item.FuncDefn]) + case As(value: Expr, toType: Type) + case Assign(assignee: Expr, value: Expr) + case With(value: Expr, fields: Expr.Record) + case Subscript(receiver: Expr, index: Expr) + case Match(scrutinee: Expr, branches: ArrayBuffer[CaseBranch]) + case Literal(value: BigInt | BigDecimal | Boolean | String | UnitValue) + case New(apply: Option[(TypeName, List[Expr])], body: Isolation) + case IfThenElse(condition: Expr, consequent: Expr, alternate: Option[Expr]) + case Isolated(isolation: Isolation) + + def asBoolean(): Boolean = this match + case Literal(value: BigInt) => value != 0 + case Literal(value: BigDecimal) => value != 0 + case Literal(value: Boolean) => value + case Literal(value: String) => !value.isEmpty() + case Literal(_) => false + case _ => false + + def getDebugOutput: DebugOutput = + DebugOutput.Code(ExprPrinter.printLines(this)) + + override def toString(): String = this match + case Ref(name) => name + case Lambda(params, body) => + val head = params.mkString("(", ", ", ")") + s"(fun $head -> $body)" + case Apply(Apply(Ref(op), lhs :: Nil), rhs :: Nil) + if !op.headOption.forall(_.isLetter) => + s"($lhs $op $rhs)" + case Apply(callee, arguments) => + callee.toString + arguments.mkString("(", ", ", ")") + case Tuple(fields) => + val inner = fields.mkString(", ") + "(" + (if fields.length == 1 then inner + ", " else inner) + ")" + case Record(fields) => + "{" + fields.iterator.map { (name, value) => s"$name = $value" } + "}" + case Select(receiver, field) => s"$receiver.$field" + case LetIn(isRec, name, rhs, body) => s"let $name = $rhs in $body" + case Block(items) => items.mkString(";") + case As(value, toType) => s"$value as $toType" + case Assign(assignee, value) => s"$assignee = $value" + case With(value, fields) => s"$value with $fields" + case Subscript(receiver, index) => s"$receiver[$index]" + case Match(scrutinee, branches) => + s"$scrutinee match " + branches.iterator.mkString("{", "; ", "}") + case Literal(value) => value.toString + case New(Some((callee, args)), body) => + s"new ${callee.name}" + args.mkString(" (", ", ", ") ") + body.toString + case New(None, body) => "new " + body.toString + case IfThenElse(condition, consequent, None) => + s"if $condition then $consequent" + case IfThenElse(condition, consequent, Some(alternate)) => + s"if $condition then $consequent else $alternate" + case Isolated(isolation) => s"{\n$isolation\n}" +end Expr + +// This corresponds to `mlscript.UnitLit`. +enum UnitValue: + case Null, Undefined + + override def toString(): String = + this match + case Null => "null" + case Undefined => "()" // `()` is shorter than `undefined` + +enum CaseBranch: + val body: Expr + + case Instance(className: Expr.Ref, alias: Expr.Ref, body: Expr) + case Constant(literal: Expr.Literal, body: Expr) + case Wildcard(body: Expr) + + override def toString(): String = + this match + case Instance(Expr.Ref(className), Expr.Ref(alias), body) => + s"case $alias: $className => $body" + case Constant(literal, body) => s"case $literal => $body" + case Wildcard(body) => s"_ => $body" + +enum TypeDeclKind: + case Alias, Class, Trait + + override def toString(): String = this match + case Alias => "alias" + case Class => "class" + case Trait => "trait" + +/** + * Function parameters: `(specializable, name)`. + */ +type Parameter = (Boolean, Expr.Ref) + +enum Item extends Printable: + val name: Expr.Ref + + /** + * Type declarations: aliases, classes and traits. + */ + case TypeDecl(name: Expr.Ref, kind: TypeDeclKind, typeParams: List[TypeName], + params: List[Parameter], parents: List[(NamedType, List[Expr])], body: Isolation) + /** + * Function declaration (with implementation). + */ + case FuncDecl(name: Expr.Ref, params: List[Parameter], body: Expr) + /** + * Function definition (with definition) + */ + case FuncDefn(name: Expr.Ref, typeParams: List[TypeName], body: PolyType) + + override def toString(): String = this match + case TypeDecl(Expr.Ref(name), kind, typeParams, params, parents, body) => + val typeParamsStr = if typeParams.isEmpty then "" + else typeParams.iterator.map(_.name).mkString("[", ", ", "]") + val parentsStr = if parents.isEmpty then "" + else parents.mkString(" extends ", " with ", " ") + s"$kind $name$typeParamsStr$parentsStr { $body }" + case FuncDecl(Expr.Ref(name), params, body) => + val parameters = params.iterator.map { + case (spec, Expr.Ref(name)) => + (if spec then "#" else "") + name + }.mkString("(", ", ", ")") + s"fun $name$parameters = $body" + case FuncDefn(Expr.Ref(name), Nil, polyType) => + s"fun $name: $polyType" + case FuncDefn(Expr.Ref(name), typeParams, polyType) => + s"fun $name: ${typeParams.mkString("[", ", ", "]")} => $polyType" + + def getDebugOutput: DebugOutput = + DebugOutput.Code(ExprPrinter.printLines(this)) + +object Item: + /** + * A shorthand constructor for classes without type parameters and parents. + */ + def classDecl(name: String, params: List[Parameter], body: Isolation): Item.TypeDecl = + Item.TypeDecl(Expr.Ref(name), TypeDeclKind.Class, Nil, params, Nil, body) + +/** + * An `Isolation` is like a `TypingUnit` but without nested classes. + */ +class Isolation(val items: List[Expr | Item.FuncDecl | Item.FuncDefn]) extends Printable: + private val namedItemMap = HashMap.from(items.iterator.flatMap { + case _: Expr => None: Option[(String, Item.FuncDecl | Item.FuncDefn)] + case item: Item.FuncDecl => Some((item.name.name, item)) + case item: Item.FuncDefn => Some((item.name.name, item)) + }) + + def get(name: String): Option[Item.FuncDecl | Item.FuncDefn] = + namedItemMap.get(name) + + def getDebugOutput: DebugOutput = + DebugOutput.Code(ExprPrinter.printLines(this)) + + override def toString(): String = items.mkString("\n") + +object Isolation: + def empty = Isolation(Nil) + +/** + * A `Module` is like a `TypingUnit`. + * This name conflicts with `java.lang.Module`. + * TODO: Find a better name. + */ +class Module(val items: List[Expr | Item]) extends Printable: + def getDebugOutput: DebugOutput = + DebugOutput.Code(ExprPrinter.printLines(this)) + + override def toString(): String = items.mkString("\n") diff --git a/compiler/shared/test/diff/mono.mls b/compiler/shared/test/diff/mono.mls new file mode 100644 index 000000000..00bc53eb9 --- /dev/null +++ b/compiler/shared/test/diff/mono.mls @@ -0,0 +1,198 @@ +:NewParser +:ParseOnly +:mono +fun f(x) = if x then 42 else 1337 +//│ |#fun| |f|(|x|)| |#=| |#if| |x| |#then| |42| |#else| |1337| +//│ Parsed: {fun f = x, => if (x) then 42 else 1337} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), If((x) then 42, Some(IntLit(1337)))))) +//│ Lifted: +//│ TypingUnit {fun f = x, => if (x) then 42 else 1337} +//│ Mono: +//│ fun f(x) = +//│ if x then 42 else 1337 + +:mono +fun foo() = 42 +//│ |#fun| |foo|(||)| |#=| |42| +//│ Parsed: {fun foo = => 42} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(), IntLit(42)))) +//│ Lifted: +//│ TypingUnit {fun foo = => 42} +//│ Mono: +//│ fun foo() = +//│ 42 + +:mono +fun foo(x, #b) = if b then x else 1337 +let a = foo(42, true) +let b = foo(23, false) +//│ |#fun| |foo|(|x|,| |##|b|)| |#=| |#if| |b| |#then| |x| |#else| |1337|↵|#let| |a| |#=| |foo|(|42|,| |true|)|↵|#let| |b| |#=| |foo|(|23|,| |false|)| +//│ Parsed: {fun foo = x, #b, => if (b) then x else 1337; let a = foo (42, true,); let b = foo (23, false,)} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(x), _: Var(b)), If((b) then x, Some(IntLit(1337))))), NuFunDef(Some(false), a, [], App(Var(foo), Tup(_: IntLit(42), _: Var(true)))), NuFunDef(Some(false), b, [], App(Var(foo), Tup(_: IntLit(23), _: Var(false))))) +//│ Lifted: +//│ TypingUnit { +//│ fun foo = x, #b, => if (b) then x else 1337 +//│ let a = foo (42, true,) +//│ let b = foo (23, false,) +//│ } +//│ Mono: +//│ fun foo(x, #b) = +//│ if b then x else 1337 +//│ fun a() = +//│ foo__unknown(42) +//│ fun b() = +//│ foo__unknown(23) +//│ fun foo__unknown(x) = +//│ 1337 + +:mono +let x = 42 + 1337 +//│ |#let| |x| |#=| |42| |+| |1337| +//│ Parsed: {let x = + (42,) (1337,)} +//│ Parsed: +//│ TypingUnit(NuFunDef(Some(false), x, [], App(App(Var(+), Tup(_: IntLit(42))), Tup(_: IntLit(1337))))) +//│ Lifted: +//│ TypingUnit {let x = + (42,) (1337,)} +//│ Mono: +//│ fun x() = +//│ (42 + 1337) + +:mono +class Bar(#x) +fun foo(#b) = b +let a = foo(Bar(1)) +let b = foo(Bar(2)) +//│ |#class| |Bar|(|##|x|)|↵|#fun| |foo|(|##|b|)| |#=| |b|↵|#let| |a| |#=| |foo|(|Bar|(|1|)|)|↵|#let| |b| |#=| |foo|(|Bar|(|2|)|)| +//│ Parsed: {class Bar(#x,) {}; fun foo = #b, => b; let a = foo (Bar (1,),); let b = foo (Bar (2,),)} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, Bar, (), Tup(_: Var(x)), (), TypingUnit()), NuFunDef(None, foo, [], Lam(Tup(_: Var(b)), Var(b))), NuFunDef(Some(false), a, [], App(Var(foo), Tup(_: App(Var(Bar), Tup(_: IntLit(1)))))), NuFunDef(Some(false), b, [], App(Var(foo), Tup(_: App(Var(Bar), Tup(_: IntLit(2))))))) +//│ Lifted: +//│ TypingUnit { +//│ class Bar$1(#x,) {} +//│ fun foo = #b, => b +//│ let a = foo (Bar$1 (1,),) +//│ let b = foo (Bar$1 (2,),) +//│ } +//│ Mono: +//│ fun foo(#b) = +//│ b +//│ fun a() = +//│ foo__class Bar$1__1() +//│ fun b() = +//│ foo__class Bar$1__2() +//│ fun foo__class Bar$1__2() = +//│ Bar$1__2() +//│ fun foo__class Bar$1__1() = +//│ Bar$1__1() +//│ class Bar$1() { +//│ } +//│ class Bar$1__1(): Bar$1() { +//│ } +//│ class Bar$1__2(): Bar$1() { +//│ } + +:mono +fun fac(#n) = + if (n > 1) then fac(n - 1) * n else 1 +fac(10) +//│ |#fun| |fac|(|##|n|)| |#=| |→|#if| |(|n| |>| |1|)| |#then| |fac|(|n| |-| |1|)| |*| |n| |#else| |1|←|↵|fac|(|10|)| +//│ Parsed: {fun fac = #n, => {if ('(' > (n,) (1,), ')') then * (fac (- (n,) (1,),),) (n,) else 1}; fac (10,)} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, fac, [], Lam(Tup(_: Var(n)), Blk(...))), App(Var(fac), Tup(_: IntLit(10)))) +//│ Lifted: +//│ TypingUnit { +//│ fun fac = #n, => {if ('(' > (n,) (1,), ')') then * (fac (- (n,) (1,),),) (n,) else 1} +//│ Code(List(fac (10,))) +//│ } +//│ Mono: +//│ fun fac(#n) = +//│ if ((n > 1), ) then (fac((n - 1)) * n) else 1 +//│ fac__10() +//│ fun fac__10() = +//│ 1 + +:mono +trait AnyFoo { + fun bar(b: int): int +} +class FooPlus(#a: int): AnyFoo { + fun bar(b: int) = a + b +} +class FooMinus(#a: int): AnyFoo { + fun Bar(b: int) = a - b +} +fun f(x: AnyFoo) = x.bar(42) +f(FooPlus(1)) +f(FooMinus(2)) +//│ |#trait| |AnyFoo| |{|→|#fun| |bar|(|b|#:| |int|)|#:| |int|←|↵|}|↵|#class| |FooPlus|(|##|a|#:| |int|)|#:| |AnyFoo| |{|→|#fun| |bar|(|b|#:| |int|)| |#=| |a| |+| |b|←|↵|}|↵|#class| |FooMinus|(|##|a|#:| |int|)|#:| |AnyFoo| |{|→|#fun| |Bar|(|b|#:| |int|)| |#=| |a| |-| |b|←|↵|}|↵|#fun| |f|(|x|#:| |AnyFoo|)| |#=| |x|.bar|(|42|)|↵|f|(|FooPlus|(|1|)|)|↵|f|(|FooMinus|(|2|)|)| +//│ Parsed: {trait AnyFoo(): {fun bar: [] -> (b: int,) -> int}; class FooPlus(#a: int,): AnyFoo {fun bar = b: int, => + (a,) (b,)}; class FooMinus(#a: int,): AnyFoo {fun Bar = b: int, => - (a,) (b,)}; fun f = x: AnyFoo, => (x).bar (42,); f (FooPlus (1,),); f (FooMinus (2,),)} +//│ Parsed: +//│ TypingUnit(NuTypeDef(trait, AnyFoo, (), Tup(), (), TypingUnit(NuFunDef(None, bar, [], PolyType(List(),Function(Tuple(List((Some(b),Field(None,TypeName(int))))),TypeName(int)))))), NuTypeDef(class, FooPlus, (), Tup(a: Var(int)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(b: Var(int)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))))), NuTypeDef(class, FooMinus, (), Tup(a: Var(int)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, Bar, [], Lam(Tup(b: Var(int)), App(App(Var(-), Tup(_: Var(a))), Tup(_: Var(b))))))), NuFunDef(None, f, [], Lam(Tup(x: Var(AnyFoo)), App(Sel(Var(x), bar), Tup(_: IntLit(42))))), App(Var(f), Tup(_: App(Var(FooPlus), Tup(_: IntLit(1))))), App(Var(f), Tup(_: App(Var(FooMinus), Tup(_: IntLit(2)))))) +//│ Lifted: +//│ TypingUnit { +//│ trait AnyFoo$1() {fun bar = (b: int,) -> int} +//│ class FooPlus$2(#a: int,): AnyFoo$1 () {fun bar = b: int, => + ((this).a,) (b,)} +//│ class FooMinus$3(#a: int,): AnyFoo$1 () {fun Bar = b: int, => - ((this).a,) (b,)} +//│ fun f = x: AnyFoo$1, => (x).bar (42,) +//│ Code(List(f (FooPlus$2 (1,),))) +//│ Code(List(f (FooMinus$3 (2,),))) +//│ } +//│ Mono: +//│ fun f(AnyFoo$1) = +//│ x.bar(42) +//│ f(FooPlus$2__1()) +//│ f(FooMinus$3__2()) +//│ class FooPlus$2() { +//│ } +//│ class FooPlus$2__1(): FooPlus$2() { +//│ fun bar(int) = +//│ (this.a + b) +//│ } +//│ class FooMinus$3() { +//│ } +//│ class FooMinus$3__2(): FooMinus$3() { +//│ fun Bar(int) = +//│ (this.a - b) +//│ } + +:mono +class Bar(x: int) { + fun FooMinus(y: int) = x + y + fun car = foo(2) +} +class Car { + fun da(b: Bar) = b.foo(2) +} +fun baz(b: Bar) = b.foo(2) +let bar = Bar(42) +baz(bar) +Car().da(Bar(1337)) +bar.car +//│ |#class| |Bar|(|x|#:| |int|)| |{|→|#fun| |FooMinus|(|y|#:| |int|)| |#=| |x| |+| |y|↵|#fun| |car| |#=| |foo|(|2|)|←|↵|}|↵|#class| |Car| |{|→|#fun| |da|(|b|#:| |Bar|)| |#=| |b|.foo|(|2|)|←|↵|}|↵|#fun| |baz|(|b|#:| |Bar|)| |#=| |b|.foo|(|2|)|↵|#let| |bar| |#=| |Bar|(|42|)|↵|baz|(|bar|)|↵|Car|(||)|.da|(|Bar|(|1337|)|)|↵|bar|.car| +//│ Parsed: {class Bar(x: int,) {fun FooMinus = y: int, => + (x,) (y,); fun car = foo (2,)}; class Car() {fun da = b: Bar, => (b).foo (2,)}; fun baz = b: Bar, => (b).foo (2,); let bar = Bar (42,); baz (bar,); (Car ()).da (Bar (1337,),); (bar).car} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, Bar, (), Tup(x: Var(int)), (), TypingUnit(NuFunDef(None, FooMinus, [], Lam(Tup(y: Var(int)), App(App(Var(+), Tup(_: Var(x))), Tup(_: Var(y))))), NuFunDef(None, car, [], App(Var(foo), Tup(_: IntLit(2)))))), NuTypeDef(class, Car, (), Tup(), (), TypingUnit(NuFunDef(None, da, [], Lam(Tup(b: Var(Bar)), App(Sel(Var(b), foo), Tup(_: IntLit(2))))))), NuFunDef(None, baz, [], Lam(Tup(b: Var(Bar)), App(Sel(Var(b), foo), Tup(_: IntLit(2))))), NuFunDef(Some(false), bar, [], App(Var(Bar), Tup(_: IntLit(42)))), App(Var(baz), Tup(_: Var(bar))), App(Sel(App(Var(Car), Tup()), da), Tup(_: App(Var(Bar), Tup(_: IntLit(1337))))), Sel(Var(bar), car)) +//│ Lifted: +//│ TypingUnit { +//│ class Bar$1(x: int,) { +//│ fun FooMinus = y: int, => + ((this).x,) (y,) +//│ fun car = foo (2,) +//│ } +//│ class Car$2() {fun da = b: Bar$1, => (b).foo (2,)} +//│ fun baz = b: Bar$1, => (b).foo (2,) +//│ let bar = Bar$1 (42,) +//│ Code(List(baz (bar,))) +//│ Code(List((Car$2 ()).da (Bar$1 (1337,),))) +//│ Code(List((bar).car)) +//│ } +//│ Mono: +//│ fun baz(Bar$1) = +//│ b.foo(2) +//│ fun bar() = +//│ Bar$1(42) +//│ baz(bar) +//│ Car$2().da(Bar$1(1337)) +//│ bar.car diff --git a/compiler/shared/test/scala/mlscript/compiler/Test.scala b/compiler/shared/test/scala/mlscript/compiler/Test.scala index df325ec59..c8af030d6 100644 --- a/compiler/shared/test/scala/mlscript/compiler/Test.scala +++ b/compiler/shared/test/scala/mlscript/compiler/Test.scala @@ -1,10 +1,14 @@ -package mlscript -package compiler +package mlscript.compiler import mlscript.utils.shorthands.* import scala.util.control.NonFatal import scala.collection.mutable.StringBuilder import mlscript.codegen.Helpers.inspect as showStructure +import mlscript.{DiffTests, ModeType, TypingUnit} +import mlscript.compiler.debug.TreeDebug +import mlscript.compiler.mono.Monomorph +import mlscript.compiler.printer.ExprPrinter +import mlscript.compiler.mono.MonomorphError class DiffTestCompiler extends DiffTests { import DiffTestCompiler.* @@ -23,6 +27,17 @@ class DiffTestCompiler extends DiffTests { outputBuilder ++= "Lifting failed: " ++ err.toString() if mode.fullExceptionStack then outputBuilder ++= "\n" ++ err.getStackTrace().map(_.toString()).mkString("\n") + if(mode.mono){ + outputBuilder ++= "\nMono:\n" + val treeDebug = new TreeDebug() + try{ + val monomorph = new Monomorph(treeDebug) + val monomorphized = monomorph.monomorphize(rstUnit) + outputBuilder ++= ExprPrinter.print(monomorphized) + }catch{ + case error: MonomorphError => outputBuilder ++= (error.getMessage() :: error.getStackTrace().map(_.toString()).toList ++ treeDebug.getLines).mkString("\n") + } + } outputBuilder.toString().linesIterator.toList override protected lazy val files = allFiles.filter { file => diff --git a/shared/src/test/scala/mlscript/DiffTests.scala b/shared/src/test/scala/mlscript/DiffTests.scala index b63fbc4a2..d0b841a8e 100644 --- a/shared/src/test/scala/mlscript/DiffTests.scala +++ b/shared/src/test/scala/mlscript/DiffTests.scala @@ -42,6 +42,7 @@ abstract class ModeType { def expectCodeGenErrors: Bool def showRepl: Bool def allowEscape: Bool + def mono: Bool } class DiffTests @@ -153,20 +154,21 @@ class DiffTests expectCodeGenErrors: Bool = false, showRepl: Bool = false, allowEscape: Bool = false, + mono: Bool = false, // noProvs: Bool = false, ) extends ModeType { def isDebugging: Bool = dbg || dbgSimplif } val defaultMode = Mode() - var parseOnly = basePath.headOption.contains("parser") || basePath.headOption.contains("compiler") + var parseOnly = basePath.headOption.contains("parser") var allowTypeErrors = false var allowParseErrors = false // TODO use var showRelativeLineNums = false var noJavaScript = false var noProvs = false var allowRuntimeErrors = false - var newParser = basePath.headOption.contains("parser") || basePath.headOption.contains("compiler") + var newParser = basePath.headOption.contains("parser") val backend = new JSTestBackend() val host = ReplHost() @@ -206,6 +208,7 @@ class DiffTests case "re" => mode.copy(expectRuntimeErrors = true) case "ShowRepl" => mode.copy(showRepl = true) case "escape" => mode.copy(allowEscape = true) + case "mono" => {println("mono set"); mode.copy(mono = true)} case _ => failures += allLines.size - lines.size output("/!\\ Unrecognized option " + line) @@ -342,7 +345,7 @@ class DiffTests // try to parse block of text into mlscript ast val ans = try { - if (newParser || basePath.headOption.contains("compiler")) { + if (newParser) { val origin = Origin(testName, globalStartLineNum, fph) val lexer = new NewLexer(origin, raise, dbg = mode.dbgParsing) From 02db47d7b28e8b1172af649b184aed06d1ffd388 Mon Sep 17 00:00:00 2001 From: YKY Date: Sat, 10 Dec 2022 18:49:20 +0800 Subject: [PATCH 02/13] defunctionalizer prototype --- .../scala/mlscript/compiler/Helpers.scala | 117 ++ .../mlscript/compiler/mono/Monomorph.scala | 717 ++++++---- .../mono/specializer/BoundedExpr.scala | 249 ++++ .../compiler/mono/specializer/Builtin.scala | 36 + .../compiler/mono/specializer/Context.scala | 15 +- .../mono/specializer/Specializer.scala | 253 +++- .../scala/mlscript/compiler/mono/utils.scala | 3 + .../main/scala/mlscript/compiler/syntax.scala | 155 ++- compiler/shared/test/diff/mono.mls | 1178 +++++++++++++++-- .../test/scala/mlscript/compiler/Test.scala | 6 +- 10 files changed, 2308 insertions(+), 421 deletions(-) create mode 100644 compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala create mode 100644 compiler/shared/main/scala/mlscript/compiler/mono/utils.scala diff --git a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala index 764accf23..6d76551ed 100644 --- a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala +++ b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala @@ -6,6 +6,18 @@ import mlscript.{IfBody, IfThen, IfElse, IfLet, IfOpApp, IfOpsApp, IfBlock} import mlscript.UnitLit import mlscript.codegen.Helpers.inspect as showStructure import mlscript.compiler.mono.MonomorphError +import mlscript.NuTypeDef +import mlscript.NuFunDef +import scala.collection.mutable.ArrayBuffer +import mlscript.CaseBranches +import mlscript.Case +import mlscript.NoCases +import mlscript.Wildcard +import mlscript.DecLit +import mlscript.IntLit +import mlscript.StrLit +import mlscript.AppliedType +import mlscript.TypeName object Helpers: /** @@ -28,3 +40,108 @@ object Helpers: case Tup((_, Fld(_, _, UnitLit(true))) :: Nil) => Iterable.empty case Tup(fields) => fields.iterator.map(_._2.value) case _ => Some(term) + + def term2Expr(term: Term): Expr = { + term match + case Var(name) => Expr.Ref(name) + case Lam(lhs, rhs) => + val params = toFuncParams(lhs).toList + Expr.Lambda(params, term2Expr(rhs)) + case App(App(Var("=>"), Bra(false, args: Tup)), body) => + val params = toFuncParams(args).toList + Expr.Lambda(params, term2Expr(body)) + case App(App(Var("."), self), App(Var(method), args: Tup)) => + Expr.Apply(Expr.Select(term2Expr(self), Expr.Ref(method)), List.from(toFuncArgs(args).map(term2Expr))) + case App(lhs, rhs) => + val callee = term2Expr(lhs) + val arguments = toFuncArgs(rhs).map(term2Expr).toList + Expr.Apply(callee, arguments) + case Tup(fields) => + Expr.Tuple(fields.map { + case (_, Fld(mut, spec, value)) => term2Expr(value) + }) + case Rcd(fields) => + Expr.Record(fields.map { + case (name, Fld(mut, spec, value)) => (Expr.Ref(name.name), term2Expr(value)) + }) + case Sel(receiver, fieldName) => + Expr.Select(term2Expr(receiver), Expr.Ref(fieldName.name)) + case Let(rec, Var(name), rhs, body) => + val exprRhs = term2Expr(rhs) + val exprBody = term2Expr(body) + Expr.LetIn(rec, Expr.Ref(name), exprRhs, exprBody) + case Blk(stmts) => Expr.Block(stmts.flatMap[Expr | Item.FuncDecl | Item.FuncDefn] { + case term: Term => Some(term2Expr(term)) + case tyDef: NuTypeDef => ??? + case funDef: NuFunDef => + val NuFunDef(_, nme, targs, rhs) = funDef + val ret: Item.FuncDecl | Item.FuncDefn = rhs match + case Left(Lam(params, body)) => + Item.FuncDecl(Expr.Ref(nme.name), toFuncParams(params).toList, term2Expr(body)) + case Left(body: Term) => Item.FuncDecl(Expr.Ref(nme.name), Nil, term2Expr(body)) + case Right(polyType) => Item.FuncDefn(Expr.Ref(nme.name), targs, polyType) + Some(ret) + case mlscript.DataDefn(_) => throw MonomorphError("unsupported DataDefn") + case mlscript.DatatypeDefn(_, _) => throw MonomorphError("unsupported DatatypeDefn") + case mlscript.TypeDef(_, _, _, _, _, _, _) => throw MonomorphError("unsupported TypeDef") + case mlscript.Def(_, _, _, _) => throw MonomorphError("unsupported Def") + case mlscript.LetS(_, _, _) => throw MonomorphError("unsupported LetS") + }) + case Bra(rcd, term) => term2Expr(term) + case Asc(term, ty) => Expr.As(term2Expr(term), ty) + case _: Bind => throw MonomorphError("cannot monomorphize `Bind`") + case _: Test => throw MonomorphError("cannot monomorphize `Test`") + case With(term, Rcd(fields)) => + Expr.With(term2Expr(term), Expr.Record(fields.map { + case (name, Fld(mut, spec, value)) => (Expr.Ref(name.name), term2Expr(term)) + })) + case CaseOf(term, cases) => + def rec(bra: CaseBranches)(using buffer: ArrayBuffer[CaseBranch]): Unit = bra match + case Case(pat, body, rest) => + val newCase = pat match + case Var(name) => CaseBranch.Instance(Expr.Ref(name), Expr.Ref("_"), term2Expr(body)) + case DecLit(value) => CaseBranch.Constant(Expr.Literal(value), term2Expr(body)) + case IntLit(value) => CaseBranch.Constant(Expr.Literal(value), term2Expr(body)) + case StrLit(value) => CaseBranch.Constant(Expr.Literal(value), term2Expr(body)) + case UnitLit(undefinedOrNull) => CaseBranch.Constant(Expr.Literal(UnitValue.Undefined), term2Expr(body)) + buffer.addOne(newCase) + rec(rest) + case NoCases => () + case Wildcard(body) => + buffer.addOne(CaseBranch.Wildcard(term2Expr(body))) + val branchBuffer = ArrayBuffer[CaseBranch]() + rec(cases)(using branchBuffer) + Expr.Match(term2Expr(term), branchBuffer) + + case Subs(array, index) => + Expr.Subscript(term2Expr(array), term2Expr(index)) + case Assign(lhs, rhs) => + Expr.Assign(term2Expr(lhs), term2Expr(rhs)) + case New(None, body) => + ??? + case New(Some((constructor, args)), body) => + val typeName = constructor match + case AppliedType(TypeName(name), _) => name + case TypeName(name) => name + Expr.New(TypeName(typeName), toFuncArgs(args).map(term2Expr).toList) + // case Blk(unit) => Expr.Isolated(monomorphizeBody(TypingUnit(unit))) + case If(body, alternate) => body match + case IfThen(condition, consequent) => + Expr.IfThenElse( + term2Expr(condition), + term2Expr(consequent), + alternate.map(term2Expr) + ) + case term: IfElse => throw MonomorphError("unsupported IfElse") + case term: IfLet => throw MonomorphError("unsupported IfLet") + case term: IfOpApp => throw MonomorphError("unsupported IfOpApp") + case term: IfOpsApp => throw MonomorphError("unsupported IfOpsApp") + case term: IfBlock => throw MonomorphError("unsupported IfBlock") + case IntLit(value) => Expr.Literal(value) + case DecLit(value) => Expr.Literal(value) + case StrLit(value) => Expr.Literal(value) + case UnitLit(undefinedOrNull) => + Expr.Literal(if undefinedOrNull + then UnitValue.Undefined + else UnitValue.Null) + } diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala index b349593e1..c56dbbdf3 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala @@ -9,7 +9,7 @@ import mlscript.{IfThen, IfElse, IfLet, IfOpApp, IfOpsApp, IfBlock} import mlscript.{IntLit, DecLit, StrLit, UnitLit} import scala.collection.immutable.{HashMap} import scala.collection.mutable.{Map as MutMap, Set as MutSet} -import scala.collection.mutable.ArrayBuffer +import scala.collection.mutable.ListBuffer import mlscript.Cls import mlscript.CaseBranches import mlscript.TypeDefKind @@ -19,6 +19,8 @@ import mlscript.compiler.mono.specializer.Context import mlscript.compiler.* import mlscript.compiler.printer.ExprPrinter +import mlscript.compiler.mono.specializer.BoundedExpr +import mlscript.compiler.mono.specializer.{MonoValue, ObjectValue, UnknownValue, FunctionValue} class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: import Helpers._ @@ -27,12 +29,21 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: /** * Specialized implementations of function declarations. */ - private val funImpls = MutMap[String, (Item.FuncDecl, MutMap[String, Item.FuncDecl])]() - private def allFunImpls: IterableOnce[(Item.FuncDecl, Item.FuncDecl)] = - funImpls.iterator.flatMap { case (name, (protoFunc, implFunc)) => - implFunc.values.map((protoFunc, _)) - } + private val funImpls = MutMap[String, (Item.FuncDecl, MutMap[String, Item.FuncDecl], List[(BoundedExpr, Int)], BoundedExpr)]() + + private def getfunInfo(nm: String): String = + val info = funImpls.get(nm).get + s"$nm: (${info._3.mkString(" X ")}) -> ${info._4} @${funDependence.get(nm).get.mkString("{", ", ", "}")}" + + // private def allFunImpls: IterableOnce[(Item.FuncDecl, Item.FuncDecl)] = + // funImpls.iterator.flatMap { case (name, (protoFunc, implFunc, _, _)) => + // implFunc.values.map((protoFunc, _)) + // } + private val funDependence = MutMap[String, Set[String]]() + val evalQueue = MutSet[String]() + val evalCnt = MutMap[String, Int]() + /** * Specialized implementations of each type declarations. */ @@ -43,6 +54,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: */ private def addPrototypeTypeDecl(typeDecl: Item.TypeDecl) = tyImpls.addOne(typeDecl.name.name, SpecializationMap(typeDecl)) + allTypeImpls.addOne(typeDecl.name.name, typeDecl) /** * An iterator going through all type declarations. */ @@ -60,31 +72,79 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: def findClassByName(name: String): Option[mlscript.compiler.Item.TypeDecl] = allTypeImpls.get(name) + + val specializer = mono.specializer.Specializer(this)(using debug) + + def addNewFunction(func: Item.FuncDecl): Unit = { + funImpls.addOne(func.name.name, (func, MutMap(), func.params.map(_ => BoundedExpr()->0), BoundedExpr())) + funDependence.addOne(func.name.name, Set()) + } /** * This function monomorphizes the top-level `TypingUnit` into a `Module`. */ def monomorphize(tu: TypingUnit): Module = - debug.trace("MONO MODL", PrettyPrinter.show(tu)) { - mlscript.compiler.Module(tu.entities.iterator.flatMap[Expr | Item] { - case term: Term => - Some(monomorphizeTerm(term)(using MonomorphContext.empty)) - case tyDef: NuTypeDef => + // debug.trace("MONO MODL", PrettyPrinter.show(tu)) { + val exps = tu.entities.zipWithIndex.flatMap[Expr] { + case (term: Term, i) => + val exp = term2Expr(term) + val funcName = s"main$$$$$i" + val asFunc: Item.FuncDecl = Item.FuncDecl(Expr.Ref(funcName), Nil, exp) + addNewFunction(asFunc) + evalQueue.addOne(funcName) + Some(Expr.Apply(Expr.Ref(funcName), Nil)) + case (tyDef: NuTypeDef, _) => monomorphizeTypeDef(tyDef) None - case funDef: NuFunDef => + case (funDef: NuFunDef, _) => val funcItem = monomorphizeFunDef(funDef) funcItem match case funcDecl: Item.FuncDecl => - funImpls.addOne(funcDecl.name.name, (funcDecl, MutMap())) + addNewFunction(funcDecl) case _ => () - Some(funcItem) - }.concat(allFunImpls.map(_._2)) + None + }; + while(!evalQueue.isEmpty){ + val crt = evalQueue.head + evalQueue.remove(crt) + updateFunction(crt) + } + funImpls.mapValuesInPlace{ + case (_, (Item.FuncDecl(nm, as, body), mp, la, lr)) => + (Item.FuncDecl(nm, as, specializer.defunctionalize(body)), mp, la, lr) + } + val ret = mlscript.compiler.Module(exps.concat[Expr | Item](funImpls.map(x => x._2._1)) .concat(allTypeDecls) .concat(lamTyDefs.values) .concat(anonymTyDefs.values) .toList) - }(identity) + debug.log("") + debug.log("==============final function signatures==================") + funImpls.foreach( + (nm, info) => { + debug.log(s"$nm: (${info._3.map(_._1).mkString(" X ")}) -> ${info._4}") + // updateFunc(nm) + // debug.log("") + } + ) + + ret + // }() + + def updateFunction(crt: String): Unit = { + debug.log(s"evaluating $crt, rests: ${evalQueue}") + val cnt = evalCnt.get(crt).getOrElse(0) + if(cnt <= 20){ + evalCnt.update(crt, cnt+1) + debug.log("=" * 10 + s" updating $crt " + "=" * 10) + debug.log(getfunInfo(crt)) + updateFunc(crt) + debug.log(getfunInfo(crt)) + } + else{ + throw new MonomorphError("stack overflow!!!") + } + } /** * This function monomorphizes the nested `TypingUnit` into a `Isolation`. @@ -93,7 +153,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: debug.trace("MONO BODY", PrettyPrinter.show(body)) { Isolation(body.entities.flatMap[Expr | Item.FuncDecl | Item.FuncDefn] { case term: Term => - Some(monomorphizeTerm(term)(using MonomorphContext.empty)) + Some(term2Expr(term)) case tyDef: NuTypeDef => monomorphizeTypeDef(tyDef) None @@ -107,19 +167,19 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: * type definition. There is a simple class lifting here. */ private def monomorphizeTypeDef(tyDef: NuTypeDef): Item.TypeDecl = - debug.trace("MONO TDEF", PrettyPrinter.show(tyDef)) { + // debug.trace("MONO TDEF", PrettyPrinter.show(tyDef)) { /** * The recursive function doing the real work. * @param tyDef the type definition * @param namePath enclosing class names and this class name */ def rec(tyDef: NuTypeDef, namePath: List[String]): Item.TypeDecl = - debug.trace[Item.TypeDecl]("LIFT", PrettyPrinter.show(tyDef)) { + // debug.trace[Item.TypeDecl]("LIFT", PrettyPrinter.show(tyDef)) { val NuTypeDef(kind, _, tparams, params, parents, body) = tyDef val isolation = Isolation(body.entities.flatMap { // Question: Will there be pure terms in class body? case term: Term => - Some(monomorphizeTerm(term)(using MonomorphContext.empty)) + Some(term2Expr(term)) case subTypeDef: NuTypeDef => rec(subTypeDef, subTypeDef.nme.name :: namePath) None @@ -141,163 +201,218 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: ) addPrototypeTypeDecl(typeDecl) typeDecl - }() + // }() rec(tyDef, tyDef.nme.name :: Nil) - }(identity) + // }(identity) /** * This function monomorphizes a function definition in smoe typing units. * @param tyDecls the destination of nested type declarations */ private def monomorphizeFunDef(funDef: NuFunDef): Item.FuncDecl | Item.FuncDefn = - debug.trace[Item.FuncDecl | Item.FuncDefn]("MONO FUNC", PrettyPrinter.show(funDef)) { + // debug.trace[Item.FuncDecl | Item.FuncDefn]("MONO FUNC", PrettyPrinter.show(funDef)) { val NuFunDef(_, nme, targs, rhs) = funDef rhs match case Left(Lam(params, body)) => - Item.FuncDecl(nme, toFuncParams(params).toList, monomorphizeTerm(body)(using MonomorphContext.empty)) - case Left(body: Term) => Item.FuncDecl(nme, Nil, monomorphizeTerm(body)(using MonomorphContext.empty)) + Item.FuncDecl(nme, toFuncParams(params).toList, term2Expr(body)) + case Left(body: Term) => Item.FuncDecl(nme, Nil, term2Expr(body)) case Right(polyType) => Item.FuncDefn(nme, targs, polyType) - }(identity) + // }(identity) /** * This function monomophizes a `Term` into an `Expr`. */ - def monomorphizeTerm(term: Term)(using context: MonomorphContext): Expr = - debug.trace[Expr]("MONO " + term.getClass.getSimpleName.toUpperCase, PrettyPrinter.show(term)) { - term match - case Var(name) => Expr.Ref(name) - case Lam(lhs, rhs) => monomorphizeLambda(lhs, rhs) - case App(App(Var("=>"), Bra(false, args: Tup)), body) => - monomorphizeLambda(args, body) - case App(App(Var("."), self), App(Var(method), args: Tup)) => - debug.log(s"meet a member method invocation") - Expr.Apply(Expr.Select(monomorphizeTerm(self), method), List.from(toFuncArgs(args).map(monomorphizeTerm))) - case App(lhs, rhs) => - debug.log("Monomorphizing the callee...") - val callee = monomorphizeTerm(lhs) - debug.log("Monomorphizing arguments...") - val arguments = toFuncArgs(rhs).map(monomorphizeTerm).toList - debug.log("Specializing the invocation...") - callee match - case Expr.Ref(name) => - specializeCall(name, arguments).fold(Expr.Apply(callee, arguments))(identity) - case _ => Expr.Apply(callee, arguments) - case Tup(fields) => - Expr.Tuple(fields.map { - case (_, Fld(mut, spec, value)) => monomorphizeTerm(value) - }) - case Rcd(fields) => - Expr.Record(fields.map { - case (name, Fld(mut, spec, value)) => (name, monomorphizeTerm(value)) - }) - case Sel(receiver, fieldName) => - Expr.Select(monomorphizeTerm(receiver), fieldName) - case Let(true, Var(name), rhs, body) => - val exprRhs = monomorphizeTerm(rhs)(using context + (name, DataType.Unknown)) - val exprBody = monomorphizeTerm(body)(using context + (name, infer(exprRhs, None))) - Expr.LetIn(true, name, exprRhs, exprBody) - case Let(false, Var(name), rhs, body) => - val exprRhs = monomorphizeTerm(rhs) - val exprBody = monomorphizeTerm(body)(using context + (name, infer(exprRhs, None))) - Expr.LetIn(false, name, exprRhs, exprBody) - case Blk(stmts) => Expr.Block(stmts.flatMap[Expr | Item.FuncDecl | Item.FuncDefn] { - case term: Term => Some(monomorphizeTerm(term)) - case tyDef: NuTypeDef => - monomorphizeTypeDef(tyDef) - None - case funDef: NuFunDef => Some(monomorphizeFunDef(funDef)) - case mlscript.DataDefn(_) => throw MonomorphError("unsupported DataDefn") - case mlscript.DatatypeDefn(_, _) => throw MonomorphError("unsupported DatatypeDefn") - case mlscript.TypeDef(_, _, _, _, _, _, _) => throw MonomorphError("unsupported TypeDef") - case mlscript.Def(_, _, _, _) => throw MonomorphError("unsupported Def") - case mlscript.LetS(_, _, _) => throw MonomorphError("unsupported LetS") - }) - case Bra(rcd, term) => monomorphizeTerm(term) - case Asc(term, ty) => Expr.As(monomorphizeTerm(term), ty) - case _: Bind => throw MonomorphError("cannot monomorphize `Bind`") - case _: Test => throw MonomorphError("cannot monomorphize `Test`") - case With(term, Rcd(fields)) => - Expr.With(monomorphizeTerm(term), Expr.Record(fields.map { - case (name, Fld(mut, spec, value)) => (name, monomorphizeTerm(term)) - })) - case CaseOf(term, cases) => ??? - case Subs(array, index) => - Expr.Subscript(monomorphizeTerm(array), monomorphizeTerm(index)) - case Assign(lhs, rhs) => - Expr.Assign(monomorphizeTerm(lhs), monomorphizeTerm(rhs)) - case New(None, body) => - val className = s"Anonym_${anonymTyDefs.size}" - val classDecl = Item.classDecl(className, Nil, monomorphizeBody(body)) - Expr.Apply(className, Nil) - case New(Some((constructor, args)), body) => - val typeName = constructor match - case AppliedType(TypeName(name), _) => name - case TypeName(name) => name - monomorphizeNew(typeName, toFuncArgs(args).toList, body) - // case Blk(unit) => Expr.Isolated(monomorphizeBody(TypingUnit(unit))) - case If(body, alternate) => body match - case IfThen(condition, consequent) => - Expr.IfThenElse( - monomorphizeTerm(condition), - monomorphizeTerm(consequent), - alternate.map(monomorphizeTerm) - ) - case term: IfElse => throw MonomorphError("unsupported IfElse") - case term: IfLet => throw MonomorphError("unsupported IfLet") - case term: IfOpApp => throw MonomorphError("unsupported IfOpApp") - case term: IfOpsApp => throw MonomorphError("unsupported IfOpsApp") - case term: IfBlock => throw MonomorphError("unsupported IfBlock") - case IntLit(value) => Expr.Literal(value) - case DecLit(value) => Expr.Literal(value) - case StrLit(value) => Expr.Literal(value) - case UnitLit(undefinedOrNull) => - Expr.Literal(if undefinedOrNull - then UnitValue.Undefined - else UnitValue.Null) - }(identity) + // def monomorphizeTerm(term: Term)(using context: MonomorphContext): Expr = + // debug.trace[Expr]("MONO " + term.getClass.getSimpleName.toUpperCase, PrettyPrinter.show(term)) { + // term match + // case Var(name) => Expr.Ref(name) + // case Lam(lhs, rhs) => monomorphizeLambda(lhs, rhs) + // case App(App(Var("=>"), Bra(false, args: Tup)), body) => + // monomorphizeLambda(args, body) + // case App(App(Var("."), self), App(Var(method), args: Tup)) => + // debug.log(s"meet a member method invocation") + // Expr.Apply(Expr.Select(monomorphizeTerm(self), method), List.from(toFuncArgs(args).map(monomorphizeTerm))) + // case App(lhs, rhs) => + // debug.log("Monomorphizing the callee...") + // val callee = monomorphizeTerm(lhs) + // debug.log("Monomorphizing arguments...") + // val arguments = toFuncArgs(rhs).map(monomorphizeTerm).toList + // debug.log("Specializing the invocation...") + // callee match + // case Expr.Ref(name) => + // specializeCall(name, arguments).fold(Expr.Apply(callee, arguments))(identity) + // case _ => Expr.Apply(callee, arguments) + // case Tup(fields) => + // Expr.Tuple(fields.map { + // case (_, Fld(mut, spec, value)) => monomorphizeTerm(value) + // }) + // case Rcd(fields) => + // Expr.Record(fields.map { + // case (name, Fld(mut, spec, value)) => (name, monomorphizeTerm(value)) + // }) + // case Sel(receiver, fieldName) => + // Expr.Select(monomorphizeTerm(receiver), fieldName) + // case Let(true, Var(name), rhs, body) => + // val exprRhs = monomorphizeTerm(rhs)(using context + (name, DataType.Unknown)) + // val exprBody = monomorphizeTerm(body)(using context + (name, infer(exprRhs, None))) + // Expr.LetIn(true, name, exprRhs, exprBody) + // case Let(false, Var(name), rhs, body) => + // val exprRhs = monomorphizeTerm(rhs) + // val exprBody = monomorphizeTerm(body)(using context + (name, infer(exprRhs, None))) + // Expr.LetIn(false, name, exprRhs, exprBody) + // case Blk(stmts) => Expr.Block(stmts.flatMap[Expr | Item.FuncDecl | Item.FuncDefn] { + // case term: Term => Some(monomorphizeTerm(term)) + // case tyDef: NuTypeDef => + // monomorphizeTypeDef(tyDef) + // None + // case funDef: NuFunDef => Some(monomorphizeFunDef(funDef)) + // case mlscript.DataDefn(_) => throw MonomorphError("unsupported DataDefn") + // case mlscript.DatatypeDefn(_, _) => throw MonomorphError("unsupported DatatypeDefn") + // case mlscript.TypeDef(_, _, _, _, _, _, _) => throw MonomorphError("unsupported TypeDef") + // case mlscript.Def(_, _, _, _) => throw MonomorphError("unsupported Def") + // case mlscript.LetS(_, _, _) => throw MonomorphError("unsupported LetS") + // }) + // case Bra(rcd, term) => monomorphizeTerm(term) + // case Asc(term, ty) => Expr.As(monomorphizeTerm(term), ty) + // case _: Bind => throw MonomorphError("cannot monomorphize `Bind`") + // case _: Test => throw MonomorphError("cannot monomorphize `Test`") + // case With(term, Rcd(fields)) => + // Expr.With(monomorphizeTerm(term), Expr.Record(fields.map { + // case (name, Fld(mut, spec, value)) => (name, monomorphizeTerm(term)) + // })) + // case CaseOf(term, cases) => ??? + // case Subs(array, index) => + // Expr.Subscript(monomorphizeTerm(array), monomorphizeTerm(index)) + // case Assign(lhs, rhs) => + // Expr.Assign(monomorphizeTerm(lhs), monomorphizeTerm(rhs)) + // case New(None, body) => + // val className = s"Anonym_${anonymTyDefs.size}" + // val classDecl = Item.classDecl(className, Nil, monomorphizeBody(body)) + // Expr.Apply(className, Nil) + // case New(Some((constructor, args)), body) => + // val typeName = constructor match + // case AppliedType(TypeName(name), _) => name + // case TypeName(name) => name + // monomorphizeNew(typeName, toFuncArgs(args).toList, body) + // // case Blk(unit) => Expr.Isolated(monomorphizeBody(TypingUnit(unit))) + // case If(body, alternate) => body match + // case IfThen(condition, consequent) => + // Expr.IfThenElse( + // monomorphizeTerm(condition), + // monomorphizeTerm(consequent), + // alternate.map(monomorphizeTerm) + // ) + // case term: IfElse => throw MonomorphError("unsupported IfElse") + // case term: IfLet => throw MonomorphError("unsupported IfLet") + // case term: IfOpApp => throw MonomorphError("unsupported IfOpApp") + // case term: IfOpsApp => throw MonomorphError("unsupported IfOpsApp") + // case term: IfBlock => throw MonomorphError("unsupported IfBlock") + // case IntLit(value) => Expr.Literal(value) + // case DecLit(value) => Expr.Literal(value) + // case StrLit(value) => Expr.Literal(value) + // case UnitLit(undefinedOrNull) => + // Expr.Literal(if undefinedOrNull + // then UnitValue.Undefined + // else UnitValue.Null) + // }(identity) - def monomorphizeLambda(args: Term, body: Term): Expr = - debug.trace("MONO LAMBDA", args.toString + " => " + body) { - val params = toFuncParams(args).toList - // TODO: Capture variables referenced in the lambda body. - // We should capture: closure variables and referenced type variables. - val className = s"Lambda_${lamTyDefs.size}" - val applyMethod: Item.FuncDecl = - Item.FuncDecl("apply", toFuncParams(args).toList, monomorphizeTerm(body)(using MonomorphContext.empty)) - val classBody = Isolation(applyMethod :: Nil) - val classDecl = Item.classDecl(className, Nil, classBody) - // Add to the global store. - lamTyDefs.addOne((className, classDecl)) - // Returns a class construction. - Expr.Apply(Expr.Ref(className), Nil) - }(identity) + // def monomorphizeLambda(args: Term, body: Term): Expr = + // debug.trace("MONO LAMBDA", args.toString + " => " + body) { + // val params = toFuncParams(args).toList + // // TODO: Capture variables referenced in the lambda body. + // // We should capture: closure variables and referenced type variables. + // val className = s"Lambda_${lamTyDefs.size}" + // val applyMethod: Item.FuncDecl = + // Item.FuncDecl("apply", toFuncParams(args).toList, term2Expr(body)(using MonomorphContext.empty)) + // val classBody = Isolation(applyMethod :: Nil) + // val classDecl = Item.classDecl(className, Nil, classBody) + // // Add to the global store. + // lamTyDefs.addOne((className, classDecl)) + // // Returns a class construction. + // Expr.Apply(Expr.Ref(className), Nil) + // }(identity) /** * `new C(...) { ... }` expressions are converted into * `{ class CImpl extends C(...) { ... }; CImpl() }`. * ~~This requires you to add a `LetClass` construct to `mlscript.Term`.~~ */ - def monomorphizeNew(name: String, termArgs: List[Term], termBody: TypingUnit): Expr.Apply = - debug.trace[Expr.Apply]("MONO NEW", { - name + termArgs.iterator.map(_.toString).mkString("(", ", ", ")") + - " with " + PrettyPrinter.show(termBody) - }) { - val args = termArgs.map(monomorphizeTerm(_)(using MonomorphContext.empty)) - val body = monomorphizeBody(termBody) - val specTypeDecl = specializeTypeDef(name, args, body) - Expr.Apply(specTypeDecl.name, Nil) - }(identity) + // def monomorphizeNew(name: String, termArgs: List[Term], termBody: TypingUnit): Expr.Apply = + // debug.trace[Expr.Apply]("MONO NEW", { + // name + termArgs.iterator.map(_.toString).mkString("(", ", ", ")") + + // " with " + PrettyPrinter.show(termBody) + // }) { + // val args = termArgs.map(term2Expr(_)(using MonomorphContext.empty)) + // val body = monomorphizeBody(termBody) + // val specTypeDecl = specializeTypeDef(name, args, body) + // Expr.Apply(specTypeDecl.name, Nil) + // }(identity) - def specializeCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = - debug.trace("SPEC CALL", name + args.mkString(" with (", ", ", ")")) { - if tyImpls.contains(name) then specializeClassCall(name, args) - else if funImpls.contains(name) then specializeFunctionCall(name, args) + // def specializeCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = + // debug.trace("SPEC CALL", name + args.mkString(" with (", ", ", ")")) { + // if tyImpls.contains(name) then specializeClassCall(name, args) + // else if funImpls.contains(name) then specializeFunctionCall(name, args) + // else { + // debug.log(s"Not found: $name") + // None + // } + // }() + + def monomorphizeCall(name: String, args: List[BoundedExpr])(using evalCtx: Context, callingStack: List[String]): BoundedExpr = { + debug.trace[BoundedExpr]("SPEC CALL", name + args.mkString(" with (", ", ", ")")) { + if(funImpls.contains(name)){ + val (funcdecl, mps, oldArgsWithCnt, oldVs) = funImpls.get(name).get + val (oldArgs, lastUpdateCnt) = oldArgsWithCnt.unzip + val old = funDependence.get(name).get + funDependence.update(name, old ++ callingStack.headOption) + // debug.log(s"adding dependence ${callingStack.headOption}") + val nArgs = (oldArgs zip args).map(_ ++ _) + debug.log(s"comparing ${oldArgsWithCnt.mkString("(", ", ", ")")} with ${nArgs.map(_.getDebugOutput).mkString("(", ", ", ")")}") + if(evalCnt.get(name).isEmpty || (oldArgs zip nArgs).find(x => x._1.compare(x._2)).isDefined || (oldArgs zip lastUpdateCnt).find(x => x._1.eleCnt > x._2).isDefined){ + funImpls.update(name, (funcdecl, mps, nArgs.map(x => (x, x.eleCnt)), oldVs)) + if(!evalQueue.contains(name)){ + if(evalCnt.get(name).isEmpty){ + debug.log(s"first time encounter $name") + updateFunction(name) + } + else{ + // val newA = (oldArgs zip nArgs).find(x => x._1.compare(x._2)).get + debug.log(s"find finer args") + evalQueue.add(name) + } + } + } + funImpls.get(name).get._4 + } else { - debug.log(s"Not found: $name") - None + debug.log("!!!!!!!") + debug.log(s"calling unknown function $name(${args.mkString(",")})") + debug.log(funImpls.keySet.toString()) + BoundedExpr(UnknownValue()) } - }() + }(identity) + } + + private def updateFunc(name: String): Unit = { + val (funcdecl, mps, args, _) = funImpls.get(name).get + val ctx = (funcdecl.params.map(_._2.name) zip args.unzip._1).toMap + val nBody = specializer.evaluate(funcdecl.body)(using Context()++ctx, List(funcdecl.name.name)) + val nVs = nBody.expValue + val oldVs = funImpls.get(name).get._4 + debug.log(s"comparing ${oldVs} with ${nVs}") + if(oldVs.compare(nVs)){ + debug.log(s"adding these funcs to queue: ${funDependence.get(name).get}") + funDependence.get(name).get.foreach(x => if !evalQueue.contains(x) then evalQueue.add(x)) + } + funImpls.updateWith(name)(_.map(x => { + val nFuncDecl: Item.FuncDecl = x._1.copy(body = nBody) + x._4 += nVs + (nFuncDecl, x._2, x._3, x._4) + })) + // funImpls.get(name).get._4 += nVs + // funImpls.update(name, funImpls.get(name).get.copy(_4 = nVs)) + } private def partitationArguments(name: String, params: List[Parameter], args: List[Expr]): (List[Expr], List[Expr]) = if (args.length != params.length) { @@ -319,146 +434,184 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: def specializeClassCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = debug.trace("SPEC CALL", "class " + name + args.mkString(" with (", ", ", ")")) { - import TypeDeclKind._ - tyImpls.get(name).flatMap { specClassMap => specClassMap.prototype match - case Item.TypeDecl(Expr.Ref(name), Class, typeParams, params, parents, body) => - val (staticArguments, dynamicArguments) = partitationArguments(name, params, args) - val (staticParameters, dynamicParameters) = params.partition(_._1) - if (staticArguments.isEmpty) { - None - } else { - val signature = generateSignature(staticArguments) - val specClassDecl = specClassMap.getOrInsert(signature, { - specClassMap.base = Item.TypeDecl( - Expr.Ref(name), // name - Class, // kind - typeParams, // typeParams - dynamicParameters, // params - Nil, // parents - Isolation.empty // body - ) - val values = params.iterator.zip(args).flatMap({ - case ((true, Expr.Ref(name)), value) => Some((name, value)) - case ((false, _), _) => None - }) - val typeImpl: Item.TypeDecl = Item.TypeDecl( - Expr.Ref(s"${name}" + signature), // name - Class, // kind - typeParams, // typeParams - dynamicParameters, // params - (TypeName(name), dynamicParameters.map(_._2)) :: Nil, // parents - specializeClass(specClassMap.prototype)(using Context(values)) // body - ) - allTypeImpls += (typeImpl.name.name -> typeImpl) - typeImpl - }) - Some(Expr.Apply(specClassDecl.name, dynamicArguments)) - } - case Item.TypeDecl(_, Trait, _, _, _, _) => - throw new MonomorphError(s"cannot specialize trait $name") - case Item.TypeDecl(_, Alias, _, _, _, _) => - throw new MonomorphError(s"cannot specialize type alias $name") - } + // import TypeDeclKind._ + // tyImpls.get(name).flatMap { specClassMap => specClassMap.prototype match + // case Item.TypeDecl(Expr.Ref(name), Class, typeParams, params, parents, body) => + // val (staticArguments, dynamicArguments) = partitationArguments(name, params, args) + // val (staticParameters, dynamicParameters) = params.partition(_._1) + // if (staticArguments.isEmpty) { + // None + // } else { + // val signature = generateSignature(staticArguments) + // val specClassDecl = specClassMap.getOrInsert(signature, { + // specClassMap.base = Item.TypeDecl( + // Expr.Ref(name), // name + // Class, // kind + // typeParams, // typeParams + // dynamicParameters, // params + // Nil, // parents + // Isolation.empty // body + // ) + // val values = params.iterator.zip(args).flatMap({ + // case ((true, Expr.Ref(name)), value) => Some((name, value)) + // case ((false, _), _) => None + // }) + // val typeImpl: Item.TypeDecl = Item.TypeDecl( + // Expr.Ref(s"${name}" + signature), // name + // Class, // kind + // typeParams, // typeParams + // dynamicParameters, // params + // (TypeName(name), dynamicParameters.map(_._2)) :: Nil, // parents + // specializeClass(specClassMap.prototype)(using Context(values)) // body + // ) + // allTypeImpls += (typeImpl.name.name -> typeImpl) + // typeImpl + // }) + // Some(Expr.Apply(specClassDecl.name, dynamicArguments)) + // } + // case Item.TypeDecl(_, Trait, _, _, _, _) => + // throw new MonomorphError(s"cannot specialize trait $name") + // case Item.TypeDecl(_, Alias, _, _, _, _) => + // throw new MonomorphError(s"cannot specialize type alias $name") + // } + ??? }(_.fold(Debug.noPostTrace)(identity)) + def specializeNew(name: String, args: List[BoundedExpr]): MonoValue = { + if(allTypeImpls.contains(name)){ + val tp = allTypeImpls.get(name).get + val ags = (tp.params.map(_._2.name) zip args) + ObjectValue(name, MutMap(ags: _*)) + } + else ??? + } + + def specializeSelect(obj: ObjectValue, field: String): MonoValue = { + if(allTypeImpls.contains(obj.name)){ + val tpDef = allTypeImpls.get(obj.name).get + val func = tpDef.body.items.flatMap{ + case funcDecl@Item.FuncDecl(Expr.Ref(nm), prms, bd) if nm.equals(field) => + Some(funcDecl) + case _ => None + }.headOption + if(func.isDefined){ + val Item.FuncDecl(nm, prms, bd) = func.get + val nFuncName = s"${nm.name}$$${obj.name}" + if(!funImpls.contains(nFuncName)){ + val nFunc: Item.FuncDecl = Item.FuncDecl(Expr.Ref(nFuncName), (false, Expr.Ref("this")) :: prms, bd) + addNewFunction(nFunc) + } + FunctionValue(nFuncName, prms.map(_._2.name), List("this" -> BoundedExpr(obj))) + } + else{ + ??? + } + } + else { + ??? + } + } + // TODO: Remove `Option[Expr]` by passing the callee. def specializeFunctionCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = debug.trace("SPEC CALL", "function " + name + args.mkString(" with (", ", ", ")")) { - funImpls.get(name).flatMap { case (Item.FuncDecl(ref, params, body), impls) => - val (staticArguments, dynamicArguments) = partitationArguments(name, params, args) - if (staticArguments.isEmpty) { - None - } else { - val signature = generateSignature(staticArguments) - val specFuncDecl = impls.get(signature).getOrElse[Item.FuncDecl] { - val values = params.iterator.zip(args).flatMap({ - case ((true, Expr.Ref(name)), value) => Some((name, value)) - case ((false, _), _) => None - }) - val specFuncBody = specializeExpr(body)(using Context(values)) - val staticParams = params.filter(!_._1) - val specFuncName = s"${name}" + signature - val funcDecl: Item.FuncDecl = Item.FuncDecl(specFuncName, staticParams, specFuncBody) - impls.addOne((specFuncName, funcDecl)) - funcDecl - } - Some(Expr.Apply(specFuncDecl.name, dynamicArguments)) - } - } + // funImpls.get(name).flatMap { case (Item.FuncDecl(ref, params, body), impls) => + // val (staticArguments, dynamicArguments) = partitationArguments(name, params, args) + // if (staticArguments.isEmpty) { + // None + // } else { + // val signature = generateSignature(staticArguments) + // val specFuncDecl = impls.get(signature).getOrElse[Item.FuncDecl] { + // val values = params.iterator.zip(args).flatMap({ + // case ((true, Expr.Ref(name)), value) => Some((name, value)) + // case ((false, _), _) => None + // }) + // val specFuncBody = specializeExpr(body)(using Context(values)) + // val staticParams = params.filter(!_._1) + // val specFuncName = s"${name}" + signature + // val funcDecl: Item.FuncDecl = Item.FuncDecl(specFuncName, staticParams, specFuncBody) + // impls.addOne((specFuncName, funcDecl)) + // funcDecl + // } + // Some(Expr.Apply(specFuncDecl.name, dynamicArguments)) + // } + // } + ??? }(_.fold(Debug.noPostTrace)(identity)) def specializeExpr(expr: Expr)(using ctx: Context, typeContext: MonomorphContext): Expr = debug.trace[Expr]("SPEC EXPR", expr, "in context", ctx) { - expr match - case Expr.Ref(name) => ctx.get(name) match - case Some(value) => value - case None => expr - case _: Expr.Lambda => expr - case Expr.Apply(Expr.Apply(ident @ Expr.Ref(name), lhsExpr :: Nil), rhsExpr :: Nil) - if Builtin.isBinaryOperator(name) => - val lhs = specializeExpr(lhsExpr) - val rhs = specializeExpr(rhsExpr) - Builtin.evalulateBinaryOperation(name, lhs, rhs) - .getOrElse(Expr.Apply(Expr.Apply(ident, lhs :: Nil), rhs :: Nil)) - case Expr.Apply(callee, arguments) => - val specCallee = specializeExpr(callee) - val specArgs = arguments.map(specializeExpr) - specCallee match - case Expr.Ref(name) => specializeCall(name, specArgs).getOrElse(expr) - case Expr.Lambda(params, body) => - // Same as `specializeFuncDecl` but I should extract some common stuffs. - ??? - case Expr.Select(receiver, Expr.Ref(fieldName)) => - infer(receiver, None) match - case DataType.Class(declaration) => declaration.body.get(fieldName) match - case Some(memberFuncDecl: Item.FuncDecl) => - // FIXME: the context should be from the class - val specFuncDecl = specializeFunction(memberFuncDecl) - val branches = ArrayBuffer[CaseBranch]() - val alias: Expr.Ref = Expr.Ref("alpha") // alpha conversion needed - branches += CaseBranch.Instance( - declaration.name, - alias, - Expr.Apply(Expr.Select(alias, specFuncDecl.name), specArgs) - ) - Expr.Match(receiver, branches) - case Some(memberFuncDefn: Item.FuncDefn) => - throw MonomorphError(s"class ${declaration.name.name}.$fieldName is not implemented") - case None => throw MonomorphError(s"class ${declaration.name.name} does not have $fieldName") - case other => throw MonomorphError(s"cannot select a non-class instance") - case other => throw MonomorphError(s"not a callable: $other") - case Expr.Tuple(elements) => Expr.Tuple(elements.map(specializeExpr)) - case Expr.Record(fields) => Expr.Record(fields.map { - case (key, value) => (key, specializeExpr(value)) - }) - case Expr.Select(receiver, field) => - // We can do more. - Expr.Select(specializeExpr(receiver), field) - case Expr.LetIn(true, name, Expr.Lambda(params, body), cont) => - // Create a callable entry in the context and recursively specialize - // the continuation. - throw MonomorphError(s"recursive local functions are not implemented") - case Expr.LetIn(true, _, _, _) => - throw MonomorphError(s"recursive non-function definition are not allowed") - case Expr.LetIn(false, Expr.Ref(name), rhs, body) => - val specRhs = specializeExpr(rhs) - specializeExpr(body)(using ctx + (name -> specRhs)) - case Expr.Block(items) => - val onlyExpressions = items.iterator.flatMap { - case expr: Expr => Some(expr) - case _ => None - } - onlyExpressions.map(specializeExpr).toList match - case Nil => Expr.Literal(UnitValue.Undefined) - case items => items.last - case expr: Expr.Literal => expr - case Expr.IfThenElse(condition, consequent, alternate) => - specializeExpr( - if specializeExpr(condition).asBoolean() - then consequent - else alternate.getOrElse(Expr.Literal(UnitValue.Undefined)) - ) - case _ => throw MonomorphError(s"unimplemented ${expr.getClass()}") + // expr match + // case Expr.Ref(name) => ctx.get(name) match + // case Some(value) => value + // case None => expr + // case _: Expr.Lambda => expr + // case Expr.Apply(Expr.Apply(ident @ Expr.Ref(name), lhsExpr :: Nil), rhsExpr :: Nil) + // if Builtin.isBinaryOperator(name) => + // val lhs = specializeExpr(lhsExpr) + // val rhs = specializeExpr(rhsExpr) + // Builtin.evalulateBinaryOperation(name, lhs, rhs) + // .getOrElse(Expr.Apply(Expr.Apply(ident, lhs :: Nil), rhs :: Nil)) + // case Expr.Apply(callee, arguments) => + // val specCallee = specializeExpr(callee) + // val specArgs = arguments.map(specializeExpr) + // specCallee match + // case Expr.Ref(name) => specializeCall(name, specArgs).getOrElse(expr) + // case Expr.Lambda(params, body) => + // // Same as `specializeFuncDecl` but I should extract some common stuffs. + // ??? + // case Expr.Select(receiver, Expr.Ref(fieldName)) => + // infer(receiver, None) match + // case DataType.Class(declaration) => declaration.body.get(fieldName) match + // case Some(memberFuncDecl: Item.FuncDecl) => + // // FIXME: the context should be from the class + // val specFuncDecl = specializeFunction(memberFuncDecl) + // val branches = ArrayBuffer[CaseBranch]() + // val alias: Expr.Ref = Expr.Ref("alpha") // alpha conversion needed + // branches += CaseBranch.Instance( + // declaration.name, + // alias, + // Expr.Apply(Expr.Select(alias, specFuncDecl.name), specArgs) + // ) + // Expr.Match(receiver, branches) + // case Some(memberFuncDefn: Item.FuncDefn) => + // throw MonomorphError(s"class ${declaration.name.name}.$fieldName is not implemented") + // case None => throw MonomorphError(s"class ${declaration.name.name} does not have $fieldName") + // case other => throw MonomorphError(s"cannot select a non-class instance") + // case other => throw MonomorphError(s"not a callable: $other") + // case Expr.Tuple(elements) => Expr.Tuple(elements.map(specializeExpr)) + // case Expr.Record(fields) => Expr.Record(fields.map { + // case (key, value) => (key, specializeExpr(value)) + // }) + // case Expr.Select(receiver, field) => + // // We can do more. + // Expr.Select(specializeExpr(receiver), field) + // case Expr.LetIn(true, name, Expr.Lambda(params, body), cont) => + // // Create a callable entry in the context and recursively specialize + // // the continuation. + // throw MonomorphError(s"recursive local functions are not implemented") + // case Expr.LetIn(true, _, _, _) => + // throw MonomorphError(s"recursive non-function definition are not allowed") + // case Expr.LetIn(false, Expr.Ref(name), rhs, body) => + // val specRhs = specializeExpr(rhs) + // specializeExpr(body)(using ctx + (name -> specRhs)) + // case Expr.Block(items) => + // val onlyExpressions = items.iterator.flatMap { + // case expr: Expr => Some(expr) + // case _ => None + // } + // onlyExpressions.map(specializeExpr).toList match + // case Nil => Expr.Literal(UnitValue.Undefined) + // case items => items.last + // case expr: Expr.Literal => expr + // case Expr.IfThenElse(condition, consequent, alternate) => + // specializeExpr( + // if specializeExpr(condition).asBoolean() + // then consequent + // else alternate.getOrElse(Expr.Literal(UnitValue.Undefined)) + // ) + // case _ => throw MonomorphError(s"unimplemented ${expr.getClass()}") + ??? }(identity) /** diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala new file mode 100644 index 000000000..3c5d1bc4c --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala @@ -0,0 +1,249 @@ +package mlscript.compiler.mono.specializer + +import mlscript.compiler.{Expr, UnitValue} +import mlscript.compiler.debug.Printable +import mlscript.compiler.debug.DebugOutput +import scala.collection.mutable.Map as MutMap +import scala.collection.mutable.Set as MutSet + +abstract class MonoValue { + def toBoundedExpr = BoundedExpr(this) + def toStringSafe(using Set[Int]) = this.toString() +} +case class ObjectValue(name: String, fields: MutMap[String, BoundedExpr]) extends MonoValue{ + override def toString(): String = fields.map(x => (s"${x._1}: ${x._2.toStringSafe}")).mkString(s"$name@{", ", ", "}") + override def toStringSafe(using Set[Int]): String = fields.map(x => (s"${x._1}: ${x._2.toStringSafe}")).mkString(s"$name@{", ", ", "}") + def merge(other: ObjectValue)(using inStackExps: Set[Int]): ObjectValue = { + val allKeys = fields.keySet + val nFlds = allKeys.map(k => { + val s1 = fields.get(k).get + val s2 = other.fields.get(k).get + if(inStackExps.contains(s1.hashCode()) && inStackExps.contains(s2.hashCode())) + (k -> s1) + else (k -> (s1 ++ s2)) + }) + ObjectValue(name, MutMap(nFlds.toSeq: _*)) + } + def mergeMut(other: ObjectValue)(using inStackExps: Set[Int]): Boolean = { + val retVals = other.fields.map[Boolean]((k, s2) => { + val s1 = fields.get(k).get + if(!inStackExps.contains(s1.hashCode()) || !inStackExps.contains(s2.hashCode())){ + if(inStackExps.contains(s1.hashCode())){ + val tmp = BoundedExpr() + s1.values.foreach(tmp.values.addOne(_)) + val ret = tmp += s2 + fields.update(k, tmp) + ret + } + else + s1 += s2 + } + else false + }) + retVals.fold(false)(_ || _) + } + override def equals(x: Any): Boolean = { + x match { + case ObjectValue(xName, _) => name.equals(xName) + case _ => false + } + } +} +case class FunctionValue(name: String, prm: List[String], ctx: List[(String, BoundedExpr)]) extends MonoValue{ + override def toString(): String = prm.mkString(s"$name(", ", ", ")") + ctx.map(x => (s"${x._1}: ${x._2.toStringSafe}")).mkString(" given {", ", ", "}") + override def toStringSafe(using Set[Int]): String = prm.mkString(s"$name(", ", ", ")") + ctx.map(x => (s"${x._1}: ${x._2.toStringSafe}")).mkString(" given {", ", ", "}") + override def equals(x: Any): Boolean = x match{ + case FunctionValue(xName, _, _) => name.equals(xName) + case _ => false + } +} +case class UnknownValue() extends MonoValue{ + val idValue = UnknownValue.refresh() + override def toString(): String = s"?$idValue?" +} +object UnknownValue{ + var unknownCnt: Int = 0 + def refresh() = { + unknownCnt += 1 + unknownCnt + } +} +case class LiteralValue(i: BigInt | BigDecimal | Boolean | String | UnitValue) extends MonoValue{ + def asBoolean(): Option[Boolean] = i match{ + case x: Boolean => Some(x) + case _ => None + } + override def toString(): String = i.toString() +} +case class PrimitiveValue() extends MonoValue{ + override def toString(): String = "*LIT*" +} + +class BoundedExpr(val values: MutSet[MonoValue]) extends Printable { + def this(singleVal: MonoValue) = this(MutSet(singleVal)) + def this() = this(MutSet()) + def this(vs: Set[MonoValue]) = this(MutSet(vs.toSeq: _*)) + def getDebugOutput: DebugOutput = DebugOutput.Plain(toStringSafe) + def getObjNames() = values.flatMap{ + // case FunctionValue(name, body, prm, ctx) => Some(name) + case ObjectValue(name, _) => Some(name) + case _ => None + }.toSet + override def hashCode(): Int = values.hashCode() + override def toString(): String = toStringSafe + var updateCnt: Int = 0 + def toStringSafe(using printed: Set[Int] = Set()): String = { + if(printed.contains(this.hashCode())) s"***" + else values.map(_.toStringSafe(using printed + this.hashCode())).mkString("[", " | ", s"]") + } + def asValue: Option[MonoValue] = { + if(values.size == 1) { + Some(values.head) + } + else None + } + // def crossList(other: Set[List[MonoValue]]): Set[List[MonoValue]] = { + // for{ + // x <- values; + // y <- other + // } yield x :: y + // } + // def crossP[A](other: Set[A]): Set[(MonoValue, A)] = { + // for{ + // x <- values; + // y <- other + // } yield (x, y) + // } + + private def split(vs: Set[MonoValue], nms: Set[String]): (Set[MonoValue], Map[String, ObjectValue]) = { + val ret = vs.map{ + case o@ObjectValue(name, fields) => + if nms.contains(name) then { + (None, Some(name -> o)) + } else { + (Some(o), None) + } + case x => (Some(x), None) + }.unzip + val ret1 = ret._1.flatten + val ret2 = ret._2.flatten.toMap + (ret1, ret2) + } + + def ++(other: BoundedExpr)(using instackExps: Set[Int] = Set()): BoundedExpr = { + if(this == other) this + else { + val mergingValNms = getObjNames().intersect(other.getObjNames()) + val (restVals1, mergingVals1) = split(values.toSet, mergingValNms) + val (restVals2, mergingVals2) = split(other.values.toSet, mergingValNms) + // val map2 = other.values.flatMap(x => if(values.fin(x)) then None else Some(x)) + val ret = mergingValNms.map(nm => (mergingVals1.get(nm), mergingVals2.get(nm)) match + case (Some(x1: ObjectValue), Some(x2: ObjectValue)) => x1.merge(x2)(using instackExps ++ Set(this.hashCode(), other.hashCode())) + case _ => ??? + ) + // println(s"get ${BoundedExpr(restVals1 ++ restVals2 ++ ret)}") + var ret2 = restVals1 ++ restVals2 + if(ret2.count(x => (x.isInstanceOf[LiteralValue] || x.isInstanceOf[PrimitiveValue])) > 1){ + ret2 = ret2.filterNot(_.isInstanceOf[LiteralValue]) + PrimitiveValue() + } + val retVals = BoundedExpr(MutSet((ret2 ++ ret).toSeq: _*)) + retVals.updateCnt = this.updateCnt + if(this.compare(retVals)) retVals.updateCnt += 1 + retVals + } + } + + def +=(other: BoundedExpr)(using instackExps: Set[Int] = Set()): Boolean = { + val retVal = if(other != this) { + val mergingValNms = getObjNames().intersect(other.getObjNames()).toSet + val (_, mergingVals) = split(values.toSet, mergingValNms) + var litCount = values.find(x => (x.isInstanceOf[LiteralValue] || x.isInstanceOf[PrimitiveValue])) + val ret = other.values.map{ + case i: (LiteralValue | PrimitiveValue) => + if(litCount.isEmpty) { + values.add(i) + true + } + else if(!litCount.get.isInstanceOf[PrimitiveValue]) { + values.remove(litCount.get) + values.add(PrimitiveValue()) + litCount = Some(PrimitiveValue()) + true + } + else false + case o@ObjectValue(name, fields) => + mergingVals.get(name).fold[Boolean]{ + values.add(o) + true + }(v => { + v.mergeMut(o)(using instackExps ++ Set(this.hashCode(), other.hashCode())) + }) + case other => { + values.add(other) + true + } + } + ret.fold(false)(_ || _) + } + else false + if(retVal) updateCnt += 1 + retVal + } + + def size = values.size + // lazy val eleCnt: Int = countEles + def eleCnt(using objCallingStack: Set[String] = Set()): Int = { + if(values.size == 0) { + 0 + } + else { + val seperated = values.map{ + case o: ObjectValue => (None, Some(o)) + case f: FunctionValue => (Some(1), None) + case _: LiteralValue => (Some(1), None) + case _: PrimitiveValue => (Some(100000), None) + case UnknownValue() => (Some(1), None) + }.unzip + val (lits, objs) = (seperated._1.flatten, seperated._2.flatten) + val objn = objs.map{ + case ObjectValue(name, fields) => + if(objCallingStack.contains(name)) 1 + else { + fields.map(x => x._2.eleCnt(using objCallingStack + name)).fold(0)(_ + _) + 1 + } + }.fold(0)(_ + _) + lits.fold(0)(_ + _) + objn + } + } + def compare(other: BoundedExpr)(using instackExps: Set[Int] = Set()): Boolean = { + if(instackExps.contains(this.hashCode()) && instackExps.contains(other.hashCode())) + false + else if(values.find(_.isInstanceOf[PrimitiveValue]).isEmpty && other.values.find(_.isInstanceOf[PrimitiveValue]).isDefined) + true + else if(this.size != other.size) + this.size < other.size + else{ + val nms1 = this.getObjNames() + val nms2 = other.getObjNames() + if(nms1.equals(nms2)){ + val (rests1, objs1) = split(this.values.toSet, nms1) + val (rests2, objs2) = split(other.values.toSet, nms1) + nms1.find(nm => { + val v1s = objs1.get(nm).get.fields + val v2s = objs2.get(nm).get.fields + v1s.keySet.find(k => v1s.get(k).get.compare(v2s.get(k).get)(using instackExps + this.hashCode() + other.hashCode())).isDefined + }).isDefined + } + else true + } + // (values.find(_.isInstanceOf[UnknownValue]), other.values.find(_.isInstanceOf[UnknownValue])) match{ + // // case (Some(_), None) => true + // // case (None, Some(_)) => false + // } + } +} + +// given Conversion[MutSet[? <: MonoValue], BoundedExpr] with +// def apply(x: MutSet[? <: MonoValue]): BoundedExpr = BoundedExpr(x) +// given Conversion[BoundedExpr, MutSet[? <: MonoValue]] with +// def apply(x: BoundedExpr): MutSet[? <: MonoValue] = x.values \ No newline at end of file diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala index 185d52949..1f180973d 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala @@ -4,6 +4,8 @@ import mlscript.compiler.Expr import mlscript.compiler.mono.MonomorphError object Builtin: + val builtinRefs = Set(">", "-", "+", "*", "true", "false") + private val builtinBinaryOperations = Map[String, (Expr, Expr) => Option[Expr]]( (">", { case (Expr.Literal(lhs: BigInt), Expr.Literal(rhs: BigInt)) => @@ -35,8 +37,42 @@ object Builtin: }) ) + private val builtinBinaryOperationsValue = Map[String, (MonoValue, MonoValue) => Option[MonoValue]]( + (">", { + case (LiteralValue(lhs: BigInt), LiteralValue(rhs: BigInt)) => + Some(LiteralValue(lhs > rhs)) + case (LiteralValue(lhs: BigDecimal), LiteralValue(rhs: BigDecimal)) => + Some(LiteralValue(lhs > rhs)) + case (_, _) => None + }), + ("-", { + case (LiteralValue(lhs: BigInt), LiteralValue(rhs: BigInt)) => + Some(LiteralValue(lhs - rhs)) + case (LiteralValue(lhs: BigDecimal), LiteralValue(rhs: BigDecimal)) => + Some(LiteralValue(lhs - rhs)) + case (_, _) => None + }), + ("+", { + case (LiteralValue(lhs: BigInt), LiteralValue(rhs: BigInt)) => + Some(LiteralValue(lhs + rhs)) + case (LiteralValue(lhs: BigDecimal), LiteralValue(rhs: BigDecimal)) => + Some(LiteralValue(lhs + rhs)) + case (_, _) => None + }), + ("*", { + case (LiteralValue(lhs: BigInt), LiteralValue(rhs: BigInt)) => + Some(LiteralValue(lhs * rhs)) + case (LiteralValue(lhs: BigDecimal), LiteralValue(rhs: BigDecimal)) => + Some(LiteralValue(lhs * rhs)) + case (_, _) => None + }) + ) + def isBinaryOperator(name: String): Boolean = builtinBinaryOperations.contains(name) def evalulateBinaryOperation(name: String, lhs: Expr, rhs: Expr): Option[Expr] = builtinBinaryOperations(name)(lhs, rhs) + + def evaluateBinaryOpValue(name: String, lhs: MonoValue, rhs: MonoValue): Option[MonoValue] = + builtinBinaryOperationsValue(name)(lhs, rhs) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala index 566b150ff..a7e3b4afb 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala @@ -2,14 +2,19 @@ package mlscript.compiler.mono.specializer import mlscript.compiler.Expr import mlscript.compiler.debug.{DebugOutput, Printable} -import scala.collection.immutable.HashMap +import mlscript.compiler.mono.specializer.BoundedExpr -class Context(private val entries: HashMap[String, Expr]) extends Printable: - def this(entries: IterableOnce[(String, Expr)]) = this(HashMap.from(entries)) - inline def get(name: String): Option[Expr] = entries.get(name) - inline def +(entry: (String, Expr)): Context = Context(entries + entry) +class Context(private val entries: Map[String, BoundedExpr]) extends Printable: + def this() = this(Map("true" -> BoundedExpr(LiteralValue(true)), "false" -> BoundedExpr(LiteralValue(false)))) + inline def get(name: String): BoundedExpr = entries.get(name).getOrElse(BoundedExpr(UnknownValue())) + inline def +(entry: (String, BoundedExpr)): Context = Context(entries + entry) + inline def ++(other: Context): Context = Context(entries ++ other.entries) + inline def ++(other: IterableOnce[(String, BoundedExpr)]) = Context(entries ++ other) inline def isEmpty: Boolean = entries.isEmpty def getDebugOutput: DebugOutput = DebugOutput.Map(entries.iterator.map { (key, value) => (key, value.toString) }.toList) +object Context{ + def toCtx(entries: IterableOnce[(String, BoundedExpr)]) = Context(Map.from(entries)) +} \ No newline at end of file diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala index bfe09610a..551bc52e4 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala @@ -1,5 +1,256 @@ package mlscript.compiler.mono.specializer +import scala.collection.mutable.ArrayBuffer +import scala.collection.mutable.Map as MutMap import mlscript.compiler.debug.Debug +import mlscript.compiler.mono.MonomorphError +import mlscript.compiler.mono.Monomorph +import mlscript.compiler.UnitValue +import mlscript.TypeName +import mlscript.compiler.Item +import mlscript.compiler.CaseBranch +import mlscript.compiler.Expr -class Specializer(using debug: Debug) +class Specializer(monoer: Monomorph)(using debug: Debug){ + + // def evaluateFunction(callee: MonoValue, arguments: List[MonoValue])(using evalCtx: Context, callingStack: List[String], typeCtx: Map[String, Item.TypeDecl], funcCtx: Map[String, Item.FuncDecl]): BoundedExpr = { + // debug.trace[BoundedExpr]("FUNC ", callee.toString() + arguments.mkString("(", ", ", ")")) { + // callee match + // case LiteralValue(s: String) if Builtin.isBinaryOperator(s) && arguments.length == 2 => + // val retValue = Builtin.evaluateBinaryOpValue(s, arguments.head, arguments.tail.head) + // if(retValue.isDefined){ + // BoundedExpr(retValue.get) + // } + // else BoundedExpr(UnknownValue()) + // case FunctionValue(name, body, prm, thisCtx) => + // val argCtx = Context.toCtx(prm.zip(arguments)) + // val ret = evaluate(body)(using evalCtx ++ Context.toCtx(thisCtx) ++ argCtx, name :: callingStack) + // ret._2 + // case _ => BoundedExpr(UnknownValue()) + // }(identity) + // } + + // def evaluateConstructor(tpName: TypeName, arguments: List[MonoValue])(using evalCtx: Context, typeCtx: Map[String, Item.TypeDecl], funcCtx: Map[String, Item.FuncDecl]): BoundedExpr = + // debug.trace[BoundedExpr]("NEW ", tpName.toString() + arguments.mkString("(", ", ", ")")){ + // val Item.TypeDecl(name, kind, typeParams, params, parents, body) = typeCtx.get(tpName.name).get + // val plainPrm = params.map(_._2.name) + // val objValue: ObjectValue = ObjectValue(tpName.name, + // (plainPrm.zip(arguments.map(_.toBoundedExpr)) ++ body.items.flatMap{ + // case f@Item.FuncDecl(nm, prm, bd) => + // Some(nm.name -> funcDecl2Val(f).toBoundedExpr) + // case _ => None + // }).toMap) + // objValue.fields.foreach{ + // case (nm, v: FunctionValue) if !plainPrm.contains(nm) => v.ctx.addOne("this" -> objValue.toBoundedExpr) + // case _ => () + // } + // BoundedExpr(objValue) + // }(identity) + + // def funcDecl2Val(fd: Item.FuncDecl)(using evalCtx: Context): FunctionValue = { + // FunctionValue(fd.name.name, fd.body, fd.params.map(_._2.name), MutMap()) + // } + + def evaluate(rawExpr: Expr)(using evalCtx: Context, callingStack: List[String]): Expr = + // debug.trace[Expr]("EVAL ", rawExpr.toString()) { + rawExpr match{ + case Expr.Ref(name) => + rawExpr.expValue = evalCtx.get(name) + rawExpr + case Expr.Apply(Expr.Apply(opE@Expr.Ref(op), a1), a2) if Builtin.isBinaryOperator(op) => + if(a1.length == 1 && a2.length == 1) + { + val a1E = evaluate(a1.head) + val a2E = evaluate(a2.head) + val pairedAV = (a1E.expValue.asValue, a2E.expValue.asValue) match { + case (Some(i1: LiteralValue), Some(i2: LiteralValue)) => + Builtin.evaluateBinaryOpValue(op, i1, i2) match{ + case Some(value) => value + case None => PrimitiveValue() + } + case _ => PrimitiveValue() + } + val retExp = Expr.Apply(Expr.Apply(opE, List(a1E)), List(a2E)) + retExp.expValue = BoundedExpr(pairedAV) + retExp + } + else ??? + + case Expr.Apply(nm@Expr.Ref(name), arguments) => + val nArgs = arguments.map(evaluate(_)) + val args = nArgs.map(_.expValue) + val retVal = monoer.monomorphizeCall(name, args) + val retExp = Expr.Apply(nm, nArgs) + retExp.expValue = retVal + retExp + + case other@Expr.Apply(callee, arguments) => + val calE = evaluate(callee) + val nArgs = arguments.map(evaluate) + val args = nArgs.map(_.expValue) + val cal = calE.expValue + val retV = cal.values.map{ + case FunctionValue(name, prm, ctxArg) => + monoer.monomorphizeCall(name, ctxArg.unzip._2 ++ args) + case _ => BoundedExpr(UnknownValue()) + }.fold(BoundedExpr())(_ ++ _) + val retExp = Expr.Apply(calE, nArgs) + retExp.expValue = retV + retExp + + case Expr.Select(receiver, field) => + val rec = evaluate(receiver) + val retV = rec.expValue.values.map{ + case ObjectValue(_, flds) if flds.contains(field.name) => + flds.get(field.name).get + case obj: ObjectValue => + BoundedExpr(monoer.specializeSelect(obj, field.name)) + case _ => + BoundedExpr(UnknownValue()) + }.fold(BoundedExpr())(_ ++ _) + val retExp = Expr.Select(rec, field) + retExp.expValue = retV + retExp + + case Expr.LetIn(false, name, rhs, body) => + val nRhs = evaluate(rhs) + val nCtx = evalCtx + (name.name -> nRhs.expValue) + val nBody = evaluate(body)(using nCtx) + val retExp = Expr.LetIn(false, name, nRhs, nBody) + retExp.expValue = body.expValue + retExp + + case l@Expr.Literal(value) => + l.expValue = BoundedExpr(LiteralValue(value)) + l + + case Expr.New(apply, arguments) => + val nArgs = arguments.map(evaluate(_)) + val args = nArgs.map(_.expValue) + val retV = BoundedExpr(monoer.specializeNew(apply.name, args)) + val retExp = Expr.New(apply, nArgs) + retExp.expValue = retV + retExp + + case Expr.IfThenElse(condition, consequent, Some(alternate)) => + val nCond = evaluate(condition) + val nCons = evaluate(consequent) + val nAlter = evaluate(alternate) + val retV = nCond.expValue.asValue match { + case Some(x: LiteralValue) if x.asBoolean().isDefined => + if(x.asBoolean().get){ + nCons.expValue + } + else { + nAlter.expValue + } + case _ => + nCons.expValue ++ nAlter.expValue + } + val retExp = Expr.IfThenElse(nCond, nCons, Some(nAlter)) + retExp.expValue = retV + retExp + case Expr.IfThenElse(condition, consequent, None) => + val nCond = evaluate(condition) + val nCons = evaluate(consequent) + val retExp = Expr.IfThenElse(nCond, nCons, None) + retExp.expValue = BoundedExpr(LiteralValue(UnitValue.Undefined)) + retExp + + case self@Expr.Lambda(prm, body) => + ??? + + case Expr.Isolated(isolation) => ??? + + case Expr.Tuple(fields) => + if(fields.length == 1){ + evaluate(fields.head) + } + else + ??? + case Expr.Record(fields) => ??? + case Expr.LetIn(true, name, rhs, body) => ??? + case Expr.Block(items) => + val exps = items.flatMap{ + case e: Expr => Some(evaluate(e)) + case _ => None + } + if(exps.length == 0){ + val retE = Expr.Literal(UnitValue.Undefined) + val retV = BoundedExpr(LiteralValue(UnitValue.Undefined)) + retE.expValue = retV + retE + } + else if(exps.length == 1){ + exps.head + } + else { + val retV = exps.reverse.head.expValue + val retE = Expr.Block(exps) + retE.expValue = retV + retE + } + + case Expr.As(value, toType) => ??? + case Expr.Assign(assignee, value) => ??? + case Expr.With(value, fields) => ??? + case Expr.Subscript(receiver, index) => ??? + case Expr.Match(scrutinee, branches) => ??? + } + // }(_.expValue) + + def defunctionalize(rawExpr: Expr): Expr = { + val ret: Expr = rawExpr match { + case _: (Expr.Ref | Expr.Literal) => rawExpr + case Expr.Apply(sel@Expr.Select(receiver, field), args) => + val nRec = defunctionalize(receiver) + val nArgs = args.map(defunctionalize) + val branches = ArrayBuffer[CaseBranch]() + receiver.expValue.values.foreach{ + case ObjectValue(name, _) => + branches.addOne(CaseBranch.Instance(Expr.Ref(name), Expr.Ref("obj"), Expr.Apply(Expr.Ref(s"$field$$$name"), Expr.Ref("obj") :: nArgs))) + case _ => () + } + Expr.Match(nRec, branches) + case Expr.Apply(callee, arguments) => Expr.Apply(defunctionalize(callee), arguments.map(defunctionalize)) + case Expr.New(typeName, args) => Expr.New(typeName, args.map(defunctionalize)) + case Expr.Tuple(fields) => Expr.Tuple(fields.map(defunctionalize)) + case Expr.LetIn(isRec, name, rhs, body) => Expr.LetIn(isRec, name, defunctionalize(rhs), defunctionalize(body)) + case Expr.IfThenElse(condition, consequent, alternate) => Expr.IfThenElse(defunctionalize(condition), defunctionalize(consequent), alternate.map(defunctionalize)) + case Expr.Block(items) => Expr.Block(items.map{ + case e: Expr => defunctionalize(e) + case other => other + }) + case Expr.Select(receiver, field) => Expr.Select(defunctionalize(receiver), field) + case _ => ??? + } + ret.expValue = rawExpr.expValue + ret + } + // def updateResult(rawExpr: Expr)(using evalCtx: Context, callingStack: List[String], diff: Map[String, BoundedExpr]): Option[BoundedExpr] = { + // if(rawExpr.freeVars.intersect(diff.keySet).isEmpty){ + // None + // } + // else { + // rawExpr match + // case Expr.Ref(name) => diff.get(name) + // case Expr.Apply(callee, arguments) => + + // case Expr.Tuple(fields) => + // case Expr.Record(fields) => + // case Expr.Select(receiver, field) => + // case Expr.LetIn(isRec, name, rhs, body) => + // case Expr.Block(items) => + // case Expr.As(value, toType) => + // case Expr.Assign(assignee, value) => + // case Expr.With(value, fields) => + // case Expr.Subscript(receiver, index) => + // case Expr.Match(scrutinee, branches) => + // case Expr.Literal(value) => + // case Expr.New(typeName, args) => + // case Expr.IfThenElse(condition, consequent, alternate) => + // case Expr.Isolated(isolation) => + // case Expr.Lambda(params, body) => ??? + // } + // } +} diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/utils.scala b/compiler/shared/main/scala/mlscript/compiler/mono/utils.scala new file mode 100644 index 000000000..ff3090ff2 --- /dev/null +++ b/compiler/shared/main/scala/mlscript/compiler/mono/utils.scala @@ -0,0 +1,3 @@ +package mlscript.compiler.mono + + diff --git a/compiler/shared/main/scala/mlscript/compiler/syntax.scala b/compiler/shared/main/scala/mlscript/compiler/syntax.scala index 89d80f01a..8140eeb2d 100644 --- a/compiler/shared/main/scala/mlscript/compiler/syntax.scala +++ b/compiler/shared/main/scala/mlscript/compiler/syntax.scala @@ -7,10 +7,19 @@ import mlscript.{Type, Union, Inter, Function, Record, Tuple, Recursive, Applied Neg, Rem, Bounds, WithExtension, Constrained, Top, Bot, Literal, TypeName, TypeVar, PolyType, NamedType} import scala.collection.immutable.HashMap +import mlscript.compiler.mono.specializer.BoundedExpr +import mlscript.compiler.mono.specializer.Builtin -enum Expr extends Printable: +trait ASTNode: + var parent: ASTNode = null + def setNodeFields(): Unit + var expValue: BoundedExpr = BoundedExpr() + var freeVars: Set[String] = null + var isStatic: Boolean = false + +enum Expr extends Printable, ASTNode: case Ref(name: String) - case Lambda(params: List[Ref], body: Expr) + case Lambda(params: List[Parameter], body: Expr) case Apply(callee: Expr, arguments: List[Expr]) case Tuple(fields: List[Expr]) case Record(fields: List[(Ref, Expr)]) @@ -23,10 +32,80 @@ enum Expr extends Printable: case Subscript(receiver: Expr, index: Expr) case Match(scrutinee: Expr, branches: ArrayBuffer[CaseBranch]) case Literal(value: BigInt | BigDecimal | Boolean | String | UnitValue) - case New(apply: Option[(TypeName, List[Expr])], body: Isolation) + case New(typeName: TypeName, args: List[Expr]) case IfThenElse(condition: Expr, consequent: Expr, alternate: Option[Expr]) case Isolated(isolation: Isolation) + val workaround = setNodeFields() + + def setNodeFields(): Unit = this match + case Expr.Ref(name) => + freeVars = if Builtin.builtinRefs.contains(name) then Set() else Set(name) + case Expr.Lambda(params, body) => + body.parent = this; freeVars = body.freeVars -- params.map(_._2.name) + case Expr.Apply(callee, arguments) => + callee.parent = this; arguments.foreach(x => x.parent = this); freeVars = callee.freeVars ++ arguments.flatMap(_.freeVars); isStatic = arguments.map(_.isStatic).fold(callee.isStatic)(_ && _) + case Expr.Tuple(fields) => + fields.foreach(x => x.parent = this); freeVars = fields.flatMap(_.freeVars).toSet; isStatic = fields.map(_.isStatic).fold(true)(_ && _) + case Expr.Record(fields) => + fields.foreach(x => x._2.parent = this); freeVars = fields.flatMap(_._2.freeVars).toSet -- fields.map(_._1.name); isStatic = fields.map(_._2.isStatic).fold(true)(_ && _) + case Expr.Select(receiver, field) => + receiver.parent = this; field.parent = this; freeVars = receiver.freeVars; isStatic = receiver.isStatic + case Expr.LetIn(isRec, name, rhs, body) => + rhs.parent = this; body.parent = this; freeVars = rhs.freeVars ++ body.freeVars - name.name; isStatic = rhs.isStatic && body.isStatic + case Expr.Block(items) => + val expItems = items.flatMap{ + case x: Expr => Some(x) + case _ => None + } + freeVars = expItems.flatMap(_.freeVars).toSet + expItems.foreach(x => {x.parent = this}) + isStatic = expItems.map(_.isStatic).fold(true)(_ && _) + case Expr.As(value, toType) => + value.parent = this; freeVars = value.freeVars; isStatic = value.isStatic + case Expr.Assign(assignee, value) => + assignee.parent = this; value.parent = this; freeVars = assignee.freeVars ++ value.freeVars; isStatic = true + case Expr.With(value, fields) => + value.parent = this; fields.parent = this; freeVars = value.freeVars ++ fields.freeVars; isStatic = value.isStatic && fields.isStatic + case Expr.Subscript(receiver, index) => + receiver.parent = this; index.parent = this; freeVars = receiver.freeVars ++ index.freeVars; isStatic = receiver.isStatic && index.isStatic + case Expr.Match(scrutinee, branches) => + scrutinee.parent = this + isStatic = scrutinee.isStatic + freeVars = scrutinee.freeVars ++ branches.flatMap{ + case CaseBranch.Instance(className, alias, body) => + isStatic &&= body.isStatic + body.freeVars - alias.name + case CaseBranch.Constant(literal, body) => + isStatic &&= body.isStatic + body.freeVars + case CaseBranch.Wildcard(body) => + isStatic &&= body.isStatic + body.freeVars + } + branches.foreach(x => x.body.parent = this) + case Expr.Literal(value) => + freeVars = Set() + isStatic = true + case Expr.New(typeName, args) => + args.foreach(x => x.parent = this) + isStatic = args.map(_.isStatic).fold(true)(_ && _) + freeVars = args.flatMap(_.freeVars).toSet + typeName.name + case Expr.IfThenElse(condition, consequent, alternate) => + condition.parent = this + consequent.parent = this + alternate.foreach(x => x.parent = this) + freeVars = condition.freeVars ++ consequent.freeVars ++ alternate.map(_.freeVars).getOrElse(Set()) + isStatic = alternate.map(_.isStatic && condition.isStatic && consequent.isStatic).getOrElse(true) + case Expr.Isolated(isolation) => + val exps = isolation.items.flatMap{ + case x: Expr => Some(x) + case _ => None + } + exps.foreach{x => x.parent = this} + freeVars = exps.flatMap(_.freeVars).toSet + isStatic = exps.map(_.isStatic).fold(true)(_ && _) + def asBoolean(): Boolean = this match case Literal(value: BigInt) => value != 0 case Literal(value: BigDecimal) => value != 0 @@ -38,39 +117,43 @@ enum Expr extends Printable: def getDebugOutput: DebugOutput = DebugOutput.Code(ExprPrinter.printLines(this)) - override def toString(): String = this match - case Ref(name) => name - case Lambda(params, body) => - val head = params.mkString("(", ", ", ")") - s"(fun $head -> $body)" - case Apply(Apply(Ref(op), lhs :: Nil), rhs :: Nil) - if !op.headOption.forall(_.isLetter) => - s"($lhs $op $rhs)" - case Apply(callee, arguments) => - callee.toString + arguments.mkString("(", ", ", ")") - case Tuple(fields) => - val inner = fields.mkString(", ") - "(" + (if fields.length == 1 then inner + ", " else inner) + ")" - case Record(fields) => - "{" + fields.iterator.map { (name, value) => s"$name = $value" } + "}" - case Select(receiver, field) => s"$receiver.$field" - case LetIn(isRec, name, rhs, body) => s"let $name = $rhs in $body" - case Block(items) => items.mkString(";") - case As(value, toType) => s"$value as $toType" - case Assign(assignee, value) => s"$assignee = $value" - case With(value, fields) => s"$value with $fields" - case Subscript(receiver, index) => s"$receiver[$index]" - case Match(scrutinee, branches) => - s"$scrutinee match " + branches.iterator.mkString("{", "; ", "}") - case Literal(value) => value.toString - case New(Some((callee, args)), body) => - s"new ${callee.name}" + args.mkString(" (", ", ", ") ") + body.toString - case New(None, body) => "new " + body.toString - case IfThenElse(condition, consequent, None) => - s"if $condition then $consequent" - case IfThenElse(condition, consequent, Some(alternate)) => - s"if $condition then $consequent else $alternate" - case Isolated(isolation) => s"{\n$isolation\n}" + override def toString(): String = + // val header = if this.parent == null then this.freeVars.mkString("[", ", ", "]~") else "" + val body = this match { + case Ref(name) => name + case Lambda(params, body) => + val head = params.mkString("(", ", ", ")") + s"(fun $head -> $body)" + case Apply(Apply(Ref(op), lhs :: Nil), rhs :: Nil) + if !op.headOption.forall(_.isLetter) => + s"($lhs $op $rhs)" + case Apply(callee, arguments) => + callee.toString + arguments.mkString("(", ", ", ")") + case Tuple(fields) => + val inner = fields.mkString(", ") + "(" + (if fields.length == 1 then inner + ", " else inner) + ")" + case Record(fields) => + "{" + fields.iterator.map { (name, value) => s"$name = $value" } + "}" + case Select(receiver, field) => s"$receiver.$field" + case LetIn(isRec, name, rhs, body) => s"let $name = $rhs in $body" + case Block(items) => items.mkString(";") + case As(value, toType) => s"$value as $toType" + case Assign(assignee, value) => s"$assignee = $value" + case With(value, fields) => s"$value with $fields" + case Subscript(receiver, index) => s"$receiver[$index]" + case Match(scrutinee, branches) => + s"$scrutinee match " + branches.iterator.mkString("{", "; ", "}") + case Literal(value) => "#" + value.toString + case New(callee, args) => + s"new ${callee.name}" + args.mkString(" (", ", ", ") ") + case IfThenElse(condition, consequent, None) => + s"if $condition then $consequent" + case IfThenElse(condition, consequent, Some(alternate)) => + s"if $condition then $consequent else $alternate" + case Isolated(isolation) => s"{\n$isolation\n}" + } + // header + + body end Expr // This corresponds to `mlscript.UnitLit`. diff --git a/compiler/shared/test/diff/mono.mls b/compiler/shared/test/diff/mono.mls index 00bc53eb9..c0de92e71 100644 --- a/compiler/shared/test/diff/mono.mls +++ b/compiler/shared/test/diff/mono.mls @@ -1,6 +1,6 @@ :NewParser :ParseOnly -:mono +// :mono fun f(x) = if x then 42 else 1337 //│ |#fun| |f|(|x|)| |#=| |#if| |x| |#then| |42| |#else| |1337| //│ Parsed: {fun f = x, => if (x) then 42 else 1337} @@ -8,11 +8,8 @@ fun f(x) = if x then 42 else 1337 //│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), If((x) then 42, Some(IntLit(1337)))))) //│ Lifted: //│ TypingUnit {fun f = x, => if (x) then 42 else 1337} -//│ Mono: -//│ fun f(x) = -//│ if x then 42 else 1337 -:mono +// :mono fun foo() = 42 //│ |#fun| |foo|(||)| |#=| |42| //│ Parsed: {fun foo = => 42} @@ -20,11 +17,8 @@ fun foo() = 42 //│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(), IntLit(42)))) //│ Lifted: //│ TypingUnit {fun foo = => 42} -//│ Mono: -//│ fun foo() = -//│ 42 -:mono +// :mono fun foo(x, #b) = if b then x else 1337 let a = foo(42, true) let b = foo(23, false) @@ -38,17 +32,8 @@ let b = foo(23, false) //│ let a = foo (42, true,) //│ let b = foo (23, false,) //│ } -//│ Mono: -//│ fun foo(x, #b) = -//│ if b then x else 1337 -//│ fun a() = -//│ foo__unknown(42) -//│ fun b() = -//│ foo__unknown(23) -//│ fun foo__unknown(x) = -//│ 1337 -:mono +// :mono let x = 42 + 1337 //│ |#let| |x| |#=| |42| |+| |1337| //│ Parsed: {let x = + (42,) (1337,)} @@ -56,109 +41,1118 @@ let x = 42 + 1337 //│ TypingUnit(NuFunDef(Some(false), x, [], App(App(Var(+), Tup(_: IntLit(42))), Tup(_: IntLit(1337))))) //│ Lifted: //│ TypingUnit {let x = + (42,) (1337,)} -//│ Mono: -//│ fun x() = -//│ (42 + 1337) -:mono class Bar(#x) fun foo(#b) = b -let a = foo(Bar(1)) -let b = foo(Bar(2)) -//│ |#class| |Bar|(|##|x|)|↵|#fun| |foo|(|##|b|)| |#=| |b|↵|#let| |a| |#=| |foo|(|Bar|(|1|)|)|↵|#let| |b| |#=| |foo|(|Bar|(|2|)|)| -//│ Parsed: {class Bar(#x,) {}; fun foo = #b, => b; let a = foo (Bar (1,),); let b = foo (Bar (2,),)} +let a = foo(new Bar(1)) +let b = foo(new Bar(2)) +//│ |#class| |Bar|(|##|x|)|↵|#fun| |foo|(|##|b|)| |#=| |b|↵|#let| |a| |#=| |foo|(|#new| |Bar|(|1|)|)|↵|#let| |b| |#=| |foo|(|#new| |Bar|(|2|)|)| +//│ Parsed: {class Bar(#x,) {}; fun foo = #b, => b; let a = foo (new Bar(1,) {},); let b = foo (new Bar(2,) {},)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Bar, (), Tup(_: Var(x)), (), TypingUnit()), NuFunDef(None, foo, [], Lam(Tup(_: Var(b)), Var(b))), NuFunDef(Some(false), a, [], App(Var(foo), Tup(_: App(Var(Bar), Tup(_: IntLit(1)))))), NuFunDef(Some(false), b, [], App(Var(foo), Tup(_: App(Var(Bar), Tup(_: IntLit(2))))))) +//│ TypingUnit(NuTypeDef(class, Bar, (), Tup(_: Var(x)), (), TypingUnit()), NuFunDef(None, foo, [], Lam(Tup(_: Var(b)), Var(b))), NuFunDef(Some(false), a, [], App(Var(foo), Tup(_: New(Some((TypeName(Bar),1,)), TypingUnit(List()))))), NuFunDef(Some(false), b, [], App(Var(foo), Tup(_: New(Some((TypeName(Bar),2,)), TypingUnit(List())))))) //│ Lifted: //│ TypingUnit { //│ class Bar$1(#x,) {} //│ fun foo = #b, => b -//│ let a = foo (Bar$1 (1,),) -//│ let b = foo (Bar$1 (2,),) +//│ let a = foo (new Bar$1(1,) {},) +//│ let b = foo (new Bar$1(2,) {},) //│ } -//│ Mono: -//│ fun foo(#b) = -//│ b -//│ fun a() = -//│ foo__class Bar$1__1() -//│ fun b() = -//│ foo__class Bar$1__2() -//│ fun foo__class Bar$1__2() = -//│ Bar$1__2() -//│ fun foo__class Bar$1__1() = -//│ Bar$1__1() -//│ class Bar$1() { + +// :mono +class OneInt(#a){ + fun inc() = a+1 +} +(new OneInt(1)).inc() +//│ |#class| |OneInt|(|##|a|)|{|→|#fun| |inc|(||)| |#=| |a|+|1|←|↵|}|↵|(|#new| |OneInt|(|1|)|)|.inc|(||)| +//│ Parsed: {class OneInt(#a,) {fun inc = => + (a,) (1,)}; ('(' new OneInt(1,) {}, ')').inc ()} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, inc, [], Lam(Tup(), App(App(Var(+), Tup(_: Var(a))), Tup(_: IntLit(1))))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(OneInt),1,)), TypingUnit(List())))), inc), Tup())) +//│ Lifted: +//│ TypingUnit { +//│ class OneInt$1(#a,) {fun inc = => + ((this).a,) (1,)} +//│ Code(List(('(' new OneInt$1(1,) {}, ')').inc ())) //│ } -//│ class Bar$1__1(): Bar$1() { + +// :mono +class OneInt(#a){ + fun add(x) = + new OneInt(a+x.a) +} +(new OneInt(1)).add(new OneInt(2)) +//│ |#class| |OneInt|(|##|a|)|{|→|#fun| |add|(|x|)| |#=| |→|#new| |OneInt|(|a|+|x|.a|)|←|←|↵|}|↵|(|#new| |OneInt|(|1|)|)|.add|(|#new| |OneInt|(|2|)|)| +//│ Parsed: {class OneInt(#a,) {fun add = x, => {new OneInt(+ (a,) ((x).a,),) {}}}; ('(' new OneInt(1,) {}, ')').add (new OneInt(2,) {},)} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, add, [], Lam(Tup(_: Var(x)), Blk(...))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(OneInt),1,)), TypingUnit(List())))), add), Tup(_: New(Some((TypeName(OneInt),2,)), TypingUnit(List()))))) +//│ Lifted: +//│ TypingUnit { +//│ class OneInt$1(#a,) { +//│ fun add = x, => {new OneInt$1(+ ((this).a,) ((x).a,),) {}} +//│ } +//│ Code(List(('(' new OneInt$1(1,) {}, ')').add (new OneInt$1(2,) {},))) //│ } -//│ class Bar$1__2(): Bar$1() { + +// :mono +if true then 1 else 0 +if 1+1 > 1 then 1-1 else 1*1 +//│ |#if| |true| |#then| |1| |#else| |0|↵|#if| |1|+|1| |>| |1| |#then| |1|-|1| |#else| |1|*|1| +//│ Parsed: {if (true) then 1 else 0; if (> (+ (1,) (1,),) (1,)) then - (1,) (1,) else * (1,) (1,)} +//│ Parsed: +//│ TypingUnit(If((true) then 1, Some(IntLit(0))), If((> (+ (1,) (1,),) (1,)) then - (1,) (1,), Some(App(App(Var(*), Tup(_: IntLit(1))), Tup(_: IntLit(1)))))) +//│ Lifted: +//│ TypingUnit { +//│ Code(List(if (true) then 1 else 0)) +//│ Code(List(if (> (+ (1,) (1,),) (1,)) then - (1,) (1,) else * (1,) (1,))) //│ } -:mono -fun fac(#n) = +// :mono +if(b) then 1 else 2 +//│ |#if|(|b|)| |#then| |1| |#else| |2| +//│ Parsed: {if ('(' b, ')') then 1 else 2} +//│ Parsed: +//│ TypingUnit(If(('(' b, ')') then 1, Some(IntLit(2)))) +//│ Lifted: +//│ TypingUnit {Code(List(if ('(' b, ')') then 1 else 2))} + +// :mono +((f, g) => f(g))(f => f, true) +//│ |(|(|f|,| |g|)| |=>| |f|(|g|)|)|(|f| |=>| |f|,| |true|)| +//│ Parsed: {'(' f, g, => f (g,), ')' (f, => f, true,)} +//│ Parsed: +//│ TypingUnit(App(Bra(rcd = false, Tup(_: Lam(Tup(_: Var(f), _: Var(g)), App(Var(f), Tup(_: Var(g)))))), Tup(_: Lam(Tup(_: Var(f)), Var(f)), _: Var(true)))) +//│ Lifted: +//│ TypingUnit { +//│ Code(List('(' f, g, => f (g,), ')' (f, => f, true,))) +//│ } + + +// :mono +(b => if b then true else false) (true) +//│ |(|b| |=>| |#if| |b| |#then| |true| |#else| |false|)| |(|true|)| +//│ Parsed: {'(' b, => if (b) then true else false, ')' (true,)} +//│ Parsed: +//│ TypingUnit(App(Bra(rcd = false, Tup(_: Lam(Tup(_: Var(b)), If((b) then true, Some(Var(false)))))), Tup(_: Var(true)))) +//│ Lifted: +//│ TypingUnit { +//│ Code(List('(' b, => if (b) then true else false, ')' (true,))) +//│ } + +// :mono +fun f(x) = + if(x > 0) then x+1 else x-1 +f(2)+3 +//│ |#fun| |f|(|x|)| |#=|→|#if|(|x| |>| |0|)| |#then| |x|+|1| |#else| |x|-|1|←|↵|f|(|2|)|+|3| +//│ Parsed: {fun f = x, => {if ('(' > (x,) (0,), ')') then + (x,) (1,) else - (x,) (1,)}; + (f (2,),) (3,)} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Blk(...))), App(App(Var(+), Tup(_: App(Var(f), Tup(_: IntLit(2))))), Tup(_: IntLit(3)))) +//│ Lifted: +//│ TypingUnit { +//│ fun f = x, => {if ('(' > (x,) (0,), ')') then + (x,) (1,) else - (x,) (1,)} +//│ Code(List(+ (f (2,),) (3,))) +//│ } + +// :mono +fun fac(n) = if (n > 1) then fac(n - 1) * n else 1 -fac(10) -//│ |#fun| |fac|(|##|n|)| |#=| |→|#if| |(|n| |>| |1|)| |#then| |fac|(|n| |-| |1|)| |*| |n| |#else| |1|←|↵|fac|(|10|)| -//│ Parsed: {fun fac = #n, => {if ('(' > (n,) (1,), ')') then * (fac (- (n,) (1,),),) (n,) else 1}; fac (10,)} +fac(2) +//│ |#fun| |fac|(|n|)| |#=| |→|#if| |(|n| |>| |1|)| |#then| |fac|(|n| |-| |1|)| |*| |n| |#else| |1|←|↵|fac|(|2|)| +//│ Parsed: {fun fac = n, => {if ('(' > (n,) (1,), ')') then * (fac (- (n,) (1,),),) (n,) else 1}; fac (2,)} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, fac, [], Lam(Tup(_: Var(n)), Blk(...))), App(Var(fac), Tup(_: IntLit(2)))) +//│ Lifted: +//│ TypingUnit { +//│ fun fac = n, => {if ('(' > (n,) (1,), ')') then * (fac (- (n,) (1,),),) (n,) else 1} +//│ Code(List(fac (2,))) +//│ } + +// :mono +class List(l, hasTail) {} +class Nil(l, hasTail) {} +fun count(lst) = + if lst.hasTail then count(lst.l)+1 else 1 +count(new List(new List(new Nil(0, false), true), true)) +//│ |#class| |List|(|l|,| |hasTail|)| |{||}|↵|#class| |Nil|(|l|,| |hasTail|)| |{||}|↵|#fun| |count|(|lst|)| |#=|→|#if| |lst|.hasTail| |#then| |count|(|lst|.l|)|+|1| |#else| |1|←|↵|count|(|#new| |List|(|#new| |List|(|#new| |Nil|(|0|,| |false|)|,| |true|)|,| |true|)|)| +//│ Parsed: {class List(l, hasTail,) {}; class Nil(l, hasTail,) {}; fun count = lst, => {if ((lst).hasTail) then + (count ((lst).l,),) (1,) else 1}; count (new List(new List(new Nil(0, false,) {}, true,) {}, true,) {},)} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(l), _: Var(hasTail)), (), TypingUnit()), NuTypeDef(class, Nil, (), Tup(_: Var(l), _: Var(hasTail)), (), TypingUnit()), NuFunDef(None, count, [], Lam(Tup(_: Var(lst)), Blk(...))), App(Var(count), Tup(_: New(Some((TypeName(List),new List(new Nil(0, false,) {}, true,) {}, true,)), TypingUnit(List()))))) +//│ Lifted: +//│ TypingUnit { +//│ class List$1(l, hasTail,) {} +//│ class Nil$2(l, hasTail,) {} +//│ fun count = lst, => {if ((lst).hasTail) then + (count ((lst).l,),) (1,) else 1} +//│ Code(List(count (new List$1(new List$1(new Nil$2(0, false,) {}, true,) {}, true,) {},))) +//│ } + +:mono +class List(e, tail){ + fun gen() = new List(e, tail.gen()) +} +class Nil(){ + fun gen() = new List(0, this) +} +fun generate(x) = + if x > 0 then new List(x, generate(x+1)) else new Nil() +generate(10).gen() +//│ |#class| |List|(|e|,| |tail|)|{|→|#fun| |gen|(||)| |#=| |#new| |List|(|e|,| |tail|.gen|(||)|)|←|↵|}|↵|#class| |Nil|(||)|{|→|#fun| |gen|(||)| |#=| |#new| |List|(|0|,| |this|)|←|↵|}|↵|#fun| |generate|(|x|)| |#=| |→|#if| |x| |>| |0| |#then| |#new| |List|(|x|,| |generate|(|x|+|1|)|)| |#else| |#new| |Nil|(||)|←|↵|generate|(|10|)|.gen|(||)| +//│ Parsed: {class List(e, tail,) {fun gen = => new List(e, (tail).gen (),) {}}; class Nil() {fun gen = => new List(0, this,) {}}; fun generate = x, => {if (> (x,) (0,)) then new List(x, generate (+ (x,) (1,),),) {} else new Nil() {}}; (generate (10,)).gen ()} //│ Parsed: -//│ TypingUnit(NuFunDef(None, fac, [], Lam(Tup(_: Var(n)), Blk(...))), App(Var(fac), Tup(_: IntLit(10)))) +//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, gen, [], Lam(Tup(), New(Some((TypeName(List),e, (tail).gen (),)), TypingUnit(List())))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, gen, [], Lam(Tup(), New(Some((TypeName(List),0, this,)), TypingUnit(List())))))), NuFunDef(None, generate, [], Lam(Tup(_: Var(x)), Blk(...))), App(Sel(App(Var(generate), Tup(_: IntLit(10))), gen), Tup())) //│ Lifted: //│ TypingUnit { -//│ fun fac = #n, => {if ('(' > (n,) (1,), ')') then * (fac (- (n,) (1,),),) (n,) else 1} -//│ Code(List(fac (10,))) +//│ class List$1(e, tail,) { +//│ fun gen = => new List$1((this).e, ((this).tail).gen (),) {} +//│ } +//│ class Nil$2() {fun gen = => new List$1(0, this,) {}} +//│ fun generate = x, => {if (> (x,) (0,)) then new List$1(x, generate (+ (x,) (1,),),) {} else new Nil$2() {}} +//│ Code(List((generate (10,)).gen ())) //│ } //│ Mono: -//│ fun fac(#n) = -//│ if ((n > 1), ) then (fac((n - 1)) * n) else 1 -//│ fac__10() -//│ fun fac__10() = -//│ 1 +//│ +//│ Mono result: +//│ main$$3() +//│ fun gen$List$1(this) = +//│ new List$1 (this.e, this.tail match {case obj: List$1 => gen$List$1(obj); case obj: Nil$2 => gen$Nil$2(obj)}) +//│ fun gen$Nil$2(this) = +//│ new List$1 (#0, this) +//│ fun main$$3() = +//│ generate(#10) match {case obj: Nil$2 => gen$Nil$2(obj); case obj: List$1 => gen$List$1(obj)} +//│ fun generate(x) = +//│ if (x > #0) then new List$1 (x, generate((x + #1))) else new Nil$2 () +//│ [mono] evaluating main$$3, rests: HashSet() +//│ [mono] ========== updating main$$3 ========== +//│ [mono] main$$3: () -> [] @{} +//│ [mono] ┌ SPEC CALL generate with ([10]) +//│ [mono] │ comparing (([],0)) with (Plain([10])) +//│ [mono] │ first time encounter generate +//│ [mono] │ evaluating generate, rests: HashSet() +//│ [mono] │ ========== updating generate ========== +//│ [mono] │ generate: (([10],1)) -> [] @{main$$3} +//│ [mono] │ ┌ SPEC CALL generate with ([11]) +//│ [mono] │ │ comparing (([10],1)) with (Plain([*LIT*])) +//│ [mono] │ │ find finer args +//│ [mono] │ └ SPEC CALL [] +//│ [mono] │ comparing [] with [List$1@{e: [10], tail: []}] +//│ [mono] │ adding these funcs to queue: Set(main$$3, generate) +//│ [mono] │ generate: (([*LIT*],100000)) -> [List$1@{e: [10], tail: ***}] @{main$$3, generate} +//│ [mono] └ SPEC CALL [List$1@{e: [10], tail: ***}] +//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}]) +//│ [mono] │ comparing (([],0)) with (Plain([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}])) +//│ [mono] │ first time encounter gen$List$1 +//│ [mono] │ evaluating gen$List$1, rests: HashSet(main$$3, generate) +//│ [mono] │ ========== updating gen$List$1 ========== +//│ [mono] │ gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [] @{main$$3} +//│ [mono] │ ┌ SPEC CALL gen$List$1 with ([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}]) +//│ [mono] │ │ comparing (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) with (Plain([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}])) +//│ [mono] │ └ SPEC CALL [] +//│ [mono] │ comparing [] with [List$1@{e: [10], tail: []}] +//│ [mono] │ adding these funcs to queue: Set(main$$3, gen$List$1) +//│ [mono] │ gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [List$1@{e: [10], tail: []}] @{main$$3, gen$List$1} +//│ [mono] └ SPEC CALL [List$1@{e: [10], tail: []}] +//│ [mono] comparing [] with [List$1@{e: [10], tail: []}] +//│ [mono] adding these funcs to queue: Set() +//│ [mono] main$$3: () -> [List$1@{e: [10], tail: []}] @{} +//│ [mono] evaluating gen$List$1, rests: HashSet(main$$3, generate) +//│ [mono] ========== updating gen$List$1 ========== +//│ [mono] gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [List$1@{e: [10], tail: []}] @{main$$3, gen$List$1} +//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}]) +//│ [mono] │ comparing (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) with (Plain([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}])) +//│ [mono] └ SPEC CALL [List$1@{e: [10], tail: []}] +//│ [mono] comparing [List$1@{e: [10], tail: []}] with [List$1@{e: [10], tail: [List$1@{e: [10], tail: []}]}] +//│ [mono] adding these funcs to queue: Set(main$$3, gen$List$1) +//│ [mono] gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{main$$3, gen$List$1} +//│ [mono] evaluating gen$List$1, rests: HashSet(main$$3, generate) +//│ [mono] ========== updating gen$List$1 ========== +//│ [mono] gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{main$$3, gen$List$1} +//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}]) +//│ [mono] │ comparing (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) with (Plain([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}])) +//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] +//│ [mono] comparing [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] with [List$1@{e: [10], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}]}] +//│ [mono] gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{main$$3, gen$List$1} +//│ [mono] evaluating main$$3, rests: HashSet(generate) +//│ [mono] ========== updating main$$3 ========== +//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{} +//│ [mono] ┌ SPEC CALL generate with ([10]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [List$1@{e: [10], tail: ***}] +//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}]) +//│ [mono] │ comparing (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) with (Plain([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}])) +//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] +//│ [mono] comparing [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] with [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] +//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{} +//│ [mono] evaluating generate, rests: HashSet() +//│ [mono] ========== updating generate ========== +//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [10], tail: ***}] @{main$$3, generate} +//│ [mono] ┌ SPEC CALL generate with ([*LIT*]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [List$1@{e: [10], tail: ***}] +//│ [mono] comparing [List$1@{e: [10], tail: ***}] with [List$1@{e: [*LIT*], tail: [List$1@{e: [10], tail: ***}]} | Nil$2@{}] +//│ [mono] adding these funcs to queue: Set(main$$3, generate) +//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$3, generate} +//│ [mono] evaluating main$$3, rests: HashSet(generate) +//│ [mono] ========== updating main$$3 ========== +//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{} +//│ [mono] ┌ SPEC CALL generate with ([10]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] +//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]) +//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}],3)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}])) +//│ [mono] │ find finer args +//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] +//│ [mono] ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]) +//│ [mono] │ comparing (([],0)) with (Plain([Nil$2@{}])) +//│ [mono] │ first time encounter gen$Nil$2 +//│ [mono] │ evaluating gen$Nil$2, rests: HashSet(gen$List$1, generate) +//│ [mono] │ ========== updating gen$Nil$2 ========== +//│ [mono] │ gen$Nil$2: (([Nil$2@{}],1)) -> [] @{main$$3} +//│ [mono] │ comparing [] with [List$1@{e: [0], tail: [Nil$2@{}]}] +//│ [mono] │ adding these funcs to queue: Set(main$$3) +//│ [mono] │ gen$Nil$2: (([Nil$2@{}],1)) -> [List$1@{e: [0], tail: [Nil$2@{}]}] @{main$$3} +//│ [mono] └ SPEC CALL [List$1@{e: [0], tail: [Nil$2@{}]}] +//│ [mono] comparing [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] with [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]} | Nil$2@{}]}] +//│ [mono] adding these funcs to queue: Set() +//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] @{} +//│ [mono] evaluating gen$List$1, rests: HashSet(main$$3, generate) +//│ [mono] ========== updating gen$List$1 ========== +//│ [mono] gen$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}],100002)) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] @{main$$3, gen$List$1} +//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]) +//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}],100002)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}])) +//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] +//│ [mono] ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]) +//│ [mono] │ comparing (([Nil$2@{}],1)) with (Plain([Nil$2@{}])) +//│ [mono] └ SPEC CALL [List$1@{e: [0], tail: [Nil$2@{}]}] +//│ [mono] comparing [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] with [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]}]}] +//│ [mono] gen$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}],100002)) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] @{main$$3, gen$List$1} +//│ [mono] evaluating main$$3, rests: HashSet(generate) +//│ [mono] ========== updating main$$3 ========== +//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] @{} +//│ [mono] ┌ SPEC CALL generate with ([10]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] +//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]) +//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}],100002)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}])) +//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] +//│ [mono] ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]) +//│ [mono] │ comparing (([Nil$2@{}],1)) with (Plain([Nil$2@{}])) +//│ [mono] └ SPEC CALL [List$1@{e: [0], tail: [Nil$2@{}]}] +//│ [mono] comparing [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] with [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]}] +//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] @{} +//│ [mono] evaluating generate, rests: HashSet() +//│ [mono] ========== updating generate ========== +//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$3, generate} +//│ [mono] ┌ SPEC CALL generate with ([*LIT*]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] +//│ [mono] comparing [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] with [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] +//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$3, generate} +//│ [mono] +//│ [mono] ==============final function signatures================== +//│ [mono] gen$List$1: ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] +//│ [mono] gen$Nil$2: ([Nil$2@{}]) -> [List$1@{e: [0], tail: [Nil$2@{}]}] +//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] +//│ [mono] generate: ([*LIT*]) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] :mono -trait AnyFoo { - fun bar(b: int): int +class List(e, tail) { + fun count() = 1 + tail.count() } -class FooPlus(#a: int): AnyFoo { - fun bar(b: int) = a + b +class Nil() { + fun count() = 0 } -class FooMinus(#a: int): AnyFoo { - fun Bar(b: int) = a - b +fun foo(x) = x.count() +fun generate(x) = + if x > 0 then new List(x, generate(x+1)) else new Nil() +foo(new List(1, new List(2, new Nil()))) +foo(generate(1)) +//│ |#class| |List|(|e|,| |tail|)| |{|→|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#fun| |foo|(|x|)| |#=| |x|.count|(||)|↵|#fun| |generate|(|x|)| |#=| |→|#if| |x| |>| |0| |#then| |#new| |List|(|x|,| |generate|(|x|+|1|)|)| |#else| |#new| |Nil|(||)|←|↵|foo|(|#new| |List|(|1|,| |#new| |List|(|2|,| |#new| |Nil|(||)|)|)|)|↵|foo|(|generate|(|1|)|)| +//│ Parsed: {class List(e, tail,) {fun count = => + (1,) ((tail).count (),)}; class Nil() {fun count = => 0}; fun foo = x, => (x).count (); fun generate = x, => {if (> (x,) (0,)) then new List(x, generate (+ (x,) (1,),),) {} else new Nil() {}}; foo (new List(1, new List(2, new Nil() {},) {},) {},); foo (generate (1,),)} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), App(Sel(Var(x), count), Tup()))), NuFunDef(None, generate, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: New(Some((TypeName(List),1, new List(2, new Nil() {},) {},)), TypingUnit(List())))), App(Var(foo), Tup(_: App(Var(generate), Tup(_: IntLit(1)))))) +//│ Lifted: +//│ TypingUnit { +//│ class List$1(e, tail,) {fun count = => + (1,) (((this).tail).count (),)} +//│ class Nil$2() {fun count = => 0} +//│ fun foo = x, => (x).count () +//│ fun generate = x, => {if (> (x,) (0,)) then new List$1(x, generate (+ (x,) (1,),),) {} else new Nil$2() {}} +//│ Code(List(foo (new List$1(1, new List$1(2, new Nil$2() {},) {},) {},))) +//│ Code(List(foo (generate (1,),))) +//│ } +//│ Mono: +//│ +//│ Mono result: +//│ main$$4() +//│ main$$5() +//│ fun count$Nil$2(this) = +//│ #0 +//│ fun foo(x) = +//│ x match {case obj: List$1 => count$List$1(obj); case obj: Nil$2 => count$Nil$2(obj)} +//│ fun count$List$1(this) = +//│ (#1 + this.tail match {case obj: Nil$2 => count$Nil$2(obj); case obj: List$1 => count$List$1(obj)}) +//│ fun main$$5() = +//│ foo(generate(#1)) +//│ fun main$$4() = +//│ foo(new List$1 (#1, new List$1 (#2, new Nil$2 () ) ) ) +//│ fun generate(x) = +//│ if (x > #0) then new List$1 (x, generate((x + #1))) else new Nil$2 () +//│ [mono] evaluating main$$5, rests: HashSet(main$$4) +//│ [mono] ========== updating main$$5 ========== +//│ [mono] main$$5: () -> [] @{} +//│ [mono] ┌ SPEC CALL generate with ([1]) +//│ [mono] │ comparing (([],0)) with (Plain([1])) +//│ [mono] │ first time encounter generate +//│ [mono] │ evaluating generate, rests: HashSet(main$$4) +//│ [mono] │ ========== updating generate ========== +//│ [mono] │ generate: (([1],1)) -> [] @{main$$5} +//│ [mono] │ ┌ SPEC CALL generate with ([2]) +//│ [mono] │ │ comparing (([1],1)) with (Plain([*LIT*])) +//│ [mono] │ │ find finer args +//│ [mono] │ └ SPEC CALL [] +//│ [mono] │ comparing [] with [List$1@{e: [1], tail: []}] +//│ [mono] │ adding these funcs to queue: Set(main$$5, generate) +//│ [mono] │ generate: (([*LIT*],100000)) -> [List$1@{e: [1], tail: ***}] @{main$$5, generate} +//│ [mono] └ SPEC CALL [List$1@{e: [1], tail: ***}] +//│ [mono] ┌ SPEC CALL foo with ([List$1@{e: [1], tail: ***}]) +//│ [mono] │ comparing (([],0)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) +//│ [mono] │ first time encounter foo +//│ [mono] │ evaluating foo, rests: HashSet(main$$5, main$$4, generate) +//│ [mono] │ ========== updating foo ========== +//│ [mono] │ foo: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [] @{main$$5} +//│ [mono] │ ┌ SPEC CALL count$List$1 with ([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}]) +//│ [mono] │ │ comparing (([],0)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) +//│ [mono] │ │ first time encounter count$List$1 +//│ [mono] │ │ evaluating count$List$1, rests: HashSet(main$$5, main$$4, generate) +//│ [mono] │ │ ========== updating count$List$1 ========== +//│ [mono] │ │ count$List$1: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [] @{foo} +//│ [mono] │ │ ┌ SPEC CALL count$List$1 with ([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}]) +//│ [mono] │ │ │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) +//│ [mono] │ │ └ SPEC CALL [] +//│ [mono] │ │ comparing [] with [*LIT*] +//│ [mono] │ │ adding these funcs to queue: Set(foo, count$List$1) +//│ [mono] │ │ count$List$1: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{foo, count$List$1} +//│ [mono] │ └ SPEC CALL [*LIT*] +//│ [mono] │ comparing [] with [*LIT*] +//│ [mono] │ adding these funcs to queue: Set(main$$5) +//│ [mono] │ foo: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{main$$5} +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [] with [*LIT*] +//│ [mono] adding these funcs to queue: Set() +//│ [mono] main$$5: () -> [*LIT*] @{} +//│ [mono] evaluating foo, rests: HashSet(count$List$1, main$$5, main$$4, generate) +//│ [mono] ========== updating foo ========== +//│ [mono] foo: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{main$$5} +//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}]) +//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] foo: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{main$$5} +//│ [mono] evaluating count$List$1, rests: HashSet(main$$5, main$$4, generate) +//│ [mono] ========== updating count$List$1 ========== +//│ [mono] count$List$1: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{foo, count$List$1} +//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}]) +//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] count$List$1: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{foo, count$List$1} +//│ [mono] evaluating main$$5, rests: HashSet(main$$4, generate) +//│ [mono] ========== updating main$$5 ========== +//│ [mono] main$$5: () -> [*LIT*] @{} +//│ [mono] ┌ SPEC CALL generate with ([1]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [List$1@{e: [1], tail: ***}] +//│ [mono] ┌ SPEC CALL foo with ([List$1@{e: [1], tail: ***}]) +//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] main$$5: () -> [*LIT*] @{} +//│ [mono] evaluating main$$4, rests: HashSet(generate) +//│ [mono] ========== updating main$$4 ========== +//│ [mono] main$$4: () -> [] @{} +//│ [mono] ┌ SPEC CALL foo with ([List$1@{e: [1], tail: [List$1@{e: [2], tail: [Nil$2@{}]}]}]) +//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}])) +//│ [mono] │ find finer args +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [] with [*LIT*] +//│ [mono] adding these funcs to queue: Set() +//│ [mono] main$$4: () -> [*LIT*] @{} +//│ [mono] evaluating foo, rests: HashSet(generate) +//│ [mono] ========== updating foo ========== +//│ [mono] foo: (([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}],3)) -> [*LIT*] @{main$$5, main$$4} +//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}]) +//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}])) +//│ [mono] │ find finer args +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] foo: (([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}],3)) -> [*LIT*] @{main$$5, main$$4} +//│ [mono] evaluating count$List$1, rests: HashSet(generate) +//│ [mono] ========== updating count$List$1 ========== +//│ [mono] count$List$1: (([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}],3)) -> [*LIT*] @{foo, count$List$1} +//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]) +//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}],3)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}])) +//│ [mono] │ find finer args +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] count$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) -> [*LIT*] @{foo, count$List$1} +//│ [mono] evaluating count$List$1, rests: HashSet(generate) +//│ [mono] ========== updating count$List$1 ========== +//│ [mono] count$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) -> [*LIT*] @{foo, count$List$1} +//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]) +//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] ┌ SPEC CALL count$Nil$2 with ([Nil$2@{}]) +//│ [mono] │ comparing (([],0)) with (Plain([Nil$2@{}])) +//│ [mono] │ first time encounter count$Nil$2 +//│ [mono] │ evaluating count$Nil$2, rests: HashSet(generate) +//│ [mono] │ ========== updating count$Nil$2 ========== +//│ [mono] │ count$Nil$2: (([Nil$2@{}],1)) -> [] @{count$List$1} +//│ [mono] │ comparing [] with [0] +//│ [mono] │ adding these funcs to queue: Set(count$List$1) +//│ [mono] │ count$Nil$2: (([Nil$2@{}],1)) -> [0] @{count$List$1} +//│ [mono] └ SPEC CALL [0] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] count$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) -> [*LIT*] @{foo, count$List$1} +//│ [mono] evaluating count$List$1, rests: HashSet(generate) +//│ [mono] ========== updating count$List$1 ========== +//│ [mono] count$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) -> [*LIT*] @{foo, count$List$1} +//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]) +//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] ┌ SPEC CALL count$Nil$2 with ([Nil$2@{}]) +//│ [mono] │ comparing (([Nil$2@{}],1)) with (Plain([Nil$2@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] count$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) -> [*LIT*] @{foo, count$List$1} +//│ [mono] evaluating generate, rests: HashSet() +//│ [mono] ========== updating generate ========== +//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [1], tail: ***}] @{main$$5, generate} +//│ [mono] ┌ SPEC CALL generate with ([*LIT*]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [List$1@{e: [1], tail: ***}] +//│ [mono] comparing [List$1@{e: [1], tail: ***}] with [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}] +//│ [mono] adding these funcs to queue: Set(main$$5, generate) +//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$5, generate} +//│ [mono] evaluating main$$5, rests: HashSet(generate) +//│ [mono] ========== updating main$$5 ========== +//│ [mono] main$$5: () -> [*LIT*] @{} +//│ [mono] ┌ SPEC CALL generate with ([1]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] +//│ [mono] ┌ SPEC CALL foo with ([List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]) +//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]}]}],3)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]} | Nil$2@{}])) +//│ [mono] │ find finer args +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] main$$5: () -> [*LIT*] @{} +//│ [mono] evaluating foo, rests: HashSet(generate) +//│ [mono] ========== updating foo ========== +//│ [mono] foo: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]} | Nil$2@{}],100003)) -> [*LIT*] @{main$$5, main$$4} +//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]}]) +//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]}],100002)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] ┌ SPEC CALL count$Nil$2 with ([Nil$2@{}]) +//│ [mono] │ comparing (([Nil$2@{}],1)) with (Plain([Nil$2@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] foo: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]} | Nil$2@{}],100003)) -> [*LIT*] @{main$$5, main$$4} +//│ [mono] evaluating generate, rests: HashSet() +//│ [mono] ========== updating generate ========== +//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$5, generate} +//│ [mono] ┌ SPEC CALL generate with ([*LIT*]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] +//│ [mono] comparing [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] with [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] +//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$5, generate} +//│ [mono] +//│ [mono] ==============final function signatures================== +//│ [mono] count$Nil$2: ([Nil$2@{}]) -> [0] +//│ [mono] foo: ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]} | Nil$2@{}]) -> [*LIT*] +//│ [mono] count$List$1: ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]}]) -> [*LIT*] +//│ [mono] main$$5: () -> [*LIT*] +//│ [mono] main$$4: () -> [*LIT*] +//│ [mono] generate: ([*LIT*]) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] + + +:mono +class E() { + fun derive(x) = new E + fun isEmpty() = 0 +} +class Ep(){ + fun derive(x) = new E + fun isEmpty() = 1 +} +class C(i){ + fun derive(x) = + if x < i then new Ep else new E + fun isEmpty() = 0 } -fun f(x: AnyFoo) = x.bar(42) -f(FooPlus(1)) -f(FooMinus(2)) -//│ |#trait| |AnyFoo| |{|→|#fun| |bar|(|b|#:| |int|)|#:| |int|←|↵|}|↵|#class| |FooPlus|(|##|a|#:| |int|)|#:| |AnyFoo| |{|→|#fun| |bar|(|b|#:| |int|)| |#=| |a| |+| |b|←|↵|}|↵|#class| |FooMinus|(|##|a|#:| |int|)|#:| |AnyFoo| |{|→|#fun| |Bar|(|b|#:| |int|)| |#=| |a| |-| |b|←|↵|}|↵|#fun| |f|(|x|#:| |AnyFoo|)| |#=| |x|.bar|(|42|)|↵|f|(|FooPlus|(|1|)|)|↵|f|(|FooMinus|(|2|)|)| -//│ Parsed: {trait AnyFoo(): {fun bar: [] -> (b: int,) -> int}; class FooPlus(#a: int,): AnyFoo {fun bar = b: int, => + (a,) (b,)}; class FooMinus(#a: int,): AnyFoo {fun Bar = b: int, => - (a,) (b,)}; fun f = x: AnyFoo, => (x).bar (42,); f (FooPlus (1,),); f (FooMinus (2,),)} +class A(e1, e2){ + fun derive(x) = new A(e1.derive(x), e2.derive(x)) + fun isEmpty() = e1.isEmpty() * e2.isEmpty() +} +fun gen(x) = + if x then new A(gen(x+1), new C(x)) else new E() +// (new A(new C(1), new A(new C(2), new C(3)))).derive(0).isEmpty() +gen(1).derive(0).isEmpty() +gen(1).isEmpty() +(new C(1)).derive(0).isEmpty() +//│ |#class| |E|(||)| |{|→|#fun| |derive|(|x|)| |#=| |#new| |E|↵|#fun| |isEmpty|(||)| |#=| |0|←|↵|}|↵|#class| |Ep|(||)|{|→|#fun| |derive|(|x|)| |#=| |#new| |E|↵|#fun| |isEmpty|(||)| |#=| |1|←|↵|}|↵|#class| |C|(|i|)|{|→|#fun| |derive|(|x|)| |#=| |→|#if| |x| |<| |i| |#then| |#new| |Ep| |#else| |#new| |E|←|↵|#fun| |isEmpty|(||)| |#=| |0|←|↵|}|↵|#class| |A|(|e1|,| |e2|)|{|→|#fun| |derive|(|x|)| |#=| |#new| |A|(|e1|.derive|(|x|)|,| |e2|.derive|(|x|)|)|↵|#fun| |isEmpty|(||)| |#=| |e1|.isEmpty|(||)| |*| |e2|.isEmpty|(||)|←|↵|}|↵|#fun| |gen|(|x|)| |#=| |→|#if| |x| |#then| |#new| |A|(|gen|(|x|+|1|)|,| |#new| |C|(|x|)|)| |#else| |#new| |E|(||)|←|↵|/* (new A(new C(1), new A(new C(2), new C(3)))).derive(0).isEmpty()*/|↵|gen|(|1|)|.derive|(|0|)|.isEmpty|(||)|↵|gen|(|1|)|.isEmpty|(||)|↵|(|#new| |C|(|1|)|)|.derive|(|0|)|.isEmpty|(||)| +//│ Parsed: {class E() {fun derive = x, => new E() {}; fun isEmpty = => 0}; class Ep() {fun derive = x, => new E() {}; fun isEmpty = => 1}; class C(i,) {fun derive = x, => {if (< (x,) (i,)) then new Ep() {} else new E() {}}; fun isEmpty = => 0}; class A(e1, e2,) {fun derive = x, => new A((e1).derive (x,), (e2).derive (x,),) {}; fun isEmpty = => * ((e1).isEmpty (),) ((e2).isEmpty (),)}; fun gen = x, => {if (x) then new A(gen (+ (x,) (1,),), new C(x,) {},) {} else new E() {}}; ((gen (1,)).derive (0,)).isEmpty (); (gen (1,)).isEmpty (); (('(' new C(1,) {}, ')').derive (0,)).isEmpty ()} //│ Parsed: -//│ TypingUnit(NuTypeDef(trait, AnyFoo, (), Tup(), (), TypingUnit(NuFunDef(None, bar, [], PolyType(List(),Function(Tuple(List((Some(b),Field(None,TypeName(int))))),TypeName(int)))))), NuTypeDef(class, FooPlus, (), Tup(a: Var(int)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(b: Var(int)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))))), NuTypeDef(class, FooMinus, (), Tup(a: Var(int)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, Bar, [], Lam(Tup(b: Var(int)), App(App(Var(-), Tup(_: Var(a))), Tup(_: Var(b))))))), NuFunDef(None, f, [], Lam(Tup(x: Var(AnyFoo)), App(Sel(Var(x), bar), Tup(_: IntLit(42))))), App(Var(f), Tup(_: App(Var(FooPlus), Tup(_: IntLit(1))))), App(Var(f), Tup(_: App(Var(FooMinus), Tup(_: IntLit(2)))))) +//│ TypingUnit(NuTypeDef(class, E, (), Tup(), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), New(Some((TypeName(E),)), TypingUnit(List())))), NuFunDef(None, isEmpty, [], Lam(Tup(), IntLit(0))))), NuTypeDef(class, Ep, (), Tup(), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), New(Some((TypeName(E),)), TypingUnit(List())))), NuFunDef(None, isEmpty, [], Lam(Tup(), IntLit(1))))), NuTypeDef(class, C, (), Tup(_: Var(i)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), IntLit(0))))), NuTypeDef(class, A, (), Tup(_: Var(e1), _: Var(e2)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), New(Some((TypeName(A),(e1).derive (x,), (e2).derive (x,),)), TypingUnit(List())))), NuFunDef(None, isEmpty, [], Lam(Tup(), App(App(Var(*), Tup(_: App(Sel(Var(e1), isEmpty), Tup()))), Tup(_: App(Sel(Var(e2), isEmpty), Tup()))))))), NuFunDef(None, gen, [], Lam(Tup(_: Var(x)), Blk(...))), App(Sel(App(Sel(App(Var(gen), Tup(_: IntLit(1))), derive), Tup(_: IntLit(0))), isEmpty), Tup()), App(Sel(App(Var(gen), Tup(_: IntLit(1))), isEmpty), Tup()), App(Sel(App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(C),1,)), TypingUnit(List())))), derive), Tup(_: IntLit(0))), isEmpty), Tup())) //│ Lifted: //│ TypingUnit { -//│ trait AnyFoo$1() {fun bar = (b: int,) -> int} -//│ class FooPlus$2(#a: int,): AnyFoo$1 () {fun bar = b: int, => + ((this).a,) (b,)} -//│ class FooMinus$3(#a: int,): AnyFoo$1 () {fun Bar = b: int, => - ((this).a,) (b,)} -//│ fun f = x: AnyFoo$1, => (x).bar (42,) -//│ Code(List(f (FooPlus$2 (1,),))) -//│ Code(List(f (FooMinus$3 (2,),))) +//│ class E$1() {fun derive = x, => new E$1() {}; fun isEmpty = => 0} +//│ class Ep$2() {fun derive = x, => new E$1() {}; fun isEmpty = => 1} +//│ class C$3(i,) { +//│ fun derive = x, => {if (< (x,) ((this).i,)) then new Ep$2() {} else new E$1() {}} +//│ fun isEmpty = => 0 +//│ } +//│ class A$4(e1, e2,) { +//│ fun derive = x, => new A$4(((this).e1).derive (x,), ((this).e2).derive (x,),) {} +//│ fun isEmpty = => * (((this).e1).isEmpty (),) (((this).e2).isEmpty (),) +//│ } +//│ fun gen = x, => {if (x) then new A$4(gen (+ (x,) (1,),), new C$3(x,) {},) {} else new E$1() {}} +//│ Code(List(((gen (1,)).derive (0,)).isEmpty ())) +//│ Code(List((gen (1,)).isEmpty ())) +//│ Code(List((('(' new C$3(1,) {}, ')').derive (0,)).isEmpty ())) //│ } //│ Mono: -//│ fun f(AnyFoo$1) = -//│ x.bar(42) -//│ f(FooPlus$2__1()) -//│ f(FooMinus$3__2()) -//│ class FooPlus$2() { +//│ +//│ Mono result: +//│ main$$5() +//│ main$$6() +//│ main$$7() +//│ fun isEmpty$Ep$2(this) = +//│ #1 +//│ fun gen(x) = +//│ if x then new A$4 (gen((x + #1)), new C$3 (x) ) else new E$1 () +//│ fun isEmpty$C$3(this) = +//│ #0 +//│ fun isEmpty$E$1(this) = +//│ #0 +//│ fun isEmpty$A$4(this) = +//│ (this.e1 match {case obj: A$4 => isEmpty$A$4(obj); case obj: E$1 => isEmpty$E$1(obj)} * this.e2 match {case obj: C$3 => isEmpty$C$3(obj); case obj: Ep$2 => isEmpty$Ep$2(obj); case obj: E$1 => isEmpty$E$1(obj)}) +//│ fun derive$A$4(this, x) = +//│ new A$4 (this.e1 match {case obj: A$4 => derive$A$4(obj, x); case obj: E$1 => derive$E$1(obj, x)}, this.e2 match {case obj: C$3 => derive$C$3(obj, x)}) +//│ fun derive$E$1(this, x) = +//│ new E$1 () +//│ fun derive$C$3(this, x) = +//│ if (x < this.i) then new Ep$2 () else new E$1 () +//│ fun main$$7() = +//│ new C$3 (#1) match {case obj: C$3 => derive$C$3(obj, #0)} match {case obj: Ep$2 => isEmpty$Ep$2(obj); case obj: E$1 => isEmpty$E$1(obj)} +//│ fun main$$6() = +//│ gen(#1) match {case obj: A$4 => isEmpty$A$4(obj); case obj: E$1 => isEmpty$E$1(obj)} +//│ fun main$$5() = +//│ gen(#1) match {case obj: A$4 => derive$A$4(obj, #0); case obj: E$1 => derive$E$1(obj, #0)} match {case obj: A$4 => isEmpty$A$4(obj); case obj: E$1 => isEmpty$E$1(obj)} +//│ [mono] evaluating main$$7, rests: HashSet(main$$6, main$$5) +//│ [mono] ========== updating main$$7 ========== +//│ [mono] main$$7: () -> [] @{} +//│ [mono] ┌ SPEC CALL derive$C$3 with ([C$3@{i: [1]}], [0]) +//│ [mono] │ comparing (([],0), ([],0)) with (Plain([C$3@{i: [1]}]), Plain([0])) +//│ [mono] │ first time encounter derive$C$3 +//│ [mono] │ evaluating derive$C$3, rests: HashSet(main$$6, main$$5) +//│ [mono] │ ========== updating derive$C$3 ========== +//│ [mono] │ derive$C$3: (([C$3@{i: [1]}],2) X ([0],1)) -> [] @{main$$7} +//│ [mono] │ ┌ SPEC CALL < with ([0]) +//│ [mono] │ │ !!!!!!! +//│ [mono] │ │ calling unknown function <([0]) +//│ [mono] │ │ Set(gen, derive$C$3, main$$7, main$$6, main$$5) +//│ [mono] │ └ SPEC CALL [?1?] +//│ [mono] │ comparing [] with [E$1@{} | Ep$2@{}] +//│ [mono] │ adding these funcs to queue: Set(main$$7) +//│ [mono] │ derive$C$3: (([C$3@{i: [1]}],2) X ([0],1)) -> [E$1@{} | Ep$2@{}] @{main$$7} +//│ [mono] └ SPEC CALL [E$1@{} | Ep$2@{}] +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([],0)) with (Plain([E$1@{}])) +//│ [mono] │ first time encounter isEmpty$E$1 +//│ [mono] │ evaluating isEmpty$E$1, rests: HashSet(main$$7, main$$6, main$$5) +//│ [mono] │ ========== updating isEmpty$E$1 ========== +//│ [mono] │ isEmpty$E$1: (([E$1@{}],1)) -> [] @{main$$7} +//│ [mono] │ comparing [] with [0] +//│ [mono] │ adding these funcs to queue: Set(main$$7) +//│ [mono] │ isEmpty$E$1: (([E$1@{}],1)) -> [0] @{main$$7} +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$Ep$2 with ([Ep$2@{}]) +//│ [mono] │ comparing (([],0)) with (Plain([Ep$2@{}])) +//│ [mono] │ first time encounter isEmpty$Ep$2 +//│ [mono] │ evaluating isEmpty$Ep$2, rests: HashSet(main$$7, main$$6, main$$5) +//│ [mono] │ ========== updating isEmpty$Ep$2 ========== +//│ [mono] │ isEmpty$Ep$2: (([Ep$2@{}],1)) -> [] @{main$$7} +//│ [mono] │ comparing [] with [1] +//│ [mono] │ adding these funcs to queue: Set(main$$7) +//│ [mono] │ isEmpty$Ep$2: (([Ep$2@{}],1)) -> [1] @{main$$7} +//│ [mono] └ SPEC CALL [1] +//│ [mono] comparing [] with [*LIT*] +//│ [mono] adding these funcs to queue: Set() +//│ [mono] main$$7: () -> [*LIT*] @{} +//│ [mono] evaluating main$$7, rests: HashSet(main$$6, main$$5) +//│ [mono] ========== updating main$$7 ========== +//│ [mono] main$$7: () -> [*LIT*] @{} +//│ [mono] ┌ SPEC CALL derive$C$3 with ([C$3@{i: [1]}], [0]) +//│ [mono] │ comparing (([C$3@{i: [1]}],2), ([0],1)) with (Plain([C$3@{i: [1]}]), Plain([0])) +//│ [mono] └ SPEC CALL [E$1@{} | Ep$2@{}] +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$Ep$2 with ([Ep$2@{}]) +//│ [mono] │ comparing (([Ep$2@{}],1)) with (Plain([Ep$2@{}])) +//│ [mono] └ SPEC CALL [1] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] main$$7: () -> [*LIT*] @{} +//│ [mono] evaluating main$$6, rests: HashSet(main$$5) +//│ [mono] ========== updating main$$6 ========== +//│ [mono] main$$6: () -> [] @{} +//│ [mono] ┌ SPEC CALL gen with ([1]) +//│ [mono] │ comparing (([],0)) with (Plain([1])) +//│ [mono] │ first time encounter gen +//│ [mono] │ evaluating gen, rests: HashSet(main$$5) +//│ [mono] │ ========== updating gen ========== +//│ [mono] │ gen: (([1],1)) -> [] @{main$$6} +//│ [mono] │ ┌ SPEC CALL gen with ([2]) +//│ [mono] │ │ comparing (([1],1)) with (Plain([*LIT*])) +//│ [mono] │ │ find finer args +//│ [mono] │ └ SPEC CALL [] +//│ [mono] │ comparing [] with [E$1@{} | A$4@{e1: [], e2: [C$3@{i: [1]}]}] +//│ [mono] │ adding these funcs to queue: Set(main$$6, gen) +//│ [mono] │ gen: (([*LIT*],100000)) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}] @{main$$6, gen} +//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}] +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}]) +//│ [mono] │ comparing (([],0)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}])) +//│ [mono] │ first time encounter isEmpty$A$4 +//│ [mono] │ evaluating isEmpty$A$4, rests: HashSet(gen, main$$6, main$$5) +//│ [mono] │ ========== updating isEmpty$A$4 ========== +//│ [mono] │ isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}],4)) -> [] @{main$$6} +//│ [mono] │ ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] │ └ SPEC CALL [0] +//│ [mono] │ ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}]) +//│ [mono] │ │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}],4)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}])) +//│ [mono] │ └ SPEC CALL [] +//│ [mono] │ ┌ SPEC CALL isEmpty$C$3 with ([C$3@{i: [1]}]) +//│ [mono] │ │ comparing (([],0)) with (Plain([C$3@{i: [1]}])) +//│ [mono] │ │ first time encounter isEmpty$C$3 +//│ [mono] │ │ evaluating isEmpty$C$3, rests: HashSet(gen, main$$6, main$$5) +//│ [mono] │ │ ========== updating isEmpty$C$3 ========== +//│ [mono] │ │ isEmpty$C$3: (([C$3@{i: [1]}],2)) -> [] @{isEmpty$A$4} +//│ [mono] │ │ comparing [] with [0] +//│ [mono] │ │ adding these funcs to queue: Set(isEmpty$A$4) +//│ [mono] │ │ isEmpty$C$3: (([C$3@{i: [1]}],2)) -> [0] @{isEmpty$A$4} +//│ [mono] │ └ SPEC CALL [0] +//│ [mono] │ comparing [] with [0] +//│ [mono] │ adding these funcs to queue: Set(main$$6, isEmpty$A$4) +//│ [mono] │ isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}],4)) -> [0] @{main$$6, isEmpty$A$4} +//│ [mono] └ SPEC CALL [0] +//│ [mono] comparing [] with [0] +//│ [mono] adding these funcs to queue: Set() +//│ [mono] main$$6: () -> [0] @{} +//│ [mono] evaluating gen, rests: HashSet(isEmpty$A$4, main$$6, main$$5) +//│ [mono] ========== updating gen ========== +//│ [mono] gen: (([*LIT*],100000)) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}] @{main$$6, gen} +//│ [mono] ┌ SPEC CALL gen with ([*LIT*]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}] +//│ [mono] comparing [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}] with [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [*LIT*]}]}] +//│ [mono] adding these funcs to queue: Set(main$$6, gen) +//│ [mono] gen: (([*LIT*],100000)) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] @{main$$6, gen} +//│ [mono] evaluating gen, rests: HashSet(isEmpty$A$4, main$$6, main$$5) +//│ [mono] ========== updating gen ========== +//│ [mono] gen: (([*LIT*],100000)) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] @{main$$6, gen} +//│ [mono] ┌ SPEC CALL gen with ([*LIT*]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] +//│ [mono] comparing [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] with [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}] +//│ [mono] gen: (([*LIT*],100000)) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] @{main$$6, gen} +//│ [mono] evaluating isEmpty$A$4, rests: HashSet(main$$6, main$$5) +//│ [mono] ========== updating isEmpty$A$4 ========== +//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],4)) -> [0] @{main$$6, isEmpty$A$4} +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]) +//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],4)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}])) +//│ [mono] │ find finer args +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$C$3 with ([C$3@{i: [*LIT*]}]) +//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],2)) with (Plain([C$3@{i: [*LIT*]}])) +//│ [mono] │ find finer args +//│ [mono] └ SPEC CALL [0] +//│ [mono] comparing [0] with [0] +//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) -> [*LIT*] @{main$$6, isEmpty$A$4} +//│ [mono] evaluating isEmpty$C$3, rests: HashSet(isEmpty$A$4, main$$6, main$$5) +//│ [mono] ========== updating isEmpty$C$3 ========== +//│ [mono] isEmpty$C$3: (([C$3@{i: [*LIT*]}],100001)) -> [0] @{isEmpty$A$4} +//│ [mono] comparing [0] with [0] +//│ [mono] isEmpty$C$3: (([C$3@{i: [*LIT*]}],100001)) -> [*LIT*] @{isEmpty$A$4} +//│ [mono] evaluating isEmpty$A$4, rests: HashSet(main$$6, main$$5) +//│ [mono] ========== updating isEmpty$A$4 ========== +//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) -> [*LIT*] @{main$$6, isEmpty$A$4} +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]) +//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] ┌ SPEC CALL isEmpty$C$3 with ([C$3@{i: [*LIT*]}]) +//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],100001)) with (Plain([C$3@{i: [*LIT*]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) -> [*LIT*] @{main$$6, isEmpty$A$4} +//│ [mono] evaluating main$$6, rests: HashSet(main$$5) +//│ [mono] ========== updating main$$6 ========== +//│ [mono] main$$6: () -> [0] @{} +//│ [mono] ┌ SPEC CALL gen with ([1]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]) +//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [0] with [*LIT*] +//│ [mono] adding these funcs to queue: Set() +//│ [mono] main$$6: () -> [*LIT*] @{} +//│ [mono] evaluating main$$5, rests: HashSet() +//│ [mono] ========== updating main$$5 ========== +//│ [mono] main$$5: () -> [] @{} +//│ [mono] ┌ SPEC CALL gen with ([1]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] +//│ [mono] ┌ SPEC CALL derive$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], [0]) +//│ [mono] │ comparing (([],0), ([],0)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]), Plain([0])) +//│ [mono] │ first time encounter derive$A$4 +//│ [mono] │ evaluating derive$A$4, rests: HashSet() +//│ [mono] │ ========== updating derive$A$4 ========== +//│ [mono] │ derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [] @{main$$5} +//│ [mono] │ ┌ SPEC CALL derive$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], [0]) +//│ [mono] │ │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003), ([0],1)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]), Plain([0])) +//│ [mono] │ └ SPEC CALL [] +//│ [mono] │ ┌ SPEC CALL derive$E$1 with ([E$1@{}], [0]) +//│ [mono] │ │ comparing (([],0), ([],0)) with (Plain([E$1@{}]), Plain([0])) +//│ [mono] │ │ first time encounter derive$E$1 +//│ [mono] │ │ evaluating derive$E$1, rests: HashSet() +//│ [mono] │ │ ========== updating derive$E$1 ========== +//│ [mono] │ │ derive$E$1: (([E$1@{}],1) X ([0],1)) -> [] @{derive$A$4} +//│ [mono] │ │ comparing [] with [E$1@{}] +//│ [mono] │ │ adding these funcs to queue: Set(derive$A$4) +//│ [mono] │ │ derive$E$1: (([E$1@{}],1) X ([0],1)) -> [E$1@{}] @{derive$A$4} +//│ [mono] │ └ SPEC CALL [E$1@{}] +//│ [mono] │ ┌ SPEC CALL derive$C$3 with ([C$3@{i: [*LIT*]}], [0]) +//│ [mono] │ │ comparing (([C$3@{i: [1]}],2), ([0],1)) with (Plain([C$3@{i: [*LIT*]}]), Plain([0])) +//│ [mono] │ │ find finer args +//│ [mono] │ └ SPEC CALL [E$1@{} | Ep$2@{}] +//│ [mono] │ comparing [] with [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] +//│ [mono] │ adding these funcs to queue: Set(main$$5, derive$A$4) +//│ [mono] │ derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] @{main$$5, derive$A$4} +//│ [mono] └ SPEC CALL [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] +//│ [mono] ┌ SPEC CALL derive$E$1 with ([E$1@{}], [0]) +//│ [mono] │ comparing (([E$1@{}],1), ([0],1)) with (Plain([E$1@{}]), Plain([0])) +//│ [mono] └ SPEC CALL [E$1@{}] +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}]) +//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}])) +//│ [mono] │ find finer args +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [] with [*LIT*] +//│ [mono] adding these funcs to queue: Set() +//│ [mono] main$$5: () -> [*LIT*] @{} +//│ [mono] evaluating isEmpty$A$4, rests: HashSet(derive$A$4, derive$C$3, main$$5) +//│ [mono] ========== updating isEmpty$A$4 ========== +//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) -> [*LIT*] @{main$$6, isEmpty$A$4, main$$5} +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]) +//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$C$3 with ([C$3@{i: [*LIT*]}]) +//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],100001)) with (Plain([C$3@{i: [*LIT*]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] ┌ SPEC CALL isEmpty$Ep$2 with ([Ep$2@{}]) +//│ [mono] │ comparing (([Ep$2@{}],1)) with (Plain([Ep$2@{}])) +//│ [mono] └ SPEC CALL [1] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) -> [*LIT*] @{main$$6, isEmpty$A$4, main$$5} +//│ [mono] evaluating derive$A$4, rests: HashSet(derive$C$3, main$$5) +//│ [mono] ========== updating derive$A$4 ========== +//│ [mono] derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] @{main$$5, derive$A$4} +//│ [mono] ┌ SPEC CALL derive$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], [0]) +//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003), ([0],1)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]), Plain([0])) +//│ [mono] └ SPEC CALL [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] +//│ [mono] ┌ SPEC CALL derive$E$1 with ([E$1@{}], [0]) +//│ [mono] │ comparing (([E$1@{}],1), ([0],1)) with (Plain([E$1@{}]), Plain([0])) +//│ [mono] └ SPEC CALL [E$1@{}] +//│ [mono] ┌ SPEC CALL derive$C$3 with ([C$3@{i: [*LIT*]}], [0]) +//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],100001), ([0],1)) with (Plain([C$3@{i: [*LIT*]}]), Plain([0])) +//│ [mono] └ SPEC CALL [E$1@{} | Ep$2@{}] +//│ [mono] comparing [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] with [A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] +//│ [mono] adding these funcs to queue: Set(main$$5, derive$A$4) +//│ [mono] derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] @{main$$5, derive$A$4} +//│ [mono] evaluating derive$A$4, rests: HashSet(derive$C$3, main$$5) +//│ [mono] ========== updating derive$A$4 ========== +//│ [mono] derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] @{main$$5, derive$A$4} +//│ [mono] ┌ SPEC CALL derive$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], [0]) +//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003), ([0],1)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]), Plain([0])) +//│ [mono] └ SPEC CALL [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] +//│ [mono] ┌ SPEC CALL derive$E$1 with ([E$1@{}], [0]) +//│ [mono] │ comparing (([E$1@{}],1), ([0],1)) with (Plain([E$1@{}]), Plain([0])) +//│ [mono] └ SPEC CALL [E$1@{}] +//│ [mono] ┌ SPEC CALL derive$C$3 with ([C$3@{i: [*LIT*]}], [0]) +//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],100001), ([0],1)) with (Plain([C$3@{i: [*LIT*]}]), Plain([0])) +//│ [mono] └ SPEC CALL [E$1@{} | Ep$2@{}] +//│ [mono] comparing [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] with [A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] +//│ [mono] derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] @{main$$5, derive$A$4} +//│ [mono] evaluating derive$C$3, rests: HashSet(main$$5) +//│ [mono] ========== updating derive$C$3 ========== +//│ [mono] derive$C$3: (([C$3@{i: [*LIT*]}],100001) X ([0],1)) -> [E$1@{} | Ep$2@{}] @{main$$7, derive$A$4} +//│ [mono] ┌ SPEC CALL < with ([0]) +//│ [mono] │ !!!!!!! +//│ [mono] │ calling unknown function <([0]) +//│ [mono] │ Set(isEmpty$Ep$2, gen, isEmpty$C$3, isEmpty$E$1, isEmpty$A$4, derive$A$4, derive$E$1, derive$C$3, main$$7, main$$6, main$$5) +//│ [mono] └ SPEC CALL [?3?] +//│ [mono] comparing [E$1@{} | Ep$2@{}] with [E$1@{} | Ep$2@{}] +//│ [mono] derive$C$3: (([C$3@{i: [*LIT*]}],100001) X ([0],1)) -> [E$1@{} | Ep$2@{}] @{main$$7, derive$A$4} +//│ [mono] evaluating main$$5, rests: HashSet() +//│ [mono] ========== updating main$$5 ========== +//│ [mono] main$$5: () -> [*LIT*] @{} +//│ [mono] ┌ SPEC CALL gen with ([1]) +//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) +//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] +//│ [mono] ┌ SPEC CALL derive$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], [0]) +//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003), ([0],1)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]), Plain([0])) +//│ [mono] └ SPEC CALL [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] +//│ [mono] ┌ SPEC CALL derive$E$1 with ([E$1@{}], [0]) +//│ [mono] │ comparing (([E$1@{}],1), ([0],1)) with (Plain([E$1@{}]), Plain([0])) +//│ [mono] └ SPEC CALL [E$1@{}] +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}]) +//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}])) +//│ [mono] │ find finer args +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] main$$5: () -> [*LIT*] @{} +//│ [mono] evaluating isEmpty$A$4, rests: HashSet() +//│ [mono] ========== updating isEmpty$A$4 ========== +//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) -> [*LIT*] @{main$$6, isEmpty$A$4, main$$5} +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}]) +//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) +//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) +//│ [mono] └ SPEC CALL [0] +//│ [mono] ┌ SPEC CALL isEmpty$C$3 with ([C$3@{i: [*LIT*]}]) +//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],100001)) with (Plain([C$3@{i: [*LIT*]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] ┌ SPEC CALL isEmpty$Ep$2 with ([Ep$2@{}]) +//│ [mono] │ comparing (([Ep$2@{}],1)) with (Plain([Ep$2@{}])) +//│ [mono] └ SPEC CALL [1] +//│ [mono] comparing [*LIT*] with [*LIT*] +//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) -> [*LIT*] @{main$$6, isEmpty$A$4, main$$5} +//│ [mono] +//│ [mono] ==============final function signatures================== +//│ [mono] isEmpty$Ep$2: ([Ep$2@{}]) -> [1] +//│ [mono] gen: ([*LIT*]) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] +//│ [mono] isEmpty$C$3: ([C$3@{i: [*LIT*]}]) -> [*LIT*] +//│ [mono] isEmpty$E$1: ([E$1@{}]) -> [0] +//│ [mono] isEmpty$A$4: ([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}]) -> [*LIT*] +//│ [mono] derive$A$4: ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}] X [0]) -> [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] +//│ [mono] derive$E$1: ([E$1@{}] X [0]) -> [E$1@{}] +//│ [mono] derive$C$3: ([C$3@{i: [*LIT*]}] X [0]) -> [E$1@{} | Ep$2@{}] +//│ [mono] main$$7: () -> [*LIT*] +//│ [mono] main$$6: () -> [*LIT*] +//│ [mono] main$$5: () -> [*LIT*] + + +// :mono +class List(l, hasTail) {} +class Nil(hasTail) {} +fun gen() = + if anyUnknown then new List(gen(), true) else new Nil(false) +gen() +//│ |#class| |List|(|l|,| |hasTail|)| |{||}|↵|#class| |Nil|(|hasTail|)| |{||}|↵|#fun| |gen|(||)| |#=| |→|#if| |anyUnknown| |#then| |#new| |List|(|gen|(||)|,| |true|)| |#else| |#new| |Nil|(|false|)|←|↵|gen|(||)| +//│ Parsed: {class List(l, hasTail,) {}; class Nil(hasTail,) {}; fun gen = => {if (anyUnknown) then new List(gen (), true,) {} else new Nil(false,) {}}; gen ()} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(l), _: Var(hasTail)), (), TypingUnit()), NuTypeDef(class, Nil, (), Tup(_: Var(hasTail)), (), TypingUnit()), NuFunDef(None, gen, [], Lam(Tup(), Blk(...))), App(Var(gen), Tup())) +//│ Lifted: +//│ TypingUnit { +//│ class List$1(l, hasTail,) {} +//│ class Nil$2(hasTail,) {} +//│ fun gen = => {if (anyUnknown) then new List$1(gen (), true,) {} else new Nil$2(false,) {}} +//│ Code(List(gen ())) +//│ } + + + +// :mono +class Foo(x){ + fun bar(y) = x+y + fun boo(z) = bar(z)+x +} +(new Foo(1)).boo(2) +//│ |#class| |Foo|(|x|)|{|→|#fun| |bar|(|y|)| |#=| |x|+|y|↵|#fun| |boo|(|z|)| |#=| |bar|(|z|)|+|x|←|↵|}|↵|(|#new| |Foo|(|1|)|)|.boo|(|2|)| +//│ Parsed: {class Foo(x,) {fun bar = y, => + (x,) (y,); fun boo = z, => + (bar (z,),) (x,)}; ('(' new Foo(1,) {}, ')').boo (2,)} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(_: Var(x)), (), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(y)), App(App(Var(+), Tup(_: Var(x))), Tup(_: Var(y))))), NuFunDef(None, boo, [], Lam(Tup(_: Var(z)), App(App(Var(+), Tup(_: App(Var(bar), Tup(_: Var(z))))), Tup(_: Var(x))))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Foo),1,)), TypingUnit(List())))), boo), Tup(_: IntLit(2)))) +//│ Lifted: +//│ TypingUnit { +//│ class Foo$1(x,) { +//│ fun bar = y, => + ((this).x,) (y,) +//│ fun boo = z, => + ((this).bar (z,),) ((this).x,) +//│ } +//│ Code(List(('(' new Foo$1(1,) {}, ')').boo (2,))) //│ } -//│ class FooPlus$2__1(): FooPlus$2() { -//│ fun bar(int) = -//│ (this.a + b) + +:mono +class OneInt(a){ + fun fac() = + if(a > 0) then (new OneInt(a-1)).fac() else 1 +} +(new OneInt(10)).fac() +//│ |#class| |OneInt|(|a|)|{|→|#fun| |fac|(||)| |#=| |→|#if|(|a| |>| |0|)| |#then| |(|#new| |OneInt|(|a|-|1|)|)|.fac|(||)| |#else| |1| |←|←|↵|}|↵|(|#new| |OneInt|(|10|)|)|.fac|(||)| +//│ Parsed: {class OneInt(a,) {fun fac = => {if ('(' > (a,) (0,), ')') then ('(' new OneInt(- (a,) (1,),) {}, ')').fac () else 1}}; ('(' new OneInt(10,) {}, ')').fac ()} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, fac, [], Lam(Tup(), Blk(...))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(OneInt),10,)), TypingUnit(List())))), fac), Tup())) +//│ Lifted: +//│ TypingUnit { +//│ class OneInt$1(a,) { +//│ fun fac = => {if ('(' > ((this).a,) (0,), ')') then ('(' new OneInt$1(- ((this).a,) (1,),) {}, ')').fac () else 1} +//│ } +//│ Code(List(('(' new OneInt$1(10,) {}, ')').fac ())) //│ } -//│ class FooMinus$3() { +//│ Mono: +//│ +//│ Mono result: +//│ main$$1() +//│ fun fac$OneInt$1(this) = +//│ if (this.a > #0) then new OneInt$1 ((this.a - #1)) match {case obj: OneInt$1 => fac$OneInt$1(obj)} else #1 +//│ fun main$$1() = +//│ new OneInt$1 (#10) match {case obj: OneInt$1 => fac$OneInt$1(obj)} +//│ [mono] evaluating main$$1, rests: HashSet() +//│ [mono] ========== updating main$$1 ========== +//│ [mono] main$$1: () -> [] @{} +//│ [mono] ┌ SPEC CALL fac$OneInt$1 with ([OneInt$1@{a: [10]}]) +//│ [mono] │ comparing (([],0)) with (Plain([OneInt$1@{a: [10]}])) +//│ [mono] │ first time encounter fac$OneInt$1 +//│ [mono] │ evaluating fac$OneInt$1, rests: HashSet() +//│ [mono] │ ========== updating fac$OneInt$1 ========== +//│ [mono] │ fac$OneInt$1: (([OneInt$1@{a: [10]}],2)) -> [] @{main$$1} +//│ [mono] │ ┌ SPEC CALL fac$OneInt$1 with ([OneInt$1@{a: [9]}]) +//│ [mono] │ │ comparing (([OneInt$1@{a: [10]}],2)) with (Plain([OneInt$1@{a: [*LIT*]}])) +//│ [mono] │ │ find finer args +//│ [mono] │ └ SPEC CALL [] +//│ [mono] │ comparing [] with [] +//│ [mono] │ fac$OneInt$1: (([OneInt$1@{a: [*LIT*]}],100001)) -> [] @{main$$1, fac$OneInt$1} +//│ [mono] └ SPEC CALL [] +//│ [mono] comparing [] with [] +//│ [mono] main$$1: () -> [] @{} +//│ [mono] evaluating fac$OneInt$1, rests: HashSet() +//│ [mono] ========== updating fac$OneInt$1 ========== +//│ [mono] fac$OneInt$1: (([OneInt$1@{a: [*LIT*]}],100001)) -> [] @{main$$1, fac$OneInt$1} +//│ [mono] ┌ SPEC CALL fac$OneInt$1 with ([OneInt$1@{a: [*LIT*]}]) +//│ [mono] │ comparing (([OneInt$1@{a: [*LIT*]}],100001)) with (Plain([OneInt$1@{a: [*LIT*]}])) +//│ [mono] └ SPEC CALL [] +//│ [mono] comparing [] with [1] +//│ [mono] adding these funcs to queue: Set(main$$1, fac$OneInt$1) +//│ [mono] fac$OneInt$1: (([OneInt$1@{a: [*LIT*]}],100001)) -> [1] @{main$$1, fac$OneInt$1} +//│ [mono] evaluating fac$OneInt$1, rests: HashSet(main$$1) +//│ [mono] ========== updating fac$OneInt$1 ========== +//│ [mono] fac$OneInt$1: (([OneInt$1@{a: [*LIT*]}],100001)) -> [1] @{main$$1, fac$OneInt$1} +//│ [mono] ┌ SPEC CALL fac$OneInt$1 with ([OneInt$1@{a: [*LIT*]}]) +//│ [mono] │ comparing (([OneInt$1@{a: [*LIT*]}],100001)) with (Plain([OneInt$1@{a: [*LIT*]}])) +//│ [mono] └ SPEC CALL [1] +//│ [mono] comparing [1] with [1] +//│ [mono] fac$OneInt$1: (([OneInt$1@{a: [*LIT*]}],100001)) -> [*LIT*] @{main$$1, fac$OneInt$1} +//│ [mono] evaluating main$$1, rests: HashSet() +//│ [mono] ========== updating main$$1 ========== +//│ [mono] main$$1: () -> [] @{} +//│ [mono] ┌ SPEC CALL fac$OneInt$1 with ([OneInt$1@{a: [10]}]) +//│ [mono] │ comparing (([OneInt$1@{a: [*LIT*]}],100001)) with (Plain([OneInt$1@{a: [*LIT*]}])) +//│ [mono] └ SPEC CALL [*LIT*] +//│ [mono] comparing [] with [*LIT*] +//│ [mono] adding these funcs to queue: Set() +//│ [mono] main$$1: () -> [*LIT*] @{} +//│ [mono] +//│ [mono] ==============final function signatures================== +//│ [mono] fac$OneInt$1: ([OneInt$1@{a: [*LIT*]}]) -> [*LIT*] +//│ [mono] main$$1: () -> [*LIT*] + +// :mono +trait AnyFoo { + fun bar(b): int +} +class FooPlus(#a): AnyFoo { + fun bar(b) = a + b +} +class FooMinus(#a): AnyFoo { + fun bar(b) = a - b +} +fun f(x) = x.bar(42) +f(new FooPlus(1)) +f(new FooMinus(2)) +//│ |#trait| |AnyFoo| |{|→|#fun| |bar|(|b|)|#:| |int|←|↵|}|↵|#class| |FooPlus|(|##|a|)|#:| |AnyFoo| |{|→|#fun| |bar|(|b|)| |#=| |a| |+| |b|←|↵|}|↵|#class| |FooMinus|(|##|a|)|#:| |AnyFoo| |{|→|#fun| |bar|(|b|)| |#=| |a| |-| |b|←|↵|}|↵|#fun| |f|(|x|)| |#=| |x|.bar|(|42|)|↵|f|(|#new| |FooPlus|(|1|)|)|↵|f|(|#new| |FooMinus|(|2|)|)| +//│ Parsed: {trait AnyFoo(): {fun bar: [] -> b -> int}; class FooPlus(#a,): AnyFoo {fun bar = b, => + (a,) (b,)}; class FooMinus(#a,): AnyFoo {fun bar = b, => - (a,) (b,)}; fun f = x, => (x).bar (42,); f (new FooPlus(1,) {},); f (new FooMinus(2,) {},)} +//│ Parsed: +//│ TypingUnit(NuTypeDef(trait, AnyFoo, (), Tup(), (), TypingUnit(NuFunDef(None, bar, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(b))))),TypeName(int)))))), NuTypeDef(class, FooPlus, (), Tup(_: Var(a)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(b)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))))), NuTypeDef(class, FooMinus, (), Tup(_: Var(a)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(b)), App(App(Var(-), Tup(_: Var(a))), Tup(_: Var(b))))))), NuFunDef(None, f, [], Lam(Tup(_: Var(x)), App(Sel(Var(x), bar), Tup(_: IntLit(42))))), App(Var(f), Tup(_: New(Some((TypeName(FooPlus),1,)), TypingUnit(List())))), App(Var(f), Tup(_: New(Some((TypeName(FooMinus),2,)), TypingUnit(List()))))) +//│ Lifted: +//│ TypingUnit { +//│ trait AnyFoo$1[b]() {fun bar = b -> int} +//│ class FooPlus$2[b](#a,): AnyFoo$1 () {fun bar = b, => + ((this).a,) (b,)} +//│ class FooMinus$3[b](#a,): AnyFoo$1 () {fun bar = b, => - ((this).a,) (b,)} +//│ fun f = x, => (x).bar (42,) +//│ Code(List(f (new FooPlus$2(1,) {},))) +//│ Code(List(f (new FooMinus$3(2,) {},))) //│ } -//│ class FooMinus$3__2(): FooMinus$3() { -//│ fun Bar(int) = -//│ (this.a - b) + +// :mono +fun f(x) = + if x > any then 0 + else g(x-1) +fun g(x) = + if x > any then g(x-1) + else f(x-2) +g(1) +//│ |#fun| |f|(|x|)| |#=| |→|#if| |x| |>| |any| |#then| |0|↵|#else| |g|(|x|-|1|)|←|↵|#fun| |g|(|x|)| |#=| |→|#if| |x| |>| |any| |#then| |g|(|x|-|1|)|↵|#else| |f|(|x|-|2|)|←|↵|g|(|1|)| +//│ Parsed: {fun f = x, => {if (> (x,) (any,)) then 0 else g (- (x,) (1,),)}; fun g = x, => {if (> (x,) (any,)) then g (- (x,) (1,),) else f (- (x,) (2,),)}; g (1,)} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, g, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(g), Tup(_: IntLit(1)))) +//│ Lifted: +//│ TypingUnit { +//│ fun f = x, => {if (> (x,) (any,)) then 0 else g (- (x,) (1,),)} +//│ fun g = x, => {if (> (x,) (any,)) then g (- (x,) (1,),) else f (- (x,) (2,),)} +//│ Code(List(g (1,))) //│ } -:mono +// :mono +class OneInt(a){ + fun get = a +} +class OneBool(b){ + fun get = b +} +(if b then new OneInt(1) else new OneBool(true)).get() +//│ |#class| |OneInt|(|a|)|{|→|#fun| |get| |#=| |a|←|↵|}|↵|#class| |OneBool|(|b|)|{|→|#fun| |get| |#=| |b|←|↵|}|↵|(|#if| |b| |#then| |#new| |OneInt|(|1|)| |#else| |#new| |OneBool|(|true|)|)|.get|(||)| +//│ Parsed: {class OneInt(a,) {fun get = a}; class OneBool(b,) {fun get = b}; ('(' if (b) then new OneInt(1,) {} else new OneBool(true,) {}, ')').get ()} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, get, [], Var(a)))), NuTypeDef(class, OneBool, (), Tup(_: Var(b)), (), TypingUnit(NuFunDef(None, get, [], Var(b)))), App(Sel(Bra(rcd = false, Tup(_: If((b) then new OneInt(1,) {}, Some(New(Some((TypeName(OneBool),true,)), TypingUnit(List())))))), get), Tup())) +//│ Lifted: +//│ TypingUnit { +//│ class OneInt$1(a,) {fun get = (this).a} +//│ class OneBool$2(b,) {fun get = (this).b} +//│ Code(List(('(' if (b) then new OneInt$1(1,) {} else new OneBool$2(true,) {}, ')').get ())) +//│ } + +// :mono class Bar(x: int) { fun FooMinus(y: int) = x + y fun car = foo(2) @@ -188,11 +1182,3 @@ bar.car //│ Code(List((Car$2 ()).da (Bar$1 (1337,),))) //│ Code(List((bar).car)) //│ } -//│ Mono: -//│ fun baz(Bar$1) = -//│ b.foo(2) -//│ fun bar() = -//│ Bar$1(42) -//│ baz(bar) -//│ Car$2().da(Bar$1(1337)) -//│ bar.car diff --git a/compiler/shared/test/scala/mlscript/compiler/Test.scala b/compiler/shared/test/scala/mlscript/compiler/Test.scala index c8af030d6..d34700e40 100644 --- a/compiler/shared/test/scala/mlscript/compiler/Test.scala +++ b/compiler/shared/test/scala/mlscript/compiler/Test.scala @@ -33,10 +33,14 @@ class DiffTestCompiler extends DiffTests { try{ val monomorph = new Monomorph(treeDebug) val monomorphized = monomorph.monomorphize(rstUnit) + outputBuilder ++= "\nMono result: \n" outputBuilder ++= ExprPrinter.print(monomorphized) + outputBuilder ++= "\n" }catch{ - case error: MonomorphError => outputBuilder ++= (error.getMessage() :: error.getStackTrace().map(_.toString()).toList ++ treeDebug.getLines).mkString("\n") + case error: MonomorphError => outputBuilder ++= (error.getMessage() :: error.getStackTrace().map(_.toString()).toList).mkString("\n") + // case error: StackOverflowError => outputBuilder ++= (error.getMessage() :: error.getStackTrace().take(40).map(_.toString()).toList).mkString("\n") } + outputBuilder ++= treeDebug.getLines.mkString("\n") } outputBuilder.toString().linesIterator.toList From 8355ef86b977a03a839550e58133d2d9580edca3 Mon Sep 17 00:00:00 2001 From: YKY Date: Sat, 31 Dec 2022 15:11:39 +0800 Subject: [PATCH 03/13] updates --- .../scala/mlscript/compiler/ClassLifter.scala | 135 +- .../scala/mlscript/compiler/Helpers.scala | 40 + .../mlscript/compiler/mono/Monomorph.scala | 160 +- .../mono/specializer/BoundedExpr.scala | 164 +- .../compiler/mono/specializer/Builtin.scala | 19 +- .../compiler/mono/specializer/Context.scala | 1 + .../mono/specializer/Specializer.scala | 62 +- .../main/scala/mlscript/compiler/syntax.scala | 1 + compiler/shared/test/diff/LambLift.mls | 72 + compiler/shared/test/diff/LifterBlks.mls | 6 +- compiler/shared/test/diff/mono.mls | 2063 +++++++++++------ .../test/scala/mlscript/compiler/Test.scala | 4 +- .../src/test/scala/mlscript/DiffTests.scala | 2 +- 13 files changed, 1836 insertions(+), 893 deletions(-) create mode 100644 compiler/shared/test/diff/LambLift.mls diff --git a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala index 681de94c6..016eecb54 100644 --- a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala +++ b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala @@ -5,6 +5,7 @@ import mlscript.utils.StringOps import scala.collection.mutable.StringBuilder as StringBuilder import scala.collection.mutable.Map as MMap import scala.collection.mutable.Set as MSet +import scala.collection.mutable.ArrayBuffer as ArrayBuffer import mlscript.codegen.Helpers.inspect as showStructure import mlscript.codegen.CodeGenError @@ -54,6 +55,8 @@ class ClassLifter(logDebugMsg: Boolean = false) { type NamePath = List[String] var retSeq: List[NuTypeDef] = Nil + val globalFunctions: ArrayBuffer[NuFunDef] = ArrayBuffer() + def globalNames: List[Var] = globalFunctions.toList.map(_.nme) var anonymCnt: Int = 0 var clsCnt: Int = 0 val logOutput: StringBuilder = new StringBuilder @@ -289,6 +292,9 @@ class ClassLifter(logDebugMsg: Boolean = false) { } } + private def newLambObj(lhs: Term, rhs: Term) = + New(None, TypingUnit(List(NuFunDef(None, Var("apply"), Nil, Left(Lam(lhs, rhs)))))) + private def liftTermNew(target: Term)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (Term, LocalContext) = target match{ case v: Var => if(ctx.contains(v) || v.name.equals("this") || primiTypes.contains(v.name)) (v, emptyCtx) @@ -303,10 +309,17 @@ class ClassLifter(logDebugMsg: Boolean = false) { } } case Lam(lhs, rhs) => - val lctx = getFreeVars(lhs)(using emptyCtx, cache, None) - val (ltrm, _) = liftTermNew(lhs)(using ctx.addV(lctx.vSet)) - val (rtrm, rctx) = liftTermNew(rhs)(using ctx.addV(lctx.vSet)) - (Lam(ltrm, rtrm), rctx -+ lctx) + val prmCnt = getFreeVars(lhs)(using emptyCtx, cache, None).vSet.size + val nTpNm = TypeName(genAnoName("Lambda"+prmCnt)) + val anoCls = NuTypeDef(Cls, nTpNm, Nil, Tup(Nil), Nil, TypingUnit(List(NuFunDef(None, Var("apply"), Nil, Left(Lam(lhs, rhs)))))) + val nSta = New(Some((nTpNm, Tup(Nil))), TypingUnit(Nil)) + val ret = liftEntitiesNew(List(anoCls, nSta)) + (Blk(ret._1), ret._2) + // liftTermNew(newLambObj(lhs, rhs)) + // val lctx = getFreeVars(lhs)(using emptyCtx, cache, None) + // val (ltrm, _) = liftTermNew(lhs)(using ctx.addV(lctx.vSet)) + // val (rtrm, rctx) = liftTermNew(rhs)(using ctx.addV(lctx.vSet)) + // (Lam(ltrm, rtrm), rctx -+ lctx) case t: Tup => liftTuple(t) case Rcd(fields) => @@ -519,6 +532,11 @@ class ClassLifter(logDebugMsg: Boolean = false) { log(s"liftFunc $func under $ctx # $cache # $outer") val NuFunDef(rec, nm, tpVs, body) = func body match{ + case Left(Lam(lhs, rhs)) => + val lctx = getFreeVars(lhs)(using emptyCtx, cache, None) + val lret = liftTermNew(lhs)(using ctx.addV(lctx.vSet + nm)) + val ret = liftTermNew(rhs)(using ctx.addV(lctx.vSet + nm).addT(tpVs)) + (func.copy(rhs = Left(Lam(lret._1, ret._1))), ret._2 -+ lret._2) case Left(value) => val ret = liftTermNew(value)(using ctx.addV(nm).addT(tpVs)) (func.copy(rhs = Left(ret._1)), ret._2) @@ -541,7 +559,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { // val fullMp = cache ++ nameInfoMap val clsNmsAsTypeNm = newClsNms.map(x => TypeName(x.name)) val len = clsInfos.size - for(_ <- 1 to len){ + for(_ <- 0 to len){ val tmp = nameInfoMap.toList tmp.foreach{case (nmOfCls, infoOfCls@ClassInfoCache(_, _, ctx, flds, inners, sups, _, _, _)) => { val usedClsNmList = ctx.vSet.map(x => TypeName(x.name)).intersect(clsNmsAsTypeNm) @@ -563,6 +581,55 @@ class ClassLifter(logDebugMsg: Boolean = false) { nameInfoMap.toMap } + private def mixFuncFreeVs(funcVs: Map[Var, Set[Var]]): Map[Var, List[Var]] = { + val nameVsMap: Map[Var, MSet[Var]] = funcVs.map(entry => entry._1 -> MSet(entry._2.toSeq: _*)) + val concernedFs = funcVs.keySet + for(_ <- 0 to funcVs.size){ + val tmp = nameVsMap.toList + tmp.foreach((v, vset) => { + val recVs = concernedFs.intersect(vset.toSet) + recVs.foreach(x => nameVsMap.get(v).get.addAll(nameVsMap.get(x).get)) + }) + } + nameVsMap.map((k, v) => k -> (v--concernedFs).toList) + } + + private def updateFuncSigStmt(targetTrm: Statement)(using extFuncArgs: Map[Var, (Var, List[Var], Tup)]): Statement = targetTrm match{ + case NuFunDef(isLetRec, nme, targs, Left(body)) => NuFunDef(isLetRec, nme, targs, Left(updateFuncSignatures(body)(using extFuncArgs-nme))) + case NuTypeDef(kind, nme, tparams, params, parents, body) => + NuTypeDef(kind, nme, tparams, params, parents.map(updateFuncSignatures), TypingUnit(body.entities.map(updateFuncSigStmt))) + case x: Term => updateFuncSignatures(x) + case others => others + } + + + private def updateFuncSignatures(targetTrm: Term)(using extFuncArgs: Map[Var, (Var, List[Var], Tup)]): Term = targetTrm match{ + case x: Var if extFuncArgs.contains(x) => + val infos = extFuncArgs.get(x).get + val concatedPrm = Tup(infos._2.map(toFldsEle) ++ infos._3.fields) + newLambObj(infos._3, App(infos._1, concatedPrm)) + case App(x: Var, Tup(flds)) if extFuncArgs.contains(x) => + val infos = extFuncArgs.get(x).get + val nArgs = Tup(infos._2.map(toFldsEle) ++ flds.map{case (o, Fld(b1, b2, t)) => (o, Fld(b1, b2, updateFuncSignatures(t)))}) + App(infos._1, nArgs) + case App(lhs, rhs) => + App(updateFuncSignatures(lhs), updateFuncSignatures(rhs)) + case Lam(lhs, rhs) => + val absVs = getFreeVars(lhs)(using emptyCtx, Map(), None).vSet + Lam(lhs, updateFuncSignatures(rhs)(using extFuncArgs -- absVs)) + case If(IfThen(cond, tru), els) => + If(IfThen(updateFuncSignatures(cond), updateFuncSignatures(tru)), els.map(updateFuncSignatures)) + case Let(isRec, name, rhs, body) => + Let(isRec, name, updateFuncSignatures(rhs)(using extFuncArgs-name), updateFuncSignatures(body)(using extFuncArgs-name)) + case Blk(stmts) => + Blk(stmts.map(updateFuncSigStmt)) + case New(head, body) => + New(head.map((x, y) => x -> updateFuncSignatures(y)), TypingUnit(body.entities.map(updateFuncSigStmt))) + case Sel(receiver, fieldName) => + Sel(updateFuncSignatures(receiver), fieldName) + case others => others + } + private def liftEntitiesNew(etts: List[Statement])(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (List[Statement], LocalContext) = { log("liftEntities: " ++ etts.headOption.map(_.toString()).getOrElse("")) val (newCls, newFuncs, rstTrms) = splitEntities(etts) @@ -571,13 +638,60 @@ class ClassLifter(logDebugMsg: Boolean = false) { val nmsInTrm = rstTrms.flatMap(grepFieldsInTrm) val clsInfos = newCls.map(x => { val infos = collectClassInfo(x, newCls.map(_.nme).toSet)(using emptyCtx) - infos.capturedParams = infos.capturedParams.copy(vSet = infos.capturedParams.vSet.intersect(ctx.vSet ++ newClsNms ++ newFuncNms ++ nmsInTrm)) + infos.capturedParams = infos.capturedParams.copy(vSet = infos.capturedParams.vSet.intersect(ctx.vSet ++ newClsNms ++ newFuncNms ++ nmsInTrm -- globalNames)) x.nme -> infos}).toMap log("captured cls infos: \n" ++ clsInfos.toString()) val refinedInfo = mixClsInfos(clsInfos, newClsNms) val newCache = cache ++ refinedInfo refinedInfo.foreach((_, clsi) => completeClsInfo(clsi)(using newCache)) +// // transform local functions to global ones +// val seperatedRstTerms = rstTrms.map{ +// case l@Let(isRec, name, rhs, Blk(Nil)) => (Some(NuFunDef(Some(isRec), name, Nil, Left(rhs))), None) +// case other => (None, Some(other)) +// }.unzip +// val letFuncs = seperatedRstTerms._1.flatten +// val nonLetRstTerms = seperatedRstTerms._2.flatten + +// val funcCapVars = (newFuncs ++ letFuncs).flatMap{ +// case NuFunDef(_, nme, _, Left(body)) => Some(nme -> getFreeVars(body)(using emptyCtx, Map(), None).vSet.intersect(ctx.vSet ++ newFuncNms ++ nmsInTrm)) +// case _ => None +// }.toMap +// val mixedFuncCapVs = mixFuncFreeVs(funcCapVars) +// val nFuncSig = (newFuncs ++ letFuncs).flatMap{ +// case NuFunDef(_, nme, _, Left(Lam(x: Tup, _))) => Some(nme -> (Var(genAnoName(nme.name)), mixedFuncCapVs.get(nme).get, x)) +// case NuFunDef(_, nme, _, Left(_)) => Some(nme -> (Var(genAnoName(nme.name)), mixedFuncCapVs.get(nme).get, Tup(Nil))) +// case _ => None +// }.toMap +// // mixedFuncCapVs.map(x => x._1 -> (genAnoName(x._1.name), x._2)) +// (newFuncs ++ letFuncs).foreach{ +// case NuFunDef(isLetRec, nme, targs, Left(Lam(lhs, rhs))) => +// lhs match{ +// case Tup(fields) => +// val nPrm = Tup(nFuncSig.get(nme).get._2.map(toFldsEle) ++ fields) +// val nBody = updateFuncSignatures(rhs)(using nFuncSig) +// val liftedFuncBody = liftTermNew(nBody)(using getFreeVars(nPrm)(using emptyCtx, cache, None), newCache, None) +// globalFunctions.addOne(NuFunDef(isLetRec, nFuncSig.get(nme).get._1, targs, Left(Lam(nPrm, liftedFuncBody._1)))) +// // case v@Var(name) => +// // val nFields = nFuncSig.get(nme).get._2.map(toFldsEle) ++ List(toFldsEle(v)) +// // val nBody = updateFuncSignatures(rhs)(using nFuncSig) +// // val liftedFuncBody = liftTermNew(nBody)(using getFreeVars(nPrm)(using emptyCtx, cache, None), cache, None) +// // globalFunctions.addOne(NuFunDef(isLetRec, nFuncSig.get(nme).get._1, targs, Left(Lam(nPrm, liftedFuncBody._1)))) +// case _ => ??? +// } +// case NuFunDef(isLetRec, nme, targs, Left(term)) => +// val nPrm = Tup(nFuncSig.get(nme).get._2.map(toFldsEle)) +// val nBody = updateFuncSignatures(term)(using nFuncSig) +// val liftedFuncBody = liftTermNew(nBody)(using getFreeVars(nPrm)(using emptyCtx, cache, None), newCache, None) +// globalFunctions.addOne(NuFunDef(isLetRec, nFuncSig.get(nme).get._1, targs, Left(Lam(nPrm, liftedFuncBody._1)))) +// // case _ => ??? +// } + +// newCls.map(updateFuncSigStmt(_)(using nFuncSig)).foreach{case x: NuTypeDef => liftTypeDefNew(x)(using newCache)} + +// // val (liftedFuns, funVs) = newFuncs.map(liftFunc(_)(using ctx.addV(newFuncNms), newCache)).unzip +// val (liftedTerms, termVs) = nonLetRstTerms.map(updateFuncSignatures(_)(using nFuncSig)).map(liftTermNew(_)(using ctx, newCache)).unzip +// (liftedTerms, termVs.fold(emptyCtx)(_ ++ _)) newCls.foreach(x => liftTypeDefNew(x)(using newCache)) val (liftedFuns, funVs) = newFuncs.map(liftFunc(_)(using ctx.addV(newFuncNms), newCache)).unzip val (liftedTerms, termVs) = rstTrms.map(liftTermNew(_)(using ctx.addV(newFuncNms), newCache)).unzip @@ -625,9 +739,16 @@ class ClassLifter(logDebugMsg: Boolean = false) { log("=========================\n") log(s"lifting: \n${showStructure(rawUnit)}\n") retSeq = Nil + val (_, newFuncs, rstTrms) = splitEntities(rawUnit.entities) + globalFunctions.addAll(newFuncs) + globalFunctions.addAll(rstTrms.flatMap{ + case Let(isRec, name, rhs, Blk(Nil)) => + Some(NuFunDef(Some(isRec), name, Nil, Left(rhs))) + case _ => None + }) val re = liftEntitiesNew(rawUnit.entities)(using emptyCtx, Map(), None) log(s"freeVars: ${re._2}") // println(logOutput.toString()) - TypingUnit(retSeq.toList++re._1) + TypingUnit(retSeq.toList ++ re._1) } } diff --git a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala index 6d76551ed..31b4fdece 100644 --- a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala +++ b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala @@ -18,6 +18,7 @@ import mlscript.IntLit import mlscript.StrLit import mlscript.AppliedType import mlscript.TypeName +import mlscript.TypeDefKind object Helpers: /** @@ -145,3 +146,42 @@ object Helpers: then UnitValue.Undefined else UnitValue.Null) } + + def func2Item(funDef: NuFunDef): Item.FuncDecl | Item.FuncDefn = + val NuFunDef(_, nme, targs, rhs) = funDef + rhs match + case Left(Lam(params, body)) => + Item.FuncDecl(Expr.Ref(nme.name), toFuncParams(params).toList, term2Expr(body)) + case Left(body: Term) => Item.FuncDecl(Expr.Ref(nme.name), Nil, term2Expr(body)) + case Right(polyType) => Item.FuncDefn(Expr.Ref(nme.name), targs, polyType) + + def type2Item(tyDef: NuTypeDef): Item.TypeDecl = + val NuTypeDef(kind, className, tparams, params, parents, body) = tyDef + val isolation = Isolation(body.entities.flatMap { + // Question: Will there be pure terms in class body? + case term: Term => + Some(term2Expr(term)) + case subTypeDef: NuTypeDef => ??? + case subFunDef: NuFunDef => + Some(func2Item(subFunDef)) + }) + val typeDecl: Item.TypeDecl = Item.TypeDecl( + Expr.Ref(className.name), // name + kind, // kind + tparams, // typeParams + toFuncParams(params).toList, // params + parents.map { + case Var(name) => (TypeName(name), Nil) + case App(Var(name), _) => (TypeName(name), Nil) + case _ => throw MonomorphError("unsupported parent term") + }, // parents + isolation // body + ) + typeDecl + + private given Conversion[TypeDefKind, TypeDeclKind] with + import mlscript.{Als, Cls, Trt} + def apply(kind: TypeDefKind): TypeDeclKind = kind match + case Als => TypeDeclKind.Alias + case Cls => TypeDeclKind.Class + case Trt => TypeDeclKind.Trait diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala index c56dbbdf3..cc90afe0f 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala @@ -20,7 +20,7 @@ import mlscript.compiler.* import mlscript.compiler.printer.ExprPrinter import mlscript.compiler.mono.specializer.BoundedExpr -import mlscript.compiler.mono.specializer.{MonoValue, ObjectValue, UnknownValue, FunctionValue} +import mlscript.compiler.mono.specializer.{MonoValue, ObjectValue, UnknownValue, FunctionValue, VariableValue} class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: import Helpers._ @@ -29,7 +29,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: /** * Specialized implementations of function declarations. */ - private val funImpls = MutMap[String, (Item.FuncDecl, MutMap[String, Item.FuncDecl], List[(BoundedExpr, Int)], BoundedExpr)]() + private val funImpls = MutMap[String, (Item.FuncDecl, MutMap[String, Item.FuncDecl], List[(BoundedExpr, Int)], VariableValue)]() private def getfunInfo(nm: String): String = val info = funImpls.get(nm).get @@ -76,10 +76,16 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: val specializer = mono.specializer.Specializer(this)(using debug) def addNewFunction(func: Item.FuncDecl): Unit = { - funImpls.addOne(func.name.name, (func, MutMap(), func.params.map(_ => BoundedExpr()->0), BoundedExpr())) + funImpls.addOne(func.name.name, (func, MutMap(), func.params.map(_ => BoundedExpr()->0), VariableValue.refresh())) funDependence.addOne(func.name.name, Set()) } + def getResult(exps: List[Expr]) = mlscript.compiler.Module(exps.concat[Expr | Item](funImpls.map(x => x._2._1)) + .concat(allTypeImpls.values.map(x => x.copy(body = Isolation(Nil)))) + .concat(lamTyDefs.values) + .concat(anonymTyDefs.values) + .toList) + /** * This function monomorphizes the top-level `TypingUnit` into a `Module`. */ @@ -94,16 +100,18 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: evalQueue.addOne(funcName) Some(Expr.Apply(Expr.Ref(funcName), Nil)) case (tyDef: NuTypeDef, _) => - monomorphizeTypeDef(tyDef) + val ret = type2Item(tyDef) + addPrototypeTypeDecl(ret) None case (funDef: NuFunDef, _) => - val funcItem = monomorphizeFunDef(funDef) + val funcItem = func2Item(funDef) funcItem match case funcDecl: Item.FuncDecl => addNewFunction(funcDecl) case _ => () None }; + debug.log(getResult(exps).getDebugOutput.toLines(using false).mkString("\n")) while(!evalQueue.isEmpty){ val crt = evalQueue.head evalQueue.remove(crt) @@ -113,14 +121,10 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: case (_, (Item.FuncDecl(nm, as, body), mp, la, lr)) => (Item.FuncDecl(nm, as, specializer.defunctionalize(body)), mp, la, lr) } - val ret = mlscript.compiler.Module(exps.concat[Expr | Item](funImpls.map(x => x._2._1)) - .concat(allTypeDecls) - .concat(lamTyDefs.values) - .concat(anonymTyDefs.values) - .toList) - debug.log("") - debug.log("==============final function signatures==================") - funImpls.foreach( + val ret = getResult(exps) + debug.log("") + debug.log("==============final function signatures==================") + funImpls.foreach( (nm, info) => { debug.log(s"$nm: (${info._3.map(_._1).mkString(" X ")}) -> ${info._4}") // updateFunc(nm) @@ -134,7 +138,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: def updateFunction(crt: String): Unit = { debug.log(s"evaluating $crt, rests: ${evalQueue}") val cnt = evalCnt.get(crt).getOrElse(0) - if(cnt <= 20){ + if(cnt <= 4){ evalCnt.update(crt, cnt+1) debug.log("=" * 10 + s" updating $crt " + "=" * 10) debug.log(getfunInfo(crt)) @@ -155,10 +159,11 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: case term: Term => Some(term2Expr(term)) case tyDef: NuTypeDef => - monomorphizeTypeDef(tyDef) + val ret = type2Item(tyDef) + addPrototypeTypeDecl(ret) None case funDef: NuFunDef => - Some(monomorphizeFunDef(funDef)) + Some(func2Item(funDef)) }) }(identity) @@ -166,58 +171,58 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: * This function flattens a top-level type definition and returns the root * type definition. There is a simple class lifting here. */ - private def monomorphizeTypeDef(tyDef: NuTypeDef): Item.TypeDecl = + // private def monomorphizeTypeDef(tyDef: NuTypeDef): Item.TypeDecl = // debug.trace("MONO TDEF", PrettyPrinter.show(tyDef)) { /** * The recursive function doing the real work. * @param tyDef the type definition * @param namePath enclosing class names and this class name */ - def rec(tyDef: NuTypeDef, namePath: List[String]): Item.TypeDecl = - // debug.trace[Item.TypeDecl]("LIFT", PrettyPrinter.show(tyDef)) { - val NuTypeDef(kind, _, tparams, params, parents, body) = tyDef - val isolation = Isolation(body.entities.flatMap { - // Question: Will there be pure terms in class body? - case term: Term => - Some(term2Expr(term)) - case subTypeDef: NuTypeDef => - rec(subTypeDef, subTypeDef.nme.name :: namePath) - None - case subFunDef: NuFunDef => - Some(monomorphizeFunDef(subFunDef)) - }) - val className = namePath.reverseIterator.mkString("_") - val typeDecl: Item.TypeDecl = Item.TypeDecl( - className, // name - kind, // kind - tparams, // typeParams - toFuncParams(params).toList, // params - parents.map { - case Var(name) => (TypeName(name), Nil) - case App(Var(name), _) => (TypeName(name), Nil) - case _ => throw MonomorphError("unsupported parent term") - }, // parents - isolation // body - ) - addPrototypeTypeDecl(typeDecl) - typeDecl - // }() - - rec(tyDef, tyDef.nme.name :: Nil) + // def rec(tyDef: NuTypeDef, namePath: List[String]): Item.TypeDecl = + // // debug.trace[Item.TypeDecl]("LIFT", PrettyPrinter.show(tyDef)) { + // val NuTypeDef(kind, _, tparams, params, parents, body) = tyDef + // val isolation = Isolation(body.entities.flatMap { + // // Question: Will there be pure terms in class body? + // case term: Term => + // Some(term2Expr(term)) + // case subTypeDef: NuTypeDef => + // rec(subTypeDef, subTypeDef.nme.name :: namePath) + // None + // case subFunDef: NuFunDef => + // Some(monomorphizeFunDef(subFunDef)) + // }) + // val className = namePath.reverseIterator.mkString("_") + // val typeDecl: Item.TypeDecl = Item.TypeDecl( + // className, // name + // kind, // kind + // tparams, // typeParams + // toFuncParams(params).toList, // params + // parents.map { + // case Var(name) => (TypeName(name), Nil) + // case App(Var(name), _) => (TypeName(name), Nil) + // case _ => throw MonomorphError("unsupported parent term") + // }, // parents + // isolation // body + // ) + // addPrototypeTypeDecl(typeDecl) + // typeDecl + // // }() + + // rec(tyDef, tyDef.nme.name :: Nil) // }(identity) /** * This function monomorphizes a function definition in smoe typing units. * @param tyDecls the destination of nested type declarations */ - private def monomorphizeFunDef(funDef: NuFunDef): Item.FuncDecl | Item.FuncDefn = - // debug.trace[Item.FuncDecl | Item.FuncDefn]("MONO FUNC", PrettyPrinter.show(funDef)) { - val NuFunDef(_, nme, targs, rhs) = funDef - rhs match - case Left(Lam(params, body)) => - Item.FuncDecl(nme, toFuncParams(params).toList, term2Expr(body)) - case Left(body: Term) => Item.FuncDecl(nme, Nil, term2Expr(body)) - case Right(polyType) => Item.FuncDefn(nme, targs, polyType) + // private def monomorphizeFunDef(funDef: NuFunDef): Item.FuncDecl | Item.FuncDefn = + // // debug.trace[Item.FuncDecl | Item.FuncDefn]("MONO FUNC", PrettyPrinter.show(funDef)) { + // val NuFunDef(_, nme, targs, rhs) = funDef + // rhs match + // case Left(Lam(params, body)) => + // Item.FuncDecl(nme, toFuncParams(params).toList, term2Expr(body)) + // case Left(body: Term) => Item.FuncDecl(nme, Nil, term2Expr(body)) + // case Right(polyType) => Item.FuncDefn(nme, targs, polyType) // }(identity) /** @@ -383,7 +388,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: } } } - funImpls.get(name).get._4 + BoundedExpr(funImpls.get(name).get._4) } else { debug.log("!!!!!!!") @@ -399,7 +404,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: val ctx = (funcdecl.params.map(_._2.name) zip args.unzip._1).toMap val nBody = specializer.evaluate(funcdecl.body)(using Context()++ctx, List(funcdecl.name.name)) val nVs = nBody.expValue - val oldVs = funImpls.get(name).get._4 + val oldVs = VariableValue.get(funImpls.get(name).get._4) debug.log(s"comparing ${oldVs} with ${nVs}") if(oldVs.compare(nVs)){ debug.log(s"adding these funcs to queue: ${funDependence.get(name).get}") @@ -407,13 +412,26 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: } funImpls.updateWith(name)(_.map(x => { val nFuncDecl: Item.FuncDecl = x._1.copy(body = nBody) - x._4 += nVs + // debug.log(s"merging ${nVs.hashCode()%1000000} into ${x._4.hashCode()%1000000}") + VariableValue.update(x._4, nVs) + // debug.log(s"merged: ${x._4.hashCode()%1000000}") (nFuncDecl, x._2, x._3, x._4) })) // funImpls.get(name).get._4 += nVs // funImpls.update(name, funImpls.get(name).get.copy(_4 = nVs)) } + def findVar(name: String)(using evalCtx: Context, callingStack: List[String]): MonoValue = { + if(funImpls.contains(name)){ + val funcBody = funImpls.get(name).get + funDependence.update(name, funDependence.get(name).get ++ callingStack.headOption) + FunctionValue(name, funcBody._1.params.map(_._2.name), Nil) + } + else{ + UnknownValue() + } + } + private def partitationArguments(name: String, params: List[Parameter], args: List[Expr]): (List[Expr], List[Expr]) = if (args.length != params.length) { debug.log("") @@ -655,21 +673,21 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: // Shorthand implicit conversions. - private given Conversion[String, Expr.Ref] with - def apply(name: String): Expr.Ref = Expr.Ref(name) + // private given Conversion[String, Expr.Ref] with + // def apply(name: String): Expr.Ref = Expr.Ref(name) - private given Conversion[Var, Expr.Ref] with - def apply(nme: Var): Expr.Ref = Expr.Ref(nme.name) + // private given Conversion[Var, Expr.Ref] with + // def apply(nme: Var): Expr.Ref = Expr.Ref(nme.name) - private given Conversion[TypeName, Expr.Ref] with - def apply(nme: TypeName): Expr.Ref = Expr.Ref(nme.name) + // private given Conversion[TypeName, Expr.Ref] with + // def apply(nme: TypeName): Expr.Ref = Expr.Ref(nme.name) - private given Conversion[TypeDefKind, TypeDeclKind] with - import mlscript.{Als, Cls, Trt} - def apply(kind: TypeDefKind): TypeDeclKind = kind match - case Als => TypeDeclKind.Alias - case Cls => TypeDeclKind.Class - case Trt => TypeDeclKind.Trait + // private given Conversion[TypeDefKind, TypeDeclKind] with + // import mlscript.{Als, Cls, Trt} + // def apply(kind: TypeDefKind): TypeDeclKind = kind match + // case Als => TypeDeclKind.Alias + // case Cls => TypeDeclKind.Class + // case Trt => TypeDeclKind.Trait object Monomorph: class SpecializationMap[T <: Item](val prototype: T): diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala index 3c5d1bc4c..75757fa36 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala @@ -5,6 +5,8 @@ import mlscript.compiler.debug.Printable import mlscript.compiler.debug.DebugOutput import scala.collection.mutable.Map as MutMap import scala.collection.mutable.Set as MutSet +import mlscript.Var +import scala.collection.immutable abstract class MonoValue { def toBoundedExpr = BoundedExpr(this) @@ -30,7 +32,7 @@ case class ObjectValue(name: String, fields: MutMap[String, BoundedExpr]) extend if(!inStackExps.contains(s1.hashCode()) || !inStackExps.contains(s2.hashCode())){ if(inStackExps.contains(s1.hashCode())){ val tmp = BoundedExpr() - s1.values.foreach(tmp.values.addOne(_)) + tmp += s1 val ret = tmp += s2 fields.update(k, tmp) ret @@ -68,6 +70,25 @@ object UnknownValue{ unknownCnt } } +case class VariableValue(vx: Int) extends MonoValue{ + override def toStringSafe(using Set[Int]): String = s"*$vx*=${VariableValue.get(this).toStringSafe}" + override def toString(): String = toStringSafe(using Set()) +} +object VariableValue{ + var vxCnt = 0 + val vMap = MutMap[Int, BoundedExpr]() + def refresh(): VariableValue = { + vxCnt += 1 + val ret = VariableValue(vxCnt) + vMap.addOne(vxCnt -> BoundedExpr(ret)) + ret + } + def get(v: VariableValue): BoundedExpr = vMap.get(v.vx).get + def update(v: VariableValue, s: BoundedExpr): Unit = { + vMap.update(v.vx, s) + } +} + case class LiteralValue(i: BigInt | BigDecimal | Boolean | String | UnitValue) extends MonoValue{ def asBoolean(): Option[Boolean] = i match{ case x: Boolean => Some(x) @@ -79,7 +100,7 @@ case class PrimitiveValue() extends MonoValue{ override def toString(): String = "*LIT*" } -class BoundedExpr(val values: MutSet[MonoValue]) extends Printable { +class BoundedExpr(private val values: MutSet[MonoValue]) extends Printable { def this(singleVal: MonoValue) = this(MutSet(singleVal)) def this() = this(MutSet()) def this(vs: Set[MonoValue]) = this(MutSet(vs.toSeq: _*)) @@ -89,31 +110,23 @@ class BoundedExpr(val values: MutSet[MonoValue]) extends Printable { case ObjectValue(name, _) => Some(name) case _ => None }.toSet - override def hashCode(): Int = values.hashCode() + // override def hashCode(): Int = values.hashCode() override def toString(): String = toStringSafe var updateCnt: Int = 0 def toStringSafe(using printed: Set[Int] = Set()): String = { - if(printed.contains(this.hashCode())) s"***" - else values.map(_.toStringSafe(using printed + this.hashCode())).mkString("[", " | ", s"]") + if(printed.contains(this.hashCode())) s"..." + else values.map(_.toStringSafe(using printed + this.hashCode())).mkString("[", " | ", s"]${hashCode()%1000000}") } def asValue: Option[MonoValue] = { - if(values.size == 1) { - Some(values.head) + val tmp = this.unfoldVars + if(tmp.values.size == 1) { + Some(tmp.values.head) } else None } - // def crossList(other: Set[List[MonoValue]]): Set[List[MonoValue]] = { - // for{ - // x <- values; - // y <- other - // } yield x :: y - // } - // def crossP[A](other: Set[A]): Set[(MonoValue, A)] = { - // for{ - // x <- values; - // y <- other - // } yield (x, y) - // } + def getValue: Set[MonoValue] = { + unfoldVars.values.toSet.filterNot(_.isInstanceOf[VariableValue]) + } private def split(vs: Set[MonoValue], nms: Set[String]): (Set[MonoValue], Map[String, ObjectValue]) = { val ret = vs.map{ @@ -129,10 +142,35 @@ class BoundedExpr(val values: MutSet[MonoValue]) extends Printable { val ret2 = ret._2.flatten.toMap (ret1, ret2) } + + def unfoldVars(using instackExps: Set[Int] = Set()): BoundedExpr = { + val vars = values.toList.map{ + case vx: VariableValue => (Some(vx), None) + case others => (None, Some(others)) + }.unzip + val varSets: List[BoundedExpr] = vars._1.flatten.map(x => { + val vSet = VariableValue.get(x) + if(!instackExps.contains(vSet.hashCode())){ + // val ret = vSet.values.toList.toSet + // println(s"found $x mapsto $ret") + // values -= x + // println(s"found $x mapsto $ret") + vSet.unfoldVars(using instackExps + vSet.hashCode()) + } + else BoundedExpr(x) + }) + val ret = BoundedExpr(MutSet(vars._2.flatten.toSeq: _*)) + // if(varSets.size > 0) + // println(s"adding $varSets to $this") + varSets.foreach(x => {ret.mergeWithoutUnfold(x)(using instackExps + x.hashCode())}) + ret + } def ++(other: BoundedExpr)(using instackExps: Set[Int] = Set()): BoundedExpr = { if(this == other) this else { + // unfoldVars + // other.unfoldVars val mergingValNms = getObjNames().intersect(other.getObjNames()) val (restVals1, mergingVals1) = split(values.toSet, mergingValNms) val (restVals2, mergingVals2) = split(other.values.toSet, mergingValNms) @@ -153,8 +191,49 @@ class BoundedExpr(val values: MutSet[MonoValue]) extends Printable { } } + def mergeWithoutUnfold(other: BoundedExpr)(using instackExps: Set[Int] = Set()): Boolean = { + val retVal = if(other != this) { + // println(s"merging $other into $this") + val mergingValNms = getObjNames().intersect(other.getObjNames()).toSet + val (_, mergingVals) = split(values.toSet, mergingValNms) + var litCount = values.find(x => (x.isInstanceOf[LiteralValue] || x.isInstanceOf[PrimitiveValue])) + val ret = other.values.map{ + case i: (LiteralValue | PrimitiveValue) => + if(litCount.isEmpty) { + values.add(i) + true + } + else if(!litCount.get.isInstanceOf[PrimitiveValue]) { + values.remove(litCount.get) + values.add(PrimitiveValue()) + litCount = Some(PrimitiveValue()) + true + } + else false + case o@ObjectValue(name, fields) => + mergingVals.get(name).fold[Boolean]{ + values.add(o) + true + }(v => { + v.mergeMut(o)(using instackExps ++ Set(this.hashCode(), other.hashCode())) + }) + case other => { + // println(s"adding $other to $this") + values.add(other) + true + } + } + ret.fold(false)(_ || _) + } + else false + if(retVal) updateCnt += 1 + retVal + } + def +=(other: BoundedExpr)(using instackExps: Set[Int] = Set()): Boolean = { val retVal = if(other != this) { + // unfoldVars + // other.unfoldVars val mergingValNms = getObjNames().intersect(other.getObjNames()).toSet val (_, mergingVals) = split(values.toSet, mergingValNms) var litCount = values.find(x => (x.isInstanceOf[LiteralValue] || x.isInstanceOf[PrimitiveValue])) @@ -192,7 +271,7 @@ class BoundedExpr(val values: MutSet[MonoValue]) extends Printable { def size = values.size // lazy val eleCnt: Int = countEles - def eleCnt(using objCallingStack: Set[String] = Set()): Int = { + def eleCnt(using instackExps: Set[Int] = Set()): Int = { if(values.size == 0) { 0 } @@ -203,14 +282,15 @@ class BoundedExpr(val values: MutSet[MonoValue]) extends Printable { case _: LiteralValue => (Some(1), None) case _: PrimitiveValue => (Some(100000), None) case UnknownValue() => (Some(1), None) + case vx: VariableValue => (Some(VariableValue.get(vx).eleCnt(using instackExps + VariableValue.get(vx).hashCode())), None) }.unzip val (lits, objs) = (seperated._1.flatten, seperated._2.flatten) val objn = objs.map{ case ObjectValue(name, fields) => - if(objCallingStack.contains(name)) 1 - else { - fields.map(x => x._2.eleCnt(using objCallingStack + name)).fold(0)(_ + _) + 1 - } + fields.map(x => { + if(instackExps.contains(x._2.hashCode())) 1 + else x._2.eleCnt(using instackExps + x._2.hashCode()) + }).fold(0)(_ + _) + 1 }.fold(0)(_ + _) lits.fold(0)(_ + _) + objn } @@ -218,23 +298,27 @@ class BoundedExpr(val values: MutSet[MonoValue]) extends Printable { def compare(other: BoundedExpr)(using instackExps: Set[Int] = Set()): Boolean = { if(instackExps.contains(this.hashCode()) && instackExps.contains(other.hashCode())) false - else if(values.find(_.isInstanceOf[PrimitiveValue]).isEmpty && other.values.find(_.isInstanceOf[PrimitiveValue]).isDefined) - true - else if(this.size != other.size) - this.size < other.size - else{ - val nms1 = this.getObjNames() - val nms2 = other.getObjNames() - if(nms1.equals(nms2)){ - val (rests1, objs1) = split(this.values.toSet, nms1) - val (rests2, objs2) = split(other.values.toSet, nms1) - nms1.find(nm => { - val v1s = objs1.get(nm).get.fields - val v2s = objs2.get(nm).get.fields - v1s.keySet.find(k => v1s.get(k).get.compare(v2s.get(k).get)(using instackExps + this.hashCode() + other.hashCode())).isDefined - }).isDefined + else { + // this.unfoldVars + // other.unfoldVars + if(values.find(_.isInstanceOf[PrimitiveValue]).isEmpty && other.values.find(_.isInstanceOf[PrimitiveValue]).isDefined) + true + else if(this.size != other.size) + this.size < other.size + else{ + val nms1 = this.getObjNames() + val nms2 = other.getObjNames() + if(nms1.equals(nms2)){ + val (rests1, objs1) = split(this.values.toSet, nms1) + val (rests2, objs2) = split(other.values.toSet, nms1) + nms1.find(nm => { + val v1s = objs1.get(nm).get.fields + val v2s = objs2.get(nm).get.fields + v1s.keySet.find(k => v1s.get(k).get.compare(v2s.get(k).get)(using instackExps + this.hashCode() + other.hashCode())).isDefined + }).isDefined + } + else true } - else true } // (values.find(_.isInstanceOf[UnknownValue]), other.values.find(_.isInstanceOf[UnknownValue])) match{ // // case (Some(_), None) => true diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala index 1f180973d..a1a7b12c1 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Builtin.scala @@ -4,7 +4,7 @@ import mlscript.compiler.Expr import mlscript.compiler.mono.MonomorphError object Builtin: - val builtinRefs = Set(">", "-", "+", "*", "true", "false") + val builtinRefs = Set(">", "-", "+", "*", "&&", "||", "==", "true", "false") private val builtinBinaryOperations = Map[String, (Expr, Expr) => Option[Expr]]( (">", { @@ -65,6 +65,23 @@ object Builtin: case (LiteralValue(lhs: BigDecimal), LiteralValue(rhs: BigDecimal)) => Some(LiteralValue(lhs * rhs)) case (_, _) => None + }), + ("&&", { + case (LiteralValue(lhs: Boolean), LiteralValue(rhs: Boolean)) => + Some(LiteralValue(lhs && rhs)) + case (_, _) => None + }), + ("||", { + case (LiteralValue(lhs: Boolean), LiteralValue(rhs: Boolean)) => + Some(LiteralValue(lhs || rhs)) + case (_, _) => None + }), + ("==", { + case (LiteralValue(lhs: BigInt), LiteralValue(rhs: BigInt)) => + Some(LiteralValue(lhs == rhs)) + case (LiteralValue(lhs: Boolean), LiteralValue(rhs: Boolean)) => + Some(LiteralValue(lhs == rhs)) + case (_, _) => None }) ) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala index a7e3b4afb..bd1d8faec 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Context.scala @@ -11,6 +11,7 @@ class Context(private val entries: Map[String, BoundedExpr]) extends Printable: inline def ++(other: Context): Context = Context(entries ++ other.entries) inline def ++(other: IterableOnce[(String, BoundedExpr)]) = Context(entries ++ other) inline def isEmpty: Boolean = entries.isEmpty + inline def contains(name: String): Boolean = entries.contains(name) def getDebugOutput: DebugOutput = DebugOutput.Map(entries.iterator.map { (key, value) => (key, value.toString) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala index 551bc52e4..f04c1eb15 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala @@ -52,10 +52,11 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ // } def evaluate(rawExpr: Expr)(using evalCtx: Context, callingStack: List[String]): Expr = - // debug.trace[Expr]("EVAL ", rawExpr.toString()) { + debug.trace[Expr]("EVAL ", rawExpr.toString()) { rawExpr match{ case Expr.Ref(name) => - rawExpr.expValue = evalCtx.get(name) + rawExpr.expValue = + if evalCtx.contains(name) then evalCtx.get(name) else BoundedExpr(monoer.findVar(name)) rawExpr case Expr.Apply(Expr.Apply(opE@Expr.Ref(op), a1), a2) if Builtin.isBinaryOperator(op) => if(a1.length == 1 && a2.length == 1) @@ -76,31 +77,54 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ } else ??? - case Expr.Apply(nm@Expr.Ref(name), arguments) => - val nArgs = arguments.map(evaluate(_)) - val args = nArgs.map(_.expValue) - val retVal = monoer.monomorphizeCall(name, args) - val retExp = Expr.Apply(nm, nArgs) - retExp.expValue = retVal - retExp + // case Expr.Apply(nm@Expr.Ref(name), arguments) => + // val nArgs = arguments.map(evaluate(_)) + // val args = nArgs.map(_.expValue) + // val retVal = monoer.monomorphizeCall(name, args) + // val retExp = Expr.Apply(nm, nArgs) + // retExp.expValue = retVal + // retExp case other@Expr.Apply(callee, arguments) => + // def rec(x: MonoValue): MonoValue = { + // x match + // case f: FunctionValue => f + // case o: ObjectValue => rec(monoer.specializeSelect(o, "apply")) + // case _ => UnknownValue() + // } val calE = evaluate(callee) + val cal = calE.expValue val nArgs = arguments.map(evaluate) val args = nArgs.map(_.expValue) - val cal = calE.expValue - val retV = cal.values.map{ + val retV = cal.getValue.map{ case FunctionValue(name, prm, ctxArg) => - monoer.monomorphizeCall(name, ctxArg.unzip._2 ++ args) + val callResult = monoer.monomorphizeCall(name, ctxArg.unzip._2 ++ args) + debug.log(s"call result: $callResult") + callResult + case o: ObjectValue => + val sel = monoer.specializeSelect(o, "apply") + sel match + case FunctionValue(name, prm, ctx) => + val callResult = monoer.monomorphizeCall(name, ctx.unzip._2 ++ args) + debug.log(s"call result: $callResult") + callResult + case _ => BoundedExpr(UnknownValue()) case _ => BoundedExpr(UnknownValue()) - }.fold(BoundedExpr())(_ ++ _) + }.fold(BoundedExpr())((x, y) => { + x.unfoldVars + y.unfoldVars + debug.log(s"merging $x with $y") + val xy = x ++ y + debug.log(s"result $xy") + xy + }) val retExp = Expr.Apply(calE, nArgs) retExp.expValue = retV retExp case Expr.Select(receiver, field) => val rec = evaluate(receiver) - val retV = rec.expValue.values.map{ + val retV = rec.expValue.getValue.map{ case ObjectValue(_, flds) if flds.contains(field.name) => flds.get(field.name).get case obj: ObjectValue => @@ -197,7 +221,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ case Expr.Subscript(receiver, index) => ??? case Expr.Match(scrutinee, branches) => ??? } - // }(_.expValue) + }(_.expValue) def defunctionalize(rawExpr: Expr): Expr = { val ret: Expr = rawExpr match { @@ -206,13 +230,17 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ val nRec = defunctionalize(receiver) val nArgs = args.map(defunctionalize) val branches = ArrayBuffer[CaseBranch]() - receiver.expValue.values.foreach{ + receiver.expValue.getValue.foreach{ case ObjectValue(name, _) => branches.addOne(CaseBranch.Instance(Expr.Ref(name), Expr.Ref("obj"), Expr.Apply(Expr.Ref(s"$field$$$name"), Expr.Ref("obj") :: nArgs))) case _ => () } Expr.Match(nRec, branches) - case Expr.Apply(callee, arguments) => Expr.Apply(defunctionalize(callee), arguments.map(defunctionalize)) + case Expr.Apply(callee, arguments) => + if(callee.expValue.getValue.find(_.isInstanceOf[ObjectValue]).isDefined) + defunctionalize(Expr.Apply(Expr.Select(callee, Expr.Ref("apply")), arguments)) + else + Expr.Apply(defunctionalize(callee), arguments.map(defunctionalize)) case Expr.New(typeName, args) => Expr.New(typeName, args.map(defunctionalize)) case Expr.Tuple(fields) => Expr.Tuple(fields.map(defunctionalize)) case Expr.LetIn(isRec, name, rhs, body) => Expr.LetIn(isRec, name, defunctionalize(rhs), defunctionalize(body)) diff --git a/compiler/shared/main/scala/mlscript/compiler/syntax.scala b/compiler/shared/main/scala/mlscript/compiler/syntax.scala index 8140eeb2d..ce7496080 100644 --- a/compiler/shared/main/scala/mlscript/compiler/syntax.scala +++ b/compiler/shared/main/scala/mlscript/compiler/syntax.scala @@ -186,6 +186,7 @@ enum TypeDeclKind: case Alias => "alias" case Class => "class" case Trait => "trait" + /** * Function parameters: `(specializable, name)`. diff --git a/compiler/shared/test/diff/LambLift.mls b/compiler/shared/test/diff/LambLift.mls new file mode 100644 index 000000000..7ad648f7c --- /dev/null +++ b/compiler/shared/test/diff/LambLift.mls @@ -0,0 +1,72 @@ +:NewParser +:ParseOnly + +fun foo() = + fun local(x) = + class Foo { + fun bar = x + foo(x) + } + Foo().bar + local(1) +foo() +//│ |#fun| |foo|(||)| |#=|→|#fun| |local|(|x|)| |#=|→|#class| |Foo| |{|→|#fun| |bar| |#=| |x| |+| |foo|(|x|)|←|↵|}|↵|Foo|(||)|.bar|←|↵|local|(|1|)|←|↵|foo|(||)| +//│ Parsed: {fun foo = => {fun local = x, => {class Foo() {fun bar = + (x,) (foo (x,),)}; (Foo ()).bar}; local (1,)}; foo ()} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(), Blk(...))), App(Var(foo), Tup())) +//│ Lifted: +//│ TypingUnit { +//│ class Foo$1(x,) {fun bar = + ((this).x,) (foo ((this).x,),)} +//│ fun foo = => {fun local = x, => {(Foo$1 (x,)).bar}; local (1,)} +//│ Code(List(foo ())) +//│ } + +fun foo(f) = + f(1) +foo(x => x+1) +//│ |#fun| |foo|(|f|)| |#=| |→|f|(|1|)|←|↵|foo|(|x| |=>| |x|+|1|)| +//│ Parsed: {fun foo = f, => {f (1,)}; foo (x, => + (x,) (1,),)} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(f)), Blk(...))), App(Var(foo), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1))))))) +//│ Lifted: +//│ TypingUnit { +//│ class Lambda1$1$1() {fun apply = x, => + (x,) (1,)} +//│ fun foo = f, => {f (1,)} +//│ Code(List(foo ({new Lambda1$1$1() {}},))) +//│ } + +fun foo(x) = + fun bar(f) = + f(x) + bar(y => y+x) +foo(1) +//│ |#fun| |foo|(|x|)| |#=| |→|#fun| |bar|(|f|)| |#=| |→|f|(|x|)|←|↵|bar|(|y| |=>| |y|+|x|)|←|↵|foo|(|1|)| +//│ Parsed: {fun foo = x, => {fun bar = f, => {f (x,)}; bar (y, => + (y,) (x,),)}; foo (1,)} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: IntLit(1)))) +//│ Lifted: +//│ TypingUnit { +//│ class Lambda1$1$1(x,) {fun apply = y, => + (y,) ((this).x,)} +//│ fun foo = x, => {fun bar = f, => {f (x,)}; bar ({new Lambda1$1$1(x,) {}},)} +//│ Code(List(foo (1,))) +//│ } + +fun foo(f) = + f(1) +class A(y){ + fun bar(z) = y+z +} +fun app(a) = + foo(z => a.bar(z)) +app(new A(1)) +//│ |#fun| |foo|(|f|)| |#=| |→|f|(|1|)|←|↵|#class| |A|(|y|)|{|→|#fun| |bar|(|z|)| |#=| |y|+|z|←|↵|}|↵|#fun| |app|(|a|)| |#=| |→|foo|(|z| |=>| |a|.bar|(|z|)|)|←|↵|app|(|#new| |A|(|1|)|)| +//│ Parsed: {fun foo = f, => {f (1,)}; class A(y,) {fun bar = z, => + (y,) (z,)}; fun app = a, => {foo (z, => (a).bar (z,),)}; app (new A(1,) {},)} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(f)), Blk(...))), NuTypeDef(class, A, (), Tup(_: Var(y)), (), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(z)), App(App(Var(+), Tup(_: Var(y))), Tup(_: Var(z))))))), NuFunDef(None, app, [], Lam(Tup(_: Var(a)), Blk(...))), App(Var(app), Tup(_: New(Some((TypeName(A),1,)), TypingUnit(List()))))) +//│ Lifted: +//│ TypingUnit { +//│ class A$1(y,) {fun bar = z, => + ((this).y,) (z,)} +//│ class Lambda1$1$2(a,) {fun apply = z, => ((this).a).bar (z,)} +//│ fun foo = f, => {f (1,)} +//│ fun app = a, => {foo ({new Lambda1$1$2(a,) {}},)} +//│ Code(List(app (new A$1(1,) {},))) +//│ } diff --git a/compiler/shared/test/diff/LifterBlks.mls b/compiler/shared/test/diff/LifterBlks.mls index b9f90318b..3fd026b82 100644 --- a/compiler/shared/test/diff/LifterBlks.mls +++ b/compiler/shared/test/diff/LifterBlks.mls @@ -222,8 +222,12 @@ class A{ //│ TypingUnit(NuTypeDef(class, A, (TypeName(T)), Tup(), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, f, [], Asc(Lam(Tup(_: Var(x)), Lam(Tup(_: Var(y)), Var(x))), Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T))))), NuFunDef(None, g, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T)))))))))) //│ Lifted: //│ TypingUnit { +//│ class A$1_B$2_Lambda1$1$3_Lambda1$2$4(par$A$1_B$2_Lambda1$1$3, x,) {fun apply = y, => (this).x} +//│ class A$1_B$2_Lambda1$1$3(par$A$1_B$2,) { +//│ fun apply = x, => {new A$1_B$2_Lambda1$1$3_Lambda1$2$4(this, x,) {}} +//│ } //│ class A$1_B$2[T](par$A$1,) { -//│ fun f = x, => y, => x : Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(A$1_B$2))))),TypeName(T))) +//│ fun f = {new A$1_B$2_Lambda1$1$3(this,) {}} : Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(A$1_B$2))))),TypeName(T))) //│ fun g = T -> A$1_B$2 -> T //│ } //│ class A$1[T]() {} diff --git a/compiler/shared/test/diff/mono.mls b/compiler/shared/test/diff/mono.mls index c0de92e71..a7bf04ee3 100644 --- a/compiler/shared/test/diff/mono.mls +++ b/compiler/shared/test/diff/mono.mls @@ -121,7 +121,9 @@ if(b) then 1 else 2 //│ TypingUnit(App(Bra(rcd = false, Tup(_: Lam(Tup(_: Var(f), _: Var(g)), App(Var(f), Tup(_: Var(g)))))), Tup(_: Lam(Tup(_: Var(f)), Var(f)), _: Var(true)))) //│ Lifted: //│ TypingUnit { -//│ Code(List('(' f, g, => f (g,), ')' (f, => f, true,))) +//│ class Lambda2$1$1() {fun apply = f, g, => f (g,)} +//│ class Lambda1$2$2() {fun apply = f, => f} +//│ Code(List('(' {new Lambda2$1$1() {}}, ')' ({new Lambda1$2$2() {}}, true,))) //│ } @@ -133,7 +135,8 @@ if(b) then 1 else 2 //│ TypingUnit(App(Bra(rcd = false, Tup(_: Lam(Tup(_: Var(b)), If((b) then true, Some(Var(false)))))), Tup(_: Var(true)))) //│ Lifted: //│ TypingUnit { -//│ Code(List('(' b, => if (b) then true else false, ')' (true,))) +//│ class Lambda1$1$1() {fun apply = b, => if (b) then true else false} +//│ Code(List('(' {new Lambda1$1$1() {}}, ')' (true,))) //│ } // :mono @@ -183,174 +186,468 @@ count(new List(new List(new Nil(0, false), true), true)) //│ } :mono -class List(e, tail){ - fun gen() = new List(e, tail.gen()) +class Cons(e, tail){ + fun gen() = new Cons(e, tail.gen()) } class Nil(){ - fun gen() = new List(0, this) + fun gen() = new Cons(0, this) } fun generate(x) = - if x > 0 then new List(x, generate(x+1)) else new Nil() + if x > 0 then new Cons(x, generate(x+1)) else new Nil() generate(10).gen() -//│ |#class| |List|(|e|,| |tail|)|{|→|#fun| |gen|(||)| |#=| |#new| |List|(|e|,| |tail|.gen|(||)|)|←|↵|}|↵|#class| |Nil|(||)|{|→|#fun| |gen|(||)| |#=| |#new| |List|(|0|,| |this|)|←|↵|}|↵|#fun| |generate|(|x|)| |#=| |→|#if| |x| |>| |0| |#then| |#new| |List|(|x|,| |generate|(|x|+|1|)|)| |#else| |#new| |Nil|(||)|←|↵|generate|(|10|)|.gen|(||)| -//│ Parsed: {class List(e, tail,) {fun gen = => new List(e, (tail).gen (),) {}}; class Nil() {fun gen = => new List(0, this,) {}}; fun generate = x, => {if (> (x,) (0,)) then new List(x, generate (+ (x,) (1,),),) {} else new Nil() {}}; (generate (10,)).gen ()} +//│ |#class| |Cons|(|e|,| |tail|)|{|→|#fun| |gen|(||)| |#=| |#new| |Cons|(|e|,| |tail|.gen|(||)|)|←|↵|}|↵|#class| |Nil|(||)|{|→|#fun| |gen|(||)| |#=| |#new| |Cons|(|0|,| |this|)|←|↵|}|↵|#fun| |generate|(|x|)| |#=| |→|#if| |x| |>| |0| |#then| |#new| |Cons|(|x|,| |generate|(|x|+|1|)|)| |#else| |#new| |Nil|(||)|←|↵|generate|(|10|)|.gen|(||)| +//│ Parsed: {class Cons(e, tail,) {fun gen = => new Cons(e, (tail).gen (),) {}}; class Nil() {fun gen = => new Cons(0, this,) {}}; fun generate = x, => {if (> (x,) (0,)) then new Cons(x, generate (+ (x,) (1,),),) {} else new Nil() {}}; (generate (10,)).gen ()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, gen, [], Lam(Tup(), New(Some((TypeName(List),e, (tail).gen (),)), TypingUnit(List())))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, gen, [], Lam(Tup(), New(Some((TypeName(List),0, this,)), TypingUnit(List())))))), NuFunDef(None, generate, [], Lam(Tup(_: Var(x)), Blk(...))), App(Sel(App(Var(generate), Tup(_: IntLit(10))), gen), Tup())) +//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, gen, [], Lam(Tup(), New(Some((TypeName(Cons),e, (tail).gen (),)), TypingUnit(List())))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, gen, [], Lam(Tup(), New(Some((TypeName(Cons),0, this,)), TypingUnit(List())))))), NuFunDef(None, generate, [], Lam(Tup(_: Var(x)), Blk(...))), App(Sel(App(Var(generate), Tup(_: IntLit(10))), gen), Tup())) //│ Lifted: //│ TypingUnit { -//│ class List$1(e, tail,) { -//│ fun gen = => new List$1((this).e, ((this).tail).gen (),) {} +//│ class Cons$1(e, tail,) { +//│ fun gen = => new Cons$1((this).e, ((this).tail).gen (),) {} //│ } -//│ class Nil$2() {fun gen = => new List$1(0, this,) {}} -//│ fun generate = x, => {if (> (x,) (0,)) then new List$1(x, generate (+ (x,) (1,),),) {} else new Nil$2() {}} +//│ class Nil$2() {fun gen = => new Cons$1(0, this,) {}} +//│ fun generate = x, => {if (> (x,) (0,)) then new Cons$1(x, generate (+ (x,) (1,),),) {} else new Nil$2() {}} //│ Code(List((generate (10,)).gen ())) //│ } //│ Mono: //│ //│ Mono result: //│ main$$3() -//│ fun gen$List$1(this) = -//│ new List$1 (this.e, this.tail match {case obj: List$1 => gen$List$1(obj); case obj: Nil$2 => gen$Nil$2(obj)}) +//│ fun gen$Cons$1(this) = +//│ new Cons$1 (this.e, this.tail match {case obj: Nil$2 => gen$Nil$2(obj); case obj: Cons$1 => gen$Cons$1(obj)}) //│ fun gen$Nil$2(this) = -//│ new List$1 (#0, this) +//│ new Cons$1 (#0, this) //│ fun main$$3() = -//│ generate(#10) match {case obj: Nil$2 => gen$Nil$2(obj); case obj: List$1 => gen$List$1(obj)} +//│ generate(#10) match {case obj: Nil$2 => gen$Nil$2(obj); case obj: Cons$1 => gen$Cons$1(obj)} //│ fun generate(x) = -//│ if (x > #0) then new List$1 (x, generate((x + #1))) else new Nil$2 () +//│ if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () +//│ class Nil$2() { +//│ } +//│ class Cons$1(e, tail) { +//│ } +//│ [mono] ┌───┬───────────────────────────────────────────────────────────────────────────┐ +//│ │ 1 │ main$$3() │ +//│ │ 2 │ fun main$$3() = │ +//│ │ 3 │ generate(#10).gen() │ +//│ │ 4 │ fun generate(x) = │ +//│ │ 5 │ if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () │ +//│ │ 6 │ class Nil$2() { │ +//│ │ 7 │ } │ +//│ │ 8 │ class Cons$1(e, tail) { │ +//│ │ 9 │ } │ +//│ └───┴───────────────────────────────────────────────────────────────────────────┘ //│ [mono] evaluating main$$3, rests: HashSet() //│ [mono] ========== updating main$$3 ========== -//│ [mono] main$$3: () -> [] @{} -//│ [mono] ┌ SPEC CALL generate with ([10]) -//│ [mono] │ comparing (([],0)) with (Plain([10])) -//│ [mono] │ first time encounter generate -//│ [mono] │ evaluating generate, rests: HashSet() -//│ [mono] │ ========== updating generate ========== -//│ [mono] │ generate: (([10],1)) -> [] @{main$$3} -//│ [mono] │ ┌ SPEC CALL generate with ([11]) -//│ [mono] │ │ comparing (([10],1)) with (Plain([*LIT*])) -//│ [mono] │ │ find finer args -//│ [mono] │ └ SPEC CALL [] -//│ [mono] │ comparing [] with [List$1@{e: [10], tail: []}] -//│ [mono] │ adding these funcs to queue: Set(main$$3, generate) -//│ [mono] │ generate: (([*LIT*],100000)) -> [List$1@{e: [10], tail: ***}] @{main$$3, generate} -//│ [mono] └ SPEC CALL [List$1@{e: [10], tail: ***}] -//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}]) -//│ [mono] │ comparing (([],0)) with (Plain([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}])) -//│ [mono] │ first time encounter gen$List$1 -//│ [mono] │ evaluating gen$List$1, rests: HashSet(main$$3, generate) -//│ [mono] │ ========== updating gen$List$1 ========== -//│ [mono] │ gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [] @{main$$3} -//│ [mono] │ ┌ SPEC CALL gen$List$1 with ([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}]) -//│ [mono] │ │ comparing (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) with (Plain([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}])) -//│ [mono] │ └ SPEC CALL [] -//│ [mono] │ comparing [] with [List$1@{e: [10], tail: []}] -//│ [mono] │ adding these funcs to queue: Set(main$$3, gen$List$1) -//│ [mono] │ gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [List$1@{e: [10], tail: []}] @{main$$3, gen$List$1} -//│ [mono] └ SPEC CALL [List$1@{e: [10], tail: []}] -//│ [mono] comparing [] with [List$1@{e: [10], tail: []}] -//│ [mono] adding these funcs to queue: Set() -//│ [mono] main$$3: () -> [List$1@{e: [10], tail: []}] @{} -//│ [mono] evaluating gen$List$1, rests: HashSet(main$$3, generate) -//│ [mono] ========== updating gen$List$1 ========== -//│ [mono] gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [List$1@{e: [10], tail: []}] @{main$$3, gen$List$1} -//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}]) -//│ [mono] │ comparing (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) with (Plain([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}])) -//│ [mono] └ SPEC CALL [List$1@{e: [10], tail: []}] -//│ [mono] comparing [List$1@{e: [10], tail: []}] with [List$1@{e: [10], tail: [List$1@{e: [10], tail: []}]}] -//│ [mono] adding these funcs to queue: Set(main$$3, gen$List$1) -//│ [mono] gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{main$$3, gen$List$1} -//│ [mono] evaluating gen$List$1, rests: HashSet(main$$3, generate) -//│ [mono] ========== updating gen$List$1 ========== -//│ [mono] gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{main$$3, gen$List$1} -//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}]) -//│ [mono] │ comparing (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) with (Plain([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}])) -//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] -//│ [mono] comparing [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] with [List$1@{e: [10], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}]}] -//│ [mono] gen$List$1: (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{main$$3, gen$List$1} +//│ [mono] main$$3: () -> *2*=[*2*=...]446468 @{} +//│ [mono] ┌ EVAL generate(#10).gen() +//│ [mono] │ ┌ EVAL generate(#10).gen +//│ [mono] │ │ ┌ EVAL generate(#10) +//│ [mono] │ │ │ ┌ EVAL generate +//│ [mono] │ │ │ └ EVAL [generate(x) given {}]241205 +//│ [mono] │ │ │ ┌ EVAL #10 +//│ [mono] │ │ │ └ EVAL [10]946944 +//│ [mono] │ │ │ ┌ SPEC CALL generate with ([10]946944) +//│ [mono] │ │ │ │ comparing (([]944117,0)) with (Plain([10]773991)) +//│ [mono] │ │ │ │ first time encounter generate +//│ [mono] │ │ │ │ evaluating generate, rests: HashSet() +//│ [mono] │ │ │ │ ========== updating generate ========== +//│ [mono] │ │ │ │ generate: (([10]773991,1)) -> *1*=[*1*=...]435529 @{main$$3} +//│ [mono] │ │ │ │ ┌ EVAL if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () +//│ [mono] │ │ │ │ │ ┌ EVAL if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () +//│ [mono] │ │ │ │ │ │ ┌ EVAL (x > #0) +//│ [mono] │ │ │ │ │ │ │ ┌ EVAL x +//│ [mono] │ │ │ │ │ │ │ └ EVAL [10]773991 +//│ [mono] │ │ │ │ │ │ │ ┌ EVAL #0 +//│ [mono] │ │ │ │ │ │ │ └ EVAL [0]245244 +//│ [mono] │ │ │ │ │ │ └ EVAL [true]467840 +//│ [mono] │ │ │ │ │ │ ┌ EVAL new Cons$1 (x, generate((x + #1))) +//│ [mono] │ │ │ │ │ │ │ ┌ EVAL x +//│ [mono] │ │ │ │ │ │ │ └ EVAL [10]773991 +//│ [mono] │ │ │ │ │ │ │ ┌ EVAL generate((x + #1)) +//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL generate +//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [generate(x) given {}]98216 +//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL (x + #1) +//│ [mono] │ │ │ │ │ │ │ │ │ ┌ EVAL x +//│ [mono] │ │ │ │ │ │ │ │ │ └ EVAL [10]773991 +//│ [mono] │ │ │ │ │ │ │ │ │ ┌ EVAL #1 +//│ [mono] │ │ │ │ │ │ │ │ │ └ EVAL [1]618214 +//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [11]771866 +//│ [mono] │ │ │ │ │ │ │ │ ┌ SPEC CALL generate with ([11]771866) +//│ [mono] │ │ │ │ │ │ │ │ │ comparing (([10]773991,1)) with (Plain([*LIT*]566055)) +//│ [mono] │ │ │ │ │ │ │ │ │ find finer args +//│ [mono] │ │ │ │ │ │ │ │ └ SPEC CALL [*1*=[*1*=...]435529]59154 +//│ [mono] │ │ │ │ │ │ │ │ call result: [*1*=[*1*=...]435529]59154 +//│ [mono] │ │ │ │ │ │ │ │ merging []115737 with [*1*=[*1*=...]435529]59154 +//│ [mono] │ │ │ │ │ │ │ │ result [*1*=[*1*=...]435529]5068 +//│ [mono] │ │ │ │ │ │ │ └ EVAL [*1*=[*1*=...]435529]5068 +//│ [mono] │ │ │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[*1*=...]435529]5068}]356015 +//│ [mono] │ │ │ │ │ │ ┌ EVAL new Nil$2 () +//│ [mono] │ │ │ │ │ │ └ EVAL [Nil$2@{}]431217 +//│ [mono] │ │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[*1*=...]435529]5068}]356015 +//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[*1*=...]435529]5068}]356015 +//│ [mono] │ │ │ │ comparing [*1*=...]435529 with [Cons$1@{e: [10]773991, tail: [*1*=[*1*=...]435529]5068}]356015 +//│ [mono] │ │ │ │ adding these funcs to queue: Set(main$$3, generate) +//│ [mono] │ │ │ │ generate: (([*LIT*]566055,100000)) -> *1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015 @{main$$3, generate} +//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]185805 +//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]185805 +//│ [mono] │ │ │ merging []938256 with [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]185805 +//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]290413 +//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]290413 +//│ [mono] │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]265840}]840962 +//│ [mono] │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]265840) +//│ [mono] │ │ comparing (([]364339,0)) with (Plain([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107)) +//│ [mono] │ │ first time encounter gen$Cons$1 +//│ [mono] │ │ evaluating gen$Cons$1, rests: HashSet(main$$3, generate) +//│ [mono] │ │ ========== updating gen$Cons$1 ========== +//│ [mono] │ │ gen$Cons$1: (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) -> *3*=[*3*=...]678569 @{main$$3} +//│ [mono] │ │ ┌ EVAL new Cons$1 (this.e, this.tail.gen()) +//│ [mono] │ │ │ ┌ EVAL this.e +//│ [mono] │ │ │ │ ┌ EVAL this +//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107 +//│ [mono] │ │ │ └ EVAL [10]277488 +//│ [mono] │ │ │ ┌ EVAL this.tail.gen() +//│ [mono] │ │ │ │ ┌ EVAL this.tail.gen +//│ [mono] │ │ │ │ │ ┌ EVAL this.tail +//│ [mono] │ │ │ │ │ │ ┌ EVAL this +//│ [mono] │ │ │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107 +//│ [mono] │ │ │ │ │ └ EVAL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]568228 +//│ [mono] │ │ │ │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]791258}]62179 +//│ [mono] │ │ │ │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]791258) +//│ [mono] │ │ │ │ │ comparing (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) with (Plain([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]933119)) +//│ [mono] │ │ │ │ └ SPEC CALL [*3*=[*3*=...]678569]809765 +//│ [mono] │ │ │ │ call result: [*3*=[*3*=...]678569]809765 +//│ [mono] │ │ │ │ merging []218815 with [*3*=[*3*=...]678569]809765 +//│ [mono] │ │ │ │ result [*3*=[*3*=...]678569]300678 +//│ [mono] │ │ │ └ EVAL [*3*=[*3*=...]678569]300678 +//│ [mono] │ │ └ EVAL [Cons$1@{e: [10]277488, tail: [*3*=[*3*=...]678569]300678}]407363 +//│ [mono] │ │ comparing [*3*=...]678569 with [Cons$1@{e: [10]277488, tail: [*3*=[*3*=...]678569]300678}]407363 +//│ [mono] │ │ adding these funcs to queue: Set(main$$3, gen$Cons$1) +//│ [mono] │ │ gen$Cons$1: (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) -> *3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363 @{main$$3, gen$Cons$1} +//│ [mono] │ └ SPEC CALL [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]595743 +//│ [mono] │ call result: [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]595743 +//│ [mono] │ merging []932118 with [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]595743 +//│ [mono] │ result [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]726572 +//│ [mono] └ EVAL [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]726572 +//│ [mono] comparing [*2*=...]446468 with [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]726572 +//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]726572 @{} +//│ [mono] evaluating gen$Cons$1, rests: HashSet(main$$3, generate) +//│ [mono] ========== updating gen$Cons$1 ========== +//│ [mono] gen$Cons$1: (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) -> *3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363 @{main$$3, gen$Cons$1} +//│ [mono] ┌ EVAL new Cons$1 (this.e, this.tail.gen()) +//│ [mono] │ ┌ EVAL this.e +//│ [mono] │ │ ┌ EVAL this +//│ [mono] │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107 +//│ [mono] │ └ EVAL [10]364447 +//│ [mono] │ ┌ EVAL this.tail.gen() +//│ [mono] │ │ ┌ EVAL this.tail.gen +//│ [mono] │ │ │ ┌ EVAL this.tail +//│ [mono] │ │ │ │ ┌ EVAL this +//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107 +//│ [mono] │ │ │ └ EVAL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]659072 +//│ [mono] │ │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]621451}]111512 +//│ [mono] │ │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]621451) +//│ [mono] │ │ │ comparing (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) with (Plain([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]90170)) +//│ [mono] │ │ └ SPEC CALL [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]7835 +//│ [mono] │ │ call result: [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]7835 +//│ [mono] │ │ merging []437242 with [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]7835 +//│ [mono] │ │ result [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]767874 +//│ [mono] │ └ EVAL [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]767874 +//│ [mono] └ EVAL [Cons$1@{e: [10]364447, tail: [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]767874}]507104 +//│ [mono] comparing [Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363 with [Cons$1@{e: [10]364447, tail: [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]767874}]507104 +//│ [mono] gen$Cons$1: (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) -> *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104 @{main$$3, gen$Cons$1} //│ [mono] evaluating main$$3, rests: HashSet(generate) //│ [mono] ========== updating main$$3 ========== -//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{} -//│ [mono] ┌ SPEC CALL generate with ([10]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [List$1@{e: [10], tail: ***}] -//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}]) -//│ [mono] │ comparing (([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}],3)) with (Plain([List$1@{e: [10], tail: [List$1@{e: [10], tail: ***}]}])) -//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] -//│ [mono] comparing [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] with [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] -//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{} +//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726572 @{} +//│ [mono] ┌ EVAL generate(#10).gen() +//│ [mono] │ ┌ EVAL generate(#10).gen +//│ [mono] │ │ ┌ EVAL generate(#10) +//│ [mono] │ │ │ ┌ EVAL generate +//│ [mono] │ │ │ └ EVAL [generate(x) given {}]226557 +//│ [mono] │ │ │ ┌ EVAL #10 +//│ [mono] │ │ │ └ EVAL [10]710582 +//│ [mono] │ │ │ ┌ SPEC CALL generate with ([10]710582) +//│ [mono] │ │ │ │ comparing (([*LIT*]566055,100000)) with (Plain([*LIT*]310229)) +//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]120919 +//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]120919 +//│ [mono] │ │ │ merging []708150 with [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]120919 +//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]709851 +//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]709851 +//│ [mono] │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]493684}]525682 +//│ [mono] │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]493684) +//│ [mono] │ │ comparing (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) with (Plain([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]295517)) +//│ [mono] │ └ SPEC CALL [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]400460 +//│ [mono] │ call result: [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]400460 +//│ [mono] │ merging []669796 with [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]400460 +//│ [mono] │ result [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 +//│ [mono] └ EVAL [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 +//│ [mono] comparing [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726572 with [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 +//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 @{} //│ [mono] evaluating generate, rests: HashSet() //│ [mono] ========== updating generate ========== -//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [10], tail: ***}] @{main$$3, generate} -//│ [mono] ┌ SPEC CALL generate with ([*LIT*]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [List$1@{e: [10], tail: ***}] -//│ [mono] comparing [List$1@{e: [10], tail: ***}] with [List$1@{e: [*LIT*], tail: [List$1@{e: [10], tail: ***}]} | Nil$2@{}] +//│ [mono] generate: (([*LIT*]566055,100000)) -> *1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015 @{main$$3, generate} +//│ [mono] ┌ EVAL if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () +//│ [mono] │ ┌ EVAL (x > #0) +//│ [mono] │ │ ┌ EVAL x +//│ [mono] │ │ └ EVAL [*LIT*]566055 +//│ [mono] │ │ ┌ EVAL #0 +//│ [mono] │ │ └ EVAL [0]425176 +//│ [mono] │ └ EVAL [*LIT*]455673 +//│ [mono] │ ┌ EVAL new Cons$1 (x, generate((x + #1))) +//│ [mono] │ │ ┌ EVAL x +//│ [mono] │ │ └ EVAL [*LIT*]566055 +//│ [mono] │ │ ┌ EVAL generate((x + #1)) +//│ [mono] │ │ │ ┌ EVAL generate +//│ [mono] │ │ │ └ EVAL [generate(x) given {}]68659 +//│ [mono] │ │ │ ┌ EVAL (x + #1) +//│ [mono] │ │ │ │ ┌ EVAL x +//│ [mono] │ │ │ │ └ EVAL [*LIT*]566055 +//│ [mono] │ │ │ │ ┌ EVAL #1 +//│ [mono] │ │ │ │ └ EVAL [1]230662 +//│ [mono] │ │ │ └ EVAL [*LIT*]687925 +//│ [mono] │ │ │ ┌ SPEC CALL generate with ([*LIT*]687925) +//│ [mono] │ │ │ │ comparing (([*LIT*]566055,100000)) with (Plain([*LIT*]345917)) +//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]385696 +//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]385696 +//│ [mono] │ │ │ merging []33723 with [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]385696 +//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]47299 +//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]47299 +//│ [mono] │ └ EVAL [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]47299}]543166 +//│ [mono] │ ┌ EVAL new Nil$2 () +//│ [mono] │ └ EVAL [Nil$2@{}]142725 +//│ [mono] └ EVAL [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]47299} | Nil$2@{}]642012 +//│ [mono] comparing [Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015 with [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]47299} | Nil$2@{}]642012 //│ [mono] adding these funcs to queue: Set(main$$3, generate) -//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$3, generate} +//│ [mono] generate: (([*LIT*]566055,100000)) -> *1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012 @{main$$3, generate} //│ [mono] evaluating main$$3, rests: HashSet(generate) //│ [mono] ========== updating main$$3 ========== -//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] @{} -//│ [mono] ┌ SPEC CALL generate with ([10]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] -//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]) -//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}],3)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}])) -//│ [mono] │ find finer args -//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] -//│ [mono] ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]) -//│ [mono] │ comparing (([],0)) with (Plain([Nil$2@{}])) -//│ [mono] │ first time encounter gen$Nil$2 -//│ [mono] │ evaluating gen$Nil$2, rests: HashSet(gen$List$1, generate) -//│ [mono] │ ========== updating gen$Nil$2 ========== -//│ [mono] │ gen$Nil$2: (([Nil$2@{}],1)) -> [] @{main$$3} -//│ [mono] │ comparing [] with [List$1@{e: [0], tail: [Nil$2@{}]}] -//│ [mono] │ adding these funcs to queue: Set(main$$3) -//│ [mono] │ gen$Nil$2: (([Nil$2@{}],1)) -> [List$1@{e: [0], tail: [Nil$2@{}]}] @{main$$3} -//│ [mono] └ SPEC CALL [List$1@{e: [0], tail: [Nil$2@{}]}] -//│ [mono] comparing [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]}] with [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***}]} | Nil$2@{}]}] +//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 @{} +//│ [mono] ┌ EVAL generate(#10).gen() +//│ [mono] │ ┌ EVAL generate(#10).gen +//│ [mono] │ │ ┌ EVAL generate(#10) +//│ [mono] │ │ │ ┌ EVAL generate +//│ [mono] │ │ │ └ EVAL [generate(x) given {}]111869 +//│ [mono] │ │ │ ┌ EVAL #10 +//│ [mono] │ │ │ └ EVAL [10]704974 +//│ [mono] │ │ │ ┌ SPEC CALL generate with ([10]704974) +//│ [mono] │ │ │ │ comparing (([*LIT*]566055,100000)) with (Plain([*LIT*]127031)) +//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]43871 +//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]43871 +//│ [mono] │ │ │ merging []554043 with [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]43871 +//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]841328 +//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]841328 +//│ [mono] │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]238870} | gen$Nil$2() given {this: [Nil$2@{}]935508}]123268 +//│ [mono] │ ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]935508) +//│ [mono] │ │ comparing (([]97006,0)) with (Plain([Nil$2@{}]877701)) +//│ [mono] │ │ first time encounter gen$Nil$2 +//│ [mono] │ │ evaluating gen$Nil$2, rests: HashSet(generate) +//│ [mono] │ │ ========== updating gen$Nil$2 ========== +//│ [mono] │ │ gen$Nil$2: (([Nil$2@{}]877701,1)) -> *4*=[*4*=...]519152 @{main$$3} +//│ [mono] │ │ ┌ EVAL new Cons$1 (#0, this) +//│ [mono] │ │ │ ┌ EVAL #0 +//│ [mono] │ │ │ └ EVAL [0]413996 +//│ [mono] │ │ │ ┌ EVAL this +//│ [mono] │ │ │ └ EVAL [Nil$2@{}]877701 +//│ [mono] │ │ └ EVAL [Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 +//│ [mono] │ │ comparing [*4*=...]519152 with [Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 +//│ [mono] │ │ adding these funcs to queue: Set(main$$3) +//│ [mono] │ │ gen$Nil$2: (([Nil$2@{}]877701,1)) -> *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 @{main$$3} +//│ [mono] │ └ SPEC CALL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]656947 +//│ [mono] │ call result: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]656947 +//│ [mono] │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]238870) +//│ [mono] │ │ comparing (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]5068}]506107,5)) with (Plain([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521)) +//│ [mono] │ │ find finer args +//│ [mono] │ └ SPEC CALL [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]978844 +//│ [mono] │ call result: [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]978844 +//│ [mono] │ merging []294987 with [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]656947 +//│ [mono] │ result [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]19092 +//│ [mono] │ merging [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]19092 with [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]978844 +//│ [mono] │ result [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]969872 +//│ [mono] └ EVAL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]969872 +//│ [mono] comparing [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 with [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]969872 //│ [mono] adding these funcs to queue: Set() -//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] @{} -//│ [mono] evaluating gen$List$1, rests: HashSet(main$$3, generate) -//│ [mono] ========== updating gen$List$1 ========== -//│ [mono] gen$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}],100002)) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] @{main$$3, gen$List$1} -//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]) -//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}],100002)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}])) -//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] -//│ [mono] ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]) -//│ [mono] │ comparing (([Nil$2@{}],1)) with (Plain([Nil$2@{}])) -//│ [mono] └ SPEC CALL [List$1@{e: [0], tail: [Nil$2@{}]}] -//│ [mono] comparing [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] with [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]}]}] -//│ [mono] gen$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}],100002)) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] @{main$$3, gen$List$1} +//│ [mono] main$$3: () -> *2*=[*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]969872 @{} +//│ [mono] evaluating gen$Cons$1, rests: HashSet(main$$3, generate) +//│ [mono] ========== updating gen$Cons$1 ========== +//│ [mono] gen$Cons$1: (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) -> *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104 @{main$$3, gen$Cons$1} +//│ [mono] ┌ EVAL new Cons$1 (this.e, this.tail.gen()) +//│ [mono] │ ┌ EVAL this.e +//│ [mono] │ │ ┌ EVAL this +//│ [mono] │ │ └ EVAL [Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521 +//│ [mono] │ └ EVAL [*LIT*]211259 +//│ [mono] │ ┌ EVAL this.tail.gen() +//│ [mono] │ │ ┌ EVAL this.tail.gen +//│ [mono] │ │ │ ┌ EVAL this.tail +//│ [mono] │ │ │ │ ┌ EVAL this +//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521 +//│ [mono] │ │ │ └ EVAL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]987988 +//│ [mono] │ │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]611974} | gen$Nil$2() given {this: [Nil$2@{}]710241}]564852 +//│ [mono] │ │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]611974) +//│ [mono] │ │ │ comparing (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) with (Plain([Cons$1@{e: [*LIT*]45932, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]795876}]173592)) +//│ [mono] │ │ └ SPEC CALL [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]472898 +//│ [mono] │ │ call result: [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]472898 +//│ [mono] │ │ ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]710241) +//│ [mono] │ │ │ comparing (([Nil$2@{}]877701,1)) with (Plain([Nil$2@{}]467485)) +//│ [mono] │ │ └ SPEC CALL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]443107 +//│ [mono] │ │ call result: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]443107 +//│ [mono] │ │ merging []996289 with [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]472898 +//│ [mono] │ │ result [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]179437 +//│ [mono] │ │ merging [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]179437 with [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]443107 +//│ [mono] │ │ result [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726509 +//│ [mono] │ └ EVAL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726509 +//│ [mono] └ EVAL [Cons$1@{e: [*LIT*]211259, tail: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726509}]130025 +//│ [mono] comparing [Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104 with [Cons$1@{e: [*LIT*]211259, tail: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726509}]130025 +//│ [mono] adding these funcs to queue: Set(main$$3, gen$Cons$1) +//│ [mono] gen$Cons$1: (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) -> *3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 @{main$$3, gen$Cons$1} +//│ [mono] evaluating gen$Cons$1, rests: HashSet(main$$3, generate) +//│ [mono] ========== updating gen$Cons$1 ========== +//│ [mono] gen$Cons$1: (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) -> *3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 @{main$$3, gen$Cons$1} +//│ [mono] ┌ EVAL new Cons$1 (this.e, this.tail.gen()) +//│ [mono] │ ┌ EVAL this.e +//│ [mono] │ │ ┌ EVAL this +//│ [mono] │ │ └ EVAL [Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521 +//│ [mono] │ └ EVAL [*LIT*]144235 +//│ [mono] │ ┌ EVAL this.tail.gen() +//│ [mono] │ │ ┌ EVAL this.tail.gen +//│ [mono] │ │ │ ┌ EVAL this.tail +//│ [mono] │ │ │ │ ┌ EVAL this +//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521 +//│ [mono] │ │ │ └ EVAL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]683896 +//│ [mono] │ │ └ EVAL [gen$Nil$2() given {this: [Nil$2@{}]402304} | gen$Cons$1() given {this: [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]954800}]797408 +//│ [mono] │ │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]954800) +//│ [mono] │ │ │ comparing (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) with (Plain([Cons$1@{e: [*LIT*]390244, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]550955}]868530)) +//│ [mono] │ │ └ SPEC CALL [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025]751281 +//│ [mono] │ │ call result: [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025]751281 +//│ [mono] │ │ ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]402304) +//│ [mono] │ │ │ comparing (([Nil$2@{}]877701,1)) with (Plain([Nil$2@{}]784911)) +//│ [mono] │ │ └ SPEC CALL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]862537 +//│ [mono] │ │ call result: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]862537 +//│ [mono] │ │ merging []983536 with [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025]751281 +//│ [mono] │ │ result [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025]532223 +//│ [mono] │ │ merging [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025]532223 with [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]862537 +//│ [mono] │ │ result [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361 +//│ [mono] │ └ EVAL [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361 +//│ [mono] └ EVAL [Cons$1@{e: [*LIT*]144235, tail: [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 +//│ [mono] comparing [Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 with [Cons$1@{e: [*LIT*]144235, tail: [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 +//│ [mono] gen$Cons$1: (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) -> *3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 @{main$$3, gen$Cons$1} //│ [mono] evaluating main$$3, rests: HashSet(generate) //│ [mono] ========== updating main$$3 ========== -//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] @{} -//│ [mono] ┌ SPEC CALL generate with ([10]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] -//│ [mono] ┌ SPEC CALL gen$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]) -//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}],100002)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}])) -//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] -//│ [mono] ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]) -//│ [mono] │ comparing (([Nil$2@{}],1)) with (Plain([Nil$2@{}])) -//│ [mono] └ SPEC CALL [List$1@{e: [0], tail: [Nil$2@{}]}] -//│ [mono] comparing [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] with [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]}] -//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] @{} +//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]969872 @{} +//│ [mono] ┌ EVAL generate(#10).gen() +//│ [mono] │ ┌ EVAL generate(#10).gen +//│ [mono] │ │ ┌ EVAL generate(#10) +//│ [mono] │ │ │ ┌ EVAL generate +//│ [mono] │ │ │ └ EVAL [generate(x) given {}]676913 +//│ [mono] │ │ │ ┌ EVAL #10 +//│ [mono] │ │ │ └ EVAL [10]123882 +//│ [mono] │ │ │ ┌ SPEC CALL generate with ([10]123882) +//│ [mono] │ │ │ │ comparing (([*LIT*]566055,100000)) with (Plain([*LIT*]823410)) +//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]862113 +//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]862113 +//│ [mono] │ │ │ merging []880020 with [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]862113 +//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]26923 +//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]26923 +//│ [mono] │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]577613} | gen$Nil$2() given {this: [Nil$2@{}]256414}]160088 +//│ [mono] │ ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]256414) +//│ [mono] │ │ comparing (([Nil$2@{}]877701,1)) with (Plain([Nil$2@{}]586004)) +//│ [mono] │ └ SPEC CALL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]204477 +//│ [mono] │ call result: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]204477 +//│ [mono] │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]577613) +//│ [mono] │ │ comparing (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) with (Plain([Cons$1@{e: [*LIT*]203630, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]402242}]147)) +//│ [mono] │ └ SPEC CALL [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794]436063 +//│ [mono] │ call result: [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794]436063 +//│ [mono] │ merging []782992 with [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]204477 +//│ [mono] │ result [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]977956 +//│ [mono] │ merging [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]977956 with [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794]436063 +//│ [mono] │ result [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]233330 +//│ [mono] └ EVAL [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]233330 +//│ [mono] comparing [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]969872 with [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]233330 +//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]233330 @{} //│ [mono] evaluating generate, rests: HashSet() //│ [mono] ========== updating generate ========== -//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$3, generate} -//│ [mono] ┌ SPEC CALL generate with ([*LIT*]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] -//│ [mono] comparing [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] with [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] -//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$3, generate} +//│ [mono] generate: (([*LIT*]566055,100000)) -> *1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012 @{main$$3, generate} +//│ [mono] ┌ EVAL if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () +//│ [mono] │ ┌ EVAL (x > #0) +//│ [mono] │ │ ┌ EVAL x +//│ [mono] │ │ └ EVAL [*LIT*]566055 +//│ [mono] │ │ ┌ EVAL #0 +//│ [mono] │ │ └ EVAL [0]86794 +//│ [mono] │ └ EVAL [*LIT*]973248 +//│ [mono] │ ┌ EVAL new Cons$1 (x, generate((x + #1))) +//│ [mono] │ │ ┌ EVAL x +//│ [mono] │ │ └ EVAL [*LIT*]566055 +//│ [mono] │ │ ┌ EVAL generate((x + #1)) +//│ [mono] │ │ │ ┌ EVAL generate +//│ [mono] │ │ │ └ EVAL [generate(x) given {}]985318 +//│ [mono] │ │ │ ┌ EVAL (x + #1) +//│ [mono] │ │ │ │ ┌ EVAL x +//│ [mono] │ │ │ │ └ EVAL [*LIT*]566055 +//│ [mono] │ │ │ │ ┌ EVAL #1 +//│ [mono] │ │ │ │ └ EVAL [1]131514 +//│ [mono] │ │ │ └ EVAL [*LIT*]436284 +//│ [mono] │ │ │ ┌ SPEC CALL generate with ([*LIT*]436284) +//│ [mono] │ │ │ │ comparing (([*LIT*]566055,100000)) with (Plain([*LIT*]804833)) +//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]679966 +//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]679966 +//│ [mono] │ │ │ merging []902989 with [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]679966 +//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]631787 +//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]631787 +//│ [mono] │ └ EVAL [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]631787}]601940 +//│ [mono] │ ┌ EVAL new Nil$2 () +//│ [mono] │ └ EVAL [Nil$2@{}]990186 +//│ [mono] └ EVAL [Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]631787}]359428 +//│ [mono] comparing [Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012 with [Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]631787}]359428 +//│ [mono] generate: (([*LIT*]566055,100000)) -> *1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]631787} | Nil$2@{}]359428 @{main$$3, generate} //│ [mono] //│ [mono] ==============final function signatures================== -//│ [mono] gen$List$1: ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]) -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] -//│ [mono] gen$Nil$2: ([Nil$2@{}]) -> [List$1@{e: [0], tail: [Nil$2@{}]}] -//│ [mono] main$$3: () -> [List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] -//│ [mono] generate: ([*LIT*]) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] +//│ [mono] gen$Cons$1: ([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]631787} | Nil$2@{}]359428]734933}]141521) -> *3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 +//│ [mono] gen$Nil$2: ([Nil$2@{}]877701) -> *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 +//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]233330 +//│ [mono] generate: ([*LIT*]566055) -> *1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]631787} | Nil$2@{}]359428 -:mono +// :mono +class List(e, tail) { + fun map(f) = new List(f(e), tail.map(f)) + fun count() = 1 + tail.count() +} +class Nil() { + fun map(f) = this + fun count() = 0 +} +fun add2(x) = x+2 +(new List(1, new List(2, new Nil()))).map(x => x+1).map(x => add2(x)) +//│ |#class| |List|(|e|,| |tail|)| |{|→|#fun| |map|(|f|)| |#=| |#new| |List|(|f|(|e|)|,| |tail|.map|(|f|)|)|↵|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |map|(|f|)| |#=| |this|↵|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#fun| |add2|(|x|)| |#=| |x|+|2|↵|(|#new| |List|(|1|,| |#new| |List|(|2|,| |#new| |Nil|(||)|)|)|)|.map|(|x| |=>| |x|+|1|)|.map|(|x| |=>| |add2|(|x|)|)| +//│ Parsed: {class List(e, tail,) {fun map = f, => new List(f (e,), (tail).map (f,),) {}; fun count = => + (1,) ((tail).count (),)}; class Nil() {fun map = f, => this; fun count = => 0}; fun add2 = x, => + (x,) (2,); (('(' new List(1, new List(2, new Nil() {},) {},) {}, ')').map (x, => + (x,) (1,),)).map (x, => add2 (x,),)} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, map, [], Lam(Tup(_: Var(f)), New(Some((TypeName(List),f (e,), (tail).map (f,),)), TypingUnit(List())))), NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, map, [], Lam(Tup(_: Var(f)), Var(this))), NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, add2, [], Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(2))))), App(Sel(App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(List),1, new List(2, new Nil() {},) {},)), TypingUnit(List())))), map), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1)))))), map), Tup(_: Lam(Tup(_: Var(x)), App(Var(add2), Tup(_: Var(x))))))) +//│ Lifted: +//│ TypingUnit { +//│ class List$1(e, tail,) { +//│ fun map = f, => new List$1(f ((this).e,), ((this).tail).map (f,),) {} +//│ fun count = => + (1,) (((this).tail).count (),) +//│ } +//│ class Nil$2() {fun map = f, => this; fun count = => 0} +//│ class Lambda1$1$3() {fun apply = x, => + (x,) (1,)} +//│ class Lambda1$2$4() {fun apply = x, => add2 (x,)} +//│ fun add2 = x, => + (x,) (2,) +//│ Code(List((('(' new List$1(1, new List$1(2, new Nil$2() {},) {},) {}, ')').map ({new Lambda1$1$3() {}},)).map ({new Lambda1$2$4() {}},))) +//│ } + +//| f match { +//| case obj: Lambda1$1$3 => apply$Lambda1$1$3(obj, this.e); +//| case obj: Lambda1$2$4 => apply$Lambda1$2$4(obj, this.e) +//| }, +//| this.tail match { +//| case obj: Nil$2 => map$Nil$2(obj, f); +//| case obj: List$1 => map$List$1(obj, f) +//| } +//| ) +//| case obj: List$1 => map$List$1(obj, new Lambda1$1$3 () ) +//| } match { +//| case obj: List$1 => map$List$1(obj, new Lambda1$2$4 () ) +//| } + + + +// :mono class List(e, tail) { fun count() = 1 + tail.count() } @@ -375,603 +672,919 @@ foo(generate(1)) //│ Code(List(foo (new List$1(1, new List$1(2, new Nil$2() {},) {},) {},))) //│ Code(List(foo (generate (1,),))) //│ } + +:mono +fun foo(x) = + (f => f(x))(z => z+1) +foo(2) +//│ |#fun| |foo|(|x|)| |#=| |→|(|f| |=>| |f|(|x|)|)|(|z| |=>| |z|+|1|)|←|↵|foo|(|2|)| +//│ Parsed: {fun foo = x, => {'(' f, => f (x,), ')' (z, => + (z,) (1,),)}; foo (2,)} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: IntLit(2)))) +//│ Lifted: +//│ TypingUnit { +//│ class Lambda1$1$1(x,) {fun apply = f, => f ((this).x,)} +//│ class Lambda1$2$2() {fun apply = z, => + (z,) (1,)} +//│ fun foo = x, => {'(' {new Lambda1$1$1(x,) {}}, ')' ({new Lambda1$2$2() {}},)} +//│ Code(List(foo (2,))) +//│ } //│ Mono: //│ //│ Mono result: -//│ main$$4() -//│ main$$5() -//│ fun count$Nil$2(this) = -//│ #0 +//│ main$$3() +//│ fun apply$Lambda1$1$1(this, f) = +//│ f match {case obj: Lambda1$2$2 => apply$Lambda1$2$2(obj, this.x)} //│ fun foo(x) = -//│ x match {case obj: List$1 => count$List$1(obj); case obj: Nil$2 => count$Nil$2(obj)} -//│ fun count$List$1(this) = -//│ (#1 + this.tail match {case obj: Nil$2 => count$Nil$2(obj); case obj: List$1 => count$List$1(obj)}) -//│ fun main$$5() = -//│ foo(generate(#1)) -//│ fun main$$4() = -//│ foo(new List$1 (#1, new List$1 (#2, new Nil$2 () ) ) ) -//│ fun generate(x) = -//│ if (x > #0) then new List$1 (x, generate((x + #1))) else new Nil$2 () -//│ [mono] evaluating main$$5, rests: HashSet(main$$4) -//│ [mono] ========== updating main$$5 ========== -//│ [mono] main$$5: () -> [] @{} -//│ [mono] ┌ SPEC CALL generate with ([1]) -//│ [mono] │ comparing (([],0)) with (Plain([1])) -//│ [mono] │ first time encounter generate -//│ [mono] │ evaluating generate, rests: HashSet(main$$4) -//│ [mono] │ ========== updating generate ========== -//│ [mono] │ generate: (([1],1)) -> [] @{main$$5} -//│ [mono] │ ┌ SPEC CALL generate with ([2]) -//│ [mono] │ │ comparing (([1],1)) with (Plain([*LIT*])) +//│ new Lambda1$1$1 (x) match {case obj: Lambda1$1$1 => apply$Lambda1$1$1(obj, new Lambda1$2$2 () )} +//│ fun main$$3() = +//│ foo(#2) +//│ fun apply$Lambda1$2$2(this, z) = +//│ (z + #1) +//│ class Lambda1$1$1(x) { +//│ } +//│ class Lambda1$2$2() { +//│ } +//│ [mono] ┌───┬─────────────────────────────────────────────────┐ +//│ │ 1 │ main$$3() │ +//│ │ 2 │ fun foo(x) = │ +//│ │ 3 │ (new Lambda1$1$1 (x) , )(new Lambda1$2$2 () ) │ +//│ │ 4 │ fun main$$3() = │ +//│ │ 5 │ foo(#2) │ +//│ │ 6 │ class Lambda1$1$1(x) { │ +//│ │ 7 │ } │ +//│ │ 8 │ class Lambda1$2$2() { │ +//│ │ 9 │ } │ +//│ └───┴─────────────────────────────────────────────────┘ +//│ [mono] evaluating main$$3, rests: HashSet() +//│ [mono] ========== updating main$$3 ========== +//│ [mono] main$$3: () -> *6*=[*6*=...]972540 @{} +//│ [mono] ┌ EVAL foo(#2) +//│ [mono] │ ┌ EVAL foo +//│ [mono] │ └ EVAL [foo(x) given {}]292788 +//│ [mono] │ ┌ EVAL #2 +//│ [mono] │ └ EVAL [2]44328 +//│ [mono] │ ┌ SPEC CALL foo with ([2]44328) +//│ [mono] │ │ comparing (([]249361,0)) with (Plain([2]884782)) +//│ [mono] │ │ first time encounter foo +//│ [mono] │ │ evaluating foo, rests: HashSet() +//│ [mono] │ │ ========== updating foo ========== +//│ [mono] │ │ foo: (([2]884782,1)) -> *5*=[*5*=...]221469 @{main$$3} +//│ [mono] │ │ ┌ EVAL (new Lambda1$1$1 (x) , )(new Lambda1$2$2 () ) +//│ [mono] │ │ │ ┌ EVAL (new Lambda1$1$1 (x) , )(new Lambda1$2$2 () ) +//│ [mono] │ │ │ │ ┌ EVAL (new Lambda1$1$1 (x) , ) +//│ [mono] │ │ │ │ │ ┌ EVAL new Lambda1$1$1 (x) +//│ [mono] │ │ │ │ │ │ ┌ EVAL new Lambda1$1$1 (x) +//│ [mono] │ │ │ │ │ │ │ ┌ EVAL x +//│ [mono] │ │ │ │ │ │ │ └ EVAL [2]884782 +//│ [mono] │ │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [2]884782}]241619 +//│ [mono] │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [2]884782}]241619 +//│ [mono] │ │ │ │ └ EVAL [Lambda1$1$1@{x: [2]884782}]241619 +//│ [mono] │ │ │ │ ┌ EVAL new Lambda1$2$2 () +//│ [mono] │ │ │ │ │ ┌ EVAL new Lambda1$2$2 () +//│ [mono] │ │ │ │ │ └ EVAL [Lambda1$2$2@{}]748878 +//│ [mono] │ │ │ │ └ EVAL [Lambda1$2$2@{}]748878 +//│ [mono] │ │ │ │ ┌ SPEC CALL apply$Lambda1$1$1 with ([Lambda1$1$1@{x: [2]884782}]318593, [Lambda1$2$2@{}]748878) +//│ [mono] │ │ │ │ │ comparing (([]844284,0), ([]374495,0)) with (Plain([Lambda1$1$1@{x: [2]884782}]890026), Plain([Lambda1$2$2@{}]97477)) +//│ [mono] │ │ │ │ │ first time encounter apply$Lambda1$1$1 +//│ [mono] │ │ │ │ │ evaluating apply$Lambda1$1$1, rests: HashSet() +//│ [mono] │ │ │ │ │ ========== updating apply$Lambda1$1$1 ========== +//│ [mono] │ │ │ │ │ apply$Lambda1$1$1: (([Lambda1$1$1@{x: [2]884782}]890026,2) X ([Lambda1$2$2@{}]97477,1)) -> *7*=[*7*=...]154467 @{foo} +//│ [mono] │ │ │ │ │ ┌ EVAL f(this.x) +//│ [mono] │ │ │ │ │ │ ┌ EVAL f +//│ [mono] │ │ │ │ │ │ └ EVAL [Lambda1$2$2@{}]97477 +//│ [mono] │ │ │ │ │ │ ┌ EVAL this.x +//│ [mono] │ │ │ │ │ │ │ ┌ EVAL this +//│ [mono] │ │ │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [2]884782}]890026 +//│ [mono] │ │ │ │ │ │ └ EVAL [2]124143 +//│ [mono] │ │ │ │ │ │ ┌ SPEC CALL apply$Lambda1$2$2 with ([Lambda1$2$2@{}]965309, [2]124143) +//│ [mono] │ │ │ │ │ │ │ comparing (([]522878,0), ([]246758,0)) with (Plain([Lambda1$2$2@{}]151341), Plain([2]679883)) +//│ [mono] │ │ │ │ │ │ │ first time encounter apply$Lambda1$2$2 +//│ [mono] │ │ │ │ │ │ │ evaluating apply$Lambda1$2$2, rests: HashSet() +//│ [mono] │ │ │ │ │ │ │ ========== updating apply$Lambda1$2$2 ========== +//│ [mono] │ │ │ │ │ │ │ apply$Lambda1$2$2: (([Lambda1$2$2@{}]151341,1) X ([2]679883,1)) -> *8*=[*8*=...]427103 @{apply$Lambda1$1$1} +//│ [mono] │ │ │ │ │ │ │ ┌ EVAL (z + #1) +//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL z +//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [2]679883 +//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL #1 +//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [1]447076 +//│ [mono] │ │ │ │ │ │ │ └ EVAL [3]329135 +//│ [mono] │ │ │ │ │ │ │ comparing [*8*=...]427103 with [3]329135 +//│ [mono] │ │ │ │ │ │ │ apply$Lambda1$2$2: (([Lambda1$2$2@{}]151341,1) X ([2]679883,1)) -> *8*=[3]329135 @{apply$Lambda1$1$1} +//│ [mono] │ │ │ │ │ │ └ SPEC CALL [*8*=[3]329135]597991 +//│ [mono] │ │ │ │ │ │ call result: [*8*=[3]329135]597991 +//│ [mono] │ │ │ │ │ │ merging []963048 with [*8*=[3]329135]597991 +//│ [mono] │ │ │ │ │ │ result [*8*=[3]329135]570854 +//│ [mono] │ │ │ │ │ └ EVAL [*8*=[3]329135]570854 +//│ [mono] │ │ │ │ │ comparing [*7*=...]154467 with [*8*=[3]329135]570854 +//│ [mono] │ │ │ │ │ apply$Lambda1$1$1: (([Lambda1$1$1@{x: [2]884782}]890026,2) X ([Lambda1$2$2@{}]97477,1)) -> *7*=[*8*=[3]329135]570854 @{foo} +//│ [mono] │ │ │ │ └ SPEC CALL [*7*=[*8*=[3]329135]570854]518807 +//│ [mono] │ │ │ │ call result: [*7*=[*8*=[3]329135]570854]518807 +//│ [mono] │ │ │ │ merging []524013 with [*7*=[*8*=[3]329135]570854]518807 +//│ [mono] │ │ │ │ result [*7*=[*8*=[3]329135]570854]58141 +//│ [mono] │ │ │ └ EVAL [*7*=[*8*=[3]329135]570854]58141 +//│ [mono] │ │ └ EVAL [*7*=[*8*=[3]329135]570854]58141 +//│ [mono] │ │ comparing [*5*=...]221469 with [*7*=[*8*=[3]329135]570854]58141 +//│ [mono] │ │ foo: (([2]884782,1)) -> *5*=[*7*=[*8*=[3]329135]570854]58141 @{main$$3} +//│ [mono] │ └ SPEC CALL [*5*=[*7*=[*8*=[3]329135]570854]58141]733948 +//│ [mono] │ call result: [*5*=[*7*=[*8*=[3]329135]570854]58141]733948 +//│ [mono] │ merging []860020 with [*5*=[*7*=[*8*=[3]329135]570854]58141]733948 +//│ [mono] │ result [*5*=[*7*=[*8*=[3]329135]570854]58141]992452 +//│ [mono] └ EVAL [*5*=[*7*=[*8*=[3]329135]570854]58141]992452 +//│ [mono] comparing [*6*=...]972540 with [*5*=[*7*=[*8*=[3]329135]570854]58141]992452 +//│ [mono] main$$3: () -> *6*=[*5*=[*7*=[*8*=[3]329135]570854]58141]992452 @{} +//│ [mono] +//│ [mono] ==============final function signatures================== +//│ [mono] apply$Lambda1$1$1: ([Lambda1$1$1@{x: [2]884782}]890026 X [Lambda1$2$2@{}]97477) -> *7*=[*8*=[3]329135]570854 +//│ [mono] foo: ([2]884782) -> *5*=[*7*=[*8*=[3]329135]570854]58141 +//│ [mono] main$$3: () -> *6*=[*5*=[*7*=[*8*=[3]329135]570854]58141]992452 +//│ [mono] apply$Lambda1$2$2: ([Lambda1$2$2@{}]151341 X [2]679883) -> *8*=[3]329135 + +:mono +fun f(x) = + (y => f(x+y)).apply(x+1) +f(1) +//│ |#fun| |f|(|x|)| |#=|→|(|y| |=>| |f|(|x|+|y|)|)|.apply|(|x|+|1|)|←|↵|f|(|1|)| +//│ Parsed: {fun f = x, => {('(' y, => f (+ (x,) (y,),), ')').apply (+ (x,) (1,),)}; f (1,)} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(f), Tup(_: IntLit(1)))) +//│ Lifted: +//│ TypingUnit { +//│ class Lambda1$1$1(x,) {fun apply = y, => f (+ ((this).x,) (y,),)} +//│ fun f = x, => {('(' {new Lambda1$1$1(x,) {}}, ')').apply (+ (x,) (1,),)} +//│ Code(List(f (1,))) +//│ } +//│ Mono: +//│ +//│ Mono result: +//│ main$$2() +//│ fun apply$Lambda1$1$1(this, y) = +//│ f((this.x + y)) +//│ fun f(x) = +//│ new Lambda1$1$1 (x) match {case obj: Lambda1$1$1 => apply$Lambda1$1$1(obj, (x + #1))} +//│ fun main$$2() = +//│ f(#1) +//│ class Lambda1$1$1(x) { +//│ } +//│ [mono] ┌───┬────────────────────────────────────────────┐ +//│ │ 1 │ main$$2() │ +//│ │ 2 │ fun f(x) = │ +//│ │ 3 │ (new Lambda1$1$1 (x) , ).apply((x + #1)) │ +//│ │ 4 │ fun main$$2() = │ +//│ │ 5 │ f(#1) │ +//│ │ 6 │ class Lambda1$1$1(x) { │ +//│ │ 7 │ } │ +//│ └───┴────────────────────────────────────────────┘ +//│ [mono] evaluating main$$2, rests: HashSet() +//│ [mono] ========== updating main$$2 ========== +//│ [mono] main$$2: () -> *10*=[*10*=...]263411 @{} +//│ [mono] ┌ EVAL f(#1) +//│ [mono] │ ┌ EVAL f +//│ [mono] │ └ EVAL [f(x) given {}]652110 +//│ [mono] │ ┌ EVAL #1 +//│ [mono] │ └ EVAL [1]711504 +//│ [mono] │ ┌ SPEC CALL f with ([1]711504) +//│ [mono] │ │ comparing (([]43423,0)) with (Plain([1]551120)) +//│ [mono] │ │ first time encounter f +//│ [mono] │ │ evaluating f, rests: HashSet() +//│ [mono] │ │ ========== updating f ========== +//│ [mono] │ │ f: (([1]551120,1)) -> *9*=[*9*=...]272491 @{main$$2} +//│ [mono] │ │ ┌ EVAL (new Lambda1$1$1 (x) , ).apply((x + #1)) +//│ [mono] │ │ │ ┌ EVAL (new Lambda1$1$1 (x) , ).apply((x + #1)) +//│ [mono] │ │ │ │ ┌ EVAL (new Lambda1$1$1 (x) , ).apply +//│ [mono] │ │ │ │ │ ┌ EVAL (new Lambda1$1$1 (x) , ) +//│ [mono] │ │ │ │ │ │ ┌ EVAL new Lambda1$1$1 (x) +//│ [mono] │ │ │ │ │ │ │ ┌ EVAL new Lambda1$1$1 (x) +//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL x +//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [1]551120 +//│ [mono] │ │ │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [1]551120}]260519 +//│ [mono] │ │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [1]551120}]260519 +//│ [mono] │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [1]551120}]260519 +//│ [mono] │ │ │ │ └ EVAL [apply$Lambda1$1$1(y) given {this: [Lambda1$1$1@{x: [1]551120}]70265}]125057 +//│ [mono] │ │ │ │ ┌ EVAL (x + #1) +//│ [mono] │ │ │ │ │ ┌ EVAL x +//│ [mono] │ │ │ │ │ └ EVAL [1]551120 +//│ [mono] │ │ │ │ │ ┌ EVAL #1 +//│ [mono] │ │ │ │ │ └ EVAL [1]850514 +//│ [mono] │ │ │ │ └ EVAL [2]225064 +//│ [mono] │ │ │ │ ┌ SPEC CALL apply$Lambda1$1$1 with ([Lambda1$1$1@{x: [1]551120}]70265, [2]225064) +//│ [mono] │ │ │ │ │ comparing (([]331078,0), ([]317254,0)) with (Plain([Lambda1$1$1@{x: [1]551120}]899673), Plain([2]885273)) +//│ [mono] │ │ │ │ │ first time encounter apply$Lambda1$1$1 +//│ [mono] │ │ │ │ │ evaluating apply$Lambda1$1$1, rests: HashSet() +//│ [mono] │ │ │ │ │ ========== updating apply$Lambda1$1$1 ========== +//│ [mono] │ │ │ │ │ apply$Lambda1$1$1: (([Lambda1$1$1@{x: [1]551120}]899673,2) X ([2]885273,1)) -> *11*=[*11*=...]628892 @{f} +//│ [mono] │ │ │ │ │ ┌ EVAL f((this.x + y)) +//│ [mono] │ │ │ │ │ │ ┌ EVAL f +//│ [mono] │ │ │ │ │ │ └ EVAL [f(x) given {}]710076 +//│ [mono] │ │ │ │ │ │ ┌ EVAL (this.x + y) +//│ [mono] │ │ │ │ │ │ │ ┌ EVAL this.x +//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL this +//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [1]551120}]899673 +//│ [mono] │ │ │ │ │ │ │ └ EVAL [1]546668 +//│ [mono] │ │ │ │ │ │ │ ┌ EVAL y +//│ [mono] │ │ │ │ │ │ │ └ EVAL [2]885273 +//│ [mono] │ │ │ │ │ │ └ EVAL [3]620274 +//│ [mono] │ │ │ │ │ │ ┌ SPEC CALL f with ([3]620274) +//│ [mono] │ │ │ │ │ │ │ comparing (([1]551120,1)) with (Plain([*LIT*]137338)) +//│ [mono] │ │ │ │ │ │ │ find finer args +//│ [mono] │ │ │ │ │ │ └ SPEC CALL [*9*=[*9*=...]272491]118118 +//│ [mono] │ │ │ │ │ │ call result: [*9*=[*9*=...]272491]118118 +//│ [mono] │ │ │ │ │ │ merging []294569 with [*9*=[*9*=...]272491]118118 +//│ [mono] │ │ │ │ │ │ result [*9*=[*9*=...]272491]493312 +//│ [mono] │ │ │ │ │ └ EVAL [*9*=[*9*=...]272491]493312 +//│ [mono] │ │ │ │ │ comparing [*11*=...]628892 with [*9*=[*9*=...]272491]493312 +//│ [mono] │ │ │ │ │ apply$Lambda1$1$1: (([Lambda1$1$1@{x: [1]551120}]899673,2) X ([2]885273,1)) -> *11*=[*9*=[*9*=...]272491]493312 @{f} +//│ [mono] │ │ │ │ └ SPEC CALL [*11*=[*9*=[*9*=...]272491]493312]410939 +//│ [mono] │ │ │ │ call result: [*11*=[*9*=[*9*=...]272491]493312]410939 +//│ [mono] │ │ │ │ merging []909038 with [*11*=[*9*=[*9*=...]272491]493312]410939 +//│ [mono] │ │ │ │ result [*11*=[*9*=[*9*=...]272491]493312]350837 +//│ [mono] │ │ │ └ EVAL [*11*=[*9*=[*9*=...]272491]493312]350837 +//│ [mono] │ │ └ EVAL [*11*=[*9*=[*9*=...]272491]493312]350837 +//│ [mono] │ │ comparing [*9*=...]272491 with [*11*=[*9*=[*9*=...]272491]493312]350837 +//│ [mono] │ │ f: (([*LIT*]137338,100000)) -> *9*=[*11*=[*9*=...]493312]350837 @{main$$2, apply$Lambda1$1$1} +//│ [mono] │ └ SPEC CALL [*9*=[*11*=[*9*=...]493312]350837]49790 +//│ [mono] │ call result: [*9*=[*11*=[*9*=...]493312]350837]49790 +//│ [mono] │ merging []617696 with [*9*=[*11*=[*9*=...]493312]350837]49790 +//│ [mono] │ result [*9*=[*11*=[*9*=...]493312]350837]43915 +//│ [mono] └ EVAL [*9*=[*11*=[*9*=...]493312]350837]43915 +//│ [mono] comparing [*10*=...]263411 with [*9*=[*11*=[*9*=...]493312]350837]43915 +//│ [mono] main$$2: () -> *10*=[*9*=[*11*=[*9*=...]493312]350837]43915 @{} +//│ [mono] evaluating f, rests: HashSet() +//│ [mono] ========== updating f ========== +//│ [mono] f: (([*LIT*]137338,100000)) -> *9*=[*11*=[*9*=...]493312]350837 @{main$$2, apply$Lambda1$1$1} +//│ [mono] ┌ EVAL new Lambda1$1$1 (x) .apply((x + #1)) +//│ [mono] │ ┌ EVAL new Lambda1$1$1 (x) .apply +//│ [mono] │ │ ┌ EVAL new Lambda1$1$1 (x) +//│ [mono] │ │ │ ┌ EVAL x +//│ [mono] │ │ │ └ EVAL [*LIT*]137338 +//│ [mono] │ │ └ EVAL [Lambda1$1$1@{x: [*LIT*]137338}]873892 +//│ [mono] │ └ EVAL [apply$Lambda1$1$1(y) given {this: [Lambda1$1$1@{x: [*LIT*]137338}]255015}]243686 +//│ [mono] │ ┌ EVAL (x + #1) +//│ [mono] │ │ ┌ EVAL x +//│ [mono] │ │ └ EVAL [*LIT*]137338 +//│ [mono] │ │ ┌ EVAL #1 +//│ [mono] │ │ └ EVAL [1]484532 +//│ [mono] │ └ EVAL [*LIT*]349816 +//│ [mono] │ ┌ SPEC CALL apply$Lambda1$1$1 with ([Lambda1$1$1@{x: [*LIT*]137338}]255015, [*LIT*]349816) +//│ [mono] │ │ comparing (([Lambda1$1$1@{x: [1]551120}]899673,2), ([2]885273,1)) with (Plain([Lambda1$1$1@{x: [*LIT*]62147}]944362), Plain([*LIT*]621953)) //│ [mono] │ │ find finer args -//│ [mono] │ └ SPEC CALL [] -//│ [mono] │ comparing [] with [List$1@{e: [1], tail: []}] -//│ [mono] │ adding these funcs to queue: Set(main$$5, generate) -//│ [mono] │ generate: (([*LIT*],100000)) -> [List$1@{e: [1], tail: ***}] @{main$$5, generate} -//│ [mono] └ SPEC CALL [List$1@{e: [1], tail: ***}] -//│ [mono] ┌ SPEC CALL foo with ([List$1@{e: [1], tail: ***}]) -//│ [mono] │ comparing (([],0)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) -//│ [mono] │ first time encounter foo -//│ [mono] │ evaluating foo, rests: HashSet(main$$5, main$$4, generate) -//│ [mono] │ ========== updating foo ========== -//│ [mono] │ foo: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [] @{main$$5} -//│ [mono] │ ┌ SPEC CALL count$List$1 with ([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}]) -//│ [mono] │ │ comparing (([],0)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) -//│ [mono] │ │ first time encounter count$List$1 -//│ [mono] │ │ evaluating count$List$1, rests: HashSet(main$$5, main$$4, generate) -//│ [mono] │ │ ========== updating count$List$1 ========== -//│ [mono] │ │ count$List$1: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [] @{foo} -//│ [mono] │ │ ┌ SPEC CALL count$List$1 with ([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}]) -//│ [mono] │ │ │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) -//│ [mono] │ │ └ SPEC CALL [] -//│ [mono] │ │ comparing [] with [*LIT*] -//│ [mono] │ │ adding these funcs to queue: Set(foo, count$List$1) -//│ [mono] │ │ count$List$1: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{foo, count$List$1} -//│ [mono] │ └ SPEC CALL [*LIT*] -//│ [mono] │ comparing [] with [*LIT*] -//│ [mono] │ adding these funcs to queue: Set(main$$5) -//│ [mono] │ foo: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{main$$5} -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [] with [*LIT*] -//│ [mono] adding these funcs to queue: Set() -//│ [mono] main$$5: () -> [*LIT*] @{} -//│ [mono] evaluating foo, rests: HashSet(count$List$1, main$$5, main$$4, generate) -//│ [mono] ========== updating foo ========== -//│ [mono] foo: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{main$$5} -//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}]) -//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] foo: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{main$$5} -//│ [mono] evaluating count$List$1, rests: HashSet(main$$5, main$$4, generate) -//│ [mono] ========== updating count$List$1 ========== -//│ [mono] count$List$1: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{foo, count$List$1} -//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}]) -//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] count$List$1: (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) -> [*LIT*] @{foo, count$List$1} -//│ [mono] evaluating main$$5, rests: HashSet(main$$4, generate) -//│ [mono] ========== updating main$$5 ========== -//│ [mono] main$$5: () -> [*LIT*] @{} -//│ [mono] ┌ SPEC CALL generate with ([1]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [List$1@{e: [1], tail: ***}] -//│ [mono] ┌ SPEC CALL foo with ([List$1@{e: [1], tail: ***}]) -//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] main$$5: () -> [*LIT*] @{} -//│ [mono] evaluating main$$4, rests: HashSet(generate) -//│ [mono] ========== updating main$$4 ========== -//│ [mono] main$$4: () -> [] @{} -//│ [mono] ┌ SPEC CALL foo with ([List$1@{e: [1], tail: [List$1@{e: [2], tail: [Nil$2@{}]}]}]) -//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}])) -//│ [mono] │ find finer args -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [] with [*LIT*] -//│ [mono] adding these funcs to queue: Set() -//│ [mono] main$$4: () -> [*LIT*] @{} -//│ [mono] evaluating foo, rests: HashSet(generate) -//│ [mono] ========== updating foo ========== -//│ [mono] foo: (([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}],3)) -> [*LIT*] @{main$$5, main$$4} -//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}]) -//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]}],3)) with (Plain([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}])) -//│ [mono] │ find finer args -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] foo: (([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}],3)) -> [*LIT*] @{main$$5, main$$4} -//│ [mono] evaluating count$List$1, rests: HashSet(generate) -//│ [mono] ========== updating count$List$1 ========== -//│ [mono] count$List$1: (([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}],3)) -> [*LIT*] @{foo, count$List$1} -//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]) -//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]}],3)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}])) -//│ [mono] │ find finer args -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] count$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) -> [*LIT*] @{foo, count$List$1} -//│ [mono] evaluating count$List$1, rests: HashSet(generate) -//│ [mono] ========== updating count$List$1 ========== -//│ [mono] count$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) -> [*LIT*] @{foo, count$List$1} -//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]) -//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] ┌ SPEC CALL count$Nil$2 with ([Nil$2@{}]) -//│ [mono] │ comparing (([],0)) with (Plain([Nil$2@{}])) -//│ [mono] │ first time encounter count$Nil$2 -//│ [mono] │ evaluating count$Nil$2, rests: HashSet(generate) -//│ [mono] │ ========== updating count$Nil$2 ========== -//│ [mono] │ count$Nil$2: (([Nil$2@{}],1)) -> [] @{count$List$1} -//│ [mono] │ comparing [] with [0] -//│ [mono] │ adding these funcs to queue: Set(count$List$1) -//│ [mono] │ count$Nil$2: (([Nil$2@{}],1)) -> [0] @{count$List$1} -//│ [mono] └ SPEC CALL [0] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] count$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) -> [*LIT*] @{foo, count$List$1} -//│ [mono] evaluating count$List$1, rests: HashSet(generate) -//│ [mono] ========== updating count$List$1 ========== -//│ [mono] count$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) -> [*LIT*] @{foo, count$List$1} -//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]}]) -//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] ┌ SPEC CALL count$Nil$2 with ([Nil$2@{}]) -//│ [mono] │ comparing (([Nil$2@{}],1)) with (Plain([Nil$2@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] count$List$1: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}]} | Nil$2@{}]}],100002)) -> [*LIT*] @{foo, count$List$1} -//│ [mono] evaluating generate, rests: HashSet() -//│ [mono] ========== updating generate ========== -//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [1], tail: ***}] @{main$$5, generate} -//│ [mono] ┌ SPEC CALL generate with ([*LIT*]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [List$1@{e: [1], tail: ***}] -//│ [mono] comparing [List$1@{e: [1], tail: ***}] with [List$1@{e: [*LIT*], tail: [List$1@{e: [1], tail: ***}]} | Nil$2@{}] -//│ [mono] adding these funcs to queue: Set(main$$5, generate) -//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$5, generate} -//│ [mono] evaluating main$$5, rests: HashSet(generate) -//│ [mono] ========== updating main$$5 ========== -//│ [mono] main$$5: () -> [*LIT*] @{} -//│ [mono] ┌ SPEC CALL generate with ([1]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] -//│ [mono] ┌ SPEC CALL foo with ([List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]) -//│ [mono] │ comparing (([List$1@{e: [1], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]}]}],3)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]} | Nil$2@{}])) -//│ [mono] │ find finer args -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] main$$5: () -> [*LIT*] @{} -//│ [mono] evaluating foo, rests: HashSet(generate) -//│ [mono] ========== updating foo ========== -//│ [mono] foo: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]} | Nil$2@{}],100003)) -> [*LIT*] @{main$$5, main$$4} -//│ [mono] ┌ SPEC CALL count$List$1 with ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]}]) -//│ [mono] │ comparing (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]}],100002)) with (Plain([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] ┌ SPEC CALL count$Nil$2 with ([Nil$2@{}]) -//│ [mono] │ comparing (([Nil$2@{}],1)) with (Plain([Nil$2@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] foo: (([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]} | Nil$2@{}],100003)) -> [*LIT*] @{main$$5, main$$4} -//│ [mono] evaluating generate, rests: HashSet() -//│ [mono] ========== updating generate ========== -//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$5, generate} -//│ [mono] ┌ SPEC CALL generate with ([*LIT*]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] -//│ [mono] comparing [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] with [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}] -//│ [mono] generate: (([*LIT*],100000)) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] @{main$$5, generate} +//│ [mono] │ └ SPEC CALL [*11*=[*9*=[*11*=...]350837]493312]198943 +//│ [mono] │ call result: [*11*=[*9*=[*11*=...]350837]493312]198943 +//│ [mono] │ merging []583841 with [*11*=[*9*=[*11*=...]350837]493312]198943 +//│ [mono] │ result [*11*=[*9*=[*11*=...]350837]493312]422571 +//│ [mono] └ EVAL [*11*=[*9*=[*11*=...]350837]493312]422571 +//│ [mono] comparing [*11*=[*9*=...]493312]350837 with [*11*=[*9*=[*11*=...]350837]493312]422571 +//│ [mono] f: (([*LIT*]137338,100000)) -> *9*=[*11*=[*9*=...]493312]422571 @{main$$2, apply$Lambda1$1$1} +//│ [mono] evaluating apply$Lambda1$1$1, rests: HashSet() +//│ [mono] ========== updating apply$Lambda1$1$1 ========== +//│ [mono] apply$Lambda1$1$1: (([Lambda1$1$1@{x: [*LIT*]62147}]944362,100001) X ([*LIT*]621953,100000)) -> *11*=[*9*=[*11*=...]422571]493312 @{f} +//│ [mono] ┌ EVAL f((this.x + y)) +//│ [mono] │ ┌ EVAL f +//│ [mono] │ └ EVAL [f(x) given {}]539759 +//│ [mono] │ ┌ EVAL (this.x + y) +//│ [mono] │ │ ┌ EVAL this.x +//│ [mono] │ │ │ ┌ EVAL this +//│ [mono] │ │ │ └ EVAL [Lambda1$1$1@{x: [*LIT*]62147}]944362 +//│ [mono] │ │ └ EVAL [*LIT*]31983 +//│ [mono] │ │ ┌ EVAL y +//│ [mono] │ │ └ EVAL [*LIT*]621953 +//│ [mono] │ └ EVAL [*LIT*]252249 +//│ [mono] │ ┌ SPEC CALL f with ([*LIT*]252249) +//│ [mono] │ │ comparing (([*LIT*]137338,100000)) with (Plain([*LIT*]266429)) +//│ [mono] │ └ SPEC CALL [*9*=[*11*=[*9*=...]493312]422571]665559 +//│ [mono] │ call result: [*9*=[*11*=[*9*=...]493312]422571]665559 +//│ [mono] │ merging []782169 with [*9*=[*11*=[*9*=...]493312]422571]665559 +//│ [mono] │ result [*9*=[*11*=[*9*=...]493312]422571]449699 +//│ [mono] └ EVAL [*9*=[*11*=[*9*=...]493312]422571]449699 +//│ [mono] comparing [*9*=[*11*=...]422571]493312 with [*9*=[*11*=[*9*=...]493312]422571]449699 +//│ [mono] apply$Lambda1$1$1: (([Lambda1$1$1@{x: [*LIT*]62147}]944362,100001) X ([*LIT*]621953,100000)) -> *11*=[*9*=[*11*=...]422571]449699 @{f} //│ [mono] //│ [mono] ==============final function signatures================== -//│ [mono] count$Nil$2: ([Nil$2@{}]) -> [0] -//│ [mono] foo: ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]} | Nil$2@{}]) -> [*LIT*] -//│ [mono] count$List$1: ([List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: [Nil$2@{} | List$1@{e: [*LIT*], tail: [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}]}]} | Nil$2@{}]}]) -> [*LIT*] -//│ [mono] main$$5: () -> [*LIT*] -//│ [mono] main$$4: () -> [*LIT*] -//│ [mono] generate: ([*LIT*]) -> [List$1@{e: [*LIT*], tail: ***} | Nil$2@{}] +//│ [mono] apply$Lambda1$1$1: ([Lambda1$1$1@{x: [*LIT*]62147}]944362 X [*LIT*]621953) -> *11*=[*9*=[*11*=...]422571]449699 +//│ [mono] f: ([*LIT*]137338) -> *9*=[*11*=[*9*=...]449699]422571 +//│ [mono] main$$2: () -> *10*=[*9*=[*11*=[*9*=...]449699]422571]43915 :mono -class E() { - fun derive(x) = new E - fun isEmpty() = 0 +fun f(x) = f(x) +f(0) +f(1) +//│ |#fun| |f|(|x|)| |#=| |f|(|x|)|↵|f|(|0|)|↵|f|(|1|)| +//│ Parsed: {fun f = x, => f (x,); f (0,); f (1,)} +//│ Parsed: +//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), App(Var(f), Tup(_: Var(x))))), App(Var(f), Tup(_: IntLit(0))), App(Var(f), Tup(_: IntLit(1)))) +//│ Lifted: +//│ TypingUnit { +//│ fun f = x, => f (x,) +//│ Code(List(f (0,))) +//│ Code(List(f (1,))) +//│ } +//│ Mono: +//│ +//│ Mono result: +//│ main$$1() +//│ main$$2() +//│ fun f(x) = +//│ f(x) +//│ fun main$$2() = +//│ f(#1) +//│ fun main$$1() = +//│ f(#0) +//│ [mono] ┌───┬─────────────────┐ +//│ │ 1 │ main$$1() │ +//│ │ 2 │ main$$2() │ +//│ │ 3 │ fun f(x) = │ +//│ │ 4 │ f(x) │ +//│ │ 5 │ fun main$$2() = │ +//│ │ 6 │ f(#1) │ +//│ │ 7 │ fun main$$1() = │ +//│ │ 8 │ f(#0) │ +//│ └───┴─────────────────┘ +//│ [mono] evaluating main$$2, rests: HashSet(main$$1) +//│ [mono] ========== updating main$$2 ========== +//│ [mono] main$$2: () -> *14*=[*14*=...]114427 @{} +//│ [mono] ┌ EVAL f(#1) +//│ [mono] │ ┌ EVAL f +//│ [mono] │ └ EVAL [f(x) given {}]878353 +//│ [mono] │ ┌ EVAL #1 +//│ [mono] │ └ EVAL [1]317186 +//│ [mono] │ ┌ SPEC CALL f with ([1]317186) +//│ [mono] │ │ comparing (([]498318,0)) with (Plain([1]240397)) +//│ [mono] │ │ first time encounter f +//│ [mono] │ │ evaluating f, rests: HashSet(main$$1) +//│ [mono] │ │ ========== updating f ========== +//│ [mono] │ │ f: (([1]240397,1)) -> *12*=[*12*=...]683949 @{main$$2} +//│ [mono] │ │ ┌ EVAL f(x) +//│ [mono] │ │ │ ┌ EVAL f +//│ [mono] │ │ │ └ EVAL [f(x) given {}]464149 +//│ [mono] │ │ │ ┌ EVAL x +//│ [mono] │ │ │ └ EVAL [1]240397 +//│ [mono] │ │ │ ┌ SPEC CALL f with ([1]240397) +//│ [mono] │ │ │ │ comparing (([1]240397,1)) with (Plain([1]240397)) +//│ [mono] │ │ │ └ SPEC CALL [*12*=[*12*=...]683949]736838 +//│ [mono] │ │ │ call result: [*12*=[*12*=...]683949]736838 +//│ [mono] │ │ │ merging []992352 with [*12*=[*12*=...]683949]736838 +//│ [mono] │ │ │ result [*12*=[*12*=...]683949]258386 +//│ [mono] │ │ └ EVAL [*12*=[*12*=...]683949]258386 +//│ [mono] │ │ comparing [*12*=...]683949 with [*12*=[*12*=...]683949]258386 +//│ [mono] │ │ f: (([1]240397,1)) -> *12*=[*12*=...]258386 @{main$$2, f} +//│ [mono] │ └ SPEC CALL [*12*=[*12*=...]258386]262549 +//│ [mono] │ call result: [*12*=[*12*=...]258386]262549 +//│ [mono] │ merging []614422 with [*12*=[*12*=...]258386]262549 +//│ [mono] │ result [*12*=[*12*=...]258386]136125 +//│ [mono] └ EVAL [*12*=[*12*=...]258386]136125 +//│ [mono] comparing [*14*=...]114427 with [*12*=[*12*=...]258386]136125 +//│ [mono] main$$2: () -> *14*=[*12*=[*12*=...]258386]136125 @{} +//│ [mono] evaluating main$$1, rests: HashSet() +//│ [mono] ========== updating main$$1 ========== +//│ [mono] main$$1: () -> *13*=[*13*=...]360724 @{} +//│ [mono] ┌ EVAL f(#0) +//│ [mono] │ ┌ EVAL f +//│ [mono] │ └ EVAL [f(x) given {}]311634 +//│ [mono] │ ┌ EVAL #0 +//│ [mono] │ └ EVAL [0]971042 +//│ [mono] │ ┌ SPEC CALL f with ([0]971042) +//│ [mono] │ │ comparing (([1]240397,1)) with (Plain([*LIT*]435420)) +//│ [mono] │ │ find finer args +//│ [mono] │ └ SPEC CALL [*12*=[*12*=...]258386]981428 +//│ [mono] │ call result: [*12*=[*12*=...]258386]981428 +//│ [mono] │ merging []487067 with [*12*=[*12*=...]258386]981428 +//│ [mono] │ result [*12*=[*12*=...]258386]655301 +//│ [mono] └ EVAL [*12*=[*12*=...]258386]655301 +//│ [mono] comparing [*13*=...]360724 with [*12*=[*12*=...]258386]655301 +//│ [mono] main$$1: () -> *13*=[*12*=[*12*=...]258386]655301 @{} +//│ [mono] evaluating f, rests: HashSet() +//│ [mono] ========== updating f ========== +//│ [mono] f: (([*LIT*]435420,100000)) -> *12*=[*12*=...]258386 @{main$$2, f, main$$1} +//│ [mono] ┌ EVAL f(x) +//│ [mono] │ ┌ EVAL f +//│ [mono] │ └ EVAL [f(x) given {}]209798 +//│ [mono] │ ┌ EVAL x +//│ [mono] │ └ EVAL [*LIT*]435420 +//│ [mono] │ ┌ SPEC CALL f with ([*LIT*]435420) +//│ [mono] │ │ comparing (([*LIT*]435420,100000)) with (Plain([*LIT*]435420)) +//│ [mono] │ └ SPEC CALL [*12*=[*12*=...]258386]550649 +//│ [mono] │ call result: [*12*=[*12*=...]258386]550649 +//│ [mono] │ merging []375204 with [*12*=[*12*=...]258386]550649 +//│ [mono] │ result [*12*=[*12*=...]258386]123356 +//│ [mono] └ EVAL [*12*=[*12*=...]258386]123356 +//│ [mono] comparing [*12*=...]258386 with [*12*=[*12*=...]258386]123356 +//│ [mono] f: (([*LIT*]435420,100000)) -> *12*=[*12*=...]123356 @{main$$2, f, main$$1} +//│ [mono] +//│ [mono] ==============final function signatures================== +//│ [mono] f: ([*LIT*]435420) -> *12*=[*12*=...]123356 +//│ [mono] main$$2: () -> *14*=[*12*=[*12*=...]123356]136125 +//│ [mono] main$$1: () -> *13*=[*12*=[*12*=...]123356]655301 + +:mono +class Cons(e, tail) { + fun count() = 1 + tail.count() } -class Ep(){ - fun derive(x) = new E - fun isEmpty() = 1 +class Nil() { + fun count() = 0 } -class C(i){ - fun derive(x) = - if x < i then new Ep else new E - fun isEmpty() = 0 +class Lambda(){ + fun apply(l) = + l.count() } -class A(e1, e2){ - fun derive(x) = new A(e1.derive(x), e2.derive(x)) - fun isEmpty() = e1.isEmpty() * e2.isEmpty() +class Lambda2(a){ + fun apply(l) = + (new Cons(a, l)).count() } -fun gen(x) = - if x then new A(gen(x+1), new C(x)) else new E() -// (new A(new C(1), new A(new C(2), new C(3)))).derive(0).isEmpty() -gen(1).derive(0).isEmpty() -gen(1).isEmpty() -(new C(1)).derive(0).isEmpty() -//│ |#class| |E|(||)| |{|→|#fun| |derive|(|x|)| |#=| |#new| |E|↵|#fun| |isEmpty|(||)| |#=| |0|←|↵|}|↵|#class| |Ep|(||)|{|→|#fun| |derive|(|x|)| |#=| |#new| |E|↵|#fun| |isEmpty|(||)| |#=| |1|←|↵|}|↵|#class| |C|(|i|)|{|→|#fun| |derive|(|x|)| |#=| |→|#if| |x| |<| |i| |#then| |#new| |Ep| |#else| |#new| |E|←|↵|#fun| |isEmpty|(||)| |#=| |0|←|↵|}|↵|#class| |A|(|e1|,| |e2|)|{|→|#fun| |derive|(|x|)| |#=| |#new| |A|(|e1|.derive|(|x|)|,| |e2|.derive|(|x|)|)|↵|#fun| |isEmpty|(||)| |#=| |e1|.isEmpty|(||)| |*| |e2|.isEmpty|(||)|←|↵|}|↵|#fun| |gen|(|x|)| |#=| |→|#if| |x| |#then| |#new| |A|(|gen|(|x|+|1|)|,| |#new| |C|(|x|)|)| |#else| |#new| |E|(||)|←|↵|/* (new A(new C(1), new A(new C(2), new C(3)))).derive(0).isEmpty()*/|↵|gen|(|1|)|.derive|(|0|)|.isEmpty|(||)|↵|gen|(|1|)|.isEmpty|(||)|↵|(|#new| |C|(|1|)|)|.derive|(|0|)|.isEmpty|(||)| -//│ Parsed: {class E() {fun derive = x, => new E() {}; fun isEmpty = => 0}; class Ep() {fun derive = x, => new E() {}; fun isEmpty = => 1}; class C(i,) {fun derive = x, => {if (< (x,) (i,)) then new Ep() {} else new E() {}}; fun isEmpty = => 0}; class A(e1, e2,) {fun derive = x, => new A((e1).derive (x,), (e2).derive (x,),) {}; fun isEmpty = => * ((e1).isEmpty (),) ((e2).isEmpty (),)}; fun gen = x, => {if (x) then new A(gen (+ (x,) (1,),), new C(x,) {},) {} else new E() {}}; ((gen (1,)).derive (0,)).isEmpty (); (gen (1,)).isEmpty (); (('(' new C(1,) {}, ')').derive (0,)).isEmpty ()} +fun foo(x) = + x.apply(new Cons(1, new Nil())) + x.apply(new Nil()) +foo(new Lambda()) +foo(new Lambda2(2)) +//│ |#class| |Cons|(|e|,| |tail|)| |{|→|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#class| |Lambda|(||)|{|→|#fun| |apply|(|l|)| |#=| |→|l|.count|(||)|←|←|↵|}|↵|#class| |Lambda2|(|a|)|{|→|#fun| |apply|(|l|)| |#=| |→|(|#new| |Cons|(|a|,| |l|)|)|.count|(||)|←|←|↵|}|↵|#fun| |foo|(|x|)| |#=| |→|x|.apply|(|#new| |Cons|(|1|,| |#new| |Nil|(||)|)|)| |+| |x|.apply|(|#new| |Nil|(||)|)|←|↵|foo|(|#new| |Lambda|(||)|)|↵|foo|(|#new| |Lambda2|(|2|)|)| +//│ Parsed: {class Cons(e, tail,) {fun count = => + (1,) ((tail).count (),)}; class Nil() {fun count = => 0}; class Lambda() {fun apply = l, => {(l).count ()}}; class Lambda2(a,) {fun apply = l, => {('(' new Cons(a, l,) {}, ')').count ()}}; fun foo = x, => {+ ((x).apply (new Cons(1, new Nil() {},) {},),) ((x).apply (new Nil() {},),)}; foo (new Lambda() {},); foo (new Lambda2(2,) {},)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, E, (), Tup(), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), New(Some((TypeName(E),)), TypingUnit(List())))), NuFunDef(None, isEmpty, [], Lam(Tup(), IntLit(0))))), NuTypeDef(class, Ep, (), Tup(), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), New(Some((TypeName(E),)), TypingUnit(List())))), NuFunDef(None, isEmpty, [], Lam(Tup(), IntLit(1))))), NuTypeDef(class, C, (), Tup(_: Var(i)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), IntLit(0))))), NuTypeDef(class, A, (), Tup(_: Var(e1), _: Var(e2)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), New(Some((TypeName(A),(e1).derive (x,), (e2).derive (x,),)), TypingUnit(List())))), NuFunDef(None, isEmpty, [], Lam(Tup(), App(App(Var(*), Tup(_: App(Sel(Var(e1), isEmpty), Tup()))), Tup(_: App(Sel(Var(e2), isEmpty), Tup()))))))), NuFunDef(None, gen, [], Lam(Tup(_: Var(x)), Blk(...))), App(Sel(App(Sel(App(Var(gen), Tup(_: IntLit(1))), derive), Tup(_: IntLit(0))), isEmpty), Tup()), App(Sel(App(Var(gen), Tup(_: IntLit(1))), isEmpty), Tup()), App(Sel(App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(C),1,)), TypingUnit(List())))), derive), Tup(_: IntLit(0))), isEmpty), Tup())) +//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuTypeDef(class, Lambda, (), Tup(), (), TypingUnit(NuFunDef(None, apply, [], Lam(Tup(_: Var(l)), Blk(...))))), NuTypeDef(class, Lambda2, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, apply, [], Lam(Tup(_: Var(l)), Blk(...))))), NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: New(Some((TypeName(Lambda),)), TypingUnit(List())))), App(Var(foo), Tup(_: New(Some((TypeName(Lambda2),2,)), TypingUnit(List()))))) //│ Lifted: //│ TypingUnit { -//│ class E$1() {fun derive = x, => new E$1() {}; fun isEmpty = => 0} -//│ class Ep$2() {fun derive = x, => new E$1() {}; fun isEmpty = => 1} -//│ class C$3(i,) { -//│ fun derive = x, => {if (< (x,) ((this).i,)) then new Ep$2() {} else new E$1() {}} -//│ fun isEmpty = => 0 -//│ } -//│ class A$4(e1, e2,) { -//│ fun derive = x, => new A$4(((this).e1).derive (x,), ((this).e2).derive (x,),) {} -//│ fun isEmpty = => * (((this).e1).isEmpty (),) (((this).e2).isEmpty (),) +//│ class Cons$1(e, tail,) {fun count = => + (1,) (((this).tail).count (),)} +//│ class Nil$2() {fun count = => 0} +//│ class Lambda$3() {fun apply = l, => {(l).count ()}} +//│ class Lambda2$4(a,) { +//│ fun apply = l, => {('(' new Cons$1((this).a, l,) {}, ')').count ()} //│ } -//│ fun gen = x, => {if (x) then new A$4(gen (+ (x,) (1,),), new C$3(x,) {},) {} else new E$1() {}} -//│ Code(List(((gen (1,)).derive (0,)).isEmpty ())) -//│ Code(List((gen (1,)).isEmpty ())) -//│ Code(List((('(' new C$3(1,) {}, ')').derive (0,)).isEmpty ())) +//│ fun foo = x, => {+ ((x).apply (new Cons$1(1, new Nil$2() {},) {},),) ((x).apply (new Nil$2() {},),)} +//│ Code(List(foo (new Lambda$3() {},))) +//│ Code(List(foo (new Lambda2$4(2,) {},))) //│ } //│ Mono: //│ //│ Mono result: //│ main$$5() //│ main$$6() -//│ main$$7() -//│ fun isEmpty$Ep$2(this) = -//│ #1 -//│ fun gen(x) = -//│ if x then new A$4 (gen((x + #1)), new C$3 (x) ) else new E$1 () -//│ fun isEmpty$C$3(this) = -//│ #0 -//│ fun isEmpty$E$1(this) = +//│ fun count$Cons$1(this) = +//│ (#1 + this.tail match {case obj: Nil$2 => count$Nil$2(obj); case obj: Cons$1 => count$Cons$1(obj)}) +//│ fun apply$Lambda$3(this, l) = +//│ l match {case obj: Cons$1 => count$Cons$1(obj); case obj: Nil$2 => count$Nil$2(obj)} +//│ fun count$Nil$2(this) = //│ #0 -//│ fun isEmpty$A$4(this) = -//│ (this.e1 match {case obj: A$4 => isEmpty$A$4(obj); case obj: E$1 => isEmpty$E$1(obj)} * this.e2 match {case obj: C$3 => isEmpty$C$3(obj); case obj: Ep$2 => isEmpty$Ep$2(obj); case obj: E$1 => isEmpty$E$1(obj)}) -//│ fun derive$A$4(this, x) = -//│ new A$4 (this.e1 match {case obj: A$4 => derive$A$4(obj, x); case obj: E$1 => derive$E$1(obj, x)}, this.e2 match {case obj: C$3 => derive$C$3(obj, x)}) -//│ fun derive$E$1(this, x) = -//│ new E$1 () -//│ fun derive$C$3(this, x) = -//│ if (x < this.i) then new Ep$2 () else new E$1 () -//│ fun main$$7() = -//│ new C$3 (#1) match {case obj: C$3 => derive$C$3(obj, #0)} match {case obj: Ep$2 => isEmpty$Ep$2(obj); case obj: E$1 => isEmpty$E$1(obj)} +//│ fun foo(x) = +//│ (x match {case obj: Lambda$3 => apply$Lambda$3(obj, new Cons$1 (#1, new Nil$2 () ) ); case obj: Lambda2$4 => apply$Lambda2$4(obj, new Cons$1 (#1, new Nil$2 () ) )} + x match {case obj: Lambda$3 => apply$Lambda$3(obj, new Nil$2 () ); case obj: Lambda2$4 => apply$Lambda2$4(obj, new Nil$2 () )}) +//│ fun apply$Lambda2$4(this, l) = +//│ new Cons$1 (this.a, l) match {case obj: Cons$1 => count$Cons$1(obj)} //│ fun main$$6() = -//│ gen(#1) match {case obj: A$4 => isEmpty$A$4(obj); case obj: E$1 => isEmpty$E$1(obj)} +//│ foo(new Lambda2$4 (#2) ) //│ fun main$$5() = -//│ gen(#1) match {case obj: A$4 => derive$A$4(obj, #0); case obj: E$1 => derive$E$1(obj, #0)} match {case obj: A$4 => isEmpty$A$4(obj); case obj: E$1 => isEmpty$E$1(obj)} -//│ [mono] evaluating main$$7, rests: HashSet(main$$6, main$$5) -//│ [mono] ========== updating main$$7 ========== -//│ [mono] main$$7: () -> [] @{} -//│ [mono] ┌ SPEC CALL derive$C$3 with ([C$3@{i: [1]}], [0]) -//│ [mono] │ comparing (([],0), ([],0)) with (Plain([C$3@{i: [1]}]), Plain([0])) -//│ [mono] │ first time encounter derive$C$3 -//│ [mono] │ evaluating derive$C$3, rests: HashSet(main$$6, main$$5) -//│ [mono] │ ========== updating derive$C$3 ========== -//│ [mono] │ derive$C$3: (([C$3@{i: [1]}],2) X ([0],1)) -> [] @{main$$7} -//│ [mono] │ ┌ SPEC CALL < with ([0]) -//│ [mono] │ │ !!!!!!! -//│ [mono] │ │ calling unknown function <([0]) -//│ [mono] │ │ Set(gen, derive$C$3, main$$7, main$$6, main$$5) -//│ [mono] │ └ SPEC CALL [?1?] -//│ [mono] │ comparing [] with [E$1@{} | Ep$2@{}] -//│ [mono] │ adding these funcs to queue: Set(main$$7) -//│ [mono] │ derive$C$3: (([C$3@{i: [1]}],2) X ([0],1)) -> [E$1@{} | Ep$2@{}] @{main$$7} -//│ [mono] └ SPEC CALL [E$1@{} | Ep$2@{}] -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([],0)) with (Plain([E$1@{}])) -//│ [mono] │ first time encounter isEmpty$E$1 -//│ [mono] │ evaluating isEmpty$E$1, rests: HashSet(main$$7, main$$6, main$$5) -//│ [mono] │ ========== updating isEmpty$E$1 ========== -//│ [mono] │ isEmpty$E$1: (([E$1@{}],1)) -> [] @{main$$7} -//│ [mono] │ comparing [] with [0] -//│ [mono] │ adding these funcs to queue: Set(main$$7) -//│ [mono] │ isEmpty$E$1: (([E$1@{}],1)) -> [0] @{main$$7} -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$Ep$2 with ([Ep$2@{}]) -//│ [mono] │ comparing (([],0)) with (Plain([Ep$2@{}])) -//│ [mono] │ first time encounter isEmpty$Ep$2 -//│ [mono] │ evaluating isEmpty$Ep$2, rests: HashSet(main$$7, main$$6, main$$5) -//│ [mono] │ ========== updating isEmpty$Ep$2 ========== -//│ [mono] │ isEmpty$Ep$2: (([Ep$2@{}],1)) -> [] @{main$$7} -//│ [mono] │ comparing [] with [1] -//│ [mono] │ adding these funcs to queue: Set(main$$7) -//│ [mono] │ isEmpty$Ep$2: (([Ep$2@{}],1)) -> [1] @{main$$7} -//│ [mono] └ SPEC CALL [1] -//│ [mono] comparing [] with [*LIT*] -//│ [mono] adding these funcs to queue: Set() -//│ [mono] main$$7: () -> [*LIT*] @{} -//│ [mono] evaluating main$$7, rests: HashSet(main$$6, main$$5) -//│ [mono] ========== updating main$$7 ========== -//│ [mono] main$$7: () -> [*LIT*] @{} -//│ [mono] ┌ SPEC CALL derive$C$3 with ([C$3@{i: [1]}], [0]) -//│ [mono] │ comparing (([C$3@{i: [1]}],2), ([0],1)) with (Plain([C$3@{i: [1]}]), Plain([0])) -//│ [mono] └ SPEC CALL [E$1@{} | Ep$2@{}] -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$Ep$2 with ([Ep$2@{}]) -//│ [mono] │ comparing (([Ep$2@{}],1)) with (Plain([Ep$2@{}])) -//│ [mono] └ SPEC CALL [1] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] main$$7: () -> [*LIT*] @{} +//│ foo(new Lambda$3 () ) +//│ class Nil$2() { +//│ } +//│ class Lambda2$4(a) { +//│ } +//│ class Cons$1(e, tail) { +//│ } +//│ class Lambda$3() { +//│ } +//│ [mono] ┌────┬───────────────────────────────────────────────────────────────────────┐ +//│ │ 1 │ main$$5() │ +//│ │ 2 │ main$$6() │ +//│ │ 3 │ fun foo(x) = │ +//│ │ 4 │ (x.apply(new Cons$1 (#1, new Nil$2 () ) ) + x.apply(new Nil$2 () )) │ +//│ │ 5 │ fun main$$6() = │ +//│ │ 6 │ foo(new Lambda2$4 (#2) ) │ +//│ │ 7 │ fun main$$5() = │ +//│ │ 8 │ foo(new Lambda$3 () ) │ +//│ │ 9 │ class Nil$2() { │ +//│ │ 10 │ } │ +//│ │ 11 │ class Lambda2$4(a) { │ +//│ │ 12 │ } │ +//│ │ 13 │ class Cons$1(e, tail) { │ +//│ │ 14 │ } │ +//│ │ 15 │ class Lambda$3() { │ +//│ │ 16 │ } │ +//│ └────┴───────────────────────────────────────────────────────────────────────┘ //│ [mono] evaluating main$$6, rests: HashSet(main$$5) //│ [mono] ========== updating main$$6 ========== -//│ [mono] main$$6: () -> [] @{} -//│ [mono] ┌ SPEC CALL gen with ([1]) -//│ [mono] │ comparing (([],0)) with (Plain([1])) -//│ [mono] │ first time encounter gen -//│ [mono] │ evaluating gen, rests: HashSet(main$$5) -//│ [mono] │ ========== updating gen ========== -//│ [mono] │ gen: (([1],1)) -> [] @{main$$6} -//│ [mono] │ ┌ SPEC CALL gen with ([2]) -//│ [mono] │ │ comparing (([1],1)) with (Plain([*LIT*])) -//│ [mono] │ │ find finer args -//│ [mono] │ └ SPEC CALL [] -//│ [mono] │ comparing [] with [E$1@{} | A$4@{e1: [], e2: [C$3@{i: [1]}]}] -//│ [mono] │ adding these funcs to queue: Set(main$$6, gen) -//│ [mono] │ gen: (([*LIT*],100000)) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}] @{main$$6, gen} -//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}] -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}]) -//│ [mono] │ comparing (([],0)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}])) -//│ [mono] │ first time encounter isEmpty$A$4 -//│ [mono] │ evaluating isEmpty$A$4, rests: HashSet(gen, main$$6, main$$5) -//│ [mono] │ ========== updating isEmpty$A$4 ========== -//│ [mono] │ isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}],4)) -> [] @{main$$6} -//│ [mono] │ ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] │ └ SPEC CALL [0] -//│ [mono] │ ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}]) -//│ [mono] │ │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}],4)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}])) -//│ [mono] │ └ SPEC CALL [] -//│ [mono] │ ┌ SPEC CALL isEmpty$C$3 with ([C$3@{i: [1]}]) -//│ [mono] │ │ comparing (([],0)) with (Plain([C$3@{i: [1]}])) -//│ [mono] │ │ first time encounter isEmpty$C$3 -//│ [mono] │ │ evaluating isEmpty$C$3, rests: HashSet(gen, main$$6, main$$5) -//│ [mono] │ │ ========== updating isEmpty$C$3 ========== -//│ [mono] │ │ isEmpty$C$3: (([C$3@{i: [1]}],2)) -> [] @{isEmpty$A$4} -//│ [mono] │ │ comparing [] with [0] -//│ [mono] │ │ adding these funcs to queue: Set(isEmpty$A$4) -//│ [mono] │ │ isEmpty$C$3: (([C$3@{i: [1]}],2)) -> [0] @{isEmpty$A$4} -//│ [mono] │ └ SPEC CALL [0] -//│ [mono] │ comparing [] with [0] -//│ [mono] │ adding these funcs to queue: Set(main$$6, isEmpty$A$4) -//│ [mono] │ isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [1]}]}],4)) -> [0] @{main$$6, isEmpty$A$4} -//│ [mono] └ SPEC CALL [0] -//│ [mono] comparing [] with [0] -//│ [mono] adding these funcs to queue: Set() -//│ [mono] main$$6: () -> [0] @{} -//│ [mono] evaluating gen, rests: HashSet(isEmpty$A$4, main$$6, main$$5) -//│ [mono] ========== updating gen ========== -//│ [mono] gen: (([*LIT*],100000)) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}] @{main$$6, gen} -//│ [mono] ┌ SPEC CALL gen with ([*LIT*]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}] -//│ [mono] comparing [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}] with [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [1]}]}], e2: [C$3@{i: [*LIT*]}]}] -//│ [mono] adding these funcs to queue: Set(main$$6, gen) -//│ [mono] gen: (([*LIT*],100000)) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] @{main$$6, gen} -//│ [mono] evaluating gen, rests: HashSet(isEmpty$A$4, main$$6, main$$5) -//│ [mono] ========== updating gen ========== -//│ [mono] gen: (([*LIT*],100000)) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] @{main$$6, gen} -//│ [mono] ┌ SPEC CALL gen with ([*LIT*]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] -//│ [mono] comparing [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] with [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}] -//│ [mono] gen: (([*LIT*],100000)) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] @{main$$6, gen} -//│ [mono] evaluating isEmpty$A$4, rests: HashSet(main$$6, main$$5) -//│ [mono] ========== updating isEmpty$A$4 ========== -//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],4)) -> [0] @{main$$6, isEmpty$A$4} -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]) -//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],4)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}])) -//│ [mono] │ find finer args -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$C$3 with ([C$3@{i: [*LIT*]}]) -//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],2)) with (Plain([C$3@{i: [*LIT*]}])) -//│ [mono] │ find finer args -//│ [mono] └ SPEC CALL [0] -//│ [mono] comparing [0] with [0] -//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) -> [*LIT*] @{main$$6, isEmpty$A$4} -//│ [mono] evaluating isEmpty$C$3, rests: HashSet(isEmpty$A$4, main$$6, main$$5) -//│ [mono] ========== updating isEmpty$C$3 ========== -//│ [mono] isEmpty$C$3: (([C$3@{i: [*LIT*]}],100001)) -> [0] @{isEmpty$A$4} -//│ [mono] comparing [0] with [0] -//│ [mono] isEmpty$C$3: (([C$3@{i: [*LIT*]}],100001)) -> [*LIT*] @{isEmpty$A$4} -//│ [mono] evaluating isEmpty$A$4, rests: HashSet(main$$6, main$$5) -//│ [mono] ========== updating isEmpty$A$4 ========== -//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) -> [*LIT*] @{main$$6, isEmpty$A$4} -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]) -//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] ┌ SPEC CALL isEmpty$C$3 with ([C$3@{i: [*LIT*]}]) -//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],100001)) with (Plain([C$3@{i: [*LIT*]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) -> [*LIT*] @{main$$6, isEmpty$A$4} +//│ [mono] main$$6: () -> *17*=[*17*=...]135615 @{} +//│ [mono] ┌ EVAL foo(new Lambda2$4 (#2) ) +//│ [mono] │ ┌ EVAL foo +//│ [mono] │ └ EVAL [foo(x) given {}]490848 +//│ [mono] │ ┌ EVAL new Lambda2$4 (#2) +//│ [mono] │ │ ┌ EVAL #2 +//│ [mono] │ │ └ EVAL [2]752278 +//│ [mono] │ └ EVAL [Lambda2$4@{a: [2]752278}]743793 +//│ [mono] │ ┌ SPEC CALL foo with ([Lambda2$4@{a: [2]752278}]743793) +//│ [mono] │ │ comparing (([]205038,0)) with (Plain([Lambda2$4@{a: [2]752278}]622915)) +//│ [mono] │ │ first time encounter foo +//│ [mono] │ │ evaluating foo, rests: HashSet(main$$5) +//│ [mono] │ │ ========== updating foo ========== +//│ [mono] │ │ foo: (([Lambda2$4@{a: [2]752278}]622915,2)) -> *15*=[*15*=...]11760 @{main$$6} +//│ [mono] │ │ ┌ EVAL (x.apply(new Cons$1 (#1, new Nil$2 () ) ) + x.apply(new Nil$2 () )) +//│ [mono] │ │ │ ┌ EVAL (x.apply(new Cons$1 (#1, new Nil$2 () ) ) + x.apply(new Nil$2 () )) +//│ [mono] │ │ │ │ ┌ EVAL x.apply(new Cons$1 (#1, new Nil$2 () ) ) +//│ [mono] │ │ │ │ │ ┌ EVAL x.apply +//│ [mono] │ │ │ │ │ │ ┌ EVAL x +//│ [mono] │ │ │ │ │ │ └ EVAL [Lambda2$4@{a: [2]752278}]622915 +//│ [mono] │ │ │ │ │ └ EVAL [apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]112002}]760449 +//│ [mono] │ │ │ │ │ ┌ EVAL new Cons$1 (#1, new Nil$2 () ) +//│ [mono] │ │ │ │ │ │ ┌ EVAL #1 +//│ [mono] │ │ │ │ │ │ └ EVAL [1]224258 +//│ [mono] │ │ │ │ │ │ ┌ EVAL new Nil$2 () +//│ [mono] │ │ │ │ │ │ └ EVAL [Nil$2@{}]644816 +//│ [mono] │ │ │ │ │ └ EVAL [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]606578 +//│ [mono] │ │ │ │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]112002, [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]606578) +//│ [mono] │ │ │ │ │ │ comparing (([]184127,0), ([]757322,0)) with (Plain([Lambda2$4@{a: [2]752278}]258791), Plain([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571)) +//│ [mono] │ │ │ │ │ │ first time encounter apply$Lambda2$4 +//│ [mono] │ │ │ │ │ │ evaluating apply$Lambda2$4, rests: HashSet(main$$5) +//│ [mono] │ │ │ │ │ │ ========== updating apply$Lambda2$4 ========== +//│ [mono] │ │ │ │ │ │ apply$Lambda2$4: (([Lambda2$4@{a: [2]752278}]258791,2) X ([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571,3)) -> *18*=[*18*=...]325416 @{foo} +//│ [mono] │ │ │ │ │ │ ┌ EVAL (new Cons$1 (this.a, l) , ).count() +//│ [mono] │ │ │ │ │ │ │ ┌ EVAL (new Cons$1 (this.a, l) , ).count() +//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL (new Cons$1 (this.a, l) , ).count +//│ [mono] │ │ │ │ │ │ │ │ │ ┌ EVAL (new Cons$1 (this.a, l) , ) +//│ [mono] │ │ │ │ │ │ │ │ │ │ ┌ EVAL new Cons$1 (this.a, l) +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL this.a +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL this +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ └ EVAL [Lambda2$4@{a: [2]752278}]258791 +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ └ EVAL [2]414137 +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL l +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ └ EVAL [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571 +//│ [mono] │ │ │ │ │ │ │ │ │ │ └ EVAL [Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]202264 +//│ [mono] │ │ │ │ │ │ │ │ │ └ EVAL [Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]202264 +//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [count$Cons$1() given {this: [Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]469034}]762670 +//│ [mono] │ │ │ │ │ │ │ │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]469034) +//│ [mono] │ │ │ │ │ │ │ │ │ comparing (([]624201,0)) with (Plain([Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]240592)) +//│ [mono] │ │ │ │ │ │ │ │ │ first time encounter count$Cons$1 +//│ [mono] │ │ │ │ │ │ │ │ │ evaluating count$Cons$1, rests: HashSet(main$$5) +//│ [mono] │ │ │ │ │ │ │ │ │ ========== updating count$Cons$1 ========== +//│ [mono] │ │ │ │ │ │ │ │ │ count$Cons$1: (([Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]240592,5)) -> *19*=[*19*=...]579205 @{apply$Lambda2$4} +//│ [mono] │ │ │ │ │ │ │ │ │ ┌ EVAL (#1 + this.tail.count()) +//│ [mono] │ │ │ │ │ │ │ │ │ │ ┌ EVAL #1 +//│ [mono] │ │ │ │ │ │ │ │ │ │ └ EVAL [1]754681 +//│ [mono] │ │ │ │ │ │ │ │ │ │ ┌ EVAL this.tail.count() +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL this.tail.count +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL this.tail +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL this +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ │ └ EVAL [Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]240592 +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ └ EVAL [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]407077 +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ └ EVAL [count$Cons$1() given {this: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]62302}]807916 +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]62302) +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ comparing (([Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]240592,5)) with (Plain([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965)) +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ find finer args +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ └ SPEC CALL [*19*=[*19*=...]579205]73107 +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ call result: [*19*=[*19*=...]579205]73107 +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ merging []606375 with [*19*=[*19*=...]579205]73107 +//│ [mono] │ │ │ │ │ │ │ │ │ │ │ result [*19*=[*19*=...]579205]716762 +//│ [mono] │ │ │ │ │ │ │ │ │ │ └ EVAL [*19*=[*19*=...]579205]716762 +//│ [mono] │ │ │ │ │ │ │ │ │ └ EVAL [*LIT*]636435 +//│ [mono] │ │ │ │ │ │ │ │ │ comparing [*19*=...]579205 with [*LIT*]636435 +//│ [mono] │ │ │ │ │ │ │ │ │ adding these funcs to queue: Set(apply$Lambda2$4, count$Cons$1) +//│ [mono] │ │ │ │ │ │ │ │ │ count$Cons$1: (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) -> *19*=[*LIT*]636435 @{apply$Lambda2$4, count$Cons$1} +//│ [mono] │ │ │ │ │ │ │ │ └ SPEC CALL [*19*=[*LIT*]636435]475732 +//│ [mono] │ │ │ │ │ │ │ │ call result: [*19*=[*LIT*]636435]475732 +//│ [mono] │ │ │ │ │ │ │ │ merging []889370 with [*19*=[*LIT*]636435]475732 +//│ [mono] │ │ │ │ │ │ │ │ result [*19*=[*LIT*]636435]780388 +//│ [mono] │ │ │ │ │ │ │ └ EVAL [*19*=[*LIT*]636435]780388 +//│ [mono] │ │ │ │ │ │ └ EVAL [*19*=[*LIT*]636435]780388 +//│ [mono] │ │ │ │ │ │ comparing [*18*=...]325416 with [*19*=[*LIT*]636435]780388 +//│ [mono] │ │ │ │ │ │ apply$Lambda2$4: (([Lambda2$4@{a: [2]752278}]258791,2) X ([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571,3)) -> *18*=[*19*=[*LIT*]636435]780388 @{foo} +//│ [mono] │ │ │ │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]636435]780388]749644 +//│ [mono] │ │ │ │ │ call result: [*18*=[*19*=[*LIT*]636435]780388]749644 +//│ [mono] │ │ │ │ │ merging []80780 with [*18*=[*19*=[*LIT*]636435]780388]749644 +//│ [mono] │ │ │ │ │ result [*18*=[*19*=[*LIT*]636435]780388]819398 +//│ [mono] │ │ │ │ └ EVAL [*18*=[*19*=[*LIT*]636435]780388]819398 +//│ [mono] │ │ │ │ ┌ EVAL x.apply(new Nil$2 () ) +//│ [mono] │ │ │ │ │ ┌ EVAL x.apply +//│ [mono] │ │ │ │ │ │ ┌ EVAL x +//│ [mono] │ │ │ │ │ │ └ EVAL [Lambda2$4@{a: [2]752278}]622915 +//│ [mono] │ │ │ │ │ └ EVAL [apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]577458}]352590 +//│ [mono] │ │ │ │ │ ┌ EVAL new Nil$2 () +//│ [mono] │ │ │ │ │ └ EVAL [Nil$2@{}]906549 +//│ [mono] │ │ │ │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]577458, [Nil$2@{}]906549) +//│ [mono] │ │ │ │ │ │ comparing (([Lambda2$4@{a: [2]752278}]258791,2), ([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571,3)) with (Plain([Lambda2$4@{a: [2]752278}]91381), Plain([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016)) +//│ [mono] │ │ │ │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]636435]780388]193076 +//│ [mono] │ │ │ │ │ call result: [*18*=[*19*=[*LIT*]636435]780388]193076 +//│ [mono] │ │ │ │ │ merging []687883 with [*18*=[*19*=[*LIT*]636435]780388]193076 +//│ [mono] │ │ │ │ │ result [*18*=[*19*=[*LIT*]636435]780388]314840 +//│ [mono] │ │ │ │ └ EVAL [*18*=[*19*=[*LIT*]636435]780388]314840 +//│ [mono] │ │ │ └ EVAL [*LIT*]67195 +//│ [mono] │ │ └ EVAL [*LIT*]67195 +//│ [mono] │ │ comparing [*15*=...]11760 with [*LIT*]67195 +//│ [mono] │ │ adding these funcs to queue: Set(main$$6) +//│ [mono] │ │ foo: (([Lambda2$4@{a: [2]752278}]622915,2)) -> *15*=[*LIT*]67195 @{main$$6} +//│ [mono] │ └ SPEC CALL [*15*=[*LIT*]67195]546539 +//│ [mono] │ call result: [*15*=[*LIT*]67195]546539 +//│ [mono] │ merging []239270 with [*15*=[*LIT*]67195]546539 +//│ [mono] │ result [*15*=[*LIT*]67195]203295 +//│ [mono] └ EVAL [*15*=[*LIT*]67195]203295 +//│ [mono] comparing [*17*=...]135615 with [*15*=[*LIT*]67195]203295 +//│ [mono] main$$6: () -> *17*=[*15*=[*LIT*]67195]203295 @{} +//│ [mono] evaluating count$Cons$1, rests: HashSet(apply$Lambda2$4, main$$6, main$$5) +//│ [mono] ========== updating count$Cons$1 ========== +//│ [mono] count$Cons$1: (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) -> *19*=[*LIT*]636435 @{apply$Lambda2$4, count$Cons$1} +//│ [mono] ┌ EVAL (#1 + this.tail.count()) +//│ [mono] │ ┌ EVAL #1 +//│ [mono] │ └ EVAL [1]710392 +//│ [mono] │ ┌ EVAL this.tail.count() +//│ [mono] │ │ ┌ EVAL this.tail.count +//│ [mono] │ │ │ ┌ EVAL this.tail +//│ [mono] │ │ │ │ ┌ EVAL this +//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965 +//│ [mono] │ │ │ └ EVAL [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]237888 +//│ [mono] │ │ └ EVAL [count$Cons$1() given {this: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]474004} | count$Nil$2() given {this: [Nil$2@{}]615890}]52513 +//│ [mono] │ │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]474004) +//│ [mono] │ │ │ comparing (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) with (Plain([Cons$1@{e: [*LIT*]825810, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]451748}]686061)) +//│ [mono] │ │ └ SPEC CALL [*19*=[*LIT*]636435]675852 +//│ [mono] │ │ call result: [*19*=[*LIT*]636435]675852 +//│ [mono] │ │ ┌ SPEC CALL count$Nil$2 with ([Nil$2@{}]615890) +//│ [mono] │ │ │ comparing (([]333536,0)) with (Plain([Nil$2@{}]560462)) +//│ [mono] │ │ │ first time encounter count$Nil$2 +//│ [mono] │ │ │ evaluating count$Nil$2, rests: HashSet(apply$Lambda2$4, main$$6, main$$5) +//│ [mono] │ │ │ ========== updating count$Nil$2 ========== +//│ [mono] │ │ │ count$Nil$2: (([Nil$2@{}]560462,1)) -> *20*=[*20*=...]763413 @{count$Cons$1} +//│ [mono] │ │ │ ┌ EVAL #0 +//│ [mono] │ │ │ └ EVAL [0]326453 +//│ [mono] │ │ │ comparing [*20*=...]763413 with [0]326453 +//│ [mono] │ │ │ count$Nil$2: (([Nil$2@{}]560462,1)) -> *20*=[0]326453 @{count$Cons$1} +//│ [mono] │ │ └ SPEC CALL [*20*=[0]326453]576211 +//│ [mono] │ │ call result: [*20*=[0]326453]576211 +//│ [mono] │ │ merging []342306 with [*19*=[*LIT*]636435]675852 +//│ [mono] │ │ result [*19*=[*LIT*]636435]599657 +//│ [mono] │ │ merging [*19*=[*LIT*]636435]599657 with [*20*=[0]326453]576211 +//│ [mono] │ │ result [*20*=[0]326453 | *19*=[*LIT*]636435]99068 +//│ [mono] │ └ EVAL [*20*=[0]326453 | *19*=[*LIT*]636435]99068 +//│ [mono] └ EVAL [*LIT*]513374 +//│ [mono] comparing [*LIT*]636435 with [*LIT*]513374 +//│ [mono] count$Cons$1: (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) -> *19*=[*LIT*]513374 @{apply$Lambda2$4, count$Cons$1} +//│ [mono] evaluating apply$Lambda2$4, rests: HashSet(main$$6, main$$5) +//│ [mono] ========== updating apply$Lambda2$4 ========== +//│ [mono] apply$Lambda2$4: (([Lambda2$4@{a: [2]752278}]91381,2) X ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) -> *18*=[*19*=[*LIT*]513374]780388 @{foo} +//│ [mono] ┌ EVAL new Cons$1 (this.a, l) .count() +//│ [mono] │ ┌ EVAL new Cons$1 (this.a, l) .count +//│ [mono] │ │ ┌ EVAL new Cons$1 (this.a, l) +//│ [mono] │ │ │ ┌ EVAL this.a +//│ [mono] │ │ │ │ ┌ EVAL this +//│ [mono] │ │ │ │ └ EVAL [Lambda2$4@{a: [2]752278}]91381 +//│ [mono] │ │ │ └ EVAL [2]422643 +//│ [mono] │ │ │ ┌ EVAL l +//│ [mono] │ │ │ └ EVAL [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016 +//│ [mono] │ │ └ EVAL [Cons$1@{e: [2]422643, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016}]482343 +//│ [mono] │ └ EVAL [count$Cons$1() given {this: [Cons$1@{e: [2]422643, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016}]553308}]479302 +//│ [mono] │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [2]422643, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016}]553308) +//│ [mono] │ │ comparing (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) with (Plain([Cons$1@{e: [*LIT*]498010, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]567350}]697741)) +//│ [mono] │ └ SPEC CALL [*19*=[*LIT*]513374]918946 +//│ [mono] │ call result: [*19*=[*LIT*]513374]918946 +//│ [mono] │ merging []317828 with [*19*=[*LIT*]513374]918946 +//│ [mono] │ result [*19*=[*LIT*]513374]980184 +//│ [mono] └ EVAL [*19*=[*LIT*]513374]980184 +//│ [mono] comparing [*19*=[*LIT*]513374]780388 with [*19*=[*LIT*]513374]980184 +//│ [mono] apply$Lambda2$4: (([Lambda2$4@{a: [2]752278}]91381,2) X ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) -> *18*=[*19*=[*LIT*]513374]980184 @{foo} //│ [mono] evaluating main$$6, rests: HashSet(main$$5) //│ [mono] ========== updating main$$6 ========== -//│ [mono] main$$6: () -> [0] @{} -//│ [mono] ┌ SPEC CALL gen with ([1]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]) -//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [0] with [*LIT*] -//│ [mono] adding these funcs to queue: Set() -//│ [mono] main$$6: () -> [*LIT*] @{} +//│ [mono] main$$6: () -> *17*=[*15*=[*LIT*]67195]203295 @{} +//│ [mono] ┌ EVAL foo(new Lambda2$4 (#2) ) +//│ [mono] │ ┌ EVAL foo +//│ [mono] │ └ EVAL [foo(x) given {}]152639 +//│ [mono] │ ┌ EVAL new Lambda2$4 (#2) +//│ [mono] │ │ ┌ EVAL #2 +//│ [mono] │ │ └ EVAL [2]386284 +//│ [mono] │ └ EVAL [Lambda2$4@{a: [2]386284}]259571 +//│ [mono] │ ┌ SPEC CALL foo with ([Lambda2$4@{a: [2]386284}]259571) +//│ [mono] │ │ comparing (([Lambda2$4@{a: [2]752278}]622915,2)) with (Plain([Lambda2$4@{a: [2]541966}]360855)) +//│ [mono] │ └ SPEC CALL [*15*=[*LIT*]67195]902018 +//│ [mono] │ call result: [*15*=[*LIT*]67195]902018 +//│ [mono] │ merging []617314 with [*15*=[*LIT*]67195]902018 +//│ [mono] │ result [*15*=[*LIT*]67195]963429 +//│ [mono] └ EVAL [*15*=[*LIT*]67195]963429 +//│ [mono] comparing [*15*=[*LIT*]67195]203295 with [*15*=[*LIT*]67195]963429 +//│ [mono] main$$6: () -> *17*=[*15*=[*LIT*]67195]963429 @{} //│ [mono] evaluating main$$5, rests: HashSet() //│ [mono] ========== updating main$$5 ========== -//│ [mono] main$$5: () -> [] @{} -//│ [mono] ┌ SPEC CALL gen with ([1]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] -//│ [mono] ┌ SPEC CALL derive$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], [0]) -//│ [mono] │ comparing (([],0), ([],0)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]), Plain([0])) -//│ [mono] │ first time encounter derive$A$4 -//│ [mono] │ evaluating derive$A$4, rests: HashSet() -//│ [mono] │ ========== updating derive$A$4 ========== -//│ [mono] │ derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [] @{main$$5} -//│ [mono] │ ┌ SPEC CALL derive$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], [0]) -//│ [mono] │ │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003), ([0],1)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]), Plain([0])) -//│ [mono] │ └ SPEC CALL [] -//│ [mono] │ ┌ SPEC CALL derive$E$1 with ([E$1@{}], [0]) -//│ [mono] │ │ comparing (([],0), ([],0)) with (Plain([E$1@{}]), Plain([0])) -//│ [mono] │ │ first time encounter derive$E$1 -//│ [mono] │ │ evaluating derive$E$1, rests: HashSet() -//│ [mono] │ │ ========== updating derive$E$1 ========== -//│ [mono] │ │ derive$E$1: (([E$1@{}],1) X ([0],1)) -> [] @{derive$A$4} -//│ [mono] │ │ comparing [] with [E$1@{}] -//│ [mono] │ │ adding these funcs to queue: Set(derive$A$4) -//│ [mono] │ │ derive$E$1: (([E$1@{}],1) X ([0],1)) -> [E$1@{}] @{derive$A$4} -//│ [mono] │ └ SPEC CALL [E$1@{}] -//│ [mono] │ ┌ SPEC CALL derive$C$3 with ([C$3@{i: [*LIT*]}], [0]) -//│ [mono] │ │ comparing (([C$3@{i: [1]}],2), ([0],1)) with (Plain([C$3@{i: [*LIT*]}]), Plain([0])) +//│ [mono] main$$5: () -> *16*=[*16*=...]810726 @{} +//│ [mono] ┌ EVAL foo(new Lambda$3 () ) +//│ [mono] │ ┌ EVAL foo +//│ [mono] │ └ EVAL [foo(x) given {}]647833 +//│ [mono] │ ┌ EVAL new Lambda$3 () +//│ [mono] │ └ EVAL [Lambda$3@{}]123140 +//│ [mono] │ ┌ SPEC CALL foo with ([Lambda$3@{}]123140) +//│ [mono] │ │ comparing (([Lambda2$4@{a: [2]752278}]622915,2)) with (Plain([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780)) //│ [mono] │ │ find finer args -//│ [mono] │ └ SPEC CALL [E$1@{} | Ep$2@{}] -//│ [mono] │ comparing [] with [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] -//│ [mono] │ adding these funcs to queue: Set(main$$5, derive$A$4) -//│ [mono] │ derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] @{main$$5, derive$A$4} -//│ [mono] └ SPEC CALL [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] -//│ [mono] ┌ SPEC CALL derive$E$1 with ([E$1@{}], [0]) -//│ [mono] │ comparing (([E$1@{}],1), ([0],1)) with (Plain([E$1@{}]), Plain([0])) -//│ [mono] └ SPEC CALL [E$1@{}] -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}]) -//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}])) -//│ [mono] │ find finer args -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [] with [*LIT*] -//│ [mono] adding these funcs to queue: Set() -//│ [mono] main$$5: () -> [*LIT*] @{} -//│ [mono] evaluating isEmpty$A$4, rests: HashSet(derive$A$4, derive$C$3, main$$5) -//│ [mono] ========== updating isEmpty$A$4 ========== -//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) -> [*LIT*] @{main$$6, isEmpty$A$4, main$$5} -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]) -//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$C$3 with ([C$3@{i: [*LIT*]}]) -//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],100001)) with (Plain([C$3@{i: [*LIT*]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] ┌ SPEC CALL isEmpty$Ep$2 with ([Ep$2@{}]) -//│ [mono] │ comparing (([Ep$2@{}],1)) with (Plain([Ep$2@{}])) -//│ [mono] └ SPEC CALL [1] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) -> [*LIT*] @{main$$6, isEmpty$A$4, main$$5} -//│ [mono] evaluating derive$A$4, rests: HashSet(derive$C$3, main$$5) -//│ [mono] ========== updating derive$A$4 ========== -//│ [mono] derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] @{main$$5, derive$A$4} -//│ [mono] ┌ SPEC CALL derive$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], [0]) -//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003), ([0],1)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]), Plain([0])) -//│ [mono] └ SPEC CALL [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] -//│ [mono] ┌ SPEC CALL derive$E$1 with ([E$1@{}], [0]) -//│ [mono] │ comparing (([E$1@{}],1), ([0],1)) with (Plain([E$1@{}]), Plain([0])) -//│ [mono] └ SPEC CALL [E$1@{}] -//│ [mono] ┌ SPEC CALL derive$C$3 with ([C$3@{i: [*LIT*]}], [0]) -//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],100001), ([0],1)) with (Plain([C$3@{i: [*LIT*]}]), Plain([0])) -//│ [mono] └ SPEC CALL [E$1@{} | Ep$2@{}] -//│ [mono] comparing [A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}] with [A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{}], e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] -//│ [mono] adding these funcs to queue: Set(main$$5, derive$A$4) -//│ [mono] derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] @{main$$5, derive$A$4} -//│ [mono] evaluating derive$A$4, rests: HashSet(derive$C$3, main$$5) -//│ [mono] ========== updating derive$A$4 ========== -//│ [mono] derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] @{main$$5, derive$A$4} -//│ [mono] ┌ SPEC CALL derive$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], [0]) -//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003), ([0],1)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]), Plain([0])) -//│ [mono] └ SPEC CALL [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] -//│ [mono] ┌ SPEC CALL derive$E$1 with ([E$1@{}], [0]) -//│ [mono] │ comparing (([E$1@{}],1), ([0],1)) with (Plain([E$1@{}]), Plain([0])) -//│ [mono] └ SPEC CALL [E$1@{}] -//│ [mono] ┌ SPEC CALL derive$C$3 with ([C$3@{i: [*LIT*]}], [0]) -//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],100001), ([0],1)) with (Plain([C$3@{i: [*LIT*]}]), Plain([0])) -//│ [mono] └ SPEC CALL [E$1@{} | Ep$2@{}] -//│ [mono] comparing [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] with [A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] -//│ [mono] derive$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003) X ([0],1)) -> [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] @{main$$5, derive$A$4} -//│ [mono] evaluating derive$C$3, rests: HashSet(main$$5) -//│ [mono] ========== updating derive$C$3 ========== -//│ [mono] derive$C$3: (([C$3@{i: [*LIT*]}],100001) X ([0],1)) -> [E$1@{} | Ep$2@{}] @{main$$7, derive$A$4} -//│ [mono] ┌ SPEC CALL < with ([0]) -//│ [mono] │ !!!!!!! -//│ [mono] │ calling unknown function <([0]) -//│ [mono] │ Set(isEmpty$Ep$2, gen, isEmpty$C$3, isEmpty$E$1, isEmpty$A$4, derive$A$4, derive$E$1, derive$C$3, main$$7, main$$6, main$$5) -//│ [mono] └ SPEC CALL [?3?] -//│ [mono] comparing [E$1@{} | Ep$2@{}] with [E$1@{} | Ep$2@{}] -//│ [mono] derive$C$3: (([C$3@{i: [*LIT*]}],100001) X ([0],1)) -> [E$1@{} | Ep$2@{}] @{main$$7, derive$A$4} -//│ [mono] evaluating main$$5, rests: HashSet() -//│ [mono] ========== updating main$$5 ========== -//│ [mono] main$$5: () -> [*LIT*] @{} -//│ [mono] ┌ SPEC CALL gen with ([1]) -//│ [mono] │ comparing (([*LIT*],100000)) with (Plain([*LIT*])) -//│ [mono] └ SPEC CALL [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] -//│ [mono] ┌ SPEC CALL derive$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], [0]) -//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}],100003), ([0],1)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}]), Plain([0])) -//│ [mono] └ SPEC CALL [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] -//│ [mono] ┌ SPEC CALL derive$E$1 with ([E$1@{}], [0]) -//│ [mono] │ comparing (([E$1@{}],1), ([0],1)) with (Plain([E$1@{}]), Plain([0])) -//│ [mono] └ SPEC CALL [E$1@{}] -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}]) -//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}])) -//│ [mono] │ find finer args -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] main$$5: () -> [*LIT*] @{} -//│ [mono] evaluating isEmpty$A$4, rests: HashSet() -//│ [mono] ========== updating isEmpty$A$4 ========== -//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) -> [*LIT*] @{main$$6, isEmpty$A$4, main$$5} -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$A$4 with ([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}]) -//│ [mono] │ comparing (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) with (Plain([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] ┌ SPEC CALL isEmpty$E$1 with ([E$1@{}]) -//│ [mono] │ comparing (([E$1@{}],1)) with (Plain([E$1@{}])) -//│ [mono] └ SPEC CALL [0] -//│ [mono] ┌ SPEC CALL isEmpty$C$3 with ([C$3@{i: [*LIT*]}]) -//│ [mono] │ comparing (([C$3@{i: [*LIT*]}],100001)) with (Plain([C$3@{i: [*LIT*]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] ┌ SPEC CALL isEmpty$Ep$2 with ([Ep$2@{}]) -//│ [mono] │ comparing (([Ep$2@{}],1)) with (Plain([Ep$2@{}])) -//│ [mono] └ SPEC CALL [1] -//│ [mono] comparing [*LIT*] with [*LIT*] -//│ [mono] isEmpty$A$4: (([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}],100004)) -> [*LIT*] @{main$$6, isEmpty$A$4, main$$5} +//│ [mono] │ └ SPEC CALL [*15*=[*LIT*]67195]41480 +//│ [mono] │ call result: [*15*=[*LIT*]67195]41480 +//│ [mono] │ merging []590767 with [*15*=[*LIT*]67195]41480 +//│ [mono] │ result [*15*=[*LIT*]67195]298303 +//│ [mono] └ EVAL [*15*=[*LIT*]67195]298303 +//│ [mono] comparing [*16*=...]810726 with [*15*=[*LIT*]67195]298303 +//│ [mono] main$$5: () -> *16*=[*15*=[*LIT*]67195]298303 @{} +//│ [mono] evaluating foo, rests: HashSet() +//│ [mono] ========== updating foo ========== +//│ [mono] foo: (([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780,3)) -> *15*=[*LIT*]67195 @{main$$6, main$$5} +//│ [mono] ┌ EVAL (x.apply(new Cons$1 (#1, new Nil$2 () ) ) + x.apply(new Nil$2 () )) +//│ [mono] │ ┌ EVAL x.apply(new Cons$1 (#1, new Nil$2 () ) ) +//│ [mono] │ │ ┌ EVAL x.apply +//│ [mono] │ │ │ ┌ EVAL x +//│ [mono] │ │ │ └ EVAL [Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780 +//│ [mono] │ │ └ EVAL [apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]992279} | apply$Lambda$3(l) given {this: [Lambda$3@{}]793571}]732519 +//│ [mono] │ │ ┌ EVAL new Cons$1 (#1, new Nil$2 () ) +//│ [mono] │ │ │ ┌ EVAL #1 +//│ [mono] │ │ │ └ EVAL [1]456454 +//│ [mono] │ │ │ ┌ EVAL new Nil$2 () +//│ [mono] │ │ │ └ EVAL [Nil$2@{}]142364 +//│ [mono] │ │ └ EVAL [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]903239 +//│ [mono] │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]992279, [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]903239) +//│ [mono] │ │ │ comparing (([Lambda2$4@{a: [2]752278}]91381,2), ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) with (Plain([Lambda2$4@{a: [2]752278}]138839), Plain([Cons$1@{e: [1]995583, tail: [Nil$2@{}]927154} | Nil$2@{}]504129)) +//│ [mono] │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]513374]980184]739668 +//│ [mono] │ │ call result: [*18*=[*19*=[*LIT*]513374]980184]739668 +//│ [mono] │ │ ┌ SPEC CALL apply$Lambda$3 with ([Lambda$3@{}]793571, [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]903239) +//│ [mono] │ │ │ comparing (([]652955,0), ([]66778,0)) with (Plain([Lambda$3@{}]988452), Plain([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]209615)) +//│ [mono] │ │ │ first time encounter apply$Lambda$3 +//│ [mono] │ │ │ evaluating apply$Lambda$3, rests: HashSet() +//│ [mono] │ │ │ ========== updating apply$Lambda$3 ========== +//│ [mono] │ │ │ apply$Lambda$3: (([Lambda$3@{}]988452,1) X ([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]209615,3)) -> *21*=[*21*=...]989283 @{foo} +//│ [mono] │ │ │ ┌ EVAL l.count() +//│ [mono] │ │ │ │ ┌ EVAL l.count() +//│ [mono] │ │ │ │ │ ┌ EVAL l.count +//│ [mono] │ │ │ │ │ │ ┌ EVAL l +//│ [mono] │ │ │ │ │ │ └ EVAL [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]209615 +//│ [mono] │ │ │ │ │ └ EVAL [count$Cons$1() given {this: [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]477491}]445270 +//│ [mono] │ │ │ │ │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]477491) +//│ [mono] │ │ │ │ │ │ comparing (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) with (Plain([Cons$1@{e: [*LIT*]608008, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]782101}]639500)) +//│ [mono] │ │ │ │ │ └ SPEC CALL [*19*=[*LIT*]513374]172112 +//│ [mono] │ │ │ │ │ call result: [*19*=[*LIT*]513374]172112 +//│ [mono] │ │ │ │ │ merging []756915 with [*19*=[*LIT*]513374]172112 +//│ [mono] │ │ │ │ │ result [*19*=[*LIT*]513374]286621 +//│ [mono] │ │ │ │ └ EVAL [*19*=[*LIT*]513374]286621 +//│ [mono] │ │ │ └ EVAL [*19*=[*LIT*]513374]286621 +//│ [mono] │ │ │ comparing [*21*=...]989283 with [*19*=[*LIT*]513374]286621 +//│ [mono] │ │ │ apply$Lambda$3: (([Lambda$3@{}]988452,1) X ([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]209615,3)) -> *21*=[*19*=[*LIT*]513374]286621 @{foo} +//│ [mono] │ │ └ SPEC CALL [*21*=[*19*=[*LIT*]513374]286621]767426 +//│ [mono] │ │ call result: [*21*=[*19*=[*LIT*]513374]286621]767426 +//│ [mono] │ │ merging []319684 with [*18*=[*19*=[*LIT*]513374]980184]739668 +//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184]830712 +//│ [mono] │ │ merging [*18*=[*19*=[*LIT*]513374]980184]830712 with [*21*=[*19*=[*LIT*]513374]286621]767426 +//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184 | *21*=[*19*=[*LIT*]513374]286621]77626 +//│ [mono] │ └ EVAL [*18*=[*19*=[*LIT*]513374]980184 | *21*=[*19*=[*LIT*]513374]286621]77626 +//│ [mono] │ ┌ EVAL x.apply(new Nil$2 () ) +//│ [mono] │ │ ┌ EVAL x.apply +//│ [mono] │ │ │ ┌ EVAL x +//│ [mono] │ │ │ └ EVAL [Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780 +//│ [mono] │ │ └ EVAL [apply$Lambda$3(l) given {this: [Lambda$3@{}]442930} | apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]808077}]684849 +//│ [mono] │ │ ┌ EVAL new Nil$2 () +//│ [mono] │ │ └ EVAL [Nil$2@{}]686449 +//│ [mono] │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]808077, [Nil$2@{}]686449) +//│ [mono] │ │ │ comparing (([Lambda2$4@{a: [2]752278}]91381,2), ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) with (Plain([Lambda2$4@{a: [2]752278}]939024), Plain([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]368348)) +//│ [mono] │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]513374]980184]590325 +//│ [mono] │ │ call result: [*18*=[*19*=[*LIT*]513374]980184]590325 +//│ [mono] │ │ ┌ SPEC CALL apply$Lambda$3 with ([Lambda$3@{}]442930, [Nil$2@{}]686449) +//│ [mono] │ │ │ comparing (([Lambda$3@{}]988452,1), ([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]209615,3)) with (Plain([Lambda$3@{}]195071), Plain([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468)) +//│ [mono] │ │ │ find finer args +//│ [mono] │ │ └ SPEC CALL [*21*=[*19*=[*LIT*]513374]286621]970626 +//│ [mono] │ │ call result: [*21*=[*19*=[*LIT*]513374]286621]970626 +//│ [mono] │ │ merging []845011 with [*18*=[*19*=[*LIT*]513374]980184]590325 +//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184]981314 +//│ [mono] │ │ merging [*18*=[*19*=[*LIT*]513374]980184]981314 with [*21*=[*19*=[*LIT*]513374]286621]970626 +//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184 | *21*=[*19*=[*LIT*]513374]286621]312038 +//│ [mono] │ └ EVAL [*18*=[*19*=[*LIT*]513374]980184 | *21*=[*19*=[*LIT*]513374]286621]312038 +//│ [mono] └ EVAL [*LIT*]52478 +//│ [mono] comparing [*LIT*]67195 with [*LIT*]52478 +//│ [mono] foo: (([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780,3)) -> *15*=[*LIT*]52478 @{main$$6, main$$5} +//│ [mono] evaluating apply$Lambda$3, rests: HashSet() +//│ [mono] ========== updating apply$Lambda$3 ========== +//│ [mono] apply$Lambda$3: (([Lambda$3@{}]195071,1) X ([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468,4)) -> *21*=[*19*=[*LIT*]513374]286621 @{foo} +//│ [mono] ┌ EVAL l.count() +//│ [mono] │ ┌ EVAL l.count +//│ [mono] │ │ ┌ EVAL l +//│ [mono] │ │ └ EVAL [Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468 +//│ [mono] │ └ EVAL [count$Nil$2() given {this: [Nil$2@{}]202478} | count$Cons$1() given {this: [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]305777}]658816 +//│ [mono] │ ┌ SPEC CALL count$Nil$2 with ([Nil$2@{}]202478) +//│ [mono] │ │ comparing (([Nil$2@{}]560462,1)) with (Plain([Nil$2@{}]689512)) +//│ [mono] │ └ SPEC CALL [*20*=[0]326453]434307 +//│ [mono] │ call result: [*20*=[0]326453]434307 +//│ [mono] │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]305777) +//│ [mono] │ │ comparing (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) with (Plain([Cons$1@{e: [*LIT*]232010, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]655168}]625967)) +//│ [mono] │ └ SPEC CALL [*19*=[*LIT*]513374]232324 +//│ [mono] │ call result: [*19*=[*LIT*]513374]232324 +//│ [mono] │ merging []923571 with [*20*=[0]326453]434307 +//│ [mono] │ result [*20*=[0]326453]909846 +//│ [mono] │ merging [*20*=[0]326453]909846 with [*19*=[*LIT*]513374]232324 +//│ [mono] │ result [*19*=[*LIT*]513374 | *20*=[0]326453]994788 +//│ [mono] └ EVAL [*19*=[*LIT*]513374 | *20*=[0]326453]994788 +//│ [mono] comparing [*19*=[*LIT*]513374]286621 with [*19*=[*LIT*]513374 | *20*=[0]326453]994788 +//│ [mono] adding these funcs to queue: Set(foo) +//│ [mono] apply$Lambda$3: (([Lambda$3@{}]195071,1) X ([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468,4)) -> *21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 @{foo} +//│ [mono] evaluating foo, rests: HashSet() +//│ [mono] ========== updating foo ========== +//│ [mono] foo: (([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780,3)) -> *15*=[*LIT*]52478 @{main$$6, main$$5} +//│ [mono] ┌ EVAL (x.apply(new Cons$1 (#1, new Nil$2 () ) ) + x.apply(new Nil$2 () )) +//│ [mono] │ ┌ EVAL x.apply(new Cons$1 (#1, new Nil$2 () ) ) +//│ [mono] │ │ ┌ EVAL x.apply +//│ [mono] │ │ │ ┌ EVAL x +//│ [mono] │ │ │ └ EVAL [Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780 +//│ [mono] │ │ └ EVAL [apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]464438} | apply$Lambda$3(l) given {this: [Lambda$3@{}]190192}]291875 +//│ [mono] │ │ ┌ EVAL new Cons$1 (#1, new Nil$2 () ) +//│ [mono] │ │ │ ┌ EVAL #1 +//│ [mono] │ │ │ └ EVAL [1]942335 +//│ [mono] │ │ │ ┌ EVAL new Nil$2 () +//│ [mono] │ │ │ └ EVAL [Nil$2@{}]201541 +//│ [mono] │ │ └ EVAL [Cons$1@{e: [1]942335, tail: [Nil$2@{}]201541}]426752 +//│ [mono] │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]464438, [Cons$1@{e: [1]942335, tail: [Nil$2@{}]201541}]426752) +//│ [mono] │ │ │ comparing (([Lambda2$4@{a: [2]752278}]91381,2), ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) with (Plain([Lambda2$4@{a: [2]752278}]209630), Plain([Cons$1@{e: [1]95172, tail: [Nil$2@{}]958140} | Nil$2@{}]795421)) +//│ [mono] │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]513374]980184]78520 +//│ [mono] │ │ call result: [*18*=[*19*=[*LIT*]513374]980184]78520 +//│ [mono] │ │ ┌ SPEC CALL apply$Lambda$3 with ([Lambda$3@{}]190192, [Cons$1@{e: [1]942335, tail: [Nil$2@{}]201541}]426752) +//│ [mono] │ │ │ comparing (([Lambda$3@{}]195071,1), ([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468,4)) with (Plain([Lambda$3@{}]905090), Plain([Cons$1@{e: [1]541051, tail: [Nil$2@{}]530234} | Nil$2@{}]17701)) +//│ [mono] │ │ └ SPEC CALL [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]788726 +//│ [mono] │ │ call result: [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]788726 +//│ [mono] │ │ merging []853155 with [*18*=[*19*=[*LIT*]513374]980184]78520 +//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184]259345 +//│ [mono] │ │ merging [*18*=[*19*=[*LIT*]513374]980184]259345 with [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]788726 +//│ [mono] │ │ result [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 | *18*=[*19*=[*LIT*]513374]980184]545957 +//│ [mono] │ └ EVAL [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 | *18*=[*19*=[*LIT*]513374]980184]545957 +//│ [mono] │ ┌ EVAL x.apply(new Nil$2 () ) +//│ [mono] │ │ ┌ EVAL x.apply +//│ [mono] │ │ │ ┌ EVAL x +//│ [mono] │ │ │ └ EVAL [Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780 +//│ [mono] │ │ └ EVAL [apply$Lambda$3(l) given {this: [Lambda$3@{}]218234} | apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]851318}]806082 +//│ [mono] │ │ ┌ EVAL new Nil$2 () +//│ [mono] │ │ └ EVAL [Nil$2@{}]205827 +//│ [mono] │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]851318, [Nil$2@{}]205827) +//│ [mono] │ │ │ comparing (([Lambda2$4@{a: [2]752278}]91381,2), ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) with (Plain([Lambda2$4@{a: [2]752278}]249616), Plain([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]796479)) +//│ [mono] │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]513374]980184]519713 +//│ [mono] │ │ call result: [*18*=[*19*=[*LIT*]513374]980184]519713 +//│ [mono] │ │ ┌ SPEC CALL apply$Lambda$3 with ([Lambda$3@{}]218234, [Nil$2@{}]205827) +//│ [mono] │ │ │ comparing (([Lambda$3@{}]195071,1), ([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468,4)) with (Plain([Lambda$3@{}]575409), Plain([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]107065)) +//│ [mono] │ │ └ SPEC CALL [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]183012 +//│ [mono] │ │ call result: [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]183012 +//│ [mono] │ │ merging []7556 with [*18*=[*19*=[*LIT*]513374]980184]519713 +//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184]657118 +//│ [mono] │ │ merging [*18*=[*19*=[*LIT*]513374]980184]657118 with [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]183012 +//│ [mono] │ │ result [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 | *18*=[*19*=[*LIT*]513374]980184]952944 +//│ [mono] │ └ EVAL [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 | *18*=[*19*=[*LIT*]513374]980184]952944 +//│ [mono] └ EVAL [*LIT*]197099 +//│ [mono] comparing [*LIT*]52478 with [*LIT*]197099 +//│ [mono] foo: (([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780,3)) -> *15*=[*LIT*]197099 @{main$$6, main$$5} //│ [mono] //│ [mono] ==============final function signatures================== -//│ [mono] isEmpty$Ep$2: ([Ep$2@{}]) -> [1] -//│ [mono] gen: ([*LIT*]) -> [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}] -//│ [mono] isEmpty$C$3: ([C$3@{i: [*LIT*]}]) -> [*LIT*] -//│ [mono] isEmpty$E$1: ([E$1@{}]) -> [0] -//│ [mono] isEmpty$A$4: ([A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}], e2: [E$1@{} | Ep$2@{} | C$3@{i: [*LIT*]}]}]) -> [*LIT*] -//│ [mono] derive$A$4: ([A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [C$3@{i: [*LIT*]}]}], e2: [C$3@{i: [*LIT*]}]}] X [0]) -> [A$4@{e1: [E$1@{} | A$4@{e1: ***, e2: [E$1@{} | Ep$2@{}]}], e2: [E$1@{} | Ep$2@{}]}] -//│ [mono] derive$E$1: ([E$1@{}] X [0]) -> [E$1@{}] -//│ [mono] derive$C$3: ([C$3@{i: [*LIT*]}] X [0]) -> [E$1@{} | Ep$2@{}] -//│ [mono] main$$7: () -> [*LIT*] -//│ [mono] main$$6: () -> [*LIT*] -//│ [mono] main$$5: () -> [*LIT*] +//│ [mono] count$Cons$1: ([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965) -> *19*=[*LIT*]513374 +//│ [mono] apply$Lambda$3: ([Lambda$3@{}]195071 X [Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468) -> *21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 +//│ [mono] count$Nil$2: ([Nil$2@{}]560462) -> *20*=[0]326453 +//│ [mono] foo: ([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780) -> *15*=[*LIT*]197099 +//│ [mono] apply$Lambda2$4: ([Lambda2$4@{a: [2]752278}]91381 X [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016) -> *18*=[*19*=[*LIT*]513374]980184 +//│ [mono] main$$6: () -> *17*=[*15*=[*LIT*]197099]963429 +//│ [mono] main$$5: () -> *16*=[*15*=[*LIT*]197099]298303 + +// :mono +class E() { + fun derive(x) = + new E + fun isEmpty() = + false +} +class Ep(){ + fun derive(x) = + new E + fun isEmpty() = + true +} +class Ch(i){ + fun derive(x) = + if x == i then new Ep else new E + fun isEmpty() = + false +} +class A(e1, e2){ + fun derive(x) = + new A(e1.derive(x), e2.derive(x)) + fun isEmpty() = + e1.isEmpty() || e2.isEmpty() +} +class C(e1, e2){ + fun derive(x) = + if e1.isEmpty() then new A(new C(e1.derive(x), e2), e2.derive(x)) else new C(e1.derive(x), e2) + fun isEmpty() = + e1.isEmpty() && e2.isEmpty() +} +(new C(new Ch(1), new A(new Ch(2), new Ch(3)))).derive(0).isEmpty() +//│ |#class| |E|(||)| |{|→|#fun| |derive|(|x|)| |#=| |→|#new| |E|←|↵|#fun| |isEmpty|(||)| |#=| |→|false|←|←|↵|}|↵|#class| |Ep|(||)|{|→|#fun| |derive|(|x|)| |#=| |→|#new| |E|←|↵|#fun| |isEmpty|(||)| |#=| |→|true|←|←|↵|}|↵|#class| |Ch|(|i|)|{|→|#fun| |derive|(|x|)| |#=| |→|#if| |x| |==| |i| |#then| |#new| |Ep| |#else| |#new| |E|←|↵|#fun| |isEmpty|(||)| |#=| |→|false|←|←|↵|}|↵|#class| |A|(|e1|,| |e2|)|{|→|#fun| |derive|(|x|)| |#=| |→|#new| |A|(|e1|.derive|(|x|)|,| |e2|.derive|(|x|)|)|←|↵|#fun| |isEmpty|(||)| |#=| |→|e1|.isEmpty|(||)| |||| |e2|.isEmpty|(||)|←|←|↵|}|↵|#class| |C|(|e1|,| |e2|)|{|→|#fun| |derive|(|x|)| |#=| |→|#if| |e1|.isEmpty|(||)| |#then| |#new| |A|(|#new| |C|(|e1|.derive|(|x|)|,| |e2|)|,| |e2|.derive|(|x|)|)| |#else| |#new| |C|(|e1|.derive|(|x|)|,| |e2|)|←|↵|#fun| |isEmpty|(||)| |#=| |→|e1|.isEmpty|(||)| |&&| |e2|.isEmpty|(||)|←|←|↵|}|↵|(|#new| |C|(|#new| |Ch|(|1|)|,| |#new| |A|(|#new| |Ch|(|2|)|,| |#new| |Ch|(|3|)|)|)|)|.derive|(|0|)|.isEmpty|(||)| +//│ Parsed: {class E() {fun derive = x, => {new E() {}}; fun isEmpty = => {false}}; class Ep() {fun derive = x, => {new E() {}}; fun isEmpty = => {true}}; class Ch(i,) {fun derive = x, => {if (== (x,) (i,)) then new Ep() {} else new E() {}}; fun isEmpty = => {false}}; class A(e1, e2,) {fun derive = x, => {new A((e1).derive (x,), (e2).derive (x,),) {}}; fun isEmpty = => {|| ((e1).isEmpty (),) ((e2).isEmpty (),)}}; class C(e1, e2,) {fun derive = x, => {if ((e1).isEmpty ()) then new A(new C((e1).derive (x,), e2,) {}, (e2).derive (x,),) {} else new C((e1).derive (x,), e2,) {}}; fun isEmpty = => {&& ((e1).isEmpty (),) ((e2).isEmpty (),)}}; (('(' new C(new Ch(1,) {}, new A(new Ch(2,) {}, new Ch(3,) {},) {},) {}, ')').derive (0,)).isEmpty ()} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, E, (), Tup(), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ep, (), Tup(), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ch, (), Tup(_: Var(i)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, A, (), Tup(_: Var(e1), _: Var(e2)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, C, (), Tup(_: Var(e1), _: Var(e2)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), App(Sel(App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(C),new Ch(1,) {}, new A(new Ch(2,) {}, new Ch(3,) {},) {},)), TypingUnit(List())))), derive), Tup(_: IntLit(0))), isEmpty), Tup())) +//│ Lifted: +//│ TypingUnit { +//│ class E$1() { +//│ fun derive = x, => {new E$1() {}} +//│ fun isEmpty = => {false} +//│ } +//│ class Ep$2() { +//│ fun derive = x, => {new E$1() {}} +//│ fun isEmpty = => {true} +//│ } +//│ class Ch$3(i,) { +//│ fun derive = x, => {if (== (x,) ((this).i,)) then new Ep$2() {} else new E$1() {}} +//│ fun isEmpty = => {false} +//│ } +//│ class A$4(e1, e2,) { +//│ fun derive = x, => {new A$4(((this).e1).derive (x,), ((this).e2).derive (x,),) {}} +//│ fun isEmpty = => {|| (((this).e1).isEmpty (),) (((this).e2).isEmpty (),)} +//│ } +//│ class C$5(e1, e2,) { +//│ fun derive = x, => {if (((this).e1).isEmpty ()) then new A$4(new C$5(((this).e1).derive (x,), (this).e2,) {}, ((this).e2).derive (x,),) {} else new C$5(((this).e1).derive (x,), (this).e2,) {}} +//│ fun isEmpty = => {&& (((this).e1).isEmpty (),) (((this).e2).isEmpty (),)} +//│ } +//│ Code(List((('(' new C$5(new Ch$3(1,) {}, new A$4(new Ch$3(2,) {}, new Ch$3(3,) {},) {},) {}, ')').derive (0,)).isEmpty ())) +//│ } // :mono @@ -1013,7 +1626,7 @@ class Foo(x){ //│ Code(List(('(' new Foo$1(1,) {}, ')').boo (2,))) //│ } -:mono +// :mono class OneInt(a){ fun fac() = if(a > 0) then (new OneInt(a-1)).fac() else 1 @@ -1030,62 +1643,6 @@ class OneInt(a){ //│ } //│ Code(List(('(' new OneInt$1(10,) {}, ')').fac ())) //│ } -//│ Mono: -//│ -//│ Mono result: -//│ main$$1() -//│ fun fac$OneInt$1(this) = -//│ if (this.a > #0) then new OneInt$1 ((this.a - #1)) match {case obj: OneInt$1 => fac$OneInt$1(obj)} else #1 -//│ fun main$$1() = -//│ new OneInt$1 (#10) match {case obj: OneInt$1 => fac$OneInt$1(obj)} -//│ [mono] evaluating main$$1, rests: HashSet() -//│ [mono] ========== updating main$$1 ========== -//│ [mono] main$$1: () -> [] @{} -//│ [mono] ┌ SPEC CALL fac$OneInt$1 with ([OneInt$1@{a: [10]}]) -//│ [mono] │ comparing (([],0)) with (Plain([OneInt$1@{a: [10]}])) -//│ [mono] │ first time encounter fac$OneInt$1 -//│ [mono] │ evaluating fac$OneInt$1, rests: HashSet() -//│ [mono] │ ========== updating fac$OneInt$1 ========== -//│ [mono] │ fac$OneInt$1: (([OneInt$1@{a: [10]}],2)) -> [] @{main$$1} -//│ [mono] │ ┌ SPEC CALL fac$OneInt$1 with ([OneInt$1@{a: [9]}]) -//│ [mono] │ │ comparing (([OneInt$1@{a: [10]}],2)) with (Plain([OneInt$1@{a: [*LIT*]}])) -//│ [mono] │ │ find finer args -//│ [mono] │ └ SPEC CALL [] -//│ [mono] │ comparing [] with [] -//│ [mono] │ fac$OneInt$1: (([OneInt$1@{a: [*LIT*]}],100001)) -> [] @{main$$1, fac$OneInt$1} -//│ [mono] └ SPEC CALL [] -//│ [mono] comparing [] with [] -//│ [mono] main$$1: () -> [] @{} -//│ [mono] evaluating fac$OneInt$1, rests: HashSet() -//│ [mono] ========== updating fac$OneInt$1 ========== -//│ [mono] fac$OneInt$1: (([OneInt$1@{a: [*LIT*]}],100001)) -> [] @{main$$1, fac$OneInt$1} -//│ [mono] ┌ SPEC CALL fac$OneInt$1 with ([OneInt$1@{a: [*LIT*]}]) -//│ [mono] │ comparing (([OneInt$1@{a: [*LIT*]}],100001)) with (Plain([OneInt$1@{a: [*LIT*]}])) -//│ [mono] └ SPEC CALL [] -//│ [mono] comparing [] with [1] -//│ [mono] adding these funcs to queue: Set(main$$1, fac$OneInt$1) -//│ [mono] fac$OneInt$1: (([OneInt$1@{a: [*LIT*]}],100001)) -> [1] @{main$$1, fac$OneInt$1} -//│ [mono] evaluating fac$OneInt$1, rests: HashSet(main$$1) -//│ [mono] ========== updating fac$OneInt$1 ========== -//│ [mono] fac$OneInt$1: (([OneInt$1@{a: [*LIT*]}],100001)) -> [1] @{main$$1, fac$OneInt$1} -//│ [mono] ┌ SPEC CALL fac$OneInt$1 with ([OneInt$1@{a: [*LIT*]}]) -//│ [mono] │ comparing (([OneInt$1@{a: [*LIT*]}],100001)) with (Plain([OneInt$1@{a: [*LIT*]}])) -//│ [mono] └ SPEC CALL [1] -//│ [mono] comparing [1] with [1] -//│ [mono] fac$OneInt$1: (([OneInt$1@{a: [*LIT*]}],100001)) -> [*LIT*] @{main$$1, fac$OneInt$1} -//│ [mono] evaluating main$$1, rests: HashSet() -//│ [mono] ========== updating main$$1 ========== -//│ [mono] main$$1: () -> [] @{} -//│ [mono] ┌ SPEC CALL fac$OneInt$1 with ([OneInt$1@{a: [10]}]) -//│ [mono] │ comparing (([OneInt$1@{a: [*LIT*]}],100001)) with (Plain([OneInt$1@{a: [*LIT*]}])) -//│ [mono] └ SPEC CALL [*LIT*] -//│ [mono] comparing [] with [*LIT*] -//│ [mono] adding these funcs to queue: Set() -//│ [mono] main$$1: () -> [*LIT*] @{} -//│ [mono] -//│ [mono] ==============final function signatures================== -//│ [mono] fac$OneInt$1: ([OneInt$1@{a: [*LIT*]}]) -> [*LIT*] -//│ [mono] main$$1: () -> [*LIT*] // :mono trait AnyFoo { diff --git a/compiler/shared/test/scala/mlscript/compiler/Test.scala b/compiler/shared/test/scala/mlscript/compiler/Test.scala index d34700e40..f02bea392 100644 --- a/compiler/shared/test/scala/mlscript/compiler/Test.scala +++ b/compiler/shared/test/scala/mlscript/compiler/Test.scala @@ -25,8 +25,8 @@ class DiffTestCompiler extends DiffTests { catch case NonFatal(err) => outputBuilder ++= "Lifting failed: " ++ err.toString() - if mode.fullExceptionStack then outputBuilder ++= - "\n" ++ err.getStackTrace().map(_.toString()).mkString("\n") + if mode.fullExceptionStack then + outputBuilder ++= "\n" ++ err.getStackTrace().map(_.toString()).mkString("\n") if(mode.mono){ outputBuilder ++= "\nMono:\n" val treeDebug = new TreeDebug() diff --git a/shared/src/test/scala/mlscript/DiffTests.scala b/shared/src/test/scala/mlscript/DiffTests.scala index d0b841a8e..2dcb45112 100644 --- a/shared/src/test/scala/mlscript/DiffTests.scala +++ b/shared/src/test/scala/mlscript/DiffTests.scala @@ -208,7 +208,7 @@ class DiffTests case "re" => mode.copy(expectRuntimeErrors = true) case "ShowRepl" => mode.copy(showRepl = true) case "escape" => mode.copy(allowEscape = true) - case "mono" => {println("mono set"); mode.copy(mono = true)} + case "mono" => {mode.copy(mono = true)} case _ => failures += allLines.size - lines.size output("/!\\ Unrecognized option " + line) From 8dd886dfb59f763fd5d008d4d78fbf5a36cc62d1 Mon Sep 17 00:00:00 2001 From: YKY Date: Fri, 7 Apr 2023 21:46:11 +0800 Subject: [PATCH 04/13] progress in spring --- .../scala/mlscript/compiler/ClassLifter.scala | 296 ++-- .../scala/mlscript/compiler/Helpers.scala | 5 +- .../mlscript/compiler/mono/Monomorph.scala | 391 +---- .../mono/specializer/BoundedExpr.scala | 152 +- .../mono/specializer/Specializer.scala | 122 +- compiler/shared/test/diff/LambLift.mls | 28 +- compiler/shared/test/diff/LiftType.mls | 12 +- compiler/shared/test/diff/Lifter.mls | 162 +- compiler/shared/test/diff/LifterBlks.mls | 106 +- compiler/shared/test/diff/mono.mls | 1495 ++++------------- .../test/scala/mlscript/compiler/Test.scala | 6 +- 11 files changed, 702 insertions(+), 2073 deletions(-) diff --git a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala index 016eecb54..fe7b5ebf7 100644 --- a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala +++ b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala @@ -28,6 +28,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { LocalContext(vSet ++ inters.map(x => Var(x.name)), tSet -- inters) } def intersect(rst: LocalContext) = LocalContext(vSet intersect rst.vSet, tSet intersect rst.tSet) + def intersectV(rst: Set[Var]) = LocalContext(vSet.intersect(rst), tSet) def contains(v: Var) = vSet.contains(v) || tSet.contains(TypeName(v.name)) def contains(tv: TypeName) = vSet.contains(Var(tv.name)) || tSet.contains(tv) override def toString(): String = "(" ++ vSet.mkString(", ") ++ "; " ++ tSet.mkString(", ") ++ ")" @@ -37,6 +38,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { private def asContext(t: TypeName) = LocalContext(Set(), Set(t)) private def asContextT(tS: IterableOnce[TypeName]) = LocalContext(Set(), tS.iterator.toSet) private def emptyCtx = LocalContext(Set(), Set()) + private def emptyCtxObj = LocalContext(Set(Var("this")), Set()) case class ClassInfoCache( originNm: TypeName, @@ -56,7 +58,6 @@ class ClassLifter(logDebugMsg: Boolean = false) { var retSeq: List[NuTypeDef] = Nil val globalFunctions: ArrayBuffer[NuFunDef] = ArrayBuffer() - def globalNames: List[Var] = globalFunctions.toList.map(_.nme) var anonymCnt: Int = 0 var clsCnt: Int = 0 val logOutput: StringBuilder = new StringBuilder @@ -146,7 +147,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { (tmp._1.flatten, tmp._2.flatten, tmp._3.flatten) } - private def genClassNm(orgNm: String)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): TypeName = { + private def genClassNm(orgNm: String)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): TypeName = { TypeName(outer match{ case None => clsCnt = clsCnt+1 @@ -155,10 +156,14 @@ class ClassLifter(logDebugMsg: Boolean = false) { }) } - private def getFreeVars(stmt: Located)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): LocalContext = stmt match{ + private def getFreeVars(stmt: Located)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): LocalContext = stmt match{ case v:Var => - log(s"get free var find $v: ${ctx.vSet.contains(v)}/${buildPathToVar(v).isDefined}/${cache.contains(TypeName(v.name))}/${v.name.equals("this")}") - if(ctx.vSet.contains(v) || buildPathToVar(v).isDefined || cache.contains(TypeName(v.name)) || v.name.equals("this") || primiTypes.contains(v.name)) then emptyCtx else asContext(v) + val caseEmpty = ctx.vSet.contains(v) || cache.contains(TypeName(v.name)) || globFuncs.contains(v) || primiTypes.contains(v.name) + val caseThis = buildPathToVar(v).isDefined && !ctx.vSet.contains(Var("this")) + log(s"get free var find $v: $caseEmpty/$caseThis") + if(caseEmpty) then emptyCtx + else if(caseThis) asContext(Var("this")) + else asContext(v) case t: NamedType => log(s"get type $t under $ctx, $cache, $outer") asContextT(t.collectTypeNames.map(TypeName(_)).filterNot(x => ctx.contains(x) || cache.contains(x) || primiTypes.contains(x.name))) @@ -183,7 +188,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { case TyApp(trm, tpLst) => getFreeVars(trm).addT(tpLst.flatMap(_.collectTypeNames.map(TypeName(_)))) case NuTypeDef(_, nm, tps, param, pars, body) => - val prmVs = getFreeVars(param)(using emptyCtx, Map(), None) + val prmVs = getFreeVars(param)(using emptyCtx, Map(), globFuncs, None) val newVs = prmVs.vSet ++ getFields(body.entities) + Var(nm.name) val nCtx = ctx.addV(newVs).addT(nm).addT(tps) val parVs = pars.map(getFreeVars(_)(using nCtx)).fold(emptyCtx)(_ ++ _) @@ -198,20 +203,20 @@ class ClassLifter(logDebugMsg: Boolean = false) { others.children.map(getFreeVars).fold(emptyCtx)(_ ++ _) } - private def collectClassInfo(cls: NuTypeDef, preClss: Set[TypeName])(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): ClassInfoCache = { + private def collectClassInfo(cls: NuTypeDef, preClss: Set[TypeName])(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): ClassInfoCache = { val NuTypeDef(_, nm, tps, param, pars, body) = cls - log(s"grep context of ${cls.nme.name} under {\n$ctx\n$cache\n$outer\n}\n") + log(s"grep context of ${cls.nme.name} under $ctx # $cache # $globFuncs # $outer ") val (clses, funcs, trms) = splitEntities(cls.body.entities) val (supNms, rcdFlds) = pars.map(getSupClsInfoByTerm).unzip val flds = rcdFlds.flatten.map{ case (v, Fld(_, _, trm)) => - val tmp = getFreeVars(trm)(using emptyCtx) + val tmp = getFreeVars(trm)(using emptyCtxObj) val ret = tmp.tSet ++ tmp.vSet.map(x => TypeName(x.name)) (v, ret) }.unzip log(s"par record: ${flds._2.flatten}") val fields = (param.fields.flatMap(tupleEntityToVar) ++ funcs.map(_.nme) ++ clses.map(x => Var(x.nme.name)) ++ trms.flatMap(grepFieldsInTrm) ++ flds._1).toSet - val nCtx = ctx.addV(fields).addV(flds._1).extT(tps) + val nCtx = ctx.addV(fields).addV(flds._1).extT(tps).addV(Var("this")) val tmpCtx = ((body.entities.map(getFreeVars(_)(using nCtx)) ++ pars.map(getFreeVars(_)(using nCtx))).fold(emptyCtx)(_ ++ _).moveT2V(preClss) ).addT(flds._2.flatten.toSet).extV(supNms.flatten.map(x => Var(x.name))) @@ -220,7 +225,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { ret } - private def liftCaseBranch(brn: CaseBranches)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (CaseBranches, LocalContext) = brn match{ + private def liftCaseBranch(brn: CaseBranches)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (CaseBranches, LocalContext) = brn match{ case Case(v: Var, body, rest) => val nTrm = liftTermNew(body)(using ctx.addV(v)) val nRest = liftCaseBranch(rest) @@ -235,7 +240,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { case NoCases => (brn, emptyCtx) } - private def liftIf(body: IfBody)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (IfBody, LocalContext) = body match{ + private def liftIf(body: IfBody)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (IfBody, LocalContext) = body match{ case IfElse(expr) => val ret = liftTermNew(expr) (IfElse(ret._1), ret._2) @@ -246,7 +251,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { case _ => ??? } - private def liftTuple(tup: Tup)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (Tup, LocalContext) = { + private def liftTuple(tup: Tup)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Tup, LocalContext) = { val ret = tup.fields.map{ case (None, Fld(b1, b2, trm)) => val tmp = liftTermNew(trm) @@ -258,7 +263,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { (Tup(ret._1), ret._2.fold(emptyCtx)(_ ++ _)) } - private def liftConstr(tp: TypeName, prm: Tup)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (TypeName, Tup, LocalContext) = { + private def liftConstr(tp: TypeName, prm: Tup)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (TypeName, Tup, LocalContext) = { def findAncestor(crt: ClassInfoCache, target: Option[ClassInfoCache]): Option[(List[String], Option[String])] = { (crt.outerCls, target) match{ case (None, None) => None @@ -295,7 +300,9 @@ class ClassLifter(logDebugMsg: Boolean = false) { private def newLambObj(lhs: Term, rhs: Term) = New(None, TypingUnit(List(NuFunDef(None, Var("apply"), Nil, Left(Lam(lhs, rhs)))))) - private def liftTermNew(target: Term)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (Term, LocalContext) = target match{ + private def liftTermNew(target: Term)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Term, LocalContext) = + log(s"liftTerm $target in $ctx, $cache, $globFuncs, $outer") + target match{ case v: Var => if(ctx.contains(v) || v.name.equals("this") || primiTypes.contains(v.name)) (v, emptyCtx) else if(cache.contains(TypeName(v.name))){ @@ -309,17 +316,12 @@ class ClassLifter(logDebugMsg: Boolean = false) { } } case Lam(lhs, rhs) => - val prmCnt = getFreeVars(lhs)(using emptyCtx, cache, None).vSet.size + val prmCnt = getFreeVars(lhs)(using emptyCtx, cache, globFuncs, None).vSet.size val nTpNm = TypeName(genAnoName("Lambda"+prmCnt)) val anoCls = NuTypeDef(Cls, nTpNm, Nil, Tup(Nil), Nil, TypingUnit(List(NuFunDef(None, Var("apply"), Nil, Left(Lam(lhs, rhs)))))) val nSta = New(Some((nTpNm, Tup(Nil))), TypingUnit(Nil)) val ret = liftEntitiesNew(List(anoCls, nSta)) (Blk(ret._1), ret._2) - // liftTermNew(newLambObj(lhs, rhs)) - // val lctx = getFreeVars(lhs)(using emptyCtx, cache, None) - // val (ltrm, _) = liftTermNew(lhs)(using ctx.addV(lctx.vSet)) - // val (rtrm, rctx) = liftTermNew(rhs)(using ctx.addV(lctx.vSet)) - // (Lam(ltrm, rtrm), rctx -+ lctx) case t: Tup => liftTuple(t) case Rcd(fields) => @@ -336,6 +338,11 @@ class ClassLifter(logDebugMsg: Boolean = false) { case App(v: Var, prm: Tup) if cache.contains(TypeName(v.name)) => val ret = liftConstr(TypeName(v.name), prm) (App(Var(ret._1.name), ret._2), ret._3) + case App(v: Var, prm: Tup) if globFuncs.contains(v) => + val (nFuncName, nCtxs) = globFuncs.get(v).get + val addiArgs = nCtxs.vSet.toList.map(toFldsEle(_)) + val nPrm = liftTuple(prm) + (App(nFuncName, Tup(nPrm._1.fields ++ addiArgs)), nPrm._2) case App(lhs, rhs) => val (ltrm, lctx) = liftTermNew(lhs) val (rtrm, rctx) = liftTermNew(rhs) @@ -409,7 +416,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { } //serves for lifting Tup(Some(_), Fld(_, _, trm)), where trm refers to a type - private def liftTermAsType(target: Term)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (Term, LocalContext) = + private def liftTermAsType(target: Term)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Term, LocalContext) = log(s"liftTermAsType $target in $ctx, $cache") target match{ case v: Var => @@ -444,20 +451,20 @@ class ClassLifter(logDebugMsg: Boolean = false) { case _ => ??? } - private def liftTypeName(target: TypeName)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (TypeName, LocalContext) = { + private def liftTypeName(target: TypeName)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (TypeName, LocalContext) = { if(ctx.contains(target) || primiTypes.contains(target.name)) { target -> emptyCtx } else { cache.get(target).map(x => (x.liftedNm -> emptyCtx)).getOrElse(target -> asContext(target)) } } - private def liftTypeField(target: Field)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (Field, LocalContext) = { + private def liftTypeField(target: Field)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Field, LocalContext) = { val (inT, iCtx) = target.in.map(liftType).unzip val (outT, oCtx) = liftType(target.out) Field(inT, outT) -> (iCtx.getOrElse(emptyCtx) ++ oCtx) } - private def liftType(target: Type)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (Type, LocalContext) = target match{ + private def liftType(target: Type)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Type, LocalContext) = target match{ case AppliedType(base, targs) => val (nTargs, nCtx) = targs.map(liftType).unzip val (nBase, bCtx) = liftTypeName(base) @@ -523,29 +530,54 @@ class ClassLifter(logDebugMsg: Boolean = false) { Union(nlhs._1, nrhs._1) -> (nlhs._2 ++ nrhs._2) case x : TypeName => liftTypeName(x) - // Bot, Literal, Top, TypeTag, TypeVar case others => others -> emptyCtx } - private def liftFunc(func: NuFunDef)(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (NuFunDef, LocalContext) = { - log(s"liftFunc $func under $ctx # $cache # $outer") + private def liftMemberFunc(func: NuFunDef)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (NuFunDef, LocalContext) = { + log(s"liftMemberFunc $func under $ctx # $cache # $globFuncs # $outer") val NuFunDef(rec, nm, tpVs, body) = func body match{ - case Left(Lam(lhs, rhs)) => - val lctx = getFreeVars(lhs)(using emptyCtx, cache, None) - val lret = liftTermNew(lhs)(using ctx.addV(lctx.vSet + nm)) - val ret = liftTermNew(rhs)(using ctx.addV(lctx.vSet + nm).addT(tpVs)) + case Left(Lam(lhs@Tup(etts), rhs)) => + val lctx = getFreeVars(lhs)(using emptyCtx, cache, globFuncs, None) + val lret = liftTuple(lhs)(using ctx.addV(lctx.vSet)) + val ret = liftTermNew(rhs)(using ctx.addV(lctx.vSet).addT(tpVs)) (func.copy(rhs = Left(Lam(lret._1, ret._1))), ret._2 -+ lret._2) case Left(value) => - val ret = liftTermNew(value)(using ctx.addV(nm).addT(tpVs)) - (func.copy(rhs = Left(ret._1)), ret._2) + // will be treated as Lam(Tup(Nil), rhs) + val ret = liftTermNew(value)(using ctx.addT(tpVs)) + (func.copy(rhs = Left(Lam(Tup(Nil), ret._1))), ret._2) case Right(PolyType(targs, body)) => val nBody = liftType(body)(using ctx.addT(tpVs)) val nTargs = targs.map(liftTypeName(_)(using ctx.addT(tpVs))).unzip (func.copy(rhs = Right(PolyType(nTargs._1, nBody._1))), nTargs._2.fold(nBody._2)(_ ++ _)) } } + + private def liftGlobalFunc(func: NuFunDef)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): Unit = { + log(s"liftGlobalFunc $func under $ctx # $cache # $globFuncs # $outer") + val NuFunDef(rec, nm, tpVs, body) = func + val nTpVs = tpVs ++ globFuncs.get(nm).get._2.tSet.toList + globalFunctions.addOne(body match{ + case Left(Lam(lhs@Tup(etts), rhs)) => + val tmp = globFuncs.get(nm).get._2.vSet.toList.map(toFldsEle) + val lctx = getFreeVars(lhs)(using emptyCtx, cache, globFuncs, None) + val lret = liftTuple(lhs)(using ctx.addV(lctx.vSet) ++ globFuncs.get(nm).get._2, cache, globFuncs) + val ret = liftTermNew(rhs)(using ctx.addV(lctx.vSet) ++ globFuncs.get(nm).get._2, cache, globFuncs) + NuFunDef(rec, globFuncs.get(nm).get._1, nTpVs, Left(Lam(Tup(lret._1.fields ++ tmp), ret._1))) + case Left(rhs) => + // will be treated as Lam(Tup(Nil), rhs) + val tmp = globFuncs.get(nm).get._2.vSet.toList.map(toFldsEle) + val ret = liftTermNew(rhs)(using ctx ++ globFuncs.get(nm).get._2, cache, globFuncs) + NuFunDef(rec, globFuncs.get(nm).get._1, nTpVs, Left(Lam(Tup(tmp), ret._1))) + // val ret = liftTermNew(value)(using ctx.addV(nm) ++ globFuncs.get(nm).get._2, cache, globFuncs) + // NuFunDef(rec, globFuncs.get(nm).get._1, nTpVs, Left(ret._1)) + case Right(PolyType(targs, body)) => + val nBody = liftType(body)(using ctx ++ globFuncs.get(nm).get._2, cache, globFuncs, None) + val nTargs = targs.map(liftTypeName(_)(using ctx.addT(nTpVs), cache, globFuncs, None)).unzip + NuFunDef(rec, globFuncs.get(nm).get._1, nTpVs, Right(PolyType(nTargs._1, nBody._1))) + }) + } private def grepFieldsInTrm(trm: Term): Option[Var] = trm match{ @@ -553,84 +585,48 @@ class ClassLifter(logDebugMsg: Boolean = false) { case _ => None } - private def mixClsInfos(clsInfos: Map[TypeName, ClassInfoCache], newClsNms: Set[Var])(using cache: ClassCache): Map[TypeName, ClassInfoCache] = { - val nameInfoMap: MMap[TypeName, ClassInfoCache] = MMap(clsInfos.toSeq: _*) - log(s"mix cls infos $nameInfoMap") + private def mixClsInfos(clsInfos: Map[String, ClassInfoCache], funcInfos: Map[String, LocalContext])(using cache: ClassCache): (Map[String, ClassInfoCache], Map[String, LocalContext]) = { + val nameInfoMap: MMap[String, ClassInfoCache] = MMap(clsInfos.toSeq: _*) + val nameFuncMap: MMap[String, LocalContext] = MMap(funcInfos.toSeq: _*) + log(s"mix cls infos $nameInfoMap, $nameFuncMap") // val fullMp = cache ++ nameInfoMap - val clsNmsAsTypeNm = newClsNms.map(x => TypeName(x.name)) - val len = clsInfos.size + val clsNmsAsTypeNm = clsInfos.keySet.map(x => TypeName(x)) + val len = clsInfos.size + nameFuncMap.size for(_ <- 0 to len){ - val tmp = nameInfoMap.toList - tmp.foreach{case (nmOfCls, infoOfCls@ClassInfoCache(_, _, ctx, flds, inners, sups, _, _, _)) => { - val usedClsNmList = ctx.vSet.map(x => TypeName(x.name)).intersect(clsNmsAsTypeNm) - val newCtxForCls = usedClsNmList.foldLeft(ctx)((c1, c2) => c1 ++ nameInfoMap.get(c2).get.capturedParams) + nameInfoMap.toList.foreach{case (nmOfCls, infoOfCls@ClassInfoCache(_, _, ctx, flds, inners, sups, _, _, _)) => { + val usedClsNmList = ctx.vSet.map(_.name).intersect(clsInfos.keySet) + val newCtxForCls_tmp = usedClsNmList.foldLeft(ctx)((c1, c2) => c1 ++ nameInfoMap.get(c2).get.capturedParams) + + val usedFuncNmList = ctx.vSet.map(_.name).intersect(funcInfos.keySet) + val newCtxForCls = usedFuncNmList.foldLeft(newCtxForCls_tmp)((c, x) => c ++ nameFuncMap.get(x).get) + val supClsNmList = infoOfCls.supClses - val newFields = supClsNmList.foreach(c2 => flds.addAll( - nameInfoMap.get(c2).map(_.fields).getOrElse(cache.get(c2).map(_.fields).getOrElse(Nil)) + supClsNmList.foreach(c2 => flds.addAll( + nameInfoMap.get(c2.name).map(_.fields).getOrElse(cache.get(c2).map(_.fields).getOrElse(Nil)) )) - val newInners = supClsNmList.foreach(c2 => inners.addAll( - nameInfoMap.get(c2).map(_.innerClses).getOrElse(cache.get(c2).map(_.innerClses).getOrElse(Nil)) + supClsNmList.foreach(c2 => inners.addAll( + nameInfoMap.get(c2.name).map(_.innerClses).getOrElse(cache.get(c2).map(_.innerClses).getOrElse(Nil)) )) val newCtxFromSup = supClsNmList.map(c2 => - nameInfoMap.get(c2).map(_.capturedParams).getOrElse(cache.get(c2).map(_.capturedParams).getOrElse(emptyCtx)) + nameInfoMap.get(c2.name).map(_.capturedParams).getOrElse(cache.get(c2).map(_.capturedParams).getOrElse(emptyCtx)) ).fold(emptyCtx)(_ ++ _) infoOfCls.capturedParams = newCtxForCls ++ newCtxFromSup }} - } - nameInfoMap.foreach((x1, x2) => x2.capturedParams = (x2.capturedParams extV newClsNms).extT(x2.innerClses.keySet)) - nameInfoMap.toMap - } - - private def mixFuncFreeVs(funcVs: Map[Var, Set[Var]]): Map[Var, List[Var]] = { - val nameVsMap: Map[Var, MSet[Var]] = funcVs.map(entry => entry._1 -> MSet(entry._2.toSeq: _*)) - val concernedFs = funcVs.keySet - for(_ <- 0 to funcVs.size){ - val tmp = nameVsMap.toList - tmp.foreach((v, vset) => { - val recVs = concernedFs.intersect(vset.toSet) - recVs.foreach(x => nameVsMap.get(v).get.addAll(nameVsMap.get(x).get)) + nameFuncMap.toList.foreach((nm, ctx) => { + val usedClsNmList = ctx.vSet.map(_.name).intersect(clsInfos.keySet) + val usedFuncNmList = ctx.vSet.map(_.name).intersect(funcInfos.keySet) + val nCtx = (usedClsNmList.map(x => nameInfoMap.get(x).get.capturedParams) ++ usedFuncNmList.map(x => nameFuncMap.get(x).get)).foldLeft(ctx)(_ ++ _) + nameFuncMap.update(nm, nCtx) }) } - nameVsMap.map((k, v) => k -> (v--concernedFs).toList) - } - - private def updateFuncSigStmt(targetTrm: Statement)(using extFuncArgs: Map[Var, (Var, List[Var], Tup)]): Statement = targetTrm match{ - case NuFunDef(isLetRec, nme, targs, Left(body)) => NuFunDef(isLetRec, nme, targs, Left(updateFuncSignatures(body)(using extFuncArgs-nme))) - case NuTypeDef(kind, nme, tparams, params, parents, body) => - NuTypeDef(kind, nme, tparams, params, parents.map(updateFuncSignatures), TypingUnit(body.entities.map(updateFuncSigStmt))) - case x: Term => updateFuncSignatures(x) - case others => others + nameInfoMap.foreach((x1, x2) => x2.capturedParams = (x2.capturedParams.extV(clsInfos.keySet.map(Var(_)))).extV(funcInfos.keySet.map(Var(_))).extT(x2.innerClses.keySet)) + nameFuncMap.toList.foreach((x, c) => nameFuncMap.update(x, c.extV(clsInfos.keySet.map(Var(_))).extV(funcInfos.keySet.map(Var(_))))) + log(s"mix result: $nameInfoMap, $nameFuncMap") + nameInfoMap.toMap -> nameFuncMap.toMap } - private def updateFuncSignatures(targetTrm: Term)(using extFuncArgs: Map[Var, (Var, List[Var], Tup)]): Term = targetTrm match{ - case x: Var if extFuncArgs.contains(x) => - val infos = extFuncArgs.get(x).get - val concatedPrm = Tup(infos._2.map(toFldsEle) ++ infos._3.fields) - newLambObj(infos._3, App(infos._1, concatedPrm)) - case App(x: Var, Tup(flds)) if extFuncArgs.contains(x) => - val infos = extFuncArgs.get(x).get - val nArgs = Tup(infos._2.map(toFldsEle) ++ flds.map{case (o, Fld(b1, b2, t)) => (o, Fld(b1, b2, updateFuncSignatures(t)))}) - App(infos._1, nArgs) - case App(lhs, rhs) => - App(updateFuncSignatures(lhs), updateFuncSignatures(rhs)) - case Lam(lhs, rhs) => - val absVs = getFreeVars(lhs)(using emptyCtx, Map(), None).vSet - Lam(lhs, updateFuncSignatures(rhs)(using extFuncArgs -- absVs)) - case If(IfThen(cond, tru), els) => - If(IfThen(updateFuncSignatures(cond), updateFuncSignatures(tru)), els.map(updateFuncSignatures)) - case Let(isRec, name, rhs, body) => - Let(isRec, name, updateFuncSignatures(rhs)(using extFuncArgs-name), updateFuncSignatures(body)(using extFuncArgs-name)) - case Blk(stmts) => - Blk(stmts.map(updateFuncSigStmt)) - case New(head, body) => - New(head.map((x, y) => x -> updateFuncSignatures(y)), TypingUnit(body.entities.map(updateFuncSigStmt))) - case Sel(receiver, fieldName) => - Sel(updateFuncSignatures(receiver), fieldName) - case others => others - } - - private def liftEntitiesNew(etts: List[Statement])(using ctx: LocalContext, cache: ClassCache, outer: Option[ClassInfoCache]): (List[Statement], LocalContext) = { + private def liftEntitiesNew(etts: List[Statement])(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (List[Statement], LocalContext) = { log("liftEntities: " ++ etts.headOption.map(_.toString()).getOrElse("")) val (newCls, newFuncs, rstTrms) = splitEntities(etts) val newClsNms = newCls.map(x => Var(x.nme.name)).toSet @@ -638,77 +634,39 @@ class ClassLifter(logDebugMsg: Boolean = false) { val nmsInTrm = rstTrms.flatMap(grepFieldsInTrm) val clsInfos = newCls.map(x => { val infos = collectClassInfo(x, newCls.map(_.nme).toSet)(using emptyCtx) - infos.capturedParams = infos.capturedParams.copy(vSet = infos.capturedParams.vSet.intersect(ctx.vSet ++ newClsNms ++ newFuncNms ++ nmsInTrm -- globalNames)) - x.nme -> infos}).toMap + infos.capturedParams = infos.capturedParams.intersect(ctx.addV(newClsNms ++ newFuncNms ++ nmsInTrm -- globFuncs.keySet ++ outer.map(_ => Var("this")))) + x.nme.name -> infos}).toMap + val funcInfos = + newFuncs.map(x => x.nme.name -> (x.rhs match { + case Left(trm) => getFreeVars(trm)(using emptyCtx) + .intersect(ctx.addV(newClsNms ++ newFuncNms ++ nmsInTrm -- globFuncs.keySet ++ outer.map(_ => Var("this")))) + .extT(x.targs) + case _ => emptyCtx}) + ).toMap log("captured cls infos: \n" ++ clsInfos.toString()) - val refinedInfo = mixClsInfos(clsInfos, newClsNms) - val newCache = cache ++ refinedInfo - refinedInfo.foreach((_, clsi) => completeClsInfo(clsi)(using newCache)) - -// // transform local functions to global ones -// val seperatedRstTerms = rstTrms.map{ -// case l@Let(isRec, name, rhs, Blk(Nil)) => (Some(NuFunDef(Some(isRec), name, Nil, Left(rhs))), None) -// case other => (None, Some(other)) -// }.unzip -// val letFuncs = seperatedRstTerms._1.flatten -// val nonLetRstTerms = seperatedRstTerms._2.flatten - -// val funcCapVars = (newFuncs ++ letFuncs).flatMap{ -// case NuFunDef(_, nme, _, Left(body)) => Some(nme -> getFreeVars(body)(using emptyCtx, Map(), None).vSet.intersect(ctx.vSet ++ newFuncNms ++ nmsInTrm)) -// case _ => None -// }.toMap -// val mixedFuncCapVs = mixFuncFreeVs(funcCapVars) -// val nFuncSig = (newFuncs ++ letFuncs).flatMap{ -// case NuFunDef(_, nme, _, Left(Lam(x: Tup, _))) => Some(nme -> (Var(genAnoName(nme.name)), mixedFuncCapVs.get(nme).get, x)) -// case NuFunDef(_, nme, _, Left(_)) => Some(nme -> (Var(genAnoName(nme.name)), mixedFuncCapVs.get(nme).get, Tup(Nil))) -// case _ => None -// }.toMap -// // mixedFuncCapVs.map(x => x._1 -> (genAnoName(x._1.name), x._2)) -// (newFuncs ++ letFuncs).foreach{ -// case NuFunDef(isLetRec, nme, targs, Left(Lam(lhs, rhs))) => -// lhs match{ -// case Tup(fields) => -// val nPrm = Tup(nFuncSig.get(nme).get._2.map(toFldsEle) ++ fields) -// val nBody = updateFuncSignatures(rhs)(using nFuncSig) -// val liftedFuncBody = liftTermNew(nBody)(using getFreeVars(nPrm)(using emptyCtx, cache, None), newCache, None) -// globalFunctions.addOne(NuFunDef(isLetRec, nFuncSig.get(nme).get._1, targs, Left(Lam(nPrm, liftedFuncBody._1)))) -// // case v@Var(name) => -// // val nFields = nFuncSig.get(nme).get._2.map(toFldsEle) ++ List(toFldsEle(v)) -// // val nBody = updateFuncSignatures(rhs)(using nFuncSig) -// // val liftedFuncBody = liftTermNew(nBody)(using getFreeVars(nPrm)(using emptyCtx, cache, None), cache, None) -// // globalFunctions.addOne(NuFunDef(isLetRec, nFuncSig.get(nme).get._1, targs, Left(Lam(nPrm, liftedFuncBody._1)))) -// case _ => ??? -// } -// case NuFunDef(isLetRec, nme, targs, Left(term)) => -// val nPrm = Tup(nFuncSig.get(nme).get._2.map(toFldsEle)) -// val nBody = updateFuncSignatures(term)(using nFuncSig) -// val liftedFuncBody = liftTermNew(nBody)(using getFreeVars(nPrm)(using emptyCtx, cache, None), newCache, None) -// globalFunctions.addOne(NuFunDef(isLetRec, nFuncSig.get(nme).get._1, targs, Left(Lam(nPrm, liftedFuncBody._1)))) -// // case _ => ??? -// } - -// newCls.map(updateFuncSigStmt(_)(using nFuncSig)).foreach{case x: NuTypeDef => liftTypeDefNew(x)(using newCache)} - -// // val (liftedFuns, funVs) = newFuncs.map(liftFunc(_)(using ctx.addV(newFuncNms), newCache)).unzip -// val (liftedTerms, termVs) = nonLetRstTerms.map(updateFuncSignatures(_)(using nFuncSig)).map(liftTermNew(_)(using ctx, newCache)).unzip -// (liftedTerms, termVs.fold(emptyCtx)(_ ++ _)) - newCls.foreach(x => liftTypeDefNew(x)(using newCache)) - val (liftedFuns, funVs) = newFuncs.map(liftFunc(_)(using ctx.addV(newFuncNms), newCache)).unzip - val (liftedTerms, termVs) = rstTrms.map(liftTermNew(_)(using ctx.addV(newFuncNms), newCache)).unzip - (liftedFuns ++ liftedTerms, (funVs ++ termVs).fold(emptyCtx)(_ ++ _)) + log("captured func infos: \n" ++ funcInfos.toString()) + val (refinedClsInfo, refinedFuncInfo) = mixClsInfos(clsInfos, funcInfos) + val newCache = cache ++ refinedClsInfo.map(x => (TypeName(x._1) -> x._2)) + refinedClsInfo.foreach((_, clsi) => completeClsInfo(clsi)(using newCache)) + val newGlobalFuncs = refinedFuncInfo.map((nm, vs) => (Var(nm) -> (Var(genAnoName(nm)), vs))) + + newCls.foreach(x => liftTypeDefNew(x)(using newCache, globFuncs ++ newGlobalFuncs)) + (newFuncs zip refinedFuncInfo).foreach((f, c) => liftGlobalFunc(f)(using ctx, newCache, globFuncs ++ newGlobalFuncs)) + val (liftedTerms, termVs) = rstTrms.map(liftTermNew(_)(using ctx.addV(newFuncNms), newCache, globFuncs ++ newGlobalFuncs)).unzip + (liftedTerms, (termVs).fold(emptyCtx)(_ ++ _)) } - private def completeClsInfo(clsInfo: ClassInfoCache)(using cache: ClassCache): Unit = { + private def completeClsInfo(clsInfo: ClassInfoCache)(using cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)]): Unit = { val ClassInfoCache(_, nName, freeVs, flds, inners, _, _, cls, _) = clsInfo val (clsList, _, _) = splitEntities(cls.body.entities) val innerClsNmSet = clsList.map(_.nme).toSet - val innerClsInfos = clsList.map(x => x.nme -> collectClassInfo(x, innerClsNmSet)(using asContextV(freeVs.vSet ++ flds), cache, Some(clsInfo))).toMap - val refinedInfos = mixClsInfos(innerClsInfos, innerClsNmSet.map(x => Var(x.name))) + val innerClsInfos = clsList.map(x => x.nme.name -> collectClassInfo(x, innerClsNmSet)(using asContextV(freeVs.vSet ++ flds), cache, globFuncs, Some(clsInfo))).toMap + val refinedInfos = mixClsInfos(innerClsInfos, Map())._1.map(x => (TypeName(x._1) -> x._2)) refinedInfos.foreach((_, info) => completeClsInfo(info)(using cache ++ refinedInfos)) inners.addAll(refinedInfos) } - private def liftTypeDefNew(target: NuTypeDef)(using cache: ClassCache, outer: Option[ClassInfoCache]): Unit = { + private def liftTypeDefNew(target: NuTypeDef)(using cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): Unit = { def getAllInners(sups: Set[TypeName]): ClassCache = { sups.flatMap( t => cache.get(t).map(x => getAllInners(x.supClses) ++ x.innerClses) @@ -728,10 +686,10 @@ class ClassLifter(logDebugMsg: Boolean = false) { outer.map(x => List(toFldsEle(Var(genParName(x.liftedNm.name))))).getOrElse(Nil) ++ params.fields ++ freeVs.vSet.map(toFldsEle) - val nPars = pars.map(liftTermNew(_)(using emptyCtx, nCache, nOuter)).unzip - val nFuncs = funcList.map(liftFunc(_)(using emptyCtx, nCache, nOuter)).unzip - val nTerms = termList.map(liftTermNew(_)(using emptyCtx, nCache, nOuter)).unzip - clsList.foreach(x => liftTypeDefNew(x)(using nCache, nOuter)) + val nPars = pars.map(liftTermNew(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip + val nFuncs = funcList.map(liftMemberFunc(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip + val nTerms = termList.map(liftTermNew(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip + clsList.foreach(x => liftTypeDefNew(x)(using nCache, globFuncs, nOuter)) retSeq = retSeq.appended(NuTypeDef(kind, nName, nTps, Tup(nParams), nPars._1, TypingUnit(nFuncs._1 ++ nTerms._1))) } @@ -739,16 +697,10 @@ class ClassLifter(logDebugMsg: Boolean = false) { log("=========================\n") log(s"lifting: \n${showStructure(rawUnit)}\n") retSeq = Nil - val (_, newFuncs, rstTrms) = splitEntities(rawUnit.entities) - globalFunctions.addAll(newFuncs) - globalFunctions.addAll(rstTrms.flatMap{ - case Let(isRec, name, rhs, Blk(Nil)) => - Some(NuFunDef(Some(isRec), name, Nil, Left(rhs))) - case _ => None - }) - val re = liftEntitiesNew(rawUnit.entities)(using emptyCtx, Map(), None) + globalFunctions.clear() + val re = liftEntitiesNew(rawUnit.entities)(using emptyCtx, Map(), Map(), None) log(s"freeVars: ${re._2}") // println(logOutput.toString()) - TypingUnit(retSeq.toList ++ re._1) + TypingUnit(retSeq.toList ++ globalFunctions.toList ++ re._1) } } diff --git a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala index 31b4fdece..f62303b3c 100644 --- a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala +++ b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala @@ -172,7 +172,10 @@ object Helpers: toFuncParams(params).toList, // params parents.map { case Var(name) => (TypeName(name), Nil) - case App(Var(name), _) => (TypeName(name), Nil) + case App(Var(name), args) => (TypeName(name), term2Expr(args) match{ + case Expr.Tuple(fields) => fields + case _ => Nil + }) case _ => throw MonomorphError("unsupported parent term") }, // parents isolation // body diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala index cc90afe0f..14303348c 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala @@ -29,7 +29,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: /** * Specialized implementations of function declarations. */ - private val funImpls = MutMap[String, (Item.FuncDecl, MutMap[String, Item.FuncDecl], List[(BoundedExpr, Int)], VariableValue)]() + private val funImpls = MutMap[String, (Item.FuncDecl, MutMap[String, Item.FuncDecl], List[BoundedExpr], VariableValue)]() private def getfunInfo(nm: String): String = val info = funImpls.get(nm).get @@ -76,7 +76,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: val specializer = mono.specializer.Specializer(this)(using debug) def addNewFunction(func: Item.FuncDecl): Unit = { - funImpls.addOne(func.name.name, (func, MutMap(), func.params.map(_ => BoundedExpr()->0), VariableValue.refresh())) + funImpls.addOne(func.name.name, (func, MutMap(), func.params.map(_ => BoundedExpr()), VariableValue.refresh())) funDependence.addOne(func.name.name, Set()) } @@ -126,7 +126,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: debug.log("==============final function signatures==================") funImpls.foreach( (nm, info) => { - debug.log(s"$nm: (${info._3.map(_._1).mkString(" X ")}) -> ${info._4}") + debug.log(s"$nm: (${info._3.mkString(" X ")}) -> ${info._4}") // updateFunc(nm) // debug.log("") } @@ -138,7 +138,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: def updateFunction(crt: String): Unit = { debug.log(s"evaluating $crt, rests: ${evalQueue}") val cnt = evalCnt.get(crt).getOrElse(0) - if(cnt <= 4){ + if(cnt <= 10){ evalCnt.update(crt, cnt+1) debug.log("=" * 10 + s" updating $crt " + "=" * 10) debug.log(getfunInfo(crt)) @@ -166,216 +166,21 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: Some(func2Item(funDef)) }) }(identity) - - /** - * This function flattens a top-level type definition and returns the root - * type definition. There is a simple class lifting here. - */ - // private def monomorphizeTypeDef(tyDef: NuTypeDef): Item.TypeDecl = - // debug.trace("MONO TDEF", PrettyPrinter.show(tyDef)) { - /** - * The recursive function doing the real work. - * @param tyDef the type definition - * @param namePath enclosing class names and this class name - */ - // def rec(tyDef: NuTypeDef, namePath: List[String]): Item.TypeDecl = - // // debug.trace[Item.TypeDecl]("LIFT", PrettyPrinter.show(tyDef)) { - // val NuTypeDef(kind, _, tparams, params, parents, body) = tyDef - // val isolation = Isolation(body.entities.flatMap { - // // Question: Will there be pure terms in class body? - // case term: Term => - // Some(term2Expr(term)) - // case subTypeDef: NuTypeDef => - // rec(subTypeDef, subTypeDef.nme.name :: namePath) - // None - // case subFunDef: NuFunDef => - // Some(monomorphizeFunDef(subFunDef)) - // }) - // val className = namePath.reverseIterator.mkString("_") - // val typeDecl: Item.TypeDecl = Item.TypeDecl( - // className, // name - // kind, // kind - // tparams, // typeParams - // toFuncParams(params).toList, // params - // parents.map { - // case Var(name) => (TypeName(name), Nil) - // case App(Var(name), _) => (TypeName(name), Nil) - // case _ => throw MonomorphError("unsupported parent term") - // }, // parents - // isolation // body - // ) - // addPrototypeTypeDecl(typeDecl) - // typeDecl - // // }() - - // rec(tyDef, tyDef.nme.name :: Nil) - // }(identity) - - /** - * This function monomorphizes a function definition in smoe typing units. - * @param tyDecls the destination of nested type declarations - */ - // private def monomorphizeFunDef(funDef: NuFunDef): Item.FuncDecl | Item.FuncDefn = - // // debug.trace[Item.FuncDecl | Item.FuncDefn]("MONO FUNC", PrettyPrinter.show(funDef)) { - // val NuFunDef(_, nme, targs, rhs) = funDef - // rhs match - // case Left(Lam(params, body)) => - // Item.FuncDecl(nme, toFuncParams(params).toList, term2Expr(body)) - // case Left(body: Term) => Item.FuncDecl(nme, Nil, term2Expr(body)) - // case Right(polyType) => Item.FuncDefn(nme, targs, polyType) - // }(identity) - - /** - * This function monomophizes a `Term` into an `Expr`. - */ - // def monomorphizeTerm(term: Term)(using context: MonomorphContext): Expr = - // debug.trace[Expr]("MONO " + term.getClass.getSimpleName.toUpperCase, PrettyPrinter.show(term)) { - // term match - // case Var(name) => Expr.Ref(name) - // case Lam(lhs, rhs) => monomorphizeLambda(lhs, rhs) - // case App(App(Var("=>"), Bra(false, args: Tup)), body) => - // monomorphizeLambda(args, body) - // case App(App(Var("."), self), App(Var(method), args: Tup)) => - // debug.log(s"meet a member method invocation") - // Expr.Apply(Expr.Select(monomorphizeTerm(self), method), List.from(toFuncArgs(args).map(monomorphizeTerm))) - // case App(lhs, rhs) => - // debug.log("Monomorphizing the callee...") - // val callee = monomorphizeTerm(lhs) - // debug.log("Monomorphizing arguments...") - // val arguments = toFuncArgs(rhs).map(monomorphizeTerm).toList - // debug.log("Specializing the invocation...") - // callee match - // case Expr.Ref(name) => - // specializeCall(name, arguments).fold(Expr.Apply(callee, arguments))(identity) - // case _ => Expr.Apply(callee, arguments) - // case Tup(fields) => - // Expr.Tuple(fields.map { - // case (_, Fld(mut, spec, value)) => monomorphizeTerm(value) - // }) - // case Rcd(fields) => - // Expr.Record(fields.map { - // case (name, Fld(mut, spec, value)) => (name, monomorphizeTerm(value)) - // }) - // case Sel(receiver, fieldName) => - // Expr.Select(monomorphizeTerm(receiver), fieldName) - // case Let(true, Var(name), rhs, body) => - // val exprRhs = monomorphizeTerm(rhs)(using context + (name, DataType.Unknown)) - // val exprBody = monomorphizeTerm(body)(using context + (name, infer(exprRhs, None))) - // Expr.LetIn(true, name, exprRhs, exprBody) - // case Let(false, Var(name), rhs, body) => - // val exprRhs = monomorphizeTerm(rhs) - // val exprBody = monomorphizeTerm(body)(using context + (name, infer(exprRhs, None))) - // Expr.LetIn(false, name, exprRhs, exprBody) - // case Blk(stmts) => Expr.Block(stmts.flatMap[Expr | Item.FuncDecl | Item.FuncDefn] { - // case term: Term => Some(monomorphizeTerm(term)) - // case tyDef: NuTypeDef => - // monomorphizeTypeDef(tyDef) - // None - // case funDef: NuFunDef => Some(monomorphizeFunDef(funDef)) - // case mlscript.DataDefn(_) => throw MonomorphError("unsupported DataDefn") - // case mlscript.DatatypeDefn(_, _) => throw MonomorphError("unsupported DatatypeDefn") - // case mlscript.TypeDef(_, _, _, _, _, _, _) => throw MonomorphError("unsupported TypeDef") - // case mlscript.Def(_, _, _, _) => throw MonomorphError("unsupported Def") - // case mlscript.LetS(_, _, _) => throw MonomorphError("unsupported LetS") - // }) - // case Bra(rcd, term) => monomorphizeTerm(term) - // case Asc(term, ty) => Expr.As(monomorphizeTerm(term), ty) - // case _: Bind => throw MonomorphError("cannot monomorphize `Bind`") - // case _: Test => throw MonomorphError("cannot monomorphize `Test`") - // case With(term, Rcd(fields)) => - // Expr.With(monomorphizeTerm(term), Expr.Record(fields.map { - // case (name, Fld(mut, spec, value)) => (name, monomorphizeTerm(term)) - // })) - // case CaseOf(term, cases) => ??? - // case Subs(array, index) => - // Expr.Subscript(monomorphizeTerm(array), monomorphizeTerm(index)) - // case Assign(lhs, rhs) => - // Expr.Assign(monomorphizeTerm(lhs), monomorphizeTerm(rhs)) - // case New(None, body) => - // val className = s"Anonym_${anonymTyDefs.size}" - // val classDecl = Item.classDecl(className, Nil, monomorphizeBody(body)) - // Expr.Apply(className, Nil) - // case New(Some((constructor, args)), body) => - // val typeName = constructor match - // case AppliedType(TypeName(name), _) => name - // case TypeName(name) => name - // monomorphizeNew(typeName, toFuncArgs(args).toList, body) - // // case Blk(unit) => Expr.Isolated(monomorphizeBody(TypingUnit(unit))) - // case If(body, alternate) => body match - // case IfThen(condition, consequent) => - // Expr.IfThenElse( - // monomorphizeTerm(condition), - // monomorphizeTerm(consequent), - // alternate.map(monomorphizeTerm) - // ) - // case term: IfElse => throw MonomorphError("unsupported IfElse") - // case term: IfLet => throw MonomorphError("unsupported IfLet") - // case term: IfOpApp => throw MonomorphError("unsupported IfOpApp") - // case term: IfOpsApp => throw MonomorphError("unsupported IfOpsApp") - // case term: IfBlock => throw MonomorphError("unsupported IfBlock") - // case IntLit(value) => Expr.Literal(value) - // case DecLit(value) => Expr.Literal(value) - // case StrLit(value) => Expr.Literal(value) - // case UnitLit(undefinedOrNull) => - // Expr.Literal(if undefinedOrNull - // then UnitValue.Undefined - // else UnitValue.Null) - // }(identity) - - // def monomorphizeLambda(args: Term, body: Term): Expr = - // debug.trace("MONO LAMBDA", args.toString + " => " + body) { - // val params = toFuncParams(args).toList - // // TODO: Capture variables referenced in the lambda body. - // // We should capture: closure variables and referenced type variables. - // val className = s"Lambda_${lamTyDefs.size}" - // val applyMethod: Item.FuncDecl = - // Item.FuncDecl("apply", toFuncParams(args).toList, term2Expr(body)(using MonomorphContext.empty)) - // val classBody = Isolation(applyMethod :: Nil) - // val classDecl = Item.classDecl(className, Nil, classBody) - // // Add to the global store. - // lamTyDefs.addOne((className, classDecl)) - // // Returns a class construction. - // Expr.Apply(Expr.Ref(className), Nil) - // }(identity) - - /** - * `new C(...) { ... }` expressions are converted into - * `{ class CImpl extends C(...) { ... }; CImpl() }`. - * ~~This requires you to add a `LetClass` construct to `mlscript.Term`.~~ - */ - // def monomorphizeNew(name: String, termArgs: List[Term], termBody: TypingUnit): Expr.Apply = - // debug.trace[Expr.Apply]("MONO NEW", { - // name + termArgs.iterator.map(_.toString).mkString("(", ", ", ")") + - // " with " + PrettyPrinter.show(termBody) - // }) { - // val args = termArgs.map(term2Expr(_)(using MonomorphContext.empty)) - // val body = monomorphizeBody(termBody) - // val specTypeDecl = specializeTypeDef(name, args, body) - // Expr.Apply(specTypeDecl.name, Nil) - // }(identity) - - // def specializeCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = - // debug.trace("SPEC CALL", name + args.mkString(" with (", ", ", ")")) { - // if tyImpls.contains(name) then specializeClassCall(name, args) - // else if funImpls.contains(name) then specializeFunctionCall(name, args) - // else { - // debug.log(s"Not found: $name") - // None - // } - // }() def monomorphizeCall(name: String, args: List[BoundedExpr])(using evalCtx: Context, callingStack: List[String]): BoundedExpr = { debug.trace[BoundedExpr]("SPEC CALL", name + args.mkString(" with (", ", ", ")")) { if(funImpls.contains(name)){ - val (funcdecl, mps, oldArgsWithCnt, oldVs) = funImpls.get(name).get - val (oldArgs, lastUpdateCnt) = oldArgsWithCnt.unzip + val (funcdecl, mps, oldArgs, oldVs) = funImpls.get(name).get val old = funDependence.get(name).get funDependence.update(name, old ++ callingStack.headOption) // debug.log(s"adding dependence ${callingStack.headOption}") - val nArgs = (oldArgs zip args).map(_ ++ _) - debug.log(s"comparing ${oldArgsWithCnt.mkString("(", ", ", ")")} with ${nArgs.map(_.getDebugOutput).mkString("(", ", ", ")")}") - if(evalCnt.get(name).isEmpty || (oldArgs zip nArgs).find(x => x._1.compare(x._2)).isDefined || (oldArgs zip lastUpdateCnt).find(x => x._1.eleCnt > x._2).isDefined){ - funImpls.update(name, (funcdecl, mps, nArgs.map(x => (x, x.eleCnt)), oldVs)) + val nArgs = (oldArgs zip (args.map(_.unfoldVars))).map(_ ++ _).zip(funcdecl.params).map( + (x,y) => if(y._1) then x else x.literals2Prims + ) + + debug.log(s"comparing ${oldArgs.mkString("(", ", ", ")")} with ${nArgs.map(_.getDebugOutput).mkString("(", ", ", ")")}") + if(evalCnt.get(name).isEmpty || (oldArgs zip nArgs).find(x => x._1.compare(x._2)).isDefined){ + funImpls.update(name, (funcdecl, mps, nArgs, oldVs)) if(!evalQueue.contains(name)){ if(evalCnt.get(name).isEmpty){ debug.log(s"first time encounter $name") @@ -401,7 +206,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: private def updateFunc(name: String): Unit = { val (funcdecl, mps, args, _) = funImpls.get(name).get - val ctx = (funcdecl.params.map(_._2.name) zip args.unzip._1).toMap + val ctx = (funcdecl.params.map(_._2.name) zip args).toMap val nBody = specializer.evaluate(funcdecl.body)(using Context()++ctx, List(funcdecl.name.name)) val nVs = nBody.expValue val oldVs = VariableValue.get(funImpls.get(name).get._4) @@ -412,13 +217,9 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: } funImpls.updateWith(name)(_.map(x => { val nFuncDecl: Item.FuncDecl = x._1.copy(body = nBody) - // debug.log(s"merging ${nVs.hashCode()%1000000} into ${x._4.hashCode()%1000000}") VariableValue.update(x._4, nVs) - // debug.log(s"merged: ${x._4.hashCode()%1000000}") (nFuncDecl, x._2, x._3, x._4) })) - // funImpls.get(name).get._4 += nVs - // funImpls.update(name, funImpls.get(name).get.copy(_4 = nVs)) } def findVar(name: String)(using evalCtx: Context, callingStack: List[String]): MonoValue = { @@ -452,59 +253,29 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: def specializeClassCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = debug.trace("SPEC CALL", "class " + name + args.mkString(" with (", ", ", ")")) { - // import TypeDeclKind._ - // tyImpls.get(name).flatMap { specClassMap => specClassMap.prototype match - // case Item.TypeDecl(Expr.Ref(name), Class, typeParams, params, parents, body) => - // val (staticArguments, dynamicArguments) = partitationArguments(name, params, args) - // val (staticParameters, dynamicParameters) = params.partition(_._1) - // if (staticArguments.isEmpty) { - // None - // } else { - // val signature = generateSignature(staticArguments) - // val specClassDecl = specClassMap.getOrInsert(signature, { - // specClassMap.base = Item.TypeDecl( - // Expr.Ref(name), // name - // Class, // kind - // typeParams, // typeParams - // dynamicParameters, // params - // Nil, // parents - // Isolation.empty // body - // ) - // val values = params.iterator.zip(args).flatMap({ - // case ((true, Expr.Ref(name)), value) => Some((name, value)) - // case ((false, _), _) => None - // }) - // val typeImpl: Item.TypeDecl = Item.TypeDecl( - // Expr.Ref(s"${name}" + signature), // name - // Class, // kind - // typeParams, // typeParams - // dynamicParameters, // params - // (TypeName(name), dynamicParameters.map(_._2)) :: Nil, // parents - // specializeClass(specClassMap.prototype)(using Context(values)) // body - // ) - // allTypeImpls += (typeImpl.name.name -> typeImpl) - // typeImpl - // }) - // Some(Expr.Apply(specClassDecl.name, dynamicArguments)) - // } - // case Item.TypeDecl(_, Trait, _, _, _, _) => - // throw new MonomorphError(s"cannot specialize trait $name") - // case Item.TypeDecl(_, Alias, _, _, _, _) => - // throw new MonomorphError(s"cannot specialize type alias $name") - // } ??? }(_.fold(Debug.noPostTrace)(identity)) - def specializeNew(name: String, args: List[BoundedExpr]): MonoValue = { + def specializeNew(name: String, args: List[BoundedExpr]): MonoValue = + debug.trace("SPEC NEW", s"$name($args)"){ if(allTypeImpls.contains(name)){ val tp = allTypeImpls.get(name).get val ags = (tp.params.map(_._2.name) zip args) - ObjectValue(name, MutMap(ags: _*)) + val ret = ObjectValue(name, MutMap(ags: _*)) + val pars = tp.parents.map((supTp, prms) => { + val evArgs = prms.map(specializer.evaluate(_)(using Context() ++ (("this"->BoundedExpr(ret)) :: ags), List(name)).expValue) + BoundedExpr(specializeNew(supTp.base.name, evArgs)) + }) + val parObjs = pars.zipWithIndex.map((e, i) => s"sup$$$i" -> e) + debug.log(s"par objs: $parObjs") + ret.fields.addAll(parObjs) + ret } else ??? - } + }(identity) - def specializeSelect(obj: ObjectValue, field: String): MonoValue = { + def specializeSelect(obj: ObjectValue, field: String): BoundedExpr = + debug.trace("SPEC SEL", s"$obj :: $field"){ if(allTypeImpls.contains(obj.name)){ val tpDef = allTypeImpls.get(obj.name).get val func = tpDef.body.items.flatMap{ @@ -519,116 +290,36 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: val nFunc: Item.FuncDecl = Item.FuncDecl(Expr.Ref(nFuncName), (false, Expr.Ref("this")) :: prms, bd) addNewFunction(nFunc) } - FunctionValue(nFuncName, prms.map(_._2.name), List("this" -> BoundedExpr(obj))) + BoundedExpr(FunctionValue(nFuncName, prms.map(_._2.name), List("this" -> BoundedExpr(obj)))) } + else if(obj.fields.contains(field)) + obj.fields.get(field).get else{ - ??? + obj.fields.flatMap(x => { + if (x._1.matches("sup\\$[0-9]+")) { + x._2.asValue match{ + case Some(o: ObjectValue) => + Some(specializeSelect(o, field)) + case _ => None + } + } + else None + }).headOption.get//OrElse(BoundedExpr(UnknownValue())) } } else { ??? } - } + }(identity) // TODO: Remove `Option[Expr]` by passing the callee. def specializeFunctionCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = debug.trace("SPEC CALL", "function " + name + args.mkString(" with (", ", ", ")")) { - // funImpls.get(name).flatMap { case (Item.FuncDecl(ref, params, body), impls) => - // val (staticArguments, dynamicArguments) = partitationArguments(name, params, args) - // if (staticArguments.isEmpty) { - // None - // } else { - // val signature = generateSignature(staticArguments) - // val specFuncDecl = impls.get(signature).getOrElse[Item.FuncDecl] { - // val values = params.iterator.zip(args).flatMap({ - // case ((true, Expr.Ref(name)), value) => Some((name, value)) - // case ((false, _), _) => None - // }) - // val specFuncBody = specializeExpr(body)(using Context(values)) - // val staticParams = params.filter(!_._1) - // val specFuncName = s"${name}" + signature - // val funcDecl: Item.FuncDecl = Item.FuncDecl(specFuncName, staticParams, specFuncBody) - // impls.addOne((specFuncName, funcDecl)) - // funcDecl - // } - // Some(Expr.Apply(specFuncDecl.name, dynamicArguments)) - // } - // } ??? }(_.fold(Debug.noPostTrace)(identity)) def specializeExpr(expr: Expr)(using ctx: Context, typeContext: MonomorphContext): Expr = debug.trace[Expr]("SPEC EXPR", expr, "in context", ctx) { - // expr match - // case Expr.Ref(name) => ctx.get(name) match - // case Some(value) => value - // case None => expr - // case _: Expr.Lambda => expr - // case Expr.Apply(Expr.Apply(ident @ Expr.Ref(name), lhsExpr :: Nil), rhsExpr :: Nil) - // if Builtin.isBinaryOperator(name) => - // val lhs = specializeExpr(lhsExpr) - // val rhs = specializeExpr(rhsExpr) - // Builtin.evalulateBinaryOperation(name, lhs, rhs) - // .getOrElse(Expr.Apply(Expr.Apply(ident, lhs :: Nil), rhs :: Nil)) - // case Expr.Apply(callee, arguments) => - // val specCallee = specializeExpr(callee) - // val specArgs = arguments.map(specializeExpr) - // specCallee match - // case Expr.Ref(name) => specializeCall(name, specArgs).getOrElse(expr) - // case Expr.Lambda(params, body) => - // // Same as `specializeFuncDecl` but I should extract some common stuffs. - // ??? - // case Expr.Select(receiver, Expr.Ref(fieldName)) => - // infer(receiver, None) match - // case DataType.Class(declaration) => declaration.body.get(fieldName) match - // case Some(memberFuncDecl: Item.FuncDecl) => - // // FIXME: the context should be from the class - // val specFuncDecl = specializeFunction(memberFuncDecl) - // val branches = ArrayBuffer[CaseBranch]() - // val alias: Expr.Ref = Expr.Ref("alpha") // alpha conversion needed - // branches += CaseBranch.Instance( - // declaration.name, - // alias, - // Expr.Apply(Expr.Select(alias, specFuncDecl.name), specArgs) - // ) - // Expr.Match(receiver, branches) - // case Some(memberFuncDefn: Item.FuncDefn) => - // throw MonomorphError(s"class ${declaration.name.name}.$fieldName is not implemented") - // case None => throw MonomorphError(s"class ${declaration.name.name} does not have $fieldName") - // case other => throw MonomorphError(s"cannot select a non-class instance") - // case other => throw MonomorphError(s"not a callable: $other") - // case Expr.Tuple(elements) => Expr.Tuple(elements.map(specializeExpr)) - // case Expr.Record(fields) => Expr.Record(fields.map { - // case (key, value) => (key, specializeExpr(value)) - // }) - // case Expr.Select(receiver, field) => - // // We can do more. - // Expr.Select(specializeExpr(receiver), field) - // case Expr.LetIn(true, name, Expr.Lambda(params, body), cont) => - // // Create a callable entry in the context and recursively specialize - // // the continuation. - // throw MonomorphError(s"recursive local functions are not implemented") - // case Expr.LetIn(true, _, _, _) => - // throw MonomorphError(s"recursive non-function definition are not allowed") - // case Expr.LetIn(false, Expr.Ref(name), rhs, body) => - // val specRhs = specializeExpr(rhs) - // specializeExpr(body)(using ctx + (name -> specRhs)) - // case Expr.Block(items) => - // val onlyExpressions = items.iterator.flatMap { - // case expr: Expr => Some(expr) - // case _ => None - // } - // onlyExpressions.map(specializeExpr).toList match - // case Nil => Expr.Literal(UnitValue.Undefined) - // case items => items.last - // case expr: Expr.Literal => expr - // case Expr.IfThenElse(condition, consequent, alternate) => - // specializeExpr( - // if specializeExpr(condition).asBoolean() - // then consequent - // else alternate.getOrElse(Expr.Literal(UnitValue.Undefined)) - // ) - // case _ => throw MonomorphError(s"unimplemented ${expr.getClass()}") ??? }(identity) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala index 75757fa36..9f14742db 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala @@ -26,24 +26,6 @@ case class ObjectValue(name: String, fields: MutMap[String, BoundedExpr]) extend }) ObjectValue(name, MutMap(nFlds.toSeq: _*)) } - def mergeMut(other: ObjectValue)(using inStackExps: Set[Int]): Boolean = { - val retVals = other.fields.map[Boolean]((k, s2) => { - val s1 = fields.get(k).get - if(!inStackExps.contains(s1.hashCode()) || !inStackExps.contains(s2.hashCode())){ - if(inStackExps.contains(s1.hashCode())){ - val tmp = BoundedExpr() - tmp += s1 - val ret = tmp += s2 - fields.update(k, tmp) - ret - } - else - s1 += s2 - } - else false - }) - retVals.fold(false)(_ || _) - } override def equals(x: Any): Boolean = { x match { case ObjectValue(xName, _) => name.equals(xName) @@ -70,16 +52,17 @@ object UnknownValue{ unknownCnt } } -case class VariableValue(vx: Int) extends MonoValue{ +case class VariableValue(vx: Int, version: Int) extends MonoValue{ override def toStringSafe(using Set[Int]): String = s"*$vx*=${VariableValue.get(this).toStringSafe}" override def toString(): String = toStringSafe(using Set()) + def refresh() = VariableValue(vx, version+1) } object VariableValue{ var vxCnt = 0 val vMap = MutMap[Int, BoundedExpr]() def refresh(): VariableValue = { vxCnt += 1 - val ret = VariableValue(vxCnt) + val ret = VariableValue(vxCnt, 0) vMap.addOne(vxCnt -> BoundedExpr(ret)) ret } @@ -100,10 +83,9 @@ case class PrimitiveValue() extends MonoValue{ override def toString(): String = "*LIT*" } -class BoundedExpr(private val values: MutSet[MonoValue]) extends Printable { - def this(singleVal: MonoValue) = this(MutSet(singleVal)) - def this() = this(MutSet()) - def this(vs: Set[MonoValue]) = this(MutSet(vs.toSeq: _*)) +class BoundedExpr(private val values: Set[MonoValue]) extends Printable { + def this(singleVal: MonoValue) = this(Set(singleVal)) + def this() = this(Set()) def getDebugOutput: DebugOutput = DebugOutput.Plain(toStringSafe) def getObjNames() = values.flatMap{ // case FunctionValue(name, body, prm, ctx) => Some(name) @@ -115,7 +97,7 @@ class BoundedExpr(private val values: MutSet[MonoValue]) extends Printable { var updateCnt: Int = 0 def toStringSafe(using printed: Set[Int] = Set()): String = { if(printed.contains(this.hashCode())) s"..." - else values.map(_.toStringSafe(using printed + this.hashCode())).mkString("[", " | ", s"]${hashCode()%1000000}") + else values.map(_.toStringSafe(using printed + this.hashCode())).mkString("[", " | ", s"]") } def asValue: Option[MonoValue] = { val tmp = this.unfoldVars @@ -128,7 +110,7 @@ class BoundedExpr(private val values: MutSet[MonoValue]) extends Printable { unfoldVars.values.toSet.filterNot(_.isInstanceOf[VariableValue]) } - private def split(vs: Set[MonoValue], nms: Set[String]): (Set[MonoValue], Map[String, ObjectValue]) = { + private def splitSpecifiedObjects(vs: Set[MonoValue], nms: Set[String]): (Set[MonoValue], Map[String, ObjectValue]) = { val ret = vs.map{ case o@ObjectValue(name, fields) => if nms.contains(name) then { @@ -151,19 +133,18 @@ class BoundedExpr(private val values: MutSet[MonoValue]) extends Printable { val varSets: List[BoundedExpr] = vars._1.flatten.map(x => { val vSet = VariableValue.get(x) if(!instackExps.contains(vSet.hashCode())){ - // val ret = vSet.values.toList.toSet - // println(s"found $x mapsto $ret") - // values -= x - // println(s"found $x mapsto $ret") vSet.unfoldVars(using instackExps + vSet.hashCode()) } else BoundedExpr(x) }) - val ret = BoundedExpr(MutSet(vars._2.flatten.toSeq: _*)) - // if(varSets.size > 0) - // println(s"adding $varSets to $this") - varSets.foreach(x => {ret.mergeWithoutUnfold(x)(using instackExps + x.hashCode())}) - ret + varSets.foldLeft(BoundedExpr(vars._2.flatten.toSet))((x, y) => (x ++ y)(using instackExps + y.hashCode())) + } + + def literals2Prims: BoundedExpr = { + val hasPrim = values.find(x => x.isInstanceOf[PrimitiveValue] || x.isInstanceOf[LiteralValue]).isDefined + if(hasPrim) + BoundedExpr(values.filterNot(x => x.isInstanceOf[PrimitiveValue] || x.isInstanceOf[LiteralValue]) + PrimitiveValue()) + else this } def ++(other: BoundedExpr)(using instackExps: Set[Int] = Set()): BoundedExpr = { @@ -172,8 +153,8 @@ class BoundedExpr(private val values: MutSet[MonoValue]) extends Printable { // unfoldVars // other.unfoldVars val mergingValNms = getObjNames().intersect(other.getObjNames()) - val (restVals1, mergingVals1) = split(values.toSet, mergingValNms) - val (restVals2, mergingVals2) = split(other.values.toSet, mergingValNms) + val (restVals1, mergingVals1) = splitSpecifiedObjects(values.toSet, mergingValNms) + val (restVals2, mergingVals2) = splitSpecifiedObjects(other.values.toSet, mergingValNms) // val map2 = other.values.flatMap(x => if(values.fin(x)) then None else Some(x)) val ret = mergingValNms.map(nm => (mergingVals1.get(nm), mergingVals2.get(nm)) match case (Some(x1: ObjectValue), Some(x2: ObjectValue)) => x1.merge(x2)(using instackExps ++ Set(this.hashCode(), other.hashCode())) @@ -184,91 +165,13 @@ class BoundedExpr(private val values: MutSet[MonoValue]) extends Printable { if(ret2.count(x => (x.isInstanceOf[LiteralValue] || x.isInstanceOf[PrimitiveValue])) > 1){ ret2 = ret2.filterNot(_.isInstanceOf[LiteralValue]) + PrimitiveValue() } - val retVals = BoundedExpr(MutSet((ret2 ++ ret).toSeq: _*)) + val retVals = BoundedExpr(ret2 ++ ret) retVals.updateCnt = this.updateCnt if(this.compare(retVals)) retVals.updateCnt += 1 retVals } } - def mergeWithoutUnfold(other: BoundedExpr)(using instackExps: Set[Int] = Set()): Boolean = { - val retVal = if(other != this) { - // println(s"merging $other into $this") - val mergingValNms = getObjNames().intersect(other.getObjNames()).toSet - val (_, mergingVals) = split(values.toSet, mergingValNms) - var litCount = values.find(x => (x.isInstanceOf[LiteralValue] || x.isInstanceOf[PrimitiveValue])) - val ret = other.values.map{ - case i: (LiteralValue | PrimitiveValue) => - if(litCount.isEmpty) { - values.add(i) - true - } - else if(!litCount.get.isInstanceOf[PrimitiveValue]) { - values.remove(litCount.get) - values.add(PrimitiveValue()) - litCount = Some(PrimitiveValue()) - true - } - else false - case o@ObjectValue(name, fields) => - mergingVals.get(name).fold[Boolean]{ - values.add(o) - true - }(v => { - v.mergeMut(o)(using instackExps ++ Set(this.hashCode(), other.hashCode())) - }) - case other => { - // println(s"adding $other to $this") - values.add(other) - true - } - } - ret.fold(false)(_ || _) - } - else false - if(retVal) updateCnt += 1 - retVal - } - - def +=(other: BoundedExpr)(using instackExps: Set[Int] = Set()): Boolean = { - val retVal = if(other != this) { - // unfoldVars - // other.unfoldVars - val mergingValNms = getObjNames().intersect(other.getObjNames()).toSet - val (_, mergingVals) = split(values.toSet, mergingValNms) - var litCount = values.find(x => (x.isInstanceOf[LiteralValue] || x.isInstanceOf[PrimitiveValue])) - val ret = other.values.map{ - case i: (LiteralValue | PrimitiveValue) => - if(litCount.isEmpty) { - values.add(i) - true - } - else if(!litCount.get.isInstanceOf[PrimitiveValue]) { - values.remove(litCount.get) - values.add(PrimitiveValue()) - litCount = Some(PrimitiveValue()) - true - } - else false - case o@ObjectValue(name, fields) => - mergingVals.get(name).fold[Boolean]{ - values.add(o) - true - }(v => { - v.mergeMut(o)(using instackExps ++ Set(this.hashCode(), other.hashCode())) - }) - case other => { - values.add(other) - true - } - } - ret.fold(false)(_ || _) - } - else false - if(retVal) updateCnt += 1 - retVal - } - def size = values.size // lazy val eleCnt: Int = countEles def eleCnt(using instackExps: Set[Int] = Set()): Int = { @@ -299,8 +202,6 @@ class BoundedExpr(private val values: MutSet[MonoValue]) extends Printable { if(instackExps.contains(this.hashCode()) && instackExps.contains(other.hashCode())) false else { - // this.unfoldVars - // other.unfoldVars if(values.find(_.isInstanceOf[PrimitiveValue]).isEmpty && other.values.find(_.isInstanceOf[PrimitiveValue]).isDefined) true else if(this.size != other.size) @@ -309,8 +210,8 @@ class BoundedExpr(private val values: MutSet[MonoValue]) extends Printable { val nms1 = this.getObjNames() val nms2 = other.getObjNames() if(nms1.equals(nms2)){ - val (rests1, objs1) = split(this.values.toSet, nms1) - val (rests2, objs2) = split(other.values.toSet, nms1) + val (rests1, objs1) = splitSpecifiedObjects(this.values.toSet, nms1) + val (rests2, objs2) = splitSpecifiedObjects(other.values.toSet, nms1) nms1.find(nm => { val v1s = objs1.get(nm).get.fields val v2s = objs2.get(nm).get.fields @@ -320,14 +221,5 @@ class BoundedExpr(private val values: MutSet[MonoValue]) extends Printable { else true } } - // (values.find(_.isInstanceOf[UnknownValue]), other.values.find(_.isInstanceOf[UnknownValue])) match{ - // // case (Some(_), None) => true - // // case (None, Some(_)) => false - // } } -} - -// given Conversion[MutSet[? <: MonoValue], BoundedExpr] with -// def apply(x: MutSet[? <: MonoValue]): BoundedExpr = BoundedExpr(x) -// given Conversion[BoundedExpr, MutSet[? <: MonoValue]] with -// def apply(x: BoundedExpr): MutSet[? <: MonoValue] = x.values \ No newline at end of file +} \ No newline at end of file diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala index f04c1eb15..5d6af253d 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala @@ -13,46 +13,8 @@ import mlscript.compiler.Expr class Specializer(monoer: Monomorph)(using debug: Debug){ - // def evaluateFunction(callee: MonoValue, arguments: List[MonoValue])(using evalCtx: Context, callingStack: List[String], typeCtx: Map[String, Item.TypeDecl], funcCtx: Map[String, Item.FuncDecl]): BoundedExpr = { - // debug.trace[BoundedExpr]("FUNC ", callee.toString() + arguments.mkString("(", ", ", ")")) { - // callee match - // case LiteralValue(s: String) if Builtin.isBinaryOperator(s) && arguments.length == 2 => - // val retValue = Builtin.evaluateBinaryOpValue(s, arguments.head, arguments.tail.head) - // if(retValue.isDefined){ - // BoundedExpr(retValue.get) - // } - // else BoundedExpr(UnknownValue()) - // case FunctionValue(name, body, prm, thisCtx) => - // val argCtx = Context.toCtx(prm.zip(arguments)) - // val ret = evaluate(body)(using evalCtx ++ Context.toCtx(thisCtx) ++ argCtx, name :: callingStack) - // ret._2 - // case _ => BoundedExpr(UnknownValue()) - // }(identity) - // } - - // def evaluateConstructor(tpName: TypeName, arguments: List[MonoValue])(using evalCtx: Context, typeCtx: Map[String, Item.TypeDecl], funcCtx: Map[String, Item.FuncDecl]): BoundedExpr = - // debug.trace[BoundedExpr]("NEW ", tpName.toString() + arguments.mkString("(", ", ", ")")){ - // val Item.TypeDecl(name, kind, typeParams, params, parents, body) = typeCtx.get(tpName.name).get - // val plainPrm = params.map(_._2.name) - // val objValue: ObjectValue = ObjectValue(tpName.name, - // (plainPrm.zip(arguments.map(_.toBoundedExpr)) ++ body.items.flatMap{ - // case f@Item.FuncDecl(nm, prm, bd) => - // Some(nm.name -> funcDecl2Val(f).toBoundedExpr) - // case _ => None - // }).toMap) - // objValue.fields.foreach{ - // case (nm, v: FunctionValue) if !plainPrm.contains(nm) => v.ctx.addOne("this" -> objValue.toBoundedExpr) - // case _ => () - // } - // BoundedExpr(objValue) - // }(identity) - - // def funcDecl2Val(fd: Item.FuncDecl)(using evalCtx: Context): FunctionValue = { - // FunctionValue(fd.name.name, fd.body, fd.params.map(_._2.name), MutMap()) - // } - def evaluate(rawExpr: Expr)(using evalCtx: Context, callingStack: List[String]): Expr = - debug.trace[Expr]("EVAL ", rawExpr.toString()) { + // debug.trace[Expr]("EVAL ", rawExpr.toString()) { rawExpr match{ case Expr.Ref(name) => rawExpr.expValue = @@ -76,22 +38,8 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ retExp } else ??? - - // case Expr.Apply(nm@Expr.Ref(name), arguments) => - // val nArgs = arguments.map(evaluate(_)) - // val args = nArgs.map(_.expValue) - // val retVal = monoer.monomorphizeCall(name, args) - // val retExp = Expr.Apply(nm, nArgs) - // retExp.expValue = retVal - // retExp case other@Expr.Apply(callee, arguments) => - // def rec(x: MonoValue): MonoValue = { - // x match - // case f: FunctionValue => f - // case o: ObjectValue => rec(monoer.specializeSelect(o, "apply")) - // case _ => UnknownValue() - // } val calE = evaluate(callee) val cal = calE.expValue val nArgs = arguments.map(evaluate) @@ -99,23 +47,21 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ val retV = cal.getValue.map{ case FunctionValue(name, prm, ctxArg) => val callResult = monoer.monomorphizeCall(name, ctxArg.unzip._2 ++ args) - debug.log(s"call result: $callResult") + // debug.log(s"call result: $callResult") callResult case o: ObjectValue => val sel = monoer.specializeSelect(o, "apply") - sel match - case FunctionValue(name, prm, ctx) => + sel.asValue match + case Some(FunctionValue(name, prm, ctx)) => val callResult = monoer.monomorphizeCall(name, ctx.unzip._2 ++ args) - debug.log(s"call result: $callResult") + // debug.log(s"call result: $callResult") callResult case _ => BoundedExpr(UnknownValue()) case _ => BoundedExpr(UnknownValue()) }.fold(BoundedExpr())((x, y) => { - x.unfoldVars - y.unfoldVars - debug.log(s"merging $x with $y") + // debug.log(s"merging $x with $y") val xy = x ++ y - debug.log(s"result $xy") + // debug.log(s"result $xy") xy }) val retExp = Expr.Apply(calE, nArgs) @@ -128,7 +74,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ case ObjectValue(_, flds) if flds.contains(field.name) => flds.get(field.name).get case obj: ObjectValue => - BoundedExpr(monoer.specializeSelect(obj, field.name)) + monoer.specializeSelect(obj, field.name) case _ => BoundedExpr(UnknownValue()) }.fold(BoundedExpr())(_ ++ _) @@ -221,7 +167,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ case Expr.Subscript(receiver, index) => ??? case Expr.Match(scrutinee, branches) => ??? } - }(_.expValue) + // }(_.expValue) def defunctionalize(rawExpr: Expr): Expr = { val ret: Expr = rawExpr match { @@ -231,8 +177,28 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ val nArgs = args.map(defunctionalize) val branches = ArrayBuffer[CaseBranch]() receiver.expValue.getValue.foreach{ - case ObjectValue(name, _) => - branches.addOne(CaseBranch.Instance(Expr.Ref(name), Expr.Ref("obj"), Expr.Apply(Expr.Ref(s"$field$$$name"), Expr.Ref("obj") :: nArgs))) + case o@ObjectValue(name, _) => + val selValue = monoer.specializeSelect(o, field.name) + val branchExp = selValue.asValue match{ + // foo.f is a member function + case Some(f: FunctionValue) => + Expr.Apply(Expr.Ref(f.name), Expr.Ref("obj") :: nArgs) + // foo.f is (many candidate) lambda(Object) + case _ if selValue.getValue.forall(_.isInstanceOf[ObjectValue]) => + // foo.f match ... + val scrut = Expr.Select(Expr.Ref("obj"), field) + val brchs = selValue.getValue.toList.map(_.asInstanceOf[ObjectValue]) + .map(o => { + val lambdaMemFunc = monoer.specializeSelect(o, "apply").asValue.get.asInstanceOf[FunctionValue] + val caseVarNm: Expr.Ref = Expr.Ref(s"obj$$${o.name}") + CaseBranch.Instance(Expr.Ref(o.name), caseVarNm, + Expr.Apply(Expr.Ref(lambdaMemFunc.name), caseVarNm :: nArgs)) + }) + Expr.Match(scrut, ArrayBuffer(brchs: _*)) + case _ => ??? + + } + branches.addOne(CaseBranch.Instance(Expr.Ref(name), Expr.Ref("obj"), branchExp)) case _ => () } Expr.Match(nRec, branches) @@ -255,30 +221,4 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ ret.expValue = rawExpr.expValue ret } - // def updateResult(rawExpr: Expr)(using evalCtx: Context, callingStack: List[String], diff: Map[String, BoundedExpr]): Option[BoundedExpr] = { - // if(rawExpr.freeVars.intersect(diff.keySet).isEmpty){ - // None - // } - // else { - // rawExpr match - // case Expr.Ref(name) => diff.get(name) - // case Expr.Apply(callee, arguments) => - - // case Expr.Tuple(fields) => - // case Expr.Record(fields) => - // case Expr.Select(receiver, field) => - // case Expr.LetIn(isRec, name, rhs, body) => - // case Expr.Block(items) => - // case Expr.As(value, toType) => - // case Expr.Assign(assignee, value) => - // case Expr.With(value, fields) => - // case Expr.Subscript(receiver, index) => - // case Expr.Match(scrutinee, branches) => - // case Expr.Literal(value) => - // case Expr.New(typeName, args) => - // case Expr.IfThenElse(condition, consequent, alternate) => - // case Expr.Isolated(isolation) => - // case Expr.Lambda(params, body) => ??? - // } - // } } diff --git a/compiler/shared/test/diff/LambLift.mls b/compiler/shared/test/diff/LambLift.mls index 7ad648f7c..88e8f8eed 100644 --- a/compiler/shared/test/diff/LambLift.mls +++ b/compiler/shared/test/diff/LambLift.mls @@ -15,9 +15,10 @@ foo() //│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(), Blk(...))), App(Var(foo), Tup())) //│ Lifted: //│ TypingUnit { -//│ class Foo$1(x,) {fun bar = + ((this).x,) (foo ((this).x,),)} -//│ fun foo = => {fun local = x, => {(Foo$1 (x,)).bar}; local (1,)} -//│ Code(List(foo ())) +//│ class Foo$1(x,) {fun bar = => + ((this).x,) (foo$1 ((this).x,),)} +//│ fun local$2 = x, => {(Foo$1 (x,)).bar} +//│ fun foo$1 = => {local$2 (1,)} +//│ Code(List(foo$1 ())) //│ } fun foo(f) = @@ -29,9 +30,9 @@ foo(x => x+1) //│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(f)), Blk(...))), App(Var(foo), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1))))))) //│ Lifted: //│ TypingUnit { -//│ class Lambda1$1$1() {fun apply = x, => + (x,) (1,)} -//│ fun foo = f, => {f (1,)} -//│ Code(List(foo ({new Lambda1$1$1() {}},))) +//│ class Lambda1$2$1() {fun apply = x, => + (x,) (1,)} +//│ fun foo$1 = f, => {f (1,)} +//│ Code(List(foo$1 ({new Lambda1$2$1() {}},))) //│ } fun foo(x) = @@ -45,9 +46,10 @@ foo(1) //│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: IntLit(1)))) //│ Lifted: //│ TypingUnit { -//│ class Lambda1$1$1(x,) {fun apply = y, => + (y,) ((this).x,)} -//│ fun foo = x, => {fun bar = f, => {f (x,)}; bar ({new Lambda1$1$1(x,) {}},)} -//│ Code(List(foo (1,))) +//│ class Lambda1$3$1(x,) {fun apply = y, => + (y,) ((this).x,)} +//│ fun bar$2 = f, x, => {f (x,)} +//│ fun foo$1 = x, => {bar$2 ({new Lambda1$3$1(x,) {}}, x,)} +//│ Code(List(foo$1 (1,))) //│ } fun foo(f) = @@ -65,8 +67,8 @@ app(new A(1)) //│ Lifted: //│ TypingUnit { //│ class A$1(y,) {fun bar = z, => + ((this).y,) (z,)} -//│ class Lambda1$1$2(a,) {fun apply = z, => ((this).a).bar (z,)} -//│ fun foo = f, => {f (1,)} -//│ fun app = a, => {foo ({new Lambda1$1$2(a,) {}},)} -//│ Code(List(app (new A$1(1,) {},))) +//│ class Lambda1$3$2(a,) {fun apply = z, => ((this).a).bar (z,)} +//│ fun foo$2 = f, => {f (1,)} +//│ fun app$1 = a, => {foo$2 ({new Lambda1$3$2(a,) {}},)} +//│ Code(List(app$1 (new A$1(1,) {},))) //│ } diff --git a/compiler/shared/test/diff/LiftType.mls b/compiler/shared/test/diff/LiftType.mls index 6a0e5b554..5b779574e 100644 --- a/compiler/shared/test/diff/LiftType.mls +++ b/compiler/shared/test/diff/LiftType.mls @@ -28,8 +28,8 @@ class CTX(x, y){ //│ TypingUnit(NuTypeDef(class, CTX, (), Tup(_: Var(x), _: Var(y)), (), TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], Var(x)))), NuTypeDef(class, B, (), Tup(), (Var(A)), TypingUnit(NuFunDef(None, foo, [], Var(y)))), NuFunDef(None, foo, [], Lam(Tup(any: Bra(rcd = false, Tup(_: Var(A), _: Var(B)))), Asc(Bra(rcd = false, Tup(_: Sel(Var(any), _2), _: Sel(Var(any), _1))), Tuple(List((None,Field(None,TypeName(B))), (None,Field(None,TypeName(A))))))))))) //│ Lifted: //│ TypingUnit { -//│ class CTX$1_A$2(par$CTX$1,) {fun foo = ((this).par$CTX$1).x} -//│ class CTX$1_B$3(par$CTX$1,): CTX$1_A$2 ((this).par$CTX$1,) {fun foo = ((this).par$CTX$1).y} +//│ class CTX$1_A$2(par$CTX$1,) {fun foo = => ((this).par$CTX$1).x} +//│ class CTX$1_B$3(par$CTX$1,): CTX$1_A$2 ((this).par$CTX$1,) {fun foo = => ((this).par$CTX$1).y} //│ class CTX$1(x, y,) { //│ fun foo = any: '(' CTX$1_A$2, CTX$1_B$3, ')', => '(' (any)._2, (any)._1, ')' : Tuple(List((None,Field(None,TypeName(CTX$1_B$3))), (None,Field(None,TypeName(CTX$1_A$2))))) //│ } @@ -46,8 +46,8 @@ class CTX(x, y){ //│ TypingUnit(NuTypeDef(class, CTX, (), Tup(_: Var(x), _: Var(y)), (), TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], Var(x)))), NuTypeDef(class, B, (), Tup(), (Var(A)), TypingUnit(NuFunDef(None, foo, [], Var(y)))), NuFunDef(None, foo, [], Lam(Tup(any: Bra(rcd = true, Rcd(Var(p1) = Var(A), Var(p2) = Var(B)))), Asc(Bra(rcd = false, Tup(_: Sel(Var(any), p2), _: Sel(Var(any), p1))), Tuple(List((None,Field(None,TypeName(B))), (None,Field(None,TypeName(A))))))))))) //│ Lifted: //│ TypingUnit { -//│ class CTX$1_A$2(par$CTX$1,) {fun foo = ((this).par$CTX$1).x} -//│ class CTX$1_B$3(par$CTX$1,): CTX$1_A$2 ((this).par$CTX$1,) {fun foo = ((this).par$CTX$1).y} +//│ class CTX$1_A$2(par$CTX$1,) {fun foo = => ((this).par$CTX$1).x} +//│ class CTX$1_B$3(par$CTX$1,): CTX$1_A$2 ((this).par$CTX$1,) {fun foo = => ((this).par$CTX$1).y} //│ class CTX$1(x, y,) { //│ fun foo = any: '{' {p1: CTX$1_A$2, p2: CTX$1_B$3} '}', => '(' (any).p2, (any).p1, ')' : Tuple(List((None,Field(None,TypeName(CTX$1_B$3))), (None,Field(None,TypeName(CTX$1_A$2))))) //│ } @@ -64,8 +64,8 @@ class CTX(x, y){ //│ TypingUnit(NuTypeDef(class, CTX, (), Tup(_: Var(x), _: Var(y)), (), TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], Var(x)))), NuTypeDef(class, B, (TypeName(T)), Tup(), (), TypingUnit(NuFunDef(None, foo, [], Var(y)))), NuFunDef(None, foo, [], Lam(Tup(any: Bra(rcd = false, Tup(_: Var(A), _: TyApp(Var(B), List(TypeName(A)))))), Asc(Bra(rcd = false, Tup(_: Var(any), _: Sel(Var(any), _1))), Tuple(List((None,Field(None,Tuple(List((None,Field(None,AppliedType(TypeName(B),List(TypeName(A))))), (None,Field(None,TypeName(A))))))), (None,Field(None,TypeName(A))))))))))) //│ Lifted: //│ TypingUnit { -//│ class CTX$1_A$2(par$CTX$1,) {fun foo = ((this).par$CTX$1).x} -//│ class CTX$1_B$3[T](par$CTX$1,) {fun foo = ((this).par$CTX$1).y} +//│ class CTX$1_A$2(par$CTX$1,) {fun foo = => ((this).par$CTX$1).x} +//│ class CTX$1_B$3[T](par$CTX$1,) {fun foo = => ((this).par$CTX$1).y} //│ class CTX$1(x, y,) { //│ fun foo = any: '(' CTX$1_A$2, CTX$1_B$3‹CTX$1_A$2›, ')', => '(' any, (any)._1, ')' : Tuple(List((None,Field(None,Tuple(List((None,Field(None,AppliedType(TypeName(CTX$1_B$3),List(TypeName(CTX$1_A$2))))), (None,Field(None,TypeName(CTX$1_A$2))))))), (None,Field(None,TypeName(CTX$1_A$2))))) //│ } diff --git a/compiler/shared/test/diff/Lifter.mls b/compiler/shared/test/diff/Lifter.mls index aef043e7e..45114e64e 100644 --- a/compiler/shared/test/diff/Lifter.mls +++ b/compiler/shared/test/diff/Lifter.mls @@ -31,29 +31,29 @@ class A(x) { //│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuTypeDef(class, B, (), Tup(_: Var(y)), (), TypingUnit(NuFunDef(None, getX, [], Var(x)), NuFunDef(None, getB1, [], App(Var(B1), Tup(_: Var(y)))), NuTypeDef(class, C, (), Tup(_: Var(z)), (), TypingUnit(NuFunDef(None, inc, [], Lam(Tup(), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1))))), NuFunDef(None, getY, [], Var(y)), NuFunDef(None, getA, [], App(Var(A), Tup(_: Var(z)))), NuFunDef(None, getB, [], Lam(Tup(_: Var(w)), App(Var(B), Tup(_: Var(w))))), NuFunDef(None, getC, [], New(Some((TypeName(C),inc (),)), TypingUnit(List()))), NuFunDef(None, getSelf, [], Var(this)))))), NuTypeDef(class, B1, (), Tup(_: Var(y)), (), TypingUnit(NuFunDef(None, getX, [], Var(x)), NuFunDef(None, getY, [], Var(y)), NuFunDef(None, getB, [], New(Some((TypeName(B),y,)), TypingUnit(List()))), NuFunDef(None, getB1, [], New(Some((TypeName(B1),y,)), TypingUnit(List()))))), NuFunDef(None, getB, [], New(Some((TypeName(B),x,)), TypingUnit(List()))), NuFunDef(None, getB2, [], Lam(Tup(_: Var(y)), App(Var(B1), Tup(_: Var(y))))), NuFunDef(None, getB3, [], Lam(Tup(_: Var(z)), App(Var(getB2), Tup(_: Var(z))))), NuFunDef(None, getA, [], App(Var(A), Tup(_: Var(x))))))) //│ Lifted: //│ TypingUnit { -//│ class A$1_B$2_C$4(par$A$1_B$2, z,) { -//│ fun inc = => + ((((this).par$A$1_B$2).par$A$1).x,) (1,) -//│ fun getY = ((this).par$A$1_B$2).y -//│ fun getA = A$1 ((this).z,) +//│ class A$1_B$2_C$4(par$A$1_B$2, z, x,) { +//│ fun inc = => + ((this).x,) (1,) +//│ fun getY = => ((this).par$A$1_B$2).y +//│ fun getA = => A$1 ((this).z,) //│ fun getB = w, => A$1_B$2 (((this).par$A$1_B$2).par$A$1, w,) -//│ fun getC = new A$1_B$2_C$4((this).par$A$1_B$2, (this).inc (),) {} -//│ fun getSelf = this +//│ fun getC = => new A$1_B$2_C$4((this).par$A$1_B$2, (this).inc (), (this).x,) {} +//│ fun getSelf = => this //│ } //│ class A$1_B$2(par$A$1, y,) { -//│ fun getX = ((this).par$A$1).x -//│ fun getB1 = A$1_B1$3 ((this).par$A$1, (this).y,) +//│ fun getX = => ((this).par$A$1).x +//│ fun getB1 = => A$1_B1$3 ((this).par$A$1, (this).y,) //│ } //│ class A$1_B1$3(par$A$1, y,) { -//│ fun getX = ((this).par$A$1).x -//│ fun getY = (this).y -//│ fun getB = new A$1_B$2((this).par$A$1, (this).y,) {} -//│ fun getB1 = new A$1_B1$3((this).par$A$1, (this).y,) {} +//│ fun getX = => ((this).par$A$1).x +//│ fun getY = => (this).y +//│ fun getB = => new A$1_B$2((this).par$A$1, (this).y,) {} +//│ fun getB1 = => new A$1_B1$3((this).par$A$1, (this).y,) {} //│ } //│ class A$1(x,) { -//│ fun getB = new A$1_B$2(this, (this).x,) {} +//│ fun getB = => new A$1_B$2(this, (this).x,) {} //│ fun getB2 = y, => A$1_B1$3 (this, y,) //│ fun getB3 = z, => (this).getB2 (z,) -//│ fun getA = A$1 ((this).x,) +//│ fun getA = => A$1 ((this).x,) //│ } //│ } @@ -70,8 +70,8 @@ class A(x) { //│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuTypeDef(class, B, (), Tup(_: Var(y)), (), TypingUnit(NuTypeDef(class, C, (), Tup(_: Var(z)), (), TypingUnit(NuFunDef(None, sum, [], App(App(Var(+), Tup(_: App(App(Var(+), Tup(_: Var(x))), Tup(_: Var(y))))), Tup(_: Var(z))))))))))) //│ Lifted: //│ TypingUnit { -//│ class A$1_B$2_C$3(par$A$1_B$2, z,) { -//│ fun sum = + (+ ((((this).par$A$1_B$2).par$A$1).x,) (((this).par$A$1_B$2).y,),) ((this).z,) +//│ class A$1_B$2_C$3(par$A$1_B$2, z, x,) { +//│ fun sum = => + (+ ((this).x,) (((this).par$A$1_B$2).y,),) ((this).z,) //│ } //│ class A$1_B$2(par$A$1, y,) {} //│ class A$1(x,) {} @@ -109,13 +109,22 @@ new C{ //│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], IntLit(1)), NuFunDef(None, bar, [], IntLit(11)))), NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(List(fun foo = 2, fun bar = 12)))), NuFunDef(None, bar, [], IntLit(13)))), NuTypeDef(class, C, (), Tup(), (Var(A)), TypingUnit(NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(List(fun foo = 3, fun bar = 14)))), NuFunDef(None, bar, [], IntLit(15)))), New(Some((TypeName(C),)), TypingUnit(List(fun getB = new B() {fun foo = 4; fun bar = 16}, fun bar = 17)))) //│ Lifted: //│ TypingUnit { -//│ class A$1_B$1$4(par$A$1,): A$1_B$3 ((this).par$A$1,) {fun foo = 2; fun bar = 12} -//│ class A$1_B$3(par$A$1,) {fun foo = 1; fun bar = 11} -//│ class A$1(x,) {fun getB = {new A$1_B$1$4(this,) {}}; fun bar = 13} -//│ class C$2_B$2$5(par$C$2,): A$1_B$3 ((this).par$C$2,) {fun foo = 3; fun bar = 14} -//│ class C$2(): A$1 () {fun getB = {new C$2_B$2$5(this,) {}}; fun bar = 15} -//│ class C$3$6_B$4$7(par$C$3$6,): A$1_B$3 ((this).par$C$3$6,) {fun foo = 4; fun bar = 16} -//│ class C$3$6(): C$2 () {fun getB = {new C$3$6_B$4$7(this,) {}}; fun bar = 17} +//│ class A$1_B$1$4(par$A$1,): A$1_B$3 ((this).par$A$1,) {fun foo = => 2; fun bar = => 12} +//│ class A$1_B$3(par$A$1,) {fun foo = => 1; fun bar = => 11} +//│ class A$1(x,) { +//│ fun getB = => {new A$1_B$1$4(this,) {}} +//│ fun bar = => 13 +//│ } +//│ class C$2_B$2$5(par$C$2,): A$1_B$3 ((this).par$C$2,) {fun foo = => 3; fun bar = => 14} +//│ class C$2(): A$1 () { +//│ fun getB = => {new C$2_B$2$5(this,) {}} +//│ fun bar = => 15 +//│ } +//│ class C$3$6_B$4$7(par$C$3$6,): A$1_B$3 ((this).par$C$3$6,) {fun foo = => 4; fun bar = => 16} +//│ class C$3$6(): C$2 () { +//│ fun getB = => {new C$3$6_B$4$7(this,) {}} +//│ fun bar = => 17 +//│ } //│ Code(List({new C$3$6() {}})) //│ } @@ -159,7 +168,7 @@ class A(x: Int): {a1: Int} & B & D(x){ //│ class B$1[T]() {} //│ class C$2() {} //│ class D$3(y: Int,) {} -//│ class A$4_C$1$5[T](par$A$4,): C$2 () {fun foo = x: T, => x} +//│ class A$4_C$1$5(par$A$4,): C$2 () {fun foo = x: T, => x} //│ class A$4[T,U](x: Int,): & ('{' {a1: Int} '}',) (& (B$1 ()‹T›,) (D$3 ((this).x,),),) {fun getA = => {new A$4_C$1$5(this,) {}}} //│ } // │ TypingUnit(NuTypeDef(class, B, (TypeName(T)), Tup(), (), TypingUnit()), NuTypeDef(class, C, (), Tup(), (), TypingUnit()), NuTypeDef(class, A, (TypeName(T), TypeName(U)), Tup(x: Var(Int)), (App(App(Var(&), Tup(_: Bra(rcd = true, Rcd(Var(a1) = Var(Int)})))), Tup(_: TyApp(Var(B), List(TypeName(T)))))), TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = x: T, => x)))))))) @@ -198,10 +207,10 @@ class Child(x): { age: T } & { name: String} { //│ TypingUnit(NuTypeDef(class, Child, (TypeName(T), TypeName(U)), Tup(_: Var(x)), (App(App(Var(&), Tup(_: Bra(rcd = true, Rcd(Var(age) = Var(T))))), Tup(_: Bra(rcd = true, Rcd(Var(name) = Var(String)))))), TypingUnit(NuTypeDef(class, Inner, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], Var(age)))), NuFunDef(None, bar, [], Var(age)), NuFunDef(None, boo, [], New(Some((TypeName(Inner),)), TypingUnit(List())))))) //│ Lifted: //│ TypingUnit { -//│ class Child$1_Inner$2(par$Child$1,) {fun foo = ((this).par$Child$1).age} +//│ class Child$1_Inner$2(par$Child$1,) {fun foo = => ((this).par$Child$1).age} //│ class Child$1[T,U](x,): & ('{' {age: T} '}',) ('{' {name: String} '}',) { -//│ fun bar = (this).age -//│ fun boo = new Child$1_Inner$2(this,) {} +//│ fun bar = => (this).age +//│ fun boo = => new Child$1_Inner$2(this,) {} //│ } //│ } @@ -220,8 +229,8 @@ new A(0) { //│ TypingUnit(NuTypeDef(class, A, (), Tup(x: Var(Int)), (), TypingUnit(NuFunDef(None, getA, [], Asc(IntLit(0), TypeName(Int))), NuFunDef(None, getA1, [], IntLit(1)))), New(Some((TypeName(A),0,)), TypingUnit(List(fun getA = 3, fun getA2 = 2)))) //│ Lifted: //│ TypingUnit { -//│ class A$1(x: Int,) {fun getA = 0 : TypeName(Int); fun getA1 = 1} -//│ class A$1$2(x: Int,): A$1 ((this).x,) {fun getA = 3; fun getA2 = 2} +//│ class A$1(x: Int,) {fun getA = => 0 : TypeName(Int); fun getA1 = => 1} +//│ class A$1$2(x: Int,): A$1 ((this).x,) {fun getA = => 3; fun getA2 = => 2} //│ Code(List({new A$1$2(0,) {}})) //│ } @@ -242,8 +251,8 @@ new A(1) { //│ TypingUnit { //│ class A$1_B$2(par$A$1, y,) {} //│ class A$1(x,) {} -//│ class A$1$3_B$2$4(par$A$1$3, y,): A$1_B$2 ((this).par$A$1$3, (this).y,) {fun getB = new A$1_B$2((this).par$A$1$3, 3,) {}} -//│ class A$1$3(x,): A$1 ((this).x,) {fun getB = {new A$1$3_B$2$4(this, 2,) {}}} +//│ class A$1$3_B$2$4(par$A$1$3, y,): A$1_B$2 ((this).par$A$1$3, (this).y,) {fun getB = => new A$1_B$2((this).par$A$1$3, 3,) {}} +//│ class A$1$3(x,): A$1 ((this).x,) {fun getB = => {new A$1$3_B$2$4(this, 2,) {}}} //│ Code(List({new A$1$3(1,) {}})) //│ } @@ -272,15 +281,15 @@ new B{ //│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuFunDef(None, getA, [], IntLit(0)), NuFunDef(None, funcA, [], IntLit(10)))), NuTypeDef(class, B, (), Tup(), (Var(A)), TypingUnit(NuFunDef(None, getA, [], IntLit(1)), NuFunDef(None, funcB, [], IntLit(11)))), New(Some((TypeName(A),)), TypingUnit(List())), New(Some((TypeName(B),)), TypingUnit(List())), NuFunDef(None, f, [], Lam(Tup(_: Var(x)), If((is (x,) (A,)) then 0, Some(IntLit(1))))), App(Var(f), Tup(_: New(Some((TypeName(A),)), TypingUnit(List(fun getA = 2))))), New(Some((TypeName(B),)), TypingUnit(List(fun getA = funcB)))) //│ Lifted: //│ TypingUnit { -//│ class A$1() {fun getA = 0; fun funcA = 10} -//│ class B$2(): A$1 () {fun getA = 1; fun funcB = 11} -//│ class A$1$3(): A$1 () {fun getA = 2} -//│ class B$2$4(): B$2 () {fun getA = (this).funcB} -//│ fun f = x, => if (is (x,) (A$1 (),)) then 0 else 1 +//│ class A$1() {fun getA = => 0; fun funcA = => 10} +//│ class B$2(): A$1 () {fun getA = => 1; fun funcB = => 11} +//│ class A$2$3(): A$1 () {fun getA = => 2} +//│ class B$3$4(): B$2 () {fun getA = => (this).funcB} +//│ fun f$1 = x, => if (is (x,) (A$1 (),)) then 0 else 1 //│ Code(List(new A$1() {})) //│ Code(List(new B$2() {})) -//│ Code(List(f ({new A$1$3() {}},))) -//│ Code(List({new B$2$4() {}})) +//│ Code(List(f$1 ({new A$2$3() {}},))) +//│ Code(List({new B$3$4() {}})) //│ } @@ -312,11 +321,11 @@ class A{ //│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, funB, [], IntLit(1)), NuFunDef(None, foo, [], IntLit(100)))), NuTypeDef(class, C, (), Tup(), (Var(B)), TypingUnit(NuFunDef(None, funC, [], IntLit(2)), NuFunDef(None, foo, [], IntLit(1000)))), NuTypeDef(class, D, (), Tup(), (), TypingUnit(NuFunDef(None, funD, [], IntLit(3)), NuFunDef(None, foo, [], IntLit(10000)), NuTypeDef(class, E, (), Tup(), (Var(C)), TypingUnit(NuFunDef(None, funE, [], IntLit(4)), NuFunDef(None, foo, [], IntLit(100000)))), NuTypeDef(class, F, (), Tup(), (Var(E)), TypingUnit(NuFunDef(None, funF, [], IntLit(5)), NuFunDef(None, foo, [], IntLit(1000000))))))))) //│ Lifted: //│ TypingUnit { -//│ class A$1_B$2(par$A$1,) {fun funB = 1; fun foo = 100} -//│ class A$1_C$3(par$A$1,): A$1_B$2 ((this).par$A$1,) {fun funC = 2; fun foo = 1000} -//│ class A$1_D$4_E$5(par$A$1_D$4,): A$1_C$3 (((this).par$A$1_D$4).par$A$1,) {fun funE = 4; fun foo = 100000} -//│ class A$1_D$4_F$6(par$A$1_D$4,): A$1_D$4_E$5 ((this).par$A$1_D$4,) {fun funF = 5; fun foo = 1000000} -//│ class A$1_D$4(par$A$1,) {fun funD = 3; fun foo = 10000} +//│ class A$1_B$2(par$A$1,) {fun funB = => 1; fun foo = => 100} +//│ class A$1_C$3(par$A$1,): A$1_B$2 ((this).par$A$1,) {fun funC = => 2; fun foo = => 1000} +//│ class A$1_D$4_E$5(par$A$1_D$4,): A$1_C$3 (((this).par$A$1_D$4).par$A$1,) {fun funE = => 4; fun foo = => 100000} +//│ class A$1_D$4_F$6(par$A$1_D$4,): A$1_D$4_E$5 ((this).par$A$1_D$4,) {fun funF = => 5; fun foo = => 1000000} +//│ class A$1_D$4(par$A$1,) {fun funD = => 3; fun foo = => 10000} //│ class A$1() {} //│ } @@ -354,24 +363,24 @@ class A{ //│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, funB, [], IntLit(1)), NuFunDef(None, foo, [], IntLit(100)))), NuTypeDef(class, C, (), Tup(), (Var(B)), TypingUnit(NuFunDef(None, funC, [], IntLit(2)), NuFunDef(None, foo, [], IntLit(1000)), NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(List()))))), NuTypeDef(class, D, (), Tup(), (), TypingUnit(NuFunDef(None, funD, [], IntLit(3)), NuFunDef(None, foo, [], IntLit(10000)), NuTypeDef(class, E, (), Tup(), (Var(C)), TypingUnit(NuFunDef(None, funE, [], IntLit(4)), NuFunDef(None, foo, [], IntLit(100000)), NuFunDef(None, getD, [], New(Some((TypeName(D),)), TypingUnit(List()))))), NuTypeDef(class, F, (), Tup(), (Var(E)), TypingUnit(NuFunDef(None, funF, [], IntLit(5)), NuFunDef(None, foo, [], IntLit(1000000)), NuFunDef(None, getE, [], New(Some((TypeName(E),)), TypingUnit(List(fun foo = 0))))))))))) //│ Lifted: //│ TypingUnit { -//│ class A$1_B$2(par$A$1,) {fun funB = 1; fun foo = 100} +//│ class A$1_B$2(par$A$1,) {fun funB = => 1; fun foo = => 100} //│ class A$1_C$3(par$A$1,): A$1_B$2 ((this).par$A$1,) { -//│ fun funC = 2 -//│ fun foo = 1000 -//│ fun getB = new A$1_B$2((this).par$A$1,) {} +//│ fun funC = => 2 +//│ fun foo = => 1000 +//│ fun getB = => new A$1_B$2((this).par$A$1,) {} //│ } //│ class A$1_D$4_E$5(par$A$1_D$4,): A$1_C$3 (((this).par$A$1_D$4).par$A$1,) { -//│ fun funE = 4 -//│ fun foo = 100000 -//│ fun getD = new A$1_D$4(((this).par$A$1_D$4).par$A$1,) {} +//│ fun funE = => 4 +//│ fun foo = => 100000 +//│ fun getD = => new A$1_D$4(((this).par$A$1_D$4).par$A$1,) {} //│ } -//│ class A$1_D$4_F$6_E$1$7(par$A$1_D$4_F$6,): A$1_D$4_E$5 (((this).par$A$1_D$4_F$6).par$A$1_D$4,) {fun foo = 0} +//│ class A$1_D$4_F$6_E$1$7(par$A$1_D$4_F$6,): A$1_D$4_E$5 (((this).par$A$1_D$4_F$6).par$A$1_D$4,) {fun foo = => 0} //│ class A$1_D$4_F$6(par$A$1_D$4,): A$1_D$4_E$5 ((this).par$A$1_D$4,) { -//│ fun funF = 5 -//│ fun foo = 1000000 -//│ fun getE = {new A$1_D$4_F$6_E$1$7(this,) {}} +//│ fun funF = => 5 +//│ fun foo = => 1000000 +//│ fun getE = => {new A$1_D$4_F$6_E$1$7(this,) {}} //│ } -//│ class A$1_D$4(par$A$1,) {fun funD = 3; fun foo = 10000} +//│ class A$1_D$4(par$A$1,) {fun funD = => 3; fun foo = => 10000} //│ class A$1() {} //│ } @@ -389,8 +398,8 @@ new A //│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], IntLit(1)))), NuFunDef(None, bar, [], New(Some((TypeName(B),)), TypingUnit(List()))))), New(Some((TypeName(A),)), TypingUnit(List()))) //│ Lifted: //│ TypingUnit { -//│ class A$1_B$2(par$A$1,) {fun foo = 1} -//│ class A$1() {fun bar = new A$1_B$2(this,) {}} +//│ class A$1_B$2(par$A$1,) {fun foo = => 1} +//│ class A$1() {fun bar = => new A$1_B$2(this,) {}} //│ Code(List(new A$1() {})) //│ } @@ -413,17 +422,17 @@ let x = new A{ //│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuFunDef(None, foo, [], IntLit(0)), NuFunDef(None, bar, [], Var(x)))), NuFunDef(Some(false), x, [], New(Some((TypeName(A),)), TypingUnit(List(fun foo = 1, fun newFun = 2, fun bar = new A(foo,) {fun foo = + (bar,) (1,); fun bar2 = + (newFun,) (1,)}))))) //│ Lifted: //│ TypingUnit { -//│ class A$1(x,) {fun foo = 0; fun bar = (this).x} -//│ class A$1$2_A$2$3(par$A$1$2, x,): A$1 ((this).x,) { -//│ fun foo = + ((this).bar,) (1,) -//│ fun bar2 = + (((this).par$A$1$2).newFun,) (1,) +//│ class A$1(x,) {fun foo = => 0; fun bar = => (this).x} +//│ class A$2$2_A$3$3(par$A$2$2, x,): A$1 ((this).x,) { +//│ fun foo = => + ((this).bar,) (1,) +//│ fun bar2 = => + (((this).par$A$2$2).newFun,) (1,) //│ } -//│ class A$1$2(x,): A$1 ((this).x,) { -//│ fun foo = 1 -//│ fun newFun = 2 -//│ fun bar = {new A$1$2_A$2$3(this, (this).foo,) {}} +//│ class A$2$2(x,): A$1 ((this).x,) { +//│ fun foo = => 1 +//│ fun newFun = => 2 +//│ fun bar = => {new A$2$2_A$3$3(this, (this).foo,) {}} //│ } -//│ let x = {new A$1$2() {}} +//│ let x$1 = => {new A$2$2() {}} //│ } class A {} @@ -451,22 +460,25 @@ new A{ //│ TypingUnit { //│ class A$1() {} //│ class A$1$2_A$2$3_A$3$4_A$4$5_A$5$6(par$A$1$2_A$2$3_A$3$4_A$4$5,): A$1 () { -//│ fun foo4 = (((((this).par$A$1$2_A$2$3_A$3$4_A$4$5).par$A$1$2_A$2$3_A$3$4).par$A$1$2_A$2$3).par$A$1$2).foo -//│ fun bar4 = 0 +//│ fun foo4 = => (((((this).par$A$1$2_A$2$3_A$3$4_A$4$5).par$A$1$2_A$2$3_A$3$4).par$A$1$2_A$2$3).par$A$1$2).foo +//│ fun bar4 = => 0 //│ } //│ class A$1$2_A$2$3_A$3$4_A$4$5(par$A$1$2_A$2$3_A$3$4,): A$1 () { -//│ fun foo3 = ((((this).par$A$1$2_A$2$3_A$3$4).par$A$1$2_A$2$3).par$A$1$2).foo -//│ fun bar3 = {new A$1$2_A$2$3_A$3$4_A$4$5_A$5$6(this,) {}} +//│ fun foo3 = => ((((this).par$A$1$2_A$2$3_A$3$4).par$A$1$2_A$2$3).par$A$1$2).foo +//│ fun bar3 = => {new A$1$2_A$2$3_A$3$4_A$4$5_A$5$6(this,) {}} //│ } //│ class A$1$2_A$2$3_A$3$4(par$A$1$2_A$2$3,): A$1 () { -//│ fun foo2 = (((this).par$A$1$2_A$2$3).par$A$1$2).foo -//│ fun bar2 = {new A$1$2_A$2$3_A$3$4_A$4$5(this,) {}} +//│ fun foo2 = => (((this).par$A$1$2_A$2$3).par$A$1$2).foo +//│ fun bar2 = => {new A$1$2_A$2$3_A$3$4_A$4$5(this,) {}} //│ } //│ class A$1$2_A$2$3(par$A$1$2,): A$1 () { -//│ fun foo1 = ((this).par$A$1$2).foo -//│ fun bar1 = {new A$1$2_A$2$3_A$3$4(this,) {}} +//│ fun foo1 = => ((this).par$A$1$2).foo +//│ fun bar1 = => {new A$1$2_A$2$3_A$3$4(this,) {}} +//│ } +//│ class A$1$2(): A$1 () { +//│ fun foo = => 1 +//│ fun bar = => {new A$1$2_A$2$3(this,) {}} //│ } -//│ class A$1$2(): A$1 () {fun foo = 1; fun bar = {new A$1$2_A$2$3(this,) {}}} //│ Code(List({new A$1$2() {}})) //│ } diff --git a/compiler/shared/test/diff/LifterBlks.mls b/compiler/shared/test/diff/LifterBlks.mls index 3fd026b82..ae1ed807c 100644 --- a/compiler/shared/test/diff/LifterBlks.mls +++ b/compiler/shared/test/diff/LifterBlks.mls @@ -9,7 +9,7 @@ fun foo = //│ Parsed: //│ TypingUnit(NuFunDef(None, foo, [], Blk(...))) //│ Lifted: -//│ TypingUnit {fun foo = {print ("ok",); print ("ko",)}} +//│ TypingUnit {fun foo$1 = => {print ("ok",); print ("ko",)}} class A{ class B {} @@ -42,8 +42,10 @@ fun foo = //│ TypingUnit(NuFunDef(None, foo, [], Blk(...))) //│ Lifted: //│ TypingUnit { -//│ class Foo$1(x,) {fun bar = + ((this).x,) (1,)} -//│ fun foo = {fun local = x, => {(Foo$1 (x,)).bar}; fun tmp = 1; fun tmp = 2; print (+ (local (0,),) (local (1,),),); print (+ (local (0,),) (local (1,),),); print (local (+ (0,) (local (1,),),),)} +//│ class Foo$1(x,) {fun bar = => + ((this).x,) (1,)} +//│ fun local$3 = x, => {(Foo$1 (x,)).bar} +//│ fun tmp$2 = => 1 +//│ fun foo$1 = => {print (+ (local$3 (0,),) (local$3 (1,),),); print (+ (local$3 (0,),) (local$3 (1,),),); print (local$3 (+ (0,) (local$3 (1,),),),)} //│ } class A(y){} @@ -56,9 +58,9 @@ f(0) //│ Lifted: //│ TypingUnit { //│ class A$1(y,) {} -//│ class A$1$2(y, x,): A$1 ((this).y,) {fun bar = + ((this).x,) ((this).y,)} -//│ let f = x, => {new A$1$2(0, x,) {}} -//│ Code(List(f (0,))) +//│ class A$2$2(y, x,): A$1 ((this).y,) {fun bar = => + ((this).x,) ((this).y,)} +//│ let f$1 = x, => {new A$2$2(0, x,) {}} +//│ Code(List(f$1 (0,))) //│ } class A(x){ @@ -78,13 +80,13 @@ class A(x){ //│ Lifted: //│ TypingUnit { //│ class A$1_B$2(par$A$1, z, y,) { -//│ fun bar = + (+ (((this).par$A$1).x,) ((this).y,),) ((this).z,) +//│ fun bar = => + (+ (((this).par$A$1).x,) ((this).y,),) ((this).z,) //│ } //│ class A$1_B$1$3(par$A$1, z, y,): A$1_B$2 ((this).par$A$1, (this).z, (this).y,) { -//│ fun bar = + (+ (((this).par$A$1).w,) ((this).y,),) ((this).z,) +//│ fun bar = => + (+ (((this).par$A$1).w,) ((this).y,),) ((this).z,) //│ } //│ class A$1(x,) { -//│ fun w = (this).x +//│ fun w = => (this).x //│ fun foo = y, => {{new A$1_B$1$3(this, 0, y,) {}}} //│ } //│ } @@ -108,15 +110,15 @@ fun f(x,y,z) = //│ Lifted: //│ TypingUnit { //│ class A$1(x, y,) { -//│ fun foo = new B$2((this).y, (this).x,) {} -//│ fun bar1 = (this).x +//│ fun foo = => new B$2((this).y, (this).x,) {} +//│ fun bar1 = => (this).x //│ } //│ class B$2(y, x,) { -//│ fun foo = new A$1((this).x, (this).y,) {} -//│ fun bar2 = (this).y +//│ fun foo = => new A$1((this).x, (this).y,) {} +//│ fun bar2 = => (this).y //│ } -//│ class C$3(x, y,): A$1 ((this).x, (this).y,), B$2 ((this).y, (this).x,) {fun bar = + ((this).bar1,) ((this).bar2,)} -//│ fun f = x, y, z, => {} +//│ class C$3(x, y,): A$1 ((this).x, (this).y,), B$2 ((this).y, (this).x,) {fun bar = => + ((this).bar1,) ((this).bar2,)} +//│ fun f$1 = x, y, z, => {} //│ } fun f(x,y,z) = @@ -138,33 +140,34 @@ fun f(x,y,z) = //│ Lifted: //│ TypingUnit { //│ class C$1_A$2(par$C$1,) { -//│ fun foo = new C$1_B$3((this).par$C$1,) {} -//│ fun bar1 = ((this).par$C$1).x +//│ fun foo = => new C$1_B$3((this).par$C$1,) {} +//│ fun bar1 = => ((this).par$C$1).x //│ } //│ class C$1_B$3(par$C$1,) { -//│ fun foo = new C$1_A$2((this).par$C$1,) {} -//│ fun bar2 = ((this).par$C$1).y +//│ fun foo = => new C$1_A$2((this).par$C$1,) {} +//│ fun bar2 = => ((this).par$C$1).y //│ } //│ class C$1(x, y, z,) { -//│ fun boo = + (('(' new C$1_A$2(this,) {}, ')').bar1,) (+ ((C$1_B$3 (this,)).bar2,) ((this).z,),) +//│ fun boo = => + (('(' new C$1_A$2(this,) {}, ')').bar1,) (+ ((C$1_B$3 (this,)).bar2,) ((this).z,),) //│ } -//│ fun f = x, y, z, => {} +//│ fun f$1 = x, y, z, => {} //│ } -fun f(x) = - let g(x) = x + 1 +fun f(y) = + let g(x) = x + y + 1 class Foo(x) { fun h = g(x) } - Foo(x).h -//│ |#fun| |f|(|x|)| |#=|→|#let| |g|(|x|)| |#=| |x| |+| |1|↵|#class| |Foo|(|x|)| |{|→|#fun| |h| |#=| |g|(|x|)|←|↵|}|↵|Foo|(|x|)|.h|←| -//│ Parsed: {fun f = x, => {let g = x, => + (x,) (1,); class Foo(x,) {fun h = g (x,)}; (Foo (x,)).h}} + Foo(1).h +//│ |#fun| |f|(|y|)| |#=|→|#let| |g|(|x|)| |#=| |x| |+| |y| |+| |1|↵|#class| |Foo|(|x|)| |{|→|#fun| |h| |#=| |g|(|x|)|←|↵|}|↵|Foo|(|1|)|.h|←| +//│ Parsed: {fun f = y, => {let g = x, => + (+ (x,) (y,),) (1,); class Foo(x,) {fun h = g (x,)}; (Foo (1,)).h}} //│ Parsed: -//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Blk(...)))) +//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(y)), Blk(...)))) //│ Lifted: //│ TypingUnit { -//│ class Foo$1(x, g,) {fun h = (this).g ((this).x,)} -//│ fun f = x, => {let g = x, => + (x,) (1,); (Foo$1 (x, g,)).h} +//│ class Foo$1(x, y,) {fun h = => g$2 ((this).x, y,)} +//│ let g$2 = x, y, => + (+ (x,) (y,),) (1,) +//│ fun f$1 = y, => {(Foo$1 (1, y,)).h} //│ } fun f(x) = @@ -181,8 +184,10 @@ fun f(x) = //│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Blk(...)))) //│ Lifted: //│ TypingUnit { -//│ class Foo$1(x, y, g,) {fun bar = + ((this).g ((this).x,),) ((this).y,)} -//│ fun f = x, => {let g = x, => {let h = x, => + (x,) (2,); (Foo$1 (h (x,), x, g,)).bar}; (Foo$1 (x, x, g,)).bar} +//│ class Foo$1(x, y,) {fun bar = => + (g$2 ((this).x,),) ((this).y,)} +//│ let h$3 = x, => + (x,) (2,) +//│ let g$2 = x, => {(Foo$1 (h$3 (x,), x,)).bar} +//│ fun f$1 = x, => {(Foo$1 (x, x,)).bar} //│ } class Foo(x, y): Bar(y, x), Baz(x + y) @@ -206,28 +211,25 @@ fun foo(x: T): string = //│ TypingUnit(NuFunDef(None, foo, [TypeName(T), TypeName(U)], Lam(Tup(x: Var(T)), Asc(Blk(...), TypeName(string))))) //│ Lifted: //│ TypingUnit { -//│ class A$1[T,U](y,): B‹T›, C (y: U,) {fun bar = this} -//│ fun foo[T, U] = x: T, => {"rua"} : TypeName(string) +//│ class A$1(y,): B‹T›, C (y: U,) {fun bar = => this} +//│ fun foo$1[T, U] = x: T, => {"rua"} : TypeName(string) //│ } class A{ class B{ - fun f: T => B => T = x => y => x + fun f = x => y => x fun g: T => B => T } } -//│ |#class| |A|‹|T|›|{|→|#class| |B|{|→|#fun| |f|#:| |T| |=>| |B| |=>| |T| |#=| |x| |=>| |y| |=>| |x|↵|#fun| |g|#:| |T| |=>| |B| |=>| |T|←|↵|}|←|↵|}| -//│ Parsed: {class A[T]() {class B() {fun f = x, => y, => x : Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T))); fun g: [] -> T -> B -> T}}} +//│ |#class| |A|‹|T|›|{|→|#class| |B|{|→|#fun| |f| |#=| |x| |=>| |y| |=>| |x|↵|#fun| |g|#:| |T| |=>| |B| |=>| |T|←|↵|}|←|↵|}| +//│ Parsed: {class A[T]() {class B() {fun f = x, => y, => x; fun g: [] -> T -> B -> T}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (TypeName(T)), Tup(), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, f, [], Asc(Lam(Tup(_: Var(x)), Lam(Tup(_: Var(y)), Var(x))), Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T))))), NuFunDef(None, g, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T)))))))))) +//│ TypingUnit(NuTypeDef(class, A, (TypeName(T)), Tup(), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Lam(Tup(_: Var(y)), Var(x)))), NuFunDef(None, g, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T)))))))))) //│ Lifted: //│ TypingUnit { -//│ class A$1_B$2_Lambda1$1$3_Lambda1$2$4(par$A$1_B$2_Lambda1$1$3, x,) {fun apply = y, => (this).x} -//│ class A$1_B$2_Lambda1$1$3(par$A$1_B$2,) { -//│ fun apply = x, => {new A$1_B$2_Lambda1$1$3_Lambda1$2$4(this, x,) {}} -//│ } +//│ class A$1_B$2_Lambda1$1$3(par$A$1_B$2, x,) {fun apply = y, => (this).x} //│ class A$1_B$2[T](par$A$1,) { -//│ fun f = {new A$1_B$2_Lambda1$1$3(this,) {}} : Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(A$1_B$2))))),TypeName(T))) +//│ fun f = x, => {new A$1_B$2_Lambda1$1$3(this, x,) {}} //│ fun g = T -> A$1_B$2 -> T //│ } //│ class A$1[T]() {} @@ -268,8 +270,9 @@ fun ctx(a,b) = //│ TypingUnit { //│ class Func$1[T,U]() {fun apply = T -> U} //│ class Lambda$2[T,U](): Func$1 ()‹T, U› {} -//│ class Lambda$1$3[T,U](a,): Lambda$2 () {fun apply = x, => + ((this).a,) (x,)} -//│ fun ctx = a, b, => {fun foo = f: Func$1, x, => {(f).apply (x,)}; foo ({new Lambda$1$3(a,) {}}, b,)} +//│ class Lambda$3$3(a,): Lambda$2 () {fun apply = x, => + ((this).a,) (x,)} +//│ fun foo$2 = f: Func$1, x, => {(f).apply (x,)} +//│ fun ctx$1 = a, b, => {foo$2 ({new Lambda$3$3(a,) {}}, b,)} //│ } fun f(T) = @@ -281,3 +284,18 @@ f(MyClass) //│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(T)), Blk(...))), App(Var(f), Tup(_: Var(MyClass)))) //│ Lifted: //│ Lifting failed: mlscript.codegen.CodeGenError: Cannot find type T. Class values are not supported in lifter. + +class A { + fun foo = + fun bar = foo() + bar() +} +//│ |#class| |A| |{|→|#fun| |foo| |#=| |→|#fun| |bar| |#=| |foo|(||)|↵|bar|(||)|←|←|↵|}| +//│ Parsed: {class A() {fun foo = {fun bar = foo (); bar ()}}} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], Blk(...))))) +//│ Lifted: +//│ TypingUnit { +//│ class A$1() {fun foo = => {bar$1 (this,)}} +//│ fun bar$1 = this, => (this).foo () +//│ } diff --git a/compiler/shared/test/diff/mono.mls b/compiler/shared/test/diff/mono.mls index a7bf04ee3..661d51fcb 100644 --- a/compiler/shared/test/diff/mono.mls +++ b/compiler/shared/test/diff/mono.mls @@ -7,7 +7,7 @@ fun f(x) = if x then 42 else 1337 //│ Parsed: //│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), If((x) then 42, Some(IntLit(1337)))))) //│ Lifted: -//│ TypingUnit {fun f = x, => if (x) then 42 else 1337} +//│ TypingUnit {fun f$1 = x, => if (x) then 42 else 1337} // :mono fun foo() = 42 @@ -16,7 +16,7 @@ fun foo() = 42 //│ Parsed: //│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(), IntLit(42)))) //│ Lifted: -//│ TypingUnit {fun foo = => 42} +//│ TypingUnit {fun foo$1 = => 42} // :mono fun foo(x, #b) = if b then x else 1337 @@ -28,9 +28,9 @@ let b = foo(23, false) //│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(x), _: Var(b)), If((b) then x, Some(IntLit(1337))))), NuFunDef(Some(false), a, [], App(Var(foo), Tup(_: IntLit(42), _: Var(true)))), NuFunDef(Some(false), b, [], App(Var(foo), Tup(_: IntLit(23), _: Var(false))))) //│ Lifted: //│ TypingUnit { -//│ fun foo = x, #b, => if (b) then x else 1337 -//│ let a = foo (42, true,) -//│ let b = foo (23, false,) +//│ fun foo$3 = x, #b, => if (b) then x else 1337 +//│ let a$1 = => foo$3 (42, true,) +//│ let b$2 = => foo$3 (23, false,) //│ } // :mono @@ -40,8 +40,9 @@ let x = 42 + 1337 //│ Parsed: //│ TypingUnit(NuFunDef(Some(false), x, [], App(App(Var(+), Tup(_: IntLit(42))), Tup(_: IntLit(1337))))) //│ Lifted: -//│ TypingUnit {let x = + (42,) (1337,)} +//│ TypingUnit {let x$1 = => + (42,) (1337,)} +// :mono class Bar(#x) fun foo(#b) = b let a = foo(new Bar(1)) @@ -53,9 +54,9 @@ let b = foo(new Bar(2)) //│ Lifted: //│ TypingUnit { //│ class Bar$1(#x,) {} -//│ fun foo = #b, => b -//│ let a = foo (new Bar$1(1,) {},) -//│ let b = foo (new Bar$1(2,) {},) +//│ fun foo$3 = #b, => b +//│ let a$1 = => foo$3 (new Bar$1(1,) {},) +//│ let b$2 = => foo$3 (new Bar$1(2,) {},) //│ } // :mono @@ -149,8 +150,8 @@ f(2)+3 //│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Blk(...))), App(App(Var(+), Tup(_: App(Var(f), Tup(_: IntLit(2))))), Tup(_: IntLit(3)))) //│ Lifted: //│ TypingUnit { -//│ fun f = x, => {if ('(' > (x,) (0,), ')') then + (x,) (1,) else - (x,) (1,)} -//│ Code(List(+ (f (2,),) (3,))) +//│ fun f$1 = x, => {if ('(' > (x,) (0,), ')') then + (x,) (1,) else - (x,) (1,)} +//│ Code(List(+ (f$1 (2,),) (3,))) //│ } // :mono @@ -163,8 +164,8 @@ fac(2) //│ TypingUnit(NuFunDef(None, fac, [], Lam(Tup(_: Var(n)), Blk(...))), App(Var(fac), Tup(_: IntLit(2)))) //│ Lifted: //│ TypingUnit { -//│ fun fac = n, => {if ('(' > (n,) (1,), ')') then * (fac (- (n,) (1,),),) (n,) else 1} -//│ Code(List(fac (2,))) +//│ fun fac$1 = n, => {if ('(' > (n,) (1,), ')') then * (fac$1 (- (n,) (1,),),) (n,) else 1} +//│ Code(List(fac$1 (2,))) //│ } // :mono @@ -181,8 +182,8 @@ count(new List(new List(new Nil(0, false), true), true)) //│ TypingUnit { //│ class List$1(l, hasTail,) {} //│ class Nil$2(l, hasTail,) {} -//│ fun count = lst, => {if ((lst).hasTail) then + (count ((lst).l,),) (1,) else 1} -//│ Code(List(count (new List$1(new List$1(new Nil$2(0, false,) {}, true,) {}, true,) {},))) +//│ fun count$1 = lst, => {if ((lst).hasTail) then + (count$1 ((lst).l,),) (1,) else 1} +//│ Code(List(count$1 (new List$1(new List$1(new Nil$2(0, false,) {}, true,) {}, true,) {},))) //│ } :mono @@ -205,405 +206,27 @@ generate(10).gen() //│ fun gen = => new Cons$1((this).e, ((this).tail).gen (),) {} //│ } //│ class Nil$2() {fun gen = => new Cons$1(0, this,) {}} -//│ fun generate = x, => {if (> (x,) (0,)) then new Cons$1(x, generate (+ (x,) (1,),),) {} else new Nil$2() {}} -//│ Code(List((generate (10,)).gen ())) +//│ fun generate$1 = x, => {if (> (x,) (0,)) then new Cons$1(x, generate$1 (+ (x,) (1,),),) {} else new Nil$2() {}} +//│ Code(List((generate$1 (10,)).gen ())) //│ } //│ Mono: //│ -//│ Mono result: +//│ Defunc result: //│ main$$3() //│ fun gen$Cons$1(this) = -//│ new Cons$1 (this.e, this.tail match {case obj: Nil$2 => gen$Nil$2(obj); case obj: Cons$1 => gen$Cons$1(obj)}) +//│ new Cons$1 (this.e, this.tail match {case obj: Cons$1 => gen$Cons$1(obj); case obj: Nil$2 => gen$Nil$2(obj)}) +//│ fun generate$1(x) = +//│ if (x > #0) then new Cons$1 (x, generate$1((x + #1))) else new Nil$2 () //│ fun gen$Nil$2(this) = //│ new Cons$1 (#0, this) //│ fun main$$3() = -//│ generate(#10) match {case obj: Nil$2 => gen$Nil$2(obj); case obj: Cons$1 => gen$Cons$1(obj)} -//│ fun generate(x) = -//│ if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () +//│ generate$1(#10) match {case obj: Cons$1 => gen$Cons$1(obj); case obj: Nil$2 => gen$Nil$2(obj)} //│ class Nil$2() { //│ } //│ class Cons$1(e, tail) { //│ } -//│ [mono] ┌───┬───────────────────────────────────────────────────────────────────────────┐ -//│ │ 1 │ main$$3() │ -//│ │ 2 │ fun main$$3() = │ -//│ │ 3 │ generate(#10).gen() │ -//│ │ 4 │ fun generate(x) = │ -//│ │ 5 │ if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () │ -//│ │ 6 │ class Nil$2() { │ -//│ │ 7 │ } │ -//│ │ 8 │ class Cons$1(e, tail) { │ -//│ │ 9 │ } │ -//│ └───┴───────────────────────────────────────────────────────────────────────────┘ -//│ [mono] evaluating main$$3, rests: HashSet() -//│ [mono] ========== updating main$$3 ========== -//│ [mono] main$$3: () -> *2*=[*2*=...]446468 @{} -//│ [mono] ┌ EVAL generate(#10).gen() -//│ [mono] │ ┌ EVAL generate(#10).gen -//│ [mono] │ │ ┌ EVAL generate(#10) -//│ [mono] │ │ │ ┌ EVAL generate -//│ [mono] │ │ │ └ EVAL [generate(x) given {}]241205 -//│ [mono] │ │ │ ┌ EVAL #10 -//│ [mono] │ │ │ └ EVAL [10]946944 -//│ [mono] │ │ │ ┌ SPEC CALL generate with ([10]946944) -//│ [mono] │ │ │ │ comparing (([]944117,0)) with (Plain([10]773991)) -//│ [mono] │ │ │ │ first time encounter generate -//│ [mono] │ │ │ │ evaluating generate, rests: HashSet() -//│ [mono] │ │ │ │ ========== updating generate ========== -//│ [mono] │ │ │ │ generate: (([10]773991,1)) -> *1*=[*1*=...]435529 @{main$$3} -//│ [mono] │ │ │ │ ┌ EVAL if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () -//│ [mono] │ │ │ │ │ ┌ EVAL if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () -//│ [mono] │ │ │ │ │ │ ┌ EVAL (x > #0) -//│ [mono] │ │ │ │ │ │ │ ┌ EVAL x -//│ [mono] │ │ │ │ │ │ │ └ EVAL [10]773991 -//│ [mono] │ │ │ │ │ │ │ ┌ EVAL #0 -//│ [mono] │ │ │ │ │ │ │ └ EVAL [0]245244 -//│ [mono] │ │ │ │ │ │ └ EVAL [true]467840 -//│ [mono] │ │ │ │ │ │ ┌ EVAL new Cons$1 (x, generate((x + #1))) -//│ [mono] │ │ │ │ │ │ │ ┌ EVAL x -//│ [mono] │ │ │ │ │ │ │ └ EVAL [10]773991 -//│ [mono] │ │ │ │ │ │ │ ┌ EVAL generate((x + #1)) -//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL generate -//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [generate(x) given {}]98216 -//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL (x + #1) -//│ [mono] │ │ │ │ │ │ │ │ │ ┌ EVAL x -//│ [mono] │ │ │ │ │ │ │ │ │ └ EVAL [10]773991 -//│ [mono] │ │ │ │ │ │ │ │ │ ┌ EVAL #1 -//│ [mono] │ │ │ │ │ │ │ │ │ └ EVAL [1]618214 -//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [11]771866 -//│ [mono] │ │ │ │ │ │ │ │ ┌ SPEC CALL generate with ([11]771866) -//│ [mono] │ │ │ │ │ │ │ │ │ comparing (([10]773991,1)) with (Plain([*LIT*]566055)) -//│ [mono] │ │ │ │ │ │ │ │ │ find finer args -//│ [mono] │ │ │ │ │ │ │ │ └ SPEC CALL [*1*=[*1*=...]435529]59154 -//│ [mono] │ │ │ │ │ │ │ │ call result: [*1*=[*1*=...]435529]59154 -//│ [mono] │ │ │ │ │ │ │ │ merging []115737 with [*1*=[*1*=...]435529]59154 -//│ [mono] │ │ │ │ │ │ │ │ result [*1*=[*1*=...]435529]5068 -//│ [mono] │ │ │ │ │ │ │ └ EVAL [*1*=[*1*=...]435529]5068 -//│ [mono] │ │ │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[*1*=...]435529]5068}]356015 -//│ [mono] │ │ │ │ │ │ ┌ EVAL new Nil$2 () -//│ [mono] │ │ │ │ │ │ └ EVAL [Nil$2@{}]431217 -//│ [mono] │ │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[*1*=...]435529]5068}]356015 -//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[*1*=...]435529]5068}]356015 -//│ [mono] │ │ │ │ comparing [*1*=...]435529 with [Cons$1@{e: [10]773991, tail: [*1*=[*1*=...]435529]5068}]356015 -//│ [mono] │ │ │ │ adding these funcs to queue: Set(main$$3, generate) -//│ [mono] │ │ │ │ generate: (([*LIT*]566055,100000)) -> *1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015 @{main$$3, generate} -//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]185805 -//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]185805 -//│ [mono] │ │ │ merging []938256 with [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]185805 -//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]290413 -//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]290413 -//│ [mono] │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]265840}]840962 -//│ [mono] │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]265840) -//│ [mono] │ │ comparing (([]364339,0)) with (Plain([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107)) -//│ [mono] │ │ first time encounter gen$Cons$1 -//│ [mono] │ │ evaluating gen$Cons$1, rests: HashSet(main$$3, generate) -//│ [mono] │ │ ========== updating gen$Cons$1 ========== -//│ [mono] │ │ gen$Cons$1: (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) -> *3*=[*3*=...]678569 @{main$$3} -//│ [mono] │ │ ┌ EVAL new Cons$1 (this.e, this.tail.gen()) -//│ [mono] │ │ │ ┌ EVAL this.e -//│ [mono] │ │ │ │ ┌ EVAL this -//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107 -//│ [mono] │ │ │ └ EVAL [10]277488 -//│ [mono] │ │ │ ┌ EVAL this.tail.gen() -//│ [mono] │ │ │ │ ┌ EVAL this.tail.gen -//│ [mono] │ │ │ │ │ ┌ EVAL this.tail -//│ [mono] │ │ │ │ │ │ ┌ EVAL this -//│ [mono] │ │ │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107 -//│ [mono] │ │ │ │ │ └ EVAL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]568228 -//│ [mono] │ │ │ │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]791258}]62179 -//│ [mono] │ │ │ │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]791258) -//│ [mono] │ │ │ │ │ comparing (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) with (Plain([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]933119)) -//│ [mono] │ │ │ │ └ SPEC CALL [*3*=[*3*=...]678569]809765 -//│ [mono] │ │ │ │ call result: [*3*=[*3*=...]678569]809765 -//│ [mono] │ │ │ │ merging []218815 with [*3*=[*3*=...]678569]809765 -//│ [mono] │ │ │ │ result [*3*=[*3*=...]678569]300678 -//│ [mono] │ │ │ └ EVAL [*3*=[*3*=...]678569]300678 -//│ [mono] │ │ └ EVAL [Cons$1@{e: [10]277488, tail: [*3*=[*3*=...]678569]300678}]407363 -//│ [mono] │ │ comparing [*3*=...]678569 with [Cons$1@{e: [10]277488, tail: [*3*=[*3*=...]678569]300678}]407363 -//│ [mono] │ │ adding these funcs to queue: Set(main$$3, gen$Cons$1) -//│ [mono] │ │ gen$Cons$1: (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) -> *3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363 @{main$$3, gen$Cons$1} -//│ [mono] │ └ SPEC CALL [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]595743 -//│ [mono] │ call result: [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]595743 -//│ [mono] │ merging []932118 with [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]595743 -//│ [mono] │ result [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]726572 -//│ [mono] └ EVAL [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]726572 -//│ [mono] comparing [*2*=...]446468 with [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]726572 -//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]726572 @{} -//│ [mono] evaluating gen$Cons$1, rests: HashSet(main$$3, generate) -//│ [mono] ========== updating gen$Cons$1 ========== -//│ [mono] gen$Cons$1: (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) -> *3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363 @{main$$3, gen$Cons$1} -//│ [mono] ┌ EVAL new Cons$1 (this.e, this.tail.gen()) -//│ [mono] │ ┌ EVAL this.e -//│ [mono] │ │ ┌ EVAL this -//│ [mono] │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107 -//│ [mono] │ └ EVAL [10]364447 -//│ [mono] │ ┌ EVAL this.tail.gen() -//│ [mono] │ │ ┌ EVAL this.tail.gen -//│ [mono] │ │ │ ┌ EVAL this.tail -//│ [mono] │ │ │ │ ┌ EVAL this -//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107 -//│ [mono] │ │ │ └ EVAL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]659072 -//│ [mono] │ │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]621451}]111512 -//│ [mono] │ │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]621451) -//│ [mono] │ │ │ comparing (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) with (Plain([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]90170)) -//│ [mono] │ │ └ SPEC CALL [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]7835 -//│ [mono] │ │ call result: [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]7835 -//│ [mono] │ │ merging []437242 with [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]7835 -//│ [mono] │ │ result [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]767874 -//│ [mono] │ └ EVAL [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]767874 -//│ [mono] └ EVAL [Cons$1@{e: [10]364447, tail: [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]767874}]507104 -//│ [mono] comparing [Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363 with [Cons$1@{e: [10]364447, tail: [*3*=[Cons$1@{e: [10]277488, tail: [*3*=...]300678}]407363]767874}]507104 -//│ [mono] gen$Cons$1: (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) -> *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104 @{main$$3, gen$Cons$1} -//│ [mono] evaluating main$$3, rests: HashSet(generate) -//│ [mono] ========== updating main$$3 ========== -//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726572 @{} -//│ [mono] ┌ EVAL generate(#10).gen() -//│ [mono] │ ┌ EVAL generate(#10).gen -//│ [mono] │ │ ┌ EVAL generate(#10) -//│ [mono] │ │ │ ┌ EVAL generate -//│ [mono] │ │ │ └ EVAL [generate(x) given {}]226557 -//│ [mono] │ │ │ ┌ EVAL #10 -//│ [mono] │ │ │ └ EVAL [10]710582 -//│ [mono] │ │ │ ┌ SPEC CALL generate with ([10]710582) -//│ [mono] │ │ │ │ comparing (([*LIT*]566055,100000)) with (Plain([*LIT*]310229)) -//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]120919 -//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]120919 -//│ [mono] │ │ │ merging []708150 with [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]120919 -//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]709851 -//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]709851 -//│ [mono] │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]493684}]525682 -//│ [mono] │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]493684) -//│ [mono] │ │ comparing (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]506107,5)) with (Plain([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [10]773991, tail: ...}]356015]5068}]295517)) -//│ [mono] │ └ SPEC CALL [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]400460 -//│ [mono] │ call result: [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]400460 -//│ [mono] │ merging []669796 with [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]400460 -//│ [mono] │ result [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 -//│ [mono] └ EVAL [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 -//│ [mono] comparing [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726572 with [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 -//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 @{} -//│ [mono] evaluating generate, rests: HashSet() -//│ [mono] ========== updating generate ========== -//│ [mono] generate: (([*LIT*]566055,100000)) -> *1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015 @{main$$3, generate} -//│ [mono] ┌ EVAL if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () -//│ [mono] │ ┌ EVAL (x > #0) -//│ [mono] │ │ ┌ EVAL x -//│ [mono] │ │ └ EVAL [*LIT*]566055 -//│ [mono] │ │ ┌ EVAL #0 -//│ [mono] │ │ └ EVAL [0]425176 -//│ [mono] │ └ EVAL [*LIT*]455673 -//│ [mono] │ ┌ EVAL new Cons$1 (x, generate((x + #1))) -//│ [mono] │ │ ┌ EVAL x -//│ [mono] │ │ └ EVAL [*LIT*]566055 -//│ [mono] │ │ ┌ EVAL generate((x + #1)) -//│ [mono] │ │ │ ┌ EVAL generate -//│ [mono] │ │ │ └ EVAL [generate(x) given {}]68659 -//│ [mono] │ │ │ ┌ EVAL (x + #1) -//│ [mono] │ │ │ │ ┌ EVAL x -//│ [mono] │ │ │ │ └ EVAL [*LIT*]566055 -//│ [mono] │ │ │ │ ┌ EVAL #1 -//│ [mono] │ │ │ │ └ EVAL [1]230662 -//│ [mono] │ │ │ └ EVAL [*LIT*]687925 -//│ [mono] │ │ │ ┌ SPEC CALL generate with ([*LIT*]687925) -//│ [mono] │ │ │ │ comparing (([*LIT*]566055,100000)) with (Plain([*LIT*]345917)) -//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]385696 -//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]385696 -//│ [mono] │ │ │ merging []33723 with [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]385696 -//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]47299 -//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]47299 -//│ [mono] │ └ EVAL [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]47299}]543166 -//│ [mono] │ ┌ EVAL new Nil$2 () -//│ [mono] │ └ EVAL [Nil$2@{}]142725 -//│ [mono] └ EVAL [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]47299} | Nil$2@{}]642012 -//│ [mono] comparing [Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015 with [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [10]773991, tail: [*1*=...]5068}]356015]47299} | Nil$2@{}]642012 -//│ [mono] adding these funcs to queue: Set(main$$3, generate) -//│ [mono] generate: (([*LIT*]566055,100000)) -> *1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012 @{main$$3, generate} -//│ [mono] evaluating main$$3, rests: HashSet(generate) -//│ [mono] ========== updating main$$3 ========== -//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 @{} -//│ [mono] ┌ EVAL generate(#10).gen() -//│ [mono] │ ┌ EVAL generate(#10).gen -//│ [mono] │ │ ┌ EVAL generate(#10) -//│ [mono] │ │ │ ┌ EVAL generate -//│ [mono] │ │ │ └ EVAL [generate(x) given {}]111869 -//│ [mono] │ │ │ ┌ EVAL #10 -//│ [mono] │ │ │ └ EVAL [10]704974 -//│ [mono] │ │ │ ┌ SPEC CALL generate with ([10]704974) -//│ [mono] │ │ │ │ comparing (([*LIT*]566055,100000)) with (Plain([*LIT*]127031)) -//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]43871 -//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]43871 -//│ [mono] │ │ │ merging []554043 with [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]43871 -//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]841328 -//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]841328 -//│ [mono] │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]238870} | gen$Nil$2() given {this: [Nil$2@{}]935508}]123268 -//│ [mono] │ ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]935508) -//│ [mono] │ │ comparing (([]97006,0)) with (Plain([Nil$2@{}]877701)) -//│ [mono] │ │ first time encounter gen$Nil$2 -//│ [mono] │ │ evaluating gen$Nil$2, rests: HashSet(generate) -//│ [mono] │ │ ========== updating gen$Nil$2 ========== -//│ [mono] │ │ gen$Nil$2: (([Nil$2@{}]877701,1)) -> *4*=[*4*=...]519152 @{main$$3} -//│ [mono] │ │ ┌ EVAL new Cons$1 (#0, this) -//│ [mono] │ │ │ ┌ EVAL #0 -//│ [mono] │ │ │ └ EVAL [0]413996 -//│ [mono] │ │ │ ┌ EVAL this -//│ [mono] │ │ │ └ EVAL [Nil$2@{}]877701 -//│ [mono] │ │ └ EVAL [Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 -//│ [mono] │ │ comparing [*4*=...]519152 with [Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 -//│ [mono] │ │ adding these funcs to queue: Set(main$$3) -//│ [mono] │ │ gen$Nil$2: (([Nil$2@{}]877701,1)) -> *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 @{main$$3} -//│ [mono] │ └ SPEC CALL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]656947 -//│ [mono] │ call result: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]656947 -//│ [mono] │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]238870) -//│ [mono] │ │ comparing (([Cons$1@{e: [10]773991, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]5068}]506107,5)) with (Plain([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521)) -//│ [mono] │ │ find finer args -//│ [mono] │ └ SPEC CALL [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]978844 -//│ [mono] │ call result: [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]978844 -//│ [mono] │ merging []294987 with [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]656947 -//│ [mono] │ result [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]19092 -//│ [mono] │ merging [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]19092 with [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]978844 -//│ [mono] │ result [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]969872 -//│ [mono] └ EVAL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]969872 -//│ [mono] comparing [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]329367 with [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]969872 -//│ [mono] adding these funcs to queue: Set() -//│ [mono] main$$3: () -> *2*=[*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]969872 @{} -//│ [mono] evaluating gen$Cons$1, rests: HashSet(main$$3, generate) -//│ [mono] ========== updating gen$Cons$1 ========== -//│ [mono] gen$Cons$1: (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) -> *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104 @{main$$3, gen$Cons$1} -//│ [mono] ┌ EVAL new Cons$1 (this.e, this.tail.gen()) -//│ [mono] │ ┌ EVAL this.e -//│ [mono] │ │ ┌ EVAL this -//│ [mono] │ │ └ EVAL [Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521 -//│ [mono] │ └ EVAL [*LIT*]211259 -//│ [mono] │ ┌ EVAL this.tail.gen() -//│ [mono] │ │ ┌ EVAL this.tail.gen -//│ [mono] │ │ │ ┌ EVAL this.tail -//│ [mono] │ │ │ │ ┌ EVAL this -//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521 -//│ [mono] │ │ │ └ EVAL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]987988 -//│ [mono] │ │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]611974} | gen$Nil$2() given {this: [Nil$2@{}]710241}]564852 -//│ [mono] │ │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]611974) -//│ [mono] │ │ │ comparing (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) with (Plain([Cons$1@{e: [*LIT*]45932, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]795876}]173592)) -//│ [mono] │ │ └ SPEC CALL [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]472898 -//│ [mono] │ │ call result: [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]472898 -//│ [mono] │ │ ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]710241) -//│ [mono] │ │ │ comparing (([Nil$2@{}]877701,1)) with (Plain([Nil$2@{}]467485)) -//│ [mono] │ │ └ SPEC CALL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]443107 -//│ [mono] │ │ call result: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]443107 -//│ [mono] │ │ merging []996289 with [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]472898 -//│ [mono] │ │ result [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]179437 -//│ [mono] │ │ merging [*3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]179437 with [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]443107 -//│ [mono] │ │ result [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726509 -//│ [mono] │ └ EVAL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726509 -//│ [mono] └ EVAL [Cons$1@{e: [*LIT*]211259, tail: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726509}]130025 -//│ [mono] comparing [Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104 with [Cons$1@{e: [*LIT*]211259, tail: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 | *3*=[Cons$1@{e: [10]364447, tail: [*3*=...]767874}]507104]726509}]130025 -//│ [mono] adding these funcs to queue: Set(main$$3, gen$Cons$1) -//│ [mono] gen$Cons$1: (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) -> *3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 @{main$$3, gen$Cons$1} -//│ [mono] evaluating gen$Cons$1, rests: HashSet(main$$3, generate) -//│ [mono] ========== updating gen$Cons$1 ========== -//│ [mono] gen$Cons$1: (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) -> *3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 @{main$$3, gen$Cons$1} -//│ [mono] ┌ EVAL new Cons$1 (this.e, this.tail.gen()) -//│ [mono] │ ┌ EVAL this.e -//│ [mono] │ │ ┌ EVAL this -//│ [mono] │ │ └ EVAL [Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521 -//│ [mono] │ └ EVAL [*LIT*]144235 -//│ [mono] │ ┌ EVAL this.tail.gen() -//│ [mono] │ │ ┌ EVAL this.tail.gen -//│ [mono] │ │ │ ┌ EVAL this.tail -//│ [mono] │ │ │ │ ┌ EVAL this -//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521 -//│ [mono] │ │ │ └ EVAL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]683896 -//│ [mono] │ │ └ EVAL [gen$Nil$2() given {this: [Nil$2@{}]402304} | gen$Cons$1() given {this: [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]954800}]797408 -//│ [mono] │ │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]954800) -//│ [mono] │ │ │ comparing (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) with (Plain([Cons$1@{e: [*LIT*]390244, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]550955}]868530)) -//│ [mono] │ │ └ SPEC CALL [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025]751281 -//│ [mono] │ │ call result: [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025]751281 -//│ [mono] │ │ ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]402304) -//│ [mono] │ │ │ comparing (([Nil$2@{}]877701,1)) with (Plain([Nil$2@{}]784911)) -//│ [mono] │ │ └ SPEC CALL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]862537 -//│ [mono] │ │ call result: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]862537 -//│ [mono] │ │ merging []983536 with [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025]751281 -//│ [mono] │ │ result [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025]532223 -//│ [mono] │ │ merging [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025]532223 with [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]862537 -//│ [mono] │ │ result [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361 -//│ [mono] │ └ EVAL [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361 -//│ [mono] └ EVAL [Cons$1@{e: [*LIT*]144235, tail: [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 -//│ [mono] comparing [Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 with [Cons$1@{e: [*LIT*]144235, tail: [*3*=[Cons$1@{e: [*LIT*]211259, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]726509}]130025 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 -//│ [mono] gen$Cons$1: (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) -> *3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 @{main$$3, gen$Cons$1} -//│ [mono] evaluating main$$3, rests: HashSet(generate) -//│ [mono] ========== updating main$$3 ========== -//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]969872 @{} -//│ [mono] ┌ EVAL generate(#10).gen() -//│ [mono] │ ┌ EVAL generate(#10).gen -//│ [mono] │ │ ┌ EVAL generate(#10) -//│ [mono] │ │ │ ┌ EVAL generate -//│ [mono] │ │ │ └ EVAL [generate(x) given {}]676913 -//│ [mono] │ │ │ ┌ EVAL #10 -//│ [mono] │ │ │ └ EVAL [10]123882 -//│ [mono] │ │ │ ┌ SPEC CALL generate with ([10]123882) -//│ [mono] │ │ │ │ comparing (([*LIT*]566055,100000)) with (Plain([*LIT*]823410)) -//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]862113 -//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]862113 -//│ [mono] │ │ │ merging []880020 with [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]862113 -//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]26923 -//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]26923 -//│ [mono] │ └ EVAL [gen$Cons$1() given {this: [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]577613} | gen$Nil$2() given {this: [Nil$2@{}]256414}]160088 -//│ [mono] │ ┌ SPEC CALL gen$Nil$2 with ([Nil$2@{}]256414) -//│ [mono] │ │ comparing (([Nil$2@{}]877701,1)) with (Plain([Nil$2@{}]586004)) -//│ [mono] │ └ SPEC CALL [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]204477 -//│ [mono] │ call result: [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]204477 -//│ [mono] │ ┌ SPEC CALL gen$Cons$1 with ([Cons$1@{e: [*LIT*]566055, tail: [*1*=[Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: ...}]642012]47299}]577613) -//│ [mono] │ │ comparing (([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]734933}]141521,300006)) with (Plain([Cons$1@{e: [*LIT*]203630, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]402242}]147)) -//│ [mono] │ └ SPEC CALL [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794]436063 -//│ [mono] │ call result: [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794]436063 -//│ [mono] │ merging []782992 with [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]204477 -//│ [mono] │ result [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]977956 -//│ [mono] │ merging [*4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]977956 with [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794]436063 -//│ [mono] │ result [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]233330 -//│ [mono] └ EVAL [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]233330 -//│ [mono] comparing [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]969872 with [*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]233330 -//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]233330 @{} -//│ [mono] evaluating generate, rests: HashSet() -//│ [mono] ========== updating generate ========== -//│ [mono] generate: (([*LIT*]566055,100000)) -> *1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012 @{main$$3, generate} -//│ [mono] ┌ EVAL if (x > #0) then new Cons$1 (x, generate((x + #1))) else new Nil$2 () -//│ [mono] │ ┌ EVAL (x > #0) -//│ [mono] │ │ ┌ EVAL x -//│ [mono] │ │ └ EVAL [*LIT*]566055 -//│ [mono] │ │ ┌ EVAL #0 -//│ [mono] │ │ └ EVAL [0]86794 -//│ [mono] │ └ EVAL [*LIT*]973248 -//│ [mono] │ ┌ EVAL new Cons$1 (x, generate((x + #1))) -//│ [mono] │ │ ┌ EVAL x -//│ [mono] │ │ └ EVAL [*LIT*]566055 -//│ [mono] │ │ ┌ EVAL generate((x + #1)) -//│ [mono] │ │ │ ┌ EVAL generate -//│ [mono] │ │ │ └ EVAL [generate(x) given {}]985318 -//│ [mono] │ │ │ ┌ EVAL (x + #1) -//│ [mono] │ │ │ │ ┌ EVAL x -//│ [mono] │ │ │ │ └ EVAL [*LIT*]566055 -//│ [mono] │ │ │ │ ┌ EVAL #1 -//│ [mono] │ │ │ │ └ EVAL [1]131514 -//│ [mono] │ │ │ └ EVAL [*LIT*]436284 -//│ [mono] │ │ │ ┌ SPEC CALL generate with ([*LIT*]436284) -//│ [mono] │ │ │ │ comparing (([*LIT*]566055,100000)) with (Plain([*LIT*]804833)) -//│ [mono] │ │ │ └ SPEC CALL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]679966 -//│ [mono] │ │ │ call result: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]679966 -//│ [mono] │ │ │ merging []902989 with [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]679966 -//│ [mono] │ │ │ result [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]631787 -//│ [mono] │ │ └ EVAL [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]631787 -//│ [mono] │ └ EVAL [Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]631787}]601940 -//│ [mono] │ ┌ EVAL new Nil$2 () -//│ [mono] │ └ EVAL [Nil$2@{}]990186 -//│ [mono] └ EVAL [Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]631787}]359428 -//│ [mono] comparing [Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012 with [Nil$2@{} | Cons$1@{e: [*LIT*]566055, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]47299} | Nil$2@{}]642012]631787}]359428 -//│ [mono] generate: (([*LIT*]566055,100000)) -> *1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]631787} | Nil$2@{}]359428 @{main$$3, generate} -//│ [mono] -//│ [mono] ==============final function signatures================== -//│ [mono] gen$Cons$1: ([Cons$1@{e: [*LIT*]285710, tail: [*1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]631787} | Nil$2@{}]359428]734933}]141521) -> *3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 -//│ [mono] gen$Nil$2: ([Nil$2@{}]877701) -> *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774 -//│ [mono] main$$3: () -> *2*=[*3*=[Cons$1@{e: [*LIT*]144235, tail: [*3*=... | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]166361}]134794 | *4*=[Cons$1@{e: [0]413996, tail: [Nil$2@{}]877701}]244774]233330 -//│ [mono] generate: ([*LIT*]566055) -> *1*=[Cons$1@{e: [*LIT*]566055, tail: [*1*=...]631787} | Nil$2@{}]359428 -// :mono +:mono class List(e, tail) { fun map(f) = new List(f(e), tail.map(f)) fun count() = 1 + tail.count() @@ -625,27 +248,35 @@ fun add2(x) = x+2 //│ fun count = => + (1,) (((this).tail).count (),) //│ } //│ class Nil$2() {fun map = f, => this; fun count = => 0} -//│ class Lambda1$1$3() {fun apply = x, => + (x,) (1,)} -//│ class Lambda1$2$4() {fun apply = x, => add2 (x,)} -//│ fun add2 = x, => + (x,) (2,) -//│ Code(List((('(' new List$1(1, new List$1(2, new Nil$2() {},) {},) {}, ')').map ({new Lambda1$1$3() {}},)).map ({new Lambda1$2$4() {}},))) +//│ class Lambda1$2$3() {fun apply = x, => + (x,) (1,)} +//│ class Lambda1$3$4() {fun apply = x, => add2$1 (x,)} +//│ fun add2$1 = x, => + (x,) (2,) +//│ Code(List((('(' new List$1(1, new List$1(2, new Nil$2() {},) {},) {}, ')').map ({new Lambda1$2$3() {}},)).map ({new Lambda1$3$4() {}},))) +//│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$5() +//│ fun map$List$1(this, f) = +//│ new List$1 (f match {case obj: Lambda1$2$3 => apply$Lambda1$2$3(obj, this.e); case obj: Lambda1$3$4 => apply$Lambda1$3$4(obj, this.e)}, this.tail match {case obj: List$1 => map$List$1(obj, f); case obj: Nil$2 => map$Nil$2(obj, f)}) +//│ fun add2$1(x) = +//│ (x + #2) +//│ fun main$$5() = +//│ new List$1 (#1, new List$1 (#2, new Nil$2 () ) ) match {case obj: List$1 => map$List$1(obj, new Lambda1$2$3 () )} match {case obj: List$1 => map$List$1(obj, new Lambda1$3$4 () )} +//│ fun apply$Lambda1$3$4(this, x) = +//│ add2$1(x) +//│ fun map$Nil$2(this, f) = +//│ this +//│ fun apply$Lambda1$2$3(this, x) = +//│ (x + #1) +//│ class Lambda1$3$4() { +//│ } +//│ class Nil$2() { +//│ } +//│ class List$1(e, tail) { +//│ } +//│ class Lambda1$2$3() { //│ } - -//| f match { -//| case obj: Lambda1$1$3 => apply$Lambda1$1$3(obj, this.e); -//| case obj: Lambda1$2$4 => apply$Lambda1$2$4(obj, this.e) -//| }, -//| this.tail match { -//| case obj: Nil$2 => map$Nil$2(obj, f); -//| case obj: List$1 => map$List$1(obj, f) -//| } -//| ) -//| case obj: List$1 => map$List$1(obj, new Lambda1$1$3 () ) -//| } match { -//| case obj: List$1 => map$List$1(obj, new Lambda1$2$4 () ) -//| } - - // :mono class List(e, tail) { @@ -667,10 +298,10 @@ foo(generate(1)) //│ TypingUnit { //│ class List$1(e, tail,) {fun count = => + (1,) (((this).tail).count (),)} //│ class Nil$2() {fun count = => 0} -//│ fun foo = x, => (x).count () -//│ fun generate = x, => {if (> (x,) (0,)) then new List$1(x, generate (+ (x,) (1,),),) {} else new Nil$2() {}} -//│ Code(List(foo (new List$1(1, new List$1(2, new Nil$2() {},) {},) {},))) -//│ Code(List(foo (generate (1,),))) +//│ fun foo$1 = x, => (x).count () +//│ fun generate$2 = x, => {if (> (x,) (0,)) then new List$1(x, generate$2 (+ (x,) (1,),),) {} else new Nil$2() {}} +//│ Code(List(foo$1 (new List$1(1, new List$1(2, new Nil$2() {},) {},) {},))) +//│ Code(List(foo$1 (generate$2 (1,),))) //│ } :mono @@ -683,121 +314,27 @@ foo(2) //│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: IntLit(2)))) //│ Lifted: //│ TypingUnit { -//│ class Lambda1$1$1(x,) {fun apply = f, => f ((this).x,)} -//│ class Lambda1$2$2() {fun apply = z, => + (z,) (1,)} -//│ fun foo = x, => {'(' {new Lambda1$1$1(x,) {}}, ')' ({new Lambda1$2$2() {}},)} -//│ Code(List(foo (2,))) +//│ class Lambda1$2$1(x,) {fun apply = f, => f ((this).x,)} +//│ class Lambda1$3$2() {fun apply = z, => + (z,) (1,)} +//│ fun foo$1 = x, => {'(' {new Lambda1$2$1(x,) {}}, ')' ({new Lambda1$3$2() {}},)} +//│ Code(List(foo$1 (2,))) //│ } //│ Mono: //│ -//│ Mono result: +//│ Defunc result: //│ main$$3() -//│ fun apply$Lambda1$1$1(this, f) = -//│ f match {case obj: Lambda1$2$2 => apply$Lambda1$2$2(obj, this.x)} -//│ fun foo(x) = -//│ new Lambda1$1$1 (x) match {case obj: Lambda1$1$1 => apply$Lambda1$1$1(obj, new Lambda1$2$2 () )} +//│ fun apply$Lambda1$2$1(this, f) = +//│ f match {case obj: Lambda1$3$2 => apply$Lambda1$3$2(obj, this.x)} +//│ fun foo$1(x) = +//│ new Lambda1$2$1 (x) match {case obj: Lambda1$2$1 => apply$Lambda1$2$1(obj, new Lambda1$3$2 () )} //│ fun main$$3() = -//│ foo(#2) -//│ fun apply$Lambda1$2$2(this, z) = +//│ foo$1(#2) +//│ fun apply$Lambda1$3$2(this, z) = //│ (z + #1) -//│ class Lambda1$1$1(x) { +//│ class Lambda1$2$1(x) { //│ } -//│ class Lambda1$2$2() { +//│ class Lambda1$3$2() { //│ } -//│ [mono] ┌───┬─────────────────────────────────────────────────┐ -//│ │ 1 │ main$$3() │ -//│ │ 2 │ fun foo(x) = │ -//│ │ 3 │ (new Lambda1$1$1 (x) , )(new Lambda1$2$2 () ) │ -//│ │ 4 │ fun main$$3() = │ -//│ │ 5 │ foo(#2) │ -//│ │ 6 │ class Lambda1$1$1(x) { │ -//│ │ 7 │ } │ -//│ │ 8 │ class Lambda1$2$2() { │ -//│ │ 9 │ } │ -//│ └───┴─────────────────────────────────────────────────┘ -//│ [mono] evaluating main$$3, rests: HashSet() -//│ [mono] ========== updating main$$3 ========== -//│ [mono] main$$3: () -> *6*=[*6*=...]972540 @{} -//│ [mono] ┌ EVAL foo(#2) -//│ [mono] │ ┌ EVAL foo -//│ [mono] │ └ EVAL [foo(x) given {}]292788 -//│ [mono] │ ┌ EVAL #2 -//│ [mono] │ └ EVAL [2]44328 -//│ [mono] │ ┌ SPEC CALL foo with ([2]44328) -//│ [mono] │ │ comparing (([]249361,0)) with (Plain([2]884782)) -//│ [mono] │ │ first time encounter foo -//│ [mono] │ │ evaluating foo, rests: HashSet() -//│ [mono] │ │ ========== updating foo ========== -//│ [mono] │ │ foo: (([2]884782,1)) -> *5*=[*5*=...]221469 @{main$$3} -//│ [mono] │ │ ┌ EVAL (new Lambda1$1$1 (x) , )(new Lambda1$2$2 () ) -//│ [mono] │ │ │ ┌ EVAL (new Lambda1$1$1 (x) , )(new Lambda1$2$2 () ) -//│ [mono] │ │ │ │ ┌ EVAL (new Lambda1$1$1 (x) , ) -//│ [mono] │ │ │ │ │ ┌ EVAL new Lambda1$1$1 (x) -//│ [mono] │ │ │ │ │ │ ┌ EVAL new Lambda1$1$1 (x) -//│ [mono] │ │ │ │ │ │ │ ┌ EVAL x -//│ [mono] │ │ │ │ │ │ │ └ EVAL [2]884782 -//│ [mono] │ │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [2]884782}]241619 -//│ [mono] │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [2]884782}]241619 -//│ [mono] │ │ │ │ └ EVAL [Lambda1$1$1@{x: [2]884782}]241619 -//│ [mono] │ │ │ │ ┌ EVAL new Lambda1$2$2 () -//│ [mono] │ │ │ │ │ ┌ EVAL new Lambda1$2$2 () -//│ [mono] │ │ │ │ │ └ EVAL [Lambda1$2$2@{}]748878 -//│ [mono] │ │ │ │ └ EVAL [Lambda1$2$2@{}]748878 -//│ [mono] │ │ │ │ ┌ SPEC CALL apply$Lambda1$1$1 with ([Lambda1$1$1@{x: [2]884782}]318593, [Lambda1$2$2@{}]748878) -//│ [mono] │ │ │ │ │ comparing (([]844284,0), ([]374495,0)) with (Plain([Lambda1$1$1@{x: [2]884782}]890026), Plain([Lambda1$2$2@{}]97477)) -//│ [mono] │ │ │ │ │ first time encounter apply$Lambda1$1$1 -//│ [mono] │ │ │ │ │ evaluating apply$Lambda1$1$1, rests: HashSet() -//│ [mono] │ │ │ │ │ ========== updating apply$Lambda1$1$1 ========== -//│ [mono] │ │ │ │ │ apply$Lambda1$1$1: (([Lambda1$1$1@{x: [2]884782}]890026,2) X ([Lambda1$2$2@{}]97477,1)) -> *7*=[*7*=...]154467 @{foo} -//│ [mono] │ │ │ │ │ ┌ EVAL f(this.x) -//│ [mono] │ │ │ │ │ │ ┌ EVAL f -//│ [mono] │ │ │ │ │ │ └ EVAL [Lambda1$2$2@{}]97477 -//│ [mono] │ │ │ │ │ │ ┌ EVAL this.x -//│ [mono] │ │ │ │ │ │ │ ┌ EVAL this -//│ [mono] │ │ │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [2]884782}]890026 -//│ [mono] │ │ │ │ │ │ └ EVAL [2]124143 -//│ [mono] │ │ │ │ │ │ ┌ SPEC CALL apply$Lambda1$2$2 with ([Lambda1$2$2@{}]965309, [2]124143) -//│ [mono] │ │ │ │ │ │ │ comparing (([]522878,0), ([]246758,0)) with (Plain([Lambda1$2$2@{}]151341), Plain([2]679883)) -//│ [mono] │ │ │ │ │ │ │ first time encounter apply$Lambda1$2$2 -//│ [mono] │ │ │ │ │ │ │ evaluating apply$Lambda1$2$2, rests: HashSet() -//│ [mono] │ │ │ │ │ │ │ ========== updating apply$Lambda1$2$2 ========== -//│ [mono] │ │ │ │ │ │ │ apply$Lambda1$2$2: (([Lambda1$2$2@{}]151341,1) X ([2]679883,1)) -> *8*=[*8*=...]427103 @{apply$Lambda1$1$1} -//│ [mono] │ │ │ │ │ │ │ ┌ EVAL (z + #1) -//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL z -//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [2]679883 -//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL #1 -//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [1]447076 -//│ [mono] │ │ │ │ │ │ │ └ EVAL [3]329135 -//│ [mono] │ │ │ │ │ │ │ comparing [*8*=...]427103 with [3]329135 -//│ [mono] │ │ │ │ │ │ │ apply$Lambda1$2$2: (([Lambda1$2$2@{}]151341,1) X ([2]679883,1)) -> *8*=[3]329135 @{apply$Lambda1$1$1} -//│ [mono] │ │ │ │ │ │ └ SPEC CALL [*8*=[3]329135]597991 -//│ [mono] │ │ │ │ │ │ call result: [*8*=[3]329135]597991 -//│ [mono] │ │ │ │ │ │ merging []963048 with [*8*=[3]329135]597991 -//│ [mono] │ │ │ │ │ │ result [*8*=[3]329135]570854 -//│ [mono] │ │ │ │ │ └ EVAL [*8*=[3]329135]570854 -//│ [mono] │ │ │ │ │ comparing [*7*=...]154467 with [*8*=[3]329135]570854 -//│ [mono] │ │ │ │ │ apply$Lambda1$1$1: (([Lambda1$1$1@{x: [2]884782}]890026,2) X ([Lambda1$2$2@{}]97477,1)) -> *7*=[*8*=[3]329135]570854 @{foo} -//│ [mono] │ │ │ │ └ SPEC CALL [*7*=[*8*=[3]329135]570854]518807 -//│ [mono] │ │ │ │ call result: [*7*=[*8*=[3]329135]570854]518807 -//│ [mono] │ │ │ │ merging []524013 with [*7*=[*8*=[3]329135]570854]518807 -//│ [mono] │ │ │ │ result [*7*=[*8*=[3]329135]570854]58141 -//│ [mono] │ │ │ └ EVAL [*7*=[*8*=[3]329135]570854]58141 -//│ [mono] │ │ └ EVAL [*7*=[*8*=[3]329135]570854]58141 -//│ [mono] │ │ comparing [*5*=...]221469 with [*7*=[*8*=[3]329135]570854]58141 -//│ [mono] │ │ foo: (([2]884782,1)) -> *5*=[*7*=[*8*=[3]329135]570854]58141 @{main$$3} -//│ [mono] │ └ SPEC CALL [*5*=[*7*=[*8*=[3]329135]570854]58141]733948 -//│ [mono] │ call result: [*5*=[*7*=[*8*=[3]329135]570854]58141]733948 -//│ [mono] │ merging []860020 with [*5*=[*7*=[*8*=[3]329135]570854]58141]733948 -//│ [mono] │ result [*5*=[*7*=[*8*=[3]329135]570854]58141]992452 -//│ [mono] └ EVAL [*5*=[*7*=[*8*=[3]329135]570854]58141]992452 -//│ [mono] comparing [*6*=...]972540 with [*5*=[*7*=[*8*=[3]329135]570854]58141]992452 -//│ [mono] main$$3: () -> *6*=[*5*=[*7*=[*8*=[3]329135]570854]58141]992452 @{} -//│ [mono] -//│ [mono] ==============final function signatures================== -//│ [mono] apply$Lambda1$1$1: ([Lambda1$1$1@{x: [2]884782}]890026 X [Lambda1$2$2@{}]97477) -> *7*=[*8*=[3]329135]570854 -//│ [mono] foo: ([2]884782) -> *5*=[*7*=[*8*=[3]329135]570854]58141 -//│ [mono] main$$3: () -> *6*=[*5*=[*7*=[*8*=[3]329135]570854]58141]992452 -//│ [mono] apply$Lambda1$2$2: ([Lambda1$2$2@{}]151341 X [2]679883) -> *8*=[3]329135 :mono fun f(x) = @@ -809,159 +346,22 @@ f(1) //│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(f), Tup(_: IntLit(1)))) //│ Lifted: //│ TypingUnit { -//│ class Lambda1$1$1(x,) {fun apply = y, => f (+ ((this).x,) (y,),)} -//│ fun f = x, => {('(' {new Lambda1$1$1(x,) {}}, ')').apply (+ (x,) (1,),)} -//│ Code(List(f (1,))) +//│ class Lambda1$2$1(x,) {fun apply = y, => f$1 (+ ((this).x,) (y,),)} +//│ fun f$1 = x, => {('(' {new Lambda1$2$1(x,) {}}, ')').apply (+ (x,) (1,),)} +//│ Code(List(f$1 (1,))) //│ } //│ Mono: //│ -//│ Mono result: +//│ Defunc result: //│ main$$2() -//│ fun apply$Lambda1$1$1(this, y) = -//│ f((this.x + y)) -//│ fun f(x) = -//│ new Lambda1$1$1 (x) match {case obj: Lambda1$1$1 => apply$Lambda1$1$1(obj, (x + #1))} +//│ fun apply$Lambda1$2$1(this, y) = +//│ f$1((this.x + y)) +//│ fun f$1(x) = +//│ new Lambda1$2$1 (x) match {case obj: Lambda1$2$1 => apply$Lambda1$2$1(obj, (x + #1))} //│ fun main$$2() = -//│ f(#1) -//│ class Lambda1$1$1(x) { +//│ f$1(#1) +//│ class Lambda1$2$1(x) { //│ } -//│ [mono] ┌───┬────────────────────────────────────────────┐ -//│ │ 1 │ main$$2() │ -//│ │ 2 │ fun f(x) = │ -//│ │ 3 │ (new Lambda1$1$1 (x) , ).apply((x + #1)) │ -//│ │ 4 │ fun main$$2() = │ -//│ │ 5 │ f(#1) │ -//│ │ 6 │ class Lambda1$1$1(x) { │ -//│ │ 7 │ } │ -//│ └───┴────────────────────────────────────────────┘ -//│ [mono] evaluating main$$2, rests: HashSet() -//│ [mono] ========== updating main$$2 ========== -//│ [mono] main$$2: () -> *10*=[*10*=...]263411 @{} -//│ [mono] ┌ EVAL f(#1) -//│ [mono] │ ┌ EVAL f -//│ [mono] │ └ EVAL [f(x) given {}]652110 -//│ [mono] │ ┌ EVAL #1 -//│ [mono] │ └ EVAL [1]711504 -//│ [mono] │ ┌ SPEC CALL f with ([1]711504) -//│ [mono] │ │ comparing (([]43423,0)) with (Plain([1]551120)) -//│ [mono] │ │ first time encounter f -//│ [mono] │ │ evaluating f, rests: HashSet() -//│ [mono] │ │ ========== updating f ========== -//│ [mono] │ │ f: (([1]551120,1)) -> *9*=[*9*=...]272491 @{main$$2} -//│ [mono] │ │ ┌ EVAL (new Lambda1$1$1 (x) , ).apply((x + #1)) -//│ [mono] │ │ │ ┌ EVAL (new Lambda1$1$1 (x) , ).apply((x + #1)) -//│ [mono] │ │ │ │ ┌ EVAL (new Lambda1$1$1 (x) , ).apply -//│ [mono] │ │ │ │ │ ┌ EVAL (new Lambda1$1$1 (x) , ) -//│ [mono] │ │ │ │ │ │ ┌ EVAL new Lambda1$1$1 (x) -//│ [mono] │ │ │ │ │ │ │ ┌ EVAL new Lambda1$1$1 (x) -//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL x -//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [1]551120 -//│ [mono] │ │ │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [1]551120}]260519 -//│ [mono] │ │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [1]551120}]260519 -//│ [mono] │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [1]551120}]260519 -//│ [mono] │ │ │ │ └ EVAL [apply$Lambda1$1$1(y) given {this: [Lambda1$1$1@{x: [1]551120}]70265}]125057 -//│ [mono] │ │ │ │ ┌ EVAL (x + #1) -//│ [mono] │ │ │ │ │ ┌ EVAL x -//│ [mono] │ │ │ │ │ └ EVAL [1]551120 -//│ [mono] │ │ │ │ │ ┌ EVAL #1 -//│ [mono] │ │ │ │ │ └ EVAL [1]850514 -//│ [mono] │ │ │ │ └ EVAL [2]225064 -//│ [mono] │ │ │ │ ┌ SPEC CALL apply$Lambda1$1$1 with ([Lambda1$1$1@{x: [1]551120}]70265, [2]225064) -//│ [mono] │ │ │ │ │ comparing (([]331078,0), ([]317254,0)) with (Plain([Lambda1$1$1@{x: [1]551120}]899673), Plain([2]885273)) -//│ [mono] │ │ │ │ │ first time encounter apply$Lambda1$1$1 -//│ [mono] │ │ │ │ │ evaluating apply$Lambda1$1$1, rests: HashSet() -//│ [mono] │ │ │ │ │ ========== updating apply$Lambda1$1$1 ========== -//│ [mono] │ │ │ │ │ apply$Lambda1$1$1: (([Lambda1$1$1@{x: [1]551120}]899673,2) X ([2]885273,1)) -> *11*=[*11*=...]628892 @{f} -//│ [mono] │ │ │ │ │ ┌ EVAL f((this.x + y)) -//│ [mono] │ │ │ │ │ │ ┌ EVAL f -//│ [mono] │ │ │ │ │ │ └ EVAL [f(x) given {}]710076 -//│ [mono] │ │ │ │ │ │ ┌ EVAL (this.x + y) -//│ [mono] │ │ │ │ │ │ │ ┌ EVAL this.x -//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL this -//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [Lambda1$1$1@{x: [1]551120}]899673 -//│ [mono] │ │ │ │ │ │ │ └ EVAL [1]546668 -//│ [mono] │ │ │ │ │ │ │ ┌ EVAL y -//│ [mono] │ │ │ │ │ │ │ └ EVAL [2]885273 -//│ [mono] │ │ │ │ │ │ └ EVAL [3]620274 -//│ [mono] │ │ │ │ │ │ ┌ SPEC CALL f with ([3]620274) -//│ [mono] │ │ │ │ │ │ │ comparing (([1]551120,1)) with (Plain([*LIT*]137338)) -//│ [mono] │ │ │ │ │ │ │ find finer args -//│ [mono] │ │ │ │ │ │ └ SPEC CALL [*9*=[*9*=...]272491]118118 -//│ [mono] │ │ │ │ │ │ call result: [*9*=[*9*=...]272491]118118 -//│ [mono] │ │ │ │ │ │ merging []294569 with [*9*=[*9*=...]272491]118118 -//│ [mono] │ │ │ │ │ │ result [*9*=[*9*=...]272491]493312 -//│ [mono] │ │ │ │ │ └ EVAL [*9*=[*9*=...]272491]493312 -//│ [mono] │ │ │ │ │ comparing [*11*=...]628892 with [*9*=[*9*=...]272491]493312 -//│ [mono] │ │ │ │ │ apply$Lambda1$1$1: (([Lambda1$1$1@{x: [1]551120}]899673,2) X ([2]885273,1)) -> *11*=[*9*=[*9*=...]272491]493312 @{f} -//│ [mono] │ │ │ │ └ SPEC CALL [*11*=[*9*=[*9*=...]272491]493312]410939 -//│ [mono] │ │ │ │ call result: [*11*=[*9*=[*9*=...]272491]493312]410939 -//│ [mono] │ │ │ │ merging []909038 with [*11*=[*9*=[*9*=...]272491]493312]410939 -//│ [mono] │ │ │ │ result [*11*=[*9*=[*9*=...]272491]493312]350837 -//│ [mono] │ │ │ └ EVAL [*11*=[*9*=[*9*=...]272491]493312]350837 -//│ [mono] │ │ └ EVAL [*11*=[*9*=[*9*=...]272491]493312]350837 -//│ [mono] │ │ comparing [*9*=...]272491 with [*11*=[*9*=[*9*=...]272491]493312]350837 -//│ [mono] │ │ f: (([*LIT*]137338,100000)) -> *9*=[*11*=[*9*=...]493312]350837 @{main$$2, apply$Lambda1$1$1} -//│ [mono] │ └ SPEC CALL [*9*=[*11*=[*9*=...]493312]350837]49790 -//│ [mono] │ call result: [*9*=[*11*=[*9*=...]493312]350837]49790 -//│ [mono] │ merging []617696 with [*9*=[*11*=[*9*=...]493312]350837]49790 -//│ [mono] │ result [*9*=[*11*=[*9*=...]493312]350837]43915 -//│ [mono] └ EVAL [*9*=[*11*=[*9*=...]493312]350837]43915 -//│ [mono] comparing [*10*=...]263411 with [*9*=[*11*=[*9*=...]493312]350837]43915 -//│ [mono] main$$2: () -> *10*=[*9*=[*11*=[*9*=...]493312]350837]43915 @{} -//│ [mono] evaluating f, rests: HashSet() -//│ [mono] ========== updating f ========== -//│ [mono] f: (([*LIT*]137338,100000)) -> *9*=[*11*=[*9*=...]493312]350837 @{main$$2, apply$Lambda1$1$1} -//│ [mono] ┌ EVAL new Lambda1$1$1 (x) .apply((x + #1)) -//│ [mono] │ ┌ EVAL new Lambda1$1$1 (x) .apply -//│ [mono] │ │ ┌ EVAL new Lambda1$1$1 (x) -//│ [mono] │ │ │ ┌ EVAL x -//│ [mono] │ │ │ └ EVAL [*LIT*]137338 -//│ [mono] │ │ └ EVAL [Lambda1$1$1@{x: [*LIT*]137338}]873892 -//│ [mono] │ └ EVAL [apply$Lambda1$1$1(y) given {this: [Lambda1$1$1@{x: [*LIT*]137338}]255015}]243686 -//│ [mono] │ ┌ EVAL (x + #1) -//│ [mono] │ │ ┌ EVAL x -//│ [mono] │ │ └ EVAL [*LIT*]137338 -//│ [mono] │ │ ┌ EVAL #1 -//│ [mono] │ │ └ EVAL [1]484532 -//│ [mono] │ └ EVAL [*LIT*]349816 -//│ [mono] │ ┌ SPEC CALL apply$Lambda1$1$1 with ([Lambda1$1$1@{x: [*LIT*]137338}]255015, [*LIT*]349816) -//│ [mono] │ │ comparing (([Lambda1$1$1@{x: [1]551120}]899673,2), ([2]885273,1)) with (Plain([Lambda1$1$1@{x: [*LIT*]62147}]944362), Plain([*LIT*]621953)) -//│ [mono] │ │ find finer args -//│ [mono] │ └ SPEC CALL [*11*=[*9*=[*11*=...]350837]493312]198943 -//│ [mono] │ call result: [*11*=[*9*=[*11*=...]350837]493312]198943 -//│ [mono] │ merging []583841 with [*11*=[*9*=[*11*=...]350837]493312]198943 -//│ [mono] │ result [*11*=[*9*=[*11*=...]350837]493312]422571 -//│ [mono] └ EVAL [*11*=[*9*=[*11*=...]350837]493312]422571 -//│ [mono] comparing [*11*=[*9*=...]493312]350837 with [*11*=[*9*=[*11*=...]350837]493312]422571 -//│ [mono] f: (([*LIT*]137338,100000)) -> *9*=[*11*=[*9*=...]493312]422571 @{main$$2, apply$Lambda1$1$1} -//│ [mono] evaluating apply$Lambda1$1$1, rests: HashSet() -//│ [mono] ========== updating apply$Lambda1$1$1 ========== -//│ [mono] apply$Lambda1$1$1: (([Lambda1$1$1@{x: [*LIT*]62147}]944362,100001) X ([*LIT*]621953,100000)) -> *11*=[*9*=[*11*=...]422571]493312 @{f} -//│ [mono] ┌ EVAL f((this.x + y)) -//│ [mono] │ ┌ EVAL f -//│ [mono] │ └ EVAL [f(x) given {}]539759 -//│ [mono] │ ┌ EVAL (this.x + y) -//│ [mono] │ │ ┌ EVAL this.x -//│ [mono] │ │ │ ┌ EVAL this -//│ [mono] │ │ │ └ EVAL [Lambda1$1$1@{x: [*LIT*]62147}]944362 -//│ [mono] │ │ └ EVAL [*LIT*]31983 -//│ [mono] │ │ ┌ EVAL y -//│ [mono] │ │ └ EVAL [*LIT*]621953 -//│ [mono] │ └ EVAL [*LIT*]252249 -//│ [mono] │ ┌ SPEC CALL f with ([*LIT*]252249) -//│ [mono] │ │ comparing (([*LIT*]137338,100000)) with (Plain([*LIT*]266429)) -//│ [mono] │ └ SPEC CALL [*9*=[*11*=[*9*=...]493312]422571]665559 -//│ [mono] │ call result: [*9*=[*11*=[*9*=...]493312]422571]665559 -//│ [mono] │ merging []782169 with [*9*=[*11*=[*9*=...]493312]422571]665559 -//│ [mono] │ result [*9*=[*11*=[*9*=...]493312]422571]449699 -//│ [mono] └ EVAL [*9*=[*11*=[*9*=...]493312]422571]449699 -//│ [mono] comparing [*9*=[*11*=...]422571]493312 with [*9*=[*11*=[*9*=...]493312]422571]449699 -//│ [mono] apply$Lambda1$1$1: (([Lambda1$1$1@{x: [*LIT*]62147}]944362,100001) X ([*LIT*]621953,100000)) -> *11*=[*9*=[*11*=...]422571]449699 @{f} -//│ [mono] -//│ [mono] ==============final function signatures================== -//│ [mono] apply$Lambda1$1$1: ([Lambda1$1$1@{x: [*LIT*]62147}]944362 X [*LIT*]621953) -> *11*=[*9*=[*11*=...]422571]449699 -//│ [mono] f: ([*LIT*]137338) -> *9*=[*11*=[*9*=...]449699]422571 -//│ [mono] main$$2: () -> *10*=[*9*=[*11*=[*9*=...]449699]422571]43915 :mono @@ -974,106 +374,21 @@ f(1) //│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), App(Var(f), Tup(_: Var(x))))), App(Var(f), Tup(_: IntLit(0))), App(Var(f), Tup(_: IntLit(1)))) //│ Lifted: //│ TypingUnit { -//│ fun f = x, => f (x,) -//│ Code(List(f (0,))) -//│ Code(List(f (1,))) +//│ fun f$1 = x, => f$1 (x,) +//│ Code(List(f$1 (0,))) +//│ Code(List(f$1 (1,))) //│ } //│ Mono: //│ -//│ Mono result: +//│ Defunc result: //│ main$$1() //│ main$$2() -//│ fun f(x) = -//│ f(x) +//│ fun f$1(x) = +//│ f$1(x) //│ fun main$$2() = -//│ f(#1) +//│ f$1(#1) //│ fun main$$1() = -//│ f(#0) -//│ [mono] ┌───┬─────────────────┐ -//│ │ 1 │ main$$1() │ -//│ │ 2 │ main$$2() │ -//│ │ 3 │ fun f(x) = │ -//│ │ 4 │ f(x) │ -//│ │ 5 │ fun main$$2() = │ -//│ │ 6 │ f(#1) │ -//│ │ 7 │ fun main$$1() = │ -//│ │ 8 │ f(#0) │ -//│ └───┴─────────────────┘ -//│ [mono] evaluating main$$2, rests: HashSet(main$$1) -//│ [mono] ========== updating main$$2 ========== -//│ [mono] main$$2: () -> *14*=[*14*=...]114427 @{} -//│ [mono] ┌ EVAL f(#1) -//│ [mono] │ ┌ EVAL f -//│ [mono] │ └ EVAL [f(x) given {}]878353 -//│ [mono] │ ┌ EVAL #1 -//│ [mono] │ └ EVAL [1]317186 -//│ [mono] │ ┌ SPEC CALL f with ([1]317186) -//│ [mono] │ │ comparing (([]498318,0)) with (Plain([1]240397)) -//│ [mono] │ │ first time encounter f -//│ [mono] │ │ evaluating f, rests: HashSet(main$$1) -//│ [mono] │ │ ========== updating f ========== -//│ [mono] │ │ f: (([1]240397,1)) -> *12*=[*12*=...]683949 @{main$$2} -//│ [mono] │ │ ┌ EVAL f(x) -//│ [mono] │ │ │ ┌ EVAL f -//│ [mono] │ │ │ └ EVAL [f(x) given {}]464149 -//│ [mono] │ │ │ ┌ EVAL x -//│ [mono] │ │ │ └ EVAL [1]240397 -//│ [mono] │ │ │ ┌ SPEC CALL f with ([1]240397) -//│ [mono] │ │ │ │ comparing (([1]240397,1)) with (Plain([1]240397)) -//│ [mono] │ │ │ └ SPEC CALL [*12*=[*12*=...]683949]736838 -//│ [mono] │ │ │ call result: [*12*=[*12*=...]683949]736838 -//│ [mono] │ │ │ merging []992352 with [*12*=[*12*=...]683949]736838 -//│ [mono] │ │ │ result [*12*=[*12*=...]683949]258386 -//│ [mono] │ │ └ EVAL [*12*=[*12*=...]683949]258386 -//│ [mono] │ │ comparing [*12*=...]683949 with [*12*=[*12*=...]683949]258386 -//│ [mono] │ │ f: (([1]240397,1)) -> *12*=[*12*=...]258386 @{main$$2, f} -//│ [mono] │ └ SPEC CALL [*12*=[*12*=...]258386]262549 -//│ [mono] │ call result: [*12*=[*12*=...]258386]262549 -//│ [mono] │ merging []614422 with [*12*=[*12*=...]258386]262549 -//│ [mono] │ result [*12*=[*12*=...]258386]136125 -//│ [mono] └ EVAL [*12*=[*12*=...]258386]136125 -//│ [mono] comparing [*14*=...]114427 with [*12*=[*12*=...]258386]136125 -//│ [mono] main$$2: () -> *14*=[*12*=[*12*=...]258386]136125 @{} -//│ [mono] evaluating main$$1, rests: HashSet() -//│ [mono] ========== updating main$$1 ========== -//│ [mono] main$$1: () -> *13*=[*13*=...]360724 @{} -//│ [mono] ┌ EVAL f(#0) -//│ [mono] │ ┌ EVAL f -//│ [mono] │ └ EVAL [f(x) given {}]311634 -//│ [mono] │ ┌ EVAL #0 -//│ [mono] │ └ EVAL [0]971042 -//│ [mono] │ ┌ SPEC CALL f with ([0]971042) -//│ [mono] │ │ comparing (([1]240397,1)) with (Plain([*LIT*]435420)) -//│ [mono] │ │ find finer args -//│ [mono] │ └ SPEC CALL [*12*=[*12*=...]258386]981428 -//│ [mono] │ call result: [*12*=[*12*=...]258386]981428 -//│ [mono] │ merging []487067 with [*12*=[*12*=...]258386]981428 -//│ [mono] │ result [*12*=[*12*=...]258386]655301 -//│ [mono] └ EVAL [*12*=[*12*=...]258386]655301 -//│ [mono] comparing [*13*=...]360724 with [*12*=[*12*=...]258386]655301 -//│ [mono] main$$1: () -> *13*=[*12*=[*12*=...]258386]655301 @{} -//│ [mono] evaluating f, rests: HashSet() -//│ [mono] ========== updating f ========== -//│ [mono] f: (([*LIT*]435420,100000)) -> *12*=[*12*=...]258386 @{main$$2, f, main$$1} -//│ [mono] ┌ EVAL f(x) -//│ [mono] │ ┌ EVAL f -//│ [mono] │ └ EVAL [f(x) given {}]209798 -//│ [mono] │ ┌ EVAL x -//│ [mono] │ └ EVAL [*LIT*]435420 -//│ [mono] │ ┌ SPEC CALL f with ([*LIT*]435420) -//│ [mono] │ │ comparing (([*LIT*]435420,100000)) with (Plain([*LIT*]435420)) -//│ [mono] │ └ SPEC CALL [*12*=[*12*=...]258386]550649 -//│ [mono] │ call result: [*12*=[*12*=...]258386]550649 -//│ [mono] │ merging []375204 with [*12*=[*12*=...]258386]550649 -//│ [mono] │ result [*12*=[*12*=...]258386]123356 -//│ [mono] └ EVAL [*12*=[*12*=...]258386]123356 -//│ [mono] comparing [*12*=...]258386 with [*12*=[*12*=...]258386]123356 -//│ [mono] f: (([*LIT*]435420,100000)) -> *12*=[*12*=...]123356 @{main$$2, f, main$$1} -//│ [mono] -//│ [mono] ==============final function signatures================== -//│ [mono] f: ([*LIT*]435420) -> *12*=[*12*=...]123356 -//│ [mono] main$$2: () -> *14*=[*12*=[*12*=...]123356]136125 -//│ [mono] main$$1: () -> *13*=[*12*=[*12*=...]123356]655301 +//│ f$1(#0) :mono class Cons(e, tail) { @@ -1106,29 +421,29 @@ foo(new Lambda2(2)) //│ class Lambda2$4(a,) { //│ fun apply = l, => {('(' new Cons$1((this).a, l,) {}, ')').count ()} //│ } -//│ fun foo = x, => {+ ((x).apply (new Cons$1(1, new Nil$2() {},) {},),) ((x).apply (new Nil$2() {},),)} -//│ Code(List(foo (new Lambda$3() {},))) -//│ Code(List(foo (new Lambda2$4(2,) {},))) +//│ fun foo$1 = x, => {+ ((x).apply (new Cons$1(1, new Nil$2() {},) {},),) ((x).apply (new Nil$2() {},),)} +//│ Code(List(foo$1 (new Lambda$3() {},))) +//│ Code(List(foo$1 (new Lambda2$4(2,) {},))) //│ } //│ Mono: //│ -//│ Mono result: +//│ Defunc result: //│ main$$5() //│ main$$6() //│ fun count$Cons$1(this) = -//│ (#1 + this.tail match {case obj: Nil$2 => count$Nil$2(obj); case obj: Cons$1 => count$Cons$1(obj)}) +//│ (#1 + this.tail match {case obj: Cons$1 => count$Cons$1(obj); case obj: Nil$2 => count$Nil$2(obj)}) +//│ fun foo$1(x) = +//│ (x match {case obj: Lambda2$4 => apply$Lambda2$4(obj, new Cons$1 (#1, new Nil$2 () ) ); case obj: Lambda$3 => apply$Lambda$3(obj, new Cons$1 (#1, new Nil$2 () ) )} + x match {case obj: Lambda2$4 => apply$Lambda2$4(obj, new Nil$2 () ); case obj: Lambda$3 => apply$Lambda$3(obj, new Nil$2 () )}) //│ fun apply$Lambda$3(this, l) = //│ l match {case obj: Cons$1 => count$Cons$1(obj); case obj: Nil$2 => count$Nil$2(obj)} //│ fun count$Nil$2(this) = //│ #0 -//│ fun foo(x) = -//│ (x match {case obj: Lambda$3 => apply$Lambda$3(obj, new Cons$1 (#1, new Nil$2 () ) ); case obj: Lambda2$4 => apply$Lambda2$4(obj, new Cons$1 (#1, new Nil$2 () ) )} + x match {case obj: Lambda$3 => apply$Lambda$3(obj, new Nil$2 () ); case obj: Lambda2$4 => apply$Lambda2$4(obj, new Nil$2 () )}) //│ fun apply$Lambda2$4(this, l) = //│ new Cons$1 (this.a, l) match {case obj: Cons$1 => count$Cons$1(obj)} //│ fun main$$6() = -//│ foo(new Lambda2$4 (#2) ) +//│ foo$1(new Lambda2$4 (#2) ) //│ fun main$$5() = -//│ foo(new Lambda$3 () ) +//│ foo$1(new Lambda$3 () ) //│ class Nil$2() { //│ } //│ class Lambda2$4(a) { @@ -1137,393 +452,61 @@ foo(new Lambda2(2)) //│ } //│ class Lambda$3() { //│ } -//│ [mono] ┌────┬───────────────────────────────────────────────────────────────────────┐ -//│ │ 1 │ main$$5() │ -//│ │ 2 │ main$$6() │ -//│ │ 3 │ fun foo(x) = │ -//│ │ 4 │ (x.apply(new Cons$1 (#1, new Nil$2 () ) ) + x.apply(new Nil$2 () )) │ -//│ │ 5 │ fun main$$6() = │ -//│ │ 6 │ foo(new Lambda2$4 (#2) ) │ -//│ │ 7 │ fun main$$5() = │ -//│ │ 8 │ foo(new Lambda$3 () ) │ -//│ │ 9 │ class Nil$2() { │ -//│ │ 10 │ } │ -//│ │ 11 │ class Lambda2$4(a) { │ -//│ │ 12 │ } │ -//│ │ 13 │ class Cons$1(e, tail) { │ -//│ │ 14 │ } │ -//│ │ 15 │ class Lambda$3() { │ -//│ │ 16 │ } │ -//│ └────┴───────────────────────────────────────────────────────────────────────┘ -//│ [mono] evaluating main$$6, rests: HashSet(main$$5) -//│ [mono] ========== updating main$$6 ========== -//│ [mono] main$$6: () -> *17*=[*17*=...]135615 @{} -//│ [mono] ┌ EVAL foo(new Lambda2$4 (#2) ) -//│ [mono] │ ┌ EVAL foo -//│ [mono] │ └ EVAL [foo(x) given {}]490848 -//│ [mono] │ ┌ EVAL new Lambda2$4 (#2) -//│ [mono] │ │ ┌ EVAL #2 -//│ [mono] │ │ └ EVAL [2]752278 -//│ [mono] │ └ EVAL [Lambda2$4@{a: [2]752278}]743793 -//│ [mono] │ ┌ SPEC CALL foo with ([Lambda2$4@{a: [2]752278}]743793) -//│ [mono] │ │ comparing (([]205038,0)) with (Plain([Lambda2$4@{a: [2]752278}]622915)) -//│ [mono] │ │ first time encounter foo -//│ [mono] │ │ evaluating foo, rests: HashSet(main$$5) -//│ [mono] │ │ ========== updating foo ========== -//│ [mono] │ │ foo: (([Lambda2$4@{a: [2]752278}]622915,2)) -> *15*=[*15*=...]11760 @{main$$6} -//│ [mono] │ │ ┌ EVAL (x.apply(new Cons$1 (#1, new Nil$2 () ) ) + x.apply(new Nil$2 () )) -//│ [mono] │ │ │ ┌ EVAL (x.apply(new Cons$1 (#1, new Nil$2 () ) ) + x.apply(new Nil$2 () )) -//│ [mono] │ │ │ │ ┌ EVAL x.apply(new Cons$1 (#1, new Nil$2 () ) ) -//│ [mono] │ │ │ │ │ ┌ EVAL x.apply -//│ [mono] │ │ │ │ │ │ ┌ EVAL x -//│ [mono] │ │ │ │ │ │ └ EVAL [Lambda2$4@{a: [2]752278}]622915 -//│ [mono] │ │ │ │ │ └ EVAL [apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]112002}]760449 -//│ [mono] │ │ │ │ │ ┌ EVAL new Cons$1 (#1, new Nil$2 () ) -//│ [mono] │ │ │ │ │ │ ┌ EVAL #1 -//│ [mono] │ │ │ │ │ │ └ EVAL [1]224258 -//│ [mono] │ │ │ │ │ │ ┌ EVAL new Nil$2 () -//│ [mono] │ │ │ │ │ │ └ EVAL [Nil$2@{}]644816 -//│ [mono] │ │ │ │ │ └ EVAL [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]606578 -//│ [mono] │ │ │ │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]112002, [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]606578) -//│ [mono] │ │ │ │ │ │ comparing (([]184127,0), ([]757322,0)) with (Plain([Lambda2$4@{a: [2]752278}]258791), Plain([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571)) -//│ [mono] │ │ │ │ │ │ first time encounter apply$Lambda2$4 -//│ [mono] │ │ │ │ │ │ evaluating apply$Lambda2$4, rests: HashSet(main$$5) -//│ [mono] │ │ │ │ │ │ ========== updating apply$Lambda2$4 ========== -//│ [mono] │ │ │ │ │ │ apply$Lambda2$4: (([Lambda2$4@{a: [2]752278}]258791,2) X ([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571,3)) -> *18*=[*18*=...]325416 @{foo} -//│ [mono] │ │ │ │ │ │ ┌ EVAL (new Cons$1 (this.a, l) , ).count() -//│ [mono] │ │ │ │ │ │ │ ┌ EVAL (new Cons$1 (this.a, l) , ).count() -//│ [mono] │ │ │ │ │ │ │ │ ┌ EVAL (new Cons$1 (this.a, l) , ).count -//│ [mono] │ │ │ │ │ │ │ │ │ ┌ EVAL (new Cons$1 (this.a, l) , ) -//│ [mono] │ │ │ │ │ │ │ │ │ │ ┌ EVAL new Cons$1 (this.a, l) -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL this.a -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL this -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ └ EVAL [Lambda2$4@{a: [2]752278}]258791 -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ └ EVAL [2]414137 -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL l -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ └ EVAL [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571 -//│ [mono] │ │ │ │ │ │ │ │ │ │ └ EVAL [Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]202264 -//│ [mono] │ │ │ │ │ │ │ │ │ └ EVAL [Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]202264 -//│ [mono] │ │ │ │ │ │ │ │ └ EVAL [count$Cons$1() given {this: [Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]469034}]762670 -//│ [mono] │ │ │ │ │ │ │ │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]469034) -//│ [mono] │ │ │ │ │ │ │ │ │ comparing (([]624201,0)) with (Plain([Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]240592)) -//│ [mono] │ │ │ │ │ │ │ │ │ first time encounter count$Cons$1 -//│ [mono] │ │ │ │ │ │ │ │ │ evaluating count$Cons$1, rests: HashSet(main$$5) -//│ [mono] │ │ │ │ │ │ │ │ │ ========== updating count$Cons$1 ========== -//│ [mono] │ │ │ │ │ │ │ │ │ count$Cons$1: (([Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]240592,5)) -> *19*=[*19*=...]579205 @{apply$Lambda2$4} -//│ [mono] │ │ │ │ │ │ │ │ │ ┌ EVAL (#1 + this.tail.count()) -//│ [mono] │ │ │ │ │ │ │ │ │ │ ┌ EVAL #1 -//│ [mono] │ │ │ │ │ │ │ │ │ │ └ EVAL [1]754681 -//│ [mono] │ │ │ │ │ │ │ │ │ │ ┌ EVAL this.tail.count() -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL this.tail.count -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL this.tail -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ │ ┌ EVAL this -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ │ └ EVAL [Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]240592 -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ └ EVAL [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]407077 -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ └ EVAL [count$Cons$1() given {this: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]62302}]807916 -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]62302) -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ comparing (([Cons$1@{e: [2]414137, tail: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571}]240592,5)) with (Plain([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965)) -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ │ find finer args -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ └ SPEC CALL [*19*=[*19*=...]579205]73107 -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ call result: [*19*=[*19*=...]579205]73107 -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ merging []606375 with [*19*=[*19*=...]579205]73107 -//│ [mono] │ │ │ │ │ │ │ │ │ │ │ result [*19*=[*19*=...]579205]716762 -//│ [mono] │ │ │ │ │ │ │ │ │ │ └ EVAL [*19*=[*19*=...]579205]716762 -//│ [mono] │ │ │ │ │ │ │ │ │ └ EVAL [*LIT*]636435 -//│ [mono] │ │ │ │ │ │ │ │ │ comparing [*19*=...]579205 with [*LIT*]636435 -//│ [mono] │ │ │ │ │ │ │ │ │ adding these funcs to queue: Set(apply$Lambda2$4, count$Cons$1) -//│ [mono] │ │ │ │ │ │ │ │ │ count$Cons$1: (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) -> *19*=[*LIT*]636435 @{apply$Lambda2$4, count$Cons$1} -//│ [mono] │ │ │ │ │ │ │ │ └ SPEC CALL [*19*=[*LIT*]636435]475732 -//│ [mono] │ │ │ │ │ │ │ │ call result: [*19*=[*LIT*]636435]475732 -//│ [mono] │ │ │ │ │ │ │ │ merging []889370 with [*19*=[*LIT*]636435]475732 -//│ [mono] │ │ │ │ │ │ │ │ result [*19*=[*LIT*]636435]780388 -//│ [mono] │ │ │ │ │ │ │ └ EVAL [*19*=[*LIT*]636435]780388 -//│ [mono] │ │ │ │ │ │ └ EVAL [*19*=[*LIT*]636435]780388 -//│ [mono] │ │ │ │ │ │ comparing [*18*=...]325416 with [*19*=[*LIT*]636435]780388 -//│ [mono] │ │ │ │ │ │ apply$Lambda2$4: (([Lambda2$4@{a: [2]752278}]258791,2) X ([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571,3)) -> *18*=[*19*=[*LIT*]636435]780388 @{foo} -//│ [mono] │ │ │ │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]636435]780388]749644 -//│ [mono] │ │ │ │ │ call result: [*18*=[*19*=[*LIT*]636435]780388]749644 -//│ [mono] │ │ │ │ │ merging []80780 with [*18*=[*19*=[*LIT*]636435]780388]749644 -//│ [mono] │ │ │ │ │ result [*18*=[*19*=[*LIT*]636435]780388]819398 -//│ [mono] │ │ │ │ └ EVAL [*18*=[*19*=[*LIT*]636435]780388]819398 -//│ [mono] │ │ │ │ ┌ EVAL x.apply(new Nil$2 () ) -//│ [mono] │ │ │ │ │ ┌ EVAL x.apply -//│ [mono] │ │ │ │ │ │ ┌ EVAL x -//│ [mono] │ │ │ │ │ │ └ EVAL [Lambda2$4@{a: [2]752278}]622915 -//│ [mono] │ │ │ │ │ └ EVAL [apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]577458}]352590 -//│ [mono] │ │ │ │ │ ┌ EVAL new Nil$2 () -//│ [mono] │ │ │ │ │ └ EVAL [Nil$2@{}]906549 -//│ [mono] │ │ │ │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]577458, [Nil$2@{}]906549) -//│ [mono] │ │ │ │ │ │ comparing (([Lambda2$4@{a: [2]752278}]258791,2), ([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]236571,3)) with (Plain([Lambda2$4@{a: [2]752278}]91381), Plain([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016)) -//│ [mono] │ │ │ │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]636435]780388]193076 -//│ [mono] │ │ │ │ │ call result: [*18*=[*19*=[*LIT*]636435]780388]193076 -//│ [mono] │ │ │ │ │ merging []687883 with [*18*=[*19*=[*LIT*]636435]780388]193076 -//│ [mono] │ │ │ │ │ result [*18*=[*19*=[*LIT*]636435]780388]314840 -//│ [mono] │ │ │ │ └ EVAL [*18*=[*19*=[*LIT*]636435]780388]314840 -//│ [mono] │ │ │ └ EVAL [*LIT*]67195 -//│ [mono] │ │ └ EVAL [*LIT*]67195 -//│ [mono] │ │ comparing [*15*=...]11760 with [*LIT*]67195 -//│ [mono] │ │ adding these funcs to queue: Set(main$$6) -//│ [mono] │ │ foo: (([Lambda2$4@{a: [2]752278}]622915,2)) -> *15*=[*LIT*]67195 @{main$$6} -//│ [mono] │ └ SPEC CALL [*15*=[*LIT*]67195]546539 -//│ [mono] │ call result: [*15*=[*LIT*]67195]546539 -//│ [mono] │ merging []239270 with [*15*=[*LIT*]67195]546539 -//│ [mono] │ result [*15*=[*LIT*]67195]203295 -//│ [mono] └ EVAL [*15*=[*LIT*]67195]203295 -//│ [mono] comparing [*17*=...]135615 with [*15*=[*LIT*]67195]203295 -//│ [mono] main$$6: () -> *17*=[*15*=[*LIT*]67195]203295 @{} -//│ [mono] evaluating count$Cons$1, rests: HashSet(apply$Lambda2$4, main$$6, main$$5) -//│ [mono] ========== updating count$Cons$1 ========== -//│ [mono] count$Cons$1: (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) -> *19*=[*LIT*]636435 @{apply$Lambda2$4, count$Cons$1} -//│ [mono] ┌ EVAL (#1 + this.tail.count()) -//│ [mono] │ ┌ EVAL #1 -//│ [mono] │ └ EVAL [1]710392 -//│ [mono] │ ┌ EVAL this.tail.count() -//│ [mono] │ │ ┌ EVAL this.tail.count -//│ [mono] │ │ │ ┌ EVAL this.tail -//│ [mono] │ │ │ │ ┌ EVAL this -//│ [mono] │ │ │ │ └ EVAL [Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965 -//│ [mono] │ │ │ └ EVAL [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]237888 -//│ [mono] │ │ └ EVAL [count$Cons$1() given {this: [Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]474004} | count$Nil$2() given {this: [Nil$2@{}]615890}]52513 -//│ [mono] │ │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]474004) -//│ [mono] │ │ │ comparing (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) with (Plain([Cons$1@{e: [*LIT*]825810, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]451748}]686061)) -//│ [mono] │ │ └ SPEC CALL [*19*=[*LIT*]636435]675852 -//│ [mono] │ │ call result: [*19*=[*LIT*]636435]675852 -//│ [mono] │ │ ┌ SPEC CALL count$Nil$2 with ([Nil$2@{}]615890) -//│ [mono] │ │ │ comparing (([]333536,0)) with (Plain([Nil$2@{}]560462)) -//│ [mono] │ │ │ first time encounter count$Nil$2 -//│ [mono] │ │ │ evaluating count$Nil$2, rests: HashSet(apply$Lambda2$4, main$$6, main$$5) -//│ [mono] │ │ │ ========== updating count$Nil$2 ========== -//│ [mono] │ │ │ count$Nil$2: (([Nil$2@{}]560462,1)) -> *20*=[*20*=...]763413 @{count$Cons$1} -//│ [mono] │ │ │ ┌ EVAL #0 -//│ [mono] │ │ │ └ EVAL [0]326453 -//│ [mono] │ │ │ comparing [*20*=...]763413 with [0]326453 -//│ [mono] │ │ │ count$Nil$2: (([Nil$2@{}]560462,1)) -> *20*=[0]326453 @{count$Cons$1} -//│ [mono] │ │ └ SPEC CALL [*20*=[0]326453]576211 -//│ [mono] │ │ call result: [*20*=[0]326453]576211 -//│ [mono] │ │ merging []342306 with [*19*=[*LIT*]636435]675852 -//│ [mono] │ │ result [*19*=[*LIT*]636435]599657 -//│ [mono] │ │ merging [*19*=[*LIT*]636435]599657 with [*20*=[0]326453]576211 -//│ [mono] │ │ result [*20*=[0]326453 | *19*=[*LIT*]636435]99068 -//│ [mono] │ └ EVAL [*20*=[0]326453 | *19*=[*LIT*]636435]99068 -//│ [mono] └ EVAL [*LIT*]513374 -//│ [mono] comparing [*LIT*]636435 with [*LIT*]513374 -//│ [mono] count$Cons$1: (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) -> *19*=[*LIT*]513374 @{apply$Lambda2$4, count$Cons$1} -//│ [mono] evaluating apply$Lambda2$4, rests: HashSet(main$$6, main$$5) -//│ [mono] ========== updating apply$Lambda2$4 ========== -//│ [mono] apply$Lambda2$4: (([Lambda2$4@{a: [2]752278}]91381,2) X ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) -> *18*=[*19*=[*LIT*]513374]780388 @{foo} -//│ [mono] ┌ EVAL new Cons$1 (this.a, l) .count() -//│ [mono] │ ┌ EVAL new Cons$1 (this.a, l) .count -//│ [mono] │ │ ┌ EVAL new Cons$1 (this.a, l) -//│ [mono] │ │ │ ┌ EVAL this.a -//│ [mono] │ │ │ │ ┌ EVAL this -//│ [mono] │ │ │ │ └ EVAL [Lambda2$4@{a: [2]752278}]91381 -//│ [mono] │ │ │ └ EVAL [2]422643 -//│ [mono] │ │ │ ┌ EVAL l -//│ [mono] │ │ │ └ EVAL [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016 -//│ [mono] │ │ └ EVAL [Cons$1@{e: [2]422643, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016}]482343 -//│ [mono] │ └ EVAL [count$Cons$1() given {this: [Cons$1@{e: [2]422643, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016}]553308}]479302 -//│ [mono] │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [2]422643, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016}]553308) -//│ [mono] │ │ comparing (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) with (Plain([Cons$1@{e: [*LIT*]498010, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]567350}]697741)) -//│ [mono] │ └ SPEC CALL [*19*=[*LIT*]513374]918946 -//│ [mono] │ call result: [*19*=[*LIT*]513374]918946 -//│ [mono] │ merging []317828 with [*19*=[*LIT*]513374]918946 -//│ [mono] │ result [*19*=[*LIT*]513374]980184 -//│ [mono] └ EVAL [*19*=[*LIT*]513374]980184 -//│ [mono] comparing [*19*=[*LIT*]513374]780388 with [*19*=[*LIT*]513374]980184 -//│ [mono] apply$Lambda2$4: (([Lambda2$4@{a: [2]752278}]91381,2) X ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) -> *18*=[*19*=[*LIT*]513374]980184 @{foo} -//│ [mono] evaluating main$$6, rests: HashSet(main$$5) -//│ [mono] ========== updating main$$6 ========== -//│ [mono] main$$6: () -> *17*=[*15*=[*LIT*]67195]203295 @{} -//│ [mono] ┌ EVAL foo(new Lambda2$4 (#2) ) -//│ [mono] │ ┌ EVAL foo -//│ [mono] │ └ EVAL [foo(x) given {}]152639 -//│ [mono] │ ┌ EVAL new Lambda2$4 (#2) -//│ [mono] │ │ ┌ EVAL #2 -//│ [mono] │ │ └ EVAL [2]386284 -//│ [mono] │ └ EVAL [Lambda2$4@{a: [2]386284}]259571 -//│ [mono] │ ┌ SPEC CALL foo with ([Lambda2$4@{a: [2]386284}]259571) -//│ [mono] │ │ comparing (([Lambda2$4@{a: [2]752278}]622915,2)) with (Plain([Lambda2$4@{a: [2]541966}]360855)) -//│ [mono] │ └ SPEC CALL [*15*=[*LIT*]67195]902018 -//│ [mono] │ call result: [*15*=[*LIT*]67195]902018 -//│ [mono] │ merging []617314 with [*15*=[*LIT*]67195]902018 -//│ [mono] │ result [*15*=[*LIT*]67195]963429 -//│ [mono] └ EVAL [*15*=[*LIT*]67195]963429 -//│ [mono] comparing [*15*=[*LIT*]67195]203295 with [*15*=[*LIT*]67195]963429 -//│ [mono] main$$6: () -> *17*=[*15*=[*LIT*]67195]963429 @{} -//│ [mono] evaluating main$$5, rests: HashSet() -//│ [mono] ========== updating main$$5 ========== -//│ [mono] main$$5: () -> *16*=[*16*=...]810726 @{} -//│ [mono] ┌ EVAL foo(new Lambda$3 () ) -//│ [mono] │ ┌ EVAL foo -//│ [mono] │ └ EVAL [foo(x) given {}]647833 -//│ [mono] │ ┌ EVAL new Lambda$3 () -//│ [mono] │ └ EVAL [Lambda$3@{}]123140 -//│ [mono] │ ┌ SPEC CALL foo with ([Lambda$3@{}]123140) -//│ [mono] │ │ comparing (([Lambda2$4@{a: [2]752278}]622915,2)) with (Plain([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780)) -//│ [mono] │ │ find finer args -//│ [mono] │ └ SPEC CALL [*15*=[*LIT*]67195]41480 -//│ [mono] │ call result: [*15*=[*LIT*]67195]41480 -//│ [mono] │ merging []590767 with [*15*=[*LIT*]67195]41480 -//│ [mono] │ result [*15*=[*LIT*]67195]298303 -//│ [mono] └ EVAL [*15*=[*LIT*]67195]298303 -//│ [mono] comparing [*16*=...]810726 with [*15*=[*LIT*]67195]298303 -//│ [mono] main$$5: () -> *16*=[*15*=[*LIT*]67195]298303 @{} -//│ [mono] evaluating foo, rests: HashSet() -//│ [mono] ========== updating foo ========== -//│ [mono] foo: (([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780,3)) -> *15*=[*LIT*]67195 @{main$$6, main$$5} -//│ [mono] ┌ EVAL (x.apply(new Cons$1 (#1, new Nil$2 () ) ) + x.apply(new Nil$2 () )) -//│ [mono] │ ┌ EVAL x.apply(new Cons$1 (#1, new Nil$2 () ) ) -//│ [mono] │ │ ┌ EVAL x.apply -//│ [mono] │ │ │ ┌ EVAL x -//│ [mono] │ │ │ └ EVAL [Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780 -//│ [mono] │ │ └ EVAL [apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]992279} | apply$Lambda$3(l) given {this: [Lambda$3@{}]793571}]732519 -//│ [mono] │ │ ┌ EVAL new Cons$1 (#1, new Nil$2 () ) -//│ [mono] │ │ │ ┌ EVAL #1 -//│ [mono] │ │ │ └ EVAL [1]456454 -//│ [mono] │ │ │ ┌ EVAL new Nil$2 () -//│ [mono] │ │ │ └ EVAL [Nil$2@{}]142364 -//│ [mono] │ │ └ EVAL [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]903239 -//│ [mono] │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]992279, [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]903239) -//│ [mono] │ │ │ comparing (([Lambda2$4@{a: [2]752278}]91381,2), ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) with (Plain([Lambda2$4@{a: [2]752278}]138839), Plain([Cons$1@{e: [1]995583, tail: [Nil$2@{}]927154} | Nil$2@{}]504129)) -//│ [mono] │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]513374]980184]739668 -//│ [mono] │ │ call result: [*18*=[*19*=[*LIT*]513374]980184]739668 -//│ [mono] │ │ ┌ SPEC CALL apply$Lambda$3 with ([Lambda$3@{}]793571, [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]903239) -//│ [mono] │ │ │ comparing (([]652955,0), ([]66778,0)) with (Plain([Lambda$3@{}]988452), Plain([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]209615)) -//│ [mono] │ │ │ first time encounter apply$Lambda$3 -//│ [mono] │ │ │ evaluating apply$Lambda$3, rests: HashSet() -//│ [mono] │ │ │ ========== updating apply$Lambda$3 ========== -//│ [mono] │ │ │ apply$Lambda$3: (([Lambda$3@{}]988452,1) X ([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]209615,3)) -> *21*=[*21*=...]989283 @{foo} -//│ [mono] │ │ │ ┌ EVAL l.count() -//│ [mono] │ │ │ │ ┌ EVAL l.count() -//│ [mono] │ │ │ │ │ ┌ EVAL l.count -//│ [mono] │ │ │ │ │ │ ┌ EVAL l -//│ [mono] │ │ │ │ │ │ └ EVAL [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]209615 -//│ [mono] │ │ │ │ │ └ EVAL [count$Cons$1() given {this: [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]477491}]445270 -//│ [mono] │ │ │ │ │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]477491) -//│ [mono] │ │ │ │ │ │ comparing (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) with (Plain([Cons$1@{e: [*LIT*]608008, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]782101}]639500)) -//│ [mono] │ │ │ │ │ └ SPEC CALL [*19*=[*LIT*]513374]172112 -//│ [mono] │ │ │ │ │ call result: [*19*=[*LIT*]513374]172112 -//│ [mono] │ │ │ │ │ merging []756915 with [*19*=[*LIT*]513374]172112 -//│ [mono] │ │ │ │ │ result [*19*=[*LIT*]513374]286621 -//│ [mono] │ │ │ │ └ EVAL [*19*=[*LIT*]513374]286621 -//│ [mono] │ │ │ └ EVAL [*19*=[*LIT*]513374]286621 -//│ [mono] │ │ │ comparing [*21*=...]989283 with [*19*=[*LIT*]513374]286621 -//│ [mono] │ │ │ apply$Lambda$3: (([Lambda$3@{}]988452,1) X ([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]209615,3)) -> *21*=[*19*=[*LIT*]513374]286621 @{foo} -//│ [mono] │ │ └ SPEC CALL [*21*=[*19*=[*LIT*]513374]286621]767426 -//│ [mono] │ │ call result: [*21*=[*19*=[*LIT*]513374]286621]767426 -//│ [mono] │ │ merging []319684 with [*18*=[*19*=[*LIT*]513374]980184]739668 -//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184]830712 -//│ [mono] │ │ merging [*18*=[*19*=[*LIT*]513374]980184]830712 with [*21*=[*19*=[*LIT*]513374]286621]767426 -//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184 | *21*=[*19*=[*LIT*]513374]286621]77626 -//│ [mono] │ └ EVAL [*18*=[*19*=[*LIT*]513374]980184 | *21*=[*19*=[*LIT*]513374]286621]77626 -//│ [mono] │ ┌ EVAL x.apply(new Nil$2 () ) -//│ [mono] │ │ ┌ EVAL x.apply -//│ [mono] │ │ │ ┌ EVAL x -//│ [mono] │ │ │ └ EVAL [Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780 -//│ [mono] │ │ └ EVAL [apply$Lambda$3(l) given {this: [Lambda$3@{}]442930} | apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]808077}]684849 -//│ [mono] │ │ ┌ EVAL new Nil$2 () -//│ [mono] │ │ └ EVAL [Nil$2@{}]686449 -//│ [mono] │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]808077, [Nil$2@{}]686449) -//│ [mono] │ │ │ comparing (([Lambda2$4@{a: [2]752278}]91381,2), ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) with (Plain([Lambda2$4@{a: [2]752278}]939024), Plain([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]368348)) -//│ [mono] │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]513374]980184]590325 -//│ [mono] │ │ call result: [*18*=[*19*=[*LIT*]513374]980184]590325 -//│ [mono] │ │ ┌ SPEC CALL apply$Lambda$3 with ([Lambda$3@{}]442930, [Nil$2@{}]686449) -//│ [mono] │ │ │ comparing (([Lambda$3@{}]988452,1), ([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]209615,3)) with (Plain([Lambda$3@{}]195071), Plain([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468)) -//│ [mono] │ │ │ find finer args -//│ [mono] │ │ └ SPEC CALL [*21*=[*19*=[*LIT*]513374]286621]970626 -//│ [mono] │ │ call result: [*21*=[*19*=[*LIT*]513374]286621]970626 -//│ [mono] │ │ merging []845011 with [*18*=[*19*=[*LIT*]513374]980184]590325 -//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184]981314 -//│ [mono] │ │ merging [*18*=[*19*=[*LIT*]513374]980184]981314 with [*21*=[*19*=[*LIT*]513374]286621]970626 -//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184 | *21*=[*19*=[*LIT*]513374]286621]312038 -//│ [mono] │ └ EVAL [*18*=[*19*=[*LIT*]513374]980184 | *21*=[*19*=[*LIT*]513374]286621]312038 -//│ [mono] └ EVAL [*LIT*]52478 -//│ [mono] comparing [*LIT*]67195 with [*LIT*]52478 -//│ [mono] foo: (([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780,3)) -> *15*=[*LIT*]52478 @{main$$6, main$$5} -//│ [mono] evaluating apply$Lambda$3, rests: HashSet() -//│ [mono] ========== updating apply$Lambda$3 ========== -//│ [mono] apply$Lambda$3: (([Lambda$3@{}]195071,1) X ([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468,4)) -> *21*=[*19*=[*LIT*]513374]286621 @{foo} -//│ [mono] ┌ EVAL l.count() -//│ [mono] │ ┌ EVAL l.count -//│ [mono] │ │ ┌ EVAL l -//│ [mono] │ │ └ EVAL [Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468 -//│ [mono] │ └ EVAL [count$Nil$2() given {this: [Nil$2@{}]202478} | count$Cons$1() given {this: [Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]305777}]658816 -//│ [mono] │ ┌ SPEC CALL count$Nil$2 with ([Nil$2@{}]202478) -//│ [mono] │ │ comparing (([Nil$2@{}]560462,1)) with (Plain([Nil$2@{}]689512)) -//│ [mono] │ └ SPEC CALL [*20*=[0]326453]434307 -//│ [mono] │ call result: [*20*=[0]326453]434307 -//│ [mono] │ ┌ SPEC CALL count$Cons$1 with ([Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]305777) -//│ [mono] │ │ comparing (([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965,100005)) with (Plain([Cons$1@{e: [*LIT*]232010, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]655168}]625967)) -//│ [mono] │ └ SPEC CALL [*19*=[*LIT*]513374]232324 -//│ [mono] │ call result: [*19*=[*LIT*]513374]232324 -//│ [mono] │ merging []923571 with [*20*=[0]326453]434307 -//│ [mono] │ result [*20*=[0]326453]909846 -//│ [mono] │ merging [*20*=[0]326453]909846 with [*19*=[*LIT*]513374]232324 -//│ [mono] │ result [*19*=[*LIT*]513374 | *20*=[0]326453]994788 -//│ [mono] └ EVAL [*19*=[*LIT*]513374 | *20*=[0]326453]994788 -//│ [mono] comparing [*19*=[*LIT*]513374]286621 with [*19*=[*LIT*]513374 | *20*=[0]326453]994788 -//│ [mono] adding these funcs to queue: Set(foo) -//│ [mono] apply$Lambda$3: (([Lambda$3@{}]195071,1) X ([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468,4)) -> *21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 @{foo} -//│ [mono] evaluating foo, rests: HashSet() -//│ [mono] ========== updating foo ========== -//│ [mono] foo: (([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780,3)) -> *15*=[*LIT*]52478 @{main$$6, main$$5} -//│ [mono] ┌ EVAL (x.apply(new Cons$1 (#1, new Nil$2 () ) ) + x.apply(new Nil$2 () )) -//│ [mono] │ ┌ EVAL x.apply(new Cons$1 (#1, new Nil$2 () ) ) -//│ [mono] │ │ ┌ EVAL x.apply -//│ [mono] │ │ │ ┌ EVAL x -//│ [mono] │ │ │ └ EVAL [Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780 -//│ [mono] │ │ └ EVAL [apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]464438} | apply$Lambda$3(l) given {this: [Lambda$3@{}]190192}]291875 -//│ [mono] │ │ ┌ EVAL new Cons$1 (#1, new Nil$2 () ) -//│ [mono] │ │ │ ┌ EVAL #1 -//│ [mono] │ │ │ └ EVAL [1]942335 -//│ [mono] │ │ │ ┌ EVAL new Nil$2 () -//│ [mono] │ │ │ └ EVAL [Nil$2@{}]201541 -//│ [mono] │ │ └ EVAL [Cons$1@{e: [1]942335, tail: [Nil$2@{}]201541}]426752 -//│ [mono] │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]464438, [Cons$1@{e: [1]942335, tail: [Nil$2@{}]201541}]426752) -//│ [mono] │ │ │ comparing (([Lambda2$4@{a: [2]752278}]91381,2), ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) with (Plain([Lambda2$4@{a: [2]752278}]209630), Plain([Cons$1@{e: [1]95172, tail: [Nil$2@{}]958140} | Nil$2@{}]795421)) -//│ [mono] │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]513374]980184]78520 -//│ [mono] │ │ call result: [*18*=[*19*=[*LIT*]513374]980184]78520 -//│ [mono] │ │ ┌ SPEC CALL apply$Lambda$3 with ([Lambda$3@{}]190192, [Cons$1@{e: [1]942335, tail: [Nil$2@{}]201541}]426752) -//│ [mono] │ │ │ comparing (([Lambda$3@{}]195071,1), ([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468,4)) with (Plain([Lambda$3@{}]905090), Plain([Cons$1@{e: [1]541051, tail: [Nil$2@{}]530234} | Nil$2@{}]17701)) -//│ [mono] │ │ └ SPEC CALL [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]788726 -//│ [mono] │ │ call result: [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]788726 -//│ [mono] │ │ merging []853155 with [*18*=[*19*=[*LIT*]513374]980184]78520 -//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184]259345 -//│ [mono] │ │ merging [*18*=[*19*=[*LIT*]513374]980184]259345 with [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]788726 -//│ [mono] │ │ result [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 | *18*=[*19*=[*LIT*]513374]980184]545957 -//│ [mono] │ └ EVAL [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 | *18*=[*19*=[*LIT*]513374]980184]545957 -//│ [mono] │ ┌ EVAL x.apply(new Nil$2 () ) -//│ [mono] │ │ ┌ EVAL x.apply -//│ [mono] │ │ │ ┌ EVAL x -//│ [mono] │ │ │ └ EVAL [Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780 -//│ [mono] │ │ └ EVAL [apply$Lambda$3(l) given {this: [Lambda$3@{}]218234} | apply$Lambda2$4(l) given {this: [Lambda2$4@{a: [2]752278}]851318}]806082 -//│ [mono] │ │ ┌ EVAL new Nil$2 () -//│ [mono] │ │ └ EVAL [Nil$2@{}]205827 -//│ [mono] │ │ ┌ SPEC CALL apply$Lambda2$4 with ([Lambda2$4@{a: [2]752278}]851318, [Nil$2@{}]205827) -//│ [mono] │ │ │ comparing (([Lambda2$4@{a: [2]752278}]91381,2), ([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016,4)) with (Plain([Lambda2$4@{a: [2]752278}]249616), Plain([Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]796479)) -//│ [mono] │ │ └ SPEC CALL [*18*=[*19*=[*LIT*]513374]980184]519713 -//│ [mono] │ │ call result: [*18*=[*19*=[*LIT*]513374]980184]519713 -//│ [mono] │ │ ┌ SPEC CALL apply$Lambda$3 with ([Lambda$3@{}]218234, [Nil$2@{}]205827) -//│ [mono] │ │ │ comparing (([Lambda$3@{}]195071,1), ([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468,4)) with (Plain([Lambda$3@{}]575409), Plain([Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]107065)) -//│ [mono] │ │ └ SPEC CALL [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]183012 -//│ [mono] │ │ call result: [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]183012 -//│ [mono] │ │ merging []7556 with [*18*=[*19*=[*LIT*]513374]980184]519713 -//│ [mono] │ │ result [*18*=[*19*=[*LIT*]513374]980184]657118 -//│ [mono] │ │ merging [*18*=[*19*=[*LIT*]513374]980184]657118 with [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788]183012 -//│ [mono] │ │ result [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 | *18*=[*19*=[*LIT*]513374]980184]952944 -//│ [mono] │ └ EVAL [*21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 | *18*=[*19*=[*LIT*]513374]980184]952944 -//│ [mono] └ EVAL [*LIT*]197099 -//│ [mono] comparing [*LIT*]52478 with [*LIT*]197099 -//│ [mono] foo: (([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780,3)) -> *15*=[*LIT*]197099 @{main$$6, main$$5} -//│ [mono] -//│ [mono] ==============final function signatures================== -//│ [mono] count$Cons$1: ([Cons$1@{e: [*LIT*]868503, tail: [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]644463}]473965) -> *19*=[*LIT*]513374 -//│ [mono] apply$Lambda$3: ([Lambda$3@{}]195071 X [Nil$2@{} | Cons$1@{e: [1]456454, tail: [Nil$2@{}]142364}]785468) -> *21*=[*19*=[*LIT*]513374 | *20*=[0]326453]994788 -//│ [mono] count$Nil$2: ([Nil$2@{}]560462) -> *20*=[0]326453 -//│ [mono] foo: ([Lambda$3@{} | Lambda2$4@{a: [2]752278}]149780) -> *15*=[*LIT*]197099 -//│ [mono] apply$Lambda2$4: ([Lambda2$4@{a: [2]752278}]91381 X [Nil$2@{} | Cons$1@{e: [1]224258, tail: [Nil$2@{}]644816}]429016) -> *18*=[*19*=[*LIT*]513374]980184 -//│ [mono] main$$6: () -> *17*=[*15*=[*LIT*]197099]963429 -//│ [mono] main$$5: () -> *16*=[*15*=[*LIT*]197099]298303 + +:mono +class Cons(e, tail) { + fun count() = 1 + tail.count() +} +class Nil() { + fun count() = 0 +} +fun foo(x) = + x(new Cons(1, new Nil())) + x(new Nil()) +foo(l => l.count()) +foo(l => (new Cons(2, l)).count()) +//│ |#class| |Cons|(|e|,| |tail|)| |{|→|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#fun| |foo|(|x|)| |#=| |→|x|(|#new| |Cons|(|1|,| |#new| |Nil|(||)|)|)| |+| |x|(|#new| |Nil|(||)|)|←|↵|foo|(|l| |=>| |l|.count|(||)|)|↵|foo|(|l| |=>| |(|#new| |Cons|(|2|,| |l|)|)|.count|(||)|)| +//│ Parsed: {class Cons(e, tail,) {fun count = => + (1,) ((tail).count (),)}; class Nil() {fun count = => 0}; fun foo = x, => {+ (x (new Cons(1, new Nil() {},) {},),) (x (new Nil() {},),)}; foo (l, => (l).count (),); foo (l, => ('(' new Cons(2, l,) {}, ')').count (),)} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: Lam(Tup(_: Var(l)), App(Sel(Var(l), count), Tup())))), App(Var(foo), Tup(_: Lam(Tup(_: Var(l)), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Cons),2, l,)), TypingUnit(List())))), count), Tup()))))) +//│ Lifted: +//│ TypingUnit { +//│ class Cons$1(e, tail,) {fun count = => + (1,) (((this).tail).count (),)} +//│ class Nil$2() {fun count = => 0} +//│ class Lambda1$2$3() {fun apply = l, => (l).count ()} +//│ class Lambda1$3$4() { +//│ fun apply = l, => ('(' new Cons$1(2, l,) {}, ')').count () +//│ } +//│ fun foo$1 = x, => {+ (x (new Cons$1(1, new Nil$2() {},) {},),) (x (new Nil$2() {},),)} +//│ Code(List(foo$1 ({new Lambda1$2$3() {}},))) +//│ Code(List(foo$1 ({new Lambda1$3$4() {}},))) +//│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$5() +//│ main$$6() +//│ fun count$Cons$1(this) = +//│ (#1 + this.tail match {case obj: Cons$1 => count$Cons$1(obj); case obj: Nil$2 => count$Nil$2(obj)}) +//│ fun foo$1(x) = +//│ (x match {case obj: Lambda1$3$4 => apply$Lambda1$3$4(obj, new Cons$1 (#1, new Nil$2 () ) ); case obj: Lambda1$2$3 => apply$Lambda1$2$3(obj, new Cons$1 (#1, new Nil$2 () ) )} + x match {case obj: Lambda1$3$4 => apply$Lambda1$3$4(obj, new Nil$2 () ); case obj: Lambda1$2$3 => apply$Lambda1$2$3(obj, new Nil$2 () )}) +//│ fun count$Nil$2(this) = +//│ #0 +//│ fun main$$6() = +//│ foo$1(new Lambda1$3$4 () ) +//│ fun main$$5() = +//│ foo$1(new Lambda1$2$3 () ) +//│ fun apply$Lambda1$3$4(this, l) = +//│ new Cons$1 (#2, l) match {case obj: Cons$1 => count$Cons$1(obj)} +//│ fun apply$Lambda1$2$3(this, l) = +//│ l match {case obj: Cons$1 => count$Cons$1(obj); case obj: Nil$2 => count$Nil$2(obj)} +//│ class Lambda1$3$4() { +//│ } +//│ class Nil$2() { +//│ } +//│ class Cons$1(e, tail) { +//│ } +//│ class Lambda1$2$3() { +//│ } // :mono class E() { @@ -1601,8 +584,8 @@ gen() //│ TypingUnit { //│ class List$1(l, hasTail,) {} //│ class Nil$2(hasTail,) {} -//│ fun gen = => {if (anyUnknown) then new List$1(gen (), true,) {} else new Nil$2(false,) {}} -//│ Code(List(gen ())) +//│ fun gen$1 = => {if (anyUnknown) then new List$1(gen$1 (), true,) {} else new Nil$2(false,) {}} +//│ Code(List(gen$1 ())) //│ } @@ -1644,7 +627,7 @@ class OneInt(a){ //│ Code(List(('(' new OneInt$1(10,) {}, ')').fac ())) //│ } -// :mono +:mono trait AnyFoo { fun bar(b): int } @@ -1663,15 +646,36 @@ f(new FooMinus(2)) //│ TypingUnit(NuTypeDef(trait, AnyFoo, (), Tup(), (), TypingUnit(NuFunDef(None, bar, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(b))))),TypeName(int)))))), NuTypeDef(class, FooPlus, (), Tup(_: Var(a)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(b)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))))), NuTypeDef(class, FooMinus, (), Tup(_: Var(a)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(b)), App(App(Var(-), Tup(_: Var(a))), Tup(_: Var(b))))))), NuFunDef(None, f, [], Lam(Tup(_: Var(x)), App(Sel(Var(x), bar), Tup(_: IntLit(42))))), App(Var(f), Tup(_: New(Some((TypeName(FooPlus),1,)), TypingUnit(List())))), App(Var(f), Tup(_: New(Some((TypeName(FooMinus),2,)), TypingUnit(List()))))) //│ Lifted: //│ TypingUnit { -//│ trait AnyFoo$1[b]() {fun bar = b -> int} -//│ class FooPlus$2[b](#a,): AnyFoo$1 () {fun bar = b, => + ((this).a,) (b,)} -//│ class FooMinus$3[b](#a,): AnyFoo$1 () {fun bar = b, => - ((this).a,) (b,)} -//│ fun f = x, => (x).bar (42,) -//│ Code(List(f (new FooPlus$2(1,) {},))) -//│ Code(List(f (new FooMinus$3(2,) {},))) +//│ trait AnyFoo$1() {fun bar = b -> int} +//│ class FooPlus$2(#a,): AnyFoo$1 () {fun bar = b, => + ((this).a,) (b,)} +//│ class FooMinus$3(#a,): AnyFoo$1 () {fun bar = b, => - ((this).a,) (b,)} +//│ fun f$1 = x, => (x).bar (42,) +//│ Code(List(f$1 (new FooPlus$2(1,) {},))) +//│ Code(List(f$1 (new FooMinus$3(2,) {},))) +//│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$4() +//│ main$$5() +//│ fun bar$FooPlus$2(this, b) = +//│ (this.a + b) +//│ fun f$1(x) = +//│ x match {case obj: FooMinus$3 => bar$FooMinus$3(obj, #42); case obj: FooPlus$2 => bar$FooPlus$2(obj, #42)} +//│ fun main$$5() = +//│ f$1(new FooMinus$3 (#2) ) +//│ fun bar$FooMinus$3(this, b) = +//│ (this.a - b) +//│ fun main$$4() = +//│ f$1(new FooPlus$2 (#1) ) +//│ trait AnyFoo$1() { +//│ } +//│ class FooPlus$2(#a): AnyFoo$1() { +//│ } +//│ class FooMinus$3(#a): AnyFoo$1() { //│ } -// :mono +:mono fun f(x) = if x > any then 0 else g(x-1) @@ -1685,12 +689,22 @@ g(1) //│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, g, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(g), Tup(_: IntLit(1)))) //│ Lifted: //│ TypingUnit { -//│ fun f = x, => {if (> (x,) (any,)) then 0 else g (- (x,) (1,),)} -//│ fun g = x, => {if (> (x,) (any,)) then g (- (x,) (1,),) else f (- (x,) (2,),)} -//│ Code(List(g (1,))) +//│ fun f$1 = x, => {if (> (x,) (any,)) then 0 else g$2 (- (x,) (1,),)} +//│ fun g$2 = x, => {if (> (x,) (any,)) then g$2 (- (x,) (1,),) else f$1 (- (x,) (2,),)} +//│ Code(List(g$2 (1,))) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$2() +//│ fun f$1(x) = +//│ if (x > any) then #0 else g$2((x - #1)) +//│ fun g$2(x) = +//│ if (x > any) then g$2((x - #1)) else f$1((x - #2)) +//│ fun main$$2() = +//│ g$2(#1) -// :mono +:mono class OneInt(a){ fun get = a } @@ -1704,10 +718,24 @@ class OneBool(b){ //│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, get, [], Var(a)))), NuTypeDef(class, OneBool, (), Tup(_: Var(b)), (), TypingUnit(NuFunDef(None, get, [], Var(b)))), App(Sel(Bra(rcd = false, Tup(_: If((b) then new OneInt(1,) {}, Some(New(Some((TypeName(OneBool),true,)), TypingUnit(List())))))), get), Tup())) //│ Lifted: //│ TypingUnit { -//│ class OneInt$1(a,) {fun get = (this).a} -//│ class OneBool$2(b,) {fun get = (this).b} +//│ class OneInt$1(a,) {fun get = => (this).a} +//│ class OneBool$2(b,) {fun get = => (this).b} //│ Code(List(('(' if (b) then new OneInt$1(1,) {} else new OneBool$2(true,) {}, ')').get ())) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$2() +//│ fun get$OneInt$1(this) = +//│ this.a +//│ fun get$OneBool$2(this) = +//│ this.b +//│ fun main$$2() = +//│ if b then new OneInt$1 (#1) else new OneBool$2 (true) match {case obj: OneInt$1 => get$OneInt$1(obj); case obj: OneBool$2 => get$OneBool$2(obj)} +//│ class OneInt$1(a) { +//│ } +//│ class OneBool$2(b) { +//│ } // :mono class Bar(x: int) { @@ -1730,12 +758,103 @@ bar.car //│ TypingUnit { //│ class Bar$1(x: int,) { //│ fun FooMinus = y: int, => + ((this).x,) (y,) -//│ fun car = foo (2,) +//│ fun car = => foo (2,) //│ } //│ class Car$2() {fun da = b: Bar$1, => (b).foo (2,)} -//│ fun baz = b: Bar$1, => (b).foo (2,) -//│ let bar = Bar$1 (42,) -//│ Code(List(baz (bar,))) +//│ fun baz$2 = b: Bar$1, => (b).foo (2,) +//│ let bar$1 = => Bar$1 (42,) +//│ Code(List(baz$2 (bar,))) //│ Code(List((Car$2 ()).da (Bar$1 (1337,),))) //│ Code(List((bar).car)) //│ } + +:mono +class Sup(a){ + fun foo = a +} +class Sub(b): Sup(b+b){ +} +class Sub2(c): Sub(c+c){ + fun foo = a+c +} +(new Sub(10)).foo() +(new Sub2(c)).foo() +//│ |#class| |Sup|(|a|)|{|→|#fun| |foo| |#=| |a|←|↵|}|↵|#class| |Sub|(|b|)|#:| |Sup|(|b|+|b|)|{|↵|}|↵|#class| |Sub2|(|c|)|#:| |Sub|(|c|+|c|)|{|→|#fun| |foo| |#=| |a|+|c|←|↵|}|↵|(|#new| |Sub|(|10|)|)|.foo|(||)|↵|(|#new| |Sub2|(|c|)|)|.foo|(||)| +//│ Parsed: {class Sup(a,) {fun foo = a}; class Sub(b,): Sup (+ (b,) (b,),) {}; class Sub2(c,): Sub (+ (c,) (c,),) {fun foo = + (a,) (c,)}; ('(' new Sub(10,) {}, ')').foo (); ('(' new Sub2(c,) {}, ')').foo ()} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, Sup, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, foo, [], Var(a)))), NuTypeDef(class, Sub, (), Tup(_: Var(b)), (App(Var(Sup), Tup(_: App(App(Var(+), Tup(_: Var(b))), Tup(_: Var(b)))))), TypingUnit()), NuTypeDef(class, Sub2, (), Tup(_: Var(c)), (App(Var(Sub), Tup(_: App(App(Var(+), Tup(_: Var(c))), Tup(_: Var(c)))))), TypingUnit(NuFunDef(None, foo, [], App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(c)))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Sub),10,)), TypingUnit(List())))), foo), Tup()), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Sub2),c,)), TypingUnit(List())))), foo), Tup())) +//│ Lifted: +//│ TypingUnit { +//│ class Sup$1(a,) {fun foo = => (this).a} +//│ class Sub$2(b,): Sup$1 (+ ((this).b,) ((this).b,),) {} +//│ class Sub2$3(c,): Sub$2 (+ ((this).c,) ((this).c,),) {fun foo = => + ((this).a,) ((this).c,)} +//│ Code(List(('(' new Sub$2(10,) {}, ')').foo ())) +//│ Code(List(('(' new Sub2$3(c,) {}, ')').foo ())) +//│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$3() +//│ main$$4() +//│ fun main$$4() = +//│ new Sub2$3 (c) match {case obj: Sub2$3 => foo$Sub2$3(obj)} +//│ fun foo$Sup$1(this) = +//│ this.a +//│ fun foo$Sub2$3(this) = +//│ (this.a + this.c) +//│ fun main$$3() = +//│ new Sub$2 (#10) match {case obj: Sub$2 => foo$Sup$1(obj)} +//│ class Sub2$3(c): Sub$2((this.c + this.c)) { +//│ } +//│ class Sup$1(a) { +//│ } +//│ class Sub$2(b): Sup$1((this.b + this.b)) { +//│ } + +:mono +class Foo(f){ + fun foo = f(1) +} +class F1(): Foo(x => x+1){} +class F2(): Foo(x => x+2){} +(new F1()).foo() +(new F2()).foo() +//│ |#class| |Foo|(|f|)|{|→|#fun| |foo| |#=| |f|(|1|)|←|↵|}|↵|#class| |F1|(||)|#:| |Foo|(|x| |=>| |x|+|1|)|{||}|↵|#class| |F2|(||)|#:| |Foo|(|x| |=>| |x|+|2|)|{||}|↵|(|#new| |F1|(||)|)|.foo|(||)|↵|(|#new| |F2|(||)|)|.foo|(||)| +//│ Parsed: {class Foo(f,) {fun foo = f (1,)}; class F1(): Foo (x, => + (x,) (1,),) {}; class F2(): Foo (x, => + (x,) (2,),) {}; ('(' new F1() {}, ')').foo (); ('(' new F2() {}, ')').foo ()} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(_: Var(f)), (), TypingUnit(NuFunDef(None, foo, [], App(Var(f), Tup(_: IntLit(1)))))), NuTypeDef(class, F1, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1))))))), TypingUnit()), NuTypeDef(class, F2, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(2))))))), TypingUnit()), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(F1),)), TypingUnit(List())))), foo), Tup()), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(F2),)), TypingUnit(List())))), foo), Tup())) +//│ Lifted: +//│ TypingUnit { +//│ class Foo$1(f,) {fun foo = => (this).f (1,)} +//│ class F1$2_Lambda1$1$4(par$F1$2,) {fun apply = x, => + (x,) (1,)} +//│ class F1$2(): Foo$1 ({new F1$2_Lambda1$1$4(this,) {}},) {} +//│ class F2$3_Lambda1$2$5(par$F2$3,) {fun apply = x, => + (x,) (2,)} +//│ class F2$3(): Foo$1 ({new F2$3_Lambda1$2$5(this,) {}},) {} +//│ Code(List(('(' new F1$2() {}, ')').foo ())) +//│ Code(List(('(' new F2$3() {}, ')').foo ())) +//│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$5() +//│ main$$6() +//│ fun apply$F2$3_Lambda1$2$5(this, x) = +//│ (x + #2) +//│ fun foo$Foo$1(this) = +//│ this match {case obj: Foo$1 => obj.f match {case obj$F2$3_Lambda1$2$5: F2$3_Lambda1$2$5 => apply$F2$3_Lambda1$2$5(obj$F2$3_Lambda1$2$5, #1); case obj$F1$2_Lambda1$1$4: F1$2_Lambda1$1$4 => apply$F1$2_Lambda1$1$4(obj$F1$2_Lambda1$1$4, #1)}} +//│ fun main$$6() = +//│ new F2$3 () match {case obj: F2$3 => foo$Foo$1(obj)} +//│ fun main$$5() = +//│ new F1$2 () match {case obj: F1$2 => foo$Foo$1(obj)} +//│ fun apply$F1$2_Lambda1$1$4(this, x) = +//│ (x + #1) +//│ class F1$2(): Foo$1(new F1$2_Lambda1$1$4 (this) ) { +//│ } +//│ class F2$3_Lambda1$2$5(par$F2$3) { +//│ } +//│ class F2$3(): Foo$1(new F2$3_Lambda1$2$5 (this) ) { +//│ } +//│ class Foo$1(f) { +//│ } +//│ class F1$2_Lambda1$1$4(par$F1$2) { +//│ } diff --git a/compiler/shared/test/scala/mlscript/compiler/Test.scala b/compiler/shared/test/scala/mlscript/compiler/Test.scala index f02bea392..710cfbbfa 100644 --- a/compiler/shared/test/scala/mlscript/compiler/Test.scala +++ b/compiler/shared/test/scala/mlscript/compiler/Test.scala @@ -20,7 +20,7 @@ class DiffTestCompiler extends DiffTests { outputBuilder ++= "\nLifted:\n" var rstUnit = unit; try - rstUnit = ClassLifter().liftTypingUnit(unit) + rstUnit = ClassLifter(mode.fullExceptionStack).liftTypingUnit(unit) outputBuilder ++= PrettyPrinter.showTypingUnit(rstUnit) catch case NonFatal(err) => @@ -33,14 +33,14 @@ class DiffTestCompiler extends DiffTests { try{ val monomorph = new Monomorph(treeDebug) val monomorphized = monomorph.monomorphize(rstUnit) - outputBuilder ++= "\nMono result: \n" + outputBuilder ++= "\nDefunc result: \n" outputBuilder ++= ExprPrinter.print(monomorphized) outputBuilder ++= "\n" }catch{ case error: MonomorphError => outputBuilder ++= (error.getMessage() :: error.getStackTrace().map(_.toString()).toList).mkString("\n") // case error: StackOverflowError => outputBuilder ++= (error.getMessage() :: error.getStackTrace().take(40).map(_.toString()).toList).mkString("\n") } - outputBuilder ++= treeDebug.getLines.mkString("\n") + // outputBuilder ++= treeDebug.getLines.mkString("\n") } outputBuilder.toString().linesIterator.toList From 6c415f505ae58bb0e8d801160a31d188d334c850 Mon Sep 17 00:00:00 2001 From: YKY Date: Mon, 10 Apr 2023 21:15:43 +0800 Subject: [PATCH 05/13] small fix and rename functions to improve readability --- .../scala/mlscript/compiler/ClassLifter.scala | 2 +- .../scala/mlscript/compiler/Helpers.scala | 2 +- .../mlscript/compiler/mono/Monomorph.scala | 109 +++--------------- .../mono/specializer/Specializer.scala | 14 +-- compiler/shared/test/diff/LambLift.mls | 2 +- compiler/shared/test/diff/LiftType.mls | 2 +- compiler/shared/test/diff/Lifter.mls | 24 ++-- compiler/shared/test/diff/LifterBlks.mls | 12 +- compiler/shared/test/diff/mono.mls | 61 +++++----- .../test/scala/mlscript/compiler/Test.scala | 2 +- .../main/scala/mlscript/codegen/Helpers.scala | 2 +- 11 files changed, 83 insertions(+), 149 deletions(-) diff --git a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala index fe7b5ebf7..64f226d5f 100644 --- a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala +++ b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala @@ -634,7 +634,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { val nmsInTrm = rstTrms.flatMap(grepFieldsInTrm) val clsInfos = newCls.map(x => { val infos = collectClassInfo(x, newCls.map(_.nme).toSet)(using emptyCtx) - infos.capturedParams = infos.capturedParams.intersect(ctx.addV(newClsNms ++ newFuncNms ++ nmsInTrm -- globFuncs.keySet ++ outer.map(_ => Var("this")))) + infos.capturedParams = infos.capturedParams.intersect(ctx.addT(infos.capturedParams.tSet).addV(newClsNms ++ newFuncNms ++ nmsInTrm -- globFuncs.keySet ++ outer.map(_ => Var("this")))) x.nme.name -> infos}).toMap val funcInfos = newFuncs.map(x => x.nme.name -> (x.rhs match { diff --git a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala index f62303b3c..2f990da52 100644 --- a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala +++ b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala @@ -125,7 +125,7 @@ object Helpers: case AppliedType(TypeName(name), _) => name case TypeName(name) => name Expr.New(TypeName(typeName), toFuncArgs(args).map(term2Expr).toList) - // case Blk(unit) => Expr.Isolated(monomorphizeBody(TypingUnit(unit))) + // case Blk(unit) => Expr.Isolated(trans2Expr(TypingUnit(unit))) case If(body, alternate) => body match case IfThen(condition, consequent) => Expr.IfThenElse( diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala index 14303348c..e248771ae 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala @@ -35,10 +35,6 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: val info = funImpls.get(nm).get s"$nm: (${info._3.mkString(" X ")}) -> ${info._4} @${funDependence.get(nm).get.mkString("{", ", ", "}")}" - // private def allFunImpls: IterableOnce[(Item.FuncDecl, Item.FuncDecl)] = - // funImpls.iterator.flatMap { case (name, (protoFunc, implFunc, _, _)) => - // implFunc.values.map((protoFunc, _)) - // } private val funDependence = MutMap[String, Set[String]]() val evalQueue = MutSet[String]() @@ -75,21 +71,21 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: val specializer = mono.specializer.Specializer(this)(using debug) - def addNewFunction(func: Item.FuncDecl): Unit = { + private def addNewFunction(func: Item.FuncDecl): Unit = { funImpls.addOne(func.name.name, (func, MutMap(), func.params.map(_ => BoundedExpr()), VariableValue.refresh())) funDependence.addOne(func.name.name, Set()) } - def getResult(exps: List[Expr]) = mlscript.compiler.Module(exps.concat[Expr | Item](funImpls.map(x => x._2._1)) + private def getResult(exps: List[Expr]) = mlscript.compiler.Module(exps.concat[Expr | Item](funImpls.map(x => x._2._1)) .concat(allTypeImpls.values.map(x => x.copy(body = Isolation(Nil)))) .concat(lamTyDefs.values) .concat(anonymTyDefs.values) .toList) /** - * This function monomorphizes the top-level `TypingUnit` into a `Module`. + * This function defunctionalizes the top-level `TypingUnit` into a `Module`. */ - def monomorphize(tu: TypingUnit): Module = + def defunctionalize(tu: TypingUnit): Module = // debug.trace("MONO MODL", PrettyPrinter.show(tu)) { val exps = tu.entities.zipWithIndex.flatMap[Expr] { case (term: Term, i) => @@ -127,15 +123,13 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: funImpls.foreach( (nm, info) => { debug.log(s"$nm: (${info._3.mkString(" X ")}) -> ${info._4}") - // updateFunc(nm) - // debug.log("") } ) ret // }() - def updateFunction(crt: String): Unit = { + private def updateFunction(crt: String): Unit = { debug.log(s"evaluating $crt, rests: ${evalQueue}") val cnt = evalCnt.get(crt).getOrElse(0) if(cnt <= 10){ @@ -153,7 +147,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: /** * This function monomorphizes the nested `TypingUnit` into a `Isolation`. */ - def monomorphizeBody(body: TypingUnit): Isolation = + private def trans2Expr(body: TypingUnit): Isolation = debug.trace("MONO BODY", PrettyPrinter.show(body)) { Isolation(body.entities.flatMap[Expr | Item.FuncDecl | Item.FuncDefn] { case term: Term => @@ -167,7 +161,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: }) }(identity) - def monomorphizeCall(name: String, args: List[BoundedExpr])(using evalCtx: Context, callingStack: List[String]): BoundedExpr = { + def getFuncRetVal(name: String, args: List[BoundedExpr])(using evalCtx: Context, callingStack: List[String]): BoundedExpr = { debug.trace[BoundedExpr]("SPEC CALL", name + args.mkString(" with (", ", ", ")")) { if(funImpls.contains(name)){ val (funcdecl, mps, oldArgs, oldVs) = funImpls.get(name).get @@ -187,7 +181,6 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: updateFunction(name) } else{ - // val newA = (oldArgs zip nArgs).find(x => x._1.compare(x._2)).get debug.log(s"find finer args") evalQueue.add(name) } @@ -251,20 +244,20 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: private def generateSignature(staticArguments: List[Expr])(using MonomorphContext): String = staticArguments.iterator.map(infer(_, None)).mkString("__", "_", "") - def specializeClassCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = + private def specializeClassCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = debug.trace("SPEC CALL", "class " + name + args.mkString(" with (", ", ", ")")) { ??? }(_.fold(Debug.noPostTrace)(identity)) - def specializeNew(name: String, args: List[BoundedExpr]): MonoValue = - debug.trace("SPEC NEW", s"$name($args)"){ - if(allTypeImpls.contains(name)){ - val tp = allTypeImpls.get(name).get + def createObjValue(tpName: String, args: List[BoundedExpr]): MonoValue = + debug.trace("SPEC NEW", s"$tpName($args)"){ + if(allTypeImpls.contains(tpName)){ + val tp = allTypeImpls.get(tpName).get val ags = (tp.params.map(_._2.name) zip args) - val ret = ObjectValue(name, MutMap(ags: _*)) + val ret = ObjectValue(tpName, MutMap(ags: _*)) val pars = tp.parents.map((supTp, prms) => { - val evArgs = prms.map(specializer.evaluate(_)(using Context() ++ (("this"->BoundedExpr(ret)) :: ags), List(name)).expValue) - BoundedExpr(specializeNew(supTp.base.name, evArgs)) + val evArgs = prms.map(specializer.evaluate(_)(using Context() ++ (("this"->BoundedExpr(ret)) :: ags), List(tpName)).expValue) + BoundedExpr(createObjValue(supTp.base.name, evArgs)) }) val parObjs = pars.zipWithIndex.map((e, i) => s"sup$$$i" -> e) debug.log(s"par objs: $parObjs") @@ -274,7 +267,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: else ??? }(identity) - def specializeSelect(obj: ObjectValue, field: String): BoundedExpr = + def getFieldVal(obj: ObjectValue, field: String): BoundedExpr = debug.trace("SPEC SEL", s"$obj :: $field"){ if(allTypeImpls.contains(obj.name)){ val tpDef = allTypeImpls.get(obj.name).get @@ -299,7 +292,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: if (x._1.matches("sup\\$[0-9]+")) { x._2.asValue match{ case Some(o: ObjectValue) => - Some(specializeSelect(o, field)) + Some(getFieldVal(o, field)) case _ => None } } @@ -312,74 +305,6 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: } }(identity) - // TODO: Remove `Option[Expr]` by passing the callee. - def specializeFunctionCall(name: String, args: List[Expr])(using MonomorphContext): Option[Expr] = - debug.trace("SPEC CALL", "function " + name + args.mkString(" with (", ", ", ")")) { - ??? - }(_.fold(Debug.noPostTrace)(identity)) - - def specializeExpr(expr: Expr)(using ctx: Context, typeContext: MonomorphContext): Expr = - debug.trace[Expr]("SPEC EXPR", expr, "in context", ctx) { - ??? - }(identity) - - /** - * This function monomorphizes the given class with given arguments. - * @return specialized class name and all included classes - */ - def specializeTypeDef( - name: String, - args: List[Expr], - body: Isolation - ): Item.TypeDecl = - debug.trace[Item.TypeDecl]("SPEC TDEF", name + args.mkString("(", ", ", ")") + " {\n" + body + "\n}") { - tyImpls.get(name) match { - case Some(classSpecMap) => - val Item.TypeDecl(_, kind, typeParams, params, parents, body) = classSpecMap.prototype - val implClassName: Expr.Ref = Expr.Ref(s"${name}_${classSpecMap.size}") - Item.TypeDecl(implClassName, kind, typeParams, params, parents, body) - // FIXME: Logic here does not work. - case None => throw new MonomorphError(s"cannot specialize undeclared type $name") - } - }(identity) - - def specializeFunction(funcProto: Item.FuncDecl)(using ctx: Context, typeContext: MonomorphContext): Item.FuncDecl = - Item.FuncDecl(funcProto.name, funcProto.params, specializeExpr(funcProto.body)) - - def specializeClass(classProto: Item.TypeDecl)(using ctx: Context, typeContext: MonomorphContext): Isolation = - debug.trace("SPEC CLASS", s"class ${classProto.name.name}", "in value context", ctx) { - Isolation(classProto.body.items.map { - case expr: Expr => specializeExpr(expr) - case funcDecl: Item.FuncDecl => specializeFunction(funcDecl) - case other => throw MonomorphError(s"$other is not supported") - }) - }(identity) - - def infer(expr: Expr, compatiableType: Option[DataType])(using context: MonomorphContext): DataType = - debug.trace("INFER", expr.toString) { - expr match - case Expr.Ref(name) => context.get(name).getOrElse(DataType.Unknown) - case other => super.infer(expr, compatiableType) - }(_.toString) - - // Shorthand implicit conversions. - - // private given Conversion[String, Expr.Ref] with - // def apply(name: String): Expr.Ref = Expr.Ref(name) - - // private given Conversion[Var, Expr.Ref] with - // def apply(nme: Var): Expr.Ref = Expr.Ref(nme.name) - - // private given Conversion[TypeName, Expr.Ref] with - // def apply(nme: TypeName): Expr.Ref = Expr.Ref(nme.name) - - // private given Conversion[TypeDefKind, TypeDeclKind] with - // import mlscript.{Als, Cls, Trt} - // def apply(kind: TypeDefKind): TypeDeclKind = kind match - // case Als => TypeDeclKind.Alias - // case Cls => TypeDeclKind.Class - // case Trt => TypeDeclKind.Trait - object Monomorph: class SpecializationMap[T <: Item](val prototype: T): private var basePrototype: Option[T] = None diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala index 5d6af253d..57c225b2b 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala @@ -46,14 +46,14 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ val args = nArgs.map(_.expValue) val retV = cal.getValue.map{ case FunctionValue(name, prm, ctxArg) => - val callResult = monoer.monomorphizeCall(name, ctxArg.unzip._2 ++ args) + val callResult = monoer.getFuncRetVal(name, ctxArg.unzip._2 ++ args) // debug.log(s"call result: $callResult") callResult case o: ObjectValue => - val sel = monoer.specializeSelect(o, "apply") + val sel = monoer.getFieldVal(o, "apply") sel.asValue match case Some(FunctionValue(name, prm, ctx)) => - val callResult = monoer.monomorphizeCall(name, ctx.unzip._2 ++ args) + val callResult = monoer.getFuncRetVal(name, ctx.unzip._2 ++ args) // debug.log(s"call result: $callResult") callResult case _ => BoundedExpr(UnknownValue()) @@ -74,7 +74,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ case ObjectValue(_, flds) if flds.contains(field.name) => flds.get(field.name).get case obj: ObjectValue => - monoer.specializeSelect(obj, field.name) + monoer.getFieldVal(obj, field.name) case _ => BoundedExpr(UnknownValue()) }.fold(BoundedExpr())(_ ++ _) @@ -97,7 +97,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ case Expr.New(apply, arguments) => val nArgs = arguments.map(evaluate(_)) val args = nArgs.map(_.expValue) - val retV = BoundedExpr(monoer.specializeNew(apply.name, args)) + val retV = BoundedExpr(monoer.createObjValue(apply.name, args)) val retExp = Expr.New(apply, nArgs) retExp.expValue = retV retExp @@ -178,7 +178,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ val branches = ArrayBuffer[CaseBranch]() receiver.expValue.getValue.foreach{ case o@ObjectValue(name, _) => - val selValue = monoer.specializeSelect(o, field.name) + val selValue = monoer.getFieldVal(o, field.name) val branchExp = selValue.asValue match{ // foo.f is a member function case Some(f: FunctionValue) => @@ -189,7 +189,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ val scrut = Expr.Select(Expr.Ref("obj"), field) val brchs = selValue.getValue.toList.map(_.asInstanceOf[ObjectValue]) .map(o => { - val lambdaMemFunc = monoer.specializeSelect(o, "apply").asValue.get.asInstanceOf[FunctionValue] + val lambdaMemFunc = monoer.getFieldVal(o, "apply").asValue.get.asInstanceOf[FunctionValue] val caseVarNm: Expr.Ref = Expr.Ref(s"obj$$${o.name}") CaseBranch.Instance(Expr.Ref(o.name), caseVarNm, Expr.Apply(Expr.Ref(lambdaMemFunc.name), caseVarNm :: nArgs)) diff --git a/compiler/shared/test/diff/LambLift.mls b/compiler/shared/test/diff/LambLift.mls index 88e8f8eed..a14a13d6c 100644 --- a/compiler/shared/test/diff/LambLift.mls +++ b/compiler/shared/test/diff/LambLift.mls @@ -63,7 +63,7 @@ app(new A(1)) //│ |#fun| |foo|(|f|)| |#=| |→|f|(|1|)|←|↵|#class| |A|(|y|)|{|→|#fun| |bar|(|z|)| |#=| |y|+|z|←|↵|}|↵|#fun| |app|(|a|)| |#=| |→|foo|(|z| |=>| |a|.bar|(|z|)|)|←|↵|app|(|#new| |A|(|1|)|)| //│ Parsed: {fun foo = f, => {f (1,)}; class A(y,) {fun bar = z, => + (y,) (z,)}; fun app = a, => {foo (z, => (a).bar (z,),)}; app (new A(1,) {},)} //│ Parsed: -//│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(f)), Blk(...))), NuTypeDef(class, A, (), Tup(_: Var(y)), (), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(z)), App(App(Var(+), Tup(_: Var(y))), Tup(_: Var(z))))))), NuFunDef(None, app, [], Lam(Tup(_: Var(a)), Blk(...))), App(Var(app), Tup(_: New(Some((TypeName(A),1,)), TypingUnit(List()))))) +//│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(f)), Blk(...))), NuTypeDef(class, A, (), Tup(_: Var(y)), (), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(z)), App(App(Var(+), Tup(_: Var(y))), Tup(_: Var(z))))))), NuFunDef(None, app, [], Lam(Tup(_: Var(a)), Blk(...))), App(Var(app), Tup(_: New(Some((TypeName(A),1,)), TypingUnit())))) //│ Lifted: //│ TypingUnit { //│ class A$1(y,) {fun bar = z, => + ((this).y,) (z,)} diff --git a/compiler/shared/test/diff/LiftType.mls b/compiler/shared/test/diff/LiftType.mls index ece9127d8..ac2b25aa4 100644 --- a/compiler/shared/test/diff/LiftType.mls +++ b/compiler/shared/test/diff/LiftType.mls @@ -8,7 +8,7 @@ class CTX{ //│ |#class| |CTX|{|→|#class| |A| |{||}|↵|#fun| |foo|(|f|#:| |A| |=>| |A|)|#:| |(|A| |=>| |A|)| |=>| |A| |#=| |f|(|#new| |A|)|←|↵|}| //│ Parsed: {class CTX() {class A() {}; fun foo = f: A, => A, => f (new A() {},) : Function(Tuple(List((None,Field(None,Function(Tuple(List((None,Field(None,TypeName(A))))),TypeName(A)))))),TypeName(A))}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(), (), TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit()), NuFunDef(None, foo, [], Lam(Tup(f: Lam(Tup(_: Var(A)), Var(A))), Asc(App(Var(f), Tup(_: New(Some((TypeName(A),)), TypingUnit(List())))), Function(Tuple(List((None,Field(None,Function(Tuple(List((None,Field(None,TypeName(A))))),TypeName(A)))))),TypeName(A)))))))) +//│ TypingUnit(NuTypeDef(class, CTX, (), Tup(), (), TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit()), NuFunDef(None, foo, [], Lam(Tup(f: Lam(Tup(_: Var(A)), Var(A))), Asc(App(Var(f), Tup(_: New(Some((TypeName(A),)), TypingUnit()))), Function(Tuple(List((None,Field(None,Function(Tuple(List((None,Field(None,TypeName(A))))),TypeName(A)))))),TypeName(A)))))))) //│ Lifted: //│ TypingUnit { //│ class CTX$1_A$2(par$CTX$1,) {} diff --git a/compiler/shared/test/diff/Lifter.mls b/compiler/shared/test/diff/Lifter.mls index 24b362f9a..5f4b12d6f 100644 --- a/compiler/shared/test/diff/Lifter.mls +++ b/compiler/shared/test/diff/Lifter.mls @@ -28,7 +28,7 @@ class A(x) { //│ |#class| |A|(|x|)| |{|→|#class| |B|(|y|)| |{|→|#fun| |getX| |#=| |x|↵|#fun| |getB1| |#=| |B1|(|y|)|↵|#class| |C|(|z|)| |{|→|#fun| |inc|(||)| |#=| |x| |+| |1|↵|#fun| |getY| |#=| |y|↵|#fun| |getA| |#=| |A|(|z|)|↵|#fun| |getB|(|w|)| |#=| |B|(|w|)|↵|#fun| |getC| |#=| |#new| |C|(|inc|(||)|)|↵|#fun| |getSelf| |#=| |this|←|↵|}|←|↵|}|↵|#class| |B1|(|y|)| |{|→|#fun| |getX| |#=| |x|↵|#fun| |getY| |#=| |y|↵|#fun| |getB| |#=| |#new| |B|(|y|)|↵|#fun| |getB1| |#=| |#new| |B1|(|y|)|←|↵|}|↵|#fun| |getB| |#=| |#new| |B|(|x|)|↵|#fun| |getB2|(|y|)| |#=| |B1|(|y|)|↵|#fun| |getB3|(|z|)| |#=| |getB2|(|z|)|↵|#fun| |getA| |#=| |A|(|x|)|←|↵|}| //│ Parsed: {class A(x,) {class B(y,) {fun getX = x; fun getB1 = B1 (y,); class C(z,) {fun inc = => + (x,) (1,); fun getY = y; fun getA = A (z,); fun getB = w, => B (w,); fun getC = new C(inc (),) {}; fun getSelf = this}}; class B1(y,) {fun getX = x; fun getY = y; fun getB = new B(y,) {}; fun getB1 = new B1(y,) {}}; fun getB = new B(x,) {}; fun getB2 = y, => B1 (y,); fun getB3 = z, => getB2 (z,); fun getA = A (x,)}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuTypeDef(class, B, (), Tup(_: Var(y)), (), TypingUnit(NuFunDef(None, getX, [], Var(x)), NuFunDef(None, getB1, [], App(Var(B1), Tup(_: Var(y)))), NuTypeDef(class, C, (), Tup(_: Var(z)), (), TypingUnit(NuFunDef(None, inc, [], Lam(Tup(), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1))))), NuFunDef(None, getY, [], Var(y)), NuFunDef(None, getA, [], App(Var(A), Tup(_: Var(z)))), NuFunDef(None, getB, [], Lam(Tup(_: Var(w)), App(Var(B), Tup(_: Var(w))))), NuFunDef(None, getC, [], New(Some((TypeName(C),inc (),)), TypingUnit(List()))), NuFunDef(None, getSelf, [], Var(this)))))), NuTypeDef(class, B1, (), Tup(_: Var(y)), (), TypingUnit(NuFunDef(None, getX, [], Var(x)), NuFunDef(None, getY, [], Var(y)), NuFunDef(None, getB, [], New(Some((TypeName(B),y,)), TypingUnit(List()))), NuFunDef(None, getB1, [], New(Some((TypeName(B1),y,)), TypingUnit(List()))))), NuFunDef(None, getB, [], New(Some((TypeName(B),x,)), TypingUnit(List()))), NuFunDef(None, getB2, [], Lam(Tup(_: Var(y)), App(Var(B1), Tup(_: Var(y))))), NuFunDef(None, getB3, [], Lam(Tup(_: Var(z)), App(Var(getB2), Tup(_: Var(z))))), NuFunDef(None, getA, [], App(Var(A), Tup(_: Var(x))))))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuTypeDef(class, B, (), Tup(_: Var(y)), (), TypingUnit(NuFunDef(None, getX, [], Var(x)), NuFunDef(None, getB1, [], App(Var(B1), Tup(_: Var(y)))), NuTypeDef(class, C, (), Tup(_: Var(z)), (), TypingUnit(NuFunDef(None, inc, [], Lam(Tup(), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1))))), NuFunDef(None, getY, [], Var(y)), NuFunDef(None, getA, [], App(Var(A), Tup(_: Var(z)))), NuFunDef(None, getB, [], Lam(Tup(_: Var(w)), App(Var(B), Tup(_: Var(w))))), NuFunDef(None, getC, [], New(Some((TypeName(C),inc (),)), TypingUnit())), NuFunDef(None, getSelf, [], Var(this)))))), NuTypeDef(class, B1, (), Tup(_: Var(y)), (), TypingUnit(NuFunDef(None, getX, [], Var(x)), NuFunDef(None, getY, [], Var(y)), NuFunDef(None, getB, [], New(Some((TypeName(B),y,)), TypingUnit())), NuFunDef(None, getB1, [], New(Some((TypeName(B1),y,)), TypingUnit())))), NuFunDef(None, getB, [], New(Some((TypeName(B),x,)), TypingUnit())), NuFunDef(None, getB2, [], Lam(Tup(_: Var(y)), App(Var(B1), Tup(_: Var(y))))), NuFunDef(None, getB3, [], Lam(Tup(_: Var(z)), App(Var(getB2), Tup(_: Var(z))))), NuFunDef(None, getA, [], App(Var(A), Tup(_: Var(x))))))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2_C$4(par$A$1_B$2, z, x,) { @@ -106,7 +106,7 @@ new C{ //│ |#class| |A|(|x|)| |{|→|#class| |B|{|→|#fun| |foo| |#=| |1|↵|#fun| |bar| |#=| |11|←|↵|}|↵|#fun| |getB| |#=| |#new| |B|{|→|#fun| |foo| |#=| |2|↵|#fun| |bar| |#=| |12|←|↵|}|↵|#fun| |bar| |#=| |13|←|↵|}|↵|#class| |C|#:| |A|{|→|#fun| |getB| |#=| |#new| |B|{|→|#fun| |foo| |#=| |3|↵|#fun| |bar| |#=| |14|←|↵|}|↵|#fun| |bar| |#=| |15|←|↵|}|↵|#new| |C|{|→|#fun| |getB| |#=| |#new| |B|{|→|#fun| |foo| |#=| |4|↵|#fun| |bar| |#=| |16|←|↵|}|↵|#fun| |bar| |#=| |17|←|↵|}| //│ Parsed: {class A(x,) {class B() {fun foo = 1; fun bar = 11}; fun getB = new B() {fun foo = 2; fun bar = 12}; fun bar = 13}; class C(): A {fun getB = new B() {fun foo = 3; fun bar = 14}; fun bar = 15}; new C() {fun getB = new B() {fun foo = 4; fun bar = 16}; fun bar = 17}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], IntLit(1)), NuFunDef(None, bar, [], IntLit(11)))), NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(List(fun foo = 2, fun bar = 12)))), NuFunDef(None, bar, [], IntLit(13)))), NuTypeDef(class, C, (), Tup(), (Var(A)), TypingUnit(NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(List(fun foo = 3, fun bar = 14)))), NuFunDef(None, bar, [], IntLit(15)))), New(Some((TypeName(C),)), TypingUnit(List(fun getB = new B() {fun foo = 4; fun bar = 16}, fun bar = 17)))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], IntLit(1)), NuFunDef(None, bar, [], IntLit(11)))), NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(NuFunDef(None, foo, [], IntLit(2)), NuFunDef(None, bar, [], IntLit(12))))), NuFunDef(None, bar, [], IntLit(13)))), NuTypeDef(class, C, (), Tup(), (Var(A)), TypingUnit(NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(NuFunDef(None, foo, [], IntLit(3)), NuFunDef(None, bar, [], IntLit(14))))), NuFunDef(None, bar, [], IntLit(15)))), New(Some((TypeName(C),)), TypingUnit(NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(NuFunDef(None, foo, [], IntLit(4)), NuFunDef(None, bar, [], IntLit(16))))), NuFunDef(None, bar, [], IntLit(17))))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$1$4(par$A$1,): A$1_B$3 ((this).par$A$1,) {fun foo = => 2; fun bar = => 12} @@ -162,7 +162,7 @@ class A(x: Int): {a1: Int} & B & D(x){ //│ |#class| |B|‹|T|›| |{||}|↵|#class| |C| |{||}|↵|#class| |D|(|y|#:| |Int|)| |{||}|↵|#class| |A|‹|T|,| |U|›|(|x|#:| |Int|)|#:| |{|a1|#:| |Int|}| |&| |B|‹|T|›| |&| |D|(|x|)|{|→|#fun| |getA|(||)| |#=| |#new| |C|{|→|#fun| |foo|(|x|#:| |T|)| |#=| |x|←|↵|}|←|↵|}| //│ Parsed: {class B‹T›() {}; class C() {}; class D(y: Int,) {}; class A‹T, U›(x: Int,): & (& ('{' {a1: Int} '}',) (B‹T›,),) (D (x,),) {fun getA = => new C() {fun foo = x: T, => x}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, B, (TypeName(T)), Tup(), (), TypingUnit()), NuTypeDef(class, C, (), Tup(), (), TypingUnit()), NuTypeDef(class, D, (), Tup(y: Var(Int)), (), TypingUnit()), NuTypeDef(class, A, (TypeName(T), TypeName(U)), Tup(x: Var(Int)), (App(App(Var(&), Tup(_: App(App(Var(&), Tup(_: Bra(rcd = true, Rcd(Var(a1) = Var(Int))))), Tup(_: TyApp(Var(B), List(TypeName(T))))))), Tup(_: App(Var(D), Tup(_: Var(x)))))), TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = x: T, => x)))))))) +//│ TypingUnit(NuTypeDef(class, B, (TypeName(T)), Tup(), (), TypingUnit()), NuTypeDef(class, C, (), Tup(), (), TypingUnit()), NuTypeDef(class, D, (), Tup(y: Var(Int)), (), TypingUnit()), NuTypeDef(class, A, (TypeName(T), TypeName(U)), Tup(x: Var(Int)), (App(App(Var(&), Tup(_: App(App(Var(&), Tup(_: Bra(rcd = true, Rcd(Var(a1) = Var(Int))))), Tup(_: TyApp(Var(B), List(TypeName(T))))))), Tup(_: App(Var(D), Tup(_: Var(x)))))), TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(NuFunDef(None, foo, [], Lam(Tup(x: Var(T)), Var(x)))))))))) //│ Lifted: //│ TypingUnit { //│ class B$1[T]() {} @@ -184,7 +184,7 @@ class A(x: Int): {a1: Int}, B, D(x){ //│ |#class| |B|‹|T|›| |{||}|↵|#class| |C| |{||}|↵|#class| |D|(|y|#:| |Int|)| |{||}|↵|#class| |A|‹|T|,| |U|›|(|x|#:| |Int|)|#:| |{|a1|#:| |Int|}|,| |B|‹|T|›|,| |D|(|x|)|{|→|#fun| |getA|(||)| |#=| |#new| |C|{|→|#fun| |foo|(|x|)| |#=| |x|←|↵|}|←|↵|}| //│ Parsed: {class B‹T›() {}; class C() {}; class D(y: Int,) {}; class A‹T, U›(x: Int,): '{' {a1: Int} '}', B‹T›, D (x,) {fun getA = => new C() {fun foo = x, => x}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, B, (TypeName(T)), Tup(), (), TypingUnit()), NuTypeDef(class, C, (), Tup(), (), TypingUnit()), NuTypeDef(class, D, (), Tup(y: Var(Int)), (), TypingUnit()), NuTypeDef(class, A, (TypeName(T), TypeName(U)), Tup(x: Var(Int)), (Bra(rcd = true, Rcd(Var(a1) = Var(Int))), TyApp(Var(B), List(TypeName(T))), App(Var(D), Tup(_: Var(x)))), TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = x, => x)))))))) +//│ TypingUnit(NuTypeDef(class, B, (TypeName(T)), Tup(), (), TypingUnit()), NuTypeDef(class, C, (), Tup(), (), TypingUnit()), NuTypeDef(class, D, (), Tup(y: Var(Int)), (), TypingUnit()), NuTypeDef(class, A, (TypeName(T), TypeName(U)), Tup(x: Var(Int)), (Bra(rcd = true, Rcd(Var(a1) = Var(Int))), TyApp(Var(B), List(TypeName(T))), App(Var(D), Tup(_: Var(x)))), TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), Var(x)))))))))) //│ Lifted: //│ TypingUnit { //│ class B$1[T]() {} @@ -204,7 +204,7 @@ class Child(x): { age: T } & { name: String} { //│ |#class| |Child|‹|T|,| |U|›|(|x|)|#:| |{| |age|#:| |T| |}| |&| |{| |name|#:| |String|}| |{|→|#class| |Inner|{|→|#fun| |foo| |#=| |age|←|↵|}|↵|#fun| |bar| |#=| |age|↵|#fun| |boo| |#=| |#new| |Inner|←|↵|}| //│ Parsed: {class Child‹T, U›(x,): & ('{' {age: T} '}',) ('{' {name: String} '}',) {class Inner() {fun foo = age}; fun bar = age; fun boo = new Inner() {}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Child, (TypeName(T), TypeName(U)), Tup(_: Var(x)), (App(App(Var(&), Tup(_: Bra(rcd = true, Rcd(Var(age) = Var(T))))), Tup(_: Bra(rcd = true, Rcd(Var(name) = Var(String)))))), TypingUnit(NuTypeDef(class, Inner, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], Var(age)))), NuFunDef(None, bar, [], Var(age)), NuFunDef(None, boo, [], New(Some((TypeName(Inner),)), TypingUnit(List())))))) +//│ TypingUnit(NuTypeDef(class, Child, (TypeName(T), TypeName(U)), Tup(_: Var(x)), (App(App(Var(&), Tup(_: Bra(rcd = true, Rcd(Var(age) = Var(T))))), Tup(_: Bra(rcd = true, Rcd(Var(name) = Var(String)))))), TypingUnit(NuTypeDef(class, Inner, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], Var(age)))), NuFunDef(None, bar, [], Var(age)), NuFunDef(None, boo, [], New(Some((TypeName(Inner),)), TypingUnit()))))) //│ Lifted: //│ TypingUnit { //│ class Child$1_Inner$2(par$Child$1,) {fun foo = => ((this).par$Child$1).age} @@ -226,7 +226,7 @@ new A(0) { //│ |#class| |A|(|x|#:| |Int|)| |{|→|#fun| |getA|#:| |Int| |#=| |0|↵|#fun| |getA1| |#=| |1|←|↵|}|↵|#new| |A|(|0|)| |{|→|#fun| |getA| |#=| |3|↵|#fun| |getA2| |#=| |2|←|↵|}| //│ Parsed: {class A(x: Int,) {fun getA = 0 : TypeName(Int); fun getA1 = 1}; new A(0,) {fun getA = 3; fun getA2 = 2}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(x: Var(Int)), (), TypingUnit(NuFunDef(None, getA, [], Asc(IntLit(0), TypeName(Int))), NuFunDef(None, getA1, [], IntLit(1)))), New(Some((TypeName(A),0,)), TypingUnit(List(fun getA = 3, fun getA2 = 2)))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(x: Var(Int)), (), TypingUnit(NuFunDef(None, getA, [], Asc(IntLit(0), TypeName(Int))), NuFunDef(None, getA1, [], IntLit(1)))), New(Some((TypeName(A),0,)), TypingUnit(NuFunDef(None, getA, [], IntLit(3)), NuFunDef(None, getA2, [], IntLit(2))))) //│ Lifted: //│ TypingUnit { //│ class A$1(x: Int,) {fun getA = => 0 : TypeName(Int); fun getA1 = => 1} @@ -246,7 +246,7 @@ new A(1) { //│ |#class| |A|(|x|)| |{|→|#class| |B|(|y|)| |{| |}|←|↵|}|↵|#new| |A|(|1|)| |{|→|#fun| |getB| |#=| |#new| |B|(|2|)|{|→|#fun| |getB| |#=| |#new| |B|(|3|)|←|↵|}|←|↵|}| //│ Parsed: {class A(x,) {class B(y,) {}}; new A(1,) {fun getB = new B(2,) {fun getB = new B(3,) {}}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuTypeDef(class, B, (), Tup(_: Var(y)), (), TypingUnit()))), New(Some((TypeName(A),1,)), TypingUnit(List(fun getB = new B(2,) {fun getB = new B(3,) {}})))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuTypeDef(class, B, (), Tup(_: Var(y)), (), TypingUnit()))), New(Some((TypeName(A),1,)), TypingUnit(NuFunDef(None, getB, [], New(Some((TypeName(B),2,)), TypingUnit(NuFunDef(None, getB, [], New(Some((TypeName(B),3,)), TypingUnit())))))))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2(par$A$1, y,) {} @@ -278,7 +278,7 @@ new B{ //│ |#class| |A| |{|→|#fun| |getA| |#=| |0|↵|#fun| |funcA| |#=| |10|←|↵|}|↵|#class| |B|#:| |A|{|→|#fun| |getA| |#=| |1|↵|#fun| |funcB| |#=| |11|←|↵|}|↵|#new| |A|↵|#new| |B|↵|#fun| |f|(|x|)| |#=| |#if| |x| |is| |A| |#then| |0| |#else| |1|↵|f|(|#new| |A|{|→|#fun| |getA| |#=| |2|←|↵|}|)|↵|#new| |B|{|→|#fun| |getA| |#=| |funcB|←|↵|}| //│ Parsed: {class A() {fun getA = 0; fun funcA = 10}; class B(): A {fun getA = 1; fun funcB = 11}; new A() {}; new B() {}; fun f = x, => if (is (x,) (A,)) then 0 else 1; f (new A() {fun getA = 2},); new B() {fun getA = funcB}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuFunDef(None, getA, [], IntLit(0)), NuFunDef(None, funcA, [], IntLit(10)))), NuTypeDef(class, B, (), Tup(), (Var(A)), TypingUnit(NuFunDef(None, getA, [], IntLit(1)), NuFunDef(None, funcB, [], IntLit(11)))), New(Some((TypeName(A),)), TypingUnit(List())), New(Some((TypeName(B),)), TypingUnit(List())), NuFunDef(None, f, [], Lam(Tup(_: Var(x)), If(IfThen(App(App(Var(is), Tup(_: Var(x))), Tup(_: Var(A))), IntLit(0), Some(IntLit(1))))), App(Var(f), Tup(_: New(Some((TypeName(A),)), TypingUnit(List(fun getA = 2))))), New(Some((TypeName(B),)), TypingUnit(List(fun getA = funcB)))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuFunDef(None, getA, [], IntLit(0)), NuFunDef(None, funcA, [], IntLit(10)))), NuTypeDef(class, B, (), Tup(), (Var(A)), TypingUnit(NuFunDef(None, getA, [], IntLit(1)), NuFunDef(None, funcB, [], IntLit(11)))), New(Some((TypeName(A),)), TypingUnit()), New(Some((TypeName(B),)), TypingUnit()), NuFunDef(None, f, [], Lam(Tup(_: Var(x)), If(IfThen(App(App(Var(is), Tup(_: Var(x))), Tup(_: Var(A))), IntLit(0), Some(IntLit(1))))), App(Var(f), Tup(_: New(Some((TypeName(A),)), TypingUnit(NuFunDef(None, getA, [], IntLit(2)))))), New(Some((TypeName(B),)), TypingUnit(NuFunDef(None, getA, [], Var(funcB))))) //│ Lifted: //│ TypingUnit { //│ class A$1() {fun getA = => 0; fun funcA = => 10} @@ -360,7 +360,7 @@ class A{ //│ |#class| |A|{|→|#class| |B|{|→|#fun| |funB| |#=| |1|↵|#fun| |foo| |#=| |100|←|↵|}|↵|#class| |C|#:| |B|{|→|#fun| |funC| |#=| |2|↵|#fun| |foo| |#=| |1000|↵|#fun| |getB| |#=| |#new| |B|←|↵|}|↵|#class| |D|{|→|#fun| |funD| |#=| |3|↵|#fun| |foo| |#=| |10000| |↵|#class| |E|#:| |C|{|→|#fun| |funE| |#=| |4|↵|#fun| |foo| |#=| |100000|↵|#fun| |getD| |#=| |#new| |D|←|↵|}|↵|#class| |F|#:| |E|{|→|#fun| |funF| |#=| |5|↵|#fun| |foo| |#=| |1000000|↵|#fun| |getE| |#=| |#new| |E|{|→|#fun| |foo| |#=| |0|←|↵|}|←|↵|}|←|↵|}|←|↵|}| //│ Parsed: {class A() {class B() {fun funB = 1; fun foo = 100}; class C(): B {fun funC = 2; fun foo = 1000; fun getB = new B() {}}; class D() {fun funD = 3; fun foo = 10000; class E(): C {fun funE = 4; fun foo = 100000; fun getD = new D() {}}; class F(): E {fun funF = 5; fun foo = 1000000; fun getE = new E() {fun foo = 0}}}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, funB, [], IntLit(1)), NuFunDef(None, foo, [], IntLit(100)))), NuTypeDef(class, C, (), Tup(), (Var(B)), TypingUnit(NuFunDef(None, funC, [], IntLit(2)), NuFunDef(None, foo, [], IntLit(1000)), NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit(List()))))), NuTypeDef(class, D, (), Tup(), (), TypingUnit(NuFunDef(None, funD, [], IntLit(3)), NuFunDef(None, foo, [], IntLit(10000)), NuTypeDef(class, E, (), Tup(), (Var(C)), TypingUnit(NuFunDef(None, funE, [], IntLit(4)), NuFunDef(None, foo, [], IntLit(100000)), NuFunDef(None, getD, [], New(Some((TypeName(D),)), TypingUnit(List()))))), NuTypeDef(class, F, (), Tup(), (Var(E)), TypingUnit(NuFunDef(None, funF, [], IntLit(5)), NuFunDef(None, foo, [], IntLit(1000000)), NuFunDef(None, getE, [], New(Some((TypeName(E),)), TypingUnit(List(fun foo = 0))))))))))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, funB, [], IntLit(1)), NuFunDef(None, foo, [], IntLit(100)))), NuTypeDef(class, C, (), Tup(), (Var(B)), TypingUnit(NuFunDef(None, funC, [], IntLit(2)), NuFunDef(None, foo, [], IntLit(1000)), NuFunDef(None, getB, [], New(Some((TypeName(B),)), TypingUnit())))), NuTypeDef(class, D, (), Tup(), (), TypingUnit(NuFunDef(None, funD, [], IntLit(3)), NuFunDef(None, foo, [], IntLit(10000)), NuTypeDef(class, E, (), Tup(), (Var(C)), TypingUnit(NuFunDef(None, funE, [], IntLit(4)), NuFunDef(None, foo, [], IntLit(100000)), NuFunDef(None, getD, [], New(Some((TypeName(D),)), TypingUnit())))), NuTypeDef(class, F, (), Tup(), (Var(E)), TypingUnit(NuFunDef(None, funF, [], IntLit(5)), NuFunDef(None, foo, [], IntLit(1000000)), NuFunDef(None, getE, [], New(Some((TypeName(E),)), TypingUnit(NuFunDef(None, foo, [], IntLit(0)))))))))))) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2(par$A$1,) {fun funB = => 1; fun foo = => 100} @@ -395,7 +395,7 @@ new A //│ |#class| |A|{|→|#class| |B|{|→|#fun| |foo| |#=| |1|←|↵|}|↵|#fun| |bar| |#=| |#new| |B|←|↵|}|↵|#new| |A| //│ Parsed: {class A() {class B() {fun foo = 1}; fun bar = new B() {}}; new A() {}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], IntLit(1)))), NuFunDef(None, bar, [], New(Some((TypeName(B),)), TypingUnit(List()))))), New(Some((TypeName(A),)), TypingUnit(List()))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, foo, [], IntLit(1)))), NuFunDef(None, bar, [], New(Some((TypeName(B),)), TypingUnit())))), New(Some((TypeName(A),)), TypingUnit())) //│ Lifted: //│ TypingUnit { //│ class A$1_B$2(par$A$1,) {fun foo = => 1} @@ -419,7 +419,7 @@ let x = new A{ //│ |#class| |A|(|x|)| |{|→|#fun| |foo| |#=| |0|↵|#fun| |bar| |#=| |x|←|↵|}|↵|#let| |x| |#=| |#new| |A|{|→|#fun| |foo| |#=| |1|↵|#fun| |newFun| |#=| |2|↵|#fun| |bar| |#=| |#new| |A|(|foo|)|{|→|#fun| |foo| |#=| |bar| |+| |1|↵|#fun| |bar2| |#=| |newFun| |+| |1|←|↵|}|←|↵|}| //│ Parsed: {class A(x,) {fun foo = 0; fun bar = x}; let x = new A() {fun foo = 1; fun newFun = 2; fun bar = new A(foo,) {fun foo = + (bar,) (1,); fun bar2 = + (newFun,) (1,)}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuFunDef(None, foo, [], IntLit(0)), NuFunDef(None, bar, [], Var(x)))), NuFunDef(Some(false), x, [], New(Some((TypeName(A),)), TypingUnit(List(fun foo = 1, fun newFun = 2, fun bar = new A(foo,) {fun foo = + (bar,) (1,); fun bar2 = + (newFun,) (1,)}))))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(x)), (), TypingUnit(NuFunDef(None, foo, [], IntLit(0)), NuFunDef(None, bar, [], Var(x)))), NuFunDef(Some(false), x, [], New(Some((TypeName(A),)), TypingUnit(NuFunDef(None, foo, [], IntLit(1)), NuFunDef(None, newFun, [], IntLit(2)), NuFunDef(None, bar, [], New(Some((TypeName(A),foo,)), TypingUnit(NuFunDef(None, foo, [], App(App(Var(+), Tup(_: Var(bar))), Tup(_: IntLit(1)))), NuFunDef(None, bar2, [], App(App(Var(+), Tup(_: Var(newFun))), Tup(_: IntLit(1))))))))))) //│ Lifted: //│ TypingUnit { //│ class A$1(x,) {fun foo = => 0; fun bar = => (this).x} @@ -455,7 +455,7 @@ new A{ //│ |#class| |A| |{||}|↵|#new| |A|{|→|#fun| |foo| |#=| |1|↵|#fun| |bar| |#=| |#new| |A|{|→|#fun| |foo1| |#=| |foo|↵|#fun| |bar1| |#=| |#new| |A|{|→|#fun| |foo2| |#=| |foo|↵|#fun| |bar2| |#=| |#new| |A|{|→|#fun| |foo3| |#=| |foo|↵|#fun| |bar3| |#=| |#new| |A|{|→|#fun| |foo4| |#=| |foo|↵|#fun| |bar4| |#=| |0|←|↵|}|←|↵|}|←|↵|}|←|↵|}|←|↵|}| //│ Parsed: {class A() {}; new A() {fun foo = 1; fun bar = new A() {fun foo1 = foo; fun bar1 = new A() {fun foo2 = foo; fun bar2 = new A() {fun foo3 = foo; fun bar3 = new A() {fun foo4 = foo; fun bar4 = 0}}}}}} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit()), New(Some((TypeName(A),)), TypingUnit(List(fun foo = 1, fun bar = new A() {fun foo1 = foo; fun bar1 = new A() {fun foo2 = foo; fun bar2 = new A() {fun foo3 = foo; fun bar3 = new A() {fun foo4 = foo; fun bar4 = 0}}}})))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(), (), TypingUnit()), New(Some((TypeName(A),)), TypingUnit(NuFunDef(None, foo, [], IntLit(1)), NuFunDef(None, bar, [], New(Some((TypeName(A),)), TypingUnit(NuFunDef(None, foo1, [], Var(foo)), NuFunDef(None, bar1, [], New(Some((TypeName(A),)), TypingUnit(NuFunDef(None, foo2, [], Var(foo)), NuFunDef(None, bar2, [], New(Some((TypeName(A),)), TypingUnit(NuFunDef(None, foo3, [], Var(foo)), NuFunDef(None, bar3, [], New(Some((TypeName(A),)), TypingUnit(NuFunDef(None, foo4, [], Var(foo)), NuFunDef(None, bar4, [], IntLit(0))))))))))))))))) //│ Lifted: //│ TypingUnit { //│ class A$1() {} diff --git a/compiler/shared/test/diff/LifterBlks.mls b/compiler/shared/test/diff/LifterBlks.mls index 2532eae31..53a91bfb9 100644 --- a/compiler/shared/test/diff/LifterBlks.mls +++ b/compiler/shared/test/diff/LifterBlks.mls @@ -54,7 +54,7 @@ f(0) //│ |#class| |A|(|y|)|{||}|↵|#let| |f| |#=| |x| |=>| |#new| |A|(|0|)|{|#fun| |bar| |#=| |x|+|y|}|↵|f|(|0|)| //│ Parsed: {class A(y,) {}; let f = x, => new A(0,) {fun bar = + (x,) (y,)}; f (0,)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(y)), (), TypingUnit()), NuFunDef(Some(false), f, [], Lam(Tup(_: Var(x)), New(Some((TypeName(A),0,)), TypingUnit(List(fun bar = + (x,) (y,)))))), App(Var(f), Tup(_: IntLit(0)))) +//│ TypingUnit(NuTypeDef(class, A, (), Tup(_: Var(y)), (), TypingUnit()), NuFunDef(Some(false), f, [], Lam(Tup(_: Var(x)), New(Some((TypeName(A),0,)), TypingUnit(NuFunDef(None, bar, [], App(App(Var(+), Tup(_: Var(x))), Tup(_: Var(y)))))))), App(Var(f), Tup(_: IntLit(0)))) //│ Lifted: //│ TypingUnit { //│ class A$1(y,) {} @@ -148,7 +148,7 @@ fun f(x,y,z) = //│ fun bar2 = => ((this).par$C$1).y //│ } //│ class C$1(x, y, z,) { -//│ fun boo = => + (('(' new C$1_A$2(this,) {}, ')').bar1,) (+ ((C$1_B$3 (this,)).bar2,) ((this).z,),) +//│ fun boo = => + (+ (('(' new C$1_A$2(this,) {}, ')').bar1,) ((C$1_B$3 (this,)).bar2,),) ((this).z,) //│ } //│ fun f$1 = x, y, z, => {} //│ } @@ -211,7 +211,7 @@ fun foo(x: T): string = //│ TypingUnit(NuFunDef(None, foo, [TypeName(T), TypeName(U)], Lam(Tup(x: Var(T)), Asc(Blk(...), TypeName(string))))) //│ Lifted: //│ TypingUnit { -//│ class A$1(y,): B‹T›, C (y: U,) {fun bar = => this} +//│ class A$1[T,U](y,): B‹T›, C (y: U,) {fun bar = => this} //│ fun foo$1[T, U] = x: T, => {"rua"} : TypeName(string) //│ } @@ -221,8 +221,8 @@ class A{ fun g: T => B => T } } -//│ |#class| |A|‹|T|›|{|→|#class| |B|{|→|#fun| |f|#:| |T| |=>| |B| |=>| |T| |#=| |x| |=>| |y| |=>| |x|↵|#fun| |g|#:| |T| |=>| |B| |=>| |T|←|↵|}|←|↵|}| -//│ Parsed: {class A‹T›() {class B() {fun f = x, => y, => x : Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T))); fun g: [] -> T -> B -> T}}} +//│ |#class| |A|‹|T|›|{|→|#class| |B|{|→|#fun| |f| |#=| |x| |=>| |y| |=>| |x|↵|#fun| |g|#:| |T| |=>| |B| |=>| |T|←|↵|}|←|↵|}| +//│ Parsed: {class A‹T›() {class B() {fun f = x, => y, => x; fun g: [] -> T -> B -> T}}} //│ Parsed: //│ TypingUnit(NuTypeDef(class, A, (TypeName(T)), Tup(), (), TypingUnit(NuTypeDef(class, B, (), Tup(), (), TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), Lam(Tup(_: Var(y)), Var(x)))), NuFunDef(None, g, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T)))))))))) //│ Lifted: @@ -270,7 +270,7 @@ fun ctx(a,b) = //│ TypingUnit { //│ class Func$1[T,U]() {fun apply = T -> U} //│ class Lambda$2[T,U](): Func$1 ()‹T, U› {} -//│ class Lambda$3$3(a,): Lambda$2 () {fun apply = x, => + ((this).a,) (x,)} +//│ class Lambda$3$3[T,U](a,): Lambda$2 () {fun apply = x, => + ((this).a,) (x,)} //│ fun foo$2 = f: Func$1, x, => {(f).apply (x,)} //│ fun ctx$1 = a, b, => {foo$2 ({new Lambda$3$3(a,) {}}, b,)} //│ } diff --git a/compiler/shared/test/diff/mono.mls b/compiler/shared/test/diff/mono.mls index 661d51fcb..613a7da1c 100644 --- a/compiler/shared/test/diff/mono.mls +++ b/compiler/shared/test/diff/mono.mls @@ -5,7 +5,7 @@ fun f(x) = if x then 42 else 1337 //│ |#fun| |f|(|x|)| |#=| |#if| |x| |#then| |42| |#else| |1337| //│ Parsed: {fun f = x, => if (x) then 42 else 1337} //│ Parsed: -//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), If((x) then 42, Some(IntLit(1337)))))) +//│ TypingUnit(NuFunDef(None, f, [], Lam(Tup(_: Var(x)), If(IfThen(Var(x), IntLit(42), Some(IntLit(1337)))))) //│ Lifted: //│ TypingUnit {fun f$1 = x, => if (x) then 42 else 1337} @@ -25,7 +25,7 @@ let b = foo(23, false) //│ |#fun| |foo|(|x|,| |##|b|)| |#=| |#if| |b| |#then| |x| |#else| |1337|↵|#let| |a| |#=| |foo|(|42|,| |true|)|↵|#let| |b| |#=| |foo|(|23|,| |false|)| //│ Parsed: {fun foo = x, #b, => if (b) then x else 1337; let a = foo (42, true,); let b = foo (23, false,)} //│ Parsed: -//│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(x), _: Var(b)), If((b) then x, Some(IntLit(1337))))), NuFunDef(Some(false), a, [], App(Var(foo), Tup(_: IntLit(42), _: Var(true)))), NuFunDef(Some(false), b, [], App(Var(foo), Tup(_: IntLit(23), _: Var(false))))) +//│ TypingUnit(NuFunDef(None, foo, [], Lam(Tup(_: Var(x), _: Var(b)), If(IfThen(Var(b), Var(x), Some(IntLit(1337))))), NuFunDef(Some(false), a, [], App(Var(foo), Tup(_: IntLit(42), _: Var(true)))), NuFunDef(Some(false), b, [], App(Var(foo), Tup(_: IntLit(23), _: Var(false))))) //│ Lifted: //│ TypingUnit { //│ fun foo$3 = x, #b, => if (b) then x else 1337 @@ -50,7 +50,7 @@ let b = foo(new Bar(2)) //│ |#class| |Bar|(|##|x|)|↵|#fun| |foo|(|##|b|)| |#=| |b|↵|#let| |a| |#=| |foo|(|#new| |Bar|(|1|)|)|↵|#let| |b| |#=| |foo|(|#new| |Bar|(|2|)|)| //│ Parsed: {class Bar(#x,) {}; fun foo = #b, => b; let a = foo (new Bar(1,) {},); let b = foo (new Bar(2,) {},)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Bar, (), Tup(_: Var(x)), (), TypingUnit()), NuFunDef(None, foo, [], Lam(Tup(_: Var(b)), Var(b))), NuFunDef(Some(false), a, [], App(Var(foo), Tup(_: New(Some((TypeName(Bar),1,)), TypingUnit(List()))))), NuFunDef(Some(false), b, [], App(Var(foo), Tup(_: New(Some((TypeName(Bar),2,)), TypingUnit(List())))))) +//│ TypingUnit(NuTypeDef(class, Bar, (), Tup(_: Var(x)), (), TypingUnit()), NuFunDef(None, foo, [], Lam(Tup(_: Var(b)), Var(b))), NuFunDef(Some(false), a, [], App(Var(foo), Tup(_: New(Some((TypeName(Bar),1,)), TypingUnit())))), NuFunDef(Some(false), b, [], App(Var(foo), Tup(_: New(Some((TypeName(Bar),2,)), TypingUnit()))))) //│ Lifted: //│ TypingUnit { //│ class Bar$1(#x,) {} @@ -67,7 +67,7 @@ class OneInt(#a){ //│ |#class| |OneInt|(|##|a|)|{|→|#fun| |inc|(||)| |#=| |a|+|1|←|↵|}|↵|(|#new| |OneInt|(|1|)|)|.inc|(||)| //│ Parsed: {class OneInt(#a,) {fun inc = => + (a,) (1,)}; ('(' new OneInt(1,) {}, ')').inc ()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, inc, [], Lam(Tup(), App(App(Var(+), Tup(_: Var(a))), Tup(_: IntLit(1))))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(OneInt),1,)), TypingUnit(List())))), inc), Tup())) +//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, inc, [], Lam(Tup(), App(App(Var(+), Tup(_: Var(a))), Tup(_: IntLit(1))))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(OneInt),1,)), TypingUnit()))), inc), Tup())) //│ Lifted: //│ TypingUnit { //│ class OneInt$1(#a,) {fun inc = => + ((this).a,) (1,)} @@ -83,7 +83,7 @@ class OneInt(#a){ //│ |#class| |OneInt|(|##|a|)|{|→|#fun| |add|(|x|)| |#=| |→|#new| |OneInt|(|a|+|x|.a|)|←|←|↵|}|↵|(|#new| |OneInt|(|1|)|)|.add|(|#new| |OneInt|(|2|)|)| //│ Parsed: {class OneInt(#a,) {fun add = x, => {new OneInt(+ (a,) ((x).a,),) {}}}; ('(' new OneInt(1,) {}, ')').add (new OneInt(2,) {},)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, add, [], Lam(Tup(_: Var(x)), Blk(...))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(OneInt),1,)), TypingUnit(List())))), add), Tup(_: New(Some((TypeName(OneInt),2,)), TypingUnit(List()))))) +//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, add, [], Lam(Tup(_: Var(x)), Blk(...))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(OneInt),1,)), TypingUnit()))), add), Tup(_: New(Some((TypeName(OneInt),2,)), TypingUnit())))) //│ Lifted: //│ TypingUnit { //│ class OneInt$1(#a,) { @@ -98,7 +98,7 @@ if 1+1 > 1 then 1-1 else 1*1 //│ |#if| |true| |#then| |1| |#else| |0|↵|#if| |1|+|1| |>| |1| |#then| |1|-|1| |#else| |1|*|1| //│ Parsed: {if (true) then 1 else 0; if (> (+ (1,) (1,),) (1,)) then - (1,) (1,) else * (1,) (1,)} //│ Parsed: -//│ TypingUnit(If((true) then 1, Some(IntLit(0))), If((> (+ (1,) (1,),) (1,)) then - (1,) (1,), Some(App(App(Var(*), Tup(_: IntLit(1))), Tup(_: IntLit(1)))))) +//│ TypingUnit(If(IfThen(Var(true), IntLit(1), Some(IntLit(0))), If(IfThen(App(App(Var(>), Tup(_: App(App(Var(+), Tup(_: IntLit(1))), Tup(_: IntLit(1))))), Tup(_: IntLit(1))), App(App(Var(-), Tup(_: IntLit(1))), Tup(_: IntLit(1))), Some(App(App(Var(*), Tup(_: IntLit(1))), Tup(_: IntLit(1)))))) //│ Lifted: //│ TypingUnit { //│ Code(List(if (true) then 1 else 0)) @@ -110,7 +110,7 @@ if(b) then 1 else 2 //│ |#if|(|b|)| |#then| |1| |#else| |2| //│ Parsed: {if ('(' b, ')') then 1 else 2} //│ Parsed: -//│ TypingUnit(If(('(' b, ')') then 1, Some(IntLit(2)))) +//│ TypingUnit(If(IfThen(Bra(rcd = false, Tup(_: Var(b))), IntLit(1), Some(IntLit(2)))) //│ Lifted: //│ TypingUnit {Code(List(if ('(' b, ')') then 1 else 2))} @@ -128,17 +128,27 @@ if(b) then 1 else 2 //│ } -// :mono +:mono (b => if b then true else false) (true) //│ |(|b| |=>| |#if| |b| |#then| |true| |#else| |false|)| |(|true|)| //│ Parsed: {'(' b, => if (b) then true else false, ')' (true,)} //│ Parsed: -//│ TypingUnit(App(Bra(rcd = false, Tup(_: Lam(Tup(_: Var(b)), If((b) then true, Some(Var(false)))))), Tup(_: Var(true)))) +//│ TypingUnit(App(Bra(rcd = false, Tup(_: Lam(Tup(_: Var(b)), If(IfThen(Var(b), Var(true), Some(Var(false)))))), Tup(_: Var(true)))) //│ Lifted: //│ TypingUnit { //│ class Lambda1$1$1() {fun apply = b, => if (b) then true else false} //│ Code(List('(' {new Lambda1$1$1() {}}, ')' (true,))) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$1() +//│ fun apply$Lambda1$1$1(this, b) = +//│ if b then true else false +//│ fun main$$1() = +//│ new Lambda1$1$1 () match {case obj: Lambda1$1$1 => apply$Lambda1$1$1(obj, true)} +//│ class Lambda1$1$1() { +//│ } // :mono fun f(x) = @@ -177,7 +187,7 @@ count(new List(new List(new Nil(0, false), true), true)) //│ |#class| |List|(|l|,| |hasTail|)| |{||}|↵|#class| |Nil|(|l|,| |hasTail|)| |{||}|↵|#fun| |count|(|lst|)| |#=|→|#if| |lst|.hasTail| |#then| |count|(|lst|.l|)|+|1| |#else| |1|←|↵|count|(|#new| |List|(|#new| |List|(|#new| |Nil|(|0|,| |false|)|,| |true|)|,| |true|)|)| //│ Parsed: {class List(l, hasTail,) {}; class Nil(l, hasTail,) {}; fun count = lst, => {if ((lst).hasTail) then + (count ((lst).l,),) (1,) else 1}; count (new List(new List(new Nil(0, false,) {}, true,) {}, true,) {},)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(l), _: Var(hasTail)), (), TypingUnit()), NuTypeDef(class, Nil, (), Tup(_: Var(l), _: Var(hasTail)), (), TypingUnit()), NuFunDef(None, count, [], Lam(Tup(_: Var(lst)), Blk(...))), App(Var(count), Tup(_: New(Some((TypeName(List),new List(new Nil(0, false,) {}, true,) {}, true,)), TypingUnit(List()))))) +//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(l), _: Var(hasTail)), (), TypingUnit()), NuTypeDef(class, Nil, (), Tup(_: Var(l), _: Var(hasTail)), (), TypingUnit()), NuFunDef(None, count, [], Lam(Tup(_: Var(lst)), Blk(...))), App(Var(count), Tup(_: New(Some((TypeName(List),new List(new Nil(0, false,) {}, true,) {}, true,)), TypingUnit())))) //│ Lifted: //│ TypingUnit { //│ class List$1(l, hasTail,) {} @@ -199,7 +209,7 @@ generate(10).gen() //│ |#class| |Cons|(|e|,| |tail|)|{|→|#fun| |gen|(||)| |#=| |#new| |Cons|(|e|,| |tail|.gen|(||)|)|←|↵|}|↵|#class| |Nil|(||)|{|→|#fun| |gen|(||)| |#=| |#new| |Cons|(|0|,| |this|)|←|↵|}|↵|#fun| |generate|(|x|)| |#=| |→|#if| |x| |>| |0| |#then| |#new| |Cons|(|x|,| |generate|(|x|+|1|)|)| |#else| |#new| |Nil|(||)|←|↵|generate|(|10|)|.gen|(||)| //│ Parsed: {class Cons(e, tail,) {fun gen = => new Cons(e, (tail).gen (),) {}}; class Nil() {fun gen = => new Cons(0, this,) {}}; fun generate = x, => {if (> (x,) (0,)) then new Cons(x, generate (+ (x,) (1,),),) {} else new Nil() {}}; (generate (10,)).gen ()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, gen, [], Lam(Tup(), New(Some((TypeName(Cons),e, (tail).gen (),)), TypingUnit(List())))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, gen, [], Lam(Tup(), New(Some((TypeName(Cons),0, this,)), TypingUnit(List())))))), NuFunDef(None, generate, [], Lam(Tup(_: Var(x)), Blk(...))), App(Sel(App(Var(generate), Tup(_: IntLit(10))), gen), Tup())) +//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, gen, [], Lam(Tup(), New(Some((TypeName(Cons),e, (tail).gen (),)), TypingUnit()))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, gen, [], Lam(Tup(), New(Some((TypeName(Cons),0, this,)), TypingUnit()))))), NuFunDef(None, generate, [], Lam(Tup(_: Var(x)), Blk(...))), App(Sel(App(Var(generate), Tup(_: IntLit(10))), gen), Tup())) //│ Lifted: //│ TypingUnit { //│ class Cons$1(e, tail,) { @@ -240,7 +250,7 @@ fun add2(x) = x+2 //│ |#class| |List|(|e|,| |tail|)| |{|→|#fun| |map|(|f|)| |#=| |#new| |List|(|f|(|e|)|,| |tail|.map|(|f|)|)|↵|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |map|(|f|)| |#=| |this|↵|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#fun| |add2|(|x|)| |#=| |x|+|2|↵|(|#new| |List|(|1|,| |#new| |List|(|2|,| |#new| |Nil|(||)|)|)|)|.map|(|x| |=>| |x|+|1|)|.map|(|x| |=>| |add2|(|x|)|)| //│ Parsed: {class List(e, tail,) {fun map = f, => new List(f (e,), (tail).map (f,),) {}; fun count = => + (1,) ((tail).count (),)}; class Nil() {fun map = f, => this; fun count = => 0}; fun add2 = x, => + (x,) (2,); (('(' new List(1, new List(2, new Nil() {},) {},) {}, ')').map (x, => + (x,) (1,),)).map (x, => add2 (x,),)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, map, [], Lam(Tup(_: Var(f)), New(Some((TypeName(List),f (e,), (tail).map (f,),)), TypingUnit(List())))), NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, map, [], Lam(Tup(_: Var(f)), Var(this))), NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, add2, [], Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(2))))), App(Sel(App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(List),1, new List(2, new Nil() {},) {},)), TypingUnit(List())))), map), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1)))))), map), Tup(_: Lam(Tup(_: Var(x)), App(Var(add2), Tup(_: Var(x))))))) +//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, map, [], Lam(Tup(_: Var(f)), New(Some((TypeName(List),f (e,), (tail).map (f,),)), TypingUnit()))), NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, map, [], Lam(Tup(_: Var(f)), Var(this))), NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, add2, [], Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(2))))), App(Sel(App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(List),1, new List(2, new Nil() {},) {},)), TypingUnit()))), map), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1)))))), map), Tup(_: Lam(Tup(_: Var(x)), App(Var(add2), Tup(_: Var(x))))))) //│ Lifted: //│ TypingUnit { //│ class List$1(e, tail,) { @@ -293,7 +303,7 @@ foo(generate(1)) //│ |#class| |List|(|e|,| |tail|)| |{|→|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#fun| |foo|(|x|)| |#=| |x|.count|(||)|↵|#fun| |generate|(|x|)| |#=| |→|#if| |x| |>| |0| |#then| |#new| |List|(|x|,| |generate|(|x|+|1|)|)| |#else| |#new| |Nil|(||)|←|↵|foo|(|#new| |List|(|1|,| |#new| |List|(|2|,| |#new| |Nil|(||)|)|)|)|↵|foo|(|generate|(|1|)|)| //│ Parsed: {class List(e, tail,) {fun count = => + (1,) ((tail).count (),)}; class Nil() {fun count = => 0}; fun foo = x, => (x).count (); fun generate = x, => {if (> (x,) (0,)) then new List(x, generate (+ (x,) (1,),),) {} else new Nil() {}}; foo (new List(1, new List(2, new Nil() {},) {},) {},); foo (generate (1,),)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), App(Sel(Var(x), count), Tup()))), NuFunDef(None, generate, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: New(Some((TypeName(List),1, new List(2, new Nil() {},) {},)), TypingUnit(List())))), App(Var(foo), Tup(_: App(Var(generate), Tup(_: IntLit(1)))))) +//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), App(Sel(Var(x), count), Tup()))), NuFunDef(None, generate, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: New(Some((TypeName(List),1, new List(2, new Nil() {},) {},)), TypingUnit()))), App(Var(foo), Tup(_: App(Var(generate), Tup(_: IntLit(1)))))) //│ Lifted: //│ TypingUnit { //│ class List$1(e, tail,) {fun count = => + (1,) (((this).tail).count (),)} @@ -412,7 +422,7 @@ foo(new Lambda2(2)) //│ |#class| |Cons|(|e|,| |tail|)| |{|→|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#class| |Lambda|(||)|{|→|#fun| |apply|(|l|)| |#=| |→|l|.count|(||)|←|←|↵|}|↵|#class| |Lambda2|(|a|)|{|→|#fun| |apply|(|l|)| |#=| |→|(|#new| |Cons|(|a|,| |l|)|)|.count|(||)|←|←|↵|}|↵|#fun| |foo|(|x|)| |#=| |→|x|.apply|(|#new| |Cons|(|1|,| |#new| |Nil|(||)|)|)| |+| |x|.apply|(|#new| |Nil|(||)|)|←|↵|foo|(|#new| |Lambda|(||)|)|↵|foo|(|#new| |Lambda2|(|2|)|)| //│ Parsed: {class Cons(e, tail,) {fun count = => + (1,) ((tail).count (),)}; class Nil() {fun count = => 0}; class Lambda() {fun apply = l, => {(l).count ()}}; class Lambda2(a,) {fun apply = l, => {('(' new Cons(a, l,) {}, ')').count ()}}; fun foo = x, => {+ ((x).apply (new Cons(1, new Nil() {},) {},),) ((x).apply (new Nil() {},),)}; foo (new Lambda() {},); foo (new Lambda2(2,) {},)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuTypeDef(class, Lambda, (), Tup(), (), TypingUnit(NuFunDef(None, apply, [], Lam(Tup(_: Var(l)), Blk(...))))), NuTypeDef(class, Lambda2, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, apply, [], Lam(Tup(_: Var(l)), Blk(...))))), NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: New(Some((TypeName(Lambda),)), TypingUnit(List())))), App(Var(foo), Tup(_: New(Some((TypeName(Lambda2),2,)), TypingUnit(List()))))) +//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuTypeDef(class, Lambda, (), Tup(), (), TypingUnit(NuFunDef(None, apply, [], Lam(Tup(_: Var(l)), Blk(...))))), NuTypeDef(class, Lambda2, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, apply, [], Lam(Tup(_: Var(l)), Blk(...))))), NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: New(Some((TypeName(Lambda),)), TypingUnit()))), App(Var(foo), Tup(_: New(Some((TypeName(Lambda2),2,)), TypingUnit())))) //│ Lifted: //│ TypingUnit { //│ class Cons$1(e, tail,) {fun count = => + (1,) (((this).tail).count (),)} @@ -467,7 +477,7 @@ foo(l => (new Cons(2, l)).count()) //│ |#class| |Cons|(|e|,| |tail|)| |{|→|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#fun| |foo|(|x|)| |#=| |→|x|(|#new| |Cons|(|1|,| |#new| |Nil|(||)|)|)| |+| |x|(|#new| |Nil|(||)|)|←|↵|foo|(|l| |=>| |l|.count|(||)|)|↵|foo|(|l| |=>| |(|#new| |Cons|(|2|,| |l|)|)|.count|(||)|)| //│ Parsed: {class Cons(e, tail,) {fun count = => + (1,) ((tail).count (),)}; class Nil() {fun count = => 0}; fun foo = x, => {+ (x (new Cons(1, new Nil() {},) {},),) (x (new Nil() {},),)}; foo (l, => (l).count (),); foo (l, => ('(' new Cons(2, l,) {}, ')').count (),)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: Lam(Tup(_: Var(l)), App(Sel(Var(l), count), Tup())))), App(Var(foo), Tup(_: Lam(Tup(_: Var(l)), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Cons),2, l,)), TypingUnit(List())))), count), Tup()))))) +//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), App(App(Var(+), Tup(_: IntLit(1))), Tup(_: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), TypingUnit(NuFunDef(None, count, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, foo, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: Lam(Tup(_: Var(l)), App(Sel(Var(l), count), Tup())))), App(Var(foo), Tup(_: Lam(Tup(_: Var(l)), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Cons),2, l,)), TypingUnit()))), count), Tup()))))) //│ Lifted: //│ TypingUnit { //│ class Cons$1(e, tail,) {fun count = => + (1,) (((this).tail).count (),)} @@ -543,7 +553,7 @@ class C(e1, e2){ //│ |#class| |E|(||)| |{|→|#fun| |derive|(|x|)| |#=| |→|#new| |E|←|↵|#fun| |isEmpty|(||)| |#=| |→|false|←|←|↵|}|↵|#class| |Ep|(||)|{|→|#fun| |derive|(|x|)| |#=| |→|#new| |E|←|↵|#fun| |isEmpty|(||)| |#=| |→|true|←|←|↵|}|↵|#class| |Ch|(|i|)|{|→|#fun| |derive|(|x|)| |#=| |→|#if| |x| |==| |i| |#then| |#new| |Ep| |#else| |#new| |E|←|↵|#fun| |isEmpty|(||)| |#=| |→|false|←|←|↵|}|↵|#class| |A|(|e1|,| |e2|)|{|→|#fun| |derive|(|x|)| |#=| |→|#new| |A|(|e1|.derive|(|x|)|,| |e2|.derive|(|x|)|)|←|↵|#fun| |isEmpty|(||)| |#=| |→|e1|.isEmpty|(||)| |||| |e2|.isEmpty|(||)|←|←|↵|}|↵|#class| |C|(|e1|,| |e2|)|{|→|#fun| |derive|(|x|)| |#=| |→|#if| |e1|.isEmpty|(||)| |#then| |#new| |A|(|#new| |C|(|e1|.derive|(|x|)|,| |e2|)|,| |e2|.derive|(|x|)|)| |#else| |#new| |C|(|e1|.derive|(|x|)|,| |e2|)|←|↵|#fun| |isEmpty|(||)| |#=| |→|e1|.isEmpty|(||)| |&&| |e2|.isEmpty|(||)|←|←|↵|}|↵|(|#new| |C|(|#new| |Ch|(|1|)|,| |#new| |A|(|#new| |Ch|(|2|)|,| |#new| |Ch|(|3|)|)|)|)|.derive|(|0|)|.isEmpty|(||)| //│ Parsed: {class E() {fun derive = x, => {new E() {}}; fun isEmpty = => {false}}; class Ep() {fun derive = x, => {new E() {}}; fun isEmpty = => {true}}; class Ch(i,) {fun derive = x, => {if (== (x,) (i,)) then new Ep() {} else new E() {}}; fun isEmpty = => {false}}; class A(e1, e2,) {fun derive = x, => {new A((e1).derive (x,), (e2).derive (x,),) {}}; fun isEmpty = => {|| ((e1).isEmpty (),) ((e2).isEmpty (),)}}; class C(e1, e2,) {fun derive = x, => {if ((e1).isEmpty ()) then new A(new C((e1).derive (x,), e2,) {}, (e2).derive (x,),) {} else new C((e1).derive (x,), e2,) {}}; fun isEmpty = => {&& ((e1).isEmpty (),) ((e2).isEmpty (),)}}; (('(' new C(new Ch(1,) {}, new A(new Ch(2,) {}, new Ch(3,) {},) {},) {}, ')').derive (0,)).isEmpty ()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, E, (), Tup(), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ep, (), Tup(), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ch, (), Tup(_: Var(i)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, A, (), Tup(_: Var(e1), _: Var(e2)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, C, (), Tup(_: Var(e1), _: Var(e2)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), App(Sel(App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(C),new Ch(1,) {}, new A(new Ch(2,) {}, new Ch(3,) {},) {},)), TypingUnit(List())))), derive), Tup(_: IntLit(0))), isEmpty), Tup())) +//│ TypingUnit(NuTypeDef(class, E, (), Tup(), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ep, (), Tup(), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ch, (), Tup(_: Var(i)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, A, (), Tup(_: Var(e1), _: Var(e2)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, C, (), Tup(_: Var(e1), _: Var(e2)), (), TypingUnit(NuFunDef(None, derive, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, [], Lam(Tup(), Blk(...))))), App(Sel(App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(C),new Ch(1,) {}, new A(new Ch(2,) {}, new Ch(3,) {},) {},)), TypingUnit()))), derive), Tup(_: IntLit(0))), isEmpty), Tup())) //│ Lifted: //│ TypingUnit { //│ class E$1() { @@ -599,7 +609,7 @@ class Foo(x){ //│ |#class| |Foo|(|x|)|{|→|#fun| |bar|(|y|)| |#=| |x|+|y|↵|#fun| |boo|(|z|)| |#=| |bar|(|z|)|+|x|←|↵|}|↵|(|#new| |Foo|(|1|)|)|.boo|(|2|)| //│ Parsed: {class Foo(x,) {fun bar = y, => + (x,) (y,); fun boo = z, => + (bar (z,),) (x,)}; ('(' new Foo(1,) {}, ')').boo (2,)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(_: Var(x)), (), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(y)), App(App(Var(+), Tup(_: Var(x))), Tup(_: Var(y))))), NuFunDef(None, boo, [], Lam(Tup(_: Var(z)), App(App(Var(+), Tup(_: App(Var(bar), Tup(_: Var(z))))), Tup(_: Var(x))))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Foo),1,)), TypingUnit(List())))), boo), Tup(_: IntLit(2)))) +//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(_: Var(x)), (), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(y)), App(App(Var(+), Tup(_: Var(x))), Tup(_: Var(y))))), NuFunDef(None, boo, [], Lam(Tup(_: Var(z)), App(App(Var(+), Tup(_: App(Var(bar), Tup(_: Var(z))))), Tup(_: Var(x))))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Foo),1,)), TypingUnit()))), boo), Tup(_: IntLit(2)))) //│ Lifted: //│ TypingUnit { //│ class Foo$1(x,) { @@ -618,7 +628,7 @@ class OneInt(a){ //│ |#class| |OneInt|(|a|)|{|→|#fun| |fac|(||)| |#=| |→|#if|(|a| |>| |0|)| |#then| |(|#new| |OneInt|(|a|-|1|)|)|.fac|(||)| |#else| |1| |←|←|↵|}|↵|(|#new| |OneInt|(|10|)|)|.fac|(||)| //│ Parsed: {class OneInt(a,) {fun fac = => {if ('(' > (a,) (0,), ')') then ('(' new OneInt(- (a,) (1,),) {}, ')').fac () else 1}}; ('(' new OneInt(10,) {}, ')').fac ()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, fac, [], Lam(Tup(), Blk(...))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(OneInt),10,)), TypingUnit(List())))), fac), Tup())) +//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, fac, [], Lam(Tup(), Blk(...))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(OneInt),10,)), TypingUnit()))), fac), Tup())) //│ Lifted: //│ TypingUnit { //│ class OneInt$1(a,) { @@ -629,7 +639,6 @@ class OneInt(a){ :mono trait AnyFoo { - fun bar(b): int } class FooPlus(#a): AnyFoo { fun bar(b) = a + b @@ -640,13 +649,13 @@ class FooMinus(#a): AnyFoo { fun f(x) = x.bar(42) f(new FooPlus(1)) f(new FooMinus(2)) -//│ |#trait| |AnyFoo| |{|→|#fun| |bar|(|b|)|#:| |int|←|↵|}|↵|#class| |FooPlus|(|##|a|)|#:| |AnyFoo| |{|→|#fun| |bar|(|b|)| |#=| |a| |+| |b|←|↵|}|↵|#class| |FooMinus|(|##|a|)|#:| |AnyFoo| |{|→|#fun| |bar|(|b|)| |#=| |a| |-| |b|←|↵|}|↵|#fun| |f|(|x|)| |#=| |x|.bar|(|42|)|↵|f|(|#new| |FooPlus|(|1|)|)|↵|f|(|#new| |FooMinus|(|2|)|)| -//│ Parsed: {trait AnyFoo(): {fun bar: [] -> b -> int}; class FooPlus(#a,): AnyFoo {fun bar = b, => + (a,) (b,)}; class FooMinus(#a,): AnyFoo {fun bar = b, => - (a,) (b,)}; fun f = x, => (x).bar (42,); f (new FooPlus(1,) {},); f (new FooMinus(2,) {},)} +//│ |#trait| |AnyFoo| |{|↵|}|↵|#class| |FooPlus|(|##|a|)|#:| |AnyFoo| |{|→|#fun| |bar|(|b|)| |#=| |a| |+| |b|←|↵|}|↵|#class| |FooMinus|(|##|a|)|#:| |AnyFoo| |{|→|#fun| |bar|(|b|)| |#=| |a| |-| |b|←|↵|}|↵|#fun| |f|(|x|)| |#=| |x|.bar|(|42|)|↵|f|(|#new| |FooPlus|(|1|)|)|↵|f|(|#new| |FooMinus|(|2|)|)| +//│ Parsed: {trait AnyFoo() {}; class FooPlus(#a,): AnyFoo {fun bar = b, => + (a,) (b,)}; class FooMinus(#a,): AnyFoo {fun bar = b, => - (a,) (b,)}; fun f = x, => (x).bar (42,); f (new FooPlus(1,) {},); f (new FooMinus(2,) {},)} //│ Parsed: -//│ TypingUnit(NuTypeDef(trait, AnyFoo, (), Tup(), (), TypingUnit(NuFunDef(None, bar, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(b))))),TypeName(int)))))), NuTypeDef(class, FooPlus, (), Tup(_: Var(a)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(b)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))))), NuTypeDef(class, FooMinus, (), Tup(_: Var(a)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(b)), App(App(Var(-), Tup(_: Var(a))), Tup(_: Var(b))))))), NuFunDef(None, f, [], Lam(Tup(_: Var(x)), App(Sel(Var(x), bar), Tup(_: IntLit(42))))), App(Var(f), Tup(_: New(Some((TypeName(FooPlus),1,)), TypingUnit(List())))), App(Var(f), Tup(_: New(Some((TypeName(FooMinus),2,)), TypingUnit(List()))))) +//│ TypingUnit(NuTypeDef(trait, AnyFoo, (), Tup(), (), TypingUnit()), NuTypeDef(class, FooPlus, (), Tup(_: Var(a)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(b)), App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(b))))))), NuTypeDef(class, FooMinus, (), Tup(_: Var(a)), (Var(AnyFoo)), TypingUnit(NuFunDef(None, bar, [], Lam(Tup(_: Var(b)), App(App(Var(-), Tup(_: Var(a))), Tup(_: Var(b))))))), NuFunDef(None, f, [], Lam(Tup(_: Var(x)), App(Sel(Var(x), bar), Tup(_: IntLit(42))))), App(Var(f), Tup(_: New(Some((TypeName(FooPlus),1,)), TypingUnit()))), App(Var(f), Tup(_: New(Some((TypeName(FooMinus),2,)), TypingUnit())))) //│ Lifted: //│ TypingUnit { -//│ trait AnyFoo$1() {fun bar = b -> int} +//│ trait AnyFoo$1() {} //│ class FooPlus$2(#a,): AnyFoo$1 () {fun bar = b, => + ((this).a,) (b,)} //│ class FooMinus$3(#a,): AnyFoo$1 () {fun bar = b, => - ((this).a,) (b,)} //│ fun f$1 = x, => (x).bar (42,) @@ -715,7 +724,7 @@ class OneBool(b){ //│ |#class| |OneInt|(|a|)|{|→|#fun| |get| |#=| |a|←|↵|}|↵|#class| |OneBool|(|b|)|{|→|#fun| |get| |#=| |b|←|↵|}|↵|(|#if| |b| |#then| |#new| |OneInt|(|1|)| |#else| |#new| |OneBool|(|true|)|)|.get|(||)| //│ Parsed: {class OneInt(a,) {fun get = a}; class OneBool(b,) {fun get = b}; ('(' if (b) then new OneInt(1,) {} else new OneBool(true,) {}, ')').get ()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, get, [], Var(a)))), NuTypeDef(class, OneBool, (), Tup(_: Var(b)), (), TypingUnit(NuFunDef(None, get, [], Var(b)))), App(Sel(Bra(rcd = false, Tup(_: If((b) then new OneInt(1,) {}, Some(New(Some((TypeName(OneBool),true,)), TypingUnit(List())))))), get), Tup())) +//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, get, [], Var(a)))), NuTypeDef(class, OneBool, (), Tup(_: Var(b)), (), TypingUnit(NuFunDef(None, get, [], Var(b)))), App(Sel(Bra(rcd = false, Tup(_: If(IfThen(Var(b), New(Some((TypeName(OneInt),1,)), TypingUnit()), Some(New(Some((TypeName(OneBool),true,)), TypingUnit()))))), get), Tup())) //│ Lifted: //│ TypingUnit { //│ class OneInt$1(a,) {fun get = => (this).a} @@ -782,7 +791,7 @@ class Sub2(c): Sub(c+c){ //│ |#class| |Sup|(|a|)|{|→|#fun| |foo| |#=| |a|←|↵|}|↵|#class| |Sub|(|b|)|#:| |Sup|(|b|+|b|)|{|↵|}|↵|#class| |Sub2|(|c|)|#:| |Sub|(|c|+|c|)|{|→|#fun| |foo| |#=| |a|+|c|←|↵|}|↵|(|#new| |Sub|(|10|)|)|.foo|(||)|↵|(|#new| |Sub2|(|c|)|)|.foo|(||)| //│ Parsed: {class Sup(a,) {fun foo = a}; class Sub(b,): Sup (+ (b,) (b,),) {}; class Sub2(c,): Sub (+ (c,) (c,),) {fun foo = + (a,) (c,)}; ('(' new Sub(10,) {}, ')').foo (); ('(' new Sub2(c,) {}, ')').foo ()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Sup, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, foo, [], Var(a)))), NuTypeDef(class, Sub, (), Tup(_: Var(b)), (App(Var(Sup), Tup(_: App(App(Var(+), Tup(_: Var(b))), Tup(_: Var(b)))))), TypingUnit()), NuTypeDef(class, Sub2, (), Tup(_: Var(c)), (App(Var(Sub), Tup(_: App(App(Var(+), Tup(_: Var(c))), Tup(_: Var(c)))))), TypingUnit(NuFunDef(None, foo, [], App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(c)))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Sub),10,)), TypingUnit(List())))), foo), Tup()), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Sub2),c,)), TypingUnit(List())))), foo), Tup())) +//│ TypingUnit(NuTypeDef(class, Sup, (), Tup(_: Var(a)), (), TypingUnit(NuFunDef(None, foo, [], Var(a)))), NuTypeDef(class, Sub, (), Tup(_: Var(b)), (App(Var(Sup), Tup(_: App(App(Var(+), Tup(_: Var(b))), Tup(_: Var(b)))))), TypingUnit()), NuTypeDef(class, Sub2, (), Tup(_: Var(c)), (App(Var(Sub), Tup(_: App(App(Var(+), Tup(_: Var(c))), Tup(_: Var(c)))))), TypingUnit(NuFunDef(None, foo, [], App(App(Var(+), Tup(_: Var(a))), Tup(_: Var(c)))))), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Sub),10,)), TypingUnit()))), foo), Tup()), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(Sub2),c,)), TypingUnit()))), foo), Tup())) //│ Lifted: //│ TypingUnit { //│ class Sup$1(a,) {fun foo = => (this).a} @@ -822,7 +831,7 @@ class F2(): Foo(x => x+2){} //│ |#class| |Foo|(|f|)|{|→|#fun| |foo| |#=| |f|(|1|)|←|↵|}|↵|#class| |F1|(||)|#:| |Foo|(|x| |=>| |x|+|1|)|{||}|↵|#class| |F2|(||)|#:| |Foo|(|x| |=>| |x|+|2|)|{||}|↵|(|#new| |F1|(||)|)|.foo|(||)|↵|(|#new| |F2|(||)|)|.foo|(||)| //│ Parsed: {class Foo(f,) {fun foo = f (1,)}; class F1(): Foo (x, => + (x,) (1,),) {}; class F2(): Foo (x, => + (x,) (2,),) {}; ('(' new F1() {}, ')').foo (); ('(' new F2() {}, ')').foo ()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(_: Var(f)), (), TypingUnit(NuFunDef(None, foo, [], App(Var(f), Tup(_: IntLit(1)))))), NuTypeDef(class, F1, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1))))))), TypingUnit()), NuTypeDef(class, F2, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(2))))))), TypingUnit()), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(F1),)), TypingUnit(List())))), foo), Tup()), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(F2),)), TypingUnit(List())))), foo), Tup())) +//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(_: Var(f)), (), TypingUnit(NuFunDef(None, foo, [], App(Var(f), Tup(_: IntLit(1)))))), NuTypeDef(class, F1, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1))))))), TypingUnit()), NuTypeDef(class, F2, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(2))))))), TypingUnit()), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(F1),)), TypingUnit()))), foo), Tup()), App(Sel(Bra(rcd = false, Tup(_: New(Some((TypeName(F2),)), TypingUnit()))), foo), Tup())) //│ Lifted: //│ TypingUnit { //│ class Foo$1(f,) {fun foo = => (this).f (1,)} diff --git a/compiler/shared/test/scala/mlscript/compiler/Test.scala b/compiler/shared/test/scala/mlscript/compiler/Test.scala index 710cfbbfa..e0df0d8f0 100644 --- a/compiler/shared/test/scala/mlscript/compiler/Test.scala +++ b/compiler/shared/test/scala/mlscript/compiler/Test.scala @@ -32,7 +32,7 @@ class DiffTestCompiler extends DiffTests { val treeDebug = new TreeDebug() try{ val monomorph = new Monomorph(treeDebug) - val monomorphized = monomorph.monomorphize(rstUnit) + val monomorphized = monomorph.defunctionalize(rstUnit) outputBuilder ++= "\nDefunc result: \n" outputBuilder ++= ExprPrinter.print(monomorphized) outputBuilder ++= "\n" diff --git a/shared/src/main/scala/mlscript/codegen/Helpers.scala b/shared/src/main/scala/mlscript/codegen/Helpers.scala index 07c55d212..796b7dfa3 100644 --- a/shared/src/main/scala/mlscript/codegen/Helpers.scala +++ b/shared/src/main/scala/mlscript/codegen/Helpers.scala @@ -49,7 +49,7 @@ object Helpers { val elems = fs.map{case L(l) => s"...${inspect(l)}" case R(Fld(_, _, r)) => inspect(r)}.mkString(", ") s"Splc($elems)" case If(bod, els) => s"If(${inspect(bod)}, ${els.map(inspect)})" - case New(base, body) => s"New(${base}, ${body})" + case New(base, body) => s"New(${base}, ${inspect(body)})" case TyApp(base, targs) => s"TyApp(${inspect(base)}, ${targs})" case Def(rec, nme, rhs, isByname) => s"Def($rec, $nme, ${rhs.fold(inspect, "" + _)}, $isByname)" From 483a08ee1ada9efc4392ded0928e1d3fa1e3f06a Mon Sep 17 00:00:00 2001 From: HarrisL2 Date: Mon, 25 Sep 2023 12:53:21 +0800 Subject: [PATCH 06/13] debugging changes --- .../mlscript/compiler/mono/Monomorph.scala | 3 + compiler/shared/test/diff/mono.mls | 98 +++++++++++++++++-- .../test/scala/mlscript/compiler/Test.scala | 5 + .../src/test/scala/mlscript/DiffTests.scala | 4 +- 4 files changed, 103 insertions(+), 7 deletions(-) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala index e248771ae..507bc0963 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala @@ -277,6 +277,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: case _ => None }.headOption if(func.isDefined){ + debug.log("defined") val Item.FuncDecl(nm, prms, bd) = func.get val nFuncName = s"${nm.name}$$${obj.name}" if(!funImpls.contains(nFuncName)){ @@ -286,8 +287,10 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: BoundedExpr(FunctionValue(nFuncName, prms.map(_._2.name), List("this" -> BoundedExpr(obj)))) } else if(obj.fields.contains(field)) + debug.log("contains") obj.fields.get(field).get else{ + debug.log("else") obj.fields.flatMap(x => { if (x._1.matches("sup\\$[0-9]+")) { x._2.asValue match{ diff --git a/compiler/shared/test/diff/mono.mls b/compiler/shared/test/diff/mono.mls index d6af3ded7..1ce4e49c2 100644 --- a/compiler/shared/test/diff/mono.mls +++ b/compiler/shared/test/diff/mono.mls @@ -840,17 +840,70 @@ class Sub2(c): Sub(c+c){ (new Sub2(c)).foo() //│ |#class| |Sup|(|a|)|{|→|#fun| |foo| |#=| |a|←|↵|}|↵|#class| |Sub|(|b|)|#:| |Sup|(|b|+|b|)|{|↵|}|↵|#class| |Sub2|(|c|)|#:| |Sub|(|c|+|c|)|{|→|#fun| |foo| |#=| |a|+|c|←|↵|}|↵|(|#new| |Sub|(|10|)|)|.foo|(||)|↵|(|#new| |Sub2|(|c|)|)|.foo|(||)| //│ Parsed: {class Sup(a,) {fun foo = a}; class Sub(b,): Sup[+[b, b]] {}; class Sub2(c,): Sub[+[c, c]] {fun foo = +(a, c,)}; ('(' new Sub([10,]) {} ')').foo(); ('(' new Sub2([c,]) {} ')').foo()} -//│ /!!!\ Uncaught error: java.util.NoSuchElementException: None.get +//│ //│ at: scala.None$.get(Option.scala:627) //│ at: scala.None$.get(Option.scala:626) -//│ at: mlscript.compiler.mono.Monomorph.getFieldVal$$anonfun$1(Monomorph.scala:300) +//│ at: mlscript.compiler.mono.Monomorph.getFieldVal$$anonfun$1(Monomorph.scala:303) //│ at: mlscript.compiler.debug.RainbowDebug.trace(RainbowDebug.scala:21) -//│ at: mlscript.compiler.mono.Monomorph.getFieldVal(Monomorph.scala:306) +//│ at: mlscript.compiler.mono.Monomorph.getFieldVal(Monomorph.scala:309) //│ at: mlscript.compiler.mono.specializer.Specializer.$anonfun$5(Specializer.scala:77) //│ at: scala.collection.StrictOptimizedIterableOps.map(StrictOptimizedIterableOps.scala:100) //│ at: scala.collection.StrictOptimizedIterableOps.map$(StrictOptimizedIterableOps.scala:87) //│ at: scala.collection.immutable.Set$Set1.map(Set.scala:156) //│ at: mlscript.compiler.mono.specializer.Specializer.evaluate(Specializer.scala:80) +//│ at: mlscript.compiler.mono.specializer.Specializer.evaluate(Specializer.scala:43) +//│ at: mlscript.compiler.mono.Monomorph.updateFunc(Monomorph.scala:203) +//│ at: mlscript.compiler.mono.Monomorph.updateFunction(Monomorph.scala:139) +//│ at: mlscript.compiler.mono.Monomorph.defunctionalize(Monomorph.scala:114) +//│ at: mlscript.compiler.DiffTestCompiler.postProcess(Test.scala:35) +//│ at: mlscript.DiffTests.rec$1(DiffTests.scala:432) +//│ at: mlscript.DiffTests.$anonfun$new$3(DiffTests.scala:1055) +//│ at: org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85) +//│ at: org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83) +//│ at: org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104) +//│ [mono] ┌────┬──────────────────────────┐ +//│ │ 1 │ main$$3() │ +//│ │ 2 │ main$$4() │ +//│ │ 3 │ fun main$$4() = │ +//│ │ 4 │ new Sub2$3 (c) .foo() │ +//│ │ 5 │ fun main$$3() = │ +//│ │ 6 │ new Sub$2 (#10) .foo() │ +//│ │ 7 │ class Sub2$3(c) { │ +//│ │ 8 │ } │ +//│ │ 9 │ class Sup$1(a) { │ +//│ │ 10 │ } │ +//│ │ 11 │ class Sub$2(b) { │ +//│ │ 12 │ } │ +//│ └────┴──────────────────────────┘ +//│ [mono] evaluating main$$4, rests: HashSet(main$$3) +//│ [mono] ========== updating main$$4 ========== +//│ [mono] main$$4: () -> *49*=[*49*=...] @{} +//│ [mono] ┌ SPEC NEW Sub2$3(List([?74?])) +//│ [mono] │ par objs: List() +//│ [mono] └ SPEC NEW Sub2$3@{c: [?74?]} +//│ [mono] ┌ SPEC SEL Sub2$3@{c: [?74?]} :: foo +//│ [mono] │ defined +//│ [mono] └ SPEC SEL [foo$Sub2$3() given {this: [Sub2$3@{c: [?74?]}]}] +//│ [mono] ┌ SPEC CALL foo$Sub2$3 with ([Sub2$3@{c: [?74?]}]) +//│ [mono] │ comparing ([]) with (Plain([Sub2$3@{c: [?74?]}])) +//│ [mono] │ first time encounter foo$Sub2$3 +//│ [mono] │ evaluating foo$Sub2$3, rests: HashSet(main$$3) +//│ [mono] │ ========== updating foo$Sub2$3 ========== +//│ [mono] │ foo$Sub2$3: ([Sub2$3@{c: [?74?]}]) -> *50*=[*50*=...] @{main$$4} +//│ [mono] │ comparing [*50*=...] with [?77?] +//│ [mono] │ foo$Sub2$3: ([Sub2$3@{c: [?74?]}]) -> *50*=[?77?] @{main$$4} +//│ [mono] └ SPEC CALL [*50*=[?77?]] +//│ [mono] comparing [*49*=...] with [*50*=[?77?]] +//│ [mono] main$$4: () -> *49*=[*50*=[?77?]] @{} +//│ [mono] evaluating main$$3, rests: HashSet() +//│ [mono] ========== updating main$$3 ========== +//│ [mono] main$$3: () -> *48*=[*48*=...] @{} +//│ [mono] ┌ SPEC NEW Sub$2(List([10])) +//│ [mono] │ par objs: List() +//│ [mono] └ SPEC NEW Sub$2@{b: [10]} +//│ [mono] ┌ SPEC SEL Sub$2@{b: [10]} :: foo +//│ [mono] │ else +//│ :mono class Foo(f){ @@ -862,14 +915,47 @@ class F2(): Foo(x => x+2){} (new F2()).foo() //│ |#class| |Foo|(|f|)|{|→|#fun| |foo| |#=| |f|(|1|)|←|↵|}|↵|#class| |F1|(||)|#:| |Foo|(|x| |=>| |x|+|1|)|{||}|↵|#class| |F2|(||)|#:| |Foo|(|x| |=>| |x|+|2|)|{||}|↵|(|#new| |F1|(||)|)|.foo|(||)|↵|(|#new| |F2|(||)|)|.foo|(||)| //│ Parsed: {class Foo(f,) {fun foo = f(1,)}; class F1(): Foo[x -> +[x, 1]] {}; class F2(): Foo[x -> +[x, 2]] {}; ('(' new F1([]) {} ')').foo(); ('(' new F2([]) {} ')').foo()} -//│ /!!!\ Uncaught error: java.util.NoSuchElementException: None.get +//│ //│ at: scala.None$.get(Option.scala:627) //│ at: scala.None$.get(Option.scala:626) -//│ at: mlscript.compiler.mono.Monomorph.getFieldVal$$anonfun$1(Monomorph.scala:300) +//│ at: mlscript.compiler.mono.Monomorph.getFieldVal$$anonfun$1(Monomorph.scala:303) //│ at: mlscript.compiler.debug.RainbowDebug.trace(RainbowDebug.scala:21) -//│ at: mlscript.compiler.mono.Monomorph.getFieldVal(Monomorph.scala:306) +//│ at: mlscript.compiler.mono.Monomorph.getFieldVal(Monomorph.scala:309) //│ at: mlscript.compiler.mono.specializer.Specializer.$anonfun$5(Specializer.scala:77) //│ at: scala.collection.StrictOptimizedIterableOps.map(StrictOptimizedIterableOps.scala:100) //│ at: scala.collection.StrictOptimizedIterableOps.map$(StrictOptimizedIterableOps.scala:87) //│ at: scala.collection.immutable.Set$Set1.map(Set.scala:156) //│ at: mlscript.compiler.mono.specializer.Specializer.evaluate(Specializer.scala:80) +//│ at: mlscript.compiler.mono.specializer.Specializer.evaluate(Specializer.scala:43) +//│ at: mlscript.compiler.mono.Monomorph.updateFunc(Monomorph.scala:203) +//│ at: mlscript.compiler.mono.Monomorph.updateFunction(Monomorph.scala:139) +//│ at: mlscript.compiler.mono.Monomorph.defunctionalize(Monomorph.scala:114) +//│ at: mlscript.compiler.DiffTestCompiler.postProcess(Test.scala:35) +//│ at: mlscript.DiffTests.rec$1(DiffTests.scala:432) +//│ at: mlscript.DiffTests.$anonfun$new$3(DiffTests.scala:1055) +//│ at: org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85) +//│ at: org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83) +//│ at: org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104) +//│ [mono] ┌────┬──────────────────────┐ +//│ │ 1 │ main$$3() │ +//│ │ 2 │ main$$4() │ +//│ │ 3 │ fun main$$4() = │ +//│ │ 4 │ new F2$3 () .foo() │ +//│ │ 5 │ fun main$$3() = │ +//│ │ 6 │ new F1$2 () .foo() │ +//│ │ 7 │ class F1$2() { │ +//│ │ 8 │ } │ +//│ │ 9 │ class F2$3() { │ +//│ │ 10 │ } │ +//│ │ 11 │ class Foo$1(f) { │ +//│ │ 12 │ } │ +//│ └────┴──────────────────────┘ +//│ [mono] evaluating main$$4, rests: HashSet(main$$3) +//│ [mono] ========== updating main$$4 ========== +//│ [mono] main$$4: () -> *52*=[*52*=...] @{} +//│ [mono] ┌ SPEC NEW F2$3(List()) +//│ [mono] │ par objs: List() +//│ [mono] └ SPEC NEW F2$3@{} +//│ [mono] ┌ SPEC SEL F2$3@{} :: foo +//│ [mono] │ else +//│ diff --git a/compiler/shared/test/scala/mlscript/compiler/Test.scala b/compiler/shared/test/scala/mlscript/compiler/Test.scala index e0df0d8f0..8795fd34e 100644 --- a/compiler/shared/test/scala/mlscript/compiler/Test.scala +++ b/compiler/shared/test/scala/mlscript/compiler/Test.scala @@ -38,6 +38,11 @@ class DiffTestCompiler extends DiffTests { outputBuilder ++= "\n" }catch{ case error: MonomorphError => outputBuilder ++= (error.getMessage() :: error.getStackTrace().map(_.toString()).toList).mkString("\n") + case e : Throwable => + throw Error( + e.getStackTrace().take(20 + ).map("\n" + "\tat: " + _).mkString+"\n"+ + treeDebug.getLines.foldLeft("")((acc, str) => acc + str + "\n")) // case error: StackOverflowError => outputBuilder ++= (error.getMessage() :: error.getStackTrace().take(40).map(_.toString()).toList).mkString("\n") } // outputBuilder ++= treeDebug.getLines.mkString("\n") diff --git a/shared/src/test/scala/mlscript/DiffTests.scala b/shared/src/test/scala/mlscript/DiffTests.scala index a1a50d739..35417904a 100644 --- a/shared/src/test/scala/mlscript/DiffTests.scala +++ b/shared/src/test/scala/mlscript/DiffTests.scala @@ -1032,6 +1032,8 @@ class DiffTests failures += blockLineNum } catch { case oh_noes: ThreadDeath => throw oh_noes + case debug: Error => + output(debug.getMessage()) case err: Throwable => if (!mode.fixme) failures += allLines.size - lines.size @@ -1040,7 +1042,7 @@ class DiffTests err.getStackTrace().take( if (mode.fullExceptionStack) Int.MaxValue else if (mode.fixme || err.isInstanceOf[StackOverflowError]) 0 - else 10 + else 20 ).map("\n" + "\tat: " + _).mkString) } finally { typer.dbg = false From b2bde3275a2a4afa8a5f607b32179cfc1033b180 Mon Sep 17 00:00:00 2001 From: Harris Date: Sat, 30 Sep 2023 23:05:58 +0800 Subject: [PATCH 07/13] Fix mono tests --- compiler/shared/test/diff/mono.mls | 511 ++++++++++++------ .../test/scala/mlscript/compiler/Test.scala | 5 - .../src/test/scala/mlscript/DiffTests.scala | 4 +- 3 files changed, 337 insertions(+), 183 deletions(-) diff --git a/compiler/shared/test/diff/mono.mls b/compiler/shared/test/diff/mono.mls index 1ce4e49c2..1b4517e24 100644 --- a/compiler/shared/test/diff/mono.mls +++ b/compiler/shared/test/diff/mono.mls @@ -1,7 +1,8 @@ -:NewParser + :NewDefs :ParseOnly -// :mono + +:mono fun f(x) = if x then 42 else 1337 //│ |#fun| |f|(|x|)| |#=| |#if| |x| |#then| |42| |#else| |1337| //│ Parsed: {fun f = (x,) => if (x) then 42 else 1337} @@ -9,9 +10,14 @@ fun f(x) = if x then 42 else 1337 //│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), If(IfThen(Var(x), IntLit(42), Some(IntLit(1337)))))) //│ Lifted: //│ TypingUnit {fun f$1 = (x,) => if (x) then 42 else 1337} +//│ Mono: +//│ +//│ Defunc result: +//│ fun f$1(x) = +//│ if x then #42 else #1337 //│ -// :mono +:mono fun foo() = 42 //│ |#fun| |foo|(||)| |#=| |42| //│ Parsed: {fun foo = () => 42} @@ -19,9 +25,14 @@ fun foo() = 42 //│ TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(), IntLit(42)))) //│ Lifted: //│ TypingUnit {fun foo$1 = () => 42} +//│ Mono: +//│ +//│ Defunc result: +//│ fun foo$1() = +//│ #42 //│ -// :mono +:mono fun foo(x, #b) = if b then x else 1337 let a = foo(42, true) let b = foo(23, false) @@ -35,9 +46,18 @@ let b = foo(23, false) //│ let a$1 = () => foo$3(42, true,) //│ let b$2 = () => foo$3(23, false,) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ fun b$2() = +//│ foo$3(#23, false) +//│ fun foo$3(x, #b) = +//│ if b then x else #1337 +//│ fun a$1() = +//│ foo$3(#42, true) //│ -// :mono +:mono let x = 42 + 1337 //│ |#let| |x| |#=| |42| |+| |1337| //│ Parsed: {let x = +(42, 1337,)} @@ -45,9 +65,14 @@ let x = 42 + 1337 //│ TypingUnit(NuFunDef(Some(false), x, None, [], App(Var(+), Tup(_: IntLit(42), _: IntLit(1337))))) //│ Lifted: //│ TypingUnit {let x$1 = () => +(42, 1337,)} +//│ Mono: +//│ +//│ Defunc result: +//│ fun x$1() = +//│ +(#42, #1337) //│ -// :mono +:mono class Bar(#x) fun foo(#b) = b let a = foo(new Bar(1)) @@ -63,9 +88,20 @@ let b = foo(new Bar(2)) //│ let a$1 = () => foo$3(new Bar$1([1,]) {},) //│ let b$2 = () => foo$3(new Bar$1([2,]) {},) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ fun b$2() = +//│ foo$3(new Bar$1 (#2) ) +//│ fun foo$3(#b) = +//│ b +//│ fun a$1() = +//│ foo$3(new Bar$1 (#1) ) +//│ class Bar$1(#x) { +//│ } //│ -// :mono +:mono class OneInt(#a){ fun inc() = a+1 } @@ -79,9 +115,19 @@ class OneInt(#a){ //│ class OneInt$1([#a,]) {fun inc = () => +((this).a, 1,)} //│ Code(List(('(' new OneInt$1([1,]) {} ')').inc())) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$1() +//│ fun inc$OneInt$1(this) = +//│ +(this.a, #1) +//│ fun main$$1() = +//│ new OneInt$1 (#1) match {case obj: OneInt$1 => inc$OneInt$1(obj)} +//│ class OneInt$1(#a) { +//│ } //│ -// :mono +:mono class OneInt(#a){ fun add(x) = new OneInt(a+x.a) @@ -98,26 +144,42 @@ class OneInt(#a){ //│ } //│ Code(List(('(' new OneInt$1([1,]) {} ')').add(new OneInt$1([2,]) {},))) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$1() +//│ fun add$OneInt$1(this, x) = +//│ new OneInt$1 (+(this.a, x.a)) +//│ fun main$$1() = +//│ new OneInt$1 (#1) match {case obj: OneInt$1 => add$OneInt$1(obj, new OneInt$1 (#2) )} +//│ class OneInt$1(#a) { +//│ } //│ -// :mono +:mono if true then 1 else 0 -if 1+1 > 1 then 1-1 else 1*1 -//│ |#if| |true| |#then| |1| |#else| |0|↵|#if| |1|+|1| |>| |1| |#then| |1|-1| |#else| |1|*|1| -//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword -//│ ║ l.105: if 1+1 > 1 then 1-1 else 1*1 -//│ ╙── ^^^ -//│ Parsed: {if (true) then 1 else 0; if (>(+(1, 1,), 1,)) then 1(-1,) else *(1, 1,)} +if 1+1 > 1 then 1 - 1 else 1*1 +//│ |#if| |true| |#then| |1| |#else| |0|↵|#if| |1|+|1| |>| |1| |#then| |1| |-| |1| |#else| |1|*|1| +//│ Parsed: {if (true) then 1 else 0; if (>(+(1, 1,), 1,)) then -(1, 1,) else *(1, 1,)} //│ Parsed: -//│ TypingUnit(If(IfThen(Var(true), IntLit(1), Some(IntLit(0))), If(IfThen(App(Var(>), Tup(_: App(Var(+), Tup(_: IntLit(1), _: IntLit(1))), _: IntLit(1))), App(IntLit(1), Tup(_: IntLit(-1))), Some(App(Var(*), Tup(_: IntLit(1), _: IntLit(1)))))) +//│ TypingUnit(If(IfThen(Var(true), IntLit(1), Some(IntLit(0))), If(IfThen(App(Var(>), Tup(_: App(Var(+), Tup(_: IntLit(1), _: IntLit(1))), _: IntLit(1))), App(Var(-), Tup(_: IntLit(1), _: IntLit(1))), Some(App(Var(*), Tup(_: IntLit(1), _: IntLit(1)))))) //│ Lifted: //│ TypingUnit { //│ Code(List(if (true) then 1 else 0)) -//│ Code(List(if (>(+(1, 1,), 1,)) then 1(-1,) else *(1, 1,))) +//│ Code(List(if (>(+(1, 1,), 1,)) then -(1, 1,) else *(1, 1,))) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$0() +//│ main$$1() +//│ fun main$$0() = +//│ if true then #1 else #0 +//│ fun main$$1() = +//│ if >(+(#1, #1), #1) then -(#1, #1) else *(#1, #1) //│ -// :mono +:mono if(b) then 1 else 2 //│ |#if|(|b|)| |#then| |1| |#else| |2| //│ Parsed: {if ('(' b ')') then 1 else 2} @@ -125,9 +187,15 @@ if(b) then 1 else 2 //│ TypingUnit(If(IfThen(Bra(rcd = false, Var(b)), IntLit(1), Some(IntLit(2)))) //│ Lifted: //│ TypingUnit {Code(List(if ('(' b ')') then 1 else 2))} +//│ Mono: +//│ +//│ Defunc result: +//│ main$$0() +//│ fun main$$0() = +//│ if b then #1 else #2 //│ -// :mono +:mono ((f, g) => f(g))(f => f, true) //│ |(|(|f|,| |g|)| |=>| |f|(|g|)|)|(|f| |=>| |f|,| |true|)| //│ Parsed: {'(' (f, g,) => f(g,) ')'((f,) => f, true,)} @@ -139,6 +207,20 @@ if(b) then 1 else 2 //│ class Lambda1$2$2([]) {fun apply = (f,) => f} //│ Code(List('(' {new Lambda2$1$1([]) {}} ')'({new Lambda1$2$2([]) {}}, true,))) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$2() +//│ fun apply$Lambda2$1$1(this, f, g) = +//│ f match {case obj: Lambda1$2$2 => apply$Lambda1$2$2(obj, g)} +//│ fun main$$2() = +//│ new Lambda2$1$1 () match {case obj: Lambda2$1$1 => apply$Lambda2$1$1(obj, new Lambda1$2$2 () , true)} +//│ fun apply$Lambda1$2$2(this, f) = +//│ f +//│ class Lambda2$1$1() { +//│ } +//│ class Lambda1$2$2() { +//│ } //│ @@ -165,25 +247,30 @@ if(b) then 1 else 2 //│ } //│ -// :mono +:mono fun f(x) = - if(x > 0) then x+1 else x-1 + if(x > 0) then x+1 else x - 1 f(2)+3 -//│ |#fun| |f|(|x|)| |#=|→|#if|(|x| |>| |0|)| |#then| |x|+|1| |#else| |x|-1|←|↵|f|(|2|)|+|3| -//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword -//│ ║ l.170: if(x > 0) then x+1 else x-1 -//│ ╙── ^^^ -//│ Parsed: {fun f = (x,) => {if ('(' >(x, 0,) ')') then +(x, 1,) else x(-1,)}; +(f(2,), 3,)} +//│ |#fun| |f|(|x|)| |#=|→|#if|(|x| |>| |0|)| |#then| |x|+|1| |#else| |x| |-| |1|←|↵|f|(|2|)|+|3| +//│ Parsed: {fun f = (x,) => {if ('(' >(x, 0,) ')') then +(x, 1,) else -(x, 1,)}; +(f(2,), 3,)} //│ Parsed: //│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(+), Tup(_: App(Var(f), Tup(_: IntLit(2))), _: IntLit(3)))) //│ Lifted: //│ TypingUnit { -//│ fun f$1 = (x,) => {if ('(' >(x, 0,) ')') then +(x, 1,) else x(-1,)} +//│ fun f$1 = (x,) => {if ('(' >(x, 0,) ')') then +(x, 1,) else -(x, 1,)} //│ Code(List(+(f$1(2,), 3,))) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$1() +//│ fun f$1(x) = +//│ if >(x, #0) then +(x, #1) else -(x, #1) +//│ fun main$$1() = +//│ +(f$1(#2), #3) //│ -// :mono +:mono fun fac(n) = if (n > 1) then fac(n - 1) * n else 1 fac(2) @@ -196,9 +283,17 @@ fac(2) //│ fun fac$1 = (n,) => {if ('(' >(n, 1,) ')') then *(fac$1(-(n, 1,),), n,) else 1} //│ Code(List(fac$1(2,))) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$1() +//│ fun fac$1(n) = +//│ if >(n, #1) then *(fac$1(-(n, #1)), n) else #1 +//│ fun main$$1() = +//│ fac$1(#2) //│ -// :mono +:mono class List(l, hasTail) {} class Nil(l, hasTail) {} fun count(lst) = @@ -215,6 +310,18 @@ count(new List(new List(new Nil(0, false), true), true)) //│ fun count$1 = (lst,) => {if ((lst).hasTail) then +(count$1((lst).l,), 1,) else 1} //│ Code(List(count$1(new List$1([new List$1([new Nil$2([0, false,]) {}, true,]) {}, true,]) {},))) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$3() +//│ fun count$1(lst) = +//│ if lst.hasTail then +(count$1(lst.l), #1) else #1 +//│ fun main$$3() = +//│ count$1(new List$1 (new List$1 (new Nil$2 (#0, false) , true) , true) ) +//│ class Nil$2(l, hasTail) { +//│ } +//│ class List$1(l, hasTail) { +//│ } //│ :mono @@ -311,7 +418,7 @@ fun add2(x) = x+2 //│ } //│ -// :mono +:mono class List(e, tail) { fun count() = 1 + tail.count() } @@ -336,6 +443,27 @@ foo(generate(1)) //│ Code(List(foo$1(new List$1([1, new List$1([2, new Nil$2([]) {},]) {},]) {},))) //│ Code(List(foo$1(generate$2(1,),))) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$4() +//│ main$$5() +//│ fun foo$1(x) = +//│ x match {case obj: Nil$2 => count$Nil$2(obj); case obj: List$1 => count$List$1(obj)} +//│ fun count$Nil$2(this) = +//│ #0 +//│ fun count$List$1(this) = +//│ +(#1, this.tail match {case obj: List$1 => count$List$1(obj); case obj: Nil$2 => count$Nil$2(obj)}) +//│ fun generate$2(x) = +//│ if >(x, #0) then new List$1 (x, generate$2(+(x, #1))) else new Nil$2 () +//│ fun main$$5() = +//│ foo$1(generate$2(#1)) +//│ fun main$$4() = +//│ foo$1(new List$1 (#1, new List$1 (#2, new Nil$2 () ) ) ) +//│ class Nil$2() { +//│ } +//│ class List$1(e, tail) { +//│ } //│ :mono @@ -547,7 +675,7 @@ foo(l => (new Cons(2, l)).count()) //│ } //│ -// :mono +:mono class E() { fun derive(x) = new E @@ -607,10 +735,42 @@ class C(e1, e2){ //│ } //│ Code(List((('(' new C$5([new Ch$3([1,]) {}, new A$4([new Ch$3([2,]) {}, new Ch$3([3,]) {},]) {},]) {} ')').derive(0,)).isEmpty())) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$5() +//│ fun isEmpty$C$5(this) = +//│ &&(this.e1 match {case obj: Ep$2 => isEmpty$Ep$2(obj); case obj: E$1 => isEmpty$E$1(obj)}, this.e2 match {case obj: A$4 => isEmpty$A$4(obj)}) +//│ fun isEmpty$Ch$3(this) = +//│ false +//│ fun isEmpty$E$1(this) = +//│ false +//│ fun isEmpty$A$4(this) = +//│ ||(this.e1 match {case obj: Ch$3 => isEmpty$Ch$3(obj)}, this.e2 match {case obj: Ch$3 => isEmpty$Ch$3(obj)}) +//│ fun derive$A$4(this, x) = +//│ new A$4 (this.e1 match {case obj: Ch$3 => derive$Ch$3(obj, x)}, this.e2 match {case obj: Ch$3 => derive$Ch$3(obj, x)}) +//│ fun derive$C$5(this, x) = +//│ if this.e1 match {case obj: Ch$3 => isEmpty$Ch$3(obj)} then new A$4 (new C$5 (this.e1 match {case obj: Ch$3 => derive$Ch$3(obj, x)}, this.e2) , this.e2 match {case obj: A$4 => derive$A$4(obj, x)}) else new C$5 (this.e1 match {case obj: Ch$3 => derive$Ch$3(obj, x)}, this.e2) +//│ fun derive$Ch$3(this, x) = +//│ if ==(x, this.i) then new Ep$2 () else new E$1 () +//│ fun main$$5() = +//│ new C$5 (new Ch$3 (#1) , new A$4 (new Ch$3 (#2) , new Ch$3 (#3) ) ) match {case obj: C$5 => derive$C$5(obj, #0)} match {case obj: C$5 => isEmpty$C$5(obj)} +//│ fun isEmpty$Ep$2(this) = +//│ true +//│ class A$4(e1, e2) { +//│ } +//│ class E$1() { +//│ } +//│ class C$5(e1, e2) { +//│ } +//│ class Ep$2() { +//│ } +//│ class Ch$3(i) { +//│ } //│ -// :mono +:mono class List(l, hasTail) {} class Nil(hasTail) {} fun gen() = @@ -627,11 +787,23 @@ gen() //│ fun gen$1 = () => {if (anyUnknown) then new List$1([gen$1(), true,]) {} else new Nil$2([false,]) {}} //│ Code(List(gen$1())) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$3() +//│ fun gen$1() = +//│ if anyUnknown then new List$1 (gen$1(), true) else new Nil$2 (false) +//│ fun main$$3() = +//│ gen$1() +//│ class Nil$2(hasTail) { +//│ } +//│ class List$1(l, hasTail) { +//│ } //│ -// :mono +:mono class Foo(x){ fun bar(y) = x+y fun boo(z) = bar(z)+x @@ -649,28 +821,47 @@ class Foo(x){ //│ } //│ Code(List(('(' new Foo$1([1,]) {} ')').boo(2,))) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$1() +//│ fun boo$Foo$1(this, z) = +//│ +(this match {case obj: Foo$1 => bar$Foo$1(obj, z)}, this.x) +//│ fun bar$Foo$1(this, y) = +//│ +(this.x, y) +//│ fun main$$1() = +//│ new Foo$1 (#1) match {case obj: Foo$1 => boo$Foo$1(obj, #2)} +//│ class Foo$1(x) { +//│ } //│ -// :mono +:mono class OneInt(a){ fun fac() = - if(a > 0) then (new OneInt(a-1)).fac() else 1 + if(a > 0) then (new OneInt(a - 1)).fac() else 1 } (new OneInt(10)).fac() -//│ |#class| |OneInt|(|a|)|{|→|#fun| |fac|(||)| |#=| |→|#if|(|a| |>| |0|)| |#then| |(|#new| |OneInt|(|a|-1|)|)|.fac|(||)| |#else| |1| |←|←|↵|}|↵|(|#new| |OneInt|(|10|)|)|.fac|(||)| -//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword -//│ ║ l.657: if(a > 0) then (new OneInt(a-1)).fac() else 1 -//│ ╙── ^^^ -//│ Parsed: {class OneInt(a,) {fun fac = () => {if ('(' >(a, 0,) ')') then ('(' new OneInt([a(-1,),]) {} ')').fac() else 1}}; ('(' new OneInt([10,]) {} ')').fac()} +//│ |#class| |OneInt|(|a|)|{|→|#fun| |fac|(||)| |#=| |→|#if|(|a| |>| |0|)| |#then| |(|#new| |OneInt|(|a| |-| |1|)|)|.fac|(||)| |#else| |1| |←|←|↵|}|↵|(|#new| |OneInt|(|10|)|)|.fac|(||)| +//│ Parsed: {class OneInt(a,) {fun fac = () => {if ('(' >(a, 0,) ')') then ('(' new OneInt([-(a, 1,),]) {} ')').fac() else 1}}; ('(' new OneInt([10,]) {} ')').fac()} //│ Parsed: //│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), None, None, TypingUnit(NuFunDef(None, fac, None, [], Lam(Tup(), Blk(...))))), App(Sel(Bra(rcd = false, New(Some((TypeName(OneInt),[10,])), TypingUnit())), fac), Tup())) //│ Lifted: //│ TypingUnit { //│ class OneInt$1([a,]) { -//│ fun fac = () => {if ('(' >((this).a, 0,) ')') then ('(' new OneInt$1([(this).a(-1,),]) {} ')').fac() else 1} +//│ fun fac = () => {if ('(' >((this).a, 0,) ')') then ('(' new OneInt$1([-((this).a, 1,),]) {} ')').fac() else 1} //│ } //│ Code(List(('(' new OneInt$1([10,]) {} ')').fac())) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$1() +//│ fun fac$OneInt$1(this) = +//│ if >(this.a, #0) then new OneInt$1 (-(this.a, #1)) match {case obj: OneInt$1 => fac$OneInt$1(obj)} else #1 +//│ fun main$$1() = +//│ new OneInt$1 (#10) match {case obj: OneInt$1 => fac$OneInt$1(obj)} +//│ class OneInt$1(a) { +//│ } //│ :mono @@ -724,28 +915,19 @@ f(new FooMinus(2)) :mono fun f(x) = if x > any then 0 - else g(x-1) + else g(x - 1) fun g(x) = - if x > any then g(x-1) - else f(x-2) + if x > any then g(x - 1) + else f(x - 2) g(1) -//│ |#fun| |f|(|x|)| |#=| |→|#if| |x| |>| |any| |#then| |0|↵|#else| |g|(|x|-1|)|←|↵|#fun| |g|(|x|)| |#=| |→|#if| |x| |>| |any| |#then| |g|(|x|-1|)|↵|#else| |f|(|x|-2|)|←|↵|g|(|1|)| -//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword -//│ ║ l.727: else g(x-1) -//│ ╙── ^^^ -//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword -//│ ║ l.729: if x > any then g(x-1) -//│ ╙── ^^^ -//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword -//│ ║ l.730: else f(x-2) -//│ ╙── ^^^ -//│ Parsed: {fun f = (x,) => {if (>(x, any,)) then 0 else g(x(-1,),)}; fun g = (x,) => {if (>(x, any,)) then g(x(-1,),) else f(x(-2,),)}; g(1,)} +//│ |#fun| |f|(|x|)| |#=| |→|#if| |x| |>| |any| |#then| |0|↵|#else| |g|(|x| |-| |1|)|←|↵|#fun| |g|(|x|)| |#=| |→|#if| |x| |>| |any| |#then| |g|(|x| |-| |1|)|↵|#else| |f|(|x| |-| |2|)|←|↵|g|(|1|)| +//│ Parsed: {fun f = (x,) => {if (>(x, any,)) then 0 else g(-(x, 1,),)}; fun g = (x,) => {if (>(x, any,)) then g(-(x, 1,),) else f(-(x, 2,),)}; g(1,)} //│ Parsed: //│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, g, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(g), Tup(_: IntLit(1)))) //│ Lifted: //│ TypingUnit { -//│ fun f$1 = (x,) => {if (>(x, any,)) then 0 else g$2(x(-1,),)} -//│ fun g$2 = (x,) => {if (>(x, any,)) then g$2(x(-1,),) else f$1(x(-2,),)} +//│ fun f$1 = (x,) => {if (>(x, any,)) then 0 else g$2(-(x, 1,),)} +//│ fun g$2 = (x,) => {if (>(x, any,)) then g$2(-(x, 1,),) else f$1(-(x, 2,),)} //│ Code(List(g$2(1,))) //│ } //│ Mono: @@ -753,9 +935,9 @@ g(1) //│ Defunc result: //│ main$$2() //│ fun f$1(x) = -//│ if >(x, any) then #0 else g$2(x(#-1)) +//│ if >(x, any) then #0 else g$2(-(x, #1)) //│ fun g$2(x) = -//│ if >(x, any) then g$2(x(#-1)) else f$1(x(#-2)) +//│ if >(x, any) then g$2(-(x, #1)) else f$1(-(x, #2)) //│ fun main$$2() = //│ g$2(#1) //│ @@ -794,7 +976,7 @@ class OneBool(b){ //│ } //│ -// :mono +:mono class Bar(x: int) { fun FooMinus(y: int) = x + y fun car = foo(2) @@ -824,138 +1006,117 @@ bar.car //│ Code(List((Car$2()).da(Bar$1(1337,),))) //│ Code(List((bar).car)) //│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$4() +//│ main$$5() +//│ main$$6() +//│ fun bar$1() = +//│ Bar$1(#42) +//│ fun main$$6() = +//│ bar.car +//│ fun baz$2(Bar$1) = +//│ b match {} +//│ fun main$$5() = +//│ Car$2() match {} +//│ fun main$$4() = +//│ baz$2(bar) +//│ class Bar$1(int) { +//│ } +//│ class Car$2() { +//│ } //│ :mono -:d class Sup(a){ fun foo = a } -class Sub(b): Sup(b+b){ +class Sub(b) extends Sup(b+b){ } -class Sub2(c): Sub(c+c){ +class Sub2(c) extends Sub(c+c){ fun foo = a+c } (new Sub(10)).foo() (new Sub2(c)).foo() -//│ |#class| |Sup|(|a|)|{|→|#fun| |foo| |#=| |a|←|↵|}|↵|#class| |Sub|(|b|)|#:| |Sup|(|b|+|b|)|{|↵|}|↵|#class| |Sub2|(|c|)|#:| |Sub|(|c|+|c|)|{|→|#fun| |foo| |#=| |a|+|c|←|↵|}|↵|(|#new| |Sub|(|10|)|)|.foo|(||)|↵|(|#new| |Sub2|(|c|)|)|.foo|(||)| -//│ Parsed: {class Sup(a,) {fun foo = a}; class Sub(b,): Sup[+[b, b]] {}; class Sub2(c,): Sub[+[c, c]] {fun foo = +(a, c,)}; ('(' new Sub([10,]) {} ')').foo(); ('(' new Sub2([c,]) {} ')').foo()} -//│ -//│ at: scala.None$.get(Option.scala:627) -//│ at: scala.None$.get(Option.scala:626) -//│ at: mlscript.compiler.mono.Monomorph.getFieldVal$$anonfun$1(Monomorph.scala:303) -//│ at: mlscript.compiler.debug.RainbowDebug.trace(RainbowDebug.scala:21) -//│ at: mlscript.compiler.mono.Monomorph.getFieldVal(Monomorph.scala:309) -//│ at: mlscript.compiler.mono.specializer.Specializer.$anonfun$5(Specializer.scala:77) -//│ at: scala.collection.StrictOptimizedIterableOps.map(StrictOptimizedIterableOps.scala:100) -//│ at: scala.collection.StrictOptimizedIterableOps.map$(StrictOptimizedIterableOps.scala:87) -//│ at: scala.collection.immutable.Set$Set1.map(Set.scala:156) -//│ at: mlscript.compiler.mono.specializer.Specializer.evaluate(Specializer.scala:80) -//│ at: mlscript.compiler.mono.specializer.Specializer.evaluate(Specializer.scala:43) -//│ at: mlscript.compiler.mono.Monomorph.updateFunc(Monomorph.scala:203) -//│ at: mlscript.compiler.mono.Monomorph.updateFunction(Monomorph.scala:139) -//│ at: mlscript.compiler.mono.Monomorph.defunctionalize(Monomorph.scala:114) -//│ at: mlscript.compiler.DiffTestCompiler.postProcess(Test.scala:35) -//│ at: mlscript.DiffTests.rec$1(DiffTests.scala:432) -//│ at: mlscript.DiffTests.$anonfun$new$3(DiffTests.scala:1055) -//│ at: org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85) -//│ at: org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83) -//│ at: org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104) -//│ [mono] ┌────┬──────────────────────────┐ -//│ │ 1 │ main$$3() │ -//│ │ 2 │ main$$4() │ -//│ │ 3 │ fun main$$4() = │ -//│ │ 4 │ new Sub2$3 (c) .foo() │ -//│ │ 5 │ fun main$$3() = │ -//│ │ 6 │ new Sub$2 (#10) .foo() │ -//│ │ 7 │ class Sub2$3(c) { │ -//│ │ 8 │ } │ -//│ │ 9 │ class Sup$1(a) { │ -//│ │ 10 │ } │ -//│ │ 11 │ class Sub$2(b) { │ -//│ │ 12 │ } │ -//│ └────┴──────────────────────────┘ -//│ [mono] evaluating main$$4, rests: HashSet(main$$3) -//│ [mono] ========== updating main$$4 ========== -//│ [mono] main$$4: () -> *49*=[*49*=...] @{} -//│ [mono] ┌ SPEC NEW Sub2$3(List([?74?])) -//│ [mono] │ par objs: List() -//│ [mono] └ SPEC NEW Sub2$3@{c: [?74?]} -//│ [mono] ┌ SPEC SEL Sub2$3@{c: [?74?]} :: foo -//│ [mono] │ defined -//│ [mono] └ SPEC SEL [foo$Sub2$3() given {this: [Sub2$3@{c: [?74?]}]}] -//│ [mono] ┌ SPEC CALL foo$Sub2$3 with ([Sub2$3@{c: [?74?]}]) -//│ [mono] │ comparing ([]) with (Plain([Sub2$3@{c: [?74?]}])) -//│ [mono] │ first time encounter foo$Sub2$3 -//│ [mono] │ evaluating foo$Sub2$3, rests: HashSet(main$$3) -//│ [mono] │ ========== updating foo$Sub2$3 ========== -//│ [mono] │ foo$Sub2$3: ([Sub2$3@{c: [?74?]}]) -> *50*=[*50*=...] @{main$$4} -//│ [mono] │ comparing [*50*=...] with [?77?] -//│ [mono] │ foo$Sub2$3: ([Sub2$3@{c: [?74?]}]) -> *50*=[?77?] @{main$$4} -//│ [mono] └ SPEC CALL [*50*=[?77?]] -//│ [mono] comparing [*49*=...] with [*50*=[?77?]] -//│ [mono] main$$4: () -> *49*=[*50*=[?77?]] @{} -//│ [mono] evaluating main$$3, rests: HashSet() -//│ [mono] ========== updating main$$3 ========== -//│ [mono] main$$3: () -> *48*=[*48*=...] @{} -//│ [mono] ┌ SPEC NEW Sub$2(List([10])) -//│ [mono] │ par objs: List() -//│ [mono] └ SPEC NEW Sub$2@{b: [10]} -//│ [mono] ┌ SPEC SEL Sub$2@{b: [10]} :: foo -//│ [mono] │ else +//│ |#class| |Sup|(|a|)|{|→|#fun| |foo| |#=| |a|←|↵|}|↵|#class| |Sub|(|b|)| |#extends| |Sup|(|b|+|b|)|{|↵|}|↵|#class| |Sub2|(|c|)| |#extends| |Sub|(|c|+|c|)|{|→|#fun| |foo| |#=| |a|+|c|←|↵|}|↵|(|#new| |Sub|(|10|)|)|.foo|(||)|↵|(|#new| |Sub2|(|c|)|)|.foo|(||)| +//│ Parsed: {class Sup(a,) {fun foo = a}; class Sub(b,): Sup(+(b, b,),) {}; class Sub2(c,): Sub(+(c, c,),) {fun foo = +(a, c,)}; ('(' new Sub([10,]) {} ')').foo(); ('(' new Sub2([c,]) {} ')').foo()} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, Sup, (), Tup(_: Var(a)), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Var(a)))), NuTypeDef(class, Sub, (), Tup(_: Var(b)), (App(Var(Sup), Tup(_: App(Var(+), Tup(_: Var(b), _: Var(b)))))), None, None, TypingUnit()), NuTypeDef(class, Sub2, (), Tup(_: Var(c)), (App(Var(Sub), Tup(_: App(Var(+), Tup(_: Var(c), _: Var(c)))))), None, None, TypingUnit(NuFunDef(None, foo, None, [], App(Var(+), Tup(_: Var(a), _: Var(c)))))), App(Sel(Bra(rcd = false, New(Some((TypeName(Sub),[10,])), TypingUnit())), foo), Tup()), App(Sel(Bra(rcd = false, New(Some((TypeName(Sub2),[c,])), TypingUnit())), foo), Tup())) +//│ Lifted: +//│ TypingUnit { +//│ class Sup$1([a,]) {fun foo = () => (this).a} +//│ class Sub$2([b,]): Sup$1(+((this).b, (this).b,),) {} +//│ class Sub2$3([c,]): Sub$2(+((this).c, (this).c,),) {fun foo = () => +((this).a, (this).c,)} +//│ Code(List(('(' new Sub$2([10,]) {} ')').foo())) +//│ Code(List(('(' new Sub2$3([c,]) {} ')').foo())) +//│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$3() +//│ main$$4() +//│ fun main$$4() = +//│ new Sub2$3 (c) match {case obj: Sub2$3 => foo$Sub2$3(obj)} +//│ fun foo$Sup$1(this) = +//│ this.a +//│ fun foo$Sub2$3(this) = +//│ +(this.a, this.c) +//│ fun main$$3() = +//│ new Sub$2 (#10) match {case obj: Sub$2 => foo$Sup$1(obj)} +//│ class Sub2$3(c): Sub$2(+(this.c, this.c)) { +//│ } +//│ class Sup$1(a) { +//│ } +//│ class Sub$2(b): Sup$1(+(this.b, this.b)) { +//│ } //│ :mono class Foo(f){ fun foo = f(1) } -class F1(): Foo(x => x+1){} -class F2(): Foo(x => x+2){} +class F1() extends Foo(x => x+1){} +class F2() extends Foo(x => x+2){} (new F1()).foo() (new F2()).foo() -//│ |#class| |Foo|(|f|)|{|→|#fun| |foo| |#=| |f|(|1|)|←|↵|}|↵|#class| |F1|(||)|#:| |Foo|(|x| |=>| |x|+|1|)|{||}|↵|#class| |F2|(||)|#:| |Foo|(|x| |=>| |x|+|2|)|{||}|↵|(|#new| |F1|(||)|)|.foo|(||)|↵|(|#new| |F2|(||)|)|.foo|(||)| -//│ Parsed: {class Foo(f,) {fun foo = f(1,)}; class F1(): Foo[x -> +[x, 1]] {}; class F2(): Foo[x -> +[x, 2]] {}; ('(' new F1([]) {} ')').foo(); ('(' new F2([]) {} ')').foo()} -//│ -//│ at: scala.None$.get(Option.scala:627) -//│ at: scala.None$.get(Option.scala:626) -//│ at: mlscript.compiler.mono.Monomorph.getFieldVal$$anonfun$1(Monomorph.scala:303) -//│ at: mlscript.compiler.debug.RainbowDebug.trace(RainbowDebug.scala:21) -//│ at: mlscript.compiler.mono.Monomorph.getFieldVal(Monomorph.scala:309) -//│ at: mlscript.compiler.mono.specializer.Specializer.$anonfun$5(Specializer.scala:77) -//│ at: scala.collection.StrictOptimizedIterableOps.map(StrictOptimizedIterableOps.scala:100) -//│ at: scala.collection.StrictOptimizedIterableOps.map$(StrictOptimizedIterableOps.scala:87) -//│ at: scala.collection.immutable.Set$Set1.map(Set.scala:156) -//│ at: mlscript.compiler.mono.specializer.Specializer.evaluate(Specializer.scala:80) -//│ at: mlscript.compiler.mono.specializer.Specializer.evaluate(Specializer.scala:43) -//│ at: mlscript.compiler.mono.Monomorph.updateFunc(Monomorph.scala:203) -//│ at: mlscript.compiler.mono.Monomorph.updateFunction(Monomorph.scala:139) -//│ at: mlscript.compiler.mono.Monomorph.defunctionalize(Monomorph.scala:114) -//│ at: mlscript.compiler.DiffTestCompiler.postProcess(Test.scala:35) -//│ at: mlscript.DiffTests.rec$1(DiffTests.scala:432) -//│ at: mlscript.DiffTests.$anonfun$new$3(DiffTests.scala:1055) -//│ at: org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85) -//│ at: org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83) -//│ at: org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104) -//│ [mono] ┌────┬──────────────────────┐ -//│ │ 1 │ main$$3() │ -//│ │ 2 │ main$$4() │ -//│ │ 3 │ fun main$$4() = │ -//│ │ 4 │ new F2$3 () .foo() │ -//│ │ 5 │ fun main$$3() = │ -//│ │ 6 │ new F1$2 () .foo() │ -//│ │ 7 │ class F1$2() { │ -//│ │ 8 │ } │ -//│ │ 9 │ class F2$3() { │ -//│ │ 10 │ } │ -//│ │ 11 │ class Foo$1(f) { │ -//│ │ 12 │ } │ -//│ └────┴──────────────────────┘ -//│ [mono] evaluating main$$4, rests: HashSet(main$$3) -//│ [mono] ========== updating main$$4 ========== -//│ [mono] main$$4: () -> *52*=[*52*=...] @{} -//│ [mono] ┌ SPEC NEW F2$3(List()) -//│ [mono] │ par objs: List() -//│ [mono] └ SPEC NEW F2$3@{} -//│ [mono] ┌ SPEC SEL F2$3@{} :: foo -//│ [mono] │ else +//│ |#class| |Foo|(|f|)|{|→|#fun| |foo| |#=| |f|(|1|)|←|↵|}|↵|#class| |F1|(||)| |#extends| |Foo|(|x| |=>| |x|+|1|)|{||}|↵|#class| |F2|(||)| |#extends| |Foo|(|x| |=>| |x|+|2|)|{||}|↵|(|#new| |F1|(||)|)|.foo|(||)|↵|(|#new| |F2|(||)|)|.foo|(||)| +//│ Parsed: {class Foo(f,) {fun foo = f(1,)}; class F1(): Foo((x,) => +(x, 1,),) {}; class F2(): Foo((x,) => +(x, 2,),) {}; ('(' new F1([]) {} ')').foo(); ('(' new F2([]) {} ')').foo()} +//│ Parsed: +//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(_: Var(f)), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], App(Var(f), Tup(_: IntLit(1)))))), NuTypeDef(class, F1, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(Var(+), Tup(_: Var(x), _: IntLit(1))))))), None, None, TypingUnit()), NuTypeDef(class, F2, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(Var(+), Tup(_: Var(x), _: IntLit(2))))))), None, None, TypingUnit()), App(Sel(Bra(rcd = false, New(Some((TypeName(F1),[])), TypingUnit())), foo), Tup()), App(Sel(Bra(rcd = false, New(Some((TypeName(F2),[])), TypingUnit())), foo), Tup())) +//│ Lifted: +//│ TypingUnit { +//│ class Foo$1([f,]) {fun foo = () => (this).f(1,)} +//│ class F1$2_Lambda1$1$4([par$F1$2,]) {fun apply = (x,) => +(x, 1,)} +//│ class F1$2([]): Foo$1({new F1$2_Lambda1$1$4([this,]) {}},) {} +//│ class F2$3_Lambda1$2$5([par$F2$3,]) {fun apply = (x,) => +(x, 2,)} +//│ class F2$3([]): Foo$1({new F2$3_Lambda1$2$5([this,]) {}},) {} +//│ Code(List(('(' new F1$2([]) {} ')').foo())) +//│ Code(List(('(' new F2$3([]) {} ')').foo())) +//│ } +//│ Mono: +//│ +//│ Defunc result: +//│ main$$5() +//│ main$$6() +//│ fun apply$F2$3_Lambda1$2$5(this, x) = +//│ +(x, #2) +//│ fun foo$Foo$1(this) = +//│ this match {case obj: Foo$1 => obj.f match {case obj$F2$3_Lambda1$2$5: F2$3_Lambda1$2$5 => apply$F2$3_Lambda1$2$5(obj$F2$3_Lambda1$2$5, #1); case obj$F1$2_Lambda1$1$4: F1$2_Lambda1$1$4 => apply$F1$2_Lambda1$1$4(obj$F1$2_Lambda1$1$4, #1)}} +//│ fun main$$6() = +//│ new F2$3 () match {case obj: F2$3 => foo$Foo$1(obj)} +//│ fun main$$5() = +//│ new F1$2 () match {case obj: F1$2 => foo$Foo$1(obj)} +//│ fun apply$F1$2_Lambda1$1$4(this, x) = +//│ +(x, #1) +//│ class F1$2(): Foo$1(new F1$2_Lambda1$1$4 (this) ) { +//│ } +//│ class F2$3_Lambda1$2$5(par$F2$3) { +//│ } +//│ class F2$3(): Foo$1(new F2$3_Lambda1$2$5 (this) ) { +//│ } +//│ class Foo$1(f) { +//│ } +//│ class F1$2_Lambda1$1$4(par$F1$2) { +//│ } //│ diff --git a/compiler/shared/test/scala/mlscript/compiler/Test.scala b/compiler/shared/test/scala/mlscript/compiler/Test.scala index 8795fd34e..e0df0d8f0 100644 --- a/compiler/shared/test/scala/mlscript/compiler/Test.scala +++ b/compiler/shared/test/scala/mlscript/compiler/Test.scala @@ -38,11 +38,6 @@ class DiffTestCompiler extends DiffTests { outputBuilder ++= "\n" }catch{ case error: MonomorphError => outputBuilder ++= (error.getMessage() :: error.getStackTrace().map(_.toString()).toList).mkString("\n") - case e : Throwable => - throw Error( - e.getStackTrace().take(20 - ).map("\n" + "\tat: " + _).mkString+"\n"+ - treeDebug.getLines.foldLeft("")((acc, str) => acc + str + "\n")) // case error: StackOverflowError => outputBuilder ++= (error.getMessage() :: error.getStackTrace().take(40).map(_.toString()).toList).mkString("\n") } // outputBuilder ++= treeDebug.getLines.mkString("\n") diff --git a/shared/src/test/scala/mlscript/DiffTests.scala b/shared/src/test/scala/mlscript/DiffTests.scala index 35417904a..a1a50d739 100644 --- a/shared/src/test/scala/mlscript/DiffTests.scala +++ b/shared/src/test/scala/mlscript/DiffTests.scala @@ -1032,8 +1032,6 @@ class DiffTests failures += blockLineNum } catch { case oh_noes: ThreadDeath => throw oh_noes - case debug: Error => - output(debug.getMessage()) case err: Throwable => if (!mode.fixme) failures += allLines.size - lines.size @@ -1042,7 +1040,7 @@ class DiffTests err.getStackTrace().take( if (mode.fullExceptionStack) Int.MaxValue else if (mode.fixme || err.isInstanceOf[StackOverflowError]) 0 - else 20 + else 10 ).map("\n" + "\tat: " + _).mkString) } finally { typer.dbg = false From 30552885c2cee67f9924ff79054b2061939fd51c Mon Sep 17 00:00:00 2001 From: HarrisL2 Date: Sun, 1 Oct 2023 16:51:27 +0800 Subject: [PATCH 08/13] remove unused file --- compiler/shared/main/scala/mlscript/compiler/mono/utils.scala | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 compiler/shared/main/scala/mlscript/compiler/mono/utils.scala diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/utils.scala b/compiler/shared/main/scala/mlscript/compiler/mono/utils.scala deleted file mode 100644 index ff3090ff2..000000000 --- a/compiler/shared/main/scala/mlscript/compiler/mono/utils.scala +++ /dev/null @@ -1,3 +0,0 @@ -package mlscript.compiler.mono - - From 1e5cb880ebe3bf61e32c1e8e75e58d96b225dc3c Mon Sep 17 00:00:00 2001 From: HarrisL2 Date: Wed, 4 Oct 2023 19:04:00 +0800 Subject: [PATCH 09/13] Fixed mono tests --- .../scala/mlscript/compiler/Helpers.scala | 3 +- .../mlscript/compiler/mono/Monomorph.scala | 4 +- .../mono/specializer/Specializer.scala | 7 +- compiler/shared/test/diff/LambLift.mls | 75 +- compiler/shared/test/diff/LifterBlks.mls | 12 +- compiler/shared/test/diff/mono.mls | 759 +++++++++++------- 6 files changed, 517 insertions(+), 343 deletions(-) diff --git a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala index b9ed1db8d..fe465d44b 100644 --- a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala +++ b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala @@ -28,7 +28,8 @@ object Helpers: case Tup(fields) => fields.iterator.flatMap { // The new parser emits `Tup(_: UnitLit(true))` from `fun f() = x`. case (_, Fld(FldFlags(_, _, _), UnitLit(true))) => None - case (_, Fld(FldFlags(_, spec, _), Var(name))) => Some((spec, Expr.Ref(name))) + case (None, Fld(FldFlags(_, spec, _), Var(name))) => Some((spec, Expr.Ref(name))) + case (Some(Var(name)), Fld(FldFlags(_, spec, _), _)) => Some((spec, Expr.Ref(name))) case _ => throw new MonomorphError( s"only `Var` can be parameters but we meet ${showStructure(term)}" ) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala index 507bc0963..5a324836d 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala @@ -300,7 +300,9 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: } } else None - }).headOption.get//OrElse(BoundedExpr(UnknownValue())) + }).headOption.getOrElse( + throw MonomorphError("Field not Found in"+obj.toString()) + ) } } else { diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala index 57c225b2b..d64ad24d5 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala @@ -161,7 +161,10 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ retE } - case Expr.As(value, toType) => ??? + case Expr.As(value, toType) => + val retV = evaluate(value) + rawExpr.expValue = retV.expValue + rawExpr case Expr.Assign(assignee, value) => ??? case Expr.With(value, fields) => ??? case Expr.Subscript(receiver, index) => ??? @@ -216,7 +219,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ case other => other }) case Expr.Select(receiver, field) => Expr.Select(defunctionalize(receiver), field) - case _ => ??? + case Expr.As(value, toType) => Expr.As(defunctionalize(value), toType) } ret.expValue = rawExpr.expValue ret diff --git a/compiler/shared/test/diff/LambLift.mls b/compiler/shared/test/diff/LambLift.mls index 541d703c8..df3381f5d 100644 --- a/compiler/shared/test/diff/LambLift.mls +++ b/compiler/shared/test/diff/LambLift.mls @@ -1,74 +1,105 @@ -:NewParser -:ParseOnly +:NewDefs +:e // FIXME: Malformed Test? fun foo() = - fun local(x) = + let local(x) = class Foo { fun bar = x + foo(x) } - Foo().bar + (new Foo()).bar local(1) foo() -//│ |#fun| |foo|(||)| |#=|→|#fun| |local|(|x|)| |#=|→|#class| |Foo| |{|→|#fun| |bar| |#=| |x| |+| |foo|(|x|)|←|↵|}|↵|Foo|(||)|.bar|←|↵|local|(|1|)|←|↵|foo|(||)| -//│ Parsed: {fun foo = () => {fun local = (x,) => {class Foo {fun bar = +(x,)(foo(x,),)}; (Foo()).bar}; local(1,)}; foo()} //│ Parsed: //│ TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(), Blk(...))), App(Var(foo), Tup())) //│ Lifted: //│ TypingUnit { -//│ class Foo$1([x,]) {fun bar = () => +((this).x,)(foo$1((this).x,),)} -//│ fun local$2 = (x,) => {(Foo$1(x,)).bar} +//│ class Foo$1([x,]) {fun bar = () => +((this).x, foo$1((this).x,),)} +//│ let local$2 = (x,) => {('(' new Foo$1([x,]) {} ')').bar} //│ fun foo$1 = () => {local$2(1,)} //│ Code(List(foo$1())) //│ } +//│ ╔══[ERROR] Type mismatch in definition: +//│ ║ l.4: fun foo() = +//│ ║ ^^^^^^^ +//│ ║ l.5: let local(x) = +//│ ║ ^^^^^^^^^^^^^^^^ +//│ ║ l.6: class Foo { +//│ ║ ^^^^^^^^^^^^^^^ +//│ ║ l.7: fun bar = x + foo(x) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.8: } +//│ ║ ^^^^^ +//│ ║ l.9: (new Foo()).bar +//│ ║ ^^^^^^^^^^^^^^^^^^^ +//│ ║ l.10: local(1) +//│ ║ ^^^^^^^^^^ +//│ ╟── argument of type `[?a]` does not match type `[]` +//│ ║ l.7: fun bar = x + foo(x) +//│ ╙── ^^^ +//│ fun foo: () -> Int +//│ Int +//│ res +//│ Runtime error: +//│ RangeError: Maximum call stack size exceeded fun foo(f) = f(1) foo(x => x+1) -//│ |#fun| |foo|(|f|)| |#=| |→|f|(|1|)|←|↵|foo|(|x| |=>| |x|+|1|)| -//│ Parsed: {fun foo = (f,) => {f(1,)}; foo((x,) => +(x,)(1,),)} //│ Parsed: -//│ TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(_: Var(f)), Blk(...))), App(Var(foo), Tup(_: Lam(Tup(_: Var(x)), App(App(Var(+), Tup(_: Var(x))), Tup(_: IntLit(1))))))) +//│ TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(_: Var(f)), Blk(...))), App(Var(foo), Tup(_: Lam(Tup(_: Var(x)), App(Var(+), Tup(_: Var(x), _: IntLit(1))))))) //│ Lifted: //│ TypingUnit { -//│ class Lambda1$2$1([]) {fun apply = (x,) => +(x,)(1,)} +//│ class Lambda1$2$1([]) {fun apply = (x,) => +(x, 1,)} //│ fun foo$1 = (f,) => {f(1,)} //│ Code(List(foo$1({new Lambda1$2$1([]) {}},))) //│ } +//│ fun foo: forall 'a. (1 -> 'a) -> 'a +//│ Int +//│ res +//│ = 2 fun foo(x) = - fun bar(f) = + let bar(f) = f(x) bar(y => y+x) foo(1) -//│ |#fun| |foo|(|x|)| |#=| |→|#fun| |bar|(|f|)| |#=| |→|f|(|x|)|←|↵|bar|(|y| |=>| |y|+|x|)|←|↵|foo|(|1|)| -//│ Parsed: {fun foo = (x,) => {fun bar = (f,) => {f(x,)}; bar((y,) => +(y,)(x,),)}; foo(1,)} //│ Parsed: //│ TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: IntLit(1)))) //│ Lifted: //│ TypingUnit { -//│ class Lambda1$3$1([x,]) {fun apply = (y,) => +(y,)((this).x,)} -//│ fun bar$2 = (f, x,) => {f(x,)} +//│ class Lambda1$3$1([x,]) {fun apply = (y,) => +(y, (this).x,)} +//│ let bar$2 = (f, x,) => {f(x,)} //│ fun foo$1 = (x,) => {bar$2({new Lambda1$3$1([x,]) {}}, x,)} //│ Code(List(foo$1(1,))) //│ } +//│ fun foo: Int -> Int +//│ Int +//│ res +//│ = 2 fun foo(f) = f(1) -class A(y){ +class A(y: Int){ fun bar(z) = y+z } fun app(a) = foo(z => a.bar(z)) app(new A(1)) -//│ |#fun| |foo|(|f|)| |#=| |→|f|(|1|)|←|↵|#class| |A|(|y|)|{|→|#fun| |bar|(|z|)| |#=| |y|+|z|←|↵|}|↵|#fun| |app|(|a|)| |#=| |→|foo|(|z| |=>| |a|.bar|(|z|)|)|←|↵|app|(|#new| |A|(|1|)|)| -//│ Parsed: {fun foo = (f,) => {f(1,)}; class A(y,) {fun bar = (z,) => +(y,)(z,)}; fun app = (a,) => {foo((z,) => (a).bar(z,),)}; app(new A([1,]) {},)} //│ Parsed: -//│ TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(_: Var(f)), Blk(...))), NuTypeDef(class, A, (), Tup(_: Var(y)), (), None, None, TypingUnit(NuFunDef(None, bar, None, [], Lam(Tup(_: Var(z)), App(App(Var(+), Tup(_: Var(y))), Tup(_: Var(z))))))), NuFunDef(None, app, None, [], Lam(Tup(_: Var(a)), Blk(...))), App(Var(app), Tup(_: New(Some((TypeName(A),[1,])), TypingUnit())))) +//│ TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(_: Var(f)), Blk(...))), NuTypeDef(class, A, (), Tup(y: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, bar, None, [], Lam(Tup(_: Var(z)), App(Var(+), Tup(_: Var(y), _: Var(z))))))), NuFunDef(None, app, None, [], Lam(Tup(_: Var(a)), Blk(...))), App(Var(app), Tup(_: New(Some((TypeName(A),[1,])), TypingUnit())))) //│ Lifted: //│ TypingUnit { -//│ class A$1([y,]) {fun bar = (z,) => +((this).y,)(z,)} +//│ class A$1([y: Int,]) {fun bar = (z,) => +((this).y, z,)} //│ class Lambda1$3$2([a,]) {fun apply = (z,) => ((this).a).bar(z,)} //│ fun foo$2 = (f,) => {f(1,)} //│ fun app$1 = (a,) => {foo$2({new Lambda1$3$2([a,]) {}},)} //│ Code(List(app$1(new A$1([1,]) {},))) //│ } +//│ fun foo: forall 'a. (1 -> 'a) -> 'a +//│ class A(y: Int) { +//│ fun bar: Int -> Int +//│ } +//│ fun app: forall 'b. {bar: 1 -> 'b} -> 'b +//│ Int +//│ res +//│ = 2 diff --git a/compiler/shared/test/diff/LifterBlks.mls b/compiler/shared/test/diff/LifterBlks.mls index 773c0193c..67d569bd5 100644 --- a/compiler/shared/test/diff/LifterBlks.mls +++ b/compiler/shared/test/diff/LifterBlks.mls @@ -28,7 +28,7 @@ class A{ //│ fun foo = - fun local(x) = + let local(x) = class Foo { fun bar = x + 1 } @@ -38,14 +38,14 @@ fun foo = fun tmp = 1 print of local of 0 + local of 1 fun tmp = 2 -//│ |#fun| |foo| |#=|→|#fun| |local|(|x|)| |#=|→|#class| |Foo| |{|→|#fun| |bar| |#=| |x| |+| |1|←|↵|}|↵|Foo|(||)|.bar|←|↵|print| |#of| |local|(|0|)| |+| |local|(|1|)|↵|print| |#of| |(|local| |#of| |0|)| |+| |local| |#of| |1|↵|#fun| |tmp| |#=| |1|↵|print| |#of| |local| |#of| |0| |+| |local| |#of| |1|↵|#fun| |tmp| |#=| |2|←| -//│ Parsed: {fun foo = {fun local = (x,) => {class Foo {fun bar = +(x, 1,)}; (Foo()).bar}; print(+(local(0,), local(1,),),); print(+('(' local(0,) ')', local(1,),),); fun tmp = 1; print(local(+(0, local(1,),),),); fun tmp = 2}} +//│ |#fun| |foo| |#=|→|#let| |local|(|x|)| |#=|→|#class| |Foo| |{|→|#fun| |bar| |#=| |x| |+| |1|←|↵|}|↵|Foo|(||)|.bar|←|↵|print| |#of| |local|(|0|)| |+| |local|(|1|)|↵|print| |#of| |(|local| |#of| |0|)| |+| |local| |#of| |1|↵|#fun| |tmp| |#=| |1|↵|print| |#of| |local| |#of| |0| |+| |local| |#of| |1|↵|#fun| |tmp| |#=| |2|←| +//│ Parsed: {fun foo = {let local = (x,) => {class Foo {fun bar = +(x, 1,)}; (Foo()).bar}; print(+(local(0,), local(1,),),); print(+('(' local(0,) ')', local(1,),),); fun tmp = 1; print(local(+(0, local(1,),),),); fun tmp = 2}} //│ Parsed: //│ TypingUnit(NuFunDef(None, foo, None, [], Blk(...))) //│ Lifted: //│ TypingUnit { //│ class Foo$1([x,]) {fun bar = () => +((this).x, 1,)} -//│ fun local$3 = (x,) => {(Foo$1(x,)).bar} +//│ let local$3 = (x,) => {(Foo$1(x,)).bar} //│ fun tmp$2 = () => 1 //│ fun foo$1 = () => {print(+(local$3(0,), local$3(1,),),); print(+('(' local$3(0,) ')', local$3(1,),),); print(local$3(+(0, local$3(1,),),),)} //│ } @@ -247,8 +247,8 @@ class A{ fun g: T => B => T } } -//│ |#class| |A|‹|T|›|{|→|#class| |B|{|→|#fun| |f|#:| |T| |#=>| |B| |#=>| |T| |#=| |x| |#=>| |y| |#=>| |x|↵|#fun| |g|#:| |T| |#=>| |B| |#=>| |T|←|↵|}|←|↵|}| -//│ Parsed: {class A‹T› {class B {fun f = (x,) => (y,) => x : T -> B -> T; fun g: T -> B -> T}}} +//│ |#class| |A|‹|T|›|{|→|#class| |B|{|→|#fun| |f| |#=| |x| |#=>| |y| |#=>| |x|↵|#fun| |g|#:| |T| |#=>| |B| |#=>| |T|←|↵|}|←|↵|}| +//│ Parsed: {class A‹T› {class B {fun f = (x,) => (y,) => x; fun g: T -> B -> T}}} //│ Parsed: //│ TypingUnit(NuTypeDef(class, A, ((None,TypeName(T))), Tup(), (), None, None, TypingUnit(NuTypeDef(class, B, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), Lam(Tup(_: Var(y)), Var(x)))), NuFunDef(None, g, None, [], PolyType(List(),Function(Tuple(List((None,Field(None,TypeName(T))))),Function(Tuple(List((None,Field(None,TypeName(B))))),TypeName(T)))))))))) //│ Lifted: diff --git a/compiler/shared/test/diff/mono.mls b/compiler/shared/test/diff/mono.mls index 1b4517e24..57d6fd32e 100644 --- a/compiler/shared/test/diff/mono.mls +++ b/compiler/shared/test/diff/mono.mls @@ -1,26 +1,23 @@ :NewDefs -:ParseOnly :mono -fun f(x) = if x then 42 else 1337 -//│ |#fun| |f|(|x|)| |#=| |#if| |x| |#then| |42| |#else| |1337| -//│ Parsed: {fun f = (x,) => if (x) then 42 else 1337} +fun f(x: Int) = if x then 42 else 1337 //│ Parsed: -//│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), If(IfThen(Var(x), IntLit(42), Some(IntLit(1337)))))) +//│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(x: Var(Int)), If(IfThen(Var(x), IntLit(42), Some(IntLit(1337)))))) //│ Lifted: -//│ TypingUnit {fun f$1 = (x,) => if (x) then 42 else 1337} +//│ TypingUnit { +//│ fun f$1 = (x: Int,) => if (x) then 42 else 1337 +//│ } //│ Mono: //│ //│ Defunc result: //│ fun f$1(x) = //│ if x then #42 else #1337 -//│ +//│ fun f: (x: Int) -> (1337 | 42) :mono fun foo() = 42 -//│ |#fun| |foo|(||)| |#=| |42| -//│ Parsed: {fun foo = () => 42} //│ Parsed: //│ TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(), IntLit(42)))) //│ Lifted: @@ -30,14 +27,12 @@ fun foo() = 42 //│ Defunc result: //│ fun foo$1() = //│ #42 -//│ +//│ fun foo: () -> 42 :mono fun foo(x, #b) = if b then x else 1337 let a = foo(42, true) let b = foo(23, false) -//│ |#fun| |foo|(|x|,| |##|b|)| |#=| |#if| |b| |#then| |x| |#else| |1337|↵|#let| |a| |#=| |foo|(|42|,| |true|)|↵|#let| |b| |#=| |foo|(|23|,| |false|)| -//│ Parsed: {fun foo = (x, #b,) => if (b) then x else 1337; let a = foo(42, true,); let b = foo(23, false,)} //│ Parsed: //│ TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(_: Var(x), _: Var(b)), If(IfThen(Var(b), Var(x), Some(IntLit(1337))))), NuFunDef(Some(false), a, None, [], App(Var(foo), Tup(_: IntLit(42), _: Var(true)))), NuFunDef(Some(false), b, None, [], App(Var(foo), Tup(_: IntLit(23), _: Var(false))))) //│ Lifted: @@ -55,12 +50,16 @@ let b = foo(23, false) //│ if b then x else #1337 //│ fun a$1() = //│ foo$3(#42, true) -//│ +//│ fun foo: forall 'a. ('a, Object) -> (1337 | 'a) +//│ let a: 1337 | 42 +//│ let b: 1337 | 23 +//│ a +//│ = 42 +//│ b +//│ = 1337 :mono let x = 42 + 1337 -//│ |#let| |x| |#=| |42| |+| |1337| -//│ Parsed: {let x = +(42, 1337,)} //│ Parsed: //│ TypingUnit(NuFunDef(Some(false), x, None, [], App(Var(+), Tup(_: IntLit(42), _: IntLit(1337))))) //│ Lifted: @@ -70,97 +69,35 @@ let x = 42 + 1337 //│ Defunc result: //│ fun x$1() = //│ +(#42, #1337) -//│ +//│ let x: Int +//│ x +//│ = 1379 -:mono -class Bar(#x) -fun foo(#b) = b -let a = foo(new Bar(1)) -let b = foo(new Bar(2)) -//│ |#class| |Bar|(|##|x|)|↵|#fun| |foo|(|##|b|)| |#=| |b|↵|#let| |a| |#=| |foo|(|#new| |Bar|(|1|)|)|↵|#let| |b| |#=| |foo|(|#new| |Bar|(|2|)|)| -//│ Parsed: {class Bar(#x,) {}; fun foo = (#b,) => b; let a = foo(new Bar([1,]) {},); let b = foo(new Bar([2,]) {},)} -//│ Parsed: -//│ TypingUnit(NuTypeDef(class, Bar, (), Tup(_: Var(x)), (), None, None, TypingUnit()), NuFunDef(None, foo, None, [], Lam(Tup(_: Var(b)), Var(b))), NuFunDef(Some(false), a, None, [], App(Var(foo), Tup(_: New(Some((TypeName(Bar),[1,])), TypingUnit())))), NuFunDef(Some(false), b, None, [], App(Var(foo), Tup(_: New(Some((TypeName(Bar),[2,])), TypingUnit()))))) -//│ Lifted: -//│ TypingUnit { -//│ class Bar$1([#x,]) {} -//│ fun foo$3 = (#b,) => b -//│ let a$1 = () => foo$3(new Bar$1([1,]) {},) -//│ let b$2 = () => foo$3(new Bar$1([2,]) {},) -//│ } -//│ Mono: -//│ -//│ Defunc result: -//│ fun b$2() = -//│ foo$3(new Bar$1 (#2) ) -//│ fun foo$3(#b) = -//│ b -//│ fun a$1() = -//│ foo$3(new Bar$1 (#1) ) -//│ class Bar$1(#x) { -//│ } -//│ +//:mono +//:e // FIXME: Mutable Parameters +//class Bar(#x) +//fun foo(#b) = b +//let a = foo(new Bar(1)) +//let b = foo(new Bar(2)) -:mono -class OneInt(#a){ - fun inc() = a+1 -} -(new OneInt(1)).inc() -//│ |#class| |OneInt|(|##|a|)|{|→|#fun| |inc|(||)| |#=| |a|+|1|←|↵|}|↵|(|#new| |OneInt|(|1|)|)|.inc|(||)| -//│ Parsed: {class OneInt(#a,) {fun inc = () => +(a, 1,)}; ('(' new OneInt([1,]) {} ')').inc()} -//│ Parsed: -//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), None, None, TypingUnit(NuFunDef(None, inc, None, [], Lam(Tup(), App(Var(+), Tup(_: Var(a), _: IntLit(1))))))), App(Sel(Bra(rcd = false, New(Some((TypeName(OneInt),[1,])), TypingUnit())), inc), Tup())) -//│ Lifted: -//│ TypingUnit { -//│ class OneInt$1([#a,]) {fun inc = () => +((this).a, 1,)} -//│ Code(List(('(' new OneInt$1([1,]) {} ')').inc())) -//│ } -//│ Mono: -//│ -//│ Defunc result: -//│ main$$1() -//│ fun inc$OneInt$1(this) = -//│ +(this.a, #1) -//│ fun main$$1() = -//│ new OneInt$1 (#1) match {case obj: OneInt$1 => inc$OneInt$1(obj)} -//│ class OneInt$1(#a) { -//│ } -//│ +//:mono +//:w // FIXME: Mutable Parameters +//class OneInt(#a){ +// fun inc() = a+1 +//} +//(new OneInt(1)).inc() -:mono -class OneInt(#a){ - fun add(x) = - new OneInt(a+x.a) -} -(new OneInt(1)).add(new OneInt(2)) -//│ |#class| |OneInt|(|##|a|)|{|→|#fun| |add|(|x|)| |#=| |→|#new| |OneInt|(|a|+|x|.a|)|←|←|↵|}|↵|(|#new| |OneInt|(|1|)|)|.add|(|#new| |OneInt|(|2|)|)| -//│ Parsed: {class OneInt(#a,) {fun add = (x,) => {new OneInt([+(a, (x).a,),]) {}}}; ('(' new OneInt([1,]) {} ')').add(new OneInt([2,]) {},)} -//│ Parsed: -//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), None, None, TypingUnit(NuFunDef(None, add, None, [], Lam(Tup(_: Var(x)), Blk(...))))), App(Sel(Bra(rcd = false, New(Some((TypeName(OneInt),[1,])), TypingUnit())), add), Tup(_: New(Some((TypeName(OneInt),[2,])), TypingUnit())))) -//│ Lifted: -//│ TypingUnit { -//│ class OneInt$1([#a,]) { -//│ fun add = (x,) => {new OneInt$1([+((this).a, (x).a,),]) {}} -//│ } -//│ Code(List(('(' new OneInt$1([1,]) {} ')').add(new OneInt$1([2,]) {},))) -//│ } -//│ Mono: -//│ -//│ Defunc result: -//│ main$$1() -//│ fun add$OneInt$1(this, x) = -//│ new OneInt$1 (+(this.a, x.a)) -//│ fun main$$1() = -//│ new OneInt$1 (#1) match {case obj: OneInt$1 => add$OneInt$1(obj, new OneInt$1 (#2) )} -//│ class OneInt$1(#a) { -//│ } -//│ +//:mono +//:e // FIXME: Mutable Parameters +//class OneInt(#a){ +// fun add(x) = +// new OneInt(a+x.a) +//} +//(new OneInt(1)).add(new OneInt(2)) :mono if true then 1 else 0 if 1+1 > 1 then 1 - 1 else 1*1 -//│ |#if| |true| |#then| |1| |#else| |0|↵|#if| |1|+|1| |>| |1| |#then| |1| |-| |1| |#else| |1|*|1| -//│ Parsed: {if (true) then 1 else 0; if (>(+(1, 1,), 1,)) then -(1, 1,) else *(1, 1,)} //│ Parsed: //│ TypingUnit(If(IfThen(Var(true), IntLit(1), Some(IntLit(0))), If(IfThen(App(Var(>), Tup(_: App(Var(+), Tup(_: IntLit(1), _: IntLit(1))), _: IntLit(1))), App(Var(-), Tup(_: IntLit(1), _: IntLit(1))), Some(App(Var(*), Tup(_: IntLit(1), _: IntLit(1)))))) //│ Lifted: @@ -177,12 +114,14 @@ if 1+1 > 1 then 1 - 1 else 1*1 //│ if true then #1 else #0 //│ fun main$$1() = //│ if >(+(#1, #1), #1) then -(#1, #1) else *(#1, #1) -//│ +//│ Int +//│ res +//│ = 1 +//│ res +//│ = 0 :mono if(b) then 1 else 2 -//│ |#if|(|b|)| |#then| |1| |#else| |2| -//│ Parsed: {if ('(' b ')') then 1 else 2} //│ Parsed: //│ TypingUnit(If(IfThen(Bra(rcd = false, Var(b)), IntLit(1), Some(IntLit(2)))) //│ Lifted: @@ -193,12 +132,12 @@ if(b) then 1 else 2 //│ main$$0() //│ fun main$$0() = //│ if b then #1 else #2 -//│ +//│ 1 | 2 +//│ res +//│ = 2 :mono ((f, g) => f(g))(f => f, true) -//│ |(|(|f|,| |g|)| |=>| |f|(|g|)|)|(|f| |=>| |f|,| |true|)| -//│ Parsed: {'(' (f, g,) => f(g,) ')'((f,) => f, true,)} //│ Parsed: //│ TypingUnit(App(Bra(rcd = false, Lam(Tup(_: Var(f), _: Var(g)), App(Var(f), Tup(_: Var(g))))), Tup(_: Lam(Tup(_: Var(f)), Var(f)), _: Var(true)))) //│ Lifted: @@ -221,13 +160,13 @@ if(b) then 1 else 2 //│ } //│ class Lambda1$2$2() { //│ } -//│ +//│ true +//│ res +//│ = true :mono (b => if b then true else false) (true) -//│ |(|b| |=>| |#if| |b| |#then| |true| |#else| |false|)| |(|true|)| -//│ Parsed: {'(' (b,) => if (b) then true else false ')'(true,)} //│ Parsed: //│ TypingUnit(App(Bra(rcd = false, Lam(Tup(_: Var(b)), If(IfThen(Var(b), Var(true), Some(Var(false))))), Tup(_: Var(true)))) //│ Lifted: @@ -245,14 +184,14 @@ if(b) then 1 else 2 //│ new Lambda1$1$1 () match {case obj: Lambda1$1$1 => apply$Lambda1$1$1(obj, true)} //│ class Lambda1$1$1() { //│ } -//│ +//│ Bool +//│ res +//│ = true :mono fun f(x) = if(x > 0) then x+1 else x - 1 f(2)+3 -//│ |#fun| |f|(|x|)| |#=|→|#if|(|x| |>| |0|)| |#then| |x|+|1| |#else| |x| |-| |1|←|↵|f|(|2|)|+|3| -//│ Parsed: {fun f = (x,) => {if ('(' >(x, 0,) ')') then +(x, 1,) else -(x, 1,)}; +(f(2,), 3,)} //│ Parsed: //│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(+), Tup(_: App(Var(f), Tup(_: IntLit(2))), _: IntLit(3)))) //│ Lifted: @@ -268,14 +207,15 @@ f(2)+3 //│ if >(x, #0) then +(x, #1) else -(x, #1) //│ fun main$$1() = //│ +(f$1(#2), #3) -//│ +//│ fun f: Int -> Int +//│ Int +//│ res +//│ = 6 :mono fun fac(n) = if (n > 1) then fac(n - 1) * n else 1 fac(2) -//│ |#fun| |fac|(|n|)| |#=| |→|#if| |(|n| |>| |1|)| |#then| |fac|(|n| |-| |1|)| |*| |n| |#else| |1|←|↵|fac|(|2|)| -//│ Parsed: {fun fac = (n,) => {if ('(' >(n, 1,) ')') then *(fac(-(n, 1,),), n,) else 1}; fac(2,)} //│ Parsed: //│ TypingUnit(NuFunDef(None, fac, None, [], Lam(Tup(_: Var(n)), Blk(...))), App(Var(fac), Tup(_: IntLit(2)))) //│ Lifted: @@ -291,16 +231,18 @@ fac(2) //│ if >(n, #1) then *(fac$1(-(n, #1)), n) else #1 //│ fun main$$1() = //│ fac$1(#2) -//│ +//│ fun fac: Int -> Int +//│ Int +//│ res +//│ = 2 :mono +:e // FIXME: Malformed Test? class List(l, hasTail) {} class Nil(l, hasTail) {} fun count(lst) = if lst.hasTail then count(lst.l)+1 else 1 count(new List(new List(new Nil(0, false), true), true)) -//│ |#class| |List|(|l|,| |hasTail|)| |{||}|↵|#class| |Nil|(|l|,| |hasTail|)| |{||}|↵|#fun| |count|(|lst|)| |#=|→|#if| |lst|.hasTail| |#then| |count|(|lst|.l|)|+|1| |#else| |1|←|↵|count|(|#new| |List|(|#new| |List|(|#new| |Nil|(|0|,| |false|)|,| |true|)|,| |true|)|)| -//│ Parsed: {class List(l, hasTail,) {}; class Nil(l, hasTail,) {}; fun count = (lst,) => {if ((lst).hasTail) then +(count((lst).l,), 1,) else 1}; count(new List([new List([new Nil([0, false,]) {}, true,]) {}, true,]) {},)} //│ Parsed: //│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(l), _: Var(hasTail)), (), None, None, TypingUnit()), NuTypeDef(class, Nil, (), Tup(_: Var(l), _: Var(hasTail)), (), None, None, TypingUnit()), NuFunDef(None, count, None, [], Lam(Tup(_: Var(lst)), Blk(...))), App(Var(count), Tup(_: New(Some((TypeName(List),[new List([new Nil([0, false,]) {}, true,]) {}, true,])), TypingUnit())))) //│ Lifted: @@ -322,52 +264,49 @@ count(new List(new List(new Nil(0, false), true), true)) //│ } //│ class List$1(l, hasTail) { //│ } -//│ +//│ ╔══[ERROR] Class parameters currently need type annotations +//│ ║ l.241: class List(l, hasTail) {} +//│ ╙── ^ +//│ ╔══[ERROR] Class parameters currently need type annotations +//│ ║ l.241: class List(l, hasTail) {} +//│ ╙── ^^^^^^^ +//│ ╔══[ERROR] Class parameters currently need type annotations +//│ ║ l.242: class Nil(l, hasTail) {} +//│ ╙── ^ +//│ ╔══[ERROR] Class parameters currently need type annotations +//│ ║ l.242: class Nil(l, hasTail) {} +//│ ╙── ^^^^^^^ +//│ ╔══[ERROR] Parameter 'l' cannot tbe accessed as a field +//│ ║ l.244: if lst.hasTail then count(lst.l)+1 else 1 +//│ ║ ^^ +//│ ╟── Either make the parameter a `val` or access it through destructuring +//│ ║ l.241: class List(l, hasTail) {} +//│ ╙── ^ +//│ class List(l: error, hasTail: error) +//│ class Nil(l: error, hasTail: error) +//│ fun count: forall 'a. 'a -> Int +//│ Int | error +//│ where +//│ 'a <: {hasTail: Object, l: 'a} +//│ res +//│ = 1 -:mono -class Cons(e, tail){ - fun gen() = new Cons(e, tail.gen()) -} -class Nil(){ - fun gen() = new Cons(0, this) -} -fun generate(x) = - if x > 0 then new Cons(x, generate(x+1)) else new Nil() -generate(10).gen() -//│ |#class| |Cons|(|e|,| |tail|)|{|→|#fun| |gen|(||)| |#=| |#new| |Cons|(|e|,| |tail|.gen|(||)|)|←|↵|}|↵|#class| |Nil|(||)|{|→|#fun| |gen|(||)| |#=| |#new| |Cons|(|0|,| |this|)|←|↵|}|↵|#fun| |generate|(|x|)| |#=| |→|#if| |x| |>| |0| |#then| |#new| |Cons|(|x|,| |generate|(|x|+|1|)|)| |#else| |#new| |Nil|(||)|←|↵|generate|(|10|)|.gen|(||)| -//│ Parsed: {class Cons(e, tail,) {fun gen = () => new Cons([e, (tail).gen(),]) {}}; class Nil() {fun gen = () => new Cons([0, this,]) {}}; fun generate = (x,) => {if (>(x, 0,)) then new Cons([x, generate(+(x, 1,),),]) {} else new Nil([]) {}}; (generate(10,)).gen()} -//│ Parsed: -//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), None, None, TypingUnit(NuFunDef(None, gen, None, [], Lam(Tup(), New(Some((TypeName(Cons),[e, (tail).gen(),])), TypingUnit()))))), NuTypeDef(class, Nil, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, gen, None, [], Lam(Tup(), New(Some((TypeName(Cons),[0, this,])), TypingUnit()))))), NuFunDef(None, generate, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Sel(App(Var(generate), Tup(_: IntLit(10))), gen), Tup())) -//│ Lifted: -//│ TypingUnit { -//│ class Cons$1([e, tail,]) { -//│ fun gen = () => new Cons$1([(this).e, ((this).tail).gen(),]) {} -//│ } -//│ class Nil$2([]) {fun gen = () => new Cons$1([0, this,]) {}} -//│ fun generate$1 = (x,) => {if (>(x, 0,)) then new Cons$1([x, generate$1(+(x, 1,),),]) {} else new Nil$2([]) {}} -//│ Code(List((generate$1(10,)).gen())) -//│ } -//│ Mono: -//│ -//│ Defunc result: -//│ main$$3() -//│ fun gen$Cons$1(this) = -//│ new Cons$1 (this.e, this.tail match {case obj: Cons$1 => gen$Cons$1(obj); case obj: Nil$2 => gen$Nil$2(obj)}) -//│ fun generate$1(x) = -//│ if >(x, #0) then new Cons$1 (x, generate$1(+(x, #1))) else new Nil$2 () -//│ fun gen$Nil$2(this) = -//│ new Cons$1 (#0, this) -//│ fun main$$3() = -//│ generate$1(#10) match {case obj: Cons$1 => gen$Cons$1(obj); case obj: Nil$2 => gen$Nil$2(obj)} -//│ class Nil$2() { -//│ } -//│ class Cons$1(e, tail) { -//│ } -//│ +//:mono +//class Cons(e, tail){ +// fun gen() = new Cons(e, tail.gen()) +//} +//class Nil(){ +// fun gen() = new Cons(0, this) +//} +//fun generate(x) = +// if x > 0 then new Cons(x, generate(x+1)) else new Nil() +//generate(10).gen() :mono -class List(e, tail) { - fun map(f) = new List(f(e), tail.map(f)) +class List(e: Int, tail: List | Nil) { + fun map: (Int -> Int) -> List + fun map(f)= new List(f(e), tail.map(f)) + fun count(): Int fun count() = 1 + tail.count() } class Nil() { @@ -376,14 +315,14 @@ class Nil() { } fun add2(x) = x+2 (new List(1, new List(2, new Nil()))).map(x => x+1).map(x => add2(x)) -//│ |#class| |List|(|e|,| |tail|)| |{|→|#fun| |map|(|f|)| |#=| |#new| |List|(|f|(|e|)|,| |tail|.map|(|f|)|)|↵|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |map|(|f|)| |#=| |this|↵|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#fun| |add2|(|x|)| |#=| |x|+|2|↵|(|#new| |List|(|1|,| |#new| |List|(|2|,| |#new| |Nil|(||)|)|)|)|.map|(|x| |=>| |x|+|1|)|.map|(|x| |=>| |add2|(|x|)|)| -//│ Parsed: {class List(e, tail,) {fun map = (f,) => new List([f(e,), (tail).map(f,),]) {}; fun count = () => +(1, (tail).count(),)}; class Nil() {fun map = (f,) => this; fun count = () => 0}; fun add2 = (x,) => +(x, 2,); (('(' new List([1, new List([2, new Nil([]) {},]) {},]) {} ')').map((x,) => +(x, 1,),)).map((x,) => add2(x,),)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(e), _: Var(tail)), (), None, None, TypingUnit(NuFunDef(None, map, None, [], Lam(Tup(_: Var(f)), New(Some((TypeName(List),[f(e,), (tail).map(f,),])), TypingUnit()))), NuFunDef(None, count, None, [], Lam(Tup(), App(Var(+), Tup(_: IntLit(1), _: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, map, None, [], Lam(Tup(_: Var(f)), Var(this))), NuFunDef(None, count, None, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, add2, None, [], Lam(Tup(_: Var(x)), App(Var(+), Tup(_: Var(x), _: IntLit(2))))), App(Sel(App(Sel(Bra(rcd = false, New(Some((TypeName(List),[1, new List([2, new Nil([]) {},]) {},])), TypingUnit())), map), Tup(_: Lam(Tup(_: Var(x)), App(Var(+), Tup(_: Var(x), _: IntLit(1)))))), map), Tup(_: Lam(Tup(_: Var(x)), App(Var(add2), Tup(_: Var(x))))))) +//│ TypingUnit(NuTypeDef(class, List, (), Tup(e: Var(Int), tail: App(Var(|), Tup(_: Var(List), _: Var(Nil)))), (), None, None, TypingUnit(NuFunDef(None, map, None, [], PolyType(List(),Function(Tuple(List((None,Field(None,Function(Tuple(List((None,Field(None,TypeName(Int))))),TypeName(Int)))))),TypeName(List)))), NuFunDef(None, map, None, [], Lam(Tup(_: Var(f)), New(Some((TypeName(List),[f(e,), (tail).map(f,),])), TypingUnit()))), NuFunDef(None, count, None, [], PolyType(List(),Function(Tuple(List()),TypeName(Int)))), NuFunDef(None, count, None, [], Lam(Tup(), App(Var(+), Tup(_: IntLit(1), _: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, map, None, [], Lam(Tup(_: Var(f)), Var(this))), NuFunDef(None, count, None, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, add2, None, [], Lam(Tup(_: Var(x)), App(Var(+), Tup(_: Var(x), _: IntLit(2))))), App(Sel(App(Sel(Bra(rcd = false, New(Some((TypeName(List),[1, new List([2, new Nil([]) {},]) {},])), TypingUnit())), map), Tup(_: Lam(Tup(_: Var(x)), App(Var(+), Tup(_: Var(x), _: IntLit(1)))))), map), Tup(_: Lam(Tup(_: Var(x)), App(Var(add2), Tup(_: Var(x))))))) //│ Lifted: //│ TypingUnit { -//│ class List$1([e, tail,]) { +//│ class List$1([e: Int, tail: |(List, Nil,),]) { +//│ fun map = (Int -> Int) -> List$1 //│ fun map = (f,) => new List$1([f((this).e,), ((this).tail).map(f,),]) {} +//│ fun count = () -> Int //│ fun count = () => +(1, ((this).tail).count(),) //│ } //│ class Nil$2([]) {fun map = (f,) => this; fun count = () => 0} @@ -416,10 +355,23 @@ fun add2(x) = x+2 //│ } //│ class Lambda1$2$3() { //│ } -//│ +//│ class List(e: Int, tail: List | Nil) { +//│ fun count: () -> Int +//│ fun map: (Int -> Int) -> List +//│ } +//│ class Nil() { +//│ fun count: () -> 0 +//│ fun map: anything -> Nil +//│ } +//│ fun add2: Int -> Int +//│ List +//│ res +//│ = List {} :mono -class List(e, tail) { +:AllowRuntimeErrors +class List(e: Int, tail: List | Nil) { + fun count(): Int fun count() = 1 + tail.count() } class Nil() { @@ -430,13 +382,14 @@ fun generate(x) = if x > 0 then new List(x, generate(x+1)) else new Nil() foo(new List(1, new List(2, new Nil()))) foo(generate(1)) -//│ |#class| |List|(|e|,| |tail|)| |{|→|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#fun| |foo|(|x|)| |#=| |x|.count|(||)|↵|#fun| |generate|(|x|)| |#=| |→|#if| |x| |>| |0| |#then| |#new| |List|(|x|,| |generate|(|x|+|1|)|)| |#else| |#new| |Nil|(||)|←|↵|foo|(|#new| |List|(|1|,| |#new| |List|(|2|,| |#new| |Nil|(||)|)|)|)|↵|foo|(|generate|(|1|)|)| -//│ Parsed: {class List(e, tail,) {fun count = () => +(1, (tail).count(),)}; class Nil() {fun count = () => 0}; fun foo = (x,) => (x).count(); fun generate = (x,) => {if (>(x, 0,)) then new List([x, generate(+(x, 1,),),]) {} else new Nil([]) {}}; foo(new List([1, new List([2, new Nil([]) {},]) {},]) {},); foo(generate(1,),)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(e), _: Var(tail)), (), None, None, TypingUnit(NuFunDef(None, count, None, [], Lam(Tup(), App(Var(+), Tup(_: IntLit(1), _: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, count, None, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, foo, None, [], Lam(Tup(_: Var(x)), App(Sel(Var(x), count), Tup()))), NuFunDef(None, generate, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: New(Some((TypeName(List),[1, new List([2, new Nil([]) {},]) {},])), TypingUnit()))), App(Var(foo), Tup(_: App(Var(generate), Tup(_: IntLit(1)))))) +//│ TypingUnit(NuTypeDef(class, List, (), Tup(e: Var(Int), tail: App(Var(|), Tup(_: Var(List), _: Var(Nil)))), (), None, None, TypingUnit(NuFunDef(None, count, None, [], PolyType(List(),Function(Tuple(List()),TypeName(Int)))), NuFunDef(None, count, None, [], Lam(Tup(), App(Var(+), Tup(_: IntLit(1), _: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, count, None, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, foo, None, [], Lam(Tup(_: Var(x)), App(Sel(Var(x), count), Tup()))), NuFunDef(None, generate, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: New(Some((TypeName(List),[1, new List([2, new Nil([]) {},]) {},])), TypingUnit()))), App(Var(foo), Tup(_: App(Var(generate), Tup(_: IntLit(1)))))) //│ Lifted: //│ TypingUnit { -//│ class List$1([e, tail,]) {fun count = () => +(1, ((this).tail).count(),)} +//│ class List$1([e: Int, tail: |(List, Nil,),]) { +//│ fun count = () -> Int +//│ fun count = () => +(1, ((this).tail).count(),) +//│ } //│ class Nil$2([]) {fun count = () => 0} //│ fun foo$1 = (x,) => (x).count() //│ fun generate$2 = (x,) => {if (>(x, 0,)) then new List$1([x, generate$2(+(x, 1,),),]) {} else new Nil$2([]) {}} @@ -464,14 +417,25 @@ foo(generate(1)) //│ } //│ class List$1(e, tail) { //│ } -//│ +//│ class List(e: Int, tail: List | Nil) { +//│ fun count: () -> Int +//│ } +//│ class Nil() { +//│ fun count: () -> 0 +//│ } +//│ fun foo: forall 'a. {count: () -> 'a} -> 'a +//│ fun generate: Int -> (List | Nil) +//│ Int +//│ res +//│ = 2 +//│ res +//│ Runtime error: +//│ RangeError: Maximum call stack size exceeded :mono fun foo(x) = (f => f(x))(z => z+1) foo(2) -//│ |#fun| |foo|(|x|)| |#=| |→|(|f| |=>| |f|(|x|)|)|(|z| |=>| |z|+|1|)|←|↵|foo|(|2|)| -//│ Parsed: {fun foo = (x,) => {'(' (f,) => f(x,) ')'((z,) => +(z, 1,),)}; foo(2,)} //│ Parsed: //│ TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: IntLit(2)))) //│ Lifted: @@ -497,20 +461,21 @@ foo(2) //│ } //│ class Lambda1$3$2() { //│ } -//│ +//│ fun foo: Int -> Int +//│ Int +//│ res +//│ = 3 :mono fun f(x) = - (y => f(x+y)).apply(x+1) + (y => f(x+y))(x+1) f(1) -//│ |#fun| |f|(|x|)| |#=|→|(|y| |=>| |f|(|x|+|y|)|)|.apply|(|x|+|1|)|←|↵|f|(|1|)| -//│ Parsed: {fun f = (x,) => {('(' (y,) => f(+(x, y,),) ')').apply(+(x, 1,),)}; f(1,)} //│ Parsed: //│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(f), Tup(_: IntLit(1)))) //│ Lifted: //│ TypingUnit { //│ class Lambda1$2$1([x,]) {fun apply = (y,) => f$1(+((this).x, y,),)} -//│ fun f$1 = (x,) => {('(' {new Lambda1$2$1([x,]) {}} ')').apply(+(x, 1,),)} +//│ fun f$1 = (x,) => {'(' {new Lambda1$2$1([x,]) {}} ')'(+(x, 1,),)} //│ Code(List(f$1(1,))) //│ } //│ Mono: @@ -525,15 +490,17 @@ f(1) //│ f$1(#1) //│ class Lambda1$2$1(x) { //│ } -//│ +//│ fun f: Int -> nothing +//│ nothing +//│ res +//│ Runtime error: +//│ RangeError: Maximum call stack size exceeded :mono fun f(x) = f(x) f(0) f(1) -//│ |#fun| |f|(|x|)| |#=| |f|(|x|)|↵|f|(|0|)|↵|f|(|1|)| -//│ Parsed: {fun f = (x,) => f(x,); f(0,); f(1,)} //│ Parsed: //│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), App(Var(f), Tup(_: Var(x))))), App(Var(f), Tup(_: IntLit(0))), App(Var(f), Tup(_: IntLit(1)))) //│ Lifted: @@ -553,10 +520,18 @@ f(1) //│ f$1(#1) //│ fun main$$1() = //│ f$1(#0) -//│ +//│ fun f: anything -> nothing +//│ nothing +//│ res +//│ Runtime error: +//│ RangeError: Maximum call stack size exceeded +//│ res +//│ Runtime error: +//│ RangeError: Maximum call stack size exceeded :mono -class Cons(e, tail) { +class Cons(e: 'A, tail: Cons | Nil) { + fun count(): Int fun count() = 1 + tail.count() } class Nil() { @@ -566,7 +541,7 @@ class Lambda(){ fun apply(l) = l.count() } -class Lambda2(a){ +class Lambda2(a: Int){ fun apply(l) = (new Cons(a, l)).count() } @@ -574,16 +549,17 @@ fun foo(x) = x.apply(new Cons(1, new Nil())) + x.apply(new Nil()) foo(new Lambda()) foo(new Lambda2(2)) -//│ |#class| |Cons|(|e|,| |tail|)| |{|→|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#class| |Lambda|(||)|{|→|#fun| |apply|(|l|)| |#=| |→|l|.count|(||)|←|←|↵|}|↵|#class| |Lambda2|(|a|)|{|→|#fun| |apply|(|l|)| |#=| |→|(|#new| |Cons|(|a|,| |l|)|)|.count|(||)|←|←|↵|}|↵|#fun| |foo|(|x|)| |#=| |→|x|.apply|(|#new| |Cons|(|1|,| |#new| |Nil|(||)|)|)| |+| |x|.apply|(|#new| |Nil|(||)|)|←|↵|foo|(|#new| |Lambda|(||)|)|↵|foo|(|#new| |Lambda2|(|2|)|)| -//│ Parsed: {class Cons(e, tail,) {fun count = () => +(1, (tail).count(),)}; class Nil() {fun count = () => 0}; class Lambda() {fun apply = (l,) => {(l).count()}}; class Lambda2(a,) {fun apply = (l,) => {('(' new Cons([a, l,]) {} ')').count()}}; fun foo = (x,) => {+((x).apply(new Cons([1, new Nil([]) {},]) {},), (x).apply(new Nil([]) {},),)}; foo(new Lambda([]) {},); foo(new Lambda2([2,]) {},)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), None, None, TypingUnit(NuFunDef(None, count, None, [], Lam(Tup(), App(Var(+), Tup(_: IntLit(1), _: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, count, None, [], Lam(Tup(), IntLit(0))))), NuTypeDef(class, Lambda, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, apply, None, [], Lam(Tup(_: Var(l)), Blk(...))))), NuTypeDef(class, Lambda2, (), Tup(_: Var(a)), (), None, None, TypingUnit(NuFunDef(None, apply, None, [], Lam(Tup(_: Var(l)), Blk(...))))), NuFunDef(None, foo, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: New(Some((TypeName(Lambda),[])), TypingUnit()))), App(Var(foo), Tup(_: New(Some((TypeName(Lambda2),[2,])), TypingUnit())))) +//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(e: Var('A), tail: App(Var(|), Tup(_: Var(Cons), _: Var(Nil)))), (), None, None, TypingUnit(NuFunDef(None, count, None, [], PolyType(List(),Function(Tuple(List()),TypeName(Int)))), NuFunDef(None, count, None, [], Lam(Tup(), App(Var(+), Tup(_: IntLit(1), _: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, count, None, [], Lam(Tup(), IntLit(0))))), NuTypeDef(class, Lambda, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, apply, None, [], Lam(Tup(_: Var(l)), Blk(...))))), NuTypeDef(class, Lambda2, (), Tup(a: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, apply, None, [], Lam(Tup(_: Var(l)), Blk(...))))), NuFunDef(None, foo, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: New(Some((TypeName(Lambda),[])), TypingUnit()))), App(Var(foo), Tup(_: New(Some((TypeName(Lambda2),[2,])), TypingUnit())))) //│ Lifted: //│ TypingUnit { -//│ class Cons$1([e, tail,]) {fun count = () => +(1, ((this).tail).count(),)} +//│ class Cons$1([e: 'A, tail: |(Cons, Nil,),]) { +//│ fun count = () -> Int +//│ fun count = () => +(1, ((this).tail).count(),) +//│ } //│ class Nil$2([]) {fun count = () => 0} //│ class Lambda$3([]) {fun apply = (l,) => {(l).count()}} -//│ class Lambda2$4([a,]) { +//│ class Lambda2$4([a: Int,]) { //│ fun apply = (l,) => {('(' new Cons$1([(this).a, l,]) {} ')').count()} //│ } //│ fun foo$1 = (x,) => {+((x).apply(new Cons$1([1, new Nil$2([]) {},]) {},), (x).apply(new Nil$2([]) {},),)} @@ -617,10 +593,28 @@ foo(new Lambda2(2)) //│ } //│ class Lambda$3() { //│ } -//│ +//│ class Cons(e: nothing, tail: Cons | Nil) { +//│ fun count: () -> Int +//│ } +//│ class Nil() { +//│ fun count: () -> 0 +//│ } +//│ class Lambda() { +//│ fun apply: forall 'a. {count: () -> 'a} -> 'a +//│ } +//│ class Lambda2(a: Int) { +//│ fun apply: (Cons | Nil) -> Int +//│ } +//│ fun foo: {apply: (Cons | Nil) -> Int} -> Int +//│ Int +//│ res +//│ = 1 +//│ res +//│ = 3 :mono -class Cons(e, tail) { +class Cons(e: Int, tail: Cons | Nil) { + fun count(): Int fun count() = 1 + tail.count() } class Nil() { @@ -630,13 +624,14 @@ fun foo(x) = x(new Cons(1, new Nil())) + x(new Nil()) foo(l => l.count()) foo(l => (new Cons(2, l)).count()) -//│ |#class| |Cons|(|e|,| |tail|)| |{|→|#fun| |count|(||)| |#=| |1| |+| |tail|.count|(||)|←|↵|}|↵|#class| |Nil|(||)| |{|→|#fun| |count|(||)| |#=| |0|←|↵|}|↵|#fun| |foo|(|x|)| |#=| |→|x|(|#new| |Cons|(|1|,| |#new| |Nil|(||)|)|)| |+| |x|(|#new| |Nil|(||)|)|←|↵|foo|(|l| |=>| |l|.count|(||)|)|↵|foo|(|l| |=>| |(|#new| |Cons|(|2|,| |l|)|)|.count|(||)|)| -//│ Parsed: {class Cons(e, tail,) {fun count = () => +(1, (tail).count(),)}; class Nil() {fun count = () => 0}; fun foo = (x,) => {+(x(new Cons([1, new Nil([]) {},]) {},), x(new Nil([]) {},),)}; foo((l,) => (l).count(),); foo((l,) => ('(' new Cons([2, l,]) {} ')').count(),)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(_: Var(e), _: Var(tail)), (), None, None, TypingUnit(NuFunDef(None, count, None, [], Lam(Tup(), App(Var(+), Tup(_: IntLit(1), _: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, count, None, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, foo, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: Lam(Tup(_: Var(l)), App(Sel(Var(l), count), Tup())))), App(Var(foo), Tup(_: Lam(Tup(_: Var(l)), App(Sel(Bra(rcd = false, New(Some((TypeName(Cons),[2, l,])), TypingUnit())), count), Tup()))))) +//│ TypingUnit(NuTypeDef(class, Cons, (), Tup(e: Var(Int), tail: App(Var(|), Tup(_: Var(Cons), _: Var(Nil)))), (), None, None, TypingUnit(NuFunDef(None, count, None, [], PolyType(List(),Function(Tuple(List()),TypeName(Int)))), NuFunDef(None, count, None, [], Lam(Tup(), App(Var(+), Tup(_: IntLit(1), _: App(Sel(Var(tail), count), Tup()))))))), NuTypeDef(class, Nil, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, count, None, [], Lam(Tup(), IntLit(0))))), NuFunDef(None, foo, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(foo), Tup(_: Lam(Tup(_: Var(l)), App(Sel(Var(l), count), Tup())))), App(Var(foo), Tup(_: Lam(Tup(_: Var(l)), App(Sel(Bra(rcd = false, New(Some((TypeName(Cons),[2, l,])), TypingUnit())), count), Tup()))))) //│ Lifted: //│ TypingUnit { -//│ class Cons$1([e, tail,]) {fun count = () => +(1, ((this).tail).count(),)} +//│ class Cons$1([e: Int, tail: |(Cons, Nil,),]) { +//│ fun count = () -> Int +//│ fun count = () => +(1, ((this).tail).count(),) +//│ } //│ class Nil$2([]) {fun count = () => 0} //│ class Lambda1$2$3([]) {fun apply = (l,) => (l).count()} //│ class Lambda1$3$4([]) { @@ -673,9 +668,21 @@ foo(l => (new Cons(2, l)).count()) //│ } //│ class Lambda1$2$3() { //│ } -//│ +//│ class Cons(e: Int, tail: Cons | Nil) { +//│ fun count: () -> Int +//│ } +//│ class Nil() { +//│ fun count: () -> 0 +//│ } +//│ fun foo: ((Cons | Nil) -> Int) -> Int +//│ Int +//│ res +//│ = 1 +//│ res +//│ = 3 :mono +:e // FIXME: Malformed Test? class E() { fun derive(x) = new E @@ -707,8 +714,6 @@ class C(e1, e2){ e1.isEmpty() && e2.isEmpty() } (new C(new Ch(1), new A(new Ch(2), new Ch(3)))).derive(0).isEmpty() -//│ |#class| |E|(||)| |{|→|#fun| |derive|(|x|)| |#=| |→|#new| |E|←|↵|#fun| |isEmpty|(||)| |#=| |→|false|←|←|↵|}|↵|#class| |Ep|(||)|{|→|#fun| |derive|(|x|)| |#=| |→|#new| |E|←|↵|#fun| |isEmpty|(||)| |#=| |→|true|←|←|↵|}|↵|#class| |Ch|(|i|)|{|→|#fun| |derive|(|x|)| |#=| |→|#if| |x| |==| |i| |#then| |#new| |Ep| |#else| |#new| |E|←|↵|#fun| |isEmpty|(||)| |#=| |→|false|←|←|↵|}|↵|#class| |A|(|e1|,| |e2|)|{|→|#fun| |derive|(|x|)| |#=| |→|#new| |A|(|e1|.derive|(|x|)|,| |e2|.derive|(|x|)|)|←|↵|#fun| |isEmpty|(||)| |#=| |→|e1|.isEmpty|(||)| |||| |e2|.isEmpty|(||)|←|←|↵|}|↵|#class| |C|(|e1|,| |e2|)|{|→|#fun| |derive|(|x|)| |#=| |→|#if| |e1|.isEmpty|(||)| |#then| |#new| |A|(|#new| |C|(|e1|.derive|(|x|)|,| |e2|)|,| |e2|.derive|(|x|)|)| |#else| |#new| |C|(|e1|.derive|(|x|)|,| |e2|)|←|↵|#fun| |isEmpty|(||)| |#=| |→|e1|.isEmpty|(||)| |&&| |e2|.isEmpty|(||)|←|←|↵|}|↵|(|#new| |C|(|#new| |Ch|(|1|)|,| |#new| |A|(|#new| |Ch|(|2|)|,| |#new| |Ch|(|3|)|)|)|)|.derive|(|0|)|.isEmpty|(||)| -//│ Parsed: {class E() {fun derive = (x,) => {new E([]) {}}; fun isEmpty = () => {false}}; class Ep() {fun derive = (x,) => {new E([]) {}}; fun isEmpty = () => {true}}; class Ch(i,) {fun derive = (x,) => {if (==(x, i,)) then new Ep([]) {} else new E([]) {}}; fun isEmpty = () => {false}}; class A(e1, e2,) {fun derive = (x,) => {new A([(e1).derive(x,), (e2).derive(x,),]) {}}; fun isEmpty = () => {||((e1).isEmpty(), (e2).isEmpty(),)}}; class C(e1, e2,) {fun derive = (x,) => {if ((e1).isEmpty()) then new A([new C([(e1).derive(x,), e2,]) {}, (e2).derive(x,),]) {} else new C([(e1).derive(x,), e2,]) {}}; fun isEmpty = () => {&&((e1).isEmpty(), (e2).isEmpty(),)}}; (('(' new C([new Ch([1,]) {}, new A([new Ch([2,]) {}, new Ch([3,]) {},]) {},]) {} ')').derive(0,)).isEmpty()} //│ Parsed: //│ TypingUnit(NuTypeDef(class, E, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ep, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ch, (), Tup(_: Var(i)), (), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, A, (), Tup(_: Var(e1), _: Var(e2)), (), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, C, (), Tup(_: Var(e1), _: Var(e2)), (), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), App(Sel(App(Sel(Bra(rcd = false, New(Some((TypeName(C),[new Ch([1,]) {}, new A([new Ch([2,]) {}, new Ch([3,]) {},]) {},])), TypingUnit())), derive), Tup(_: IntLit(0))), isEmpty), Tup())) //│ Lifted: @@ -767,23 +772,59 @@ class C(e1, e2){ //│ } //│ class Ch$3(i) { //│ } -//│ +//│ ╔══[ERROR] Class parameters currently need type annotations +//│ ║ l.698: class Ch(i){ +//│ ╙── ^ +//│ ╔══[ERROR] Class parameters currently need type annotations +//│ ║ l.704: class A(e1, e2){ +//│ ╙── ^^ +//│ ╔══[ERROR] Class parameters currently need type annotations +//│ ║ l.704: class A(e1, e2){ +//│ ╙── ^^ +//│ ╔══[ERROR] Class parameters currently need type annotations +//│ ║ l.710: class C(e1, e2){ +//│ ╙── ^^ +//│ ╔══[ERROR] Class parameters currently need type annotations +//│ ║ l.710: class C(e1, e2){ +//│ ╙── ^^ +//│ class E() { +//│ fun derive: anything -> E +//│ fun isEmpty: () -> false +//│ } +//│ class Ep() { +//│ fun derive: anything -> E +//│ fun isEmpty: () -> true +//│ } +//│ class Ch(i: error) { +//│ fun derive: Num -> (E | Ep) +//│ fun isEmpty: () -> false +//│ } +//│ class A(e1: error, e2: error) { +//│ fun derive: anything -> A +//│ fun isEmpty: () -> Bool +//│ } +//│ class C(e1: error, e2: error) { +//│ fun derive: anything -> (A | C) +//│ fun isEmpty: () -> Bool +//│ } +//│ Bool +//│ res +//│ = false :mono -class List(l, hasTail) {} -class Nil(hasTail) {} +:e // FIXME: Malformed Test? +class List(l: List | Nil, hasTail: Bool) {} +class Nil(hasTail: Bool) {} fun gen() = if anyUnknown then new List(gen(), true) else new Nil(false) gen() -//│ |#class| |List|(|l|,| |hasTail|)| |{||}|↵|#class| |Nil|(|hasTail|)| |{||}|↵|#fun| |gen|(||)| |#=| |→|#if| |anyUnknown| |#then| |#new| |List|(|gen|(||)|,| |true|)| |#else| |#new| |Nil|(|false|)|←|↵|gen|(||)| -//│ Parsed: {class List(l, hasTail,) {}; class Nil(hasTail,) {}; fun gen = () => {if (anyUnknown) then new List([gen(), true,]) {} else new Nil([false,]) {}}; gen()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(l), _: Var(hasTail)), (), None, None, TypingUnit()), NuTypeDef(class, Nil, (), Tup(_: Var(hasTail)), (), None, None, TypingUnit()), NuFunDef(None, gen, None, [], Lam(Tup(), Blk(...))), App(Var(gen), Tup())) +//│ TypingUnit(NuTypeDef(class, List, (), Tup(l: App(Var(|), Tup(_: Var(List), _: Var(Nil))), hasTail: Var(Bool)), (), None, None, TypingUnit()), NuTypeDef(class, Nil, (), Tup(hasTail: Var(Bool)), (), None, None, TypingUnit()), NuFunDef(None, gen, None, [], Lam(Tup(), Blk(...))), App(Var(gen), Tup())) //│ Lifted: //│ TypingUnit { -//│ class List$1([l, hasTail,]) {} -//│ class Nil$2([hasTail,]) {} +//│ class List$1([l: |(List, Nil,), hasTail: Bool,]) {} +//│ class Nil$2([hasTail: Bool,]) {} //│ fun gen$1 = () => {if (anyUnknown) then new List$1([gen$1(), true,]) {} else new Nil$2([false,]) {}} //│ Code(List(gen$1())) //│ } @@ -799,23 +840,29 @@ gen() //│ } //│ class List$1(l, hasTail) { //│ } -//│ +//│ ╔══[ERROR] identifier not found: anyUnknown +//│ ║ l.820: if anyUnknown then new List(gen(), true) else new Nil(false) +//│ ╙── ^^^^^^^^^^ +//│ class List(l: List | Nil, hasTail: Bool) +//│ class Nil(hasTail: Bool) +//│ fun gen: () -> (List | Nil) +//│ List | Nil +//│ Code generation encountered an error: +//│ unresolved symbol anyUnknown :mono -class Foo(x){ +class Foo(x: Int){ fun bar(y) = x+y fun boo(z) = bar(z)+x } (new Foo(1)).boo(2) -//│ |#class| |Foo|(|x|)|{|→|#fun| |bar|(|y|)| |#=| |x|+|y|↵|#fun| |boo|(|z|)| |#=| |bar|(|z|)|+|x|←|↵|}|↵|(|#new| |Foo|(|1|)|)|.boo|(|2|)| -//│ Parsed: {class Foo(x,) {fun bar = (y,) => +(x, y,); fun boo = (z,) => +(bar(z,), x,)}; ('(' new Foo([1,]) {} ')').boo(2,)} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(_: Var(x)), (), None, None, TypingUnit(NuFunDef(None, bar, None, [], Lam(Tup(_: Var(y)), App(Var(+), Tup(_: Var(x), _: Var(y))))), NuFunDef(None, boo, None, [], Lam(Tup(_: Var(z)), App(Var(+), Tup(_: App(Var(bar), Tup(_: Var(z))), _: Var(x))))))), App(Sel(Bra(rcd = false, New(Some((TypeName(Foo),[1,])), TypingUnit())), boo), Tup(_: IntLit(2)))) +//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(x: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, bar, None, [], Lam(Tup(_: Var(y)), App(Var(+), Tup(_: Var(x), _: Var(y))))), NuFunDef(None, boo, None, [], Lam(Tup(_: Var(z)), App(Var(+), Tup(_: App(Var(bar), Tup(_: Var(z))), _: Var(x))))))), App(Sel(Bra(rcd = false, New(Some((TypeName(Foo),[1,])), TypingUnit())), boo), Tup(_: IntLit(2)))) //│ Lifted: //│ TypingUnit { -//│ class Foo$1([x,]) { +//│ class Foo$1([x: Int,]) { //│ fun bar = (y,) => +((this).x, y,) //│ fun boo = (z,) => +((this).bar(z,), (this).x,) //│ } @@ -833,21 +880,27 @@ class Foo(x){ //│ new Foo$1 (#1) match {case obj: Foo$1 => boo$Foo$1(obj, #2)} //│ class Foo$1(x) { //│ } -//│ +//│ class Foo(x: Int) { +//│ fun bar: Int -> Int +//│ fun boo: Int -> Int +//│ } +//│ Int +//│ res +//│ = 4 :mono -class OneInt(a){ - fun fac() = +class OneInt(a: Int){ + fun fac: () -> Int + fun fac = () -> if(a > 0) then (new OneInt(a - 1)).fac() else 1 } (new OneInt(10)).fac() -//│ |#class| |OneInt|(|a|)|{|→|#fun| |fac|(||)| |#=| |→|#if|(|a| |>| |0|)| |#then| |(|#new| |OneInt|(|a| |-| |1|)|)|.fac|(||)| |#else| |1| |←|←|↵|}|↵|(|#new| |OneInt|(|10|)|)|.fac|(||)| -//│ Parsed: {class OneInt(a,) {fun fac = () => {if ('(' >(a, 0,) ')') then ('(' new OneInt([-(a, 1,),]) {} ')').fac() else 1}}; ('(' new OneInt([10,]) {} ')').fac()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), None, None, TypingUnit(NuFunDef(None, fac, None, [], Lam(Tup(), Blk(...))))), App(Sel(Bra(rcd = false, New(Some((TypeName(OneInt),[10,])), TypingUnit())), fac), Tup())) +//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(a: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, fac, None, [], PolyType(List(),Function(Tuple(List()),TypeName(Int)))), NuFunDef(None, fac, None, [], Lam(Tup(), Blk(...))))), App(Sel(Bra(rcd = false, New(Some((TypeName(OneInt),[10,])), TypingUnit())), fac), Tup())) //│ Lifted: //│ TypingUnit { -//│ class OneInt$1([a,]) { +//│ class OneInt$1([a: Int,]) { +//│ fun fac = () -> Int //│ fun fac = () => {if ('(' >((this).a, 0,) ')') then ('(' new OneInt$1([-((this).a, 1,),]) {} ')').fac() else 1} //│ } //│ Code(List(('(' new OneInt$1([10,]) {} ')').fac())) @@ -862,57 +915,29 @@ class OneInt(a){ //│ new OneInt$1 (#10) match {case obj: OneInt$1 => fac$OneInt$1(obj)} //│ class OneInt$1(a) { //│ } -//│ - -:mono -trait AnyFoo { -} -class FooPlus(#a): AnyFoo { - fun bar(b) = a + b -} -class FooMinus(#a): AnyFoo { - fun bar(b) = a - b -} -fun f(x) = x.bar(42) -f(new FooPlus(1)) -f(new FooMinus(2)) -//│ |#trait| |AnyFoo| |{|↵|}|↵|#class| |FooPlus|(|##|a|)|#:| |AnyFoo| |{|→|#fun| |bar|(|b|)| |#=| |a| |+| |b|←|↵|}|↵|#class| |FooMinus|(|##|a|)|#:| |AnyFoo| |{|→|#fun| |bar|(|b|)| |#=| |a| |-| |b|←|↵|}|↵|#fun| |f|(|x|)| |#=| |x|.bar|(|42|)|↵|f|(|#new| |FooPlus|(|1|)|)|↵|f|(|#new| |FooMinus|(|2|)|)| -//│ Parsed: {trait AnyFoo {}; class FooPlus(#a,): AnyFoo {fun bar = (b,) => +(a, b,)}; class FooMinus(#a,): AnyFoo {fun bar = (b,) => -(a, b,)}; fun f = (x,) => (x).bar(42,); f(new FooPlus([1,]) {},); f(new FooMinus([2,]) {},)} -//│ Parsed: -//│ TypingUnit(NuTypeDef(trait, AnyFoo, (), Tup(), (), None, None, TypingUnit()), NuTypeDef(class, FooPlus, (), Tup(_: Var(a)), (), None, None, TypingUnit(NuFunDef(None, bar, None, [], Lam(Tup(_: Var(b)), App(Var(+), Tup(_: Var(a), _: Var(b))))))), NuTypeDef(class, FooMinus, (), Tup(_: Var(a)), (), None, None, TypingUnit(NuFunDef(None, bar, None, [], Lam(Tup(_: Var(b)), App(Var(-), Tup(_: Var(a), _: Var(b))))))), NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), App(Sel(Var(x), bar), Tup(_: IntLit(42))))), App(Var(f), Tup(_: New(Some((TypeName(FooPlus),[1,])), TypingUnit()))), App(Var(f), Tup(_: New(Some((TypeName(FooMinus),[2,])), TypingUnit())))) -//│ Lifted: -//│ TypingUnit { -//│ trait AnyFoo$1([]) {} -//│ class FooPlus$2([#a,]) {fun bar = (b,) => +((this).a, b,)} -//│ class FooMinus$3([#a,]) {fun bar = (b,) => -((this).a, b,)} -//│ fun f$1 = (x,) => (x).bar(42,) -//│ Code(List(f$1(new FooPlus$2([1,]) {},))) -//│ Code(List(f$1(new FooMinus$3([2,]) {},))) +//│ class OneInt(a: Int) { +//│ fun fac: () -> Int //│ } -//│ Mono: -//│ -//│ Defunc result: -//│ main$$4() -//│ main$$5() -//│ fun bar$FooPlus$2(this, b) = -//│ +(this.a, b) -//│ fun f$1(x) = -//│ x match {case obj: FooMinus$3 => bar$FooMinus$3(obj, #42); case obj: FooPlus$2 => bar$FooPlus$2(obj, #42)} -//│ fun main$$5() = -//│ f$1(new FooMinus$3 (#2) ) -//│ fun bar$FooMinus$3(this, b) = -//│ -(this.a, b) -//│ fun main$$4() = -//│ f$1(new FooPlus$2 (#1) ) -//│ trait AnyFoo$1() { -//│ } -//│ class FooPlus$2(#a) { -//│ } -//│ class FooMinus$3(#a) { -//│ } -//│ +//│ Int +//│ res +//│ = 1 + +//:mono +//:e // FIXME: Mutable Parameters +//trait AnyFoo { +//} +//class FooPlus(#a): AnyFoo { +// fun bar(b) = a + b +//} +//class FooMinus(#a): AnyFoo { +// fun bar(b) = a - b +//} +//fun f(x) = x.bar(42) +//f(new FooPlus(1)) +//f(new FooMinus(2)) :mono +val any = -20 fun f(x) = if x > any then 0 else g(x - 1) @@ -920,12 +945,11 @@ fun g(x) = if x > any then g(x - 1) else f(x - 2) g(1) -//│ |#fun| |f|(|x|)| |#=| |→|#if| |x| |>| |any| |#then| |0|↵|#else| |g|(|x| |-| |1|)|←|↵|#fun| |g|(|x|)| |#=| |→|#if| |x| |>| |any| |#then| |g|(|x| |-| |1|)|↵|#else| |f|(|x| |-| |2|)|←|↵|g|(|1|)| -//│ Parsed: {fun f = (x,) => {if (>(x, any,)) then 0 else g(-(x, 1,),)}; fun g = (x,) => {if (>(x, any,)) then g(-(x, 1,),) else f(-(x, 2,),)}; g(1,)} //│ Parsed: -//│ TypingUnit(NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, g, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(g), Tup(_: IntLit(1)))) +//│ TypingUnit(NuFunDef(Some(false), any, None, [], IntLit(-20)), NuFunDef(None, f, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, g, None, [], Lam(Tup(_: Var(x)), Blk(...))), App(Var(g), Tup(_: IntLit(1)))) //│ Lifted: //│ TypingUnit { +//│ let any$3 = () => -20 //│ fun f$1 = (x,) => {if (>(x, any,)) then 0 else g$2(-(x, 1,),)} //│ fun g$2 = (x,) => {if (>(x, any,)) then g$2(-(x, 1,),) else f$1(-(x, 2,),)} //│ Code(List(g$2(1,))) @@ -933,31 +957,39 @@ g(1) //│ Mono: //│ //│ Defunc result: -//│ main$$2() +//│ main$$3() +//│ fun any$3() = +//│ #-20 //│ fun f$1(x) = //│ if >(x, any) then #0 else g$2(-(x, #1)) //│ fun g$2(x) = //│ if >(x, any) then g$2(-(x, #1)) else f$1(-(x, #2)) -//│ fun main$$2() = +//│ fun main$$3() = //│ g$2(#1) -//│ +//│ val any: -20 +//│ fun f: Int -> 0 +//│ fun g: Int -> 0 +//│ 0 +//│ any +//│ = -20 +//│ res +//│ Runtime error: +//│ RangeError: Maximum call stack size exceeded :mono -class OneInt(a){ - fun get = a +class OneInt(a: Int){ + fun get = () -> a } -class OneBool(b){ - fun get = b +class OneBool(b: Bool){ + fun get = () -> b } (if b then new OneInt(1) else new OneBool(true)).get() -//│ |#class| |OneInt|(|a|)|{|→|#fun| |get| |#=| |a|←|↵|}|↵|#class| |OneBool|(|b|)|{|→|#fun| |get| |#=| |b|←|↵|}|↵|(|#if| |b| |#then| |#new| |OneInt|(|1|)| |#else| |#new| |OneBool|(|true|)|)|.get|(||)| -//│ Parsed: {class OneInt(a,) {fun get = a}; class OneBool(b,) {fun get = b}; ('(' if (b) then new OneInt([1,]) {} else new OneBool([true,]) {} ')').get()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(_: Var(a)), (), None, None, TypingUnit(NuFunDef(None, get, None, [], Var(a)))), NuTypeDef(class, OneBool, (), Tup(_: Var(b)), (), None, None, TypingUnit(NuFunDef(None, get, None, [], Var(b)))), App(Sel(Bra(rcd = false, If(IfThen(Var(b), New(Some((TypeName(OneInt),[1,])), TypingUnit()), Some(New(Some((TypeName(OneBool),[true,])), TypingUnit())))), get), Tup())) +//│ TypingUnit(NuTypeDef(class, OneInt, (), Tup(a: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, get, None, [], Lam(Tup(), Var(a))))), NuTypeDef(class, OneBool, (), Tup(b: Var(Bool)), (), None, None, TypingUnit(NuFunDef(None, get, None, [], Lam(Tup(), Var(b))))), App(Sel(Bra(rcd = false, If(IfThen(Var(b), New(Some((TypeName(OneInt),[1,])), TypingUnit()), Some(New(Some((TypeName(OneBool),[true,])), TypingUnit())))), get), Tup())) //│ Lifted: //│ TypingUnit { -//│ class OneInt$1([a,]) {fun get = () => (this).a} -//│ class OneBool$2([b,]) {fun get = () => (this).b} +//│ class OneInt$1([a: Int,]) {fun get = () => (this).a} +//│ class OneBool$2([b: Bool,]) {fun get = () => (this).b} //│ Code(List(('(' if (b) then new OneInt$1([1,]) {} else new OneBool$2([true,]) {} ')').get())) //│ } //│ Mono: @@ -974,9 +1006,18 @@ class OneBool(b){ //│ } //│ class OneBool$2(b) { //│ } -//│ +//│ class OneInt(a: Int) { +//│ fun get: () -> Int +//│ } +//│ class OneBool(b: Bool) { +//│ fun get: () -> Bool +//│ } +//│ Int | false | true +//│ res +//│ = true :mono +:e // FIXME: Malformed Test? class Bar(x: int) { fun FooMinus(y: int) = x + y fun car = foo(2) @@ -989,8 +1030,6 @@ let bar = Bar(42) baz(bar) Car().da(Bar(1337)) bar.car -//│ |#class| |Bar|(|x|#:| |int|)| |{|→|#fun| |FooMinus|(|y|#:| |int|)| |#=| |x| |+| |y|↵|#fun| |car| |#=| |foo|(|2|)|←|↵|}|↵|#class| |Car| |{|→|#fun| |da|(|b|#:| |Bar|)| |#=| |b|.foo|(|2|)|←|↵|}|↵|#fun| |baz|(|b|#:| |Bar|)| |#=| |b|.foo|(|2|)|↵|#let| |bar| |#=| |Bar|(|42|)|↵|baz|(|bar|)|↵|Car|(||)|.da|(|Bar|(|1337|)|)|↵|bar|.car| -//│ Parsed: {class Bar(x: int,) {fun FooMinus = (y: int,) => +(x, y,); fun car = foo(2,)}; class Car {fun da = (b: Bar,) => (b).foo(2,)}; fun baz = (b: Bar,) => (b).foo(2,); let bar = Bar(42,); baz(bar,); (Car()).da(Bar(1337,),); (bar).car} //│ Parsed: //│ TypingUnit(NuTypeDef(class, Bar, (), Tup(x: Var(int)), (), None, None, TypingUnit(NuFunDef(None, FooMinus, None, [], Lam(Tup(y: Var(int)), App(Var(+), Tup(_: Var(x), _: Var(y))))), NuFunDef(None, car, None, [], App(Var(foo), Tup(_: IntLit(2)))))), NuTypeDef(class, Car, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, da, None, [], Lam(Tup(b: Var(Bar)), App(Sel(Var(b), foo), Tup(_: IntLit(2))))))), NuFunDef(None, baz, None, [], Lam(Tup(b: Var(Bar)), App(Sel(Var(b), foo), Tup(_: IntLit(2))))), NuFunDef(Some(false), bar, None, [], App(Var(Bar), Tup(_: IntLit(42)))), App(Var(baz), Tup(_: Var(bar))), App(Sel(App(Var(Car), Tup()), da), Tup(_: App(Var(Bar), Tup(_: IntLit(1337))))), Sel(Var(bar), car)) //│ Lifted: @@ -1016,77 +1055,162 @@ bar.car //│ Bar$1(#42) //│ fun main$$6() = //│ bar.car -//│ fun baz$2(Bar$1) = +//│ fun baz$2(b) = //│ b match {} //│ fun main$$5() = //│ Car$2() match {} //│ fun main$$4() = //│ baz$2(bar) -//│ class Bar$1(int) { +//│ class Bar$1(x) { //│ } //│ class Car$2() { //│ } -//│ +//│ ╔══[ERROR] Type mismatch in operator application: +//│ ║ l.1022: fun FooMinus(y: int) = x + y +//│ ║ ^^^^^ +//│ ╟── type `int` is not an instance of `Int` +//│ ║ l.1021: class Bar(x: int) { +//│ ║ ^^^ +//│ ╟── but it flows into reference with expected type `Int` +//│ ║ l.1022: fun FooMinus(y: int) = x + y +//│ ╙── ^ +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.1023: fun car = foo(2) +//│ ║ ^^^^^^ +//│ ╟── integer literal of type `2` is not a function +//│ ║ l.1023: fun car = foo(2) +//│ ║ ^ +//│ ╟── Note: constraint arises from application: +//│ ║ l.624: x(new Cons(1, new Nil())) + x(new Nil()) +//│ ║ ^^^^^^^^^^^^ +//│ ╟── from reference: +//│ ║ l.624: x(new Cons(1, new Nil())) + x(new Nil()) +//│ ╙── ^ +//│ ╔══[ERROR] Type `Bar` does not contain member `foo` +//│ ║ l.1026: fun da(b: Bar) = b.foo(2) +//│ ╙── ^^^^ +//│ ╔══[ERROR] Type `Bar` does not contain member `foo` +//│ ║ l.1028: fun baz(b: Bar) = b.foo(2) +//│ ╙── ^^^^ +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.1029: let bar = Bar(42) +//│ ║ ^^^^^^^ +//│ ╟── integer literal of type `42` is not an instance of type `int` +//│ ║ l.1029: let bar = Bar(42) +//│ ║ ^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.1021: class Bar(x: int) { +//│ ╙── ^^^ +//│ ╔══[ERROR] Construction of unparameterized class Car should use the `new` keyword +//│ ║ l.1031: Car().da(Bar(1337)) +//│ ╙── ^^^ +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.1031: Car().da(Bar(1337)) +//│ ║ ^^^^^^^^^ +//│ ╟── integer literal of type `1337` is not an instance of type `int` +//│ ║ l.1031: Car().da(Bar(1337)) +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.1021: class Bar(x: int) { +//│ ╙── ^^^ +//│ class Bar(x: int) { +//│ fun FooMinus: (y: int) -> (Int | error) +//│ fun car: Int | error +//│ } +//│ class Car { +//│ constructor() +//│ fun da: (b: Bar) -> error +//│ } +//│ fun baz: (b: Bar) -> error +//│ let bar: Bar | error +//│ Int | error +//│ bar +//│ = Bar {} +//│ res +//│ Runtime error: +//│ TypeError: b.foo is not a function +//│ res +//│ Runtime error: +//│ TypeError: Class constructor Car cannot be invoked without 'new' +//│ res +//│ Runtime error: +//│ TypeError: x is not a function :mono -class Sup(a){ - fun foo = a +val c = 5 +class Sup(a: Int){ + virtual fun foo = () -> a } -class Sub(b) extends Sup(b+b){ +class Sub(b: Int) extends Sup(b+b){ } -class Sub2(c) extends Sub(c+c){ - fun foo = a+c +class Sub2(c: Int) extends Sub(c+c){ + fun foo = () -> a+c } (new Sub(10)).foo() (new Sub2(c)).foo() -//│ |#class| |Sup|(|a|)|{|→|#fun| |foo| |#=| |a|←|↵|}|↵|#class| |Sub|(|b|)| |#extends| |Sup|(|b|+|b|)|{|↵|}|↵|#class| |Sub2|(|c|)| |#extends| |Sub|(|c|+|c|)|{|→|#fun| |foo| |#=| |a|+|c|←|↵|}|↵|(|#new| |Sub|(|10|)|)|.foo|(||)|↵|(|#new| |Sub2|(|c|)|)|.foo|(||)| -//│ Parsed: {class Sup(a,) {fun foo = a}; class Sub(b,): Sup(+(b, b,),) {}; class Sub2(c,): Sub(+(c, c,),) {fun foo = +(a, c,)}; ('(' new Sub([10,]) {} ')').foo(); ('(' new Sub2([c,]) {} ')').foo()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Sup, (), Tup(_: Var(a)), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Var(a)))), NuTypeDef(class, Sub, (), Tup(_: Var(b)), (App(Var(Sup), Tup(_: App(Var(+), Tup(_: Var(b), _: Var(b)))))), None, None, TypingUnit()), NuTypeDef(class, Sub2, (), Tup(_: Var(c)), (App(Var(Sub), Tup(_: App(Var(+), Tup(_: Var(c), _: Var(c)))))), None, None, TypingUnit(NuFunDef(None, foo, None, [], App(Var(+), Tup(_: Var(a), _: Var(c)))))), App(Sel(Bra(rcd = false, New(Some((TypeName(Sub),[10,])), TypingUnit())), foo), Tup()), App(Sel(Bra(rcd = false, New(Some((TypeName(Sub2),[c,])), TypingUnit())), foo), Tup())) +//│ TypingUnit(NuFunDef(Some(false), c, None, [], IntLit(5)), NuTypeDef(class, Sup, (), Tup(a: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(), Var(a))))), NuTypeDef(class, Sub, (), Tup(b: Var(Int)), (App(Var(Sup), Tup(_: App(Var(+), Tup(_: Var(b), _: Var(b)))))), None, None, TypingUnit()), NuTypeDef(class, Sub2, (), Tup(c: Var(Int)), (App(Var(Sub), Tup(_: App(Var(+), Tup(_: Var(c), _: Var(c)))))), None, None, TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(), App(Var(+), Tup(_: Var(a), _: Var(c))))))), App(Sel(Bra(rcd = false, New(Some((TypeName(Sub),[10,])), TypingUnit())), foo), Tup()), App(Sel(Bra(rcd = false, New(Some((TypeName(Sub2),[c,])), TypingUnit())), foo), Tup())) //│ Lifted: //│ TypingUnit { -//│ class Sup$1([a,]) {fun foo = () => (this).a} -//│ class Sub$2([b,]): Sup$1(+((this).b, (this).b,),) {} -//│ class Sub2$3([c,]): Sub$2(+((this).c, (this).c,),) {fun foo = () => +((this).a, (this).c,)} +//│ class Sup$1([a: Int,]) {fun foo = () => (this).a} +//│ class Sub$2([b: Int,]): Sup$1(+((this).b, (this).b,),) {} +//│ class Sub2$3([c: Int,]): Sub$2(+((this).c, (this).c,),) {fun foo = () => +((this).a, (this).c,)} +//│ let c$1 = () => 5 //│ Code(List(('(' new Sub$2([10,]) {} ')').foo())) //│ Code(List(('(' new Sub2$3([c,]) {} ')').foo())) //│ } //│ Mono: //│ //│ Defunc result: -//│ main$$3() //│ main$$4() -//│ fun main$$4() = +//│ main$$5() +//│ fun c$1() = +//│ #5 +//│ fun main$$5() = //│ new Sub2$3 (c) match {case obj: Sub2$3 => foo$Sub2$3(obj)} +//│ fun main$$4() = +//│ new Sub$2 (#10) match {case obj: Sub$2 => foo$Sup$1(obj)} //│ fun foo$Sup$1(this) = //│ this.a //│ fun foo$Sub2$3(this) = //│ +(this.a, this.c) -//│ fun main$$3() = -//│ new Sub$2 (#10) match {case obj: Sub$2 => foo$Sup$1(obj)} //│ class Sub2$3(c): Sub$2(+(this.c, this.c)) { //│ } //│ class Sup$1(a) { //│ } //│ class Sub$2(b): Sup$1(+(this.b, this.b)) { //│ } -//│ +//│ val c: 5 +//│ class Sup(a: Int) { +//│ fun foo: () -> Int +//│ } +//│ class Sub(b: Int) extends Sup { +//│ fun foo: () -> Int +//│ } +//│ class Sub2(c: Int) extends Sub, Sup { +//│ fun foo: () -> Int +//│ } +//│ Int +//│ c +//│ = 5 +//│ res +//│ = 20 +//│ res +//│ = 47 :mono -class Foo(f){ - fun foo = f(1) +class Foo(f: Int -> Int){ + fun foo = () -> f(1) } class F1() extends Foo(x => x+1){} class F2() extends Foo(x => x+2){} (new F1()).foo() (new F2()).foo() -//│ |#class| |Foo|(|f|)|{|→|#fun| |foo| |#=| |f|(|1|)|←|↵|}|↵|#class| |F1|(||)| |#extends| |Foo|(|x| |=>| |x|+|1|)|{||}|↵|#class| |F2|(||)| |#extends| |Foo|(|x| |=>| |x|+|2|)|{||}|↵|(|#new| |F1|(||)|)|.foo|(||)|↵|(|#new| |F2|(||)|)|.foo|(||)| -//│ Parsed: {class Foo(f,) {fun foo = f(1,)}; class F1(): Foo((x,) => +(x, 1,),) {}; class F2(): Foo((x,) => +(x, 2,),) {}; ('(' new F1([]) {} ')').foo(); ('(' new F2([]) {} ')').foo()} //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(_: Var(f)), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], App(Var(f), Tup(_: IntLit(1)))))), NuTypeDef(class, F1, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(Var(+), Tup(_: Var(x), _: IntLit(1))))))), None, None, TypingUnit()), NuTypeDef(class, F2, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(Var(+), Tup(_: Var(x), _: IntLit(2))))))), None, None, TypingUnit()), App(Sel(Bra(rcd = false, New(Some((TypeName(F1),[])), TypingUnit())), foo), Tup()), App(Sel(Bra(rcd = false, New(Some((TypeName(F2),[])), TypingUnit())), foo), Tup())) +//│ TypingUnit(NuTypeDef(class, Foo, (), Tup(f: App(Var(->), Tup(_: Var(Int), _: Var(Int)))), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(), App(Var(f), Tup(_: IntLit(1))))))), NuTypeDef(class, F1, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(Var(+), Tup(_: Var(x), _: IntLit(1))))))), None, None, TypingUnit()), NuTypeDef(class, F2, (), Tup(), (App(Var(Foo), Tup(_: Lam(Tup(_: Var(x)), App(Var(+), Tup(_: Var(x), _: IntLit(2))))))), None, None, TypingUnit()), App(Sel(Bra(rcd = false, New(Some((TypeName(F1),[])), TypingUnit())), foo), Tup()), App(Sel(Bra(rcd = false, New(Some((TypeName(F2),[])), TypingUnit())), foo), Tup())) //│ Lifted: //│ TypingUnit { -//│ class Foo$1([f,]) {fun foo = () => (this).f(1,)} +//│ class Foo$1([f: ->(Int, Int,),]) {fun foo = () => (this).f(1,)} //│ class F1$2_Lambda1$1$4([par$F1$2,]) {fun apply = (x,) => +(x, 1,)} //│ class F1$2([]): Foo$1({new F1$2_Lambda1$1$4([this,]) {}},) {} //│ class F2$3_Lambda1$2$5([par$F2$3,]) {fun apply = (x,) => +(x, 2,)} @@ -1119,4 +1243,17 @@ class F2() extends Foo(x => x+2){} //│ } //│ class F1$2_Lambda1$1$4(par$F1$2) { //│ } -//│ +//│ class Foo(f: Int -> Int) { +//│ fun foo: () -> Int +//│ } +//│ class F1() extends Foo { +//│ fun foo: () -> Int +//│ } +//│ class F2() extends Foo { +//│ fun foo: () -> Int +//│ } +//│ Int +//│ res +//│ = 2 +//│ res +//│ = 3 From 3fb7c693b1802f0c7e3eefb05b8131e787f9905b Mon Sep 17 00:00:00 2001 From: HarrisL2 Date: Thu, 5 Oct 2023 00:06:47 +0800 Subject: [PATCH 10/13] fix compilation warnings --- .../shared/main/scala/mlscript/compiler/ClassLifter.scala | 2 ++ compiler/shared/main/scala/mlscript/compiler/Helpers.scala | 5 +++++ .../shared/main/scala/mlscript/compiler/mono/Monomorph.scala | 2 ++ .../main/scala/mlscript/compiler/mono/MonomorphContext.scala | 2 +- .../mlscript/compiler/mono/specializer/Specializer.scala | 1 + 5 files changed, 11 insertions(+), 1 deletion(-) diff --git a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala index 9f216ee03..83ba401d3 100644 --- a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala +++ b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala @@ -9,6 +9,7 @@ import scala.collection.mutable.Set as MutSet import scala.collection.mutable.ArrayBuffer as ArrayBuffer import mlscript.codegen.Helpers.inspect as showStructure import mlscript.codegen.CodeGenError +import mlscript.compiler.mono.MonomorphError class ClassLifter(logDebugMsg: Boolean = false) { type ClassName = String @@ -613,6 +614,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { case (tn, ctx) => (L(tn), ctx) case R(tv) => R(tv) -> emptyCtx}).unzip NuFunDef(rec, globFuncs.get(nm).get._1, N, nTpVs, Right(PolyType(nTargs._1, nBody._1)))(N, N, N, N, true) //TODO: Use proper arguments + case _ => ??? }) } diff --git a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala index fe465d44b..8fec8de09 100644 --- a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala +++ b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala @@ -19,6 +19,7 @@ import mlscript.StrLit import mlscript.AppliedType import mlscript.TypeName import mlscript.TypeDefKind +import mlscript.compiler.mono.Monomorph object Helpers: /** @@ -88,6 +89,7 @@ object Helpers: case mlscript.TypeDef(_, _, _, _, _, _, _, _) => throw MonomorphError("unsupported TypeDef") case mlscript.Def(_, _, _, _) => throw MonomorphError("unsupported Def") case mlscript.LetS(_, _, _) => throw MonomorphError("unsupported LetS") + case mlscript.Constructor(_, _) => throw MonomorphError("unsupported Constructor") }) case Bra(rcd, term) => term2Expr(term) case Asc(term, ty) => Expr.As(term2Expr(term), ty) @@ -146,6 +148,7 @@ object Helpers: Expr.Literal(if undefinedOrNull then UnitValue.Undefined else UnitValue.Null) + case _ => throw MonomorphError("unsupported term"+ term.toString) } def func2Item(funDef: NuFunDef): Item.FuncDecl | Item.FuncDefn = @@ -165,6 +168,7 @@ object Helpers: case subTypeDef: NuTypeDef => ??? case subFunDef: NuFunDef => Some(func2Item(subFunDef)) + case term => throw MonomorphError(term.toString) }) val typeDecl: Item.TypeDecl = Item.TypeDecl( Expr.Ref(className.name), // name @@ -189,3 +193,4 @@ object Helpers: case Als => TypeDeclKind.Alias case Cls => TypeDeclKind.Class case Trt => TypeDeclKind.Trait + case _ => ??? diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala index 5a324836d..b56845b4f 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala @@ -106,6 +106,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: addNewFunction(funcDecl) case _ => () None + case _ => ??? }; debug.log(getResult(exps).getDebugOutput.toLines(using false).mkString("\n")) while(!evalQueue.isEmpty){ @@ -158,6 +159,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: None case funDef: NuFunDef => Some(func2Item(funDef)) + case _ => ??? }) }(identity) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/MonomorphContext.scala b/compiler/shared/main/scala/mlscript/compiler/mono/MonomorphContext.scala index d73292633..b3eef1342 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/MonomorphContext.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/MonomorphContext.scala @@ -15,7 +15,7 @@ class MonomorphContext(context: List[Map[String, DataType]]) extends Printable: def :+(entry: (String, DataType)): MonomorphContext = MonomorphContext((Map.empty + entry) :: context) - def unary_+(): MonomorphContext = + def unary_+ : MonomorphContext = MonomorphContext(Map.empty :: context) def get(key: String): Option[DataType] = diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala index d64ad24d5..e7622a8d6 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala @@ -220,6 +220,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ }) case Expr.Select(receiver, field) => Expr.Select(defunctionalize(receiver), field) case Expr.As(value, toType) => Expr.As(defunctionalize(value), toType) + case _ => ??? } ret.expValue = rawExpr.expValue ret From 72afbfb9995cc68c99dc1772c753ec6888ea8912 Mon Sep 17 00:00:00 2001 From: HarrisL2 Date: Tue, 10 Oct 2023 01:08:23 +0800 Subject: [PATCH 11/13] Rename functions, remove comments and fix tests --- .../scala/mlscript/compiler/ClassLifter.scala | 90 +++---- .../mlscript/compiler/mono/Monomorph.scala | 7 +- .../compiler/printer/ExprPrinter.scala | 49 +--- .../main/scala/mlscript/compiler/syntax.scala | 2 +- compiler/shared/test/diff/LambLift.mls | 24 +- compiler/shared/test/diff/mono.mls | 240 ++++++++---------- 6 files changed, 157 insertions(+), 255 deletions(-) diff --git a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala index 83ba401d3..d552b2ae7 100644 --- a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala +++ b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala @@ -229,26 +229,26 @@ class ClassLifter(logDebugMsg: Boolean = false) { private def liftCaseBranch(brn: CaseBranches)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (CaseBranches, LocalContext) = brn match{ case Case(v: Var, body, rest) => - val nTrm = liftTermNew(body)(using ctx.addV(v)) + val nTrm = liftTerm(body)(using ctx.addV(v)) val nRest = liftCaseBranch(rest) (Case(v, nTrm._1, nRest._1), nTrm._2 ++ nRest._2) case Case(pat, body, rest) => - val nTrm = liftTermNew(body) + val nTrm = liftTerm(body) val nRest = liftCaseBranch(rest) (Case(pat, nTrm._1, nRest._1), nTrm._2 ++ nRest._2) case Wildcard(body) => - val nTrm = liftTermNew(body) + val nTrm = liftTerm(body) (Wildcard(nTrm._1), nTrm._2) case NoCases => (brn, emptyCtx) } private def liftIf(body: IfBody)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (IfBody, LocalContext) = body match{ case IfElse(expr) => - val ret = liftTermNew(expr) + val ret = liftTerm(expr) (IfElse(ret._1), ret._2) case IfThen(expr, rhs) => - val nE = liftTermNew(expr) - val nR = liftTermNew(rhs) + val nE = liftTerm(expr) + val nR = liftTerm(rhs) (IfThen(nE._1, nR._1), nE._2 ++ nR._2) case _ => ??? } @@ -256,7 +256,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { private def liftTuple(tup: Tup)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Tup, LocalContext) = { val ret = tup.fields.map{ case (None, Fld(flags, trm)) => - val tmp = liftTermNew(trm) + val tmp = liftTerm(trm) ((None, Fld(flags, tmp._1)), tmp._2) case (Some(v), Fld(flags, trm)) => val nTrm = liftTermAsType(trm) @@ -302,7 +302,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { private def newLambObj(lhs: Term, rhs: Term) = New(None, TypingUnit(List(NuFunDef(None, Var("apply"), None, Nil, Left(Lam(lhs, rhs)))(N, N, N, N, false)))) //TODO: Use Proper Arguments - private def liftTermNew(target: Term)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Term, LocalContext) = + private def liftTerm(target: Term)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Term, LocalContext) = log(s"liftTermNew $target in $ctx, $cache, $globFuncs, $outer") target match{ case v: Var => @@ -324,7 +324,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { Cls, nTpNm, Nil, S(Tup(Nil)), N, N, Nil, N, N, TypingUnit(List(NuFunDef(None, Var("apply"), N, Nil, Left(Lam(lhs, rhs)))(N, N, N, N, false))))(N, N) //TODO: Use Proper Arguments val nSta = New(Some((nTpNm, Tup(Nil))), TypingUnit(Nil)) - val ret = liftEntitiesNew(List(anoCls, nSta)) + val ret = liftEntities(List(anoCls, nSta)) (Blk(ret._1), ret._2) case t: Tup => liftTuple(t) @@ -336,7 +336,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { }.unzip (Rcd(ret._1), ret._2.fold(emptyCtx)(_ ++ _)) case Asc(trm, ty) => - val ret = liftTermNew(trm) + val ret = liftTerm(trm) val nTy = liftType(ty) (Asc(ret._1, nTy._1), ret._2 ++ nTy._2) case App(v: Var, prm: Tup) if cache.contains(TypeName(v.name)) => @@ -348,22 +348,22 @@ class ClassLifter(logDebugMsg: Boolean = false) { val nPrm = liftTuple(prm) (App(nFuncName, Tup(nPrm._1.fields ++ addiArgs)), nPrm._2) case App(lhs, rhs) => - val (ltrm, lctx) = liftTermNew(lhs) - val (rtrm, rctx) = liftTermNew(rhs) + val (ltrm, lctx) = liftTerm(lhs) + val (rtrm, rctx) = liftTerm(rhs) (App(ltrm, rtrm), lctx ++ rctx) case Assign(lhs, rhs) => - val (ltrm, lctx) = liftTermNew(lhs) - val (rtrm, rctx) = liftTermNew(rhs) + val (ltrm, lctx) = liftTerm(lhs) + val (rtrm, rctx) = liftTerm(rhs) (Assign(ltrm, rtrm), lctx ++ rctx) case Bind(lhs, rhs) => - val (ltrm, lctx) = liftTermNew(lhs) + val (ltrm, lctx) = liftTerm(lhs) val (rtrm, rctx) = liftTermAsType(rhs) (Bind(ltrm, rtrm), lctx ++ rctx) case Bra(rcd, trm) => - val ret = liftTermNew(trm) + val ret = liftTerm(trm) (Bra(rcd, ret._1), ret._2) case CaseOf(trm, cases) => - val nTrm = liftTermNew(trm) + val nTrm = liftTerm(trm) val nCases = liftCaseBranch(cases) (CaseOf(nTrm._1, nCases._1), nTrm._2 ++ nCases._2) case If(body, None) => @@ -371,26 +371,26 @@ class ClassLifter(logDebugMsg: Boolean = false) { (If(ret._1, None), ret._2) case If(body, Some(trm)) => val ret = liftIf(body) - val nTrm = liftTermNew(trm) + val nTrm = liftTerm(trm) (If(ret._1, Some(nTrm._1)), ret._2 ++ nTrm._2) case Let(isRec, name, rhs, body) => - val nRhs = if(isRec) liftTermNew(rhs)(using ctx.addV(name)) else liftTermNew(rhs) - val nBody = liftTermNew(body)(using ctx.addV(name)) + val nRhs = if(isRec) liftTerm(rhs)(using ctx.addV(name)) else liftTerm(rhs) + val nBody = liftTerm(body)(using ctx.addV(name)) (Let(isRec, name, nRhs._1, nBody._1), nRhs._2 ++ nBody._2) case Sel(receiver, fieldName) => - val nRec = liftTermNew(receiver) + val nRec = liftTerm(receiver) (Sel(nRec._1, fieldName), nRec._2) case Splc(fields) => ??? case Subs(arr, idx) => - val (ltrm, lctx) = liftTermNew(arr) - val (rtrm, rctx) = liftTermNew(idx) + val (ltrm, lctx) = liftTerm(arr) + val (rtrm, rctx) = liftTerm(idx) (Subs(ltrm, rtrm), lctx ++ rctx) case Test(trm, ty) => - val (ltrm, lctx) = liftTermNew(trm) + val (ltrm, lctx) = liftTerm(trm) val (rtrm, rctx) = liftTermAsType(ty) (Test(ltrm, rtrm), lctx ++ rctx) case TyApp(lhs, targs) => - val ret = liftTermNew(lhs) + val ret = liftTerm(lhs) val nTs = targs.map(liftType).unzip (TyApp(ret._1, nTs._1), nTs._2.fold(ret._2)(_ ++ _)) case With(trm, fields) => ??? @@ -405,28 +405,28 @@ class ClassLifter(logDebugMsg: Boolean = false) { val anoCls = NuTypeDef(Cls, nTpNm, Nil, cls.body.params, None, None, List(App(Var(t.name), supArgs)), None, None, tu)(None, None) val nSta = New(Some((nTpNm, prm)), TypingUnit(Nil)) - val ret = liftEntitiesNew(List(anoCls, nSta)) + val ret = liftEntities(List(anoCls, nSta)) (Blk(ret._1), ret._2) case New(None, tu) => val nTpNm = TypeName(genAnoName()) val anoCls = NuTypeDef(Cls, nTpNm, Nil, None, None, None, Nil, None, None, tu)(None, None) val nSta = New(Some((nTpNm, Tup(Nil))), TypingUnit(Nil)) - val ret = liftEntitiesNew(List(anoCls, nSta)) + val ret = liftEntities(List(anoCls, nSta)) (Blk(ret._1), ret._2) case New(head, body) => ??? case Blk(stmts) => - val ret = liftEntitiesNew(stmts) + val ret = liftEntities(stmts) (Blk(ret._1), ret._2) case lit: Lit => (lit, emptyCtx) case Inst(bod) => - val (trm, ctx) = liftTermNew(bod) + val (trm, ctx) = liftTerm(bod) (Inst(trm), ctx) case Forall(ps, bod) => - val (trm, ctx) = liftTermNew(bod) + val (trm, ctx) = liftTerm(bod) (Forall(ps, trm), ctx) case Where(bod, sts) => - val (bod2, ctx) = liftTermNew(bod) - val (sts2, ctx2) = liftEntitiesNew(sts) + val (bod2, ctx) = liftTerm(bod) + val (sts2, ctx2) = liftEntities(sts) (Where(bod2, sts2), ctx2) case _: Eqn | _: Super => ??? // TODO case patmat: AdtMatchWith => lastWords(s"Cannot liftTermNew ${patmat}") @@ -570,11 +570,11 @@ class ClassLifter(logDebugMsg: Boolean = false) { case Left(Lam(lhs@Tup(etts), rhs)) => val lctx = getFreeVars(lhs)(using emptyCtx, cache, globFuncs, None) val lret = liftTuple(lhs)(using ctx.addV(lctx.vSet)) - val ret = liftTermNew(rhs)(using ctx.addV(lctx.vSet).addT(tpVs)) + val ret = liftTerm(rhs)(using ctx.addV(lctx.vSet).addT(tpVs)) (func.copy(rhs = Left(Lam(lret._1, ret._1)))(func.declareLoc, func.virtualLoc, func.signature, func.outer, func.genField), ret._2 -+ lret._2) //TODO: Check correctness case Left(value) => // will be treated as Lam(Tup(Nil), rhs) - val ret = liftTermNew(value)(using ctx.addT(tpVs)) + val ret = liftTerm(value)(using ctx.addT(tpVs)) (func.copy(rhs = Left(Lam(Tup(Nil), ret._1)))(func.declareLoc, func.virtualLoc, func.signature, func.outer, func.genField), ret._2) //TODO: Check correctness case Right(PolyType(targs, body)) => val nBody = liftType(body)(using ctx.addT(tpVs)) @@ -597,12 +597,12 @@ class ClassLifter(logDebugMsg: Boolean = false) { val tmp = globFuncs.get(nm).get._2.vSet.toList.map(toFldsEle) val lctx = getFreeVars(lhs)(using emptyCtx, cache, globFuncs, None) val lret = liftTuple(lhs)(using ctx.addV(lctx.vSet) ++ globFuncs.get(nm).get._2, cache, globFuncs) - val ret = liftTermNew(rhs)(using ctx.addV(lctx.vSet) ++ globFuncs.get(nm).get._2, cache, globFuncs) + val ret = liftTerm(rhs)(using ctx.addV(lctx.vSet) ++ globFuncs.get(nm).get._2, cache, globFuncs) NuFunDef(rec, globFuncs.get(nm).get._1, N, nTpVs, Left(Lam(Tup(lret._1.fields ++ tmp), ret._1)))(N, N, N, N, true) //TODO: Use proper arguments case Left(rhs) => // will be treated as Lam(Tup(Nil), rhs) val tmp = globFuncs.get(nm).get._2.vSet.toList.map(toFldsEle) - val ret = liftTermNew(rhs)(using ctx ++ globFuncs.get(nm).get._2, cache, globFuncs) + val ret = liftTerm(rhs)(using ctx ++ globFuncs.get(nm).get._2, cache, globFuncs) NuFunDef(rec, globFuncs.get(nm).get._1, N, nTpVs, Left(Lam(Tup(tmp), ret._1)))(N, N, N, N, true) //TODO: Use proper arguments // val ret = liftTermNew(value)(using ctx.addV(nm) ++ globFuncs.get(nm).get._2, cache, globFuncs) // NuFunDef(rec, globFuncs.get(nm).get._1, nTpVs, Left(ret._1)) @@ -665,8 +665,8 @@ class ClassLifter(logDebugMsg: Boolean = false) { } - private def liftEntitiesNew(etts: List[Statement])(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (List[Statement], LocalContext) = { - log("liftEntitiesNew: " ++ etts.headOption.map(_.toString()).getOrElse("")) + private def liftEntities(etts: List[Statement])(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (List[Statement], LocalContext) = { + log("liftEntities: " ++ etts.headOption.map(_.toString()).getOrElse("")) val (newCls, newFuncs, rstTrms) = splitEntities(etts) val newClsNms = newCls.map(x => Var(x.nme.name)).toSet val newFuncNms = newFuncs.map(_.nme) @@ -689,9 +689,9 @@ class ClassLifter(logDebugMsg: Boolean = false) { refinedClsInfo.foreach((_, clsi) => completeClsInfo(clsi)(using newCache)) val newGlobalFuncs = refinedFuncInfo.map((nm, vs) => (Var(nm) -> (Var(genAnoName(nm)), vs))) - newCls.foreach(x => liftTypeDefNew(x)(using newCache, globFuncs ++ newGlobalFuncs)) + newCls.foreach(x => liftTypeDef(x)(using newCache, globFuncs ++ newGlobalFuncs)) (newFuncs zip refinedFuncInfo).foreach((f, c) => liftGlobalFunc(f)(using ctx, newCache, globFuncs ++ newGlobalFuncs)) - val (liftedTerms, termVs) = rstTrms.map(liftTermNew(_)(using ctx.addV(newFuncNms), newCache, globFuncs ++ newGlobalFuncs)).unzip + val (liftedTerms, termVs) = rstTrms.map(liftTerm(_)(using ctx.addV(newFuncNms), newCache, globFuncs ++ newGlobalFuncs)).unzip (liftedTerms, (termVs).fold(emptyCtx)(_ ++ _)) } @@ -705,7 +705,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { inners.addAll(refinedInfos) } - private def liftTypeDefNew(target: NuTypeDef)(using cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): Unit = { + private def liftTypeDef(target: NuTypeDef)(using cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): Unit = { def getAllInners(sups: Set[TypeName]): ClassCache = { sups.flatMap( t => cache.get(t).map(x => getAllInners(x.supClses) ++ x.innerClses) @@ -725,10 +725,10 @@ class ClassLifter(logDebugMsg: Boolean = false) { outer.map(x => List(toFldsEle(Var(genParName(x.liftedNm.name))))).getOrElse(Nil) ++ params.fold(Nil)(t => t.fields) ++ freeVs.vSet.map(toFldsEle) - val nPars = pars.map(liftTermNew(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip + val nPars = pars.map(liftTerm(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip val nFuncs = funcList.map(liftMemberFunc(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip - val nTerms = termList.map(liftTermNew(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip - clsList.foreach(x => liftTypeDefNew(x)(using nCache, globFuncs, nOuter)) + val nTerms = termList.map(liftTerm(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip + clsList.foreach(x => liftTypeDef(x)(using nCache, globFuncs, nOuter)) retSeq = retSeq.appended(NuTypeDef( kind, nName, nTps.map((None, _)), S(Tup(nParams)), None, None, nPars._1, None, None, TypingUnit(nFuncs._1 ++ nTerms._1))(None, None)) @@ -739,7 +739,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { log(s"lifting: \n${showStructure(rawUnit)}\n") retSeq = Nil globalFunctions.clear() - val re = liftEntitiesNew(rawUnit.entities)(using emptyCtx, Map(), Map(), None) + val re = liftEntities(rawUnit.entities)(using emptyCtx, Map(), Map(), None) log(s"freeVars: ${re._2}") // println(logOutput.toString()) TypingUnit(retSeq.toList ++ globalFunctions.toList ++ re._1) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala index b56845b4f..c47d9b7e0 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala @@ -76,7 +76,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: funDependence.addOne(func.name.name, Set()) } - private def getResult(exps: List[Expr]) = mlscript.compiler.Module(exps.concat[Expr | Item](funImpls.map(x => x._2._1)) + private def getResult(exps: List[Expr]) = mlscript.compiler.ModuleUnit(exps.concat[Expr | Item](funImpls.map(x => x._2._1)) .concat(allTypeImpls.values.map(x => x.copy(body = Isolation(Nil)))) .concat(lamTyDefs.values) .concat(anonymTyDefs.values) @@ -85,7 +85,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: /** * This function defunctionalizes the top-level `TypingUnit` into a `Module`. */ - def defunctionalize(tu: TypingUnit): Module = + def defunctionalize(tu: TypingUnit): ModuleUnit = // debug.trace("MONO MODL", PrettyPrinter.show(tu)) { val exps = tu.entities.zipWithIndex.flatMap[Expr] { case (term: Term, i) => @@ -191,7 +191,6 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: BoundedExpr(funImpls.get(name).get._4) } else { - debug.log("!!!!!!!") debug.log(s"calling unknown function $name(${args.mkString(",")})") debug.log(funImpls.keySet.toString()) BoundedExpr(UnknownValue()) @@ -303,7 +302,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: } else None }).headOption.getOrElse( - throw MonomorphError("Field not Found in"+obj.toString()) + throw MonomorphError(s"Field ${field} not Found in"+obj.toString()) ) } } diff --git a/compiler/shared/main/scala/mlscript/compiler/printer/ExprPrinter.scala b/compiler/shared/main/scala/mlscript/compiler/printer/ExprPrinter.scala index a9ede3ac3..6026a9ea0 100644 --- a/compiler/shared/main/scala/mlscript/compiler/printer/ExprPrinter.scala +++ b/compiler/shared/main/scala/mlscript/compiler/printer/ExprPrinter.scala @@ -1,13 +1,13 @@ package mlscript.compiler.printer -import mlscript.compiler.{Expr, Isolation, Item, Module, Parameter} +import mlscript.compiler.{Expr, Isolation, Item, ModuleUnit, Parameter} class ExprPrinter: private val printer = BlockPrinter() import printer.{endLine, enter, leave, print} - private def show(module: Module): Unit = module.items.foreach { + private def show(module: ModuleUnit): Unit = module.items.foreach { case expr: Expr => show(expr) case item: Item => show(item) } @@ -53,57 +53,20 @@ class ExprPrinter: override def toString(): String = printer.toString - // private def show(expr: Expr): Unit = expr match - // case Expr.Ref(name) => name - // case Expr.Lambda(params, body) => - // val head = params.mkString("(", ", ", ")") - // s"(fun $head -> $body)" - // case Expr.Apply(Expr.Apply(Expr.Ref("."), lhs :: Nil), rhs :: Nil) => - // s"$lhs.$rhs" - // case Expr.Apply(Expr.Apply(Expr.Ref(op), lhs :: Nil), rhs :: Nil) - // if !op.headOption.forall(_.isLetter) => - // s"($lhs $op $rhs)" - // case Expr.Apply(callee, arguments) => - // val tail = arguments.mkString(", ") - // s"($callee $tail)" - // case Expr.Tuple(fields) => - // val inner = fields.mkString(", ") - // "(" + (if fields.length == 1 then inner + ", " else inner) + ")" - // case Expr.Record(fields) => - // "{" + fields.iterator.map { (name, value) => s"$name = $value" } + "}" - // case Expr.Select(receiver, field) => s"$receiver.$field" - // case Expr.LetIn(isRec, name, rhs, body) => s"let $name = $rhs in $body" - // case Expr.Block(items) => items.mkString(";") - // case Expr.As(value, toType) => s"$value as $toType" - // case Expr.Assign(assignee, value) => s"$assignee = $value" - // case Expr.With(value, fields) => s"$value with $fields" - // case Expr.Subscript(receiver, index) => s"$receiver[$index]" - // case Expr.Match(scrutinee, branches) => - // s"$scrutinee match " + branches.iterator.mkString("{", "; ", "}") - // case Expr.Literal(value) => value.toString - // case Expr.New(Some((callee, args)), body) => - // s"new ${callee.name}" + args.mkString(" (", ", ", ") ") + body.toString - // case Expr.New(None, body) => "new " + body.toString - // case Expr.IfThenElse(condition, consequent, None) => - // s"if $condition then $consequent" - // case Expr.IfThenElse(condition, consequent, Some(alternate)) => - // s"if $condition then $consequent else $alternate" - // case Expr.Isolated(isolation) => s"{\n$isolation\n}" - object ExprPrinter: - def print(node: Module | Item | Isolation | Expr): String = + def print(node: ModuleUnit | Item | Isolation | Expr): String = val printer = ExprPrinter() node match - case module: Module => printer.show(module) + case module: ModuleUnit => printer.show(module) case item: Item => printer.show(item) case isolation: Isolation => printer.show(isolation) case expr: Expr => printer.show(expr) printer.toString - def printLines(node: Module | Item | Isolation | Expr): List[String] = + def printLines(node: ModuleUnit | Item | Isolation | Expr): List[String] = val printer = ExprPrinter() node match - case module: Module => printer.show(module) + case module: ModuleUnit => printer.show(module) case item: Item => printer.show(item) case isolation: Isolation => printer.show(isolation) case expr: Expr => printer.show(expr) diff --git a/compiler/shared/main/scala/mlscript/compiler/syntax.scala b/compiler/shared/main/scala/mlscript/compiler/syntax.scala index ce7496080..b7e205112 100644 --- a/compiler/shared/main/scala/mlscript/compiler/syntax.scala +++ b/compiler/shared/main/scala/mlscript/compiler/syntax.scala @@ -264,7 +264,7 @@ object Isolation: * This name conflicts with `java.lang.Module`. * TODO: Find a better name. */ -class Module(val items: List[Expr | Item]) extends Printable: +class ModuleUnit(val items: List[Expr | Item]) extends Printable: def getDebugOutput: DebugOutput = DebugOutput.Code(ExprPrinter.printLines(this)) diff --git a/compiler/shared/test/diff/LambLift.mls b/compiler/shared/test/diff/LambLift.mls index df3381f5d..5e5054efe 100644 --- a/compiler/shared/test/diff/LambLift.mls +++ b/compiler/shared/test/diff/LambLift.mls @@ -1,10 +1,10 @@ :NewDefs -:e // FIXME: Malformed Test? +:AllowRuntimeErrors fun foo() = let local(x) = class Foo { - fun bar = x + foo(x) + fun bar = x + foo() } (new Foo()).bar local(1) @@ -13,29 +13,11 @@ foo() //│ TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(), Blk(...))), App(Var(foo), Tup())) //│ Lifted: //│ TypingUnit { -//│ class Foo$1([x,]) {fun bar = () => +((this).x, foo$1((this).x,),)} +//│ class Foo$1([x,]) {fun bar = () => +((this).x, foo$1(),)} //│ let local$2 = (x,) => {('(' new Foo$1([x,]) {} ')').bar} //│ fun foo$1 = () => {local$2(1,)} //│ Code(List(foo$1())) //│ } -//│ ╔══[ERROR] Type mismatch in definition: -//│ ║ l.4: fun foo() = -//│ ║ ^^^^^^^ -//│ ║ l.5: let local(x) = -//│ ║ ^^^^^^^^^^^^^^^^ -//│ ║ l.6: class Foo { -//│ ║ ^^^^^^^^^^^^^^^ -//│ ║ l.7: fun bar = x + foo(x) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.8: } -//│ ║ ^^^^^ -//│ ║ l.9: (new Foo()).bar -//│ ║ ^^^^^^^^^^^^^^^^^^^ -//│ ║ l.10: local(1) -//│ ║ ^^^^^^^^^^ -//│ ╟── argument of type `[?a]` does not match type `[]` -//│ ║ l.7: fun bar = x + foo(x) -//│ ╙── ^^^ //│ fun foo: () -> Int //│ Int //│ res diff --git a/compiler/shared/test/diff/mono.mls b/compiler/shared/test/diff/mono.mls index 57d6fd32e..fede5cb0c 100644 --- a/compiler/shared/test/diff/mono.mls +++ b/compiler/shared/test/diff/mono.mls @@ -682,32 +682,37 @@ foo(l => (new Cons(2, l)).count()) //│ = 3 :mono -:e // FIXME: Malformed Test? -class E() { +class Exp() { + virtual fun derive(x: Int): Exp + virtual fun derive(x: Int) = Exp() + virtual fun isEmpty(): Bool + virtual fun isEmpty() = false +} +class E() extends Exp { fun derive(x) = new E fun isEmpty() = false } -class Ep(){ +class Ep() extends Exp { fun derive(x) = new E fun isEmpty() = true } -class Ch(i){ +class Ch(i: Int) extends Exp { fun derive(x) = if x == i then new Ep else new E fun isEmpty() = false } -class A(e1, e2){ +class A(e1: Exp, e2: Exp) extends Exp { fun derive(x) = new A(e1.derive(x), e2.derive(x)) fun isEmpty() = e1.isEmpty() || e2.isEmpty() } -class C(e1, e2){ +class C(e1: Exp, e2: Exp) extends Exp { fun derive(x) = if e1.isEmpty() then new A(new C(e1.derive(x), e2), e2.derive(x)) else new C(e1.derive(x), e2) fun isEmpty() = @@ -715,96 +720,93 @@ class C(e1, e2){ } (new C(new Ch(1), new A(new Ch(2), new Ch(3)))).derive(0).isEmpty() //│ Parsed: -//│ TypingUnit(NuTypeDef(class, E, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ep, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ch, (), Tup(_: Var(i)), (), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, A, (), Tup(_: Var(e1), _: Var(e2)), (), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, C, (), Tup(_: Var(e1), _: Var(e2)), (), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), App(Sel(App(Sel(Bra(rcd = false, New(Some((TypeName(C),[new Ch([1,]) {}, new A([new Ch([2,]) {}, new Ch([3,]) {},]) {},])), TypingUnit())), derive), Tup(_: IntLit(0))), isEmpty), Tup())) +//│ TypingUnit(NuTypeDef(class, Exp, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, derive, None, [], PolyType(List(),Function(Tuple(List((Some(x),Field(None,TypeName(Int))))),TypeName(Exp)))), NuFunDef(None, derive, None, [], Lam(Tup(x: Var(Int)), App(Var(Exp), Tup()))), NuFunDef(None, isEmpty, None, [], PolyType(List(),Function(Tuple(List()),TypeName(Bool)))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Var(false))))), NuTypeDef(class, E, (), Tup(), (Var(Exp)), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ep, (), Tup(), (Var(Exp)), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, Ch, (), Tup(i: Var(Int)), (Var(Exp)), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, A, (), Tup(e1: Var(Exp), e2: Var(Exp)), (Var(Exp)), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), NuTypeDef(class, C, (), Tup(e1: Var(Exp), e2: Var(Exp)), (Var(Exp)), None, None, TypingUnit(NuFunDef(None, derive, None, [], Lam(Tup(_: Var(x)), Blk(...))), NuFunDef(None, isEmpty, None, [], Lam(Tup(), Blk(...))))), App(Sel(App(Sel(Bra(rcd = false, New(Some((TypeName(C),[new Ch([1,]) {}, new A([new Ch([2,]) {}, new Ch([3,]) {},]) {},])), TypingUnit())), derive), Tup(_: IntLit(0))), isEmpty), Tup())) //│ Lifted: //│ TypingUnit { -//│ class E$1([]) { -//│ fun derive = (x,) => {new E$1([]) {}} +//│ class Exp$1([]) { +//│ fun derive = (x: Int) -> Exp$1 +//│ fun derive = (x: Int,) => Exp$1() +//│ fun isEmpty = () -> Bool +//│ fun isEmpty = () => false +//│ } +//│ class E$2([]): Exp$1() { +//│ fun derive = (x,) => {new E$2([]) {}} //│ fun isEmpty = () => {false} //│ } -//│ class Ep$2([]) { -//│ fun derive = (x,) => {new E$1([]) {}} +//│ class Ep$3([]): Exp$1() { +//│ fun derive = (x,) => {new E$2([]) {}} //│ fun isEmpty = () => {true} //│ } -//│ class Ch$3([i,]) { -//│ fun derive = (x,) => {if (==(x, (this).i,)) then new Ep$2([]) {} else new E$1([]) {}} +//│ class Ch$4([i: Int,]): Exp$1() { +//│ fun derive = (x,) => {if (==(x, (this).i,)) then new Ep$3([]) {} else new E$2([]) {}} //│ fun isEmpty = () => {false} //│ } -//│ class A$4([e1, e2,]) { -//│ fun derive = (x,) => {new A$4([((this).e1).derive(x,), ((this).e2).derive(x,),]) {}} +//│ class A$5([e1: Exp, e2: Exp,]): Exp$1() { +//│ fun derive = (x,) => {new A$5([((this).e1).derive(x,), ((this).e2).derive(x,),]) {}} //│ fun isEmpty = () => {||(((this).e1).isEmpty(), ((this).e2).isEmpty(),)} //│ } -//│ class C$5([e1, e2,]) { -//│ fun derive = (x,) => {if (((this).e1).isEmpty()) then new A$4([new C$5([((this).e1).derive(x,), (this).e2,]) {}, ((this).e2).derive(x,),]) {} else new C$5([((this).e1).derive(x,), (this).e2,]) {}} +//│ class C$6([e1: Exp, e2: Exp,]): Exp$1() { +//│ fun derive = (x,) => {if (((this).e1).isEmpty()) then new A$5([new C$6([((this).e1).derive(x,), (this).e2,]) {}, ((this).e2).derive(x,),]) {} else new C$6([((this).e1).derive(x,), (this).e2,]) {}} //│ fun isEmpty = () => {&&(((this).e1).isEmpty(), ((this).e2).isEmpty(),)} //│ } -//│ Code(List((('(' new C$5([new Ch$3([1,]) {}, new A$4([new Ch$3([2,]) {}, new Ch$3([3,]) {},]) {},]) {} ')').derive(0,)).isEmpty())) +//│ Code(List((('(' new C$6([new Ch$4([1,]) {}, new A$5([new Ch$4([2,]) {}, new Ch$4([3,]) {},]) {},]) {} ')').derive(0,)).isEmpty())) //│ } //│ Mono: //│ //│ Defunc result: -//│ main$$5() -//│ fun isEmpty$C$5(this) = -//│ &&(this.e1 match {case obj: Ep$2 => isEmpty$Ep$2(obj); case obj: E$1 => isEmpty$E$1(obj)}, this.e2 match {case obj: A$4 => isEmpty$A$4(obj)}) -//│ fun isEmpty$Ch$3(this) = +//│ main$$6() +//│ fun isEmpty$E$2(this) = //│ false -//│ fun isEmpty$E$1(this) = +//│ fun isEmpty$A$5(this) = +//│ ||(this.e1 match {case obj: Ch$4 => isEmpty$Ch$4(obj)}, this.e2 match {case obj: Ch$4 => isEmpty$Ch$4(obj)}) +//│ fun isEmpty$Ch$4(this) = //│ false -//│ fun isEmpty$A$4(this) = -//│ ||(this.e1 match {case obj: Ch$3 => isEmpty$Ch$3(obj)}, this.e2 match {case obj: Ch$3 => isEmpty$Ch$3(obj)}) -//│ fun derive$A$4(this, x) = -//│ new A$4 (this.e1 match {case obj: Ch$3 => derive$Ch$3(obj, x)}, this.e2 match {case obj: Ch$3 => derive$Ch$3(obj, x)}) -//│ fun derive$C$5(this, x) = -//│ if this.e1 match {case obj: Ch$3 => isEmpty$Ch$3(obj)} then new A$4 (new C$5 (this.e1 match {case obj: Ch$3 => derive$Ch$3(obj, x)}, this.e2) , this.e2 match {case obj: A$4 => derive$A$4(obj, x)}) else new C$5 (this.e1 match {case obj: Ch$3 => derive$Ch$3(obj, x)}, this.e2) -//│ fun derive$Ch$3(this, x) = -//│ if ==(x, this.i) then new Ep$2 () else new E$1 () -//│ fun main$$5() = -//│ new C$5 (new Ch$3 (#1) , new A$4 (new Ch$3 (#2) , new Ch$3 (#3) ) ) match {case obj: C$5 => derive$C$5(obj, #0)} match {case obj: C$5 => isEmpty$C$5(obj)} -//│ fun isEmpty$Ep$2(this) = +//│ fun derive$A$5(this, x) = +//│ new A$5 (this.e1 match {case obj: Ch$4 => derive$Ch$4(obj, x)}, this.e2 match {case obj: Ch$4 => derive$Ch$4(obj, x)}) +//│ fun isEmpty$C$6(this) = +//│ &&(this.e1 match {case obj: Ep$3 => isEmpty$Ep$3(obj); case obj: E$2 => isEmpty$E$2(obj)}, this.e2 match {case obj: A$5 => isEmpty$A$5(obj)}) +//│ fun derive$C$6(this, x) = +//│ if this.e1 match {case obj: Ch$4 => isEmpty$Ch$4(obj)} then new A$5 (new C$6 (this.e1 match {case obj: Ch$4 => derive$Ch$4(obj, x)}, this.e2) , this.e2 match {case obj: A$5 => derive$A$5(obj, x)}) else new C$6 (this.e1 match {case obj: Ch$4 => derive$Ch$4(obj, x)}, this.e2) +//│ fun main$$6() = +//│ new C$6 (new Ch$4 (#1) , new A$5 (new Ch$4 (#2) , new Ch$4 (#3) ) ) match {case obj: C$6 => derive$C$6(obj, #0)} match {case obj: C$6 => isEmpty$C$6(obj)} +//│ fun derive$Ch$4(this, x) = +//│ if ==(x, this.i) then new Ep$3 () else new E$2 () +//│ fun isEmpty$Ep$3(this) = //│ true -//│ class A$4(e1, e2) { +//│ class A$5(e1, e2): Exp$1() { //│ } -//│ class E$1() { +//│ class E$2(): Exp$1() { //│ } -//│ class C$5(e1, e2) { +//│ class C$6(e1, e2): Exp$1() { //│ } -//│ class Ep$2() { +//│ class Ch$4(i): Exp$1() { //│ } -//│ class Ch$3(i) { +//│ class Ep$3(): Exp$1() { //│ } -//│ ╔══[ERROR] Class parameters currently need type annotations -//│ ║ l.698: class Ch(i){ -//│ ╙── ^ -//│ ╔══[ERROR] Class parameters currently need type annotations -//│ ║ l.704: class A(e1, e2){ -//│ ╙── ^^ -//│ ╔══[ERROR] Class parameters currently need type annotations -//│ ║ l.704: class A(e1, e2){ -//│ ╙── ^^ -//│ ╔══[ERROR] Class parameters currently need type annotations -//│ ║ l.710: class C(e1, e2){ -//│ ╙── ^^ -//│ ╔══[ERROR] Class parameters currently need type annotations -//│ ║ l.710: class C(e1, e2){ -//│ ╙── ^^ -//│ class E() { +//│ class Exp$1() { +//│ } +//│ class Exp() { +//│ fun derive: (x: Int) -> Exp +//│ fun isEmpty: () -> Bool +//│ } +//│ class E() extends Exp { //│ fun derive: anything -> E //│ fun isEmpty: () -> false //│ } -//│ class Ep() { +//│ class Ep() extends Exp { //│ fun derive: anything -> E //│ fun isEmpty: () -> true //│ } -//│ class Ch(i: error) { +//│ class Ch(i: Int) extends Exp { //│ fun derive: Num -> (E | Ep) //│ fun isEmpty: () -> false //│ } -//│ class A(e1: error, e2: error) { -//│ fun derive: anything -> A +//│ class A(e1: Exp, e2: Exp) extends Exp { +//│ fun derive: Int -> A //│ fun isEmpty: () -> Bool //│ } -//│ class C(e1: error, e2: error) { -//│ fun derive: anything -> (A | C) +//│ class C(e1: Exp, e2: Exp) extends Exp { +//│ fun derive: Int -> (A | C) //│ fun isEmpty: () -> Bool //│ } //│ Bool @@ -813,42 +815,45 @@ class C(e1, e2){ :mono -:e // FIXME: Malformed Test? +val anyUnknown = false class List(l: List | Nil, hasTail: Bool) {} class Nil(hasTail: Bool) {} fun gen() = if anyUnknown then new List(gen(), true) else new Nil(false) gen() //│ Parsed: -//│ TypingUnit(NuTypeDef(class, List, (), Tup(l: App(Var(|), Tup(_: Var(List), _: Var(Nil))), hasTail: Var(Bool)), (), None, None, TypingUnit()), NuTypeDef(class, Nil, (), Tup(hasTail: Var(Bool)), (), None, None, TypingUnit()), NuFunDef(None, gen, None, [], Lam(Tup(), Blk(...))), App(Var(gen), Tup())) +//│ TypingUnit(NuFunDef(Some(false), anyUnknown, None, [], Var(false)), NuTypeDef(class, List, (), Tup(l: App(Var(|), Tup(_: Var(List), _: Var(Nil))), hasTail: Var(Bool)), (), None, None, TypingUnit()), NuTypeDef(class, Nil, (), Tup(hasTail: Var(Bool)), (), None, None, TypingUnit()), NuFunDef(None, gen, None, [], Lam(Tup(), Blk(...))), App(Var(gen), Tup())) //│ Lifted: //│ TypingUnit { //│ class List$1([l: |(List, Nil,), hasTail: Bool,]) {} //│ class Nil$2([hasTail: Bool,]) {} +//│ let anyUnknown$2 = () => false //│ fun gen$1 = () => {if (anyUnknown) then new List$1([gen$1(), true,]) {} else new Nil$2([false,]) {}} //│ Code(List(gen$1())) //│ } //│ Mono: //│ //│ Defunc result: -//│ main$$3() +//│ main$$4() +//│ fun anyUnknown$2() = +//│ false //│ fun gen$1() = //│ if anyUnknown then new List$1 (gen$1(), true) else new Nil$2 (false) -//│ fun main$$3() = +//│ fun main$$4() = //│ gen$1() //│ class Nil$2(hasTail) { //│ } //│ class List$1(l, hasTail) { //│ } -//│ ╔══[ERROR] identifier not found: anyUnknown -//│ ║ l.820: if anyUnknown then new List(gen(), true) else new Nil(false) -//│ ╙── ^^^^^^^^^^ +//│ val anyUnknown: false //│ class List(l: List | Nil, hasTail: Bool) //│ class Nil(hasTail: Bool) //│ fun gen: () -> (List | Nil) //│ List | Nil -//│ Code generation encountered an error: -//│ unresolved symbol anyUnknown +//│ anyUnknown +//│ = false +//│ res +//│ = Nil {} @@ -1017,9 +1022,9 @@ class OneBool(b: Bool){ //│ = true :mono -:e // FIXME: Malformed Test? -class Bar(x: int) { - fun FooMinus(y: int) = x + y +class Bar(x: Int) { + fun foo(x) = x + fun FooMinus(y: Int) = x + y fun car = foo(2) } class Car { @@ -1028,21 +1033,22 @@ class Car { fun baz(b: Bar) = b.foo(2) let bar = Bar(42) baz(bar) -Car().da(Bar(1337)) +(new Car()).da(Bar(1337)) bar.car //│ Parsed: -//│ TypingUnit(NuTypeDef(class, Bar, (), Tup(x: Var(int)), (), None, None, TypingUnit(NuFunDef(None, FooMinus, None, [], Lam(Tup(y: Var(int)), App(Var(+), Tup(_: Var(x), _: Var(y))))), NuFunDef(None, car, None, [], App(Var(foo), Tup(_: IntLit(2)))))), NuTypeDef(class, Car, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, da, None, [], Lam(Tup(b: Var(Bar)), App(Sel(Var(b), foo), Tup(_: IntLit(2))))))), NuFunDef(None, baz, None, [], Lam(Tup(b: Var(Bar)), App(Sel(Var(b), foo), Tup(_: IntLit(2))))), NuFunDef(Some(false), bar, None, [], App(Var(Bar), Tup(_: IntLit(42)))), App(Var(baz), Tup(_: Var(bar))), App(Sel(App(Var(Car), Tup()), da), Tup(_: App(Var(Bar), Tup(_: IntLit(1337))))), Sel(Var(bar), car)) +//│ TypingUnit(NuTypeDef(class, Bar, (), Tup(x: Var(Int)), (), None, None, TypingUnit(NuFunDef(None, foo, None, [], Lam(Tup(_: Var(x)), Var(x))), NuFunDef(None, FooMinus, None, [], Lam(Tup(y: Var(Int)), App(Var(+), Tup(_: Var(x), _: Var(y))))), NuFunDef(None, car, None, [], App(Var(foo), Tup(_: IntLit(2)))))), NuTypeDef(class, Car, (), Tup(), (), None, None, TypingUnit(NuFunDef(None, da, None, [], Lam(Tup(b: Var(Bar)), App(Sel(Var(b), foo), Tup(_: IntLit(2))))))), NuFunDef(None, baz, None, [], Lam(Tup(b: Var(Bar)), App(Sel(Var(b), foo), Tup(_: IntLit(2))))), NuFunDef(Some(false), bar, None, [], App(Var(Bar), Tup(_: IntLit(42)))), App(Var(baz), Tup(_: Var(bar))), App(Sel(Bra(rcd = false, New(Some((TypeName(Car),[])), TypingUnit())), da), Tup(_: App(Var(Bar), Tup(_: IntLit(1337))))), Sel(Var(bar), car)) //│ Lifted: //│ TypingUnit { -//│ class Bar$1([x: int,]) { -//│ fun FooMinus = (y: int,) => +((this).x, y,) -//│ fun car = () => foo(2,) +//│ class Bar$1([x: Int,]) { +//│ fun foo = (x,) => x +//│ fun FooMinus = (y: Int,) => +((this).x, y,) +//│ fun car = () => (this).foo(2,) //│ } //│ class Car$2([]) {fun da = (b: Bar$1,) => (b).foo(2,)} //│ fun baz$2 = (b: Bar$1,) => (b).foo(2,) //│ let bar$1 = () => Bar$1(42,) //│ Code(List(baz$2(bar,))) -//│ Code(List((Car$2()).da(Bar$1(1337,),))) +//│ Code(List(('(' new Car$2([]) {} ')').da(Bar$1(1337,),))) //│ Code(List((bar).car)) //│ } //│ Mono: @@ -1053,88 +1059,40 @@ bar.car //│ main$$6() //│ fun bar$1() = //│ Bar$1(#42) +//│ fun da$Car$2(this, b) = +//│ b match {} //│ fun main$$6() = //│ bar.car //│ fun baz$2(b) = //│ b match {} //│ fun main$$5() = -//│ Car$2() match {} +//│ new Car$2 () match {case obj: Car$2 => da$Car$2(obj, Bar$1(#1337))} //│ fun main$$4() = //│ baz$2(bar) //│ class Bar$1(x) { //│ } //│ class Car$2() { //│ } -//│ ╔══[ERROR] Type mismatch in operator application: -//│ ║ l.1022: fun FooMinus(y: int) = x + y -//│ ║ ^^^^^ -//│ ╟── type `int` is not an instance of `Int` -//│ ║ l.1021: class Bar(x: int) { -//│ ║ ^^^ -//│ ╟── but it flows into reference with expected type `Int` -//│ ║ l.1022: fun FooMinus(y: int) = x + y -//│ ╙── ^ -//│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.1023: fun car = foo(2) -//│ ║ ^^^^^^ -//│ ╟── integer literal of type `2` is not a function -//│ ║ l.1023: fun car = foo(2) -//│ ║ ^ -//│ ╟── Note: constraint arises from application: -//│ ║ l.624: x(new Cons(1, new Nil())) + x(new Nil()) -//│ ║ ^^^^^^^^^^^^ -//│ ╟── from reference: -//│ ║ l.624: x(new Cons(1, new Nil())) + x(new Nil()) -//│ ╙── ^ -//│ ╔══[ERROR] Type `Bar` does not contain member `foo` -//│ ║ l.1026: fun da(b: Bar) = b.foo(2) -//│ ╙── ^^^^ -//│ ╔══[ERROR] Type `Bar` does not contain member `foo` -//│ ║ l.1028: fun baz(b: Bar) = b.foo(2) -//│ ╙── ^^^^ -//│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.1029: let bar = Bar(42) -//│ ║ ^^^^^^^ -//│ ╟── integer literal of type `42` is not an instance of type `int` -//│ ║ l.1029: let bar = Bar(42) -//│ ║ ^^ -//│ ╟── Note: constraint arises from type reference: -//│ ║ l.1021: class Bar(x: int) { -//│ ╙── ^^^ -//│ ╔══[ERROR] Construction of unparameterized class Car should use the `new` keyword -//│ ║ l.1031: Car().da(Bar(1337)) -//│ ╙── ^^^ -//│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.1031: Car().da(Bar(1337)) -//│ ║ ^^^^^^^^^ -//│ ╟── integer literal of type `1337` is not an instance of type `int` -//│ ║ l.1031: Car().da(Bar(1337)) -//│ ║ ^^^^ -//│ ╟── Note: constraint arises from type reference: -//│ ║ l.1021: class Bar(x: int) { -//│ ╙── ^^^ -//│ class Bar(x: int) { -//│ fun FooMinus: (y: int) -> (Int | error) -//│ fun car: Int | error +//│ class Bar(x: Int) { +//│ fun FooMinus: (y: Int) -> Int +//│ fun car: 2 +//│ fun foo: forall 'a. 'a -> 'a //│ } //│ class Car { //│ constructor() -//│ fun da: (b: Bar) -> error +//│ fun da: (b: Bar) -> 2 //│ } -//│ fun baz: (b: Bar) -> error -//│ let bar: Bar | error -//│ Int | error +//│ fun baz: (b: Bar) -> 2 +//│ let bar: Bar +//│ 2 //│ bar //│ = Bar {} //│ res -//│ Runtime error: -//│ TypeError: b.foo is not a function +//│ = 2 //│ res -//│ Runtime error: -//│ TypeError: Class constructor Car cannot be invoked without 'new' +//│ = 2 //│ res -//│ Runtime error: -//│ TypeError: x is not a function +//│ = 2 :mono val c = 5 From 50fce34c1cdb14a83458391206c66b398719eee4 Mon Sep 17 00:00:00 2001 From: HarrisL2 Date: Wed, 11 Oct 2023 20:56:53 +0800 Subject: [PATCH 12/13] Fix malformed test --- compiler/shared/test/diff/mono.mls | 61 ++++++++++++------------------ 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/compiler/shared/test/diff/mono.mls b/compiler/shared/test/diff/mono.mls index fede5cb0c..5116e6600 100644 --- a/compiler/shared/test/diff/mono.mls +++ b/compiler/shared/test/diff/mono.mls @@ -237,59 +237,46 @@ fac(2) //│ = 2 :mono -:e // FIXME: Malformed Test? -class List(l, hasTail) {} -class Nil(l, hasTail) {} +class List(val l: List | Nil | undefined, val hasTail: Bool) {} +class Nil(val l: List | Nil | undefined, val hasTail: Bool) {} fun count(lst) = - if lst.hasTail then count(lst.l)+1 else 1 -count(new List(new List(new Nil(0, false), true), true)) + if lst.hasTail then + let l = lst.l + if l is undefined then 1 else count(l)+1 + else 0 +count(new List(new List(new Nil(undefined, false), true), true)) //│ Parsed: -//│ TypingUnit(NuTypeDef(class, List, (), Tup(_: Var(l), _: Var(hasTail)), (), None, None, TypingUnit()), NuTypeDef(class, Nil, (), Tup(_: Var(l), _: Var(hasTail)), (), None, None, TypingUnit()), NuFunDef(None, count, None, [], Lam(Tup(_: Var(lst)), Blk(...))), App(Var(count), Tup(_: New(Some((TypeName(List),[new List([new Nil([0, false,]) {}, true,]) {}, true,])), TypingUnit())))) +//│ TypingUnit(NuTypeDef(class, List, (), Tup(l: App(Var(|), Tup(_: App(Var(|), Tup(_: Var(List), _: Var(Nil))), _: UnitLit(true))), hasTail: Var(Bool)), (), None, None, TypingUnit()), NuTypeDef(class, Nil, (), Tup(l: App(Var(|), Tup(_: App(Var(|), Tup(_: Var(List), _: Var(Nil))), _: UnitLit(true))), hasTail: Var(Bool)), (), None, None, TypingUnit()), NuFunDef(None, count, None, [], Lam(Tup(_: Var(lst)), Blk(...))), App(Var(count), Tup(_: New(Some((TypeName(List),[new List([new Nil([undefined, false,]) {}, true,]) {}, true,])), TypingUnit())))) //│ Lifted: //│ TypingUnit { -//│ class List$1([l, hasTail,]) {} -//│ class Nil$2([l, hasTail,]) {} -//│ fun count$1 = (lst,) => {if ((lst).hasTail) then +(count$1((lst).l,), 1,) else 1} -//│ Code(List(count$1(new List$1([new List$1([new Nil$2([0, false,]) {}, true,]) {}, true,]) {},))) +//│ class List$1([val l: |(|(List, Nil,), undefined,), val hasTail: Bool,]) {} +//│ class Nil$2([val l: |(|(List, Nil,), undefined,), val hasTail: Bool,]) {} +//│ let l$2 = (lst,) => (lst).l +//│ fun count$1 = (lst,) => {if ((lst).hasTail) then {if (is(l, undefined,)) then 1 else +(count$1(l,), 1,)} else 0} +//│ Code(List(count$1(new List$1([new List$1([new Nil$2([undefined, false,]) {}, true,]) {}, true,]) {},))) //│ } //│ Mono: //│ //│ Defunc result: -//│ main$$3() +//│ main$$4() +//│ fun l$2(lst) = +//│ lst.l //│ fun count$1(lst) = -//│ if lst.hasTail then +(count$1(lst.l), #1) else #1 -//│ fun main$$3() = -//│ count$1(new List$1 (new List$1 (new Nil$2 (#0, false) , true) , true) ) +//│ if lst.hasTail then if is(l, #()) then #1 else +(count$1(l), #1) else #0 +//│ fun main$$4() = +//│ count$1(new List$1 (new List$1 (new Nil$2 (#(), false) , true) , true) ) //│ class Nil$2(l, hasTail) { //│ } //│ class List$1(l, hasTail) { //│ } -//│ ╔══[ERROR] Class parameters currently need type annotations -//│ ║ l.241: class List(l, hasTail) {} -//│ ╙── ^ -//│ ╔══[ERROR] Class parameters currently need type annotations -//│ ║ l.241: class List(l, hasTail) {} -//│ ╙── ^^^^^^^ -//│ ╔══[ERROR] Class parameters currently need type annotations -//│ ║ l.242: class Nil(l, hasTail) {} -//│ ╙── ^ -//│ ╔══[ERROR] Class parameters currently need type annotations -//│ ║ l.242: class Nil(l, hasTail) {} -//│ ╙── ^^^^^^^ -//│ ╔══[ERROR] Parameter 'l' cannot tbe accessed as a field -//│ ║ l.244: if lst.hasTail then count(lst.l)+1 else 1 -//│ ║ ^^ -//│ ╟── Either make the parameter a `val` or access it through destructuring -//│ ║ l.241: class List(l, hasTail) {} -//│ ╙── ^ -//│ class List(l: error, hasTail: error) -//│ class Nil(l: error, hasTail: error) +//│ class List(l: List | Nil | (), hasTail: Bool) +//│ class Nil(l: List | Nil | (), hasTail: Bool) //│ fun count: forall 'a. 'a -> Int -//│ Int | error +//│ Int //│ where -//│ 'a <: {hasTail: Object, l: 'a} +//│ 'a <: {hasTail: Object, l: Object & 'a & ~() | ()} //│ res -//│ = 1 +//│ = 2 //:mono //class Cons(e, tail){ From 6068f59428c9947eabb62a903f7de15c14b0f04e Mon Sep 17 00:00:00 2001 From: HarrisL2 Date: Wed, 11 Oct 2023 23:51:22 +0800 Subject: [PATCH 13/13] Change unimplemented to throw error with info --- .../scala/mlscript/compiler/ClassLifter.scala | 18 +++++++------- .../scala/mlscript/compiler/Helpers.scala | 8 +++---- .../mlscript/compiler/mono/Monomorph.scala | 8 +++---- .../mono/specializer/BoundedExpr.scala | 3 ++- .../mono/specializer/Specializer.scala | 24 +++++++++---------- 5 files changed, 31 insertions(+), 30 deletions(-) diff --git a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala index d552b2ae7..5c0c8da40 100644 --- a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala +++ b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala @@ -250,7 +250,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { val nE = liftTerm(expr) val nR = liftTerm(rhs) (IfThen(nE._1, nR._1), nE._2 ++ nR._2) - case _ => ??? + case _ => throw MonomorphError(s"Unknown IfBody: ${body}") } private def liftTuple(tup: Tup)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Tup, LocalContext) = { @@ -380,7 +380,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { case Sel(receiver, fieldName) => val nRec = liftTerm(receiver) (Sel(nRec._1, fieldName), nRec._2) - case Splc(fields) => ??? + case Splc(fields) => throw MonomorphError(s"Unimplemented liftTerm: ${target}") case Subs(arr, idx) => val (ltrm, lctx) = liftTerm(arr) val (rtrm, rctx) = liftTerm(idx) @@ -393,7 +393,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { val ret = liftTerm(lhs) val nTs = targs.map(liftType).unzip (TyApp(ret._1, nTs._1), nTs._2.fold(ret._2)(_ ++ _)) - case With(trm, fields) => ??? + case With(trm, fields) => throw MonomorphError(s"Unimplemented liftTerm: ${target}") case New(Some((t: TypeName, prm: Tup)), TypingUnit(Nil)) => val ret = liftConstr(t, prm) (New(Some((ret._1, ret._2)), TypingUnit(Nil)), ret._3) @@ -413,7 +413,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { val nSta = New(Some((nTpNm, Tup(Nil))), TypingUnit(Nil)) val ret = liftEntities(List(anoCls, nSta)) (Blk(ret._1), ret._2) - case New(head, body) => ??? + case New(head, body) => throw MonomorphError(s"Unimplemented liftTerm: ${target}") case Blk(stmts) => val ret = liftEntities(stmts) (Blk(ret._1), ret._2) @@ -428,7 +428,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { val (bod2, ctx) = liftTerm(bod) val (sts2, ctx2) = liftEntities(sts) (Where(bod2, sts2), ctx2) - case _: Eqn | _: Super => ??? // TODO + case _: Eqn | _: Super => throw MonomorphError(s"Unimplemented liftTerm: ${target}") // TODO case patmat: AdtMatchWith => lastWords(s"Cannot liftTermNew ${patmat}") } @@ -465,7 +465,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { ((v, Fld(flags, tmp._1)), tmp._2) }.unzip (Rcd(ret._1), ret._2.fold(emptyCtx)(_ ++ _)) - case _ => ??? + case _ => throw MonomorphError(s"Unimplemented liftTermAsType: ${target}") } private def liftTypeName(target: TypeName)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (TypeName, LocalContext) = { @@ -559,7 +559,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { val (body2, ctx) = liftType(body) PolyType(targs, body2) -> ctx case Top | Bot | _: Literal | _: TypeTag | _: TypeVar => target.asInstanceOf[Type] -> emptyCtx - case _: Selection => ??? // TODO + case _: Selection => throw MonomorphError(s"Unimplemented liftType: ${target}") // TODO } @@ -584,7 +584,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { }.unzip (func.copy(rhs = Right(PolyType(nTargs._1, nBody._1)))(func.declareLoc, func.virtualLoc, func.signature, func.outer, func.genField), nTargs._2.fold(nBody._2)(_ ++ _)) - case _ => ??? // TODO + case _ => throw MonomorphError(s"Unimplemented liftMemberFunc: ${func}") // TODO } } @@ -614,7 +614,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { case (tn, ctx) => (L(tn), ctx) case R(tv) => R(tv) -> emptyCtx}).unzip NuFunDef(rec, globFuncs.get(nm).get._1, N, nTpVs, Right(PolyType(nTargs._1, nBody._1)))(N, N, N, N, true) //TODO: Use proper arguments - case _ => ??? + case _ => throw MonomorphError(s"Unimplemented liftGlobalFunc: ${func}") }) } diff --git a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala index 8fec8de09..a49bd85bd 100644 --- a/compiler/shared/main/scala/mlscript/compiler/Helpers.scala +++ b/compiler/shared/main/scala/mlscript/compiler/Helpers.scala @@ -75,7 +75,7 @@ object Helpers: Expr.LetIn(rec, Expr.Ref(name), exprRhs, exprBody) case Blk(stmts) => Expr.Block(stmts.flatMap[Expr | Item.FuncDecl | Item.FuncDefn] { case term: Term => Some(term2Expr(term)) - case tyDef: NuTypeDef => ??? + case tyDef: NuTypeDef => throw MonomorphError(s"Unimplemented term2Expr ${term}") case funDef: NuFunDef => val NuFunDef(_, nme, sn, targs, rhs) = funDef val ret: Item.FuncDecl | Item.FuncDefn = rhs match @@ -122,7 +122,7 @@ object Helpers: case Assign(lhs, rhs) => Expr.Assign(term2Expr(lhs), term2Expr(rhs)) case New(None, body) => - ??? + throw MonomorphError(s"Unimplemented term2Expr ${term}") case New(Some((constructor, args)), body) => val typeName = constructor match case AppliedType(TypeName(name), _) => name @@ -165,7 +165,7 @@ object Helpers: // Question: Will there be pure terms in class body? case term: Term => Some(term2Expr(term)) - case subTypeDef: NuTypeDef => ??? + case subTypeDef: NuTypeDef => throw MonomorphError(s"Unimplemented func2Item ${tyDef}") case subFunDef: NuFunDef => Some(func2Item(subFunDef)) case term => throw MonomorphError(term.toString) @@ -193,4 +193,4 @@ object Helpers: case Als => TypeDeclKind.Alias case Cls => TypeDeclKind.Class case Trt => TypeDeclKind.Trait - case _ => ??? + case _ => throw MonomorphError(s"Unsupported TypeDefKind conversion ${kind}") diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala index c47d9b7e0..fde9c93ed 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/Monomorph.scala @@ -106,7 +106,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: addNewFunction(funcDecl) case _ => () None - case _ => ??? + case (other, _) => throw MonomorphError(s"Unknown Statement in TypingUnit: ${other}") }; debug.log(getResult(exps).getDebugOutput.toLines(using false).mkString("\n")) while(!evalQueue.isEmpty){ @@ -159,7 +159,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: None case funDef: NuFunDef => Some(func2Item(funDef)) - case _ => ??? + case other => throw MonomorphError(s"Unknown Statement in TypingUnit: ${other}") }) }(identity) @@ -265,7 +265,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: ret.fields.addAll(parObjs) ret } - else ??? + else throw MonomorphError(s"tpName ${tpName} not found in implementations ${allTypeImpls}") }(identity) def getFieldVal(obj: ObjectValue, field: String): BoundedExpr = @@ -307,7 +307,7 @@ class Monomorph(debug: Debug = DummyDebug) extends DataTypeInferer: } } else { - ??? + throw MonomorphError(s"ObjectValue ${obj} not found in implementations ${allTypeImpls}") } }(identity) diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala index 9f14742db..fc60c04da 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/BoundedExpr.scala @@ -7,6 +7,7 @@ import scala.collection.mutable.Map as MutMap import scala.collection.mutable.Set as MutSet import mlscript.Var import scala.collection.immutable +import mlscript.compiler.mono.MonomorphError abstract class MonoValue { def toBoundedExpr = BoundedExpr(this) @@ -158,7 +159,7 @@ class BoundedExpr(private val values: Set[MonoValue]) extends Printable { // val map2 = other.values.flatMap(x => if(values.fin(x)) then None else Some(x)) val ret = mergingValNms.map(nm => (mergingVals1.get(nm), mergingVals2.get(nm)) match case (Some(x1: ObjectValue), Some(x2: ObjectValue)) => x1.merge(x2)(using instackExps ++ Set(this.hashCode(), other.hashCode())) - case _ => ??? + case _ => throw MonomorphError(s"Name ${nm} not found in BoundedExpr merging") ) // println(s"get ${BoundedExpr(restVals1 ++ restVals2 ++ ret)}") var ret2 = restVals1 ++ restVals2 diff --git a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala index e7622a8d6..6a8adea77 100644 --- a/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala +++ b/compiler/shared/main/scala/mlscript/compiler/mono/specializer/Specializer.scala @@ -37,7 +37,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ retExp.expValue = BoundedExpr(pairedAV) retExp } - else ??? + else throw MonomorphError(s"Malformed Expr: ${rawExpr}") case other@Expr.Apply(callee, arguments) => val calE = evaluate(callee) @@ -128,18 +128,18 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ retExp case self@Expr.Lambda(prm, body) => - ??? + throw MonomorphError(s"Unhandled case: ${rawExpr}") - case Expr.Isolated(isolation) => ??? + case Expr.Isolated(isolation) => throw MonomorphError(s"Unhandled case: ${rawExpr}") case Expr.Tuple(fields) => if(fields.length == 1){ evaluate(fields.head) } else - ??? - case Expr.Record(fields) => ??? - case Expr.LetIn(true, name, rhs, body) => ??? + throw MonomorphError(s"Unhandled case: ${rawExpr}") + case Expr.Record(fields) => throw MonomorphError(s"Unhandled case: ${rawExpr}") + case Expr.LetIn(true, name, rhs, body) => throw MonomorphError(s"Unhandled case: ${rawExpr}") case Expr.Block(items) => val exps = items.flatMap{ case e: Expr => Some(evaluate(e)) @@ -165,10 +165,10 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ val retV = evaluate(value) rawExpr.expValue = retV.expValue rawExpr - case Expr.Assign(assignee, value) => ??? - case Expr.With(value, fields) => ??? - case Expr.Subscript(receiver, index) => ??? - case Expr.Match(scrutinee, branches) => ??? + case Expr.Assign(assignee, value) => throw MonomorphError(s"Unhandled case: ${rawExpr}") + case Expr.With(value, fields) => throw MonomorphError(s"Unhandled case: ${rawExpr}") + case Expr.Subscript(receiver, index) => throw MonomorphError(s"Unhandled case: ${rawExpr}") + case Expr.Match(scrutinee, branches) => throw MonomorphError(s"Unhandled case: ${rawExpr}") } // }(_.expValue) @@ -198,7 +198,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ Expr.Apply(Expr.Ref(lambdaMemFunc.name), caseVarNm :: nArgs)) }) Expr.Match(scrut, ArrayBuffer(brchs: _*)) - case _ => ??? + case _ => throw MonomorphError(s"Unhandled case: ${rawExpr}") } branches.addOne(CaseBranch.Instance(Expr.Ref(name), Expr.Ref("obj"), branchExp)) @@ -220,7 +220,7 @@ class Specializer(monoer: Monomorph)(using debug: Debug){ }) case Expr.Select(receiver, field) => Expr.Select(defunctionalize(receiver), field) case Expr.As(value, toType) => Expr.As(defunctionalize(value), toType) - case _ => ??? + case _ => throw MonomorphError(s"Unhandled case: ${rawExpr}") } ret.expValue = rawExpr.expValue ret