diff --git a/build.sbt b/build.sbt index 58303cf47f..8367d1b8bf 100644 --- a/build.sbt +++ b/build.sbt @@ -71,11 +71,16 @@ lazy val hkmc2DiffTests = project.in(file("hkmc2DiffTests")) Test/run/fork := true, // so that CTRL+C actually terminates the watcher ) -lazy val hkmc2AllTests = project.in(file("hkmc2AllTests")) +lazy val hkmc2MainTests = project.in(file("hkmc2MainTests")) .settings( Test / test := ((hkmc2DiffTests / Test / test) dependsOn (hkmc2JVM / Test / test)).value ) +lazy val hkmc2AllTests = project.in(file("hkmc2AllTests")) + .settings( + Test / test := ((hkmc2Benchmarks / Test / test) dependsOn hkmc2MainTests / Test / test).value + ) + lazy val core = crossProject(JSPlatform, JVMPlatform).in(file("core")) .settings( sourceDirectory := baseDirectory.value.getParentFile()/"shared", diff --git a/hkmc2/jvm/src/test/scala/hkmc2/CompileTestRunner.scala b/hkmc2/jvm/src/test/scala/hkmc2/CompileTestRunner.scala index 6d04813ef2..7449fa6dfc 100644 --- a/hkmc2/jvm/src/test/scala/hkmc2/CompileTestRunner.scala +++ b/hkmc2/jvm/src/test/scala/hkmc2/CompileTestRunner.scala @@ -48,7 +48,15 @@ class CompileTestRunner val preludePath = mainTestDir/"mlscript"/"decls"/"Prelude.mls" - given Config = Config.default + given Config = + if file.segments.contains("nofib-deforest") then + Config.default.copy(deforest = S(Config.Deforestation( + seethroughModules = Set(workingDir/"hkmc2Benchmarks"/"src"/"test"/"bench"/"mlscript-compile"/"nofib-deforest"/"NofibPrelude.mls"), + seeThroughLazySymbolsNames = Set("lazy"), + seeThroughForceSymbolsNames = Set("force") + ))) + else + Config.default val compiler = MLsCompiler( preludePath, diff --git a/hkmc2/shared/src/main/scala/hkmc2/Config.scala b/hkmc2/shared/src/main/scala/hkmc2/Config.scala index 827636b38b..0d8b7133c1 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/Config.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/Config.scala @@ -14,6 +14,7 @@ case class Config( sanityChecks: Opt[SanityChecks], effectHandlers: Opt[EffectHandlers], liftDefns: Opt[LiftDefns], + deforest: Opt[Deforestation] ): def stackSafety: Opt[StackSafety] = effectHandlers.flatMap(_.stackSafety) @@ -28,6 +29,7 @@ object Config: // sanityChecks = S(SanityChecks(light = true)), effectHandlers = N, liftDefns = N, + deforest = N ) case class SanityChecks(light: Bool) @@ -42,6 +44,12 @@ object Config: case class LiftDefns() // there may be other settings in the future, having it as a case class now + case class Deforestation( + val seethroughModules: Set[os.Path], + val seeThroughLazySymbolsNames: Set[String], + val seeThroughForceSymbolsNames: Set[String] + ) + end Config diff --git a/hkmc2/shared/src/main/scala/hkmc2/MLsCompiler.scala b/hkmc2/shared/src/main/scala/hkmc2/MLsCompiler.scala index 86eef96736..3debfc5b73 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/MLsCompiler.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/MLsCompiler.scala @@ -10,6 +10,8 @@ import hkmc2.semantics.Elaborator import hkmc2.semantics.Resolver import hkmc2.syntax.Keyword.`override` import semantics.Elaborator.{Ctx, State} +import hkmc2.codegen.deforest.Deforest +import hkmc2.Config.LiftDefns class ParserSetup(file: os.Path, dbgParsing: Bool)(using Elaborator.State, Raise): @@ -37,7 +39,7 @@ class ParserSetup(file: os.Path, dbgParsing: Bool)(using Elaborator.State, Raise // * The weird type of `mkOutput` is to allow wrapping the reporting of diagnostics in synchronized blocks -class MLsCompiler(preludeFile: os.Path, mkOutput: ((Str => Unit) => Unit) => Unit)(using Config): +class MLsCompiler(preludeFile: os.Path, mkOutput: ((Str => Unit) => Unit) => Unit)(using cfg: Config): val runtimeFile: os.Path = preludeFile/os.up/os.up/os.up/"mlscript-compile"/"Runtime.mjs" val termFile: os.Path = preludeFile/os.up/os.up/os.up/"mlscript-compile"/"Term.mjs" @@ -94,6 +96,25 @@ class MLsCompiler(preludeFile: os.Path, mkOutput: ((Str => Unit) => Unit) => Uni val jsb = ltl.givenIn: codegen.js.JSBuilder() val le = low.program(blk) + + val lowered = + if cfg.deforest.isEmpty then + le + else + val deforestLow = ltl.givenIn: + cfg.copy(liftDefns = S(LiftDefns())).givenIn: + new codegen.Lowering() + val deforestResult = Deforest.apply(deforestLow.program(blk), wd)(using + cfg, + ltl, + raise, + newCtx, + new Deforest.State(), + State) + deforestResult match + case Right(msg) => le + case Left(prog) => prog + val baseScp: utils.Scope = utils.Scope.empty // * This line serves for `import.meta.url`, which retrieves directory and file names of mjs files. @@ -103,7 +124,7 @@ class MLsCompiler(preludeFile: os.Path, mkOutput: ((Str => Unit) => Unit) => Uni val nme = file.baseName val exportedSymbol = parsed.definedSymbols.find(_._1 === nme).map(_._2) val je = nestedScp.givenIn: - jsb.program(le, exportedSymbol, wd) + jsb.program(lowered, exportedSymbol, wd) val jsStr = je.stripBreaks.mkString(100) val out = file / os.up / (file.baseName + ".mjs") os.write.over(out, jsStr) diff --git a/hkmc2/shared/src/main/scala/hkmc2/Uid.scala b/hkmc2/shared/src/main/scala/hkmc2/Uid.scala index 235b375c37..4c88a1c634 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/Uid.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/Uid.scala @@ -13,6 +13,8 @@ object Uid: curUid def reset = curUid = -1 object Symbol extends Handler[semantics.Symbol] + object StratVar extends Handler[codegen.deforest.StratVarState] + object Result extends Handler[codegen.Result] extension [T] (x: Uid[T]) def <=(rhs: Uid[T]) = x <= rhs diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala index c8b9ccd103..8c373002ea 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala @@ -227,9 +227,18 @@ sealed abstract class Block extends Product: case f@FunDefn(owner, sym, params, body) => val newBody = body.flattened if newBody is body then f else f.copy(body = newBody) - if (newPreCtor is c.preCtor) && (newCtor is c.ctor) && (newMethods is c.methods) + val newCompanion = c.companion.mapConserve: + case b@ClsLikeBody(isym, methods, privateFields, publicFields, ctor) => + val newMethods = methods.mapConserve: + case f@FunDefn(owner, sym, params, body) => + val newBody = body.flattened + if newBody is body then f else f.copy(body = newBody) + val newCtor = ctor.flattened + if (newMethods is methods) && (newCtor is ctor) then b + else b.copy(methods = newMethods, ctor = newCtor) + if (newPreCtor is c.preCtor) && (newCtor is c.ctor) && (newMethods is c.methods) && (newCompanion is c.companion) then c - else c.copy(preCtor = newPreCtor, ctor = newCtor, methods = newMethods) + else c.copy(preCtor = newPreCtor, ctor = newCtor, methods = newMethods, companion = newCompanion) val newRest = rest.flatten(k) if (newDefn is defn) && (newRest is rest) @@ -538,6 +547,16 @@ sealed abstract class Result extends AutoLocated: case Value.Lit(lit) => Set.empty case DynSelect(qual, fld, arrayIdx) => qual.freeVarsLLIR ++ fld.freeVarsLLIR + + def uid(using ds: deforest.Deforest.State): Uid[Result] = + ds.resultToResultId.getOrElseUpdate( + this, + locally: + val id = ds.ResultUidState.nextUid + ds.resultIdToResult.addOne(id -> this) + id) + + // type Local = LocalSymbol type Local = Symbol diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/LambdaRewriter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/LambdaRewriter.scala index 220f01d329..545ab481a3 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/LambdaRewriter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/LambdaRewriter.scala @@ -13,7 +13,9 @@ object LambdaRewriter: def rewriteOneBlk(b: Block) = b match case Assign(lhs, Lambda(params, body), rest) if !lhs.isInstanceOf[TempSymbol] => - val newSym = BlockMemberSymbol(lhs.nme, Nil, + // use dummy TermDef of kind syntax.Fun here so that we know this symbol refers to a function + // for deforestation + val newSym = BlockMemberSymbol(lhs.nme, syntax.Tree.DummyTermDef(syntax.Fun) :: Nil, nameIsMeaningful = true // TODO: lhs.nme is not always meaningful ) val blk = blockBuilder @@ -26,7 +28,10 @@ object LambdaRewriter: val lambdaRewriter = new BlockDataTransformer(SymbolSubst()): override def applyResult(r: Result): Result = r match case lam: Lambda => - val sym = BlockMemberSymbol("lambda", Nil, nameIsMeaningful = false) + val sym = BlockMemberSymbol( + "lambda", + syntax.Tree.DummyTermDef(syntax.Fun) :: Nil, + nameIsMeaningful = false) lambdasList ::= (sym -> super.applyLam(lam)) Value.Ref(sym) case _ => super.applyResult(r) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala index 0f91a65646..8e1d594656 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala @@ -86,8 +86,8 @@ object Lifter: def getVars(d: Defn)(using state: State): Set[Local] = d match case f: FunDefn => (f.body.definedVars ++ f.params.flatMap(_.paramSyms)).collect: - case s: FlowSymbol if !(s is state.runtimeSymbol) => s - case c: ClsLikeDefn => + case s: FlowSymbol if !(s is state.runtimeSymbol) => s // FIXME: doesn't this test always fail? + case c: ClsLikeDefn => val companionVars = c.companion.fold(Set.empty)(_.ctor.definedVars) (companionVars ++ c.preCtor.definedVars ++ c.ctor.definedVars).collect: case s: FlowSymbol if !(s is state.runtimeSymbol) => s @@ -552,7 +552,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise): case c: ClsLikeDefn if !modLocal.isDefined => S(BlockMemberSymbol(d.sym.nme + "$ctor", Nil)) case _ => N - val singleCallBms = BlockMemberSymbol(d.sym.nme + "$", Nil) + val singleCallBms = BlockMemberSymbol(d.sym.nme + "$", Tree.DummyTermDef(syntax.Fun) :: Nil) val info = LiftedInfo( includedCaptures, includedLocals, clsCaptures, diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala index 273c473ec6..8d84582ea1 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala @@ -406,7 +406,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): val isAnd = sym is State.andSymbol val isOr = sym is State.orSymbol if isAnd || isOr then - val lamSym = BlockMemberSymbol("lambda", Nil, false) + val lamSym = BlockMemberSymbol("lambda", syntax.Tree.DummyTermDef(syntax.Fun) :: Nil, false) val lamDef = FunDefn(N, lamSym, PlainParamList(Nil) :: Nil, returnedTerm(arg2)) Define( lamDef, @@ -513,7 +513,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): if k.isInstanceOf[TailOp] || bodyBlock.size <= 5 then k(Lambda(paramLists.head, bodyBlock)) else - val lamSym = new BlockMemberSymbol("lambda", Nil, false) + val lamSym = new BlockMemberSymbol("lambda", syntax.Tree.DummyTermDef(syntax.Fun) :: Nil, false) val lamDef = FunDefn(N, lamSym, paramLists, bodyBlock) Define( lamDef, @@ -997,7 +997,7 @@ class Lowering()(using Config, TL, Raise, State, Ctx): case v: Value => k(v) case p: Path => k(p) case Lambda(params, body) => - val lamSym = BlockMemberSymbol("lambda", Nil, false) + val lamSym = BlockMemberSymbol("lambda", syntax.Tree.DummyTermDef(syntax.Fun) :: Nil, false) val lamDef = FunDefn(N, lamSym, params :: Nil, body) Define(lamDef, k(lamSym |> Value.Ref.apply)) case r => diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Analyze.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Analyze.scala new file mode 100644 index 0000000000..ce08024949 --- /dev/null +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Analyze.scala @@ -0,0 +1,938 @@ +package hkmc2 +package codegen +package deforest + +import semantics.* +import syntax.Tree +import utils.* +import mlscript.utils.*, shorthands.* +import scala.collection.mutable + +final case class NotDeforestableException(msg: String) extends Exception(msg) + +type ResultId = Uid[Result] +type StratVarId = Uid[StratVarState] +type InstantiationId = Ls[ResultId] + +class StratVarState(val uid: StratVarId, val name: Str, val generatedForDef: Opt[BlockMemberSymbol]): + lazy val asProdStrat = ProdVar(this) + lazy val asConsStrat = ConsVar(this) + override def toString(): String = s"${if name.isEmpty() then "var" else name}@${uid}@$generatedForDef" +object StratVarState: + def freshVar(nme: String, generatedForDef: Opt[BlockMemberSymbol])(using vuid: Uid.StratVar.State) = + val newId = vuid.nextUid + StratVarState(newId, nme, generatedForDef) +trait StratVar(s: StratVarState): + this: ProdVar | ConsVar => + def asProdStrat = s.asProdStrat + def asConsStrat = s.asConsStrat + def uid = s.uid + + +sealed abstract class ProdStrat +case class ProdVar(s: StratVarState) extends ProdStrat with StratVar(s) +case class ProdFun(params: Ls[ConsStrat], res: ProdStrat) extends ProdStrat +case object NoProd extends ProdStrat + +case class Ctor( + val exprId: ResultId, + val instantiationId: Opt[InstantiationId])( + val ctor: ClassLikeSymbol, + val args: Ls[TermSymbol -> ProdStrat])(using pre: DeforestPreAnalyzer) extends ProdStrat + +sealed abstract class ConsStrat +case class ConsVar(s: StratVarState) extends ConsStrat with StratVar(s) +case class ConsFun(params: Ls[ProdStrat], res: ConsStrat) extends ConsStrat +case object NoCons extends ConsStrat +class FieldSel( + val exprId: ResultId, + val instantiationId: Opt[InstantiationId], + val field: Tree.Ident, + val consVar: ConsVar) extends ConsStrat: + // this filter means that this selection occurs in match branches where the + // keys (of type ProdVar) are known to be of the type of the ClassLikeSymbols + val filter = mutable.Map.empty[ProdVar, Ls[ClassLikeSymbol]].withDefaultValue(Nil) + def updateFilter(p: ProdVar, c: Ls[ClassLikeSymbol]) = + filter += p -> (c ::: filter(p)) + +class Dtor( + val scrutExprId: ResultId, + val instantiationId: Opt[InstantiationId]) extends ConsStrat + +class ProdStratScheme(s: StratVarState, constraints: Ls[ProdStrat -> ConsStrat]): + def instantiate(referSite: ResultId)(using d: DeforestConstraintsCollector, cc: d.ConstraintsAndCacheHitCollector): ProdVar = d.preAnalyzer.tl.trace(s"inst ${d.preAnalyzer.getReferredFunSym(referSite)} under ${cc.forFun}"): + given DeforestPreAnalyzer = d.preAnalyzer + val instantiatingFunSym = d.preAnalyzer.getReferredFunSym(referSite) + val instantiatingRecursiveGroup = d.funSymToProdStratScheme.recursiveGroups(instantiatingFunSym) + val stratVarMap = mutable.Map.empty[StratVarState, StratVarState] + def updateInstantiationId(instId: Opt[InstantiationId]) = + S(instId.fold(referSite :: Nil)(l => referSite :: l)) + def duplicateVarState(s: StratVarState) = + if s.generatedForDef.fold(false)(instantiatingRecursiveGroup.contains) then + stratVarMap.getOrElseUpdate.curried(s): + StratVarState.freshVar(s.name, cc.forFun)(using d.stratVarUidState) + else + s + def duplicateProdStrat(s: ProdStrat): ProdStrat = s match + case ProdVar(s) => duplicateVarState(s).asProdStrat + case ProdFun(params, res) => ProdFun(params.map(duplicateConsStrat), duplicateProdStrat(res)) + case NoProd => NoProd + case c: Ctor => new Ctor( + c.exprId, + updateInstantiationId(c.instantiationId))( + c.ctor, + c.args.map((a, b) => a -> duplicateProdStrat(b)) + ) + def duplicateConsStrat(c: ConsStrat): ConsStrat = c match + case ConsVar(s) => duplicateVarState(s).asConsStrat + case ConsFun(params, res) => ConsFun(params.map(duplicateProdStrat), duplicateConsStrat(res)) + case NoCons => NoCons + case fSel: FieldSel => + val res = new FieldSel( + fSel.exprId, + updateInstantiationId(fSel.instantiationId), + fSel.field, + duplicateVarState(fSel.consVar.s).asConsStrat) + fSel.filter.foreach: (p, ls) => + res.updateFilter(duplicateVarState(p.s).asProdStrat, ls) + res + case dtor: Dtor => new Dtor(dtor.scrutExprId, updateInstantiationId(dtor.instantiationId)) + val newProd = duplicateVarState(s).asProdStrat + constraints.foreach: (p, c) => + cc.constrain(duplicateProdStrat(p), duplicateConsStrat(c)) + newProd + +class DeforestPreAnalyzer( + val b: Block, + val importedInfo: ImportedInfo +)(using val elabState: Elaborator.State, val tl: TraceLogger, val dState: Deforest.State) extends BlockTraverser: + given stratVarUidState: Uid.StratVar.State = new Uid.StratVar.State + import StratVarState.freshVar + + // this contains + // - top level functions + // - exported functions in modules + // - ctor in modules + // these will be rewritten in-place. + // top level computations also get rewritten in-place + // but they are not contained here. + var topLevelLikeComputations: Ls[Block | FunDefn] = Nil + // for rewriting top level functions + var dummyRefsToTopLevelLikeFuns = Map.empty[BlockMemberSymbol, Value.Ref] + lazy val dummyRefsInstantiationIds: Set[InstantiationId] = dummyRefsToTopLevelLikeFuns.values.map(_.uid :: Nil).toSet + object arrBlkMemSym: + val store = mutable.Map.empty[Int, ClassSymbol] + def apply(n: Int) = store.getOrElseUpdate.curried(n): + ClassSymbol(Tree.DummyTypeDef(syntax.Cls), Tree.Ident(s"Deforest_Arr_$n")) + val noProdStratVar = freshVar("primitive", N).asProdStrat + val topLevelFunSymToFun = mutable.Map.empty[BlockMemberSymbol, FunDefn] + val matchScrutToMatchBlock = mutable.Map.empty[ResultId, Match] + val matchScrutToParentMatchScruts = mutable.Map.empty[ResultId, Ls[ResultId]] + val selsToMatchingArmsContainingIt = mutable.Map.empty[ResultId, Ls[ResultId -> Opt[ClassLikeSymbol]]] + val symToStratVar = mutable.Map.empty[Symbol, ProdVar] + val usedFunSyms = mutable.Set.empty[BlockMemberSymbol] + val ownedValDefSyms = mutable.Set.empty[BlockMemberSymbol] + lazy val topLevelDefinedFunSyms = topLevelFunSymToFun.keySet + val nonTopLevelDefinedFunSyms = mutable.Set.empty[BlockMemberSymbol] + def getProdVarForSym(s: Symbol) = s match + case _: (BuiltinSymbol | TopLevelSymbol) => noProdStratVar + case _ if s.asCls.isDefined => noProdStratVar + case _ => symToStratVar(s) + def getTopLevelFunDefnForSym(s: BlockMemberSymbol) = topLevelFunSymToFun.get(s) + def getCtorSymFromCtorLikeExprId(id: ResultId): Opt[ClassLikeSymbol] = + dState.resultIdToResult(id).getCtorSymFromCtorLikeExpr(using this) + def getMatchFromMatchScrutExprId(scrutExprId: ResultId): Opt[Match] = + matchScrutToMatchBlock.get(scrutExprId) + def getResult(id: ResultId) = dState.resultIdToResult(id) + def getStableResultId(id: ResultId) = resultIdToStableId.getOrElseUpdate.curried(id): + val prev = stableResuldIt + stableResuldIt += 1 + prev + def getReferredFunSym(id: ResultId) = + def chk(s: BlockMemberSymbol) = + assert(s.isFunction) + s + dState.resultIdToResult(id) match + case s: Select => chk(s.symbol.get.asBlkMember.get) + case Value.Ref(l) => chk(l.asBlkMember.get) + case _ => die + + private var moduleFuns: Opt[Set[BlockMemberSymbol]] = N + // indicate if a block contains features that current implementation cannot handle (other than side effects) + private var handleable = true + // if a function is imported or not + private var imported = false + private val resultIdToStableId = mutable.Map.empty[ResultId, Int] + private var stableResuldIt = 0 + private var inMatchScrutsArms: Ls[ResultId -> Opt[ClassLikeSymbol]] = Nil + private def inMatchScruts = inMatchScrutsArms.unzip._1 + private var inFunDef: Opt[BlockMemberSymbol] = N + private var symsDefinedForFun: Opt[Set[Symbol]] = N + private def maybeCollectFun(fun: FunDefn) = + if handleable then + topLevelFunSymToFun += fun.sym -> fun + if !imported then + topLevelLikeComputations ::= fun + val dummyRef = Value.Ref(fun.sym) + dummyRefsToTopLevelLikeFuns += fun.sym -> dummyRef.asInstanceOf[Value.Ref] + private def isPrivatelyDefined(s: Symbol) = + imported && importedInfo.privateSymbols.contains(s) + override def applyFunDefn(fun: FunDefn): Unit = + inFunDef match + case N => + handleable = moduleFuns.fold(true)(s => s.contains(fun.sym)) + inFunDef = S(fun.sym) + symsDefinedForFun = S(fun.deforestDefinedVars) + super.applyFunDefn(fun) + maybeCollectFun(fun) + inFunDef = N + symsDefinedForFun = N + case S(value) => + // nothing special for non-top-level functions + nonTopLevelDefinedFunSyms += fun.sym + super.applyFunDefn(fun) + + override def applySymbol(s: Symbol): Unit = s match + case _: (TopLevelSymbol | BuiltinSymbol | ClassLikeSymbol) => () + case s: BlockMemberSymbol if s.isFunction && symsDefinedForFun.fold(true)(x => !x.contains(s)) => symToStratVar.updateWith(s): + case N => S(freshVar(s.nme, S(s)).asProdStrat) + case S(x) => S(x) + case v: (BlockMemberSymbol | VarSymbol | TermSymbol | TempSymbol | FlowSymbol) => symToStratVar.updateWith(s): + case N => + val inFunOrNot = symsDefinedForFun.fold(false)(_.contains(s)) + S(freshVar(s.nme, if inFunOrNot then inFunDef else N).asProdStrat) + case S(x) => S(x) + case _ => lastWords(s"$s") + + override def applyResult(r: Result): Unit = + r match + case DeforestTupSelect(scrut, idx) => + selsToMatchingArmsContainingIt += r.uid -> inMatchScrutsArms + case _ => () + super.applyResult(r) + + override def applyPath(p: Path): Unit = + p match + case s@Select(path, nme) => + selsToMatchingArmsContainingIt += s.uid -> inMatchScrutsArms + s.symbol match + case None => () + case Some(sym) => + if isPrivatelyDefined(sym) then handleable = false + if sym.isFunction then usedFunSyms += s.symbol.get.asBlkMember.get + case _ => () + super.applyPath(p) + + override def applyValue(v: Value): Unit = + v match + case Value.Ref(l) => + if l.isFunction then usedFunSyms += l.asBlkMember.get + if isPrivatelyDefined(l) then handleable = false + case Value.This(_) => handleable = false + case _ => () + super.applyValue(v) + + override def applyBlock(b: Block): Unit = b match + case m@Match(scrut, arms, dflt, rest) => + matchScrutToMatchBlock += scrut.uid -> m + matchScrutToParentMatchScruts += scrut.uid -> inMatchScruts + applyPath(scrut) + + val prev = inMatchScrutsArms + arms.foreach: arm => + val cse = arm._1 match + case Case.Cls(cls, path) => S(cls) + case _ => N + inMatchScrutsArms = (scrut.uid -> cse) :: inMatchScrutsArms + applyCase(arm._1); applySubBlock(arm._2) + inMatchScrutsArms = prev + + inMatchScrutsArms = (scrut.uid -> N) :: inMatchScrutsArms + dflt.foreach(applySubBlock) + inMatchScrutsArms = prev + + applySubBlock(rest) + case _ => super.applyBlock(b) + + override def applyDefn(defn: Defn): Unit = defn match + case clsLike: ClsLikeDefn if clsLike.companion.isDefined => + val comp = clsLike.companion.get + topLevelLikeComputations ::= comp.ctor + moduleFuns = S(comp.methods.map(_.sym).toSet) + super.applyDefn(defn) + moduleFuns = N + case _: ClsLikeDefn => + if inFunDef.isDefined then + throw NotDeforestableException(s"cls like defn inside a function") + else () + case _ => super.applyDefn(defn) + + override def applyValDefn(defn: ValDefn): Unit = + if defn.isOwned then + ownedValDefSyms.add(defn.sym) + super.applyValDefn(defn) + + override def applyArg(arg: Arg): Unit = + if arg.spread.isDefined then handleable = false + super.applyArg(arg) + + override def applyParamList(pl: ParamList): Unit = + if pl.restParam.isDefined then handleable = false + super.applyParamList(pl) + + imported = true + importedInfo.funAndDefs.foreach: (_, fdefn) => + applyFunDefn(fdefn) + imported = false + applyBlock(b) + + +class DeforestConstraintsCollector(val preAnalyzer: DeforestPreAnalyzer): + given stratVarUidState: Uid.StratVar.State = preAnalyzer.stratVarUidState + given elabState: Elaborator.State = preAnalyzer.elabState + given DeforestPreAnalyzer = preAnalyzer + given dState: Deforest.State = preAnalyzer.dState + import StratVarState.freshVar + + + val constraints = processTopLevel + class ConstraintsAndCacheHitCollector(val forFun: Opt[BlockMemberSymbol]): + var constraints: Ls[ProdStrat -> ConsStrat] = Nil + var trackedFunctionSymbolsInOneRecGroup: Ls[BlockMemberSymbol] = Nil + def constrain(p: ProdStrat, c: ConsStrat) = constraints ::= p -> c + def constrain(cs: Ls[ProdStrat -> ConsStrat]) = constraints :::= cs + def hit(s: BlockMemberSymbol) = trackedFunctionSymbolsInOneRecGroup ::= s + def hit(ss: Ls[BlockMemberSymbol]) = trackedFunctionSymbolsInOneRecGroup :::= ss + + object funSymToProdStratScheme: + val processedFunToCollector = mutable.Map.empty[BlockMemberSymbol, ConstraintsAndCacheHitCollector] + val store = mutable.Map.empty[BlockMemberSymbol, ProdStratScheme] + val recursiveGroups = mutable.Map.empty[BlockMemberSymbol, Ls[BlockMemberSymbol]] + def getOrUpdate(s: BlockMemberSymbol)(using processingDefs: Ls[BlockMemberSymbol], cc: ConstraintsAndCacheHitCollector): ProdVar | ProdStratScheme = + preAnalyzer.getTopLevelFunDefnForSym(s) match + // not a fun whose definition is visible for fusion, just return its prodvar + case None => + preAnalyzer.getProdVarForSym(s) + case Some(funDefn) => store.get(s) match + case Some(scheme) => scheme + case None => processingDefs.filter(_ is s) match + case sym :: Nil => + cc.hit(sym) + processingDefs.headOption.foreach: h => + cc.hit(h) + preAnalyzer.getProdVarForSym(sym) + case Nil => + processedFunToCollector.get(s) match + case Some(otherCC) => + cc.hit(otherCC.trackedFunctionSymbolsInOneRecGroup) + processingDefs.headOption.foreach: h => + cc.hit(h) + preAnalyzer.getProdVarForSym(s) + case None => + // start processing this function, if the cache hit contains the currently processing defs functions + // then: 1. the referred function belongs to the same recursion group and need to share the constraints 2. return the prodvar + // else: we found a new recursive group, for each member of the group, update the store with the correct type scheme and return the type scheme + val newcc = processFunDefn(funDefn, processingDefs) + if newcc.trackedFunctionSymbolsInOneRecGroup.exists(x => processingDefs.contains(x)) then + cc.hit(newcc.trackedFunctionSymbolsInOneRecGroup) + cc.constrain(newcc.constraints) + processingDefs.headOption.foreach: h => + cc.hit(h) + preAnalyzer.getProdVarForSym(s) + else + val recursiveGroupMembers = (s :: newcc.trackedFunctionSymbolsInOneRecGroup).distinct + recursiveGroupMembers.foreach: f => + store.updateWith(f): + case N => S(ProdStratScheme(preAnalyzer.getProdVarForSym(f).s, newcc.constraints)) + case S(_) => die // this means the scc is not computed corrrectely + recursiveGroups.updateWith(f): + case N => S(recursiveGroupMembers) + case S(_) => die // this means the scc is not computed corrrectely + store(s) + case _ => die // die if something occurs twice in the processing list + + def processTopLevel: Ls[ProdStrat -> ConsStrat] = + val cc = new ConstraintsAndCacheHitCollector(N) + cc.constrain(preAnalyzer.noProdStratVar, NoCons) + cc.constrain(NoProd, preAnalyzer.noProdStratVar.asConsStrat) + + val stratOfRealTopLevel = processBlock(preAnalyzer.b)(using Nil, cc) + cc.constrain(stratOfRealTopLevel, NoCons) + + preAnalyzer.topLevelLikeComputations.foreach: + case b: Block => processBlock(b)(using Nil, cc) + case FunDefn(_, sym, params, body) => + val bodyStrat = processResult(preAnalyzer.dummyRefsToTopLevelLikeFuns(sym))(using Nil, cc).asInstanceOf[ProdVar] + cc.constrain(bodyStrat, NoCons) + cc.constrain(NoProd, bodyStrat.asConsStrat) + + preAnalyzer.usedFunSyms + .diff(preAnalyzer.topLevelDefinedFunSyms) + .diff(preAnalyzer.nonTopLevelDefinedFunSyms) + .foreach: usedButNotDefined => + cc.constrain(NoProd, preAnalyzer.getProdVarForSym(usedButNotDefined).asConsStrat) + + preAnalyzer.ownedValDefSyms.foreach: s => + cc.constrain(NoProd, preAnalyzer.getProdVarForSym(s).asConsStrat) + cc.constrain(preAnalyzer.getProdVarForSym(s), NoCons) + + cc.constraints + + def processFunDefn(defn: FunDefn, processingDefs: Ls[BlockMemberSymbol]): ConstraintsAndCacheHitCollector = + val cc = funSymToProdStratScheme.processedFunToCollector + .updateWith(defn.sym): + case Some(_) => lastWords(s"process ${defn.sym} again") + case None => Some(new ConstraintsAndCacheHitCollector(S(defn.sym))) + .get + val thisFunVar = preAnalyzer.getProdVarForSym(defn.sym) + val res = freshVar(s"${defn.sym.nme}_res", S(defn.sym)) + val funProdStrat = defn.params.foldRight[ProdStrat](res.asProdStrat): (ps, acc) => + assert(ps.restParam.isEmpty) // TODO: the `restParam` + val psTys = ps.params.map: + case Param(_, sym, _, _) => preAnalyzer.getProdVarForSym(sym).asConsStrat + ProdFun(psTys, acc) + val bodyStrat = processBlock(defn.body)(using defn.sym :: processingDefs, cc) + cc.constrain(bodyStrat, res.asConsStrat) + cc.constrain(funProdStrat, thisFunVar.asConsStrat) + cc + + def processBlock(b: Block)(using + processingDefs: Ls[BlockMemberSymbol], + cc: ConstraintsAndCacheHitCollector + ): ProdStrat = b match + case m@Match(scrut, arms, dflt, rest) => + val scrutStrat = processResult(scrut) + cc.constrain(scrutStrat, new Dtor(scrut.uid, cc.forFun.fold(S(Nil))(_ => N))) + val armsRes = + if arms.forall{ case (cse, _) => cse.isInstanceOf[Case.Cls] } then + arms.map: + case (_: Case.Cls, body) => processBlock(body) + else if arms.forall{ case (cse, _) => cse.isInstanceOf[Case.Tup] } then + arms.map(a => processBlock(a._2)) + else + arms.map: + case (_, armBody) => processBlock(armBody) + val dfltRes = dflt.map(processBlock) + rest match + case End(msg) => + val matchRes = freshVar("", cc.forFun) + armsRes.appendedAll(dfltRes).foreach: r => + cc.constrain(r, matchRes.asConsStrat) + matchRes.asProdStrat + case _ => processBlock(rest) + + case Return(res, implct) => processResult(res) + case Assign(lhs, rhs, rest) => + cc.constrain(processResult(rhs), preAnalyzer.getProdVarForSym(lhs).asConsStrat) + processBlock(rest) + case Begin(sub, rest) => + processBlock(sub) + processBlock(rest) + case Define(defn, rest) => + defn match + case FunDefn(_, sym, params, body) => + if processingDefs.nonEmpty then + val paramSyms = params.head.params.map: + case Param(_, sym, _, _) => preAnalyzer.getProdVarForSym(sym).asConsStrat + val res = freshVar(s"${sym.nme}_res", cc.forFun) + val funProdStrat = params.foldRight[ProdStrat](res.asProdStrat): (ps, acc) => + assert(ps.restParam.isEmpty) // TODO: the `restParam` + val psTys = ps.params.map: + case Param(_, sym, _, _) => preAnalyzer.getProdVarForSym(sym).asConsStrat + ProdFun(psTys, acc) + val bodyStrat = processBlock(body) + cc.constrain(bodyStrat, res.asConsStrat) + cc.constrain(funProdStrat, preAnalyzer.getProdVarForSym(sym).asConsStrat) + else + () // skip toplevel fundefs are they are processed when needed + case ValDefn(_, sym, rhs) => + val valStrat = preAnalyzer.getProdVarForSym(sym) + val stratRhs = processResult(rhs) + cc.constrain(stratRhs, valStrat.asConsStrat) + case c: ClsLikeDefn => () + processBlock(rest) + case End(msg) => NoProd + // make it a type var instead of `NoProd` so that things like `throw match error` in + // default else branches do not block fusion... + case Throw(exc) => + processResult(exc) + freshVar("throw", cc.forFun).asProdStrat + case _ => throw NotDeforestableException(s"not supported: $b") + + def processResult(r: Result)(using + processingDefs: Ls[BlockMemberSymbol], + cc: ConstraintsAndCacheHitCollector + ): ProdStrat = + val generatedForDef = cc.forFun + val instantiationId = cc.forFun.fold(S(Nil))(_ => N) + def handleCallLike(f: Path, args: Ls[Path], c: Result): ProdStrat = + def lookThroughLazy(args: Ls[Path]) = + args match + case (arg@Value.Ref(lamSym: BlockMemberSymbol)) :: Nil => + val res = freshVar("lz_res", generatedForDef) + val lamStrat = funSymToProdStratScheme.getOrUpdate(lamSym) match + case t: ProdStratScheme => + t.instantiate(arg.uid)(using this, cc) + case s: ProdVar => s + cc.constrain(lamStrat, ConsFun(Nil, res.asConsStrat)) + res.asProdStrat + case (arg@Value.Ref(lamSym)) :: Nil => + val lamStrat = preAnalyzer.getProdVarForSym(lamSym) + val res = freshVar("lz_res", generatedForDef) + cc.constrain(lamStrat, ConsFun(Nil, res.asConsStrat)) + res.asProdStrat + f match + case s: Select if s.symbol.exists(preAnalyzer.importedInfo.forceSymbols.contains) => + val arg :: Nil = args: @unchecked + processResult(arg) + case Value.Ref(l) if preAnalyzer.importedInfo.forceSymbols.contains(l) => + val arg :: Nil = args: @unchecked + processResult(arg) + case s: Select if s.symbol.exists(preAnalyzer.importedInfo.lazySymbols.contains) => + lookThroughLazy(args) + case Value.Ref(l) if preAnalyzer.importedInfo.lazySymbols.contains(l) => + lookThroughLazy(args) + case s@Select(p, nme) => + val argsTpe = args.map(processResult) + s.symbol.map(_.asCls) match + case None => + val pStrat = processResult(p) + val tpeVar = freshVar("", generatedForDef) + cc.constrain(pStrat, new FieldSel(s.uid, instantiationId, nme, tpeVar.asConsStrat)) + val appRes = freshVar("", generatedForDef) // unknown function symbol + cc.constrain(tpeVar.asProdStrat, ConsFun(argsTpe, appRes.asConsStrat)) + appRes.asProdStrat + case Some(None) => + val funSym = s.symbol.get + val appRes = freshVar("call_" + funSym.nme + "_res", generatedForDef) + funSym.asBlkMember match + case None => + cc.constrain(preAnalyzer.getProdVarForSym(funSym), ConsFun(argsTpe, appRes.asConsStrat)) + case Some(s) => + funSymToProdStratScheme.getOrUpdate(s) match + case v: ProdVar => cc.constrain(v, ConsFun(argsTpe, appRes.asConsStrat)) + case t: ProdStratScheme => + val instantiated = t.instantiate(f.uid)(using this, cc) + cc.constrain(instantiated, ConsFun(argsTpe, appRes.asConsStrat)) + appRes.asProdStrat + case Some(Some(s)) => + val clsFields = s.tree.clsParams + new Ctor(c.uid, instantiationId)(s, clsFields.zip(argsTpe)) + case Value.Ref(funSym) => + val argsTpe = args.map(processResult) + funSym.asCls match + case Some(s) => + val clsFields = s.tree.clsParams + new Ctor(c.uid, instantiationId)(s, clsFields.zip(argsTpe)) + case _ => // then it is a function + val appRes = freshVar("call_" + funSym.nme + "_res", generatedForDef) + funSym.asBlkMember match + case None => + cc.constrain(preAnalyzer.getProdVarForSym(funSym), ConsFun(argsTpe, appRes.asConsStrat)) + case Some(s) => + funSymToProdStratScheme.getOrUpdate(s) match + case v: ProdVar => cc.constrain(v, ConsFun(argsTpe, appRes.asConsStrat)) + case t: ProdStratScheme => + val instantiated = t.instantiate(f.uid)(using this, cc) + cc.constrain(instantiated, ConsFun(argsTpe, appRes.asConsStrat)) + appRes.asProdStrat + // case lam@Value.Lam(params, body) => + // val argsTpe = args.map(processResult) + // val funTpe = processResult(lam) + // val appRes = freshVar("call_lam_res", generatedForDef) + // cc.constrain(funTpe, ConsFun(argsTpe, appRes.asConsStrat)) + // appRes.asProdStrat + case Value.This(sym) => throw NotDeforestableException("No support for `this` as a callee yet") + case Value.Lit(lit) => lastWords(s"try to call literal $lit") + // case Value.Arr(_, elems) => lastWords(s"try to call array $elems") + r match + case sel@DeforestTupSelect(scrut, idx) => + val pStrat = processResult(scrut) + pStrat match + case ProdVar(pStratVar) => + val inMatchingArm = preAnalyzer.selsToMatchingArmsContainingIt(sel.uid).flatMap: + case (scrutUid, S(inArm)) => + preAnalyzer.matchScrutToMatchBlock(scrutUid).scrut match + case Value.Ref(l) => + S(preAnalyzer.getProdVarForSym(l) -> inArm) + case _ => N + case _ => N + val tpeVar = freshVar("sel_res", generatedForDef) + val selStrat = new FieldSel(sel.uid, instantiationId, Tree.Ident(idx.toString()), tpeVar.asConsStrat) + inMatchingArm.foreach: (p, c) => + selStrat.updateFilter(p, c :: Nil) + cc.constrain(pStrat, selStrat) + tpeVar.asProdStrat + case _ => die + case c@Call(f, args) => handleCallLike(f, args.map {case Arg(N, value) => value}, c) + case i@Instantiate(false, cls, args) => handleCallLike(cls, args.map {case Arg(N, value) => value}, i) + case sel@Select(p, nme) => sel.symbol match + case Some(s) if s.asObj.isDefined => + new Ctor(sel.uid, instantiationId)(s.asObj.get, Nil) + case Some(s) if s.isFunction && + preAnalyzer.topLevelDefinedFunSyms.contains(s.asBlkMember.get) => + funSymToProdStratScheme.getOrUpdate(s.asBlkMember.get) match + case v: ProdVar => v + case t: ProdStratScheme => + val instantiated = t.instantiate(sel.uid)(using this, cc) + instantiated + case _ => + p match + // special case for selecting from a module... + case Value.Ref(l) if l.asMod.isDefined && sel.symbol.isDefined => + preAnalyzer.getProdVarForSym(sel.symbol.get) + case _ => + val pStrat = processResult(p) + pStrat match + case ProdVar(pStratVar) => + val inMatchingArm = preAnalyzer.selsToMatchingArmsContainingIt(sel.uid).flatMap: + case (scrutUid, S(inArm)) => + preAnalyzer.matchScrutToMatchBlock(scrutUid).scrut match + case Value.Ref(l) => + S(preAnalyzer.getProdVarForSym(l) -> inArm) + case _ => N + case _ => N + val tpeVar = freshVar("sel_res", generatedForDef) + val selStrat = new FieldSel(sel.uid, instantiationId, nme, tpeVar.asConsStrat) + inMatchingArm.foreach: (p, c) => + selStrat.updateFilter(p, c :: Nil) + cc.constrain(pStrat, selStrat) + tpeVar.asProdStrat + case _ => + val tpeVar = freshVar("sel_res", generatedForDef) + cc.constrain(pStrat, new FieldSel(sel.uid, instantiationId, nme, tpeVar.asConsStrat)) + tpeVar.asProdStrat + + case v@Value.Ref(l) => l.asObj match + case None => + if l.asBlkMember.exists(preAnalyzer.topLevelDefinedFunSyms.contains) then + funSymToProdStratScheme.getOrUpdate(l.asBlkMember.get) match + case v: ProdVar => v + case t: ProdStratScheme => + val instantiated = t.instantiate(v.uid)(using this, cc) + instantiated + else + preAnalyzer.getProdVarForSym(l) + case Some(m) => new Ctor(v.uid, instantiationId)(m, Nil) + + case Value.This(sym) => throw NotDeforestableException("No support for `this` yet") + case Value.Lit(lit) => NoProd + case Lambda(ParamList(_, params, N), body) => // TODO: the `restParam` + val paramSyms = params.map: + case Param(_, sym, _, _) => preAnalyzer.getProdVarForSym(sym).asConsStrat + val bodyStrat = processBlock(body) + val res = freshVar(s"lam_res", generatedForDef) + cc.constrain(bodyStrat, res.asConsStrat) + ProdFun(paramSyms, res.asProdStrat) + case Tuple(false, elems) => + val args = elems.zipWithIndex.map: + case (Arg(N, value), n) => + TermSymbol(syntax.ImmutVal, N, Tree.Ident(n.toString())) -> + processResult(value) + case _ => throw NotDeforestableException("no support for array with spread") + new Ctor(r.uid, instantiationId)(preAnalyzer.arrBlkMemSym(elems.length), args) + + preAnalyzer.tl.trace(constraints + .map: (p, c) => + (s"$p --> $c") + .mkString("\n") + )(()) + +class DeforestConstrainSolver(val collector: DeforestConstraintsCollector): + given dState: Deforest.State = collector.dState + + val preAnalyzer = collector.preAnalyzer + val constraints = collector.constraints + val upperBounds = mutable.Map.empty[StratVarId, Ls[ConsStrat]].withDefaultValue(Nil) + val lowerBounds = mutable.Map.empty[StratVarId, Ls[ProdStrat]].withDefaultValue(Nil) + object ctorDests: + val store = mutable.LinkedHashMap.empty[Ctor, Ls[Dtor | FieldSel] -> Bool] + def update(c: Ctor, d: Dtor | FieldSel | NoCons.type) = d match + case NoCons => store.updateWith(c): + case S(l -> _) => S(l, true) + case N => S(Nil, true) + case d: (Dtor | FieldSel) => store.updateWith(c): + case S(l -> b) => S(d :: l, b) + case N => S(d :: Nil, false) + def get(c: Ctor) = store.get(c).map(l => l._1.distinct -> l._2) + object dtorSources: + val store = mutable.LinkedHashMap.empty[Dtor | FieldSel, Ls[Ctor] -> Bool] + def update(d: Dtor | FieldSel, c: Ctor | NoProd.type) = c match + case NoProd => store.updateWith(d): + case S(l -> _) => S(l, true) + case N => S(Nil, true) + case c: Ctor => store.updateWith(d): + case S(l -> b) => S(c :: l, b) + case N => S(c :: Nil, false) + + private def handle(constraint: ProdStrat -> ConsStrat)(using cache: mutable.Set[ProdStrat -> ConsStrat]): Unit = + val prod = constraint._1 + val cons = constraint._2 + val proceed = cache.add(constraint) + assert: + (!prod.isInstanceOf[Ctor] || prod.asInstanceOf[Ctor].instantiationId.isDefined) && + (!cons.isInstanceOf[Dtor] || cons.asInstanceOf[Dtor].instantiationId.isDefined) + if proceed then constraint match + case (c: Ctor, d: Dtor) => + ctorDests.update(c, d) + dtorSources.update(d, c) + case (c: Ctor, d: FieldSel) => + ctorDests.update(c, d) + dtorSources.update(d, c) + c.args.find(a => a._1.id == d.field) match + case None => + handle(c, NoCons) + handle(NoProd, d.consVar) + case Some(p) => handle(p._2 -> d.consVar) + case (c: Ctor, d: ConsFun) => () + case (p: ProdVar, _) => + upperBounds += p.uid -> (cons :: upperBounds(p.uid)) + lowerBounds(p.uid).foreach: l => + (l, cons) match + case (l: ProdVar, sel: FieldSel) => + sel.updateFilter(l, sel.filter(p)) + handle(l -> cons) + case (c: Ctor, sel: FieldSel) => + if sel.filter.get(p).forall(_.contains(c.ctor)) then + handle(l -> cons) + case _ => handle(l -> cons) + case (_, c: ConsVar) => + lowerBounds += c.uid -> (prod :: lowerBounds(c.uid)) + upperBounds(c.uid).foreach: u => + (prod, u) match + case (ctor: Ctor, sel: FieldSel) => + if sel.filter.get(c.asProdStrat).forall(_.contains(ctor.ctor)) then + handle(prod -> u) + case (_: ProdVar, _) => die + case _ => handle(prod -> u) + case (ctor: Ctor, NoCons) => + ctorDests.update(ctor, NoCons) + ctor.args.foreach(a => handle(a._2, NoCons)) + case (ProdFun(l, r), _: Dtor) => () // ignore + case (ProdFun(l, r), _: FieldSel) => () // ignore + case (ProdFun(lp, rp), ConsFun(lc, rc)) => + lc.zip(lp).foreach(handle) + handle(rp, rc) + case (ProdFun(l, r), NoCons) => + l.foreach(a => handle(NoProd, a)) + handle(r, NoCons) + case (NoProd, d: Dtor) => dtorSources.update(d, NoProd) + case (NoProd, fSel: FieldSel) => + dtorSources.update(fSel, NoProd) + handle(NoProd, fSel.consVar) + case (NoProd, ConsFun(l, r)) => + l.foreach(a => handle(a, NoCons)) + handle(NoProd, r) + case (NoProd, NoCons) => () + + locally: + given mutable.Set[ProdStrat -> ConsStrat] = mutable.Set.empty + constraints.foreach(handle) + + + def removeCtor(rm: (Ctor | CtorId))(using + ctorToDtor: mutable.LinkedHashMap[Ctor, Ls[Dtor | FieldSel] -> Bool], + dtorToCtor: mutable.LinkedHashMap[Dtor | FieldSel, Ls[Ctor] -> Bool], + toRmCtor: mutable.Set[Ctor], + toRmDtor: mutable.Set[Dtor | FieldSel] + ): Unit = rm match + case rm: Ctor => + if toRmCtor.add(rm) then + for + (dtors, _) <- ctorToDtor.get(rm) + dtor <- dtors + do removeDtor(dtor) + case rm: CtorId => + for + rm <- ctorToDtor.keySet.filter: x => + x.exprId === rm._1 && x.instantiationId.fold(false)(_ === rm._2) + do removeCtor(rm) + + + def removeDtor(rm: Dtor | FieldSel)(using + ctorToDtor: mutable.LinkedHashMap[Ctor, Ls[Dtor | FieldSel] -> Bool], + dtorToCtor: mutable.LinkedHashMap[Dtor | FieldSel, Ls[Ctor] -> Bool], + toRmCtor: mutable.Set[Ctor], + toRmDtor: mutable.Set[Dtor | FieldSel] + ) = + if toRmDtor.add(rm) then + for (ctors, _) <- dtorToCtor.get(rm) + x <- ctors do removeCtor(x) + + + val resolveClashes -> cyclicOnes = + given ctorToDtor: mutable.LinkedHashMap[Ctor, Ls[Dtor | FieldSel] -> Bool] = ctorDests.store + given dtorToCtor: mutable.LinkedHashMap[Dtor | FieldSel, Ls[Ctor] -> Bool] = dtorSources.store + + given toRmCtor: mutable.Set[Ctor] = mutable.Set.empty[Ctor] + given toRmDtor: mutable.Set[Dtor | FieldSel] = mutable.Set.empty[Dtor | FieldSel] + + + // remove clashes + for + (rm, dtors -> noCons) <- ctorToDtor + _ = assert(rm.instantiationId.isDefined) + (mats, sels) = dtors.partitionMap: + case d: Dtor => + assert(d.instantiationId.isDefined) + L(d) + case s: FieldSel => R(s) + if noCons || !locally: + mats.size == 0 && sels.size == 1 || + mats.size == 1 && locally: + val matScrutExprId = mats.head.scrutExprId + val matExprInstantiationId = mats.head.instantiationId.get + val matScrutSym = preAnalyzer.getResult(matScrutExprId).asInstanceOf[Value.Ref].l + sels.forall: s => + val selExprId = s.exprId + given Elaborator.State = collector.preAnalyzer.elabState + def chk(l: Symbol) = + preAnalyzer.selsToMatchingArmsContainingIt(selExprId).exists(_._1 === matScrutExprId) && + (l is matScrutSym) && + s.instantiationId.get === matExprInstantiationId + preAnalyzer.getResult(selExprId) match + case Select(Value.Ref(l), _) => chk(l) + case DeforestTupSelect(Value.Ref(l), _) => chk(l) + case _ => false + do removeCtor(rm) + for + case (rm, _ -> true) <- dtorToCtor + do removeDtor(rm) + toRmCtor.foreach(rm => ctorToDtor.remove(rm)) + toRmDtor.foreach(rm => dtorToCtor.remove(rm)) + toRmCtor.clear() + toRmDtor.clear() + + // remove cycle + def getCtorInArm(ctorExprId: CtorId , dtorScrutExprId: MatchId) = + val ctorSym = preAnalyzer.getCtorSymFromCtorLikeExprId(ctorExprId._1).get + val dtor = preAnalyzer.getMatchFromMatchScrutExprId(dtorScrutExprId._1).get + val arm = + dtor.arms.find: + case (Case.Cls(c1, _) -> body) => c1 is ctorSym + case (Case.Tup(len, _) -> _) => preAnalyzer.arrBlkMemSym(len) is ctorSym + .map(_._2).orElse(dtor.dflt).get + val armAndMatchRest = preAnalyzer + .matchScrutToParentMatchScruts(dtorScrutExprId._1) + .foldLeft(Begin(arm, dtor.rest)): (acc, x) => + val newRest = preAnalyzer.getMatchFromMatchScrutExprId(x).get.rest + Begin(acc, newRest) + val traverser = new GetCtorsTraverser(armAndMatchRest) + traverser.ctors.map(_ -> dtorScrutExprId._2) + def findCycle(c: Ctor, d: Dtor): Ls[CtorId] = + val cache = mutable.Set(c.exprId -> c.instantiationId.get) + def go(ctorAndMatchesScrutExprIds: Ls[CtorId -> MatchId]): Ls[CtorId] = + val newCtorsAndNewMatches = for + (c, m) <- ctorAndMatchesScrutExprIds + c <- getCtorInArm(c, m) + (ds -> noCons) <- ctorToDtor + .get: + new Ctor(c._1, S(c._2))(preAnalyzer.arrBlkMemSym(0), Nil)(using preAnalyzer) + .toSeq + _ = assert(!noCons) + case (m: Dtor) <- ds + yield c -> (m.scrutExprId -> m.instantiationId.get) + val cycled = newCtorsAndNewMatches.filter: c => + !cache.add(c._1) + if newCtorsAndNewMatches.isEmpty then + Nil + else if cycled.nonEmpty then + cycled.map(_._1) + else + go(newCtorsAndNewMatches) + c.instantiationId -> d.instantiationId match + case S(id1) -> S(id2) => + go(Ls((c.exprId -> id1) -> (d.scrutExprId -> id2))) + case _ => Nil + for + (ctor, dtors -> noCons) <- ctorToDtor + (mats, sels) = dtors.partitionMap: + case d: Dtor => L(d) + case s: FieldSel => R(s) + _ = assert(!noCons && mats.size <= 1) + dtor <- mats + rm <- findCycle(ctor, dtor) + do removeCtor(rm) + val cyclic = toRmCtor -> toRmDtor + + ctorToDtor -> dtorToCtor -> cyclic + + + +class GetCtorsTraverser(b: Block)(using dState: Deforest.State) extends BlockTraverser: + var ctors = Set.empty[ResultId] + override def applyResult(r: Result): Unit = r match + case Call(f, args) => + if f.asClsSymbol.isDefined then ctors += r.uid + args.foreach: + case Arg(N, v) => applyResult(v) + case Instantiate(false, cls, args) => + if cls.asClsSymbol.isDefined then ctors += r.uid + args.foreach(applyArg) + case Tuple(false, elems) => + ctors += r.uid + elems.foreach: + case Arg(N, v) => applyResult(v) + case p: Path => if p.asObjSymbol.isDefined then ctors += r.uid + applyBlock(b) + +extension (fun: FunDefn) + def deforestDefinedVars: Set[Local] = + fun.body.deforestDefinedVars ++ fun.params.flatMap(_.params.map(_.sym)) + fun.sym + +extension (b: Block) + // a different version of `Block.definedVars` which also consider the vars in nested defs + def deforestDefinedVars: Set[Local] = b match + case _: Return | _: Throw => Set.empty + case Begin(sub, rst) => sub.deforestDefinedVars ++ rst.deforestDefinedVars + case Assign(l: TermSymbol, r, rst) => rst.deforestDefinedVars + case Assign(l, r, rst) => rst.deforestDefinedVars + l + case AssignField(l, n, r, rst) => rst.deforestDefinedVars + case AssignDynField(l, n, ai, r, rst) => rst.deforestDefinedVars + case Match(scrut, arms, dflt, rst) => + arms.flatMap(_._2.deforestDefinedVars).toSet ++ dflt.toList.flatMap(_.deforestDefinedVars) ++ rst.deforestDefinedVars + case End(_) => Set.empty + case Break(_) => Set.empty + case Continue(_) => Set.empty + case Define(defn, rst) => + val rest = rst.deforestDefinedVars + if defn.isOwned then rest else + defn match + case fdef: FunDefn => rest ++ fdef.deforestDefinedVars + case _: ValDefn => rest + defn.sym + case _ => throw NotDeforestableException(s"no support for fun containing a cls like def") + case HandleBlock(lhs, res, par, args, cls, hdr, bod, rst) => rst.deforestDefinedVars + res + case TryBlock(sub, fin, rst) => sub.deforestDefinedVars ++ fin.deforestDefinedVars ++ rst.deforestDefinedVars + case Label(lbl, bod, rst) => bod.deforestDefinedVars ++ rst.deforestDefinedVars + + +extension (p: Path) + def asClsSymbol = p match + case s: Select => s.symbol.flatMap(_.asCls) + case Value.Ref(l) => l.asCls + case _ => N + def asObjSymbol = p match + case s: Select => s.symbol.flatMap(_.asObj) + case Value.Ref(l) => l.asObj + case _ => N + +extension (r: Result) + def getCtorSymFromCtorLikeExpr(using pre: DeforestPreAnalyzer) = r match + case Call(f, _) => f.asClsSymbol + case Instantiate(_, cls, _) => cls.asClsSymbol + case Tuple(_, elems) => S(pre.arrBlkMemSym(elems.length)) + case p: Path => p.asObjSymbol + +object DeforestTupSelect: + def unapply(v: Result)(using elabState: Elaborator.State): Opt[Value.Ref -> Int] = v match + case Call( + Select(Select(Value.Ref(elabState.runtimeSymbol), Tree.Ident("Tuple")), Tree.Ident("get")), + Arg(N, scrut: Value.Ref) :: Arg(N, Value.Lit(Tree.IntLit(x))) :: Nil) => S(scrut -> x.toInt) + case _ => N + + def getDeforestSelNameFromResult(r: Result)(using elabState: Elaborator.State): Tree.Ident = r match + case Select(_, name) => name + case _ => unapply(r) match + case N => die + case Some(_, idx) => Tree.Ident(idx.toString()) + \ No newline at end of file diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Deforest.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Deforest.scala new file mode 100644 index 0000000000..cc8b36247a --- /dev/null +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Deforest.scala @@ -0,0 +1,124 @@ +package hkmc2 +package codegen +package deforest + +import scala.jdk.CollectionConverters.MapHasAsScala +import semantics.* +import syntax.Tree +import utils.* +import mlscript.utils.*, shorthands.* +import scala.collection.mutable +import hkmc2.Config.LiftDefns +import hkmc2.syntax.Keyword.in + + +case class ImportedInfo( + otherImports: Ls[Symbol -> Str], + innerSymbolsToOutterSymbols: Ls[InnerSymbol -> BlockMemberSymbol], + funAndDefs: Ls[BlockMemberSymbol -> FunDefn], + lazySymbols: Ls[Symbol], + forceSymbols: Ls[Symbol], + privateSymbols: Ls[BlockMemberSymbol]): + + def :::(other: ImportedInfo) = + ImportedInfo( + otherImports ::: other.otherImports, + innerSymbolsToOutterSymbols ::: other.innerSymbolsToOutterSymbols, + funAndDefs ::: other.funAndDefs, + lazySymbols ::: other.lazySymbols, + forceSymbols ::: other.forceSymbols, + privateSymbols ::: other.privateSymbols) + +object ImportedInfo: + val empty = ImportedInfo(Nil, Nil, Nil, Nil, Nil, Nil) + +class GetInfoOfImportedFile(cfg: Config.Deforestation) extends BlockTraverser: + var funAndDefs: Ls[BlockMemberSymbol -> FunDefn] = Nil + var innerToOutter: Opt[InnerSymbol -> BlockMemberSymbol] = N + var lazySymbols: Ls[Symbol] = Nil + var forceSymbols: Ls[Symbol] = Nil + var privateFunSyms = Set.empty[BlockMemberSymbol] + override def applyDefn(defn: Defn): Unit = defn match + case clsLike: ClsLikeDefn + if clsLike.companion.isDefined && + cfg.seethroughModules.exists(p => p.baseName == clsLike.sym.nme) => + val comp = clsLike.companion.get + innerToOutter = S(comp.isym -> clsLike.sym) + funAndDefs :::= comp.methods.map(f => f.sym -> f) + super.applyDefn(defn) + case _ => super.applyDefn(defn) + + override def applyFunDefn(fun: FunDefn): Unit = + privateFunSyms += fun.sym + if cfg.seeThroughLazySymbolsNames.contains(fun.sym.nme) then + lazySymbols ::= fun.sym + if cfg.seeThroughForceSymbolsNames.contains(fun.sym.nme) then + forceSymbols ::= fun.sym + + def apply(b: Block): Unit = + applyBlock(b) + privateFunSyms = privateFunSyms -- funAndDefs.keys + +object Deforest: + class State: + val importedFileNameToLoweredBlock = mutable.Map.empty[os.Path, Program] + val topLevelFunInPrevDiffBlocks = mutable.Map.empty[BlockMemberSymbol, FunDefn] + val resultToResultId = new java.util.IdentityHashMap[Result, Uid[Result]].asScala + val resultIdToResult = mutable.Map.empty[Uid[Result], Result] + object ResultUidState extends Uid.Result.State + + def deforestImport(file: os.Path)(using + cfg: Config, + raise: Raise, + st: State, + elabSt: Elaborator.State, + ctx: Elaborator.Ctx, + ): ImportedInfo = + given localTL: TraceLogger = new TraceLogger: + override def doTrace: Bool = false + + val prog = st.importedFileNameToLoweredBlock.getOrElseUpdate.curried(file): + val semBlk -> _ = elabSt.importedFileNameToSemBlk(file) + val resolver = Resolver(localTL) + resolver.traverseBlock(semBlk)(using Resolver.ICtx.empty) + val low = codegen.Lowering()(using + cfg.copy(liftDefns = S(LiftDefns())), localTL, raise, elabSt, ctx) + low.program(semBlk) + val traverser = new GetInfoOfImportedFile(cfg.deforest.get) + traverser(prog.main) + ImportedInfo( + prog.imports, + traverser.innerToOutter.toList, + traverser.funAndDefs, + traverser.lazySymbols, + traverser.forceSymbols, + traverser.privateFunSyms.toList.sortBy(_.uid)) + + def apply(p: Program, wd: os.Path)(using + cfg: Config, + tl: TL, + raise: Raise, + ctx: Elaborator.Ctx, + st: State, + elabSt: Elaborator.State, + ): Either[Program, String] = + val importedInfo = + val trulyImported = p.imports + .map: (_, path) => + if path.startsWith("/") + then os.Path(path.replace(".mjs", ".mls")) + else wd / os.RelPath(path.replace(".mjs", ".mls")) + .filter(cfg.deforest.get.seethroughModules.contains) + .foldLeft(ImportedInfo.empty): (acc, path) => + acc ::: deforestImport(path) + trulyImported.copy(funAndDefs = trulyImported.funAndDefs ++ st.topLevelFunInPrevDiffBlocks) + try + val pre = new DeforestPreAnalyzer(p.main, importedInfo) + val col = new DeforestConstraintsCollector(pre) + val ana = new DeforestConstrainSolver(col) + val rwp = new DeforestRewritePrepare(ana) + val rw = new DeforestRewriter(rwp) + val deforestRes = rw() + L(Program(p.imports, deforestRes)) + catch + case NotDeforestableException(msg) => R(msg) diff --git a/hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Rewrite.scala b/hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Rewrite.scala new file mode 100644 index 0000000000..03abe14f26 --- /dev/null +++ b/hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Rewrite.scala @@ -0,0 +1,851 @@ +package hkmc2 +package codegen +package deforest + + +import semantics.* +import semantics.Elaborator.State +import syntax.Tree +import utils.* +import mlscript.utils.*, shorthands.* +import scala.collection.mutable + + +type CtorId = ResultId -> InstantiationId +type MatchId = ResultId -> InstantiationId +type SelId = ResultId -> InstantiationId + + +enum FinalDest: + // A match arm is considered a final destination. + // `selsInArm` totally depends on `matchId` and `arm`, while + // `tmpSymbolForASpecificCtorId` depends on the ctor that reaches this destination. + // This field is in the second param list because we want maps from `FinalDest`s + // to only consider `matchId` and `arm` (i.e. the match arm). + case Match(val matchId: MatchId, val arm: Opt[ClassLikeSymbol])(val selsInArm: Ls[SelId], val tmpSymbolForASpecificCtorId: Ls[TempSymbol]) + case Sel(val s: SelId) + def toString(pre: DeforestPreAnalyzer): String = this match + case Match(matchId, arm) => pre.getResult(matchId._1).toString() + "@" + matchId._2.makeSuffix(pre) + "@" + arm.fold("dflt")(_.nme) + case Sel(s) => pre.getResult(s._1).toString() + "@" + s._2.makeSuffix(pre) + + + +class DeforestRewritePrepare(val sol: DeforestConstrainSolver): + drwp => + given eState: Elaborator.State = sol.collector.elabState + given dState: Deforest.State = sol.dState + val preAnalyzer = sol.preAnalyzer + + val instIdToMappingFromOldToNewSyms = mutable.Map.empty[InstantiationId, Map[BlockMemberSymbol, BlockMemberSymbol]] + // need to be ordered because we need to traverse it to generate new fun def bodies + val newSymToInstIdAndOldSym = mutable.LinkedHashMap.empty[BlockMemberSymbol, InstantiationId -> BlockMemberSymbol] + locally: + for + (ctor, _) <- sol.resolveClashes._1 + instantiationId = ctor.instantiationId.get + case instId@(_ :+ invokedReferSite) <- instantiationId.scanLeft(Nil)(_ :+ _) + do instIdToMappingFromOldToNewSyms.getOrElseUpdate.curried(instId): + val invokedFunSym = preAnalyzer.getReferredFunSym(invokedReferSite) + val recursiveGroupFunSym = sol.collector.funSymToProdStratScheme.recursiveGroups(invokedFunSym) + val newSymSuffix = instId.makeSuffix(preAnalyzer) + val mapping = recursiveGroupFunSym.map: old => + val newSymbol = + // for dummy refer refs, since we modify the fun def in-place, no need for new symbol + if preAnalyzer.dummyRefsInstantiationIds.contains(instId) && + (old is preAnalyzer.getReferredFunSym(instId.head)) then old + else + BlockMemberSymbol(old.nme + s"_$newSymSuffix", Nil, old.nameIsMeaningful) + newSymToInstIdAndOldSym.updateWith(newSymbol): + case N => S(instId -> old) + case S(_) => die + old -> newSymbol + mapping.toMap + // TODO: can merge all ids that *only* have dtor to one id, but also need to consider all other + // referred functions along the way? + for + (dtorOrSel, _) <- sol.resolveClashes._2 + instantiationId = dtorOrSel match + case f: FieldSel => f.instantiationId.get + case d: Dtor => d.instantiationId.get + case instId@(_ :+ invokedReferSite) <- instantiationId.scanLeft(Nil)(_ :+ _) + do instIdToMappingFromOldToNewSyms.getOrElseUpdate.curried(instId): + val invokedFunSym = preAnalyzer.getReferredFunSym(invokedReferSite) + val recursiveGroupFunSym = sol.collector.funSymToProdStratScheme.recursiveGroups(invokedFunSym) + val newSymSuffix = instId.makeSuffix(preAnalyzer) + val mapping = recursiveGroupFunSym.map: old => + val newSymbol = + // for dummy refer refs, since we modify the fun def in-place, no need for new symbol + if preAnalyzer.dummyRefsInstantiationIds.contains(instId) && + (old is preAnalyzer.getReferredFunSym(instId.head)) then old + else + BlockMemberSymbol(old.nme + s"_$newSymSuffix", Nil, old.nameIsMeaningful) + newSymToInstIdAndOldSym.updateWith(newSymbol): + case N => S(instId -> old) + case S(_) => die + old -> newSymbol + mapping.toMap + + val finalDestToCtorIds = mutable.LinkedHashMap.empty[FinalDest, Set[CtorId]] + val ctorIdToFinalDest = mutable.LinkedHashMap.empty[CtorId, FinalDest] + sol.resolveClashes._1.foreach: + case (c: Ctor, dtors -> noCons) => + assert(!noCons) + val (dtor, sel) = dtors.partitionMap: + case d: Dtor => L(d) + case s: FieldSel => R(s) + val ctorExprId = c.exprId -> c.instantiationId.get + val ctorFinalDest = + if dtor.isEmpty then + assert(sel.size == 1) + FinalDest.Sel(sel.head.exprId -> sel.head.instantiationId.get) + else + assert(dtor.size == 1) + val dtorScrutExprId = dtor.head.scrutExprId -> dtor.head.instantiationId.get + val distinctSels = sel + .map: s => + assert(s.instantiationId.get == dtorScrutExprId._2) + s.exprId -> s.instantiationId.get + .distinct // need to preserve order + assert: + distinctSels.forall: s => + preAnalyzer.selsToMatchingArmsContainingIt(s._1).exists: armInfo => + armInfo._1 == dtorScrutExprId._1 && + armInfo._2.fold(true): clsSym => + clsSym is c.ctor + val ctorCls = preAnalyzer.getCtorSymFromCtorLikeExprId(c.exprId).get + val whichArm = preAnalyzer.matchScrutToMatchBlock(dtorScrutExprId._1).arms + .flatMap: x => + x._1 match + case Case.Cls(cls, _) => if (cls is ctorCls) then S(cls) else N + case Case.Tup(len, _) => if (preAnalyzer.arrBlkMemSym(len) is ctorCls) then S(ctorCls) else N + case _ => die + .headOption + val tmpSymbolsForFieldsOfCtor = ctorCls.asCls + .map: cls => + cls.getClsParamNames(preAnalyzer).map: fieldName => + TempSymbol(N, s"_deforest_${cls.nme}_$fieldName") + .getOrElse(Nil) + FinalDest.Match(dtorScrutExprId, whichArm)(distinctSels, tmpSymbolsForFieldsOfCtor) + finalDestToCtorIds.updateWith(ctorFinalDest): + case N => S(Set(ctorExprId)) + case S(s) => S(s + ctorExprId) + ctorIdToFinalDest.updateWith(ctorExprId): + case N => S(ctorFinalDest) + case S(x) => die + + val rewritingMatchIds -> rewritingSelIds = finalDestToCtorIds.keySet.partitionMap: + case FinalDest.Match(matchId, _) => L(matchId) + case FinalDest.Sel(s) => R(s) + + // not all symbols are used because some of the match rests are just `End`s, so no need to + // create a new function for them. + val fusingMatchIdToMatchRestFunSymbols = mutable.LinkedHashMap.empty[MatchId, BlockMemberSymbol] + locally: + // the order of traversal is deterministic because rewritingMatchIds is from + // the keySet of linkedHashMap + for + case (FinalDest.Match(matchId, _), _) <- finalDestToCtorIds + numOfMatchingArms = finalDestToCtorIds.keySet.count: + case FinalDest.Match(matId, _) => matId == matchId + case _ => false + if numOfMatchingArms > 1 + do + fusingMatchIdToMatchRestFunSymbols.updateWith(matchId): + case N => + val scrutName = preAnalyzer.getResult(matchId._1).asInstanceOf[Value.Ref].l.nme + S(BlockMemberSymbol( + s"match_${scrutName}_rest_${matchId._2.makeSuffix(preAnalyzer)}", + Nil)) + case S(x) => S(x) + + + // if a key doesn't exist, it means the final dest is only used once + val finalDestToVarSymbolsToReplaceSelInArms = mutable.Map.empty[ + FinalDest, + Map[SelId, VarSymbol] -> Map[Tree.Ident, VarSymbol]] + // if a key doesn't exist, it means the matchId doesn't have any arm that is used more than once + val fusingMatchIdToVarSymbolsToReplacedInAllBranches = mutable.Map.empty[ + MatchId, + Map[SelId, VarSymbol]] + // if a key doesn't exist, it means the all the arms of this matchId are used more than once + val fusingMatchIdToTmpSymbolsToReplacedInAllBranches = mutable.Map.empty[ + MatchId, + Map[SelId, TempSymbol]] + // if a key doesn't exist, it means the final dest is only used once + val finalDestToMatchArmFunSymbols = mutable.Map.empty[FinalDest, BlockMemberSymbol] + val selIdsInAllArmsToSymbolsToReplace = mutable.Map.empty[SelId, TempSymbol | VarSymbol] + locally: + def matDestToTempSymbolMap(mat: FinalDest.Match) = + mat.arm.fold(Nil): c => + mat.selsInArm.map: selId => + val ctorFieldNames = c.asCls.get.getClsParamNames(preAnalyzer) + val selName = DeforestTupSelect.getDeforestSelNameFromResult(preAnalyzer.getResult(selId._1)) + val idx = ctorFieldNames.indexWhere(_ == selName.name) + selId -> mat.tmpSymbolForASpecificCtorId(idx) + for case (c, matchArmDest@FinalDest.Match(matchId, cls)) <- ctorIdToFinalDest do + val numOfCtors = finalDestToCtorIds(matchArmDest).size + if numOfCtors < 1 then + die + else if numOfCtors == 1 && !locally: + sol.cyclicOnes._1.exists: ctor => + ctor.exprId === c._1 && ctor.instantiationId.get === c._2 + then + val selsToTmpSyms = matDestToTempSymbolMap(matchArmDest) + fusingMatchIdToTmpSymbolsToReplacedInAllBranches.updateWith(matchId): + case N => S(selsToTmpSyms.toMap) + case S(m) => S(m ++ selsToTmpSyms) + selIdsInAllArmsToSymbolsToReplace.addAll(selsToTmpSyms) + else + finalDestToMatchArmFunSymbols.getOrElseUpdate.curried(matchArmDest): + val selNameToNewSymbol = mutable.Map.empty[Tree.Ident, VarSymbol] + val selExprIdToNewSymbol = mutable.Map.empty[SelId, VarSymbol] + for cls <- cls do + for selId <- matchArmDest.selsInArm do + val selName = DeforestTupSelect.getDeforestSelNameFromResult(preAnalyzer.getResult(selId._1)) + val symName = s"_deforest_${cls.nme}_${selName.name}_${selId._2.makeSuffix(preAnalyzer)}" + val sym = selNameToNewSymbol.getOrElseUpdate.curried(selName): + VarSymbol(Tree.Ident(symName)) + selExprIdToNewSymbol += selId -> sym + finalDestToVarSymbolsToReplaceSelInArms += matchArmDest -> (selExprIdToNewSymbol.toMap -> selNameToNewSymbol.toMap) + fusingMatchIdToVarSymbolsToReplacedInAllBranches.updateWith(matchId): + case N => S(selExprIdToNewSymbol.toMap) + case S(x) => S(x ++ selExprIdToNewSymbol.toMap) + selIdsInAllArmsToSymbolsToReplace.addAll(selExprIdToNewSymbol) + val scrutName = preAnalyzer.getResult(matchId._1).asInstanceOf[Value.Ref].l.nme + val armName = cls.fold("default")(_.nme) + val funSym = BlockMemberSymbol( + s"match_${scrutName}_arm_${armName}_${matchId._2.makeSuffix(preAnalyzer)}", + Nil, false) + funSym + + + val alwaysNonFreeVars = + sol.preAnalyzer.b.definedVars ++ + newSymToInstIdAndOldSym.keySet ++ + fusingMatchIdToMatchRestFunSymbols.values ++ + finalDestToMatchArmFunSymbols.values + + State.globalThisSymbol + + State.runtimeSymbol + + object freeVarsOfOriginalMatchesConsideringDeforestation: + val store = mutable.Map.empty[MatchId, Ls[Symbol]] + def apply(m: MatchId) = store.getOrElseUpdate.curried(m): + new FreeVarTraverserForMatchConsideringDeforestation(m, drwp).freeVars + + preAnalyzer.tl.log( + "---------- deforest summary ----------\n" ++ + ctorIdToFinalDest + .map: (ctorid, dest) => + preAnalyzer.getResult(ctorid._1).toString() + + "@" + + preAnalyzer.getStableResultId(ctorid._1) + + "@" + + ctorid._2.makeSuffix(preAnalyzer) + + " --> " + + dest.toString(preAnalyzer) + .mkString("\n"), + true) + + + +class DeforestRewriter(val rewritePrepare: DeforestRewritePrepare): + given eState: Elaborator.State = rewritePrepare.eState + given dState: Deforest.State = rewritePrepare.dState + val preAnalyzer = rewritePrepare.preAnalyzer + + def apply() = + val duplicatedDefs = for + newSym -> (instId -> oldSym) <- rewritePrepare.newSymToInstIdAndOldSym + if !locally: + // the dummy refs are for rewriting exported module functions in-place, so no new defs + preAnalyzer.dummyRefsInstantiationIds.contains(instId) && locally: + (oldSym is preAnalyzer.getReferredFunSym(instId.head)) && locally: + assert(oldSym is newSym) + true + yield + // 1. find original fundefs + // 2. transform fun body under the specific instantiation id + val FunDefn(_, _, param, body) = preAnalyzer.getTopLevelFunDefnForSym(oldSym).get + val oldToNewParam = mutable.Map.empty[VarSymbol, VarSymbol] + val newParam = param.map: + case ParamList(flags, params, restParam) => + def makeNewParam(p: Param) = + val Param(flags, sym, sign, modulefulness) = p + val newSym = VarSymbol(sym.id) + oldToNewParam += sym -> newSym + Param(flags, newSym, sign, modulefulness) + val newParams = params.map(makeNewParam) + val newRestParam = restParam.map(makeNewParam) + ParamList(flags, newParams, newRestParam) + val newBody = Transform(instId)(body).replaceSymbols(oldToNewParam.toMap) + // the owner is `N` because duplicated functions shouldn't be inside any module + FunDefn(N, newSym, newParam, newBody) + + val withDuplicatedDefs = duplicatedDefs.foldRight(Transform(Nil)(preAnalyzer.b)): + case (newFunDefn, acc) => + Define(newFunDefn, acc) + matchRestOfFusingMatches.prependAllFunDefs: + matchArmsOfFusingMatches.prependAllFunDefs: + withDuplicatedDefs + + object matchRestOfFusingMatches: + // from match scrut expr id to either a function def with a set of args that should be applied + // or a block containing the computation in the `rest` of the match + val store = mutable.Map.empty[MatchId, Either[FunDefn -> Ls[Symbol], Block]] + def prependAllFunDefs = + rewritePrepare.fusingMatchIdToMatchRestFunSymbols.foldRight(identity: Block => Block): + case matchId -> _ -> k => store.get(matchId) match + case S(Left(fdef -> _)) => r => Define(fdef, k(r)) + case S(Right(b)) => + assert(b.isInstanceOf[End]) + k + case _ => + lastWords(s"not here ${preAnalyzer.getResult(matchId._1)}@${matchId._1}@${matchId._2.toReadableCallPath(preAnalyzer)}@${matchId._2}") + + // returns the block of match rest, or a `Return` block that calls the function extracted + // from the match rest + def getOrElseUpdate(matchId: MatchId): Block = store.get(matchId) match + case S(R(blk)) => blk + case S(L(fdef -> args)) => + Return( + Call(callNewFun(fdef.sym), args.map(a => Arg(N, Value.Ref(a))))(true, false), + false) + case N => + val scrutExprId -> instantiationId = matchId + val parentMatchesScrutExprIds -> thePossiblyFusingOne = preAnalyzer + .matchScrutToParentMatchScruts(scrutExprId) + .span: x => + !rewritePrepare.rewritingMatchIds.contains(x -> instantiationId) + val transform = new Transform(instantiationId) + val transformedCurrentMatchRest = + transform(preAnalyzer.matchScrutToMatchBlock(scrutExprId).rest) + val withAllParentMatchesRests = + parentMatchesScrutExprIds.foldLeft[Block](transformedCurrentMatchRest): (acc, p) => + val parentMatchRest = transform(preAnalyzer.matchScrutToMatchBlock(p).rest) + val isEnd = parentMatchRest.isInstanceOf[End] + if isEnd then acc else Begin(acc, parentMatchRest) + val withTheRestOfPossiblyFusingMatch = thePossiblyFusingOne.headOption + .fold(withAllParentMatchesRests): scrutExprIdOfTheFusingOne => + Begin(withAllParentMatchesRests, getOrElseUpdate(scrutExprIdOfTheFusingOne, instantiationId)) + .flattened + + // if the rest is empty or only going to be used once, + // then no need to build a function for it + val noNeedToBuild = + withTheRestOfPossiblyFusingMatch.isInstanceOf[End] || + rewritePrepare.fusingMatchIdToMatchRestFunSymbols.get(matchId).isEmpty + if noNeedToBuild then + store.updateWith(matchId): + case S(_) => die + case N => S(R(withTheRestOfPossiblyFusingMatch)) + withTheRestOfPossiblyFusingMatch + else // build a new function for the rest of this fusing match + val sym = rewritePrepare.fusingMatchIdToMatchRestFunSymbols(matchId) + val freeVars = withTheRestOfPossiblyFusingMatch + .sortedFvsForTransformedBlocks(rewritePrepare.alwaysNonFreeVars) + val newSymbols = freeVars.map(s => VarSymbol(Tree.Ident(s.nme))) + val newFunDef = FunDefn(N, sym, newSymbols.asParamList :: Nil, + withTheRestOfPossiblyFusingMatch.replaceSymbols(freeVars.zip(newSymbols).toMap)) + store.updateWith(matchId): + case S(_) => die + case N => S(L(newFunDef -> freeVars)) + Return( + Call(callNewFun(sym), freeVars.map(a => Arg(N, Value.Ref(a))))(true, false), + false) + + object matchArmsOfFusingMatches: + private var transforming = mutable.Map.empty[FinalDest.Match, BlockMemberSymbol] + val store = mutable.Map.empty[FinalDest.Match, Either[FunDefn, Block]] + def prependAllFunDefs = + rewritePrepare.finalDestToCtorIds.keys.foldRight(identity: Block => Block): + case (m: FinalDest.Match, acc) => + store.get(m) match + case S(L(fdefn)) => rest => Define(fdefn, acc(rest)) + case _ => acc + case (_, acc) => acc + def getAllFunDefs = + for + case (m: FinalDest.Match, _) <- rewritePrepare.finalDestToCtorIds + if store.get(m).exists(x => x.isLeft) + yield + val L(fdef) = store(m): @unchecked + fdef + + // return a lambda, which either calls the extracted arm function + // or contains the computations in matching arms + def getOrElseUpdate(ctorId: CtorId): Lambda = + val dest = rewritePrepare.ctorIdToFinalDest(ctorId).asInstanceOf[FinalDest.Match] + val freeVarsInTheMatch = + rewritePrepare.freeVarsOfOriginalMatchesConsideringDeforestation(dest.matchId) + val symsForArmFreeVarsInLam = freeVarsInTheMatch.map: x => + VarSymbol(Tree.Ident(x.nme)) + transforming.get(dest) match + case Some(sym) => + Lambda( + symsForArmFreeVarsInLam.asParamList, + Return( + Call( + callNewFun(sym), + symsForArmFreeVarsInLam.asArgsList ::: dest.tmpSymbolForASpecificCtorId.asArgsList)(true, false), + false)) + case None => + val armFunOrBlk = store.get(dest) match + case Some(R(a)) => lastWords(s"$a in ${dest.matchId._2.toReadableCallPath(preAnalyzer)}") + case Some(f@L(_)) => f + case None => + val maybeFunSym = rewritePrepare.finalDestToMatchArmFunSymbols.get(dest) + maybeFunSym match + case Some(sym) => transforming.addOne(dest -> sym) + case None => () + val transformedRest = matchRestOfFusingMatches.getOrElseUpdate(dest.matchId) + val originalMatchArmBody = + val matchExpr = preAnalyzer.matchScrutToMatchBlock(dest.matchId._1) + dest.arm.fold(matchExpr.dflt.get): armCls => + armCls.asCls.flatMap(c => c.getArrClsSymSize(preAnalyzer)) match + case N => + matchExpr.arms.find(a => a._1.asInstanceOf[Case.Cls].cls is armCls).get._2 + case S(n) => matchExpr.arms.find(a => a._1.asInstanceOf[Case.Tup].len == n).get._2 + // this rewrittenBody here already has its selection replaced with + // the pre-computed var symbols (if the arm is used multiple times) + // or the temp symbols (if the arm is used only once) + val rewrittenBody = Begin(Transform(dest.matchId._2)(originalMatchArmBody), transformedRest).flattened + val res = maybeFunSym match + case N => R(rewrittenBody) + case Some(funSym) => + val freeVarSymForFunDef = freeVarsInTheMatch.map: x => + VarSymbol(Tree.Ident(x.nme)) + val funBody = rewrittenBody.replaceSymbols(freeVarsInTheMatch.zip(freeVarSymForFunDef).toMap).mapTail: + case Return(res, implct) => Return(res, false) + case t => t + val varSymbolsThatReplacedSelections = + // the order is the same as class ctor param + preAnalyzer.getCtorSymFromCtorLikeExprId(ctorId._1).get.asCls.fold(Nil): c => + c.getClsParamNames(preAnalyzer).map: p => + rewritePrepare + .finalDestToVarSymbolsToReplaceSelInArms(dest)._2 + .getOrElse(Tree.Ident(p), VarSymbol(Tree.Ident(s"_unused_${p}"))) + L(FunDefn( + N, + funSym, + (freeVarSymForFunDef ::: varSymbolsThatReplacedSelections).asParamList :: Nil, + funBody)) + store.updateWith(dest): + case None => S(res) + case Some(x) => lastWords(s"already exist? $x") + res + armFunOrBlk match + case L(fdefn) => Lambda( + symsForArmFreeVarsInLam.asParamList, + Return( + Call( + callNewFun(fdefn.sym), + symsForArmFreeVarsInLam.asArgsList ::: dest.tmpSymbolForASpecificCtorId.asArgsList)(true, false), + false)) + case R(b) => Lambda( + symsForArmFreeVarsInLam.asParamList, + b.replaceSymbols(freeVarsInTheMatch.zip(symsForArmFreeVarsInLam).toMap).mapTail: + case Return(res, implct) => Return(res, false) + case t => t) + + + private def callNewFun(sym: BlockMemberSymbol): Path = + Value.Ref(sym) + + private val uselessSymbolSubst = new SymbolSubst + // rewrite ctor and dtors + // replace selections in match arms + // replace refer site symbols to their new symbols + class Transform(instId: InstantiationId) extends BlockTransformer(uselessSymbolSubst): + extension (resId: ResultId) + def withInstId = resId -> instId + override def applyBlock(b: Block): Block = b match + case mat@Match(scrut, arms, dflt, rest) => + if rewritePrepare.rewritingMatchIds.contains(scrut.uid.withInstId) then + // since all fusing matches will be considered to be in the tail position, + // if any of the parent `rest`s has explicit return, the rewritten match will have explicit return + val oneOfParentMatchRestHasExplicitRet = + preAnalyzer.matchScrutToParentMatchScruts(scrut.uid).foldRight(false): (pid, acc) => + acc || preAnalyzer.matchScrutToMatchBlock(pid).rest.hasExplicitRet + val needExplicitRet = rest.hasExplicitRet || arms.exists(_._2.hasExplicitRet) || oneOfParentMatchRestHasExplicitRet + val freeVars = rewritePrepare.freeVarsOfOriginalMatchesConsideringDeforestation(scrut.uid.withInstId) + Return(Call(scrut, freeVars.asArgsList)(false, false), !needExplicitRet) + else + val allArmWillBeNonEnd = + dflt.fold(false)(_.willBeNonEndTailBlock(instId, rewritePrepare)) && + arms.forall: + case (_, body) => body.willBeNonEndTailBlock(instId, rewritePrepare) + if allArmWillBeNonEnd then + super.applyBlock(Match(scrut, arms, dflt, End(""))) + else + super.applyBlock(b) + case _ => super.applyBlock(b) + + override def applyResult(r: Result): Result = r match + case _: Call => + // calls to fusing contructors are handled in `applyResult2` + // here we only handle calls to non-fusing constructors and functions + assert(!rewritePrepare.ctorIdToFinalDest.isDefinedAt(r.uid.withInstId)) + super.applyResult(r) + case _ => super.applyResult(r) + + override def applyResult2(r: Result)(k: Result => Block): Block = + def handleCallLike(ctorResId: ResultId)(args: Ls[Path]) = + val c = preAnalyzer.getCtorSymFromCtorLikeExprId(ctorResId).get.asCls.get + rewritePrepare.ctorIdToFinalDest(ctorResId.withInstId) match + case matchDest@FinalDest.Match(matchId, whichArm) => + // use pre-determined symbols + val tempSymbolsForFields = matchDest.tmpSymbolForASpecificCtorId + tempSymbolsForFields + .zip(args) + .foldRight(k(matchArmsOfFusingMatches.getOrElseUpdate(ctorResId.withInstId))): + case (tmpSym, arg) -> rest => + applyResult2(arg): r => + Assign(tmpSym, r, rest) + case FinalDest.Sel(s) => + val selFieldName = DeforestTupSelect.getDeforestSelNameFromResult(preAnalyzer.getResult(s._1)).name + val idx = c.getClsParamNames(preAnalyzer).indexWhere(_ === selFieldName) + k(args(idx)) + r match + case DeforestTupSelect(v, idx) if rewritePrepare.rewritingSelIds(r.uid.withInstId) => + k(applyPath(v)) + case DeforestTupSelect(v, idx) if rewritePrepare.selIdsInAllArmsToSymbolsToReplace.get(r.uid.withInstId).isDefined => + k(Value.Ref(rewritePrepare.selIdsInAllArmsToSymbolsToReplace(r.uid.withInstId))) + case call@Call(f, args) if rewritePrepare.ctorIdToFinalDest.isDefinedAt(call.uid.withInstId) => + handleCallLike(call.uid): + args.map: + case Arg(N, value) => value + case ins@Instantiate(false, cls, args) if rewritePrepare.ctorIdToFinalDest.isDefinedAt(ins.uid.withInstId) => + handleCallLike(ins.uid): + args.map: + case Arg(N, value) => value + case v@Tuple(false, elems) if rewritePrepare.ctorIdToFinalDest.isDefinedAt(v.uid.withInstId) => + handleCallLike(v.uid): + elems.map: + case Arg(N, value) => value + case s@Select(p, nme) + if s.symbol.flatMap(_.asObj).isDefined && rewritePrepare.ctorIdToFinalDest.isDefinedAt(s.uid.withInstId) => + k(matchArmsOfFusingMatches.getOrElseUpdate(s.uid.withInstId)) + case Value.Ref(l) + if l.asObj.isDefined && rewritePrepare.ctorIdToFinalDest.isDefinedAt(r.uid.withInstId) => + k(matchArmsOfFusingMatches.getOrElseUpdate(r.uid.withInstId)) + + case r @ Call(fun, args) => + val fun2 = applyPath(fun) + val args2 -> newBindings = applyArgs(args) + newBindings.foldRight(k(if (fun2 is fun) && (args2 is args) then r else Call(fun2, args2)(r.isMlsFun, r.mayRaiseEffects))): + case ((sym, res), acc) => Assign(sym, res, acc) + case Instantiate(mut, cls, args) => + val cls2 = applyPath(cls) + val args2 -> newBindings = applyArgs(args) + newBindings.foldRight(k(if (cls2 is cls) && (args2 is args) then r else Instantiate(mut, cls2, args2))): + case ((sym, res), acc) => Assign(sym, res, acc) + case Tuple(mut, elems) => + val elems2 -> newBindings = applyArgs(elems) + newBindings.foldRight(k(if (elems2 is elems) then r else Tuple(mut, elems2))): + case ((sym, res), acc) => Assign(sym, res, acc) + case Record(mut, fields) => ??? + + case _ => super.applyResult2(r)(k) + + def applyArgs(args: List[Arg]): (List[Arg], List[BlockMemberSymbol -> Result]) = + args.foldRight[(List[Arg], List[BlockMemberSymbol -> Result])](Nil -> Nil): + case (arg, (newArgs, bindings)) => + arg.value match + case s@Select(p, nme) + if s.symbol.flatMap(_.asObj).isDefined && rewritePrepare.ctorIdToFinalDest.isDefinedAt(s.uid.withInstId) => + val lambdaSym = BlockMemberSymbol("lambda", Nil, false) + val lambdaBody = matchArmsOfFusingMatches.getOrElseUpdate(s.uid.withInstId) + (Arg(arg.spread, Value.Ref(lambdaSym)) :: newArgs) -> ((lambdaSym -> lambdaBody) :: bindings) + case r@Value.Ref(l) + if l.asObj.isDefined && rewritePrepare.ctorIdToFinalDest.isDefinedAt(r.uid.withInstId) => + val lambdaSym = BlockMemberSymbol("lambda", Nil, false) + val lambdaBody = matchArmsOfFusingMatches.getOrElseUpdate(r.uid.withInstId) + (Arg(arg.spread, Value.Ref(lambdaSym)) :: newArgs) -> ((lambdaSym -> lambdaBody) :: bindings) + case _ => + val newArg = applyArg(arg) + (newArg :: newArgs) -> bindings + + + + override def applyPath(p: Path): Path = p match + // a selection which is a consumer on its own + case Select(qual, _) if rewritePrepare.rewritingSelIds(p.uid.withInstId) => applyPath(qual) + // a selection inside a fusing match that needs to be replaced by pre-computed symbols + case s: Select if rewritePrepare.selIdsInAllArmsToSymbolsToReplace.get(s.uid.withInstId).isDefined => + Value.Ref(rewritePrepare.selIdsInAllArmsToSymbolsToReplace(s.uid.withInstId)) + case s@Select(p, nme) => s.symbol.flatMap(_.asObj) match + // a fusing object constructor + case Some(obj) if rewritePrepare.ctorIdToFinalDest.isDefinedAt(s.uid.withInstId) => + lastWords("unreachable") + case _ => s.symbol.flatMap(_.asBlkMember) match + case Some(blk) if blk.isFunction && preAnalyzer.topLevelDefinedFunSyms.contains(blk) => + val inTheSameRecursiveGroup = instId.lastOption.fold(false): currentReferSite => + val currentSym = preAnalyzer.getReferredFunSym(currentReferSite) + rewritePrepare.sol.collector.funSymToProdStratScheme.recursiveGroups(currentSym).contains(blk) + val newInstId = if inTheSameRecursiveGroup then instId else instId :+ s.uid + rewritePrepare.instIdToMappingFromOldToNewSyms.get(newInstId).fold(super.applyPath(s)): m => + if m(blk) is blk then + // the new symbol being the same as the old symbol means + // that this refer site should refer to the in-place rewritten + // function, and to refer to the function defined in the original + // place the selection is still needed. + s + else + Value.Ref(m(blk)) + case _ => super.applyPath(s) + case v: Value => applyValue(v) + case _ => super.applyPath(p) + + override def applyValue(v: Value): Value = v match + case r@Value.Ref(l) => l.asObj match + case Some(obj) if rewritePrepare.ctorIdToFinalDest.isDefinedAt(r.uid.withInstId) => + lastWords("unreachable") + case None => l.asBlkMember match + case Some(blk) if blk.isFunction && preAnalyzer.topLevelDefinedFunSyms.contains(blk) => + val inTheSameRecursiveGroup = instId.lastOption.fold(false): currentReferSite => + val currentSym = preAnalyzer.getReferredFunSym(currentReferSite) + rewritePrepare.sol.collector.funSymToProdStratScheme.recursiveGroups(currentSym).contains(blk) + val newInstId = if inTheSameRecursiveGroup then instId else instId :+ r.uid + rewritePrepare.instIdToMappingFromOldToNewSyms.get(newInstId).fold(super.applyValue(v)): m => + Value.Ref(m(blk)) + case _ => + preAnalyzer.importedInfo.innerSymbolsToOutterSymbols + .find: (in, out) => + l is in + .fold(super.applyValue(v)): (in, out) => + Value.Ref(out) + case _ => super.applyValue(v) + case _ => super.applyValue(v) + + override def applyFunDefn(fun: FunDefn): FunDefn = + if instId.isEmpty then + preAnalyzer.dummyRefsToTopLevelLikeFuns.get(fun.sym) match + case Some(ref) => + val param = fun.params + val body = fun.body + val oldToNewParam = mutable.Map.empty[VarSymbol, VarSymbol] + val newParam = param.map: + case ParamList(flags, params, restParam) => + def makeNewParam(p: Param) = + val Param(flags, sym, sign, modulefulness) = p + val newSym = VarSymbol(sym.id) + oldToNewParam += sym -> newSym + Param(flags, newSym, sign, modulefulness) + val newParams = params.map(makeNewParam) + val newRestParam = restParam.map(makeNewParam) + ParamList(flags, newParams, newRestParam) + val newBody = Transform(ref.uid :: Nil)(body).replaceSymbols(oldToNewParam.toMap) + FunDefn(fun.owner, fun.sym, newParam, newBody) + case None => fun // skip other top level functions + else + super.applyFunDefn(fun) + def apply(b: Block) = + applyBlock(b) + + + +// Compute free vars for a block, without considering deforestation. +// Used on blocks after the deforestation transformation. +// This means that for matches we don't need to consider the extra +// free vars that may be introduced by deforestation: +// 1. the free vars from the `rest` of the their parent matches +// 2. the free vars caused by the substitution of selections of scrutinees of their parent matches +class FreeVarTraverser(val blk: Block, alwaysDefined: Set[Symbol]) extends BlockTraverser: + protected val ctx = mutable.Set.from(alwaysDefined) + protected val result = mutable.Set.empty[Symbol] + + override def applyBlock(b: Block): Unit = b match + case Match(scrut, arms, dflt, rest) => + applyPath(scrut) + (arms.map(_._2) ++ dflt).foreach: a => + // dflt may just be `throw error``, and `rest` may use vars assigned in non default arms. + // So use `flattened` to remove dead code (after `throw error`) and spurious free vars. + val realArm = Begin(a, rest) + applyBlock(realArm) + + case Assign(lhs, rhs, rest) => + applyResult(rhs) + ctx += lhs + applyBlock(rest) + ctx -= lhs + case Begin(sub, rest) => applyBlock(b.flattened) + case Define(defn, rest) => defn match + case FunDefn(owner, sym, params, body) => + val paramSymbols = params.flatMap: + case ParamList(_, params, restParam) => (params ++ restParam).map: + case Param(_, sym, _, _) => sym + ctx += sym + ctx ++= paramSymbols + applyBlock(body) + ctx --= paramSymbols + applyBlock(rest) + ctx -= sym + case ValDefn(_, sym, rhs) => + ctx += sym + applyPath(rhs) + applyBlock(rest) + ctx -= sym + case c: ClsLikeDefn => die // not supported + + case _ => super.applyBlock(b) + + override def applyValue(v: Value): Unit = v match + case Value.Ref(l) => l match + // builtin symbols and toplevel symbols are always in scope + case _: (BuiltinSymbol | TopLevelSymbol) => () + // NOTE: assume all class definitions are in the toplevel + case b if b.asClsLike.isDefined || b.asMod.isDefined => () + case _ => if !ctx.contains(l) then result += l + case _ => super.applyValue(v) + + override def applyLam(l: Lambda): Unit = + val paramSymbols = l.params.params.map(p => p.sym) + ctx ++= paramSymbols + applyBlock(l.body) + ctx --= paramSymbols + + lazy val freeVars = + applyBlock(blk) + (result.diff(blk.definedVars)).toList.sortBy(_.uid) + +// Used on match blocks before deforestation transformation +// Compute free vars considering new vars introduced by deforestation +class FreeVarTraverserForMatchConsideringDeforestation( + matchId: MatchId, + drwp: DeforestRewritePrepare +) extends FreeVarTraverser(drwp.preAnalyzer.matchScrutToMatchBlock(matchId._1), drwp.alwaysNonFreeVars): + given dState: Deforest.State = drwp.dState + val instantiationId = matchId._2 + val preAnalyzer = drwp.preAnalyzer + + val selsReplacementByCurrentMatch = + drwp.fusingMatchIdToVarSymbolsToReplacedInAllBranches.getOrElse[Map[SelId, VarSymbol | TempSymbol]](matchId, Map.empty) ++ + drwp.fusingMatchIdToTmpSymbolsToReplacedInAllBranches.getOrElse(matchId, Map.empty) + val selsReplacementNotForThisMatch = + drwp.selIdsInAllArmsToSymbolsToReplace.toMap -- + selsReplacementByCurrentMatch.keySet + val currentMatchScrutSymbol = blk.asInstanceOf[Match].scrut.asInstanceOf[Value.Ref].l + + + override def applyBlock(b: Block): Unit = b match + // a nested match + case m@Match(scrut, _, _, _) => + result ++= drwp.freeVarsOfOriginalMatchesConsideringDeforestation(scrut.uid -> instantiationId) + + // sub-matches' scruts (which are not included in freeVarsOfNonTransformedMatches) + // are also free vars + val Value.Ref(l) = scrut: @unchecked + if !ctx(l) then result += l + + // free vars in nested-matches reported by freeVarsOfNonTransformedMatches may also contain + // spurious ones: those that are going to be substitued by the current match, + // and those that are in the ctx, so we remove them now + result --= selsReplacementByCurrentMatch.values + result --= ctx + case _ => super.applyBlock(b) + + override def applyResult(r: Result): Unit = + given Elaborator.State = drwp.preAnalyzer.elabState + r match + case DeforestTupSelect(qual, name) => selsReplacementNotForThisMatch.get(r.uid -> instantiationId) match + case None => qual match + // if it is the scrut of current match and the computation containing + // this selection is moved, then the selection will be replaced and there will be no free vars + case Value.Ref(l) if l is currentMatchScrutSymbol => () + case _ => super.applyResult(r) + case Some(s) => result += s + case _ => super.applyResult(r) + + + override def applyPath(p: Path): Unit = p match + case p@Select(qual, name) => selsReplacementNotForThisMatch.get(p.uid -> instantiationId) match + case None => qual match + // if it is the scrut of current match and the computation containing + // this selection is moved, then the selection will be replaced and there will be no free vars + case Value.Ref(l) if l is currentMatchScrutSymbol => () + case _ => super.applyPath(p) + case Some(s) => result += s + case _ => super.applyPath(p) + + override lazy val freeVars: List[Symbol] = + val Match(_, arms, dflt, rest) = blk: @unchecked + val parentMatchRest = drwp.preAnalyzer + .matchScrutToParentMatchScruts(matchId._1) + .foldRight[Block](End("")): (p, acc) => + Begin(preAnalyzer.matchScrutToMatchBlock(p).rest, acc) + (arms.map(_._2) ++ dflt).foreach: a => + // dflt may just be `throw error``, and `rest` may use vars assigned in non default arms. + // So use `flattened` to remove dead code (after `throw error`) and spurious free vars. + // Also take care of the `rest`s of its parent match blocks. + val realArm = Begin(a, Begin(rest, parentMatchRest)).flattened + applyBlock(realArm) + (result.diff(blk.definedVars)).toList.sortBy(_.uid) + +class ReplaceLocalSymTransformer(freeVarsAndTheirNewSyms: Map[Symbol, Symbol]) extends BlockTransformer(new SymbolSubst()): + override def applyValue(v: Value): Value = v match + case Value.Ref(l) => Value.Ref(freeVarsAndTheirNewSyms.getOrElse(l, l)) + case _ => super.applyValue(v) + +class HasExplicitRetTraverser(b: Block) extends BlockTraverserShallow: + var result = false + override def applyBlock(b: Block): Unit = b match + case Return(_, imp) => result = !imp + case _ => super.applyBlock(b) + + applyBlock(b) + +class WillBeNonEndTailBlockTraverser(b: Block, instId: InstantiationId, drwp: DeforestRewritePrepare) extends BlockTraverserShallow: + given dState: Deforest.State = drwp.dState + var result = false + override def applyBlock(b: Block): Unit = b match + case Match(scrut, arms, dflt, rest) => + result = + drwp.rewritingMatchIds.contains(scrut.uid -> instId) || + rest.willBeNonEndTailBlock(instId, drwp) || + locally: + dflt.fold(true)(_.willBeNonEndTailBlock(instId, drwp)) && + arms.forall: + case (_, b) => b.willBeNonEndTailBlock(instId, drwp) + case _: End => () + case _: BlockTail => result = true + case _ => super.applyBlock(b) + + applyBlock(b) + +extension (b: Block) + def replaceSymbols(freeVarsAndTheirNewSyms: Map[Symbol, Symbol]) = + new ReplaceLocalSymTransformer(freeVarsAndTheirNewSyms).applyBlock(b) + def sortedFvsForTransformedBlocks(alwaysDefined: Set[Symbol]) = + new FreeVarTraverser(b, alwaysDefined).freeVars + def hasExplicitRet = + new HasExplicitRetTraverser(b).result + def willBeNonEndTailBlock(instId: InstantiationId, drwp: DeforestRewritePrepare) = + new WillBeNonEndTailBlockTraverser(b, instId, drwp).result + +extension (ps: Ls[VarSymbol]) + def asParamList = ParamList( + ParamListFlags.empty, + ps.map(s => Param(FldFlags.empty, s, N, Modulefulness.none)), + N) + +extension (ss: Ls[Symbol]) + def asArgsList = ss.map: s => + Arg(N, Value.Ref(s)) + +extension (instId: InstantiationId) + def makeSuffix(preAnalyzer: DeforestPreAnalyzer) = + "inst_" + instId.map(preAnalyzer.getStableResultId).mkString("_") + "_tsni" + // "inst_" + instId.toReadableCallPath(preAnalyzer) + "_tsni" + def toReadableCallPath(preAnalyzer: DeforestPreAnalyzer) = + instId.map(x => preAnalyzer.getReferredFunSym(x).nme).mkString("_") + // instId.map(x => preAnalyzer.getReferredFunSym(x).nme + s"$x").mkString("_") + +extension (clsSym: ClassSymbol) + def getClsParamNames(pre: DeforestPreAnalyzer) = + pre.arrBlkMemSym.store.find(_._2 is clsSym) match + case None => clsSym.tree.clsParams.map(_.nme) + case Some(n, _) => Ls.range(0, n).map(_.toString()) + def getArrClsSymSize(pre: DeforestPreAnalyzer) = + pre.arrBlkMemSym.store.find(_._2 is clsSym) match + case None => N + case Some(n, _) => S(n) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index ce66d08ffe..8af11bc8cc 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -265,6 +265,7 @@ object Elaborator: .toMap baseBuiltins ++ aliasOps.map: case (alias, base) => alias -> baseBuiltins(base) + val importedFileNameToSemBlk = mutable.Map.empty[os.Path, Blk -> BlockMemberSymbol] val andSymbol = builtinOpsMap("&&") val orSymbol = builtinOpsMap("||") def init(using State): Ctx = Ctx.empty.copy(env = Map( diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Importer.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Importer.scala index cddf5bc2a9..624ef4a8e1 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Importer.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Importer.scala @@ -41,32 +41,40 @@ class Importer: Import(sym, file.toString) case "mls" => - - val block = os.read(file) - val fph = new FastParseHelpers(block) - val origin = Origin(file, 0, fph) - - val sym = tl.trace(s">>> Importing $file"): - - // TODO add parser option to omit internal impls - - val lexer = new syntax.Lexer(origin, dbg = tl.doTrace) - val tokens = lexer.bracketedTokens - val rules = syntax.ParseRules() - val p = new syntax.Parser(origin, tokens, rules, raise, dbg = tl.doTrace): - def doPrintDbg(msg: => Str): Unit = - // if dbg then output(msg) - if dbg then tl.log(msg) - val res = p.parseAll(p.block(allowNewlines = true)) - val resBlk = new syntax.Tree.Block(res) - - given Elaborator.Ctx = prelude.copy(mode = Mode.Light).nestLocal("prelude") - val elab = Elaborator(tl, file / os.up, prelude) - elab.importFrom(resBlk) - - resBlk.definedSymbols.find(_._1 === nme) match - case Some(nme -> sym) => sym - case None => lastWords(s"File $file does not define a symbol named $nme") + val _ -> sym = + self.state.importedFileNameToSemBlk.getOrElseUpdate.curried(file): + tl.trace(s">>> Importing $file"): + val block = os.read(file) + val fph = new FastParseHelpers(block) + val origin = Origin(file, 0, fph) + + // TODO add parser option to omit internal impls + + val lexer = new syntax.Lexer(origin, dbg = tl.doTrace) + val tokens = lexer.bracketedTokens + val rules = syntax.ParseRules() + val p = new syntax.Parser(origin, tokens, rules, raise, dbg = tl.doTrace): + def doPrintDbg(msg: => Str): Unit = + // if dbg then output(msg) + if dbg then tl.log(msg) + val res = p.parseAll(p.block(allowNewlines = true)) + val resBlk = new syntax.Tree.Block(res) + + given newCtx: Elaborator.Ctx = + val shouldFullyElab = config.deforest.fold(false): dConfig => + dConfig.seethroughModules.contains(file) + if shouldFullyElab then + prelude.copy(mode = Mode.Full).nestLocal("prelude") + else + prelude.copy(mode = Mode.Light).nestLocal("prelude") + + val elab = Elaborator(tl, file / os.up, prelude) + val (semBlk, _) = elab.importFrom(resBlk) + + + resBlk.definedSymbols.find(_._1 === nme) match + case Some(nme -> sym) => semBlk -> sym + case None => lastWords(s"File $file does not define a symbol named $nme") val jsFile = file / os.up / (file.baseName + ".mjs") Import(sym, jsFile.toString) diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index 9290b61a16..6191d088c0 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -30,6 +30,7 @@ abstract class Symbol(using State) extends Located: res def refsNumber: Int = directRefs.size + def isFunction: Bool = asBlkMember.exists(b => b.isFunctionSymbol) def existsNonModuleful: Bool = this match case mod: ModuleOrObjectSymbol => !(mod.tree.k is Mod) case mem: BlockMemberSymbol => @@ -100,6 +101,7 @@ abstract class Symbol(using State) extends Located: case S(defn: TypeLikeDef) => S(defn.bsym) case S(defn: TermDefinition) => S(defn.sym) case N => N + case _ => N /** Get the symbol corresponding to the "representative" of a set of overloaded definitions, * or the sole definition, if it is not overloaded. @@ -221,6 +223,7 @@ class BlockMemberSymbol(val nme: Str, val trees: Ls[TypeOrTermDef], val nameIsMe case t: Tree.TermDef if t.rhs.isDefined => t def isParameterizedMethod: Bool = trmTree.exists(_.isParameterizedMethod) + def isFunctionSymbol: Bool = trmTree.exists(_.k is syntax.Fun) lazy val hasLiftedClass: Bool = objTree.isDefined || trmTree.isDefined || clsTree.exists(_.paramLists.nonEmpty) diff --git a/hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala b/hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala index ea41d2df03..f3f73b7a19 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala @@ -333,6 +333,10 @@ object Tree: val DummyTup: Tup = Tup(Dummy :: Nil) def DummyTypeDef(k: TypeDefKind)(using State): TypeDef = Tree.TypeDef(k, Tree.Dummy, N) + // used in BMSs newly created during lowering to mark them as function symbols + // needed by deforestation + def DummyTermDef(k: TermDefKind)(using State): TermDef = + Tree.TermDef(k, Tree.Dummy, N) object Block: def mk(stmts: Ls[Tree])(using State): Tree = stmts match case Nil => UnitLit(false) diff --git a/hkmc2/shared/src/main/scala/hkmc2/utils/Scope.scala b/hkmc2/shared/src/main/scala/hkmc2/utils/Scope.scala index fcb5c047ac..5cde6a955f 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/utils/Scope.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/utils/Scope.scala @@ -47,7 +47,8 @@ case class Scope die def addToBindings(symbol: Local, name: String, shadow: Bool) = - if !shadow then assert(lookup(symbol).isEmpty, (symbol, this.showAsTree)) + // FIXME: deforestation makes this assertion fail + // if !shadow then assert(lookup(symbol).isEmpty, (symbol, this.showAsTree)) bindings += symbol -> name existingNames += name diff --git a/hkmc2/shared/src/test/mlscript/backlog/ToTriage.mls b/hkmc2/shared/src/test/mlscript/backlog/ToTriage.mls index a7ae413a7a..f7e1b7a6e4 100644 --- a/hkmc2/shared/src/test/mlscript/backlog/ToTriage.mls +++ b/hkmc2/shared/src/test/mlscript/backlog/ToTriage.mls @@ -292,6 +292,20 @@ id(Foo)(1) // ——— ——— ——— +if x > 0 + then A + then B +//│ ╔══[ERROR] Unexpected infix use of keyword 'then' here +//│ ║ l.295: if x > 0 +//│ ║ ^^^^^ +//│ ║ l.296: then A +//│ ╙── ^^^^^^^^ +//│ ╔══[ERROR] Name not found: B +//│ ║ l.297: then B +//│ ╙── ^ + +// ——— ——— ——— + data class Foo(...args) Foo(1, 2, 3).args @@ -300,22 +314,22 @@ Foo(1, 2, 3).args :todo if Foo(1, 2, 3) is Foo(...args) then args //│ ╔══[ERROR] Unrecognized pattern (spread) -//│ ║ l.301: if Foo(1, 2, 3) is Foo(...args) then args +//│ ║ l.315: if Foo(1, 2, 3) is Foo(...args) then args //│ ╙── ^^^^^^^ //│ ╔══[ERROR] The constructor does not take any arguments but found one argument. -//│ ║ l.301: if Foo(1, 2, 3) is Foo(...args) then args +//│ ║ l.315: if Foo(1, 2, 3) is Foo(...args) then args //│ ╙── ^^^^^^^ //│ ═══[RUNTIME ERROR] Error: match error if Foo(1, 2, 3) is Foo(a, b, c) then [a, b, c] //│ ╔══[ERROR] The constructor does not take any arguments but found three arguments. -//│ ║ l.310: if Foo(1, 2, 3) is Foo(a, b, c) then [a, b, c] +//│ ║ l.324: if Foo(1, 2, 3) is Foo(a, b, c) then [a, b, c] //│ ╙── ^^^^^^^ //│ ═══[RUNTIME ERROR] Error: match error if Foo(1, 2, 3) is Foo(arg) then arg //│ ╔══[ERROR] The constructor does not take any arguments but found one argument. -//│ ║ l.316: if Foo(1, 2, 3) is Foo(arg) then arg +//│ ║ l.330: if Foo(1, 2, 3) is Foo(arg) then arg //│ ╙── ^^^ //│ ═══[RUNTIME ERROR] Error: match error @@ -349,10 +363,10 @@ fun foo() = let bar(x: Str): Str = x + x bar("test") //│ ╔══[ERROR] Unsupported let binding shape -//│ ║ l.349: let bar(x: Str): Str = x + x +//│ ║ l.363: let bar(x: Str): Str = x + x //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╔══[ERROR] Expected 0 arguments, got 1 -//│ ║ l.350: bar("test") +//│ ║ l.364: bar("test") //│ ╙── ^^^^^^^^ // ——— ——— ——— @@ -362,7 +376,7 @@ fun foo() = module Foo(x) //│ ╔══[COMPILATION ERROR] No definition found in scope for member 'x' //│ ╟── which references the symbol introduced here -//│ ║ l.362: module Foo(x) +//│ ║ l.376: module Foo(x) //│ ╙── ^ //│ JS (unsanitized): //│ let Foo5; @@ -386,7 +400,7 @@ module Foo(x) module Foo(val x) //│ ╔══[COMPILATION ERROR] No definition found in scope for member 'x' //│ ╟── which references the symbol introduced here -//│ ║ l.386: module Foo(val x) +//│ ║ l.400: module Foo(val x) //│ ╙── ^ //│ JS (unsanitized): //│ let Foo7; @@ -409,7 +423,7 @@ module Foo(val x) // TODO support syntax? data class Foo(mut x) //│ ╔══[ERROR] Expected a valid parameter, found 'mut'-modified identifier -//│ ║ l.410: data class Foo(mut x) +//│ ║ l.424: data class Foo(mut x) //│ ╙── ^ // ——— ——— ——— diff --git a/hkmc2/shared/src/test/mlscript/deforest/append.mls b/hkmc2/shared/src/test/mlscript/deforest/append.mls new file mode 100644 index 0000000000..ef9c60030a --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/append.mls @@ -0,0 +1,108 @@ +:js +:deforest + +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +object Nil +data class (::) Cons(h, t) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun append1(xs1, ys) = if xs1 is + h :: t then h :: append1(t, ys) + Nil then ys +fun append2(xs2, ys) = if xs2 is + h :: t then h :: append2(t, ys) + Nil then ys +fun appendThree(xs, ys, zs) = + append1(append2(xs, ys), zs) +appendThree of + id(1 :: 2 :: Nil) + id(3 :: 4 :: Nil) + id(5 :: 6 :: Nil) +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil)))))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil)))))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +// maybe the fusion target for the previous program +fun appendReified(ys, zs) = if ys is + h :: t then h :: appendReified(t, zs) + Nil then zs +fun append1(ys, zs) = ys(zs) +fun append2(xs, ys) = + if xs is + h :: t then + zs => h :: append1(append2(t, ys), zs) // normal fusion + Nil then zs => appendReified(ys, zs) // reified +fun test(xs, ys, zs) = append1(append2(xs, ys), zs) +test of + id(1 :: 2 :: Nil) + id(3 :: 4 :: Nil) + id(5 :: 6 :: Nil) +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil)))))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil)))))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun idList(l) = if l is + h :: t then h :: idList(t) + Nil then Nil +fun append(xs, ys) = if xs is + h :: t then h :: append(t, ys) + Nil then idList(ys) +fun appendThree(xs, ys, zs) = + append(append(xs, ys), zs) +appendThree of + id(1 :: 2 :: Nil) + id(3 :: 4 :: Nil) + id(5 :: 6 :: Nil) +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil)))))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:Nil)@5@inst_0_1_2_tsni --> Ref(xs)@inst_0_4_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(h)), Arg(None,Ref($tmp))))@6@inst_0_1_2_tsni --> Ref(xs)@inst_0_4_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Ref(h)), Arg(None,Ref($tmp))))@7@inst_0_1_tsni --> Ref(xs)@inst_0_4_tsni@Cons +//│ Ref(member:Nil)@5@inst_3_1_2_tsni --> Ref(xs)@inst_3_4_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(h)), Arg(None,Ref($tmp))))@6@inst_3_1_2_tsni --> Ref(xs)@inst_3_4_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Ref(h)), Arg(None,Ref($tmp))))@7@inst_3_1_tsni --> Ref(xs)@inst_3_4_tsni@Cons +//│ -------------- executing ------------- +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil)))))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun append(xs, ys) = if xs is + h :: t then h :: append(t, ys) + Nil then idList(ys) +fun concat(lss) = if lss is + hh :: tt then append(hh, concat(tt)) + Nil then Nil +concat of id of + (1 :: 2 :: Nil) :: + (3 :: 4 :: Nil) :: + (5 :: 6 :: Nil) :: Nil +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil)))))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil)))))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/hkmc2/shared/src/test/mlscript/deforest/clashes.mls b/hkmc2/shared/src/test/mlscript/deforest/clashes.mls new file mode 100644 index 0000000000..86cca6033a --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/clashes.mls @@ -0,0 +1,107 @@ +:js +:deforest + +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +data class A(x) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +data class (::) Cons(h, t) +object Nil +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun to(n) = if n > 0 then n :: to(n - 1) else Nil +fun f1(ls) = if ls is + h :: t then h + Nil then 2 +fun f2(ls) = if ls is + h :: t then h + 1 + Nil then 3 +fun badWrap(n) = + let x = to(n) + f1(x) + f2(x) + x +f1(badWrap(4)) + f2(badWrap(5)) +//│ = 10 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = 10 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +fun p(x) = A(x) +let one = p(1) +let two = p(2) +fun f1(p) = if p is A(a) then a + 1 +fun f2(p) = if p is A(b) then b + 2 +f1(one) + f2(one) + f2(two) +//│ = 9 +//│ one = A(1) +//│ two = A(2) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Ref(x))))@2@inst_0_tsni --> Ref(p)@inst_1_tsni@A +//│ -------------- executing ------------- +//│ = 9 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun p(a) = a +fun f1(a1) = if a1 is A(x1) then x1 +fun f2(a2) = if a2 is A(x2) then x2 + 1 +fun test() = + let x = A(1) + let y = A(2) + let res1 = p(if true then x else y) // both x and y flows into this callsiteres + let res2 = p(x) // x flows into this callsiteres + let res3 = p(y) // y flows into this callsiteres + // f1(res1) + f2(res1) + f1(res2) + f2(res3) + f1(res1) + f1(res2) + f2(res3) +test() +//│ = 5 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = 5 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun f1(a1) = if a1 is A(x1) then x1 +fun f2(a2) = if a2 is A(x2) then x2 + 1 +fun p(x, clashedCtor) = + if true then A(x) + else clashedCtor +let clashed = A(3) +f1(p(1, clashed)) + f2(p(2, clashed)) +//│ = 4 +//│ clashed = A(3) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = 4 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + diff --git a/hkmc2/shared/src/test/mlscript/deforest/cyclic.mls b/hkmc2/shared/src/test/mlscript/deforest/cyclic.mls new file mode 100644 index 0000000000..58fff7d59f --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/cyclic.mls @@ -0,0 +1,309 @@ +:js + +data class A(x) +data class B(x) +data object C +data object D +data class (::) Cons(h, t) +object Nil +object None +data class Some(x) + + + + + + +:deforest +fun test() = + fun f(a) = if a is + C then C + else D + (x => 0)(f(f(C))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:C)@1@inst_0_tsni --> Ref(a)@inst_0_tsni@C +//│ Ref(member:C)@2@inst_0_tsni --> Ref(a)@inst_0_tsni@C +//│ Ref(member:D)@3@inst_0_tsni --> Ref(a)@inst_0_tsni@dflt +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +:deforest +fun maxOpt(ls) = if ls is + Nil then None + h :: t then + if maxOpt(t) is + None then Some(h) + Some(m) then if m > h then Some(m) else Some(h) +drop maxOpt(id(1 :: 2 :: Nil)) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:None)@1@inst_0_tsni --> Ref($scrut)@inst_0_tsni@None +//│ Call(Ref(member:Some),List(Arg(None,Ref(m))))@2@inst_0_tsni --> Ref($scrut)@inst_0_tsni@Some +//│ Call(Ref(member:Some),List(Arg(None,Ref(h))))@3@inst_0_tsni --> Ref($scrut)@inst_0_tsni@Some +//│ Call(Ref(member:Some),List(Arg(None,Ref(h))))@4@inst_0_tsni --> Ref($scrut)@inst_0_tsni@Some +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +:deforest +:sjs +fun modSome(x, m) = if x is + Some(n) and + n >= m then modSome(Some(n - m), m) + else Some(n) + None then None +modSome(Some(17), 3) +//│ JS (unsanitized): +//│ let modSome, tmp8; +//│ modSome = function modSome(x, m) { +//│ let param0, n, scrut, tmp9, tmp10; +//│ if (x instanceof Some1.class) { +//│ param0 = x.x; +//│ n = param0; +//│ scrut = n >= m; +//│ if (scrut === true) { +//│ tmp9 = n - m; +//│ tmp10 = Some1(tmp9); +//│ return modSome(tmp10, m) +//│ } else { +//│ return Some1(n) +//│ } +//│ } else if (x instanceof None1.class) { +//│ return None1 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ tmp8 = Some1(17); +//│ modSome(tmp8, 3) +//│ >>>>>>>>>>>>>>>>>>>>>>>>> Deforestation JS >>>>>>>>>>>>>>>>>>>>>>>>>> +//│ const definitionMetadata1 = globalThis.Symbol.for("mlscript.definitionMetadata"); +//│ const prettyPrint1 = globalThis.Symbol.for("mlscript.prettyPrint"); +//│ +//│ let modSome, tmp8, modSome_inst_0_tsni, _deforest_Some_x, match_x_arm_Some_inst_0_tsni; +//│ match_x_arm_Some_inst_0_tsni = (undefined, function (m, _deforest_Some_x_inst_0_tsni) { +//│ let param0, n, scrut, tmp9, tmp10, _deforest_Some_x1; +//│ param0 = _deforest_Some_x_inst_0_tsni; +//│ n = param0; +//│ scrut = n >= m; +//│ if (scrut === true) { +//│ tmp9 = n - m; +//│ _deforest_Some_x1 = tmp9; +//│ tmp10 = (m1) => { +//│ return match_x_arm_Some_inst_0_tsni(m1, _deforest_Some_x1) +//│ }; +//│ return modSome_inst_0_tsni(tmp10, m) +//│ } else { +//│ return Some1(n) +//│ } +//│ }); +//│ modSome_inst_0_tsni = function modSome_inst_0_tsni(x, m) { +//│ return runtime.safeCall(x(m)) +//│ }; +//│ modSome = function modSome(x, m) { +//│ let param0, n, scrut, tmp9, tmp10; +//│ if (x instanceof Some1.class) { +//│ param0 = x.x; +//│ n = param0; +//│ scrut = n >= m; +//│ if (scrut === true) { +//│ tmp9 = n - m; +//│ tmp10 = Some1(tmp9); +//│ return modSome(tmp10, m) +//│ } else { +//│ return Some1(n) +//│ } +//│ } else if (x instanceof None1.class) { +//│ return None1 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ _deforest_Some_x = 17; +//│ tmp8 = (m) => { +//│ return match_x_arm_Some_inst_0_tsni(m, _deforest_Some_x) +//│ }; +//│ modSome_inst_0_tsni(tmp8, 3) +//│ <<<<<<<<<<<<<<<<<<<<<<<<< Deforestation JS <<<<<<<<<<<<<<<<<<<<<<<<<< +//│ = Some(2) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Some),List(Arg(None,Ref($tmp))))@1@inst_0_tsni --> Ref(x)@inst_0_tsni@Some +//│ Call(Ref(member:Some),List(Arg(None,Lit(IntLit(17)))))@2@inst__tsni --> Ref(x)@inst_0_tsni@Some +//│ -------------- executing ------------- +//│ = Some(2) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun maxOpt2(ls, x) = if ls is + Nil then x + h :: t and x is + None then maxOpt2(t, Some(h)) + Some(m) and + h > m then maxOpt2(t, Some(h)) + else maxOpt2(t, Some(m)) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +:sjs +fun zipWith(xsys, f) = if xsys is + [hx :: tx, hy :: ty] then f(hx, hy) :: zipWith([tx, ty], f) + [Nil, Nil] then Nil +zipWith([id(Nil), id(Nil)], (x, y) => x) +//│ JS (unsanitized): +//│ let zipWith, tmp10, tmp11, tmp12, lambda; +//│ zipWith = function zipWith(xsys, f) { +//│ let first1, first0, param0, param1, hx, tx, param01, param11, hy, ty, tmp13, tmp14, tmp15; +//│ if (runtime.Tuple.isArrayLike(xsys) && xsys.length === 2) { +//│ first0 = runtime.Tuple.get(xsys, 0); +//│ first1 = runtime.Tuple.get(xsys, 1); +//│ if (first0 instanceof Cons1.class) { +//│ param0 = first0.h; +//│ param1 = first0.t; +//│ hx = param0; +//│ tx = param1; +//│ if (first1 instanceof Cons1.class) { +//│ param01 = first1.h; +//│ param11 = first1.t; +//│ hy = param01; +//│ ty = param11; +//│ tmp13 = runtime.safeCall(f(hx, hy)); +//│ tmp14 = globalThis.Object.freeze([ +//│ tx, +//│ ty +//│ ]); +//│ tmp15 = zipWith(tmp14, f); +//│ return Cons1(tmp13, tmp15) +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else if (first0 instanceof Nil1.class) { +//│ if (first1 instanceof Nil1.class) { +//│ return Nil1 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ tmp10 = Predef.id(Nil1); +//│ tmp11 = Predef.id(Nil1); +//│ tmp12 = globalThis.Object.freeze([ +//│ tmp10, +//│ tmp11 +//│ ]); +//│ lambda = (undefined, function (x, y) { return x }); +//│ zipWith(tmp12, lambda) +//│ >>>>>>>>>>>>>>>>>>>>>>>>> Deforestation JS >>>>>>>>>>>>>>>>>>>>>>>>>> +//│ const definitionMetadata1 = globalThis.Symbol.for("mlscript.definitionMetadata"); +//│ const prettyPrint1 = globalThis.Symbol.for("mlscript.prettyPrint"); +//│ +//│ let zipWith, tmp10, tmp11, tmp12, lambda, zipWith_inst_0_tsni, _deforest_Deforest_Arr_2_0, _deforest_Deforest_Arr_2_1, match_xsys_arm_Deforest_Arr_2_inst_0_tsni; +//│ match_xsys_arm_Deforest_Arr_2_inst_0_tsni = (undefined, function (f, _deforest_Deforest_Arr_2_0_inst_0_tsni, _deforest_Deforest_Arr_2_1_inst_0_tsni) { +//│ let first1, first0, param0, param1, hx, tx, param01, param11, hy, ty, tmp13, tmp14, tmp15, _deforest_Deforest_Arr_2_01, _deforest_Deforest_Arr_2_11; +//│ first0 = _deforest_Deforest_Arr_2_0_inst_0_tsni; +//│ first1 = _deforest_Deforest_Arr_2_1_inst_0_tsni; +//│ if (first0 instanceof Cons1.class) { +//│ param0 = first0.h; +//│ param1 = first0.t; +//│ hx = param0; +//│ tx = param1; +//│ if (first1 instanceof Cons1.class) { +//│ param01 = first1.h; +//│ param11 = first1.t; +//│ hy = param01; +//│ ty = param11; +//│ tmp13 = runtime.safeCall(f(hx, hy)); +//│ _deforest_Deforest_Arr_2_01 = tx; +//│ _deforest_Deforest_Arr_2_11 = ty; +//│ tmp14 = (f1) => { +//│ return match_xsys_arm_Deforest_Arr_2_inst_0_tsni(f1, _deforest_Deforest_Arr_2_01, _deforest_Deforest_Arr_2_11) +//│ }; +//│ tmp15 = zipWith_inst_0_tsni(tmp14, f); +//│ return Cons1(tmp13, tmp15) +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else if (first0 instanceof Nil1.class) { +//│ if (first1 instanceof Nil1.class) { +//│ return Nil1 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }); +//│ zipWith_inst_0_tsni = function zipWith_inst_0_tsni(xsys, f) { +//│ return runtime.safeCall(xsys(f)) +//│ }; +//│ zipWith = function zipWith(xsys, f) { +//│ let first1, first0, param0, param1, hx, tx, param01, param11, hy, ty, tmp13, tmp14, tmp15; +//│ if (runtime.Tuple.isArrayLike(xsys) && xsys.length === 2) { +//│ first0 = runtime.Tuple.get(xsys, 0); +//│ first1 = runtime.Tuple.get(xsys, 1); +//│ if (first0 instanceof Cons1.class) { +//│ param0 = first0.h; +//│ param1 = first0.t; +//│ hx = param0; +//│ tx = param1; +//│ if (first1 instanceof Cons1.class) { +//│ param01 = first1.h; +//│ param11 = first1.t; +//│ hy = param01; +//│ ty = param11; +//│ tmp13 = runtime.safeCall(f(hx, hy)); +//│ tmp14 = globalThis.Object.freeze([ +//│ tx, +//│ ty +//│ ]); +//│ tmp15 = zipWith(tmp14, f); +//│ return Cons1(tmp13, tmp15) +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else if (first0 instanceof Nil1.class) { +//│ if (first1 instanceof Nil1.class) { +//│ return Nil1 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ tmp10 = Predef.id(Nil1); +//│ tmp11 = Predef.id(Nil1); +//│ _deforest_Deforest_Arr_2_0 = tmp10; +//│ _deforest_Deforest_Arr_2_1 = tmp11; +//│ tmp12 = (f) => { +//│ return match_xsys_arm_Deforest_Arr_2_inst_0_tsni(f, _deforest_Deforest_Arr_2_0, _deforest_Deforest_Arr_2_1) +//│ }; +//│ lambda = (undefined, function (x, y) { return x }); +//│ zipWith_inst_0_tsni(tmp12, lambda) +//│ <<<<<<<<<<<<<<<<<<<<<<<<< Deforestation JS <<<<<<<<<<<<<<<<<<<<<<<<<< +//│ = Nil +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Tuple(false,List(Arg(None,Ref(tx)), Arg(None,Ref(ty))))@1@inst_0_tsni --> Ref(xsys)@inst_0_tsni@Deforest_Arr_2 +//│ Tuple(false,List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@2@inst__tsni --> Ref(xsys)@inst_0_tsni@Deforest_Arr_2 +//│ -------------- executing ------------- +//│ = Nil +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/hkmc2/shared/src/test/mlscript/deforest/determinism.mls b/hkmc2/shared/src/test/mlscript/deforest/determinism.mls new file mode 100644 index 0000000000..1e9598e11f --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/determinism.mls @@ -0,0 +1,203 @@ +:js + +data class A(a) +data class B(a, b, c, d, e) + +:deforest +:sjs +if B(1,2,3,4,5) is + B(a,b,c,d,e) then 0 +//│ JS (unsanitized): +//│ let scrut, param0, param1, param2, param3, param4, a, b, c, d, e; +//│ scrut = B1(1, 2, 3, 4, 5); +//│ if (scrut instanceof B1.class) { +//│ param0 = scrut.a; +//│ param1 = scrut.b; +//│ param2 = scrut.c; +//│ param3 = scrut.d; +//│ param4 = scrut.e; +//│ a = param0; +//│ b = param1; +//│ c = param2; +//│ d = param3; +//│ e = param4; +//│ 0 +//│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } +//│ >>>>>>>>>>>>>>>>>>>>>>>>> Deforestation JS >>>>>>>>>>>>>>>>>>>>>>>>>> +//│ const definitionMetadata1 = globalThis.Symbol.for("mlscript.definitionMetadata"); +//│ const prettyPrint1 = globalThis.Symbol.for("mlscript.prettyPrint"); +//│ +//│ let scrut, _deforest_B_a, _deforest_B_b, _deforest_B_c, _deforest_B_d, _deforest_B_e; +//│ _deforest_B_a = 1; +//│ _deforest_B_b = 2; +//│ _deforest_B_c = 3; +//│ _deforest_B_d = 4; +//│ _deforest_B_e = 5; +//│ scrut = () => { +//│ let param0, param1, param2, param3, param4, a, b, c, d, e; +//│ param0 = _deforest_B_a; +//│ param1 = _deforest_B_b; +//│ param2 = _deforest_B_c; +//│ param3 = _deforest_B_d; +//│ param4 = _deforest_B_e; +//│ a = param0; +//│ b = param1; +//│ c = param2; +//│ d = param3; +//│ e = param4; +//│ return 0 +//│ }; +//│ runtime.safeCall(scrut()) +//│ <<<<<<<<<<<<<<<<<<<<<<<<< Deforestation JS <<<<<<<<<<<<<<<<<<<<<<<<<< +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:B),List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(2))), Arg(None,Lit(IntLit(3))), Arg(None,Lit(IntLit(4))), Arg(None,Lit(IntLit(5)))))@0@inst__tsni --> Ref($scrut)@inst__tsni@B +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:sjs +:deforest +fun c2(x) = if x is + A(A(A(A(A(A(a)))))) then a +c2 of A(A(A(A(A(A(1)))))) +//│ JS (unsanitized): +//│ let c2, tmp, tmp1, tmp2, tmp3, tmp4, tmp5; +//│ c2 = function c2(x) { +//│ let param01, param02, param03, param04, param05, param06, a1; +//│ if (x instanceof A1.class) { +//│ param01 = x.a; +//│ if (param01 instanceof A1.class) { +//│ param02 = param01.a; +//│ if (param02 instanceof A1.class) { +//│ param03 = param02.a; +//│ if (param03 instanceof A1.class) { +//│ param04 = param03.a; +//│ if (param04 instanceof A1.class) { +//│ param05 = param04.a; +//│ if (param05 instanceof A1.class) { +//│ param06 = param05.a; +//│ a1 = param06; +//│ return a1 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ tmp = A1(1); +//│ tmp1 = A1(tmp); +//│ tmp2 = A1(tmp1); +//│ tmp3 = A1(tmp2); +//│ tmp4 = A1(tmp3); +//│ tmp5 = A1(tmp4); +//│ c2(tmp5) +//│ >>>>>>>>>>>>>>>>>>>>>>>>> Deforestation JS >>>>>>>>>>>>>>>>>>>>>>>>>> +//│ const definitionMetadata1 = globalThis.Symbol.for("mlscript.definitionMetadata"); +//│ const prettyPrint1 = globalThis.Symbol.for("mlscript.prettyPrint"); +//│ +//│ let c2, tmp, tmp1, tmp2, tmp3, tmp4, tmp5, c2_inst_0_tsni, _deforest_A_a, _deforest_A_a1, _deforest_A_a2, _deforest_A_a3, _deforest_A_a4, _deforest_A_a5; +//│ c2_inst_0_tsni = function c2_inst_0_tsni(x) { +//│ return runtime.safeCall(x()) +//│ }; +//│ c2 = function c2(x) { +//│ let param01, param02, param03, param04, param05, param06, a1; +//│ if (x instanceof A1.class) { +//│ param01 = x.a; +//│ if (param01 instanceof A1.class) { +//│ param02 = param01.a; +//│ if (param02 instanceof A1.class) { +//│ param03 = param02.a; +//│ if (param03 instanceof A1.class) { +//│ param04 = param03.a; +//│ if (param04 instanceof A1.class) { +//│ param05 = param04.a; +//│ if (param05 instanceof A1.class) { +//│ param06 = param05.a; +//│ a1 = param06; +//│ return a1 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ _deforest_A_a5 = 1; +//│ tmp = () => { +//│ let param01, a1; +//│ param01 = _deforest_A_a5; +//│ a1 = param01; +//│ return a1 +//│ }; +//│ _deforest_A_a4 = tmp; +//│ tmp1 = () => { +//│ let param01; +//│ param01 = _deforest_A_a4; +//│ return runtime.safeCall(param01()) +//│ }; +//│ _deforest_A_a3 = tmp1; +//│ tmp2 = () => { +//│ let param01; +//│ param01 = _deforest_A_a3; +//│ return runtime.safeCall(param01()) +//│ }; +//│ _deforest_A_a2 = tmp2; +//│ tmp3 = () => { +//│ let param01; +//│ param01 = _deforest_A_a2; +//│ return runtime.safeCall(param01()) +//│ }; +//│ _deforest_A_a1 = tmp3; +//│ tmp4 = () => { +//│ let param01; +//│ param01 = _deforest_A_a1; +//│ return runtime.safeCall(param01()) +//│ }; +//│ _deforest_A_a = tmp4; +//│ tmp5 = () => { +//│ let param01; +//│ param01 = _deforest_A_a; +//│ return runtime.safeCall(param01()) +//│ }; +//│ c2_inst_0_tsni(tmp5) +//│ <<<<<<<<<<<<<<<<<<<<<<<<< Deforestation JS <<<<<<<<<<<<<<<<<<<<<<<<<< +//│ = 1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(x)@inst_0_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Ref($tmp))))@2@inst__tsni --> Ref($param0)@inst_0_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Ref($tmp))))@3@inst__tsni --> Ref($param0)@inst_0_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Ref($tmp))))@4@inst__tsni --> Ref($param0)@inst_0_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Ref($tmp))))@5@inst__tsni --> Ref($param0)@inst_0_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(1)))))@6@inst__tsni --> Ref($param0)@inst_0_tsni@A +//│ -------------- executing ------------- +//│ = 1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/hkmc2/shared/src/test/mlscript/deforest/imperative.mls b/hkmc2/shared/src/test/mlscript/deforest/imperative.mls new file mode 100644 index 0000000000..5e913d2e73 --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/imperative.mls @@ -0,0 +1,69 @@ +:js +:deforest + +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +object A +object B +// object C +// class AA(aa) +// class BB(bb) +// object None +// class Some(value) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +// * Not fused: two `x is A` consumers +let x = if true then A else B +fun foo(x) = + if x is A do print(123) + if x is + A then 1 + B then 2 +//│ x = A +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +// * We could make it work. But it's a special case that's probably not very important +let x = if true then A else B +fun foo(x) = + if x is A do print(123) + if x is B do print(456) +//│ x = A +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun foo(k, x) = + if x === 0 do k(A) + k of + if x > 0 + then A + else B +fun bar(v) = if v is + A then 1 + B then 2 +foo(bar, 123) +//│ = 1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:B)@2@inst_0_tsni --> Ref(v)@inst_1_tsni@B +//│ Ref(member:A)@3@inst_0_tsni --> Ref(v)@inst_1_tsni@A +//│ Ref(member:A)@4@inst_0_tsni --> Ref(v)@inst_1_tsni@A +//│ -------------- executing ------------- +//│ = 1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + diff --git a/hkmc2/shared/src/test/mlscript/deforest/listComprehension.mls b/hkmc2/shared/src/test/mlscript/deforest/listComprehension.mls new file mode 100644 index 0000000000..d53b74503c --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/listComprehension.mls @@ -0,0 +1,257 @@ +:js +:deforest + +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< +object Nil +data class (::) Cons(h, t) +data class Pair(a, b) +object A +object B +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun zip(xs_zip, ys_zip) = if + xs_zip is x :: xt and ys_zip is y :: yt then Pair(x, y) :: zip(xt, yt) + else Nil +fun enumFromTo(a, b) = if a < (b + 1) then a :: enumFromTo(a + 1, b) else Nil +fun test() = + fun lscomp1(ls) = if ls is + Pair(x, y1) :: t then + fun lscomp2(ls2) = if ls2 is + Pair(y2, z) :: t2 and + y1 == y2 then Pair(x, z) :: lscomp2(t2) + else lscomp2(t2) + else lscomp1(t) + lscomp2(zip(enumFromTo(x, x + 2), enumFromTo(y1, y1 + 1))) + else Nil + lscomp1(zip(enumFromTo(1, 3), enumFromTo(2, 4))) +test() +//│ = Cons(Pair(1, 3), Cons(Pair(2, 4), Cons(Pair(3, 5), Nil))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@8@inst_0_1_tsni --> Ref(xs_zip)@inst_0_3_tsni@Cons +//│ Ref(member:Nil)@9@inst_0_1_tsni --> Ref(xs_zip)@inst_0_3_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@8@inst_0_2_tsni --> Ref(ys_zip)@inst_0_3_tsni@Cons +//│ Ref(member:Nil)@9@inst_0_2_tsni --> Ref(ys_zip)@inst_0_3_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@10@inst_0_3_tsni --> Ref(ls2)@inst_0_tsni@Cons +//│ Ref(member:Nil)@11@inst_0_3_tsni --> Ref(ls2)@inst_0_tsni@dflt +//│ Ref(member:Nil)@12@inst_0_3_tsni --> Ref(ls2)@inst_0_tsni@dflt +//│ Call(Ref(member:Pair),List(Arg(None,Ref(x)), Arg(None,Ref(y))))@13@inst_0_3_tsni --> Ref($param0)@inst_0_tsni@Pair +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@8@inst_0_4_tsni --> Ref(xs_zip)@inst_0_6_tsni@Cons +//│ Ref(member:Nil)@9@inst_0_4_tsni --> Ref(xs_zip)@inst_0_6_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@8@inst_0_5_tsni --> Ref(ys_zip)@inst_0_6_tsni@Cons +//│ Ref(member:Nil)@9@inst_0_5_tsni --> Ref(ys_zip)@inst_0_6_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@10@inst_0_6_tsni --> Ref(ls)@inst_0_tsni@Cons +//│ Ref(member:Nil)@11@inst_0_6_tsni --> Ref(ls)@inst_0_tsni@dflt +//│ Ref(member:Nil)@12@inst_0_6_tsni --> Ref(ls)@inst_0_tsni@dflt +//│ Call(Ref(member:Pair),List(Arg(None,Ref(x)), Arg(None,Ref(y))))@13@inst_0_6_tsni --> Ref($param0)@inst_0_tsni@Pair +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@8@inst_7_1_tsni --> Ref(xs_zip)@inst_7_3_tsni@Cons +//│ Ref(member:Nil)@9@inst_7_1_tsni --> Ref(xs_zip)@inst_7_3_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@8@inst_7_2_tsni --> Ref(ys_zip)@inst_7_3_tsni@Cons +//│ Ref(member:Nil)@9@inst_7_2_tsni --> Ref(ys_zip)@inst_7_3_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@10@inst_7_3_tsni --> Ref(ls2)@inst_7_tsni@Cons +//│ Ref(member:Nil)@11@inst_7_3_tsni --> Ref(ls2)@inst_7_tsni@dflt +//│ Ref(member:Nil)@12@inst_7_3_tsni --> Ref(ls2)@inst_7_tsni@dflt +//│ Call(Ref(member:Pair),List(Arg(None,Ref(x)), Arg(None,Ref(y))))@13@inst_7_3_tsni --> Ref($param0)@inst_7_tsni@Pair +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@8@inst_7_4_tsni --> Ref(xs_zip)@inst_7_6_tsni@Cons +//│ Ref(member:Nil)@9@inst_7_4_tsni --> Ref(xs_zip)@inst_7_6_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@8@inst_7_5_tsni --> Ref(ys_zip)@inst_7_6_tsni@Cons +//│ Ref(member:Nil)@9@inst_7_5_tsni --> Ref(ys_zip)@inst_7_6_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@10@inst_7_6_tsni --> Ref(ls)@inst_7_tsni@Cons +//│ Ref(member:Nil)@11@inst_7_6_tsni --> Ref(ls)@inst_7_tsni@dflt +//│ Ref(member:Nil)@12@inst_7_6_tsni --> Ref(ls)@inst_7_tsni@dflt +//│ Call(Ref(member:Pair),List(Arg(None,Ref(x)), Arg(None,Ref(y))))@13@inst_7_6_tsni --> Ref($param0)@inst_7_tsni@Pair +//│ -------------- executing ------------- +//│ = Cons(Pair(1, 3), Cons(Pair(2, 4), Cons(Pair(3, 5), Nil))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun append(xs, ys) = if xs is + h :: t then h :: append(t, ys) + Nil then ys +fun concatMap(f, ls) = if ls is + h :: t then append(f(h), concatMap(f, t)) + Nil then Nil +fun test() = + fun f1(a1) = if a1 is + Pair(a, b) then + fun f2(a2) = if a2 is Pair(c, d) then Pair(a, c) :: Nil else Nil + concatMap(f2, Pair(1, 3) :: Pair(2, 3) :: Pair(a, b) :: Nil) + else Nil + concatMap(f1, Pair(5, 10) :: Nil) +test() +//│ = Cons(Pair(5, 1), Cons(Pair(5, 2), Cons(Pair(5, 5), Nil))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref(member:Nil))))@5@inst_0_tsni --> Ref(xs)@inst_0_1_2_tsni@Cons +//│ Ref(member:Nil)@6@inst_0_tsni --> Ref(xs)@inst_0_1_2_tsni@Nil +//│ Ref(member:Nil)@7@inst_0_tsni --> Ref(xs)@inst_0_1_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@8@inst_0_tsni --> Ref(ls)@inst_0_1_tsni@Cons +//│ Call(Ref(member:Pair),List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(3)))))@9@inst_0_tsni --> Ref(a2)@inst_0_tsni@Pair +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@10@inst_0_tsni --> Ref(ls)@inst_0_1_tsni@Cons +//│ Call(Ref(member:Pair),List(Arg(None,Lit(IntLit(2))), Arg(None,Lit(IntLit(3)))))@11@inst_0_tsni --> Ref(a2)@inst_0_tsni@Pair +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref(member:Nil))))@12@inst_0_tsni --> Ref(ls)@inst_0_1_tsni@Cons +//│ Call(Ref(member:Pair),List(Arg(None,Ref(a)), Arg(None,Ref(b))))@13@inst_0_tsni --> Ref(a2)@inst_0_tsni@Pair +//│ Ref(member:Nil)@14@inst_0_tsni --> Ref(ls)@inst_0_1_tsni@Nil +//│ Ref(member:Nil)@15@inst_0_1_tsni --> Ref(xs)@inst_0_4_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(h)), Arg(None,Ref($tmp))))@16@inst_0_1_2_tsni --> Ref(xs)@inst_0_4_2_tsni@Cons +//│ Ref(member:Nil)@17@inst_0_tsni --> Ref(xs)@inst_0_4_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref(member:Nil))))@18@inst_0_tsni --> Ref(ls)@inst_0_4_tsni@Cons +//│ Call(Ref(member:Pair),List(Arg(None,Lit(IntLit(5))), Arg(None,Lit(IntLit(10)))))@19@inst_0_tsni --> Ref(a1)@inst_0_tsni@Pair +//│ Ref(member:Nil)@20@inst_0_tsni --> Ref(ls)@inst_0_4_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref(member:Nil))))@5@inst_3_tsni --> Ref(xs)@inst_3_1_2_tsni@Cons +//│ Ref(member:Nil)@6@inst_3_tsni --> Ref(xs)@inst_3_1_2_tsni@Nil +//│ Ref(member:Nil)@7@inst_3_tsni --> Ref(xs)@inst_3_1_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@8@inst_3_tsni --> Ref(ls)@inst_3_1_tsni@Cons +//│ Call(Ref(member:Pair),List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(3)))))@9@inst_3_tsni --> Ref(a2)@inst_3_tsni@Pair +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@10@inst_3_tsni --> Ref(ls)@inst_3_1_tsni@Cons +//│ Call(Ref(member:Pair),List(Arg(None,Lit(IntLit(2))), Arg(None,Lit(IntLit(3)))))@11@inst_3_tsni --> Ref(a2)@inst_3_tsni@Pair +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref(member:Nil))))@12@inst_3_tsni --> Ref(ls)@inst_3_1_tsni@Cons +//│ Call(Ref(member:Pair),List(Arg(None,Ref(a)), Arg(None,Ref(b))))@13@inst_3_tsni --> Ref(a2)@inst_3_tsni@Pair +//│ Ref(member:Nil)@14@inst_3_tsni --> Ref(ls)@inst_3_1_tsni@Nil +//│ Ref(member:Nil)@15@inst_3_1_tsni --> Ref(xs)@inst_3_4_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(h)), Arg(None,Ref($tmp))))@16@inst_3_1_2_tsni --> Ref(xs)@inst_3_4_2_tsni@Cons +//│ Ref(member:Nil)@17@inst_3_tsni --> Ref(xs)@inst_3_4_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref(member:Nil))))@18@inst_3_tsni --> Ref(ls)@inst_3_4_tsni@Cons +//│ Call(Ref(member:Pair),List(Arg(None,Lit(IntLit(5))), Arg(None,Lit(IntLit(10)))))@19@inst_3_tsni --> Ref(a1)@inst_3_tsni@Pair +//│ Ref(member:Nil)@20@inst_3_tsni --> Ref(ls)@inst_3_4_tsni@Nil +//│ -------------- executing ------------- +//│ = Cons(Pair(5, 1), Cons(Pair(5, 2), Cons(Pair(5, 5), Nil))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun lscomp1(ls1, ls2) = if ls1 is + h1 :: t1 then lscomp2(ls2, h1, t1) + Nil then Nil +fun lscomp2(ls2, h1, t1) = if ls2 is + h2 :: t2 then Pair(h1, h2) :: lscomp2(t2, h1, t1) + Nil then lscomp1(t1, ls2) +lscomp1(1 :: 2 :: Nil, 3 :: 4 :: Nil) +//│ = Cons(Pair(1, 3), Cons(Pair(1, 4), Nil)) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(3))), Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(ls2)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(4))), Arg(None,Ref(member:Nil))))@2@inst__tsni --> Ref(ls2)@inst_0_tsni@Cons +//│ Ref(member:Nil)@3@inst__tsni --> Ref(ls2)@inst_0_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@4@inst__tsni --> Ref(ls1)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(member:Nil))))@5@inst__tsni --> Ref(ls1)@inst_0_tsni@Cons +//│ Ref(member:Nil)@6@inst__tsni --> Ref(ls1)@inst_0_tsni@Nil +//│ -------------- executing ------------- +//│ = Cons(Pair(1, 3), Cons(Pair(1, 4), Nil)) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun test(k, ls) = + fun lscomp(ls) = if ls is + h :: t then (h + 1) :: lscomp(t) + Nil then Nil + if k is + A then lscomp(ls) + B then Nil +test(A, 1 :: 2 :: 3 :: Nil) +//│ = Cons(2, Cons(3, Cons(4, Nil))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@1@inst__tsni --> Ref(k)@inst_0_tsni@A +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@2@inst__tsni --> Ref(ls)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref($tmp))))@3@inst__tsni --> Ref(ls)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil))))@4@inst__tsni --> Ref(ls)@inst_0_tsni@Cons +//│ Ref(member:Nil)@5@inst__tsni --> Ref(ls)@inst_0_tsni@Nil +//│ -------------- executing ------------- +//│ = Cons(2, Cons(3, Cons(4, Nil))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +:lift +:deforest +fun h() = + fun lscomp1(ls) = if ls is + Nil then Nil + x :: xs then + fun lscomp2(ls) = if ls is + Nil then lscomp1(xs) + y :: ys then [x, y] :: lscomp2(ys) + lscomp2(1 :: 2 :: 3 :: Nil) + lscomp1(1 :: 2 :: 3 :: Nil) +fun main() = h() +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@5@inst_0_tsni --> Ref(ls)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref($tmp))))@6@inst_0_tsni --> Ref(ls)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil))))@7@inst_0_tsni --> Ref(ls)@inst_0_tsni@Cons +//│ Ref(member:Nil)@8@inst_0_tsni --> Ref(ls)@inst_0_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@5@inst_1_2_tsni --> Ref(ls)@inst_1_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref($tmp))))@6@inst_1_2_tsni --> Ref(ls)@inst_1_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil))))@7@inst_1_2_tsni --> Ref(ls)@inst_1_2_tsni@Cons +//│ Ref(member:Nil)@8@inst_1_2_tsni --> Ref(ls)@inst_1_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@9@inst_1_tsni --> Ref(ls)@inst_1_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref($tmp))))@10@inst_1_tsni --> Ref(ls)@inst_1_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil))))@11@inst_1_tsni --> Ref(ls)@inst_1_2_tsni@Cons +//│ Ref(member:Nil)@12@inst_1_tsni --> Ref(ls)@inst_1_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@5@inst_3_4_2_tsni --> Ref(ls)@inst_3_4_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref($tmp))))@6@inst_3_4_2_tsni --> Ref(ls)@inst_3_4_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil))))@7@inst_3_4_2_tsni --> Ref(ls)@inst_3_4_2_tsni@Cons +//│ Ref(member:Nil)@8@inst_3_4_2_tsni --> Ref(ls)@inst_3_4_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@9@inst_3_4_tsni --> Ref(ls)@inst_3_4_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref($tmp))))@10@inst_3_4_tsni --> Ref(ls)@inst_3_4_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil))))@11@inst_3_4_tsni --> Ref(ls)@inst_3_4_2_tsni@Cons +//│ Ref(member:Nil)@12@inst_3_4_tsni --> Ref(ls)@inst_3_4_2_tsni@Nil +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +main() +//│ = Cons( +//│ [1, 1], +//│ Cons( +//│ [1, 2], +//│ Cons( +//│ [1, 3], +//│ Cons( +//│ [2, 1], +//│ Cons( +//│ [2, 2], +//│ Cons([2, 3], Cons([3, 1], Cons([3, 2], Cons([3, 3], Nil)))) +//│ ) +//│ ) +//│ ) +//│ ) +//│ ) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@3@inst_0_1_2_tsni --> Ref(ls)@inst_0_1_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref($tmp))))@4@inst_0_1_2_tsni --> Ref(ls)@inst_0_1_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil))))@5@inst_0_1_2_tsni --> Ref(ls)@inst_0_1_2_tsni@Cons +//│ Ref(member:Nil)@6@inst_0_1_2_tsni --> Ref(ls)@inst_0_1_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@7@inst_0_1_tsni --> Ref(ls)@inst_0_1_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref($tmp))))@8@inst_0_1_tsni --> Ref(ls)@inst_0_1_2_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil))))@9@inst_0_1_tsni --> Ref(ls)@inst_0_1_2_tsni@Cons +//│ Ref(member:Nil)@10@inst_0_1_tsni --> Ref(ls)@inst_0_1_2_tsni@Nil +//│ -------------- executing ------------- +//│ = Cons( +//│ [1, 1], +//│ Cons( +//│ [1, 2], +//│ Cons( +//│ [1, 3], +//│ Cons( +//│ [2, 1], +//│ Cons( +//│ [2, 2], +//│ Cons([2, 3], Cons([3, 1], Cons([3, 2], Cons([3, 3], Nil)))) +//│ ) +//│ ) +//│ ) +//│ ) +//│ ) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/hkmc2/shared/src/test/mlscript/deforest/nestedMatch.mls b/hkmc2/shared/src/test/mlscript/deforest/nestedMatch.mls new file mode 100644 index 0000000000..ece6de7bc2 --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/nestedMatch.mls @@ -0,0 +1,456 @@ +:js +:deforest + +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< +object A +object B +object C +data class AA(x) +data class BB(x) +data class CC(x) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +object Nil +data class Cons(h, t) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +object None +data class Some(x) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun f(x, y) = + let t = if x is + AA(a) then + let m = if a is + AA(x) then x + m + 9 + BB(b) then b + t + y +fun g(x) = if x is + AA then 0 +let a = AA(AA(3)) +f(a, 2) + g(a) + f(BB(3), 2) + f(AA(AA(4)), 5) +//│ = 37 +//│ a = AA(AA(3)) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@2@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(3)))))@3@inst__tsni --> Ref(x)@inst_1_tsni@BB +//│ -------------- executing ------------- +//│ = 37 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun f(x, y) = + let n = if x is + AA(a) then + if a is + AA(m) then m + n + 2 + y +f(AA(AA(3)), 9) + f(AA(AA(4)), 10) +//│ = 30 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@2@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(4)))))@3@inst__tsni --> Ref(a)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@4@inst__tsni --> Ref(x)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@5@inst__tsni --> Ref(a)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = 30 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun f(x) = + let n = if x is + AA(a) then + if a is + AA(m) then m + n + 2 +f(AA(AA(3))) +//│ = 5 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@2@inst__tsni --> Ref(a)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 5 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun f(x) = + let t = if x is + AA(AA(a)) then a + t + 3 +f(AA(AA(A))) + f(AA(AA(A))) +//│ = "A3A3" +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@2@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@3@inst__tsni --> Ref($param0)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@4@inst__tsni --> Ref(x)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@5@inst__tsni --> Ref($param0)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = "A3A3" +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun c2(x) = if x is + AA(AA(a)) then a +c2(AA(AA(0))) +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(0)))))@2@inst__tsni --> Ref($param0)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun f(a) = if a is + AA(BB(B)) then 3 +f(AA(BB(B))) +//│ = 3 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(a)@inst_0_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref(member:B))))@2@inst__tsni --> Ref($param0)@inst_0_tsni@BB +//│ Ref(member:B)@3@inst__tsni --> Ref($param0)@inst_0_tsni@B +//│ -------------- executing ------------- +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun test(x, y, z, i) = if x is + AA(a) then + let m = if y is + AA(a1) then a1 + i + let n = if z is + BB(a2) then a2 - i + m + n +test(AA(1), AA(2), BB(3), 4) + test(AA(1), AA(2), BB(3), 4) +//│ = 10 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(3)))))@2@inst__tsni --> Ref(z)@inst_0_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@3@inst__tsni --> Ref(y)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(1)))))@4@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(3)))))@5@inst__tsni --> Ref(z)@inst_1_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@6@inst__tsni --> Ref(y)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(1)))))@7@inst__tsni --> Ref(x)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = 10 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// only the match in the middle is fused +fun f1(x) = if x is + AA(x1) then + if x1 is + BB(x2) then + if x2 is + CC(x3) then x3 +fun f2(x) = if x is AA then "f2" +fun f3(x) = if x is CC then "f3" + x.x +fun aa(x) = AA(x) +let cc = CC("cc") +f1(aa(BB(cc))) + f2(aa(BB(CC(0)))) + f3(cc) +//│ = "ccf2f3cc" +//│ cc = CC("cc") +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref(x))))@4@inst_0_tsni --> Ref(x)@inst_2_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref(x))))@4@inst_1_tsni --> Ref(x)@inst_3_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref(cc))))@5@inst__tsni --> Ref(x1)@inst_3_tsni@BB +//│ -------------- executing ------------- +//│ = "ccf2f3cc" +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun c(x, y) = if x is + AA then + let t = if y is + A then 2 + t + x.x +let y = A +c(AA(2), y) +//│ = 4 +//│ y = A +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@1@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Ref(member:A)@2@inst__tsni --> Ref(y)@inst_0_tsni@A +//│ -------------- executing ------------- +//│ = 4 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun c(x, y) = if x is + AA then + let t = if y is + A then 2 + x.x + t + x.x +fun c2(y) = if y is A then 3 +let y = A +c(AA(2), y) + c2(y) +//│ = 9 +//│ y = A +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@1@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 9 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// need to include computations of `rest` from more than one levels of parent matches +fun test(x) = + let t = if x is + AA(AA(AA(a))) then a + AA then "3" + t + "5" +fun f(a) = if a is + AA(AA) then "0" +let p = AA(AA(AA("10"))) +test(p) + f(p) + test(AA(A)) +//│ = "105035" +//│ p = AA(AA(AA("10"))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@2@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Ref(member:A)@3@inst__tsni --> Ref($param0)@inst_0_tsni@dflt +//│ Call(Ref(member:AA),List(Arg(None,Lit(StrLit(10)))))@4@inst__tsni --> Ref($param0)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = "105035" +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +fun f(x, y) = + let tmp = BB(y + 1) + if tmp is + BB then + let m = if x is + AA then + if AA(2) is + AA(yf) then yf + if AA(3) is + AA then m + tmp.x +let aa = AA(3) +f(aa, 3) + f(aa, 4) +//│ = 13 +//│ aa = AA(3) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:BB),List(Arg(None,Ref($tmp))))@3@inst_0_tsni --> Ref(tmp)@inst_0_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@4@inst_0_tsni --> Ref($scrut)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@5@inst_0_tsni --> Ref($scrut)@inst_0_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref($tmp))))@3@inst_1_tsni --> Ref(tmp)@inst_1_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@4@inst_1_tsni --> Ref($scrut)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@5@inst_1_tsni --> Ref($scrut)@inst_1_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref($tmp))))@3@inst_2_tsni --> Ref(tmp)@inst_2_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@4@inst_2_tsni --> Ref($scrut)@inst_2_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@5@inst_2_tsni --> Ref($scrut)@inst_2_tsni@AA +//│ -------------- executing ------------- +//│ = 13 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun test(n, p, q) = + n + + if AA(0) is + AA then + let k = if p is + AA(x) then x + if q is + AA(y) then k + y +test(3, AA(2), AA(3)) + test(3, AA(2), AA(3)) +//│ = 16 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(0)))))@3@inst_0_tsni --> Ref($scrut)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(0)))))@3@inst_1_tsni --> Ref($scrut)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@4@inst__tsni --> Ref(q)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@5@inst__tsni --> Ref(p)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(0)))))@3@inst_2_tsni --> Ref($scrut)@inst_2_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@6@inst__tsni --> Ref(q)@inst_2_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@7@inst__tsni --> Ref(p)@inst_2_tsni@AA +//│ -------------- executing ------------- +//│ = 16 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun test(n, p, q, a) = + let o + if a is + A then + let k + if p is + AA(x) then + k = x + if q is + AA(y) then + o = k + y + o + n +let a = A +fun c(a) = if a is A then 0 +test(1, AA(2), AA(3), a) + test(2, AA(2), AA(3), a) + c(a) +//│ = 13 +//│ a = A +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@2@inst__tsni --> Ref(q)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@3@inst__tsni --> Ref(p)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@4@inst__tsni --> Ref(q)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@5@inst__tsni --> Ref(p)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = 13 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun test(x, y, z, i) = + let k = if x is + AA(a) then + let m = if y is + AA(a1) then a1 + i + let n = if z is + BB(a2) then a2 - i + m + n + k + i +test(AA(1), AA(2), BB(3), 4) + test(AA(1), AA(2), BB(3), 4) +//│ = 18 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(3)))))@2@inst__tsni --> Ref(z)@inst_0_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@3@inst__tsni --> Ref(y)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(1)))))@4@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(3)))))@5@inst__tsni --> Ref(z)@inst_1_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@6@inst__tsni --> Ref(y)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(1)))))@7@inst__tsni --> Ref(x)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = 18 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun test(x, y, z, i) = + let k = if x is + AA(a) then + let m = if y is + AA(a1) then a1 + i + BB(b2) then b2 - i + let n = if z is + BB(a2) then a2 - i + m + n + k + i +test(AA(1), AA(2), BB(3), 4) + test(AA(1), BB(2), BB(3), 4) +//│ = 10 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(3)))))@2@inst__tsni --> Ref(z)@inst_0_tsni@BB +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(2)))))@3@inst__tsni --> Ref(y)@inst_0_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(1)))))@4@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(3)))))@5@inst__tsni --> Ref(z)@inst_1_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@6@inst__tsni --> Ref(y)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(1)))))@7@inst__tsni --> Ref(x)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = 10 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun test(x) = + let n = if x is + AA(BB(b)) then b + AA(CC(c)) then c + else 0 + n + 3 +fun c(x) = if x is AA then 0 +fun p(x) = AA(x) +test(p(BB(3))) + test(p(CC(3))) + c(p(A)) +//│ = 12 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref(x))))@6@inst_0_tsni --> Ref(x)@inst_3_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref(x))))@6@inst_1_tsni --> Ref(x)@inst_4_tsni@AA +//│ Call(Ref(member:CC),List(Arg(None,Lit(IntLit(3)))))@7@inst__tsni --> Ref($param0)@inst_4_tsni@CC +//│ Call(Ref(member:AA),List(Arg(None,Ref(x))))@6@inst_2_tsni --> Ref(x)@inst_5_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(3)))))@8@inst__tsni --> Ref($param0)@inst_5_tsni@BB +//│ -------------- executing ------------- +//│ = 12 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + + +fun f(x, y, z, k) = + let tmp = if z then BB(y + 1) else BB(y - 1) + tmp.x + + if tmp is + BB then + let m = if x is + AA then + if AA(2) is + AA(yf) then yf + if AA(3) is + AA then m + k +f(AA(3), 3, true, 10) + f(AA(5), 4, false, 20) +//│ = 41 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@3@inst_0_tsni --> Ref($scrut)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@4@inst_0_tsni --> Ref($scrut)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@3@inst_1_tsni --> Ref($scrut)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@4@inst_1_tsni --> Ref($scrut)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(5)))))@5@inst__tsni --> Ref(x)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@3@inst_2_tsni --> Ref($scrut)@inst_2_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@4@inst_2_tsni --> Ref($scrut)@inst_2_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@6@inst__tsni --> Ref(x)@inst_2_tsni@AA +//│ -------------- executing ------------- +//│ = 41 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun test(x) = + let t = if x is + AA(AA(AA(a))) then a + t + 5 +fun f(a) = if a is + AA(AA) then 0 +let p = AA(AA(AA(10))) +test(p) + f(p) +//│ = 15 +//│ p = AA(AA(AA(10))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(10)))))@1@inst__tsni --> Ref($param0)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 15 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/hkmc2/shared/src/test/mlscript/deforest/new-dup-simple.mls b/hkmc2/shared/src/test/mlscript/deforest/new-dup-simple.mls new file mode 100644 index 0000000000..6604565eb9 --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/new-dup-simple.mls @@ -0,0 +1,628 @@ +:js + +data class A(x) +data class B(x) +data object C +data object D +data class (::) Cons(h, t) +object Nil + + + +:deforest +fun to(n, acc) = if n == 0 then acc else to(n - 1, n :: acc) +fun f1(ls1, acc) = if ls1 is + Nil then acc + h :: t then f1(t, acc + h) +fun f2(ls2, acc) = if ls2 is + Nil then acc + hh :: tt then f2(tt, acc + hh + 1) +f1(to(4, Nil), 0) + f2(to(5, Nil), 0) + f1(to(6, Nil), 0) +//│ = 51 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:Nil)@6@inst__tsni --> Ref(ls1)@inst_3_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(n)), Arg(None,Ref(acc))))@7@inst_0_tsni --> Ref(ls1)@inst_3_tsni@Cons +//│ Ref(member:Nil)@8@inst__tsni --> Ref(ls2)@inst_4_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(n)), Arg(None,Ref(acc))))@7@inst_1_tsni --> Ref(ls2)@inst_4_tsni@Cons +//│ Ref(member:Nil)@9@inst__tsni --> Ref(ls1)@inst_5_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(n)), Arg(None,Ref(acc))))@7@inst_2_tsni --> Ref(ls1)@inst_5_tsni@Cons +//│ -------------- executing ------------- +//│ = 51 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun id(x) = x +fun f1(a1) = if a1 is A then 1 +fun f2(a2) = if a2 is A then 2 +f1(id(A(1))) + f2(id(A(2))) +//│ = 3 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(2)))))@2@inst__tsni --> Ref(a2)@inst_0_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(1)))))@3@inst__tsni --> Ref(a1)@inst_1_tsni@A +//│ -------------- executing ------------- +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun p(x) = A(x) +fun wrap1(x) = p(x) +fun wrap(x) = wrap1(x) +fun f1(a1) = if a1 is A then 1 +fun f2(a2) = if a2 is A then 2 +f1(wrap(1)) + f2(wrap(2)) +//│ = 3 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Ref(x))))@6@inst_0_1_2_tsni --> Ref(a2)@inst_4_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Ref(x))))@6@inst_3_1_2_tsni --> Ref(a1)@inst_5_tsni@A +//│ -------------- executing ------------- +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun f(x) = if x == 0 then Nil else x :: g(x - 1) +fun g(y) = if y == 0 then Nil else y :: f(y - 1) +fun cons(a) = if a is + Nil then 0 + h :: t then h + cons(t) +fun cons1(a1) = if a1 is + Nil then 1 + h :: t then h + cons1(t) +cons(f(0)) + cons1(f(1)) +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:Nil)@4@inst_0_tsni --> Ref(a1)@inst_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(x)), Arg(None,Ref($tmp))))@5@inst_0_tsni --> Ref(a1)@inst_2_tsni@Cons +//│ Ref(member:Nil)@6@inst_0_tsni --> Ref(a1)@inst_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(y)), Arg(None,Ref($tmp))))@7@inst_0_tsni --> Ref(a1)@inst_2_tsni@Cons +//│ Ref(member:Nil)@4@inst_1_tsni --> Ref(a)@inst_3_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(x)), Arg(None,Ref($tmp))))@5@inst_1_tsni --> Ref(a)@inst_3_tsni@Cons +//│ Ref(member:Nil)@6@inst_1_tsni --> Ref(a)@inst_3_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(y)), Arg(None,Ref($tmp))))@7@inst_1_tsni --> Ref(a)@inst_3_tsni@Cons +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun map(ls, f) = if ls is + Nil then Nil + h :: t then f(h) :: map(t, f) +map(map(1 :: 2 :: Nil, x => x + 1), x => x * 2) +//│ = Cons(4, Cons(6, Nil)) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:Nil)@2@inst_0_tsni --> Ref(ls)@inst_1_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@3@inst_0_tsni --> Ref(ls)@inst_1_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@4@inst__tsni --> Ref(ls)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(member:Nil))))@5@inst__tsni --> Ref(ls)@inst_0_tsni@Cons +//│ Ref(member:Nil)@6@inst__tsni --> Ref(ls)@inst_0_tsni@Nil +//│ -------------- executing ------------- +//│ = Cons(4, Cons(6, Nil)) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// for selection +:deforest +fun map(ls, f) = if ls is + Nil then Nil + h :: t then f(h) :: map(t, f) +map(1 :: 2 :: Nil, x => x + 1) +//│ = Cons(2, Cons(3, Nil)) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(ls)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(member:Nil))))@2@inst__tsni --> Ref(ls)@inst_0_tsni@Cons +//│ Ref(member:Nil)@3@inst__tsni --> Ref(ls)@inst_0_tsni@Nil +//│ -------------- executing ------------- +//│ = Cons(2, Cons(3, Nil)) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// for cyclic strategies removal +:deforest +fun f(x) = if x is + A(_) then f(A(2)) + else 0 +f(Nil) +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(2)))))@1@inst_0_tsni --> Ref(x)@inst_0_tsni@A +//│ Ref(member:Nil)@2@inst__tsni --> Ref(x)@inst_0_tsni@dflt +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// for selection filter +:deforest +fun c1(x) = if x is + h :: t then + if t is + Nil then 0 +c1(1 :: Nil) +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(member:Nil))))@1@inst__tsni --> Ref(x)@inst_0_tsni@Cons +//│ Ref(member:Nil)@2@inst__tsni --> Ref(t)@inst_0_tsni@Nil +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// for selection filter +:deforest +fun f(x) = if x is + A then g1(x.x) + B then g2(x.x) +fun g1(y1) = if y1 is + A then 0 +fun g2(y2) = if y2 is + A then 1 +fun apply(f) = + let inner = A(0) + f(A(inner)) +apply(f) +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Ref(inner))))@3@inst_0_tsni --> Ref(x)@inst_1_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(0)))))@4@inst_0_tsni --> Ref(y1)@inst_1_2_tsni@A +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +:deforest +fun inner(y, z) = if y is + B then z +fun dtor(x) = if x is + A then inner(B(4), x.x) +dtor(A(B(0))) +//│ = B(0) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:B),List(Arg(None,Lit(IntLit(4)))))@3@inst_0_tsni --> Ref(y)@inst_0_2_tsni@B +//│ Call(Ref(member:B),List(Arg(None,Lit(IntLit(4)))))@3@inst_1_tsni --> Ref(y)@inst_1_2_tsni@B +//│ Call(Ref(member:A),List(Arg(None,Ref($tmp))))@4@inst__tsni --> Ref(x)@inst_1_tsni@A +//│ -------------- executing ------------- +//│ = B(0) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun localFuse(x) = if A(x) is + A(y) then B(y) +if localFuse(3) is + B(a) then a +localFuse(4) +//│ = B(4) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Ref(x))))@3@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Ref(x))))@3@inst_1_tsni --> Ref($scrut)@inst_1_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Ref(x))))@3@inst_2_tsni --> Ref($scrut)@inst_2_tsni@A +//│ Call(Ref(member:B),List(Arg(None,Ref(y))))@4@inst_2_tsni --> Ref($scrut)@inst__tsni@B +//│ -------------- executing ------------- +//│ = B(4) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +// cyclic strategy, shouldn't fuse +:deforest +fun f(x) = + let res = if x is + A(x) then x + if res > 0 then f(A(res - 1)) else 0 +f(A(4)) +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Ref($tmp))))@1@inst_0_tsni --> Ref(x)@inst_0_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(4)))))@2@inst__tsni --> Ref(x)@inst_0_tsni@A +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +// shouldn't have any fusion due to strategy clash +:deforest +fun g(x) = if x is + A(a) then a +fun f(x) = x.x +let o = A(1) +g(o) + f(o) + o.x +//│ = 3 +//│ o = A(1) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +:deforest +fun f(x) = if x is + A(x) then x +f(A(1)) +//│ = 1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(1)))))@1@inst__tsni --> Ref(x)@inst_0_tsni@A +//│ -------------- executing ------------- +//│ = 1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun f(x) = if x is + A(a) then x.x + a +f(A(1)) +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(1)))))@1@inst__tsni --> Ref(x)@inst_0_tsni@A +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +:deforest +fun p(x) = A(x) +fun wrap1(x) = p(x) +fun wrap(x) = wrap1(x) +fun f1(a1) = if a1 is A then 1 +fun f2(a2) = if a2 is A then 2 +f1(wrap(1)) + f2(wrap(2)) +//│ = 3 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Ref(x))))@6@inst_0_1_2_tsni --> Ref(a2)@inst_4_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Ref(x))))@6@inst_3_1_2_tsni --> Ref(a1)@inst_5_tsni@A +//│ -------------- executing ------------- +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun p1(x) = p2(x) +fun p2(x) = if x == 0 then A(x) else p1(x - 1) +fun c(a) = if a is A(x) then x +c(p1(3)) +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Ref(x))))@2@inst_0_tsni --> Ref(a)@inst_1_tsni@A +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +:deforest +fun f(x) = if x is + A(x) then 2 +f(A(2)) + f(A(3)) +//│ = 4 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(3)))))@2@inst__tsni --> Ref(x)@inst_0_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(2)))))@3@inst__tsni --> Ref(x)@inst_1_tsni@A +//│ -------------- executing ------------- +//│ = 4 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +// using `let` to declare local functions helps to avoid the problem +// caused by reordering nested `fun` functions. +:deforest +fun test() = + let x = if A(0) is + A then 1 + let f() = x + f() +test() +//│ = 1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(0)))))@2@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(0)))))@2@inst_1_tsni --> Ref($scrut)@inst_1_tsni@A +//│ -------------- executing ------------- +//│ = 1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:sjs +:deforest +if [1, 2] is + [a, b] then a + b +//│ JS (unsanitized): +//│ let scrut1, first1, first0, a1, b; +//│ scrut1 = globalThis.Object.freeze([ +//│ 1, +//│ 2 +//│ ]); +//│ if (runtime.Tuple.isArrayLike(scrut1) && scrut1.length === 2) { +//│ first0 = runtime.Tuple.get(scrut1, 0); +//│ first1 = runtime.Tuple.get(scrut1, 1); +//│ a1 = first0; +//│ b = first1; +//│ a1 + b +//│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } +//│ >>>>>>>>>>>>>>>>>>>>>>>>> Deforestation JS >>>>>>>>>>>>>>>>>>>>>>>>>> +//│ const definitionMetadata1 = globalThis.Symbol.for("mlscript.definitionMetadata"); +//│ const prettyPrint1 = globalThis.Symbol.for("mlscript.prettyPrint"); +//│ +//│ let scrut1, _deforest_Deforest_Arr_2_0, _deforest_Deforest_Arr_2_1; +//│ _deforest_Deforest_Arr_2_0 = 1; +//│ _deforest_Deforest_Arr_2_1 = 2; +//│ scrut1 = () => { +//│ let first1, first0, a1, b; +//│ first0 = _deforest_Deforest_Arr_2_0; +//│ first1 = _deforest_Deforest_Arr_2_1; +//│ a1 = first0; +//│ b = first1; +//│ return a1 + b +//│ }; +//│ runtime.safeCall(scrut1()) +//│ <<<<<<<<<<<<<<<<<<<<<<<<< Deforestation JS <<<<<<<<<<<<<<<<<<<<<<<<<< +//│ = 3 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Tuple(false,List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(2)))))@0@inst__tsni --> Ref($scrut)@inst__tsni@Deforest_Arr_2 +//│ -------------- executing ------------- +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun f(x) = if g(false) is + A and + x < 1 then B(0) + else f(x - 1) + C then D +fun g(b) = + if b then + if f(0) is + B then A(0) + D then A(1) + else + C +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(1)))))@2@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Call(Ref(member:A),List(Arg(None,Lit(IntLit(0)))))@3@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Ref(member:C)@4@inst_0_tsni --> Ref($scrut)@inst_0_tsni@C +//│ Call(Ref(member:B),List(Arg(None,Lit(IntLit(0)))))@5@inst_1_tsni --> Ref($scrut)@inst_1_tsni@B +//│ Ref(member:D)@6@inst_1_tsni --> Ref($scrut)@inst_1_tsni@D +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +[f(3), g(true)] +//│ = [D, A(1)] + + +// `y` should not be considered as a free var for the branch +:deforest +fun f(ls) = if ls is [] then + let y = 4 + fun h(z) = if z > 0 then h(z - 1) else y + h(3) +f([]) +//│ = 4 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Tuple(false,List())@1@inst__tsni --> Ref(ls)@inst_0_tsni@Deforest_Arr_0 +//│ -------------- executing ------------- +//│ = 4 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun f(x, b) = if x is + Nil then if b then f(Nil, false) else 0 +f(Nil, false) +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:Nil)@1@inst_0_tsni --> Ref(x)@inst_0_tsni@Nil +//│ Ref(member:Nil)@2@inst__tsni --> Ref(x)@inst_0_tsni@Nil +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun test() = + let p = A(1) + let a = if p is + A(x) then x + let b = if p is + A(x) then x + a + b +test() + test() +//│ = 4 + + +fun p(d) = A(3) +fun c1(x) = if x is A then 1 +fun c2(x) = if x is A then 2 +fun test() = + c1(p(1)) + c2(p(2)) +test() +//│ = 3 + + + +fun p(x) = A(x) +fun f1(a1) = if a1 is A(aa) then aa +fun f2(a2) = if a2 is A(aa) then aa +fun f3(a3) = if a3 is A(aa) then aa +fun f4(a4) = if a4 is A(aa) then aa +fun f5(a5) = if a5 is A(aa) then aa +f1(p(1)) + f2(p(2)) + f3(p(3)) + f4(p(4)) + f5(p(5)) +//│ = 15 + + + +// calls to `to` should be able to be duplicated +fun to(n) = + if n > 0 then + let m = n - 1 + n :: to(m) + else + Nil +fun f1(ls1) = if ls1 is + h :: t then h + f1(t) + Nil then 2 +fun f2(ls2) = if ls2 is + h :: t then h + f2(t) + Nil then 3 +fun f3(ls3) = if ls3 is + h :: t then h + f3(t) + Nil then 4 +fun f4(ls4) = if ls4 is + h :: t then h + f4(t) + Nil then 5 +f1(to(4)) + f2(to(5)) + f3(to(6)) + f4(to(7)) +//│ = 88 + + + +fun to(n) = + if n > 0 then + let m = n - 1 + n :: to(m) + else + Nil +fun f1(ls1) = if ls1 is + h :: t then h + f1(t) + Nil then 2 +f1(to(4)) +//│ = 12 + + + +fun map(ls, f) = if ls is + Nil then Nil + h :: t then f(h) :: map(t, f) +fun succ(x) = x + 1 +fun double(x) = x * 2 +fun test() = + map(map(1 :: 2 :: Nil, succ), double) +test() +//│ = Cons(4, Cons(6, Nil)) + + + +fun p(x) = A(x) +fun g1(b) = if b then p(1) else p(2) +fun wrap(b) = g1(b) +fun g2(b) = if b then p(3) else p(4) +fun f1(p) = if p is A(a) then a + 1 +fun f2(p) = if p is A(b) then b + 2 +f1(wrap(true)) + f2(g2(false)) +//│ = 8 + + + + +fun p(x) = A(x) +let one = p(1) +let two = p(2) +fun f1(p) = if p is A(a) then a + 1 +fun f2(p) = if p is A(b) then b + 2 +fun f3(p) = if p is A(c) then c + 3 +f1(one) + f2(one) + f3(two) +//│ = 10 +//│ one = A(1) +//│ two = A(2) + + + +fun id(x) = x +fun f1(a) = if a is A(i) then i +fun f2(a) = if a is A(i) then i + 1 +f1(id(A(1))) + f2(id(A(2))) +//│ = 4 + + + + + + + +fun to(n) = if n > 0 then n :: to(n - 1) else Nil +fun f1(ls) = if ls is + h :: t then h + Nil then 2 +fun f2(ls) = if ls is + h :: t then h + 1 + Nil then 3 +fun wrap(n) = to(n) +f1(wrap(4)) + f2(wrap(5)) +//│ = 10 + + + + + + +fun to(n, acc) = if n == 0 then acc else to(n - 1, n :: acc) +fun f1(ls, acc) = if ls is + Nil then acc + h :: t then f1(t, acc + h) +fun f2(ls, acc) = if ls is + Nil then acc + h :: t then f2(t, acc + h + 1) +f1(to(4, Nil), 0) + f2(to(5, Nil), 0) + f1(to(6, Nil), 0) +//│ = 51 + + + +fun map(ls, f) = if ls is + Nil then Nil + h :: t then f(h) :: map(t, f) +fun succ(x) = x + 1 +fun double(x) = x * 2 +fun triple(x) = x * 3 +fun test() = + map(map(map(1 :: 2 :: Nil, succ), double), triple) +test() +// //│ = Cons(12, Cons(18, Nil)) +// //│ duplication chances: +// //│ Call(Ref(member:map),List(Arg(false,Ref($tmp)), Arg(false,Ref(member:succ)))) <-- dup --> member:map_duplicated@1750 +// //│ Call(Ref(member:map),List(Arg(false,Ref($tmp)), Arg(false,Ref(member:double)))) <-- dup --> member:map_duplicated@1750 +// //│ ========= +// //│ No fusion opportunity +//│ = Cons(12, Cons(18, Nil)) + + + + +fun p(x) = A(x) +fun f1(a1) = if a1 is A(a) then a + 1 +fun f2(a2) = if a2 is A(a) then a + 2 +fun wrap(a) = a +fun test() = + f1(wrap(p(2))) + f2(p(1)) +test() +//│ = 6 diff --git a/hkmc2/shared/src/test/mlscript/deforest/new-todo.mls b/hkmc2/shared/src/test/mlscript/deforest/new-todo.mls new file mode 100644 index 0000000000..3bbc2ef565 --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/new-todo.mls @@ -0,0 +1,188 @@ +:js + + +data class AA(x) +data class BB(x) +object A +object B + +// TODO: should fuse `A` with the pattern match in `f`. +// This is because the same symbol is used for the `x`s +// introduced in the patterns of both branches, causing +// `A` also flows into consumers in `g1` and `g2` +:deforest +fun f(x) = if x is A then 1 else 2 +fun g1(x) = if x is A then 2 else 3 +fun g2(x) = if x is A then 3 else 4 +fun test() = + let prod = if true then AA(A) else BB(B) + if prod is + AA(x) then f(x) + BB(x) then g1(x) + g2(x) +test() +//│ = 1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@2@inst_0_tsni --> Ref(prod)@inst_0_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref(member:B))))@3@inst_0_tsni --> Ref(prod)@inst_0_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@2@inst_1_tsni --> Ref(prod)@inst_1_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref(member:B))))@3@inst_1_tsni --> Ref(prod)@inst_1_tsni@BB +//│ -------------- executing ------------- +//│ = 1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// TODO: fusion opportunity is lost +// when instantiation ids of dtors are also tracked: +// two call sites to `inner` leads to two `inner`s +// to be called, causing a clashing consumer. +:deforest +fun inner(x) = if x is A then 0 else 1 +fun outter1(x) = inner(x) +fun outter2(x) = inner(x) +fun test() = + let x = A + outter1(x) + outter2(x) +test() +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// TODO: duplicated instantiations of the consumer `f` +:sjs +:deforest +fun f(x) = if x is A then 1 +f(A) + f(A) +//│ JS (unsanitized): +//│ let f1, tmp, tmp1; +//│ f1 = function f(x) { +//│ if (x instanceof A1.class) { +//│ return 1 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ tmp = f1(A1); +//│ tmp1 = f1(A1); +//│ tmp + tmp1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>> Deforestation JS >>>>>>>>>>>>>>>>>>>>>>>>>> +//│ const definitionMetadata1 = globalThis.Symbol.for("mlscript.definitionMetadata"); +//│ const prettyPrint1 = globalThis.Symbol.for("mlscript.prettyPrint"); +//│ +//│ let f1, tmp, tmp1, f_inst_0_tsni, f_inst_1_tsni, lambda, lambda1; +//│ f_inst_0_tsni = function f_inst_0_tsni(x) { +//│ return runtime.safeCall(x()) +//│ }; +//│ f_inst_1_tsni = function f_inst_1_tsni(x) { +//│ return runtime.safeCall(x()) +//│ }; +//│ f1 = function f(x) { +//│ if (x instanceof A1.class) { +//│ return 1 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ lambda = () => { +//│ return 1 +//│ }; +//│ tmp = f_inst_1_tsni(lambda); +//│ lambda1 = () => { return 1 }; +//│ tmp1 = f_inst_0_tsni(lambda1); +//│ tmp + tmp1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<< Deforestation JS <<<<<<<<<<<<<<<<<<<<<<<<<< +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst__tsni --> Ref(x)@inst_0_tsni@A +//│ Ref(member:A)@3@inst__tsni --> Ref(x)@inst_1_tsni@A +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// NOTE: after trying to fuse both the original body and the instance's body, +// the `A` in this program is not fused anymore +:deforest +let x = A +fun f() = + if x is + A then 0 +f() +//│ = 0 +//│ x = A +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// TODO: the assignment of `useless` is moved inside the lambda body +// so on the toplevel `useless` is not assigned after transformation +:deforest +let lsit = [2, 1] +let useless = if lsit is [a, b] then 0 +//│ lsit = [2, 1] +//│ useless = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Tuple(false,List(Arg(None,Lit(IntLit(2))), Arg(None,Lit(IntLit(1)))))@0@inst__tsni --> Ref(lsit)@inst__tsni@Deforest_Arr_2 +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// TODO: to workaround this one can write `MMM.y` instead of `y` +:fixme +:deforest +module MMM with ... +val y = 3 +val x = MMM.f() +fun f() = + // if A is A then MMM.y + if A is A then y +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Ref(member:A)@2@inst_1_tsni --> Ref($scrut)@inst_1_tsni@A +//│ -------------- executing ------------- +//│ ═══[RUNTIME ERROR] ReferenceError: MMM2 is not defined +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +object C +object D + +// TODO: it's fine only when using `M.g` and `M.f` instead of `g` and `f` +:deforest +module M with ... +fun f(x) = if M.g(false) is + A and + x < 1 then B(0) + else M.f(x - 1) + C then D +fun g(b) = + if b then + if M.f(0) is + B then A + D then A + else + C +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Ref(member:A)@3@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Ref(member:C)@4@inst_0_tsni --> Ref($scrut)@inst_0_tsni@C +//│ Ref(member:D)@5@inst_1_tsni --> Ref($scrut)@inst_1_tsni@D +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +[M.f(3), M.g(true)] +//│ = [D, A] diff --git a/hkmc2/shared/src/test/mlscript/deforest/recursive.mls b/hkmc2/shared/src/test/mlscript/deforest/recursive.mls new file mode 100644 index 0000000000..cf72117f68 --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/recursive.mls @@ -0,0 +1,593 @@ +:js +:deforest + +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +object Nil +data class (::) Cons(h, t) +object None +data class Some(v) +object A +object B +data class T(n, l, r) +object L +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun mk(n) = if n < 0 then Nil else n :: mk(n - 1) +fun map(f, ls_map) = if ls_map is + h :: t then f(h) :: map(f, t) + Nil then Nil +fun map1(f, ls_map1) = if ls_map1 is + h :: t then f(h) :: map1(f, t) + Nil then Nil +fun incr(x) = x + 1 +fun double(x) = x * 2 +fun test(ls) = map1(incr, map(double, ls)) +test(id(mk(5))) +//│ = Cons(11, Cons(9, Cons(7, Cons(5, Cons(3, Cons(1, Nil)))))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@4@inst_0_1_tsni --> Ref(ls_map1)@inst_0_3_tsni@Cons +//│ Ref(member:Nil)@5@inst_0_1_tsni --> Ref(ls_map1)@inst_0_3_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@4@inst_2_1_tsni --> Ref(ls_map1)@inst_2_3_tsni@Cons +//│ Ref(member:Nil)@5@inst_2_1_tsni --> Ref(ls_map1)@inst_2_3_tsni@Nil +//│ -------------- executing ------------- +//│ = Cons(11, Cons(9, Cons(7, Cons(5, Cons(3, Cons(1, Nil)))))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil +fun map(ls) = if ls is + Nil then Nil + h :: t then (h + 4) :: map(t) +map(enumFromTo(1, 4)) +//│ = Cons(5, Cons(6, Cons(7, Nil))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@2@inst_0_tsni --> Ref(ls)@inst_1_tsni@Cons +//│ Ref(member:Nil)@3@inst_0_tsni --> Ref(ls)@inst_1_tsni@Nil +//│ -------------- executing ------------- +//│ = Cons(5, Cons(6, Cons(7, Nil))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil +fun sum(ls) = if ls is + Nil then 0 + h :: t then h + sum(t) +sum(enumFromTo(1,10)) +//│ = 45 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@2@inst_0_tsni --> Ref(ls)@inst_1_tsni@Cons +//│ Ref(member:Nil)@3@inst_0_tsni --> Ref(ls)@inst_1_tsni@Nil +//│ -------------- executing ------------- +//│ = 45 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil +fun map(f, ls) = + if ls is + Nil then Nil + h :: t then f(h) :: map(f, t) +map(x => x + 4, enumFromTo(1, 4)) +//│ = Cons(5, Cons(6, Cons(7, Nil))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@2@inst_0_tsni --> Ref(ls)@inst_1_tsni@Cons +//│ Ref(member:Nil)@3@inst_0_tsni --> Ref(ls)@inst_1_tsni@Nil +//│ -------------- executing ------------- +//│ = Cons(5, Cons(6, Cons(7, Nil))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil +fun map(f, ls) = + (if ls is + Nil then f => Nil + h :: t then f => f(h) :: map(f, t) + )(f) +map(x => x + 4, enumFromTo(1, 4)) +//│ = Cons(5, Cons(6, Cons(7, Nil))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@2@inst_0_tsni --> Ref(ls)@inst_1_tsni@Cons +//│ Ref(member:Nil)@3@inst_0_tsni --> Ref(ls)@inst_1_tsni@Nil +//│ -------------- executing ------------- +//│ = Cons(5, Cons(6, Cons(7, Nil))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil +fun sum(ls, a) = if ls is + Nil then a + h :: t then sum(t, h + a) +sum(enumFromTo(1, 10), 0) +//│ = 45 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref($tmp))))@2@inst_0_tsni --> Ref(ls)@inst_1_tsni@Cons +//│ Ref(member:Nil)@3@inst_0_tsni --> Ref(ls)@inst_1_tsni@Nil +//│ -------------- executing ------------- +//│ = 45 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun mk(n) = if n < 0 then Nil else n :: mk(n - 1) +fun incr(x) = x + 1 +fun map(f, xs_map) = if xs_map is + Nil then Nil + x :: xs then f(x) :: map(f, xs) +fun rev(xs_rev, acc) = if xs_rev is + x :: xs then rev(xs, x :: acc) + Nil then acc +fun test(xs) = map(incr, rev(xs, Nil)) +test(id(mk(5))) +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil)))))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:Nil)@4@inst_0_tsni --> Ref(xs_map)@inst_0_3_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(x)), Arg(None,Ref(acc))))@5@inst_0_1_tsni --> Ref(xs_map)@inst_0_3_tsni@Cons +//│ Ref(member:Nil)@4@inst_2_tsni --> Ref(xs_map)@inst_2_3_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(x)), Arg(None,Ref(acc))))@5@inst_2_1_tsni --> Ref(xs_map)@inst_2_3_tsni@Cons +//│ -------------- executing ------------- +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil)))))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun mk(n) = if n < 0 then Nil else n :: mk(n - 1) +fun incr(x) = x + 1 +fun map(f, xs_map) = if xs_map is + Nil then Nil + x :: xs then f(x) :: map(f, xs) +fun rev(xs_rev, acc) = if xs_rev is + x :: xs then rev(xs, x :: acc) + Nil then acc +fun test(xs) = rev(map(incr, xs), Nil) +test(id(mk(3))) +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Nil)))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:Nil)@4@inst_0_1_tsni --> Ref(xs_rev)@inst_0_3_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@5@inst_0_1_tsni --> Ref(xs_rev)@inst_0_3_tsni@Cons +//│ Ref(member:Nil)@4@inst_2_1_tsni --> Ref(xs_rev)@inst_2_3_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@5@inst_2_1_tsni --> Ref(xs_rev)@inst_2_3_tsni@Cons +//│ -------------- executing ------------- +//│ = Cons(1, Cons(2, Cons(3, Cons(4, Nil)))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +data class Pair(a, b) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun pair_up(xs) = + if xs is + x :: xss then + if xss is + y :: xs then Pair(x, y) :: pair_up(xs) + else Nil + else Nil +fun mk(n) = if n > 0 then (n - 1) :: n :: (n + 1) :: mk(n - 1) else Nil +fun test(x) = pair_up(mk(x)) +test(4) +//│ = Cons( +//│ Pair(3, 4), +//│ Cons( +//│ Pair(5, 2), +//│ Cons( +//│ Pair(3, 4), +//│ Cons(Pair(1, 2), Cons(Pair(3, 0), Cons(Pair(1, 2), Nil))) +//│ ) +//│ ) +//│ ) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = Cons( +//│ Pair(3, 4), +//│ Cons( +//│ Pair(5, 2), +//│ Cons( +//│ Pair(3, 4), +//│ Cons(Pair(1, 2), Cons(Pair(3, 0), Cons(Pair(1, 2), Nil))) +//│ ) +//│ ) +//│ ) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun mk(n) = if n > 0 then n :: mk(n - 1) else Nil +fun mk2d(n) = if n > 0 then mk(n) :: mk2d(n - 1) else Nil +fun append(xs, ys) = if xs is + Nil then ys + x :: xs then x :: append(xs, ys) +fun sum(ls_sum) = if ls_sum is + Nil then 0 + x :: xs then x + sum(xs) +fun flatten(ls_flatten) = if ls_flatten is + Nil then Nil + x :: xs then append(x, flatten(xs)) +fun test(ls) = sum(flatten(ls)) +test(id(mk2d(4))) +//│ = 20 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Ref(x)), Arg(None,Ref($tmp))))@5@inst_0_1_2_tsni --> Ref(ls_sum)@inst_0_4_tsni@Cons +//│ Ref(member:Nil)@6@inst_0_1_tsni --> Ref(ls_sum)@inst_0_4_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(x)), Arg(None,Ref($tmp))))@5@inst_3_1_2_tsni --> Ref(ls_sum)@inst_3_4_tsni@Cons +//│ Ref(member:Nil)@6@inst_3_1_tsni --> Ref(ls_sum)@inst_3_4_tsni@Nil +//│ -------------- executing ------------- +//│ = 20 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun count(c, xs) = if xs is + h :: t then count(c + 1, t) + Nil then c +fun rev(a, ys) = if ys is + h :: t then rev(h :: a, t) + Nil then a +count(0, rev(Nil, 1 :: 2 :: Nil)) +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:Nil)@2@inst__tsni --> Ref(xs)@inst_1_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(h)), Arg(None,Ref(a))))@3@inst_0_tsni --> Ref(xs)@inst_1_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@4@inst__tsni --> Ref(ys)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(member:Nil))))@5@inst__tsni --> Ref(ys)@inst_0_tsni@Cons +//│ Ref(member:Nil)@6@inst__tsni --> Ref(ys)@inst_0_tsni@Nil +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun last(ls) = if ls is + h :: t and t is + Nil then Some(h) + _ :: _ then last(t) + Nil then None +let p = 1 :: 2 :: Nil +last(p) +//│ = Some(2) +//│ p = Cons(1, Cons(2, Nil)) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = Some(2) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun map(f, xs_map) = if xs_map is + Nil then Nil + x :: xs then f(x) :: map(f, xs) +map(x => if x is A then 1 else 0, A :: B :: Nil) +//│ = Cons(1, Cons(0, Nil)) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Ref(member:A)), Arg(None,Ref($tmp))))@2@inst__tsni --> Ref(xs_map)@inst_0_tsni@Cons +//│ Ref(member:A)@3@inst__tsni --> Ref(x)@inst_1_tsni@A +//│ Call(Ref(member:Cons),List(Arg(None,Ref(member:B)), Arg(None,Ref(member:Nil))))@4@inst__tsni --> Ref(xs_map)@inst_0_tsni@Cons +//│ Ref(member:Nil)@5@inst__tsni --> Ref(xs_map)@inst_0_tsni@Nil +//│ Ref(member:B)@6@inst__tsni --> Ref(x)@inst_1_tsni@dflt +//│ -------------- executing ------------- +//│ = Cons(1, Cons(0, Nil)) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun c(x) = if x is + T(n, l, r) then T of + if n is + A then 0 + B then 1 + c(l) + c(r) + L then L +c(T(A, T(B, L, L), T(A, L, L))) +//│ = T(0, T(1, L, L), T(0, L, L)) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:T),List(Arg(None,Ref(member:A)), Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(x)@inst_0_tsni@T +//│ Ref(member:A)@2@inst__tsni --> Ref(n)@inst_0_tsni@A +//│ Call(Ref(member:T),List(Arg(None,Ref(member:A)), Arg(None,Ref(member:L)), Arg(None,Ref(member:L))))@3@inst__tsni --> Ref(x)@inst_0_tsni@T +//│ Ref(member:L)@4@inst__tsni --> Ref(x)@inst_0_tsni@L +//│ Ref(member:L)@5@inst__tsni --> Ref(x)@inst_0_tsni@L +//│ Ref(member:A)@6@inst__tsni --> Ref(n)@inst_0_tsni@A +//│ Call(Ref(member:T),List(Arg(None,Ref(member:B)), Arg(None,Ref(member:L)), Arg(None,Ref(member:L))))@7@inst__tsni --> Ref(x)@inst_0_tsni@T +//│ Ref(member:L)@8@inst__tsni --> Ref(x)@inst_0_tsni@L +//│ Ref(member:L)@9@inst__tsni --> Ref(x)@inst_0_tsni@L +//│ Ref(member:B)@10@inst__tsni --> Ref(n)@inst_0_tsni@B +//│ -------------- executing ------------- +//│ = T(0, T(1, L, L), T(0, L, L)) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun max(ms, m) = if ms is + h :: t and + h > m then max(t, h) + else max(t, m) + Nil then m +max(3 :: 2 :: 4 :: 1 :: 0 :: Nil, 0) +//│ = 4 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(3))), Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(ms)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(2))), Arg(None,Ref($tmp))))@2@inst__tsni --> Ref(ms)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(4))), Arg(None,Ref($tmp))))@3@inst__tsni --> Ref(ms)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@4@inst__tsni --> Ref(ms)@inst_0_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Lit(IntLit(0))), Arg(None,Ref(member:Nil))))@5@inst__tsni --> Ref(ms)@inst_0_tsni@Cons +//│ Ref(member:Nil)@6@inst__tsni --> Ref(ms)@inst_0_tsni@Nil +//│ -------------- executing ------------- +//│ = 4 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun filter(ls, f) = if ls is + h :: t and + f(h) then h :: filter(t, f) + else filter(t, f) + Nil then Nil +fun last(ls_last) = + fun go(a, ls_go) = if ls_go is + Nil then a + h :: t then go(h, t) + if ls_last is + h :: t then Some(go(h, t)) + Nil then None +fun lastFilter(ls, f) = last(filter(ls, f)) +lastFilter(id(1 :: 2 :: 3 :: 4 :: 5 :: Nil), x => (x % 2 == 0)) +//│ = Some(4) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = Some(4) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +// should prevent processing a function body more than once +:deforest +fun g() = f() +fun f() = g() + g() +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// should prevent processing a function body more than once +:deforest +fun h1() = g() +fun h2() = g() +fun g() = f() +fun f() = h1() + h2() +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +// should prevent processing a function body more than once +:deforest +fun h1() = g() +fun h2() = g() + h1() +fun g() = f() +fun f() = h1() + h2() +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// should prevent processing a function body more than once +:deforest +fun main() = if + false then f() + g() + else 0 +fun f() = if + false then h() + else 0 +fun h() = if + false then f() + main() + else 0 +fun g() = if + false then h() + main() + else 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + + +:deforest +fun f() = + if B is + B then h1() + h2() +fun h1() = g1() +fun g1() = f() +fun h2() = g2() +fun g2() = f() +fun main() = f() +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:B)@7@inst_0_tsni --> Ref($scrut)@inst_0_tsni@B +//│ Ref(member:B)@7@inst_1_tsni --> Ref($scrut)@inst_1_tsni@B +//│ Ref(member:B)@7@inst_2_tsni --> Ref($scrut)@inst_2_tsni@B +//│ Ref(member:B)@7@inst_3_tsni --> Ref($scrut)@inst_3_tsni@B +//│ Ref(member:B)@7@inst_4_tsni --> Ref($scrut)@inst_4_tsni@B +//│ Ref(member:B)@7@inst_5_6_tsni --> Ref($scrut)@inst_5_6_tsni@B +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun h1() = g() +fun h2() = g() + h2() +fun g() = f() +fun f() = h1() + h2() +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +:deforest +fun g() = f() +fun f() = g() +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun h1() = g() +fun h2() = g() + h1() +fun g() = f() +fun f() = h1() + h2() +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +:deforest +fun g() = 0 +fun f() = f() + g() +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun h(x) = if x is + A then 0 + else f() +fun g1() = h(B) +fun g2() = h(B) +fun g3() = h(B) +fun g4() = h(B) +fun f() = + [g1(), g2(), g3(), g4(), h(B)] +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:B)@5@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@6@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@7@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@8@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@9@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@5@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@6@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@7@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@8@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@9@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@5@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ Ref(member:B)@6@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ Ref(member:B)@7@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ Ref(member:B)@8@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ Ref(member:B)@9@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ Ref(member:B)@5@inst_3_tsni --> Ref(x)@inst_3_tsni@dflt +//│ Ref(member:B)@6@inst_3_tsni --> Ref(x)@inst_3_tsni@dflt +//│ Ref(member:B)@7@inst_3_tsni --> Ref(x)@inst_3_tsni@dflt +//│ Ref(member:B)@8@inst_3_tsni --> Ref(x)@inst_3_tsni@dflt +//│ Ref(member:B)@9@inst_3_tsni --> Ref(x)@inst_3_tsni@dflt +//│ Ref(member:B)@5@inst_4_tsni --> Ref(x)@inst_4_tsni@dflt +//│ Ref(member:B)@6@inst_4_tsni --> Ref(x)@inst_4_tsni@dflt +//│ Ref(member:B)@7@inst_4_tsni --> Ref(x)@inst_4_tsni@dflt +//│ Ref(member:B)@8@inst_4_tsni --> Ref(x)@inst_4_tsni@dflt +//│ Ref(member:B)@9@inst_4_tsni --> Ref(x)@inst_4_tsni@dflt +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:deforest +fun h(x) = if x is + A then 0 + else f() +fun g1() = h(B) +fun g2() = h(B) +fun f() = + [g1(), g2()] +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:B)@3@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@4@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@3@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@4@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@3@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ Ref(member:B)@4@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +:deforest +:lift +fun f() = + fun h(x) = if x is + A then 0 + else f() + [() => h(B), () => h(B), () => h(B), () => h(B), h(B)] +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:B)@5@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@6@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@7@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@8@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@9@inst_0_tsni --> Ref(x)@inst_0_tsni@dflt +//│ Ref(member:B)@5@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@6@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@7@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@8@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@9@inst_1_tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:B)@5@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ Ref(member:B)@6@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ Ref(member:B)@7@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ Ref(member:B)@8@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ Ref(member:B)@9@inst_2_tsni --> Ref(x)@inst_2_tsni@dflt +//│ Ref(member:B)@5@inst_3_tsni --> Ref(x)@inst_3_tsni@dflt +//│ Ref(member:B)@6@inst_3_tsni --> Ref(x)@inst_3_tsni@dflt +//│ Ref(member:B)@7@inst_3_tsni --> Ref(x)@inst_3_tsni@dflt +//│ Ref(member:B)@8@inst_3_tsni --> Ref(x)@inst_3_tsni@dflt +//│ Ref(member:B)@9@inst_3_tsni --> Ref(x)@inst_3_tsni@dflt +//│ Ref(member:B)@5@inst_4_tsni --> Ref(x)@inst_4_tsni@dflt +//│ Ref(member:B)@6@inst_4_tsni --> Ref(x)@inst_4_tsni@dflt +//│ Ref(member:B)@7@inst_4_tsni --> Ref(x)@inst_4_tsni@dflt +//│ Ref(member:B)@8@inst_4_tsni --> Ref(x)@inst_4_tsni@dflt +//│ Ref(member:B)@9@inst_4_tsni --> Ref(x)@inst_4_tsni@dflt +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/hkmc2/shared/src/test/mlscript/deforest/selectionsInNestedMatch.mls b/hkmc2/shared/src/test/mlscript/deforest/selectionsInNestedMatch.mls new file mode 100644 index 0000000000..eefb85b4c1 --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/selectionsInNestedMatch.mls @@ -0,0 +1,169 @@ +:js +:deforest + +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< +object A +object B +object C +data class AA(x) +data class BB(x) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +object Nil +data class Cons(h, t) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +object None +data class Some(x) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +fun c(x) = if x is + AA then + if A is + A then x.x +c(AA(2)) +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Ref(member:A)@2@inst_1_tsni --> Ref($scrut)@inst_1_tsni@A +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@3@inst__tsni --> Ref(x)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun c(x, y) = if x is + AA then + if y is + A then x.x +c(AA(2), A) +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@1@inst__tsni --> Ref(y)@inst_0_tsni@A +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@2@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun c(x, y) = if x is + AA then + if y is + A then x.x +fun p() = AA(2) +c(p(), A) +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst__tsni --> Ref(y)@inst_1_tsni@A +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@3@inst_0_tsni --> Ref(x)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +fun c(x, y) = if x is + AA then + let a = if y is + A then 1 + a + x.x +fun p() = AA(2) +c(p(), A) +//│ = 3 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst__tsni --> Ref(y)@inst_1_tsni@A +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@3@inst_0_tsni --> Ref(x)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +fun f(x) = if x is + AA(AA(a)) then g(a) +fun g(x) = if x is + AA(b) then f(b) + A then 42 +f(AA(AA(AA(AA(AA(A)))))) +//│ = 42 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@2@inst__tsni --> Ref($param0)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@3@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@4@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@5@inst__tsni --> Ref($param0)@inst_0_tsni@AA +//│ Ref(member:A)@6@inst__tsni --> Ref(x)@inst_0_tsni@A +//│ -------------- executing ------------- +//│ = 42 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun f(x) = if x is + AA(AA(a)) then a +f(AA(AA(A))) +//│ = A +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@2@inst__tsni --> Ref($param0)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = A +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun f(x) = if x is + AA(AA(a)) then a +fun p() = AA(AA(A)) +f(p()) +//│ = A +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@2@inst_0_tsni --> Ref(x)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@3@inst_0_tsni --> Ref($param0)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = A +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun c(x, y) = + let t = if x is + AA then + if A is + A then x.x + t + y +c(AA(2), 10) +//│ = 12 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Ref(member:A)@2@inst_1_tsni --> Ref($scrut)@inst_1_tsni@A +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@3@inst__tsni --> Ref(x)@inst_1_tsni@AA +//│ -------------- executing ------------- +//│ = 12 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/hkmc2/shared/src/test/mlscript/deforest/simple.mls b/hkmc2/shared/src/test/mlscript/deforest/simple.mls new file mode 100644 index 0000000000..fb4ed7a861 --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/simple.mls @@ -0,0 +1,686 @@ +:js +:deforest + +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +object A +object B +object C +data class AA(aa) +data class BB(bb) +data class AAA(x, y) +data class BBB(x, y) +data class CCC(c) +object None +data class Some(value) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun test() = + let x = if true then A else B + if x is + A then 1 + B then 2 +test() +//│ = 1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst_0_tsni --> Ref(x)@inst_0_tsni@A +//│ Ref(member:B)@3@inst_0_tsni --> Ref(x)@inst_0_tsni@B +//│ Ref(member:A)@2@inst_1_tsni --> Ref(x)@inst_1_tsni@A +//│ Ref(member:B)@3@inst_1_tsni --> Ref(x)@inst_1_tsni@B +//│ -------------- executing ------------- +//│ = 1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun test() = + let x = if true then AA(A) else BB(B) + if x is + AA(x) then x + BB(x) then x +test() +//│ = A +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@2@inst_0_tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref(member:B))))@3@inst_0_tsni --> Ref(x)@inst_0_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@2@inst_1_tsni --> Ref(x)@inst_1_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref(member:B))))@3@inst_1_tsni --> Ref(x)@inst_1_tsni@BB +//│ -------------- executing ------------- +//│ = A +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun f(a) = if a is + A then 1 + B then 2 +fun test() = + let x = if true then AA(A) else BB(B) + if x is + AA(x) then f(x) + BB(x) then f(x) +test() +//│ = 1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@2@inst_0_tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref(member:B))))@3@inst_0_tsni --> Ref(x)@inst_0_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@2@inst_1_tsni --> Ref(x)@inst_1_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref(member:B))))@3@inst_1_tsni --> Ref(x)@inst_1_tsni@BB +//│ -------------- executing ------------- +//│ = 1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// `x.x` is successfully fused +fun f1(a) = if a is + A then 1 + B then 2 + C then 3 +fun f2(a) = if a is + A then 4 + B then 5 + C then 6 +fun test() = + let x = if true then AA(A) else BB(B) + if x is + AA then f1(x.aa) + BB then f2(x.bb) +test() +//│ = 1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@4@inst_0_tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref(member:B))))@5@inst_0_tsni --> Ref(x)@inst_0_tsni@BB +//│ Ref(member:A)@6@inst_0_tsni --> Ref(a)@inst_0_2_tsni@A +//│ Ref(member:B)@7@inst_0_tsni --> Ref(a)@inst_0_3_tsni@B +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:A))))@4@inst_1_tsni --> Ref(x)@inst_1_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Ref(member:B))))@5@inst_1_tsni --> Ref(x)@inst_1_tsni@BB +//│ Ref(member:A)@6@inst_1_tsni --> Ref(a)@inst_1_2_tsni@A +//│ Ref(member:B)@7@inst_1_tsni --> Ref(a)@inst_1_3_tsni@B +//│ -------------- executing ------------- +//│ = 1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun test() = + fun g(x) = if true then AA(11) else BB(22) + fun c(x) = if x is + AA(x) then x + BB(x) then x + c(g(true)) +test() +//│ = 11 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(11)))))@2@inst_0_tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(22)))))@3@inst_0_tsni --> Ref(x)@inst_0_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(11)))))@2@inst_1_tsni --> Ref(x)@inst_1_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(22)))))@3@inst_1_tsni --> Ref(x)@inst_1_tsni@BB +//│ -------------- executing ------------- +//│ = 11 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +// multiple match, no fusion +fun test() = + let x = B + if x is + A then 1 + B then 3 + if x is + B then 2 +test() +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun test() = + let x = A + let y = B + if x is + A then 1 + if y is + B then 2 +test() +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst_0_tsni --> Ref(x)@inst_0_tsni@A +//│ Ref(member:B)@3@inst_0_tsni --> Ref(y)@inst_0_tsni@B +//│ Ref(member:A)@2@inst_1_tsni --> Ref(x)@inst_1_tsni@A +//│ Ref(member:B)@3@inst_1_tsni --> Ref(y)@inst_1_tsni@B +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun c(a) = + let x = if a is + A then 1 + B then 2 + print(x) + x +c(A) + c(B) +//│ > 1 +//│ > 2 +//│ = 3 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:B)@2@inst__tsni --> Ref(a)@inst_0_tsni@B +//│ Ref(member:A)@3@inst__tsni --> Ref(a)@inst_1_tsni@A +//│ -------------- executing ------------- +//│ > 1 +//│ > 2 +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +// simple free var example + + + + + +:expect 5 +fun c(x) = + let t = x.aa + let n = if x is + AA then 2 + n + t +c(AA(3)) +//│ = 5 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ = 5 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun f(a, b) = if a is + A then if b is + B then 3 +f(A, B) +//│ = 3 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@1@inst__tsni --> Ref(a)@inst_0_tsni@A +//│ Ref(member:B)@2@inst__tsni --> Ref(b)@inst_0_tsni@B +//│ -------------- executing ------------- +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun f(x) = if x is + Some then if x.value > 1 then f(Some(x.value - 1)) else 0 +f(Some(2)) +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Some),List(Arg(None,Ref($tmp))))@1@inst_0_tsni --> Ref(x)@inst_0_tsni@Some +//│ Call(Ref(member:Some),List(Arg(None,Lit(IntLit(2)))))@2@inst__tsni --> Ref(x)@inst_0_tsni@Some +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +let x = A +let y = B +if x is + A then 1 +if y is + B then 2 +//│ = 2 +//│ x = A +//│ y = B +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:B)@0@inst__tsni --> Ref(y)@inst__tsni@B +//│ Ref(member:A)@1@inst__tsni --> Ref(x)@inst__tsni@A +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun test() = + let x = A + let y = B + if x is + A then 1 + if y is + B then 2 +test() +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst_0_tsni --> Ref(x)@inst_0_tsni@A +//│ Ref(member:B)@3@inst_0_tsni --> Ref(y)@inst_0_tsni@B +//│ Ref(member:A)@2@inst_1_tsni --> Ref(x)@inst_1_tsni@A +//│ Ref(member:B)@3@inst_1_tsni --> Ref(y)@inst_1_tsni@B +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun f(x, y) = + let a = if x is + AAA(n, m) then y + n - m + BBB(n, m) then m + 1 - n + a + 3 +f(AAA(1, 3), 1) + f(BBB(2, 3), 2) + f(AAA(3, 2), 4) + f(BBB(4, 6), 0) +//│ = 21 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:BBB),List(Arg(None,Lit(IntLit(4))), Arg(None,Lit(IntLit(6)))))@4@inst__tsni --> Ref(x)@inst_0_tsni@BBB +//│ Call(Ref(member:AAA),List(Arg(None,Lit(IntLit(3))), Arg(None,Lit(IntLit(2)))))@5@inst__tsni --> Ref(x)@inst_1_tsni@AAA +//│ Call(Ref(member:BBB),List(Arg(None,Lit(IntLit(2))), Arg(None,Lit(IntLit(3)))))@6@inst__tsni --> Ref(x)@inst_2_tsni@BBB +//│ Call(Ref(member:AAA),List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(3)))))@7@inst__tsni --> Ref(x)@inst_3_tsni@AAA +//│ -------------- executing ------------- +//│ = 21 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun c1(x) = if x is + AA then + if A is + A then x.aa +fun c2(x) = if x is + AA then x.aa +fun p(a) = c1(a) + c2(a) +p(AA(1)) +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@4@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Ref(member:A)@4@inst_1_2_tsni --> Ref($scrut)@inst_1_2_tsni@A +//│ Ref(member:A)@4@inst_3_2_tsni --> Ref($scrut)@inst_3_2_tsni@A +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun c(x, y) = if x is + AA(a) then + if y is + A then a +c(AA(2), A) +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@1@inst__tsni --> Ref(y)@inst_0_tsni@A +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@2@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun f(x, y) = + let a = if x is + AAA(n, m) then y + n - m + CCC(n) then n + 1 + a + 3 +f(AAA(1, 3), 1) + f(CCC(2), 2) + f(AAA(3, 2), 4) + f(CCC(4), 0) +//│ = 24 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:CCC),List(Arg(None,Lit(IntLit(4)))))@4@inst__tsni --> Ref(x)@inst_0_tsni@CCC +//│ Call(Ref(member:AAA),List(Arg(None,Lit(IntLit(3))), Arg(None,Lit(IntLit(2)))))@5@inst__tsni --> Ref(x)@inst_1_tsni@AAA +//│ Call(Ref(member:CCC),List(Arg(None,Lit(IntLit(2)))))@6@inst__tsni --> Ref(x)@inst_2_tsni@CCC +//│ Call(Ref(member:AAA),List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(3)))))@7@inst__tsni --> Ref(x)@inst_3_tsni@AAA +//│ -------------- executing ------------- +//│ = 24 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +fun f(x, y) = + let a = if x is + AAA then y + x.y + CCC(n) then n + 1 + a + 3 +f(AAA(1, 3), 1) + f(CCC(2), 2) + f(AAA(3, 2), 4) +//│ = 22 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AAA),List(Arg(None,Lit(IntLit(3))), Arg(None,Lit(IntLit(2)))))@3@inst__tsni --> Ref(x)@inst_0_tsni@AAA +//│ Call(Ref(member:CCC),List(Arg(None,Lit(IntLit(2)))))@4@inst__tsni --> Ref(x)@inst_1_tsni@CCC +//│ Call(Ref(member:AAA),List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(3)))))@5@inst__tsni --> Ref(x)@inst_2_tsni@AAA +//│ -------------- executing ------------- +//│ = 22 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun c(x, m) = if x is + AA(n) then n + 1 + else m +c(BB(3), 0) +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(3)))))@1@inst__tsni --> Ref(x)@inst_0_tsni@dflt +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + + +fun f(x) = if x is + AA(b) then g(b) +fun g(b) = if b is + AA(a) then a + 1 +f(AA(AA(0))) +//│ = 1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@2@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(0)))))@3@inst__tsni --> Ref(b)@inst_0_1_tsni@AA +//│ -------------- executing ------------- +//│ = 1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun f(x) = x.aa.aa +f(AA(AA(3))) +//│ = 3 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@1@inst__tsni --> Select(Ref(x),Ident(aa))@inst_0_tsni +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@2@inst__tsni --> Select(Select(Ref(x),Ident(aa)),Ident(aa))@inst_0_tsni +//│ -------------- executing ------------- +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun inner(x, y) = + let t = if x is + AA(a) then a + y + BB(b) then b - y + t * y +fun outer1(x, y, z) = + let t = if x is + AA(a) then inner(a, y) + BB(b) then inner(b, y) + t + z +fun outer2(x, y, z) = + let t = if x is + AA(a) then inner(a, z) + BB(b) then inner(b, y) + t + y +let p = AA(AA(3)) +outer1(p, 1, 2) + outer2(p, 3, 4) + inner(AA(5), 6) +//│ = 103 +//│ p = AA(AA(3)) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(5)))))@1@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 103 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun mapHead(f, x) = if x is + AAA(h, t) then f(h) +mapHead(x => x, AAA(1, AAA(2, None))) +//│ = 1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AAA),List(Arg(None,Lit(IntLit(1))), Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(x)@inst_0_tsni@AAA +//│ -------------- executing ------------- +//│ = 1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun test() = + let k + if A is + A then + k = 3 + k + 2 +test() +//│ = 5 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Ref(member:A)@2@inst_1_tsni --> Ref($scrut)@inst_1_tsni@A +//│ -------------- executing ------------- +//│ = 5 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun test(a) = if a is + AA then 1 + else 2 +test(B) + test(C) +//│ = 4 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:C)@2@inst__tsni --> Ref(a)@inst_0_tsni@dflt +//│ Ref(member:B)@3@inst__tsni --> Ref(a)@inst_1_tsni@dflt +//│ -------------- executing ------------- +//│ = 4 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +// technically ill-typed, so `AA(3)` (which flows to `z`) is not fused +fun test(x, y, z) = if x is + AA(a) then + let m = if y is + AA(a1) then a1 + z + let n = if z is + AA(a2) then a2 - z + m + n +test(AA(1), AA(2), AA(3)) +//│ = "2AA(3)NaN" +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@1@inst__tsni --> Ref(y)@inst_0_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(1)))))@2@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = "2AA(3)NaN" +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun test(x) = + let t = id of + if x is + AA(a) then a + BB(a) then a + t(123).c + 5 * 4 - 3 + 2 - 1 +let p = if true then AA(CCC) else BB(CCC) +test(p) +//│ = 141 +//│ p = AA(fun CCC { class: class CCC }) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:BB),List(Arg(None,Ref(member:CCC))))@1@inst__tsni --> Ref(x)@inst_0_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:CCC))))@2@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 141 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun test(x, y) = + let t = + if y is CCC then + if x is + AA(a) then a + BB(a) then a + t(123).c + 5 * 4 - 3 + 2 - 1 +let p = if true then AA(CCC) else BB(CCC) +test(p, id(CCC(123))) +//│ = 141 +//│ p = AA(fun CCC { class: class CCC }) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:BB),List(Arg(None,Ref(member:CCC))))@1@inst__tsni --> Ref(x)@inst_0_tsni@BB +//│ Call(Ref(member:AA),List(Arg(None,Ref(member:CCC))))@2@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 141 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +:sjs +fun f(x) = if x is + A then 1 +f(id(A)) + f(A) +//│ JS (unsanitized): +//│ let f10, tmp111, tmp112, tmp113; +//│ f10 = function f(x1) { +//│ if (x1 instanceof A1.class) { +//│ return 1 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ tmp111 = Predef.id(A1); +//│ tmp112 = f10(tmp111); +//│ tmp113 = f10(A1); +//│ tmp112 + tmp113 +//│ >>>>>>>>>>>>>>>>>>>>>>>>> Deforestation JS >>>>>>>>>>>>>>>>>>>>>>>>>> +//│ const definitionMetadata1 = globalThis.Symbol.for("mlscript.definitionMetadata"); +//│ const prettyPrint1 = globalThis.Symbol.for("mlscript.prettyPrint"); +//│ +//│ let f10, tmp111, tmp112, tmp113, f_inst_0_tsni7, lambda9; +//│ f_inst_0_tsni7 = function f_inst_0_tsni(x1) { +//│ return runtime.safeCall(x1()) +//│ }; +//│ f10 = function f(x1) { +//│ if (x1 instanceof A1.class) { +//│ return 1 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ tmp111 = Predef.id(A1); +//│ tmp112 = f10(tmp111); +//│ lambda9 = () => { return 1 }; +//│ tmp113 = f_inst_0_tsni7(lambda9); +//│ tmp112 + tmp113 +//│ <<<<<<<<<<<<<<<<<<<<<<<<< Deforestation JS <<<<<<<<<<<<<<<<<<<<<<<<<< +//│ = 2 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@1@inst__tsni --> Ref(x)@inst_0_tsni@A +//│ -------------- executing ------------- +//│ = 2 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun f(x) = if x is + A then 0 + B then 1 +fun g(x) = if x is + AA then A + BB then B +f(g(AA(1))) +//│ = 0 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@2@inst_0_tsni --> Ref(x)@inst_1_tsni@A +//│ Ref(member:B)@3@inst_0_tsni --> Ref(x)@inst_1_tsni@B +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(1)))))@4@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 0 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun f(a, b) = if a is + A and b is B then 1 + else 0 +f(A, B) +//│ = 1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@1@inst__tsni --> Ref(a)@inst_0_tsni@A +//│ Ref(member:B)@2@inst__tsni --> Ref(b)@inst_0_tsni@B +//│ -------------- executing ------------- +//│ = 1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// cannot fuse intermediate values created by +// calling data constructors passed around like functions, +// so `c1` is not fused. +fun app(f) = f(1) +fun identity(x) = x +fun c1(x) = if x is + AA(i) then i +fun c2(x) = if x is + AA(i) then i + A then 0 +c1(app(AA)) + c1(AA(2)) + c2(AA(3)) + c2(A) +//│ = 6 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@3@inst__tsni --> Ref(x)@inst_0_tsni@A +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(3)))))@4@inst__tsni --> Ref(x)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(2)))))@5@inst__tsni --> Ref(x)@inst_2_tsni@AA +//│ -------------- executing ------------- +//│ = 6 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +:re +fun p(x) = if x + then new AA(2) + else BB(3) +fun c(x) = if x is + AA(a) then a + BB(b) then b + else throw (if A is A then Error("e1") else Error("e2")) +print(c(p(true)) + c(p(false))) +c(B) +//│ > 5 +//│ ═══[RUNTIME ERROR] Error: e1 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:A)@6@inst_0_tsni --> Ref($scrut)@inst_0_tsni@A +//│ Ref(member:A)@6@inst_1_tsni --> Ref($scrut)@inst_1_tsni@A +//│ Ref(member:B)@7@inst__tsni --> Ref(x)@inst_1_tsni@dflt +//│ Ref(member:A)@6@inst_2_tsni --> Ref($scrut)@inst_2_tsni@A +//│ Instantiate(false,Select(Ref(member:AA),Ident(class)),List(Arg(None,Lit(IntLit(2)))))@8@inst_3_tsni --> Ref(x)@inst_2_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(3)))))@9@inst_3_tsni --> Ref(x)@inst_2_tsni@BB +//│ Ref(member:A)@6@inst_4_tsni --> Ref($scrut)@inst_4_tsni@A +//│ Instantiate(false,Select(Ref(member:AA),Ident(class)),List(Arg(None,Lit(IntLit(2)))))@8@inst_5_tsni --> Ref(x)@inst_4_tsni@AA +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(3)))))@9@inst_5_tsni --> Ref(x)@inst_4_tsni@BB +//│ -------------- executing ------------- +//│ > 5 +//│ ═══[RUNTIME ERROR] Error: e1 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +fun f(a, b) = if a is + AA(x) then x + b.bb +f(AA(1), BB(2)) +//│ = 3 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:BB),List(Arg(None,Lit(IntLit(2)))))@1@inst__tsni --> Select(Ref(b),Ident(bb))@inst_0_tsni +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(1)))))@2@inst__tsni --> Ref(a)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/hkmc2/shared/src/test/mlscript/deforest/todos.mls b/hkmc2/shared/src/test/mlscript/deforest/todos.mls new file mode 100644 index 0000000000..4e9e1ec994 --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/todos.mls @@ -0,0 +1,325 @@ +:js +:deforest + +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< +object A +object B +object C +data class AA(x) +data class BB(x) +data class CC(x) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +object Nil +data class Cons(h, t) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +object None +data class Some(x) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// since `x.x` is considered as being consumed +// at two places,the inner match is not fused +:sjs +fun f(x) = if x is + AA then if x.x is + AA then x.x.x +f(AA(AA(3))) +//│ JS (unsanitized): +//│ let f, tmp, tmp1; +//│ f = function f(x) { +//│ let scrut; +//│ if (x instanceof AA1.class) { +//│ scrut = x.x; +//│ if (scrut instanceof AA1.class) { +//│ return x.x.x +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ tmp = AA1(3); +//│ tmp1 = AA1(tmp); +//│ f(tmp1) +//│ >>>>>>>>>>>>>>>>>>>>>>>>> Deforestation JS >>>>>>>>>>>>>>>>>>>>>>>>>> +//│ const definitionMetadata1 = globalThis.Symbol.for("mlscript.definitionMetadata"); +//│ const prettyPrint1 = globalThis.Symbol.for("mlscript.prettyPrint"); +//│ +//│ let f, tmp, tmp1, f_inst_0_tsni, _deforest_AA_x; +//│ f_inst_0_tsni = function f_inst_0_tsni(x) { +//│ return runtime.safeCall(x()) +//│ }; +//│ f = function f(x) { +//│ let scrut; +//│ if (x instanceof AA1.class) { +//│ scrut = x.x; +//│ if (scrut instanceof AA1.class) { +//│ return x.x.x +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ tmp = AA1(3); +//│ _deforest_AA_x = tmp; +//│ tmp1 = () => { +//│ let scrut; +//│ scrut = _deforest_AA_x; +//│ if (scrut instanceof AA1.class) { +//│ return _deforest_AA_x.x +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ f_inst_0_tsni(tmp1) +//│ <<<<<<<<<<<<<<<<<<<<<<<<< Deforestation JS <<<<<<<<<<<<<<<<<<<<<<<<<< +//│ = 3 +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@1@inst__tsni --> Ref(x)@inst_0_tsni@AA +//│ -------------- executing ------------- +//│ = 3 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// TODO: the computation of `t + 5 * 4 - 3 + 2 - 1` is still duplicated... +:sjs +fun test(x) = + let t = if x is + AA(AA(AA(a))) then a + else 4 + t + 5 * 4 - 3 + 2 - 1 +fun f(a) = if a is + AA(AA) then 0 +let p = AA(AA(AA(10))) +test(p) + f(p) + test(AA(AA(AA(10)))) + test(B) +//│ JS (unsanitized): +//│ let test, f1, p, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14; +//│ test = function test(x) { +//│ let t, param0, param01, param02, a, tmp15, tmp16, tmp17, tmp18, tmp19; +//│ if (x instanceof AA1.class) { +//│ param0 = x.x; +//│ if (param0 instanceof AA1.class) { +//│ param01 = param0.x; +//│ if (param01 instanceof AA1.class) { +//│ param02 = param01.x; +//│ a = param02; +//│ tmp15 = a; +//│ } else { +//│ tmp15 = 4; +//│ } +//│ } else { +//│ tmp15 = 4; +//│ } +//│ } else { +//│ tmp15 = 4; +//│ } +//│ t = tmp15; +//│ tmp16 = 5 * 4; +//│ tmp17 = t + tmp16; +//│ tmp18 = tmp17 - 3; +//│ tmp19 = tmp18 + 2; +//│ return tmp19 - 1 +//│ }; +//│ f1 = function f(a) { +//│ let param0; +//│ if (a instanceof AA1.class) { +//│ param0 = a.x; +//│ if (param0 instanceof AA1.class) { +//│ return 0 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ tmp4 = AA1(10); +//│ tmp5 = AA1(tmp4); +//│ p = AA1(tmp5); +//│ tmp6 = test(p); +//│ tmp7 = f1(p); +//│ tmp8 = tmp6 + tmp7; +//│ tmp9 = AA1(10); +//│ tmp10 = AA1(tmp9); +//│ tmp11 = AA1(tmp10); +//│ tmp12 = test(tmp11); +//│ tmp13 = tmp8 + tmp12; +//│ tmp14 = test(B1); +//│ tmp13 + tmp14 +//│ >>>>>>>>>>>>>>>>>>>>>>>>> Deforestation JS >>>>>>>>>>>>>>>>>>>>>>>>>> +//│ const definitionMetadata1 = globalThis.Symbol.for("mlscript.definitionMetadata"); +//│ const prettyPrint1 = globalThis.Symbol.for("mlscript.prettyPrint"); +//│ +//│ let test, f1, p, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, test_inst_0_tsni, test_inst_1_tsni, test_inst_2_tsni, _deforest_AA_x1, _deforest_AA_x2, _deforest_AA_x3, _deforest_AA_x4, lambda; +//│ test_inst_0_tsni = function test_inst_0_tsni(x) { +//│ return runtime.safeCall(x()) +//│ }; +//│ test_inst_1_tsni = function test_inst_1_tsni(x) { +//│ return runtime.safeCall(x()) +//│ }; +//│ test_inst_2_tsni = function test_inst_2_tsni(x) { +//│ let t, param0, param01, tmp15, tmp16, tmp17, tmp18, tmp19; +//│ if (x instanceof AA1.class) { +//│ param0 = x.x; +//│ if (param0 instanceof AA1.class) { +//│ param01 = param0.x; +//│ return runtime.safeCall(param01()) +//│ } else { +//│ tmp15 = 4; +//│ } +//│ } else { +//│ tmp15 = 4; +//│ } +//│ t = tmp15; +//│ tmp16 = 5 * 4; +//│ tmp17 = t + tmp16; +//│ tmp18 = tmp17 - 3; +//│ tmp19 = tmp18 + 2; +//│ return tmp19 - 1 +//│ }; +//│ test = function test(x) { +//│ let t, param0, param01, param02, a, tmp15, tmp16, tmp17, tmp18, tmp19; +//│ if (x instanceof AA1.class) { +//│ param0 = x.x; +//│ if (param0 instanceof AA1.class) { +//│ param01 = param0.x; +//│ if (param01 instanceof AA1.class) { +//│ param02 = param01.x; +//│ a = param02; +//│ tmp15 = a; +//│ } else { +//│ tmp15 = 4; +//│ } +//│ } else { +//│ tmp15 = 4; +//│ } +//│ } else { +//│ tmp15 = 4; +//│ } +//│ t = tmp15; +//│ tmp16 = 5 * 4; +//│ tmp17 = t + tmp16; +//│ tmp18 = tmp17 - 3; +//│ tmp19 = tmp18 + 2; +//│ return tmp19 - 1 +//│ }; +//│ f1 = function f(a) { +//│ let param0; +//│ if (a instanceof AA1.class) { +//│ param0 = a.x; +//│ if (param0 instanceof AA1.class) { +//│ return 0 +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ } else { +//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) +//│ } +//│ }; +//│ _deforest_AA_x4 = 10; +//│ tmp4 = () => { +//│ let t, param0, a, tmp15, tmp16, tmp17, tmp18, tmp19; +//│ param0 = _deforest_AA_x4; +//│ a = param0; +//│ tmp15 = a; +//│ t = tmp15; +//│ tmp16 = 5 * 4; +//│ tmp17 = t + tmp16; +//│ tmp18 = tmp17 - 3; +//│ tmp19 = tmp18 + 2; +//│ return tmp19 - 1 +//│ }; +//│ tmp5 = AA1(tmp4); +//│ p = AA1(tmp5); +//│ tmp6 = test_inst_2_tsni(p); +//│ tmp7 = f1(p); +//│ tmp8 = tmp6 + tmp7; +//│ _deforest_AA_x3 = 10; +//│ tmp9 = () => { +//│ let t, param0, a, tmp15, tmp16, tmp17, tmp18, tmp19; +//│ param0 = _deforest_AA_x3; +//│ a = param0; +//│ tmp15 = a; +//│ t = tmp15; +//│ tmp16 = 5 * 4; +//│ tmp17 = t + tmp16; +//│ tmp18 = tmp17 - 3; +//│ tmp19 = tmp18 + 2; +//│ return tmp19 - 1 +//│ }; +//│ _deforest_AA_x2 = tmp9; +//│ tmp10 = () => { +//│ let param0; +//│ param0 = _deforest_AA_x2; +//│ return runtime.safeCall(param0()) +//│ }; +//│ _deforest_AA_x1 = tmp10; +//│ tmp11 = () => { +//│ let param0; +//│ param0 = _deforest_AA_x1; +//│ return runtime.safeCall(param0()) +//│ }; +//│ tmp12 = test_inst_1_tsni(tmp11); +//│ tmp13 = tmp8 + tmp12; +//│ lambda = () => { +//│ let t, tmp15, tmp16, tmp17, tmp18, tmp19; +//│ tmp15 = 4; +//│ t = tmp15; +//│ tmp16 = 5 * 4; +//│ tmp17 = t + tmp16; +//│ tmp18 = tmp17 - 3; +//│ tmp19 = tmp18 + 2; +//│ return tmp19 - 1 +//│ }; +//│ tmp14 = test_inst_0_tsni(lambda); +//│ tmp13 + tmp14 +//│ <<<<<<<<<<<<<<<<<<<<<<<<< Deforestation JS <<<<<<<<<<<<<<<<<<<<<<<<<< +//│ = 78 +//│ p = AA(AA(AA(10))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:B)@3@inst__tsni --> Ref(x)@inst_0_tsni@dflt +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@4@inst__tsni --> Ref(x)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Ref($tmp))))@5@inst__tsni --> Ref($param0)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(10)))))@6@inst__tsni --> Ref($param0)@inst_1_tsni@AA +//│ Call(Ref(member:AA),List(Arg(None,Lit(IntLit(10)))))@7@inst__tsni --> Ref($param0)@inst_2_tsni@AA +//│ -------------- executing ------------- +//│ = 78 +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +// TODO: currently nothing is done at all when seeing +// `Define` blocks defining things other than functions +:todo +data class Global(x) +fun test() = + data class Local(x) + if Global(1) is + Global(x) then Local(x + 1) +test() +//│ = Local(2) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ Not deforestable: no support for fun containing a cls like def +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/hkmc2/shared/src/test/mlscript/deforest/zipunzip.mls b/hkmc2/shared/src/test/mlscript/deforest/zipunzip.mls new file mode 100644 index 0000000000..5079600c2a --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/deforest/zipunzip.mls @@ -0,0 +1,116 @@ +:js +:deforest + +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + +object Nil +data class (::) Cons(h, t) +data class Pair(a, b) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ +//│ -------------- executing ------------- +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + +fun zip(xs_zip, ys_zip) = if + xs_zip is x :: xt and ys_zip is y :: yt then Pair(x, y) :: zip(xt, yt) + else Nil +fun unzip(ls_unzip) = if ls_unzip is + Pair(a, b) :: t and unzip(t) is Pair(atail, btail) then Pair(a :: atail, b :: btail) + Nil then Pair(Nil, Nil) +fun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil +fun testUnzipZip(n) = unzip(zip(id(enumFromTo(1, n)), id(enumFromTo(2, n + 3)))) +testUnzipZip(3) +//│ = Pair(Cons(1, Cons(2, Nil)), Cons(2, Cons(3, Nil))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@4@inst_0_1_tsni --> Ref(ls_unzip)@inst_0_3_tsni@Cons +//│ Call(Ref(member:Pair),List(Arg(None,Ref(x)), Arg(None,Ref(y))))@5@inst_0_1_tsni --> Ref($param0)@inst_0_3_tsni@Pair +//│ Ref(member:Nil)@6@inst_0_1_tsni --> Ref(ls_unzip)@inst_0_3_tsni@Nil +//│ Ref(member:Nil)@7@inst_0_1_tsni --> Ref(ls_unzip)@inst_0_3_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@4@inst_2_1_tsni --> Ref(ls_unzip)@inst_2_3_tsni@Cons +//│ Call(Ref(member:Pair),List(Arg(None,Ref(x)), Arg(None,Ref(y))))@5@inst_2_1_tsni --> Ref($param0)@inst_2_3_tsni@Pair +//│ Ref(member:Nil)@6@inst_2_1_tsni --> Ref(ls_unzip)@inst_2_3_tsni@Nil +//│ Ref(member:Nil)@7@inst_2_1_tsni --> Ref(ls_unzip)@inst_2_3_tsni@Nil +//│ -------------- executing ------------- +//│ = Pair(Cons(1, Cons(2, Nil)), Cons(2, Cons(3, Nil))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun zip(xs_zip, ys_zip) = if + xs_zip is x :: xt and ys_zip is y :: yt then Pair(x, y) :: zip(xt, yt) + else Nil +fun unzip(ls_unzip) = if ls_unzip is + Pair(a, b) :: t and unzip(t) is Pair(atail, btail) then Pair(a :: atail, b :: btail) + Nil then Pair(Nil, Nil) +fun makeZippedList(n) = if n > 0 then Pair(n, n + 1) :: makeZippedList(n - 1) else Nil +fun testZipUnzip(n) = if unzip(id(makeZippedList(n))) is + Pair(xs, ys) then zip(xs, ys) +testZipUnzip(3) +//│ = Cons(Pair(3, 4), Cons(Pair(2, 3), Cons(Pair(1, 2), Nil))) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:Nil)@4@inst_0_1_tsni --> Ref(xs_zip)@inst_0_3_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref(atail))))@5@inst_0_1_tsni --> Ref(xs_zip)@inst_0_3_tsni@Cons +//│ Ref(member:Nil)@6@inst_0_1_tsni --> Ref(ys_zip)@inst_0_3_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref(b)), Arg(None,Ref(btail))))@7@inst_0_1_tsni --> Ref(ys_zip)@inst_0_3_tsni@Cons +//│ Ref(member:Nil)@4@inst_2_1_tsni --> Ref(xs_zip)@inst_2_3_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref(atail))))@5@inst_2_1_tsni --> Ref(xs_zip)@inst_2_3_tsni@Cons +//│ Ref(member:Nil)@6@inst_2_1_tsni --> Ref(ys_zip)@inst_2_3_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref(b)), Arg(None,Ref(btail))))@7@inst_2_1_tsni --> Ref(ys_zip)@inst_2_3_tsni@Cons +//│ -------------- executing ------------- +//│ = Cons(Pair(3, 4), Cons(Pair(2, 3), Cons(Pair(1, 2), Nil))) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< + + + +fun zip(xs_zip, ys_zip) = if + xs_zip is x :: xt and ys_zip is y :: yt then Pair(x, y) :: zip(xt, yt) + else Nil +fun unzip(ls_unzip) = if ls_unzip is + Pair(a, b) :: t and unzip(t) is Pair(atail, btail) then Pair(a :: atail, b :: btail) + Nil then Pair(Nil, Nil) +fun map(f, ls_map) = if ls_map is + h :: t then f(h) :: map(f, t) + Nil then Nil +fun makeZippedList(n) = if n > 0 then Cons(Pair(n, n + 1), makeZippedList(n - 1)) else Nil +fun testZipMapBothUnzip(n) = if unzip(id(makeZippedList(n))) is + Pair(xs, ys) then zip( + map(x => x + 1, xs), + map(x => x * x, ys) + ) +testZipMapBothUnzip(4) +//│ = Cons( +//│ Pair(5, 25), +//│ Cons(Pair(4, 16), Cons(Pair(3, 9), Cons(Pair(2, 4), Nil))) +//│ ) +//│ >>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>> +//│ ---------- deforest summary ---------- +//│ Ref(member:Nil)@6@inst_0_1_tsni --> Ref(ls_map)@inst_0_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref(atail))))@7@inst_0_1_tsni --> Ref(ls_map)@inst_0_2_tsni@Cons +//│ Ref(member:Nil)@8@inst_0_1_tsni --> Ref(ls_map)@inst_0_3_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(b)), Arg(None,Ref(btail))))@9@inst_0_1_tsni --> Ref(ls_map)@inst_0_3_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@10@inst_0_2_tsni --> Ref(xs_zip)@inst_0_5_tsni@Cons +//│ Ref(member:Nil)@11@inst_0_2_tsni --> Ref(xs_zip)@inst_0_5_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@10@inst_0_3_tsni --> Ref(ys_zip)@inst_0_5_tsni@Cons +//│ Ref(member:Nil)@11@inst_0_3_tsni --> Ref(ys_zip)@inst_0_5_tsni@dflt +//│ Ref(member:Nil)@6@inst_4_1_tsni --> Ref(ls_map)@inst_4_2_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(a)), Arg(None,Ref(atail))))@7@inst_4_1_tsni --> Ref(ls_map)@inst_4_2_tsni@Cons +//│ Ref(member:Nil)@8@inst_4_1_tsni --> Ref(ls_map)@inst_4_3_tsni@Nil +//│ Call(Ref(member:Cons),List(Arg(None,Ref(b)), Arg(None,Ref(btail))))@9@inst_4_1_tsni --> Ref(ls_map)@inst_4_3_tsni@Cons +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@10@inst_4_2_tsni --> Ref(xs_zip)@inst_4_5_tsni@Cons +//│ Ref(member:Nil)@11@inst_4_2_tsni --> Ref(xs_zip)@inst_4_5_tsni@dflt +//│ Call(Ref(member:Cons),List(Arg(None,Ref($tmp)), Arg(None,Ref($tmp))))@10@inst_4_3_tsni --> Ref(ys_zip)@inst_4_5_tsni@Cons +//│ Ref(member:Nil)@11@inst_4_3_tsni --> Ref(ys_zip)@inst_4_5_tsni@dflt +//│ -------------- executing ------------- +//│ = Cons( +//│ Pair(5, 25), +//│ Cons(Pair(4, 16), Cons(Pair(3, 9), Cons(Pair(2, 4), Nil))) +//│ ) +//│ <<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/hkmc2/shared/src/test/mlscript/llir/nofib/NofibPrelude.mls b/hkmc2/shared/src/test/mlscript/llir/nofib/NofibPrelude.mls index e29f5c890c..df77901f17 100644 --- a/hkmc2/shared/src/test/mlscript/llir/nofib/NofibPrelude.mls +++ b/hkmc2/shared/src/test/mlscript/llir/nofib/NofibPrelude.mls @@ -265,14 +265,14 @@ fun map_lz(f, ls) = lazy of () => LzNil then LzNil LzCons(h, t) then LzCons(f(h), map_lz(f, t)) -fun filter_lz(p, ls) = Lazy of () => +fun filter_lz(p, ls) = lazy of () => if force(ls) is LzNil then LzNil LzCons(h, t) and p(h) then LzCons(h, filter_lz(p, t)) else force(filter_lz(p, t)) -fun nubBy_lz(eq, ls) = Lazy of () => +fun nubBy_lz(eq, ls) = lazy of () => if force(ls) is LzNil then LzNil LzCons(h, t) then LzCons(h, nubBy_lz(eq, filter_lz(y => nott(eq(h, y)), t))) diff --git a/hkmc2Benchmarks/src/test/bench/FingerTreesAsStacks.mls b/hkmc2Benchmarks/src/test/bench/FingerTreesAsStacks.mls index d22d45ed82..33da92ce7c 100644 --- a/hkmc2Benchmarks/src/test/bench/FingerTreesAsStacks.mls +++ b/hkmc2Benchmarks/src/test/bench/FingerTreesAsStacks.mls @@ -1,6 +1,11 @@ :js :silent +// Comment to run the benchmarks +:exit +==================================================================================================== + + import "../../../../hkmc2/shared/src/test/mlscript-compile/FingerTreeList.mls" import "../../../../hkmc2/shared/src/test/mlscript-compile/Stack.mls" import "./mlscript-compile/Benchmark.mls" diff --git a/hkmc2Benchmarks/src/test/bench/LazySpreads.mls b/hkmc2Benchmarks/src/test/bench/LazySpreads.mls index e0b7b2a3cf..7feec91f04 100644 --- a/hkmc2Benchmarks/src/test/bench/LazySpreads.mls +++ b/hkmc2Benchmarks/src/test/bench/LazySpreads.mls @@ -1,5 +1,10 @@ :js +// Comment to run the benchmarks +:exit +==================================================================================================== + + import "../../../../hkmc2/shared/src/test/mlscript-compile/LazyArray.mls" import "../../../../hkmc2/shared/src/test/mlscript-compile/FingerTreeList.mls" import "../../../../hkmc2/shared/src/test/mlscript-compile/LazyFingerTree.mls" @@ -27,16 +32,15 @@ fun buildLazy(i) = //│ JS (unsanitized): //│ let buildLazy; //│ buildLazy = function buildLazy(i) { -//│ let scrut, tmp1, tmp2, tmp3; +//│ let scrut, tmp1, tmp2, tmp3, arr, arr1; //│ scrut = i > 0; //│ if (scrut === true) { //│ tmp1 = i - 1; //│ tmp2 = buildLazy(tmp1); //│ tmp3 = - i; -//│ return globalThis.Object.freeze(runtime.Tuple.lazyConcat(i, runtime.Tuple.split, tmp2, tmp3)) -//│ } else { -//│ return globalThis.Object.freeze([]) -//│ } +//│ arr = globalThis.Object.freeze(runtime.Tuple.lazyConcat(i, runtime.Tuple.split, tmp2, tmp3)); +//│ return arr +//│ } else { arr1 = globalThis.Object.freeze([]); return arr1 } //│ }; :sjs @@ -45,16 +49,19 @@ fun buildEager(i) = //│ JS (unsanitized): //│ let buildEager; //│ buildEager = function buildEager(i) { -//│ let scrut, tmp1, tmp2, tmp3; +//│ let scrut, tmp1, tmp2, tmp3, arr, arr1; //│ scrut = i > 0; //│ if (scrut === true) { //│ tmp1 = i - 1; //│ tmp2 = buildEager(tmp1); //│ tmp3 = - i; -//│ return globalThis.Object.freeze([ i, ...tmp2, tmp3 ]) -//│ } else { -//│ return globalThis.Object.freeze([]) -//│ } +//│ arr = globalThis.Object.freeze([ +//│ i, +//│ ...tmp2, +//│ tmp3 +//│ ]); +//│ return arr +//│ } else { arr1 = globalThis.Object.freeze([]); return arr1 } //│ }; :sjs @@ -78,9 +85,7 @@ fun funnySum(xs) = if xs is //│ return tmp2 - b //│ } else if (runtime.Tuple.isArrayLike(xs) && xs.length === 0) { //│ return 0 -//│ } else { -//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) -//│ } +//│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ }; :sjs @@ -104,9 +109,7 @@ fun funnySumEager(xs) = if xs is //│ return tmp2 - b //│ } else if (runtime.Tuple.isArrayLike(xs) && xs.length === 0) { //│ return 0 -//│ } else { -//│ throw globalThis.Object.freeze(new globalThis.Error("match error")) -//│ } +//│ } else { throw globalThis.Object.freeze(new globalThis.Error("match error")) } //│ }; :silent @@ -186,7 +189,7 @@ fun map(f) = case //│ map = function map(f) { //│ let lambda18; //│ lambda18 = (undefined, function (caseScrut) { -//│ let rest, first0, a, rest1, tmp22, tmp23, tmp24; +//│ let rest, first0, a, rest1, tmp22, tmp23, tmp24, arr1, arr2; //│ if (runtime.Tuple.isArrayLike(caseScrut) && caseScrut.length >= 1) { //│ first0 = runtime.Tuple.get(caseScrut, 0); //│ rest = runtime.safeCall(runtime.Tuple.lazySlice(caseScrut, 1, 0)); @@ -195,9 +198,11 @@ fun map(f) = case //│ tmp22 = runtime.safeCall(f(a)); //│ tmp23 = map(f); //│ tmp24 = runtime.safeCall(tmp23(rest1)); -//│ return globalThis.Object.freeze(runtime.Tuple.lazyConcat(tmp22, runtime.Tuple.split, tmp24)) +//│ arr1 = globalThis.Object.freeze(runtime.Tuple.lazyConcat(tmp22, runtime.Tuple.split, tmp24)); +//│ return arr1 //│ } else if (runtime.Tuple.isArrayLike(caseScrut) && caseScrut.length === 0) { -//│ return globalThis.Object.freeze([]) +//│ arr2 = globalThis.Object.freeze([]); +//│ return arr2 //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) //│ } @@ -215,7 +220,7 @@ fun mapEager(f) = case //│ mapEager = function mapEager(f) { //│ let lambda18; //│ lambda18 = (undefined, function (caseScrut) { -//│ let rest, first0, a, rest1, tmp22, tmp23, tmp24; +//│ let rest, first0, a, rest1, tmp22, tmp23, tmp24, arr1, arr2; //│ if (runtime.Tuple.isArrayLike(caseScrut) && caseScrut.length >= 1) { //│ first0 = runtime.Tuple.get(caseScrut, 0); //│ rest = runtime.safeCall(runtime.Tuple.slice(caseScrut, 1, 0)); @@ -224,9 +229,14 @@ fun mapEager(f) = case //│ tmp22 = runtime.safeCall(f(a)); //│ tmp23 = mapEager(f); //│ tmp24 = runtime.safeCall(tmp23(rest1)); -//│ return globalThis.Object.freeze([ tmp22, ...tmp24 ]) +//│ arr1 = globalThis.Object.freeze([ +//│ tmp22, +//│ ...tmp24 +//│ ]); +//│ return arr1 //│ } else if (runtime.Tuple.isArrayLike(caseScrut) && caseScrut.length === 0) { -//│ return globalThis.Object.freeze([]) +//│ arr2 = globalThis.Object.freeze([]); +//│ return arr2 //│ } else { //│ throw globalThis.Object.freeze(new globalThis.Error("match error")) //│ } @@ -284,15 +294,15 @@ suite.add("EagerBuiltMap2Eager15", () => :ge mapEager(..[[1]]) //│ ╔══[COMPILATION ERROR] Lazy spreads are not supported in call arguments -//│ ║ l.285: mapEager(..[[1]]) +//│ ║ l.290: mapEager(..[[1]]) //│ ╙── ^^^^^^^^^ //│ ═══[RUNTIME ERROR] Error: Function 'mapEager' expected 1 argument but got 2 :e fun what(..args) = args //│ ╔══[ERROR] Lazy spread parameters not allowed. -//│ ║ l.292: fun what(..args) = args -//│ ╙── ^^^^ +//│ ║ l.297: fun what(..args) = args +//│ ╙── ^^^^^^ fun silly = case [a, b, ..xs] then [..xs, ..silly([a, ..xs])] diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/Benchmark.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/Benchmark.mls index f7dbee9925..4d0bd0d0ce 100644 --- a/hkmc2Benchmarks/src/test/bench/mlscript-compile/Benchmark.mls +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/Benchmark.mls @@ -5,7 +5,7 @@ let bm = benchmark module Benchmark with... val benchmark = bm -let prefixPath = "src/test/logs/" +let prefixPath = "hkmc2Benchmarks/src/test/logs/" fun mkSuite() = new! mut bm.Suite() diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/NofibPrelude.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/NofibPrelude.mls new file mode 100644 index 0000000000..18894a1351 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/NofibPrelude.mls @@ -0,0 +1,369 @@ +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open Predef + +module NofibPrelude with ... +type Char = String + +abstract class Option[out T]: Some[T] | None +data class Some[out T](x: T) extends Option[T] +object None extends Option + +fun fromSome(s) = if s is Some(x) then x + +data class Lazy[out A](init: () -> A) with + mut val cached: Option[A] = None + fun get() = + if cached is + Some(v) then v + else + let v = init() + set cached = Some(v) + v +fun lazy(x) = Lazy(x) +fun force(x) = if x is Lazy then x.Lazy#get() + + +abstract class List[out T]: Cons[T] | Nil +data class (::) Cons[out T](head: T, tail: List[T]) extends List[T] with + fun toString() = + "[" + _internal_cons_to_str(Cons(head, tail)) + "]" +object Nil extends List with + fun toString() = "[]" +fun _internal_cons_to_str(ls) = if ls is + Nil then "" + h :: Nil then render(h) + h :: t then render(h) + "," + _internal_cons_to_str(t) +fun ltList(xs, ys, lt, gt) = if xs is + Nil and + ys is Nil then false + else true + x :: xs and ys is + Nil then false + y :: ys and + lt(x, y) then true + gt(x, y) then false + else ltList(xs, ys, lt, gt) +fun list(...args) = if args is + [] then Nil + [x, ...xs] then x :: list(...xs) + +type LazyList[out T] = Lazy[LzList[T]] +abstract class LzList[out T]: LzCons[T] | LzNil +data class LzCons[out T](head: T, tail: LazyList[T]) extends LzList[T] +object LzNil extends LzList + +fun ltTup2(t1, t2, lt1, gt1, lt2) = if t1 is [a, b] and t2 is [c, d] and + lt1(a, c) then true + gt1(a, c) then false + else lt2(b, d) +fun eqTup2(t1, t2) = if t1 is [a, b] and t2 is [c, d] then a == c and b == d + +fun compose(f, g) = x => f(g(x)) + +fun snd(x) = if x is [f, s] then s +fun fst(x) = if x is [f, s] then f + +fun until(p, f, i) = if p(i) then i else until(p, f, f(i)) + +fun flip(f, x, y) = f(y)(x) + +fun power(a, n) = globalThis.Math.pow(a, n) + +fun intDiv(a, b) = globalThis.Math.floor(a / b) +fun intQuot(a, b) = globalThis.Math.trunc(a / b) + +fun intMod(a, b) = a - (b * intDiv(a, b)) +fun intRem(a, b) = a - (b * intQuot(a, b)) + +fun quotRem(a, b) = [intQuot(a, b), intRem(a, b)] +fun divMod(a, b) = [intDiv(a, b), intMod(a, b)] + +fun max(a, b) = globalThis.Math.max(a, b) +fun min(a, b) = globalThis.Math.min(a, b) + +fun abs(x) = globalThis.Math.abs(x) + +fun head(l) = if l is h :: t then h +fun tail(l) = if l is h :: t then t + +fun while_(p, f, x) = if p(x) then while_(p, f, f(x)) else x + +fun reverse(l) = + fun r(l', l) = if l is x :: xs then r(x :: l', xs) else l' + r(Nil, l) + +fun map(f, xs) = if xs is + x :: xs then f(x) :: map(f, xs) + Nil then Nil + +fun listLen(ls) = + fun l(ls, a) = if ls is + Nil then a + h :: t then l(t, a + 1) + l(ls, 0) + +fun listEq(xs, ys) = if + xs is Nil and ys is Nil then true + xs is hx :: tx and ys is hy :: ty and (hx == hy) then listEq(tx, ty) + else false + +fun listEqBy(f, a, b) = if a is + Nil and b is Nil then true + x :: xs and b is y :: ys then f(x, y) && listEqBy(f, xs, ys) + else false + +fun listNeq(xs, ys) = if + xs is Nil and ys is Nil then false + xs is hx :: tx and ys is hy :: ty and (hx == hy) then listNeq(tx, ty) + else true + +fun enumFromTo(a, b) = if a <= b then a :: enumFromTo(a + 1, b) else Nil + +fun enumFromThenTo(a, t, b) = if a <= b then a :: enumFromThenTo(t, 2 * t - a, b) else Nil + +fun leave(n, ls) = if ls is + Nil then Nil + h :: t and + n <= 0 then ls + else leave(n - 1, t) + +fun take(n, ls) = if ls is + Nil then Nil + h :: t and + n <= 0 then Nil + else h :: take(n - 1, t) + +fun splitAt(n, ls) = [take(n, ls), leave(n, ls)] + +fun zip(xs, ys) = if xs is + x :: xs and ys is y :: ys then [x, y] :: zip(xs, ys) + else Nil + +fun inList(x, ls) = if ls is + h :: t and + x === h then true + else inList(x, t) + Nil then false + +fun notElem(x, ls) = not(inList(x, ls)) + +fun (+:) append(xs, ys) = if xs is + Nil then ys + x :: xs then x :: append(xs, ys) + +fun concat(ls) = if ls is + Nil then Nil + x :: xs then append(x, concat(xs)) + +fun filter(f, ls) = if ls is + Nil then Nil + h :: t and + f(h) then h :: filter(f, t) + else filter(f, t) + +fun all(p, ls) = if ls is + Nil then true + h :: t and + p(h) then all(p, t) + else false + +fun orList(ls) = if ls is + Nil then false + h :: t and + h then true + else orList(t) + +fun leaveWhile(f, ls) = if ls is + Nil then Nil + h :: t and + f(h) then leaveWhile(f, t) + else h :: t + +fun foldl(f, a, xs) = if xs is + Nil then a + h :: t then foldl(f, f(a, h), t) + +fun scanl(f, q, ls) = if ls is + Nil then q :: Nil + x :: xs then q :: scanl(f, f(q, x), xs) + +fun scanr(f, q, ls) = if ls is + Nil then q :: Nil + x :: xs and scanr(f, q, xs) is q :: t then f(x, q) :: q :: t + +fun foldr(f, z, xs) = if xs is + Nil then z + h :: t then f(h, foldr(f, z, t)) + +fun foldl1(f, ls) = if + ls is x :: xs then foldl(f, x, xs) + +fun foldr1(f, ls) = if ls is + x :: Nil then x + x :: xs then f(x, foldr1(f, xs)) + +fun maximum(xs) = foldl1((x, y) => if x > y then x else y, xs) + +fun nubBy(eq, ls) = if ls is + Nil then Nil + h :: t then h :: nubBy(eq, filter(y => not(eq(h, y)), t)) + +fun zipWith(f, xss, yss) = if + xss is x :: xs and yss is y :: ys then f(x, y) :: zipWith(f, xs, ys) + else Nil + +fun deleteBy(eq, x, ys) = if ys is + Nil then Nil + y :: ys and + eq(x, y) then ys + else y :: deleteBy(eq, x, ys) + +fun unionBy(eq, xs, ys) = append(xs, foldl((acc, y) => deleteBy(eq, y, acc), nubBy(eq, ys), xs)) + +fun union(xs, ys) = unionBy((x, y) => x == y, xs, ys) + +fun atIndex(i, ls) = if ls is + h :: t and + i == 0 then h + else atIndex(i - 1, t) + +fun sum(xs) = + fun go(xs, a) = if xs is + Nil then a + h :: t then go(t, a + h) + go(xs, 0) + +fun null_(ls) = if ls is + Nil then true + else false + +fun replicate(n, x) = if n == 0 then Nil else x :: replicate(n - 1, x) + +fun unzip(l) = + fun f(l, a, b) = if l is + Nil then [reverse(a), reverse(b)] + [x, y] :: t then f(t, x :: a, y :: b) + f(l, Nil, Nil) + +fun zip3(xs, ys, zs) = if + xs is x :: xs and ys is y :: ys and zs is z :: zs then [x, y, z] :: zip3(xs, ys, zs) + else Nil + +fun transpose(xss) = + fun lscomp(ls) = if ls is + Nil then Nil + h :: t and h is + hd :: tl then [hd, tl] :: lscomp(t) + else lscomp(t) + fun combine(y, h, ys, t) = (y :: h) :: transpose(ys :: t) + if xss is + Nil then Nil + Nil :: xss then transpose(xss) + (x :: xs) :: xss and unzip(lscomp(xss)) is [hds, tls] then combine(x, hds, xs, tls) + +fun break_(p, ls) = if ls is + Nil then [Nil, Nil] + x :: xs and + p(x) then [Nil, x :: xs] + break_(p, xs) is [ys, zs] then [x :: ys, zs] + +fun flatMap(f, ls) = if ls is + Nil then Nil + h :: t then append(f(h), flatMap(f, t)) + +// ===================== + +fun map_lz(f, ls) = lazy of () => + if force(ls) is + LzNil then LzNil + LzCons(h, t) then LzCons(f(h), map_lz(f, t)) + +fun filter_lz(p, ls) = lazy of () => + if force(ls) is + LzNil then LzNil + LzCons(h, t) and + p(h) then LzCons(h, filter_lz(p, t)) + else force(filter_lz(p, t)) + +fun nubBy_lz(eq, ls) = lazy of () => + if force(ls) is + LzNil then LzNil + LzCons(h, t) then LzCons(h, nubBy_lz(eq, filter_lz(y => not(eq(h, y)), t))) + +fun nub_lz(ls) = nubBy_lz((x, y) => x == y, ls) + +fun take_lz(n, ls) = if + n > 0 and force(ls) is + LzNil then Nil + LzCons(h, t) then h :: take_lz(n - 1, t) + else Nil + +fun take_lz_lz(n, ls) = lazy of () => + if n > 0 and force(ls) is + LzNil then LzNil + LzCons(h, t) then LzCons(h, take_lz_lz(n - 1, t)) + else LzNil + +fun leave_lz(n, ls) = if + n <= 0 then ls + force(ls) is + LzNil then lazy of () => LzNil + LzCons(h, t) then leave_lz(n - 1, t) + +fun splitAt_lz(n, ls) = [take_lz(n, ls), leave_lz(n, ls)] + +fun zip_lz_nl(xs, ys) = if + force(xs) is LzCons(x, xs) and ys is y :: ys then [x, y] :: zip_lz_nl(xs, ys) + else Nil + +fun zip_lz_lz(xs, ys) = if + force(xs) is LzCons(x, xs) and force(ys) is LzCons(y, ys) then lazy of () => LzCons([x, y], zip_lz_lz(xs, ys)) + else lazy of () => LzNil + +fun zipWith_lz_lz(f, xss, yss) = lazy of () => if + force(xss) is LzCons(x, xs) and (force(yss)) is LzCons(y, ys) then LzCons(f(x, y), zipWith_lz_lz(f, xs, ys)) + else LzNil + +fun zipWith_lz_nl(f, xss, yss) = if + force(xss) is LzCons(x, xs) and yss is y :: ys then f(x, y) :: zipWith_lz_nl(f, xs, ys) + else Nil + +fun iterate(f, x) = lazy of () => LzCons(x, iterate(f, f(x))) + +fun append_nl_lz(xs, ys) = if xs is + Nil then ys + h :: t then lazy of () => LzCons(h, append_nl_lz(t, ys)) + +fun append_lz_lz(xs, ys) = lazy of () => if force(xs) is + LzNil then force(ys) + LzCons(h, t) then LzCons(h, append_lz_lz(t, ys)) + +fun replicate_lz(n, x) = if n == 0 then lazy of () => LzNil else lazy of () => LzCons(x, replicate_lz(n - 1, x)) + +fun enumFrom(a) = lazy of () => LzCons(a, enumFrom(a + 1)) + +fun head_lz(ls) = if force(ls) is LzCons(h, t) then h + +fun repeat(x) = lazy of () => LzCons(x, repeat(x)) +// ===================== + + +fun stringOfFloat(x) = x + "" +fun stringOfInt(x) = x + "" +fun stringConcat(x, y) = x + y +fun stringListConcat(ls) = if ls is + Nil then "" + h :: t then stringConcat(h, stringListConcat(t)) +fun sqrt(x) = globalThis.Math.sqrt(x) +fun tan(x) = globalThis.Math.tan(x) +fun sin(x) = globalThis.Math.sin(x) +fun cos(x) = globalThis.Math.cos(x) +fun round(x) = globalThis.Math.round(x) +fun int_of_char(x) = x.charCodeAt(0) +fun nofibStringToList(s) = + fun go(i) = if i < s.length then s.charAt(i) :: go(i + 1) else Nil + go(0) +fun nofibListToString(ls) = if ls is + Nil then "" + h :: t then h + nofibListToString(t) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/ansi.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/ansi.mls new file mode 100644 index 0000000000..04bf8af28c --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/ansi.mls @@ -0,0 +1,94 @@ +import "./NofibPrelude.mls" +open NofibPrelude + +module ansi with ... + + +val cls = nofibStringToList("L") +//│ cls = ["L"] + +fun goto(x, y) = "E" :: "[" :: (nofibStringToList(stringOfInt(y)) +: (";" :: nofibStringToList(stringOfInt(x)) +: nofibStringToList("H"))) + +fun at(x_y, s) = if x_y is [x, y] then goto(x, y) +: s + +fun highlight(s) = nofibStringToList("ESC[7m") +: s +: nofibStringToList("ESC[0m") + +fun end(xs) = nofibStringToList("") + +fun readChar(eof, consume, cs) = if cs is + Nil then eof(Nil) + c :: cs then consume(c, cs) + +fun peekChar(eof, consume, cs) = if cs is + Nil then eof(Nil) + c :: cs then consume(c, c :: cs) + +fun pressAnyKey(prog, x) = readChar(prog, (c, x) => prog(x), x) + +fun unreadChar(c, prog, cs) = prog(c :: cs) + +fun writeChar(c, prog, cs) = c :: prog(cs) + +fun writeString(s, prog, cs) = s +: prog(cs) + +fun writes(ss, a, b) = writeString(concat(ss), a, b) + +fun ringBell(prog, cs) = writeChar("B", prog, cs) + +fun clearScreen(a, b) = writeString(cls, a, b) + +fun writeAt(x_y, s, a) = if x_y is [x, y] then p => writeString(goto(x, y) +: s, a, p) + +fun moveTo(x_y, a) = if x_y is [x, y] then p => writeString(goto(x, y), a, p) + +fun returnn(s, consume) = consume(reverse(s)) + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun deletee(n, s, l, consume, d) = if n > 0 then writeString(nofibStringToList("BS_BS"), loop(n - 1, tail(s), l, consume), d) else ringBell(loop(0, nofibStringToList(""), l, consume), d) + +fun loop(n, s, l, consume) = x => readChar of + returnn(s, consume) + (c, d) => if + c == "B" then deletee(n, s, l, consume, d) + c == "D" then deletee(n, s, l, consume, d) + c == "`" then returnn(s, consume)(d) + n < l then writeChar(c, loop(n + 1, c :: s, l, consume), d) + else ringBell(loop(n, s, l, consume), d) + x +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun readAt(x_y, l, consume) = writeAt(x_y, replicate(l, "_"), moveTo(x_y, loop(0, "", l, consume))) + +fun promptReadAt(x_y, l, prompt, consume) = if x_y is [x, y] then + writeAt([x, y], prompt, readAt([x + listLen(prompt), y], l, consume)) + +fun program(input) = writes( + cls :: + at([17, 5], highlight(nofibStringToList("Demonstration program"))) :: + at([48, 5], nofibStringToList("Version 1.0")) :: + at([17, 7], nofibStringToList("This program illustrates a simple approach")) :: + at([17, 8], nofibStringToList("to screen-based interactive programs using")) :: + at([17, 9], nofibStringToList("the Hugs functional programming system.")) :: + at([17, 11], nofibStringToList("Please press any key to continue ...")) :: + Nil, + x => pressAnyKey(promptReadAt( + [17, 15], + 18, + nofibStringToList("Please enter your name: "), + (name) => + let reply = nofibStringToList("Hello ") +: name +: nofibStringToList("!") + writeAt( + [40 - (listLen(reply) / 2), 18], + reply, + moveTo( + [1, 23], + y => writeString(nofibStringToList("I'm waiting..."), x => pressAnyKey(end, x), y) + ) + ) + ), x), + input +) + +fun testAnsi_nofib(n) = foldr(compose, (x) => x, replicate(n, program))(nofibStringToList("testtesttest")) + +fun main() = nofibListToString(testAnsi_nofib(1)) diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/atom.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/atom.mls new file mode 100644 index 0000000000..f1ba8582fa --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/atom.mls @@ -0,0 +1,51 @@ +import "./NofibPrelude.mls" +open NofibPrelude + +module atom with ... + + + +data class State(position: List[Num], velocity: List[Num]) + +fun dotPlus(fs, gs) = if + fs is Nil then gs + gs is Nil then fs + fs is f :: fs and gs is g :: gs then (f + g) :: dotPlus(fs, gs) + +fun dotMult(fs, gs) = if + fs is f :: fs and gs is g :: gs then (f * g) :: dotMult(fs, gs) + else Nil + +fun scalarMut(c, fs) = if fs is + Nil then Nil + f :: fs then (c * f) :: scalarMut(c, fs) + +fun testforce(k, ss) = lazy of () => + if force(ss) is + LzCons(State(pos, vel), atoms) then LzCons(dotMult(scalarMut(-1.0, k), pos), testforce(k, atoms)) + +fun show(s) = + fun lscomp(ls) = if ls is + Nil then Nil + component :: t then Cons(stringConcat(stringOfFloat(component), "\t"), lscomp(t)) + if s is State(pos, vel) then + stringListConcat of lscomp(pos) + +fun propagate(dt, aforce, state) = if state is State(pos, vel) then + State(dotPlus(pos, scalarMut(dt, vel)), dotPlus(vel, scalarMut(dt, aforce))) + +fun runExperiment(law, dt, param, init) = lazy of () => + let stream = runExperiment(law, dt, param, init) + LzCons(init, zipWith_lz_lz((x, y) => propagate(dt, x, y), law(param, stream), stream)) + +fun testAtom_nofib(n) = + fun lscomp(ls) = if ls is + Nil then Nil + state :: t then stringConcat(show(state), "\n") :: lscomp(t) + stringListConcat of lscomp(take_lz(n, runExperiment(testforce, 0.02, 1.0 :: Nil, State(1.0 :: Nil, 0.0 :: Nil)))) + + +// NOTE: original input 1000 +fun main() = testAtom_nofib(20) + + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/awards.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/awards.mls new file mode 100644 index 0000000000..85f77c3a66 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/awards.mls @@ -0,0 +1,76 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module awards with ... + + + +fun delete_(xs, e) = deleteBy((x, y) => x == y, e, xs) + +fun listDiff(a, ls) = foldl(delete_, a, ls) + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun qsort(le, ls, r) = if ls is + Nil then r + x :: Nil then x :: r + x :: xs then qpart(le, x, xs, Nil, Nil, r) + +fun qpart(le, x, ys, rlt, rge, r) = if ys is + Nil then rqsort(le, rlt, x :: rqsort(le, rge, r)) + y :: ys and + le(x, y) then qpart(le, x, ys, rlt, y :: rge, r) + else qpart(le, x, ys, y :: rlt, rge, r) + +fun rqsort(le, ls, r) = if ls is + Nil then r + x :: Nil then x :: r + x :: xs then rqpart(le, x, xs, Nil, Nil, r) + +fun rqpart(le, x, yss, rle, rgt, r) = if yss is + Nil then qsort(le, rle, x :: qsort(le, rgt, r)) + y :: ys and + le(y, x) then rqpart(le, x, ys, y :: rle, rgt, r) + else rqpart(le, x, ys, rle, y :: rgt, r) +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun sort(l) = qsort((a, b) => ltTup2(a, b, (a, b) => a < b, (a, b) => a > b, (a, b) => ltList(a, b, (a, b) => a < b, (a, b) => a > b)), l, Nil) + +fun perms(m, nns) = if + nns is Nil then Nil + m == 1 then map(x => x :: Nil, nns) + nns is n :: ns then map(x => n :: x, perms(m-1, ns)) +: perms(m, ns) + +fun awards(scores) = + let sumscores = map(p => [sum(p), p], perms(3, scores)) + + fun atleast(threshold) = + filter(case { [sum_, p] then sum_ >= threshold }, sumscores) + + fun award(name_threshold) = if name_threshold is [name, threshold] then + map(ps => [name, ps], sort(atleast(threshold))) + + award(["Gold", 70]) +: award(["Silver", 60]) +: award(["Bronze", 50]) + +fun findawards(scores) = if awards(scores) is + Nil then Nil + head_ :: tail_ and head_ is [award, [sum_, perm]] then + [award, [sum_, perm]] :: findawards(listDiff(scores, perm)) + +fun findallawards(competitors) = + map(case { [name, scores] then [name, findawards(scores)] }, competitors) + +fun competitors(i) = list of + ["Simon", list of 35, 27, 40, i, 34, 21] + ["Hans", list of 23, 19, 45, i, 17, 10, 5, 8, 14] + ["Phil", list of 1, 18, i, 20, 21, 19, 34, 8, 16, 21] + ["Kevin", list of 9, 23, 17, 54, i, 41, 9, 18, 14] + +fun testAwards_nofib(n) = + map(x => findallawards(competitors(intMod(x, 100))), enumFromTo(1, n)) + + +// NOTE: original input 1000 +fun main() = testAwards_nofib(100) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/banner.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/banner.mls new file mode 100644 index 0000000000..b3f02e72a6 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/banner.mls @@ -0,0 +1,121 @@ +import "./NofibPrelude.mls" +open NofibPrelude + +module banner with ... + + + +val blank = + nofibStringToList(" ") :: + nofibStringToList(" ") :: + nofibStringToList(" ") :: + nofibStringToList(" ") :: + nofibStringToList(" ") :: Nil +//│ blank = [[" "," "," "," "," "],[" "," "," "," "," "],[" "," "," "," "," "],[" "," "," "," "," "],[" "," "," "," "," "]] + +val alphas = + (nofibStringToList(" A ") :: nofibStringToList(" A A ") :: nofibStringToList("AAAAA") :: nofibStringToList("A A") :: nofibStringToList("A A") :: Nil) :: + (nofibStringToList("BBBB ") :: nofibStringToList("B B") :: nofibStringToList("BBBB ") :: nofibStringToList("B B") :: nofibStringToList("BBBB ") :: Nil) :: + (nofibStringToList(" CCCC") :: nofibStringToList("C ") :: nofibStringToList("C ") :: nofibStringToList("C ") :: nofibStringToList(" CCCC") :: Nil) :: + (nofibStringToList("DDDD ") :: nofibStringToList("D D") :: nofibStringToList("D D") :: nofibStringToList("D D") :: nofibStringToList("DDDD ") :: Nil) :: + (nofibStringToList("EEEEE") :: nofibStringToList("E ") :: nofibStringToList("EEEEE") :: nofibStringToList("E ") :: nofibStringToList("EEEEE") :: Nil) :: + (nofibStringToList("FFFFF") :: nofibStringToList("F ") :: nofibStringToList("FFFF ") :: nofibStringToList("F ") :: nofibStringToList("F ") :: Nil) :: + (nofibStringToList(" GGGG") :: nofibStringToList("G ") :: nofibStringToList("G GG") :: nofibStringToList("G G") :: nofibStringToList(" GGG ") :: Nil) :: + (nofibStringToList("H H") :: nofibStringToList("H H") :: nofibStringToList("HHHHH") :: nofibStringToList("H H") :: nofibStringToList("H H") :: Nil) :: + (nofibStringToList("IIIII") :: nofibStringToList(" I ") :: nofibStringToList(" I ") :: nofibStringToList(" I ") :: nofibStringToList("IIIII") :: Nil) :: + (nofibStringToList("JJJJJ") :: nofibStringToList(" J ") :: nofibStringToList(" J ") :: nofibStringToList("J J ") :: nofibStringToList(" JJ ") :: Nil) :: + (nofibStringToList("K K") :: nofibStringToList("K K ") :: nofibStringToList("KKK ") :: nofibStringToList("K K ") :: nofibStringToList("K K") :: Nil) :: + (nofibStringToList("L ") :: nofibStringToList("L ") :: nofibStringToList("L ") :: nofibStringToList("L ") :: nofibStringToList("LLLLL") :: Nil) :: + (nofibStringToList("M M") :: nofibStringToList("MM MM") :: nofibStringToList("M M M") :: nofibStringToList("M M") :: nofibStringToList("M M") :: Nil) :: + (nofibStringToList("N N") :: nofibStringToList("NN N") :: nofibStringToList("N N N") :: nofibStringToList("N NN") :: nofibStringToList("N N") :: Nil) :: + (nofibStringToList(" OOO ") :: nofibStringToList("O O") :: nofibStringToList("O O") :: nofibStringToList("O O") :: nofibStringToList(" OOO ") :: Nil) :: + (nofibStringToList("PPPP ") :: nofibStringToList("P P") :: nofibStringToList("PPPP ") :: nofibStringToList("P ") :: nofibStringToList("P ") :: Nil) :: + (nofibStringToList(" QQQ ") :: nofibStringToList("Q Q") :: nofibStringToList("Q Q Q") :: nofibStringToList("Q Q ") :: nofibStringToList(" QQ Q") :: Nil) :: + (nofibStringToList("RRRR ") :: nofibStringToList("R R") :: nofibStringToList("RRRR ") :: nofibStringToList("R R ") :: nofibStringToList("R R") :: Nil) :: + (nofibStringToList(" SSSS") :: nofibStringToList("S ") :: nofibStringToList(" SSS ") :: nofibStringToList(" S") :: nofibStringToList("SSSS ") :: Nil) :: + (nofibStringToList("TTTTT") :: nofibStringToList(" T ") :: nofibStringToList(" T ") :: nofibStringToList(" T ") :: nofibStringToList(" T ") :: Nil) :: + (nofibStringToList("U U") :: nofibStringToList("U U") :: nofibStringToList("U U") :: nofibStringToList("U U") :: nofibStringToList(" UUU ") :: Nil) :: + (nofibStringToList("V V") :: nofibStringToList("V V") :: nofibStringToList("V V") :: nofibStringToList(" V V ") :: nofibStringToList(" V ") :: Nil) :: + (nofibStringToList("W W") :: nofibStringToList("W W") :: nofibStringToList("W W") :: nofibStringToList("W W W") :: nofibStringToList(" W W ") :: Nil) :: + (nofibStringToList("X X") :: nofibStringToList(" X X ") :: nofibStringToList(" X ") :: nofibStringToList(" X X ") :: nofibStringToList("X X") :: Nil) :: + (nofibStringToList("Y Y") :: nofibStringToList(" Y Y ") :: nofibStringToList(" Y ") :: nofibStringToList(" Y ") :: nofibStringToList(" Y ") :: Nil) :: + (nofibStringToList("ZZZZZ") :: nofibStringToList(" Z ") :: nofibStringToList(" Z ") :: nofibStringToList(" Z ") :: nofibStringToList("ZZZZZ") :: Nil) :: Nil +//│ alphas = [[[" "," ","A"," "," "],[" ","A"," ","A"," "],["A","A","A","A","A"],["A"," "," "," ","A"],["A"," "," "," ","A"]],[["B","B","B","B"," "],["B"," "," "," ","B"],["B","B","B","B"," "],["B"," "," "," ","B"],["B","B","B","B"," "]],[[" ","C","C","C","C"],["C"," "," "," "," "],["C"," "," "," "," "],["C"," "," "," "," "],[" ","C","C","C","C"]],[["D","D","D","D"," "],["D"," "," "," ","D"],["D"," "," "," ","D"],["D"," "," "," ","D"],["D","D","D","D"," "]],[["E","E","E","E","E"],["E"," "," "," "," "],["E","E","E","E","E"],["E"," "," "," "," "],["E","E","E","E","E"]],[["F","F","F","F","F"],["F"," "," "," "," "],["F","F","F","F"," "],["F"," "," "," "," "],["F"," "," "," "," "]],[[" ","G","G","G","G"],["G"," "," "," "," "],["G"," "," ","G","G"],["G"," "," "," ","G"],[" ","G","G","G"," "]],[["H"," "," "," ","H"],["H"," "," "," ","H"],["H","H","H","H","H"],["H"," "," "," ","H"],["H"," "," "," ","H"]],[["I","I","I","I","I"],[" "," ","I"," "," "],[" "," ","I"," "," "],[" "," ","I"," "," "],["I","I","I","I","I"]],[["J","J","J","J","J"],[" "," "," ","J"," "],[" "," "," ","J"," "],["J"," "," ","J"," "],[" ","J","J"," "," "]],[["K"," "," "," ","K"],["K"," "," ","K"," "],["K","K","K"," "," "],["K"," "," ","K"," "],["K"," "," "," ","K"]],[["L"," "," "," "," "],["L"," "," "," "," "],["L"," "," "," "," "],["L"," "," "," "," "],["L","L","L","L","L"]],[["M"," "," "," ","M"],["M","M"," ","M","M"],["M"," ","M"," ","M"],["M"," "," "," ","M"],["M"," "," "," ","M"]],[["N"," "," "," ","N"],["N","N"," "," ","N"],["N"," ","N"," ","N"],["N"," "," ","N","N"],["N"," "," "," ","N"]],[[" ","O","O","O"," "],["O"," "," "," ","O"],["O"," "," "," ","O"],["O"," "," "," ","O"],[" ","O","O","O"," "]],[["P","P","P","P"," "],["P"," "," "," ","P"],["P","P","P","P"," "],["P"," "," "," "," "],["P"," "," "," "," "]],[[" ","Q","Q","Q"," "],["Q"," "," "," ","Q"],["Q"," ","Q"," ","Q"],["Q"," "," ","Q"," "],[" ","Q","Q"," ","Q"]],[["R","R","R","R"," "],["R"," "," "," ","R"],["R","R","R","R"," "],["R"," "," ","R"," "],["R"," "," "," ","R"]],[[" ","S","S","S","S"],["S"," "," "," "," "],[" ","S","S","S"," "],[" "," "," "," ","S"],["S","S","S","S"," "]],[["T","T","T","T","T"],[" "," ","T"," "," "],[" "," ","T"," "," "],[" "," ","T"," "," "],[" "," ","T"," "," "]],[["U"," "," "," ","U"],["U"," "," "," ","U"],["U"," "," "," ","U"],["U"," "," "," ","U"],[" ","U","U","U"," "]],[["V"," "," "," ","V"],["V"," "," "," ","V"],["V"," "," "," ","V"],[" ","V"," ","V"," "],[" "," ","V"," "," "]],[["W"," "," "," ","W"],["W"," "," "," ","W"],["W"," "," "," ","W"],["W"," ","W"," ","W"],[" ","W"," ","W"," "]],[["X"," "," "," ","X"],[" ","X"," ","X"," "],[" "," ","X"," "," "],[" ","X"," ","X"," "],["X"," "," "," ","X"]],[["Y"," "," "," ","Y"],[" ","Y"," ","Y"," "],[" "," ","Y"," "," "],[" "," ","Y"," "," "],[" "," ","Y"," "," "]],[["Z","Z","Z","Z","Z"],[" "," "," ","Z"," "],[" "," ","Z"," "," "],[" ","Z"," "," "," "],["Z","Z","Z","Z","Z"]]] + +val slant = + nofibStringToList(" ") :: + nofibStringToList(" ") :: + nofibStringToList(" ") :: + nofibStringToList(" ") :: + nofibStringToList("") :: Nil +//│ slant = [[" "," "," "," "],[" "," "," "],[" "," "],[" "],[]] + +val punct = + [".", nofibStringToList(" ") :: nofibStringToList(" ") :: nofibStringToList(" ") :: nofibStringToList(" .. ") :: nofibStringToList(" .. ") :: Nil] :: + ["?", nofibStringToList(" ??? ") :: nofibStringToList("? ?") :: nofibStringToList(" ? ") :: nofibStringToList(" ? ") :: nofibStringToList(" . ") :: Nil] :: + ["!", nofibStringToList(" ! ") :: nofibStringToList(" ! ") :: nofibStringToList(" ! ") :: nofibStringToList(" ! ") :: nofibStringToList(" . ") :: Nil] :: + ["-", nofibStringToList(" ") :: nofibStringToList(" ") :: nofibStringToList("-----") :: nofibStringToList(" ") :: nofibStringToList(" ") :: Nil] :: + ["+", nofibStringToList(" + ") :: nofibStringToList(" + ") :: nofibStringToList("+++++") :: nofibStringToList(" + ") :: nofibStringToList(" + ") :: Nil] :: + [":", nofibStringToList(" ") :: nofibStringToList(" :: ") :: nofibStringToList(" ") :: nofibStringToList(" :: ") :: nofibStringToList(" ") :: Nil] :: + [";", nofibStringToList(" ") :: nofibStringToList(" ;; ") :: nofibStringToList(" ") :: nofibStringToList(" ;; ") :: nofibStringToList(" ;; ") :: Nil] :: Nil +//│ punct = [[".", [[" "," "," "," "," "],[" "," "," "," "," "],[" "," "," "," "," "],[" "," ",".","."," "],[" "," ",".","."," "]]],["?", [[" ","?","?","?"," "],["?"," "," "," ","?"],[" "," "," ","?"," "],[" "," ","?"," "," "],[" "," ","."," "," "]]],["!", [[" "," ","!"," "," "],[" "," ","!"," "," "],[" "," ","!"," "," "],[" "," ","!"," "," "],[" "," ","."," "," "]]],["-", [[" "," "," "," "," "],[" "," "," "," "," "],["-","-","-","-","-"],[" "," "," "," "," "],[" "," "," "," "," "]]],["+", [[" "," ","+"," "," "],[" "," ","+"," "," "],["+","+","+","+","+"],[" "," ","+"," "," "],[" "," ","+"," "," "]]],[":", [[" "," "," "," "," "],[" "," ",":",":"," "],[" "," "," "," "," "],[" "," ",":",":"," "],[" "," "," "," "," "]]],[";", [[" "," "," "," "," "],[" "," ",";",";"," "],[" "," "," "," "," "],[" "," ",";",";"," "],[" ",";",";"," "," "]]]] + +val digits = + (nofibStringToList(" OOO ") :: nofibStringToList("0 00") :: nofibStringToList("0 0 0") :: nofibStringToList("00 0") :: nofibStringToList(" 000 ") :: Nil) :: + (nofibStringToList(" 1 ") :: nofibStringToList(" 11 ") :: nofibStringToList(" 1 ") :: nofibStringToList(" 1 ") :: nofibStringToList("11111") :: Nil) :: + (nofibStringToList(" 222 ") :: nofibStringToList("2 2") :: nofibStringToList(" 2 ") :: nofibStringToList(" 2 ") :: nofibStringToList("22222") :: Nil) :: + (nofibStringToList("3333 ") :: nofibStringToList(" 3") :: nofibStringToList(" 333 ") :: nofibStringToList(" 3") :: nofibStringToList("3333 ") :: Nil) :: + (nofibStringToList(" 4 ") :: nofibStringToList(" 44 ") :: nofibStringToList(" 4 4 ") :: nofibStringToList("44444") :: nofibStringToList(" 4 ") :: Nil) :: + (nofibStringToList("55555") :: nofibStringToList("5 ") :: nofibStringToList("5555 ") :: nofibStringToList(" 5") :: nofibStringToList("5555 ") :: Nil) :: + (nofibStringToList(" 66") :: nofibStringToList(" 6 ") :: nofibStringToList(" 666 ") :: nofibStringToList("6 6") :: nofibStringToList(" 666 ") :: Nil) :: + (nofibStringToList("77777") :: nofibStringToList(" 7") :: nofibStringToList(" 7 ") :: nofibStringToList(" 7 ") :: nofibStringToList(" 7 ") :: Nil) :: + (nofibStringToList(" 888 ") :: nofibStringToList("8 8") :: nofibStringToList(" 888 ") :: nofibStringToList("8 8") :: nofibStringToList(" 888 ") :: Nil) :: + (nofibStringToList(" 999 ") :: nofibStringToList("9 9") :: nofibStringToList(" 999 ") :: nofibStringToList(" 9 ") :: nofibStringToList("99 ") :: Nil) :: Nil +//│ digits = [[[" ","O","O","O"," "],["0"," "," ","0","0"],["0"," ","0"," ","0"],["0","0"," "," ","0"],[" ","0","0","0"," "]],[[" "," ","1"," "," "],[" ","1","1"," "," "],[" "," ","1"," "," "],[" "," ","1"," "," "],["1","1","1","1","1"]],[[" ","2","2","2"," "],["2"," "," "," ","2"],[" "," "," ","2"," "],[" "," ","2"," "," "],["2","2","2","2","2"]],[["3","3","3","3"," "],[" "," "," "," ","3"],[" ","3","3","3"," "],[" "," "," "," ","3"],["3","3","3","3"," "]],[[" "," "," ","4"," "],[" "," ","4","4"," "],[" ","4"," ","4"," "],["4","4","4","4","4"],[" "," "," ","4"," "]],[["5","5","5","5","5"],["5"," "," "," "," "],["5","5","5","5"," "],[" "," "," "," ","5"],["5","5","5","5"," "]],[[" "," "," ","6","6"],[" "," ","6"," "," "],[" ","6","6","6"," "],["6"," "," "," ","6"],[" ","6","6","6"," "]],[["7","7","7","7","7"],[" "," "," "," ","7"],[" "," "," ","7"," "],[" "," "," ","7"," "],[" "," ","7"," "," "]],[[" ","8","8","8"," "],["8"," "," "," ","8"],[" ","8","8","8"," "],["8"," "," "," ","8"],[" ","8","8","8"," "]],[[" ","9","9","9"," "],["9"," "," "," ","9"],[" ","9","9","9"," "],[" "," ","9"," "," "],["9","9"," "," "," "]]] + +fun unlines(ls) = concat(map(x => x +: ("\n" :: Nil), ls)) + +fun join(ls) = foldr1((xs, ys) => xs +: (" " :: " " :: Nil) +: ys, ls) + +fun isUpper(c) = + let n = int_of_char(c) + (n >= 65) and (n <= 90) + +fun isLower(c) = + let n = int_of_char(c) + (n >= 97) and (n <= 122) + +fun isDigit(c) = + let n = int_of_char(c) + (n >= 48) and (n <= 57) + +fun isSpace(c) = + let n = int_of_char(c) + (n == 32) + +fun picChar(c) = + + fun lscomp(ls) = if ls is + Nil then Nil + h :: t and + h is [c_, letter] and c_ === c then letter :: lscomp(t) + else lscomp(t) + + if + isUpper(c) then atIndex(int_of_char(c) - int_of_char("A"), alphas) + isLower(c) then atIndex(int_of_char(c) - int_of_char("a"), alphas) + isSpace(c) then blank + isDigit(c) then atIndex(int_of_char(c) - int_of_char("0"), digits) + c === "/" then slant + c === "=" then reverse(slant) + else head(lscomp(punct) +: Nil :: Nil :: Nil) + +fun say(s) = "\n" :: (unlines(map(join, transpose(map(picChar, s))))) + +fun testBanner_nofib(n) = + let x = nofibStringToList("Is this not a great banner?") + say(concat(replicate(n, x))) + + +fun main() = nofibListToString(testBanner_nofib(1)) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/boyer.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/boyer.mls new file mode 100644 index 0000000000..780b1f7776 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/boyer.mls @@ -0,0 +1,312 @@ +import "./NofibPrelude.mls" +open NofibPrelude + + + + +module boyer with ... + + + +abstract class Id: A | B | C | D | X | Y | Z | U | W | ADD1 | AND | APPEND | CONS | CONSP | DIFFERENCE | DIVIDES | EQUAL | EVEN | EXP | F | FALSE | FOUR | GCD | GREATEREQP | GREATERP | IF | IFF | IMPLIES | LENGTH | LESSEQP | LESSP | LISTP | MEMBER | NIL | NILP | NLISTP | NOT | ODD | ONE | OR | PLUS | QUOTIENT | REMAINDER | REVERSE | SUB1 | TIMES | TRUE | TWO | ZERO | ZEROP + +object + A extends Id + B extends Id + C extends Id + D extends Id + X extends Id + Y extends Id + Z extends Id + U extends Id + W extends Id + ADD1 extends Id + AND extends Id + APPEND extends Id + CONS extends Id + CONSP extends Id + DIFFERENCE extends Id + DIVIDES extends Id + EQUAL extends Id + EVEN extends Id + EXP extends Id + F extends Id + FALSE extends Id + FOUR extends Id + GCD extends Id + GREATEREQP extends Id + GREATERP extends Id + IF extends Id + IFF extends Id + IMPLIES extends Id + LENGTH extends Id + LESSEQP extends Id + LESSP extends Id + LISTP extends Id + MEMBER extends Id + NIL extends Id + NILP extends Id + NLISTP extends Id + NOT extends Id + ODD extends Id + ONE extends Id + OR extends Id + PLUS extends Id + QUOTIENT extends Id + REMAINDER extends Id + REVERSE extends Id + SUB1 extends Id + TIMES extends Id + TRUE extends Id + TWO extends Id + ZERO extends Id + ZEROP extends Id + +abstract class Term: Var | Fun | ERROR + +data + class + Var(i: Id) extends Term + Fun(i: Id, t: List[Term], l: [Term, Term]) extends Term +object ERROR extends Term + + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun termLsEq(h1t1, h2t2) = if + h1t1 is h1 :: t1 and h2t2 is h2 :: t2 and + termEq(h1, h2) then termLsEq(t1, t2) + else false + else true + +fun termEq(t1, t2) = if + t1 is Var(i1) and t2 is Var(i2) then i1 === i2 + t1 is Fun(f1, ts1, _) and t2 is Fun(f2, ts2, _) then (f1 === f2) and termLsEq(ts1, ts2) + else false +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun termInList(term, ht) = if ht is + h :: t and + termEq(term, h) then true + else termInList(term, t) + Nil then false + +fun find(vid, ls) = if ls is + Nil then [false, ERROR] + [vid2, val2] :: bs and + vid === vid2 then [true, val2] + else find(vid, bs) + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun one_way_unify1(term1, term2, subst) = if + term2 is Var(vid2) and find(vid2, subst) is [found, v2] and + found then [termEq(term1, v2), subst] + else [true, [vid2, term1] :: subst] + term1 is Fun(f1, as1, _) and term2 is Fun(f2, as2, _) and + f1 === f2 then one_way_unify1_lst(as1, as2, subst) + else [false, Nil] + else [false, Nil] + +fun one_way_unify1_lst(tts1, tts2, subst) = if + tts1 is Nil and tts2 is Nil then [true, subst] + tts1 is t1 :: ts1 and tts2 is t2 :: ts2 and one_way_unify1(t1, t2, subst) is [hd_ok, subst_] and one_way_unify1_lst(ts1, ts2, subst_) is [tl_ok, subst__] then [hd_ok and tl_ok, subst__] + else [false, Nil] +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun one_way_unify(term1, term2) = one_way_unify1(term1, term2, Nil) + +fun apply_subst(subst, t) = if t is + Var(vid) and find(vid, subst) is [found, value] and + found then value + else Var(vid) + Fun(f, args, ls) then Fun(f, map(x => apply_subst(subst, x), args), ls) + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun rewrite_with_lemmas_helper(term, lss) = if lss is + Nil then term + [lhs, rhs] :: ls and one_way_unify(term, lhs) is [unified, subst] and + unified then rewrite(apply_subst(subst, rhs)) + else rewrite_with_lemmas_helper(term, ls) + +fun rewrite_with_lemmas(term, lss) = rewrite_with_lemmas_helper(term, force(lss)) + +fun rewrite(t) = if t is + Var(v) then Var(v) + Fun(f, args, lemmas) then rewrite_with_lemmas(Fun(f, map(rewrite, args), lemmas), lemmas) +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun truep(x, l) = if x is + Fun(TRUE, _, _) then true + else termInList(x, l) + +fun falsep(x, l) = if x is + Fun(FALSE, _, _) then true + else termInList(x, l) + +fun tautologyp(x, true_lst, false_lst) = if + truep(x, true_lst) then true + falsep(x, false_lst) then false + x is + Fun(IF, cond :: t :: e :: Nil, _) and + truep(cond, true_lst) then tautologyp(t, true_lst, false_lst) + falsep(cond, false_lst) then tautologyp(e, true_lst, false_lst) + else tautologyp(t, cond :: true_lst, false_lst) and tautologyp(e, true_lst, cond :: false_lst) + else false + +fun tautp(x) = tautologyp(rewrite(x), Nil, Nil) + +fun test0(xxxx) = + let a = Var(A) + let b = Var(B) + let c = Var(C) + let d = Var(D) + let u = Var(U) + let w = Var(W) + let x = Var(X) + let y = Var(Y) + let z = Var(Z) + let boyerFalse = Fun(FALSE, Nil, lazy of () => Nil) + let nil = Fun(NIL , Nil, lazy of () => Nil) + let boyerTrue = Fun(TRUE , Nil, lazy of () => Nil) + let zero = Fun(ZERO , Nil, lazy of () => Nil) + + fun one() = Fun(ONE, Nil, lazy of () => [one(), add1(zero)] :: Nil) + + fun two() = Fun(TWO, Nil, lazy of () => [two(), add1(one())] :: Nil) + + fun four() = Fun(FOUR, Nil, lazy of () => [four(), add1(add1(two()))] :: Nil) + + fun add1(a) = Fun(ADD1, a :: Nil, lazy of () => Nil) + + fun if_(a, b, c) = Fun(IF, a :: b :: c :: Nil, lazy of () => [if_(if_(x, y, z), u, w), if_(x, if_(y, u, w), if_(z, u, w))] :: Nil) + + fun not_(a) = Fun(NOT, a :: Nil, lazy of () => [not_(x), if_(x, boyerFalse, boyerTrue)] :: Nil) + + fun and_(a, b) = + Fun(AND, a :: b :: Nil, lazy of () => [and_(x, y), if_(x, if_(y, boyerTrue, boyerFalse), boyerFalse)] :: Nil) + + fun append_(a, b) = + Fun(APPEND, a :: b :: Nil, lazy of () => [append_(append_(x, y), z), append_(x, append_(y, z))] :: Nil) + + fun cons(a, b) = + Fun(CONS, a :: b :: Nil, lazy of () => Nil) + + fun consp(a) = + Fun(CONSP, a :: Nil, lazy of () => [consp(cons(x, y)), boyerTrue] :: Nil) + + fun difference(a, b) = + Fun(DIFFERENCE, a :: b :: Nil, lazy of () => [difference(x, x), zero] :: [difference(plus(x, y), x), y] :: [difference(plus(y, x), x), y] :: [difference(plus(x, y), plus(x, z)), difference(y, z)] :: [difference(plus(y, plus(x, z)), x), plus(y, z)] :: [difference(add1(plus(y, z)), z), add1(y)] :: [difference(add1(add1(x)), two()), x] :: Nil) + + fun divides(a, b) = + Fun(DIVIDES, a :: b :: Nil, lazy of () => [divides(x, y), zerop(remainder(y, x))] :: Nil) + + fun equal(a, b) = + Fun( + EQUAL, + a :: b :: Nil, + lazy of () => + [equal(plus(x, y), zero), and_(zerop(x), zerop(y))] :: + [equal(plus(x, y), plus(x, z)), equal(y, z)] :: + [equal(zero, difference(x, y)), not_(lessp(y, x))] :: + [equal(x, difference(x, y)), or_(equal(x, zero), zerop(y))] :: + [equal(times(x, y), zero), or_(zerop(x), zerop(y))] :: + [equal(append_(x, y), append_(x, z)), equal(y, z)] :: + [equal(y, times(x, y)), or_(equal(y, zero), equal(x, one()))] :: + [equal(x, times(x, y)), or_(equal(x, zero), equal(y, one()))] :: + [equal(times(x, y), one()), and_(equal(x, one()), equal(y, one()))] :: + [equal(difference(x, y), difference(z, y)), if_(lessp(x, y), not_(lessp(y, z)), if_(lessp(z, y), not_(lessp(y, x)), equal(x, z)))] :: + [equal(lessp(x, y), z), if_(lessp(x, y), equal(boyerTrue, z), equal(boyerFalse, z))] :: + Nil + ) + + fun even_(a) = + Fun(EVEN, a :: Nil, lazy of () => [even_(x), if_(zerop(x), boyerTrue, odd_(sub1(x)))] :: Nil) + + fun exp_(a, b) = + Fun(EXP, a :: b :: Nil, lazy of () => [exp_(x, plus(y, z)), times(exp_(x, y), exp_(x, z))] :: [exp_(x, times(y, z)), exp_(exp_(x, y), z)] :: Nil) + + fun f(a) = + Fun(F, a :: Nil, lazy of () => Nil) + + fun gcd_(a, b) = + Fun(GCD, a :: b :: Nil, lazy of () => [gcd_(x, y), gcd_(y, x)] :: [gcd_(times(x, z), times(y, z)), times(z, gcd_(x, y))] :: Nil) + + fun greatereqp(a, b) = + Fun(GREATEREQP, a :: b :: Nil, lazy of () => [greatereqp(x, y), not_(lessp(x, y))] :: Nil) + + fun greaterp(a, b) = + Fun(GREATERP, a :: b :: Nil, lazy of () => [greaterp(x, y), lessp(y, x)] :: Nil) + + fun implies(a, b) = + Fun(IMPLIES, a :: b :: Nil, lazy of () => [implies(x, y), if_(x, if_(y, boyerTrue, boyerFalse), boyerTrue)] :: Nil) + + fun iff(a, b) = + Fun(IFF, a :: b :: Nil, lazy of () => [iff(x, y), and_(implies(x, y), implies(y, x))] :: Nil) + + fun length_(a) = + Fun(LENGTH, a :: Nil, lazy of () => [length_(reverse_(x)), length_(x)] :: [length_(cons(x, cons(y, cons(z, cons(u, w))))), plus(four(), length_(w))] :: Nil) + + fun lesseqp(a, b) = + Fun(LESSEQP, a :: b :: Nil, lazy of () => [lesseqp(x, y), not_(lessp(y, x))] :: Nil) + + fun lessp(a, b) = + Fun( + LESSP, + a :: b :: Nil, + lazy of () => + [lessp(remainder(x, y), y), not_(zerop(y))] :: + [lessp(quotient(x, y), x), and_(not_(zerop(x)), lessp(one(), y))] :: + [lessp(plus(x, y), plus(x, z)), lessp(y, z)] :: + [lessp(times(x, z), times(y, z)), and_(not_(zerop(z)), lessp(x, y))] :: + [lessp(y, plus(x, y)), not_(zerop(x))] :: + Nil + ) + + fun nilp(a) = + Fun(NILP, a :: Nil, lazy of () => [nilp(x), equal(x, nil)] :: Nil) + + fun listp(a) = + Fun(LISTP, a :: Nil, lazy of () => [listp(x), or_(nilp(x), consp(x))] :: Nil) + + fun member(a, b) = + Fun(MEMBER, a :: b :: Nil, lazy of () => [member(x, append_(y, z)), or_(member(x, y), member(x, z))] :: [member(x, reverse_(y)), member(x, y)] :: Nil) + + fun nlistp(a) = + Fun(NLISTP, a :: Nil, lazy of () => [nlistp(x), not_(listp(x))] :: Nil) + + fun odd_(a) = + Fun(ODD, a :: Nil, lazy of () => [odd_(x), even_(sub1(x))] :: Nil) + + fun or_(a, b) = + Fun(OR, a :: b :: Nil, lazy of () => [or_(x, y), if_(x, boyerTrue, if_(y, boyerTrue, boyerFalse))] :: Nil) + + fun plus(a, b) = + Fun(PLUS, a :: b :: Nil, lazy of () => [plus(plus(x, y), z), plus(x, plus(y, z))] :: [plus(remainder(x, y), times(y, quotient(x, y))), x] :: [plus(x, add1(y)), add1(plus(x, y))] :: Nil) + + fun quotient(a, b) = + Fun(QUOTIENT, a :: b :: Nil, lazy of () => [quotient(plus(x, plus(x, y)), two()), plus(x, quotient(y, two()))] :: [quotient(times(y, x), y), if_(zerop(y), zero, x)] :: Nil) + + fun remainder(a, b) = + Fun(REMAINDER, a :: b :: Nil, lazy of () => [remainder(x, one()), zero] :: [remainder(x, x), zero] :: [remainder(times(x, y), x), zero] :: [remainder(times(x, y), y), zero] :: Nil) + + fun reverse_(a) = + Fun(REVERSE, a :: Nil, lazy of () => [reverse_(append_(x, y)), append_(reverse_(y), reverse_(x))] :: Nil) + + fun sub1(a) = + Fun(SUB1, a :: Nil, lazy of () => [sub1(add1(x)), x] :: Nil) + + fun times(a, b) = + Fun(TIMES, a :: b :: Nil, lazy of () => [times(x, plus(y, z)), plus(times(x, y), times(x, z))] :: [times(times(x, y), z), times(x, times(y, z))] :: [times(x, difference(y, z)), difference(times(y, x), times(z, x))] :: [times(x, add1(y)), plus(x, times(x, y))] :: Nil) + + fun zerop(a) = + Fun(ZEROP, a :: Nil, lazy of () => [zerop(x), equal(x, zero)] :: Nil) + + let subst0 = [X, f(plus(plus(a, b), plus(c, zero)))] :: [Y, f(times(times(a, b), plus(c, d)))] :: [Z, f(reverse_(append_(append_(a, b), nil)))] :: [U, equal(plus(a, b), difference(x, y))] :: [W, lessp(remainder(a, b), member(a, length_(b)))] :: Nil + + let theorem = implies(and_(implies(xxxx, y), and_(implies(y, z), and_(implies(z, u), implies(u, w)))), implies(x, w)) + + tautp(apply_subst(subst0, theorem)) + +fun testBoyer_nofib(n) = all(test0, replicate(n, Var(X))) + +fun main() = testBoyer_nofib(5) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/boyer2.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/boyer2.mls new file mode 100644 index 0000000000..f82474b5f1 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/boyer2.mls @@ -0,0 +1,340 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + + +module boyer2 with ... + + + + +abstract class Lisplist: Nill | Atom | Conss + +object Nill extends Lisplist +data + class + Atom(a: List[Char]) extends Lisplist + Conss(a: [Lisplist, Lisplist]) extends Lisplist + +fun lispListEq(x, y) = if x is + Nill and y is Nill then true + Atom(a) and y is Atom(b) then listEq(a, b) + Conss([a, b]) and y is Conss([c, d]) and (lispListEq(a, c)) then lispListEq(b, d) + else false + +fun lispmember(e_x) = if e_x is + [e, Conss([x, xs])] and + lispListEq(e, x) then true + else lispmember([e, xs]) + [_, _] then false + +fun truep(term_l) = if term_l is + [Nill, _] then false + [Conss([Atom("t" :: Nil), Nill]), _] then true + [term, l] then lispmember([term, l]) + +fun falsep(term_l) = if term_l is + [Nill, _] then false + [Conss([Atom("f" :: Nil), Nill]), _] then true + [term, l] then lispmember([term, l]) + +fun tv(x) = if x is Atom(a) then a + +fun atom(x) = if x is Atom(_) then true else false + +fun car(x) = if x is Conss([a, _]) then a else Nill + +fun cdr(x) = if x is Conss([_, b]) then b else Nill + +fun cadr(x) = car(cdr(x)) + +fun caddr(x) = car(cdr(cdr(x))) + +fun cadddr(x) = car(cdr(cdr(cdr(x)))) + +fun tautologyp(f_truelst_falselst) = if f_truelst_falselst is [f, truelst, falselst] and f is + Nill then false + Atom(x) then truep([Atom(x), truelst]) + Conss([x, y]) and + truep([Conss([x, y]), truelst]) then true + falsep([Conss([x, y]), falselst]) then false + x is + Atom("i" :: "f" :: Nil) and + truep([car(y), truelst]) then + tautologyp([cadr(y), truelst, falselst]) + falsep([car(y), falselst]) then + tautologyp([caddr(y), truelst, falselst]) + else + tautologyp([cadr(y), Conss([car(y), truelst]), falselst]) and tautologyp([caddr(y), truelst, Conss([car(y), falselst])]) + else false + +fun sublist(t) = if t is + Nil then [Nil, Nill] + ("(" :: Nil) :: t and sublist(t) is [r1, l1] and sublist(r1) is [r2, l2] then [r2, Conss([l1, l2])] + (")" :: Nil) :: t then [t, Nill] + h :: t and sublist(t) is [r, l] then [r, Conss([Atom(h), l])] + +fun mkLispList(ls) = if ls is + ("(" :: Nil) :: t and sublist(t) is [r, l] and r is + Nil then l + else Nill + _ then Nill + +fun restOfToken(s) = if s is + Nil then [Nil, Nil] + h :: t and + (h === "(") || (h === ")") || (h === " ") then [Nil, h :: t] + restOfToken(t) is [a, b] then [h :: a, b] + +fun getToken(s) = if s is + Nil then [Nil, Nil] + h :: t and + (h === " ") then getToken(t) + (h === "(") || (h === ")") then [h :: Nil, t] + boyer2.restOfToken(t) is [a, b] then [h :: a, b] + +fun strToToken(s) = if + s is Nil then Nil + getToken(s) is [a, b] then a :: strToToken(b) + +fun assoc(term_x_y) = if term_x_y is + [term, Conss([x, y])] and x is + Conss([Atom(key), rest]) and + lispListEq(term, Atom(key)) then x + else assoc([term, y]) + _ then Nill + [_, _] then Nill + +type LUTentry = [String, List[Lisplist]] + +abstract class LUT: Empty | Node + +object Empty extends LUT + +data class Node(x: [LUT, LUTentry, LUT]) extends LUT + +fun addtoLUT(k_l_lut) = if k_l_lut is + [k, l, boyer2.Empty] then boyer2.Node([boyer2.Empty, [k, l :: Nil], boyer2.Empty]) + [k, l, boyer2.Node([left, [k1, kl], right])] and + listEq(k, k1) then boyer2.Node([left, [k1, l :: kl], right]) + ltList(k, k1, (x, y) => x < y, (x, y) => x > y) then boyer2.Node([addtoLUT([k, l, left]), [k1, kl], right]) + else boyer2.Node([left, [k1, kl], addtoLUT([k, l, right])]) + +fun getLUT(t_lut) = if t_lut is + [t, Empty] then Nil + [t, Node([left, [k, kl], right])] and + listEq(t, k) then kl + ltList(t, k, (x, y) => x < y, (x, y) => x > y) then getLUT([t, left]) + else getLUT([t, right]) + +fun makelemmas(rules) = if rules is + Nil then Nil + h :: t then boyer2.mkLispList(strToToken(h)) :: makelemmas(t) + +fun addlemma(lspls, term) = if lspls is + boyer2.Nill then term + boyer2.Atom(x) then throw new Error("error") + boyer2.Conss([x, y]) then + let z = boyer2.car(y) + if listEq(boyer2.tv(x), nofibStringToList("equal")) and (not(boyer2.atom(z))) + then addtoLUT([boyer2.tv(boyer2.car(z)), boyer2.Conss([x, y]), term]) + else throw new Error("error") + +fun addlemmalst(lspls, term) = if lspls is + Nil then term + h :: t then addlemmalst(t, boyer2.addlemma(h, term)) + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun applysubstlst(alist, y) = if y is + Nill then Nill + Atom(x) then throw new Error("error") + Conss([x, y]) then Conss([applysubst(alist, x), applysubstlst(alist, y)]) + +fun applysubst(alist, x) = if x is + Nill then Nill + Atom(x) and assoc([Atom(x), alist]) is + Conss([_, y]) then y + else Atom(x) + Conss([x, y]) then Conss([x, applysubstlst(alist, y)]) +//│ ———————————————————————————————————————————————————————————————————————————————— + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun onewayunify1lst(l1, l2, u) = if + l1 is Nill then [true, u] + onewayunify1(car(l1), car(l2), u) is [b, u1] and + b then onewayunify1lst(cdr(l1), cdr(l2), u1) + else [false, u1] + +fun onewayunify1(t1, t2, u) = if + atom(t2) and assoc([t2, u]) is + Conss([_, y]) then [lispListEq(t1, y), u] + else [true, Conss([Conss([t2, t1]), u])] + atom(t1) then [false, u] + lispListEq(car(t1), car(t2)) then onewayunify1lst(cdr(t1), cdr(t2), u) + else [false, u] +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun onewayunify(t1, t2) = onewayunify1(t1, t2, Nill) + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun rewritewithlemmas(t, l, term) = if l is + Nil then t + lh :: lt and onewayunify(t, cadr(lh)) is [b, u] and + b then rewrite(applysubst(u, caddr(lh)), term) + else rewritewithlemmas(t, lt, term) + +fun rewriteargs(x, term) = if x is + Nill then Nill + Atom(_) then throw new Error("error") + Conss([x, y]) then Conss([rewrite(x, term), rewriteargs(y, term)]) + +fun rewrite(x, term) = if x is + Nill then Nill + Atom(x) then Atom(x) + Conss([l1, l2]) then rewritewithlemmas(Conss([l1, rewriteargs(l2, term)]), getLUT([tv(l1), term]), term) +//│ ———————————————————————————————————————————————————————————————————————————————— + +val statement = boyer2.mkLispList(strToToken( + nofibStringToList("( implies ( and ( implies x y )( and ( implies y z )( and ( implies z u )( implies u w ) ) ) )( implies x w ) )") +)) +//│ statement = Conss([Atom(["i","m","p","l","i","e","s"]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["i","m","p","l","i","e","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["i","m","p","l","i","e","s"]), Conss([Atom(["y"]), Conss([Atom(["z"]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["i","m","p","l","i","e","s"]), Conss([Atom(["z"]), Conss([Atom(["u"]), Nill])])]), Conss([Conss([Atom(["i","m","p","l","i","e","s"]), Conss([Atom(["u"]), Conss([Atom(["w"]), Nill])])]), Nill])])]), Nill])])]), Nill])])]), Conss([Conss([Atom(["i","m","p","l","i","e","s"]), Conss([Atom(["x"]), Conss([Atom(["w"]), Nill])])]), Nill])])]) + +fun subterm(i) = + let c = stringConcat("c", stringOfInt(i)) + let str = stringConcat( + "( ( x f ( plus ( plus a b )( plus ", + stringConcat( + c, + stringConcat( + " ( zero ) ) ) )( y f ( times ( times a b )( plus ", + stringConcat(c, " d ) ) )( z f ( reverse ( append ( append a b ) ( [] ) ) ) )(u equal ( plus a b ) ( difference x y ) )(w lessp ( remainder a b )( member a ( length b ) ) ) )") + ) + ) + ) + mkLispList(strToToken(nofibStringToList(str))) + +fun report(b) = if b then "The term is a tautology" else "The term is not a tautology" + +val rules = + nofibStringToList("(equal (compile form)(reverse (codegen (optimize form) (Nill) ) ) )") :: + nofibStringToList("(equal (eqp x y)(equal (fix x)(fix y) ) )") :: + nofibStringToList("(equal (greaterp x y)(lessp y x) )") :: + nofibStringToList("(equal (lesseqp x y)(not (lessp y x) ) )") :: + nofibStringToList("(equal (greatereqp x y)(not (lessp y x) ) )") :: + nofibStringToList("(equal (boolean x)(or (equal x (t) )(equal x (f) ) )") :: + nofibStringToList("(equal (iff x y)(and (implies x y)(implies y x) ) )") :: + nofibStringToList("(equal (even1 x)(if (zerop x)(t)(odd (1- x) ) ) )") :: + nofibStringToList("(equal (countps- l pred)(countps-loop l pred (zero) ) )") :: + nofibStringToList("(equal (fact- i)(fact-loop i 1) )") :: + nofibStringToList("(equal (reverse- x)(reverse-loop x (Nill) ) )") :: + nofibStringToList("(equal (divides x y)(zerop (remainder y x) ) )") :: + nofibStringToList("(equal (assume-true var alist)(Conss (Conss var (t) )alist) )") :: + nofibStringToList("(equal (assume-false var alist)(Conss (Conss var (f) )alist) )") :: + nofibStringToList("(equal (tautology-checker x)(tautologyp (normalize x)(Nill) ) )") :: + nofibStringToList("(equal (falsify x)(falsify1 (normalize x)(Nill) ) )") :: + nofibStringToList("(equal (prime x)(and (not (zerop x))(not (equal x (add1 (zero) ) ) )(prime1 x (1- x) ) ) )") :: + nofibStringToList("(equal (and p q)(if p (if q (t) (f) ) (f) ) )") :: + nofibStringToList("(equal (or p q)(if p (t) (if q (t) (f) ) ) )") :: + nofibStringToList("(equal (not p)(if p (f) (t) ) )") :: + nofibStringToList("(equal (implies p q)(if p (if q (t) (f) ) (t) ) )") :: + nofibStringToList("(equal (fix x)(if (numberp x) x (zero) ) )") :: + nofibStringToList("(equal (if (if a b c) d e)(if a (if b d e) (if c d e) ) )") :: + nofibStringToList("(equal (zerop x)(or (equal x (zero) )(not (numberp x) ) ) )") :: + nofibStringToList("(equal (plus (plus x y) z )(plus x (plus y z) ) )") :: + nofibStringToList("(equal (equal (plus a b) (zero ) )(and (zerop a) (zerop b) ) )") :: + nofibStringToList("(equal (difference x x)(zero) )") :: + nofibStringToList("(equal (equal (plus a b) (plus a c) )(equal (fix b) (fix c) ) )") :: + nofibStringToList("(equal (equal (zero) (difference x y) )(not (lessp y x) ) )") :: + nofibStringToList("(equal (equal x (difference x y) )(and (numberp x)(or (equal x (zero) )(zerop y) ) ) )") :: + nofibStringToList("(equal (meaning (plus-tree (append x y) ) a)(plus (meaning (plus-tree x) a)(meaning (plus-tree y) a) ) )") :: + nofibStringToList("(equal (meaning (plus-tree (plus-fringe x) ) a)(fix (meaning x a) ) )") :: + nofibStringToList("(equal (append (append x y) z)(append x (append y z) ) )") :: + nofibStringToList("(equal (reverse (append a b) )(append (reverse b) (reverse a) ) )") :: + nofibStringToList("(equal (times x (plus y z) )(plus (times x y)(times x z) ) )") :: + nofibStringToList("(equal (times (times x y) z)(times x (times y z) ) )") :: + nofibStringToList("(equal (equal (times x y) (zero) )(or (zerop x)(zerop y) ) )") :: + nofibStringToList("(equal (exec (append x y)pds envrn)(exec y (exec x pds envrn)envrn) )") :: + nofibStringToList("(equal (mc-flatten x y)(append (flatten x)y) )") :: + nofibStringToList("(equal (member x (append a b) )(or (member x a)(member x b) ) )") :: + nofibStringToList("(equal (member x (reverse y) )(member x y) )") :: + nofibStringToList("(equal (length (reverse x) )(length x) )") :: + nofibStringToList("(equal (member a (intersect b c) )(and (member a b)(member a c) ) )") :: + nofibStringToList("(equal (nth (zero)i)(zero) )") :: + nofibStringToList("(equal (exp i (plus j k) )(times (exp i j)(exp i k) ) )") :: + nofibStringToList("(equal (exp i (times j k) )(exp (exp i j)k) )") :: + nofibStringToList("(equal (reverse-loop x y)(append (reverse x)y) )") :: + nofibStringToList("(equal (reverse-loop x (Nill) )(reverse x) )") :: + nofibStringToList("(equal (count-list z (sort-lp x y) )(plus (count-list z x)(count-list z y) ) )") :: + nofibStringToList("(equal (equal (append a b)(append a c) )(equal b c) )") :: + nofibStringToList("(equal (plus (remainder x y)(times y (quotient x y) ) )(fix x) )") :: + nofibStringToList("(equal (power-eval (big-plus1 l i base)base)(plus (power-eval l base)i) )") :: + nofibStringToList("(equal (power-eval (big-plus x y i base)base)(plus i (plus (power-eval x base)(power-eval y base) ) ) )") :: + nofibStringToList("(equal (remainder y 1)(zero) )") :: + nofibStringToList("(equal (lessp (remainder x y)y)(not (zerop y) ) )") :: + nofibStringToList("(equal (remainder x x)(zero) )") :: + nofibStringToList("(equal (lessp (quotient i j)i)(and (not (zerop i) )(or (zerop j)(not (equal j 1) ) ) ) )") :: + nofibStringToList("(equal (lessp (remainder x y)x)(and (not (zerop y) )(not (zerop x) )(not (lessp x y) ) ) )") :: + nofibStringToList("(equal (power-eval (power-rep i base)base)(fix i) )") :: + nofibStringToList("(equal (power-eval (big-plus (power-rep i base)(power-rep j base)(zero)base)base)(plus i j) )") :: + nofibStringToList("(equal (gcd x y)(gcd y x) )") :: + nofibStringToList("(equal (nth (append a b)i)(append (nth a i)(nth b (difference i (length a) ) ) ) )") :: + nofibStringToList("(equal (difference (plus x y)x)(fix y) )") :: + nofibStringToList("(equal (difference (plus y x)x)(fix y) )") :: + nofibStringToList("(equal (difference (plus x y)(plus x z) )(difference y z) )") :: + nofibStringToList("(equal (times x (difference c w) )(difference (times c x)(times w x) ) )") :: + nofibStringToList("(equal (remainder (times x z)z)(zero) )") :: + nofibStringToList("(equal (difference (plus b (plus a c) )a)(plus b c) )") :: + nofibStringToList("(equal (difference (add1 (plus y z)z)(add1 y) )") :: + nofibStringToList("(equal (lessp (plus x y)(plus x z ) )(lessp y z) )") :: + nofibStringToList("(equal (lessp (times x z)(times y z) )(and (not (zerop z) )(lessp x y) ) )") :: + nofibStringToList("(equal (lessp y (plus x y) )(not (zerop x) ) )") :: + nofibStringToList("(equal (gcd (times x z)(times y z) )(times z (gcd x y) ) )") :: + nofibStringToList("(equal (value (normalize x)a)(value x a) )") :: + nofibStringToList("(equal (equal (flatten x)(Conss y (Nill) ) )(and (nlistp x)(equal x y) ) )") :: + nofibStringToList("(equal (listp (gopher x) )(listp x) )") :: + nofibStringToList("(equal (samefringe x y)(equal (flatten x)(flatten y) ) )") :: + nofibStringToList("(equal (equal (greatest-factor x y)(zero) )(and (or (zerop y)(equal y 1) )(equal x (zero) ) ) )") :: + nofibStringToList("(equal (equal (greatest-factor x y)1)(equal x 1) )") :: + nofibStringToList("(equal (numberp (greatest-factor x y) )(not (and (or (zerop y)(equal y 1) )(not (numberp x) ) ) ) )") :: + nofibStringToList("(equal (times-list (append x y) )(times (times-list x)(times-list y) ) )") :: + nofibStringToList("(equal (prime-list (append x y) )(and (prime-list x)(prime-list y) ) )") :: + nofibStringToList("(equal (equal z (times w z) )(and (numberp z)(or (equal z (zero) )(equal w 1) ) ) )") :: + nofibStringToList("(equal (greatereqpr x y)(not (lessp x y) ) )") :: + nofibStringToList("(equal (equal x (times x y) )(or (equal x (zero) )(and (numberp x)(equal y 1) ) ) )") :: + nofibStringToList("(equal (remainder (times y x)y)(zero) )") :: + nofibStringToList("(equal (equal (times a b)1)(and (not (equal a (zero) ) )(not (equal b (zero) ) )(numberp a)(numberp b)(equal (1- a)(zero) )(equal (1- b)(zero) ) ) )") :: + nofibStringToList("(equal (lessp (length (delete x l) )(length l) )(member x l) )") :: + nofibStringToList("(equal (sort2 (delete x l) )(delete x (sort2 l) ) )") :: + nofibStringToList("(equal (dsort x)(sort2 x) )") :: + nofibStringToList("(equal (length(Conss x1(Conss x2(Conss x3(Conss x4(Conss x5(Conss x6 x7) ) ) ) ) ) )(plus 6 (length x7) ) )") :: + nofibStringToList("(equal (difference (add1 (add1 x) )2)(fix x) )") :: + nofibStringToList("(equal (quotient (plus x (plus x y) )2)(plus x (quotient y 2) ) )") :: + nofibStringToList("(equal (sigma (zero)i)(quotient (times i (add1 i) )2) )") :: + nofibStringToList("(equal (plus x (add1 y) )(if (numberp y)(add1 (plus x y) )(add1 x) ) )") :: + nofibStringToList("(equal (equal (difference x y)(difference z y) )(if (lessp x y)(not (lessp y z) )(if (lessp z y)(not (lessp y x) )(equal (fix x)(fix z) ) ) ) )") :: + nofibStringToList("(equal (meaning (plus-tree (delete x y) )a)(if (member x y)(difference (meaning (plus-tree y)a)(meaning x a) )(meaning (plus-tree y)a) ) )") :: + nofibStringToList("(equal (times x (add1 y) )(if (numberp y)(plus x (times x y) )(fix x) ) )") :: + nofibStringToList("(equal (nth (Nill)i)(if (zerop i)(Nill)(zero) ) )") :: + nofibStringToList("(equal (last (append a b) )(if (listp b)(last b)(if (listp a)(Conss (car (last a) )b)b) ) )") :: + nofibStringToList("(equal (equal (lessp x y)z)(if (lessp x y)(equal t z)(equal f z) ) )") :: + nofibStringToList("(equal (assignment x (append a b) )(if (assignedp x a)(assignment x a)(assignment x b) ) )") :: + nofibStringToList("(equal (car (gopher x) )(if (listp x)(car (flatten x) )(zero) ) )") :: + nofibStringToList("(equal (flatten (cdr (gopher x) ) )(if (listp x)(cdr (flatten x) )(Conss (zero)(Nill) ) ) )") :: + nofibStringToList("(equal (quotient (times y x)y)(if (zerop y)(zero)(fix x) ) )") :: + nofibStringToList("(equal (get j (set i val mem) )(if (eqp j i)val(get j mem) ) )") :: Nil +//│ rules = [["(","e","q","u","a","l"," ","(","c","o","m","p","i","l","e"," ","f","o","r","m",")","(","r","e","v","e","r","s","e"," ","(","c","o","d","e","g","e","n"," ","(","o","p","t","i","m","i","z","e"," ","f","o","r","m",")"," ","(","N","i","l","l",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","p"," ","x"," ","y",")","(","e","q","u","a","l"," ","(","f","i","x"," ","x",")","(","f","i","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","r","e","a","t","e","r","p"," ","x"," ","y",")","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","e","q","p"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","r","e","a","t","e","r","e","q","p"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","b","o","o","l","e","a","n"," ","x",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","t",")"," ",")","(","e","q","u","a","l"," ","x"," ","(","f",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","i","f","f"," ","x"," ","y",")","(","a","n","d"," ","(","i","m","p","l","i","e","s"," ","x"," ","y",")","(","i","m","p","l","i","e","s"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","v","e","n","1"," ","x",")","(","i","f"," ","(","z","e","r","o","p"," ","x",")","(","t",")","(","o","d","d"," ","(","1","-"," ","x",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","c","o","u","n","t","p","s","-"," ","l"," ","p","r","e","d",")","(","c","o","u","n","t","p","s","-","l","o","o","p"," ","l"," ","p","r","e","d"," ","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","a","c","t","-"," ","i",")","(","f","a","c","t","-","l","o","o","p"," ","i"," ","1",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e","-"," ","x",")","(","r","e","v","e","r","s","e","-","l","o","o","p"," ","x"," ","(","N","i","l","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","v","i","d","e","s"," ","x"," ","y",")","(","z","e","r","o","p"," ","(","r","e","m","a","i","n","d","e","r"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","s","s","u","m","e","-","t","r","u","e"," ","v","a","r"," ","a","l","i","s","t",")","(","C","o","n","s","s"," ","(","C","o","n","s","s"," ","v","a","r"," ","(","t",")"," ",")","a","l","i","s","t",")"," ",")"],["(","e","q","u","a","l"," ","(","a","s","s","u","m","e","-","f","a","l","s","e"," ","v","a","r"," ","a","l","i","s","t",")","(","C","o","n","s","s"," ","(","C","o","n","s","s"," ","v","a","r"," ","(","f",")"," ",")","a","l","i","s","t",")"," ",")"],["(","e","q","u","a","l"," ","(","t","a","u","t","o","l","o","g","y","-","c","h","e","c","k","e","r"," ","x",")","(","t","a","u","t","o","l","o","g","y","p"," ","(","n","o","r","m","a","l","i","z","e"," ","x",")","(","N","i","l","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","a","l","s","i","f","y"," ","x",")","(","f","a","l","s","i","f","y","1"," ","(","n","o","r","m","a","l","i","z","e"," ","x",")","(","N","i","l","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","r","i","m","e"," ","x",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","x",")",")","(","n","o","t"," ","(","e","q","u","a","l"," ","x"," ","(","a","d","d","1"," ","(","z","e","r","o",")"," ",")"," ",")"," ",")","(","p","r","i","m","e","1"," ","x"," ","(","1","-"," ","x",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","n","d"," ","p"," ","q",")","(","i","f"," ","p"," ","(","i","f"," ","q"," ","(","t",")"," ","(","f",")"," ",")"," ","(","f",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","o","r"," ","p"," ","q",")","(","i","f"," ","p"," ","(","t",")"," ","(","i","f"," ","q"," ","(","t",")"," ","(","f",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","n","o","t"," ","p",")","(","i","f"," ","p"," ","(","f",")"," ","(","t",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","i","m","p","l","i","e","s"," ","p"," ","q",")","(","i","f"," ","p"," ","(","i","f"," ","q"," ","(","t",")"," ","(","f",")"," ",")"," ","(","t",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","i","x"," ","x",")","(","i","f"," ","(","n","u","m","b","e","r","p"," ","x",")"," ","x"," ","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","i","f"," ","(","i","f"," ","a"," ","b"," ","c",")"," ","d"," ","e",")","(","i","f"," ","a"," ","(","i","f"," ","b"," ","d"," ","e",")"," ","(","i","f"," ","c"," ","d"," ","e",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","z","e","r","o","p"," ","x",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")","(","n","o","t"," ","(","n","u","m","b","e","r","p"," ","x",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","l","u","s"," ","(","p","l","u","s"," ","x"," ","y",")"," ","z"," ",")","(","p","l","u","s"," ","x"," ","(","p","l","u","s"," ","y"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","p","l","u","s"," ","a"," ","b",")"," ","(","z","e","r","o"," ",")"," ",")","(","a","n","d"," ","(","z","e","r","o","p"," ","a",")"," ","(","z","e","r","o","p"," ","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","x",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","p","l","u","s"," ","a"," ","b",")"," ","(","p","l","u","s"," ","a"," ","c",")"," ",")","(","e","q","u","a","l"," ","(","f","i","x"," ","b",")"," ","(","f","i","x"," ","c",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","z","e","r","o",")"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","y",")"," ",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","x"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","y",")"," ",")","(","a","n","d"," ","(","n","u","m","b","e","r","p"," ","x",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")","(","z","e","r","o","p"," ","y",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ",")"," ","a",")","(","p","l","u","s"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","x",")"," ","a",")","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","y",")"," ","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","(","p","l","u","s","-","f","r","i","n","g","e"," ","x",")"," ",")"," ","a",")","(","f","i","x"," ","(","m","e","a","n","i","n","g"," ","x"," ","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","p","p","e","n","d"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ","z",")","(","a","p","p","e","n","d"," ","x"," ","(","a","p","p","e","n","d"," ","y"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","a","p","p","e","n","d"," ","(","r","e","v","e","r","s","e"," ","b",")"," ","(","r","e","v","e","r","s","e"," ","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","(","p","l","u","s"," ","y"," ","z",")"," ",")","(","p","l","u","s"," ","(","t","i","m","e","s"," ","x"," ","y",")","(","t","i","m","e","s"," ","x"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ","z",")","(","t","i","m","e","s"," ","x"," ","(","t","i","m","e","s"," ","y"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ","(","z","e","r","o",")"," ",")","(","o","r"," ","(","z","e","r","o","p"," ","x",")","(","z","e","r","o","p"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","x","e","c"," ","(","a","p","p","e","n","d"," ","x"," ","y",")","p","d","s"," ","e","n","v","r","n",")","(","e","x","e","c"," ","y"," ","(","e","x","e","c"," ","x"," ","p","d","s"," ","e","n","v","r","n",")","e","n","v","r","n",")"," ",")"],["(","e","q","u","a","l"," ","(","m","c","-","f","l","a","t","t","e","n"," ","x"," ","y",")","(","a","p","p","e","n","d"," ","(","f","l","a","t","t","e","n"," ","x",")","y",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","m","b","e","r"," ","x"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","o","r"," ","(","m","e","m","b","e","r"," ","x"," ","a",")","(","m","e","m","b","e","r"," ","x"," ","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","m","b","e","r"," ","x"," ","(","r","e","v","e","r","s","e"," ","y",")"," ",")","(","m","e","m","b","e","r"," ","x"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","n","g","t","h"," ","(","r","e","v","e","r","s","e"," ","x",")"," ",")","(","l","e","n","g","t","h"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","m","b","e","r"," ","a"," ","(","i","n","t","e","r","s","e","c","t"," ","b"," ","c",")"," ",")","(","a","n","d"," ","(","m","e","m","b","e","r"," ","a"," ","b",")","(","m","e","m","b","e","r"," ","a"," ","c",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","n","t","h"," ","(","z","e","r","o",")","i",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","e","x","p"," ","i"," ","(","p","l","u","s"," ","j"," ","k",")"," ",")","(","t","i","m","e","s"," ","(","e","x","p"," ","i"," ","j",")","(","e","x","p"," ","i"," ","k",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","x","p"," ","i"," ","(","t","i","m","e","s"," ","j"," ","k",")"," ",")","(","e","x","p"," ","(","e","x","p"," ","i"," ","j",")","k",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e","-","l","o","o","p"," ","x"," ","y",")","(","a","p","p","e","n","d"," ","(","r","e","v","e","r","s","e"," ","x",")","y",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","v","e","r","s","e","-","l","o","o","p"," ","x"," ","(","N","i","l","l",")"," ",")","(","r","e","v","e","r","s","e"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","c","o","u","n","t","-","l","i","s","t"," ","z"," ","(","s","o","r","t","-","l","p"," ","x"," ","y",")"," ",")","(","p","l","u","s"," ","(","c","o","u","n","t","-","l","i","s","t"," ","z"," ","x",")","(","c","o","u","n","t","-","l","i","s","t"," ","z"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","a","p","p","e","n","d"," ","a"," ","b",")","(","a","p","p","e","n","d"," ","a"," ","c",")"," ",")","(","e","q","u","a","l"," ","b"," ","c",")"," ",")"],["(","e","q","u","a","l"," ","(","p","l","u","s"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","y",")","(","t","i","m","e","s"," ","y"," ","(","q","u","o","t","i","e","n","t"," ","x"," ","y",")"," ",")"," ",")","(","f","i","x"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","b","i","g","-","p","l","u","s","1"," ","l"," ","i"," ","b","a","s","e",")","b","a","s","e",")","(","p","l","u","s"," ","(","p","o","w","e","r","-","e","v","a","l"," ","l"," ","b","a","s","e",")","i",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","b","i","g","-","p","l","u","s"," ","x"," ","y"," ","i"," ","b","a","s","e",")","b","a","s","e",")","(","p","l","u","s"," ","i"," ","(","p","l","u","s"," ","(","p","o","w","e","r","-","e","v","a","l"," ","x"," ","b","a","s","e",")","(","p","o","w","e","r","-","e","v","a","l"," ","y"," ","b","a","s","e",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","y"," ","1",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","y",")","y",")","(","n","o","t"," ","(","z","e","r","o","p"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","x",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","q","u","o","t","i","e","n","t"," ","i"," ","j",")","i",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","i",")"," ",")","(","o","r"," ","(","z","e","r","o","p"," ","j",")","(","n","o","t"," ","(","e","q","u","a","l"," ","j"," ","1",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","r","e","m","a","i","n","d","e","r"," ","x"," ","y",")","x",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","y",")"," ",")","(","n","o","t"," ","(","z","e","r","o","p"," ","x",")"," ",")","(","n","o","t"," ","(","l","e","s","s","p"," ","x"," ","y",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","p","o","w","e","r","-","r","e","p"," ","i"," ","b","a","s","e",")","b","a","s","e",")","(","f","i","x"," ","i",")"," ",")"],["(","e","q","u","a","l"," ","(","p","o","w","e","r","-","e","v","a","l"," ","(","b","i","g","-","p","l","u","s"," ","(","p","o","w","e","r","-","r","e","p"," ","i"," ","b","a","s","e",")","(","p","o","w","e","r","-","r","e","p"," ","j"," ","b","a","s","e",")","(","z","e","r","o",")","b","a","s","e",")","b","a","s","e",")","(","p","l","u","s"," ","i"," ","j",")"," ",")"],["(","e","q","u","a","l"," ","(","g","c","d"," ","x"," ","y",")","(","g","c","d"," ","y"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","n","t","h"," ","(","a","p","p","e","n","d"," ","a"," ","b",")","i",")","(","a","p","p","e","n","d"," ","(","n","t","h"," ","a"," ","i",")","(","n","t","h"," ","b"," ","(","d","i","f","f","e","r","e","n","c","e"," ","i"," ","(","l","e","n","g","t","h"," ","a",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","x"," ","y",")","x",")","(","f","i","x"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","y"," ","x",")","x",")","(","f","i","x"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","x"," ","y",")","(","p","l","u","s"," ","x"," ","z",")"," ",")","(","d","i","f","f","e","r","e","n","c","e"," ","y"," ","z",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","(","d","i","f","f","e","r","e","n","c","e"," ","c"," ","w",")"," ",")","(","d","i","f","f","e","r","e","n","c","e"," ","(","t","i","m","e","s"," ","c"," ","x",")","(","t","i","m","e","s"," ","w"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","(","t","i","m","e","s"," ","x"," ","z",")","z",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","p","l","u","s"," ","b"," ","(","p","l","u","s"," ","a"," ","c",")"," ",")","a",")","(","p","l","u","s"," ","b"," ","c",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","a","d","d","1"," ","(","p","l","u","s"," ","y"," ","z",")","z",")","(","a","d","d","1"," ","y",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","p","l","u","s"," ","x"," ","y",")","(","p","l","u","s"," ","x"," ","z"," ",")"," ",")","(","l","e","s","s","p"," ","y"," ","z",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","t","i","m","e","s"," ","x"," ","z",")","(","t","i","m","e","s"," ","y"," ","z",")"," ",")","(","a","n","d"," ","(","n","o","t"," ","(","z","e","r","o","p"," ","z",")"," ",")","(","l","e","s","s","p"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","y"," ","(","p","l","u","s"," ","x"," ","y",")"," ",")","(","n","o","t"," ","(","z","e","r","o","p"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","c","d"," ","(","t","i","m","e","s"," ","x"," ","z",")","(","t","i","m","e","s"," ","y"," ","z",")"," ",")","(","t","i","m","e","s"," ","z"," ","(","g","c","d"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","v","a","l","u","e"," ","(","n","o","r","m","a","l","i","z","e"," ","x",")","a",")","(","v","a","l","u","e"," ","x"," ","a",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","f","l","a","t","t","e","n"," ","x",")","(","C","o","n","s","s"," ","y"," ","(","N","i","l","l",")"," ",")"," ",")","(","a","n","d"," ","(","n","l","i","s","t","p"," ","x",")","(","e","q","u","a","l"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","i","s","t","p"," ","(","g","o","p","h","e","r"," ","x",")"," ",")","(","l","i","s","t","p"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","s","a","m","e","f","r","i","n","g","e"," ","x"," ","y",")","(","e","q","u","a","l"," ","(","f","l","a","t","t","e","n"," ","x",")","(","f","l","a","t","t","e","n"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"," ","x"," ","y",")","(","z","e","r","o",")"," ",")","(","a","n","d"," ","(","o","r"," ","(","z","e","r","o","p"," ","y",")","(","e","q","u","a","l"," ","y"," ","1",")"," ",")","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"," ","x"," ","y",")","1",")","(","e","q","u","a","l"," ","x"," ","1",")"," ",")"],["(","e","q","u","a","l"," ","(","n","u","m","b","e","r","p"," ","(","g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"," ","x"," ","y",")"," ",")","(","n","o","t"," ","(","a","n","d"," ","(","o","r"," ","(","z","e","r","o","p"," ","y",")","(","e","q","u","a","l"," ","y"," ","1",")"," ",")","(","n","o","t"," ","(","n","u","m","b","e","r","p"," ","x",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s","-","l","i","s","t"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ",")","(","t","i","m","e","s"," ","(","t","i","m","e","s","-","l","i","s","t"," ","x",")","(","t","i","m","e","s","-","l","i","s","t"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","p","r","i","m","e","-","l","i","s","t"," ","(","a","p","p","e","n","d"," ","x"," ","y",")"," ",")","(","a","n","d"," ","(","p","r","i","m","e","-","l","i","s","t"," ","x",")","(","p","r","i","m","e","-","l","i","s","t"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","z"," ","(","t","i","m","e","s"," ","w"," ","z",")"," ",")","(","a","n","d"," ","(","n","u","m","b","e","r","p"," ","z",")","(","o","r"," ","(","e","q","u","a","l"," ","z"," ","(","z","e","r","o",")"," ",")","(","e","q","u","a","l"," ","w"," ","1",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","r","e","a","t","e","r","e","q","p","r"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","x"," ","y",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","x"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ",")","(","o","r"," ","(","e","q","u","a","l"," ","x"," ","(","z","e","r","o",")"," ",")","(","a","n","d"," ","(","n","u","m","b","e","r","p"," ","x",")","(","e","q","u","a","l"," ","y"," ","1",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","r","e","m","a","i","n","d","e","r"," ","(","t","i","m","e","s"," ","y"," ","x",")","y",")","(","z","e","r","o",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","a"," ","b",")","1",")","(","a","n","d"," ","(","n","o","t"," ","(","e","q","u","a","l"," ","a"," ","(","z","e","r","o",")"," ",")"," ",")","(","n","o","t"," ","(","e","q","u","a","l"," ","b"," ","(","z","e","r","o",")"," ",")"," ",")","(","n","u","m","b","e","r","p"," ","a",")","(","n","u","m","b","e","r","p"," ","b",")","(","e","q","u","a","l"," ","(","1","-"," ","a",")","(","z","e","r","o",")"," ",")","(","e","q","u","a","l"," ","(","1","-"," ","b",")","(","z","e","r","o",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","(","l","e","n","g","t","h"," ","(","d","e","l","e","t","e"," ","x"," ","l",")"," ",")","(","l","e","n","g","t","h"," ","l",")"," ",")","(","m","e","m","b","e","r"," ","x"," ","l",")"," ",")"],["(","e","q","u","a","l"," ","(","s","o","r","t","2"," ","(","d","e","l","e","t","e"," ","x"," ","l",")"," ",")","(","d","e","l","e","t","e"," ","x"," ","(","s","o","r","t","2"," ","l",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","s","o","r","t"," ","x",")","(","s","o","r","t","2"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","l","e","n","g","t","h","(","C","o","n","s","s"," ","x","1","(","C","o","n","s","s"," ","x","2","(","C","o","n","s","s"," ","x","3","(","C","o","n","s","s"," ","x","4","(","C","o","n","s","s"," ","x","5","(","C","o","n","s","s"," ","x","6"," ","x","7",")"," ",")"," ",")"," ",")"," ",")"," ",")"," ",")","(","p","l","u","s"," ","6"," ","(","l","e","n","g","t","h"," ","x","7",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","(","a","d","d","1"," ","(","a","d","d","1"," ","x",")"," ",")","2",")","(","f","i","x"," ","x",")"," ",")"],["(","e","q","u","a","l"," ","(","q","u","o","t","i","e","n","t"," ","(","p","l","u","s"," ","x"," ","(","p","l","u","s"," ","x"," ","y",")"," ",")","2",")","(","p","l","u","s"," ","x"," ","(","q","u","o","t","i","e","n","t"," ","y"," ","2",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","s","i","g","m","a"," ","(","z","e","r","o",")","i",")","(","q","u","o","t","i","e","n","t"," ","(","t","i","m","e","s"," ","i"," ","(","a","d","d","1"," ","i",")"," ",")","2",")"," ",")"],["(","e","q","u","a","l"," ","(","p","l","u","s"," ","x"," ","(","a","d","d","1"," ","y",")"," ",")","(","i","f"," ","(","n","u","m","b","e","r","p"," ","y",")","(","a","d","d","1"," ","(","p","l","u","s"," ","x"," ","y",")"," ",")","(","a","d","d","1"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","d","i","f","f","e","r","e","n","c","e"," ","x"," ","y",")","(","d","i","f","f","e","r","e","n","c","e"," ","z"," ","y",")"," ",")","(","i","f"," ","(","l","e","s","s","p"," ","x"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","z",")"," ",")","(","i","f"," ","(","l","e","s","s","p"," ","z"," ","y",")","(","n","o","t"," ","(","l","e","s","s","p"," ","y"," ","x",")"," ",")","(","e","q","u","a","l"," ","(","f","i","x"," ","x",")","(","f","i","x"," ","z",")"," ",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","(","d","e","l","e","t","e"," ","x"," ","y",")"," ",")","a",")","(","i","f"," ","(","m","e","m","b","e","r"," ","x"," ","y",")","(","d","i","f","f","e","r","e","n","c","e"," ","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","y",")","a",")","(","m","e","a","n","i","n","g"," ","x"," ","a",")"," ",")","(","m","e","a","n","i","n","g"," ","(","p","l","u","s","-","t","r","e","e"," ","y",")","a",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","t","i","m","e","s"," ","x"," ","(","a","d","d","1"," ","y",")"," ",")","(","i","f"," ","(","n","u","m","b","e","r","p"," ","y",")","(","p","l","u","s"," ","x"," ","(","t","i","m","e","s"," ","x"," ","y",")"," ",")","(","f","i","x"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","n","t","h"," ","(","N","i","l","l",")","i",")","(","i","f"," ","(","z","e","r","o","p"," ","i",")","(","N","i","l","l",")","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","l","a","s","t"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","i","f"," ","(","l","i","s","t","p"," ","b",")","(","l","a","s","t"," ","b",")","(","i","f"," ","(","l","i","s","t","p"," ","a",")","(","C","o","n","s","s"," ","(","c","a","r"," ","(","l","a","s","t"," ","a",")"," ",")","b",")","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","e","q","u","a","l"," ","(","l","e","s","s","p"," ","x"," ","y",")","z",")","(","i","f"," ","(","l","e","s","s","p"," ","x"," ","y",")","(","e","q","u","a","l"," ","t"," ","z",")","(","e","q","u","a","l"," ","f"," ","z",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","a","s","s","i","g","n","m","e","n","t"," ","x"," ","(","a","p","p","e","n","d"," ","a"," ","b",")"," ",")","(","i","f"," ","(","a","s","s","i","g","n","e","d","p"," ","x"," ","a",")","(","a","s","s","i","g","n","m","e","n","t"," ","x"," ","a",")","(","a","s","s","i","g","n","m","e","n","t"," ","x"," ","b",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","c","a","r"," ","(","g","o","p","h","e","r"," ","x",")"," ",")","(","i","f"," ","(","l","i","s","t","p"," ","x",")","(","c","a","r"," ","(","f","l","a","t","t","e","n"," ","x",")"," ",")","(","z","e","r","o",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","f","l","a","t","t","e","n"," ","(","c","d","r"," ","(","g","o","p","h","e","r"," ","x",")"," ",")"," ",")","(","i","f"," ","(","l","i","s","t","p"," ","x",")","(","c","d","r"," ","(","f","l","a","t","t","e","n"," ","x",")"," ",")","(","C","o","n","s","s"," ","(","z","e","r","o",")","(","N","i","l","l",")"," ",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","q","u","o","t","i","e","n","t"," ","(","t","i","m","e","s"," ","y"," ","x",")","y",")","(","i","f"," ","(","z","e","r","o","p"," ","y",")","(","z","e","r","o",")","(","f","i","x"," ","x",")"," ",")"," ",")"],["(","e","q","u","a","l"," ","(","g","e","t"," ","j"," ","(","s","e","t"," ","i"," ","v","a","l"," ","m","e","m",")"," ",")","(","i","f"," ","(","e","q","p"," ","j"," ","i",")","v","a","l","(","g","e","t"," ","j"," ","m","e","m",")"," ",")"," ",")"]] + +val lemmas = addlemmalst(makelemmas(rules), Empty) +//│ lemmas = Node([Node([Node([Node([Node([Empty, [["a","n","d"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["a","n","d"]), Conss([Atom(["p"]), Conss([Atom(["q"]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Atom(["p"]), Conss([Conss([Atom(["i","f"]), Conss([Atom(["q"]), Conss([Conss([Atom(["t"]), Nill]), Conss([Conss([Atom(["f"]), Nill]), Nill])])])]), Conss([Conss([Atom(["f"]), Nill]), Nill])])])]), Nill])])])]], Node([Empty, [["a","p","p","e","n","d"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Atom(["z"]), Nill])])]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["x"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["y"]), Conss([Atom(["z"]), Nill])])]), Nill])])]), Nill])])])]], Node([Empty, [["a","s","s","i","g","n","m","e","n","t"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["a","s","s","i","g","n","m","e","n","t"]), Conss([Atom(["x"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["a"]), Conss([Atom(["b"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["a","s","s","i","g","n","e","d","p"]), Conss([Atom(["x"]), Conss([Atom(["a"]), Nill])])]), Conss([Conss([Atom(["a","s","s","i","g","n","m","e","n","t"]), Conss([Atom(["x"]), Conss([Atom(["a"]), Nill])])]), Conss([Conss([Atom(["a","s","s","i","g","n","m","e","n","t"]), Conss([Atom(["x"]), Conss([Atom(["b"]), Nill])])]), Nill])])])]), Nill])])])]], Empty])])]), [["a","s","s","u","m","e","-","f","a","l","s","e"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["a","s","s","u","m","e","-","f","a","l","s","e"]), Conss([Atom(["v","a","r"]), Conss([Atom(["a","l","i","s","t"]), Nill])])]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Atom(["v","a","r"]), Conss([Conss([Atom(["f"]), Nill]), Nill])])]), Conss([Atom(["a","l","i","s","t"]), Nill])])]), Nill])])])]], Empty]), [["a","s","s","u","m","e","-","t","r","u","e"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["a","s","s","u","m","e","-","t","r","u","e"]), Conss([Atom(["v","a","r"]), Conss([Atom(["a","l","i","s","t"]), Nill])])]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Atom(["v","a","r"]), Conss([Conss([Atom(["t"]), Nill]), Nill])])]), Conss([Atom(["a","l","i","s","t"]), Nill])])]), Nill])])])]], Empty]), [["b","o","o","l","e","a","n"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["b","o","o","l","e","a","n"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["o","r"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["x"]), Conss([Conss([Atom(["t"]), Nill]), Nill])])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["x"]), Conss([Conss([Atom(["f"]), Nill]), Nill])])]), Nill])])]), Nill])])])]], Node([Empty, [["c","a","r"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["c","a","r"]), Conss([Conss([Atom(["g","o","p","h","e","r"]), Conss([Atom(["x"]), Nill])]), Nill])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["l","i","s","t","p"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["c","a","r"]), Conss([Conss([Atom(["f","l","a","t","t","e","n"]), Conss([Atom(["x"]), Nill])]), Nill])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])])]), Nill])])])]], Empty])]), [["c","o","m","p","i","l","e"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["c","o","m","p","i","l","e"]), Conss([Atom(["f","o","r","m"]), Nill])]), Conss([Conss([Atom(["r","e","v","e","r","s","e"]), Conss([Conss([Atom(["c","o","d","e","g","e","n"]), Conss([Conss([Atom(["o","p","t","i","m","i","z","e"]), Conss([Atom(["f","o","r","m"]), Nill])]), Conss([Conss([Atom(["N","i","l","l"]), Nill]), Nill])])]), Nill])]), Nill])])])]], Node([Node([Node([Empty, [["c","o","u","n","t","-","l","i","s","t"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["c","o","u","n","t","-","l","i","s","t"]), Conss([Atom(["z"]), Conss([Conss([Atom(["s","o","r","t","-","l","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Conss([Atom(["c","o","u","n","t","-","l","i","s","t"]), Conss([Atom(["z"]), Conss([Atom(["x"]), Nill])])]), Conss([Conss([Atom(["c","o","u","n","t","-","l","i","s","t"]), Conss([Atom(["z"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Nill])])])]], Empty]), [["c","o","u","n","t","p","s","-"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["c","o","u","n","t","p","s","-"]), Conss([Atom(["l"]), Conss([Atom(["p","r","e","d"]), Nill])])]), Conss([Conss([Atom(["c","o","u","n","t","p","s","-","l","o","o","p"]), Conss([Atom(["l"]), Conss([Atom(["p","r","e","d"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])])]), Nill])])])]], Node([Node([Empty, [["d","i","f","f","e","r","e","n","c","e"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Conss([Atom(["a","d","d","1"]), Conss([Conss([Atom(["a","d","d","1"]), Conss([Atom(["x"]), Nill])]), Nill])]), Conss([Atom(["2"]), Nill])])]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["x"]), Nill])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Conss([Atom(["a","d","d","1"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["y"]), Conss([Atom(["z"]), Nill])])]), Conss([Atom(["z"]), Nill])])]), Conss([Conss([Atom(["a","d","d","1"]), Conss([Atom(["y"]), Nill])]), Nill])])]), Nill])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["b"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["a"]), Conss([Atom(["c"]), Nill])])]), Nill])])]), Conss([Atom(["a"]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["b"]), Conss([Atom(["c"]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Atom(["z"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Atom(["y"]), Conss([Atom(["z"]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["y"]), Conss([Atom(["x"]), Nill])])]), Conss([Atom(["x"]), Nill])])]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["y"]), Nill])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Atom(["x"]), Nill])])]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["y"]), Nill])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Atom(["x"]), Conss([Atom(["x"]), Nill])])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])])]], Empty]), [["d","i","v","i","d","e","s"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["d","i","v","i","d","e","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Conss([Atom(["r","e","m","a","i","n","d","e","r"]), Conss([Atom(["y"]), Conss([Atom(["x"]), Nill])])]), Nill])]), Nill])])])]], Node([Empty, [["d","s","o","r","t"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["d","s","o","r","t"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["s","o","r","t","2"]), Conss([Atom(["x"]), Nill])]), Nill])])])]], Empty])])]), [["e","q","p"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["y"]), Nill])]), Nill])])]), Nill])])])]], Node([Node([Node([Node([Empty, [["e","q","u","a","l"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Atom(["z"]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["t"]), Conss([Atom(["z"]), Nill])])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["f"]), Conss([Atom(["z"]), Nill])])]), Nill])])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Atom(["z"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["y"]), Conss([Atom(["z"]), Nill])])]), Nill])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["z"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["y"]), Conss([Atom(["x"]), Nill])])]), Nill])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["z"]), Nill])]), Nill])])]), Nill])])])]), Nill])])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["a"]), Conss([Atom(["b"]), Nill])])]), Conss([Atom(["1"]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["a"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Nill])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["b"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Nill])]), Conss([Conss([Atom(["n","u","m","b","e","r","p"]), Conss([Atom(["a"]), Nill])]), Conss([Conss([Atom(["n","u","m","b","e","r","p"]), Conss([Atom(["b"]), Nill])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["1","-"]), Conss([Atom(["a"]), Nill])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["1","-"]), Conss([Atom(["b"]), Nill])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Nill])])])])])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["x"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["o","r"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["x"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["n","u","m","b","e","r","p"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["y"]), Conss([Atom(["1"]), Nill])])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["z"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["w"]), Conss([Atom(["z"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["n","u","m","b","e","r","p"]), Conss([Atom(["z"]), Nill])]), Conss([Conss([Atom(["o","r"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["z"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["w"]), Conss([Atom(["1"]), Nill])])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Atom(["1"]), Nill])])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["x"]), Conss([Atom(["1"]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["o","r"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["y"]), Nill])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["y"]), Conss([Atom(["1"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["x"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["f","l","a","t","t","e","n"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Atom(["y"]), Conss([Conss([Atom(["N","i","l","l"]), Nill]), Nill])])]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["n","l","i","s","t","p"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["a"]), Conss([Atom(["b"]), Nill])])]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["a"]), Conss([Atom(["c"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["b"]), Conss([Atom(["c"]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Conss([Conss([Atom(["o","r"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["y"]), Nill])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["x"]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["n","u","m","b","e","r","p"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["o","r"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["x"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["y"]), Nill])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["y"]), Conss([Atom(["x"]), Nill])])]), Nill])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["a"]), Conss([Atom(["b"]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["a"]), Conss([Atom(["c"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["b"]), Nill])]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["c"]), Nill])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["a"]), Conss([Atom(["b"]), Nill])])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["a"]), Nill])]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["b"]), Nill])]), Nill])])]), Nill])])])]], Empty]), [["e","v","e","n","1"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","v","e","n","1"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["t"]), Nill]), Conss([Conss([Atom(["o","d","d"]), Conss([Conss([Atom(["1","-"]), Conss([Atom(["x"]), Nill])]), Nill])]), Nill])])])]), Nill])])])]], Node([Node([Empty, [["e","x","e","c"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","x","e","c"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Atom(["p","d","s"]), Conss([Atom(["e","n","v","r","n"]), Nill])])])]), Conss([Conss([Atom(["e","x","e","c"]), Conss([Atom(["y"]), Conss([Conss([Atom(["e","x","e","c"]), Conss([Atom(["x"]), Conss([Atom(["p","d","s"]), Conss([Atom(["e","n","v","r","n"]), Nill])])])]), Conss([Atom(["e","n","v","r","n"]), Nill])])])]), Nill])])])]], Node([Empty, [["e","x","p"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","x","p"]), Conss([Atom(["i"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["j"]), Conss([Atom(["k"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["e","x","p"]), Conss([Conss([Atom(["e","x","p"]), Conss([Atom(["i"]), Conss([Atom(["j"]), Nill])])]), Conss([Atom(["k"]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["e","x","p"]), Conss([Atom(["i"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["j"]), Conss([Atom(["k"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Conss([Atom(["e","x","p"]), Conss([Atom(["i"]), Conss([Atom(["j"]), Nill])])]), Conss([Conss([Atom(["e","x","p"]), Conss([Atom(["i"]), Conss([Atom(["k"]), Nill])])]), Nill])])]), Nill])])])]], Empty])]), [["f","a","c","t","-"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["f","a","c","t","-"]), Conss([Atom(["i"]), Nill])]), Conss([Conss([Atom(["f","a","c","t","-","l","o","o","p"]), Conss([Atom(["i"]), Conss([Atom(["1"]), Nill])])]), Nill])])])]], Node([Empty, [["f","a","l","s","i","f","y"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["f","a","l","s","i","f","y"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["f","a","l","s","i","f","y","1"]), Conss([Conss([Atom(["n","o","r","m","a","l","i","z","e"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["N","i","l","l"]), Nill]), Nill])])]), Nill])])])]], Node([Empty, [["f","i","x"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["n","u","m","b","e","r","p"]), Conss([Atom(["x"]), Nill])]), Conss([Atom(["x"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])])]), Nill])])])]], Node([Node([Empty, [["f","l","a","t","t","e","n"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["f","l","a","t","t","e","n"]), Conss([Conss([Atom(["c","d","r"]), Conss([Conss([Atom(["g","o","p","h","e","r"]), Conss([Atom(["x"]), Nill])]), Nill])]), Nill])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["l","i","s","t","p"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["c","d","r"]), Conss([Conss([Atom(["f","l","a","t","t","e","n"]), Conss([Atom(["x"]), Nill])]), Nill])]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Conss([Conss([Atom(["N","i","l","l"]), Nill]), Nill])])]), Nill])])])]), Nill])])])]], Empty]), [["g","c","d"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["g","c","d"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Atom(["z"]), Nill])])]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["y"]), Conss([Atom(["z"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["z"]), Conss([Conss([Atom(["g","c","d"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["g","c","d"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["g","c","d"]), Conss([Atom(["y"]), Conss([Atom(["x"]), Nill])])]), Nill])])])]], Node([Empty, [["g","e","t"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["g","e","t"]), Conss([Atom(["j"]), Conss([Conss([Atom(["s","e","t"]), Conss([Atom(["i"]), Conss([Atom(["v","a","l"]), Conss([Atom(["m","e","m"]), Nill])])])]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["e","q","p"]), Conss([Atom(["j"]), Conss([Atom(["i"]), Nill])])]), Conss([Atom(["v","a","l"]), Conss([Conss([Atom(["g","e","t"]), Conss([Atom(["j"]), Conss([Atom(["m","e","m"]), Nill])])]), Nill])])])]), Nill])])])]], Empty])])])])])]), [["g","r","e","a","t","e","r","e","q","p"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["g","r","e","a","t","e","r","e","q","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["y"]), Conss([Atom(["x"]), Nill])])]), Nill])]), Nill])])])]], Node([Empty, [["g","r","e","a","t","e","r","e","q","p","r"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["g","r","e","a","t","e","r","e","q","p","r"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])]), Nill])])])]], Empty])]), [["g","r","e","a","t","e","r","p"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["g","r","e","a","t","e","r","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["y"]), Conss([Atom(["x"]), Nill])])]), Nill])])])]], Node([Node([Node([Empty, [["i","f"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["i","f"]), Conss([Atom(["a"]), Conss([Atom(["b"]), Conss([Atom(["c"]), Nill])])])]), Conss([Atom(["d"]), Conss([Atom(["e"]), Nill])])])]), Conss([Conss([Atom(["i","f"]), Conss([Atom(["a"]), Conss([Conss([Atom(["i","f"]), Conss([Atom(["b"]), Conss([Atom(["d"]), Conss([Atom(["e"]), Nill])])])]), Conss([Conss([Atom(["i","f"]), Conss([Atom(["c"]), Conss([Atom(["d"]), Conss([Atom(["e"]), Nill])])])]), Nill])])])]), Nill])])])]], Empty]), [["i","f","f"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["i","f","f"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["i","m","p","l","i","e","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["i","m","p","l","i","e","s"]), Conss([Atom(["y"]), Conss([Atom(["x"]), Nill])])]), Nill])])]), Nill])])])]], Node([Empty, [["i","m","p","l","i","e","s"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["i","m","p","l","i","e","s"]), Conss([Atom(["p"]), Conss([Atom(["q"]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Atom(["p"]), Conss([Conss([Atom(["i","f"]), Conss([Atom(["q"]), Conss([Conss([Atom(["t"]), Nill]), Conss([Conss([Atom(["f"]), Nill]), Nill])])])]), Conss([Conss([Atom(["t"]), Nill]), Nill])])])]), Nill])])])]], Node([Node([Empty, [["l","a","s","t"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","a","s","t"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["a"]), Conss([Atom(["b"]), Nill])])]), Nill])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["l","i","s","t","p"]), Conss([Atom(["b"]), Nill])]), Conss([Conss([Atom(["l","a","s","t"]), Conss([Atom(["b"]), Nill])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["l","i","s","t","p"]), Conss([Atom(["a"]), Nill])]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Conss([Atom(["c","a","r"]), Conss([Conss([Atom(["l","a","s","t"]), Conss([Atom(["a"]), Nill])]), Nill])]), Conss([Atom(["b"]), Nill])])]), Conss([Atom(["b"]), Nill])])])]), Nill])])])]), Nill])])])]], Empty]), [["l","e","n","g","t","h"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","e","n","g","t","h"]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Atom(["x","1"]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Atom(["x","2"]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Atom(["x","3"]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Atom(["x","4"]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Atom(["x","5"]), Conss([Conss([Atom(["C","o","n","s","s"]), Conss([Atom(["x","6"]), Conss([Atom(["x","7"]), Nill])])]), Nill])])]), Nill])])]), Nill])])]), Nill])])]), Nill])])]), Nill])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["6"]), Conss([Conss([Atom(["l","e","n","g","t","h"]), Conss([Atom(["x","7"]), Nill])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","e","n","g","t","h"]), Conss([Conss([Atom(["r","e","v","e","r","s","e"]), Conss([Atom(["x"]), Nill])]), Nill])]), Conss([Conss([Atom(["l","e","n","g","t","h"]), Conss([Atom(["x"]), Nill])]), Nill])])])]], Empty])])]), [["l","e","s","s","e","q","p"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","e","s","s","e","q","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["y"]), Conss([Atom(["x"]), Nill])])]), Nill])]), Nill])])])]], Node([Node([Node([Node([Node([Node([Node([Empty, [["l","e","s","s","p"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Conss([Atom(["l","e","n","g","t","h"]), Conss([Conss([Atom(["d","e","l","e","t","e"]), Conss([Atom(["x"]), Conss([Atom(["l"]), Nill])])]), Nill])]), Conss([Conss([Atom(["l","e","n","g","t","h"]), Conss([Atom(["l"]), Nill])]), Nill])])]), Conss([Conss([Atom(["m","e","m","b","e","r"]), Conss([Atom(["x"]), Conss([Atom(["l"]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["y"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["x"]), Nill])]), Nill])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Atom(["z"]), Nill])])]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["y"]), Conss([Atom(["z"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["z"]), Nill])]), Nill])]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Atom(["z"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["y"]), Conss([Atom(["z"]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Conss([Atom(["r","e","m","a","i","n","d","e","r"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Atom(["x"]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["y"]), Nill])]), Nill])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["x"]), Nill])]), Nill])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])]), Nill])])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Conss([Atom(["q","u","o","t","i","e","n","t"]), Conss([Atom(["i"]), Conss([Atom(["j"]), Nill])])]), Conss([Atom(["i"]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["i"]), Nill])]), Nill])]), Conss([Conss([Atom(["o","r"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["j"]), Nill])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["j"]), Conss([Atom(["1"]), Nill])])]), Nill])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","e","s","s","p"]), Conss([Conss([Atom(["r","e","m","a","i","n","d","e","r"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["y"]), Nill])]), Nill])]), Nill])])])]], Node([Empty, [["l","i","s","t","p"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["l","i","s","t","p"]), Conss([Conss([Atom(["g","o","p","h","e","r"]), Conss([Atom(["x"]), Nill])]), Nill])]), Conss([Conss([Atom(["l","i","s","t","p"]), Conss([Atom(["x"]), Nill])]), Nill])])])]], Empty])]), [["m","c","-","f","l","a","t","t","e","n"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["m","c","-","f","l","a","t","t","e","n"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Conss([Atom(["f","l","a","t","t","e","n"]), Conss([Atom(["x"]), Nill])]), Conss([Atom(["y"]), Nill])])]), Nill])])])]], Empty]), [["m","e","a","n","i","n","g"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["m","e","a","n","i","n","g"]), Conss([Conss([Atom(["p","l","u","s","-","t","r","e","e"]), Conss([Conss([Atom(["d","e","l","e","t","e"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])]), Conss([Atom(["a"]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["m","e","m","b","e","r"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Conss([Atom(["m","e","a","n","i","n","g"]), Conss([Conss([Atom(["p","l","u","s","-","t","r","e","e"]), Conss([Atom(["y"]), Nill])]), Conss([Atom(["a"]), Nill])])]), Conss([Conss([Atom(["m","e","a","n","i","n","g"]), Conss([Atom(["x"]), Conss([Atom(["a"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["m","e","a","n","i","n","g"]), Conss([Conss([Atom(["p","l","u","s","-","t","r","e","e"]), Conss([Atom(["y"]), Nill])]), Conss([Atom(["a"]), Nill])])]), Nill])])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["m","e","a","n","i","n","g"]), Conss([Conss([Atom(["p","l","u","s","-","t","r","e","e"]), Conss([Conss([Atom(["p","l","u","s","-","f","r","i","n","g","e"]), Conss([Atom(["x"]), Nill])]), Nill])]), Conss([Atom(["a"]), Nill])])]), Conss([Conss([Atom(["f","i","x"]), Conss([Conss([Atom(["m","e","a","n","i","n","g"]), Conss([Atom(["x"]), Conss([Atom(["a"]), Nill])])]), Nill])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["m","e","a","n","i","n","g"]), Conss([Conss([Atom(["p","l","u","s","-","t","r","e","e"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])]), Conss([Atom(["a"]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Conss([Atom(["m","e","a","n","i","n","g"]), Conss([Conss([Atom(["p","l","u","s","-","t","r","e","e"]), Conss([Atom(["x"]), Nill])]), Conss([Atom(["a"]), Nill])])]), Conss([Conss([Atom(["m","e","a","n","i","n","g"]), Conss([Conss([Atom(["p","l","u","s","-","t","r","e","e"]), Conss([Atom(["y"]), Nill])]), Conss([Atom(["a"]), Nill])])]), Nill])])]), Nill])])])]], Node([Empty, [["m","e","m","b","e","r"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["m","e","m","b","e","r"]), Conss([Atom(["a"]), Conss([Conss([Atom(["i","n","t","e","r","s","e","c","t"]), Conss([Atom(["b"]), Conss([Atom(["c"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["m","e","m","b","e","r"]), Conss([Atom(["a"]), Conss([Atom(["b"]), Nill])])]), Conss([Conss([Atom(["m","e","m","b","e","r"]), Conss([Atom(["a"]), Conss([Atom(["c"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["m","e","m","b","e","r"]), Conss([Atom(["x"]), Conss([Conss([Atom(["r","e","v","e","r","s","e"]), Conss([Atom(["y"]), Nill])]), Nill])])]), Conss([Conss([Atom(["m","e","m","b","e","r"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["m","e","m","b","e","r"]), Conss([Atom(["x"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["a"]), Conss([Atom(["b"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["o","r"]), Conss([Conss([Atom(["m","e","m","b","e","r"]), Conss([Atom(["x"]), Conss([Atom(["a"]), Nill])])]), Conss([Conss([Atom(["m","e","m","b","e","r"]), Conss([Atom(["x"]), Conss([Atom(["b"]), Nill])])]), Nill])])]), Nill])])])]], Empty])]), [["n","o","t"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["n","o","t"]), Conss([Atom(["p"]), Nill])]), Conss([Conss([Atom(["i","f"]), Conss([Atom(["p"]), Conss([Conss([Atom(["f"]), Nill]), Conss([Conss([Atom(["t"]), Nill]), Nill])])])]), Nill])])])]], Node([Empty, [["n","t","h"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["n","t","h"]), Conss([Conss([Atom(["N","i","l","l"]), Nill]), Conss([Atom(["i"]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["i"]), Nill])]), Conss([Conss([Atom(["N","i","l","l"]), Nill]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["n","t","h"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["a"]), Conss([Atom(["b"]), Nill])])]), Conss([Atom(["i"]), Nill])])]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Conss([Atom(["n","t","h"]), Conss([Atom(["a"]), Conss([Atom(["i"]), Nill])])]), Conss([Conss([Atom(["n","t","h"]), Conss([Atom(["b"]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Atom(["i"]), Conss([Conss([Atom(["l","e","n","g","t","h"]), Conss([Atom(["a"]), Nill])]), Nill])])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["n","t","h"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Conss([Atom(["i"]), Nill])])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])])]], Node([Empty, [["n","u","m","b","e","r","p"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["n","u","m","b","e","r","p"]), Conss([Conss([Atom(["g","r","e","a","t","e","s","t","-","f","a","c","t","o","r"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["o","r"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["y"]), Nill])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["y"]), Conss([Atom(["1"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["n","u","m","b","e","r","p"]), Conss([Atom(["x"]), Nill])]), Nill])]), Nill])])]), Nill])]), Nill])])])]], Empty])])]), [["o","r"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["o","r"]), Conss([Atom(["p"]), Conss([Atom(["q"]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Atom(["p"]), Conss([Conss([Atom(["t"]), Nill]), Conss([Conss([Atom(["i","f"]), Conss([Atom(["q"]), Conss([Conss([Atom(["t"]), Nill]), Conss([Conss([Atom(["f"]), Nill]), Nill])])])]), Nill])])])]), Nill])])])]], Node([Empty, [["p","l","u","s"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Conss([Atom(["a","d","d","1"]), Conss([Atom(["y"]), Nill])]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["n","u","m","b","e","r","p"]), Conss([Atom(["y"]), Nill])]), Conss([Conss([Atom(["a","d","d","1"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])]), Conss([Conss([Atom(["a","d","d","1"]), Conss([Atom(["x"]), Nill])]), Nill])])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Conss([Atom(["r","e","m","a","i","n","d","e","r"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["y"]), Conss([Conss([Atom(["q","u","o","t","i","e","n","t"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Nill])])]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["x"]), Nill])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Atom(["z"]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["y"]), Conss([Atom(["z"]), Nill])])]), Nill])])]), Nill])])])]], Node([Empty, [["p","o","w","e","r","-","e","v","a","l"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["p","o","w","e","r","-","e","v","a","l"]), Conss([Conss([Atom(["b","i","g","-","p","l","u","s"]), Conss([Conss([Atom(["p","o","w","e","r","-","r","e","p"]), Conss([Atom(["i"]), Conss([Atom(["b","a","s","e"]), Nill])])]), Conss([Conss([Atom(["p","o","w","e","r","-","r","e","p"]), Conss([Atom(["j"]), Conss([Atom(["b","a","s","e"]), Nill])])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Conss([Atom(["b","a","s","e"]), Nill])])])])]), Conss([Atom(["b","a","s","e"]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["i"]), Conss([Atom(["j"]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["p","o","w","e","r","-","e","v","a","l"]), Conss([Conss([Atom(["p","o","w","e","r","-","r","e","p"]), Conss([Atom(["i"]), Conss([Atom(["b","a","s","e"]), Nill])])]), Conss([Atom(["b","a","s","e"]), Nill])])]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["i"]), Nill])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["p","o","w","e","r","-","e","v","a","l"]), Conss([Conss([Atom(["b","i","g","-","p","l","u","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Conss([Atom(["i"]), Conss([Atom(["b","a","s","e"]), Nill])])])])]), Conss([Atom(["b","a","s","e"]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["i"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Conss([Atom(["p","o","w","e","r","-","e","v","a","l"]), Conss([Atom(["x"]), Conss([Atom(["b","a","s","e"]), Nill])])]), Conss([Conss([Atom(["p","o","w","e","r","-","e","v","a","l"]), Conss([Atom(["y"]), Conss([Atom(["b","a","s","e"]), Nill])])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["p","o","w","e","r","-","e","v","a","l"]), Conss([Conss([Atom(["b","i","g","-","p","l","u","s","1"]), Conss([Atom(["l"]), Conss([Atom(["i"]), Conss([Atom(["b","a","s","e"]), Nill])])])]), Conss([Atom(["b","a","s","e"]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Conss([Atom(["p","o","w","e","r","-","e","v","a","l"]), Conss([Atom(["l"]), Conss([Atom(["b","a","s","e"]), Nill])])]), Conss([Atom(["i"]), Nill])])]), Nill])])])]], Empty])])]), [["p","r","i","m","e"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["p","r","i","m","e"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["x"]), Nill])]), Nill])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["x"]), Conss([Conss([Atom(["a","d","d","1"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])]), Nill])])]), Nill])]), Conss([Conss([Atom(["p","r","i","m","e","1"]), Conss([Atom(["x"]), Conss([Conss([Atom(["1","-"]), Conss([Atom(["x"]), Nill])]), Nill])])]), Nill])])])]), Nill])])])]], Node([Node([Node([Empty, [["p","r","i","m","e","-","l","i","s","t"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["p","r","i","m","e","-","l","i","s","t"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])]), Conss([Conss([Atom(["a","n","d"]), Conss([Conss([Atom(["p","r","i","m","e","-","l","i","s","t"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["p","r","i","m","e","-","l","i","s","t"]), Conss([Atom(["y"]), Nill])]), Nill])])]), Nill])])])]], Node([Empty, [["q","u","o","t","i","e","n","t"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["q","u","o","t","i","e","n","t"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["y"]), Conss([Atom(["x"]), Nill])])]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["y"]), Nill])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["x"]), Nill])]), Nill])])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["q","u","o","t","i","e","n","t"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Conss([Atom(["2"]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Conss([Atom(["q","u","o","t","i","e","n","t"]), Conss([Atom(["y"]), Conss([Atom(["2"]), Nill])])]), Nill])])]), Nill])])])]], Empty])]), [["r","e","m","a","i","n","d","e","r"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["r","e","m","a","i","n","d","e","r"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["y"]), Conss([Atom(["x"]), Nill])])]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["r","e","m","a","i","n","d","e","r"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Atom(["z"]), Nill])])]), Conss([Atom(["z"]), Nill])])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["r","e","m","a","i","n","d","e","r"]), Conss([Atom(["x"]), Conss([Atom(["x"]), Nill])])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["r","e","m","a","i","n","d","e","r"]), Conss([Atom(["y"]), Conss([Atom(["1"]), Nill])])]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])])]], Empty]), [["r","e","v","e","r","s","e"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["r","e","v","e","r","s","e"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["a"]), Conss([Atom(["b"]), Nill])])]), Nill])]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Conss([Atom(["r","e","v","e","r","s","e"]), Conss([Atom(["b"]), Nill])]), Conss([Conss([Atom(["r","e","v","e","r","s","e"]), Conss([Atom(["a"]), Nill])]), Nill])])]), Nill])])])]], Empty])]), [["r","e","v","e","r","s","e","-"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["r","e","v","e","r","s","e","-"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["r","e","v","e","r","s","e","-","l","o","o","p"]), Conss([Atom(["x"]), Conss([Conss([Atom(["N","i","l","l"]), Nill]), Nill])])]), Nill])])])]], Node([Node([Empty, [["r","e","v","e","r","s","e","-","l","o","o","p"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["r","e","v","e","r","s","e","-","l","o","o","p"]), Conss([Atom(["x"]), Conss([Conss([Atom(["N","i","l","l"]), Nill]), Nill])])]), Conss([Conss([Atom(["r","e","v","e","r","s","e"]), Conss([Atom(["x"]), Nill])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["r","e","v","e","r","s","e","-","l","o","o","p"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Conss([Atom(["r","e","v","e","r","s","e"]), Conss([Atom(["x"]), Nill])]), Conss([Atom(["y"]), Nill])])]), Nill])])])]], Node([Empty, [["s","a","m","e","f","r","i","n","g","e"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["s","a","m","e","f","r","i","n","g","e"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["f","l","a","t","t","e","n"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["f","l","a","t","t","e","n"]), Conss([Atom(["y"]), Nill])]), Nill])])]), Nill])])])]], Node([Node([Empty, [["s","i","g","m","a"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["s","i","g","m","a"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Conss([Atom(["i"]), Nill])])]), Conss([Conss([Atom(["q","u","o","t","i","e","n","t"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["i"]), Conss([Conss([Atom(["a","d","d","1"]), Conss([Atom(["i"]), Nill])]), Nill])])]), Conss([Atom(["2"]), Nill])])]), Nill])])])]], Empty]), [["s","o","r","t","2"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["s","o","r","t","2"]), Conss([Conss([Atom(["d","e","l","e","t","e"]), Conss([Atom(["x"]), Conss([Atom(["l"]), Nill])])]), Nill])]), Conss([Conss([Atom(["d","e","l","e","t","e"]), Conss([Atom(["x"]), Conss([Conss([Atom(["s","o","r","t","2"]), Conss([Atom(["l"]), Nill])]), Nill])])]), Nill])])])]], Empty])])]), [["t","a","u","t","o","l","o","g","y","-","c","h","e","c","k","e","r"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["t","a","u","t","o","l","o","g","y","-","c","h","e","c","k","e","r"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["t","a","u","t","o","l","o","g","y","p"]), Conss([Conss([Atom(["n","o","r","m","a","l","i","z","e"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["N","i","l","l"]), Nill]), Nill])])]), Nill])])])]], Node([Node([Empty, [["t","i","m","e","s"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Conss([Atom(["a","d","d","1"]), Conss([Atom(["y"]), Nill])]), Nill])])]), Conss([Conss([Atom(["i","f"]), Conss([Conss([Atom(["n","u","m","b","e","r","p"]), Conss([Atom(["y"]), Nill])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["x"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["f","i","x"]), Conss([Atom(["x"]), Nill])]), Nill])])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Atom(["c"]), Conss([Atom(["w"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["d","i","f","f","e","r","e","n","c","e"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["c"]), Conss([Atom(["x"]), Nill])])]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["w"]), Conss([Atom(["x"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Atom(["z"]), Nill])])]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["y"]), Conss([Atom(["z"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Atom(["y"]), Conss([Atom(["z"]), Nill])])]), Nill])])]), Conss([Conss([Atom(["p","l","u","s"]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Atom(["x"]), Conss([Atom(["z"]), Nill])])]), Nill])])]), Nill])])])]], Node([Node([Empty, [["t","i","m","e","s","-","l","i","s","t"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["t","i","m","e","s","-","l","i","s","t"]), Conss([Conss([Atom(["a","p","p","e","n","d"]), Conss([Atom(["x"]), Conss([Atom(["y"]), Nill])])]), Nill])]), Conss([Conss([Atom(["t","i","m","e","s"]), Conss([Conss([Atom(["t","i","m","e","s","-","l","i","s","t"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["t","i","m","e","s","-","l","i","s","t"]), Conss([Atom(["y"]), Nill])]), Nill])])]), Nill])])])]], Empty]), [["v","a","l","u","e"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["v","a","l","u","e"]), Conss([Conss([Atom(["n","o","r","m","a","l","i","z","e"]), Conss([Atom(["x"]), Nill])]), Conss([Atom(["a"]), Nill])])]), Conss([Conss([Atom(["v","a","l","u","e"]), Conss([Atom(["x"]), Conss([Atom(["a"]), Nill])])]), Nill])])])]], Empty])]), [["z","e","r","o","p"], [Conss([Atom(["e","q","u","a","l"]), Conss([Conss([Atom(["z","e","r","o","p"]), Conss([Atom(["x"]), Nill])]), Conss([Conss([Atom(["o","r"]), Conss([Conss([Atom(["e","q","u","a","l"]), Conss([Atom(["x"]), Conss([Conss([Atom(["z","e","r","o"]), Nill]), Nill])])]), Conss([Conss([Atom(["n","o","t"]), Conss([Conss([Atom(["n","u","m","b","e","r","p"]), Conss([Atom(["x"]), Nill])]), Nill])]), Nill])])]), Nill])])])]], Empty])])])])])])]) + +fun tautp(term) = tautologyp([rewrite(term, lemmas), Nill, Nill]) + +fun teststatement(i) = applysubst(subterm(i), statement) + +fun testresult(i) = tautp(teststatement(i)) + +fun testBoyer2_nofib(n) = report(testresult(n)) + +fun main() = testBoyer2_nofib(3) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/calendar.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/calendar.mls new file mode 100644 index 0000000000..f4f3c881f7 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/calendar.mls @@ -0,0 +1,101 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module calendar with ... + + + +fun unlines(ls) = concat(map(x => x +: ("\n" :: Nil), ls)) + +fun height(p) = listLen(p) + +fun width(p) = listLen(head(p)) + +fun stack(ls) = foldr1((a, b) => a +: b, ls) + +fun spread(ls) = foldr1((a, b) => zipWith((a, b) => a +: b, a, b), ls) + +fun emptyPic(hw) = if hw is [h, w] then replicate(h, replicate(w, " ")) + +fun groop(n, xs) = if xs is + Nil then Nil + else take(n, xs) :: groop(n, leave(n, xs)) + +fun block(n, t) = stack(map(spread, groop(n, t))) + +fun blockT(n, t) = stack(map(stack, groop(n, t))) + +fun lframe(mn, p) = if mn is [m,n] then + let h = height(p) + let w = width(p) + zipWith(append, p, emptyPic([h, n - w])) +: emptyPic([m - h, n]) + +fun leap(year) = if + intMod(year, 100) == 0 then intMod(year, 400) == 0 + else intMod(year, 4) == 0 + +fun monthLengths(year) = + let feb = if leap(year) then 29 else 28 + 31 :: feb :: 31 :: 30 :: 31 :: 30 :: 31 :: 31 :: 30 :: 31 :: 30 :: 31 :: Nil + +val monthNames = + nofibStringToList("January") :: + nofibStringToList("February") :: + nofibStringToList("March") :: + nofibStringToList("April") :: + nofibStringToList("May") :: + nofibStringToList("June") :: + nofibStringToList("July") :: + nofibStringToList("August") :: + nofibStringToList("September") :: + nofibStringToList("October") :: + nofibStringToList("November") :: + nofibStringToList("December") :: Nil +//│ monthNames = [["J","a","n","u","a","r","y"],["F","e","b","r","u","a","r","y"],["M","a","r","c","h"],["A","p","r","i","l"],["M","a","y"],["J","u","n","e"],["J","u","l","y"],["A","u","g","u","s","t"],["S","e","p","t","e","m","b","e","r"],["O","c","t","o","b","e","r"],["N","o","v","e","m","b","e","r"],["D","e","c","e","m","b","e","r"]] + +fun jan1st(year) = + let last = year - 1 + intMod(year + intDiv(last, 4) - intDiv(last, 100) + intDiv(last, 400), 7) + +fun firstDays(year) = + take(12, map(x => intMod(x, 7), scanl((a, b) => a + b, jan1st(year), monthLengths(year)))) + +fun space(n) = replicate(n, " ") + +fun ljustify(n, s) = s +: space(n - listLen(s)) + +fun rjustify(n, s) = space(n - listLen(s)) +: s + +fun date(ml, d) = if (d < 1) || (ml < d) then nofibStringToList(" ") :: Nil else rjustify(3, nofibStringToList(stringOfInt(d))) :: Nil + +fun dates(fd, ml) = map(d => date(ml, d), enumFromTo(1 - fd, 42 - fd)) + +fun cjustify(n, s) = + let m = n - listLen(s) + let halfm = intDiv(m, 2) + space(halfm) +: s +: space(m - halfm) + +fun cal(year) = + let side = emptyPic([8, 2]) + let end = emptyPic([1, 25]) + let daynames = nofibStringToList(" Su Mo Tu We Th Fr Sa") :: Nil + fun banner(yr) = cjustify(75, nofibStringToList(stringOfInt(yr))) :: emptyPic([1, 75]) + fun body(yr) = block(3, map(x => pad(pic(x)), months(yr))) + fun pic(mnfdml) = if mnfdml is [mn, fd, ml] then title(mn) +: table(fd, ml) + fun pad(p) = zipWith(append, zipWith(append, side, p), side) +: end + fun title(mn) = cjustify(21, mn) :: Nil + fun table(fd, ml) = daynames +: entries(fd, ml) + fun entries(fd, ml) = block(7, dates(fd, ml)) + fun months(yer) = zip3(monthNames, firstDays(yer), monthLengths(yer)) + + unlines(banner(year) +: body(year)) + +fun testCalendar_nofib(n) = map(x => cal(x), enumFromTo(1993, 1993 + n)) + + +// NOTE: original input: 1000 +fun main() = + nofibListToString of concat of testCalendar_nofib(0) + + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cichelli.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cichelli.mls new file mode 100644 index 0000000000..07e3036bab --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cichelli.mls @@ -0,0 +1,158 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module cichelli with ... + + + +val keys = + nofibStringToList("case") :: nofibStringToList("class") :: nofibStringToList("data") :: nofibStringToList("default") :: nofibStringToList("deriving") :: nofibStringToList("else") :: + nofibStringToList("hiding") :: nofibStringToList("if") :: nofibStringToList("import") :: nofibStringToList("in") :: nofibStringToList("infix") :: nofibStringToList("infixl") :: nofibStringToList("instance") :: + nofibStringToList("interface") :: nofibStringToList("let") :: nofibStringToList("module") :: nofibStringToList("of") :: nofibStringToList("renaming") :: nofibStringToList("then") :: nofibStringToList("to") :: + nofibStringToList("type") :: nofibStringToList("where") :: Nil +//│ keys = [["c","a","s","e"],["c","l","a","s","s"],["d","a","t","a"],["d","e","f","a","u","l","t"],["d","e","r","i","v","i","n","g"],["e","l","s","e"],["h","i","d","i","n","g"],["i","f"],["i","m","p","o","r","t"],["i","n"],["i","n","f","i","x"],["i","n","f","i","x","l"],["i","n","s","t","a","n","c","e"],["i","n","t","e","r","f","a","c","e"],["l","e","t"],["m","o","d","u","l","e"],["o","f"],["r","e","n","a","m","i","n","g"],["t","h","e","n"],["t","o"],["t","y","p","e"],["w","h","e","r","e"]] + +fun enumFromTo_lz(a, b) = lazy of () => + if a <= b then LzCons(a, enumFromTo_lz(a + 1, b)) else LzNil + +fun last(ls) = + fun go(h, t) = if t is + Nil then h + head :: t then go(head, t) + if ls is + h :: t then go(h, t) + else throw Error("last: empty list") + +data class K(s: String, c1: Char, c2: Char, i: Int) + +data class H(f: Option[Int], s: Option[Int], ls: List[Int]) + +fun ends(k) = if k is K(_, a, z, _) then a :: z :: Nil + +fun assoc(x, yz) = if yz is + [y, z] :: yzs then if x === y then z else assoc(x, yzs) + else throw Error("assoc: not found") + +fun assocm(x, yz) = if yz is + [y, z] :: yzs then if x === y then Some(z) else assocm(x, yzs) + else None + +fun histins(x, yns) = if yns is + [y, n] :: yns then if x === y then [y, n + 1] :: yns else [y, n] :: histins(x, yns) + else [x, 1] :: Nil + +fun histo(ls) = foldr(cichelli.histins, Nil, ls) + +fun subset(xs, ys) = all(x => inList(x, ys), xs) + +fun union(xs, ys) = + fun lscomp(ls) = if ls is + Nil then Nil + h :: t and + not(inList(h, xs)) then h :: lscomp(t) + else lscomp(t) + append(xs, lscomp(ys)) + +fun attribkeys(ks) = map(k => K(k, head(k), cichelli.last(k), listLen(k)), ks) + +val numberofkeys = listLen(keys) +//│ numberofkeys = 22 + +fun minm(x, y) = if x is + None then y + Some(x) then min(x, y) + +fun maxm(x, y) = if x is + None then y + Some(x) then max(x, y) + +fun hash(cvs, k) = if k is K(_, a, z, n) then n + assoc(a, cvs) + assoc(z, cvs) + +fun select(p, x, ts_fs) = if ts_fs is [ts, fs] and + p(x) then [x :: ts, fs] + else [ts, x :: fs] + +fun partition_(p, ls) = foldr((x, y) => select(p, x, y), [Nil, Nil], ls) + +fun freqsorted(x) = x + +fun blocked_(ds, ls) = if ls is + Nil then Nil + k :: ks then + let ds_ = union(ds, ends(k)) + if partition_(x => subset(ends(x), ds_), ks) is [det, rest] then + k :: (det +: blocked_(ds_, rest)) + +fun blocked(ls) = blocked_(Nil, ls) + +val freqtab = histo(concat(map(ends, attribkeys(keys)))) +//│ freqtab = [["e", 8],["w", 1],["t", 6],["o", 2],["n", 2],["g", 3],["r", 1],["f", 2],["m", 1],["l", 2],["i", 7],["x", 1],["h", 1],["d", 3],["a", 1],["s", 1],["c", 2]] + +val maxval = listLen(freqtab) +//│ maxval = 17 + +abstract class Status[T]: NotEver | YesIts[T] + +data + class + NotEver(i: Int) extends Status[Nothing] + YesIts[T](i: Int, t: T) extends Status[T] + +fun hinsert(h, hh) = if hh is H(lo, hi, hs) then + let lo_ = minm(lo, h) + let hi_ = maxm(hi, h) + if inList(h, hs) || (1 + hi_ - lo_) > numberofkeys + then None + else Some(H(Some(lo_), Some(hi_), h :: hs)) + +fun first(k, ls) = if force(ls) is + LzNil then NotEver(k) + LzCons(a, l) and a is + YesIts(leaves, y) then YesIts(k + leaves, y) + NotEver(leaves) then first(k + leaves, l) + +fun firstSuccess(f, possibles) = first(0, map_lz(f, possibles)) + +fun findhash_(keyHashSet, charAssocs, ks) = if ks is + Nil then YesIts(1, charAssocs) + K(s, a, z, n) :: ks then + fun tryy(newAssocs) = + let newCharAssocs = newAssocs +: charAssocs + if hinsert(hash(newCharAssocs, K(s, a, z, n)), keyHashSet) is + None then NotEver(1) + Some(newKeyHashSet) then findhash_(newKeyHashSet, newCharAssocs, ks) + if [assocm(a, charAssocs), assocm(z, charAssocs)] is + [None, None] and + a === z then firstSuccess(m => tryy([a, m] :: Nil), enumFromTo_lz(0, maxval)) + else + fun lscomp1(ls1) = lazy of () => + if force(ls1) is + LzNil then LzNil + LzCons(m, ms) then + fun lscomp2(ls2) = + if force(ls2) is + LzNil then lscomp1(ms) + LzCons(n, ns) then lazy of () => LzCons([m, n], lscomp2(ns)) + force(lscomp2(enumFromTo_lz(0, maxval))) + firstSuccess(case { [m, n] then tryy([a, m] :: [z, n] :: Nil) }, lscomp1(enumFromTo_lz(0, maxval))) + [None, Some(zc)] then firstSuccess(m => tryy([a, m] :: Nil), enumFromTo_lz(0, maxval)) + [Some(ac), None] then firstSuccess(n => tryy([z, n] :: Nil), enumFromTo_lz(0, maxval)) + [Some(ac), Some(zc)] then tryy(Nil) + +fun findhash(keys) = findhash_(H(None, None, Nil), Nil, keys) + +fun freq(c) = assoc(c, freqtab) + +fun morefreq(k1, k2) = if + k1 is K(_, a, x, _) and k2 is K(_, b, y, _) then (freq(a) + freq(x)) > (freq(b) + freq(y)) + +fun cichelli_(n) = + let attribkeys_ = attribkeys(keys +: take(intMod(n, 2), keys)) + let hashkeys = blocked(freqsorted(attribkeys_)) + findhash(hashkeys) + +fun prog(n) = cichelli_(n) + +fun main() = prog(6).toString() \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/circsim.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/circsim.mls new file mode 100644 index 0000000000..c4d20e5ac9 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/circsim.mls @@ -0,0 +1,321 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module circsim with ... + + + +abstract class BinTree[T, U]: Cell[T] | Node[T, U] + +data + class + Cell[T](value: T) extends BinTree[T, Nothing] + Node[T, U](value: U, left: BinTree[T, U], right: BinTree[T, U]) extends BinTree[T, U] + +abstract class Componenet: None_ | Inp | Outp | Dff | Inv | And2 | Or2 | Xor + +object + None_ extends Componenet + Inp extends Componenet + Outp extends Componenet + Dff extends Componenet + Inv extends Componenet + And2 extends Componenet + Or2 extends Componenet + Xor extends Componenet + +object Unit + +data class PS[T](pid: Int, compType: Componenet, pathDepth: Int, inports: List[[Int, Int, T]], outports: List[[Int, T, Bool, Int, Bool, Int]]) + +fun pid(p) = p.pid + +fun compType(p) = p.compType + +fun pathDepth(p) = p.pathDepth + +fun inports(p) = p.inports + +fun outports(p) = p.outports + +fun updateOutports(p, noutports) = PS(pid(p), compType(p), pathDepth(p), inports(p), noutports) + +fun updateInports(p, ninports) = PS(pid(p), compType(p), pathDepth(p), ninports, outports(p)) + +abstract class Boolean: F | T + +object + F extends Boolean + T extends Boolean + +fun put(xs) = if + xs is x :: Nil then Cell(x) + splitAt(intDiv(listLen(xs), 2), xs) is [fstHalf, sndHalf] then Node(Unit, put(fstHalf), put(sndHalf)) + +fun get(t) = if t is + Cell(x) then x :: Nil + Node(_, l, r) then get(l) +: get(r) + +fun upsweep(f, t) = if t is + Cell(a) then [a, Cell(a)] + Node(x, l, r) and upsweep(f, l) is [lv, l_] and upsweep(f, r) is [rv, r_] then + [f(lv, rv), Node([lv, rv], l_, r_)] + +fun downsweep(g, d, t) = if t is + Cell(x) then Cell(d) + Node([lv, rv], l, r) and g(lv, rv, d) is [dl, dr] then + Node(Unit, downsweep(g, dl, l), downsweep(g, dr, r)) + +fun sweep_ud(up, down, u, t) = if upsweep(up, t) is [ans, t_] then + [ans, downsweep(down, u, t_)] + +fun scanL(f, u, xs) = + fun down1(l, r, x) = [x, f(x, l)] + if sweep_ud(f, down1, u, put(xs)) is [up_ans, t_] then [up_ans, get(t_)] + +fun scanR(f, u, xs) = + fun down2(l, r, x) = [f(r, x), x] + if sweep_ud(f, down2, u, put(xs)) is [up_ans, t_] then [up_ans, get(t_)] + +fun scanlr(f, g, lu, ru, xs) = + fun up(f, g, lxly, rxry) = if lxly is [lx, ly] and rxry is [rx, ry] then [f(lx, rx), g(ly, ry)] + + fun down3(f, g, lxly, rxry, ab) = if lxly is [lx, ly] and rxry is [rx, ry] and ab is [a, b] then + [[a, g(ry, b)], [f(a, lx), b]] + + let xs_ = map(x => [x, x], xs) + + if sweep_ud((a, b) => up(f, g, a, b), (a, b, c) => down3(f, g, a, b, c), [lu, ru], put(xs_)) is [[l_ans, r_ans], t_] then + let ans = [g(r_ans, ru), f(lu, l_ans)] + [ans, get(t_)] + +fun nearest_power_of_two(x) = until(a => a >= x, a => a * 2, 1) + +val emptyState = PS(-1, None_, -1, Nil, Nil) +//│ emptyState = PS(-1, None_, -1, [], []) + +fun pad_circuit(size_ins_outs_states) = if size_ins_outs_states is [size, ins, outs, states] then + let p2 = nearest_power_of_two(size) + let states_ = append_nl_lz(states, replicate_lz(p2, emptyState)) + [p2, ins, outs, take_lz(p2, states_)] + +fun inv(x) = if x === T then F else T + +fun and2(x, y) = if x === T && y === T then T else F + +fun or2(x, y) = if x === T || y === T then T else F + +fun xor(x, y) = if x === y then T else F + +val emptyPacket = [-1, -1, F, false, 0, false, 0, 1] +//│ emptyPacket = [-1, -1, F, false, 0, false, 0, 1] + +fun send_right(a, b) = if a is [ia, sa, ma, qla, dla, qra, dra, ea] and b is [ib, sb, mb, qlb, dlb, qrb, drb, eb] and + qra and (dra > eb) then [ia, sa, ma, qla, dla, qra, dra - eb, ea + eb] + else [ib, sb, mb, qlb, dlb, qrb, drb, ea + eb] + +fun send_left(a, b) = if a is [ia, sa, ma, qla, dla, qra, dra, ea] and b is [ib, sb, mb, qlb, dlb, qrb, drb, eb] and + qlb && (dlb > ea) then [ib, sb, mb, qlb, dlb - ea, qrb, drb, ea + eb] + else [ia, sa, ma, qla, dla, qra, dra, ea + eb] + +fun send(xs) = scanlr(send_right, send_left, emptyPacket, emptyPacket, xs) + +fun update_outports(state, value) = + fun lscomp(ls) = if ls is + Nil then Nil + h :: t and + h is [p, m, ql, dl, qr, dr] then [p, value, ql, dl, qr, dr] :: lscomp(t) + else lscomp(t) + + updateOutports(state, lscomp(outports(state))) + + +fun critical_path_depth(siot) = if siot is [size, ins, outs, states] then maximum(map(pathDepth, states)) + +fun collect_outputs(tp4) = if tp4 is [size, ins, outs, states] then + fun thrid(tp3) = if tp3 is [_, _, v] then v + + fun get_output(states, label_p) = if label_p is [label, p] then + fun lscomp(ls) = if ls is + Nil then Nil + s :: t and + p == pid(s) then head(inports(s)) :: lscomp(t) + else lscomp(t) + thrid(head(lscomp(states))) + + map(p => get_output(states, p), outs) + + +fun store_inputs(label_inputs, state) = if state is + PS(pid_, Inp, _, _, _) then + fun lscomp(ls) = if ls is + Nil then Nil + h :: t and + h is [[label, input_pid], value] and pid_ == input_pid then update_outports(state, value) :: lscomp(t) + else lscomp(t) + head(lscomp(label_inputs)) + else state + +fun apply_component(comp, signals) = if comp is + Inp then None + Outp and signals is x :: Nil then Some(x) + Dff and signals is x :: Nil then Some(x) + Inv and signals is x :: Nil then Some(inv(x)) + And2 and signals is x :: y :: Nil then Some(and2(x, y)) + Or2 and signals is x :: y :: Nil then Some(or2(x, y)) + Xor and signals is x :: y :: Nil then Some(xor(x, y)) + None_ then None + +fun init_dffs(state) = if compType(state) === Dff then update_outports(state, F) else state + +fun restore_requests(old_states, new_states) = + fun restore(os, ns) = updateOutports(ns, zipWith(restore_outport, outports(os), outports(ns))) + + fun restore_outport(pql, mdq) = if pql is [p, _, ql, dl, qr, dq] and mdq is [_, m, _, _, _, _] then [p, m, ql, dl, qr, dq] + + zipWith(restore, old_states, new_states) + + +fun update_requests(b, state) = + fun lscomp(ls) = if ls is + Nil then Nil + h :: t and + h is [p, m, ql, dl, qr, dr] then [p, m, b, dl, b, dr] :: lscomp(t) + else lscomp(t) + updateOutports(state, lscomp(outports(state))) + +fun check_depth(d, state) = if pathDepth(state) == d then state else update_requests(false, state) + +fun acknowledge(d, states) = + fun check_requests(xs) = orList(map(check_lr_requests, xs)) + + fun check_lr_requests(pql) = if pql is [p,m,ql,dl,qr,dr] then ql || qr + + let states1 = map(s => check_depth(d, s), states) + + not(orList(map(s => check_requests(outports(s)), states1))) + + +fun pad_packets(pss) = + fun pad(xs) = + let max_ps = maximum(map(x => listLen(x), pss)) + take_lz(max_ps, append_nl_lz(xs, replicate_lz(max_ps, emptyPacket))) + + map(x => pad(x), pss) + + +fun make_packet(state) = + fun lscomp(ls) = if ls is + Nil then Nil + h :: t and + h is [p, m, ql, dl, qr, dr] then [pid(state), p, m, ql, dl, qr, dr, 1] :: lscomp(t) + else lscomp(t) + + lscomp(outports(state)) + + +fun compare_and_update(ipm_, pid_port_m) = + if ipm_ is [i, p, m_] and pid_port_m is [pid_, port, m] and + eqTup2([i, p], [pid_, port]) then [pid_, port, m_] + else [pid_, port, m] + +fun up_i(ipm_, ins) = if ipm_ is [i, p, m_, _, _, _, _, _] then map(x => compare_and_update([i, p, m_], x), ins) + +fun update_i(l_r, ins) = if l_r is [l, r] then up_i(l, up_i(r, ins)) + +fun check_left(a, b) = if a is [pid_, port, pm, pql, pdl, pqr, pdr, e] and b is [p, m, ql, dl, qr, dr] and + pqr && (pdr > 0) then [p, m, ql, dl, qr, dr] + else [p, m, ql, dl, false, dr] + +fun check_right(a, b) = if a is [pid_, port, pm, pql, pdl, pqr, pdr, e] and b is [p, m, ql, dl, qr, dr] and + pql && (pdl > 0) then [p, m, ql, dl, qr, dr] + else [p, m, false, dl, qr, dr] + +fun update_o(lp_rp, out_) = if lp_rp is [lp, rp] then check_left(lp, check_right(rp, out_)) + +fun update_io(d, lrps, state) = + fun update_is(state) = updateInports(state, foldr(update_i, inports(state), lrps)) + + fun update_os(state) = if pathDepth(state) == d then updateOutports(state, zipWith(update_o, lrps, outports(state))) else state + + update_os(update_is(state)) + + +fun do_send(d, states) = + let states1 = map(s => check_depth(d, s), states) + let send_results = map(x => snd(send(x)), transpose(pad_packets(map(make_packet, states1)))) + let pss_ = transpose(send_results) + + zipWith((x, y) => update_io(d, x, y), pss_, states) + + +fun do_sends(d, states) = until(s => acknowledge(d, s), x => do_send(d, x), states) + +fun simulate_component(d, state) = + fun lscomp(ls) = if ls is + Nil then Nil + h :: t and + h is [_, _, sig] then sig :: lscomp(t) + else lscomp(t) + + let out_signals = lscomp(inports(state)) + let new_value = apply_component(compType(state), out_signals) + + if + d == pathDepth(state) and not(new_value === None) and new_value is Some(v) then update_outports(state, v) + else state + +fun simulate_components(depth, states) = map(s => simulate_component(depth, s), states) + +fun do_cycle(cpd, tp4, inputs) = + fun sim_then_send(state, d) = do_sends(d, simulate_components(d, state)) + + if tp4 is [size, ins, outs, states] then + let states1 = map(s => store_inputs(zip(ins, inputs), s), states) + let states2 = do_sends(0, states1) + let states3 = foldl(sim_then_send, states2, enumFromTo(1, cpd)) + let states4 = restore_requests(states, states3) + [size, ins, outs, states4] + else throw Error(tp4) + +fun simulate(inputs_list, b) = if b is [size, ins, outs, states] then + tail(scanl((x, y) => do_cycle(critical_path_depth([size, ins, outs, states]), x, y), [size, ins, outs, map(init_dffs, states)], inputs_list)) + +fun reg(sto, n) = + PS(n, Inp, 0, Nil, [0, F, false, 0, true, 4] :: Nil) :: + PS(n + 1, Dff, 1, [n + 5, 0, F] :: Nil, [0, F, false, 0, true, 5] :: Nil) :: + PS(n + 2, Inv, 1, [sto, 0, F] :: Nil, [0, F, false, 0, true, 1] :: Nil) :: + PS(n + 3, And2, 2, [n + 1, 0, F] :: [n + 2, 0, F] :: Nil, [0, F, false, 0, true, 2] :: Nil) :: + PS(n + 4, And2, 1, [sto, 0, F] :: [n, 0, F] :: Nil, [0, F, false, 0, true, 1] :: Nil) :: + PS(n + 5, Or2, 3, [n + 3, 0, F] :: [n + 4, 0, F] :: Nil, [0, F, true, 4, false, 0] :: Nil) :: + PS(n + 6, Outp, 4, [n + 1, 0, F] :: Nil, Nil) :: + Nil + +fun regs(bits) = + fun ilabel(n, pid_) = [stringConcat("x", stringOfInt(n)), pid_] + fun olabel(n, pid_) = [stringConcat("y", stringOfInt(n)), pid_] + let is_ = ["sto", 0] :: zipWith_lz_nl(ilabel, enumFrom(0), map(x => (7 * x) + 1, enumFromTo(0, bits - 1))) + let os = zipWith_lz_nl(olabel, enumFrom(0), map(x => (7 * x) + 7, enumFromTo(0, bits - 1))) + let sto = PS(0, Inp, 0, Nil, [0, F, false, 0, true, (8 * (bits - 1)) + 5] :: Nil) + let states = sto :: concat(map(x => reg(0, x), map(x => (7 * x) + 1, enumFromTo(0, bits - 1)))) + + [1 + (7 * bits), is_, os, states] + + +fun circuit_simulate(inputs_list, circuit) = map(collect_outputs, simulate(inputs_list, circuit)) + +fun run(num_bits, num_cycles) = + let example = pad_circuit(regs(num_bits)) + let inputs = replicate(num_bits + 1, T) + let cycles = replicate(num_cycles, inputs) + + circuit_simulate(cycles, example) + + +fun testCircsim_nofib(n) = run(8, n) + + + +fun main() = testCircsim_nofib(40).toString() diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/clausify.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/clausify.mls new file mode 100644 index 0000000000..c049c89741 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/clausify.mls @@ -0,0 +1,149 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module clausify with ... + + +abstract class Formula: Sym | Not | Dis | Con | Imp | Eqv + +data + class + Sym(a: Char) extends Formula + Not(a: Formula) extends Formula + Dis(a: Formula, b: Formula) extends Formula + Con(a: Formula, b: Formula) extends Formula + Imp(a: Formula, b: Formula) extends Formula + Eqv(a: Formula, b: Formula) extends Formula + +abstract class StackFrame: Ast | Lex + +data + class + Ast(f: Formula) extends StackFrame + Lex(s: Char) extends StackFrame + +fun charLt(a, b) = a < b +fun charLeq(a, b) = a <= b +fun charGt(a, b) = a > b +fun charGeq(a, b) = a >= b + +fun insert(x, ys) = if ys is + Nil then x :: Nil + y :: ys and + charLt(x, y) then x :: y :: ys + charGt(x, y) then y :: insert(x, ys) + else y :: ys + +fun clauseHelper(p, x) = if p is + Dis(p, q) then clauseHelper(p, clauseHelper(q, x)) + Sym(s) and x is [c, a] then [insert(s, c), a] + Not(Sym(s)) and x is [c, a] then [c, insert(s, a)] + +fun clause(p) = clauseHelper(p, [Nil, Nil]) + +fun conjunct(p) = if p is Con(_, _) then true else false + +fun disin(p) = if p is + Dis(p, Con(q, r)) then Con(disin(Dis(p, q)), disin(Dis(p, r))) + Dis(Con(p, q), r) then Con(disin(Dis(p, r)), disin(Dis(q, r))) + Dis(p, q) then + let dp = disin(p) + let dq = disin(q) + if conjunct(dp) || conjunct(dq) then disin(Dis(dp, dq)) else Dis(dp, dq) + Con(p, q) then Con(disin(p), disin(q)) + else p + +fun elim(p) = if p is + Sym(s) then Sym(s) + Not(p) then Not(elim(p)) + Dis(p, q) then Dis(elim(p), elim(q)) + Con(p, q) then Con(elim(p), elim(q)) + Imp(p, q) then Dis(Not(elim(p)), elim(q)) + Eqv(f, f_) then Con(elim(Imp(f, f_)), elim(Imp(f_, f))) + +fun interleave(xs, ys) = if xs is + x :: xs then x :: interleave(ys, xs) + Nil then Nil + +fun negin(p) = if p is + Not(Not(p)) then negin(p) + Not(Con(p, q)) then Dis(negin(Not(p)), negin(Not(q))) + Not(Dis(p, q)) then Con(negin(Not(p)), negin(Not(q))) + Dis(p, q) then Dis(negin(p), negin(q)) + Con(p, q) then Con(negin(p), negin(q)) + else p + +fun opri(c) = if c + === "(" then 0 + === "=" then 1 + === ">" then 2 + === "|" then 3 + === "&" then 4 + === "~" then 5 + else throw Error(c) + +fun red(s) = if s is + Ast(p) :: Lex("=") :: Ast(q) :: s then Ast(Eqv(q, p)) :: s + Ast(p) :: Lex(">") :: Ast(q) :: s then Ast(Imp(q, p)) :: s + Ast(p) :: Lex("|") :: Ast(q) :: s then Ast(Dis(q, p)) :: s + Ast(p) :: Lex("&") :: Ast(q) :: s then Ast(Con(q, p)) :: s + Ast(p) :: Lex("~") :: s then Ast(Not(p)) :: s + +fun spri(s) = if s is + Ast(x) :: Lex(c) :: s then opri(c) + else 0 + +fun redstar(s) = while_(s => spri(s) != 0, red, s) + +fun spaces(n) = replicate(n, " ") + +fun parseHelper(t, s) = if t is + Nil then redstar(s) + " " :: t then parseHelper(t, s) + "(" :: t then parseHelper(t, Lex("(") :: s) + ")" :: t and redstar(s) is x :: Lex("(") :: ss then parseHelper(t, x :: ss) + c :: t and + charLeq("a", c) && charLeq(c, "z") then parseHelper(t, Ast(Sym(c)) :: s) + spri(s) > opri(c) then parseHelper(c :: t, red(s)) + else parseHelper(t, Lex(c) :: s) + +fun parse(t) = if parseHelper(t, Nil) is Ast(f) :: Nil then f + +fun splitHelper(p, a) = if p is + Con(p, q) then splitHelper(p, splitHelper(q, a)) + else p :: a + +fun split(p) = splitHelper(p, Nil) + +fun tautclause(c_a) = if c_a is [c, a] then + fun lscomp(ls) = if ls is + Nil then Nil + h :: t and + inList(h, a) then h :: lscomp(t) + else lscomp(t) + listNeq(lscomp(c), Nil) + +fun uniclHelper(p, x) = + let cp = clause(p) + if tautclause(cp) then x else insert(cp, x) + +fun unicl(a) = foldr(uniclHelper, Nil, a) + +fun disp(l_r) = if l_r is [l, r] then + interleave(l, spaces(listLen(l))) +: + nofibStringToList("<=") +: + interleave(spaces(listLen(r)), r) +: + nofibStringToList("\n") + +fun clauses(t) = concat of map of + disp + unicl of split of disin of negin of elim of parse of t + +// NOTE: original input "(a = a = a) = (a = a = a) = (a = a = a)" +fun testClausify_nofib(n) = + let xs = replicate(n, nofibStringToList("a = a = a")) + concat(map(clauses, xs)) + +fun main() = nofibListToString(testClausify_nofib(10)) diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/constraints.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/constraints.mls new file mode 100644 index 0000000000..234ed65947 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/constraints.mls @@ -0,0 +1,245 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module constraints with ... + + + +// -- Figure 1. CSPs in Haskell. +data class Assign(varr: Int, value: Int) + +data class CSP(vars: Int, vals: Int, rel: Int) + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun qsort(le, ls, r) = if ls is + Nil then r + x :: Nil then x :: r + x :: xs then qpart(le, x, xs, Nil, Nil, r) + +fun qpart(le, x, ls, rlt, rge, r) = if ls is + Nil then rqsort(le, rlt, x :: rqsort(le, rge, r)) + y :: ys and + le(x, y) then qpart(le, x, ys, rlt, y :: rge, r) + else qpart(le, x, ys, y :: rlt, rge, r) + +fun rqsort(le, ls, r) = if ls is + Nil then r + x :: Nil then x :: r + x :: xs then rqpart(le, x, xs, Nil, Nil, r) + +fun rqpart(le, x, ls, rle, rgt, r) = if ls is + Nil then rqsort(le, rle, x :: qsort(le, rgt, r)) + y :: ys and + le(y, x) then rqpart(le, x, ys, y :: rle, rgt, r) + else rqpart(le, x, ys, rle, y :: rgt, r) +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun level(a) = if a is Assign(v, _) then v + +fun value(a) = if a is Assign(_, v) then v + +fun maxLevel(ls) = if ls is + Nil then 0 + Assign(v, _) :: t then v + +fun complete(csp, s) = if csp is CSP(v, _, _) then maxLevel(s) == v + +fun safe(as1, as2) = if as1 is Assign(i, m) and as2 is Assign(j, n) then not(m == n) and not(abs(i - j) == abs(m - n)) + +fun queens(n) = CSP(n, n, safe) + +// -- Figure 2. Trees in Haskell. +data class Node[out T](lab: T, children: List[Node[T]]) + +fun label(n) = if n is Node(l, _) then l + +fun mapTree(f, n) = if n is Node(l, c) then Node(f(l), map((x => mapTree(f, x)), c)) + +fun foldTree(f, n) = if n is Node(l, c) then f(l, map((x => foldTree(f, x)), c)) + +fun filterTree(p, t) = + fun f1(a, cs) = Node(a, filter(x => p(label(x)), cs)) + foldTree(f1, t) + +fun prune(p, t) = filterTree(x => not(p(x)), t) + +fun leaves(t) = if t is + Node(leaf, Nil) then leaf :: Nil + Node(_, cs) then concat(map(leaves, cs)) + +fun initTree(f, x) = Node(x, map(y => initTree(f, y), f(x))) + +// -- Figure 3. Simple backtracking solver for CSPs. +fun mkTree(csp) = if csp is CSP(vars, vals, rel) then + fun next(ss) = + if maxLevel(ss) < vars then + fun lscomp1(ls) = if ls is + Nil then Nil + j :: t1 then + (Assign(maxLevel(ss) + 1, j) :: ss) :: lscomp1(t1) + lscomp1(enumFromTo(1, vals)) + else + Nil + + initTree(next, Nil) + + +fun earliestInconsistency(csp, aas) = if csp is CSP(vars, vals, rel) and aas is + Nil then None + a :: as_ and filter(x => not(rel(a, x)), reverse(as_)) is + Nil then None + b :: _ then Some([level(a), level(b)]) + +fun labelInconsistencies(csp, t) = + fun f2(s) = [s, earliestInconsistency(csp, s)] + + mapTree(f2, t) + + +fun btsolver0(csp) = + filter of + x => complete(csp, x) + leaves of + mapTree of + fst + prune of + x => not(snd(x) === None) + labelInconsistencies(csp, mkTree(csp)) + +// -- Figure 6. Conflict-directed solving of CSPs. +abstract class ConflictSet: Known | Unknown +data class Known(vs: List[Int]) extends ConflictSet +object Unknown extends ConflictSet + +fun knownConflict(c) = if c is + Known(a :: as_) then true + else false + +fun knownSolution(c) = if c is + Known(Nil) then true + else false + +fun checkComplete(csp, s) = if complete(csp, s) then Known(Nil) else Unknown + +fun search(labeler, csp) = + map of + fst + filter of + x => knownSolution(snd(x)) + leaves of prune of + x => knownConflict(snd(x)) + labeler(csp, mkTree(csp)) + +fun bt(csp, t) = + fun f3(s) = [s, (if earliestInconsistency(csp, s) is Some([a, b]) then Known(a :: b :: Nil) else checkComplete(csp, s))] + + mapTree(f3, t) + +// -- Figure 8. Backmarking. + +fun emptyTable(csp) = if csp is CSP(vars, vals, rel) then + fun lscomp1(ls) = if ls is + Nil then Nil + n :: t1 then + fun lscomp2(ls) = if ls is + Nil then Nil + m :: t2 then + Unknown :: lscomp2(t2) + lscomp2(enumFromTo(1, vals)) :: lscomp1(t1) + + Nil :: lscomp1(enumFromTo(1, vars)) + + +fun fillTable(s, csp, tbl) = if s is + Nil then tbl + Assign(var_, val_) :: as_ and csp is CSP(vars, vals, rel) then + fun f4(cs, varval) = if varval is [varr, vall] and + cs === Unknown and not(rel(Assign(var_, val_), Assign(varr, vall))) then Known(var_ :: varr :: Nil) + else cs + + fun lscomp1(ls) = if ls is + Nil then Nil + varrr :: t1 then + fun lscomp2(ls) = if ls is + Nil then Nil + valll :: t2 then [varrr, valll] :: lscomp2(t2) + lscomp2(enumFromTo(1, vals)) :: lscomp1(t1) + + zipWith((x, y) => zipWith(f4, x, y), tbl, lscomp1(enumFromTo(var_ + 1, vars))) + + +fun lookupCache(csp, t) = + fun f5(csp, tp) = if tp is + [Nil, tbl] then [[Nil, Unknown], tbl] + [a :: as_, tbl] then + let tableEntry = atIndex(value(a) - 1, head(tbl)) + let cs = if tableEntry === Unknown then checkComplete(csp, a :: as_) else tableEntry + [[a :: as_, cs], tbl] + + mapTree(x => f5(csp, x), t) + + +fun cacheChecks(csp, tbl, n) = if n is Node(s, cs) then + Node([s, tbl], map(x => cacheChecks(csp, fillTable(s, csp, tail(tbl)), x), cs)) + +fun bm(csp, t) = mapTree(fst, lookupCache(csp, cacheChecks(csp, emptyTable(csp), t))) + +// -- Figure 10. Conflict-directed backjumping. +fun combine(ls, acc) = if ls is + Nil then acc + [s, Known(cs)] :: css and + notElem(maxLevel(s), cs) then cs + else combine(css, union(cs, acc)) + +fun bj_(csp, t) = + fun f7(tp2, chs) = if tp2 is + [a, Known(cs)] then Node([a, Known(cs)], chs) + [a, Unknown] and + let cs_ = Known(combine(map(label, chs), Nil)) + knownConflict(cs_) then Node([a, cs_], Nil) + else Node([a, cs_], chs) + + foldTree(f7, t) + + +fun bj(csp, t) = + fun f6(tp2, chs) = if tp2 is + [a, Known(cs)] then Node([a, Known(cs)], chs) + [a, Unknown] then Node([a, Known(combine(map(label, chs), Nil))], chs) + + foldTree(f6, t) + + +fun bjbt(csp, t) = bj(csp, bt(csp, t)) + +fun bjbt_(csp, t) = bj_(csp, bt(csp, t)) + +// -- Figure 11. Forward checking. +fun collect(ls) = if ls is + Nil then Nil + Known(cs) :: css then union(cs, collect(css)) + +fun domainWipeout(csp, t) = if csp is CSP(vars, vals, rel) then + fun f8(tp2) = if tp2 is [[as_, cs], tbl] then + let wipedDomains = + fun lscomp1(ls) = if ls is + Nil then Nil + vs :: t1 and + all(knownConflict, vs) then vs :: lscomp1(t1) + else lscomp1(t1) + lscomp1(tbl) + let cs_ = if null_(wipedDomains) then cs else Known(collect(head(wipedDomains))) + [as_, cs_] + + mapTree(f8, t) + + +fun fc(csp, t) = domainWipeout(csp, lookupCache(csp, cacheChecks(csp, emptyTable(csp), t))) + +fun try_(n, algorithm) = listLen(search(algorithm, queens(n))) + +fun testConstraints_nofib(n) = map(x => try_(n, x), bt :: bm :: bjbt :: bjbt_ :: fc :: Nil) + + +fun main() = testConstraints_nofib(6).toString() \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cryptarithm1.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cryptarithm1.mls new file mode 100644 index 0000000000..d033310a6b --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cryptarithm1.mls @@ -0,0 +1,43 @@ +import "./NofibPrelude.mls" +open NofibPrelude + + +module cryptarithm1 with ... + + + +fun expand(a, b, c, d, e, f) = f + (e*10) + (d*100) + (c*1000) + (b*10000) + (a*100000) + +fun condition(thirywelvn) = if thirywelvn is + t :: h :: i :: r :: y :: w :: e :: l :: v :: n :: Nil then + (expand(t, h, i, r, t, y) + 5 * expand(t, w, e, l, v, e)) == expand(n, i, n, e, t, y) + +fun addj(j, ls) = if ls is + Nil then (j :: Nil) :: Nil + k :: ks then + fun lscomp(p1) = if p1 is + Nil then Nil + h1 :: t1 then (k :: h1) :: lscomp(t1) + + (j :: (k :: ks)) :: lscomp(addj(j, ks)) + +fun permutations(ls) = if ls is + Nil then Nil :: Nil + j :: js then + fun lscomp1(p1) = if p1 is + Nil then Nil + pjs :: t1 then + fun lscomp2(p2) = if p2 is + Nil then lscomp1(t1) + r :: t2 then r :: lscomp2(t2) + lscomp2(addj(j, pjs)) + + lscomp1(permutations(js)) + +fun testCryptarithm_nofib(n) = + map((i => let p0 = take(10, enumFromTo(0, 9 + i)) in filter(condition, permutations(p0))), enumFromTo(1, n)) + + +fun main() = testCryptarithm_nofib(1) + + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cryptarithm2.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cryptarithm2.mls new file mode 100644 index 0000000000..47915e74fa --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cryptarithm2.mls @@ -0,0 +1,112 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module cryptarithm2 with ... + + +object Unit + +fun unlines(ls) = concat of map(x => x +: ("\n" :: Nil), ls) + +fun lookup(k, t) = if t is + Nil then None + [x, v] :: t then if k === x then Some(v) else lookup(k, t) + +fun delete_(xs, e) = deleteBy((x, y) => x === y, e, xs) + +fun listDiff(a, ls) = foldl(delete_, a, ls) + +data class StateT[S, M, A](run) + +fun runStateT(m, s) = if m is StateT(run) then run(s) + +fun bind(m, f) = + StateT of + s => concat of map(case { [a, ss] then runStateT(f(a), ss) }, runStateT(m, s)) + +fun return_(a) = StateT(s => [a, s] :: Nil) + +fun mapM(f, ls) = foldr((a, r) => bind(f(a), x => bind(r, xs => return_(x :: xs))), return_(Nil), ls) + +fun lift(ls) = StateT(s => concat(map(x => [x, s] :: Nil, ls))) + +fun execStateT(m, s) = concat(map(case { [a, s] then s :: Nil }, runStateT(m, s))) + +fun guard(b) = if b then StateT(s => [Unit, s] :: Nil) else StateT(s => Nil) + +fun put(s) = StateT(x => [Unit, s] :: Nil) + +val get = StateT(s => [s, s] :: Nil) +//│ get = StateT([function]) + +data class Digits(i: List[Int], c: List[[Char, Int]]) + +fun digits(d) = if d is Digits(a, b) then a + +fun digitEnv(d) = if d is Digits(a, b) then b + +fun permute(c) = + bind of + get + st => + bind of + let xs = digits(st) in lift(map(x => [x, listDiff(xs, x :: Nil)], xs)) + iis => + if iis is [i, iss] then + bind of + put(Digits(iss, [c, i] :: digitEnv(st))) + _p => return_(i) + +fun select(c) = + bind of + get + st => + if lookup(c, digitEnv(st)) is + Some(r) then return_(r) + None then permute(c) + +fun rest(ls) = if ls is + Nil then Nil + x :: xs then xs + +fun solve(tops, bots, carry) = if bots is + bot :: botss then + bind of + if tops is + Nil then return_(carry) + top :: _ then bind(mapM(select, top), topNS => return_(sum(topNS) + carry)) + topN => bind of + select(bot) + botN => bind of + guard(intMod(topN, 10) === botN) + _s => solve(rest(tops), botss, intDiv(topN, 10)) + Nil and tops is Nil and carry === 0 then return_(Unit) + else StateT(_p => Nil) + +fun puzzle(top, bot) = + let solution = solve(transpose(map(reverse, top)), reverse(bot), 0) + let answer = if execStateT(solution, Digits(enumFromTo(0, 9), Nil)) is a :: _ then a + let env = digitEnv(answer) + let look = c => fromSome(lookup(c, env)) + let expand = ls => foldl((a, b) => a * 10 + look(b), 0, ls) + let topVal = sum(map(xs => expand(xs), top)) + let botVal = expand(bot) + if + listLen(nubBy((x,y) => x === y, concat(top) +: bot)) > 10 then throw Error("error") + topVal != botVal then throw Error("error") + else unlines of map of + case { [c, i] then c :: nofibStringToList(" => ") +: nofibStringToList(stringOfInt(i)) } + env + +fun testCryptarithm2_nofib(n) = + let args = + nofibStringToList("THIRTY") :: + nofibStringToList("TWELVE") :: + nofibStringToList("TWELVE") :: + nofibStringToList("TWELVE") :: + nofibStringToList("TWELVE") :: + append(nofibStringToList("TWELVE"), (if n > 999999 then nofibStringToList("1") else Nil)) :: Nil + puzzle(args, nofibStringToList("NINETY")) + +fun main() = testCryptarithm2_nofib(1).toString() diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cse.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cse.mls new file mode 100644 index 0000000000..8f5acc95b1 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/cse.mls @@ -0,0 +1,146 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module cse with ... + + + +fun retURN(a) = s => [s, a] + +fun bind(m, f) = s => if m(s) is [s_, a] then f(a)(s_) + +fun join(m) = s => if m(s) is [s_, ma] then ma(s_) + +fun mmap(f, m) = s => if m(s) is [s_, a] then [s_, f(a)] + +fun mmapl(f, aas) = if aas is + Nil then retURN(Nil) + a :: as_ then + bind of + f(a) + b => bind of + mmapl(f, as_) + bs => retURN(b :: bs) + +fun mmapr(f, xs) = if xs is + Nil then retURN(Nil) + x :: xs then + bind of + mmapr(f, xs) + ys => bind of + f(x) + y => retURN(y :: ys) + +fun mfoldl(f, a, xs) = if xs is + Nil then retURN(a) + x :: xs then + bind(f(a, x), fax => mfoldl(f, fax, xs)) + +fun mfoldr(f, a, xs) = if xs is + Nil then retURN(a) + x :: xs then + bind(mfoldr(f, a, xs), y => f(x, y)) + +fun mif(c, t, f) = bind(c, cond => if cond then t else f) + +fun startingWith(m, v) = if m(v) is [final, answer] then answer + +fun fetch(s) = [s, s] + +fun fetchWith(f) = s => [s, f(s)] + +fun update(f) = s => [f(s), s] + +fun set_(s_) = s => [s_, s] + +val incr = update(x => x + 1) +//│ incr = [function] + +data class Node[T](a: T, b: List[Node[T]]) + +fun labelTree(t) = + fun label(t) = if t is Node(x, xs) then + bind of + incr + n => bind of + mmapl(label, xs) + ts => retURN(Node([n, x], ts)) + startingWith(label(t), 0) + +fun ltGraph(t) = + fun labelOf(t) = if t is Node([n, x], xs) then n + if t is Node([n, x], xs) then + [n, x, map(labelOf, xs)] :: concat(map(ltGraph, xs)) + +fun visited(n) = bind of + fetch + us => if inList(n, us) then retURN(true) else bind(set_(n :: us), _p => retURN(false)) + +fun newlyDefined(x, fx, f, y) = if x === y then fx else f(y) + +fun findCommon(ls) = + fun sim(n_s_cs, r_lg) = if n_s_cs is [n, s, cs] and r_lg is [r, lg] then + let rcs = map(r, cs) + fun lscomp(ls) = if ls is + Nil then Nil + [m, s_, cs_] :: t and + s === s_ and listEq(cs_, rcs) then m :: lscomp(t) + else lscomp(t) + let ms = lscomp(lg) + if null_(ms) + then [r, [n, s, rcs] :: lg] + else [x => newlyDefined(n, head(ms), r, x), lg] + if foldr(sim, [x => x, Nil], ls) is [a, b] then b else throw Error(ls.toString()) + +fun cse(t) = findCommon(ltGraph(labelTree(t))) + +fun plus_(x, y) = Node("+", x :: y :: Nil) + +fun mult_(x, y) = Node("*", x :: y :: Nil) + +fun prod(xs) = Node("X", xs) + +val zerO = Node("0", Nil) +//│ zerO = Node("0", []) + +val a = Node("a", Nil) +//│ a = Node("a", []) + +val b = Node("b", Nil) +//│ b = Node("b", []) + +val c = Node("c", Nil) +//│ c = Node("c", []) + +val d = Node("d", Nil) +//│ d = Node("d", []) + +val example0 = a +//│ example0 = Node("a", []) + +val example1 = plus_(a, a) +//│ example1 = Node("+", [Node("a", []),Node("a", [])]) + +val example2 = plus_(mult_(a, b), mult_(a, b)) +//│ example2 = Node("+", [Node("*", [Node("a", []),Node("b", [])]),Node("*", [Node("a", []),Node("b", [])])]) + +val example3 = plus_(mult_(plus_(a, b), c), plus_(a, b)) +//│ example3 = Node("+", [Node("*", [Node("+", [Node("a", []),Node("b", [])]),Node("c", [])]),Node("+", [Node("a", []),Node("b", [])])]) + +val example4 = prod(scanl(plus_, zerO, a :: b :: c :: d :: Nil)) +//│ example4 = Node("X", [Node("0", []),Node("+", [Node("0", []),Node("a", [])]),Node("+", [Node("+", [Node("0", []),Node("a", [])]),Node("b", [])]),Node("+", [Node("+", [Node("+", [Node("0", []),Node("a", [])]),Node("b", [])]),Node("c", [])]),Node("+", [Node("+", [Node("+", [Node("+", [Node("0", []),Node("a", [])]),Node("b", [])]),Node("c", [])]),Node("d", [])])]) + +val example5 = prod(scanr(plus_, zerO, a :: b :: c :: d :: Nil)) +//│ example5 = Node("X", [Node("+", [Node("a", []),Node("+", [Node("b", []),Node("+", [Node("c", []),Node("+", [Node("d", []),Node("0", [])])])])]),Node("+", [Node("b", []),Node("+", [Node("c", []),Node("+", [Node("d", []),Node("0", [])])])]),Node("+", [Node("c", []),Node("+", [Node("d", []),Node("0", [])])]),Node("+", [Node("d", []),Node("0", [])]),Node("0", [])]) + +fun testCse_nofib(n) = map( + i => map( + cse, + take(intMod(i, 6), example0 :: example1 :: example2 :: example3 :: example4 :: example5 :: Nil) + ), + enumFromTo(1, n) +) + +fun main() = testCse_nofib(6).toString() \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/eliza.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/eliza.mls new file mode 100644 index 0000000000..3d2106539b --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/eliza.mls @@ -0,0 +1,351 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module eliza with ... + + + +fun toUpper(c) = c.toUpperCase() + +fun lz_map(f, ls) = lazy of () => + if ls is + Nil then LzNil + h :: t then LzCons(f(h), lz_map(f, t)) + +fun append_lz(xs, ys) = if xs is + Nil then force(ys) + h :: t then lazy of () => LzCons(h, append_lz(t, ys)) + +fun cycle(xs) = append_lz(xs, lazy of () => cycle(xs)) + +fun isSpace(c) = c === " " + +fun words(s) = if leaveWhile(eliza.isSpace, s) is + Nil then Nil + h2h :: t2t and + break_(eliza.isSpace, h2h :: t2t) is [w, s_] then w :: eliza.words(s_) + +fun unwords(ws) = + fun go(ws) = if ws is + Nil then Nil + w :: ws then " " :: w +: go(ws) + if ws is + Nil then Nil + w :: ws then w +: go(ws) + +fun null_lz(ls) = if force(ls) is + LzNil then true + LzCons(h, t) then false + +fun trim(ls) = + fun cons(x, xs) = if inList(x, nofibStringToList(" .!?,")) and null_(xs) then Nil else x :: xs + foldr(cons, Nil, leaveWhile(x => inList(x, nofibStringToList(" .!?,")), ls)) + +fun repeated(kt_rp) = if kt_rp is [kt, r :: rp] then [r, [kt, rp]] + +fun newKeyTab(kt_, kt_rp) = if kt_rp is [kt, rp] then [kt_, rp] + +fun keyTabOf(kt_rp) = if kt_rp is [kt, rp] then kt + +fun makeResponse(cs, us) = if cs is + "?" :: cs_ then cs_ +: nofibStringToList(" ") +: us +: nofibStringToList("?") + "." :: cs_ then cs_ +: nofibStringToList(" ") +: us +: nofibStringToList(".") + else cs + +val repeatMsgs = Predef.id of + nofibStringToList("Why did you repeat yourself?") :: + nofibStringToList("Do you expect a different answer by repeating yourself?") :: + nofibStringToList("Come, come, elucidate your thoughts.") :: + nofibStringToList("Please don't repeat yourself!") :: + Nil +//│ repeatMsgs = [["W","h","y"," ","d","i","d"," ","y","o","u"," ","r","e","p","e","a","t"," ","y","o","u","r","s","e","l","f","?"],["D","o"," ","y","o","u"," ","e","x","p","e","c","t"," ","a"," ","d","i","f","f","e","r","e","n","t"," ","a","n","s","w","e","r"," ","b","y"," ","r","e","p","e","a","t","i","n","g"," ","y","o","u","r","s","e","l","f","?"],["C","o","m","e",","," ","c","o","m","e",","," ","e","l","u","c","i","d","a","t","e"," ","y","o","u","r"," ","t","h","o","u","g","h","t","s","."],["P","l","e","a","s","e"," ","d","o","n","'","t"," ","r","e","p","e","a","t"," ","y","o","u","r","s","e","l","f","!"]] + +val respMsgs = + let canYou = nofibStringToList("?Don_t you believe that I can") :: + nofibStringToList("?Perhaps you would like to be able to") :: + nofibStringToList("?You want me to be able to") :: + Nil + let canI = nofibStringToList("?Perhaps you don_t want to") :: + nofibStringToList("?Do you want to be able to") :: + Nil + let youAre = nofibStringToList("?What makes you think I am") :: + nofibStringToList("?Does it please you to believe I am") :: + nofibStringToList("?Perhaps you would like to be") :: + nofibStringToList("?Do you sometimes wish you were") :: + Nil + let iDont = nofibStringToList("?Don_t you really") :: + nofibStringToList("?Why don_t you") :: + nofibStringToList("?Do you wish to be able to") :: + nofibStringToList("Does that trouble you?") :: + Nil + let iFeel = nofibStringToList("Tell me more about such feelings.") :: + nofibStringToList("?Do you often feel") :: + nofibStringToList("?Do you enjoy feeling") :: + Nil + let whyDont = nofibStringToList("?Do you really believe I don't") :: + nofibStringToList(".Perhaps in good time I will") :: + nofibStringToList("?Do you want me to") :: + Nil + let whyCant = nofibStringToList("?Do you think you should be able to") :: + nofibStringToList("?Why can't you") :: + Nil + let areYou = nofibStringToList("?Why are you interested in whether or not I am") :: + nofibStringToList("?Would you prefer if I were not") :: + nofibStringToList("?Perhaps in your fantasies I am") :: + Nil + let iCant = nofibStringToList("?How do you know you can't") :: + nofibStringToList("Have you tried?") :: + nofibStringToList("?Perhaps you can now") :: + Nil + let iAm = nofibStringToList("?Did you come to me because you are") :: + nofibStringToList("?How long have you been") :: + nofibStringToList("?Do you believe it is normal to be") :: + nofibStringToList("?Do you enjoy being") :: + Nil + let you = nofibStringToList("We were discussing you --not me.") :: + nofibStringToList("?Oh,") :: + nofibStringToList("You're not really talking about me, are you?") :: + Nil + let yes = nofibStringToList("You seem quite positive.") :: + nofibStringToList("Are you Sure?") :: + nofibStringToList("I see.") :: + nofibStringToList("I understand.") :: + Nil + let no = nofibStringToList("Are you saying no just to be negative?") :: + nofibStringToList("You are being a bit negative.") :: + nofibStringToList("Why not?") :: + nofibStringToList("Are you sure?") :: + nofibStringToList("Why no?") :: + Nil + let computer = nofibStringToList("Do computers worry you?") :: + nofibStringToList("Are you talking about me in particular?") :: + nofibStringToList("Are you frightened by machines?") :: + nofibStringToList("Why do you mention computers?") :: + nofibStringToList("What do you think machines have to do with your problems?") :: + nofibStringToList("Don't you think computers can help people?") :: + nofibStringToList("What is it about machines that worries you?") :: + Nil + let iWant = nofibStringToList("?Why do you want") :: + nofibStringToList("?What would it mean to you if you got") :: + nofibStringToList("?Suppose you got") :: + nofibStringToList("?What if you never got") :: + nofibStringToList(".I sometimes also want") :: + Nil + let question = nofibStringToList("Why do you ask?") :: + nofibStringToList("Does that question interest you?") :: + nofibStringToList("What answer would please you the most?") :: + nofibStringToList("What do you think?") :: + nofibStringToList("Are such questions on your mind often?") :: + nofibStringToList("What is it that you really want to know?") :: + nofibStringToList("Have you asked anyone else?") :: + nofibStringToList("Have you asked such questions before?") :: + nofibStringToList("What else comes to mind when you ask that?") :: + Nil + let name = nofibStringToList("Names don't interest me.") :: + nofibStringToList("I don't care about names --please go on.") :: + Nil + let because = nofibStringToList("Is that the real reason?") :: + nofibStringToList("Don't any other reasons come to mind?") :: + nofibStringToList("Does that reason explain anything else?") :: + nofibStringToList("What other reasons might there be?") :: + Nil + let sorry = nofibStringToList("Please don't apologise!") :: + nofibStringToList("Apologies are not necessary.") :: + nofibStringToList("What feelings do you have when you apologise?") :: + nofibStringToList("Don't be so defensive!") :: + Nil + let dream = nofibStringToList("What does that dream suggest to you?") :: + nofibStringToList("Do you dream often?") :: + nofibStringToList("What persons appear in your dreams?") :: + nofibStringToList("Are you disturbed by your dreams?") :: + Nil + let hello = nofibStringToList("How do you...please state your problem.") :: + Nil + let maybe = nofibStringToList("You don't seem quite certain.") :: + nofibStringToList("Why the uncertain tone?") :: + nofibStringToList("Can't you be more positive?") :: + nofibStringToList("You aren't sure?") :: + nofibStringToList("Don't you know?") :: + Nil + let your = nofibStringToList("?Why are you concerned about my") :: + nofibStringToList("?What about your own") :: + Nil + let always = nofibStringToList("Can you think of a specific example?") :: + nofibStringToList("When?") :: + nofibStringToList("What are you thinking of?") :: + nofibStringToList("Really, always?") :: + Nil + let think = nofibStringToList("Do you really think so?") :: + nofibStringToList("?But you are not sure you") :: + nofibStringToList("?Do you doubt you") :: + Nil + let alike = nofibStringToList("In what way?") :: + nofibStringToList("What resemblence do you see?") :: + nofibStringToList("What does the similarity suggest to you?") :: + nofibStringToList("What other connections do you see?") :: + nofibStringToList("Cound there really be some connection?") :: + nofibStringToList("How?") :: + Nil + let friend = nofibStringToList("Why do you bring up the topic of friends?") :: + nofibStringToList("Do your friends worry you?") :: + nofibStringToList("Do your friends pick on you?") :: + nofibStringToList("Are you sure you have any friends?") :: + nofibStringToList("Do you impose on your friends?") :: + nofibStringToList("Perhaps your love for friends worries you.") :: + Nil + let nokeyMsgs = nofibStringToList("I'm not sure I understand you fully.") :: + nofibStringToList("What does that suggest to you?") :: + nofibStringToList("I see.") :: + nofibStringToList("Can you elaborate on that?") :: + nofibStringToList("Say, do you have any psychological problems?") :: + Nil + Predef.id of + [nofibStringToList("CAN YOU"), canYou] :: + [nofibStringToList("CAN I"), canI] :: + [nofibStringToList("YOU ARE"), youAre] :: + [nofibStringToList("YOU'RE"), youAre] :: + [nofibStringToList("I DON'T"), iDont] :: + [nofibStringToList("I FEEL"), iFeel] :: + [nofibStringToList("WHY DON'T YOU"), whyDont] :: + [nofibStringToList("WHY CAN'T I"), whyCant] :: + [nofibStringToList("ARE YOU"), areYou] :: + [nofibStringToList("I CAN'T"), iCant] :: + [nofibStringToList("I AM"), iAm] :: + [nofibStringToList("I'M"), iAm] :: + [nofibStringToList("YOU"), you] :: + [nofibStringToList("YES"), yes] :: + [nofibStringToList("NO"), no] :: + [nofibStringToList("COMPUTER"), computer] :: + [nofibStringToList("COMPUTERS"), computer] :: + [nofibStringToList("I WANT"), iWant] :: + [nofibStringToList("WHAT"), question] :: + [nofibStringToList("HOW"), question] :: + [nofibStringToList("WHO"), question] :: + [nofibStringToList("WHERE"), question] :: + [nofibStringToList("WHEN"), question] :: + [nofibStringToList("NAME"), name] :: + [nofibStringToList("WHY"), question] :: + [nofibStringToList("CAUSE"), because] :: + [nofibStringToList("BECAUSE"), because] :: + [nofibStringToList("DREAM"), dream] :: + [nofibStringToList("SORRY"), sorry] :: + [nofibStringToList("HI"), hello] :: + [nofibStringToList("DREAMS"), dream] :: + [nofibStringToList("MAYBE"), maybe] :: + [nofibStringToList("HELLO"), hello] :: + [nofibStringToList("ALWAYS"), always] :: + [nofibStringToList("YOUR"), your] :: + [nofibStringToList("ALIKE"), alike] :: + [nofibStringToList("THINK"), think] :: + [nofibStringToList("FRIENDS"), friend] :: + [nofibStringToList("FRIEND"), friend] :: + [Nil, nokeyMsgs] :: + Nil +//│ respMsgs = [[["C","A","N"," ","Y","O","U"], [["?","D","o","n","_","t"," ","y","o","u"," ","b","e","l","i","e","v","e"," ","t","h","a","t"," ","I"," ","c","a","n"],["?","P","e","r","h","a","p","s"," ","y","o","u"," ","w","o","u","l","d"," ","l","i","k","e"," ","t","o"," ","b","e"," ","a","b","l","e"," ","t","o"],["?","Y","o","u"," ","w","a","n","t"," ","m","e"," ","t","o"," ","b","e"," ","a","b","l","e"," ","t","o"]]],[["C","A","N"," ","I"], [["?","P","e","r","h","a","p","s"," ","y","o","u"," ","d","o","n","_","t"," ","w","a","n","t"," ","t","o"],["?","D","o"," ","y","o","u"," ","w","a","n","t"," ","t","o"," ","b","e"," ","a","b","l","e"," ","t","o"]]],[["Y","O","U"," ","A","R","E"], [["?","W","h","a","t"," ","m","a","k","e","s"," ","y","o","u"," ","t","h","i","n","k"," ","I"," ","a","m"],["?","D","o","e","s"," ","i","t"," ","p","l","e","a","s","e"," ","y","o","u"," ","t","o"," ","b","e","l","i","e","v","e"," ","I"," ","a","m"],["?","P","e","r","h","a","p","s"," ","y","o","u"," ","w","o","u","l","d"," ","l","i","k","e"," ","t","o"," ","b","e"],["?","D","o"," ","y","o","u"," ","s","o","m","e","t","i","m","e","s"," ","w","i","s","h"," ","y","o","u"," ","w","e","r","e"]]],[["Y","O","U","'","R","E"], [["?","W","h","a","t"," ","m","a","k","e","s"," ","y","o","u"," ","t","h","i","n","k"," ","I"," ","a","m"],["?","D","o","e","s"," ","i","t"," ","p","l","e","a","s","e"," ","y","o","u"," ","t","o"," ","b","e","l","i","e","v","e"," ","I"," ","a","m"],["?","P","e","r","h","a","p","s"," ","y","o","u"," ","w","o","u","l","d"," ","l","i","k","e"," ","t","o"," ","b","e"],["?","D","o"," ","y","o","u"," ","s","o","m","e","t","i","m","e","s"," ","w","i","s","h"," ","y","o","u"," ","w","e","r","e"]]],[["I"," ","D","O","N","'","T"], [["?","D","o","n","_","t"," ","y","o","u"," ","r","e","a","l","l","y"],["?","W","h","y"," ","d","o","n","_","t"," ","y","o","u"],["?","D","o"," ","y","o","u"," ","w","i","s","h"," ","t","o"," ","b","e"," ","a","b","l","e"," ","t","o"],["D","o","e","s"," ","t","h","a","t"," ","t","r","o","u","b","l","e"," ","y","o","u","?"]]],[["I"," ","F","E","E","L"], [["T","e","l","l"," ","m","e"," ","m","o","r","e"," ","a","b","o","u","t"," ","s","u","c","h"," ","f","e","e","l","i","n","g","s","."],["?","D","o"," ","y","o","u"," ","o","f","t","e","n"," ","f","e","e","l"],["?","D","o"," ","y","o","u"," ","e","n","j","o","y"," ","f","e","e","l","i","n","g"]]],[["W","H","Y"," ","D","O","N","'","T"," ","Y","O","U"], [["?","D","o"," ","y","o","u"," ","r","e","a","l","l","y"," ","b","e","l","i","e","v","e"," ","I"," ","d","o","n","'","t"],[".","P","e","r","h","a","p","s"," ","i","n"," ","g","o","o","d"," ","t","i","m","e"," ","I"," ","w","i","l","l"],["?","D","o"," ","y","o","u"," ","w","a","n","t"," ","m","e"," ","t","o"]]],[["W","H","Y"," ","C","A","N","'","T"," ","I"], [["?","D","o"," ","y","o","u"," ","t","h","i","n","k"," ","y","o","u"," ","s","h","o","u","l","d"," ","b","e"," ","a","b","l","e"," ","t","o"],["?","W","h","y"," ","c","a","n","'","t"," ","y","o","u"]]],[["A","R","E"," ","Y","O","U"], [["?","W","h","y"," ","a","r","e"," ","y","o","u"," ","i","n","t","e","r","e","s","t","e","d"," ","i","n"," ","w","h","e","t","h","e","r"," ","o","r"," ","n","o","t"," ","I"," ","a","m"],["?","W","o","u","l","d"," ","y","o","u"," ","p","r","e","f","e","r"," ","i","f"," ","I"," ","w","e","r","e"," ","n","o","t"],["?","P","e","r","h","a","p","s"," ","i","n"," ","y","o","u","r"," ","f","a","n","t","a","s","i","e","s"," ","I"," ","a","m"]]],[["I"," ","C","A","N","'","T"], [["?","H","o","w"," ","d","o"," ","y","o","u"," ","k","n","o","w"," ","y","o","u"," ","c","a","n","'","t"],["H","a","v","e"," ","y","o","u"," ","t","r","i","e","d","?"],["?","P","e","r","h","a","p","s"," ","y","o","u"," ","c","a","n"," ","n","o","w"]]],[["I"," ","A","M"], [["?","D","i","d"," ","y","o","u"," ","c","o","m","e"," ","t","o"," ","m","e"," ","b","e","c","a","u","s","e"," ","y","o","u"," ","a","r","e"],["?","H","o","w"," ","l","o","n","g"," ","h","a","v","e"," ","y","o","u"," ","b","e","e","n"],["?","D","o"," ","y","o","u"," ","b","e","l","i","e","v","e"," ","i","t"," ","i","s"," ","n","o","r","m","a","l"," ","t","o"," ","b","e"],["?","D","o"," ","y","o","u"," ","e","n","j","o","y"," ","b","e","i","n","g"]]],[["I","'","M"], [["?","D","i","d"," ","y","o","u"," ","c","o","m","e"," ","t","o"," ","m","e"," ","b","e","c","a","u","s","e"," ","y","o","u"," ","a","r","e"],["?","H","o","w"," ","l","o","n","g"," ","h","a","v","e"," ","y","o","u"," ","b","e","e","n"],["?","D","o"," ","y","o","u"," ","b","e","l","i","e","v","e"," ","i","t"," ","i","s"," ","n","o","r","m","a","l"," ","t","o"," ","b","e"],["?","D","o"," ","y","o","u"," ","e","n","j","o","y"," ","b","e","i","n","g"]]],[["Y","O","U"], [["W","e"," ","w","e","r","e"," ","d","i","s","c","u","s","s","i","n","g"," ","y","o","u"," ","-","-","n","o","t"," ","m","e","."],["?","O","h",","],["Y","o","u","'","r","e"," ","n","o","t"," ","r","e","a","l","l","y"," ","t","a","l","k","i","n","g"," ","a","b","o","u","t"," ","m","e",","," ","a","r","e"," ","y","o","u","?"]]],[["Y","E","S"], [["Y","o","u"," ","s","e","e","m"," ","q","u","i","t","e"," ","p","o","s","i","t","i","v","e","."],["A","r","e"," ","y","o","u"," ","S","u","r","e","?"],["I"," ","s","e","e","."],["I"," ","u","n","d","e","r","s","t","a","n","d","."]]],[["N","O"], [["A","r","e"," ","y","o","u"," ","s","a","y","i","n","g"," ","n","o"," ","j","u","s","t"," ","t","o"," ","b","e"," ","n","e","g","a","t","i","v","e","?"],["Y","o","u"," ","a","r","e"," ","b","e","i","n","g"," ","a"," ","b","i","t"," ","n","e","g","a","t","i","v","e","."],["W","h","y"," ","n","o","t","?"],["A","r","e"," ","y","o","u"," ","s","u","r","e","?"],["W","h","y"," ","n","o","?"]]],[["C","O","M","P","U","T","E","R"], [["D","o"," ","c","o","m","p","u","t","e","r","s"," ","w","o","r","r","y"," ","y","o","u","?"],["A","r","e"," ","y","o","u"," ","t","a","l","k","i","n","g"," ","a","b","o","u","t"," ","m","e"," ","i","n"," ","p","a","r","t","i","c","u","l","a","r","?"],["A","r","e"," ","y","o","u"," ","f","r","i","g","h","t","e","n","e","d"," ","b","y"," ","m","a","c","h","i","n","e","s","?"],["W","h","y"," ","d","o"," ","y","o","u"," ","m","e","n","t","i","o","n"," ","c","o","m","p","u","t","e","r","s","?"],["W","h","a","t"," ","d","o"," ","y","o","u"," ","t","h","i","n","k"," ","m","a","c","h","i","n","e","s"," ","h","a","v","e"," ","t","o"," ","d","o"," ","w","i","t","h"," ","y","o","u","r"," ","p","r","o","b","l","e","m","s","?"],["D","o","n","'","t"," ","y","o","u"," ","t","h","i","n","k"," ","c","o","m","p","u","t","e","r","s"," ","c","a","n"," ","h","e","l","p"," ","p","e","o","p","l","e","?"],["W","h","a","t"," ","i","s"," ","i","t"," ","a","b","o","u","t"," ","m","a","c","h","i","n","e","s"," ","t","h","a","t"," ","w","o","r","r","i","e","s"," ","y","o","u","?"]]],[["C","O","M","P","U","T","E","R","S"], [["D","o"," ","c","o","m","p","u","t","e","r","s"," ","w","o","r","r","y"," ","y","o","u","?"],["A","r","e"," ","y","o","u"," ","t","a","l","k","i","n","g"," ","a","b","o","u","t"," ","m","e"," ","i","n"," ","p","a","r","t","i","c","u","l","a","r","?"],["A","r","e"," ","y","o","u"," ","f","r","i","g","h","t","e","n","e","d"," ","b","y"," ","m","a","c","h","i","n","e","s","?"],["W","h","y"," ","d","o"," ","y","o","u"," ","m","e","n","t","i","o","n"," ","c","o","m","p","u","t","e","r","s","?"],["W","h","a","t"," ","d","o"," ","y","o","u"," ","t","h","i","n","k"," ","m","a","c","h","i","n","e","s"," ","h","a","v","e"," ","t","o"," ","d","o"," ","w","i","t","h"," ","y","o","u","r"," ","p","r","o","b","l","e","m","s","?"],["D","o","n","'","t"," ","y","o","u"," ","t","h","i","n","k"," ","c","o","m","p","u","t","e","r","s"," ","c","a","n"," ","h","e","l","p"," ","p","e","o","p","l","e","?"],["W","h","a","t"," ","i","s"," ","i","t"," ","a","b","o","u","t"," ","m","a","c","h","i","n","e","s"," ","t","h","a","t"," ","w","o","r","r","i","e","s"," ","y","o","u","?"]]],[["I"," ","W","A","N","T"], [["?","W","h","y"," ","d","o"," ","y","o","u"," ","w","a","n","t"],["?","W","h","a","t"," ","w","o","u","l","d"," ","i","t"," ","m","e","a","n"," ","t","o"," ","y","o","u"," ","i","f"," ","y","o","u"," ","g","o","t"],["?","S","u","p","p","o","s","e"," ","y","o","u"," ","g","o","t"],["?","W","h","a","t"," ","i","f"," ","y","o","u"," ","n","e","v","e","r"," ","g","o","t"],[".","I"," ","s","o","m","e","t","i","m","e","s"," ","a","l","s","o"," ","w","a","n","t"]]],[["W","H","A","T"], [["W","h","y"," ","d","o"," ","y","o","u"," ","a","s","k","?"],["D","o","e","s"," ","t","h","a","t"," ","q","u","e","s","t","i","o","n"," ","i","n","t","e","r","e","s","t"," ","y","o","u","?"],["W","h","a","t"," ","a","n","s","w","e","r"," ","w","o","u","l","d"," ","p","l","e","a","s","e"," ","y","o","u"," ","t","h","e"," ","m","o","s","t","?"],["W","h","a","t"," ","d","o"," ","y","o","u"," ","t","h","i","n","k","?"],["A","r","e"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","o","n"," ","y","o","u","r"," ","m","i","n","d"," ","o","f","t","e","n","?"],["W","h","a","t"," ","i","s"," ","i","t"," ","t","h","a","t"," ","y","o","u"," ","r","e","a","l","l","y"," ","w","a","n","t"," ","t","o"," ","k","n","o","w","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","a","n","y","o","n","e"," ","e","l","s","e","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","b","e","f","o","r","e","?"],["W","h","a","t"," ","e","l","s","e"," ","c","o","m","e","s"," ","t","o"," ","m","i","n","d"," ","w","h","e","n"," ","y","o","u"," ","a","s","k"," ","t","h","a","t","?"]]],[["H","O","W"], [["W","h","y"," ","d","o"," ","y","o","u"," ","a","s","k","?"],["D","o","e","s"," ","t","h","a","t"," ","q","u","e","s","t","i","o","n"," ","i","n","t","e","r","e","s","t"," ","y","o","u","?"],["W","h","a","t"," ","a","n","s","w","e","r"," ","w","o","u","l","d"," ","p","l","e","a","s","e"," ","y","o","u"," ","t","h","e"," ","m","o","s","t","?"],["W","h","a","t"," ","d","o"," ","y","o","u"," ","t","h","i","n","k","?"],["A","r","e"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","o","n"," ","y","o","u","r"," ","m","i","n","d"," ","o","f","t","e","n","?"],["W","h","a","t"," ","i","s"," ","i","t"," ","t","h","a","t"," ","y","o","u"," ","r","e","a","l","l","y"," ","w","a","n","t"," ","t","o"," ","k","n","o","w","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","a","n","y","o","n","e"," ","e","l","s","e","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","b","e","f","o","r","e","?"],["W","h","a","t"," ","e","l","s","e"," ","c","o","m","e","s"," ","t","o"," ","m","i","n","d"," ","w","h","e","n"," ","y","o","u"," ","a","s","k"," ","t","h","a","t","?"]]],[["W","H","O"], [["W","h","y"," ","d","o"," ","y","o","u"," ","a","s","k","?"],["D","o","e","s"," ","t","h","a","t"," ","q","u","e","s","t","i","o","n"," ","i","n","t","e","r","e","s","t"," ","y","o","u","?"],["W","h","a","t"," ","a","n","s","w","e","r"," ","w","o","u","l","d"," ","p","l","e","a","s","e"," ","y","o","u"," ","t","h","e"," ","m","o","s","t","?"],["W","h","a","t"," ","d","o"," ","y","o","u"," ","t","h","i","n","k","?"],["A","r","e"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","o","n"," ","y","o","u","r"," ","m","i","n","d"," ","o","f","t","e","n","?"],["W","h","a","t"," ","i","s"," ","i","t"," ","t","h","a","t"," ","y","o","u"," ","r","e","a","l","l","y"," ","w","a","n","t"," ","t","o"," ","k","n","o","w","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","a","n","y","o","n","e"," ","e","l","s","e","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","b","e","f","o","r","e","?"],["W","h","a","t"," ","e","l","s","e"," ","c","o","m","e","s"," ","t","o"," ","m","i","n","d"," ","w","h","e","n"," ","y","o","u"," ","a","s","k"," ","t","h","a","t","?"]]],[["W","H","E","R","E"], [["W","h","y"," ","d","o"," ","y","o","u"," ","a","s","k","?"],["D","o","e","s"," ","t","h","a","t"," ","q","u","e","s","t","i","o","n"," ","i","n","t","e","r","e","s","t"," ","y","o","u","?"],["W","h","a","t"," ","a","n","s","w","e","r"," ","w","o","u","l","d"," ","p","l","e","a","s","e"," ","y","o","u"," ","t","h","e"," ","m","o","s","t","?"],["W","h","a","t"," ","d","o"," ","y","o","u"," ","t","h","i","n","k","?"],["A","r","e"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","o","n"," ","y","o","u","r"," ","m","i","n","d"," ","o","f","t","e","n","?"],["W","h","a","t"," ","i","s"," ","i","t"," ","t","h","a","t"," ","y","o","u"," ","r","e","a","l","l","y"," ","w","a","n","t"," ","t","o"," ","k","n","o","w","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","a","n","y","o","n","e"," ","e","l","s","e","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","b","e","f","o","r","e","?"],["W","h","a","t"," ","e","l","s","e"," ","c","o","m","e","s"," ","t","o"," ","m","i","n","d"," ","w","h","e","n"," ","y","o","u"," ","a","s","k"," ","t","h","a","t","?"]]],[["W","H","E","N"], [["W","h","y"," ","d","o"," ","y","o","u"," ","a","s","k","?"],["D","o","e","s"," ","t","h","a","t"," ","q","u","e","s","t","i","o","n"," ","i","n","t","e","r","e","s","t"," ","y","o","u","?"],["W","h","a","t"," ","a","n","s","w","e","r"," ","w","o","u","l","d"," ","p","l","e","a","s","e"," ","y","o","u"," ","t","h","e"," ","m","o","s","t","?"],["W","h","a","t"," ","d","o"," ","y","o","u"," ","t","h","i","n","k","?"],["A","r","e"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","o","n"," ","y","o","u","r"," ","m","i","n","d"," ","o","f","t","e","n","?"],["W","h","a","t"," ","i","s"," ","i","t"," ","t","h","a","t"," ","y","o","u"," ","r","e","a","l","l","y"," ","w","a","n","t"," ","t","o"," ","k","n","o","w","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","a","n","y","o","n","e"," ","e","l","s","e","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","b","e","f","o","r","e","?"],["W","h","a","t"," ","e","l","s","e"," ","c","o","m","e","s"," ","t","o"," ","m","i","n","d"," ","w","h","e","n"," ","y","o","u"," ","a","s","k"," ","t","h","a","t","?"]]],[["N","A","M","E"], [["N","a","m","e","s"," ","d","o","n","'","t"," ","i","n","t","e","r","e","s","t"," ","m","e","."],["I"," ","d","o","n","'","t"," ","c","a","r","e"," ","a","b","o","u","t"," ","n","a","m","e","s"," ","-","-","p","l","e","a","s","e"," ","g","o"," ","o","n","."]]],[["W","H","Y"], [["W","h","y"," ","d","o"," ","y","o","u"," ","a","s","k","?"],["D","o","e","s"," ","t","h","a","t"," ","q","u","e","s","t","i","o","n"," ","i","n","t","e","r","e","s","t"," ","y","o","u","?"],["W","h","a","t"," ","a","n","s","w","e","r"," ","w","o","u","l","d"," ","p","l","e","a","s","e"," ","y","o","u"," ","t","h","e"," ","m","o","s","t","?"],["W","h","a","t"," ","d","o"," ","y","o","u"," ","t","h","i","n","k","?"],["A","r","e"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","o","n"," ","y","o","u","r"," ","m","i","n","d"," ","o","f","t","e","n","?"],["W","h","a","t"," ","i","s"," ","i","t"," ","t","h","a","t"," ","y","o","u"," ","r","e","a","l","l","y"," ","w","a","n","t"," ","t","o"," ","k","n","o","w","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","a","n","y","o","n","e"," ","e","l","s","e","?"],["H","a","v","e"," ","y","o","u"," ","a","s","k","e","d"," ","s","u","c","h"," ","q","u","e","s","t","i","o","n","s"," ","b","e","f","o","r","e","?"],["W","h","a","t"," ","e","l","s","e"," ","c","o","m","e","s"," ","t","o"," ","m","i","n","d"," ","w","h","e","n"," ","y","o","u"," ","a","s","k"," ","t","h","a","t","?"]]],[["C","A","U","S","E"], [["I","s"," ","t","h","a","t"," ","t","h","e"," ","r","e","a","l"," ","r","e","a","s","o","n","?"],["D","o","n","'","t"," ","a","n","y"," ","o","t","h","e","r"," ","r","e","a","s","o","n","s"," ","c","o","m","e"," ","t","o"," ","m","i","n","d","?"],["D","o","e","s"," ","t","h","a","t"," ","r","e","a","s","o","n"," ","e","x","p","l","a","i","n"," ","a","n","y","t","h","i","n","g"," ","e","l","s","e","?"],["W","h","a","t"," ","o","t","h","e","r"," ","r","e","a","s","o","n","s"," ","m","i","g","h","t"," ","t","h","e","r","e"," ","b","e","?"]]],[["B","E","C","A","U","S","E"], [["I","s"," ","t","h","a","t"," ","t","h","e"," ","r","e","a","l"," ","r","e","a","s","o","n","?"],["D","o","n","'","t"," ","a","n","y"," ","o","t","h","e","r"," ","r","e","a","s","o","n","s"," ","c","o","m","e"," ","t","o"," ","m","i","n","d","?"],["D","o","e","s"," ","t","h","a","t"," ","r","e","a","s","o","n"," ","e","x","p","l","a","i","n"," ","a","n","y","t","h","i","n","g"," ","e","l","s","e","?"],["W","h","a","t"," ","o","t","h","e","r"," ","r","e","a","s","o","n","s"," ","m","i","g","h","t"," ","t","h","e","r","e"," ","b","e","?"]]],[["D","R","E","A","M"], [["W","h","a","t"," ","d","o","e","s"," ","t","h","a","t"," ","d","r","e","a","m"," ","s","u","g","g","e","s","t"," ","t","o"," ","y","o","u","?"],["D","o"," ","y","o","u"," ","d","r","e","a","m"," ","o","f","t","e","n","?"],["W","h","a","t"," ","p","e","r","s","o","n","s"," ","a","p","p","e","a","r"," ","i","n"," ","y","o","u","r"," ","d","r","e","a","m","s","?"],["A","r","e"," ","y","o","u"," ","d","i","s","t","u","r","b","e","d"," ","b","y"," ","y","o","u","r"," ","d","r","e","a","m","s","?"]]],[["S","O","R","R","Y"], [["P","l","e","a","s","e"," ","d","o","n","'","t"," ","a","p","o","l","o","g","i","s","e","!"],["A","p","o","l","o","g","i","e","s"," ","a","r","e"," ","n","o","t"," ","n","e","c","e","s","s","a","r","y","."],["W","h","a","t"," ","f","e","e","l","i","n","g","s"," ","d","o"," ","y","o","u"," ","h","a","v","e"," ","w","h","e","n"," ","y","o","u"," ","a","p","o","l","o","g","i","s","e","?"],["D","o","n","'","t"," ","b","e"," ","s","o"," ","d","e","f","e","n","s","i","v","e","!"]]],[["H","I"], [["H","o","w"," ","d","o"," ","y","o","u",".",".",".","p","l","e","a","s","e"," ","s","t","a","t","e"," ","y","o","u","r"," ","p","r","o","b","l","e","m","."]]],[["D","R","E","A","M","S"], [["W","h","a","t"," ","d","o","e","s"," ","t","h","a","t"," ","d","r","e","a","m"," ","s","u","g","g","e","s","t"," ","t","o"," ","y","o","u","?"],["D","o"," ","y","o","u"," ","d","r","e","a","m"," ","o","f","t","e","n","?"],["W","h","a","t"," ","p","e","r","s","o","n","s"," ","a","p","p","e","a","r"," ","i","n"," ","y","o","u","r"," ","d","r","e","a","m","s","?"],["A","r","e"," ","y","o","u"," ","d","i","s","t","u","r","b","e","d"," ","b","y"," ","y","o","u","r"," ","d","r","e","a","m","s","?"]]],[["M","A","Y","B","E"], [["Y","o","u"," ","d","o","n","'","t"," ","s","e","e","m"," ","q","u","i","t","e"," ","c","e","r","t","a","i","n","."],["W","h","y"," ","t","h","e"," ","u","n","c","e","r","t","a","i","n"," ","t","o","n","e","?"],["C","a","n","'","t"," ","y","o","u"," ","b","e"," ","m","o","r","e"," ","p","o","s","i","t","i","v","e","?"],["Y","o","u"," ","a","r","e","n","'","t"," ","s","u","r","e","?"],["D","o","n","'","t"," ","y","o","u"," ","k","n","o","w","?"]]],[["H","E","L","L","O"], [["H","o","w"," ","d","o"," ","y","o","u",".",".",".","p","l","e","a","s","e"," ","s","t","a","t","e"," ","y","o","u","r"," ","p","r","o","b","l","e","m","."]]],[["A","L","W","A","Y","S"], [["C","a","n"," ","y","o","u"," ","t","h","i","n","k"," ","o","f"," ","a"," ","s","p","e","c","i","f","i","c"," ","e","x","a","m","p","l","e","?"],["W","h","e","n","?"],["W","h","a","t"," ","a","r","e"," ","y","o","u"," ","t","h","i","n","k","i","n","g"," ","o","f","?"],["R","e","a","l","l","y",","," ","a","l","w","a","y","s","?"]]],[["Y","O","U","R"], [["?","W","h","y"," ","a","r","e"," ","y","o","u"," ","c","o","n","c","e","r","n","e","d"," ","a","b","o","u","t"," ","m","y"],["?","W","h","a","t"," ","a","b","o","u","t"," ","y","o","u","r"," ","o","w","n"]]],[["A","L","I","K","E"], [["I","n"," ","w","h","a","t"," ","w","a","y","?"],["W","h","a","t"," ","r","e","s","e","m","b","l","e","n","c","e"," ","d","o"," ","y","o","u"," ","s","e","e","?"],["W","h","a","t"," ","d","o","e","s"," ","t","h","e"," ","s","i","m","i","l","a","r","i","t","y"," ","s","u","g","g","e","s","t"," ","t","o"," ","y","o","u","?"],["W","h","a","t"," ","o","t","h","e","r"," ","c","o","n","n","e","c","t","i","o","n","s"," ","d","o"," ","y","o","u"," ","s","e","e","?"],["C","o","u","n","d"," ","t","h","e","r","e"," ","r","e","a","l","l","y"," ","b","e"," ","s","o","m","e"," ","c","o","n","n","e","c","t","i","o","n","?"],["H","o","w","?"]]],[["T","H","I","N","K"], [["D","o"," ","y","o","u"," ","r","e","a","l","l","y"," ","t","h","i","n","k"," ","s","o","?"],["?","B","u","t"," ","y","o","u"," ","a","r","e"," ","n","o","t"," ","s","u","r","e"," ","y","o","u"],["?","D","o"," ","y","o","u"," ","d","o","u","b","t"," ","y","o","u"]]],[["F","R","I","E","N","D","S"], [["W","h","y"," ","d","o"," ","y","o","u"," ","b","r","i","n","g"," ","u","p"," ","t","h","e"," ","t","o","p","i","c"," ","o","f"," ","f","r","i","e","n","d","s","?"],["D","o"," ","y","o","u","r"," ","f","r","i","e","n","d","s"," ","w","o","r","r","y"," ","y","o","u","?"],["D","o"," ","y","o","u","r"," ","f","r","i","e","n","d","s"," ","p","i","c","k"," ","o","n"," ","y","o","u","?"],["A","r","e"," ","y","o","u"," ","s","u","r","e"," ","y","o","u"," ","h","a","v","e"," ","a","n","y"," ","f","r","i","e","n","d","s","?"],["D","o"," ","y","o","u"," ","i","m","p","o","s","e"," ","o","n"," ","y","o","u","r"," ","f","r","i","e","n","d","s","?"],["P","e","r","h","a","p","s"," ","y","o","u","r"," ","l","o","v","e"," ","f","o","r"," ","f","r","i","e","n","d","s"," ","w","o","r","r","i","e","s"," ","y","o","u","."]]],[["F","R","I","E","N","D"], [["W","h","y"," ","d","o"," ","y","o","u"," ","b","r","i","n","g"," ","u","p"," ","t","h","e"," ","t","o","p","i","c"," ","o","f"," ","f","r","i","e","n","d","s","?"],["D","o"," ","y","o","u","r"," ","f","r","i","e","n","d","s"," ","w","o","r","r","y"," ","y","o","u","?"],["D","o"," ","y","o","u","r"," ","f","r","i","e","n","d","s"," ","p","i","c","k"," ","o","n"," ","y","o","u","?"],["A","r","e"," ","y","o","u"," ","s","u","r","e"," ","y","o","u"," ","h","a","v","e"," ","a","n","y"," ","f","r","i","e","n","d","s","?"],["D","o"," ","y","o","u"," ","i","m","p","o","s","e"," ","o","n"," ","y","o","u","r"," ","f","r","i","e","n","d","s","?"],["P","e","r","h","a","p","s"," ","y","o","u","r"," ","l","o","v","e"," ","f","o","r"," ","f","r","i","e","n","d","s"," ","w","o","r","r","i","e","s"," ","y","o","u","."]]],[[], [["I","'","m"," ","n","o","t"," ","s","u","r","e"," ","I"," ","u","n","d","e","r","s","t","a","n","d"," ","y","o","u"," ","f","u","l","l","y","."],["W","h","a","t"," ","d","o","e","s"," ","t","h","a","t"," ","s","u","g","g","e","s","t"," ","t","o"," ","y","o","u","?"],["I"," ","s","e","e","."],["C","a","n"," ","y","o","u"," ","e","l","a","b","o","r","a","t","e"," ","o","n"," ","t","h","a","t","?"],["S","a","y",","," ","d","o"," ","y","o","u"," ","h","a","v","e"," ","a","n","y"," ","p","s","y","c","h","o","l","o","g","i","c","a","l"," ","p","r","o","b","l","e","m","s","?"]]]] + +val initial = + fun lscomp(ls) = if ls is + Nil then Nil + [k, rs] :: t then [eliza.words(k), eliza.cycle(rs)] :: lscomp(t) + [lscomp(eliza.respMsgs), eliza.cycle(eliza.repeatMsgs)] +//│ initial = [[[[["C","A","N"],["Y","O","U"]], Lazy([function])],[[["C","A","N"],["I"]], Lazy([function])],[[["Y","O","U"],["A","R","E"]], Lazy([function])],[[["Y","O","U","'","R","E"]], Lazy([function])],[[["I"],["D","O","N","'","T"]], Lazy([function])],[[["I"],["F","E","E","L"]], Lazy([function])],[[["W","H","Y"],["D","O","N","'","T"],["Y","O","U"]], Lazy([function])],[[["W","H","Y"],["C","A","N","'","T"],["I"]], Lazy([function])],[[["A","R","E"],["Y","O","U"]], Lazy([function])],[[["I"],["C","A","N","'","T"]], Lazy([function])],[[["I"],["A","M"]], Lazy([function])],[[["I","'","M"]], Lazy([function])],[[["Y","O","U"]], Lazy([function])],[[["Y","E","S"]], Lazy([function])],[[["N","O"]], Lazy([function])],[[["C","O","M","P","U","T","E","R"]], Lazy([function])],[[["C","O","M","P","U","T","E","R","S"]], Lazy([function])],[[["I"],["W","A","N","T"]], Lazy([function])],[[["W","H","A","T"]], Lazy([function])],[[["H","O","W"]], Lazy([function])],[[["W","H","O"]], Lazy([function])],[[["W","H","E","R","E"]], Lazy([function])],[[["W","H","E","N"]], Lazy([function])],[[["N","A","M","E"]], Lazy([function])],[[["W","H","Y"]], Lazy([function])],[[["C","A","U","S","E"]], Lazy([function])],[[["B","E","C","A","U","S","E"]], Lazy([function])],[[["D","R","E","A","M"]], Lazy([function])],[[["S","O","R","R","Y"]], Lazy([function])],[[["H","I"]], Lazy([function])],[[["D","R","E","A","M","S"]], Lazy([function])],[[["M","A","Y","B","E"]], Lazy([function])],[[["H","E","L","L","O"]], Lazy([function])],[[["A","L","W","A","Y","S"]], Lazy([function])],[[["Y","O","U","R"]], Lazy([function])],[[["A","L","I","K","E"]], Lazy([function])],[[["T","H","I","N","K"]], Lazy([function])],[[["F","R","I","E","N","D","S"]], Lazy([function])],[[["F","R","I","E","N","D"]], Lazy([function])],[[], Lazy([function])]], Lazy([function])] + +fun prefix(xxs, yys) = if xxs is + Nil then true + x :: xs and + force(yys) is + LzNil then false + LzCons(y, ys) then listEq(x, y) && prefix(xs, ys) + +fun tails(xs) = lazy of () => + if xs is + Nil then LzNil + xss then LzCons(xss, tails(tail(xss))) + +fun ucase(ls) = map(toUpper, ls) + +val conjugates = + let oneways = [nofibStringToList("me"), nofibStringToList("you")] :: Nil + let bothways = [nofibStringToList("are"), nofibStringToList("am")] :: + [nofibStringToList("we're"), nofibStringToList("was")] :: + [nofibStringToList("you"), nofibStringToList("I")] :: + [nofibStringToList("your"), nofibStringToList("my")] :: + [nofibStringToList("I've"), nofibStringToList("you've")] :: + [nofibStringToList("I'm"), nofibStringToList("you're")] :: + Nil + fun prepare(ls) = map(case { [w, r] then [ucase(w), r] }, ls) + fun lscomp(ls) = if ls is + Nil then Nil + [x, y] :: t then ([x, y] :: [y, x] :: Nil) :: lscomp(t) + prepare(oneways +: concat(lscomp(bothways))) +//│ conjugates = [[["M","E"], ["y","o","u"]],[["A","R","E"], ["a","m"]],[["A","M"], ["a","r","e"]],[["W","E","'","R","E"], ["w","a","s"]],[["W","A","S"], ["w","e","'","r","e"]],[["Y","O","U"], ["I"]],[["I"], ["y","o","u"]],[["Y","O","U","R"], ["m","y"]],[["M","Y"], ["y","o","u","r"]],[["I","'","V","E"], ["y","o","u","'","v","e"]],[["Y","O","U","'","V","E"], ["I","'","v","e"]],[["I","'","M"], ["y","o","u","'","r","e"]],[["Y","O","U","'","R","E"], ["I","'","m"]]] + +fun conjug(d, w) = + fun maybe(d, xs) = if null_(xs) then d else xs + fun conj(w) = + fun lscomp(ls) = if ls is + Nil then Nil + [w_, m] :: t and + listEq(ucase(w), w_) then m :: lscomp(t) + else lscomp(t) + head(lscomp(conjugates) +: w :: Nil) + fun trailingI(ls) = + fun cons(x, xs) = + if listEq(x, nofibStringToList("I")) && null_(xs) + then nofibStringToList("me") :: Nil + else x :: xs + foldr(cons, Nil, ls) + unwords(trailingI(map(conj, maybe(d, w)))) + +fun replies(key, l) = + map_lz of + x => conjug(l, leave(listLen(key), x)) + filter_lz of + ls => prefix(key, lz_map(ucase, ls)) + tails(l) + +fun answer(st, l) = + fun cons(e, r_es) = if r_es is [r, es] then [r, e :: es] + fun ans(e_es, l) = if e_es is + [key, a_as] :: es and force(a_as) is LzCons(a, as_) then + let rs = replies(key, l) + if null_lz(rs) + then cons([key, a_as], ans(es, l)) + else [makeResponse(a, head_lz(rs)), [key, as_] :: es] + if ans(keyTabOf(st), l) is [response, kt] then [response, newKeyTab(kt, st)] + +fun session(rs, prev, ls) = if ls is + Nil then Nil + l :: ls and + (if listEqBy(listEq, prev, l) then repeated(rs) else answer(rs, l)) is [response, rs_] then + response +: nofibStringToList("\n\n") +: session(rs_, l, ls) + +fun testEliza_nofib(n) = + let input = Predef.id of + nofibStringToList("Are we alone?") :: + nofibStringToList("That the Roswell event was actually an alien encounter. Do you agreed?") :: + nofibStringToList("But why not talk about you, its more fun.") :: + nofibStringToList("I dont ask, you do") :: + nofibStringToList("do ray me") :: + nofibStringToList("Nop, thats because your a computer") :: + nofibStringToList("you dont") :: + nofibStringToList("Oh, a paranoid computer, ehh?") :: + nofibStringToList("Tell me about *your* mother") :: + nofibStringToList("No, what what was she like?") :: + nofibStringToList("I'm asking questions, not you") :: + nofibStringToList("no") :: + nofibStringToList("yes") :: + nofibStringToList("but I'm not") :: + Nil + map of + i => session of + initial + Nil + filter of + x => not(null_(x)) + map(x => eliza.words(trim(x)), take(intMod(i, 20), input)) + enumFromTo(1, n) + +fun main() = map(x => nofibListToString(x), testEliza_nofib(20)).toString() diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/gcd.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/gcd.mls new file mode 100644 index 0000000000..b3a02cd918 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/gcd.mls @@ -0,0 +1,51 @@ +import "./NofibPrelude.mls" +open NofibPrelude + + + +module gcd with ... + + + +fun g(u1u2u3, v1v2v3) = if u1u2u3 is [u1, u2, u3] and v1v2v3 is [v1, v2, v3] then + if + v3 == 0 then [u3, u1, u2] + else if + quotRem(u3, v3) is [q, r] then + g([v1, v2, v3], [u1 - (q * v1), u2 - (q * v2), r]) + +fun gcdE(x, y) = if + x == 0 then [y, 0, 1] + else g([1, 0, x], [0, 1, y]) + +fun max_(ls) = if ls is + x :: Nil then x + x :: y :: xs then if x < y then max_(y :: xs) else max_(x :: xs) + +fun test(d) = + let ns = enumFromTo(5000, 5000 + d) + + let ms = enumFromTo(10000, 10000 + d) + + fun lscomp1(p1) = if p1 is + Nil then Nil + h1 :: t1 then + fun lscomp2(p2) = if p2 is + Nil then lscomp1(t1) + h2 :: t2 then [h1, h2] :: lscomp2(t2) + lscomp2(ms) + + let tripls = + map(case { [x, y] then [x, y, gcdE(x, y)] }, lscomp1(ns)) + + let rs = map(case { [d1, d2, [gg, u, v]] then abs(gg + u + v) }, tripls) + + max_(rs) + + +fun testGcd_nofib(x) = test(x) + + + +// NOTE: original input 400 +fun main() = testGcd_nofib(40) diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/integer.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/integer.mls new file mode 100644 index 0000000000..ad8d823795 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/integer.mls @@ -0,0 +1,62 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module integer with ... + + + +fun integerbench(op, astart, astep, alim, bstart, bstep, blim) = + fun lscomp1(ls) = if ls is + Nil then Nil + a :: t1 then + fun lscomp2(ls) = if ls is + Nil then lscomp1(t1) + b :: t2 then op(a, b) :: lscomp2(t2) + lscomp2(enumFromThenTo(bstart, bstart + bstep, blim)) + + lscomp1(enumFromThenTo(astart, astart + astep, alim)) + +fun intbench(op, astart, astep, alim, bstart, bstep, blim) = + fun lscomp1(ls) = if ls is + Nil then Nil + a :: t1 then + fun lscomp2(ls) = if ls is + Nil then lscomp1(t1) + b :: t2 then op(a, b) :: lscomp2(t2) + lscomp2(enumFromThenTo(bstart, bstart + bstep, blim)) + + lscomp1(enumFromThenTo(astart, astart + astep, alim)) + +fun runbench(jop, iop, opstr, astart, astep, alim, bstart, bstep, blim) = + intbench(iop, astart, astep, alim, astart, astep, alim); + integerbench(jop, astart, astep, alim, astart, astep, alim) + +fun runalltests(astart, astep, alim, bstart, bstep, blim) = + fun z_add(a, b) = a + b + fun z_sub(a, b) = a - b + fun z_mul(a, b) = a * b + fun z_div(a, b) = intDiv(a, b) + fun z_mod(a, b) = intMod(a, b) + fun z_equal(a, b) = a == b + fun z_lt(a, b) = a < b + fun z_leq(a, b) = a <= b + fun z_gt(a, b) = a > b + fun z_geq(a, b) = a >= b + + runbench((a, b) => z_add(a, b), (a, b) => a + b, "(+)", astart, astep, alim, astart, astep, alim); + runbench((a, b) => z_sub(a, b), (a, b) => a - b, "(-)", astart, astep, alim, astart, astep, alim); + runbench((a, b) => z_mul(a, b), (a, b) => a * b, "(*)", astart, astep, alim, astart, astep, alim); + runbench((a, b) => z_div(a, b), (a, b) => intDiv(a, b), "div", astart, astep, alim, astart, astep, alim); + runbench((a, b) => z_mod(a, b), (a, b) => intMod(a, b), "mod", astart, astep, alim, astart, astep, alim); + runbench((a, b) => z_equal(a, b), (a, b) => a == b, "(==)", astart, astep, alim, astart, astep, alim); + runbench((a, b) => z_lt(a, b), (a, b) => a < b, "(<)", astart, astep, alim, astart, astep, alim); + runbench((a, b) => z_leq(a, b), (a, b) => a <= b, "(<=)", astart, astep, alim, astart, astep, alim); + runbench((a, b) => z_gt(a, b), (a, b) => a > b, "(>)", astart, astep, alim, astart, astep, alim); + runbench((a, b) => z_geq(a, b), (a, b) => a >= b, "(>=)", astart, astep, alim, astart, astep, alim) + +fun testInteger_nofib(n) = runalltests(-2100000000, n, 2100000000, -2100000000, n, -2100000000) + + +// NOTE: original input -2100000000 14000001 2100000000 +fun main() = testInteger_nofib(700000001).toString() diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/knights.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/knights.mls new file mode 100644 index 0000000000..149f9c9ddd --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/knights.mls @@ -0,0 +1,280 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module knights with ... + + +fun myIsDigit(c) = + c.codePointAt(0) >= 48 && c.codePointAt(0) <= 57 + +fun intintComp(a_b, c_d) = if a_b is [a, b] and c_d is [c, d] then (a < c) || ((a === c) && (b < d)) + +fun intChessSetComp(a_b, c_d) = if a_b is [a, b] and c_d is [c, d] then a < c + +fun myInit(a_t) = if a_t is + a :: Nil then Nil + a :: t then a :: myInit(t) + +fun myLast(a_t) = + fun go(h, t) = if t is + Nil then h + head :: t then go(head, t) + if a_t is a :: t then go(a, t) + +fun quickSortIntInt(xs) = if xs is + Nil then Nil + x :: xs then + fun lscomp1(ls) = if ls is + Nil then Nil + h :: t and + intintComp(h, x) then h :: lscomp1(t) + else lscomp1(t) + fun lscomp2(ls) = if ls is + Nil then Nil + h :: t and + not(intintComp(h, x)) then h :: lscomp2(t) + else lscomp2(t) + quickSortIntInt(lscomp1(xs)) +: (x :: quickSortIntInt(lscomp2(xs))) + +fun quickSortIntChessSet(xs) = if force(xs) is + LzNil then lazy of () => LzNil + LzCons(x, xs) then + fun lscomp1(ls) = if force(ls) is + LzNil then lazy of () => LzNil + LzCons(h, t) and + intChessSetComp(h, x) then lazy of () => LzCons(h, lscomp1(t)) + else lscomp1(t) + fun lscomp2(ls) = if force(ls) is + LzNil then lazy of () => LzNil + LzCons(h, t) and + not(intChessSetComp(h, x)) then lazy of () => LzCons(h, lscomp2(t)) + else lscomp2(t) + append_lz_lz(quickSortIntChessSet(lscomp1(xs)), lazy of () => LzCons(x, quickSortIntChessSet(lscomp2(xs)))) + +fun sizeQueue(xs) = listLen(xs) + +fun emptyQueue(x) = listEq(x, Nil) + +fun removeBack(xs) = if xs is + x :: Nil then Nil + x :: xs then x :: removeBack(xs) + +fun removeFront(xs) = if xs is + h :: t then t + +fun inquireBack(xs) = if xs is + x :: Nil then x + x :: xs then inquireBack(xs) + +fun inquireFront(h_t) = head(h_t) + +fun addAllBack(list, q) = q +: list + +fun addAllFront(list, q) = list +: q + +fun addBack(x, q) = q +: (x :: Nil) + +fun addFront(x, q) = x :: q + +val createQueue = Nil +//│ createQueue = [] + +data class Board(a: Int, b: Int, c: Lazy[[Int, Int]], d: List[[Int, Int]]) + +fun createBoard(x, t) = Board(x, 1, (lazy of (() => t)), t :: Nil) + +fun sizeBoard(b) = if b is Board(a, _, _, _) then a + +fun noPieces(b) = if b is Board(_, n, _, _) then n + +fun addPiece(t, b) = if b is Board(s, n, f, ts) then Board(s, n + 1, f, t :: ts) + +fun deleteFirst(b) = if b is Board(s, n, f, ts) then + let ts_ = myInit(ts) + Board(s, n - 1, (lazy of () => myLast(ts_)), ts_) + +fun positionPiece(x, b) = if b is Board(_, n, _, ts) then atIndex(n - x, ts) + +fun lastPiece(b) = if b is Board(_, _, _, t :: ts) then t + +fun firstPiece(b) = if b is Board(_, _, f, _) then force(f) + +fun pieceAtTile(x, b) = if b is Board(_, _, _, ts) then + fun find(x, xs) = if xs is + Nil then throw Error("Tile not used") + y :: xs then if eqTup2(x, y) then 1 + listLen(xs) else find(x, xs) + find(x, ts) + +fun tup2InList(y, xs) = if xs is + Nil then false + x :: xs and + eqTup2(y, x) then true + else tup2InList(y, xs) + +fun isSquareFree(x, b) = if b is Board(_, _, _, ts) then not(tup2InList(x, ts)) + +fun assignMoveNo(t, size, z) = if t is + Nil then Nil + [x, y] :: t then [(y - 1) * size + x, z] :: assignMoveNo(t, size, z - 1) + +fun spaces(s, y) = + fun logTen(x) = if x === 0 then 0 else 1 + logTen(intDiv(x, 10)) + replicate((logTen(s) - logTen(y)) + 1, " ") + +fun printBoard(s, n, xs) = if xs is + Nil and + n > s * s then Nil + intMod(n, s) != 0 then "*" :: (spaces(s * s, 1) +: printBoard(s, n + 1, Nil)) + intMod(n, s) === 0 then nofibStringToList("*\n") +: printBoard(s, n + 1, Nil) + else throw Error("printBoard empty list error") + [i, j] :: xs and + i === n and intMod(n, s) === 0 then nofibStringToList(stringOfInt(j)) +: nofibStringToList("\n") +: printBoard(s, n + 1, xs) + i === n and intMod(n, s) != 0 then nofibStringToList(stringOfInt(j)) +: spaces(s * s, j) +: printBoard(s, n + 1, xs) + intMod(n, s) != 0 then "*" :: (spaces(s * s, 1) +: printBoard(s, n + 1, [i, j] :: xs)) + intMod(n, s) === 0 then nofibStringToList("*\n") +: printBoard(s, n + 1, [i, j] :: xs) + else throw Error("printBoard non-empty list error") + +abstract class Direction: UL | UR | DL | DR | LU | LD | RU | RD + +object + UL extends Direction + UR extends Direction + DL extends Direction + DR extends Direction + LU extends Direction + LD extends Direction + RU extends Direction + RD extends Direction + +fun move(d, x_y) = if x_y is [x, y] and d is + UL then [x - 1, y - 2] + UR then [x + 1, y - 2] + DL then [x - 1, y + 2] + DR then [x + 1, y + 2] + LU then [x - 2, y - 1] + LD then [x - 2, y + 1] + RU then [x + 2, y - 1] + RD then [x + 2, y + 1] + +fun startTour(st, size) = + if intMod(size, 2) === 0 then createBoard(size, st) + else throw Error("Tour doesnt exist for odd size board") + +fun moveKnight(board, dir) = addPiece(move(dir, lastPiece(board)), board) + +fun canMoveTo(x_y, board) = if x_y is [x, y] then + let sze = sizeBoard(board) + let res = (x >= 1) and (x <= sze) and (y >= 1) and (y <= sze) and (isSquareFree(x_y, board)) + res + +fun canMove(board, dir) = canMoveTo(move(dir, lastPiece(board)), board) + +fun canJumpFirst(board) = canMoveTo(firstPiece(board), deleteFirst(board)) + +fun tourFinished(board) = + let sze = sizeBoard(board) + (noPieces(board) === (sze * sze)) && canJumpFirst(board) + +fun possibleMoves(board) = + fun lscomp(ls) = if ls is + Nil then Nil + x :: t and + canMove(board, x) then x :: lscomp(t) + else lscomp(t) + let res = lscomp(UL :: UR :: DL :: DR :: LU :: LD :: RU :: RD :: Nil) + res + +fun deadEnd(board) = listLen(possibleMoves(board)) === 0 + +fun allDescend(board) = map(b => moveKnight(board, b), possibleMoves(board)) + +fun descAndNo(board) = + fun lscomp(ls) = if ls is + Nil then lazy of () => LzNil + x :: t then lazy of () => LzCons([listLen(possibleMoves(deleteFirst(x))), x], lscomp(t)) + lscomp(allDescend(board)) + +fun singleDescend(board) = + fun lscomp(ls) = if force(ls) is + LzNil then Nil + LzCons([y, x], t) and + y === 1 then x :: lscomp(t) + else lscomp(t) + lscomp(descAndNo(board)) + +fun descendents(board) = + if canJumpFirst(board) && deadEnd(addPiece(firstPiece(board), board)) then lazy of () => LzNil + else + let singles = singleDescend(board) + let scrut = listLen(singles) + let res = if scrut === + 0 then map_lz(snd, quickSortIntChessSet(descAndNo(board))) + 1 then if singles is h :: Nil then lazy of () => LzCons(h, lazy of () => LzNil) else throw Error("unreachable") + else lazy of () => LzNil + res + + +fun showChessSet(b) = if b is Board(sze, n, f, ts) then + let sortedTrail = quickSortIntInt(assignMoveNo(ts, sze, n)) + printBoard(sze, 1, sortedTrail) + +fun root(sze) = + fun lscomp1(ls) = if ls is + Nil then lazy of () => LzNil + h1 :: t1 then + fun lscomp2(ls) = if ls is + Nil then lscomp1(t1) + h2 :: t2 then lazy of () => LzCons([h1, h2], lscomp2(t2)) + lscomp2(enumFromTo(1, sze)) + append_lz_lz( + zip_lz_lz( + repeat(1 - (sze * sze)), + zipWith_lz_lz(startTour, lscomp1(enumFromTo(1, sze)), replicate_lz(sze * sze, sze)) + ), + lazy of () => LzNil + ) + +fun grow(x_y) = if x_y is [x, y] then zip_lz_lz(repeat(x + 1), descendents(y)) + +fun isFinished(x_y) = if x_y is [x, y] then tourFinished(y) + +fun emptyQueue_lz(x) = force(x) is LzNil + +fun removeFront_lz(xs) = if force(xs) is LzCons(h, t) then t + +fun inquireFront_lz(h_t) = if force(h_t) is LzCons(h, t) then h + +fun addAllFront_lz(list, q) = append_lz_lz(list, q) + +fun depthSearch(q, growFn, finFn) = + if + emptyQueue_lz(q) then lazy of () => LzNil + finFn(inquireFront_lz(q)) then lazy of () => LzCons(inquireFront_lz(q), depthSearch(removeFront_lz(q), growFn, finFn)) + else depthSearch(addAllFront_lz(growFn(inquireFront_lz(q)), removeFront_lz(q)), growFn, finFn) + +fun printTour(ss) = + fun strToInt(y, xs) = if xs is + Nil then y + x :: xs then strToInt((10 * y) + (x.codePointAt(0) - 48), xs) + fun pp(xs) = if xs is + Nil then Nil + [x, y] :: xs then + nofibStringToList("\nKnights tour with ") +: + nofibStringToList(stringOfInt(x)) +: + nofibStringToList(" backtracking moves\n") +: + showChessSet(y) +: + pp(xs) + if map(x => strToInt(0, x), ss) is + size :: number :: Nil then pp(take_lz(number, depthSearch(root(size), grow, isFinished))) + else throw Error("printTour error") + +fun testKnights_nofib(ss) = + let usageString = "\nUsage: knights \n" + fun all_digits(s) = foldr((a, b) => (myIsDigit(a)) && b, true, s) + fun argsOk(ss) = (listLen(ss) === 2) && (foldr((a, b) => (all_digits(a)) && b, true, ss)) + if argsOk(ss) then (printTour(ss)) else throw Error(usageString) + + +fun main() = nofibListToString(testKnights_nofib(nofibStringToList("8") :: nofibStringToList("1") :: Nil)) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/lambda.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/lambda.mls new file mode 100644 index 0000000000..f15888b431 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/lambda.mls @@ -0,0 +1,196 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module lambda with ... + + + +fun lookup(k, t) = if t is + Nil then None + [x, v] :: t then if listEq(k, x) then Some(v) else lookup(k, t) + +data class MyState[S, A](r: S -> [S, A]) + +fun myRunState(m, s) = if m is MyState(f) then f(s) + +fun myBind(m, f) = MyState(s => if myRunState(m, s) is [s_, a] then myRunState(f(a), s_)) + +fun myReturn(a) = MyState(s => [s, a]) + +val myGet = MyState(s => [s, s]) +//│ myGet = MyState([function]) + +fun myEvalState(m, s) = if myRunState(m, s) is [s_, a] then a + + +abstract class Term: Var | Con | Incr | Add | Lam | App | IfZero | Thunk + +object Incr extends Term + +data + class + Var(s: String) extends Term + Con(i: Int) extends Term + Add(a: Term, b: Term) extends Term + Lam(s: String, t: Term) extends Term + App(a: Term, b: Term) extends Term + IfZero(a: Term, b: Term, c: Term) extends Term + Thunk(t: Term, e: List[[String, Term]]) extends Term + +object Unit + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun eqEnv(a, b) = if a is + Nil and b is Nil then true + [s1, t1] :: b and b is [s2, t2] :: d and + listEq(s1, s2) and eqTerm(t1, t2) then eqEnv(b, d) + else false + else false + +fun eqTerm(a, b) = if a is + Var(a) and b is Var(b) then listEq(a, b) + Con(a) and b is Con(b) then a === b + Incr and b is Incr then true + Add(a, b) and b is Add(c, d) then eqTerm(a, c) && eqTerm(b, d) + Lam(a, b) and b is Lam(c, d) then listEq(a, c) && eqTerm(b, d) + App(a, b) and b is App(c, d) then eqTerm(a, c) && eqTerm(b, d) + IfZero(a, b, c) and b is IfZero(d, e, f) then eqTerm(a, d) && eqTerm(b, e) && eqTerm(c, f) + Thunk(a, b) and b is Thunk(c, d) then eqTerm(a, c) && eqEnv(b, d) + else false +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun myMaybe(d, f, x) = if x is Some(x) then f(x) + +val incr = myReturn(Unit) +//│ incr = MyState([function]) + +fun lookupVar(v) = + fun lookup2(env) = myMaybe(dummy => throw Error("undefined"), x => x, lookup(v, env)) + myBind(myGet, env => myReturn(lookup2(env))) + +fun withEnv(tmp, m) = myReturn(myEvalState(m, tmp)) + +fun pushVar(v, t, m) = myBind(myGet, env => withEnv([v, t] :: env, m)) + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun traverseTerm(t) = eval(t) + +fun traverseCon(t) = + myBind( + traverseTerm(t), + _t => if _t is Con(c) then myReturn(c) else throw Error("Not a Con") + ) + +fun apply(t, a) = if t is Thunk(Lam(x, b), e) then + myBind( + myGet, + orig => withEnv(e, pushVar(x, Thunk(a, orig), traverseTerm(b))) + ) + +fun eval(ter) = if ter is + Var(x) then + myBind of + myGet + e => myBind(lookupVar(x), t => traverseTerm(t)) + Add(u, v) then + myBind of + traverseCon(u) + u_ => myBind(traverseCon(v), v_ => myReturn(Con(u_ + v_))) + Thunk(t, e) then withEnv(e, traverseTerm(t)) + Lam(x, b) then myBind(myGet, env => myReturn(Thunk(Lam(x, b), env))) + App(u, v) then myBind(traverseTerm(u), u_ => apply(u_, v)) + IfZero(c, a, b) then + myBind of + traverseTerm(c) + vall => if eqTerm(vall, Con(0)) then traverseTerm(a) else traverseTerm(b) + Con(i) then myReturn(Con(i)) + Incr then myBind(incr, _dummy => myReturn(Con(0))) +//│ ———————————————————————————————————————————————————————————————————————————————— + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun simpleEval(env, ter) = if ter is + Var(v) then simpleEval(env, myMaybe(dummy => throw Error("undefined var"), x => x, lookup(v, env))) + Con(e) then Con(e) + Incr then Con(0) + Add(u, v) then + let u_ = simpleEvalCon(env, u) + let v_ = simpleEvalCon(env, v) + Con(u_ + v_) + Lam(x, b) then Thunk(Lam(x, b), env) + App(u, v) then + let u_ = simpleEval(env, u) + simpleApply(env, u_, v) + IfZero(c, a, b) then + let val_ = simpleEval(env, c) + if eqTerm(val_, Con(0)) then simpleEval(env, a) else simpleEval(env, b) + Thunk(t, e) then simpleEval(e, t) + else throw Error(ter) + +fun simpleApply(env, t, a) = if t is + Thunk(Lam(x, b), e) then simpleEval([x, Thunk(a, env)] :: e, b) + else throw Error("bad application") + +fun simpleEvalCon(env, e) = + let e_ = simpleEval(env, e) + if e_ is Con(c) then c else throw Error("Not a Con") +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun bracket(ot, ths, t) = if ths <= ot then "(" :: (t +: nofibStringToList(")")) else t + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun ppn(n, ter) = if ter is + Var(v) then v + Con(i) then nofibStringToList(stringOfInt(i)) + Incr then nofibStringToList("INCR") + Lam(v, t) then bracket(n, 0, "@" :: (v +: nofibStringToList(". ") +: ppn(0-1, t))) + Add(a, b) then bracket(n, 1, ppn(1, a) +: nofibStringToList(" + ") +: ppn(1, b)) + App(a, b) then bracket(n, 2, ppn(2, a) +: nofibStringToList(" ") +: ppn(2, b)) + IfZero(c, a, b) then bracket(n, 0, nofibStringToList("IF ") +: ppn(0, c) +: nofibStringToList(" THEN ") +: ppn(0, a) +: nofibStringToList(" ELSE ") +: ppn(0, b)) + Thunk(t, e) then bracket(n, 0, ppn(3, t) +: nofibStringToList("::") +: ppenv(e)) + +fun pp(t) = ppn(0, t) + +fun ppenv(env) = + nofibStringToList("[") +: + flatMap( + case { [v, t] then v +: nofibStringToList("=") +: pp(t) +: nofibStringToList(", ") } + env + ) +: + nofibStringToList("]") +//│ ———————————————————————————————————————————————————————————————————————————————— + +val lfxx = Lam(nofibStringToList("x"), App(Var(nofibStringToList("F")), App(Var(nofibStringToList("x")), Var(nofibStringToList("x"))))) +//│ lfxx = Lam(["x"], App(Var(["F"]), App(Var(["x"]), Var(["x"])))) + +val fix = Lam(nofibStringToList("F"), App(lfxx, lfxx)) +//│ fix = Lam(["F"], App(Lam(["x"], App(Var(["F"]), App(Var(["x"]), Var(["x"])))), Lam(["x"], App(Var(["F"]), App(Var(["x"]), Var(["x"])))))) + +val nMinus1 = Add(Var(nofibStringToList("n")), Con(-1)) +//│ nMinus1 = Add(Var(["n"]), Con(-1)) + +val partialSum0 = Lam(nofibStringToList("sum"), Lam(nofibStringToList("n"), IfZero(Var(nofibStringToList("n")), Con(0), Add(Var(nofibStringToList("n")), App(Var(nofibStringToList("sum")), nMinus1))))) +//│ partialSum0 = Lam(["s","u","m"], Lam(["n"], IfZero(Var(["n"]), Con(0), Add(Var(["n"]), App(Var(["s","u","m"]), Add(Var(["n"]), Con(-1))))))) + +val sum0 = App(fix, partialSum0) +//│ sum0 = App(Lam(["F"], App(Lam(["x"], App(Var(["F"]), App(Var(["x"]), Var(["x"])))), Lam(["x"], App(Var(["F"]), App(Var(["x"]), Var(["x"])))))), Lam(["s","u","m"], Lam(["n"], IfZero(Var(["n"]), Con(0), Add(Var(["n"]), App(Var(["s","u","m"]), Add(Var(["n"]), Con(-1)))))))) + +fun showTerm(t) = if t is Con(a) then nofibStringToList("Con ") +: nofibStringToList(stringOfInt(a)) + +fun ev(t) = + let envt2 = myRunState(traverseTerm(t), Nil) + if envt2 is [env, t2] then pp(t2) +: nofibStringToList(" ") +: ppenv(env) + +fun mainSimple(args) = + if null_(args) + then throw Error("Args: number-to-sum-up-to") + else showTerm(simpleEval(Nil, App(sum0, Con(head(args))))) + +fun mainMonad(args) = + if null_(args) + then throw Error("Args: number-to-sum-up-to") + else ev(App(sum0, Con(head(args)))) + +fun testLambda_nofib(n) = [mainSimple(n :: Nil), mainMonad(n :: Nil)] + +fun main() = testLambda_nofib(80).toString() \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/lastpiece.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/lastpiece.mls new file mode 100644 index 0000000000..bc6b506d43 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/lastpiece.mls @@ -0,0 +1,575 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module lastpiece with ... + + + +fun isSome(x) = x is Some + +fun mapMaybe(f, ls) = if ls is + Nil then Nil + h :: t and f(h) is + None then mapMaybe(f, t) + Some(a) then a :: mapMaybe(f, t) + +object + GT + LT + EQ + +fun compareIntInt(ab, cd) = if ab is [a, b] and cd is [c, d] and + a > c then GT + a < c then LT + b > d then GT + b < d then LT + else EQ + +abstract class Map[K, A]: Tip | Bin[K, A] + +object Tip extends Map[Anything, Nothing] + +data class Bin[K, A](i: Int, k: K, v: A, l: Map[K, A], r: Map[K, A]) extends Map[K, A] + +fun mapLookup(k, m) = if m is + Tip then None + Bin(_, kx, x, l, r) and compareIntInt(k, kx) is + LT then mapLookup(k, l) + GT then mapLookup(k, r) + EQ then Some(x) + +fun size(p) = if p is + Tip then 0 + Bin(sz, _, _, _, _) then sz + +fun bin(k, x, l, r) = Bin(size(l) + size(r) + 1, k, x, l, r) + +fun singleL(k1, x1, t1, r) = if r is + Bin(_, k2, x2, t2, t3) then bin(k2, x2, bin(k1, x1, t1, t2), t3) + else throw Error("singleL Tip") + +fun singleR(k1, x1, l, t3) = if l is + Bin(_, k2, x2, t1, t2) then bin(k2, x2, t1, bin(k1, x1, t2, t3)) + else throw Error("singleR Tip") + +fun doubleL(k1, x1, t1, r) = if r is + Bin(_, k2, x2, Bin(_, k3, x3, t2, t3), t4) then bin(k3, x3, bin(k1, x1, t1, t2), bin(k2, x2, t3, t4)) + else throw Error("doubleL Tip") + +fun doubleR(k1, x1, l, t4) = if l is + Bin(_, k2, x2, t1, Bin(_, k3, x3, t2, t3)) then bin(k3, x3, bin(k2, x2, t1, t2), bin(k1, x1, t3, t4)) + else throw Error("doubleR Tip") + +fun rotateL(k, x, l, r) = if r is + Bin(_, _, _, ly, ry) and + size(ly) < 2 * size(ry) then singleL(k, x, l, r) + else doubleL(k, x, l, r) + else throw Error("rotateL Tip") + +fun rotateR(k, x, l, r) = if l is + Bin(_, _, _, ly, ry) and + size(ry) < 2 * size(ly) then singleR(k, x, l, r) + else doubleR(k, x, l, r) + else throw Error("rotateR Tip") + +fun balance(k, x, l, r) = + let sizeL = size(l) + let sizeR = size(r) + let sizeX = sizeL + sizeR + 1 + if + (sizeL + sizeR) <= 1 then Bin(sizeX, k, x, l, r) + sizeR >= (4 * sizeL) then rotateL(k, x, l, r) + sizeL >= (4 * sizeR) then rotateR(k, x, l, r) + else Bin(sizeX, k, x, l, r) + +fun insert(kx, x, m) = if m is + Tip then Bin(1, kx, x, Tip, Tip) + Bin(sz, ky, y, l, r) and compareIntInt(kx, ky) is + LT then balance(ky, y, insert(kx, x, l), r) + GT then balance(ky, y, l, insert(kx, x, r)) + EQ then Bin(sz, kx, x, l, r) + +fun indent(n) = if n <= 0 then Nil else " " :: indent(n - 1) + +data class P(i: Char, a: List[List[[Int, Int]]], b: List[List[[Int, Int]]]) + +abstract class S: Male | Female + +object + Male extends S + Female extends S + +fun flip(s) = if s is + Male then Female + Female then Male + +abstract class Solution: Soln | Choose | Fail + +type Board = Map[[Int, Int], Char] + +data + class + Soln(b: Board) extends Solution + Choose(s: List[Solution]) extends Solution + Fail(b: Board, s: [Int, Int]) extends Solution + +fun addIntInt(row_col, orow_ocol) = if row_col is [row, col] and orow_ocol is [orow, ocol] then + [row + orow, col + ocol] + +fun next(row_col) = if row_col is [row, col] then [row, col + 1] + +val maxRow = 8 +//│ maxRow = 8 + +val maxCol = 8 +//│ maxCol = 8 + +val emptyBoard = Tip +//│ emptyBoard = Tip + +fun check(bd, sq) = mapLookup(sq, bd) + +fun extend(bd, sq, id) = insert(sq, id, bd) + +fun extend_maybe(bd, sq, id) = if sq is [row, col] and + (row > maxRow) || (col < 1) || (col > maxCol) then None + check(bd, sq) is + Some(_) then None + None then Some(extend(bd, sq, id)) + +fun pickOne(xs) = + fun go(f, xs) = if xs is + Nil then Nil + x :: xs then [x, f(xs)] :: go(p => x :: f(p), xs) + go(x => x, xs) + +fun fit(bd, sq, id, os) = if os is + Nil then Some(extend(bd, sq, id)) + o :: os and extend_maybe(bd, addIntInt(sq, o), id) is + Some(bd1) then fit(bd1, sq, id, os) + None then None + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun tryy(sq, se, bd, id_is_ps) = if id_is_ps is [id, os, ps] and fit(bd, sq, id, os) is + Some(bd1) then Some(search(next(sq), flip(se), bd1, ps)) + None then None + +fun search(row_col, sey, bd, ps) = if row_col is [row, col] and + ps is Nil then Soln(bd) + col === (maxCol + 1) then search([row + 1, 1], flip(sey), bd, ps) + check(bd, row_col) is Some(_) then search(next(row_col), flip(sey), bd, ps) + else + fun lscomp1(ls) = if ls is + Nil then Nil + [P(id, ms, fs), ps] :: ls then + fun lscomp2(ls2) = if ls2 is + Nil then lscomp1(ls) + os :: ls then [id, os, ps] :: lscomp2(ls) + lscomp2(if sey is Male then ms else fs) + let choices = lscomp1(pickOne(ps)) + if mapMaybe(x => tryy(row_col, sey, bd, x), choices) is + Nil then Fail(bd, row_col) + ss then Choose(ss) +//│ ———————————————————————————————————————————————————————————————————————————————— + +val nPiece = P( + "n", + ([0,1] :: [1,1] :: [2,1] :: [2,2] :: Nil) :: + ([1,0] :: [1,-1] :: [1,-2] :: [2,-2] :: Nil) :: Nil, + Nil +) +//│ nPiece = P("n", [[[0, 1],[1, 1],[2, 1],[2, 2]],[[1, 0],[1, -1],[1, -2],[2, -2]]], []) + +val mPiece = P( + "m", + ([0,1] :: [1,0] :: [2,0] :: [3,0] :: Nil) :: Nil, + ([0,1] :: [0,2] :: [0,3] :: [1,3] :: Nil) :: + ([1,0] :: [2,0] :: [3,0] :: [3,-1] :: Nil) :: Nil +) +//│ mPiece = P("m", [[[0, 1],[1, 0],[2, 0],[3, 0]]], [[[0, 1],[0, 2],[0, 3],[1, 3]],[[1, 0],[2, 0],[3, 0],[3, -1]]]) + +val lPiece = P( + "l", + ([0,1] :: [0,2] :: [0,3] :: [1,2] :: Nil) :: + ([1,0] :: [2,0] :: [3,0] :: [2,-1] :: Nil) :: Nil, + ([1,-1] :: [1,0] :: [1,1] :: [1,2] :: Nil) :: + ([1,0] :: [2,0] :: [3,0] :: [1,1] :: Nil) :: Nil +) +//│ lPiece = P("l", [[[0, 1],[0, 2],[0, 3],[1, 2]],[[1, 0],[2, 0],[3, 0],[2, -1]]], [[[1, -1],[1, 0],[1, 1],[1, 2]],[[1, 0],[2, 0],[3, 0],[1, 1]]]) + +val kPiece = P( + "k", + ([0,1] :: [1,0] :: [2,0] :: [2,-1] :: Nil) :: Nil, + ([1,0] :: [1,1] :: [1,2] :: [2,2] :: Nil) :: Nil +) +//│ kPiece = P("k", [[[0, 1],[1, 0],[2, 0],[2, -1]]], [[[1, 0],[1, 1],[1, 2],[2, 2]]]) + +val jPiece = P( + "j", + ([0,1] :: [0,2] :: [0,3] :: [1,1] :: Nil) :: + ([1,0] :: [2,0] :: [3,0] :: [1,-1] :: Nil) :: + ([1,-2] :: [1,-1] :: [1,0] :: [1,1] :: Nil) :: Nil, + ([1,0] :: [2,0] :: [3,0] :: [2,2] :: Nil) :: Nil +) +//│ jPiece = P("j", [[[0, 1],[0, 2],[0, 3],[1, 1]],[[1, 0],[2, 0],[3, 0],[1, -1]],[[1, -2],[1, -1],[1, 0],[1, 1]]], [[[1, 0],[2, 0],[3, 0],[2, 2]]]) + +val iPiece = P( + "i", + ([1,0] :: [2,0] :: [2,1] :: [3,1] :: Nil) :: + ([0,1] :: [0,2] :: [1,0] :: [1,-1] :: Nil) :: + ([1,0] :: [1,1] :: [2,1] :: [3,1] :: Nil) :: Nil, + ([0,1] :: [1,0] :: [1,-1] :: [1,-2] :: Nil) :: Nil +) +//│ iPiece = P("i", [[[1, 0],[2, 0],[2, 1],[3, 1]],[[0, 1],[0, 2],[1, 0],[1, -1]],[[1, 0],[1, 1],[2, 1],[3, 1]]], [[[0, 1],[1, 0],[1, -1],[1, -2]]]) + +val hPiece = P( + "h", + ([0,1] :: [1,1] :: [1,2] :: [2,2] :: Nil) :: + ([1,0] :: [1,-1] :: [2,-1] :: [2,-2] :: Nil) :: + ([1,0] :: [1,1] :: [2,1] :: [2,2] :: Nil) :: Nil, + ([0,1] :: [1,0] :: [1,-1] :: [2,-1] :: Nil) :: Nil +) +//│ hPiece = P("h", [[[0, 1],[1, 1],[1, 2],[2, 2]],[[1, 0],[1, -1],[2, -1],[2, -2]],[[1, 0],[1, 1],[2, 1],[2, 2]]], [[[0, 1],[1, 0],[1, -1],[2, -1]]]) + +val gPiece = P( + "g", + Nil, + ([0,1] :: [1,1] :: [1,2] :: [1,3] :: Nil) :: + ([1,0] :: [1,-1] :: [2,-1] :: [3,-1] :: Nil) :: + ([0,1] :: [0,2] :: [1,2] :: [1,3] :: Nil) :: + ([1,0] :: [2,0] :: [2,-1] :: [3,-1] :: Nil) :: Nil +) +//│ gPiece = P("g", [], [[[0, 1],[1, 1],[1, 2],[1, 3]],[[1, 0],[1, -1],[2, -1],[3, -1]],[[0, 1],[0, 2],[1, 2],[1, 3]],[[1, 0],[2, 0],[2, -1],[3, -1]]]) + +val fPiece = P( + "f", + ([0,1] :: [1,1] :: [2,1] :: [3,1] :: Nil) :: + ([1,0] :: [1,-1] :: [1,-2] :: [1,-3] :: Nil) :: + ([1,0] :: [2,0] :: [3,0] :: [3,1] :: Nil) :: Nil, + ([0,1] :: [0,2] :: [0,3] :: [1,0] :: Nil) :: Nil +) +//│ fPiece = P("f", [[[0, 1],[1, 1],[2, 1],[3, 1]],[[1, 0],[1, -1],[1, -2],[1, -3]],[[1, 0],[2, 0],[3, 0],[3, 1]]], [[[0, 1],[0, 2],[0, 3],[1, 0]]]) + +val ePiece = P( + "e", + ([0,1] :: [1,1] :: [1,2] :: Nil) :: + ([1,0] :: [1,-1] :: [2,-1] :: Nil) :: Nil, + ([0,1] :: [1,1] :: [1,2] :: Nil) :: + ([1,0] :: [1,-1] :: [2,-1] :: Nil) :: Nil +) +//│ ePiece = P("e", [[[0, 1],[1, 1],[1, 2]],[[1, 0],[1, -1],[2, -1]]], [[[0, 1],[1, 1],[1, 2]],[[1, 0],[1, -1],[2, -1]]]) + +val dPiece = P( + "d", + ([0,1] :: [1,1] :: [2,1] :: Nil) :: + ([1,0] :: [1,-1] :: [1,-2] :: Nil) :: Nil, + ([1,0] :: [2,0] :: [2,1] :: Nil) :: Nil +) +//│ dPiece = P("d", [[[0, 1],[1, 1],[2, 1]],[[1, 0],[1, -1],[1, -2]]], [[[1, 0],[2, 0],[2, 1]]]) + +val cPiece = P( + "c", + Nil, + ([0,1] :: [0,2] :: [1,1] :: Nil) :: + ([1,0] :: [1,-1] :: [2,0] :: Nil) :: + ([1,-1] :: [1,0] :: [1,1] :: Nil) :: + ([1,0] :: [1,1] :: [2,0] :: Nil) :: Nil +) +//│ cPiece = P("c", [], [[[0, 1],[0, 2],[1, 1]],[[1, 0],[1, -1],[2, 0]],[[1, -1],[1, 0],[1, 1]],[[1, 0],[1, 1],[2, 0]]]) + +val bPiece = P( + "b", + ([0,1] :: [0,2] :: [1,2] :: Nil) :: + ([1,0] :: [2,0] :: [2,-1] :: Nil) :: + ([0,1] :: [1,0] :: [2,0] :: Nil) :: Nil, + ([1,0] :: [1,1] :: [1,2] :: Nil) :: Nil +) +//│ bPiece = P("b", [[[0, 1],[0, 2],[1, 2]],[[1, 0],[2, 0],[2, -1]],[[0, 1],[1, 0],[2, 0]]], [[[1, 0],[1, 1],[1, 2]]]) + +val initialPieces = bPiece :: cPiece :: dPiece :: ePiece :: fPiece :: + gPiece :: hPiece :: iPiece :: jPiece :: kPiece :: lPiece :: + mPiece :: nPiece :: Nil +//│ initialPieces = [P("b", [[[0, 1],[0, 2],[1, 2]],[[1, 0],[2, 0],[2, -1]],[[0, 1],[1, 0],[2, 0]]], [[[1, 0],[1, 1],[1, 2]]]),P("c", [], [[[0, 1],[0, 2],[1, 1]],[[1, 0],[1, -1],[2, 0]],[[1, -1],[1, 0],[1, 1]],[[1, 0],[1, 1],[2, 0]]]),P("d", [[[0, 1],[1, 1],[2, 1]],[[1, 0],[1, -1],[1, -2]]], [[[1, 0],[2, 0],[2, 1]]]),P("e", [[[0, 1],[1, 1],[1, 2]],[[1, 0],[1, -1],[2, -1]]], [[[0, 1],[1, 1],[1, 2]],[[1, 0],[1, -1],[2, -1]]]),P("f", [[[0, 1],[1, 1],[2, 1],[3, 1]],[[1, 0],[1, -1],[1, -2],[1, -3]],[[1, 0],[2, 0],[3, 0],[3, 1]]], [[[0, 1],[0, 2],[0, 3],[1, 0]]]),P("g", [], [[[0, 1],[1, 1],[1, 2],[1, 3]],[[1, 0],[1, -1],[2, -1],[3, -1]],[[0, 1],[0, 2],[1, 2],[1, 3]],[[1, 0],[2, 0],[2, -1],[3, -1]]]),P("h", [[[0, 1],[1, 1],[1, 2],[2, 2]],[[1, 0],[1, -1],[2, -1],[2, -2]],[[1, 0],[1, 1],[2, 1],[2, 2]]], [[[0, 1],[1, 0],[1, -1],[2, -1]]]),P("i", [[[1, 0],[2, 0],[2, 1],[3, 1]],[[0, 1],[0, 2],[1, 0],[1, -1]],[[1, 0],[1, 1],[2, 1],[3, 1]]], [[[0, 1],[1, 0],[1, -1],[1, -2]]]),P("j", [[[0, 1],[0, 2],[0, 3],[1, 1]],[[1, 0],[2, 0],[3, 0],[1, -1]],[[1, -2],[1, -1],[1, 0],[1, 1]]], [[[1, 0],[2, 0],[3, 0],[2, 2]]]),P("k", [[[0, 1],[1, 0],[2, 0],[2, -1]]], [[[1, 0],[1, 1],[1, 2],[2, 2]]]),P("l", [[[0, 1],[0, 2],[0, 3],[1, 2]],[[1, 0],[2, 0],[3, 0],[2, -1]]], [[[1, -1],[1, 0],[1, 1],[1, 2]],[[1, 0],[2, 0],[3, 0],[1, 1]]]),P("m", [[[0, 1],[1, 0],[2, 0],[3, 0]]], [[[0, 1],[0, 2],[0, 3],[1, 3]],[[1, 0],[2, 0],[3, 0],[3, -1]]]),P("n", [[[0, 1],[1, 1],[2, 1],[2, 2]],[[1, 0],[1, -1],[1, -2],[2, -2]]], [])] + +abstract class Mode: PageMode | ZigZagMode | LeftMode | OneLineMode + +object + PageMode extends Mode + ZigZagMode extends Mode + LeftMode extends Mode + OneLineMode extends Mode + +abstract class TextDetails: Chr | Str | PStr + +data + class + Chr(c: Char) extends TextDetails + Str(s: String) extends TextDetails + PStr(s: String) extends TextDetails + +abstract class AnnotDetails: AnnotStart | NoAnnot | AnnotEnd + +object + AnnotStart extends AnnotDetails + AnnotEnd extends AnnotDetails + +data class NoAnnot(t: TextDetails, i: Int) extends AnnotDetails + +abstract class IsEmptyy: IsEmpty | NotEmpty + +object + IsEmpty extends IsEmptyy + NotEmpty extends IsEmptyy + +abstract class Doc: Empty | NilAbove | TextBeside | Nest | Union | NoDoc | Beside | Above + +object + Empty extends Doc + NoDoc extends Doc + +data + class + NilAbove(d: Doc) extends Doc + TextBeside(a: AnnotDetails, d: Doc) extends Doc + Nest(i: Int, d: Doc) extends Doc + Union(d1: Doc, d2: Doc) extends Doc + Beside(d1: Doc, b: Bool, d2: Doc) extends Doc + Above(d1: Doc, b: Bool, d2: Doc) extends Doc + +val spaceText = NoAnnot(Chr(" "), 1) +//│ spaceText = NoAnnot(Chr(" "), 1) + +val nlText = NoAnnot(Chr("\n"), 1) +//│ nlText = NoAnnot(Chr("\n"), 1) + +fun annotSize(p) = if p is + NoAnnot(_, l) then l + _ then 0 + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun display(s) = if s is + Soln(bd) then vcat(text(nofibStringToList("Success!")) :: nest(2, displayBoard(bd)) :: Nil) + Choose(ss) then vcat(map(display, ss)) + Fail(bd, [row, col]) then Empty + +fun displayBoard(bd) = + fun sq(n, col) = if check(bd, [n, col]) is + Some(id) then char(id) + None then char(".") + fun row(n) = hcat(map(col => sq(n, col), enumFromTo(1, maxCol))) + above_(vcat(map(row, enumFromTo(1, maxCol))), false, text(Nil)) + +fun eliminateEmpty(cons, p, g, q) = if p is + Empty then q + else [ + NotEmpty, + if q is + [NotEmpty, q1] then cons(p, g, q1) + [IsEmpty, _] then p + ] + +fun reduceVert(doc) = if doc is + Above(p, g, q) then eliminateEmpty((a, b, c) => Above(a, b, c), snd(reduceVert(p)), g, reduceVert(q)) + else [NotEmpty, doc] + +fun vcat(ls) = snd(reduceVert(foldr((p, q) => Above(p, false, q), Empty, ls))) + +fun text(s) = + let sl = listLen(s) + TextBeside(NoAnnot(Str(s), sl), Empty) + +fun char(c) = TextBeside(NoAnnot(Chr(c), 1), Empty) + +fun reduceHoriz(doc) = if doc is + Beside(p, g, q) then eliminateEmpty((a, b, c) => Beside(a, b, c), snd(reduceHoriz(p)), g, reduceHoriz(q)) + else [NotEmpty, doc] + +fun hcat(ls) = snd of reduceHoriz of foldr of + (p, q) => Beside(p, false, q) + Empty + ls + +fun above_(p, g, q) = if + q is Empty then p + g is Empty then q + else Above(p, g, q) + +fun nest(k, p) = mkNest(k, reduceDoc(p)) + +fun mkNest(k, p) = if + p is Nest(k1, p1) then mkNest(k + k1, p1) + p is NoDoc then NoDoc + p is Empty then Empty + k === 0 then p + else Nest(k, p) + +fun reduceDoc(p) = if p is + Beside(p1, g, q) then beside(p1, g, reduceDoc(q)) + Above(p1, g, q) then above(p1, g, reduceDoc(q)) + else p + + +fun beside(p, g, q) = if p is + NoDoc then NoDoc + Union(p1, p2) then Union(beside(p1, g, q), beside(p2, g, q)) + Empty then q + Nest(k, p1) then Nest(k, beside(p1, g, q)) + Beside(p1, g1, q1) and + g1 === g then beside(p1, g1, beside(q1, g, q)) + else beside(reduceDoc(Beside(p1, g1, q1)), g, q) + Above(_, _, _) then beside(reduceDoc(p), g, q) + NilAbove(p1) then NilAbove(beside(p1, g, q)) + TextBeside(t, p1) then + let rest = if p1 is Empty then nilBeside(g, q) else beside(p1, g, q) + TextBeside(t, rest) + +fun above(p, g, q) = if p is + Above(p1, g1, q1) then above(p1, g1, above(q1, g, q)) + Beside(_, _, _) then aboveNest(reduceDoc(p), g, 0, reduceDoc(q)) + else aboveNest(p, g, 0, reduceDoc(q)) + +fun nilBeside(g, p) = if + p is Empty then Empty + p is Nest(_, p1) then nilBeside(g, p1) + g then TextBeside(spaceText, p) + else p + +fun aboveNest(p, g, k, q) = if p is + NoDoc then NoDoc + Union(p1, p2) then Union(aboveNest(p1, g, k, q), aboveNest(p2, g, k, q)) + Empty then mkNest(k, q) + Nest(k1, p1) then Nest(k1, aboveNest(p1, g, k - k1, q)) + NilAbove(p1) then NilAbove(aboveNest(p1, g, k, q)) + TextBeside(s, p1) then + let k1 = k - annotSize(s) + let rest = if p1 is Empty then nilAboveNest(g, k1, q) else aboveNest(p1, g, k1, q) + TextBeside(s, rest) + Above(_, _, _) then throw Error("aboveNest Above") + Beside(_, _, _) then throw Error("aboveNest Beside") + +fun nilAboveNest(g, k, q) = if + q is Empty then Empty + q is Nest(k1, q1) then nilAboveNest(g, k + k1, q1) + not(g) and (k > 0) then TextBeside(NoAnnot(Str(indent(k)), k), q) + else NilAbove(mkNest(k, q)) + +fun printDoc(d) = + fun put(k, next) = if k is + Chr(c) then c :: next + Str(s) then s +: next + PStr(s) then s +: next + let done = "\n" :: Nil + fullRender(ZigZagMode, 200, 1.5, put, done, d) + +fun fullRender(m, l, r, txt, a, b) = + fun annTxt(p, x) = if p is + NoAnnot(s, _) then txt(s, x) + _ then x + fullRenderAnn(m, l, r, annTxt, a, b) + +fun ceiling(x) = globalThis.Math.ceil(x) + +fun fullRenderAnn(m, lineLen, ribbons, txt, rest, doc) = if m is + OneLineMode then easyDisplay(spaceText, (a, b) => b, txt, rest, reduceDoc(doc)) + LeftMode then easyDisplay(nlText, first, txt, rest, reduceDoc(doc)) + else + let ribbonLen = ceiling(lineLen / ribbons) + let bestLineLen = if m is ZigZagMode then 2147483647 else lineLen + let doc1 = best(bestLineLen, ribbonLen, reduceDoc(doc)) + displayDoc(m, lineLen, ribbonLen, txt, rest, doc1) + +fun easyDisplay(nlSpaceText, choose, txt, end, x) = + fun lay(x) = if x is + NoDoc then throw Error("easyDisplay: NoDoc") + Union(p, q) then lay(choose(p, q)) + Nest(_, p) then lay(p) + Empty then end + NilAbove(p) then txt(nlSpaceText, lay(p)) + TextBeside(s, p) then txt(s, lay(p)) + Above(_, _, _) then throw Error("easyDisplay Above") + Beside(_, _, _) then throw Error("easyDisplay Beside") + lay(x) + +fun displayDoc(m, pageWidth, ribbonWidth, txt, end, doc) = + let gapWidth = pageWidth - ribbonWidth + let shift = intDiv(gapWidth, 2) + fun lay(k, docc) = + fun lay2(k, param) = if param is + NilAbove(p) then txt(nlText, lay(k, p)) + TextBeside(s, p) then txt(s, lay2(k + annotSize(s), p)) + Nest(_, p) then lay2(k, p) + Empty then end + fun lay1(k, s, p) = + let r = k + annotSize(s) + txt(NoAnnot(Str(indent(k)), k), txt(s, lay2(r, p))) + if docc is + Nest(k1, p) then lay(k + k1, p) + Empty then end + NilAbove(p) then txt(nlText, lay(k, p)) + TextBeside(s, p) and m is + ZigZagMode and k + >= gapWidth then txt(nlText, txt(NoAnnot(Str(replicate(shift, "/")), shift), txt(nlText, lay1(k - shift, s, p)))) + < 0 then txt(nlText, txt(NoAnnot(Str(replicate(shift, "|")), shift), txt(nlText, lay1(k + shift, s, p)))) + else lay1(k, s, p) + else lay1(k, s, p) + lay(0, doc) + +fun best(w0, r, doc) = + fun get(r, w, docc) = if docc is + Empty then Empty + NoDoc then NoDoc + NilAbove(p) then NilAbove(get(r, w, p)) + TextBeside(s, p) then TextBeside(s, get1(r, w, annotSize(s), p)) + Nest(k, p) then Nest(k, get(r, w - k, p)) + Union(p, q) then nicest(w, r, get(r, w, p), get(r, w, q)) + Above(_, _, _) then throw Error("best get Above") + Beside(_, _, _) then throw Error("best get Beside") + fun get1(r, w, sl, p) = if p is + Empty then Empty + NoDoc then NoDoc + NilAbove(p) then NilAbove(get(r, w - sl, p)) + TextBeside(s, p) then TextBeside(s, get1(r, w, sl + annotSize(s), p)) + Nest(_, p) then get1(r, w, sl, p) + Union(p, q) then nicest1(w, r, sl, get1(r, w, sl, p), get1(r, w, sl, q)) + Above(_, _, _) then throw Error("best get1 Above") + Beside(_, _, _) then throw Error("best get1 Beside") + get(r, w0, doc) + +fun nonEmptySet(doc) = if doc is + NoDoc then false + Union(_, _) then true + Empty then true + NilAbove(_) then true + TextBeside(_, p) then nonEmptySet(p) + Nest(_, p) then nonEmptySet(p) + Above(_, _, _) then throw Error("nonEmptySet Above") + Beside(_, _, _) then throw Error("nonEmptySet Beside") + +fun fits(n, param) = if + n < 0 then false + param is + NoDoc then false + Empty then true + NilAbove(_) then true + TextBeside(s, p) then fits(n - annotSize(s), p) + Above(_, _, _) then throw Error("fits Above") + Beside(_, _, _) then throw Error("fits Beside") + Union(_, _) then throw Error("fits Union") + Nest(_, _) then throw Error("fits Nest") + +fun first(p, q) = if nonEmptySet(p) then p else q + +fun nicest1(w, r, sl, p, q) = if fits(min(w, r) - sl, p) then p else q + +fun nicest(w, r, p, q) = nicest1(w, r, 0, p, q) +//│ ———————————————————————————————————————————————————————————————————————————————— + + +fun testLastPiece_nofib() = + let initialBoard = fromSome(fit(emptyBoard, [1, 1], "a", [1, 0] :: [1, 1] :: Nil)) + let solutions = search([1,2], Female, initialBoard, initialPieces) + printDoc(display(solutions)) + +fun main() = nofibListToString(testLastPiece_nofib()) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/lcss.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/lcss.mls new file mode 100644 index 0000000000..42c9ae58f1 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/lcss.mls @@ -0,0 +1,58 @@ +import "./NofibPrelude.mls" +open NofibPrelude + + + + + +module lcss with ... + + + +fun algb2(x, k0j1, k1j1, yss) = if yss is + Nil then Nil + [y, k0j] :: ys then + let kjcurr = if x == y then k0j1 + 1 else max(k1j1, k0j) + [y, kjcurr] :: algb2(x, k0j, kjcurr, ys) + +fun algb1(xss, yss) = if xss is + Nil then map(snd, yss) + x :: xs then algb1(xs, algb2(x, 0, 0, yss)) + +fun algb(xs, ys) = + fun listcomp_fun(listcomp_fun_para) = if listcomp_fun_para is + listcomp_fun_ls_h :: listcomp_fun_ls_t then [listcomp_fun_ls_h, 0] :: listcomp_fun(listcomp_fun_ls_t) + Nil then Nil + + 0 :: algb1(xs, listcomp_fun(ys)) + + +fun findk(k, km, m, ls) = if ls is + Nil then km + [x,y] :: xys then if (x + y) >= m then findk(k+1, k, x+y, xys) else findk(k+1, km, m, xys) + +fun algc(m, n, xs, ys) = if + ys is Nil then x => x + xs is + x :: Nil and + inList(x, ys) then t => x :: t + else x => x + else + let m2 = intDiv(m, 2) + let xs1 = take(m2, xs) + let xs2 = leave(m2, xs) + let l1 = algb(xs1, ys) + let l2 = reverse(algb(reverse(xs2), reverse(ys))) + let k = findk(0, 0, -1, zip(l1, l2)) + compose(algc(m2, k, xs1, take(k, ys)), (algc(m-m2, n-k, xs2, leave(k, ys)))) + +fun lcss(xs, ys) = algc(listLen(xs), listLen(ys), xs, ys)(Nil) + +fun lcssMain(a, b ,c, d, e, f) = lcss(enumFromThenTo(a,b,c), enumFromThenTo(d,e,f)) + +fun testLCSS_nofib(d) = lcssMain(1,2,60,30,31,90) + + + +fun main() = testLCSS_nofib(0).toString() + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/life.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/life.mls new file mode 100644 index 0000000000..b7da7faf38 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/life.mls @@ -0,0 +1,110 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module life with ... + + +fun last(a_t) = + fun go(h, t) = if t is + Nil then h + head :: t then go(head, t) + if a_t is a :: t then go(a, t) + +fun copy_lz(n, x) = lazy of () => + if n === 0 then LzNil else LzCons(x, copy_lz(n - 1, x)) + +fun append_lz_lz(xs, ys) = lazy of () => + if force(xs) is + LzNil then force(ys) + LzCons(h, t) then LzCons(h, append_lz_lz(t, ys)) + +fun init(ls) = if ls is + a :: Nil then Nil + a :: t then a :: init(t) + else throw Error(ls) + +fun zipWith3(f, xs, ys, zs) = if + xs is hx :: tx and ys is hy :: ty and zs is hz :: tz then f(hx, hy, hz) :: zipWith3(f, tx, ty, tz) + else Nil + +fun zip3(xs, ys, zs) = if + xs is hx :: tx and ys is hy :: ty and zs is hz :: tz then [hx, hy, hz] :: zip3(tx, ty, tz) + else Nil + +fun lzfy(ls) = lazy of () => + if ls is + a :: t then LzCons(a, lzfy(t)) + else LzNil + +val start = + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + (lazy of () => LzNil) :: + lzfy(0 :: 0 :: 0 :: 1 :: 1 :: 1 :: 1 :: 1 :: 0 :: 1 :: 1 :: 1 :: 1 :: 1 :: 0 :: 1 :: 1 :: 1 :: 1 :: 1 :: 0 :: 1 :: 1 :: 1 :: 1 :: 1 :: 0 :: Nil) :: Nil +//│ start = [Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function])] + +fun elt(a_b_c, d_e_f, g_h_i) = if a_b_c is [a, b, c] and d_e_f is [d, e, f] and g_h_i is [g, h, i] then + let tot = a + b + c + d + f + g + h + i + if + tot < 2 || tot > 3 then 0 + tot === 3 then 1 + else e + +fun shiftr(x, xs) = x :: init(xs) + +fun shiftl(x, xs) = init(xs) +: (x :: Nil) + +fun shift(x, xs) = zip3(shiftr(x, xs), xs, shiftl(x, xs)) + +fun row(last_this_next) = if last_this_next is [last, this_, next] then + zipWith3(elt, shift(0, last), shift(0, this_), shift(0, next)) + +fun gen(n, board) = map(row, shift(replicate(n, 0), board)) + +fun star(x) = if x === + 0 then nofibStringToList(" ") + 1 then nofibStringToList(" o") + +fun glue(s, xs, ys) = xs +: s +: ys + +fun limit(ls) = if force(ls) is + LzCons(x, ys) and force(ys) is LzCons(y, xs) and + listEqBy(listEq, x, y) then x :: Nil + else x :: limit(lazy of () => LzCons(y, xs)) + +fun disp(gen_xss) = if gen_xss is [genn, xss] then lazy of () => + genn +: + nofibStringToList("nn") +: + foldr((a, b) => glue("n" :: Nil, a, b), Nil, map(x => concat(map(star, x)), xss)) + +fun generations(sz) = + map of + disp + zip_lz_nl of + map_lz(i => nofibStringToList(stringOfInt(i)), enumFrom(0)), + limit of iterate of + b => gen(sz, b) + take_lz of + sz + map_lz of + l => take_lz(sz, append_lz_lz(l, copy_lz(sz, 0))), + append_nl_lz(start, copy_lz(sz, copy_lz(sz, 0))) + +fun testLife_nofib(n) = listLen(force(last(generations(n)))) + +fun main() = testLife_nofib(15) + + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/mandel.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/mandel.mls new file mode 100644 index 0000000000..1e0e8cb29a --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/mandel.mls @@ -0,0 +1,77 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module mandel with ... + + + +data class Pixmap(a: Int, b: Int, c: Int, d:List[[Int, Int, Int]]) + +fun createPixmap(width, height, max, colours) = Pixmap(width, height, max, colours) + +data class Complex(r: Num, i: Num) + +fun comp_magnitude(c) = if c is Complex(a, b) then sqrt(a * a + b * b) + +fun comp_times(x, y) = if + x is Complex(a, b) and y is Complex(c, d) then Complex((a * c) - (b * d), (a * d) + (b * c)) + +fun comp_plus(x, y) = if + x is Complex(a, b) and y is Complex(c, d) then Complex(a + c, b + d) + +fun mandel(c) = + fun infiniteMandel() = lazy of () => + LzCons(c, map_lz((z => comp_plus(comp_times(z, z), c)), infiniteMandel())) + infiniteMandel() + +fun diverge(cmplx, radius) = + comp_magnitude(cmplx) > radius + +fun whenDiverge(limit, radius, c) = + fun walkIt(ls) = if force(ls) is + LzNil then 0 + LzCons(x, xs) and + diverge(x, radius) then 0 + else 1 + walkIt(xs) + + walkIt(take_lz_lz(limit, mandel(c))) + +fun parallelMandel(mat, limit, radius) = map(c => whenDiverge(limit, radius, c), mat) + +fun mandelset(x, y, x_, y_, screenX, screenY, lIMIT) = + fun prettyRGB(s) = + let t = lIMIT - s + [s, t, t] + + fun windowToViewport(s, t) = + Complex(x + ((s * (x_ - x)) / screenX), y + ((t * (y_ - y)) / screenY)) + + fun lscomp1(ls1) = if ls1 is + Nil then Nil + t :: t1 then + fun lscomp2(ls2) = if ls2 is + Nil then lscomp1(t1) + s :: t2 then windowToViewport(s, t) :: lscomp2(t2) + lscomp2(enumFromTo(1, screenX)) + + let result = parallelMandel(lscomp1(enumFromTo(1, screenY)), lIMIT, max(x_ - x, y_ - y) / 2) + + createPixmap(screenX, screenY, lIMIT, map(prettyRGB, result)) + + +fun testMandel_nofib(dummy) = + let minx = -2.0 + let miny = -2.0 + let maxx = 2.0 + let maxy = 2.0 + let screenX = 25 + let screenY = 25 + let limit = 75 + mandelset(minx, miny, maxx, maxy, screenX, screenY, limit) + + + +fun main() = testMandel_nofib(0).toString() + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/mandel2.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/mandel2.mls new file mode 100644 index 0000000000..dc5ee1620c --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/mandel2.mls @@ -0,0 +1,128 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + + +module mandel2 with ... + + + +abstract class MandTree: NS | EW | Leaf + +data + class + NS(l: MandTree, r: MandTree) extends MandTree + EW(l: MandTree, r: MandTree) extends MandTree + Leaf(colour: Int) extends MandTree + +val size = 200 +val pmn = -2.25 +val pmx = 0.75 +val qmn = -1.5 +val qmx = 1.5 +val m = 20 +val num_cols = 26 +val delta_p = (pmx - pmn) / (size - 1) +val delta_q = (qmx - qmn) / (size - 1) +val up = [ 0,-1] +val down = [ 0, 1] +val left = [-1, 0] +val right = [ 1, 0] +//│ delta_p = 0.01507537688442211 +//│ delta_q = 0.01507537688442211 +//│ down = [0, 1] +//│ left = [-1, 0] +//│ m = 20 +//│ num_cols = 26 +//│ pmn = -2.25 +//│ pmx = 0.75 +//│ qmn = -1.5 +//│ qmx = 1.5 +//│ right = [1, 0] +//│ size = 200 +//│ up = [0, -1] + +fun equalp(p1, p2) = if p1 is [x1, x2] and p2 is [y1, y2] then (x1 == y1) and (x2 == y2) + +fun np(x) = pmn + (x * delta_p) + +fun nq(y) = qmn + (y * delta_q) + +fun radius(x, y) = (x * x) + (y * y) + +fun new_x(x, y, p) = (x * x) - (y * y) + p + +fun new_y(x, y, q) = (2.0 * x * y) + q + +fun finite(t) = if t is + Leaf(c) then c == c + NS(t1, t2) then finite(t1) and finite(t2) + EW(t1, t2) then finite(t1) and finite(t2) + +fun check_radius(p, q, k, x, y) = + let xn = new_x(x, y, p) + let yn = new_y(x, y, q) + let r = radius(xn, yn) + let kp = k + 1 + if + kp == num_cols then 0 + r > m then kp + else check_radius(p, q, kp, xn, yn) + +fun point_colour(xy) = if xy is [x, y] then check_radius(np(x), nq(y), 0, 0.0, 0.0) + +fun check_perim(x1y1, x2y2) = + let col1 = point_colour(x1y1) + if x1y1 is [x1, y1] and x2y2 is [x2, y2] then + + fun check_line(xcyc, xdyd) = + if xcyc is [xc, yc] and xdyd is [xd, yd] and + let finished = if + equalp(xdyd, right) then xc >= x2 + equalp(xdyd, down) then yc <= y2 + equalp(xdyd, left) then xc <= x1 + else yc >= y1 + finished then true + not(point_colour(xcyc) == col1) then false + else check_line([xc + xd, yc + yd], [xd, yd]) + + if + equalp(x1y1, x2y2) then col1 + let col2 = point_colour([x2, y1]) + let col3 = point_colour(x2y2) + let col4 = point_colour([x1, y2]) + let corners_diff = if (col1 == col2) and (col1 == col3) and (col1 == col4) then false else true + corners_diff then -1 + check_line([x1+1,y1], right) and check_line([x2,y1+1], down) and check_line([x2-1,y2], left) and check_line([x1,y2-1], up) then col1 + else -1 + + +fun build_tree(x1y1, x2y2) = + if x1y1 is [x1, y1] and x2y2 is [x2, y2] then + let rec_col = check_perim(x1y1, x2y2) + if + not(rec_col == -1) then Leaf(rec_col) + let split = if (x2-x1) >= (y2-y1) then "NS" else "EW" + let split_x = intDiv((x2+x1), 2) + let split_y = intDiv((y2+y1), 2) + let nsp1 = x1y1 + let nsp2 = [split_x, y2] + let nsp3 = [split_x+1, y1] + let nsp4 = x2y2 + let ewp1 = x1y1 + let ewp2 = [x2, split_y] + let ewp3 = [x1, split_y+1] + let ewp4 = x2y2 + split == "NS" then NS(build_tree(nsp1, nsp2), build_tree(nsp3, nsp4)) + else EW(build_tree(ewp1, ewp2), build_tree(ewp3, ewp4)) + +fun testMandel2_nofib(n) = + finite(build_tree([0,0], [size, intDiv(size, 2)])) + + + +fun main() = testMandel2_nofib(0) + + + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/mate.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/mate.mls new file mode 100644 index 0000000000..690c1c40b3 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/mate.mls @@ -0,0 +1,557 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module mate with ... + + + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun rqpart(le, x, ys, rle, rgt, r) = if ys is + Nil then qsort(le, rle, x :: qsort(le, rgt, r)) + y :: ys and + le(y, x) then rqpart(le, x, ys, y :: rle, rgt, r) + else rqpart(le, x, ys, rle, y :: rgt, r) + +fun rqsort(le, xs, r) = if xs is + Nil then r + x :: Nil then x :: r + x :: xs then rqpart(le, x, xs, Nil, Nil, r) + +fun qpart(le, x, ys, rlt, rge, r) = if ys is + Nil then rqsort(le, rlt, x :: rqsort(le, rge, r)) + y :: ys and + le(x, y) then qpart(le, x, ys, rlt, y :: rge, r) + else qpart(le, x, ys, y :: rlt, rge, r) + +fun qsort(le, xs, r) = if xs is + Nil then r + x :: Nil then x :: r + x :: xs then qpart(le, x, xs, Nil, Nil, r) +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun sort(l) = qsort of + (a, b) => if a is [aa, _] and b is [bb, _] then listLen(aa) <= listLen(bb) + l + Nil + +abstract class Kind: King | Queen | Rook | Bishop | Knight | Pawn + +object + King extends Kind + Queen extends Kind + Rook extends Kind + Bishop extends Kind + Knight extends Kind + Pawn extends Kind + +abstract class Colour: Black | White + +object + Black extends Colour + White extends Colour + +type Piece = [Colour,Kind] + +type Square = [Int,Int] + +data class Board(a: List[[Kind, Square]], b: List[[Kind, Square]]) + +data class Move(a: Square, b: Option[Piece], c: Option[Piece]) + +data class MoveInFull(a: Piece, b: Square, c: Move) + +data class Solution(a: MoveInFull, b: List[[List[MoveInFull],Solution]]) + +fun maybe(d, f, x) = if x is + None then d + Some(x) then f(x) + +fun isUpper(c) = let x = c.charCodeAt(0) in (x >= 65 and x <= 90) + +fun isLower(c) = let x = c.charCodeAt(0) in (x >= 97 and x <= 122) + +fun toLower(c) = if isUpper(c) then String.fromCharCode(c.charCodeAt(0) + 32) else c + +fun words(s) = if leaveWhile(x => x === " ", s) is + Nil then Nil + s_ and + break_(x => x === " ", s_) is [w, s__] then w :: words(s__) + +fun unlines(ls) = concat(map(l => append(l, "\n" :: Nil), ls)) + +fun lines(s) = if break_(x => x === "\n", s) is [l, s_] then + Cons of + l + if s_ is + Nil then Nil + Cons(_, s__) then lines(s__) + +fun any(p, ls) = if ls is + Nil then false + x :: xs then p(x) || any(p, xs) + +fun showColour(c) = nofibStringToList(if c is Black then "Black" else "White") + +fun pieceAt(bd, sq) = if bd is Board(wkss, bkss) then + fun pieceAtWith(c, n, ls) = if ls is + Nil then n + [k, s] :: xs and + eqTup2(s, sq) then Some([c, k]) + else pieceAtWith(c, n, xs) + pieceAtWith(White, pieceAtWith(Black, None, bkss), wkss) + +fun kindToChar(k) = if k is + King then "K" + Queen then "Q" + Rook then "R" + Bishop then "B" + Knight then "N" + Pawn then "P" + +fun pieceToChar(p) = if p is + [Black, k] then kindToChar(k) + [White, k] then toLower(kindToChar(k)) + +fun showBoard(bd) = + fun showRank(r) = + fun consFile(f, s) = if pieceAt(bd, [f, r]) is + None then nofibStringToList(" -") +: s + Some(p) then " " :: pieceToChar(p) :: s + foldr(consFile, Nil, enumFromTo(1, 8)) + unlines(map(showRank, reverse(enumFromTo(1, 8)))) + +fun showPiece(p) = if p is [c, k] then kindToChar(k) :: Nil + +fun showSquare(c, x_y) = if x_y is [x, y] then + atIndex( + x - 1, + nofibStringToList("QR") :: + nofibStringToList("QN") :: + nofibStringToList("QB") :: + nofibStringToList("Q") :: + nofibStringToList("K") :: + nofibStringToList("KB") :: + nofibStringToList("KN") :: + nofibStringToList("KR") :: Nil + ) +: + nofibStringToList(stringOfInt(if c is Black then 9 - y else y)) + +fun emptyAtAll(bd, e) = if bd is Board(wkss, bkss) then + fun emptyAtAllAnd(b, ls) = if ls is + Nil then b + [_, s] :: xs then (not(e(s)) and emptyAtAllAnd(b, xs)) + emptyAtAllAnd(emptyAtAllAnd(true, bkss), wkss) + +fun rPa(sq, kss) = if kss is + Nil then throw Error("rPa") + [k, s] :: kss then if eqTup2(s, sq) then kss else [k, s] :: rPa(sq, kss) + +fun rmPieceAt(c, sq, bd) = if bd is Board(wkss, bkss) and c is + White then Board(rPa(sq, wkss), bkss) + Black then Board(wkss, rPa(sq, bkss)) + +fun putPieceAt(sq, c_k, bd) = + if c_k is [c, k] and bd is Board(wkss, bkss) and c is + White then Board([k, sq] :: wkss, bkss) + Black then Board(wkss, [k, sq] :: bkss) + +fun kSq(kss) = if kss is + [King, s] :: _ then s + _ :: kss then kSq(kss) + Nil then throw Error("kSq") + +fun kingSquare(c, bd) = if bd is Board(wkss, bkss) and c is + White then kSq(wkss) + Black then kSq(bkss) + +fun opponent(c) = if c is White then Black else White + +fun colourOf(c_k) = if c_k is [c, _] then c + +fun kindOf(c_k) = if c_k is [_, k] then k + +fun onboard(p_q) = if p_q is [p, q] then + (p >= 1 and p <= 8) and (q >= 1 and q <= 8) + +fun forcesColoured(c, bd) = if bd is Board(wkss, bkss) and c is + White then wkss + Black then bkss + +val emptyBoard = Board(Nil, Nil) +//│ emptyBoard = Board([], []) + +fun showMove(withPiece, m) = if m is MoveInFull([c, k], sq, Move(sq_, mcp, mpp)) then + let capt = mcp is Some(_) + let prom = mpp is Some(_) + (if withPiece then + showPiece([c, k]) +: + if ((k === King) || (k is Pawn and not(capt || prom))) then Nil else "/" :: showSquare(c, sq) + else Nil + ) +: + maybe("-" :: Nil, cp => "x" :: append(showPiece(cp), "/" :: Nil), mcp) +: + showSquare(c, sq_) +: + maybe(Nil, pp => "(" :: append(showPiece(pp), ")" :: Nil), mpp) + +fun showMoveInFull(a) = showMove(true, a) + +fun showMovesAfter(p_, mifs) = if mifs is + Nil then Nil + MoveInFull(p, sq, d_) :: mifs and p_ is MoveInFull(p_, sq_, _) then + nofibStringToList(", ") +: + showMove(not(eqTup2(p, p_)) || not(eqTup2(sq, sq_)), MoveInFull(p, sq, d_)) +: + showMovesAfter(MoveInFull(p, sq, d_), mifs) + +fun showMoves(mifs) = if mifs is + Nil then throw Error("showMoves") + mif :: mifs then + showMoveInFull(mif) +: + showMovesAfter(mif, mifs) + +fun sift(c, bd, ms, sqs) = if sqs is + Nil then ms + sq :: sqs and + onboard(sq) and pieceAt(bd, sq) is + None then sift(c, bd, Move(sq, None, None) :: ms, sqs) + Some(p_) and + colourOf(p_) === c then sift(c, bd, ms, sqs) + else sift(c, bd, Move(sq, Some(p_), None) :: ms, sqs) + else sift(c, bd, ms, sqs) + +fun moveLine(bd, c, sq, inc, cont) = + fun ml(sq, ms) = + let sq_ = inc(sq) + if onboard(sq_) and pieceAt(bd, sq_) is + None then ml(sq_, Move(sq_, None, None) :: ms) + Some(p_) and + not(colourOf(p_) === c) then cont(Move(sq_, Some(p_), None) :: ms) + else cont(ms) + else cont(ms) + ms => ml(sq, ms) + +fun bishopmoves(c, sq, bd) = + (moveLine of + bd + c + sq + case { [x, y] then [x - 1, y + 1] } + moveLine of + bd + c + sq + case { [x, y] then [x + 1, y + 1] } + moveLine of + bd + c + sq + case { [x, y] then [x - 1, y - 1] } + moveLine of + bd + c + sq + case { [x, y] then [x + 1, y - 1] } + x => x + ) of Nil + +fun rookmoves(c, sq, bd) = + (moveLine of + bd + c + sq + case { [x, y] then [x - 1, y] } + moveLine of + bd + c + sq + case { [x, y] then [x + 1, y] } + moveLine of + bd + c + sq + case { [x, y] then [x, y - 1] } + moveLine of + bd + c + sq + case { [x, y] then [x, y + 1] } + x => x + ) of Nil + +fun kingmoves(c, pq, bd) = if pq is [p, q] then + sift of + c + bd + Nil + [p - 1, q + 1] :: + [p, q + 1] :: + [p + 1, q + 1] :: + [p - 1, q] :: + [p + 1, q] :: + [p - 1, q - 1] :: + [p, q - 1] :: + [p + 1, q - 1] :: Nil + +fun knightmoves(c, pq, bd) = if pq is [p, q] then + sift of + c + bd + Nil + [p - 1, q + 2] :: + [p + 1, q + 2] :: + [p - 2, q + 1] :: + [p + 2, q + 1] :: + [p - 2, q - 1] :: + [p + 2, q - 1] :: + [p - 1, q - 2] :: + [p + 1, q - 2] :: Nil + +fun pawnmoves(c, pq, bd) = if pq is [p, q] then + let fwd = if c is White then 1 else -1 + fun promote(xy, mcp) = if xy is [x, y] and + ((c is Black) and y === 1) || ((c is White) and y === 8) then + map( + param => Move([x, y], mcp, Some(param)), + [c, Queen] :: + [c, Rook] :: + [c, Bishop] :: + [c, Knight] :: Nil + ) + else Move([x, y], mcp, None) :: Nil + let movs = + let on1 = [p, q + fwd] + let on2 = [p, q + 2 * fwd] + if pieceAt(bd, on1) is None then + promote(on1, None) +: + (if (q === 2 and c is White) || (q === 7 and c is Black) and pieceAt(bd, on2) is None then + Move(on2, None, None) :: Nil + else Nil) + else Nil + fun lscomp1(ls) = if ls is + Nil then Nil + sq :: sqs then + fun lscomp2(ls) = if ls is + Nil then lscomp1(sqs) + h :: ls and + h is Some(p_) and not(colourOf(p_) === c) then promote(sq, Some(p_)) :: lscomp2(ls) + else lscomp2(ls) + lscomp2(pieceAt(bd, sq) :: Nil) + let caps = concat(lscomp1([p + 1, q + fwd] :: [p - 1, q + fwd] :: Nil)) + movs +: caps + +fun queenmoves(c, sq, bd) = bishopmoves(c, sq, bd) +: rookmoves(c, sq, bd) + +fun kingincheck(c, bd) = + fun givesCheck(kxy) = if kxy is [k, [x, y]] then + fun kthreat(param) = if kingSquare(c, bd) is [xk, yk] and param is + King then (abs(x - xk) <= 1) and (abs(y - yk) <= 1) + Queen then kthreat(Rook) || kthreat(Bishop) + Rook then + ((x === xk) && emptyAtAll(bd, case { [xe, ye] then (xe === xk) && ((min(y, yk) < ye) && (ye < max(y, yk))) } )) || + ((y === yk) && emptyAtAll(bd, case { [xe, ye] then (ye === yk) && ((min(x, xk) < xe) && (xe < max(x, xk))) } )) + Bishop then + (((x + y) === (xk + yk)) && emptyAtAll(bd, case { [xe, ye] then ((xe + ye) === (xk + yk)) && ((min(x, xk) < xe) && (xe < max(x, xk))) } )) || + (((x - y) === (xk - yk)) && emptyAtAll(bd, case { [xe, ye] then ((xe - ye) === (xk - yk)) && ((min(x, xk) < xe) && (xe < max(x, xk))) } )) + Knight then + (((abs(x - xk)) === 2) && ((abs(y - yk)) === 1)) || (((abs(x - xk)) === 1) && ((abs(y - yk)) === 2)) + Pawn then + ((abs(x - xk) === 1) && (if c is Black then yk === (y + 1) else yk === (y - 1))) + kthreat(k) + any(givesCheck, forcesColoured(opponent(c), bd)) + +fun tryMove(c, ksq, m, bd) = if + ksq is [k, sq] and m is Move(sq_, mcp, mpp) then + let p = [c, k] + let bd1 = rmPieceAt(c, sq, bd) + let p_ = maybe(p, x => x, mpp) + let bd2 = maybe( + putPieceAt(sq_, p_, bd1), + dummy => putPieceAt(sq_, p_, rmPieceAt(opponent(c), sq_, bd1)), + mcp + ) + if not(kingincheck(c, bd2)) then Some([MoveInFull(p, sq, Move(sq_, mcp, mpp)), bd2]) else None + else + throw Error(m) + +fun rawmoves(c, ksq, bd) = if ksq is [k, sq] then + let m = if k is + King then kingmoves + Queen then queenmoves + Rook then rookmoves + Bishop then bishopmoves + Knight then knightmoves + Pawn then pawnmoves + let res = m(c, sq, bd) + res + +fun moveDetailsFor(c, bd) = foldr of + (ksq, ms) => foldr of + (rm, ms_) => maybe(x => x, h => (t => h :: t), tryMove(c, ksq, rm, bd))(ms_) + ms + rawmoves(c, ksq, bd) + Nil + forcesColoured(c, bd) + +fun comment(s) = (s is Nil) || listEq(take(2, s), nofibStringToList("--")) + +fun last(ls) = if ls is + x :: Nil then x + h :: t then last(t) + +fun intOfString(s) = globalThis.parseInt(nofibListToString(s)) + +fun parseGoal(ls) = if ls is + gltxt :: Nil then + let ws = words(gltxt) + let c = if listEq(head(ws), nofibStringToList("Black")) then Black else White + let n = intOfString(last(ws)) + [c, n] + else throw Error("parseGoal") + +fun parseSquare(r, f, c) = if c === "-" then Nil else + let clr = if isUpper(c) then Black else White + let kin = if toLower(c) === + "k" then King + "q" then Queen + "r" then Rook + "b" then Bishop + "n" then Knight + "p" then Pawn + [[clr, kin], [f, r]] :: Nil + +fun parseRank(r, x) = concat of zipWith of + (a, b) => parseSquare(r, a, b) + enumFromTo(1, 8) + filter(pp => not(pp === " "), x) + + +fun parseBoard(ls) = + fun addPiece(p_sq, x) = if p_sq is [p, sq] then putPieceAt(sq, p, x) + foldr of + addPiece + emptyBoard + concat(zipWith(parseRank, reverse(enumFromTo(1, 8)), ls)) + +fun parseProblem(s) = + let bdtxt_gltxt = splitAt(8, filter(x => not(comment(x)), s)) + if bdtxt_gltxt is [bdtxt, gltxt] then + let bd = parseBoard(bdtxt) + let gl = parseGoal(gltxt) + [bd, gl] + +fun readProblem(s) = parseProblem(lines(s)) + +fun foldr_lz(f, a, x) = if x is + h :: t then f(h, lazy of () => foldr_lz(f, a, t)) + Nil then a + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun replies(bd, c, n) = + let mds = moveDetailsFor(c, bd) + fun solnAnd(mifb, rest) = if mifb is [mif, b] then + let sm = solution(b, opponent(c), n - 1) + if sm is + None then None + Some(s) and + force(rest) is + None then None + Some(ms) then Some([mif, s] :: ms) + if n + === 0 and + null_(mds) then Some(Nil) + else None + > 0 then foldr_lz(solnAnd, Some(Nil), mds) + else throw Error("n < 0") + +fun solution(bd, c, n) = + fun solnOr(mifb, other) = if mifb is + [mif, b] then + let rsm = replies(b, opponent(c), n - 1) + if rsm is + None then force(other) + Some(Nil) and + kingincheck(opponent(c), b) then + Some(Solution(mif, Nil)) + else force(other) + Some(rs) then Some(Solution(mif, rs)) + if n > 0 then + let mds = moveDetailsFor(c, bd) + foldr_lz(solnOr, None, mds) + else throw Error("n <= 0") +//│ ———————————————————————————————————————————————————————————————————————————————— + +data class Soln(a: MoveInFull, b: List[[List[MoveInFull],Soln]]) + +fun tab(n) = if n <= 0 then Nil else " " :: tab(n - 1) + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun showReplies(rs, n) = if rs is + Nil then Nil + [mifs, s] :: rs then + tab(n) +: + nofibStringToList("if ") +: + if null_(rs) && (listLen(mifs) > 1) then nofibStringToList("others") else showMoves(mifs) +: + nofibStringToList("; ") +: + showSoln(s, n + 1) +: + showReplies(rs, n) + +fun showSoln(s, n) = if s is Soln(mif, rs) then + nofibStringToList(stringOfInt(n)) +: + nofibStringToList(". ") +: + showMoveInFull(mif) +: + if rs is + Nil then nofibStringToList("++\n") + [mifs, s_] :: Nil then + nofibStringToList(", ") +: + (if listLen(mifs) > 1 then nofibStringToList("...") else showMoves(mifs)) +: + nofibStringToList("; ") +: + showSoln(s_, n + 1) + else + nofibStringToList(",\n") +: showReplies(sort(rs), n) +//│ ———————————————————————————————————————————————————————————————————————————————— + + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun compact(s) = if s is Solution(mif, rs) then Soln(mif, foldr(insertCompact, Nil, rs)) + +fun insertCompact(mif_s, ls) = if mif_s is [mif, s] then + fun insert(x, ls) = if ls is + Nil then x :: Nil + y :: ys then if x > y then y :: insert(x, ys) else x :: y :: ys + // TODO: recursive `let` local functions? + let cs = compact(s) + fun ic(ls) = if ls is + Nil then [mif :: Nil, cs] :: Nil + [mifs, cs_] :: etc then + let a = showSoln(cs, 1) + let b = showSoln(cs_, 1) + if + ltList(a, b, (x, y) => x < y, (x, y) => x > y) then [mif :: Nil, cs] :: [mifs, cs_] :: etc + listEq(a, b) then [insert(mif, mifs), cs] :: etc + not(ltList(a, b, (x, y) => x < y, (x, y) => x > y)) then [mifs, cs_] :: ic(etc) + else throw Error("compare error") + ic(ls) +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun showResult(s) = if s is + None then nofibStringToList("No solution!") + Some(s) then showSoln(compact(s), 1) + +fun solve(bd, c, n) = showResult(solution(bd, c, (2 * n) - 1)) + +fun testMate_nofib(dummy) = + let input = nofibStringToList of + fs.readFileSync("./hkmc2/shared/src/test/mlscript/nofib/input/heathcote3.prob").toString() + let bdcn = readProblem(input) + if bdcn is [bd, [c, n]] then + showBoard(bd) +: + nofibStringToList("\n") +: + showColour(c) +: + nofibStringToList(" to move and mate in ") +: + nofibStringToList(stringOfInt(n)) +: + nofibStringToList("\n") +: + nofibStringToList("\n") +: + solve(bd, c, n) + +fun main() = nofibListToString(testMate_nofib(0)) + + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/minimax.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/minimax.mls new file mode 100644 index 0000000000..83e664d4f0 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/minimax.mls @@ -0,0 +1,275 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module minimax with ... + + +fun andd(ls) = if ls is + Nil then true + b :: bs then b && andd(bs) + +abstract class Piece: X | O | Empty + +object + X extends Piece + O extends Piece + Empty extends Piece + +fun eqPiece(p1, p2) = if p1 is + X and p2 is X then true + O and p2 is O then true + Empty and p2 is Empty then true + else false + +abstract class Evaluation: XWin | OWin | Score + +object + XWin extends Evaluation + OWin extends Evaluation + +data class Score(i: Int) extends Evaluation + +fun evaluationEq(x, y) = if x is + XWin and y is XWin then true + OWin and y is OWin then true + Score(i) and y is Score(j) and i === j then true + else false + +data class Branch[A](a: A, cs: List[Branch[A]]) + +fun showEvaluation(e) = if e is + XWin then nofibStringToList("XWin") + OWin then nofibStringToList("OWin") + Score(i) then nofibStringToList("Score ") +: nofibStringToList(stringOfInt(i)) + +val win1 = + (1 :: 1 :: 1 :: Nil) :: + (0 :: 0 :: 0 :: Nil) :: + (0 :: 0 :: 0 :: Nil) :: Nil +//│ win1 = [[1,1,1],[0,0,0],[0,0,0]] + +val win2 = + (0 :: 0 :: 0 :: Nil) :: + (1 :: 1 :: 1 :: Nil) :: + (0 :: 0 :: 0 :: Nil) :: Nil +//│ win2 = [[0,0,0],[1,1,1],[0,0,0]] + +val win3 = + (0 :: 0 :: 0 :: Nil) :: + (0 :: 0 :: 0 :: Nil) :: + (1 :: 1 :: 1 :: Nil) :: Nil +//│ win3 = [[0,0,0],[0,0,0],[1,1,1]] + +val win4 = + (1 :: 0 :: 0 :: Nil) :: + (1 :: 0 :: 0 :: Nil) :: + (1 :: 0 :: 0 :: Nil) :: Nil +//│ win4 = [[1,0,0],[1,0,0],[1,0,0]] + +val win5 = + (0 :: 1 :: 0 :: Nil) :: + (0 :: 1 :: 0 :: Nil) :: + (0 :: 1 :: 0 :: Nil) :: Nil +//│ win5 = [[0,1,0],[0,1,0],[0,1,0]] + +val win6 = + (0 :: 0 :: 1 :: Nil) :: + (0 :: 0 :: 1 :: Nil) :: + (0 :: 0 :: 1 :: Nil) :: Nil +//│ win6 = [[0,0,1],[0,0,1],[0,0,1]] + +val win7 = + (1 :: 0 :: 0 :: Nil) :: + (0 :: 1 :: 0 :: Nil) :: + (0 :: 0 :: 1 :: Nil) :: Nil +//│ win7 = [[1,0,0],[0,1,0],[0,0,1]] + +val win8 = + (0 :: 0 :: 1 :: Nil) :: + (0 :: 1 :: 0 :: Nil) :: + (1 :: 0 :: 0 :: Nil) :: Nil +//│ win8 = [[0,0,1],[0,1,0],[1,0,0]] + +val wins = win1 :: win2 :: win3 :: win4 :: win5 :: win6 :: win7 :: win8 :: Nil +//│ wins = [[[1,1,1],[0,0,0],[0,0,0]],[[0,0,0],[1,1,1],[0,0,0]],[[0,0,0],[0,0,0],[1,1,1]],[[1,0,0],[1,0,0],[1,0,0]],[[0,1,0],[0,1,0],[0,1,0]],[[0,0,1],[0,0,1],[0,0,1]],[[1,0,0],[0,1,0],[0,0,1]],[[0,0,1],[0,1,0],[1,0,0]]] + +fun showPiece(p) = if p is + X then nofibStringToList("X") + O then nofibStringToList("O") + Empty then nofibStringToList(" ") + +fun showRow(ps) = if ps is + p1 :: p2 :: p3 :: Nil then + showPiece(p1) +: nofibStringToList("|") +: showPiece(p2) +: nofibStringToList("|") +: showPiece(p3) + +fun showBoard(rs) = if rs is + r1 :: r2 :: r3 :: Nil then + showRow(r1) +: + nofibStringToList("\n------\n") +: + showRow(r2) +: + nofibStringToList("\n------\n") +: + showRow(r3) +: + nofibStringToList("\n\n") + +fun insert(p, ps, i) = if ps is Cons(p1, Cons(p2, Cons(p3, Nil))) and i === + 1 then p :: p2 :: p3 :: Nil + 2 then p1 :: p :: p3 :: Nil + 3 then p1 :: p2 :: p :: Nil + +fun empty_(x, r) = if + x === 1 and r is Empty :: _ :: _ :: Nil then true + x === 2 and r is _ :: Empty :: _ :: Nil then true + x === 3 and r is _ :: _ :: Empty :: Nil then true + else false + +fun empty(pos, board) = if board is r1 :: r2 :: r3 :: Nil and pos is + [1, x] then empty_(x, r1) + [2, x] then empty_(x, r2) + [3, x] then empty_(x, r3) + +fun placePiece(p, board, pos) = if + not(empty(pos, board)) then Nil + board is r1 :: r2 :: r3 :: Nil and pos is + [1, x] then (insert(p, r1, x) :: r2 :: r3 :: Nil) :: Nil + [2, x] then (r1 :: insert(p, r2, x) :: r3 :: Nil) :: Nil + [3, x] then (r1 :: r2 :: insert(p, r3, x) :: Nil) :: Nil + +fun fullBoard(b) = andd of map of + x => not(eqPiece(x, Empty)) + concat(b) + +fun newPositions(piece, board) = + fun lscomp1(ls) = if ls is + Nil then Nil + x :: xs then + fun lscomp2(ls) = if ls is + Nil then lscomp1(xs) + y :: ys then [x, y] :: lscomp2(ys) + lscomp2(1 :: 2 :: 3 :: Nil) + concat of map of + pos => placePiece(piece, board, pos) + lscomp1(1 :: 2 :: 3 :: Nil) + +val initialBoard = replicate(3, replicate(3, Empty)) +//│ initialBoard = [[Empty,Empty,Empty],[Empty,Empty,Empty],[Empty,Empty,Empty]] + +fun eval(x) = if x === + 3 then XWin + -3 then OWin + else Score(x) + +fun interpret(x, l) = if l is + Nil then Score(x) + Score(y) :: ls then interpret(x + y, ls) + XWin :: _ then XWin + OWin :: _ then OWin + +fun scorePiece(p, score) = if p is + X then score + Empty then 0 + O then -score + +fun map2(f, xs, ys) = if xs is + Nil then Nil + x :: xs and + ys is + y :: ys then f(x, y) :: map2(f, xs, ys) + Nil then Nil + +fun score(board, win) = eval of sum of map of + sum + map2((x, y) => map2(scorePiece, x, y), board, win) + +fun static(board) = interpret(0, map(x => score(board, x), wins)) + +fun repTree(f, g, a) = Branch(a, map(x => repTree(g, f, x), f(a))) + +fun mapTree(f, t) = if t is Branch(a, l) then Branch(f(a), map(x => mapTree(f, x), l)) + +fun prune(n, t) = if t is Branch(a, l) and n + === 0 then Branch(a, Nil) + < 0 then throw Error("Tree.prune: < 0") + else Branch(a, map(x => prune(n - 1, x), l)) + +fun opposite(p) = if p is + X then O + O then X + else throw Error("opposite") + +fun best(f, bs, ss) = if bs is b :: bs and ss is s :: ss then + fun best_(b, s, ls1, ls2) = if ls1 is + Nil and ls2 is Nil then [b, s] + b_ :: bs and ls2 is s_ :: ss and + evaluationEq(s, f(s, s_)) then best_(b, s, bs, ss) + else best_(b_, s_, bs, ss) + best_(b, s, bs, ss) + +fun showMove(m) = if m is [b, e] then + showEvaluation(e) +: nofibStringToList("\n") +: showBoard(b) + +fun max_(e1, e2) = if + e1 is XWin then XWin + e2 is XWin then XWin + e2 is OWin then e1 + e1 is OWin then e2 + e1 is Score(x) and e2 is Score(y) and + x > y then Score(x) + else Score(y) + +fun min_(e1, e2) = if + e1 is OWin then OWin + e2 is OWin then OWin + e2 is XWin then e1 + e1 is XWin then e2 + e1 is Score(x) and e2 is Score(y) and + x < y then Score(x) + else Score(y) + +fun mise(f, g, t) = if t is + Branch(a, Nil) then a + Branch(_, l) then foldr(f, g(OWin, XWin), map(x => mise(g, f, x), l)) + +fun searchTree(p, board) = + prune of + 5 + repTree of + x => newPositions(p, x), + x => newPositions(opposite(p), x), + board + +fun cropTree(t) = if t is + Branch(a, Nil) then Branch(a, Nil) + Branch(Score(x), l) then Branch(Score(x), map(cropTree, l)) + Branch(x, l) then Branch(x, Nil) + +fun bestMove(p, f, g, b) = + mise(f, g, cropTree(mapTree(static, searchTree(p, b)))) + + +fun alternate(player, f, g, board) = if + fullBoard(board) then Nil + evaluationEq(static(board), XWin) then Nil + evaluationEq(static(board), OWin) then Nil + let opposition = opposite(player) + let possibles = newPositions(player, board) + let scores = map(x => bestMove(opposition, g, f, x), possibles) + let boardd_eval = best(f, possibles, scores) + boardd_eval is [boardd, eval] then + [boardd, eval] :: alternate(opposition, g, f, boardd) + +fun prog(input) = + let testBoard = + (Empty :: O :: Empty :: Nil) :: + (Empty :: X :: Empty :: Nil) :: + (Empty :: Empty :: Empty :: Nil) :: Nil + fun board(x) = if x === + "doesn't happen" then testBoard +: testBoard + else testBoard + let game = alternate(X, max_, min_, board(input)) + nofibStringToList("OXO\n") +: + concat of map(showMove, game) + +fun main() = nofibListToString(prog("180000")) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/para.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/para.mls new file mode 100644 index 0000000000..49e62e4e52 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/para.mls @@ -0,0 +1,235 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module para with ... + + + +fun unwords(ws) = if ws is + Nil then Nil + w :: ws then + fun go(vs) = if vs is + Nil then Nil + v :: vs then " " :: (v +: go(vs)) + w +: go(ws) + +fun break_(p, xs) = if xs is + Nil then [Nil, Nil] + x :: xs and + p(x) then [Nil, x :: xs] + break_(p, xs) is [ys, zs] then [x :: ys, zs] + +fun isSpace(c) = c === " " + +fun words(s) = if leaveWhile(isSpace, s) is + Nil then Nil + h :: t and + break_(isSpace, h :: t) is [w, s_] then w :: words(s_) + +fun lines(s) = if break_(x => x === "\n", s) is [l, s_] then + Cons( + l, + if s_ is + Nil then Nil + _ :: s__ then lines(s__) + ) + +fun unlines(ls) = concat(map(l => l +: nofibStringToList("\n"), ls)) + +fun all(p, xs) = if xs is + Nil then true + x :: xs then p(x) && all(p, xs) + +fun fold1(f, g, xs) = if xs is + a :: Nil then g(a) + a :: x then f(a, fold1(f, g, x)) + +fun scan1(f, g, xs) = fold1((a, s) => f(a, head(s)) :: s, a => g(a) :: Nil, xs) + +fun tails(xs) = scan1((a, s) => a :: s, a => a :: Nil, xs) + +fun single(xs) = if xs is + a :: Nil then true + _ then false + +fun minWith(f, xs) = fold1((a, b) => if f(a) < f(b) then a else b, x => x, xs) + +fun new_(w, ls) = (w :: Nil) :: ls + +fun glue(w, ls) = if ls is + l :: ls_ then (w :: l) :: ls_ + +fun formats(txt) = fold1 of + (w, ps) => map(p => new_(w, p), ps) +: map(p => glue(w, p), ps) + x => ((x :: Nil) :: Nil) :: Nil + txt + +val maxw = 70 +//│ maxw = 70 + +fun width(ls) = + fun plus(w, n) = listLen(w) + 1 + n + fold1(plus, listLen, ls) + +fun fits(xs) = width(xs) <= maxw + +fun feasible(a) = all(fits, a) + +val optw = 63 +//│ optw = 63 + +fun cost(ls) = + fun linc(l) = let a = optw - width(l) in a * a + fun plus(l, n) = linc(l) + n + fold1(plus, x => 0, ls) + +fun par0(x) = minWith(cost, filter(feasible, formats(x))) + +fun fitH(ls) = fits(head(ls)) + +fun fst3(a_b_c) = if a_b_c is [a, b, c] then a + +fun snd3(a_b_c) = if a_b_c is [a, b, c] then b + +fun thd3(a_b_c) = if a_b_c is [a, b, c] then c + +fun width_tl(a_b_c) = fst3(a_b_c) + +fun cost_tl(a_b_c) = snd3(a_b_c) + +fun len_tl(a_b_c) = thd3(a_b_c) + +fun tile(ws, a_b) = if a_b is + [Nil, n] then Nil + [m :: ms, n] then + let l = n - m + if splitAt(l, ws) is [ws1, ws2] then + ws1 :: tile(ws2, [leave(l, m :: ms), m]) + +fun null__(a_b) = if a_b is [Nil, Nil] then true else false + +fun single_(a_b) = if a_b is [x, y] then (null_(x) && single(y)) || (single(x) && null_(y)) + + +val nil_ = [Nil, Nil] +//│ nil_ = [[], []] + +fun head_(a_b) = if a_b is [x, y] and + not(null_(x)) then head(x) + else head(y) + +fun last_(a_b) = if a_b is [y, x] and + not(null_(x)) then head(x) + else head(y) + +fun cons_(a, a_b) = if a_b is [x, y] and + not(null_(y)) then [a :: x, y] + else [a :: Nil, x] + +fun snoc_(a, a_b) = if a_b is [y, x] and + not(null_(y)) then [y, a :: x] + else [x, a :: Nil] + +fun tail_(a_b) = if a_b is [x, y] and + null_(x) then [Nil, Nil] + single(x) and splitAt(intDiv(listLen(y), 2), y) is [y0, y1] then + [reverse(y1), y0] + else [tail(x), y] + +fun init_(a_b) = if a_b is [y, x] and + null_(x) then [Nil, Nil] + single(x) and splitAt(intDiv(listLen(y), 2), y) is [y0, y1] then + [y0, reverse(y1)] + else [y, tail(x)] + +fun unformat(a, l) = fold1((xs, ys) => xs +: (a :: Nil) +: ys, x => x, l) + +fun format(a, x) = if + x is Nil then Nil :: Nil + else + fun unknownEq(a, b) = a === b + fun breakk(a, b, xs) = + if unknownEq(a, b) + then Nil :: xs + else (b :: head(xs)) :: tail(xs) + fun start(a, b) = breakk(a, b, Nil :: Nil) + fold1((x, y) => breakk(a, x, y), y => start(a, y), x) + +fun unparas(ls) = unformat(Nil, ls) + +fun paras(ls) = filter(x => listNeq(Nil, x), format(Nil, ls)) + +fun parse(ls) = paras(map(words, lines(ls))) + +fun unparse(ls) = unlines(map(unwords, unparas(ls))) + +fun startr(a) = if + a <= maxw then [cons_([0, 0, 0], nil_), a, 1] + else throw Error("startr param error") + +fun ceildiv(n, m) = intDiv(n + m - 1, m) + +fun fmtWith(par) = unparse(map(x => par(concat(x)), parse(par))) + +fun stepr(w, ps_tw_tl) = if ps_tw_tl is [ps, tw, tl] then + let tot_width = w + 1 + tw + let tot_len = 1 + tl + fun single(p) = len_tl(p) === 0 + fun width_hd(p) = if single(p) then tot_width else tot_width - width_tl(p) - 1 + fun cost(p) = if single(p) then 0 else cost_tl(p) + (let a = optw - width_hd(p) in a * a) + fun old_width_hd(p) = if single(p) then tw else tw - width_tl(p) - 1 + fun new_(p) = if single(p) then [tw, 0, tl] else [tw, cost_tl(p) + (let x = optw - old_width_hd(p) in x * x), tl] + fun trim(ps_pq) = if + null__(ps_pq) then ps_pq + single_(ps_pq) then ps_pq + let ps_p = init_(ps_pq) + let q = last_(ps_pq) + let p = last_(ps_p) + cost(p) <= cost(q) then trim(ps_p) + else ps_pq + fun leave_nofit(ps_p) = if + null__(ps_p) then ps_p + width_hd(last_(ps_p)) > maxw then leave_nofit(init_(ps_p)) + else ps_p + fun bf(p, q) = + let wqh = width_hd(q) + let rqh = maxw - wqh + 1 + if + single(q) && cost_tl(p) === 0 then min(optw - width_hd(p), rqh) + single(q) then rqh + else min(ceildiv(cost(p) - cost(q), 2 * (wqh - width_hd(p))), rqh) + fun myAdd(p, qr_rs) = if + single_(qr_rs) || null__(qr_rs) then cons_(p, qr_rs) + let q = head_(qr_rs) + let r_rs = tail_(qr_rs) + let r = head_(r_rs) + bf(p, q) <= bf(q, r) then myAdd(p, r_rs) + else cons_(p, qr_rs) + [trim(leave_nofit(myAdd(new_(last_(ps)), ps))), tot_width, tot_len] + +fun par3(ws) = + let zs = scan1(stepr, startr, map(listLen, ws)) + tile(ws, [map(x => len_tl(last_(fst3(x))), zs), thd3(head(zs))]) + +fun fmt(x) = unparse(map(par3, concat(parse(x)))) + +val test = + concat of + nofibStringToList("In the constructive programming community it is commonplace to see ") :: + nofibStringToList("formal developments of textbook algorithms. In the algorithm design ") :: + nofibStringToList("community, on the other hand, it may be well known that the textbook ") :: + nofibStringToList("solution to a problem is not the most efficient possible. However, in ") :: + nofibStringToList("presenting the more efficient solution, the algorithm designer will ") :: + nofibStringToList("usually omit some of the implementation details, this creating an ") :: + nofibStringToList("algorithm gap between the abstract algorithm and its concrete ") :: + nofibStringToList("implementation. This is in contrast to the formal development, which ") :: + nofibStringToList("usually presents the complete concrete implementation of the less ") :: + nofibStringToList("efficient solution.\n\n") :: Nil +//│ test = ["I","n"," ","t","h","e"," ","c","o","n","s","t","r","u","c","t","i","v","e"," ","p","r","o","g","r","a","m","m","i","n","g"," ","c","o","m","m","u","n","i","t","y"," ","i","t"," ","i","s"," ","c","o","m","m","o","n","p","l","a","c","e"," ","t","o"," ","s","e","e"," ","f","o","r","m","a","l"," ","d","e","v","e","l","o","p","m","e","n","t","s"," ","o","f"," ","t","e","x","t","b","o","o","k"," ","a","l","g","o","r","i","t","h","m","s","."," ","I","n"," ","t","h","e"," ","a","l","g","o","r","i","t","h","m"," ","d","e","s","i","g","n"," ","c","o","m","m","u","n","i","t","y",","," ","o","n"," ","t","h","e"," ","o","t","h","e","r"," ","h","a","n","d",","," ","i","t"," ","m","a","y"," ","b","e"," ","w","e","l","l"," ","k","n","o","w","n"," ","t","h","a","t"," ","t","h","e"," ","t","e","x","t","b","o","o","k"," ","s","o","l","u","t","i","o","n"," ","t","o"," ","a"," ","p","r","o","b","l","e","m"," ","i","s"," ","n","o","t"," ","t","h","e"," ","m","o","s","t"," ","e","f","f","i","c","i","e","n","t"," ","p","o","s","s","i","b","l","e","."," ","H","o","w","e","v","e","r",","," ","i","n"," ","p","r","e","s","e","n","t","i","n","g"," ","t","h","e"," ","m","o","r","e"," ","e","f","f","i","c","i","e","n","t"," ","s","o","l","u","t","i","o","n",","," ","t","h","e"," ","a","l","g","o","r","i","t","h","m"," ","d","e","s","i","g","n","e","r"," ","w","i","l","l"," ","u","s","u","a","l","l","y"," ","o","m","i","t"," ","s","o","m","e"," ","o","f"," ","t","h","e"," ","i","m","p","l","e","m","e","n","t","a","t","i","o","n"," ","d","e","t","a","i","l","s",","," ","t","h","i","s"," ","c","r","e","a","t","i","n","g"," ","a","n"," ","a","l","g","o","r","i","t","h","m"," ","g","a","p"," ","b","e","t","w","e","e","n"," ","t","h","e"," ","a","b","s","t","r","a","c","t"," ","a","l","g","o","r","i","t","h","m"," ","a","n","d"," ","i","t","s"," ","c","o","n","c","r","e","t","e"," ","i","m","p","l","e","m","e","n","t","a","t","i","o","n","."," ","T","h","i","s"," ","i","s"," ","i","n"," ","c","o","n","t","r","a","s","t"," ","t","o"," ","t","h","e"," ","f","o","r","m","a","l"," ","d","e","v","e","l","o","p","m","e","n","t",","," ","w","h","i","c","h"," ","u","s","u","a","l","l","y"," ","p","r","e","s","e","n","t","s"," ","t","h","e"," ","c","o","m","p","l","e","t","e"," ","c","o","n","c","r","e","t","e"," ","i","m","p","l","e","m","e","n","t","a","t","i","o","n"," ","o","f"," ","t","h","e"," ","l","e","s","s"," ","e","f","f","i","c","i","e","n","t"," ","s","o","l","u","t","i","o","n",".","\n","\n"] + +fun testPara_nofib() = + if null_(test) then Nil else fmt(test) + +fun main() = nofibListToString(testPara_nofib()) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/power.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/power.mls new file mode 100644 index 0000000000..c8de74388c --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/power.mls @@ -0,0 +1,149 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module power with ... + + + +abstract class Pss[T]: Pz | Pc[T] + +type Ps[T] = Lazy[Pss[T]] + +data class Pc[T](f: T, s: Ps[T]) extends Pss[T] + +object Pz extends Pss + +fun list() = lazy of () => Pc(1, list()) + +fun x_() = lazy of () => Pc(0, lazy of () => Pc(1, lazy of () => Pz)) + +fun fromIntegerPs(c) = if + c == 0 then lazy of () => Pz + else lazy of () => Pc(c, lazy of () => Pz) + +fun extract(n, ps) = if + n == 0 then Nil + force(ps) is + Pz then Nil + Pc(x, ps) then x :: extract(n - 1, ps) + +fun dotMult(c, ps) = lazy of () => if force(ps) is + Pz then Pz + Pc(f, fs_) then Pc(c * f, dotMult(c, fs_)) + +fun dotMultSndLz(c, ps) = lazy of () => if force(force(ps)) is + Pz then Pz + Pc(f, fs_) then Pc(c * f, dotMult(c, fs_)) + +fun negatePs(ps) = lazy of () => if force(ps) is + Pz then Pz + Pc(f, fs_) then Pc(-f, negatePs(fs_)) + +fun addPs(fss, gs) = lazy of () => if force(fss) is + Pz then force(gs) + Pc(f, fs_) and force(gs) is + Pz then force(fss) + Pc(g, gs) then Pc(f+g, addPs(fs_, gs)) + +fun minusPs(a, b) = addPs(a, negatePs(b)) + +fun multPs(fss, gss) = lazy of () => if force(fss) is + Pz then Pz + Pc(f, fs_) and force(gss) is + Pz then Pz + Pc(g, gs) then Pc(f*g, addPs(addPs(dotMult(f, gs), dotMult(g, fs_)), multPs(multPs(x_(), fs_), gs))) + +fun multPsFstLz(fss, gss) = lazy of () => if force(force(fss)) is + Pz then Pz + Pc(f, fs_) and force(gss) is + Pz then Pz + Pc(g, gs) then Pc(f*g, addPs(addPs(dotMult(f, gs), dotMult(g, fs_)), multPs(multPs(x_(), fs_), gs))) + +fun powerPs(a, n) = if n <= 0 then fromIntegerPs(1) else multPs(a, powerPs(a, n - 1)) + +fun divPs(fss, gss) = lazy of () => if force(fss) is + Pz and force(gss) is + Pz then throw Error("power series 0/0") + Pc(0, gs) then force(divPs((lazy of () => Pz), gs)) + else Pz + Pc(0, fs_) and force(gss) is + Pc(0, gs) then force(divPs(fs_, gs)) + Pc(g, gs) then + let q = 0 + Pc(q, divPs(addPs(fs_, negatePs(dotMult(q, gs))), lazy of () => Pc(g, gs))) + Pc(f, fs_) and force(gss) is + Pc(g, gs) then + let q = f/g + Pc(q, divPs(addPs(fs_, negatePs(dotMult(q, gs))), lazy of () => Pc(g, gs))) + +fun compose_(fss, gss) = lazy of () => if force(fss) is + Pz then Pz + Pc(f, fs_) and force(gss) is + Pz then Pc(f, lazy of () => Pz) + Pc(0, gs) then Pc(f, multPs(gs, compose_(fs_, lazy of () => Pc(0, gs)))) + else force(addPs((lazy of () => Pc(f, lazy of () => Pz)), multPs(gss, compose_(fs_, gss)))) + +fun composeSndLz_(fss, gss) = lazy of () => if force(fss) is + Pz then Pz + Pc(f, fs_) and force(force(gss)) is + Pz then Pc(f, lazy of () => Pz) + Pc(0, gs) then Pc(f, multPs(gs, compose_(fs_, lazy of () => Pc(0, gs)))) + else force(addPs((lazy of () => Pc(f, lazy of () => Pz)), multPs(gss, composeSndLz_(fs_, gss)))) + +fun revert(fss) = lazy of () => if force(fss) is + Pc(0, fs_) then + fun rs() = lazy of () => Pc(0, divPs(fromIntegerPs(1), compose_(fs_, rs()))) + force(rs()) + Pc(f0, kss) and force(kss) is Pc(f1, gss) and force(gss) is Pz then + Pc(-1/f1, lazy of () => Pc(1/f1, lazy of () => Pz)) + +fun deriv(fss) = lazy of () => if force(fss) is + Pz then Pz + Pc(_, fs_) then + fun deriv1(gss, n) = lazy of () => if force(gss) is + Pz then Pz + Pc(f, fs_) then Pc(n * f, deriv1(fs_, n+1)) + force(deriv1(fs_, 1)) + +fun integral(fs_) = + fun int1(fss, n) = lazy of () => if force(fss) is + Pz then Pz + Pc(f, fs_) then Pc(f/n, int1(fs_, n + 1)) + + lazy of () => Pc(0, int1(fs_, 1)) + + +fun integralLz(fs_) = + fun int1(fss, n) = lazy of () => if force(fss) is + Pz then Pz + Pc(f, fs_) then Pc(f/n, int1(fs_, n + 1)) + + lazy of () => Pc(0, int1(fs_(), 1)) + + +fun sqrtPs(fss) = lazy of () => if force(fss) is + Pz then Pz + Pc(0, gss) and force(gss) is Pc(0, fs_) then Pc(0, sqrtPs(fs_)) + Pc(1, fs_) then + fun qs() = lazy of () => addPs(fromIntegerPs(1), integral(divPs(deriv(lazy of () => Pc(1, fs_)), dotMultSndLz(2, qs())))) + + force(force(qs())) + +fun ts() = lazy of () => Pc(1, multPs(ts(), ts())) + +fun tree() = lazy of () => Pc(0, composeSndLz_(list(), lazy of () => tree())) + +fun cosx() = minusPs((lazy of () => Pc(1, lazy of () => Pz)), integral(integralLz(cosx))) + +fun sinx() = integral(minusPs((lazy of () => Pc(1, lazy of () => Pz)), integralLz(sinx))) + +fun testPower_nofib(p) = + extract(p, minusPs(sinx(), sqrtPs(minusPs(fromIntegerPs(1), powerPs(cosx(), 2))))); + extract(p, minusPs(divPs(sinx(), cosx()), revert(integral(divPs(fromIntegerPs(1), addPs(fromIntegerPs(1), powerPs(x_(), 2))))))); + extract(p, ts()); + extract(p, tree()) + +fun main() = testPower_nofib(14).toString() + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/pretty.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/pretty.mls new file mode 100644 index 0000000000..e8a03507a3 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/pretty.mls @@ -0,0 +1,168 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module pretty with ... + + + +abstract class CSeq: CNil | CAppend | CIndent | CNewline | CStr | CCh + +data + class + CAppend(a: CSeq, b: CSeq) extends CSeq + CIndent(a: Int, b: CSeq) extends CSeq + CStr(a: List[Char]) extends CSeq + CCh(a: Char) extends CSeq + +object + CNil extends CSeq + CNewline extends CSeq + +abstract class PprStyle: PprForUser | PprDebug | PprShowAll | PprInterface + +object + PprForUser extends PprStyle + PprDebug extends PprStyle + PprShowAll extends PprStyle + PprInterface extends PprStyle + +val cNil = CNil +//│ cNil = CNil + +val cNL = CNewline +//│ cNL = CNewline + +fun cAppend(cs1, cs2) = CAppend(cs1, cs2) + +fun cIndent(n, cs) = CIndent(n, cs) + +fun cStr(s) = CStr(s) + +fun cCh(c) = CCh(c) + +fun mkIndent(n, s) = if n + === 0 then s + >= 8 then "\t" :: mkIndent(n - 8, s) + else " " :: mkIndent(n - 1, s) + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun flattenS(nlp, seqs) = if seqs is + Nil then Nil + [col, seq] :: seqs then flatten(col, nlp, seq, seqs) + +fun flatten(n, nlp, cseq, seqs) = if cseq is + CNil then flattenS(nlp, seqs) + CAppend(seq1, seq2) then flatten(n, nlp, seq1, [n, seq2] :: seqs) + CIndent(n_, seq) then flatten(n_ + n, nlp, seq, seqs) + CNewline then "\n" :: flattenS(true, seqs) + CStr(s) and + nlp then mkIndent(n, s +: flattenS(false, seqs)) + else s +: flattenS(false, seqs) + CCh(c) and + nlp then mkIndent(n, c :: flattenS(false, seqs)) + else c :: flattenS(false, seqs) +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun cShow(seq) = flatten(0, true, seq, Nil) + +data class MkPrettyRep(cseq: CSeq, n: Int, b1: Bool, b2: Bool) + +fun ppShow(width, p) = if p(width, false) is + MkPrettyRep(seq, ll, emp, sl) then cShow(seq) + +fun ppUnformatted(p) = if p(80, false) is + MkPrettyRep(seq, ll, emp, sl) then cShow(seq) + +fun ppNil(width, is_vert) = MkPrettyRep(cNil, 0, true, width >= 0) + +fun ppStr(s, width, is_vert) = + let ls = listLen(s) + MkPrettyRep(cStr(s), ls, false, width >= ls) + +fun ppChar(c, width, is_vert) = MkPrettyRep(cCh(c), 1, false, width >= 1) + +fun ppInt(n, width, is_vert) = ppStr(nofibStringToList(stringOfInt(n)), width, is_vert) + +fun pp_SP(a, b) = ppStr(nofibStringToList(", "), a, b) + +fun ppSP(a, b) = ppChar(" ", a, b) + +fun ppLbrack(a, b) = ppChar("[", a, b) + +fun ppRbrack(a, b) = ppChar("]", a, b) + +fun ppLparen(a, b) = ppChar("(", a, b) + +fun ppRparen(a, b) = ppChar(")", a, b) + +fun ppSemi(a, b) = ppChar(";", a, b) + +fun ppComma(a, b) = ppChar(",", a, b) + +fun andL(a, b) = if a then b else false + +fun orL(a, b) = if a then true else b + +fun ppBeside(p1, p2, width, is_vert) = if p1(width, false) is + MkPrettyRep(seq1, ll1, emp1, sl1) and p2(width - ll1, false) is + MkPrettyRep(seq2, ll2, emp2, sl2) then + MkPrettyRep(cAppend(seq1, cIndent(ll1, seq2)), ll1 + ll2, andL(emp1, emp2), andL(width >= 0, andL(sl1, sl2))) + +fun ppBesides(ps) = if ps is + Nil then ppNil + else foldr1((a, b) => (c, d) => ppBeside(a, b, c, d), ps) + +fun ppBesideSP(p1, p2, width, is_vert) = if p1(width, false) is MkPrettyRep(seq1, ll1, emp1, sl1) then + let li = if emp1 then 0 else ll1 + 1 + if p2(width - li, false) is MkPrettyRep(seq2, ll2, emp2, sl2) then + let wi = if emp1 then 0 else 1 + let sp = if orL(emp1, emp2) then cNil else cCh(" ") + MkPrettyRep(cAppend(seq1, cAppend(sp, cIndent(li, seq2))), li + ll2, andL(emp1, emp2), andL(width >= wi, andL(sl1, sl2))) + +fun ppCat(ps) = if ps is Nil then ppNil else foldr1((a, b) => (c, d) => ppBesideSP(a, b, c, d), ps) + +fun ppAbove(p1, p2, width, is_vert) = if p1(width, true) is + MkPrettyRep(seq1, ll1, emp1, sl1) and p2(width, true) is + MkPrettyRep(seq2, ll2, emp2, sl2) then + let nl = if orL(emp1, emp2) then cNil else cNL + MkPrettyRep(cAppend(seq1, cAppend(nl, seq2)), ll2, andL(emp1, emp2), false) + +fun ppAboves(ps, a, b) = if ps is Nil then ppNil(a, b) else foldr1((a, b) => (c, d) => ppAbove(a, b, c, d), ps)(a, b) + +fun ppNest(n, p, width, is_vert) = if + is_vert and p(width - n, true) is MkPrettyRep(seq, ll, emp, sl) then + MkPrettyRep(cIndent(n, seq), ll + n, emp, sl) + else p(width, false) + +fun ppHang(p1, n, p2, width, is_vert) = if p1(width, false) is + MkPrettyRep(seq1, ll1, emp1, sl1) and p2(width - (ll1 + 1), false) is + MkPrettyRep(seq2, ll2, emp2, sl2) and p2(width - n, false) is + MkPrettyRep(seq2_, ll2_, emp2_, sl2_) and + emp1 then p2(width, is_vert) + orL(ll1 <= n, sl2) then + MkPrettyRep(cAppend(seq1, cAppend(cCh(" "), cIndent(ll1 + 1, seq2))), ll1 + 1 + ll2, false, andL(sl1, sl2)) + else MkPrettyRep(cAppend(seq1, cAppend(cNL, cIndent(n, seq2_))), ll2_, false, false) + +fun testPretty_nofib() = + fun pp_word(a, b) = ppStr(nofibStringToList("xxxxx"), a, b) + let pp_words = replicate(50, pp_word) + fun pretty_stuff(a, b) = ppAboves( + ppBesides(((a, b) => ppInt(-42, a, b)) :: ((a, b) => ppChar("@", a, b)) :: ((a, b) => ppStr(nofibStringToList("This is a string"), a, b)) :: Nil) :: + ((a, b) => pp_SP(a, b)) :: + ((a, b) => ppHang( + (a, b) => ppStr(nofibStringToList("This is the label"), a, b), + 8, + ppCat(pp_words), + a, + b + )) :: + Nil, + a, + b + ) + ppShow(80, pretty_stuff) +: nofibStringToList("\n") + +fun main() = nofibListToString(testPretty_nofib()) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/primetest.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/primetest.mls new file mode 100644 index 0000000000..8b3ed2275b --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/primetest.mls @@ -0,0 +1,136 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module primetest with ... + + + +fun even(x) = intMod(x, 2) == 0 + +fun int_val_of_char(x) = int_of_char(x) - 48 + +fun int_val_of_string(s) = + fun f(l, a) = if l is + Nil then a + h :: t then f(t, 10 * a + int_val_of_char(h)) + f(s, 0) + +fun break_(p, ls) = if ls is + Nil then [Nil, Nil] + x :: xs and + p(x) then [Nil, x :: xs] + break_(p, xs) is [ys, zs] then [x :: ys, zs] + +fun lines(s) = if break_(x => x == "|", s) is [l, s_] then + let tt = if s_ is + Nil then Nil + _ :: s__ then lines(s__) + + l :: tt + + +fun makeNumber(b, ls) = foldl((a, x) => a * b + x, 0, ls) + +fun chop(b, n) = + fun chop_(a, n) = if divMod(n, b) is [q, r] and + n == 0 then a + else chop_(r :: a, q) + + chop_(Nil, n) + + +fun powerMod(a, b, m) = + fun f(a, b, c) = + fun g(a, b) = if even(b) then g(intMod(a * a, m), intDiv(b, 2)) else f(a, b - 1, intMod(a * c, m)) + if b == 0 then c else g(a, b) + + if + b == 0 then 1 + let a_ = intMod(a, m) + else f(a_, b - 1, a_) + + +fun log2(x) = listLen(chop(2, x)) + +fun rands(s1, s2) = + let k = intDiv(s1, 53668) + let s1_ = ((40014 * (s1 - (k * 53668))) - (k * 12211)) + let s1__ = (if s1_ < 0 then s1_ + 2147483563 else s1_) + let k_ = intDiv(s2, 52774) + let s2_ = ((40692 * (s2 - (k_ * 52774))) - (k_ * 3791)) + let s2__ = (if s2_ < 0 then s2_ + 2147483399 else s2_) + let z = (s1__ - s2__) + + if z < 1 then lazy of () => LzCons(z + 2147483562, rands(s1__, s2__)) + else lazy of () => LzCons(z, rands(s1__, s2__)) + + +fun randomInts(s1, s2) = + if (1 <= s1) and (s1 <= 2147483562) and (1 <= s2) and (s2 <= 2147483398) then rands(s1, s2) + +fun findKQ(n) = + fun f(k, q) = if divMod(q, 2) is [d, r] and + r == 0 then f(k + 1, d) + else [k, q] + + f(0, n - 1) + + +fun uniform(nns, rrs) = if + nns is n :: Nil and rrs is r :: rs then intMod(r, n) :: Nil + nns is n :: ns and rrs is r :: rs and + let t = intMod(r, n + 1) + t == n then t :: uniform(ns, rs) + else t :: map(x => intMod(x, 65536), rs) + +fun random(n, rs) = + let ns = chop(65536, n) + if splitAt_lz(listLen(ns), rs) is [rs1, rs2] then [makeNumber(65536, uniform(ns, rs1)), rs2] + +fun singleTestX(n, kq, x) = + fun square(x) = intMod(x * x, n) + + fun witness(ls) = if ls is + Nil then false + t :: ts and + t == (n - 1) then true + t == 1 then false + else witness(ts) + + if kq is [k, q] and take_lz(k, iterate(square, powerMod(x, q, n))) is t :: ts then + (t == 1) || (t == (n - 1)) || witness(ts) + + +fun singleTest(n, kq, rs) = if random(n - 2, rs) is [x, rs_] then + [singleTestX(n, kq, 2 + x), rs_] + +fun multiTest(k, rs, n) = + fun mTest(k, rs) = if + k == 0 then [true, rs] + singleTest(n, findKQ(n), rs) is [t, rs_] and + t then mTest(k - 1, rs_) + else [false, rs_] + + if ((n <= 1) || even(n)) then [n==2, rs] else mTest(k, rs) + + +fun doLine(cs, cont, rs) = + let n = int_val_of_string(cs) + if multiTest(100, rs, n) is [t, rs_] and + t then "Probably prime" :: (cont(rs_)) + else "Composite" :: (cont(rs_)) + +fun doInput(state, lls) = if lls is + Nil then Nil + l :: ls then doLine(l, state => doInput(state, ls), state) + +fun process(process_arg1) = doInput(randomInts(111, 47), process_arg1) + +fun testPrimetest_nofib(d) = + let cts = nofibStringToList("24|48|47|1317|8901") + process(lines(cts)) + + +fun main() = testPrimetest_nofib(0).toString() + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/puzzle.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/puzzle.mls new file mode 100644 index 0000000000..4cdf864f34 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/puzzle.mls @@ -0,0 +1,190 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module puzzle with ... + + +abstract class ItemType: Bono | Edge | Larry | Adam + +object + Bono extends ItemType + Edge extends ItemType + Larry extends ItemType + Adam extends ItemType + +fun itemEq(a, b) = if a is + Bono and b is Bono then true + Edge and b is Edge then true + Larry and b is Larry then true + Adam and b is Adam then true + else false + +fun succItem(i) = if i is + Bono then Edge + Edge then Larry + Larry then Adam + +fun isEnd(i) = if i is + Bono then false + Edge then false + Larry then false + Adam then true + +fun itemFromTo(a, b) = if itemEq(a, b) then a :: Nil else a :: itemFromTo(succItem(a), b) + +abstract class BankType: LeftBank | RightBank + +object + LeftBank extends BankType + RightBank extends BankType + +fun bankEq(a, b) = if a is + LeftBank and b is LeftBank then true + RightBank and b is RightBank then true + else false + +data class State(b: BankType, e: BankType, l: BankType, a: BankType) + +fun stateEq(s1, s2) = if s1 is State(a, b, c, d) and s2 is State(e, f, g, h) then + (bankEq(a, e) && bankEq(b, f) && bankEq(c, g) && bankEq(d, h)) + +fun bonoPos(s) = if s is State(a, b, c, d) then a + +fun edgePos(s) = if s is State(a, b, c, d) then b + +fun larryPos(s) = if s is State(a, b, c, d) then c + +fun adamPos(s) = if s is State(a, b, c, d) then d + +val initialState = State(LeftBank, LeftBank, LeftBank, LeftBank) +//│ initialState = State(LeftBank, LeftBank, LeftBank, LeftBank) + +val finalState = State(RightBank, RightBank, RightBank, RightBank) +//│ finalState = State(RightBank, RightBank, RightBank, RightBank) + +fun position(i, s) = if i is + Bono then bonoPos(s) + Edge then edgePos(s) + Larry then larryPos(s) + Adam then adamPos(s) + +fun updateState(s, i, pos) = if s is State(a, b, c, d) and i is + Bono then State(pos, b, c, d) + Edge then State(a, pos, c, d) + Larry then State(a, b, pos, d) + Adam then State(a, b, c, pos) + +fun opposite(b) = if b is + LeftBank then RightBank + RightBank then LeftBank + +fun notSeen(state, states) = + all(case { [_, s] then not(stateEq(state, s)) }, states) + +fun writeItem(i, b, rest) = if i is + Bono and b is LeftBank then nofibStringToList(" Bono | |\n") +: rest + Edge and b is LeftBank then nofibStringToList("The Edge | |\n") +: rest + Larry and b is LeftBank then nofibStringToList(" Larry | |\n") +: rest + Adam and b is LeftBank then nofibStringToList(" Adam | |\n") +: rest + Bono and b is RightBank then nofibStringToList(" | | Bono\n") +: rest + Edge and b is RightBank then nofibStringToList(" | | The Edge\n") +: rest + Larry and b is RightBank then nofibStringToList(" | | Larry\n") +: rest + Adam and b is RightBank then nofibStringToList(" | | Adam\n") +: rest + +fun writeState(state, s) = + nofibStringToList("----------------------------------------\n") +: + writeItem of + Bono + bonoPos(state) + writeItem of + Edge + edgePos(state) + writeItem of + Larry + larryPos(state) + writeItem of + Adam + adamPos(state) + nofibStringToList("----------------------------------------\n") +: s + +fun totalTime(history) = if history is [time, _] :: _ then time + +fun writeHistory(history, x) = if history is + Nil then x + else + foldr( + (timestate, acc) => (s) => if timestate is [time, state] then + nofibStringToList("Time: ") +: nofibStringToList(stringOfInt(totalTime(history) - time)) +: ("\n" :: writeState(state, acc(s))), + x => x, + history + )(x) + +fun writeSolutions(solutions, count, s) = if solutions is + Nil then s + item :: next then + nofibStringToList("Solution ") +: + nofibStringToList(stringOfInt(count)) +: + "\n" :: writeHistory(item, writeSolutions(next, count + 1, s)) + +fun minSolutions(history) = if history is + Nil then Nil + history :: next then + // @tailrec // TODO + fun minAcc(minSoFar, mins, ls) = if ls is + Nil then mins + history :: next then + let total = totalTime(history) + if + minSoFar < total then minAcc(minSoFar, mins, next) + minSoFar === total then minAcc(minSoFar, history :: mins, next) + else minAcc(total, history :: Nil, next) + reverse(minAcc(totalTime(history), history :: Nil, next)) + +fun u2times(i) = if i is + Bono then 10 + Edge then 5 + Larry then 2 + Adam then 1 + +fun transfer(source, dest, location, countdown, history) = + if stateEq(source, dest) then ([countdown, dest] :: history) :: Nil + else + let newHistory = [countdown, dest] :: history + let newLocation = opposite(location) + fun lscomp1(ls) = if ls is + Nil then Nil + item :: xs then + if bankEq(position(item, dest), location) then + let newDest = updateState(dest, item, newLocation) + if notSeen(newDest, history) then + let newTime = countdown + u2times(item) + transfer(source, newDest, newLocation, newTime, newHistory) :: lscomp1(xs) + else lscomp1(xs) + else lscomp1(xs) + let moveOne = concat(lscomp1(itemFromTo(Bono, Adam))) + fun lscomp2(ls) = if ls is + Nil then Nil + i :: xs then + fun lscomp3(ls) = if ls is + Nil then lscomp2(xs) + j :: ys then + if bankEq(position(i, dest), location) and bankEq(position(j, dest), location) then + let newDest = updateState(updateState(dest, i, newLocation), j, newLocation) + if notSeen(newDest, history) then + let newTime = countdown + u2times(i) + transfer(source, newDest, newLocation, newTime, newHistory) :: lscomp3(ys) + else lscomp3(ys) + else lscomp3(ys) + lscomp3(itemFromTo(succItem(i), Adam)) + let moveTwo = concat(lscomp2(itemFromTo(Bono, Larry))) + moveOne +: moveTwo + +fun testPuzzle_nofib(x) = + let time = if listLen(x) === 1 then 0 else throw Error("puzzle expects exactly one argument") + let solutions = transfer(initialState, finalState, RightBank, time, Nil) + let mins = minSolutions(solutions) + writeSolutions(mins, 1, Nil) + +fun main() = nofibListToString(testPuzzle_nofib(2 :: Nil)) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/rsa.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/rsa.mls new file mode 100644 index 0000000000..e6b71c04f0 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/rsa.mls @@ -0,0 +1,81 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module rsa with ... + + + +fun z_of_int(x) = globalThis.BigInt(x) +fun string_of_z(x) = nofibStringToList(x + "") +fun z_add(x, y) = x + y +fun z_mul(x, y) = x * y +fun z_sub(x, y) = x - y +fun z_div(x, y) = x / y +fun z_mod(x, y) = x % y +fun z_equal(x, y) = x === y +fun z_sqr(x) = x * x +fun int_if_char(c) = c.codePointAt(0) + +val const0 = z_of_int(0) +//│ const0 = 0 + +val const31 = z_of_int(31) +//│ const31 = 31 + +val const1 = z_of_int(1) +//│ const1 = 1 + +val const2 = z_of_int(2) +//│ const2 = 2 + +val const128 = z_of_int(128) +//│ const128 = 128 + +fun hash(str) = foldl of + (acc, c) => z_add(z_of_int(int_if_char(c)), z_mul(acc, const31)) + const0 + str + +fun and_(ls) = if ls is + Nil then true + h :: t and + h then and_(t) + else false + +fun unlines(ls) = concat of map(l => l +: ("\n" :: Nil), ls) + +fun even(a) = z_mod(a, const2) === const0 + +fun code(ls) = foldl of + (x, y) => z_add(z_mul(const128, x), z_of_int(int_if_char(y))) + const0 + ls + +fun collect(n, xs) = if + n === 0 then Nil + xs is Nil then Nil + else take(n, xs) :: collect(n, leave(n, xs)) + +fun size(n) = intDiv(listLen(string_of_z(n)) * 47, 100) + +fun encrypt(n, e, s) = unlines of map of + c => string_of_z(power(e, n, code(c))) + collect(size(n), s) +fun power(n, m, x) = if + z_equal(n, const0) then const1 + even(n) then z_mod(z_sqr(power(z_div(n, const2), m, x)), m) + else z_mod(z_mul(x, power(z_sub(n, const1), m, x)), m) + +val intput = nofibStringToList of fs.readFileSync("./hkmc2/shared/src/test/mlscript/nofib/input/rsa.faststdin").toString() +//│ intput = ["m","o","d","u","l","e"," ","R","s","a"," ","(","e","n","c","r","y","p","t",","," ","d","e","c","r","y","p","t",","," ","m","a","k","e","K","e","y","s",")","\n","w","h","e","r","e","\n","\n","\n","e","n","c","r","y","p","t",","," ","d","e","c","r","y","p","t"," ",":",":"," ","I","n","t","e","g","e","r"," ","-",">"," ","I","n","t","e","g","e","r"," ","-",">"," ","S","t","r","i","n","g"," ","-",">"," ","S","t","r","i","n","g","\n","e","n","c","r","y","p","t"," ","n"," ","e"," ","="," ","u","n","l","i","n","e","s"," ","."," ","m","a","p"," ","(","s","h","o","w"," ","."," ","p","o","w","e","r"," ","e"," ","n"," ","."," ","c","o","d","e",")"," ","."," ","c","o","l","l","e","c","t"," ","(","s","i","z","e"," ","n",")","\n","d","e","c","r","y","p","t"," ","n"," ","d"," ","="," ","c","o","n","c","a","t"," ","."," ","m","a","p"," ","(","d","e","c","o","d","e"," ","."," ","p","o","w","e","r"," ","d"," ","n"," ","."," ","r","e","a","d",")"," ","."," ","l","i","n","e","s","\n","\n","-","-","-","-","-","-","-","-"," ","C","o","n","v","e","r","t","i","n","g"," ","b","e","t","w","e","e","n"," ","S","t","r","i","n","g","s"," ","a","n","d"," ","I","n","t","e","g","e","r","s"," ","-","-","-","-","-","-","-","-","-","-","-","\n","\n","c","o","d","e"," ",":",":"," ","S","t","r","i","n","g"," ","-",">"," ","I","n","t","e","g","e","r","\n","c","o","d","e"," ","="," ","f","o","l","d","l"," ","a","c","c","u","m"," ","0","\n"," "," ","w","h","e","r","e"," ","a","c","c","u","m"," ","x"," ","y"," ","="," ","(","1","2","8"," ","*"," ","x",")"," ","+"," ","f","r","o","m","I","n","t","e","g","r","a","l"," ","(","f","r","o","m","E","n","u","m"," ","y",")","\n"] + +fun testRsa_nofib(_) = hash(encrypt( + z_of_int("2036450659413645137870851576872812267542175329986469156678671505255564383842535488743101632280716717779536712424613501441720195827856504007305662157107"), + z_of_int("387784473137902876992546516170169092918207676456888779623592396031349415024943784869634893342729620092877891356118467738167515879252473323905128540213"), + intput +)) + +fun main() = testRsa_nofib(0) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/scc.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/scc.mls new file mode 100644 index 0000000000..58805f2a10 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/scc.mls @@ -0,0 +1,56 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module scc with ... + + + +fun dfs(r, vsns, xs) = if vsns is [vs, ns] and + xs is + Nil then [vs, ns] + x :: xs and + inList(x, vs) then dfs(r, [vs, ns], xs) + dfs(r, [x :: vs, Nil], r(x)) is [vs', ns'] then dfs(r, [vs', (x :: ns') +: ns], xs) + +fun stronglyConnComp(es, vs) = + fun swap(a) = if a is [f, s] then [s, f] + + fun new_range(xys, w) = if xys is + Nil then Nil + [x, y] :: xys and + x == w then y :: new_range(xys, w) + else new_range(xys, w) + + fun span_tree(r, vsns, xs) = if vsns is [vs, ns] and + xs is + Nil then [vs, ns] + x :: xs and + inList(x, vs) then span_tree(r, [vs, ns], xs) + dfs(r, [x :: vs, Nil], r(x)) is [vs', ns'] then span_tree(r, [vs', (x :: ns') :: ns], xs) + + snd of span_tree of + x => new_range(map(swap, es), x) + [Nil, Nil] + snd of dfs of + x => new_range(es, x) + [Nil, Nil] + vs + + +fun testScc_nofib(d) = + let a = 1 + let b = 2 + let c = 3 + let d = 4 + let f = 5 + let g = 6 + let h = 7 + let vertices = a :: b :: c :: d :: f :: g :: h :: Nil + let edges = [b, a] :: [c, b] :: [c, d] :: [c, h] :: [d, c] :: [f, a] :: [f, g] :: [f, h] :: [g, f] :: [h, g] :: Nil + + stronglyConnComp(edges, vertices) + + +fun main() = testScc_nofib(0).toString() + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/secretary.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/secretary.mls new file mode 100644 index 0000000000..87d4e567fd --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/secretary.mls @@ -0,0 +1,46 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + + +module secretary with ... + + + +fun infRand(m, s) = + fun f(x) = lazy(() => LzCons((intMod(x, m) + 1), f(intMod((97 * x + 11), power(2, 7))))) + + f(s) + + +fun simulate(n, m, proc) = + fun lscomp(ls) = if ls is + Nil then Nil + seed :: t then proc(infRand(m, seed)) :: lscomp(t) + + listLen(filter(x => x, lscomp(enumFromTo(1, n)))) / n + + +fun sim(n, k) = + fun proc(rs) = + let xs = take_lz(100, nub_lz(rs)) + let best = 100 + let bestk = maximum(take(k, xs)) + let afterk = leaveWhile(x => x < bestk, leave(k, xs)) + listEq(best :: Nil, take(1, afterk)) + + simulate(n, 100, proc) + + +fun testSecretary_nofib(n) = + fun listcomp(ls) = if ls is + Nil then Nil + h :: t then sim(n, h) :: listcomp(t) + + listcomp(enumFromTo(35, 39)) + + + +// NOTE: original input 5000 +fun main() = testSecretary_nofib(50).toString() + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/sorting.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/sorting.mls new file mode 100644 index 0000000000..93fa7ce3ed --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/sorting.mls @@ -0,0 +1,219 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module sorting with ... + + + +fun int_of_char(c) = c.codePointAt(0) + +object + EQ + GT + LT + +fun compareList(xs, ys) = if xs is + Nil and ys is + Nil then EQ + _ :: _ then LT + _ :: _ and ys is Nil then GT + x :: xs_ and ys is y :: ys_ and + int_of_char(x) === int_of_char(y) then compareList(xs_, ys_) + int_of_char(x) < int_of_char(y) then LT + else GT + +fun gtList(a, b) = compareList(a, b) is GT + +fun leList(a, b) = not(gtList(a, b)) + +fun ltList(a, b) = compareList(a, b) is LT + +fun geList(a, b) = not(ltList(a, b)) + +fun eqList(a, b) = compareList(a, b) is EQ + +fun prependToAll(sep, xs) = if xs is + Nil then Nil + x :: xs_ then sep :: x :: prependToAll(sep, xs_) + +fun intersperse(sep, xs) = if xs is + Nil then Nil + x :: xs_ then x :: prependToAll(sep, xs_) + +fun lines(s) = if + s is Nil then Nil + break_(x => x === "\n", s) is [l, s_] then + let tt = if s_ is + Nil then Nil + _ :: s__ then lines(s__) + l :: tt + +fun unlines(ls) = concat(map(l => l +: ("\n" :: Nil), ls)) + +fun odd(x) = intMod(x, 2) === 0 + +fun z_of_int(x) = globalThis.BigInt(x) + +fun hash(str) = foldl( + (acc, c) => z_of_int(int_of_char(c)) + (acc * z_of_int(31)), + z_of_int(0), + str +) + +fun quickSort(xs) = if xs is + Nil then Nil + x :: xs_ then + fun lscomp1(ls) = if ls is + Nil then Nil + h :: t and + leList(h, x) then h :: lscomp1(t) + else lscomp1(t) + fun lscomp2(ls) = if ls is + Nil then Nil + h :: t and + gtList(h, x) then h :: lscomp2(t) + else lscomp2(t) + quickSort(lscomp1(xs_)) +: (x :: quickSort(lscomp2(xs_))) + +fun select(p, x, ts_fs) = if ts_fs is [ts, fs] and + p(x) then [x :: ts, fs] + else [ts, x :: fs] + +fun partition(p, xs) = foldr((x, y) => select(p, x, y), [Nil, Nil], xs) + +fun quickSort2(xs) = if xs is + Nil then Nil + x :: xs_ then + if partition(y => geList(x, y), xs_) is [lo, hi] then + quickSort2(lo) +: (x :: quickSort2(hi)) + +fun quickerSort(xss) = if xss is + Nil then Nil + x :: Nil then x :: Nil + x :: xs then + fun split(x, lo, hi, ys) = if ys is + Nil then quickerSort(lo) +: (x :: quickerSort(hi)) + y :: ys_ and + leList(y, x) then split(x, y :: lo, hi, ys_) + else split(x, lo, y :: hi, ys_) + split(x, Nil, Nil, xs) + +fun insertSort(xss) = if xss is + Nil then Nil + x :: xs then + fun trins(rev, xs, ys) = if xs is + Nil and ys is y :: ys_ then trins(Nil, reverse(rev) +: (y :: Nil), ys_) + xs and ys is Nil then reverse(rev) +: xs + x :: xs_ and ys is y :: ys_ and + ltList(x, y) then trins(x :: rev, xs_, y :: ys_) + else trins(Nil, reverse(rev) +: (y :: x :: xs_), ys_) + trins(Nil, x :: Nil, xs) + +abstract class Tree[T]: Tip | Branch[T] + +object Tip extends Tree[Nothing] + +data class Branch[T](a: T, l: Tree[T], r: Tree[T]) extends Tree[T] + +fun treeSort(param) = + fun mkTree(innerparam) = + fun to_tree(x, t) = if t is + Tip then Branch(x, Tip, Tip) + Branch(y, l, r) and + leList(x, y) then Branch(y, to_tree(x, l), r) + else Branch(y, l, to_tree(x, r)) + foldr(to_tree, Tip, innerparam) + fun readTree(t) = if t is + Tip then Nil + Branch(x, l, r) then readTree(l) +: (x :: readTree(r)) + readTree(mkTree(param)) + +abstract class Tree2[T]: Tip2 | Twig2[T] | Branch2[T] + +object Tip2 extends Tree2[Nothing] + +data + class + Twig2[T](a: T) extends Tree2[T] + Branch2[T](a: T, l: Tree2[T], r: Tree2[T]) extends Tree2[T] + +fun treeSort2(param) = + fun mkTree(innerparam) = + fun to_tree(x, t) = if t is + Tip2 then Twig2(x) + Twig2(y) and + leList(x, y) then Branch2(y, Twig2(x), Tip2) + else Branch2(y, Tip2, Twig2(x)) + Branch2(y, l, r) and + leList(x, y) then Branch2(y, to_tree(x, l), r) + else Branch2(y, l, to_tree(x, r)) + foldr(to_tree, Tip2, innerparam) + fun readTree(t) = if t is + Tip2 then Nil + Twig2(x) then x :: Nil + Branch2(x, l, r) then readTree(l) +: (x :: readTree(r)) + readTree(mkTree(param)) + +fun heapSort(xs) = + fun heap(k, xs) = if xs is + Nil then Tip + x :: xs_ then to_heap(k, x, heap(k + 1, xs_)) + fun to_heap(k, x, t) = if t is + Tip then Branch(x, Tip, Tip) + Branch(y, l, r) and + leList(x, y) and odd(k) then Branch(x, to_heap(intDiv(k, 2), y, l), r) + leList(x, y) then Branch(x, l, to_heap(intDiv(k, 2), y, r)) + odd(k) then Branch(y, to_heap(intDiv(k, 2), x, l), r) + else Branch(y, l, to_heap(intDiv(k, 2), x, r)) + fun clear(t) = if t is + Tip then Nil + Branch(x, l, r) then x :: clear(mix(l, r)) + fun mix(l, r) = if + l is Tip then r + r is Tip then l + l is Branch(x, l1, r1) and r is Branch(y, l2, r2) and + leList(x, y) then Branch(x, mix(l1, r1), Branch(y, l2, r2)) + else Branch(y, Branch(x, l1, r1), mix(l2, r2)) + clear(heap(0, xs)) + +fun mergeSort(param) = + fun runsplit(run, xs) = if + run is Nil and xs is Nil then Nil + xs is Nil then run :: Nil + run is Nil and xs is x :: xs_ then runsplit(x :: Nil, xs_) + run is r :: rs and xs is x :: xs_ and rs is + Nil and + gtList(x, r) then runsplit(r :: x :: Nil, xs_) + leList(x, r) then runsplit(x :: r :: rs, xs_) + else (r :: rs) :: runsplit(x :: Nil, xs_) + rs and + leList(x, r) then runsplit(x :: r :: rs, xs_) + else (r :: rs) :: runsplit(x :: Nil, xs_) + fun merge_lists(xs) = if xs is + Nil then Nil + x :: xs_ then merge(x, merge_lists(xs_)) + fun merge(xs, ys) = if + xs is Nil then ys + ys is Nil then xs + xs is x :: xs_ and ys is y :: ys_ and + eqList(x, y) then x :: y :: merge(xs_, ys_) + ltList(x, y) then x :: merge(xs_, y :: ys_) + else y :: merge(x :: xs_, ys_) + merge_lists(runsplit(Nil, param)) + +fun mangle(inpt) = + fun sort(param) = + foldr( + (f, g) => x => f(g(x)), + x => x, + intersperse(reverse, (heapSort :: insertSort :: mergeSort :: quickSort :: quickSort2 :: quickerSort :: treeSort :: treeSort2 :: Nil)), + )(param) + unlines(sort(lines(inpt))) + +fun testSorting_nofib(d) = + let f = nofibStringToList of fs.readFileSync("./hkmc2/shared/src/test/mlscript/nofib/input/Main.hs").toString() + hash(mangle(f)) + +fun main() = testSorting_nofib(0) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/sphere.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/sphere.mls new file mode 100644 index 0000000000..aac6cd0e92 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/sphere.mls @@ -0,0 +1,385 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module sphere with ... + + + +val pi = globalThis.Math.PI +val epsilon = 0.000001 +val infinity = 100000000.0 +//│ epsilon = 0.000001 +//│ infinity = 100000000 +//│ pi = 3.141592653589793 + +fun vecadd(a1, a2) = + if a1 is [x1, y1, z1] and a2 is [x2, y2, z2] then + [x1 + x2, y1 + y2, z1 + z2] + +fun vecsub(a1, a2) = + if a1 is [x1, y1, z1] and a2 is [x2, y2, z2] then + [x1 - x2, y1 - y2, z1 - z2] + +fun vecmult(a1, a2) = + if a1 is [x1, y1, z1] and a2 is [x2, y2, z2] then + [x1 * x2, y1 * y2, z1 * z2] + +fun vecsum(param) = foldr(vecadd, [0.0, 0.0, 0.0], param) + +fun vecnorm(xyz) = if xyz is [x, y, z] then + let len = sqrt(x * x + y * y + z * z) + [[x / len , y / len, z / len], len] + +fun vecscale(xyz, a) = if xyz is [x, y, z] then [a * x, a * y, a * z] + +fun vecdot(x1, x2) = if x1 is [x1, y1, z1] and x2 is [x2, y2, z2] then x1 * x2 + y1 * y2 + z1 * z2 + +fun veccross(x1, x2) = if x1 is [x1, y1, z1] and x2 is [x2, y2, z2] then + [(y1 * z2) - (y2 * z1), (z1 * x2) - (z2 * x1), (x1 * y2) - (x2 * y1)] + +fun is_zerovector(x) = if x is [x, y, z] then (x < epsilon) && (y < epsilon) && (z < epsilon) + +abstract class Light: Directional | Point + +data + class + Directional(x: [Num, Num, Num], y: [Num, Num, Num]) extends Light + Point(x: [Num, Num, Num], y: [Num, Num, Num]) extends Light + +fun lightpos(p) = if p is Point(pos, col) then pos + +fun lightdir(d) = if d is Directional(dir, col) then fst(vecnorm(dir)) + +fun lightcolour(x) = if x is + Directional(dir, col) then col + Point(pos, col) then col + +abstract class Surfspec: Ambient | Diffuse | Specular | Specpow | Reflect | Transmit | Refract | Body + +data + class + Ambient(v: [Num, Num, Num]) extends Surfspec + Diffuse(v: [Num, Num, Num]) extends Surfspec + Specular(v: [Num, Num, Num]) extends Surfspec + Specpow(v: Num) extends Surfspec + Reflect(v: Num) extends Surfspec + Transmit(v: Num) extends Surfspec + Refract(v: Num) extends Surfspec + Body(v: [Num, Num, Num]) extends Surfspec + +fun ambientsurf(ss) = + fun lscomp(ls) = if ls is + Nil then Nil + x :: t and + x is Ambient(s) then s :: lscomp(t) + else lscomp(t) + + head(append(lscomp(ss), ([0.0, 0.0, 0.0] :: Nil))) + + +fun diffusesurf(ss) = + fun lscomp(ls) = if ls is + Nil then Nil + x :: t and + x is Diffuse(s) then s :: lscomp(t) + else lscomp(t) + + head(append(lscomp(ss), ([0.0, 0.0, 0.0] :: Nil))) + + +fun specularsurf(ss) = + fun lscomp(ls) = if ls is + Nil then Nil + x :: t and + x is Specular(s) then s :: lscomp(t) + else lscomp(t) + + head(append(lscomp(ss), ([0.0, 0.0, 0.0] :: Nil))) + + +fun specpowsurf(ss) = + fun lscomp(ls) = if ls is + Nil then Nil + x :: t and + x is Specpow(s) then s :: lscomp(t) + else lscomp(t) + + head(append(lscomp(ss), (8.0 :: Nil))) + + +fun reflectsurf(ss) = + fun lscomp(ls) = if ls is + Nil then Nil + x :: t and + x is Reflect(s) then s :: lscomp(t) + else lscomp(t) + + head(append(lscomp(ss), (0.0 :: Nil))) + + +fun transmitsurf(ss) = + fun lscomp(ls) = if ls is + Nil then Nil + x :: t and + x is Transmit(s) then s :: lscomp(t) + else lscomp(t) + + head(append(lscomp(ss), (0.0 :: Nil))) + + +fun refractsurf(ss) = + fun lscomp(ls) = if ls is + Nil then Nil + x :: t and + x is Refract(s) then s :: lscomp(t) + else lscomp(t) + + head(append(lscomp(ss), (1.0 :: Nil))) + + +fun bodysurf(ss) = + fun lscomp(ls) = if ls is + Nil then Nil + x :: t and + x is Body(s) then s :: lscomp(t) + else lscomp(t) + + head(append(lscomp(ss), ([1.0, 1.0, 1.0] :: Nil))) + + +data class Sphere(pos: [Num, Num, Num], radius: Num, surface: List[Surfspec]) + +fun spheresurf(s) = if s is Sphere(pos, rad, surf) then surf + +val lookat = [0.0, 0.0, 0.0] +val vup = [0.0, 0.0, 1.0] +val fov = 45.0 +val s2 = + Ambient([0.035, 0.0325, 0.025]) :: + Diffuse([0.5, 0.45, 0.35]) :: + Specular([0.8, 0.8, 0.8]) :: + Specpow(3.0) :: + Reflect(0.5) :: + Nil +val testspheres = + Sphere([0.0, 0.0, 0.0], 0.5, s2) :: + Sphere([0.272166, 0.272166, 0.544331], 0.166667, s2) :: + Sphere([0.643951, 0.172546, 0.0], 0.166667, s2) :: + Sphere([0.172546, 0.643951, 0.0], 0.166667, s2) :: + Sphere([-0.371785, 0.0996195, 0.544331], 0.166667, s2) :: + Sphere([-0.471405, 0.471405, 0.0], 0.166667, s2) :: + Sphere([-0.643951, -0.172546, 0.0], 0.166667, s2) :: + Sphere([0.0996195, -0.371785, 0.544331], 0.166667, s2) :: + Sphere([-0.172546, -0.643951, 0.0], 0.166667, s2) :: + Sphere([0.471405, -0.471405, 0.0], 0.166667, s2) :: + Nil +val testlights = + Point([4.0, 3.0, 2.0], [0.288675, 0.288675, 0.288675]) :: + Point([1.0, -4.0, 4.0], [0.288675, 0.288675, 0.288675]) :: + Point([-3.0, 1.0, 5.0], [0.288675, 0.288675, 0.288675]) :: + Nil +val lookfrom = [2.1, 1.3, 1.7] +val background = [0.078, 0.361, 0.753] +//│ background = [0.078, 0.361, 0.753] +//│ fov = 45 +//│ lookat = [0, 0, 0] +//│ lookfrom = [2.1, 1.3, 1.7] +//│ s2 = [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)] +//│ testlights = [Point([4, 3, 2], [0.288675, 0.288675, 0.288675]),Point([1, -4, 4], [0.288675, 0.288675, 0.288675]),Point([-3, 1, 5], [0.288675, 0.288675, 0.288675])] +//│ testspheres = [Sphere([0, 0, 0], 0.5, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([0.272166, 0.272166, 0.544331], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([0.643951, 0.172546, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([0.172546, 0.643951, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([-0.371785, 0.0996195, 0.544331], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([-0.471405, 0.471405, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([-0.643951, -0.172546, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([0.0996195, -0.371785, 0.544331], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([-0.172546, -0.643951, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([0.471405, -0.471405, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)])] +//│ vup = [0, 0, 1] + +fun spherenormal(pos, sp) = if sp is Sphere(spos, rad, _) then + vecscale(vecsub(pos, spos), 1 / rad) + +fun dtor(x) = x * pi / 180.0 + +fun camparams(lookfrom, lookat, vup, fov, winsize) = + let initfirstray = vecsub(lookat, lookfrom) + if vecnorm(initfirstray) is + [lookdir, dist] and vecnorm(veccross(lookdir, vup)) is [scrni, _] and vecnorm(veccross(scrni, lookdir)) is [scrnj, _] then + let xfov = fov + let yfov = fov + let xwinsize = winsize + let ywinsize = winsize + let magx = 2.0 * dist * tan(dtor(xfov/2)) / xwinsize + let magy = 2.0 * dist * tan(dtor(yfov/2)) / ywinsize + let scrnx = vecscale(scrni, magx) + let scrny = vecscale(scrnj, magy) + let firstray = vecsub(initfirstray, vecadd(vecscale(scrnx, (0.5 * xwinsize)), vecscale(scrny, (0.5 * ywinsize)))) + [firstray, scrnx, scrny] + +fun sphereintersect(pos, dir, sp) = + if sp is Sphere(spos, rad, _) then + let m = vecsub(pos, spos) + let bm = vecdot(m, dir) + let m2 = vecdot(m, m) + let disc = (bm * bm) - m2 + (rad * rad) + let slo = -bm - sqrt(disc) + let shi = -bm + sqrt(disc) + if + disc < 0.0 then [false, 0.0] + slo < 0.0 and + shi < 0.0 then [false, 0.0] + else [true, shi] + else [true, slo] + +fun trace(spheres, pos, dir) = + fun f(d1s1, d2s2) = + if d1s1 is [d1, s1] and d2s2 is [d2, s2_] and + d1 < d2 then [d1, s1] + else [d2, s2_] + + fun sphmap(xss) = + if xss is + Nil then Nil + x :: xs and sphereintersect(pos, dir, x) is [is_hit, where_hit] and + is_hit then [where_hit, x] :: sphmap(xs) + else sphmap(xs) + + let dists = sphmap(spheres) + + if (null_(dists)) then + [false, infinity, head(spheres)] + else + if foldr(f, head(dists), tail(dists)) is [mindist, sp] then + [true, mindist, sp] + + +fun refractray(newindex, olddir, innorm) = + let dotp = -vecdot(olddir, innorm) + let matchIdent_17 = if dotp < 0.0 then + [vecscale(innorm, -1.0), -dotp, 1.0 / newindex] + else + [innorm, dotp, newindex] + if matchIdent_17 is + [norm, k, nr] then + let disc = 1.0 - nr * nr * (1.0 - (k * k)) + let t = (nr * k) - sqrt(disc) + if disc < 0.0 then + [true, [0.0, 0.0, 0.0]] + else + ([false, vecadd(vecscale(norm, t), vecscale(olddir, nr))]) + +fun lightdirection(l, pt) = if l is + Directional(dir, col) then [fst(vecnorm(dir)), infinity] + Point(pos, col) then vecnorm(vecsub(pos, pt)) + +fun shadowed(pos, dir, lcolour) = + if trace(testspheres, vecadd(pos, vecscale(dir, epsilon)), dir) is + [is_hit, dist, sp] then + if not(is_hit) then + [false, lcolour] + else + [true, lcolour] + +fun lightray(l, pos, norm, refl, surf) = + if lightdirection(l, pos) is + [ldir, dist] then + let cosangle = vecdot(ldir, norm) + if shadowed(pos, ldir, lightcolour(l)) is + [is_inshadow, lcolour] then + if + is_inshadow then [0.0, 0.0, 0.0] + let diff = diffusesurf(surf) + let spow = specpowsurf(surf) + cosangle <= 0.0 then + let bodycol = bodysurf(surf) + let cosalpha = -vecdot(refl, ldir) + let diffcont = vecmult(vecscale(diff, -cosangle), lcolour) + let speccont = if cosalpha <= 0.0 then [0.0, 0.0, 0.0] else (vecmult(vecscale(bodycol, power(cosalpha, spow)), lcolour)) + vecadd(diffcont, speccont) + let spec = specularsurf(surf) + let cosalpha = vecdot(refl, ldir) + let diffcont = vecmult(vecscale(diff, cosangle), lcolour) + let speccont = if cosalpha < 0.0 then [0.0, 0.0, 0.0] else (vecmult(vecscale(spec, power(cosalpha, spow)), lcolour)) + else vecadd(diffcont, speccont) + +//│ ———————————————————————————————————————————————————————————————————————————————— +fun shade(lights, sp, lookpos, dir, dist, contrib) = + let hitpos = vecadd(lookpos, vecscale(dir, dist)) + let ambientlight = [1.0, 1.0, 1.0] + let surf = spheresurf(sp) + let amb = vecmult(ambientlight, ambientsurf(surf)) + let norm = spherenormal(hitpos, sp) + let refl = vecadd(dir, vecscale(norm, -2.0 * vecdot(dir, norm))) + let diff = vecsum(map(l => (lightray(l, hitpos, norm, refl, surf)), lights)) + let transmitted = transmitsurf(surf) + let simple = vecadd(amb, diff) + let trintensity = vecscale(bodysurf(surf), transmitted) + let matchIdent_1 = + if transmitted < epsilon then + [false, simple] + else + transmitray(lights, simple, hitpos, dir, refractsurf(surf), trintensity, contrib, norm) + if matchIdent_1 is [is_tir, trcol] then + let reflsurf = vecscale(specularsurf(surf), reflectsurf(surf)) + let reflectiv = if is_tir then vecadd(trintensity, reflsurf) else reflsurf + let rcol = if is_zerovector(reflectiv) then trcol else (reflectray(hitpos, refl, lights, reflectiv, contrib, trcol)) + rcol + +fun transmitray(lights, colour, pos, dir, index, intens, contrib, norm) = + let newcontrib = vecmult(intens, contrib) + if refractray(index, dir, norm) is + [is_tir, newdir] then + let nearpos = vecadd(pos, vecscale(newdir, epsilon)) + if trace(testspheres, nearpos, newdir) is + [is_hit, dist, sp] then + let newcol = + if is_hit then + shade(lights, sp, nearpos, newdir, dist, newcontrib) + else + background + if is_zerovector(newcontrib) then + [false, colour] + else + ([false, vecadd(vecmult(newcol, intens), colour)]) + +fun reflectray(pos, newdir, lights, intens, contrib, colour) = + let newcontrib = vecmult(intens, contrib) + let nearpos = vecadd(pos, vecscale(newdir, epsilon)) + if trace(testspheres, nearpos, newdir) is [is_hit, dist, sp] then + let newcol = + if is_hit then + shade(lights, sp, nearpos, newdir, dist, newcontrib) + else + background + if is_zerovector(newcontrib) then + colour + else + (vecadd(colour, vecmult(newcol, intens))) +//│ ———————————————————————————————————————————————————————————————————————————————— + +fun tracepixel(spheres, lights, x, y, firstray, scrnx, scrny) = + let pos = lookfrom + if vecnorm(vecadd(vecadd(firstray, vecscale(scrnx, x)), vecscale(scrny, y))) is [dir, tracepixel_Tup2_1] and trace(spheres, pos, dir) is [hit, dist, sp] and + hit then shade(lights, sp, pos, dir, dist, [1.0, 1.0, 1.0]) + else background + +fun z_of_int(x) = globalThis.BigInt(x) + +fun hash(param) = + fun u8(x) = z_of_int(round(255 * x)) + foldr(((rgb, acc) => if rgb is [r, g, b] then u8(r) + (u8(g) * z_of_int(7)) + (u8(b) * z_of_int(23)) + (acc * z_of_int(61))), z_of_int(0), param) + +fun ray(winsize) = + let lights = testlights + if camparams(lookfrom, lookat, vup, fov, winsize) is [firstray, scrnx, scrny] then + fun f(i, j) = tracepixel(testspheres, lights, i, j, firstray, scrnx, scrny) + fun lscomp1(ls1) = if ls1 is + Nil then Nil + i :: t1 then + fun lscomp2(ls2) = if ls2 is + Nil then lscomp1(t1) + j :: t2 then [[i, j], f(i, j)] :: lscomp2(t2) + lscomp2(enumFromTo(0, winsize - 1)) + lscomp1(enumFromTo(0, winsize - 1)) + +fun run(winsize) = hash(map(snd, ray(winsize))) + +fun testSphere_nofib(n) = run(n) + + +fun main() = testSphere_nofib(30) + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/treejoin.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/treejoin.mls new file mode 100644 index 0000000000..b0bad99e42 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib-deforest/treejoin.mls @@ -0,0 +1,78 @@ +import "./NofibPrelude.mls" +import "../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls" +open NofibPrelude + +module treejoin with ... + + + +fun isSpace(c) = c === " " || c === "\n" + +fun isDigit(c) = + let n = c.codePointAt(0) + in n >= 48 && n <= 57 + +abstract class Tree[E]: Node | Leaf | Empty + +data + class + Node[E](k: Int, l: Tree[E], r: Tree[E]) extends Tree[E] + Leaf[E](k: Int, e: E) extends Tree[E] + +object Empty extends Tree + +fun insertT(k, e, t) = if t is + Node(k_, l, r) and + k <= k_ then Node(k_, insertT(k, e, l), r) + else Node(k_, l, insertT(k, e, r)) + Leaf(k_, k__) then + let l_ = Leaf(k, e) + if k + < k_ then Node(k, l_, Leaf(k_, k__)) + > k_ then Node(k_, Leaf(k_, k__), l_) + else throw Error("already exist") + Empty then Leaf(k, e) + +fun lookupT(k, t) = if t is + Node(k_, l, r) and + k <= k_ then lookupT(k, l) + else lookupT(k, r) + Leaf(k_, e) then if k === k_ then Some(e) else None + Empty then None + +fun readInt(s) = + fun readInt_(n, cs) = if cs is + c :: cs_ and + isDigit(c) then readInt_(n * 10 + c.codePointAt(0) - 48, cs_) + else let s_ = leaveWhile(isSpace, c :: cs) in [n, s_] + else + let s_ = leaveWhile(isSpace, cs) in [n, s_] + readInt_(0, s) + +fun join(t1, t2, j) = if + t1 is Empty then j + t2 is Empty then j + t1 is Leaf(k, [a, b, c]) and lookupT(c, t2) is + None then j + Some([d, e, f]) then insertT(c, [a, b, c, d, e], j) + t1 is Node(k, l, r) then join(l, t2, join(r, t2, j)) + +fun readTree(fk, s, t) = if + s is Nil then t + readInt(s) is [f, s_] and + readInt(s_) is [g, s__] and + readInt(s__) is [h, s___] then + let e = [f, g, h] + let k = fk(e) + readTree(fk, s___, insertT(k, e, t)) + + +fun testTreejoin_nofib(n) = + let c1 = nofibStringToList of fs.readFileSync("./hkmc2/shared/src/test/mlscript/nofib/input/1500.1").toString() + let c2 = nofibStringToList of fs.readFileSync("./hkmc2/shared/src/test/mlscript/nofib/input/1500.2").toString() + let a = readTree(case { [xx, _, _] then xx }, c1, Empty) + let b = readTree(case { [xx, _, _] then xx }, c2, Empty) + join(a, b, Empty) + +fun main() = testTreejoin_nofib(0).toString() + diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/NofibPrelude.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/NofibPrelude.mls new file mode 120000 index 0000000000..bd0372db0b --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/NofibPrelude.mls @@ -0,0 +1 @@ +../nofib-deforest/NofibPrelude.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/ansi.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/ansi.mls new file mode 120000 index 0000000000..356f13f055 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/ansi.mls @@ -0,0 +1 @@ +../nofib-deforest/ansi.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/atom.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/atom.mls new file mode 120000 index 0000000000..2b828ef827 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/atom.mls @@ -0,0 +1 @@ +../nofib-deforest/atom.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/awards.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/awards.mls new file mode 120000 index 0000000000..7db954ad34 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/awards.mls @@ -0,0 +1 @@ +../nofib-deforest/awards.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/banner.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/banner.mls new file mode 120000 index 0000000000..ad9bd797ac --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/banner.mls @@ -0,0 +1 @@ +../nofib-deforest/banner.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/boyer.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/boyer.mls new file mode 120000 index 0000000000..7ab6161efa --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/boyer.mls @@ -0,0 +1 @@ +../nofib-deforest/boyer.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/boyer2.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/boyer2.mls new file mode 120000 index 0000000000..dcd535f78b --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/boyer2.mls @@ -0,0 +1 @@ +../nofib-deforest/boyer2.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/calendar.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/calendar.mls new file mode 120000 index 0000000000..382a5cf60a --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/calendar.mls @@ -0,0 +1 @@ +../nofib-deforest/calendar.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cichelli.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cichelli.mls new file mode 120000 index 0000000000..a733ec5366 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cichelli.mls @@ -0,0 +1 @@ +../nofib-deforest/cichelli.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/circsim.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/circsim.mls new file mode 120000 index 0000000000..59a32735c9 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/circsim.mls @@ -0,0 +1 @@ +../nofib-deforest/circsim.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/clausify.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/clausify.mls new file mode 120000 index 0000000000..560d4343f0 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/clausify.mls @@ -0,0 +1 @@ +../nofib-deforest/clausify.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/constraints.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/constraints.mls new file mode 120000 index 0000000000..567df58a98 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/constraints.mls @@ -0,0 +1 @@ +../nofib-deforest/constraints.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cryptarithm1.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cryptarithm1.mls new file mode 120000 index 0000000000..722c4ba0bb --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cryptarithm1.mls @@ -0,0 +1 @@ +../nofib-deforest/cryptarithm1.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cryptarithm2.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cryptarithm2.mls new file mode 120000 index 0000000000..db84eee01c --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cryptarithm2.mls @@ -0,0 +1 @@ +../nofib-deforest/cryptarithm2.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cse.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cse.mls new file mode 120000 index 0000000000..0a1b23ccec --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/cse.mls @@ -0,0 +1 @@ +../nofib-deforest/cse.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/eliza.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/eliza.mls new file mode 120000 index 0000000000..2da77ec5f2 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/eliza.mls @@ -0,0 +1 @@ +../nofib-deforest/eliza.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/gcd.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/gcd.mls new file mode 120000 index 0000000000..c3af195e75 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/gcd.mls @@ -0,0 +1 @@ +../nofib-deforest/gcd.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/integer.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/integer.mls new file mode 120000 index 0000000000..f0b77d584f --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/integer.mls @@ -0,0 +1 @@ +../nofib-deforest/integer.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/knights.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/knights.mls new file mode 120000 index 0000000000..e5397973a3 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/knights.mls @@ -0,0 +1 @@ +../nofib-deforest/knights.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/lambda.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/lambda.mls new file mode 120000 index 0000000000..7cf4f3ff7e --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/lambda.mls @@ -0,0 +1 @@ +../nofib-deforest/lambda.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/lastpiece.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/lastpiece.mls new file mode 120000 index 0000000000..8d5bb05b23 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/lastpiece.mls @@ -0,0 +1 @@ +../nofib-deforest/lastpiece.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/lcss.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/lcss.mls new file mode 120000 index 0000000000..d2db5f4c51 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/lcss.mls @@ -0,0 +1 @@ +../nofib-deforest/lcss.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/life.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/life.mls new file mode 120000 index 0000000000..7b3bf9f08d --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/life.mls @@ -0,0 +1 @@ +../nofib-deforest/life.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/mandel.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/mandel.mls new file mode 120000 index 0000000000..89fd16e9a6 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/mandel.mls @@ -0,0 +1 @@ +../nofib-deforest/mandel.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/mandel2.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/mandel2.mls new file mode 120000 index 0000000000..5913e6864c --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/mandel2.mls @@ -0,0 +1 @@ +../nofib-deforest/mandel2.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/mate.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/mate.mls new file mode 120000 index 0000000000..9ac7e0d1f6 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/mate.mls @@ -0,0 +1 @@ +../nofib-deforest/mate.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/minimax.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/minimax.mls new file mode 120000 index 0000000000..0710316c09 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/minimax.mls @@ -0,0 +1 @@ +../nofib-deforest/minimax.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/para.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/para.mls new file mode 120000 index 0000000000..86fdd4e7bb --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/para.mls @@ -0,0 +1 @@ +../nofib-deforest/para.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/power.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/power.mls new file mode 120000 index 0000000000..57391805c0 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/power.mls @@ -0,0 +1 @@ +../nofib-deforest/power.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/pretty.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/pretty.mls new file mode 120000 index 0000000000..f7debfc615 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/pretty.mls @@ -0,0 +1 @@ +../nofib-deforest/pretty.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/primetest.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/primetest.mls new file mode 120000 index 0000000000..53e8d3ca6f --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/primetest.mls @@ -0,0 +1 @@ +../nofib-deforest/primetest.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/puzzle.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/puzzle.mls new file mode 120000 index 0000000000..f2e54b3d51 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/puzzle.mls @@ -0,0 +1 @@ +../nofib-deforest/puzzle.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/rsa.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/rsa.mls new file mode 120000 index 0000000000..d677d33e46 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/rsa.mls @@ -0,0 +1 @@ +../nofib-deforest/rsa.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/scc.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/scc.mls new file mode 120000 index 0000000000..2fc8647363 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/scc.mls @@ -0,0 +1 @@ +../nofib-deforest/scc.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/secretary.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/secretary.mls new file mode 120000 index 0000000000..6ed2707baa --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/secretary.mls @@ -0,0 +1 @@ +../nofib-deforest/secretary.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/sorting.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/sorting.mls new file mode 120000 index 0000000000..f727876968 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/sorting.mls @@ -0,0 +1 @@ +../nofib-deforest/sorting.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/sphere.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/sphere.mls new file mode 120000 index 0000000000..0ff9bf3abe --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/sphere.mls @@ -0,0 +1 @@ +../nofib-deforest/sphere.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/treejoin.mls b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/treejoin.mls new file mode 120000 index 0000000000..d03c195ac0 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/mlscript-compile/nofib/treejoin.mls @@ -0,0 +1 @@ +../nofib-deforest/treejoin.mls \ No newline at end of file diff --git a/hkmc2Benchmarks/src/test/bench/nofibs.mls b/hkmc2Benchmarks/src/test/bench/nofibs.mls new file mode 100644 index 0000000000..9e78afcc64 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/nofibs.mls @@ -0,0 +1,338 @@ +:js + +import "./mlscript-compile/nofib-deforest/gcd.mjs" +gcd.main() +//│ = 5021 +//│ gcd = class gcd + +:re +import "./mlscript-compile/nofib-deforest/cryptarithm1.mls" +cryptarithm1.main() +//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded + + +import "./mlscript-compile/nofib-deforest/ansi.mls" +ansi.main() +//│ = "LE[5;17HESC[7mDemonstration programESC[0mE[5;48HVersion 1.0E[7;17HThis program illustrates a simple approachE[8;17Hto screen-based interactive programs usingE[9;17Hthe Hugs functional programming system.E[11;17HPlease press any key to continue ...E[15;17HPlease enter your name: E[15;41H__________________E[15;41HesttesttestE[18;31HHello esttesttest!E[23;1HI'm waiting..." + +import "./mlscript-compile/nofib-deforest/atom.mls" +print(atom.main()) +//│ > 1 +//│ > 1 +//│ > 0.9996 +//│ > 0.9988 +//│ > 0.9976001600000001 +//│ > 0.9960008 +//│ > 0.994002399936 +//│ > 0.991605599552 +//│ > 0.9888111982080257 +//│ > 0.9856201546242305 +//│ > 0.982033586561152 +//│ > 0.978052770436224 +//│ > 0.9736791408766714 +//│ > 0.9689142902089444 +//│ > 0.9637599678848666 +//│ > 0.9582180798447053 +//│ > 0.95229068781739 +//│ > 0.9459800085581369 +//│ > 0.9392884130237569 +//│ > 0.9322184254859536 +//│ > + +import "./mlscript-compile/nofib-deforest/awards.mls" +awards.main() +//│ = [[["Simon", [["Gold", [70, [35,1,34]]],["Gold", [88, [27,40,21]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]]]]],[["Simon", [["Gold", [71, [35,2,34]]],["Gold", [88, [27,40,21]]]]],["Hans", [["Gold", [70, [23,45,2]]],["Bronze", [50, [19,17,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [70, [54,2,14]]],["Gold", [73, [9,23,41]]]]]],[["Simon", [["Gold", [70, [27,40,3]]],["Gold", [90, [35,34,21]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [71, [54,3,14]]],["Gold", [73, [9,23,41]]]]]],[["Simon", [["Gold", [71, [27,40,4]]],["Gold", [90, [35,34,21]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]]]]],[["Simon", [["Gold", [72, [27,40,5]]],["Gold", [90, [35,34,21]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]]]]],[["Simon", [["Gold", [73, [27,40,6]]],["Gold", [90, [35,34,21]]]]],["Hans", [["Gold", [70, [19,45,6]]],["Bronze", [50, [23,17,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [70, [23,6,41]]],["Gold", [72, [9,54,9]]]]]],[["Simon", [["Gold", [74, [27,40,7]]],["Gold", [90, [35,34,21]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [70, [9,54,7]]],["Gold", [72, [17,41,14]]],["Bronze", [50, [23,9,18]]]]]],[["Simon", [["Gold", [70, [35,27,8]]],["Gold", [95, [40,34,21]]]]],["Hans", [["Gold", [70, [45,8,17]]],["Bronze", [50, [23,19,8]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [71, [9,54,8]]],["Gold", [72, [17,41,14]]],["Bronze", [50, [23,9,18]]]]]],[["Simon", [["Gold", [70, [27,9,34]]],["Gold", [96, [35,40,21]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [51, [23,19,9]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Bronze", [50, [23,9,18]]]]]],[["Simon", [["Gold", [71, [27,10,34]]],["Gold", [96, [35,40,21]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Bronze", [51, [23,10,18]]]]]],[["Simon", [["Gold", [72, [27,11,34]]],["Gold", [96, [35,40,21]]]]],["Hans", [["Gold", [70, [45,11,14]]],["Bronze", [50, [23,17,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [70, [11,41,18]]],["Gold", [72, [9,54,9]]],["Bronze", [54, [23,17,14]]]]]],[["Simon", [["Gold", [73, [27,12,34]]],["Gold", [96, [35,40,21]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [70, [17,12,41]]],["Gold", [72, [9,54,9]]],["Bronze", [55, [23,18,14]]]]]],[["Simon", [["Gold", [74, [27,13,34]]],["Gold", [96, [35,40,21]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [50, [23,13,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [71, [17,13,41]]],["Gold", [72, [9,54,9]]],["Bronze", [55, [23,18,14]]]]]],[["Simon", [["Gold", [70, [35,14,21]]],["Gold", [101, [27,40,34]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [51, [23,14,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,14,41]]],["Bronze", [55, [23,18,14]]]]]],[["Simon", [["Gold", [70, [15,34,21]]],["Gold", [102, [35,27,40]]]]],["Hans", [["Gold", [70, [45,15,10]]],["Bronze", [50, [19,17,14]]]]],["Phil", [["Gold", [70, [15,21,34]]],["Silver", [60, [20,19,21]]]]],["Kevin", [["Gold", [70, [15,41,14]]],["Gold", [72, [9,54,9]]],["Bronze", [58, [23,17,18]]]]]],[["Simon", [["Gold", [71, [16,34,21]]],["Gold", [102, [35,27,40]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [16,20,34]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [71, [16,41,14]]],["Gold", [72, [9,54,9]]],["Bronze", [58, [23,17,18]]]]]],[["Simon", [["Gold", [72, [17,34,21]]],["Gold", [102, [35,27,40]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [50, [19,17,14]]]]],["Phil", [["Gold", [70, [17,19,34]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Bronze", [58, [23,17,18]]]]]],[["Simon", [["Gold", [73, [18,34,21]]],["Gold", [102, [35,27,40]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Silver", [60, [23,19,18]]]]],["Phil", [["Gold", [70, [18,18,34]]],["Silver", [60, [20,19,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Bronze", [59, [23,18,18]]]]]],[["Simon", [["Gold", [74, [19,34,21]]],["Gold", [102, [35,27,40]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Silver", [61, [23,19,19]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Silver", [60, [23,19,18]]]]]],[["Simon", [["Gold", [75, [20,34,21]]],["Gold", [102, [35,27,40]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Silver", [62, [23,19,20]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [70, [9,20,41]]],["Gold", [77, [54,9,14]]],["Bronze", [58, [23,17,18]]]]]],[["Simon", [["Gold", [76, [21,34,21]]],["Gold", [102, [35,27,40]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Silver", [63, [23,19,21]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [71, [9,21,41]]],["Gold", [77, [54,9,14]]],["Bronze", [58, [23,17,18]]]]]],[["Simon", [["Gold", [70, [27,22,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Silver", [64, [23,19,22]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,22,41]]],["Gold", [77, [54,9,14]]],["Bronze", [58, [23,17,18]]]]]],[["Simon", [["Gold", [71, [27,23,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Silver", [60, [23,23,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]],["Bronze", [50, [23,19,8]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Silver", [64, [23,23,18]]]]]],[["Simon", [["Gold", [72, [27,24,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Silver", [61, [23,24,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]],["Bronze", [51, [24,19,8]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Silver", [65, [23,24,18]]]]]],[["Simon", [["Gold", [73, [27,25,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Silver", [62, [23,25,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]],["Bronze", [52, [25,19,8]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Silver", [66, [23,25,18]]]]]],[["Simon", [["Gold", [74, [27,26,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Silver", [63, [23,26,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]],["Bronze", [53, [26,19,8]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Silver", [67, [23,26,18]]]]]],[["Simon", [["Gold", [75, [27,27,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Silver", [60, [19,27,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]],["Bronze", [54, [27,19,8]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Silver", [68, [23,27,18]]]]]],[["Simon", [["Gold", [76, [27,28,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [23,19,28]]],["Gold", [70, [45,17,8]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [70, [28,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Silver", [69, [23,28,18]]]]]],[["Simon", [["Gold", [77, [27,29,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [71, [23,19,29]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [71, [29,21,21]]]]],["Kevin", [["Gold", [70, [23,29,18]]],["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]]]]],[["Simon", [["Gold", [78, [27,30,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [23,30,17]]],["Gold", [72, [19,45,8]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [70, [30,19,21]]]]],["Kevin", [["Gold", [70, [23,17,30]]],["Gold", [72, [9,54,9]]],["Gold", [73, [41,18,14]]]]]],[["Simon", [["Gold", [79, [27,31,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [73, [23,19,31]]]]],["Phil", [["Gold", [70, [18,31,21]]],["Gold", [70, [20,34,16]]]]],["Kevin", [["Gold", [71, [23,17,31]]],["Gold", [72, [9,54,9]]],["Gold", [73, [41,18,14]]]]]],[["Simon", [["Gold", [80, [27,32,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [74, [23,19,32]]]]],["Phil", [["Gold", [70, [18,32,20]]],["Gold", [71, [21,34,16]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [73, [23,32,18]]]]]],[["Simon", [["Gold", [81, [27,33,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [23,33,14]]],["Gold", [70, [45,17,8]]]]],["Phil", [["Gold", [70, [18,33,19]]],["Gold", [70, [20,34,16]]],["Bronze", [50, [21,8,21]]]]],["Kevin", [["Gold", [70, [23,33,14]]],["Gold", [72, [9,54,9]]],["Gold", [76, [17,41,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [109, [35,40,34]]]]],["Hans", [["Gold", [70, [19,34,17]]],["Gold", [73, [23,45,5]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [71, [18,19,34]]],["Bronze", [50, [21,8,21]]]]],["Kevin", [["Gold", [71, [23,34,14]]],["Gold", [72, [9,54,9]]],["Gold", [76, [17,41,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [110, [35,40,35]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [72, [23,35,14]]]]],["Phil", [["Gold", [70, [1,35,34]]],["Silver", [60, [18,21,21]]],["Bronze", [55, [20,19,16]]]]],["Kevin", [["Gold", [70, [17,35,18]]],["Gold", [72, [9,54,9]]],["Gold", [78, [23,41,14]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [111, [35,40,36]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [73, [23,36,14]]]]],["Phil", [["Gold", [70, [18,36,16]]],["Gold", [73, [20,19,34]]],["Bronze", [50, [21,8,21]]]]],["Kevin", [["Gold", [71, [17,36,18]]],["Gold", [72, [9,54,9]]],["Gold", [78, [23,41,14]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [112, [35,40,37]]]]],["Hans", [["Gold", [70, [19,37,14]]],["Gold", [70, [45,17,8]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [74, [18,37,19]]],["Bronze", [50, [21,8,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,37,18]]],["Gold", [78, [23,41,14]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [113, [35,40,38]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [71, [19,38,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [75, [18,38,19]]],["Bronze", [50, [21,8,21]]]]],["Kevin", [["Gold", [70, [9,23,38]]],["Gold", [72, [17,41,14]]],["Gold", [81, [54,9,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [114, [35,40,39]]]]],["Hans", [["Gold", [70, [23,39,8]]],["Gold", [72, [45,17,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [76, [18,39,19]]],["Bronze", [50, [21,8,21]]]]],["Kevin", [["Gold", [70, [17,39,14]]],["Gold", [72, [9,54,9]]],["Gold", [82, [23,41,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [115, [35,40,40]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [73, [19,40,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [77, [18,40,19]]],["Bronze", [50, [21,8,21]]]]],["Kevin", [["Gold", [71, [17,40,14]]],["Gold", [72, [9,54,9]]],["Gold", [82, [23,41,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [116, [35,40,41]]]]],["Hans", [["Gold", [70, [19,41,10]]],["Gold", [70, [45,17,8]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [70, [41,8,21]]],["Bronze", [58, [18,19,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [82, [23,41,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [117, [35,40,42]]]]],["Hans", [["Gold", [70, [23,42,5]]],["Gold", [70, [45,17,8]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [71, [42,8,21]]],["Bronze", [58, [18,19,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [83, [23,42,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [118, [35,40,43]]]]],["Hans", [["Gold", [70, [19,43,8]]],["Gold", [72, [45,17,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [70, [43,19,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [70, [9,43,18]]],["Gold", [72, [17,41,14]]],["Gold", [86, [23,54,9]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [119, [35,40,44]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [72, [23,44,5]]]]],["Phil", [["Gold", [70, [18,44,8]]],["Gold", [70, [20,34,16]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [70, [9,17,44]]],["Gold", [73, [23,41,9]]],["Gold", [86, [54,18,14]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [120, [35,40,45]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [73, [23,45,5]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [71, [18,45,8]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [71, [9,17,45]]],["Gold", [73, [23,41,9]]],["Gold", [86, [54,18,14]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [121, [35,40,46]]]]],["Hans", [["Gold", [70, [19,46,5]]],["Gold", [70, [45,17,8]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [72, [18,46,8]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [72, [9,17,46]]],["Gold", [73, [23,41,9]]],["Gold", [86, [54,18,14]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [122, [35,40,47]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [71, [19,47,5]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [73, [18,47,8]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [70, [9,47,14]]],["Gold", [73, [23,41,9]]],["Gold", [89, [17,54,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [123, [35,40,48]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [72, [19,48,5]]]]],["Phil", [["Gold", [70, [1,48,21]]],["Gold", [70, [20,34,16]]],["Bronze", [58, [18,19,21]]]]],["Kevin", [["Gold", [71, [9,48,14]]],["Gold", [73, [23,41,9]]],["Gold", [89, [17,54,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [124, [35,40,49]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [73, [19,49,5]]]]],["Phil", [["Gold", [70, [1,49,20]]],["Gold", [71, [18,19,34]]],["Bronze", [50, [21,8,21]]]]],["Kevin", [["Gold", [72, [9,49,14]]],["Gold", [73, [23,41,9]]],["Gold", [89, [17,54,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [125, [35,40,50]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [74, [19,50,5]]]]],["Phil", [["Gold", [70, [1,50,19]]],["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [91, [23,50,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [126, [35,40,51]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [70, [51,5,14]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [1,18,51]]],["Gold", [70, [20,34,16]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [92, [23,51,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [127, [35,40,52]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [71, [52,5,14]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [71, [1,18,52]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [70, [9,52,9]]],["Gold", [72, [17,41,14]]],["Gold", [95, [23,54,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [128, [35,40,53]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [72, [53,5,14]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [1,53,16]]],["Gold", [71, [18,19,34]]],["Silver", [62, [20,21,21]]]]],["Kevin", [["Gold", [71, [9,53,9]]],["Gold", [72, [17,41,14]]],["Gold", [95, [23,54,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [129, [35,40,54]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [73, [54,5,14]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [73, [1,18,54]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [95, [23,54,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [130, [35,40,55]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [70, [55,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [74, [1,18,55]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [96, [23,55,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [131, [35,40,56]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [71, [56,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [75, [1,18,56]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [97, [23,56,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [132, [35,40,57]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [72, [57,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [76, [1,18,57]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [98, [23,57,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [133, [35,40,58]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [73, [58,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [77, [1,18,58]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [99, [23,58,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [134, [35,40,59]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [74, [59,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [78, [1,18,59]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [100, [23,59,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [135, [35,40,60]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [75, [60,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [79, [1,18,60]]],["Silver", [61, [21,19,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [101, [23,60,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [136, [35,40,61]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [76, [61,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [1,61,8]]],["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [102, [23,61,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [137, [35,40,62]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [77, [62,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [71, [1,62,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [103, [23,62,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [138, [35,40,63]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [78, [63,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [72, [1,63,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [104, [23,63,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [139, [35,40,64]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [79, [64,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [73, [1,64,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [105, [23,64,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [140, [35,40,65]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [80, [65,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [74, [1,65,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [106, [23,65,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [141, [35,40,66]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [81, [66,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [75, [1,66,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [107, [23,66,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [142, [35,40,67]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [82, [67,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [76, [1,67,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [108, [23,67,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [143, [35,40,68]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [83, [68,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [77, [1,68,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [109, [23,68,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [144, [35,40,69]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [84, [69,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [78, [1,69,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [110, [23,69,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [145, [35,40,70]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [85, [70,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [79, [1,70,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [111, [23,70,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [146, [35,40,71]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [86, [71,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [80, [1,71,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [112, [23,71,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [147, [35,40,72]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [87, [72,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [81, [1,72,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [113, [23,72,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [148, [35,40,73]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [88, [73,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [82, [1,73,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [114, [23,73,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [149, [35,40,74]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [89, [74,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [83, [1,74,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [115, [23,74,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [150, [35,40,75]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [90, [75,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [84, [1,75,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [116, [23,75,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [151, [35,40,76]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [91, [76,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [85, [1,76,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [117, [23,76,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [152, [35,40,77]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [92, [77,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [86, [1,77,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [118, [23,77,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [153, [35,40,78]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [93, [78,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [87, [1,78,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [119, [23,78,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [154, [35,40,79]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [94, [79,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [88, [1,79,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [120, [23,79,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [155, [35,40,80]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [95, [80,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [89, [1,80,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [121, [23,80,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [156, [35,40,81]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [96, [81,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [90, [1,81,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [122, [23,81,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [157, [35,40,82]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [97, [82,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [91, [1,82,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [123, [23,82,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [158, [35,40,83]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [98, [83,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [92, [1,83,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [124, [23,83,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [159, [35,40,84]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [99, [84,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [93, [1,84,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [125, [23,84,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [160, [35,40,85]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [100, [85,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [94, [1,85,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [126, [23,85,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [161, [35,40,86]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [101, [86,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [95, [1,86,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [127, [23,86,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [162, [35,40,87]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [102, [87,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [96, [1,87,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [128, [23,87,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [163, [35,40,88]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [103, [88,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [97, [1,88,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [129, [23,88,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [164, [35,40,89]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [104, [89,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [98, [1,89,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [130, [23,89,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [165, [35,40,90]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [105, [90,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [99, [1,90,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [131, [23,90,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [166, [35,40,91]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [106, [91,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [100, [1,91,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [132, [23,91,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [167, [35,40,92]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [107, [92,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [101, [1,92,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [133, [23,92,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [168, [35,40,93]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [108, [93,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [102, [1,93,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [134, [23,93,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [169, [35,40,94]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [109, [94,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [103, [1,94,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [135, [23,94,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [170, [35,40,95]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [110, [95,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [104, [1,95,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [136, [23,95,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [171, [35,40,96]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [111, [96,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [105, [1,96,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [137, [23,96,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [172, [35,40,97]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [112, [97,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [106, [1,97,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [138, [23,97,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [173, [35,40,98]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [113, [98,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [107, [1,98,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [139, [23,98,18]]]]]],[["Simon", [["Gold", [82, [27,34,21]]],["Gold", [174, [35,40,99]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Gold", [114, [99,10,5]]],["Bronze", [56, [23,19,14]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Gold", [108, [1,99,8]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [72, [9,54,9]]],["Gold", [72, [17,41,14]]],["Gold", [140, [23,99,18]]]]]],[["Simon", [["Gold", [74, [40,0,34]]],["Gold", [83, [35,27,21]]]]],["Hans", [["Gold", [70, [45,17,8]]],["Bronze", [52, [23,19,10]]]]],["Phil", [["Gold", [70, [20,34,16]]],["Silver", [60, [18,21,21]]]]],["Kevin", [["Gold", [71, [17,54,0]]],["Gold", [73, [9,23,41]]]]]]] + +import "./mlscript-compile/nofib-deforest/banner.mls" +print(banner.main()) +//│ > +//│ > IIIII SSSS TTTTT H H IIIII SSSS N N OOO TTTTT A GGGG RRRR EEEEE A TTTTT BBBB A N N N N EEEEE RRRR ??? +//│ > I S T H H I S NN N O O T A A G R R E A A T B B A A NN N NN N E R R ? ? +//│ > I SSS T HHHHH I SSS N N N O O T AAAAA G GG RRRR EEEEE AAAAA T BBBB AAAAA N N N N N N EEEEE RRRR ? +//│ > I S T H H I S N NN O O T A A G G R R E A A T B B A A N NN N NN E R R ? +//│ > IIIII SSSS T H H IIIII SSSS N N OOO T A A GGG R R EEEEE A A T BBBB A A N N N N EEEEE R R . +//│ > + +import "./mlscript-compile/nofib-deforest/lcss.mls" +lcss.main() +//│ = "[30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60]" + +import "./mlscript-compile/nofib-deforest/boyer.mls" +boyer.main() +//│ = true + + +import "./mlscript-compile/nofib-deforest/boyer2.mls" +boyer2.main() +//│ = "The term is a tautology" + + + +import "./mlscript-compile/nofib-deforest/calendar.mls" +print(calendar.main()) +//│ > 1993 +//│ > +//│ > January February March +//│ > Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa +//│ > 1 2 1 2 3 4 5 6 1 2 3 4 5 6 +//│ > 3 4 5 6 7 8 9 7 8 9 10 11 12 13 7 8 9 10 11 12 13 +//│ > 10 11 12 13 14 15 16 14 15 16 17 18 19 20 14 15 16 17 18 19 20 +//│ > 17 18 19 20 21 22 23 21 22 23 24 25 26 27 21 22 23 24 25 26 27 +//│ > 24 25 26 27 28 29 30 28 28 29 30 31 +//│ > 31 +//│ > +//│ > April May June +//│ > Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa +//│ > 1 2 3 1 1 2 3 4 5 +//│ > 4 5 6 7 8 9 10 2 3 4 5 6 7 8 6 7 8 9 10 11 12 +//│ > 11 12 13 14 15 16 17 9 10 11 12 13 14 15 13 14 15 16 17 18 19 +//│ > 18 19 20 21 22 23 24 16 17 18 19 20 21 22 20 21 22 23 24 25 26 +//│ > 25 26 27 28 29 30 23 24 25 26 27 28 29 27 28 29 30 +//│ > 30 31 +//│ > +//│ > July August September +//│ > Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa +//│ > 1 2 3 1 2 3 4 5 6 7 1 2 3 4 +//│ > 4 5 6 7 8 9 10 8 9 10 11 12 13 14 5 6 7 8 9 10 11 +//│ > 11 12 13 14 15 16 17 15 16 17 18 19 20 21 12 13 14 15 16 17 18 +//│ > 18 19 20 21 22 23 24 22 23 24 25 26 27 28 19 20 21 22 23 24 25 +//│ > 25 26 27 28 29 30 31 29 30 31 26 27 28 29 30 +//│ > +//│ > +//│ > October November December +//│ > Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa +//│ > 1 2 1 2 3 4 5 6 1 2 3 4 +//│ > 3 4 5 6 7 8 9 7 8 9 10 11 12 13 5 6 7 8 9 10 11 +//│ > 10 11 12 13 14 15 16 14 15 16 17 18 19 20 12 13 14 15 16 17 18 +//│ > 17 18 19 20 21 22 23 21 22 23 24 25 26 27 19 20 21 22 23 24 25 +//│ > 24 25 26 27 28 29 30 28 29 30 26 27 28 29 30 31 +//│ > 31 +//│ > +//│ > + + +import "./mlscript-compile/nofib-deforest/cichelli.mls" +cichelli.main() +//│ = "YesIts(113994, [[\"w\", 16],[\"r\", 17],[\"o\", 11],[\"m\", 17],[\"l\", 11],[\"x\", 2],[\"n\", 11],[\"i\", 4],[\"f\", 10],[\"h\", 3],[\"g\", 0],[\"t\", 5],[\"d\", 0],[\"a\", 0],[\"s\", 2],[\"c\", 0],[\"e\", 1]])" + + +import "./mlscript-compile/nofib-deforest/circsim.mls" +circsim.main() +//│ = "[[F,F,F,F,F,F,F,F],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T]]" + + +import "./mlscript-compile/nofib-deforest/clausify.mls" +clausify.main() +//│ = "a <=\na <=\na <=\na <=\na <=\na <=\na <=\na <=\na <=\na <=\n" + + +import "./mlscript-compile/nofib-deforest/constraints.mls" +constraints.main() +//│ = "[4,4,4,4,4]" + +import "./mlscript-compile/nofib-deforest/cryptarithm2.mls" +cryptarithm2.main() +//│ = "[\"W\",\" \",\"=\",\">\",\" \",\"3\",\"\\n\",\"H\",\" \",\"=\",\">\",\" \",\"9\",\"\\n\",\"N\",\" \",\"=\",\">\",\" \",\"8\",\"\\n\",\"I\",\" \",\"=\",\">\",\" \",\"4\",\"\\n\",\"L\",\" \",\"=\",\">\",\" \",\"7\",\"\\n\",\"R\",\" \",\"=\",\">\",\" \",\"2\",\"\\n\",\"V\",\" \",\"=\",\">\",\" \",\"6\",\"\\n\",\"T\",\" \",\"=\",\">\",\" \",\"1\",\"\\n\",\"E\",\" \",\"=\",\">\",\" \",\"0\",\"\\n\",\"Y\",\" \",\"=\",\">\",\" \",\"5\",\"\\n\"]" + + +import "./mlscript-compile/nofib-deforest/cse.mls" +cse.main() +//│ = "[[[[0, \"a\", []]]],[[[0, \"a\", []]],[[0, \"+\", [2,2]],[2, \"a\", []]]],[[[0, \"a\", []]],[[0, \"+\", [2,2]],[2, \"a\", []]],[[0, \"+\", [4,4]],[4, \"*\", [5,6]],[5, \"a\", []],[6, \"b\", []]]],[[[0, \"a\", []]],[[0, \"+\", [2,2]],[2, \"a\", []]],[[0, \"+\", [4,4]],[4, \"*\", [5,6]],[5, \"a\", []],[6, \"b\", []]],[[0, \"+\", [1,6]],[1, \"*\", [6,5]],[5, \"c\", []],[6, \"+\", [7,8]],[7, \"a\", []],[8, \"b\", []]]],[[[0, \"a\", []]],[[0, \"+\", [2,2]],[2, \"a\", []]],[[0, \"+\", [4,4]],[4, \"*\", [5,6]],[5, \"a\", []],[6, \"b\", []]],[[0, \"+\", [1,6]],[1, \"*\", [6,5]],[5, \"c\", []],[6, \"+\", [7,8]],[7, \"a\", []],[8, \"b\", []]],[[0, \"X\", [21,20,19,18,17]],[17, \"+\", [18,25]],[18, \"+\", [19,24]],[19, \"+\", [20,23]],[20, \"+\", [21,22]],[21, \"0\", []],[22, \"a\", []],[23, \"b\", []],[24, \"c\", []],[25, \"d\", []]]],[]]" + + +import "./mlscript-compile/nofib-deforest/eliza.mls" +eliza.main() +//│ = "[\"I'm not sure I understand you fully.\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\nCan you elaborate on that?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\nCan you elaborate on that?\\n\\nWhy do you ask?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\nCan you elaborate on that?\\n\\nWhy do you ask?\\n\\nDid you come to me because you are asking questions, not me?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\nCan you elaborate on that?\\n\\nWhy do you ask?\\n\\nDid you come to me because you are asking questions, not me?\\n\\nAre you saying no just to be negative?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\nCan you elaborate on that?\\n\\nWhy do you ask?\\n\\nDid you come to me because you are asking questions, not me?\\n\\nAre you saying no just to be negative?\\n\\nYou seem quite positive.\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\nCan you elaborate on that?\\n\\nWhy do you ask?\\n\\nDid you come to me because you are asking questions, not me?\\n\\nAre you saying no just to be negative?\\n\\nYou seem quite positive.\\n\\nHow long have you been not?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\nCan you elaborate on that?\\n\\nWhy do you ask?\\n\\nDid you come to me because you are asking questions, not me?\\n\\nAre you saying no just to be negative?\\n\\nYou seem quite positive.\\n\\nHow long have you been not?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\nCan you elaborate on that?\\n\\nWhy do you ask?\\n\\nDid you come to me because you are asking questions, not me?\\n\\nAre you saying no just to be negative?\\n\\nYou seem quite positive.\\n\\nHow long have you been not?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\nCan you elaborate on that?\\n\\nWhy do you ask?\\n\\nDid you come to me because you are asking questions, not me?\\n\\nAre you saying no just to be negative?\\n\\nYou seem quite positive.\\n\\nHow long have you been not?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\nCan you elaborate on that?\\n\\nWhy do you ask?\\n\\nDid you come to me because you are asking questions, not me?\\n\\nAre you saying no just to be negative?\\n\\nYou seem quite positive.\\n\\nHow long have you been not?\\n\\n\",\"I'm not sure I understand you fully.\\n\\nWe were discussing you --not me.\\n\\nWhy do you ask?\\n\\nOh, do?\\n\\nWhat does that suggest to you?\\n\\nDo computers worry you?\\n\\nYou're not really talking about me, are you?\\n\\nI see.\\n\\nCan you elaborate on that?\\n\\nWhy do you ask?\\n\\nDid you come to me because you are asking questions, not me?\\n\\nAre you saying no just to be negative?\\n\\nYou seem quite positive.\\n\\nHow long have you been not?\\n\\n\",\"\"]" + + +import "./mlscript-compile/nofib-deforest/integer.mls" +integer.main() +//│ = "[true,false,false,false,false,false,true,true,false,false,false,false,true,true,true,false,false,false,true,true,true,true,false,false,true,true,true,true,true,false,true,true,true,true,true,true]" + + +import "./mlscript-compile/nofib-deforest/knights.mls" +print(knights.main()) +//│ > +//│ > Knights tour with 0 backtracking moves +//│ > 1 34 3 18 41 32 13 16 +//│ > 4 19 64 33 14 17 44 31 +//│ > 35 2 37 40 63 42 15 12 +//│ > 20 5 56 47 38 45 30 43 +//│ > 55 36 39 62 57 48 11 26 +//│ > 6 21 52 49 46 27 60 29 +//│ > 51 54 23 8 61 58 25 10 +//│ > 22 7 50 53 24 9 28 59 +//│ > + + +import "./mlscript-compile/nofib-deforest/lambda.mls" +lambda.main() +//│ = "[\"C\",\"o\",\"n\",\" \",\"3\",\"2\",\"4\",\"0\"],[\"3\",\"2\",\"4\",\"0\",\" \",\" \",\"[\",\"]\"]" + + +import "./mlscript-compile/nofib-deforest/lastpiece.mls" +print(lastpiece.main()) +//│ > Success! +//│ > accchhff +//│ > aacnghhf +//│ > innnglhf +//│ > inmggllf +//│ > iimgelkk +//│ > dimeelkb +//│ > dmmejkkb +//│ > ddjjjjbb +//│ > +//│ > Success! +//│ > acccjjjj +//│ > aacffjgb +//│ > hhddfggb +//│ > lhhdfgbb +//│ > llhdfgnm +//│ > lkkennnm +//│ > lkeeniim +//│ > kkeiiimm +//│ > +//│ > Success! +//│ > ammmmccc +//│ > aaiimnch +//│ > iiinnnhh +//│ > gggnlhhj +//│ > fkgglljj +//│ > fkkklbdj +//│ > feeklbdj +//│ > ffeebbdd +//│ > +//│ > + + +import "./mlscript-compile/nofib-deforest/life.mls" +life.main() +//│ = 468 + + + +import "./mlscript-compile/nofib-deforest/mandel.mls" +mandel.main() +//│ = "Pixmap(25, 25, 75, [[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[5, 70, 70],[5, 70, 70],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[4, 71, 71],[14, 61, 61],[55, 20, 20],[4, 71, 71],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[6, 69, 69],[6, 69, 69],[59, 16, 16],[75, 0, 0],[7, 68, 68],[5, 70, 70],[4, 71, 71],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[4, 71, 71],[4, 71, 71],[5, 70, 70],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[39, 36, 36],[23, 52, 52],[3, 72, 72],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[2, 73, 73],[2, 73, 73],[3, 72, 72],[4, 71, 71],[6, 69, 69],[6, 69, 69],[6, 69, 69],[9, 66, 66],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[8, 67, 67],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[3, 72, 72],[3, 72, 72],[4, 71, 71],[6, 69, 69],[19, 56, 56],[75, 0, 0],[24, 51, 51],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[24, 51, 51],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[3, 72, 72],[5, 70, 70],[6, 69, 69],[18, 57, 57],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[6, 69, 69],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[3, 72, 72],[5, 70, 70],[6, 69, 69],[18, 57, 57],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[6, 69, 69],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[3, 72, 72],[3, 72, 72],[4, 71, 71],[6, 69, 69],[19, 56, 56],[75, 0, 0],[24, 51, 51],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[24, 51, 51],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[2, 73, 73],[2, 73, 73],[3, 72, 72],[4, 71, 71],[6, 69, 69],[6, 69, 69],[6, 69, 69],[9, 66, 66],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[8, 67, 67],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[4, 71, 71],[4, 71, 71],[5, 70, 70],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[39, 36, 36],[23, 52, 52],[3, 72, 72],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[6, 69, 69],[6, 69, 69],[59, 16, 16],[75, 0, 0],[7, 68, 68],[5, 70, 70],[4, 71, 71],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[4, 71, 71],[14, 61, 61],[55, 20, 20],[4, 71, 71],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[5, 70, 70],[5, 70, 70],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75]])" + + +import "./mlscript-compile/nofib-deforest/mandel2.mls" +mandel2.main() +//│ = true + +import "./mlscript-compile/nofib-deforest/mate.mls" +print(mate.main()) +//│ > - - - - - - - - +//│ > - - - - - - - - +//│ > - - - - - - - - +//│ > - - - - P - - - +//│ > - - - - p - k b +//│ > - P n - K - - - +//│ > - P - - - - - - +//│ > - q - - - - - - +//│ > +//│ > White to move and mate in 3 +//│ > +//│ > 1. N/QB3-QR2, +//│ > if K-Q5; 2. B/KR4-KB2, K-QB5; 3. Q/QN1-KB1++ +//│ > if K-Q7; 2. K-KB3, P/QN6xN/QR7; 3. B/KR4-K1++ +//│ > if K-K7; 2. N/QR2-QN4, +//│ > if K-Q7; 3. Q/QN1-K1++ +//│ > if K-K6; 3. Q/QN1-Q3++ +//│ > if P/QN6xN/QR7; 2. Q/QN1-QB2, ...; 3. B/KR4-KB2++ +//│ > + +import "./mlscript-compile/nofib-deforest/minimax.mls" +print(minimax.main()) +//│ > OXO +//│ > XWin +//│ > X|O| +//│ > ------ +//│ > |X| +//│ > ------ +//│ > | | +//│ > +//│ > XWin +//│ > X|O|O +//│ > ------ +//│ > |X| +//│ > ------ +//│ > | | +//│ > +//│ > XWin +//│ > X|O|O +//│ > ------ +//│ > X|X| +//│ > ------ +//│ > | | +//│ > +//│ > XWin +//│ > X|O|O +//│ > ------ +//│ > X|X|O +//│ > ------ +//│ > | | +//│ > +//│ > XWin +//│ > X|O|O +//│ > ------ +//│ > X|X|O +//│ > ------ +//│ > X| | +//│ > +//│ > + + +import "./mlscript-compile/nofib-deforest/para.mls" +para.main() +//│ = "In the constructive programming community it is commonplace to\nsee formal developments of textbook algorithms. In the algorithm\ndesign community, on the other hand, it may be well known that\nthe textbook solution to a problem is not the most efficient\npossible. However, in presenting the more efficient solution, the\nalgorithm designer will usually omit some of the implementation\ndetails, this creating an algorithm gap between the abstract\nalgorithm and its concrete implementation. This is in contrast\nto the formal development, which usually presents the complete\nconcrete implementation of the less efficient solution.\n" + +import "./mlscript-compile/nofib-deforest/power.mls" +power.main() +//│ = "[0,1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012]" + +import "./mlscript-compile/nofib-deforest/pretty.mls" +pretty.main() +//│ = "-42@This is a string\n, \nThis is the label\n\txxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx\n" + + +import "./mlscript-compile/nofib-deforest/primetest.mls" +primetest.main() +//│ = "[\"Composite\",\"Composite\",\"Probably prime\",\"Composite\",\"Composite\"]" + + +// can terminate with more stack size +:re +import "./mlscript-compile/nofib-deforest/puzzle.mls" +print(puzzle.main()) +//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded + + +import "./mlscript-compile/nofib-deforest/rsa.mls" +print(rsa.main()) +//│ > 27333540773077035891319648583115426924319682304972207061138531859687685497972324052329603672575247712822051033469833084249533708345668063349995687590898179232348381885068093916042332376874471111951277359240086024689478630903872483533692492045159120070581960228683268092981264305946420008131657132188411691046890656423813430758797867405414254427252889799598265252801351427969270327221859277538276931835433884202770274573975497479910055419604950116998779489424711382329456954759006285308055617249211518517251626537584144819963887585424355716160948313809816237911911714261525254960504461968887058634176692781918761529885191647640353988451378487593523928746420834635489374763284035135024554501992592243054651704669361294874639088141090295124111150498567814209355019358035109087855352831799613561922371560229756096541243234407756387955273981612894548796096568181979612805473591487774278882312329731123289196221054300160041623910405907021509065754120986913156062146884015988300349866352421512547114991188706014109057361892879580430212109312752658248376273202302160796406164353595904770530340704402942462200108055227350082862003023696909347848580847463903352486983305887517122394068078234691266091519485573727824252527733372590392886198860292659649377855405883044150450559660371076194186374359910112808222171852893169058046390627297042238730809765588373104750n + + +import "./mlscript-compile/nofib-deforest/scc.mls" +print(scc.main()) +//│ > [[1],[2],[7,5,6],[3,4]] + + +import "./mlscript-compile/nofib-deforest/secretary.mls" +secretary.main() +//│ = "[0.3,0.3,0.3,0.34,0.36]" + +import "./mlscript-compile/nofib-deforest/sorting.mls" +sorting.main() +//│ = 51324117188054929115411819706576305711291550658570113274291768822777898552447837804420193403034280334581113235670099168108057310001444698188883902000871912629747889286942274533143362191347715770581074120684028066661549409447053566864805982796651442411825424058139343253169753750307013113236996387277789074623630137288987589869641913268610508598505040964906263227437054452571059796961267985287441539342423613634888118731387934522320394294636575704912348025851038478882488022787377510287490741895262233989080994241592338442788051616303082788441666485156091668196999668892850523930511918729736856089560984406499736606084171798216360770991023233180481976810767432750226966921480421914178641779179040473344962763594357880599983085435482161632405644389584578524102239884780307588440751057343783694537559222924711205140877849398042544407611747227163056408231621727687968160470282720794027470616537695447289808133239223198869n + + +import "./mlscript-compile/nofib-deforest/sphere.mls" +sphere.main() +//│ = 5303517076988315313332949801059915491159227238911114869988477691048042454660240028235263286419219487056215941279053460510402913638191134284712332734906453769177119866479549825710564164275378353165954211251783583776613466486364346857260327927988942302708582821755390617347892889203137614326798040596862533046878189405070552043456176431867883325776044887939932845910768104061513326433524744308641514949931065176795629321475011168264612182133009617089963967729529385451164123717297044246136500759792365050576381593505032937197049090568454067533088406281602568506316332987816638963153657826815329120503032813525049886796008724986972866215360463470041513829818554068109887832683212349943548011864711495234825306589312943649643550119425864270325002860586630622080410969727430833935165563744592152868628452904185002185951114166726022764110066836557495639321991798761915142424731547359158796699442938595794963104455349322983423277214691169717946157629488088042966188345479757734044647446111212628224386112734239579560546540634912725760294413232437853902302947791243779581075398617923819755864459517175386729653052003619942440561460774453526472356057822015425767104792625263560820252880985395062686103756353800917765597123324396914329559953297442198091268488884729798979254734809574489636978036815249764203285502386099622910728418455221305204214764354028130536548944285925268544081227006773479419052538609413468738081133899425166931496082141812208439361999909673316291573553839847194239338723365672534513309867425104390474644888308811223216015979765648783582507394978116118320272460460255024758838512562405823893812000n + + +:re // can terminate with more stack size +import "./mlscript-compile/nofib-deforest/treejoin.mls" +treejoin.main() +//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded diff --git a/hkmc2Benchmarks/src/test/bench/nofibs1.mls b/hkmc2Benchmarks/src/test/bench/nofibs1.mls new file mode 100644 index 0000000000..4925cd53a5 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/nofibs1.mls @@ -0,0 +1,159 @@ +:js + + +// Comment to run the benchmarks +:exit +==================================================================================================== + + +import "./mlscript-compile/Benchmark.mls" +open Benchmark + + +:silent +let suite = mkSuite() + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/ansi.mls" +suite.add("ansi-deforest", () => ansi.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/ansi.mls" +suite.add("ansi", () => ansi.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/atom.mls" +suite.add("atom-deforest", () => atom.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/atom.mls" +suite.add("atom", () => atom.main()) + + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/awards.mls" +suite.add("awards-deforest", () => awards.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/awards.mls" +suite.add("awards", () => awards.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/banner.mls" +suite.add("banner-deforest", () => banner.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/banner.mls" +suite.add("banner", () => banner.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/lcss.mls" +suite.add("lcss-deforest", () => lcss.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/lcss.mls" +suite.add("lcss", () => lcss.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/boyer.mls" +suite.add("boyer-deforest", () => boyer.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/boyer.mls" +suite.add("boyer", () => boyer.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/boyer2.mls" +suite.add("boyer2-deforest", () => boyer2.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/boyer2.mls" +suite.add("boyer2", () => boyer2.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/calendar.mls" +suite.add("calendar-deforest", () => calendar.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/calendar.mls" +suite.add("calendar", () => calendar.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/cichelli.mls" +suite.add("cichelli-deforest", () => cichelli.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/cichelli.mls" +suite.add("cichelli", () => cichelli.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/circsim.mls" +suite.add("circsim-deforest", () => circsim.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/circsim.mls" +suite.add("circsim", () => circsim.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/clausify.mls" +suite.add("clausify-deforest", () => clausify.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/clausify.mls" +suite.add("clausify", () => clausify.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/constraints.mls" +suite.add("constraints-deforest", () => constraints.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/constraints.mls" +suite.add("constraints", () => constraints.main()) + + +runSuite(suite) +writeResults(suite, "nofibs1.json") diff --git a/hkmc2Benchmarks/src/test/bench/nofibs2.mls b/hkmc2Benchmarks/src/test/bench/nofibs2.mls new file mode 100644 index 0000000000..e595892b4b --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/nofibs2.mls @@ -0,0 +1,246 @@ +:js + + +// Comment to run the benchmarks +:exit +==================================================================================================== + + +import "./mlscript-compile/Benchmark.mls" +open Benchmark + + +:silent +let suite = mkSuite() + + + + +// need more stack +// :silent +// import "../../test/bench/mlscript-compile/nofib-deforest/cryptarithm1.mls" +// suite.add("cryptarithm1-deforest", () => cryptarithm1.main()) + +// :silent +// import "../../test/bench/mlscript-compile/nofib/cryptarithm1.mls" +// suite.add("cryptarithm1", () => cryptarithm1.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/cryptarithm2.mls" +suite.add("cryptarithm2-deforest", () => cryptarithm2.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/cryptarithm2.mls" +suite.add("cryptarithm2", () => cryptarithm2.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/cse.mls" +suite.add("cse-deforest", () => cse.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/cse.mls" +suite.add("cse", () => cse.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/eliza.mls" +suite.add("eliza-deforest", () => eliza.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/eliza.mls" +suite.add("eliza", () => eliza.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/gcd.mls" +suite.add("gcd-deforest", () => gcd.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/gcd.mls" +suite.add("gcd", () => gcd.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/integer.mls" +suite.add("integer-deforest", () => integer.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/integer.mls" +suite.add("integer", () => integer.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/knights.mls" +suite.add("knights-deforest", () => knights.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/knights.mls" +suite.add("knights", () => knights.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/lambda.mls" +suite.add("lambda-deforest", () => lambda.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/lambda.mls" +suite.add("lambda", () => lambda.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/lastpiece.mls" +suite.add("lastpiece-deforest", () => lastpiece.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/lastpiece.mls" +suite.add("lastpiece", () => lastpiece.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/life.mls" +suite.add("life-deforest", () => life.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/life.mls" +suite.add("life", () => life.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/mandel.mls" +suite.add("mandel-deforest", () => mandel.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/mandel.mls" +suite.add("mandel", () => mandel.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/mandel2.mls" +suite.add("mandel2-deforest", () => mandel2.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/mandel2.mls" +suite.add("mandel2", () => mandel2.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/mate.mls" +suite.add("mate-deforest", () => mate.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/mate.mls" +suite.add("mate", () => mate.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/minimax.mls" +suite.add("minimax-deforest", () => minimax.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/minimax.mls" +suite.add("minimax", () => minimax.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/para.mls" +suite.add("para-deforest", () => para.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/para.mls" +suite.add("para", () => para.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/power.mls" +suite.add("power-deforest", () => power.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/power.mls" +suite.add("power", () => power.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/pretty.mls" +suite.add("pretty-deforest", () => pretty.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/pretty.mls" +suite.add("pretty", () => pretty.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/primetest.mls" +suite.add("primetest-deforest", () => primetest.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/primetest.mls" +suite.add("primetest", () => primetest.main()) + + +// ======================= + +// need more stack +// :silent +// import "../../test/bench/mlscript-compile/nofib-deforest/puzzle.mls" +// suite.add("puzzle-deforest", () => puzzle.main()) + +// :silent +// import "../../test/bench/mlscript-compile/nofib/puzzle.mls" +// suite.add("puzzle", () => puzzle.main()) + + +runSuite(suite) +writeResults(suite, "nofibs2.json") diff --git a/hkmc2Benchmarks/src/test/bench/nofibs3.mls b/hkmc2Benchmarks/src/test/bench/nofibs3.mls new file mode 100644 index 0000000000..25b3684474 --- /dev/null +++ b/hkmc2Benchmarks/src/test/bench/nofibs3.mls @@ -0,0 +1,92 @@ +:js + + +// Comment to run the benchmarks +:exit +==================================================================================================== + + +import "./mlscript-compile/Benchmark.mls" +open Benchmark + + +:silent +let suite = mkSuite() + + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/rsa.mls" +suite.add("rsa-deforest", () => rsa.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/rsa.mls" +suite.add("rsa", () => rsa.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/scc.mls" +suite.add("scc-deforest", () => scc.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/scc.mls" +suite.add("scc", () => scc.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/secretary.mls" +suite.add("secretary-deforest", () => secretary.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/secretary.mls" +suite.add("secretary", () => secretary.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/sorting.mls" +suite.add("sorting-deforest", () => sorting.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/sorting.mls" +suite.add("sorting", () => sorting.main()) + + +// ======================= + + +:silent +import "../../test/bench/mlscript-compile/nofib-deforest/sphere.mls" +suite.add("sphere-deforest", () => sphere.main()) + +:silent +import "../../test/bench/mlscript-compile/nofib/sphere.mls" +suite.add("sphere", () => sphere.main()) + + +// ======================= + + +// need more stack +// :silent +// import "../../test/bench/mlscript-compile/nofib-deforest/treejoin.mls" +// suite.add("treejoin-deforest", () => treejoin.main()) + +// :silent +// import "../../test/bench/mlscript-compile/nofib/treejoin.mls" +// suite.add("treejoin", () => treejoin.main()) + + + + + +runSuite(suite) +writeResults(suite, "nofibs3.json") diff --git a/hkmc2Benchmarks/src/test/scala/hkmc2/BenchTestRunner.scala b/hkmc2Benchmarks/src/test/scala/hkmc2/BenchTestRunner.scala index 0d6b99733f..2349208249 100644 --- a/hkmc2Benchmarks/src/test/scala/hkmc2/BenchTestRunner.scala +++ b/hkmc2Benchmarks/src/test/scala/hkmc2/BenchTestRunner.scala @@ -19,4 +19,4 @@ class BenchTestRunner with ParallelTestExecution : override protected def createDiffMaker(file: Path, preludePath: Path, predefPath: Path, relativeName: String): DiffMaker = - new BenchDiffMaker((os.pwd/"hkmc2Benchmarks").toString, file, preludePath, predefPath, relativeName) + new BenchDiffMaker(os.pwd.toString, file, preludePath, predefPath, relativeName) diff --git a/hkmc2Benchmarks/src/test/scala/hkmc2/Watcher.scala b/hkmc2Benchmarks/src/test/scala/hkmc2/Watcher.scala index 416d49a670..a1f4d45a7a 100644 --- a/hkmc2Benchmarks/src/test/scala/hkmc2/Watcher.scala +++ b/hkmc2Benchmarks/src/test/scala/hkmc2/Watcher.scala @@ -2,5 +2,5 @@ package hkmc2 import better.files.* -object MainWatcher extends Watcher(File("../hkmc2/shared/src") :: File("./src") :: File("../hkmc2/hkmc2DiffTests/src") :: Nil): +object MainWatcher extends Watcher(File("../hkmc2/shared/src") :: File("./src") :: File("../hkmc2DiffTests/src") :: Nil): def main(args: Array[String]): Unit = run diff --git a/hkmc2DiffTests/src/test/scala/hkmc2/JSBackendDiffMaker.scala b/hkmc2DiffTests/src/test/scala/hkmc2/JSBackendDiffMaker.scala index 1adcd726b3..9aa51c40c9 100644 --- a/hkmc2DiffTests/src/test/scala/hkmc2/JSBackendDiffMaker.scala +++ b/hkmc2DiffTests/src/test/scala/hkmc2/JSBackendDiffMaker.scala @@ -24,6 +24,8 @@ abstract class JSBackendDiffMaker extends MLsDiffMaker: val showJS = NullaryCommand("sjs") val showRepl = NullaryCommand("showRepl") val traceJS = NullaryCommand("traceJS") + val deforestFlag = deforestation //NullaryCommand("deforest") + val deforestInfo = NullaryCommand("deforestInfo") val expect = Command("expect"): ln => ln.trim @@ -44,6 +46,17 @@ abstract class JSBackendDiffMaker extends MLsDiffMaker: override def doTrace = showRepl.isSet override def emitDbg(str: String): Unit = output(str) + val deforestTL = new TraceLogger: + override def doTrace: Bool = true + override def emitDbg(str: String): Unit = output(str) + override def trace[T](pre: => Str, post: T => Str = noPostTrace)(thunk: => T): T = + if deforestInfo.isSet then log(pre) + enter() + val res = try thunk finally exit() + if (post isnt noPostTrace) && deforestInfo.isSet then log(post(res)) + res + + lazy val host = hostCreated = true given TL = replTL @@ -60,6 +73,10 @@ abstract class JSBackendDiffMaker extends MLsDiffMaker: h private var hostCreated = false + + + given deforestState: deforest.Deforest.State = new deforest.Deforest.State + override def run(): Unit = try super.run() finally if hostCreated then host.terminate() @@ -68,6 +85,7 @@ abstract class JSBackendDiffMaker extends MLsDiffMaker: val outerRaise: Raise = summon val reportedMessages = mutable.Set.empty[Str] + var correctResult: Opt[Str] = None if showJS.isSet then given Raise = @@ -87,6 +105,19 @@ abstract class JSBackendDiffMaker extends MLsDiffMaker: val jsStr = je.stripBreaks.mkString(100) output(s"JS (unsanitized):") output(jsStr) + + if deforestFlag.isSet then + import codegen.deforest.* + output(">>>>>>>>>>>>>>>>>>>>>>>>> Deforestation JS >>>>>>>>>>>>>>>>>>>>>>>>>>") + new TraceLogger { override def doTrace: Bool = false }.givenIn: + Deforest(le, wd) match + case R(msg) => output(s"Not deforestable: $msg") + case L(deforestRes) => + val jsStr = baseScp.nest.givenIn: + jsb.program(deforestRes, N, wd).stripBreaks.mkString(100) + output(jsStr) + output("<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation JS <<<<<<<<<<<<<<<<<<<<<<<<<<") + if js.isSet then given Elaborator.Ctx = curCtx given Raise = @@ -101,43 +132,41 @@ abstract class JSBackendDiffMaker extends MLsDiffMaker: val jsb = ltl.givenIn: new JSBuilder with JSBuilderArgNumSanityChecks - val resSym = new TempSymbol(S(blk), "block$res") - val lowered0 = low.program(blk) - val le = lowered0.copy(main = lowered0.main.mapTail: - case e: End => - Assign(resSym, Value.Lit(syntax.Tree.UnitLit(false)), e) - case Return(res, implct) => - assert(implct) - Assign(resSym, res, Return(Value.Lit(syntax.Tree.UnitLit(false)), true)) - case tl: (Throw | Break | Continue) => tl - ) - if showLoweredTree.isSet then - output(s"Lowered:") - output(le.showAsTree) - // * We used to do this to avoid needlessly generating new variable names in separate blocks: - // val nestedScp = baseScp.nest - val nestedScp = baseScp - // val nestedScp = codegen.js.Scope(S(baseScp), curCtx.outer, collection.mutable.Map.empty) // * not needed + def getResSymAndResNme(n: Str) = + val resSym = new TempSymbol(S(blk), n) + resSym -> baseScp.allocateName(resSym) - val resNme = nestedScp.allocateName(resSym) + def assignResultSymForBlock(lowered: Program, resSym: TempSymbol) = + lowered.copy(main = lowered.main.mapTail: + case e: End => + Assign(resSym, Value.Lit(syntax.Tree.UnitLit(false)), e) + case Return(res, implct) => + assert(implct) + Assign(resSym, res, Return(Value.Lit(syntax.Tree.UnitLit(false)), true)) + case tl: (Throw | Break | Continue) => tl + ) - if ppLoweredTree.isSet then - output(s"Pretty Lowered:") - output(Printer.mkDocument(le)(using summon[Raise], nestedScp).toString) + def mkJS(le: Program) = + val (pre, js) = baseScp.givenIn: + jsb.worksheet(le) + val preStr = pre.stripBreaks.mkString(100) + val jsStr = js.stripBreaks.mkString(100) + if showSanitizedJS.isSet then + output(s"JS:") + output(jsStr) + preStr -> jsStr - val (pre, js) = nestedScp.givenIn: - jsb.worksheet(le) - val preStr = pre.stripBreaks.mkString(100) - val jsStr = js.stripBreaks.mkString(100) - if showSanitizedJS.isSet then - output(s"JS:") - output(jsStr) def mkQuery(preStr: Str, jsStr: Str)(k: Str => Unit) = val queryStr = jsStr.replaceAll("\n", " ") val (reply, stderr) = host.query(preStr, queryStr, !expectRuntimeOrCodeGenErrors && fixme.isUnset && todo.isUnset) reply match - case ReplHost.Result(content) => k(content) + case ReplHost.Result(content) => + k(content) + // val res :+ end = content.splitSane('\n') : @unchecked + // // TODO: seems that not all programs end with "undefined" now + // // assert(end == "undefined") + // handleResult(res) case ReplHost.Empty => case ReplHost.Unexecuted(message) => ??? case ReplHost.Error(isSyntaxError, message, otherOutputs) => @@ -155,20 +184,62 @@ abstract class JSBackendDiffMaker extends MLsDiffMaker: source = Diagnostic.Source.Runtime)) if stderr.nonEmpty then output(s"// Standard Error:\n${stderr}") - if traceJS.isSet then - host.execute( - s"$runtimeNme.TraceLogger.enabled = true; " + - s"$runtimeNme.TraceLogger.resetIndent(0)") + def executeJS(preStr: Str, jsStr: Str, resNme: Str) = + if traceJS.isSet then + host.execute( + s"$runtimeNme.TraceLogger.enabled = true; " + + s"$runtimeNme.TraceLogger.resetIndent(0)") + + // * Sometimes the JS block won't execute due to a syntax or runtime error so we always set this first + host.execute(s"$resNme = undefined") + + mkQuery(preStr, jsStr): stdout => + stdout.splitSane('\n').init // should always ends with "undefined" (TODO: check) + .foreach: line => + output(s"> ${line}") + if traceJS.isSet then + host.execute(s"$runtimeNme.TraceLogger.enabled = false") - // * Sometimes the JS block won't execute due to a syntax or runtime error so we always set this first - host.execute(s"$resNme = undefined") + def handleDefinedValues(nme: Str, sym: Symbol, expect: Opt[Str])(handleResult: Str => Unit) = + val le = + import codegen.* + Return( + Call( + Value.Ref(Elaborator.State.runtimeSymbol).selSN("printRaw"), + Arg(N, Value.Ref(sym)) :: Nil)(true, false), + implct = true) + val je = baseScp.givenIn: + jsb.block(le, endSemi = false) + val jsStr = je.stripBreaks.mkString(100) + mkQuery("", jsStr): out => + // Omit the last line which is always "undefined" or the unit. + val result = out.lastIndexOf('\n') match + case n if n >= 0 => out.substring(0, n) + case _ => "" + expect match + case S(expected) if result =/= expected => raise: + ErrorReport(msg"Expected: '${expected}', got: '${result}'" -> N :: Nil, + source = Diagnostic.Source.Runtime) + case _ => () + val anon = nme.isEmpty + result match + case "undefined" if anon => + case "()" if anon => + case _ => output(s"${if anon then "" else s"$nme "}= $result") - mkQuery(preStr, jsStr): stdout => - stdout.splitSane('\n').init // should always ends with "undefined" (TODO: check) - .foreach: line => - output(s"> ${line}") - if traceJS.isSet then - host.execute(s"$runtimeNme.TraceLogger.enabled = false") + val lowered0 = low.program(blk) + val resSym -> resNme = getResSymAndResNme("block$res") + val le = assignResultSymForBlock(lowered0, resSym) + if showLoweredTree.isSet then + output(s"Lowered:") + output(le.showAsTree) + + if ppLoweredTree.isSet then + output(s"Pretty Lowered:") + output(Printer.mkDocument(le)(using summon[Raise], baseScp).toString) + + val (preStr, jsStr) = mkJS(le) + executeJS(preStr, jsStr, resNme) if silent.isUnset then import Elaborator.Ctx.* @@ -182,31 +253,54 @@ abstract class JSBackendDiffMaker extends MLsDiffMaker: case _ => N case _ => N val valuesToPrint = ("", resSym, expect.get) +: definedValues.toSeq.sortBy(_._1) - valuesToPrint.foreach: (nme, sym, expect) => - val le = - import codegen.* - Return( - Call( - Value.Ref(Elaborator.State.runtimeSymbol).selSN("printRaw"), - Arg(N, Value.Ref(sym)) :: Nil)(true, false), - implct = true) - val je = nestedScp.givenIn: - jsb.block(le, endSemi = false) - val jsStr = je.stripBreaks.mkString(100) - mkQuery("", jsStr): out => - // Omit the last line which is always "undefined" or the unit. - val result = out.lastIndexOf('\n') match - case n if n >= 0 => out.substring(0, n) - case _ => "" - expect match - case S(expected) if result =/= expected => raise: - ErrorReport(msg"Expected: '${expected}', got: '${result}'" -> N :: Nil, - source = Diagnostic.Source.Runtime) - case _ => () - val anon = nme.isEmpty - result match - case "undefined" if anon => - case "()" if anon => - case _ => output(s"${if anon then "" else s"$nme "}= $result") + valuesToPrint.foreach: (nme, sym, expected) => + handleDefinedValues(nme, sym, expected)(if sym === resSym then r => correctResult = S(r) else _ => ()) + if deforestFlag.isSet then + import codegen.deforest.* + output(">>>>>>>>>>>>>>>>>>>>>>>>>>> Deforestation >>>>>>>>>>>>>>>>>>>>>>>>>>>") + val deforestLow = ltl.givenIn: + codegen.Lowering() + val le = deforestLow.program(blk) + + val collector = CollectTopLevelDefs(le.main.definedVars.filter(_.isFunction).map(_.asInstanceOf[BlockMemberSymbol])) + deforestState.topLevelFunInPrevDiffBlocks.addAll(collector.apply(le.main)) + + deforestTL.givenIn: + Deforest(le, wd) match + case R(msg) => output(s"Not deforestable: $msg") + case L(deforestRes) => + val resSym -> resNme = getResSymAndResNme("block$res_deforest") + val deforestRes2 = assignResultSymForBlock(deforestRes, resSym) + if showLoweredTree.isSet then + output(s"Lowered:") + output(deforestRes2.showAsTree) + if ppLoweredTree.isSet then + output(s"Pretty Lowered:") + output(Printer.mkDocument(deforestRes2)(using summon[Raise], baseScp).toString) + val (preStr, jsStr) = mkJS(deforestRes2) + if showSanitizedJS.isSet then + output("------ deforested sanitized js -------") + output(jsStr) + output("-------------- executing -------------") + executeJS(preStr, jsStr, resNme) + if silent.isUnset then + handleDefinedValues("", resSym, expect.get): result => + if correctResult.fold(false)(_ != result) then raise: + ErrorReport( + msg"The result from deforestated program (\"${result}\") is different from the one computed by the original prorgam (\"${correctResult.get}\")" -> N :: Nil, + source = Diagnostic.Source.Runtime) + + output("<<<<<<<<<<<<<<<<<<<<<<<<<<< Deforestation <<<<<<<<<<<<<<<<<<<<<<<<<<<") + + +class CollectTopLevelDefs(toCollect: Set[BlockMemberSymbol]) extends BlockTraverser: + val res = mutable.Map.empty[BlockMemberSymbol, FunDefn] + override def applyFunDefn(fun: FunDefn): Unit = + if toCollect.contains(fun.sym) then + res += fun.sym -> fun + def apply(b: Block): Map[BlockMemberSymbol, FunDefn] = + applyBlock(b) + res.toMap + \ No newline at end of file diff --git a/hkmc2DiffTests/src/test/scala/hkmc2/MLsDiffMaker.scala b/hkmc2DiffTests/src/test/scala/hkmc2/MLsDiffMaker.scala index 3e59ea626a..674f3863ef 100644 --- a/hkmc2DiffTests/src/test/scala/hkmc2/MLsDiffMaker.scala +++ b/hkmc2DiffTests/src/test/scala/hkmc2/MLsDiffMaker.scala @@ -63,6 +63,7 @@ abstract class MLsDiffMaker extends DiffMaker: val stackSafe = Command("stackSafe")(_.trim) val liftDefns = NullaryCommand("lift") val importQQ = NullaryCommand("qq") + val deforestation = NullaryCommand("deforest") def mkConfig: Config = import Config.* @@ -87,7 +88,12 @@ abstract class MLsDiffMaker extends DiffMaker: S(StackSafety(stackLimit = value)) , )), - liftDefns = Opt.when(liftDefns.isSet)(LiftDefns()) + liftDefns = Opt.when(liftDefns.isSet)(LiftDefns()), + deforest = Opt.when(deforestation.isSet): + Config.Deforestation( + seethroughModules = Set(os.Path(rootPath)/"hkmc2Benchmarks"/"src"/"test"/"bench"/"mlscript-compile"/"nofib-deforest"/"NofibPrelude.mls"), + seeThroughForceSymbolsNames = Set("force"), + seeThroughLazySymbolsNames = Set("lazy")) ) diff --git a/hkmc2DiffTests/src/test/scala/hkmc2/Watcher.scala b/hkmc2DiffTests/src/test/scala/hkmc2/Watcher.scala index 511b999a00..ab9f41a19d 100644 --- a/hkmc2DiffTests/src/test/scala/hkmc2/Watcher.scala +++ b/hkmc2DiffTests/src/test/scala/hkmc2/Watcher.scala @@ -95,7 +95,15 @@ class Watcher(dirs: Ls[File]): val isModuleFile = path.segments.contains("mlscript-compile") if isModuleFile then - given Config = Config.default + given Config = + if path.segments.contains("nofib-deforest") then + Config.default.copy(deforest = S(Config.Deforestation( + seethroughModules = Set(rootPath/"hkmc2Benchmarks"/"src"/"test"/"bench"/"mlscript-compile"/"nofib-deforest"/"NofibPrelude.mls"), + seeThroughLazySymbolsNames = Set("lazy"), + seeThroughForceSymbolsNames = Set("force") + ))) + else + Config.default MLsCompiler(preludePath, outputConsumer => outputConsumer(System.out.println)).compileModule(path) else val dm = new MainDiffMaker(rootPath.toString, path, preludePath, predefPath, relativeName):