├── .gitattributes ├── .github └── workflows │ └── nix.yml ├── .gitignore ├── .vscode └── settings.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── bin └── mlscript-opt.js ├── build.sbt ├── compiler └── shared │ ├── main │ └── scala │ │ └── mlscript │ │ └── compiler │ │ ├── ClassLifter.scala │ │ ├── Document.scala │ │ ├── PrettyPrinter.scala │ │ ├── codegen │ │ ├── CppAst.scala │ │ ├── CppCodeGen.scala │ │ └── CppCompilerHost.scala │ │ ├── debug │ │ ├── Debug.scala │ │ ├── DebutOutput.scala │ │ ├── DummyDebug.scala │ │ ├── Printable.scala │ │ ├── RainbowDebug.scala │ │ └── TreeDebug.scala │ │ ├── ir │ │ ├── Builder.scala │ │ ├── Fresh.scala │ │ ├── IR.scala │ │ ├── Interp.scala │ │ ├── RefResolver.scala │ │ └── Validator.scala │ │ ├── optimizer │ │ ├── Analysis.scala │ │ └── TailRecOpt.scala │ │ ├── printer │ │ └── BlockPrinter.scala │ │ └── simpledef │ │ ├── Simpledef.scala │ │ └── Uid.scala │ └── test │ ├── diff-ir │ ├── Class.mls │ ├── Currying.mls │ ├── IR.mls │ ├── IRComplex.mls │ ├── IRRec.mls │ ├── IRTailRec.mls │ ├── LiftClass.mls │ ├── LiftFun.mls │ ├── LiftLambda.mls │ ├── NuScratch.mls │ ├── Override.mls │ ├── cpp │ │ ├── Makefile │ │ └── mlsprelude.h │ └── gcd.mls │ ├── diff │ ├── CompilerScratch.mls │ ├── Defunctionalize │ │ ├── ClassConstructor.mls │ │ ├── Classes.mls │ │ ├── ClosureCapture.mls │ │ ├── Constructor.mls │ │ ├── DelayedEvaluation.mls │ │ ├── Differentiation.mls │ │ ├── FreeVariables.mls │ │ ├── FuncsWithParams.mls │ │ ├── Inheritance.mls │ │ ├── Lambda.mls │ │ ├── Lambdas.mls │ │ ├── ListConstruction.mls │ │ ├── Modules.mls │ │ ├── MonoNonLambda.mls │ │ ├── MonoTupSelect.mls │ │ ├── MutableParams.mls │ │ ├── MutualRec.mls │ │ ├── NewOperator.mls │ │ ├── NuMono.mls │ │ ├── ObjFieldAccess.mls │ │ ├── ObjFields.mls │ │ ├── ObjMultiFields.mls │ │ ├── ObjsSelection.mls │ │ ├── OldMonoList.mls │ │ ├── Polymorphic.mls │ │ ├── Record.mls │ │ ├── RecursiveFunc.mls │ │ ├── SelfReference.mls │ │ ├── SimpleClasses.mls │ │ ├── SimpleConditionals.mls │ │ ├── SimpleFunc.mls │ │ ├── Simpledef.mls │ │ └── TupleSelect.mls │ └── Lifter │ │ ├── FunctionTypeAnnotations.mls │ │ ├── LambLift.mls │ │ ├── LiftNew.mls │ │ ├── LiftType.mls │ │ ├── Lifter.mls │ │ ├── LifterBlks.mls │ │ ├── NestedClasses.mls │ │ ├── NestedFuncs.mls │ │ ├── ParameterizedInheritance.mls │ │ └── TypedClassParams.mls │ └── scala │ └── mlscript │ └── compiler │ ├── Test.scala │ └── TestIR.scala ├── doc ├── Parsing.md └── mls-codebase-doc.md ├── flake.lock ├── flake.nix ├── index.css ├── index.html ├── js └── src │ └── main │ └── scala │ ├── Main.scala │ └── fansi │ └── Str.scala ├── local_testing.html ├── package-lock.json ├── package.json ├── project ├── build.properties └── plugins.sbt ├── shared └── src │ ├── main │ └── scala │ │ └── mlscript │ │ ├── ConstraintSolver.scala │ │ ├── Diagnostic.scala │ │ ├── JSBackend.scala │ │ ├── Lexer.scala │ │ ├── MLParser.scala │ │ ├── Message.scala │ │ ├── NewLexer.scala │ │ ├── NewParser.scala │ │ ├── NormalForms.scala │ │ ├── NuTypeDefs.scala │ │ ├── Parser.scala │ │ ├── Token.scala │ │ ├── TypeDefs.scala │ │ ├── TypeSimplifier.scala │ │ ├── Typer.scala │ │ ├── TyperDatatypes.scala │ │ ├── TyperHelpers.scala │ │ ├── codegen │ │ ├── Codegen.scala │ │ ├── Error.scala │ │ ├── Polyfill.scala │ │ ├── QQHelper.scala │ │ ├── Scope.scala │ │ ├── Symbol.scala │ │ └── typescript │ │ │ └── TsTypegen.scala │ │ ├── helpers.scala │ │ ├── package.scala │ │ ├── pretyper │ │ ├── Diagnosable.scala │ │ ├── PreTyper.scala │ │ ├── Scope.scala │ │ ├── Symbol.scala │ │ └── Traceable.scala │ │ ├── syntax.scala │ │ ├── ucs │ │ ├── Desugarer.scala │ │ ├── context │ │ │ ├── Context.scala │ │ │ ├── Matchable.scala │ │ │ ├── Pattern.scala │ │ │ └── Scrutinee.scala │ │ ├── display.scala │ │ ├── package.scala │ │ ├── stages │ │ │ ├── CoverageChecking.scala │ │ │ ├── Desugaring.scala │ │ │ ├── Normalization.scala │ │ │ ├── PartialTerm.scala │ │ │ ├── PostProcessing.scala │ │ │ ├── Transformation.scala │ │ │ └── package.scala │ │ └── syntax │ │ │ ├── core.scala │ │ │ └── source.scala │ │ └── utils │ │ ├── FastParseHelpers.scala │ │ ├── Identity.scala │ │ ├── Lazy.scala │ │ ├── algorithms.scala │ │ ├── package.scala │ │ └── shorthands.scala │ └── test │ ├── diff │ ├── analysis │ │ ├── Variance.mls │ │ └── Weird.mls │ ├── basics │ │ ├── AsBindings.fun │ │ ├── Blocks.fun │ │ ├── Data.fun │ │ ├── Datatypes.fun │ │ ├── Either.fun │ │ ├── Errors.fun │ │ ├── ExplicitDatatypes.fun │ │ ├── Flow.fun │ │ ├── Intersections.fun │ │ ├── Iso.fun │ │ ├── Lambdas.fun │ │ ├── Literals.fun │ │ ├── Negations.fun │ │ ├── Operators.fun │ │ ├── RecFuns.fun │ │ ├── Records.fun │ │ ├── Simplesub1.fun │ │ ├── Simplesub2.fun │ │ ├── Slashes.fun │ │ ├── Tuples.fun │ │ ├── Twice.fun │ │ ├── Unions.fun │ │ └── VerboseErrors.fun │ ├── codegen │ │ ├── AuxiliaryConstructors.mls │ │ ├── Classes.mls │ │ ├── ConstructorStmt.mls │ │ ├── Declare.mls │ │ ├── Escape.mls │ │ ├── FieldOverride.mls │ │ ├── IndirectRecursion.mls │ │ ├── Inheritance.mls │ │ ├── LogInfo.mls │ │ ├── MemberInitShadowing.mls │ │ ├── Mixin.mls │ │ ├── MixinCapture.mls │ │ ├── Modules.mls │ │ ├── MutFields.mls │ │ ├── NamedArgsCurry.mls │ │ ├── Nested.mls │ │ ├── New.mls │ │ ├── NewClasses.mls │ │ ├── NewMatching.mls │ │ ├── NewMutualRef.mls │ │ ├── NuClasses.mls │ │ ├── NuFuns.mls │ │ ├── NuParentheses.mls │ │ ├── NuReplHost.mls │ │ ├── ParameterPattern.mls │ │ ├── Parentheses.mls │ │ ├── PatternMatch.mls │ │ ├── Polyfill.mls │ │ ├── Recursion.mls │ │ ├── ReplHost.mls │ │ ├── Res.mls │ │ ├── Shadowing.mls │ │ ├── SortClass.mls │ │ ├── Super.mls │ │ ├── SymbolicOps.mls │ │ ├── Terms.mls │ │ ├── TraitMethods.mls │ │ ├── TrickyShadowing.mls │ │ ├── TrickyTerms.mls │ │ ├── TrickyWiths.mls │ │ ├── Unicode.mls │ │ ├── ValLet.mls │ │ └── While.mls │ ├── contys │ │ ├── AbstractBounds.mls │ │ └── ExplicitConstraints.mls │ ├── ecoop23 │ │ ├── ComparePointPoly.mls │ │ ├── ExpressionProblem.mls │ │ ├── Intro.mls │ │ ├── PolymorphicVariants.mls │ │ ├── SimpleRegionDSL_annot.mls │ │ └── SimpleRegionDSL_raw.mls │ ├── ex │ │ ├── RepMin.mls │ │ └── UnboxedOptions.mls │ ├── fcp-lit │ │ ├── Boxy.mls │ │ ├── CPS_LB.mls │ │ ├── FreezeML.mls │ │ ├── GHC-rank-n.mls │ │ ├── HMF.mls │ │ ├── HML.mls │ │ ├── Jim.mls │ │ ├── Leijen.mls │ │ ├── MLF.mls │ │ ├── Misc.mls │ │ ├── PolyML.mls │ │ ├── QML.mls │ │ ├── Stability.mls │ │ └── variations_PolyML.mls │ ├── fcp │ │ ├── AA.mls │ │ ├── Aleks.mls │ │ ├── Aliases.mls │ │ ├── Basics.mls │ │ ├── Church_CT.mls │ │ ├── Church_ST.mls │ │ ├── ConstrainedTypes1.mls │ │ ├── ConstrainedTypes2.mls │ │ ├── Demo.mls │ │ ├── Distrib.mls │ │ ├── Distrib2.mls │ │ ├── DistribRight.mls │ │ ├── DistribUnionInter.mls │ │ ├── DistribWorsening.mls │ │ ├── FCPTony.mls │ │ ├── FCPTony3.mls │ │ ├── Fiota.mls │ │ ├── ForallTerms.mls │ │ ├── FunnyId.mls │ │ ├── Inst.mls │ │ ├── InvariantPolyContainer.mls │ │ ├── ListBuild.mls │ │ ├── Min1_ex_shallow.mls │ │ ├── MoreChurch.mls │ │ ├── NestedDataTypes.mls │ │ ├── NestedDataTypesGADT.mls │ │ ├── NoRecursiveTypes.mls │ │ ├── OCamlList.mls │ │ ├── OverloadSimplif.mls │ │ ├── Overloads.mls │ │ ├── Overloads_Precise.mls │ │ ├── Paper.mls │ │ ├── PaperTable.mls │ │ ├── PolyParams.mls │ │ ├── PolymorphicTypeAliases.mls │ │ ├── Proofs.mls │ │ ├── QML_exist_Classes.mls │ │ ├── QML_exist_Classes_min.mls │ │ ├── QML_exist_Records_D.mls │ │ ├── QML_exist_Records_ND.mls │ │ ├── QML_exist_Records_min_1.mls │ │ ├── QML_exist_Records_min_2.mls │ │ ├── QML_exist_Records_min_3.mls │ │ ├── QML_exist_nu.mls │ │ ├── Rank2.mls │ │ ├── RecExtr.mls │ │ ├── SelfAppMin.mls │ │ ├── Simplif.mls │ │ ├── SkolemErrors.mls │ │ ├── Skolems.mls │ │ ├── Skolems2.mls │ │ ├── Skolems3.mls │ │ ├── SystemF.mls │ │ ├── SystemF_2.mls │ │ ├── ToChurchSimplif_CT.mls │ │ ├── ToChurchSimplif_ST.mls │ │ ├── Vec.mls │ │ └── YicongFCP.mls │ ├── gadt │ │ ├── Exp1.mls │ │ ├── Exp2.mls │ │ └── ThisMatching.mls │ ├── gen │ │ └── genTests_v1-0.14-15-x2.fun │ ├── mlf-examples │ │ ├── ex_casparticuliers.mls │ │ ├── ex_concrete.mls │ │ ├── ex_demo.mls │ │ ├── ex_hashtbl.mls │ │ ├── ex_predicative.mls │ │ ├── ex_propagate.mls │ │ ├── ex_rvr_validate.mls │ │ ├── ex_selfapp.mls │ │ ├── ex_shallow.mls │ │ ├── ex_validate.mls │ │ ├── ex_voir.mls │ │ ├── ex_vr_validate.mls │ │ ├── merge_regression_min.mls │ │ └── variations_ex_hashtbl.mls │ ├── mlscript │ │ ├── ADTs.mls │ │ ├── ADTsRepro.mls │ │ ├── Addable.mls │ │ ├── AdtStyle.mls │ │ ├── AlexJ.mls │ │ ├── Annoying.mls │ │ ├── Arrays.mls │ │ ├── Arrays2.mls │ │ ├── Ascribe.mls │ │ ├── Baber.mls │ │ ├── BadAlias.mls │ │ ├── BadClasses.mls │ │ ├── BadInherit.mls │ │ ├── BadInherit2.mls │ │ ├── BadInherit2Co.mls │ │ ├── BadMethods.mls │ │ ├── BadPolym.mls │ │ ├── BadTraits.mls │ │ ├── BadTypes.mls │ │ ├── Basics.mls │ │ ├── Boolean.mls │ │ ├── BooleanFail.mls │ │ ├── ByNameByValue.mls │ │ ├── David.mls │ │ ├── David2.mls │ │ ├── DavidB.mls │ │ ├── Didier.mls │ │ ├── Dmitry.mls │ │ ├── EitherClasses.mls │ │ ├── ExplicitVariance.mls │ │ ├── ExprProb.mls │ │ ├── ExprProb2.mls │ │ ├── ExprProb_Inv.mls │ │ ├── FatNegs.mls │ │ ├── FunnySubsumptions.mls │ │ ├── GenericClasses.mls │ │ ├── GenericClasses2.mls │ │ ├── Group_2021_12_02.mls │ │ ├── Group_2022_05_10.mls │ │ ├── Group_2022_06_09.mls │ │ ├── HeadOption.mls │ │ ├── Huawei2.mls │ │ ├── Inherit.mls │ │ ├── InheritSimple.mls │ │ ├── JetBrains.mls │ │ ├── LetPolym.mls │ │ ├── LineComments.mls │ │ ├── Lists.mls │ │ ├── Luyu.mls │ │ ├── MLList.mls │ │ ├── MLTuples.mls │ │ ├── Match1.mls │ │ ├── Match2.mls │ │ ├── Match3.mls │ │ ├── MatchBool.mls │ │ ├── MethodAndMatches.mls │ │ ├── Methods.mls │ │ ├── Methods2.mls │ │ ├── Misc.mls │ │ ├── MiscExtrusion.mls │ │ ├── Mohammad.mls │ │ ├── MultiArgs.mls │ │ ├── Mut.mls │ │ ├── Mut2.mls │ │ ├── MutArray.mls │ │ ├── Neg.mls │ │ ├── NestedClassArgs.mls │ │ ├── NestedClassArgs_Co.mls │ │ ├── NestedMatch.mls │ │ ├── NestedRecursiveMatch.mls │ │ ├── OccursCheck.mls │ │ ├── Ops.mls │ │ ├── OtherErrors.mls │ │ ├── Paper.mls │ │ ├── PolyVariant.mls │ │ ├── PolyVariantCodeReuse.mls │ │ ├── Polym.mls │ │ ├── PolymExtrusion.mls │ │ ├── PolymorphicExtension.mls │ │ ├── PreservationFail.mls │ │ ├── ProvFlows.mls │ │ ├── Random1.mls │ │ ├── Random2.mls │ │ ├── RecDefs.mls │ │ ├── RecErrors.mls │ │ ├── RecursiveTypes.mls │ │ ├── RecursiveTypes2.mls │ │ ├── References.mls │ │ ├── Repro.mls │ │ ├── RigidVariables.mls │ │ ├── SafeDiv.mls │ │ ├── Scratch.mls │ │ ├── SelfNeg.mls │ │ ├── SelfNegs.mls │ │ ├── Seqs.mls │ │ ├── Sequence.mls │ │ ├── Signatures.mls │ │ ├── Simple.mls │ │ ├── SimpleErrors.mls │ │ ├── SimpleMethods.mls │ │ ├── Splice.mls │ │ ├── Stress.mls │ │ ├── StressDNF.mls │ │ ├── StressTraits.mls │ │ ├── StressUgly.mls │ │ ├── Subsume.mls │ │ ├── Test.mls │ │ ├── This.mls │ │ ├── Ticks.mls │ │ ├── Tony.mls │ │ ├── TraitMatching.mls │ │ ├── Traits.mls │ │ ├── Trans.mls │ │ ├── TrickyExtrusion.mls │ │ ├── TrickySimplif.mls │ │ ├── Trio.mls │ │ ├── TupleArray.mls │ │ ├── TupleArray2.mls │ │ ├── TypeClasses.mls │ │ ├── TypeDefs.mls │ │ ├── TypeRanges.mls │ │ ├── TypeRefs.mls │ │ ├── TypeTags.mls │ │ ├── Undef.mls │ │ ├── Undefined.mls │ │ ├── Under.mls │ │ ├── VarCycles.mls │ │ ├── Variant-sub-ad-hoc.mls │ │ ├── Variant-sub.mls │ │ ├── Weird.mls │ │ ├── Wildcards.mls │ │ ├── With.mls │ │ ├── Yicong.mls │ │ ├── Yuheng.mls │ │ ├── i26.mls │ │ ├── i56.mls │ │ └── i65.mls │ ├── nu │ │ ├── AbstractClasses.mls │ │ ├── Andong.mls │ │ ├── Annotations.mls │ │ ├── ArrayProg.mls │ │ ├── Ascription.mls │ │ ├── AuxCtors.mls │ │ ├── BadAliases.mls │ │ ├── BadBlocks.mls │ │ ├── BadClassInherit.mls │ │ ├── BadClassSignatures.mls │ │ ├── BadClasses.mls │ │ ├── BadFieldInit.mls │ │ ├── BadLets.mls │ │ ├── BadMixins.mls │ │ ├── BadScopes.mls │ │ ├── BadSignatures.mls │ │ ├── BadSuper.mls │ │ ├── BadTraits.mls │ │ ├── BadUCS.mls │ │ ├── BasicClassInheritance.mls │ │ ├── BasicClasses.mls │ │ ├── BasicMixins.mls │ │ ├── CallByName.mls │ │ ├── CaseExpr.mls │ │ ├── ClassField.mls │ │ ├── ClassInstantiation.mls │ │ ├── ClassSignatures.mls │ │ ├── ClassesInMixins.mls │ │ ├── CommaOperator.mls │ │ ├── CtorSubtraction.mls │ │ ├── CycleTypeDefErrors.mls │ │ ├── Darin.mls │ │ ├── Dates.mls │ │ ├── DecLit.mls │ │ ├── Declarations.mls │ │ ├── DiamondInherit.mls │ │ ├── DidierNu.mls │ │ ├── Eduardo.mls │ │ ├── EncodedLists.mls │ │ ├── Eql.mls │ │ ├── EqlClasses.mls │ │ ├── Eval.mls │ │ ├── EvalNegNeg.mls │ │ ├── ExplicitVariance.mls │ │ ├── ExpressionProblem_repro.mls │ │ ├── ExpressionProblem_small.mls │ │ ├── Extrusion.mls │ │ ├── FieldRefinement.mls │ │ ├── FilterMap.mls │ │ ├── FlatIfThenElse.mls │ │ ├── FlatIndentFuns.mls │ │ ├── FlatMonads.mls │ │ ├── FlatMonads_repro.mls │ │ ├── FunPatterns.mls │ │ ├── FunPoly.mls │ │ ├── FunSigs.mls │ │ ├── FunnyIndet.mls │ │ ├── FunnyPoly.mls │ │ ├── GADTMono.mls │ │ ├── GenericClassInheritance.mls │ │ ├── GenericClasses.mls │ │ ├── GenericMethods.mls │ │ ├── GenericMixins.mls │ │ ├── GenericModules.mls │ │ ├── HeungTung.mls │ │ ├── Huawei1.mls │ │ ├── ImplicitMethodPolym.mls │ │ ├── InferredInheritanceTypeArgs.mls │ │ ├── InheritanceLevelMismatches.mls │ │ ├── IntLit.mls │ │ ├── InterfaceGeneric.mls │ │ ├── InterfaceMono.mls │ │ ├── Interfaces.mls │ │ ├── IntraBlockPolymorphism.mls │ │ ├── Jonathan.mls │ │ ├── LamPatterns.mls │ │ ├── LetRec.mls │ │ ├── ListConsNil.mls │ │ ├── LitMatch.mls │ │ ├── LocalLets.mls │ │ ├── MIscPoly.mls │ │ ├── MemberConfusion.mls │ │ ├── MemberIntersections.mls │ │ ├── MetaWrap.mls │ │ ├── Metaprog.mls │ │ ├── MethodSignatures.mls │ │ ├── Misc.mls │ │ ├── MissingImplBug.mls │ │ ├── MissingTypeArg.mls │ │ ├── Mixin42.mls │ │ ├── MixinParameters.mls │ │ ├── ModuleParameters.mls │ │ ├── Mut.mls │ │ ├── MutLet.mls │ │ ├── MutualRec.mls │ │ ├── NamedArgs.mls │ │ ├── NestedClasses.mls │ │ ├── NestedRecords.mls │ │ ├── New.mls │ │ ├── NewNew.mls │ │ ├── NoThisCtor.mls │ │ ├── NuAlexJ.mls │ │ ├── NuForallTerms.mls │ │ ├── NuPolymorphicTypeAliases.mls │ │ ├── NuScratch.mls │ │ ├── Numbers.mls │ │ ├── Object.mls │ │ ├── OpLam.mls │ │ ├── OptionFilter.mls │ │ ├── OverrideShorthand.mls │ │ ├── ParamImplementing.mls │ │ ├── ParamOverride.mls │ │ ├── ParamOverriding.mls │ │ ├── ParamPassing.mls │ │ ├── Parens.mls │ │ ├── PartialApp.mls │ │ ├── PolymorphicVariants_Alt.mls │ │ ├── PostHocMixinSignature.mls │ │ ├── PrivateMemberOverriding.mls │ │ ├── RawUnionTraitSignatures.mls │ │ ├── Ref.mls │ │ ├── RefinedPattern.mls │ │ ├── Refinements.mls │ │ ├── Res.mls │ │ ├── RightAssocOps.mls │ │ ├── RigidVariables.mls │ │ ├── SelfAppMethods.mls │ │ ├── SelfRec.mls │ │ ├── Sidney.mls │ │ ├── SimpleSymbolicOps.mls │ │ ├── SimpleTraitImpl.mls │ │ ├── Splices.mls │ │ ├── StupidJS.mls │ │ ├── Subscripts.mls │ │ ├── TODO_Classes.mls │ │ ├── ThisRefinedClasses.mls │ │ ├── TraitParameters.mls │ │ ├── TraitSignatures.mls │ │ ├── TrickyExtrusion2.mls │ │ ├── TrickyGenericInheritance.mls │ │ ├── TupleParamBlunder.mls │ │ ├── Tuples.mls │ │ ├── TypeAliases.mls │ │ ├── TypeOps.mls │ │ ├── TypeSelections.mls │ │ ├── TypeVariables.mls │ │ ├── TypingUnitTerms.mls │ │ ├── TypreMembers.mls │ │ ├── Unapply.mls │ │ ├── UnaryMinus.mls │ │ ├── UndefMatching.mls │ │ ├── Uninstantiable.mls │ │ ├── UnionReordering.mls │ │ ├── Unit.mls │ │ ├── UserDefinedAnnotations.mls │ │ ├── ValSigs.mls │ │ ├── Vals.mls │ │ ├── Varargs.mls │ │ ├── Virtual.mls │ │ ├── WeirdDefs.mls │ │ ├── WeirdUnions.mls │ │ ├── With.mls │ │ ├── i180.mls │ │ ├── i191.mls │ │ ├── repro0.mls │ │ ├── repro1.mls │ │ ├── repro_EvalNegNeg.mls │ │ └── repro_PolymorphicVariants.mls │ ├── parser │ │ ├── Annot.mls │ │ ├── Arrays.mls │ │ ├── BasicSyntax.mls │ │ ├── Binds.mls │ │ ├── Blocks.mls │ │ ├── Brackets.mls │ │ ├── Classes.mls │ │ ├── Comments.mls │ │ ├── ControversialIfSplits.mls │ │ ├── FatArrows.mls │ │ ├── FlatMultiArgLams.mls │ │ ├── Forall.mls │ │ ├── Fun.mls │ │ ├── IfThenElse.mls │ │ ├── Lambdas.mls │ │ ├── Lets.mls │ │ ├── Misc.mls │ │ ├── MultiLineCalls.mls │ │ ├── MultilineFun.mls │ │ ├── NamedArrays.mls │ │ ├── NegativeLits.mls │ │ ├── New.mls │ │ ├── Ops.mls │ │ ├── Records.mls │ │ ├── Select.mls │ │ ├── SpecParams.mls │ │ ├── Subscripts.mls │ │ ├── TypeParams.mls │ │ ├── UserDefinedOpsMaybe.mls │ │ ├── WeirdIfs.mls │ │ ├── Where.mls │ │ ├── Whitespace.mls │ │ └── boolops.mls │ ├── pretyper │ │ ├── Errors.mls │ │ ├── Repro.mls │ │ ├── SymbolKind.mls │ │ └── ucs │ │ │ ├── DualOption.mls │ │ │ ├── NamePattern.mls │ │ │ ├── RecordPattern.mls │ │ │ ├── Refinement.mls │ │ │ ├── SpecilizationCollision.mls │ │ │ ├── Symbol.mls │ │ │ ├── Unapply.mls │ │ │ ├── Unconditional.mls │ │ │ ├── coverage │ │ │ ├── ConflictedCoveredCases.mls │ │ │ ├── ConflictedPatterns.mls │ │ │ ├── CoveredCases.mls │ │ │ ├── DuplicatedCases.mls │ │ │ ├── MissingCases.mls │ │ │ ├── Refinement.mls │ │ │ ├── SealedClasses.mls │ │ │ ├── Tautology.mls │ │ │ └── Unreachable.mls │ │ │ ├── examples │ │ │ ├── AVLTree.mls │ │ │ ├── BinarySearchTree.mls │ │ │ ├── Calculator.mls │ │ │ ├── EitherOrBoth.mls │ │ │ ├── JSON.mls │ │ │ ├── LeftistTree.mls │ │ │ ├── LispInterpreter.mls │ │ │ ├── List.mls │ │ │ ├── ListFold.mls │ │ │ ├── Option.mls │ │ │ ├── Permutations.mls │ │ │ ├── STLC.mls │ │ │ ├── SimpleLisp.mls │ │ │ ├── SimpleList.mls │ │ │ ├── SimpleTree.mls │ │ │ └── ULC.mls │ │ │ ├── patterns │ │ │ ├── AliasPattern.mls │ │ │ ├── Literals.mls │ │ │ └── SimpleTuple.mls │ │ │ └── stages │ │ │ ├── Normalization.mls │ │ │ ├── PostProcessing.mls │ │ │ └── Transformation.mls │ ├── qq │ │ ├── BadConst.mls │ │ ├── Basic.mls │ │ ├── Basic2.mls │ │ ├── Codegen.mls │ │ ├── EffectfulLetInsertion.mls │ │ ├── Extrusions.mls │ │ ├── Hygiene.mls │ │ ├── LetInsertion.mls │ │ ├── LetInsertion_repro.mls │ │ ├── Multiline.mls │ │ ├── Nested.mls │ │ ├── NuSyntax.mls │ │ ├── PEPM.mls │ │ ├── PEPM2.mls │ │ ├── PseudoCod.mls │ │ ├── QQFlag.mls │ │ ├── ScopeTypes.mls │ │ ├── Triple.mls │ │ ├── Unquote.mls │ │ ├── Weird.mls │ │ └── WillfulExtrusion.mls │ ├── scalac │ │ └── i13162.mls │ ├── tricky │ │ ├── IrregularSubtypes.mls │ │ ├── IrregularSubtypes2.mls │ │ └── Pottier.fun │ ├── typegen │ │ ├── TypegenTerms.mls │ │ └── TypegenTypedefs.mls │ └── ucs │ │ ├── AppSplits.mls │ │ ├── CrossBranchCapture.mls │ │ ├── DirectLines.mls │ │ ├── ElseIf.mls │ │ ├── ErrorMessage.mls │ │ ├── Exhaustiveness.mls │ │ ├── Humiliation.mls │ │ ├── Hygiene.mls │ │ ├── HygienicBindings.mls │ │ ├── InterleavedLet.mls │ │ ├── LeadingAnd.mls │ │ ├── LitUCS.mls │ │ ├── MultiwayIf.mls │ │ ├── NestedBranches.mls │ │ ├── NestedOpSplits.mls │ │ ├── NestedPattern.mls │ │ ├── NuPlainConditionals.mls │ │ ├── Or.mls │ │ ├── OverlappedBranches.mls │ │ ├── ParseFailures.mls │ │ ├── ParserFailures.mls │ │ ├── PlainConditionals.mls │ │ ├── SimpleUCS.mls │ │ ├── SplitAfterOp.mls │ │ ├── SplitAnd.mls │ │ ├── SplitAroundOp.mls │ │ ├── SplitBeforeOp.mls │ │ ├── SplitOps.mls │ │ ├── SplitScrutinee.mls │ │ ├── ThenIndent.mls │ │ ├── Tree.mls │ │ ├── TrivialIf.mls │ │ ├── WeirdIf.mls │ │ ├── WeirdSplit.mls │ │ ├── Wildcard.mls │ │ └── zipWith.mls │ └── scala │ └── mlscript │ ├── CodeGenTestHelpers.scala │ ├── DiffTests.scala │ ├── NodeTest.scala │ └── ReplHost.scala ├── ts └── dummy.ts ├── ts2mls ├── js │ └── src │ │ ├── main │ │ └── scala │ │ │ └── ts2mls │ │ │ ├── JSWriter.scala │ │ │ ├── TSCompilerInfo.scala │ │ │ ├── TSData.scala │ │ │ ├── TSNamespace.scala │ │ │ ├── TSProgram.scala │ │ │ ├── TSSourceFile.scala │ │ │ └── types │ │ │ ├── Converter.scala │ │ │ └── TSType.scala │ │ └── test │ │ ├── diff │ │ ├── Array.d.mls │ │ ├── BasicFunctions.d.mls │ │ ├── ClassMember.d.mls │ │ ├── Dec.d.mls │ │ ├── Enum.d.mls │ │ ├── Heritage.d.mls │ │ ├── HighOrderFunc.d.mls │ │ ├── InterfaceMember.d.mls │ │ ├── Intersection.d.mls │ │ ├── Literal.d.mls │ │ ├── MultiFiles.d.mls │ │ ├── Namespace.d.mls │ │ ├── Optional.d.mls │ │ ├── Overload.d.mls │ │ ├── Tuple.d.mls │ │ ├── Type.d.mls │ │ ├── TypeParameter.d.mls │ │ ├── Union.d.mls │ │ └── Variables.d.mls │ │ ├── scala │ │ └── ts2mls │ │ │ └── TSTypeGenerationTests.scala │ │ └── typescript │ │ ├── Array.ts │ │ ├── BasicFunctions.ts │ │ ├── ClassMember.ts │ │ ├── Dec.d.ts │ │ ├── Enum.ts │ │ ├── Heritage.ts │ │ ├── HighOrderFunc.ts │ │ ├── InterfaceMember.ts │ │ ├── Intersection.ts │ │ ├── Literal.ts │ │ ├── Multi1.ts │ │ ├── Multi2.ts │ │ ├── Multi3.ts │ │ ├── Namespace.ts │ │ ├── Optional.ts │ │ ├── Overload.ts │ │ ├── Tuple.ts │ │ ├── Type.ts │ │ ├── TypeParameter.ts │ │ ├── Union.ts │ │ └── Variables.ts └── jvm │ └── src │ └── test │ └── scala │ └── ts2mls │ └── TsTypeDiffTests.scala └── tsconfig.json /.gitattributes: -------------------------------------------------------------------------------- 1 | * eol=lf 2 | bin/mlscript-opt.js linguist-vendored 3 | -------------------------------------------------------------------------------- /.github/workflows/nix.yml: -------------------------------------------------------------------------------- 1 | name: Cpp Backend CI with Nix 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: [ mlscript ] 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | - name: Install Nix 14 | uses: DeterminateSystems/nix-installer-action@main 15 | - uses: rrbutani/use-nix-shell-action@v1 16 | with: 17 | devShell: .#default 18 | - name: Install TypeScript 19 | run: npm ci 20 | - name: Run test 21 | run: sbt -J-Xmx4096M -J-Xss4M test 22 | - name: Check no changes 23 | run: git diff-files -p --exit-code 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .bloop/ 3 | .metals/ 4 | .bsp/ 5 | node_modules/ 6 | metals.sbt 7 | project/Dependencies.scala 8 | project/metals.sbt 9 | **.worksheet.sc 10 | .DS_Store 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.fun": "typescript", 4 | "*.mls": "mlscript" 5 | }, 6 | "typescript.validate.enable": false, 7 | "files.watcherExclude": { 8 | "**/target": true 9 | }, 10 | "[typescript]": { 11 | "editor.quickSuggestions": { 12 | "comments": "off", 13 | "other": "off", 14 | "strings": "off" 15 | } 16 | }, 17 | "files.autoSave": "off" 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Lionel Parreaux 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /compiler/shared/main/scala/mlscript/compiler/debug/Debug.scala: -------------------------------------------------------------------------------- 1 | package mlscript.compiler 2 | 3 | abstract class Debug: 4 | def trace[T](name: String, pre: Any*) 5 | (thunk: => T) 6 | (post: T => Any = Debug.noPostTrace): T 7 | def log(msg: => String): Unit 8 | def writeLine(line: String): Unit 9 | def indent(): Unit 10 | def outdent(): Unit 11 | 12 | object Debug: 13 | val noPostTrace: Any => Any = _ => "" 14 | -------------------------------------------------------------------------------- /compiler/shared/main/scala/mlscript/compiler/debug/DummyDebug.scala: -------------------------------------------------------------------------------- 1 | package mlscript.compiler 2 | 3 | object DummyDebug extends Debug: 4 | def trace[T](name: String, pre: Any*) 5 | (thunk: => T) 6 | (post: T => Any = Debug.noPostTrace): T = thunk 7 | inline def log(msg: => String): Unit = () 8 | def writeLine(line: String): Unit = () 9 | def indent(): Unit = () 10 | def outdent(): Unit = () 11 | -------------------------------------------------------------------------------- /compiler/shared/main/scala/mlscript/compiler/debug/Printable.scala: -------------------------------------------------------------------------------- 1 | package mlscript.compiler 2 | 3 | trait Printable: 4 | def getDebugOutput: DebugOutput 5 | -------------------------------------------------------------------------------- /compiler/shared/main/scala/mlscript/compiler/debug/TreeDebug.scala: -------------------------------------------------------------------------------- 1 | package mlscript.compiler 2 | 3 | import scala.collection.mutable.ArrayBuffer 4 | 5 | class TreeDebug(output: String => Unit) extends RainbowDebug(false): 6 | private val lines = ArrayBuffer[String]() 7 | private var indentation: Int = 0 8 | 9 | override inline def writeLine(line: String): Unit = 10 | output("║"*indentation ++ line) 11 | lines += line 12 | 13 | override def indent(): Unit = 14 | indentation += 1 15 | override def outdent(): Unit = 16 | indentation -= 1 17 | 18 | def getLines: List[String] = lines.toList 19 | -------------------------------------------------------------------------------- /compiler/shared/main/scala/mlscript/compiler/ir/Fresh.scala: -------------------------------------------------------------------------------- 1 | package mlscript.compiler.ir 2 | 3 | import collection.mutable.{HashMap => MutHMap} 4 | import mlscript.utils.shorthands._ 5 | 6 | final class Fresh(div : Char = '$'): 7 | private val counter = MutHMap[Str, Int]() 8 | private def gensym(s: Str) = { 9 | val n = s.lastIndexOf(div) 10 | val (ts, suffix) = s.splitAt(if n == -1 then s.length() else n) 11 | var x = if suffix.stripPrefix(div.toString).forall(_.isDigit) then ts else s 12 | val count = counter.getOrElse(x, 0) 13 | val tmp = s"$x$div$count" 14 | counter.update(x, count + 1) 15 | Name(tmp) 16 | } 17 | 18 | def make(s: Str) = gensym(s) 19 | def make = gensym("x") 20 | 21 | final class FreshInt: 22 | private var counter = 0 23 | def make: Int = { 24 | val tmp = counter 25 | counter += 1 26 | tmp 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /compiler/shared/main/scala/mlscript/compiler/simpledef/Uid.scala: -------------------------------------------------------------------------------- 1 | package mlscript 2 | package compiler 3 | package simpledef 4 | 5 | opaque type Uid[T] = Int 6 | 7 | object Uid: 8 | class Handler[T]: 9 | class State: 10 | private val uidStore = scala.collection.mutable.Map.empty[String, Uid[T]] 11 | def nextUid: Uid[T] = nextUid("") 12 | def nextUid(key: String): Uid[T] = 13 | uidStore.updateWith(key) { 14 | case None => Some(0) 15 | case Some(v) => Some(v + 1) 16 | }.get 17 | object TypeVar extends Handler[TypeVar] 18 | object Term extends Handler[Term] -------------------------------------------------------------------------------- /compiler/shared/test/diff-ir/NuScratch.mls: -------------------------------------------------------------------------------- 1 | :NewParser 2 | :ParseOnly 3 | :UseIR 4 | -------------------------------------------------------------------------------- /compiler/shared/test/diff-ir/Override.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :ParseOnly 3 | :UseIR 4 | :NoTailRec 5 | 6 | :genCpp 7 | :runCpp 8 | :interpIR 9 | module Base { 10 | fun f() = 1 11 | } 12 | module Child extends Base { 13 | fun f() = 2 14 | } 15 | fun main() = 16 | let c = Child() 17 | Base.f(c) 18 | Child.f(c) 19 | main() 20 | //│ |#module| |Base| |{|→|#fun| |f|(||)| |#=| |1|←|↵|}|↵|#module| |Child| |#extends| |Base| |{|→|#fun| |f|(||)| |#=| |2|←|↵|}|↵|#fun| |main|(||)| |#=|→|#let| |c| |#=| |Child|(||)|↵|Base|.f|(|c|)|↵|Child|.f|(|c|)|←|↵|main|(||)| 21 | //│ Parsed: {module Base {fun f = () => 1}; module Child: Base {fun f = () => 2}; fun main = () => {let c = Child(); (Base).f(c,); (Child).f(c,)}; main()} 22 | //│ 23 | //│ 24 | //│ IR: 25 | //│ Program: 26 | //│ class Base() { 27 | //│ def f() = 28 | //│ 1 -- #16 29 | //│ } 30 | //│ class Child() extends Base { 31 | //│ def f() = 32 | //│ 2 -- #17 33 | //│ } 34 | //│ def main() = 35 | //│ let x$1 = Child() in -- #15 36 | //│ let x$2 = Base.f(x$1) in -- #14 37 | //│ let x$3 = Child.f(x$1) in -- #13 38 | //│ x$3 -- #12 39 | //│ let* (x$0) = main() in -- #2 40 | //│ x$0 -- #1 41 | //│ 42 | //│ Interpreted: 43 | //│ 2 44 | //│ 45 | //│ 46 | //│ Execution succeeded: 47 | //│ 2 48 | //│ 49 | -------------------------------------------------------------------------------- /compiler/shared/test/diff-ir/cpp/Makefile: -------------------------------------------------------------------------------- 1 | CXX := g++ 2 | CFLAGS := $(CFLAGS) -O3 -Wall -Wextra -std=c++20 -I. -Wno-inconsistent-missing-override 3 | LDFLAGS := $(LDFLAGS) -lmimalloc -lgmp 4 | SRC := 5 | INCLUDES = mlsprelude.h 6 | DST := 7 | DEFAULT_TARGET := mls 8 | TARGET := $(or $(DST),$(DEFAULT_TARGET)) 9 | 10 | .PHONY: pre all run clean auto 11 | 12 | all: $(TARGET) 13 | 14 | run: $(TARGET) 15 | ./$(TARGET) 16 | 17 | pre: $(SRC) 18 | sed -i '' 's#^//│ ##g' $(SRC) 19 | 20 | clean: 21 | rm -r $(TARGET) $(TARGET).dSYM 22 | 23 | auto: $(TARGET) 24 | 25 | $(TARGET): $(SRC) $(INCLUDES) 26 | $(CXX) $(CFLAGS) $(LDFLAGS) $(SRC) -o $(TARGET) 27 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/CompilerScratch.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/Classes.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class Bar(val x: Int) { 4 | fun foo(x) = x 5 | fun FooMinus(y: Int) = x + y 6 | fun car = foo(2) 7 | } 8 | class Car() { 9 | fun da(b: Bar) = b.foo(2) 10 | } 11 | fun baz(b: Bar) = b.foo(2) 12 | let bar = Bar(42) 13 | baz(bar) 14 | (Car()).da(Bar(1337)) 15 | bar.car 16 | //│ class Bar(x: Int) { 17 | //│ fun FooMinus: (y: Int) -> Int 18 | //│ fun car: 2 19 | //│ fun foo: forall 'a. 'a -> 'a 20 | //│ } 21 | //│ class Car() { 22 | //│ fun da: (b: Bar) -> 2 23 | //│ } 24 | //│ fun baz: (b: Bar) -> 2 25 | //│ let bar: Bar 26 | //│ 2 27 | //│ 28 | //│ Simpledef: 29 | //│ {class Bar(val x: Int,) {fun foo = (x::0,) => x 30 | //│ fun FooMinus = (y: Int,) => +(x, y,) 31 | //│ fun car = foo(2,)} 32 | //│ class Car() {fun da = (b: Bar,) => let selRes$34 = b in case selRes$34 of { Bar => (selRes$34).foo(2,) }} 33 | //│ fun baz = (b: Bar,) => let selRes$48 = b in case selRes$48 of { Bar => (selRes$48).foo(2,) } 34 | //│ let bar = Bar(42,) 35 | //│ baz(bar,) 36 | //│ let selRes$76 = '(' Car() ')' in case selRes$76 of { Car => (selRes$76).da(Bar(1337,),) } 37 | //│ let selRes$98 = bar in case selRes$98 of { Bar => (selRes$98).car }} 38 | //│ End simpledef 39 | //│ 40 | //│ bar 41 | //│ = Bar {} 42 | //│ res 43 | //│ = 2 44 | //│ res 45 | //│ = 2 46 | //│ res 47 | //│ = 2 48 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/ClosureCapture.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :AllowRuntimeErrors 3 | 4 | fun foo(x) = 5 | (f => f(x))(z => z+1) 6 | foo(2) 7 | //│ fun foo: Int -> Int 8 | //│ Int 9 | //│ 10 | //│ Simpledef: 11 | //│ {fun foo = (x::0,) => {'(' (f::1,) => f(x,) ')'((z::2,) => +(z, 1,),)} 12 | //│ foo(2,)} 13 | //│ End simpledef 14 | //│ 15 | //│ res 16 | //│ = 3 17 | 18 | fun f(x) = 19 | (y => f(x+y))(x+1) 20 | f(1) 21 | //│ fun f: Int -> nothing 22 | //│ nothing 23 | //│ 24 | //│ Simpledef: 25 | //│ {fun f = (x::3,) => {'(' (y::4,) => f(+(x, y,),) ')'(+(x, 1,),)} 26 | //│ f(1,)} 27 | //│ End simpledef 28 | //│ 29 | //│ res 30 | //│ Runtime error: 31 | //│ RangeError: Maximum call stack size exceeded 32 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/Constructor.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class X() { 4 | val a = 5 | log("ok") 6 | 6 7 | } 8 | val object = X() 9 | (new X()).a 10 | (new X()).a 11 | object.a 12 | object.a 13 | //│ class X() { 14 | //│ val a: 6 15 | //│ } 16 | //│ val object: X 17 | //│ 6 18 | //│ 19 | //│ Simpledef: 20 | //│ {class X() {let a = {log("ok",) 21 | //│ 6}} 22 | //│ let object = X() 23 | //│ let selRes$20 = '(' (new X)() ')' in case selRes$20 of { X => (selRes$20).a } 24 | //│ let selRes$30 = '(' (new X)() ')' in case selRes$30 of { X => (selRes$30).a } 25 | //│ let selRes$40 = object in case selRes$40 of { X => (selRes$40).a } 26 | //│ let selRes$44 = object in case selRes$44 of { X => (selRes$44).a }} 27 | //│ End simpledef 28 | //│ 29 | //│ object 30 | //│ = X {} 31 | //│ // Output 32 | //│ ok 33 | //│ res 34 | //│ = 6 35 | //│ // Output 36 | //│ ok 37 | //│ res 38 | //│ = 6 39 | //│ // Output 40 | //│ ok 41 | //│ res 42 | //│ = 6 43 | //│ res 44 | //│ = 6 45 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/DelayedEvaluation.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class G(val num: Int) { 4 | val x = 5 | log("once on construction") 6 | num+2 7 | val y() = 8 | log("once every call") 9 | num+2 10 | } 11 | val g = new G(6) 12 | g.y() 13 | g.x 14 | g.y() 15 | g.x 16 | //│ class G(num: Int) { 17 | //│ val x: Int 18 | //│ val y: () -> Int 19 | //│ } 20 | //│ val g: G 21 | //│ Int 22 | //│ 23 | //│ Simpledef: 24 | //│ {class G(val num: Int,) {let x = {log("once on construction",) 25 | //│ +(num, 2,)} 26 | //│ let y = () => {log("once every call",) 27 | //│ +(num, 2,)}} 28 | //│ let g = (new G)(6,) 29 | //│ let selRes$56 = g in case selRes$56 of { G => (selRes$56).y() } 30 | //│ let selRes$64 = g in case selRes$64 of { G => (selRes$64).x } 31 | //│ let selRes$68 = g in case selRes$68 of { G => (selRes$68).y() } 32 | //│ let selRes$76 = g in case selRes$76 of { G => (selRes$76).x }} 33 | //│ End simpledef 34 | //│ 35 | //│ g 36 | //│ = G {} 37 | //│ // Output 38 | //│ once on construction 39 | //│ res 40 | //│ = 8 41 | //│ // Output 42 | //│ once every call 43 | //│ res 44 | //│ = 8 45 | //│ res 46 | //│ = 8 47 | //│ // Output 48 | //│ once every call 49 | //│ res 50 | //│ = 8 51 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/FreeVariables.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class X() { 4 | val num = 5 5 | fun get() = num 6 | } 7 | X().get() 8 | //│ class X() { 9 | //│ fun get: () -> 5 10 | //│ val num: 5 11 | //│ } 12 | //│ 5 13 | //│ 14 | //│ Simpledef: 15 | //│ {class X() {let num = 5 16 | //│ fun get = () => num} 17 | //│ let selRes$10 = X() in case selRes$10 of { X => (selRes$10).get() }} 18 | //│ End simpledef 19 | //│ 20 | //│ res 21 | //│ = 5 22 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/FuncsWithParams.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | abstract class Arithmetic() { 5 | virtual fun use(num1: Int, num2: Int): Int 6 | } 7 | class Add() extends Arithmetic { 8 | fun use(num1, num2) = num1+num2 9 | } 10 | class Sub() extends Arithmetic { 11 | fun use(num1, num2) = num1-num2 12 | } 13 | fun getArith(choice) = if choice == 1 then Add() else Sub() 14 | getArith(1).use(4,6) 15 | getArith(2).use(4,6) 16 | //│ abstract class Arithmetic() { 17 | //│ fun use: (num1: Int, num2: Int) -> Int 18 | //│ } 19 | //│ class Add() extends Arithmetic { 20 | //│ fun use: (Int, Int) -> Int 21 | //│ } 22 | //│ class Sub() extends Arithmetic { 23 | //│ fun use: (Int, Int) -> Int 24 | //│ } 25 | //│ fun getArith: Num -> (Add | Sub) 26 | //│ Int 27 | //│ 28 | //│ Simpledef: 29 | //│ {class Arithmetic() {fun use: (num1: Int, num2: Int) -> Int} 30 | //│ class Add(): Arithmetic {fun use = (num1::0, num2::1,) => +(num1, num2,)} 31 | //│ class Sub(): Arithmetic {fun use = (num1::2, num2::3,) => -(num1, num2,)} 32 | //│ fun getArith = (choice::4,) => if (==(choice, 1,)) then Add() else Sub() 33 | //│ let selRes$58 = getArith(1,) in case selRes$58 of { Sub => (selRes$58).use(4, 6,) 34 | //│ Add => (selRes$58).use(4, 6,) } 35 | //│ let selRes$76 = getArith(2,) in case selRes$76 of { Sub => (selRes$76).use(4, 6,) 36 | //│ Add => (selRes$76).use(4, 6,) }} 37 | //│ End simpledef 38 | //│ 39 | //│ res 40 | //│ = 10 41 | //│ res 42 | //│ = -2 43 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/Inheritance.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | // FIXME: Pattern matches on superclass instead of subclass 4 | class Sup() { 5 | fun add(num1, num2) = num1+num2 6 | } 7 | class Sub1() extends Sup() {} 8 | class Sub2() extends Sub1() {} 9 | Sub1().add(3,4) 10 | Sub2().add(5,6) 11 | //│ class Sup() { 12 | //│ fun add: (Int, Int) -> Int 13 | //│ } 14 | //│ class Sub1() extends Sup { 15 | //│ fun add: (Int, Int) -> Int 16 | //│ } 17 | //│ class Sub2() extends Sub1, Sup { 18 | //│ fun add: (Int, Int) -> Int 19 | //│ } 20 | //│ Int 21 | //│ 22 | //│ Simpledef: 23 | //│ {class Sup() {fun add = (num1::0, num2::1,) => +(num1, num2,)} 24 | //│ class Sub1(): Sup() {} 25 | //│ class Sub2(): Sub1() {} 26 | //│ let selRes$16 = Sub1() in case selRes$16 of { Sup => (selRes$16).add(3, 4,) } 27 | //│ let selRes$32 = Sub2() in case selRes$32 of { Sup => (selRes$32).add(5, 6,) }} 28 | //│ End simpledef 29 | //│ 30 | //│ res 31 | //│ = 7 32 | //│ res 33 | //│ = 11 34 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/Lambda.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class X(val foo: Int => Int){} 5 | class Y(val foo: Int => Bool){} 6 | fun x(pred) = if pred then X(x => x+1) else Y(x => true) 7 | x(true).foo(5) 8 | //│ class X(foo: Int -> Int) 9 | //│ class Y(foo: Int -> Bool) 10 | //│ fun x: Bool -> (X | Y) 11 | //│ Int | false | true 12 | //│ 13 | //│ Simpledef: 14 | //│ {class X(val foo: (Int,) => Int,) {} 15 | //│ class Y(val foo: (Int,) => Bool,) {} 16 | //│ fun x = (pred::0,) => if (pred) then X((x::1,) => +(x, 1,),) else Y((x::2,) => true,) 17 | //│ let selRes$46 = x(true,) in case selRes$46 of { Y => (selRes$46).foo(5,) 18 | //│ X => (selRes$46).foo(5,) }} 19 | //│ End simpledef 20 | //│ 21 | //│ res 22 | //│ = 6 23 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/Lambdas.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | ((f, g) => f(g))(f => f, true) 4 | //│ true 5 | //│ 6 | //│ Simpledef: 7 | //│ {'(' (f::0, g::1,) => f(g,) ')'((f::2,) => f, true,)} 8 | //│ End simpledef 9 | //│ 10 | //│ res 11 | //│ = true 12 | 13 | (b => if b then true else false) (true) 14 | //│ Bool 15 | //│ 16 | //│ Simpledef: 17 | //│ {'(' (b::3,) => if (b) then true else false ')'(true,)} 18 | //│ End simpledef 19 | //│ 20 | //│ res 21 | //│ = true 22 | 23 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/Modules.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Foo() {fun f = 0} 5 | module x { val y = Foo() } 6 | x.y.f 7 | //│ class Foo() { 8 | //│ fun f: 0 9 | //│ } 10 | //│ module x { 11 | //│ val y: Foo 12 | //│ } 13 | //│ 0 14 | //│ 15 | //│ Simpledef: 16 | //│ {class Foo() {fun f = 0} 17 | //│ module x {let y = Foo()} 18 | //│ let selRes$10 = let selRes$12 = x in case selRes$12 of { x => (selRes$12).y } in case selRes$10 of { Foo => (selRes$10).f }} 19 | //│ End simpledef 20 | //│ 21 | //│ res 22 | //│ = 0 23 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/MonoNonLambda.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class A() { 4 | val x = 2 5 | val y() = 3 6 | fun z = 4 7 | fun w() = 5 8 | } 9 | val a = A() 10 | a.x 11 | a.y() 12 | a.z 13 | a.w() 14 | //│ class A() { 15 | //│ fun w: () -> 5 16 | //│ val x: 2 17 | //│ val y: () -> 3 18 | //│ fun z: 4 19 | //│ } 20 | //│ val a: A 21 | //│ 5 22 | //│ 23 | //│ Simpledef: 24 | //│ {class A() {let x = 2 25 | //│ let y = () => 3 26 | //│ fun z = 4 27 | //│ fun w = () => 5} 28 | //│ let a = A() 29 | //│ let selRes$24 = a in case selRes$24 of { A => (selRes$24).x } 30 | //│ let selRes$28 = a in case selRes$28 of { A => (selRes$28).y() } 31 | //│ let selRes$36 = a in case selRes$36 of { A => (selRes$36).z } 32 | //│ let selRes$40 = a in case selRes$40 of { A => (selRes$40).w() }} 33 | //│ End simpledef 34 | //│ 35 | //│ a 36 | //│ = A {} 37 | //│ res 38 | //│ = 2 39 | //│ res 40 | //│ = 3 41 | //│ res 42 | //│ = 4 43 | //│ res 44 | //│ = 5 45 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/MonoTupSelect.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class Foo() {fun f() = 0} 4 | class Bar() {fun f = 0} 5 | [Foo(), Bar()].0.f() 6 | [Foo(), Bar()].1.f 7 | //│ class Foo() { 8 | //│ fun f: () -> 0 9 | //│ } 10 | //│ class Bar() { 11 | //│ fun f: 0 12 | //│ } 13 | //│ 0 14 | //│ 15 | //│ Simpledef: 16 | //│ {class Foo() {fun f = () => 0} 17 | //│ class Bar() {fun f = 0} 18 | //│ let selRes$10 = ([Foo(), Bar(),]).0 in case selRes$10 of { Foo => (selRes$10).f() } 19 | //│ let selRes$32 = ([Foo(), Bar(),]).1 in case selRes$32 of { Bar => (selRes$32).f }} 20 | //│ End simpledef 21 | //│ 22 | //│ res 23 | //│ = 0 24 | //│ res 25 | //│ = 0 26 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/MutableParams.mls: -------------------------------------------------------------------------------- 1 | :NewDefs // TODO: Mutable Parameters 2 | 3 | //class Bar(#x) 4 | //fun foo(#b) = b 5 | //let a = foo(new Bar(1)) 6 | //let b = foo(new Bar(2)) 7 | 8 | //class OneInt(#a){ 9 | // fun inc() = a+1 10 | //} 11 | //(new OneInt(1)).inc() 12 | 13 | //class OneInt(#a){ 14 | // fun add(x) = 15 | // new OneInt(a+x.a) 16 | //} 17 | //(new OneInt(1)).add(new OneInt(2)) 18 | 19 | //trait AnyFoo { 20 | //} 21 | //class FooPlus(#a): AnyFoo { 22 | // fun bar(b) = a + b 23 | //} 24 | //class FooMinus(#a): AnyFoo { 25 | // fun bar(b) = a - b 26 | //} 27 | //fun f(x) = x.bar(42) 28 | //f(new FooPlus(1)) 29 | //f(new FooMinus(2)) 30 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/MutualRec.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :AllowRuntimeErrors 3 | 4 | val any = -20 5 | fun f(x) = 6 | if x > any then 0 7 | else g(x - 1) 8 | fun g(x) = 9 | if x > any then g(x - 1) 10 | else f(x - 2) 11 | g(1) 12 | //│ val any: -20 13 | //│ fun f: Int -> 0 14 | //│ fun g: Int -> 0 15 | //│ 0 16 | //│ 17 | //│ Simpledef: 18 | //│ {let any = -20 19 | //│ fun f = (x::0,) => {if (>(x, any,)) then 0 else g(-(x, 1,),)} 20 | //│ fun g = (x::1,) => {if (>(x, any,)) then g(-(x, 1,),) else f(-(x, 2,),)} 21 | //│ g(1,)} 22 | //│ End simpledef 23 | //│ 24 | //│ any 25 | //│ = -20 26 | //│ res 27 | //│ Runtime error: 28 | //│ RangeError: Maximum call stack size exceeded 29 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/NewOperator.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class Foo(val x: Int) { 4 | } 5 | new Foo(5).x 6 | //│ class Foo(x: Int) 7 | //│ Int 8 | //│ 9 | //│ Simpledef: 10 | //│ {class Foo(val x: Int,) {} 11 | //│ let selRes$4 = (new Foo)(5,) in case selRes$4 of { Foo => (selRes$4).x }} 12 | //│ End simpledef 13 | //│ 14 | //│ res 15 | //│ = 5 16 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/ObjFields.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class X(val bar: Int) {} 5 | class Y(val bar: Str) {} 6 | class A(val foo: X) {} 7 | class B(val foo: Y) {} 8 | fun getObj(pred) = if pred then A(X(1)) else B(Y("abc")) 9 | val x = getObj(true) 10 | x.foo.bar 11 | //│ class X(bar: Int) 12 | //│ class Y(bar: Str) 13 | //│ class A(foo: X) 14 | //│ class B(foo: Y) 15 | //│ fun getObj: Bool -> (A | B) 16 | //│ val x: A | B 17 | //│ Int | Str 18 | //│ 19 | //│ Simpledef: 20 | //│ {class X(val bar: Int,) {} 21 | //│ class Y(val bar: Str,) {} 22 | //│ class A(val foo: X,) {} 23 | //│ class B(val foo: Y,) {} 24 | //│ fun getObj = (pred::0,) => if (pred) then A(X(1,),) else B(Y("abc",),) 25 | //│ let x = getObj(true,) 26 | //│ let selRes$54 = let selRes$56 = x in case selRes$56 of { A => (selRes$56).foo 27 | //│ B => (selRes$56).foo } in case selRes$54 of { Y => (selRes$54).bar 28 | //│ X => (selRes$54).bar }} 29 | //│ End simpledef 30 | //│ 31 | //│ x 32 | //│ = A {} 33 | //│ res 34 | //│ = 1 35 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/ObjMultiFields.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class X(val foo: Int, val bar: Bool) {} 5 | class Y(val foo: Str, val bar: Int) {} 6 | class A(val foo: X) {} 7 | class B(val foo: Y) {} 8 | fun foo(pred) = if pred then A(X(1, false)) else B(Y("abc", 5)) 9 | val x = foo(true) 10 | x.foo.bar 11 | foo(false).foo.bar 12 | //│ class X(foo: Int, bar: Bool) 13 | //│ class Y(foo: Str, bar: Int) 14 | //│ class A(foo: X) 15 | //│ class B(foo: Y) 16 | //│ fun foo: Bool -> (A | B) 17 | //│ val x: A | B 18 | //│ Int | false | true 19 | //│ 20 | //│ Simpledef: 21 | //│ {class X(val foo: Int, val bar: Bool,) {} 22 | //│ class Y(val foo: Str, val bar: Int,) {} 23 | //│ class A(val foo: X,) {} 24 | //│ class B(val foo: Y,) {} 25 | //│ fun foo = (pred::0,) => if (pred) then A(X(1, false,),) else B(Y("abc", 5,),) 26 | //│ let x = foo(true,) 27 | //│ let selRes$58 = let selRes$60 = x in case selRes$60 of { A => (selRes$60).foo 28 | //│ B => (selRes$60).foo } in case selRes$58 of { Y => (selRes$58).bar 29 | //│ X => (selRes$58).bar } 30 | //│ let selRes$64 = let selRes$66 = foo(false,) in case selRes$66 of { B => (selRes$66).foo 31 | //│ A => (selRes$66).foo } in case selRes$64 of { X => (selRes$64).bar 32 | //│ Y => (selRes$64).bar }} 33 | //│ End simpledef 34 | //│ 35 | //│ x 36 | //│ = A {} 37 | //│ res 38 | //│ = false 39 | //│ res 40 | //│ = 5 41 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/ObjsSelection.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class X() { 4 | val num = 6 5 | } 6 | class Y() { 7 | val num = true 8 | } 9 | fun foo(pred) = if pred then X() else Y() 10 | fun id(x) = x 11 | val a = foo(true) 12 | val b = id(a) 13 | b.num 14 | //│ class X() { 15 | //│ val num: 6 16 | //│ } 17 | //│ class Y() { 18 | //│ val num: true 19 | //│ } 20 | //│ fun foo: Bool -> (X | Y) 21 | //│ fun id: forall 'a. 'a -> 'a 22 | //│ val a: X | Y 23 | //│ val b: X | Y 24 | //│ 6 | true 25 | //│ 26 | //│ Simpledef: 27 | //│ {class X() {let num = 6} 28 | //│ class Y() {let num = true} 29 | //│ fun foo = (pred::0,) => if (pred) then X() else Y() 30 | //│ fun id = (x::1,) => x 31 | //│ let a = foo(true,) 32 | //│ let b = id(a,) 33 | //│ let selRes$48 = b in case selRes$48 of { Y => (selRes$48).num 34 | //│ X => (selRes$48).num }} 35 | //│ End simpledef 36 | //│ 37 | //│ a 38 | //│ = X {} 39 | //│ b 40 | //│ = X {} 41 | //│ res 42 | //│ = 6 43 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/Polymorphic.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | let b = true 4 | class OneInt(val a: Int){ 5 | fun get = () -> a 6 | } 7 | class OneBool(val b: Bool){ 8 | fun get = () -> b 9 | } 10 | (if b then OneInt(1) else OneBool(true)).get() 11 | //│ let b: true 12 | //│ class OneInt(a: Int) { 13 | //│ fun get: () -> Int 14 | //│ } 15 | //│ class OneBool(b: Bool) { 16 | //│ fun get: () -> Bool 17 | //│ } 18 | //│ Int | false | true 19 | //│ 20 | //│ Simpledef: 21 | //│ {let b = true 22 | //│ class OneInt(val a: Int,) {fun get = () => a} 23 | //│ class OneBool(val b: Bool,) {fun get = () => b} 24 | //│ let selRes$20 = '(' if (b) then OneInt(1,) else OneBool(true,) ')' in case selRes$20 of { OneInt => (selRes$20).get() 25 | //│ OneBool => (selRes$20).get() }} 26 | //│ End simpledef 27 | //│ 28 | //│ b 29 | //│ = true 30 | //│ res 31 | //│ = 1 32 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/Record.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class K() { 5 | val f = true 6 | } 7 | val x = { 8 | 5: "five", 9 | 7: "seven", 10 | f: 6 11 | } 12 | fun muddle(pred) = if pred then K() else x 13 | muddle(false).f 14 | //│ class K() { 15 | //│ val f: true 16 | //│ } 17 | //│ val x: {5: "five", 7: "seven", f: 6} 18 | //│ fun muddle: Bool -> (K | {5: "five", 7: "seven", f: 6}) 19 | //│ 6 | true 20 | //│ 21 | //│ Simpledef: 22 | //│ {class K() {let f = true} 23 | //│ let x = '{' {5: "five", 7: "seven", f: 6} '}' 24 | //│ fun muddle = (pred::0,) => if (pred) then K() else x 25 | //│ (muddle(false,)).f} 26 | //│ End simpledef 27 | //│ 28 | //│ x 29 | //│ = { '5': 'five', '7': 'seven', f: 6 } 30 | //│ res 31 | //│ = 6 32 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/RecursiveFunc.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | fun fac(n) = 4 | if (n > 1) then fac(n - 1) * n else 1 5 | fac(5) 6 | //│ fun fac: Int -> Int 7 | //│ Int 8 | //│ 9 | //│ Simpledef: 10 | //│ {fun fac = (n::0,) => {if ('(' >(n, 1,) ')') then *(fac(-(n, 1,),), n,) else 1} 11 | //│ fac(5,)} 12 | //│ End simpledef 13 | //│ 14 | //│ res 15 | //│ = 120 16 | 17 | // TODO: Support for specialized pattern matching types 18 | // In this example, the type of l in count(l) would need to be constrained to 19 | // object & ~(), which requires implementing neg types, intersections, etc. 20 | class List(val l: List | Nil | undefined, val hasTail: Bool) {} 21 | class Nil(val l: List | Nil | undefined, val hasTail: Bool) {} 22 | fun count(lst) = 23 | if lst.hasTail then 24 | let l = lst.l 25 | if l is undefined then 1 else count(l)+1 26 | else 0 27 | count(new List(new List(new Nil(undefined, false), true), true)) 28 | //│ class List(l: List | Nil | (), hasTail: Bool) 29 | //│ class Nil(l: List | Nil | (), hasTail: Bool) 30 | //│ fun count: forall 'a. 'a -> Int 31 | //│ Int 32 | //│ where 33 | //│ 'a <: {hasTail: Bool, l: Object & 'a & ~() | ()} 34 | //│ 35 | //│ Simpledef: 36 | //│ /!!!\ Uncaught error: java.lang.Exception: Internal Error: Could not constrain (ProdObj(Some(Var(prim$Unit)),List(),List()),ConsObj(None,List((Var(l),ConsVar(15,13_selres))))) 37 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/SelfReference.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :AllowRuntimeErrors 3 | 4 | fun f(x) = f(x) 5 | f(0) 6 | f(1) 7 | //│ fun f: anything -> nothing 8 | //│ nothing 9 | //│ 10 | //│ Simpledef: 11 | //│ {fun f = (x::0,) => f(x,) 12 | //│ f(0,) 13 | //│ f(1,)} 14 | //│ End simpledef 15 | //│ 16 | //│ res 17 | //│ Runtime error: 18 | //│ RangeError: Maximum call stack size exceeded 19 | //│ res 20 | //│ Runtime error: 21 | //│ RangeError: Maximum call stack size exceeded 22 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/SimpleClasses.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class Foo(val x: Int){ 4 | fun bar(y) = x+y 5 | fun boo(z) = bar(z)+x 6 | } 7 | (Foo(1)).boo(2) 8 | //│ class Foo(x: Int) { 9 | //│ fun bar: Int -> Int 10 | //│ fun boo: Int -> Int 11 | //│ } 12 | //│ Int 13 | //│ 14 | //│ Simpledef: 15 | //│ {class Foo(val x: Int,) {fun bar = (y::0,) => +(x, y,) 16 | //│ fun boo = (z::1,) => +(bar(z,), x,)} 17 | //│ let selRes$38 = '(' Foo(1,) ')' in case selRes$38 of { Foo => (selRes$38).boo(2,) }} 18 | //│ End simpledef 19 | //│ 20 | //│ res 21 | //│ = 4 22 | 23 | class OneInt(val a: Int){ 24 | fun fac: () -> Int 25 | fun fac = () -> 26 | if(a > 0) then (OneInt(a - 1)).fac() else 1 27 | } 28 | (OneInt(10)).fac() 29 | //│ class OneInt(a: Int) { 30 | //│ fun fac: () -> Int 31 | //│ } 32 | //│ Int 33 | //│ 34 | //│ Simpledef: 35 | //│ {class OneInt(val a: Int,) {fun fac: () -> Int 36 | //│ fun fac = () => {if ('(' >(a, 0,) ')') then let selRes$20 = '(' OneInt(-(a, 1,),) ')' in case selRes$20 of { OneInt => (selRes$20).fac() } else 1}} 37 | //│ let selRes$50 = '(' OneInt(10,) ')' in case selRes$50 of { OneInt => (selRes$50).fac() }} 38 | //│ End simpledef 39 | //│ 40 | //│ res 41 | //│ = 1 42 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/SimpleConditionals.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | if true then 1 else 0 3 | if 1+1 > 1 then 1 - 1 else 1*1 4 | //│ Int 5 | //│ 6 | //│ Simpledef: 7 | //│ {if (true) then 1 else 0 8 | //│ if (>(+(1, 1,), 1,)) then -(1, 1,) else *(1, 1,)} 9 | //│ End simpledef 10 | //│ 11 | //│ res 12 | //│ = 1 13 | //│ res 14 | //│ = 0 15 | 16 | let b = true 17 | if(b) then 1 else 2 18 | //│ let b: true 19 | //│ 1 | 2 20 | //│ 21 | //│ Simpledef: 22 | //│ {let b = true 23 | //│ if ('(' b ')') then 1 else 2} 24 | //│ End simpledef 25 | //│ 26 | //│ b 27 | //│ = true 28 | //│ res 29 | //│ = 1 30 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/SimpleFunc.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | fun f(x: Bool) = if x then 42 else 1337 4 | //│ fun f: (x: Bool) -> (1337 | 42) 5 | //│ 6 | //│ Simpledef: 7 | //│ {fun f = (x: Bool,) => if (x) then 42 else 1337} 8 | //│ End simpledef 9 | //│ 10 | 11 | fun foo() = 42 12 | //│ fun foo: () -> 42 13 | //│ 14 | //│ Simpledef: 15 | //│ {fun foo = () => 42} 16 | //│ End simpledef 17 | //│ 18 | 19 | fun f(x) = 20 | if(x > 0) then x+1 else x - 1 21 | f(2)+3 22 | //│ fun f: Int -> Int 23 | //│ Int 24 | //│ 25 | //│ Simpledef: 26 | //│ {fun f = (x::0,) => {if ('(' >(x, 0,) ')') then +(x, 1,) else -(x, 1,)} 27 | //│ +(f(2,), 3,)} 28 | //│ End simpledef 29 | //│ 30 | //│ res 31 | //│ = 6 32 | 33 | fun foo(x, #b) = if b then x else 1337 34 | let a = foo(42, true) 35 | let b = foo(23, false) 36 | //│ fun foo: forall 'a. ('a, Bool) -> (1337 | 'a) 37 | //│ let a: 1337 | 42 38 | //│ let b: 1337 | 23 39 | //│ 40 | //│ Simpledef: 41 | //│ {fun foo = (x::1, #b::2,) => if (b) then x else 1337 42 | //│ let a = foo(42, true,) 43 | //│ let b = foo(23, false,)} 44 | //│ End simpledef 45 | //│ 46 | //│ a 47 | //│ = 42 48 | //│ b 49 | //│ = 1337 50 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Defunctionalize/TupleSelect.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | [0,"abc",()].2 5 | //│ () 6 | //│ 7 | //│ Simpledef: 8 | //│ {([0, "abc", undefined,]).2} 9 | //│ End simpledef 10 | //│ 11 | //│ res 12 | //│ = undefined 13 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Lifter/FunctionTypeAnnotations.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :ParseOnly 3 | 4 | :lift 5 | fun foo(x) = 6 | (y) => x+y 7 | foo(1)(2) 8 | foo(2)(2) 9 | //│ |#fun| |foo|(|x|)| |#=|→|(|y|)| |#=>| |x|+|y|←|↵|foo|(|1|)|(|2|)|↵|foo|(|2|)|(|2|)| 10 | //│ Parsed: {fun foo = (x,) => {('(' y ')',) => +(x, y,)}; foo(1,)(2,); foo(2,)(2,)} 11 | //│ Lifted: 12 | //│ TypingUnit { 13 | //│ class Lambda1$2$1([x,]) {fun apply = ('(' y ')',) => +((this).x, y,)} 14 | //│ fun foo$1 = (x,) => {{Lambda1$2$1(x,)}} 15 | //│ Code(List(foo$1(1,)(2,))) 16 | //│ Code(List(foo$1(2,)(2,))) 17 | //│ } 18 | //│ 19 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Lifter/LiftNew.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | :lift 4 | class A(num: Int) { 5 | } 6 | new A(5) 7 | //│ Lifted: 8 | //│ TypingUnit { 9 | //│ class A$1([num: Int,]) {} 10 | //│ Code(List((new A$1)(5,))) 11 | //│ } 12 | //│ class A$1(num: Int) 13 | //│ A$1 14 | //│ res 15 | //│ = A$1 {} 16 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Lifter/NestedClasses.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | :e // FIXME: Nested class references not updated 4 | :lift 5 | class X() { 6 | class Y() {} 7 | } 8 | X.Y() 9 | //│ Lifted: 10 | //│ TypingUnit { 11 | //│ class X$1_Y$2([par$X$1,]) {} 12 | //│ class X$1([]) {} 13 | //│ Code(List((X$1).Y())) 14 | //│ } 15 | //│ ╔══[ERROR] Class parameters currently need type annotations 16 | //│ ╙── 17 | //│ ╔══[ERROR] Type mismatch in field selection: 18 | //│ ║ l.8: X.Y() 19 | //│ ║ ^^ 20 | //│ ╙── expression of type `() -> X$1` does not have field 'Y' 21 | //│ class X$1_Y$2(par$X$1: error) 22 | //│ class X$1() 23 | //│ error 24 | //│ res 25 | //│ Runtime error: 26 | //│ TypeError: X$1.Y is not a function 27 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Lifter/NestedFuncs.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | :e // FIXME: Incorrect lifting 4 | :lift 5 | fun test(a) = 6 | let f(x) = a + x 7 | f 8 | test(6)(4) 9 | //│ Lifted: 10 | //│ TypingUnit { 11 | //│ let f$2 = (x, a,) => +(a, x,) 12 | //│ fun test$1 = (a,) => {f$2} 13 | //│ Code(List(test$1(6,)(4,))) 14 | //│ } 15 | //│ ╔══[ERROR] Type mismatch in application: 16 | //│ ║ l.8: test(6)(4) 17 | //│ ║ ^^^^ 18 | //│ ╟── argument of type `[4]` does not match type `[?a, ?b]` 19 | //│ ║ l.8: test(6)(4) 20 | //│ ║ ^ 21 | //│ ╟── Note: constraint arises from tuple literal: 22 | //│ ║ l.6: let f(x) = a + x 23 | //│ ╙── ^^^^^^ 24 | //│ val f$2: (Int, Int) -> Int 25 | //│ fun test$1: anything -> (Int, Int) -> Int 26 | //│ Int | error 27 | //│ f$2 28 | //│ = [Function: f$2] 29 | //│ res 30 | //│ = NaN 31 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Lifter/ParameterizedInheritance.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | // FIXME: correctly lift parameterized inheritance 4 | :lift 5 | val c = 5 6 | class Sup(val a: Int){ 7 | virtual fun foo = () -> a 8 | } 9 | class Sub(b: Int) extends Sup(b+b){ 10 | } 11 | class Sub2(c: Int) extends Sub(c+c){ 12 | fun foo = () -> c+c 13 | } 14 | (Sub(10)).foo() 15 | (Sub2(c)).foo() 16 | //│ Lifted: 17 | //│ TypingUnit { 18 | //│ class Sup$1([val a: Int,]) {fun foo = () => (this).a} 19 | //│ class Sub$2([b: Int,]): Sup$1(+((this).b, (this).b,),) {} 20 | //│ class Sub2$3([c: Int,]): Sub$2(+(c$1, c$1,),) {fun foo = () => +(c$1, c$1,)} 21 | //│ let c$1 = 5 22 | //│ Code(List(('(' Sub$2(10,) ')').foo())) 23 | //│ Code(List(('(' Sub2$3(c$1,) ')').foo())) 24 | //│ } 25 | //│ ╔══[ERROR] identifier not found: this 26 | //│ ╙── 27 | //│ ╔══[ERROR] identifier not found: this 28 | //│ ╙── 29 | //│ class Sup$1(a: Int) { 30 | //│ fun foo: () -> Int 31 | //│ } 32 | //│ class Sub$2(b: Int) extends Sup$1 { 33 | //│ fun foo: () -> Int 34 | //│ } 35 | //│ class Sub2$3(c: Int) extends Sub$2, Sup$1 { 36 | //│ fun foo: () -> Int 37 | //│ } 38 | //│ val c$1: 5 39 | //│ Int 40 | //│ Code generation encountered an error: 41 | //│ unguarded recursive use of by-value binding c$1 42 | -------------------------------------------------------------------------------- /compiler/shared/test/diff/Lifter/TypedClassParams.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | :lift 4 | class A() {} 5 | class B(foo: A) {} 6 | //│ Lifted: 7 | //│ TypingUnit {class A$1([]) {}; class B$2([foo: A$1,]) {}} 8 | //│ class A$1() 9 | //│ class B$2(foo: A$1) 10 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "mlscript"; 3 | 4 | inputs.nixpkgs.url = "github:NixOS/nixpkgs"; 5 | inputs.flake-utils.url = "github:numtide/flake-utils"; 6 | inputs.sbt-deriv.url = "github:zaninime/sbt-derivation"; 7 | inputs.sbt-deriv.inputs.nixpkgs.follows = "nixpkgs"; 8 | 9 | outputs = { self, nixpkgs, flake-utils, sbt-deriv }: 10 | flake-utils.lib.eachDefaultSystem 11 | (system: 12 | let 13 | sbtOverlay = self: super: { 14 | sbt = super.sbt.override { jre = super.jdk8_headless; }; 15 | }; 16 | pkgs = import nixpkgs { 17 | inherit system; 18 | overlays = [ sbtOverlay ]; 19 | }; 20 | in with pkgs; { 21 | devShells.default = mkShell { 22 | buildInputs = [ 23 | clang 24 | gcc 25 | gnumake 26 | boost 27 | gmp 28 | mimalloc 29 | sbt 30 | nodejs_22 31 | ]; 32 | }; 33 | }); 34 | } -------------------------------------------------------------------------------- /js/src/main/scala/fansi/Str.scala: -------------------------------------------------------------------------------- 1 | // Temporary shims since fansi doesn't seem to be released for this Scala version yet 2 | 3 | package fansi 4 | 5 | import scala.language.implicitConversions 6 | 7 | class Str(underlying: CharSequence) { 8 | def plainText(): String = s"$underlying" 9 | override def toString(): String = s"$underlying" 10 | } 11 | object Str { 12 | implicit def implicitApply(x: CharSequence): Str = new Str(x) 13 | def join(args: Str*): Str = args.foldLeft("")(_ ++ _.plainText()) 14 | } 15 | -------------------------------------------------------------------------------- /local_testing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | MLscript demonstration 7 | 8 | 9 |

MLscript demonstration

10 |
11 | 37 |
38 |
39 | 40 |
41 | 42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mlscript", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "typescript": "^4.7.4" 9 | } 10 | }, 11 | "node_modules/typescript": { 12 | "version": "4.7.4", 13 | "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.7.4.tgz", 14 | "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", 15 | "bin": { 16 | "tsc": "bin/tsc", 17 | "tsserver": "bin/tsserver" 18 | }, 19 | "engines": { 20 | "node": ">=4.2.0" 21 | } 22 | } 23 | }, 24 | "dependencies": { 25 | "typescript": { 26 | "version": "4.7.4", 27 | "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.7.4.tgz", 28 | "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "typescript": "^4.7.4" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.10.1 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.wartremover" % "sbt-wartremover" % "3.2.0") 2 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0") 3 | addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.2.0") 4 | -------------------------------------------------------------------------------- /shared/src/main/scala/mlscript/codegen/Error.scala: -------------------------------------------------------------------------------- 1 | package mlscript.codegen 2 | 3 | import scala.collection.mutable.ArrayBuffer 4 | 5 | final case class CodeGenError(message: String) extends Exception(message) 6 | 7 | final case class UnimplementedError(symbol: StubValueSymbol) 8 | extends Exception({ 9 | val names = new ArrayBuffer[String]() 10 | var current: Option[StubValueSymbol] = Some(symbol) 11 | while ( 12 | current match { 13 | case Some(sym) => 14 | names += sym.lexicalName 15 | current = sym.previous 16 | true 17 | case None => false 18 | } 19 | ) () 20 | val sep = ", " 21 | val concat = { 22 | val joined = names.mkString(sep) 23 | val pos = joined.lastIndexOf(sep) 24 | if (pos > -1) { 25 | joined.substring(0, pos) + " and " + joined.substring(pos + sep.length) 26 | } else { 27 | joined 28 | } 29 | } 30 | val be = if (names.lengthIs > 1) "are" else "is" 31 | s"$concat $be not implemented" 32 | }) 33 | -------------------------------------------------------------------------------- /shared/src/main/scala/mlscript/package.scala: -------------------------------------------------------------------------------- 1 | import mlscript.utils._ 2 | import mlscript.utils.shorthands._ 3 | 4 | package object mlscript { 5 | 6 | type Raise = Diagnostic => Unit 7 | 8 | val ExtrusionPrefix: Str = "??" 9 | 10 | } 11 | -------------------------------------------------------------------------------- /shared/src/main/scala/mlscript/pretyper/Diagnosable.scala: -------------------------------------------------------------------------------- 1 | package mlscript 2 | package pretyper 3 | 4 | import scala.collection.mutable.Buffer 5 | import Diagnostic.Source, Message.MessageContext 6 | import mlscript.utils._, shorthands._ 7 | 8 | /** 9 | * A trait containing a mutable buffer of diagnostics. 10 | */ 11 | trait Diagnosable { 12 | private val diagnosticBuffer = Buffer.empty[Diagnostic] 13 | 14 | protected def raise(diagnostics: Diagnostic): Unit = 15 | diagnosticBuffer += diagnostics 16 | 17 | protected def raiseMany(diagnostics: IterableOnce[Diagnostic]): Unit = 18 | diagnosticBuffer ++= diagnostics 19 | 20 | protected def raiseError(source: Source, messages: (Message -> Opt[Loc])*): Unit = 21 | raise(ErrorReport(messages.toList, newDefs = true, source)) 22 | 23 | protected def raiseWarning(source: Source, messages: (Message -> Opt[Loc])*): Unit = 24 | raise(WarningReport(messages.toList, newDefs = true, source)) 25 | 26 | @inline final def filterDiagnostics(f: Diagnostic => Bool): Ls[Diagnostic] = 27 | diagnosticBuffer.iterator.filter(f).toList 28 | 29 | @inline final def getDiagnostics: Ls[Diagnostic] = diagnosticBuffer.toList 30 | } 31 | -------------------------------------------------------------------------------- /shared/src/main/scala/mlscript/utils/FastParseHelpers.scala: -------------------------------------------------------------------------------- 1 | package mlscript 2 | 3 | import mlscript.utils._, shorthands._ 4 | 5 | class FastParseHelpers(val blockStr: Str, val lines: collection.IndexedSeq[Str]) { 6 | def this(lines: IndexedSeq[Str]) = this(lines.mkString("\n"), lines) 7 | def this(blockStr: Str) = this(blockStr, blockStr.splitSane('\n')) 8 | 9 | // this line-parsing logic was copied from fastparse internals: 10 | val lineNumberLookup: Array[Int] = fastparse.internal.Util.lineNumberLookup(blockStr) 11 | def getLineColAt(index: Int): (Int, String, Int) = { 12 | val lineNum = lineNumberLookup.indexWhere(_ > index) match { 13 | case -1 => lineNumberLookup.length 14 | case n => math.max(1, n) 15 | } 16 | val idx = lineNum.min(lines.length) - 1 17 | val colNum = index - lineNumberLookup(idx) + 1 18 | val lineStr = lines(idx) 19 | (lineNum, lineStr, colNum) 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /shared/src/main/scala/mlscript/utils/Identity.scala: -------------------------------------------------------------------------------- 1 | package mlscript.utils 2 | 3 | 4 | class Identity[T <: AnyRef](val value: T) { 5 | 6 | override def equals(other: Any): Boolean = other match { 7 | case that: Identity[_] => (that.value: Any) is this.value 8 | case _ => false 9 | } 10 | 11 | override def hashCode(): Int = System.identityHashCode(value) 12 | 13 | } 14 | 15 | -------------------------------------------------------------------------------- /shared/src/main/scala/mlscript/utils/Lazy.scala: -------------------------------------------------------------------------------- 1 | package mlscript.utils 2 | 3 | import shorthands._ 4 | 5 | abstract class Box[+A] { 6 | def get: Opt[A] 7 | def get_! : A 8 | def isComputing: Bool 9 | } 10 | 11 | class Eager[+A](val value: A) extends Box[A] { 12 | def isComputing = false 13 | lazy val get = S(value) 14 | def get_! = value 15 | } 16 | 17 | class Lazy[A](thunk: => A) extends Box[A] { 18 | def isComputing = _isComputing 19 | private var _isComputing = false 20 | private var _value: Opt[A] = N 21 | def get = if (_isComputing) N else S(get_!) 22 | def get_! = { 23 | assert(!_isComputing) 24 | _compute 25 | } 26 | private def _compute = { 27 | _isComputing = true 28 | try { 29 | val v = thunk 30 | _value = S(v) 31 | v 32 | } finally { 33 | _isComputing = false 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /shared/src/main/scala/mlscript/utils/algorithms.scala: -------------------------------------------------------------------------------- 1 | package mlscript.utils 2 | 3 | import scala.annotation.tailrec 4 | import scala.collection.immutable.SortedMap 5 | 6 | object algorithms { 7 | final class CyclicGraphError(message: String) extends Exception(message) 8 | 9 | /** 10 | * Sort a graph topologically. 11 | * 12 | * @param edges edges (target, source) in the directed acyclic graph 13 | * @param nodes provide if you want to include some isolated nodes in the result 14 | * @return 15 | */ 16 | def topologicalSort[A: Ordering](edges: Iterable[(A, A)], nodes: Iterable[A] = Nil): Iterable[A] = { 17 | @tailrec 18 | def sort(toPreds: SortedMap[A, Set[A]], done: Iterable[A]): Iterable[A] = { 19 | val (noPreds, hasPreds) = toPreds.partition { _._2.isEmpty } 20 | if (noPreds.isEmpty) { 21 | if (hasPreds.isEmpty) done else throw new CyclicGraphError(hasPreds.toString) 22 | } else { 23 | val found = noPreds.map { _._1 } 24 | sort(SortedMap.from(hasPreds.view.mapValues(_ -- found)), done ++ found) 25 | } 26 | } 27 | val toPred = edges.foldLeft(SortedMap.from(nodes.map { _ -> Set.empty[A] })) { (acc, e) => 28 | acc + (e._1 -> (acc.getOrElse(e._1, Set()) + e._2)) + (e._2 -> acc.getOrElse(e._2, Set())) 29 | } 30 | sort(toPred, Seq()) 31 | } 32 | } -------------------------------------------------------------------------------- /shared/src/test/diff/basics/AsBindings.fun: -------------------------------------------------------------------------------- 1 | 2 | let f x = 3 | discard / x as { v: (y) } // TODO accept plain `y` 4 | log / v 5 | log / y + 1 6 | //│ f: {v: int} -> unit 7 | 8 | let f x = 9 | discard / x as { v: (y) } // TODO accept plain `y` 10 | log / v + 1 11 | log / y 12 | //│ f: {v: int} -> unit 13 | 14 | 15 | -------------------------------------------------------------------------------- /shared/src/test/diff/basics/ExplicitDatatypes.fun: -------------------------------------------------------------------------------- 1 | 2 | data Left v 3 | data Right v 4 | //│ Defined class Left[+v] 5 | //│ Defined class Right[+v] 6 | //│ Left: 'a -> Left['a] 7 | //│ Right: 'a -> Right['a] 8 | 9 | let Either l r = Left l | Right r // TODO actual type parameters 10 | //│ Either: 'a -> 'b -> (Left['a] | Right['b]) 11 | 12 | Either 1 2 13 | //│ res: Left[1] | Right[2] 14 | 15 | res.v 16 | //│ res: 1 | 2 17 | 18 | -------------------------------------------------------------------------------- /shared/src/test/diff/basics/Flow.fun: -------------------------------------------------------------------------------- 1 | 2 | :p 3 | data L x 4 | data R x 5 | //│ Parsed: data L(...x); data R(...x); 6 | //│ Desugared: class L[x]: {x: x} 7 | //│ Desugared: class R[x]: {x: x} 8 | //│ Desugared: def L: forall x. (...x) -> L[x] 9 | //│ AST: Def(false,Var(L),Right(PolyType(List(Left(TypeName(x))),Function(TypeName(x),AppliedType(TypeName(L),List(TypeName(x)))))),true) 10 | //│ Desugared: def R: forall x. (...x) -> R[x] 11 | //│ AST: Def(false,Var(R),Right(PolyType(List(Left(TypeName(x))),Function(TypeName(x),AppliedType(TypeName(R),List(TypeName(x)))))),true) 12 | //│ Defined class L[+x] 13 | //│ Defined class R[+x] 14 | //│ L: 'a -> L['a] 15 | //│ R: 'a -> R['a] 16 | 17 | // TODO flow-type 18 | :e 19 | let f x = if x is L y then y else 0 20 | //│ ╔══[ERROR] Unsupported pattern shape: 21 | //│ ║ l.19: let f x = if x is L y then y else 0 22 | //│ ╙── ^^^ 23 | //│ ╔══[ERROR] identifier not found: y 24 | //│ ║ l.19: let f x = if x is L y then y else 0 25 | //│ ╙── ^ 26 | //│ f: error -> (0 | error) 27 | 28 | // TODO 29 | // true and false 30 | // :e 31 | // 1 and 2 32 | 33 | -------------------------------------------------------------------------------- /shared/src/test/diff/basics/Iso.fun: -------------------------------------------------------------------------------- 1 | // A file to isolating tests for easier debugging 2 | 3 | 4 | -------------------------------------------------------------------------------- /shared/src/test/diff/basics/RecFuns.fun: -------------------------------------------------------------------------------- 1 | 2 | // From a comment on the Simple-sub blog post: 3 | 4 | let rec r a = r 5 | //│ r: 'r 6 | //│ where 7 | //│ 'r :> anything -> 'r 8 | 9 | let join a b = if true then a else b 10 | //│ join: 'a -> 'a -> 'a 11 | 12 | // "Lateral" hash consing 13 | let s = join r r 14 | //│ s: 'r 15 | //│ where 16 | //│ 'r :> anything -> 'r 17 | 18 | -------------------------------------------------------------------------------- /shared/src/test/diff/basics/Twice.fun: -------------------------------------------------------------------------------- 1 | 2 | let twice f x = f / f x 3 | //│ twice: ('a -> 'b & 'b -> 'c) -> 'a -> 'c 4 | // Note: the pretty-printed type of `twice` *used to be* simplified to ('a -> ('a & 'b)) -> 'a -> 'b 5 | // (another equivalent simplification is ('a | 'b -> 'a) -> 'b -> 'a); 6 | // this simplification lost some information in the context of first-class polymorphism 7 | // because function types effectively become non-mergeable without losing precsion... 8 | // (Also see this HN thread: https://news.ycombinator.com/item?id=13783237) 9 | 10 | twice(x => x + 1) 11 | //│ res: int -> int 12 | 13 | twice twice 14 | //│ res: ('a -> 'b & 'b -> ('a & 'c)) -> 'a -> 'c 15 | 16 | let f = x => 1, x 17 | //│ f: 'a -> (1, 'a,) 18 | 19 | // Note: now that we instantiate during constraint solving instead of on variable reference, 20 | // we get the more useful type: 'a -> (1, (1, 'a,),). 21 | // Previously, we were getting: 'a -> ((1, 'c | 'b | 'a,) as 'b) 22 | twice f 23 | //│ res: 'a -> (1, (1, 'a,),) 24 | 25 | twice / x => x, x 26 | //│ res: 'a -> (('a, 'a,), ('a, 'a,),) 27 | 28 | let one = twice (o => o.x) { x: { x: 1 } } 29 | //│ one: 1 30 | 31 | 32 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/Escape.mls: -------------------------------------------------------------------------------- 1 | () 2 | //│ res: () 3 | //│ = [] 4 | 5 | :js 6 | :escape 7 | def console: nothing 8 | //│ // Query 1 is empty 9 | //│ // End of generated code 10 | //│ console: nothing 11 | //│ = 12 | 13 | :js 14 | console.log "hello" 15 | //│ // Query 1 16 | //│ res = console.log("hello"); 17 | //│ // End of generated code 18 | //│ res: nothing 19 | //│ = undefined 20 | 21 | :js 22 | 0 23 | //│ // Query 1 24 | //│ res = 0; 25 | //│ // End of generated code 26 | //│ res: 0 27 | //│ = 0 28 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/LogInfo.mls: -------------------------------------------------------------------------------- 1 | 2 | :js 3 | log 1 4 | //│ // Prelude 5 | //│ function log(x) { 6 | //│ return console.info(x); 7 | //│ } 8 | //│ let res; 9 | //│ // Query 1 10 | //│ res = log(1); 11 | //│ // End of generated code 12 | //│ = undefined 13 | //│ // Output 14 | //│ 1 15 | 16 | :escape 17 | def console: nothing 18 | //│ console: nothing 19 | //│ = 20 | 21 | console.log 1 22 | //│ res: nothing 23 | //│ = undefined 24 | 25 | console.info(1) 26 | //│ res: nothing 27 | //│ = undefined 28 | //│ // Output 29 | //│ 1 30 | 31 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/NewClasses.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class C[A](n: A) { 5 | fun f = g 6 | fun g = 0 7 | } 8 | //│ class C[A](n: A) { 9 | //│ fun f: 0 10 | //│ fun g: 0 11 | //│ } 12 | 13 | 14 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/NuFuns.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | :js 5 | fun foo = 6 | let bar(x) = x + 1 7 | bar(10) 8 | //│ fun foo: Int 9 | //│ // Prelude 10 | //│ let res; 11 | //│ class TypingUnit {} 12 | //│ const typing_unit = new TypingUnit; 13 | //│ // Query 1 14 | //│ globalThis.foo = function foo() { 15 | //│ return ((() => { 16 | //│ let bar = (x) => x + 1; 17 | //│ return bar(10); 18 | //│ })()); 19 | //│ }; 20 | //│ // End of generated code 21 | 22 | fun foo = 23 | class C(a: Int) { fun bar(x) = a + x + 1 } 24 | C(100).bar(10) 25 | foo 26 | //│ fun foo: Int 27 | //│ Int 28 | //│ res 29 | //│ = 111 30 | 31 | 32 | fun main = 33 | log("Hello") 34 | main 35 | //│ fun main: () 36 | //│ () 37 | //│ res 38 | //│ = undefined 39 | //│ // Output 40 | //│ Hello 41 | 42 | fun main = 43 | log("Hello") 44 | //│ fun main: () 45 | 46 | main 47 | //│ () 48 | //│ res 49 | //│ = undefined 50 | //│ // Output 51 | //│ Hello 52 | 53 | 54 | fun main = 55 | mixin B { log(1) } 56 | log(0) 57 | module M extends B 58 | log(2) 59 | main 60 | //│ fun main: () 61 | //│ () 62 | //│ res 63 | //│ = undefined 64 | //│ // Output 65 | //│ 0 66 | //│ 1 67 | //│ 2 68 | 69 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/NuParentheses.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | :js 5 | 16 / (2 / 2) 6 | //│ Num 7 | //│ // Prelude 8 | //│ let res; 9 | //│ class TypingUnit {} 10 | //│ const typing_unit = new TypingUnit; 11 | //│ // Query 1 12 | //│ res = 16 / (2 / 2); 13 | //│ // End of generated code 14 | //│ res 15 | //│ = 16 16 | 17 | :js 18 | 1 - (3 - 5) 19 | //│ Int 20 | //│ // Prelude 21 | //│ class TypingUnit1 {} 22 | //│ const typing_unit1 = new TypingUnit1; 23 | //│ // Query 1 24 | //│ res = 1 - (3 - 5); 25 | //│ // End of generated code 26 | //│ res 27 | //│ = 3 28 | 29 | 30 | fun (--) minusminus(a, b) = a - b 31 | //│ fun (--) minusminus: (Int, Int) -> Int 32 | 33 | :js 34 | 1 -- (3 -- 5) 35 | //│ Int 36 | //│ // Prelude 37 | //│ class TypingUnit3 {} 38 | //│ const typing_unit3 = new TypingUnit3; 39 | //│ // Query 1 40 | //│ res = minusminus(1, minusminus(3, 5)); 41 | //│ // End of generated code 42 | //│ res 43 | //│ = 3 44 | 45 | 46 | fun (-+-) complex(a, b) = a - 2*b 47 | //│ fun (-+-) complex: (Int, Int) -> Int 48 | 49 | :js 50 | 1 -+- (3 -+- 5) 51 | //│ Int 52 | //│ // Prelude 53 | //│ class TypingUnit5 {} 54 | //│ const typing_unit5 = new TypingUnit5; 55 | //│ // Query 1 56 | //│ res = complex(1, complex(3, 5)); 57 | //│ // End of generated code 58 | //│ res 59 | //│ = 15 60 | 61 | 62 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/NuReplHost.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | // * This should crash due to `error`, 5 | // * but the crash is somehow swallowed and we get the result of the previous statement instead! 6 | // * The same happens with any other side effect, like `log(...)` 7 | // * Note: this doesn't happen if the last line is in a spearate diff-test block 8 | :showRepl 9 | :re 10 | fun foo(x) = error 11 | let r = foo(1) 12 | //│ fun foo: anything -> nothing 13 | //│ let r: nothing 14 | //│ ┌ Block at NuReplHost.mls:10 15 | //│ ├─┬ Prelude 16 | //│ │ ├── Code 17 | //│ │ │ function error() { 18 | //│ │ │ throw new Error("an error was thrown"); 19 | //│ │ │ } 20 | //│ │ │ let res; 21 | //│ │ │ class TypingUnit {} 22 | //│ │ │ const typing_unit = new TypingUnit; 23 | //│ │ └── Reply 24 | //│ │ undefined 25 | //│ ├─┬ Query 1/2 26 | //│ │ ├── Prelude: 27 | //│ │ ├── Code: 28 | //│ │ ├── globalThis.foo = function foo(x) { 29 | //│ │ ├── return error(); 30 | //│ │ ├── }; 31 | //│ │ ├── Intermediate: [Function: foo] 32 | //│ │ └── Reply: [success] [Function: foo] 33 | //│ └─┬ Query 2/2 34 | //│ ├── Prelude: 35 | //│ ├── Code: 36 | //│ ├── globalThis.r = foo(1); 37 | //│ └── Reply: [runtime error] Error: an error was thrown 38 | //│ r 39 | //│ Runtime error: 40 | //│ Error: an error was thrown 41 | 42 | :re 43 | r 44 | //│ nothing 45 | //│ res 46 | //│ Runtime error: 47 | //│ ReferenceError: r is not defined 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/ParameterPattern.mls: -------------------------------------------------------------------------------- 1 | // This test file ensures that parameter destruction patterns are translated correctly. 2 | () 3 | //│ res: () 4 | //│ = [] 5 | 6 | :js 7 | def volatile ((this, break)) = this + break 8 | //│ // Query 1 9 | //│ globalThis.volatile1 = function volatile1([ 10 | //│ this$, 11 | //│ break$ 12 | //│ ]) { 13 | //│ return this$ + break$; 14 | //│ }; 15 | //│ // End of generated code 16 | //│ volatile: ((int, int,),) -> int 17 | //│ = [Function: volatile1] 18 | 19 | :js 20 | def volatile1 { debugger; continue } = debugger + continue 21 | //│ // Query 1 22 | //│ globalThis.volatile11 = function volatile11({ 23 | //│ "debugger": debugger$, 24 | //│ "continue": continue$ 25 | //│ }) { 26 | //│ return debugger$ + continue$; 27 | //│ }; 28 | //│ // End of generated code 29 | //│ volatile1: {continue: int, debugger: int} -> int 30 | //│ = [Function: volatile11] 31 | 32 | :js 33 | def volatile2 export = export + 2 34 | //│ // Query 1 35 | //│ globalThis.volatile2 = function volatile2(export$) { 36 | //│ return export$ + 2; 37 | //│ }; 38 | //│ // End of generated code 39 | //│ volatile2: int -> int 40 | //│ = [Function: volatile2] 41 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/PatternMatch.mls: -------------------------------------------------------------------------------- 1 | trait T 2 | //│ Defined trait T 3 | 4 | // Traits with Primitives 5 | 6 | t = T 1 7 | //│ t: 1 & #T 8 | //│ = [Number: 1] 9 | 10 | t + 1 11 | //│ res: int 12 | //│ = 2 13 | 14 | case t of { T -> 0 } 15 | //│ res: 0 16 | //│ = 0 17 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/Res.mls: -------------------------------------------------------------------------------- 1 | // This test tracks how `res` works. 2 | 3 | 0 4 | //│ res: 0 5 | //│ = 0 6 | 7 | :js 8 | res + 1 9 | //│ // Query 1 10 | //│ res = res + 1; 11 | //│ // End of generated code 12 | //│ res: int 13 | //│ = 1 14 | 15 | :js 16 | res + 1 17 | //│ // Query 1 18 | //│ res = res + 1; 19 | //│ // End of generated code 20 | //│ res: int 21 | //│ = 2 22 | 23 | :js 24 | res + 1 25 | //│ // Query 1 26 | //│ res = res + 1; 27 | //│ // End of generated code 28 | //│ res: int 29 | //│ = 3 30 | 31 | :js 32 | res + 1 33 | //│ // Query 1 34 | //│ res = res + 1; 35 | //│ // End of generated code 36 | //│ res: int 37 | //│ = 4 38 | 39 | :js 40 | res + 1 41 | //│ // Query 1 42 | //│ res = res + 1; 43 | //│ // End of generated code 44 | //│ res: int 45 | //│ = 5 46 | 47 | :js 48 | res == 4 49 | //│ // Query 1 50 | //│ res = res == 4; 51 | //│ // End of generated code 52 | //│ res: bool 53 | //│ = false 54 | 55 | :js 56 | def res = 0 57 | //│ // Query 1 58 | //│ globalThis.res1 = function res1() { 59 | //│ return 0; 60 | //│ }; 61 | //│ // End of generated code 62 | //│ res: 0 63 | //│ = [Function: res1] 64 | 65 | // However, we can shadow `res`! 66 | 67 | :js 68 | res + 1 69 | //│ // Query 1 70 | //│ res = res1() + 1; 71 | //│ // End of generated code 72 | //│ res: int 73 | //│ = 1 74 | 75 | :js 76 | res + 1 77 | //│ // Query 1 78 | //│ res = res + 1; 79 | //│ // End of generated code 80 | //│ res: int 81 | //│ = 2 82 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/Shadowing.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | :js 5 | x => 6 | x => 7 | x + 1 8 | //│ anything -> Int -> Int 9 | //│ // Prelude 10 | //│ let res; 11 | //│ class TypingUnit {} 12 | //│ const typing_unit = new TypingUnit; 13 | //│ // Query 1 14 | //│ res = ((x) => (() => { 15 | //│ return ((x) => (() => { 16 | //│ return x + 1; 17 | //│ })()); 18 | //│ })()); 19 | //│ // End of generated code 20 | //│ res 21 | //│ = [Function: res] 22 | 23 | 24 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/Unicode.mls: -------------------------------------------------------------------------------- 1 | 2 | :js 3 | "τ → π" 4 | //│ // Prelude 5 | //│ let res; 6 | //│ // Query 1 7 | //│ res = "\u03C4 \u2192 \u03C0"; 8 | //│ // End of generated code 9 | //│ res: "τ → π" 10 | //│ = 'τ → π' 11 | 12 | :js 13 | "🌮" 14 | //│ // Query 1 15 | //│ res = "\uD83C\uDF2E"; 16 | //│ // End of generated code 17 | //│ res: "🌮" 18 | //│ = '🌮' 19 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/While.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | // * TODO improve code-gen (no immediately-applied lambdas) 5 | :js 6 | mut let i = 0 7 | while i < 10 do 8 | log(i) 9 | set i = i + 1 10 | i 11 | //│ mut let i: Int 12 | //│ Int 13 | //│ // Prelude 14 | //│ function log(x) { 15 | //│ return console.info(x); 16 | //│ } 17 | //│ let res; 18 | //│ class TypingUnit {} 19 | //│ const typing_unit = new TypingUnit; 20 | //│ // Query 1 21 | //│ globalThis.i = 0; 22 | //│ // Query 2 23 | //│ res = (() => { 24 | //│ while (i < 10) { 25 | //│ (() => { 26 | //│ log(i); 27 | //│ return void(i = i + 1); 28 | //│ })() 29 | //│ } 30 | //│ })(); 31 | //│ // Query 3 32 | //│ res = i; 33 | //│ // End of generated code 34 | //│ i 35 | //│ = 0 36 | //│ res 37 | //│ = undefined 38 | //│ // Output 39 | //│ 0 40 | //│ 1 41 | //│ 2 42 | //│ 3 43 | //│ 4 44 | //│ 5 45 | //│ 6 46 | //│ 7 47 | //│ 8 48 | //│ 9 49 | //│ res 50 | //│ = 10 51 | 52 | i 53 | //│ Int 54 | //│ res 55 | //│ = 10 56 | 57 | 58 | let foo = 59 | if true then (set i = 0), () else () 60 | () 61 | //│ let foo: () 62 | //│ foo 63 | //│ = undefined 64 | 65 | mut let min = 123 66 | let go = 67 | if true then set min = 0 else () 68 | 1 69 | //│ mut let min: 0 | 123 70 | //│ let go: 1 71 | //│ min 72 | //│ = 123 73 | //│ go 74 | //│ = 1 75 | 76 | 77 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp-lit/Jim.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | 3 | 4 | // TODO also try stuff from his intersection type systems 5 | 6 | 7 | // ============ A Polar Type System (System P) ============ 8 | 9 | // λf. f (λx. x) 10 | fun f -> f (fun x -> x) 11 | //│ res: ((forall 'a. 'a -> 'a) -> 'b) -> 'b 12 | //│ = [Function: res] 13 | 14 | // λy. y y 15 | fun y -> y y 16 | //│ res: ('a -> 'b & 'a) -> 'b 17 | //│ = [Function: res] 18 | 19 | // Typeable in P; not in ML nor I2: 20 | // (λf. f (λx. x)) (λy. y y) 21 | (fun f -> f (fun x -> x)) (fun y -> y y) 22 | //│ res: 'a -> 'a 23 | //│ = [Function (anonymous)] 24 | 25 | 26 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp/AA.mls: -------------------------------------------------------------------------------- 1 | 2 | // https://github.com/cliffclick/aa/issues/28 3 | pair x y = (x, y) 4 | I = (fun x->x); 5 | K = (fun x->(fun y->x)); 6 | W = (fun x->(x x)); 7 | term = (fun z->(fun y ->((y (z I))(z K)))); 8 | test = (term W); 9 | (test (fun x -> (fun y -> (pair (x 3) (((y "a") "b") "c")) ) )) 10 | //│ pair: 'a -> 'b -> ('a, 'b,) 11 | //│ = [Function: pair] 12 | //│ I: 'a -> 'a 13 | //│ = [Function: I] 14 | //│ K: 'a -> anything -> 'a 15 | //│ = [Function: K] 16 | //│ W: ('a -> 'b & 'a) -> 'b 17 | //│ = [Function: W] 18 | //│ term: ((forall 'a. 'a -> 'a) -> 'b & (forall 'c. 'c -> anything -> 'c) -> 'd) -> ('b -> 'd -> 'e) -> 'e 19 | //│ = [Function: term] 20 | //│ test: ((forall 'a. 'a -> 'a) -> (forall 'b. anything -> 'b -> anything -> 'b) -> 'c) -> 'c 21 | //│ = [Function (anonymous)] 22 | //│ res: (3, "b",) 23 | //│ = [ 3, 'b' ] 24 | 25 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp/Aliases.mls: -------------------------------------------------------------------------------- 1 | :NoJS 2 | 3 | 4 | type Sid = forall 'A. 'A -> 'A 5 | //│ Defined type alias Sid 6 | 7 | type Sid2 = 'B -> 'B 8 | //│ Defined type alias Sid2 9 | 10 | type A1 = forall 'S. 'S -> ('S | Sid) 11 | //│ Defined type alias A1 12 | 13 | 14 | 15 | def a: Sid -> Sid 16 | //│ a: Sid -> Sid 17 | 18 | a : Sid2 -> Sid2 : Sid -> Sid 19 | //│ res: Sid -> Sid 20 | 21 | a = error : A1 22 | //│ A1 23 | //│ <: a: 24 | //│ Sid -> Sid 25 | 26 | 27 | // def f: A1 -> Sid 28 | def f: A1 -> A1 29 | //│ f: A1 -> A1 30 | 31 | def f (x: A1) = x id 32 | //│ A1 -> ('a -> 'a | Sid) 33 | //│ <: f: 34 | //│ A1 -> A1 35 | 36 | // def f: A1 -> Sid 37 | def f: A1 -> A1 38 | //│ f: A1 -> A1 39 | 40 | def f (x: Sid -> Sid) = x (fun y -> y) 41 | //│ (Sid -> Sid) -> Sid 42 | //│ <: f: 43 | //│ A1 -> A1 44 | 45 | 46 | type A2 = forall 'a. (('a | Sid) -> 'a) -> 'a -> ('a | Sid) 47 | type A3 = (Sid -> Sid) -> Sid -> Sid 48 | //│ Defined type alias A2 49 | //│ Defined type alias A3 50 | 51 | error : A2 : A3 52 | //│ res: A3 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp/NoRecursiveTypes.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | 3 | 4 | :e 5 | foo = 6 | let rec f x = f x.a in 0 7 | //│ ╔══[ERROR] Inferred recursive type: 'a 8 | //│ where 9 | //│ 'a <: {a: 'a} 10 | //│ ║ l.6: let rec f x = f x.a in 0 11 | //│ ╙── ^^^ 12 | //│ foo: 0 13 | //│ = 0 14 | 15 | 16 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp/OverloadSimplif.mls: -------------------------------------------------------------------------------- 1 | :NoJS 2 | 3 | 4 | def foo f x = 5 | if true then f x 6 | else f (id x) 7 | //│ foo: ('a -> 'b) -> 'a -> 'b 8 | 9 | def foo k f x = 10 | if true then f x 11 | else f (k x) 12 | //│ foo: ('a -> 'b) -> (('a | 'b) -> 'c) -> 'a -> 'c 13 | 14 | // * Not ethe simplified type, similar to the one above, as expected 15 | foo id 16 | //│ res: ('a -> 'b) -> 'a -> 'b 17 | 18 | 19 | def f: ('a -> 'b & 'c -> 'b & 'a -> 'c) -> 'a -> 'b 20 | //│ f: (('a | 'c) -> 'b & 'a -> 'c) -> 'a -> 'b 21 | 22 | def f: int -> int & nothing -> string 23 | //│ f: int -> int 24 | 25 | def f: int -> int & string -> anything 26 | //│ f: int -> int & string -> anything 27 | 28 | def f: int -> int & 1 -> number 29 | //│ f: int -> int 30 | 31 | def f: int -> int & 'a -> 'a 32 | //│ f: int -> int & 'a -> 'a 33 | 34 | 35 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp/PolyParams.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | 3 | 4 | def foo(f: forall 'a. 'a -> 'a) = 5 | (f 1, f true) 6 | //│ foo: (forall 'a. 'a -> 'a) -> (1, true,) 7 | //│ = [Function: foo] 8 | 9 | fooid = foo id 10 | //│ fooid: (1, true,) 11 | //│ = [ 1, true ] 12 | 13 | fooid.0 14 | fooid.1 15 | //│ res: 1 16 | //│ = 1 17 | //│ res: true 18 | //│ = true 19 | 20 | def foo(f: (forall 'A. 'A -> 'A) -> (forall 'B. 'B -> 'B)) = 21 | id f id (f id) 22 | //│ foo: ((forall 'A. 'A -> 'A) -> (forall 'B. 'B -> 'B)) -> 'B0 -> 'B0 23 | //│ = [Function: foo1] 24 | 25 | foo id 26 | //│ res: 'B -> 'B 27 | //│ = [Function: id] 28 | 29 | foo id id 30 | //│ res: 'a -> 'a 31 | //│ = [Function: id] 32 | 33 | 34 | 35 | def bui_ty: forall 'a. (forall 'b. 'a -> 'b) -> () 36 | //│ bui_ty: (nothing -> nothing) -> () 37 | //│ = 38 | 39 | // :d 40 | bui_ty = bui_ty 41 | //│ (nothing -> nothing) -> () 42 | //│ <: bui_ty: 43 | //│ (nothing -> nothing) -> () 44 | //│ = 45 | //│ bui_ty is not implemented 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp/QML_exist_Records_min_3.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | :DontDistributeForalls 3 | :NoJS 4 | 5 | 6 | type ArraysImpl[A] = { sub: A -> A } 7 | //│ Defined type alias ArraysImpl[=A] 8 | 9 | type ArraysImplConsumer[A] = ArraysImpl[A] -> int 10 | //│ Defined type alias ArraysImplConsumer[=A] 11 | 12 | def stepImpl_ty: ArraysImpl['a] -> ArraysImpl['a] 13 | //│ stepImpl_ty: ArraysImpl['a] -> ArraysImpl['a] 14 | 15 | 16 | // * There used to be a wrongly-simplified `'a <: nothing` bound here 17 | def s arr (k: ArraysImplConsumer['a]) = arr (fun impl -> k (stepImpl_ty impl)) 18 | //│ s: ((ArraysImpl['a] -> int) -> 'b) -> ArraysImplConsumer['a] -> 'b 19 | 20 | // * ...although we could see that it shouldn't be simplified to nothing: 21 | :ns 22 | s 23 | //│ res: forall 'b 'a 'a0 'c. 'b -> (forall 'a1 'd. ArraysImplConsumer['a1] -> 'd) 24 | //│ where 25 | //│ 'd :> 'c 26 | //│ 'a1 :> 'a0 27 | //│ <: 'a 28 | //│ 'b <: (forall 'e 'a2 'f. 'e -> 'f) -> 'c 29 | //│ 'f :> int 30 | //│ 'e <: ArraysImpl['a2] 31 | //│ 'a2 :> 'a 32 | //│ <: 'a0 33 | //│ 'a <: 'a0 34 | //│ 'a0 <: 'a 35 | 36 | 37 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp/SkolemErrors.mls: -------------------------------------------------------------------------------- 1 | 2 | :NoJS 3 | 4 | 5 | def k: (forall 'a. 'a -> 'a) -> int 6 | //│ k: (forall 'a. 'a -> 'a) -> int 7 | 8 | 9 | fun x -> k x 10 | //│ res: (forall 'a. 'a -> 'a) -> int 11 | 12 | fun x -> k (fun y -> x y) 13 | //│ res: (??a -> ??a0) -> int 14 | 15 | 16 | 17 | 18 | :ShowRelativeLineNums 19 | :AllowTypeErrors 20 | 21 | :e 22 | k (fun x -> x + 1) 23 | //│ ╔══[ERROR] Type mismatch in application: 24 | //│ ║ l.+1: k (fun x -> x + 1) 25 | //│ ║ ^^^^^^^^^^^^^^^^^^ 26 | //│ ╟── type `'a` is not an instance of type `int` 27 | //│ ║ l.5: def k: (forall 'a. 'a -> 'a) -> int 28 | //│ ║ ^^ 29 | //│ ╟── Note: constraint arises from reference: 30 | //│ ║ l.+1: k (fun x -> x + 1) 31 | //│ ║ ^ 32 | //│ ╟── Note: quantified type variable 'a is defined at: 33 | //│ ║ l.5: def k: (forall 'a. 'a -> 'a) -> int 34 | //│ ╙── ^^ 35 | //│ res: error | int 36 | 37 | 38 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlf-examples/ex_rvr_validate.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | 3 | // (* Value restriction. *) 4 | // let id x = x 5 | // let x = id id in x 1, x true 6 | // let x = (id id:'a) in x 1, x true 7 | // ;; 8 | def id x = x 9 | let x = id id in (x 1, x true) 10 | let x = id id : 'a in (x 1, x true) 11 | //│ id: 'a -> 'a 12 | //│ = [Function: id] 13 | //│ res: (1, true,) 14 | //│ = [ 1, true ] 15 | //│ res: (1, true,) 16 | //│ = [ 1, true ] 17 | 18 | // type sid = ['a] 'a -> 'a 19 | // ;; 20 | type Sid = forall 'a. 'a -> 'a 21 | //│ Defined type alias Sid 22 | 23 | // let annot x = (x:sid) 24 | // ;; 25 | def annot x = x : Sid 26 | //│ annot: Sid -> Sid 27 | //│ = [Function: annot] 28 | 29 | // let delta x = let y = (x:sid) in y y 30 | // ;; 31 | def delta x = let y = x : Sid in y y 32 | //│ delta: Sid -> Sid 33 | //│ = [Function: delta] 34 | 35 | // let delta x = let y = (annot x) in y y 36 | // ;; 37 | def delta x = let y = annot x in y y 38 | //│ delta: Sid -> Sid 39 | //│ = [Function: delta1] 40 | 41 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlf-examples/ex_vr_validate.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | 3 | // (* Value restriction. *) 4 | // let id x = x 5 | def id x = x 6 | //│ id: 'a -> 'a 7 | //│ = [Function: id] 8 | 9 | // untype let x = id id in x 1, x true 10 | // untype let x = (id id:'a) in x 1, x true 11 | // ;; 12 | let x = id id in (x 1, x true) 13 | let x = (id id : 'a) in (x 1, x true) 14 | //│ res: (1, true,) 15 | //│ = [ 1, true ] 16 | //│ res: (1, true,) 17 | //│ = [ 1, true ] 18 | 19 | // type sid = ['a] 'a -> 'a 20 | // ;; 21 | type Sid = forall 'a. 'a -> 'a 22 | //│ Defined type alias Sid 23 | 24 | // let annot x = (x:sid) 25 | // ;; 26 | def annot x = x : Sid 27 | //│ annot: Sid -> Sid 28 | //│ = [Function: annot] 29 | 30 | // let delta x = let y = (x:sid) in y y 31 | // ;; 32 | def delta x = let y = (x : Sid) in y y 33 | //│ delta: Sid -> Sid 34 | //│ = [Function: delta] 35 | 36 | // untype fun x -> let y = (annot x) in y y 37 | // ;; 38 | fun x -> let y = annot x in y y 39 | //│ res: Sid -> Sid 40 | //│ = [Function: res] 41 | 42 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/ADTsRepro.mls: -------------------------------------------------------------------------------- 1 | 2 | type Add[E] = { x: E -> E } 3 | //│ Defined type alias Add[=E] 4 | 5 | def e2: Add['e] as 'e 6 | //│ e2: 'e 7 | //│ where 8 | //│ 'e := Add['e] 9 | //│ = 10 | 11 | e2 : Add['e] as 'e 12 | //│ res: 'e 13 | //│ where 14 | //│ 'e := Add['e] 15 | //│ = 16 | //│ e2 is not implemented 17 | 18 | 19 | def f0: ('a -> int) as 'a 20 | //│ f0: 'a 21 | //│ where 22 | //│ 'a := 'a -> int 23 | //│ = 24 | 25 | // :e // * Did not work before when added subtype checking to constraining... 26 | f0 = f0 27 | //│ 'a 28 | //│ where 29 | //│ 'a := 'a -> int 30 | //│ <: f0: 31 | //│ 'a 32 | //│ where 33 | //│ 'a := 'a -> int 34 | //│ = 35 | //│ f0 is not implemented 36 | 37 | 38 | type F1 = F1 -> int 39 | //│ Defined type alias F1 40 | 41 | def f1: F1 42 | //│ f1: F1 43 | //│ = 44 | 45 | f1 = f1 46 | //│ F1 47 | //│ <: f1: 48 | //│ F1 49 | //│ = 50 | //│ f1 is not implemented 51 | 52 | 53 | type F2[A] = F2[A] -> A 54 | //│ Defined type alias F2[=A] 55 | 56 | def f1: F2[int] 57 | //│ f1: F2[int] 58 | //│ = 59 | 60 | f1 = f1 61 | //│ F2[int] 62 | //│ <: f1: 63 | //│ F2[int] 64 | //│ = 65 | //│ f1 is not implemented 66 | 67 | 68 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Baber.mls: -------------------------------------------------------------------------------- 1 | 2 | class Foo[A]: { x: A } 3 | class Bar 4 | //│ Defined class Foo[+A] 5 | //│ Defined class Bar 6 | 7 | def f e = case e of 8 | Foo -> e.y, 9 | Foo -> e.z, 10 | _ -> e 11 | //│ f: (Foo[?] & {y: 'y} | 'y & ~#Foo) -> 'y 12 | //│ = [Function: f] 13 | 14 | :ns 15 | f 16 | //│ res: forall 'a 'b 'y 'c 'z 'd. 'a -> ('y | 'z | 'd) 17 | //│ where 18 | //│ 'a <: #Foo & 'b | (#Foo & 'c | 'd & ~#Foo) & ~#Foo 19 | //│ 'c <: {z: 'z} 20 | //│ 'b <: {y: 'y} 21 | //│ = [Function: f] 22 | 23 | class Foo2: Foo[int] & { y: int } 24 | //│ Defined class Foo2 25 | 26 | f (Foo2{x=1;y=2}) 27 | //│ res: 2 28 | //│ = 2 29 | 30 | // #Foo 31 | 32 | def f e = case e of 33 | Foo2 -> e.y, 34 | Foo -> e.z, 35 | //│ f: (Foo[?] & {z: 'y} & ~#Foo2 | (Foo2\x with {y: 'y})) -> 'y 36 | //│ = [Function: f1] 37 | 38 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/BadClasses.mls: -------------------------------------------------------------------------------- 1 | :AllowTypeErrors 2 | 3 | 4 | class Box[T]: { inner: T } 5 | method Get = this.inner 6 | method Get2 = this.x 7 | //│ ╔══[ERROR] Type mismatch in field selection: 8 | //│ ║ l.6: method Get2 = this.x 9 | //│ ║ ^^^^^^ 10 | //│ ╟── reference of type `Box[T] & this` does not have field 'x' 11 | //│ ║ l.6: method Get2 = this.x 12 | //│ ╙── ^^^^ 13 | //│ Defined class Box[+T] 14 | //│ Defined Box.Get: Box['T] -> 'T 15 | //│ Defined Box.Get2: Box[?] -> error 16 | 17 | 18 | class Box2[T]: { inner: T } 19 | method Test = this.inner + 1 20 | //│ ╔══[ERROR] Type mismatch in operator application: 21 | //│ ║ l.19: method Test = this.inner + 1 22 | //│ ║ ^^^^^^^^^^^^ 23 | //│ ╟── field selection of type `T` is not an instance of type `int` 24 | //│ ║ l.19: method Test = this.inner + 1 25 | //│ ║ ^^^^^^^^^^ 26 | //│ ╟── Note: class type parameter T is defined at: 27 | //│ ║ l.18: class Box2[T]: { inner: T } 28 | //│ ╙── ^ 29 | //│ Defined class Box2[+T] 30 | //│ Defined Box2.Test: Box2[?] -> (error | int) 31 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Boolean.mls: -------------------------------------------------------------------------------- 1 | type Boolean = Tru | Fals 2 | class Tru 3 | class Fals 4 | def Tru: Tru 5 | def Fals: Fals 6 | //│ Defined type alias Boolean 7 | //│ Defined class Tru 8 | //│ Defined class Fals 9 | //│ Tru: Tru 10 | //│ = 11 | //│ Fals: Fals 12 | //│ = 13 | 14 | :js 15 | Tru: Boolean 16 | //│ // Query 1 aborted: Tru is not implemented 17 | //│ // End of generated code 18 | //│ res: Boolean 19 | //│ = 20 | //│ Tru is not implemented 21 | 22 | :e 23 | :ge 24 | Boolean 25 | //│ ╔══[ERROR] identifier not found: Boolean 26 | //│ ║ l.24: Boolean 27 | //│ ╙── ^^^^^^^ 28 | //│ res: error 29 | //│ Code generation encountered an error: 30 | //│ type alias Boolean is not a valid expression 31 | 32 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/EitherClasses.mls: -------------------------------------------------------------------------------- 1 | class Left[A]: { value: A } 2 | //│ Defined class Left[+A] 3 | 4 | Left{value=1} 5 | //│ res: Left[1] 6 | //│ = Left { value: 1 } 7 | 8 | def Left value = Left{ value } 9 | //│ Left: 'value -> Left['value] 10 | //│ = [Function: Left1] 11 | 12 | class Right[A]: { value: A } 13 | def Right value = Right{ value } 14 | //│ Defined class Right[+A] 15 | //│ Right: 'value -> Right['value] 16 | //│ = [Function: Right1] 17 | 18 | testVal = if true then Left 1 else Right 2 19 | //│ testVal: Left[1] | Right[2] 20 | //│ = Left { value: 1 } 21 | 22 | testVal.value 23 | //│ res: 1 | 2 24 | //│ = 1 25 | 26 | res = case testVal of 27 | { Left -> testVal.value 28 | | Right -> 1 29 | } 30 | //│ res: 1 31 | //│ = 1 32 | 33 | res: 1 34 | //│ res: 1 35 | //│ = 1 36 | 37 | case res of { 1 -> "ok" } 38 | //│ res: "ok" 39 | //│ = 'ok' 40 | 41 | res = case testVal of 42 | { Left -> testVal 43 | | Right -> 1 44 | } 45 | //│ res: 1 | Left[1] 46 | //│ = Left { value: 1 } 47 | 48 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Group_2022_05_10.mls: -------------------------------------------------------------------------------- 1 | 2 | def f x = (x 1, x "ok") 3 | //│ f: (1 -> 'a & "ok" -> 'b) -> ('a, 'b,) 4 | //│ = [Function: f] 5 | 6 | f (fun x -> (x, x)) 7 | //│ res: ((1, 1,), ("ok", "ok",),) 8 | //│ = [ [ 1, 1 ], [ 'ok', 'ok' ] ] 9 | 10 | (fun id -> id id 0) (fun x -> x) 11 | //│ res: 0 12 | //│ = 0 13 | 14 | fun id -> id id 0 15 | //│ res: ('a -> 0 -> 'b & 'a) -> 'b 16 | //│ = [Function: res] 17 | 18 | fun x -> x 19 | //│ res: 'a -> 'a 20 | //│ = [Function: res] 21 | 22 | // forall 'a. 'a -> 'a <: 'a1 -> 0 -> 'b1 & 'a1 23 | // i.e. 24 | // forall 'a. 'a -> 'a <: 'a1 -> 0 -> 'b1 25 | // forall 'a. 'a -> 'a <: 'a1 26 | // i.e. 27 | // 'a2 -> 'a2 <: 'a1 -> 0 -> 'b1 28 | // 'a3 -> 'a3 <: 'a1 29 | 30 | 31 | def g x = x (fun x -> x) 32 | //│ g: ((forall 'a. 'a -> 'a) -> 'b) -> 'b 33 | //│ = [Function: g] 34 | 35 | 36 | def g x y = x (fun x -> y x) 37 | //│ g: (('a -> 'b) -> 'c) -> ('a -> 'b) -> 'c 38 | //│ = [Function: g1] 39 | 40 | 41 | self x = x x 42 | //│ self: ('a -> 'b & 'a) -> 'b 43 | //│ = [Function: self] 44 | 45 | :re 46 | self self! 47 | //│ res: nothing 48 | //│ Runtime error: 49 | //│ RangeError: Maximum call stack size exceeded 50 | 51 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Huawei2.mls: -------------------------------------------------------------------------------- 1 | 2 | class C[A]: { a: A -> A } 3 | //│ Defined class C[=A] 4 | 5 | class D: C[int] & { b: int } 6 | //│ Defined class D 7 | 8 | d = D{a = id; b = if true then 0 else 1} 9 | //│ d: D with {a: forall 'a. 'a -> 'a, b: 0 | 1} 10 | //│ = D { a: [Function: id], b: 0 } 11 | 12 | d.a true 13 | //│ res: true 14 | //│ = true 15 | 16 | d.a 0 17 | //│ res: 0 18 | //│ = 0 19 | 20 | d : #D 21 | //│ res: D 22 | //│ = D { a: [Function: id], b: 0 } 23 | 24 | def foo x = case x of D -> x.b, _ -> 0 25 | //│ foo: ((D\a with {b: 'b}) | ~D) -> (0 | 'b) 26 | //│ = [Function: foo] 27 | 28 | // Overloading through intersections: not supported 29 | // foo: ((D\a with {b: 'b}) -> 'b) & (~D -> 0) 30 | 31 | foo d 32 | //│ res: 0 | 1 33 | //│ = 0 34 | 35 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/InheritSimple.mls: -------------------------------------------------------------------------------- 1 | 2 | class Parent: {} 3 | //│ Defined class Parent 4 | 5 | class Child: Parent 6 | //│ Defined class Child 7 | 8 | p = Parent{} 9 | //│ p: Parent 10 | //│ = Parent {} 11 | 12 | c = Child(p) 13 | //│ c: Child 14 | //│ = Child {} 15 | 16 | :e 17 | c.name 18 | //│ ╔══[ERROR] Type mismatch in field selection: 19 | //│ ║ l.17: c.name 20 | //│ ║ ^^^^^^ 21 | //│ ╟── application of type `Child` does not have field 'name' 22 | //│ ║ l.12: c = Child(p) 23 | //│ ║ ^^^^^^^^ 24 | //│ ╟── but it flows into reference with expected type `{name: ?name}` 25 | //│ ║ l.17: c.name 26 | //│ ║ ^ 27 | //│ ╟── Note: class Child is defined at: 28 | //│ ║ l.5: class Child: Parent 29 | //│ ╙── ^^^^^ 30 | //│ res: error 31 | //│ = undefined 32 | 33 | c: Child 34 | //│ res: Child 35 | //│ = Child {} 36 | 37 | c: Parent 38 | //│ res: Parent 39 | //│ = Child {} 40 | 41 | c: Parent & Child 42 | //│ res: Child & Parent 43 | //│ = Child {} 44 | 45 | c: Parent & Child & {} 46 | //│ res: Child & Parent 47 | //│ = Child {} 48 | 49 | c: Parent & anything & Child & {} 50 | //│ res: Child & Parent 51 | //│ = Child {} 52 | 53 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/LineComments.mls: -------------------------------------------------------------------------------- 1 | 2 | 1 3 | 2 4 | //│ res: 1 5 | //│ = 1 6 | //│ res: 2 7 | //│ = 2 8 | 9 | 1 10 | // A 11 | 2 12 | //│ res: 1 13 | //│ = 1 14 | //│ res: 2 15 | //│ = 2 16 | 17 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/MatchBool.mls: -------------------------------------------------------------------------------- 1 | 2 | def absImpl lt x = 3 | case lt of 4 | { true -> x 5 | | false -> 0 - x } 6 | //│ absImpl: Bool -> int -> int 7 | //│ = [Function: absImpl] 8 | 9 | // * TODO support this 10 | :e 11 | def abs x = 12 | let r = x < 0 in absImpl r x 13 | //│ ╔══[ERROR] Type mismatch in application: 14 | //│ ║ l.12: let r = x < 0 in absImpl r x 15 | //│ ║ ^^^^^^^^^ 16 | //│ ╟── operator application of type `bool` does not match type `false & ?a | true & ?b` 17 | //│ ║ l.12: let r = x < 0 in absImpl r x 18 | //│ ║ ^^^^^ 19 | //│ ╟── but it flows into reference with expected type `false & ?a | true & ?b` 20 | //│ ║ l.12: let r = x < 0 in absImpl r x 21 | //│ ║ ^ 22 | //│ ╟── Note: constraint arises from reference: 23 | //│ ║ l.3: case lt of 24 | //│ ╙── ^^ 25 | //│ abs: int -> (error | int) 26 | //│ = [Function: abs] 27 | 28 | 29 | def neg b = case b of 30 | { true -> false 31 | | false -> true } 32 | //│ neg: Bool -> Bool 33 | //│ = [Function: neg] 34 | 35 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/NestedMatch.mls: -------------------------------------------------------------------------------- 1 | 2 | def f x = case x of { 3 | | 0 -> 0 4 | | _ -> case x of { 5 | | 1 -> 1 6 | | 2 -> 2 7 | } 8 | } 9 | //│ f: (0 | 1 | 2) -> (0 | 1 | 2) 10 | //│ = [Function: f] 11 | 12 | def f x = case x of { 13 | | 0 -> 0 14 | | _ -> case x of { 15 | | 1 -> 1 16 | | _ -> 2 17 | } 18 | } 19 | //│ f: anything -> (0 | 1 | 2) 20 | //│ = [Function: f1] 21 | 22 | def f x = case x of { 23 | | 0 -> 0 24 | | _ -> case x of { 25 | | 1 -> 1 26 | | _ -> x 27 | } 28 | } 29 | //│ f: (0 | 1 | 'a & ~0 & ~1) -> (0 | 1 | 'a) 30 | //│ = [Function: f2] 31 | 32 | def f x = case x of { 33 | | 0 -> x 34 | | _ -> case x of { 35 | | 1 -> 1 36 | | _ -> x 37 | } 38 | } 39 | //│ f: (1 | 'a & (0 | ~0 & ~1)) -> (1 | 'a) 40 | //│ = [Function: f3] 41 | 42 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Polym.mls: -------------------------------------------------------------------------------- 1 | 2 | def foo f = 3 | f (fun x -> x) 4 | //│ foo: ((forall 'a. 'a -> 'a) -> 'b) -> 'b 5 | //│ = [Function: foo] 6 | 7 | def bar h = 8 | (h 0, h true) 9 | //│ bar: (0 -> 'a & true -> 'b) -> ('a, 'b,) 10 | //│ = [Function: bar] 11 | 12 | bar id 13 | //│ res: (0, true,) 14 | //│ = [ 0, true ] 15 | 16 | foo bar 17 | //│ res: (0, true,) 18 | //│ = [ 0, true ] 19 | 20 | 21 | def foo2 f = 22 | f id 23 | //│ foo2: ((forall 'a. 'a -> 'a) -> 'b) -> 'b 24 | //│ = [Function: foo2] 25 | 26 | foo2 bar 27 | //│ res: (0, true,) 28 | //│ = [ 0, true ] 29 | 30 | 31 | 32 | def foo x f = f (fun a -> (x, a)) 33 | //│ foo: 'a -> ((forall 'b. 'b -> ('a, 'b,)) -> 'c) -> 'c 34 | //│ = [Function: foo1] 35 | 36 | // Swapping the parameters givesa an isomorphic type: 37 | 38 | def foo f x = f (fun a -> (x, a)) 39 | //│ foo: ((forall 'a. 'a -> ('b, 'a,)) -> 'c) -> 'b -> 'c 40 | //│ = [Function: foo3] 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/RecDefs.mls: -------------------------------------------------------------------------------- 1 | 2 | rec def f x = x 3 | //│ f: 'a -> 'a 4 | //│ = [Function: f] 5 | 6 | f 1 7 | //│ res: 1 8 | //│ = 1 9 | 10 | f 2 11 | //│ res: 2 12 | //│ = 2 13 | 14 | 15 | 16 | rec def f = if true then fun (x: 'a) -> 32 else let tmp = f f + 1 in error 17 | //│ f: anything -> 32 18 | //│ = [Function: f1] 19 | 20 | 21 | :e 22 | rec def f = forall 'a. (fun (x: 'a) -> 32) : 'a 23 | //│ ╔══[ERROR] Type mismatch in type ascription: 24 | //│ ║ l.22: rec def f = forall 'a. (fun (x: 'a) -> 32) : 'a 25 | //│ ║ ^^^^^^^^^^^^^^^^^^^ 26 | //│ ╟── function of type `'a -> 32` does not match type `'a` 27 | //│ ║ l.22: rec def f = forall 'a. (fun (x: 'a) -> 32) : 'a 28 | //│ ║ ^^^^^^^^^^^^^^^^^ 29 | //│ ╟── Note: constraint arises from rigid type variable: 30 | //│ ║ l.22: rec def f = forall 'a. (fun (x: 'a) -> 32) : 'a 31 | //│ ╙── ^^ 32 | //│ f: nothing 33 | //│ = [Function: f2] 34 | 35 | 36 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Repro.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Scratch.mls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hkust-taco/mlscript/a7504bb818f21a802f2fc8a338888b67a7c87da5/shared/src/test/diff/mlscript/Scratch.mls -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/SelfNegs.mls: -------------------------------------------------------------------------------- 1 | 2 | // * Here the two occurrences of `'a` in different types are separate: 3 | def foo(f: (~'a) -> 'a, a: 'a) = 4 | f a 5 | //│ foo: (~'a -> 'a, ~'a,) -> 'a 6 | //│ = [Function: foo] 7 | 8 | def foo(fa: ((~'a) -> 'a, 'a)) = 9 | fa.0 fa.1 10 | //│ foo: ((~'a -> 'a, 'a,),) -> 'a 11 | //│ = [Function: foo1] 12 | 13 | :ns 14 | foo 15 | //│ res: forall 'a 'b 'c. ((~'a -> 'a, 'a,),) -> 'c 16 | //│ where 17 | //│ 'a <: 'c & 'b 18 | //│ 'b <: ~'a 19 | //│ = [Function: foo1] 20 | 21 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Signatures.mls: -------------------------------------------------------------------------------- 1 | 2 | def foo: int -> (string -> anything) 3 | //│ foo: int -> string -> anything 4 | //│ = 5 | 6 | def foo: int -> string -> anything 7 | //│ foo: int -> string -> anything 8 | //│ = 9 | 10 | def foo: (int -> string) -> anything 11 | //│ foo: (int -> string) -> anything 12 | //│ = 13 | 14 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/TrickySimplif.mls: -------------------------------------------------------------------------------- 1 | :NoJS 2 | 3 | 4 | // * This is fine 5 | def f: 'a -> 'b -> ('a, 'b) 6 | //│ f: 'a -> 'b -> ('a, 'b,) 7 | 8 | // * This is fine 9 | def f: ('b -> 'a) -> 'b 10 | //│ f: (nothing -> anything) -> nothing 11 | 12 | // * This could be simplified to `anything -> nothing` 13 | def foo: ('a | 'b) -> ('a & 'b) 14 | //│ foo: ('a | 'b) -> ('a & 'b) 15 | 16 | // * Case in point 17 | (foo 1) : bool 18 | //│ res: bool 19 | 20 | rec def foo x = foo x 21 | //│ anything -> nothing 22 | //│ <: foo: 23 | //│ ('a | 'b) -> ('a & 'b) 24 | 25 | 26 | def f: MutArray['a & 'b] 27 | //│ f: MutArray['a] 28 | 29 | def f: MutArray[('a & 'b, 'a)] 30 | //│ f: MutArray[('a & 'b, 'a,)] 31 | 32 | def f: MutArray[('a & 'b, 'a | 'b)] 33 | //│ f: MutArray[('a, 'a,)] 34 | 35 | def f: MutArray[('a & 'b, ('a | 'b) -> int)] 36 | //│ f: MutArray[('b, 'b -> int,)] 37 | 38 | def f: MutArray[('a & 'b, ('a & 'b) -> int)] 39 | //│ f: MutArray[('a, 'a -> int,)] 40 | 41 | def f: MutArray[('a & 'b) -> ('a & 'b)] 42 | //│ f: MutArray['a -> 'a] 43 | 44 | def f: MutArray[('a & 'b) -> ('a | 'b)] 45 | //│ f: MutArray[('a & 'b) -> ('a | 'b)] 46 | 47 | def f: MutArray[('a | 'b) -> ('a | 'b)] 48 | //│ f: MutArray['a -> 'a] 49 | 50 | 51 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/TypeRefs.mls: -------------------------------------------------------------------------------- 1 | :NoJS 2 | 3 | class Foo[A] 4 | method Inv: A -> A 5 | //│ Defined class Foo[=A] 6 | //│ Declared Foo.Inv: Foo['A] -> 'A -> 'A 7 | 8 | trait Bar[A] 9 | method Inv: A -> A 10 | //│ Defined trait Bar[=A] 11 | //│ Declared Bar.Inv: Bar['A] -> 'A -> 'A 12 | 13 | type Baz[A] = Bar[A -> A] 14 | //│ Defined type alias Baz[=A] 15 | 16 | def foo: Foo[int] & Bar[int] & Baz[string] 17 | //│ foo: Foo[int] & Bar[int] & Baz[string] 18 | 19 | foo: Foo['res] 20 | //│ res: Foo[int] 21 | 22 | foo: Baz['res] 23 | //│ res: Baz[string] 24 | 25 | // * Note that we don't get a `'res :> string -> string & int` upper bound because it's simplified to bottom: 26 | foo: Bar['res] 27 | //│ res: Bar['res] 28 | //│ where 29 | //│ 'res <: int | string -> string 30 | 31 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Undef.mls: -------------------------------------------------------------------------------- 1 | 2 | class Undef 3 | //│ Defined class Undef 4 | 5 | undef = Undef{} 6 | //│ undef: Undef 7 | //│ = Undef {} 8 | 9 | 10 | def example: int | Undef 11 | //│ example: Undef | int 12 | //│ = 13 | 14 | example = if true then undef else 42 15 | //│ 42 | Undef 16 | //│ <: example: 17 | //│ Undef | int 18 | //│ = Undef {} 19 | 20 | def qmrk_qmrk lhs rhs = case lhs of { Undef -> rhs | _ -> lhs } 21 | //│ qmrk_qmrk: (Undef | 'a & ~#Undef) -> 'a -> 'a 22 | //│ = [Function: qmrk_qmrk] 23 | 24 | qmrk_qmrk example 0 25 | //│ res: int 26 | //│ = 0 27 | 28 | qmrk_qmrk example "123" 29 | //│ res: "123" | int 30 | //│ = '123' 31 | 32 | qmrk_qmrk undef "123" 33 | //│ res: "123" 34 | //│ = '123' 35 | 36 | qmrk_qmrk 42 "123" 37 | //│ res: "123" | 42 38 | //│ = 42 39 | 40 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/VarCycles.mls: -------------------------------------------------------------------------------- 1 | 2 | :RecursiveTypes 3 | 4 | 5 | def foo: ('a,) as 'a 6 | //│ foo: 'a 7 | //│ where 8 | //│ 'a :> ('a,) 9 | //│ = 10 | 11 | def bar: (('b,) as 'b) -> () 12 | //│ bar: 'b -> () 13 | //│ where 14 | //│ 'b <: ('b,) 15 | //│ = 16 | 17 | 18 | bar foo 19 | //│ res: () 20 | //│ = 21 | //│ bar is not implemented 22 | 23 | 24 | :ns 25 | id1 = id 26 | //│ id1: forall 'a. 'a -> 'a 27 | //│ = [Function: id] 28 | 29 | :ns 30 | // def f x = id x 31 | def f = id : 'c -> 'c 32 | //│ f: forall 'c 'a. 'c -> 'c 33 | //│ where 34 | //│ 'c <: 'a 35 | //│ 'a <: 'c 36 | //│ = [Function: f] 37 | 38 | f 1 + 2 39 | //│ res: int 40 | //│ = 3 41 | 42 | 43 | 44 | :NoRecursiveTypes 45 | 46 | 47 | :e 48 | bar foo 49 | //│ ╔══[ERROR] Inferred recursive type: 'b 50 | //│ where 51 | //│ 'b :> ('b,) 52 | //│ ║ l.11: def bar: (('b,) as 'b) -> () 53 | //│ ╙── ^^^^^^^^^^^^^ 54 | //│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required 55 | //│ ║ l.48: bar foo 56 | //│ ║ ^^^^^^^ 57 | //│ ╙── Note: use flag `:ex` to see internal error info. 58 | //│ res: error | () 59 | //│ = 60 | //│ bar is not implemented 61 | 62 | 63 | f 1 + 2 64 | //│ res: int 65 | //│ = 3 66 | 67 | 68 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Weird.mls: -------------------------------------------------------------------------------- 1 | // * Weird features to eventually remove 2 | 3 | :AllowRuntimeErrors 4 | 5 | 6 | :ge 7 | anything 8 | //│ res: anything 9 | //│ Code generation encountered an error: 10 | //│ type alias anything is not a valid expression 11 | 12 | :ge 13 | nothing 14 | //│ res: nothing 15 | //│ Code generation encountered an error: 16 | //│ type alias nothing is not a valid expression 17 | 18 | :ge 19 | Nothing 20 | //│ res: nothing 21 | //│ Code generation encountered an error: 22 | //│ unresolved symbol Nothing 23 | 24 | :ge 25 | int 26 | //│ res: int 27 | //│ Code generation encountered an error: 28 | //│ type alias int is not a valid expression 29 | 30 | :ge 31 | int + 1 32 | //│ res: int 33 | //│ Code generation encountered an error: 34 | //│ type alias int is not a valid expression 35 | 36 | 37 | class C 38 | //│ Defined class C 39 | 40 | :p 41 | def n: C{} 42 | //│ Parsed: rec def n: C; {}; 43 | //│ Desugared: rec def n: C 44 | //│ AST: Def(true,Var(n),Right(PolyType(List(),TypeName(C))),true) 45 | //│ Desugared: {} 46 | //│ AST: Rcd(List()) 47 | //│ n: C 48 | //│ = 49 | //│ res: anything 50 | //│ = {} 51 | 52 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/i26.mls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hkust-taco/mlscript/a7504bb818f21a802f2fc8a338888b67a7c87da5/shared/src/test/diff/mlscript/i26.mls -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/i65.mls: -------------------------------------------------------------------------------- 1 | :js 2 | 42 3 | //│ // Prelude 4 | //│ let res; 5 | //│ // Query 1 6 | //│ res = 42; 7 | //│ // End of generated code 8 | //│ res: 42 9 | //│ = 42 10 | 11 | :js 12 | foo = "oops" 13 | //│ // Query 1 14 | //│ globalThis.foo = "oops"; 15 | //│ // End of generated code 16 | //│ foo: "oops" 17 | //│ = 'oops' 18 | 19 | :js 20 | res 21 | //│ // Query 1 22 | //│ res = res; 23 | //│ // End of generated code 24 | //│ res: 42 25 | //│ = 42 26 | 27 | :js 28 | res = 5 29 | //│ // Query 1 30 | //│ globalThis.res1 = 5; 31 | //│ // End of generated code 32 | //│ res: 5 33 | //│ = 5 34 | 35 | res 36 | //│ res: 5 37 | //│ = 5 38 | 39 | :js 40 | foo 41 | //│ // Query 1 42 | //│ res = foo; 43 | //│ // End of generated code 44 | //│ res: "oops" 45 | //│ = 'oops' 46 | 47 | :js 48 | res 49 | //│ // Query 1 50 | //│ res = res; 51 | //│ // End of generated code 52 | //│ res: "oops" 53 | //│ = 'oops' 54 | 55 | def res: bool 56 | //│ res: bool 57 | //│ = 58 | 59 | 42 60 | //│ res: 42 61 | //│ = 42 62 | 63 | res 64 | //│ res: 42 65 | //│ = 42 66 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Andong.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Union(a: Region, b: Region) 5 | //│ class Union[Region](a: Region, b: Region) 6 | 7 | fun hmm(x) = 8 | if x is Union(x, y) then x 9 | //│ fun hmm: forall 'a. Union['a] -> 'a 10 | 11 | fun hmm(x) = 12 | if x is Union(z, y) then x 13 | //│ fun hmm: forall 'Region. Union['Region] -> Union['Region] 14 | 15 | 16 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Ascription.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 1: Int 4 | //│ Int 5 | //│ res 6 | //│ = 1 7 | 8 | 1 : Int 9 | //│ Int 10 | //│ res 11 | //│ = 1 12 | 13 | // TODO? 14 | :pe 15 | 1 : Int : Int 16 | //│ ╔══[PARSE ERROR] Not a recognized type 17 | //│ ║ l.15: 1 : Int : Int 18 | //│ ╙── ^^^ 19 | //│ anything 20 | //│ res 21 | //│ = 1 22 | 23 | fun foo(x: Int) = x + 1 24 | //│ fun foo: (x: Int) -> Int 25 | 26 | fun foo(x : Int) = x + 1 27 | //│ fun foo: Int -> Int 28 | 29 | foo(123 : Int) : Int 30 | //│ Int 31 | //│ res 32 | //│ = 124 33 | 34 | :e 35 | foo(123: Int): Int 36 | //│ ╔══[ERROR] Cannot use named arguments as the function type has untyped arguments 37 | //│ ║ l.35: foo(123: Int): Int 38 | //│ ╙── ^^^^^^^^^^ 39 | //│ Int 40 | //│ Code generation encountered an error: 41 | //│ unresolved symbol Int 42 | 43 | :e 44 | foo(123:Int):Int 45 | //│ ╔══[ERROR] Cannot use named arguments as the function type has untyped arguments 46 | //│ ║ l.44: foo(123:Int):Int 47 | //│ ╙── ^^^^^^^^^ 48 | //│ Int 49 | //│ Code generation encountered an error: 50 | //│ unresolved symbol Int 51 | 52 | fun foo(f) = 53 | let g = (x => f(x)): forall 'a : 'a -> 'a in g(123) 54 | //│ fun foo: (??a -> ??a0) -> 123 55 | 56 | fun foo(f) = 57 | let g: forall 'a : 'a -> 'a = x => f(x) in g(123) 58 | //│ fun foo: (??a -> ??a0) -> 123 59 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/BadMixins.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | :e 5 | mixin M0 6 | M0 7 | //│ ╔══[ERROR] mixin M0 cannot be used in term position 8 | //│ ║ l.6: M0 9 | //│ ╙── ^^ 10 | //│ mixin M0() 11 | //│ error 12 | //│ res 13 | //│ = [Function (anonymous)] 14 | 15 | :e 16 | M0 17 | //│ ╔══[ERROR] mixin M0 cannot be used in term position 18 | //│ ║ l.16: M0 19 | //│ ╙── ^^ 20 | //│ error 21 | //│ res 22 | //│ = [Function (anonymous)] 23 | 24 | 25 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/BadScopes.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | :e 5 | mixin Foo(x: Int) 6 | x 7 | //│ ╔══[ERROR] identifier not found: x 8 | //│ ║ l.6: x 9 | //│ ╙── ^ 10 | //│ mixin Foo(x: Int) 11 | //│ error 12 | //│ Code generation encountered an error: 13 | //│ unresolved symbol x 14 | 15 | 16 | :e 17 | class Foo(x: Int) 18 | x 19 | //│ ╔══[ERROR] identifier not found: x 20 | //│ ║ l.18: x 21 | //│ ╙── ^ 22 | //│ class Foo(x: Int) 23 | //│ error 24 | //│ Code generation encountered an error: 25 | //│ unresolved symbol x 26 | 27 | 28 | :e 29 | class Bar { x } 30 | //│ ╔══[ERROR] identifier not found: x 31 | //│ ║ l.29: class Bar { x } 32 | //│ ╙── ^ 33 | //│ class Bar { 34 | //│ constructor() 35 | //│ } 36 | //│ Code generation encountered an error: 37 | //│ unresolved symbol x 38 | 39 | 40 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/BadSuper.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | mixin M0 { 5 | fun f = 42 6 | } 7 | //│ mixin M0() { 8 | //│ fun f: 42 9 | //│ } 10 | 11 | :e 12 | mixin M1 { 13 | fun g = super 14 | } 15 | //│ ╔══[ERROR] Illegal use of `super` 16 | //│ ║ l.13: fun g = super 17 | //│ ╙── ^^^^^ 18 | //│ mixin M1() { 19 | //│ super: 'super 20 | //│ fun g: 'super 21 | //│ } 22 | //│ Syntax error: 23 | //│ 'super' keyword unexpected here 24 | 25 | :re 26 | module C0 extends M0, M1 27 | C0.g 28 | //│ module C0 { 29 | //│ fun f: 42 30 | //│ fun g: {f: 42} 31 | //│ } 32 | //│ {f: 42} 33 | //│ res 34 | //│ Runtime error: 35 | //│ ReferenceError: M1 is not defined 36 | 37 | 38 | :e 39 | class Foo { 40 | fun f = super 41 | } 42 | //│ ╔══[ERROR] Illegal use of `super` 43 | //│ ║ l.40: fun f = super 44 | //│ ╙── ^^^^^ 45 | //│ class Foo { 46 | //│ constructor() 47 | //│ fun f: Foo 48 | //│ } 49 | //│ Syntax error: 50 | //│ 'super' keyword unexpected here 51 | 52 | 53 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/BadTraits.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | trait Foo 5 | //│ trait Foo 6 | 7 | :e 8 | Foo 9 | //│ ╔══[ERROR] trait Foo cannot be used in term position 10 | //│ ║ l.8: Foo 11 | //│ ╙── ^^^ 12 | //│ error 13 | //│ Code generation encountered an error: 14 | //│ trait used in term position 15 | 16 | 17 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/CallByName.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | let x = log("ok") 5 | //│ let x: () 6 | //│ x 7 | //│ = undefined 8 | //│ // Output 9 | //│ ok 10 | 11 | x 12 | //│ () 13 | //│ res 14 | //│ = undefined 15 | 16 | x 17 | //│ () 18 | //│ res 19 | //│ = undefined 20 | 21 | 22 | fun x = log("ok") 23 | //│ fun x: () 24 | 25 | x 26 | //│ () 27 | //│ res 28 | //│ = undefined 29 | //│ // Output 30 | //│ ok 31 | 32 | x 33 | //│ () 34 | //│ res 35 | //│ = undefined 36 | //│ // Output 37 | //│ ok 38 | 39 | 40 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/ClassInstantiation.mls: -------------------------------------------------------------------------------- 1 | // *** Class instantiation tests *** // 2 | 3 | :NewDefs 4 | 5 | 6 | class C 7 | //│ class C { 8 | //│ constructor() 9 | //│ } 10 | 11 | new C 12 | //│ C 13 | //│ res 14 | //│ = C {} 15 | 16 | // * TODO decide: forbid? 17 | new C() 18 | //│ C 19 | //│ res 20 | //│ = C {} 21 | 22 | :e 23 | C() 24 | //│ ╔══[ERROR] Construction of unparameterized class C should use the `new` keyword 25 | //│ ║ l.23: C() 26 | //│ ╙── ^ 27 | //│ C 28 | //│ res 29 | //│ Runtime error: 30 | //│ TypeError: Class constructor C cannot be invoked without 'new' 31 | 32 | 33 | class D(x: Int) 34 | //│ class D(x: Int) 35 | 36 | :js 37 | D(0) 38 | //│ D 39 | //│ // Prelude 40 | //│ class TypingUnit5 {} 41 | //│ const typing_unit5 = new TypingUnit5; 42 | //│ // Query 1 43 | //│ res = D(0); 44 | //│ // End of generated code 45 | //│ res 46 | //│ = D {} 47 | 48 | // * TODO decide: reject or accept? 49 | :js 50 | new D(0) 51 | //│ D 52 | //│ // Prelude 53 | //│ class TypingUnit6 {} 54 | //│ const typing_unit6 = new TypingUnit6; 55 | //│ // Query 1 56 | //│ res = new D.class(0); 57 | //│ // End of generated code 58 | //│ res 59 | //│ = D {} 60 | 61 | 62 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/CtorSubtraction.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Cls 5 | //│ class Cls { 6 | //│ constructor() 7 | //│ } 8 | 9 | fun x: ('a & Object) -> ('a \ Cls) 10 | fun x = case 11 | Cls then error 12 | y then y 13 | //│ fun x: forall 'b. (Cls | Object & 'b & ~#Cls) -> 'b 14 | //│ fun x: forall 'a. (Object & 'a) -> ('a & ~Cls) 15 | 16 | x : Int -> Int 17 | //│ Int -> Int 18 | //│ res 19 | //│ = [Function: x] 20 | 21 | x : Cls -> nothing 22 | //│ Cls -> nothing 23 | //│ res 24 | //│ = [Function: x] 25 | 26 | 27 | fun x: (Int | Str | Cls) \ Cls 28 | fun x = 42 29 | //│ fun x: 42 30 | //│ fun x: Int & ~Cls | Str & ~Cls 31 | 32 | x : Int | Str 33 | //│ Int | Str 34 | //│ res 35 | //│ = 42 36 | 37 | 38 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/CycleTypeDefErrors.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | // * These type definitions should be checked for cyclicity, like we did in the old frontend, 4 | // * but this is currently not implemented. 5 | 6 | 7 | type Foo = Foo 8 | //│ type Foo = Foo 9 | 10 | (f: Foo) => f : Str 11 | //│ (f: Foo) -> Str 12 | //│ res 13 | //│ = [Function: res] 14 | 15 | 16 | type Foo = Foo & Int 17 | //│ type Foo = Foo & Int 18 | 19 | // FIXME 20 | (f: Foo) => f : Str 21 | //│ /!!!\ Uncaught error: java.lang.StackOverflowError 22 | 23 | 24 | abstract class Foo: Foo 25 | //│ abstract class Foo: Foo 26 | 27 | // FIXME 28 | (f: Foo) => f : Str 29 | //│ /!!!\ Uncaught error: java.lang.StackOverflowError 30 | 31 | 32 | abstract class Foo[T]: Foo[Int] 33 | //│ abstract class Foo[T]: Foo[Int] 34 | 35 | // FIXME 36 | fun test(f: Foo['a]) = f : Str 37 | //│ /!!!\ Uncaught error: java.lang.StackOverflowError 38 | 39 | 40 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Dates.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | declare class Date { 5 | constructor(date: Num) 6 | fun toString(): Str 7 | fun toLocaleString(locales: Str | Array[Str], options: anything): Str 8 | } 9 | //│ declare class Date { 10 | //│ constructor(date: Num) 11 | //│ fun toLocaleString: (locales: Str | Array[Str], options: anything) -> Str 12 | //│ fun toString: () -> Str 13 | //│ } 14 | 15 | let date1 = new Date(12345678) 16 | //│ let date1: Date 17 | //│ date1 18 | //│ = 1970-01-01T03:25:45.678Z 19 | 20 | date1.toLocaleString("en-US", { timeZone: "America/New_York" }) 21 | //│ Str 22 | //│ res 23 | //│ = '12/31/1969, 10:25:45 PM' 24 | 25 | 26 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/DidierNu.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | // val k x y = y 5 | // val unify : A. B. A -> A -> B -> B 6 | // = fun x y z -> k (fun z -> k (z x) (k (z y))) z 7 | // val a0 = (fun z -> z) (id : A. A -> A) 1 8 | // val a1 x = (fun z -> unify x (fst z) (snd z)) (id, (id : A. A -> A)) 1 9 | 10 | 11 | fun k(x, y) = y 12 | //│ fun k: forall 'a. (anything, 'a) -> 'a 13 | 14 | fun unify : 'A -> 'A -> 'B -> 'B 15 | //│ fun unify: forall 'B. anything -> anything -> 'B -> 'B 16 | 17 | fun unify = x => y => z => k(z => k(z(x), y => k(z(y), y)), z) 18 | //│ fun unify: forall 'a. anything -> anything -> 'a -> 'a 19 | 20 | fun unify = x => y => z => k of z => k(z(x), y => k of z(y), y), z 21 | //│ fun unify: forall 'a. anything -> anything -> 'a -> 'a 22 | 23 | 24 | fun a0 = (z => z) (id : forall 'A: 'A -> 'A) of 1 25 | //│ fun a0: 1 26 | 27 | fun fst([a, _]) = a 28 | fun snd([_, b]) = b 29 | //│ fun fst: forall 'a. (['a, anything]) -> 'a 30 | //│ fun snd: forall 'b. ([anything, 'b]) -> 'b 31 | 32 | fun a1(x) = (z => unify(x)(fst of z)(snd of z))([id, (id : forall 'A: 'A -> 'A)]) of 1 33 | //│ fun a1: anything -> 1 34 | 35 | 36 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Eduardo.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | // https://twitter.com/LParreaux/status/1762843603804770408 4 | 5 | 6 | type f = forall 'a: ('a ) -> 'a where 'a : Int 7 | //│ type f = forall 'a. (Int & 'a) -> 'a 8 | 9 | type f = (forall 'a: ('a ) -> 'a where 'a : Int) 10 | //│ type f = forall 'a. (Int & 'a) -> 'a 11 | 12 | type g = forall 'a: ('a & Int) -> 'a 13 | //│ type g = forall 'a. (Int & 'a) -> 'a 14 | 15 | (id : f) : g 16 | //│ g 17 | //│ res 18 | //│ = [Function: id] 19 | 20 | 21 | type f = (forall 'a: ('a ) -> 'a where 'a : Int) 22 | type g = forall 'a: ('a & Int) -> 'a 23 | //│ type f = forall 'a. (Int & 'a) -> 'a 24 | //│ type g = forall 'a0. (Int & 'a0) -> 'a0 25 | 26 | (id : f) : g 27 | (id : g) : f 28 | //│ f 29 | //│ res 30 | //│ = [Function: id] 31 | //│ res 32 | //│ = [Function: id] 33 | 34 | x => (id : f)(x) : Int 35 | //│ Int -> Int 36 | //│ res 37 | //│ = [Function: res] 38 | 39 | 40 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/EncodedLists.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | 5 | class List { 6 | fun match: forall 'res: (ifNil: () => 'res, ifCons: ('res, List[A]) => 'res) => 'res 7 | fun match = error // TODO use self-type... 8 | } 9 | val Nil: List 10 | val Cons: (head: 'a, tail: List<'a>) => List<'a> 11 | //│ class List[A] { 12 | //│ constructor() 13 | //│ fun match: forall 'res. (ifNil: () -> 'res, ifCons: ('res, List[A]) -> 'res) -> 'res 14 | //│ } 15 | //│ val Nil: List[nothing] 16 | //│ val Cons: forall 'a. (head: 'a, tail: List['a]) -> List['a] 17 | 18 | val x: List 19 | //│ val x: List[Int] 20 | 21 | // FIXME 22 | x: List 23 | //│ ╔══[ERROR] Type mismatch in type ascription: 24 | //│ ║ l.22: x: List 25 | //│ ║ ^ 26 | //│ ╙── expression of type `anything` is not an instance of type `Int` 27 | //│ List[anything] 28 | 29 | 30 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Extrusion.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | fun f(y) = 5 | let local = forall 'A: (x: 'A) => 6 | discard of y(x) + 1 7 | x 8 | y 9 | //│ fun f: forall 'a. (??A -> Int & 'a) -> 'a 10 | 11 | :e 12 | f(id) 13 | //│ ╔══[ERROR] Type error in application 14 | //│ ║ l.12: f(id) 15 | //│ ║ ^^^^^ 16 | //│ ╟── type variable `'A` leaks out of its scope 17 | //│ ║ l.5: let local = forall 'A: (x: 'A) => 18 | //│ ║ ^^ 19 | //│ ╟── into application of type `Int` 20 | //│ ║ l.6: discard of y(x) + 1 21 | //│ ║ ^^^^ 22 | //│ ╟── adding a type annotation to any of the following terms may help resolve the problem 23 | //│ ╟── • this reference: 24 | //│ ║ l.6: discard of y(x) + 1 25 | //│ ╙── ^ 26 | //│ forall 'a. error | 'a -> 'a 27 | //│ res 28 | //│ = [Function: id] 29 | 30 | 31 | fun f(y) = 32 | let local = forall 'A: (x: 'A) => 33 | discard of (y : forall 'a: 'a -> 'a)(x) 34 | x 35 | y 36 | //│ fun f: forall 'b. (forall 'a. 'a -> 'a & 'b) -> 'b 37 | 38 | f(id) 39 | //│ forall 'a. 'a -> 'a 40 | //│ res 41 | //│ = [Function: id] 42 | 43 | 44 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/FieldRefinement.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | 5 | class Foo(val x: Int) { 6 | fun bar = x 7 | fun baz: 1 | 2 = 1 8 | } 9 | //│ class Foo(x: Int) { 10 | //│ fun bar: Int 11 | //│ fun baz: 1 | 2 12 | //│ } 13 | 14 | val foo: Foo & { x: 0 | 1, bar: 0 | 1, baz: 0 | 1, y: Bool } 15 | //│ val foo: Foo & {y: Bool, bar: 0 | 1, baz: 0 | 1, x: 0 | 1} 16 | 17 | foo.x 18 | //│ 0 | 1 19 | 20 | foo.bar 21 | //│ 0 | 1 22 | 23 | foo.baz 24 | //│ 1 25 | 26 | foo.y 27 | //│ Bool 28 | 29 | :e 30 | foo.z 31 | //│ ╔══[ERROR] Type `Foo & {y: Bool, bar: 0 | 1, baz: 0 | 1, x: 0 | 1}` does not contain member `z` 32 | //│ ║ l.30: foo.z 33 | //│ ╙── ^^ 34 | //│ error 35 | 36 | 37 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/FlatIndentFuns.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | x => 5 | y => 6 | x + y 7 | //│ Int -> Int -> Int 8 | //│ res 9 | //│ = [Function: res] 10 | 11 | id of x => 12 | y => 13 | x + y 14 | //│ Int -> Int -> Int 15 | //│ res 16 | //│ = [Function (anonymous)] 17 | 18 | let r = x => 19 | y => 20 | x + y 21 | //│ let r: Int -> Int -> Int 22 | //│ r 23 | //│ = [Function: r] 24 | 25 | r(1)(2) 26 | //│ Int 27 | //│ res 28 | //│ = 3 29 | 30 | (r of 1) of 2 31 | //│ Int 32 | //│ res 33 | //│ = 3 34 | 35 | :e 36 | r of 1 of 2 37 | //│ ╔══[ERROR] Type mismatch in application: 38 | //│ ║ l.36: r of 1 of 2 39 | //│ ║ ^^^^^^ 40 | //│ ╟── integer literal of type `1` is not a function 41 | //│ ║ l.36: r of 1 of 2 42 | //│ ╙── ^ 43 | //│ Int -> Int 44 | //│ res 45 | //│ Runtime error: 46 | //│ TypeError: 1 is not a function 47 | 48 | 49 | // * Could support this too... 50 | :pe 51 | let r = 52 | x => 53 | y => 54 | x + y 55 | //│ ╔══[PARSE ERROR] Unexpected newline in expression position 56 | //│ ║ l.51: let r = 57 | //│ ║ ^ 58 | //│ ║ l.52: x => 59 | //│ ╙── 60 | //│ let r: Int -> Int -> Int 61 | //│ r 62 | //│ = [Function: r1] 63 | 64 | 65 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/FunPatterns.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | 5 | fun f(x, y) = x + y 6 | //│ fun f: (Int, Int) -> Int 7 | 8 | // FIXME array pattern...?! 9 | fun f1([x, y]) = x + y 10 | fun f2([x, y],) = x + y 11 | fun f3([[x, y,],],) = x + y 12 | //│ fun f1: ([Int, Int]) -> Int 13 | //│ fun f2: ([Int, Int]) -> Int 14 | //│ fun f3: ([[Int, Int]]) -> Int 15 | 16 | :e 17 | fun f3([(x, y,),],) = x + y 18 | //│ ╔══[ERROR] Unsupported pattern shape: 19 | //│ ║ l.17: fun f3([(x, y,),],) = x + y 20 | //│ ╙── ^^^^^^^ 21 | //│ ╔══[ERROR] identifier not found: x 22 | //│ ║ l.17: fun f3([(x, y,),],) = x + y 23 | //│ ╙── ^ 24 | //│ ╔══[ERROR] identifier not found: y 25 | //│ ║ l.17: fun f3([(x, y,),],) = x + y 26 | //│ ╙── ^ 27 | //│ fun f3: ([error]) -> Int 28 | 29 | 30 | class Pair(lhs: Int, rhs: Int) 31 | //│ class Pair(lhs: Int, rhs: Int) 32 | 33 | :e // * TODO 34 | fun f(Pair(x, y)) = x + y 35 | //│ ╔══[ERROR] Unsupported pattern shape: 36 | //│ ║ l.34: fun f(Pair(x, y)) = x + y 37 | //│ ╙── ^^^^^^^^^^ 38 | //│ ╔══[ERROR] identifier not found: x 39 | //│ ║ l.34: fun f(Pair(x, y)) = x + y 40 | //│ ╙── ^ 41 | //│ ╔══[ERROR] identifier not found: y 42 | //│ ║ l.34: fun f(Pair(x, y)) = x + y 43 | //│ ╙── ^ 44 | //│ fun f: error -> Int 45 | 46 | 47 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/FunnyIndet.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | 2 + 5 | 2 * 6 | 3 7 | //│ Int 8 | //│ res 9 | //│ = 8 10 | 11 | 2 - 12 | 3 - 13 | 4 14 | //│ Int 15 | //│ res 16 | //│ = 3 17 | 18 | 2 + 19 | 2 20 | //│ Int 21 | //│ res 22 | //│ = 4 23 | 24 | 2 + 25 | 2 26 | //│ Int 27 | //│ res 28 | //│ = 4 29 | 30 | 31 | 2 is 32 | 2 33 | //│ Bool 34 | //│ res 35 | //│ = true 36 | 37 | if 2 is 2 then true 38 | //│ true 39 | //│ res 40 | //│ = true 41 | 42 | 2 is 43 | 2 44 | //│ Bool 45 | //│ res 46 | //│ = true 47 | 48 | 49 | if 2 is 50 | 2 then true 51 | //│ true 52 | //│ res 53 | //│ = true 54 | 55 | :pe // TODO support 56 | if 2 is 57 | 2 then true 58 | 1 then false 59 | //│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause 60 | //│ ║ l.58: 1 then false 61 | //│ ╙── ^^^^^^^^^^^^ 62 | //│ () 63 | //│ res 64 | //│ = true 65 | //│ res 66 | //│ = undefined 67 | 68 | 69 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Huawei1.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class C[out A](x: A) { 5 | fun foo = x 6 | } 7 | //│ class C[A](x: A) { 8 | //│ fun foo: A 9 | //│ } 10 | 11 | let c = C(123) 12 | //│ let c: C[123] 13 | //│ c 14 | //│ = C {} 15 | 16 | class B 17 | //│ class B { 18 | //│ constructor() 19 | //│ } 20 | 21 | fun bar(c) = if c is 22 | C(y) then y 23 | B then 0 24 | //│ fun bar: forall 'a. (B | C['a]) -> (0 | 'a) 25 | 26 | bar(c) 27 | //│ 0 | 123 28 | //│ res 29 | //│ = 123 30 | 31 | fun bar(c) = if c is 32 | C(y) then y + 1 33 | B then 0 34 | else 1 35 | //│ fun bar: (C[Int] | Object & ~#C) -> Int 36 | 37 | bar(c) 38 | //│ Int 39 | //│ res 40 | //│ = 124 41 | 42 | :e 43 | bar(C(true)) 44 | //│ ╔══[ERROR] Type mismatch in application: 45 | //│ ║ l.43: bar(C(true)) 46 | //│ ║ ^^^^^^^^^^^^ 47 | //│ ╟── reference of type `true` is not an instance of `Int` 48 | //│ ║ l.43: bar(C(true)) 49 | //│ ║ ^^^^ 50 | //│ ╟── Note: constraint arises from reference: 51 | //│ ║ l.32: C(y) then y + 1 52 | //│ ║ ^ 53 | //│ ╟── from field selection: 54 | //│ ║ l.4: class C[out A](x: A) { 55 | //│ ║ ^ 56 | //│ ╟── Note: type parameter A is defined at: 57 | //│ ║ l.4: class C[out A](x: A) { 58 | //│ ╙── ^ 59 | //│ Int | error 60 | //│ res 61 | //│ = 2 62 | 63 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/InheritanceLevelMismatches.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | :NoJS // TODO 4 | 5 | 6 | trait T1 { fun x: 0 | 1 } 7 | //│ trait T1 { 8 | //│ fun x: 0 | 1 9 | //│ } 10 | 11 | module Foo { 12 | trait T2 { fun x: 1 | 2 } 13 | class C extends T1, T2 { fun x = 1 } 14 | } 15 | //│ module Foo { 16 | //│ class C extends T1, T2 { 17 | //│ constructor() 18 | //│ fun x: 1 19 | //│ } 20 | //│ trait T2 { 21 | //│ fun x: 1 | 2 22 | //│ } 23 | //│ } 24 | 25 | 26 | mixin Foo { fun f = this.x } 27 | //│ mixin Foo() { 28 | //│ this: {x: 'x} 29 | //│ fun f: 'x 30 | //│ } 31 | 32 | module Bar { 33 | class C(val x: Int) extends Foo 34 | } 35 | //│ module Bar { 36 | //│ class C(x: Int) { 37 | //│ fun f: Int 38 | //│ } 39 | //│ } 40 | 41 | 42 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/IntraBlockPolymorphism.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | // * Note: eventually we should progressively type check every mutually-recursive group 5 | // * in topological order, to maximize polymorphism. 6 | // * But currently we just type check them in srouce code order. 7 | // * So the following inferred types differ: 8 | 9 | fun i(x) = x 10 | let a = i(0) 11 | let b = i(true) 12 | //│ fun i: forall 'a. 'a -> 'a 13 | //│ let a: 0 14 | //│ let b: true 15 | //│ a 16 | //│ = 0 17 | //│ b 18 | //│ = true 19 | 20 | :re // FIXME shouldn't be a reference error 21 | let a = i(0) 22 | fun i(x) = x 23 | let b = i(true) 24 | //│ let a: 0 | true | 'a 25 | //│ fun i: forall 'b. ('a & 'b) -> (0 | 'b) 26 | //│ let b: 0 | true 27 | //│ a 28 | //│ Runtime error: 29 | //│ ReferenceError: i1 is not defined 30 | //│ b 31 | //│ = true 32 | 33 | :re // FIXME shouldn't be a reference error 34 | let a = i(0) 35 | let b = i(true) 36 | fun i(x) = x 37 | //│ let a: 0 | true | 'a 38 | //│ let b: 0 | true | 'a 39 | //│ fun i: forall 'b. ('a & 'b) -> (0 | true | 'b) 40 | //│ a 41 | //│ Runtime error: 42 | //│ ReferenceError: i2 is not defined 43 | //│ b 44 | //│ Runtime error: 45 | //│ ReferenceError: i2 is not defined 46 | 47 | 48 | module Test { 49 | fun i(x) = x 50 | let a = i(0) 51 | let b = i(true) 52 | } 53 | //│ module Test { 54 | //│ let a: 0 55 | //│ let b: true 56 | //│ fun i: forall 'a. 'a -> 'a 57 | //│ } 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/LamPatterns.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Some(value: Int) 5 | //│ class Some(value: Int) 6 | 7 | :e // TODO 8 | Some(x) => x 9 | //│ ╔══[ERROR] Unsupported pattern shape: 10 | //│ ║ l.8: Some(x) => x 11 | //│ ╙── ^^^^^^^ 12 | //│ ╔══[ERROR] identifier not found: x 13 | //│ ║ l.8: Some(x) => x 14 | //│ ╙── ^ 15 | //│ error -> error 16 | //│ Code generation encountered an error: 17 | //│ term App(Var(Some),Tup(List((None,Fld(_,Var(x)))))) is not a valid pattern 18 | 19 | :js 20 | // FIXME type 21 | let f = Some => 0 22 | //│ let f: ((value: Int) -> Some) -> 0 23 | //│ // Prelude 24 | //│ class TypingUnit2 {} 25 | //│ const typing_unit2 = new TypingUnit2; 26 | //│ // Query 1 27 | //│ globalThis.f = function f(Some) { 28 | //│ return 0; 29 | //│ }; 30 | //│ // End of generated code 31 | //│ f 32 | //│ = [Function: f] 33 | 34 | // :e // TODO 35 | f(Some) 36 | //│ 0 37 | //│ res 38 | //│ = 0 39 | 40 | // :e // TODO 41 | f(_ => error) 42 | //│ 0 43 | //│ res 44 | //│ = 0 45 | 46 | :e // TODO 47 | f(Some(0)) 48 | //│ ╔══[ERROR] Type mismatch in application: 49 | //│ ║ l.47: f(Some(0)) 50 | //│ ║ ^^^^^^^^^^ 51 | //│ ╟── application of type `Some` is not a function 52 | //│ ║ l.47: f(Some(0)) 53 | //│ ║ ^^^^^^^ 54 | //│ ╟── Note: constraint arises from reference: 55 | //│ ║ l.21: let f = Some => 0 56 | //│ ╙── ^^^^ 57 | //│ 0 | error 58 | //│ res 59 | //│ = 0 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/LitMatch.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | let r = false : Bool 5 | //│ let r: Bool 6 | //│ r 7 | //│ = false 8 | 9 | let b = (if r then true else false) : Bool 10 | //│ let b: Bool 11 | //│ b 12 | //│ = false 13 | 14 | let b = false : Bool 15 | //│ let b: Bool 16 | //│ b 17 | //│ = false 18 | 19 | b : true | false 20 | //│ Bool 21 | //│ res 22 | //│ = false 23 | 24 | if false is false then 0 25 | //│ 0 26 | //│ res 27 | //│ = 0 28 | 29 | fun foo(x) = if x is 30 | false then 0 31 | //│ fun foo: false -> 0 32 | 33 | fun foo(x) = if x is 34 | false then 0 35 | true then 1 36 | //│ fun foo: Bool -> (0 | 1) 37 | 38 | fun foo(x) = if x is 39 | 0 then "zero" 40 | true then "true" 41 | //│ fun foo: (0 | true) -> ("true" | "zero") 42 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/LocalLets.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | let f = 5 | let tmp = "ok" 6 | 123 7 | //│ let f: 123 8 | //│ f 9 | //│ = 123 10 | 11 | 12 | :e 13 | let x : Int | string 14 | let x = 1 15 | //│ ╔══[ERROR] `let` bindings must have a right-hand side 16 | //│ ║ l.13: let x : Int | string 17 | //│ ╙── ^^^^^^^^^^^^^^^^^^^^ 18 | //│ let x: 1 19 | //│ let x: Int | string 20 | //│ x 21 | //│ = 22 | //│ x 23 | //│ = 1 24 | 25 | val x : Int | string 26 | val x = 1 27 | //│ val x: 1 28 | //│ val x: Int | string 29 | //│ x 30 | //│ = 31 | //│ x 32 | //│ = 1 33 | 34 | 35 | class E(x: Int) 36 | //│ class E(x: Int) 37 | 38 | :e // TODO support (currently parsed as a function definition named E) 39 | let E(x) = new E(1) 40 | //│ ╔══[ERROR] value E cannot be used as a type 41 | //│ ║ l.39: let E(x) = new E(1) 42 | //│ ╙── ^ 43 | //│ ╔══[ERROR] type identifier not found: E 44 | //│ ║ l.39: let E(x) = new E(1) 45 | //│ ╙── ^ 46 | //│ let E: anything -> error 47 | //│ E 48 | //│ = [Function: E1] 49 | 50 | 51 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/MissingImplBug.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | declare fun String: nothing 5 | //│ fun String: nothing 6 | 7 | let makeString: anything => { length: Int, charCodeAt: Int => Int } = String 8 | let StringInstance: { fromCharCode: Int => Str } = String 9 | //│ let makeString: anything -> {charCodeAt: Int -> Int, length: Int} 10 | //│ let StringInstance: {fromCharCode: Int -> Str} 11 | //│ makeString 12 | //│ = [Function: String] 13 | //│ StringInstance 14 | //│ = [Function: String] 15 | 16 | // * Why do we get below and not above?? 17 | 18 | declare fun String: nothing 19 | let makeString: anything => { length: Int, charCodeAt: Int => Int } = String 20 | let StringInstance: { fromCharCode: Int => Str } = String 21 | //│ let makeString: anything -> {charCodeAt: Int -> Int, length: Int} 22 | //│ let StringInstance: {fromCharCode: Int -> Str} 23 | //│ fun String: nothing 24 | //│ makeString 25 | //│ = [Function: String] 26 | //│ StringInstance 27 | //│ = [Function: String] 28 | 29 | 30 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/MixinParameters.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | mixin BaseTest(x: Int) { 5 | fun test = x 6 | } 7 | //│ mixin BaseTest(x: Int) { 8 | //│ fun test: Int 9 | //│ } 10 | 11 | module Test extends BaseTest(42) 12 | //│ module Test { 13 | //│ fun test: Int 14 | //│ } 15 | 16 | Test.test 17 | //│ Int 18 | //│ res 19 | //│ = 42 20 | 21 | :e 22 | Test.x 23 | //│ ╔══[ERROR] Type `Test` does not contain member `x` 24 | //│ ║ l.22: Test.x 25 | //│ ╙── ^^ 26 | //│ error 27 | //│ res 28 | //│ = undefined 29 | 30 | 31 | mixin BaseTest(val x: Int -> Int) 32 | //│ mixin BaseTest(x: Int -> Int) 33 | 34 | module Test extends BaseTest(id) 35 | //│ module Test 36 | 37 | Test.x(1) 38 | //│ 1 39 | //│ res 40 | //│ = 1 41 | 42 | 43 | :e // TODO support 44 | mixin BaseTest(x) { 45 | fun test = x 46 | } 47 | //│ ╔══[ERROR] Mixin parameters currently need type annotations 48 | //│ ║ l.44: mixin BaseTest(x) { 49 | //│ ╙── ^ 50 | //│ mixin BaseTest(x: error) { 51 | //│ fun test: error 52 | //│ } 53 | 54 | 55 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/NestedClasses.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class C0() { 5 | class NC0() 6 | } 7 | //│ class C0() { 8 | //│ class NC0() 9 | //│ } 10 | 11 | let c = C0() 12 | //│ let c: C0 13 | //│ c 14 | //│ = C0 {} 15 | 16 | :e 17 | c.NC0 18 | //│ ╔══[ERROR] Access to class member not yet supported 19 | //│ ║ l.17: c.NC0 20 | //│ ╙── ^^^^ 21 | //│ error 22 | //│ res 23 | //│ = [Function (anonymous)] { 24 | //│ class: [class NC0], 25 | //│ unapply: [Function: unapply] 26 | //│ } 27 | 28 | 29 | module M0 { 30 | class NC0 31 | } 32 | //│ module M0 { 33 | //│ class NC0 { 34 | //│ constructor() 35 | //│ } 36 | //│ } 37 | 38 | :e 39 | M0.NC0 40 | //│ ╔══[ERROR] Access to class member not yet supported 41 | //│ ║ l.39: M0.NC0 42 | //│ ╙── ^^^^ 43 | //│ error 44 | //│ res 45 | //│ = [class NC0] 46 | 47 | 48 | module M1 { 49 | module NM1 50 | } 51 | //│ module M1 { 52 | //│ module NM1 53 | //│ } 54 | 55 | :e 56 | M1.NM1 57 | //│ ╔══[ERROR] Access to module member not yet supported 58 | //│ ║ l.56: M1.NM1 59 | //│ ╙── ^^^^ 60 | //│ error 61 | //│ res 62 | //│ = NM1 { class: [class NM1] } 63 | 64 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/New.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Foo[A](x: A) 5 | //│ class Foo[A](x: A) 6 | 7 | let f = Foo(1) 8 | //│ let f: Foo['A] 9 | //│ where 10 | //│ 'A :> 1 11 | //│ f 12 | //│ = Foo {} 13 | 14 | // let f = new Foo(1) 15 | 16 | if f is Foo then 1 else 0 17 | //│ 0 | 1 18 | //│ res 19 | //│ = 1 20 | 21 | if f is Foo(a) then a else 0 22 | //│ 0 | 1 23 | //│ res 24 | //│ = 1 25 | 26 | // case f of 27 | // { Foo -> 28 | // let a = f.x 29 | // a 30 | // | _ -> 0 31 | // } 32 | 33 | // Foo(A) =:= Foo & { x: A } 34 | 35 | 36 | fun test(x) = if x is Foo(a) then a 37 | //│ fun test: forall 'a. Foo['a] -> 'a 38 | 39 | test(f) 40 | //│ 1 41 | //│ res 42 | //│ = 1 43 | 44 | class PoInt(x: Int, y: Int) 45 | //│ class PoInt(x: Int, y: Int) 46 | 47 | let origin = new PoInt(0, 0) 48 | //│ let origin: PoInt 49 | //│ origin 50 | //│ = PoInt {} 51 | 52 | 53 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/NuAlexJ.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | fun foo(x) = [x, x] 5 | //│ fun foo: forall 'a. 'a -> ['a, 'a] 6 | 7 | id 8 | //│ forall 'a. 'a -> 'a 9 | //│ res 10 | //│ = [Function: id] 11 | 12 | let r = foo(id) 13 | //│ let r: [forall 'a. 'a -> 'a, forall 'a. 'a -> 'a] 14 | //│ r 15 | //│ = [ [Function: id], [Function: id] ] 16 | 17 | 18 | fun fst(x, _) = x 19 | fun snd(_, x) = x 20 | //│ fun fst: forall 'a. ('a, anything) -> 'a 21 | //│ fun snd: forall 'b. (anything, 'b) -> 'b 22 | 23 | fst(1, 2) 24 | //│ 1 25 | //│ res 26 | //│ = 1 27 | 28 | :e 29 | fst([1, 2]) 30 | //│ ╔══[ERROR] Type mismatch in application: 31 | //│ ║ l.29: fst([1, 2]) 32 | //│ ║ ^^^^^^^^^^^ 33 | //│ ╟── argument of type `[[1, 2]]` does not match type `[?a, ?b]` 34 | //│ ║ l.29: fst([1, 2]) 35 | //│ ║ ^^^^^^^^ 36 | //│ ╟── Note: constraint arises from tuple literal: 37 | //│ ║ l.18: fun fst(x, _) = x 38 | //│ ╙── ^^^^^^ 39 | //│ error 40 | //│ res 41 | //│ = [ 1, 2 ] 42 | 43 | 44 | fun fst([x, _]) = x 45 | fun snd([_, x]) = x 46 | //│ fun fst: forall 'a. (['a, anything]) -> 'a 47 | //│ fun snd: forall 'b. ([anything, 'b]) -> 'b 48 | 49 | let s = fst(r) 50 | //│ let s: forall 'a. 'a -> 'a 51 | //│ s 52 | //│ = [Function: id] 53 | 54 | s("hello") 55 | //│ "hello" 56 | //│ res 57 | //│ = 'hello' 58 | 59 | s(123) 60 | //│ 123 61 | //│ res 62 | //│ = 123 63 | 64 | fst(r)("hello") 65 | //│ "hello" 66 | //│ res 67 | //│ = 'hello' 68 | 69 | 70 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/NuForallTerms.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | forall 'a: (x: 'a) => x 5 | //│ forall 'a. (x: 'a) -> 'a 6 | //│ res 7 | //│ = [Function: res] 8 | 9 | 10 | forall 'a: 11 | (x: 'a) => x 12 | //│ forall 'a. (x: 'a) -> 'a 13 | //│ res 14 | //│ = [Function (anonymous)] 15 | 16 | 17 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/NuScratch.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Numbers.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | let n = 123 5 | let m = n : Int 6 | let o = m : Num 7 | let p = o : Object 8 | let o = n : Num 9 | let p = n : Object 10 | let p = m : Object 11 | //│ let n: 123 12 | //│ let m: Int 13 | //│ let o: Num 14 | //│ let p: Object 15 | //│ let o: Num 16 | //│ let p: Object 17 | //│ let p: Object 18 | //│ n 19 | //│ = 123 20 | //│ m 21 | //│ = 123 22 | //│ o 23 | //│ = 123 24 | //│ p 25 | //│ = 123 26 | //│ o 27 | //│ = 123 28 | //│ p 29 | //│ = 123 30 | //│ p 31 | //│ = 123 32 | 33 | 34 | let x = NaN 35 | //│ let x: Num 36 | //│ x 37 | //│ = NaN 38 | 39 | // TODO polymorphic Num operations 40 | x + 1 41 | //│ ╔══[ERROR] Type mismatch in operator application: 42 | //│ ║ l.40: x + 1 43 | //│ ║ ^^^^^ 44 | //│ ╟── reference of type `Num` is not an instance of type `Int` 45 | //│ ║ l.34: let x = NaN 46 | //│ ║ ^^^ 47 | //│ ╟── but it flows into reference with expected type `Int` 48 | //│ ║ l.40: x + 1 49 | //│ ╙── ^ 50 | //│ Int | error 51 | //│ res 52 | //│ = NaN 53 | 54 | 55 | true : Bool 56 | //│ Bool 57 | //│ res 58 | //│ = true 59 | 60 | true : Bool | Str 61 | //│ Str | false | true 62 | //│ res 63 | //│ = true 64 | 65 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/ParamOverriding.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | mixin Over { 5 | fun p = "hi" 6 | } 7 | //│ mixin Over() { 8 | //│ fun p: "hi" 9 | //│ } 10 | 11 | 12 | class Base1(val p: Int) extends Over { 13 | fun test = [p, this.p] 14 | fun test2 = super.p 15 | } 16 | //│ class Base1(p: Int) { 17 | //│ fun p: "hi" 18 | //│ fun test: [Int, Int] 19 | //│ fun test2: Int 20 | //│ } 21 | 22 | 23 | Base1(123).test 24 | //│ [Int, Int] 25 | //│ res 26 | //│ = [ 123, 123 ] 27 | 28 | Base1(123).test2 29 | //│ Int 30 | //│ res 31 | //│ = 'hi' 32 | 33 | 34 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/PartialApp.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | // TODO support partial application syntax 4 | :AllowTypeErrors 5 | 6 | 7 | fun foo(x, y) = x + y 8 | //│ fun foo: (Int, Int) -> Int 9 | 10 | 11 | foo(2, _) 12 | //│ ╔══[ERROR] Widlcard in expression position. 13 | //│ ║ l.11: foo(2, _) 14 | //│ ╙── ^ 15 | //│ Int 16 | 17 | // * ie 18 | tmp => foo(2, tmp) 19 | //│ Int -> Int 20 | 21 | 22 | _.foo(1) 23 | //│ ╔══[ERROR] Widlcard in expression position. 24 | //│ ║ l.22: _.foo(1) 25 | //│ ╙── ^ 26 | //│ error 27 | 28 | // * ie 29 | x => x.foo(1) 30 | //│ forall 'a. {foo: 1 -> 'a} -> 'a 31 | 32 | 33 | _ + _ 34 | //│ ╔══[ERROR] Widlcard in expression position. 35 | //│ ║ l.33: _ + _ 36 | //│ ╙── ^ 37 | //│ ╔══[ERROR] Widlcard in expression position. 38 | //│ ║ l.33: _ + _ 39 | //│ ╙── ^ 40 | //│ Int 41 | 42 | // * ie 43 | (x, y) => x + y 44 | //│ (Int, Int) -> Int 45 | 46 | 47 | _2 + _1 48 | //│ ╔══[ERROR] identifier not found: _2 49 | //│ ║ l.47: _2 + _1 50 | //│ ╙── ^^ 51 | //│ ╔══[ERROR] identifier not found: _1 52 | //│ ║ l.47: _2 + _1 53 | //│ ╙── ^^ 54 | //│ Int 55 | 56 | // * ie 57 | (x, y) => y + x 58 | //│ (Int, Int) -> Int 59 | 60 | 61 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/PrivateMemberOverriding.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Foo(x: Int) 5 | //│ class Foo(x: Int) 6 | 7 | class Bar() extends Foo(123) { fun x = true } 8 | //│ class Bar() extends Foo { 9 | //│ fun x: true 10 | //│ } 11 | 12 | Bar().x 13 | //│ true 14 | //│ res 15 | //│ = true 16 | 17 | if Bar() is Foo(a) then a 18 | //│ Int 19 | //│ res 20 | //│ = 123 21 | 22 | 23 | class Bar(val x: Bool) extends Foo(123) 24 | //│ class Bar(x: Bool) extends Foo 25 | 26 | Bar(true).x 27 | //│ Bool 28 | //│ res 29 | //│ = true 30 | 31 | if Bar(true) is Foo(a) then a 32 | //│ Int 33 | //│ res 34 | //│ = 123 35 | 36 | 37 | class Bar(x: Bool) extends Foo(123) 38 | //│ class Bar(x: Bool) extends Foo 39 | 40 | :e // * Expected 41 | Bar(true).x 42 | //│ ╔══[ERROR] Parameter 'x' cannot be accessed as a field 43 | //│ ║ l.41: Bar(true).x 44 | //│ ║ ^^ 45 | //│ ╟── Either make the parameter a `val` or access it through destructuring 46 | //│ ║ l.37: class Bar(x: Bool) extends Foo(123) 47 | //│ ╙── ^ 48 | //│ error | false | true 49 | //│ res 50 | //│ = undefined 51 | 52 | if Bar(true) is Foo(a) then a 53 | //│ Int 54 | //│ res 55 | //│ = 123 56 | 57 | 58 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/RefinedPattern.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class C 5 | //│ class C { 6 | //│ constructor() 7 | //│ } 8 | 9 | 10 | :e 11 | fun test(x) = if x is 12 | C then x.a 13 | //│ ╔══[ERROR] Type `C` does not contain member `a` 14 | //│ ║ l.12: C then x.a 15 | //│ ╙── ^^ 16 | //│ fun test: C -> error 17 | 18 | fun test(x) = if x is 19 | refined(C) then x.a 20 | //│ fun test: forall 'a. (C & {a: 'a}) -> 'a 21 | 22 | class D(val a: Int) extends C 23 | //│ class D(a: Int) extends C 24 | 25 | test(D(123)) 26 | //│ Int 27 | //│ res 28 | //│ = 123 29 | 30 | 31 | :e 32 | refined 33 | //│ ╔══[ERROR] Illegal use of reserved operator: refined 34 | //│ ║ l.32: refined 35 | //│ ╙── ^^^^^^^ 36 | //│ ╔══[ERROR] identifier not found: refined 37 | //│ ║ l.32: refined 38 | //│ ╙── ^^^^^^^ 39 | //│ error 40 | //│ Code generation encountered an error: 41 | //│ unresolved symbol refined 42 | 43 | 44 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Res.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | x => x + 2 5 | //│ Int -> Int 6 | //│ res 7 | //│ = [Function: res] 8 | 9 | :e 10 | res(1) 11 | //│ ╔══[ERROR] identifier not found: res 12 | //│ ║ l.10: res(1) 13 | //│ ╙── ^^^ 14 | //│ error 15 | //│ res 16 | //│ = 3 17 | 18 | 19 | let res = x => x + 2 20 | //│ let res: Int -> Int 21 | //│ res 22 | //│ = [Function: res1] 23 | 24 | res(1) 25 | //│ Int 26 | //│ res 27 | //│ = 3 28 | 29 | // FIXME `res` not accounted in type context 30 | :re 31 | res(1) 32 | //│ Int 33 | //│ res 34 | //│ Runtime error: 35 | //│ TypeError: res is not a function 36 | 37 | 38 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/RigidVariables.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | // * Flexible 5 | 6 | fun f(x: 'test) = [x.b, x] 7 | //│ fun f: forall 'b 'test. (x: {b: 'b} & 'test) -> ['b, 'test] 8 | 9 | 10 | // * Rigid 11 | 12 | :e 13 | fun f[A](x: A) = x.b 14 | //│ ╔══[ERROR] Type `A` does not contain member `b` 15 | //│ ║ l.13: fun f[A](x: A) = x.b 16 | //│ ╙── ^^ 17 | //│ fun f: (x: anything) -> error 18 | 19 | fun f[A](x: A & { b: ' }) = x.b 20 | //│ fun f: forall 'b. (x: {b: 'b}) -> 'b 21 | 22 | :e 23 | module Foo { 24 | fun f[A](x: A) = x.b 25 | } 26 | //│ ╔══[ERROR] Type `A` does not contain member `b` 27 | //│ ║ l.24: fun f[A](x: A) = x.b 28 | //│ ╙── ^^ 29 | //│ module Foo { 30 | //│ fun f: (x: anything) -> error 31 | //│ } 32 | 33 | :e 34 | class Foo[A](x: A) { 35 | fun f = x.b 36 | } 37 | //│ ╔══[ERROR] Type `A` does not contain member `b` 38 | //│ ║ l.35: fun f = x.b 39 | //│ ╙── ^^ 40 | //│ class Foo[A](x: A) { 41 | //│ fun f: error 42 | //│ } 43 | 44 | 45 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/SimpleSymbolicOps.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | fun (-) i(x, y) = x 5 | //│ fun (-) i: forall 'a. ('a, anything) -> 'a 6 | 7 | 1 - 1 8 | //│ 1 9 | //│ res 10 | //│ = 1 11 | 12 | 13 | fun (-) i(x, y) = x 14 | [i(1,1), i(2,1), 1 - 1, 2 - 1] 15 | //│ fun (-) i: forall 'a. ('a, anything) -> 'a 16 | //│ [1, 2, 1, 2] 17 | //│ res 18 | //│ = [ 1, 2, 1, 2 ] 19 | 20 | 21 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/StupidJS.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | module C { fun f() = this } 5 | //│ module C { 6 | //│ fun f: () -> C 7 | //│ } 8 | 9 | C.f() 10 | //│ C 11 | //│ res 12 | //│ = C { class: [class C] } 13 | 14 | 15 | // * In JS semantics, C.f will return a plain method **without capturing `this`**!! 16 | // * This is very dumb. In Python for example, one gets a closure that captures `this`. 17 | // * We can't easily work around this without incurring either bad performance overhead 18 | // * or JS/TS interoperability woes. 19 | // * Therefore, we'll make sure to reflecy the wonky semantics in the typer 20 | // * (or maybe just make it fail type checking altogether.) 21 | 22 | // :e // TODO prevent unapplied method selections in the type system... 23 | let r = id(C.f)() 24 | //│ let r: C 25 | //│ r 26 | //│ = undefined 27 | 28 | :re 29 | r.f 30 | //│ () -> C 31 | //│ res 32 | //│ Runtime error: 33 | //│ TypeError: Cannot read properties of undefined (reading 'f') 34 | 35 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Subscripts.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | let xs = [0, 1, 2] 5 | //│ let xs: [0, 1, 2] 6 | //│ xs 7 | //│ = [ 0, 1, 2 ] 8 | 9 | if xs.[0] is 10 | undefined then 0 11 | x then x 12 | //│ 0 | 1 | 2 13 | //│ res 14 | //│ = 0 15 | 16 | 17 | :e 18 | xs.[0] + 1 19 | //│ ╔══[ERROR] Type mismatch in operator application: 20 | //│ ║ l.18: xs.[0] + 1 21 | //│ ║ ^^^^^^^^ 22 | //│ ╟── possibly-undefined array access of type `()` is not an instance of type `Int` 23 | //│ ║ l.18: xs.[0] + 1 24 | //│ ╙── ^^^^ 25 | //│ Int | error 26 | //│ res 27 | //│ = 1 28 | 29 | 30 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/TraitParameters.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | :e 5 | trait Base1(x: Int) 6 | //│ ╔══[ERROR] trait parameters are not yet supported 7 | //│ ║ l.5: trait Base1(x: Int) 8 | //│ ╙── ^^^^^^^^ 9 | //│ trait Base1 10 | 11 | 12 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/TupleParamBlunder.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | // * TODO fix the parsing of this tuple-taking function signature! 5 | fun f: [Int, Int] -> Int 6 | fun f(a, b) = a + b // should not be a valid implementation 7 | //│ fun f: (Int, Int) -> Int 8 | //│ fun f: (Int, Int) -> Int 9 | 10 | fun f: (Int, Int) -> Int 11 | fun f(a, b) = a + b 12 | //│ fun f: (Int, Int) -> Int 13 | //│ fun f: (Int, Int) -> Int 14 | 15 | :e 16 | fun f: [Int, Int] => Int 17 | fun f(a, b) = a + b 18 | //│ ╔══[ERROR] Type mismatch in definition: 19 | //│ ║ l.17: fun f(a, b) = a + b 20 | //│ ║ ^^^^^^^^^^^^^^^ 21 | //│ ╟── type `[[Int, Int]]` does not match type `[?a, ?b]` 22 | //│ ║ l.16: fun f: [Int, Int] => Int 23 | //│ ║ ^^^^^^^^^^ 24 | //│ ╟── Note: constraint arises from tuple literal: 25 | //│ ║ l.17: fun f(a, b) = a + b 26 | //│ ╙── ^^^^^^ 27 | //│ fun f: (Int, Int) -> Int 28 | //│ fun f: ([Int, Int]) -> Int 29 | 30 | fun f: (Int, Int) => Int 31 | fun f(a, b) = a + b 32 | //│ fun f: (Int, Int) -> Int 33 | //│ fun f: (Int, Int) -> Int 34 | 35 | 36 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/TypeAliases.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | type I = Int 5 | //│ type I = Int 6 | 7 | class CI1 8 | //│ class CI1 { 9 | //│ constructor() 10 | //│ } 11 | 12 | // :e 13 | type AI1 = Array[Int] 14 | //│ type AI1 = Array[Int] 15 | 16 | type AI2 = Array 17 | //│ type AI2 = Array[Int] 18 | 19 | :e 20 | type AI3(n) = Array[Int] 21 | //│ ╔══[ERROR] Type alias definitions cannot have value parameters 22 | //│ ║ l.20: type AI3(n) = Array[Int] 23 | //│ ╙── ^^^ 24 | //│ type AI3 = Array[Int] 25 | 26 | // :e 27 | type AI3[A] = Array 28 | //│ type AI3[A] = Array[A] 29 | 30 | type AI4 = Array 31 | //│ type AI4[A] = Array[A] 32 | 33 | let r = 123 34 | //│ let r: 123 35 | //│ r 36 | //│ = 123 37 | 38 | r: I 39 | //│ I 40 | //│ res 41 | //│ = 123 42 | 43 | let a = [r, r, r] 44 | //│ let a: [123, 123, 123] 45 | //│ a 46 | //│ = [ 123, 123, 123 ] 47 | 48 | a : AI1 49 | //│ AI1 50 | //│ res 51 | //│ = [ 123, 123, 123 ] 52 | 53 | a : AI2 54 | //│ AI2 55 | //│ res 56 | //│ = [ 123, 123, 123 ] 57 | 58 | a : AI3[Int] 59 | //│ AI3[Int] 60 | //│ res 61 | //│ = [ 123, 123, 123 ] 62 | 63 | a : AI4 64 | //│ AI4[Int] 65 | //│ res 66 | //│ = [ 123, 123, 123 ] 67 | 68 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/TypeOps.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | type *[A, B] = [A, B] 5 | //│ type *[A, B] = [A, B] 6 | 7 | 8 | fun x : Int * Int 9 | fun x = [0, 1] 10 | //│ fun x: [0, 1] 11 | //│ fun x: *[Int, Int] 12 | 13 | fun x : Int * [Int] 14 | fun x = [0, [1]] 15 | //│ fun x: [0, [1]] 16 | //│ fun x: *[Int, [Int]] 17 | 18 | fun x : [Int] * Int 19 | fun x = [[0], 1] 20 | //│ fun x: [[0], 1] 21 | //│ fun x: *[[Int], Int] 22 | 23 | 24 | type Id[A] = A 25 | //│ type Id[A] = A 26 | 27 | :e 28 | fun x: Id[Int, Int] 29 | //│ ╔══[ERROR] Wrong number of type arguments – expected 1, found 2 30 | //│ ║ l.28: fun x: Id[Int, Int] 31 | //│ ╙── ^^^^^^^^^^^^ 32 | //│ fun x: Id[Int] 33 | 34 | fun x: Id[[Int, Int]] 35 | //│ fun x: Id[[Int, Int]] 36 | 37 | fun x: Id[[[Int, Int]]] 38 | //│ fun x: Id[[[Int, Int]]] 39 | 40 | 41 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/TypeSelections.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | module M { 5 | type T = Int -> Int 6 | class C(n: Int) 7 | fun mkC = C 8 | } 9 | //│ module M { 10 | //│ class C(n: Int) 11 | //│ type T = Int -> Int 12 | //│ fun mkC: (n: Int) -> C 13 | //│ } 14 | 15 | let x: M.T = id 16 | //│ let x: Int -> Int 17 | //│ x 18 | //│ = [Function: id] 19 | 20 | fun foo(x: M.C) = x 21 | //│ fun foo: (x: C) -> C 22 | 23 | 24 | foo(M.mkC(42)) 25 | //│ C 26 | //│ res 27 | //│ = C {} 28 | 29 | 30 | :e 31 | 42 : M.mkC 32 | //│ ╔══[ERROR] Illegal selection of value member in type position 33 | //│ ║ l.31: 42 : M.mkC 34 | //│ ╙── ^^^^ 35 | //│ error 36 | //│ res 37 | //│ = 42 38 | 39 | 40 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/TypeVariables.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | fun x: 'a -> 'a = succ 5 | //│ fun x: Int -> Int 6 | 7 | :e 8 | fun x: forall 'a: 'a -> 'a = succ 9 | //│ ╔══[ERROR] Type mismatch in type ascription: 10 | //│ ║ l.8: fun x: forall 'a: 'a -> 'a = succ 11 | //│ ║ ^^^^ 12 | //│ ╟── type `'a` is not an instance of type `Int` 13 | //│ ║ l.8: fun x: forall 'a: 'a -> 'a = succ 14 | //│ ║ ^^ 15 | //│ ╟── Note: quantified type variable 'a is defined at: 16 | //│ ║ l.8: fun x: forall 'a: 'a -> 'a = succ 17 | //│ ╙── ^^ 18 | //│ fun x: forall 'a. 'a -> 'a 19 | 20 | fun x: [Int -> Int] = [id : forall 'a: 'a -> 'a] 21 | //│ fun x: [Int -> Int] 22 | 23 | :pe 24 | :e 25 | fun x: [Int -> Int] = [id : forall 'a: 'a -> 'a,] 26 | //│ ╔══[PARSE ERROR] Unexpected end of square bracket section; an expression was expected here 27 | //│ ║ l.25: fun x: [Int -> Int] = [id : forall 'a: 'a -> 'a,] 28 | //│ ╙── ^ 29 | //│ ╔══[ERROR] type identifier not found: , 30 | //│ ║ l.25: fun x: [Int -> Int] = [id : forall 'a: 'a -> 'a,] 31 | //│ ╙── ^^^^^^^^^ 32 | //│ fun x: [Int -> Int] 33 | 34 | fun x: [Int -> Int,] = [id : forall 'a: 'a -> 'a] 35 | //│ fun x: [Int -> Int] 36 | 37 | 38 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/TypingUnitTerms.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | :e 5 | fun test = 6 | let x = 0(0) 7 | 1 8 | //│ ╔══[ERROR] Type mismatch in application: 9 | //│ ║ l.6: let x = 0(0) 10 | //│ ║ ^^^^ 11 | //│ ╟── integer literal of type `0` is not a function 12 | //│ ║ l.6: let x = 0(0) 13 | //│ ╙── ^ 14 | //│ fun test: 1 15 | 16 | 17 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/TypreMembers.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Test { type T = Int } 5 | //│ class Test { 6 | //│ constructor() 7 | //│ type T = Int 8 | //│ } 9 | 10 | 1 : Test.T 11 | //│ Int 12 | //│ res 13 | //│ = 1 14 | 15 | 16 | trait Test { type T = Int } 17 | //│ trait Test { 18 | //│ type T = Int 19 | //│ } 20 | 21 | :e 22 | 1 : Test.T 23 | //│ ╔══[ERROR] Illegal prefix of type selection: Test 24 | //│ ║ l.22: 1 : Test.T 25 | //│ ╙── ^^^^ 26 | //│ error 27 | //│ res 28 | //│ = 1 29 | 30 | 31 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/UnaryMinus.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | -1 4 | //│ -1 5 | //│ res 6 | //│ = -1 7 | 8 | - 1 9 | //│ -1 10 | //│ res 11 | //│ = -1 12 | 13 | 1+1 14 | //│ Int 15 | //│ res 16 | //│ = 2 17 | 18 | 1-3 19 | //│ Int 20 | //│ res 21 | //│ = -2 22 | 23 | 3-1 24 | //│ Int 25 | //│ res 26 | //│ = 2 27 | 28 | 1 - (3 - 5) 29 | //│ Int 30 | //│ res 31 | //│ = 3 32 | 33 | 3 - 1 34 | //│ Int 35 | //│ res 36 | //│ = 2 37 | 38 | 1 -1 39 | //│ Int 40 | //│ res 41 | //│ = 0 42 | 43 | 1-1 44 | //│ Int 45 | //│ res 46 | //│ = 0 47 | 48 | 1+ -1 49 | //│ Int 50 | //│ res 51 | //│ = 0 52 | 53 | 1 - (1 - 1) 54 | //│ Int 55 | //│ res 56 | //│ = 1 57 | 58 | 1 - 1 59 | //│ Int 60 | //│ res 61 | //│ = 0 62 | 63 | 1 - - 1 64 | //│ Int 65 | //│ res 66 | //│ = 2 67 | 68 | 1 - - - - 1 69 | //│ Int 70 | //│ res 71 | //│ = 2 72 | 73 | fun f() = 6 74 | -f() 75 | //│ fun f: () -> 6 76 | //│ Int 77 | //│ res 78 | //│ = -6 79 | 80 | fun inv(x: Int) = -x 81 | inv(15) 82 | inv(inv(15)) 83 | //│ fun inv: (x: Int) -> Int 84 | //│ Int 85 | //│ res 86 | //│ = -15 87 | //│ res 88 | //│ = 15 89 | 90 | inv(f()) 91 | //│ Int 92 | //│ res 93 | //│ = -6 94 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Uninstantiable.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | :e 5 | Int 6 | //│ ╔══[ERROR] Class Int is abstract and cannot be instantiated 7 | //│ ║ l.5: Int 8 | //│ ╙── ^^^ 9 | //│ ╔══[ERROR] Class Int cannot be instantiated as it exposes no constructor 10 | //│ ║ l.5: Int 11 | //│ ╙── ^^^ 12 | //│ error 13 | //│ Code generation encountered an error: 14 | //│ unresolved symbol Int 15 | 16 | :e 17 | Int() 18 | //│ ╔══[ERROR] Class Int is abstract and cannot be instantiated 19 | //│ ║ l.17: Int() 20 | //│ ╙── ^^^ 21 | //│ ╔══[ERROR] Class Int cannot be instantiated as it exposes no constructor 22 | //│ ║ l.17: Int() 23 | //│ ╙── ^^^ 24 | //│ error 25 | //│ Code generation encountered an error: 26 | //│ unresolved symbol Int 27 | 28 | :e 29 | new Int 30 | //│ ╔══[ERROR] Class Int is abstract and cannot be instantiated 31 | //│ ║ l.29: new Int 32 | //│ ╙── ^^^ 33 | //│ Int 34 | //│ Code generation encountered an error: 35 | //│ unresolved symbol Int 36 | 37 | 38 | // FIXME forbid statically 39 | module A extends Int 40 | //│ module A extends Int, Num 41 | //│ Code generation encountered an error: 42 | //│ unresolved parent Int. 43 | 44 | 45 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/ValSigs.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | val x: Int 5 | //│ val x: Int 6 | //│ x 7 | //│ = 8 | 9 | // * Note that this counts as a completely new `val` since it's in a new block 10 | val x = "hi" 11 | //│ val x: "hi" 12 | //│ x 13 | //│ = 'hi' 14 | 15 | 16 | val x: Int 17 | val x = 1 18 | //│ val x: 1 19 | //│ val x: Int 20 | //│ x 21 | //│ = 22 | //│ x 23 | //│ = 1 24 | val x = 1 25 | //│ val x: 1 26 | //│ x 27 | //│ = 1 28 | 29 | x 30 | //│ 1 31 | //│ res 32 | //│ = 1 33 | 34 | 35 | :e 36 | val x: Int 37 | val x = "oops" 38 | //│ ╔══[ERROR] Type mismatch in definition: 39 | //│ ║ l.37: val x = "oops" 40 | //│ ║ ^^^^^^^^^^ 41 | //│ ╟── string literal of type `"oops"` is not an instance of type `Int` 42 | //│ ║ l.37: val x = "oops" 43 | //│ ║ ^^^^^^ 44 | //│ ╟── but it flows into definition of value x with expected type `Int` 45 | //│ ║ l.37: val x = "oops" 46 | //│ ║ ^^^^^^^^^^ 47 | //│ ╟── Note: constraint arises from type reference: 48 | //│ ║ l.36: val x: Int 49 | //│ ╙── ^^^ 50 | //│ val x: "oops" 51 | //│ val x: Int 52 | //│ x 53 | //│ = 54 | //│ x 55 | //│ = 'oops' 56 | 57 | 58 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Vals.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | val a = 1 5 | val b = a + 1 6 | //│ val a: 1 7 | //│ val b: Int 8 | //│ a 9 | //│ = 1 10 | //│ b 11 | //│ = 2 12 | 13 | 14 | // :e // FIXME should not type check 15 | :ge 16 | val c = d + 1 17 | val d = 1 18 | //│ val c: Int 19 | //│ val d: 1 20 | //│ Code generation encountered an error: 21 | //│ unguarded recursive use of by-value binding d 22 | 23 | 24 | // :e // FIXME should not type check 25 | :ge 26 | val a = a 27 | //│ val a: nothing 28 | //│ Code generation encountered an error: 29 | //│ unguarded recursive use of by-value binding a 30 | 31 | 32 | val f(x) = x 33 | //│ val f: forall 'a. 'a -> 'a 34 | //│ f 35 | //│ = [Function: f] 36 | 37 | f(123) 38 | //│ 123 39 | //│ res 40 | //│ = 123 41 | 42 | 43 | module M { 44 | let tmp = 2 45 | val f(x) = x + tmp 46 | } 47 | //│ module M { 48 | //│ val f: Int -> Int 49 | //│ let tmp: 2 50 | //│ } 51 | 52 | M.f(123) 53 | //│ Int 54 | //│ res 55 | //│ = 125 56 | 57 | 58 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Varargs.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | // * Built-in vararg 5 | 6 | :js 7 | join 8 | //│ (...Array[Str]) -> Str 9 | //│ // Prelude 10 | //│ function join(...xs) { 11 | //│ return xs.join(""); 12 | //│ } 13 | //│ let res; 14 | //│ class TypingUnit {} 15 | //│ const typing_unit = new TypingUnit; 16 | //│ // Query 1 17 | //│ res = join; 18 | //│ // End of generated code 19 | //│ res 20 | //│ = [Function: join] 21 | 22 | join("Hello", ",", " ", "World", "!") 23 | //│ Str 24 | //│ res 25 | //│ = 'Hello, World!' 26 | 27 | 28 | // * TODO It's currently not possible to define vararg-taking functions manually... 29 | 30 | :pe 31 | :e 32 | fun test(...xs) = xs.length 33 | //│ ╔══[PARSE ERROR] Unexpected operator here 34 | //│ ║ l.32: fun test(...xs) = xs.length 35 | //│ ╙── ^^^ 36 | //│ ╔══[ERROR] identifier not found: xs 37 | //│ ║ l.32: fun test(...xs) = xs.length 38 | //│ ╙── ^^ 39 | //│ fun test: () -> error 40 | //│ Code generation encountered an error: 41 | //│ unresolved symbol xs 42 | 43 | 44 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/WeirdDefs.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | fun fst[x, _] = error : x -> x 5 | //│ fun fst: forall 'x. 'x -> 'x 6 | 7 | :e 8 | fun fst[x, _] = x 9 | //│ ╔══[ERROR] identifier not found: x 10 | //│ ║ l.8: fun fst[x, _] = x 11 | //│ ╙── ^ 12 | //│ fun fst: error 13 | //│ Code generation encountered an error: 14 | //│ unresolved symbol x 15 | 16 | 17 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/With.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | {} with {} 5 | //│ anything 6 | //│ res 7 | //│ = {} 8 | 9 | {x: 1} with {y: 2} 10 | //│ {x: 1, y: 2} 11 | //│ res 12 | //│ = { x: 1, y: 2 } 13 | 14 | {x: 1} with {x: 2} 15 | //│ {x: 2} 16 | //│ res 17 | //│ = { x: 2 } 18 | 19 | 20 | :pe 21 | {x: 1} with 123 22 | //│ ╔══[PARSE ERROR] record literal expected here; found integer literal 23 | //│ ║ l.21: {x: 1} with 123 24 | //│ ╙── ^^^ 25 | //│ {x: 1} 26 | //│ res 27 | //│ = { x: 1 } 28 | 29 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/repro0.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | 5 | class Add[out E](val lhs: E) 6 | val add11 = Add(add11) 7 | module EvalAddLit { 8 | fun eval(e: Add['A]) = 9 | if e is Add then eval(e.lhs) 10 | } 11 | let res = EvalAddLit.eval(add11) 12 | //│ class Add[E](lhs: E) 13 | //│ val add11: 'E 14 | //│ module EvalAddLit { 15 | //│ fun eval: forall 'A. (e: 'A) -> nothing 16 | //│ } 17 | //│ let res: nothing 18 | //│ where 19 | //│ 'A <: Add['A] 20 | //│ 'E :> Add['E] 21 | 22 | 23 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/repro1.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | 5 | class Union[out Region](val a: Region) 6 | // class Union[Region](a: Region) 7 | //│ class Union[Region](a: Region) 8 | 9 | fun go(x) = Union(go(x)) 10 | let circles = go(2) 11 | //│ fun go: forall 'Region. anything -> 'Region 12 | //│ let circles: forall 'Region0. 'Region0 13 | //│ where 14 | //│ 'Region0 :> Union['Region0] 15 | //│ 'Region :> Union['Region] 16 | 17 | 18 | fun contains(a) = 19 | if a is Union then contains(a.a) 20 | //│ fun contains: forall 'a. 'a -> nothing 21 | //│ where 22 | //│ 'a <: Union['a] 23 | 24 | contains(circles) 25 | //│ nothing 26 | 27 | 28 | mixin Contains { 29 | fun contains(a) = 30 | if a is Union then this.contains(a.a) 31 | } 32 | //│ mixin Contains() { 33 | //│ this: {contains: 'a -> 'b} 34 | //│ fun contains: Union['a] -> 'b 35 | //│ } 36 | 37 | module TestContains extends Contains 38 | //│ module TestContains { 39 | //│ fun contains: 'a -> nothing 40 | //│ } 41 | //│ where 42 | //│ 'a <: Union['a] 43 | 44 | TestContains.contains(circles) 45 | //│ nothing 46 | 47 | 48 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/repro_EvalNegNeg.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Add(lhs: E, rhs: E) 5 | class Lit(n: Int) 6 | class Neg(expr: A) 7 | //│ class Add[E](lhs: E, rhs: E) 8 | //│ class Lit(n: Int) 9 | //│ class Neg[A](expr: A) 10 | 11 | 12 | // Note the inferred type because of current UCS limitation 13 | mixin EvalBase { 14 | fun eval(e) = 15 | if e is Neg(Neg(d)) then this.eval(d) 16 | else if e is Neg(d) then 0 - this.eval(d) 17 | else if e is 18 | Lit(n) then n 19 | Add(l, r) then this.eval(l) + this.eval(r) 20 | } 21 | //│ mixin EvalBase() { 22 | //│ this: {eval: 'a -> 'b & 'c -> Int} 23 | //│ fun eval: (Add['c] | Lit | Neg['c & (Neg['a] | Object & ~#Neg)]) -> (Int | 'b) 24 | //│ } 25 | 26 | // module TestLang extends EvalBase, EvalNeg 27 | module TestLang extends EvalBase 28 | //│ module TestLang { 29 | //│ fun eval: 'a -> Int 30 | //│ } 31 | //│ where 32 | //│ 'a <: Add['a] | Lit | Neg['a & (Neg['a] | Object & ~#Neg)] 33 | 34 | 35 | fun mk(n) = if n is 36 | 0 then Lit(0) 37 | 1 then Neg(mk(n)) 38 | _ then Add(mk(n), mk(n)) 39 | //│ fun mk: forall 'a. Object -> (Lit | 'a) 40 | //│ where 41 | //│ 'a :> Add[Lit | 'a] | Neg[Lit | 'a] 42 | 43 | :stats 44 | TestLang.eval(mk(0)) 45 | //│ Int 46 | //│ res 47 | //│ = 0 48 | //│ constrain calls : 254 49 | //│ annoying calls : 106 50 | //│ subtyping calls : 1430 51 | 52 | 53 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/repro_PolymorphicVariants.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | // Test that reprduces subtle type simplification bug 4 | 5 | class Cons[out A](head: A, tail: Cons[A] | Nil) 6 | module Nil 7 | //│ class Cons[A](head: A, tail: Cons[A] | Nil) 8 | //│ module Nil 9 | 10 | class Abs[A](x: string, t: A) 11 | class App[A](s: A, t: A) 12 | //│ class Abs[A](x: string, t: A) 13 | //│ class App[A](s: A, t: A) 14 | 15 | fun eval(sub, v) = 16 | if v is 17 | Abs(x, t) then 18 | eval(Cons([error, error], Nil), error) 19 | eval(Cons(error, sub), error) 20 | error 21 | //│ fun eval: (Cons[anything] | Nil, Abs[anything]) -> nothing 22 | 23 | mixin EvalLambda { 24 | fun eval(sub, v) = 25 | if v is 26 | Abs(x, t) then 27 | this.eval(Cons([error, error], Nil), error) 28 | this.eval(Cons([x, error], sub), error) 29 | error 30 | } 31 | //│ mixin EvalLambda() { 32 | //│ this: {eval: (Cons[[string, nothing] | 'A], nothing) -> ()} 33 | //│ fun eval: (Cons['A] | Nil, Abs[anything]) -> nothing 34 | //│ } 35 | 36 | // * Note: this used to crash because of a current type simplification bug: analyze2 does not traverse TVs witht he correct PolMap 37 | // * The original unreduced version in PolymorphicVariants.mls still crashes... 38 | // :ds 39 | module Test1 extends EvalLambda 40 | //│ module Test1 { 41 | //│ fun eval: (Cons[anything] | Nil, Abs[anything]) -> nothing 42 | //│ } 43 | 44 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/Annot.mls: -------------------------------------------------------------------------------- 1 | 2 | :p 3 | @hello 4 | fun hello(x) = 5 | @a 6 | @b 7 | let rec x = @hello 2 8 | //│ |@|hello|↵|#fun| |hello|(|x|)| |#=| |→|@|a|↵|@|b|↵|#let| |#rec| |x| |#=| |@|hello| |2|←| 9 | //│ Parsed: {fun hello = (x,) => {let rec x = @hello 2}} 10 | //│ AST: TypingUnit(List(NuFunDef(None,Var(hello),None,List(),Left(Lam(Tup(List((None,Fld(_,Var(x))))),Blk(List(NuFunDef(Some(true),Var(x),None,List(),Left(Ann(Var(hello),IntLit(2))))))))))) 11 | //│ Parsed: 12 | 13 | :p 14 | @tailrec 2 15 | //│ |@|tailrec| |2| 16 | //│ Parsed: {@tailrec 2} 17 | //│ AST: TypingUnit(List(Ann(Var(tailrec),IntLit(2)))) 18 | //│ Parsed: 19 | 20 | :p 21 | if @hello true then 2 else 3 22 | //│ |#if| |@|hello| |true| |#then| |2| |#else| |3| 23 | //│ Parsed: {if (@hello true) then 2 else 3} 24 | //│ AST: TypingUnit(List(If(IfThen(Ann(Var(hello),Var(true)),IntLit(2)),Some(IntLit(3))))) 25 | //│ Parsed: 26 | 27 | :pe 28 | if @test x 29 | is Foo then 2 30 | //│ |#if| |@|test| |x|→|is| |Foo| |#then| |2|←| 31 | //│ ╔══[PARSE ERROR] Unexpected annotation 32 | //│ ║ l.28: if @test x 33 | //│ ╙── ^^^^ 34 | //│ Parsed: {if x ‹· is (Foo) then 2›} 35 | 36 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/Binds.mls: -------------------------------------------------------------------------------- 1 | :AllowParseErrors 2 | 3 | 4 | f(x) is True 5 | //│ |f|(|x|)| |is| |True| 6 | //│ Parsed: {is(f(x,),)(True,)} 7 | 8 | // Precedence of 'of'/'is' may be surprising! 9 | f of x is True 10 | //│ |f| |#of| |x| |is| |True| 11 | //│ Parsed: {f(is(x,)(True,),)} 12 | 13 | 14 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/Brackets.mls: -------------------------------------------------------------------------------- 1 | 2 | () 3 | //│ |(||)| 4 | //│ Parsed: {undefined} 5 | 6 | [] 7 | //│ |[||]| 8 | //│ Parsed: {[]} 9 | 10 | {} 11 | //│ |{||}| 12 | //│ Parsed: {'{' {} '}'} 13 | 14 | :pe 15 | (} 16 | //│ ╔══[PARSE ERROR] Mistmatched closing curly brace 17 | //│ ║ l.15: (} 18 | //│ ║ ^ 19 | //│ ╟── does not correspond to opening parenthesis 20 | //│ ║ l.15: (} 21 | //│ ╙── ^ 22 | //│ |(||)| 23 | //│ Parsed: {undefined} 24 | 25 | (([{}])) 26 | //│ |(|(|[|{||}|]|)|)| 27 | //│ Parsed: {'(' '(' ['{' {} '}',] ')' ')'} 28 | 29 | :pe 30 | (([{})]) 31 | //│ ╔══[PARSE ERROR] Mistmatched closing parenthesis 32 | //│ ║ l.30: (([{})]) 33 | //│ ║ ^ 34 | //│ ╟── does not correspond to opening square bracket 35 | //│ ║ l.30: (([{})]) 36 | //│ ╙── ^ 37 | //│ ╔══[PARSE ERROR] Mistmatched closing square bracket 38 | //│ ║ l.30: (([{})]) 39 | //│ ║ ^ 40 | //│ ╟── does not correspond to opening parenthesis 41 | //│ ║ l.30: (([{})]) 42 | //│ ╙── ^ 43 | //│ |(|(|[|{||}|]|)|)| 44 | //│ Parsed: {'(' '(' ['{' {} '}',] ')' ')'} 45 | 46 | 47 | fun f = () 48 | //│ |#fun| |f| |#=| |(||)| 49 | //│ Parsed: {fun f = undefined} 50 | 51 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/Comments.mls: -------------------------------------------------------------------------------- 1 | 2 | 1 // whoops 3 | //│ |1| |/* whoops*/| 4 | //│ Parsed: {1} 5 | 6 | 2 /* whoops */ 7 | //│ |2| |/* whoops */| 8 | //│ Parsed: {2} 9 | 10 | 1 11 | // A 12 | 2 13 | //│ |1|↵|/* A*/|↵|2| 14 | //│ Parsed: {1; 2} 15 | 16 | :w 17 | 1 18 | // A 19 | 2 20 | //│ |1|→|/* A*/|←|↵|2| 21 | //│ ╔══[WARNING] Paren-less applications should use the 'of' keyword 22 | //│ ║ l.17: 1 23 | //│ ╙── ^ 24 | //│ Parsed: {1(); 2} 25 | 26 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/FlatMultiArgLams.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | // Extracted frrom JSON.mls 5 | 6 | parseNegative(state).flatMap of (negative, state) => 7 | parseIntegral(state).flatMap of (integral, state) => 8 | parseFraction(state).flatMap of (fraction, state) => 9 | parseExponent(state).flatMap of (exponent, state) => 10 | let value = (integral +. fraction) *. exponent 11 | Success of (if negative then (0 -. value) else value), state 12 | //│ |parseNegative|(|state|)|.flatMap| |#of| |(|negative|,| |state|)| |#=>|↵|parseIntegral|(|state|)|.flatMap| |#of| |(|integral|,| |state|)| |#=>|↵|parseFraction|(|state|)|.flatMap| |#of| |(|fraction|,| |state|)| |#=>|↵|parseExponent|(|state|)|.flatMap| |#of| |(|exponent|,| |state|)| |#=>|↵|#let| |value| |#=| |(|integral| |+.| |fraction|)| |*.| |exponent|↵|Success| |#of| |(|#if| |negative| |#then| |(|0| |-.| |value|)| |#else| |value|)|,| |state| 13 | //│ Parsed: {(parseNegative(state,)).flatMap((negative, state,) => {(parseIntegral(state,)).flatMap((integral, state,) => {(parseFraction(state,)).flatMap((fraction, state,) => {(parseExponent(state,)).flatMap((exponent, state,) => {let value = *.('(' +.(integral, fraction,) ')', exponent,); Success('(' if (negative) then '(' -.(0, value,) ')' else value ')', state,)},)},)},)},)} 14 | //│ 15 | 16 | 17 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/Forall.mls: -------------------------------------------------------------------------------- 1 | 2 | forall 'a: 'a => 'a 3 | //│ |#forall| |'a|#:| |'a| |#=>| |'a| 4 | //│ Parsed: {forall 'a. ('a,) => 'a} 5 | 6 | forall 'a, 'b: ['a, 'b] => ['b, 'a] 7 | //│ |#forall| |'a|,| |'b|#:| |[|'a|,| |'b|]| |#=>| |[|'b|,| |'a|]| 8 | //│ Parsed: {forall 'a, 'b. (['a, 'b,],) => ['b, 'a,]} 9 | 10 | fun f: forall 'a: 'a => 'a 11 | //│ |#fun| |f|#:| |#forall| |'a|#:| |'a| |#=>| |'a| 12 | //│ Parsed: {fun f: forall 'a. 'a -> 'a} 13 | 14 | fun f: forall 'a, 'b: ['a, 'b] => ['b, 'a] 15 | //│ |#fun| |f|#:| |#forall| |'a|,| |'b|#:| |[|'a|,| |'b|]| |#=>| |[|'b|,| |'a|]| 16 | //│ Parsed: {fun f: forall 'a 'b. (['a, 'b]) -> ['b, 'a]} 17 | 18 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/MultilineFun.mls: -------------------------------------------------------------------------------- 1 | :AllowParseErrors 2 | 3 | 4 | fun f( 5 | x 6 | ) = x 7 | //│ |#fun| |f|(|→|x|←|↵|)| |#=| |x| 8 | //│ Parsed: {fun f = (x,) => x} 9 | 10 | fun f(x 11 | ) = x 12 | //│ |#fun| |f|(|x|↵|)| |#=| |x| 13 | //│ Parsed: {fun f = (x,) => x} 14 | 15 | fun f( 16 | x) = x 17 | //│ |#fun| |f|(|→|x|←|)| |#=| |x| 18 | //│ Parsed: {fun f = (x,) => x} 19 | 20 | fun f( 21 | x) = x 22 | //│ |#fun| |f|(|↵|x|)| |#=| |x| 23 | //│ ╔══[PARSE ERROR] Unexpected identifier here 24 | //│ ║ l.21: x) = x 25 | //│ ╙── ^ 26 | //│ Parsed: {fun f = () => x} 27 | 28 | fun f(x, 29 | y) = x + y 30 | //│ |#fun| |f|(|x|,|→|y|←|)| |#=| |x| |+| |y| 31 | //│ Parsed: {fun f = (x, {y},) => +(x,)(y,)} 32 | 33 | fun f( 34 | x, 35 | y) = x + y 36 | //│ |#fun| |f|(|→|x|,|↵|y|←|)| |#=| |x| |+| |y| 37 | //│ Parsed: {fun f = (x, y,) => +(x,)(y,)} 38 | 39 | fun f( 40 | x, 41 | y 42 | ) = x + y 43 | //│ |#fun| |f|(|→|x|,|↵|y|←|↵|)| |#=| |x| |+| |y| 44 | //│ Parsed: {fun f = (x, y,) => +(x,)(y,)} 45 | 46 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/NegativeLits.mls: -------------------------------------------------------------------------------- 1 | :NewParser 2 | :ParseOnly 3 | 4 | type MinusOne = -1 5 | //│ |#type| |MinusOne| |#=| |-|1| 6 | //│ Parsed: {type alias MinusOne: -1 {}} 7 | 8 | fun f(x: MinusOne) = x 9 | //│ |#fun| |f|(|x|#:| |MinusOne|)| |#=| |x| 10 | //│ Parsed: {fun f = (x: MinusOne,) => x} 11 | 12 | f(-1) 13 | //│ |f|(|-|1|)| 14 | //│ Parsed: {f(-1,)} 15 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/SpecParams.mls: -------------------------------------------------------------------------------- 1 | :ParseOnly 2 | 3 | 4 | fun Foo(#x, y) = x + y 5 | //│ |#fun| |Foo|(|##|x|,| |y|)| |#=| |x| |+| |y| 6 | //│ Parsed: {fun Foo = (#x, y,) => +(x,)(y,)} 7 | 8 | fun Foo(x, #y) = x + y 9 | //│ |#fun| |Foo|(|x|,| |##|y|)| |#=| |x| |+| |y| 10 | //│ Parsed: {fun Foo = (x, #y,) => +(x,)(y,)} 11 | 12 | fun Foo(#x, #y, #z) = if z then x + y else z 13 | //│ |#fun| |Foo|(|##|x|,| |##|y|,| |##|z|)| |#=| |#if| |z| |#then| |x| |+| |y| |#else| |z| 14 | //│ Parsed: {fun Foo = (#x, #y, #z,) => if (z) then +(x,)(y,) else z} 15 | 16 | 17 | class Foo(x, #y, z) 18 | //│ |#class| |Foo|(|x|,| |##|y|,| |z|)| 19 | //│ Parsed: {class Foo(x, #y, z,) {}} 20 | 21 | 22 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/Where.mls: -------------------------------------------------------------------------------- 1 | 2 | 1 + 1 where 1 3 | //│ |1| |+| |1| |#where| |1| 4 | //│ Parsed: {+(1,)(1,) where {1}} 5 | 6 | a => a + 1 where foo 7 | //│ |a| |#=>| |a| |+| |1| |#where| |foo| 8 | //│ Parsed: {(a,) => +(a,)(1,) where {foo}} 9 | 10 | a + 1 where let a = 1 11 | //│ |a| |+| |1| |#where| |#let| |a| |#=| |1| 12 | //│ Parsed: {+(a,)(1,) where {let a = 1}} 13 | 14 | fun foo: 'a => 'a => 'a where 'a : int 15 | //│ |#fun| |foo|#:| |'a| |#=>| |'a| |#=>| |'a| |#where| |'a| |#:| |int| 16 | //│ Parsed: {fun foo: 'a -> 'a -> ('a 17 | //│ where 18 | //│ 'a <: int)} 19 | 20 | :pe 21 | fun foo: 'a + 'a + 'a where 'a : int 22 | //│ |#fun| |foo|#:| |'a| |+| |'a| |+| |'a| |#where| |'a| |#:| |int| 23 | //│ ╔══[PARSE ERROR] Not a recognized type 24 | //│ ║ l.21: fun foo: 'a + 'a + 'a where 'a : int 25 | //│ ╙── ^^^^^^^ 26 | //│ Parsed: {fun foo: anything} 27 | 28 | :pe 29 | fun foo: 'a -> 'a -> 'a where 'a : int 30 | //│ |#fun| |foo|#:| |'a| |->| |'a| |->| |'a| |#where| |'a| |#:| |int| 31 | //│ ╔══[PARSE ERROR] Not a recognized type 32 | //│ ║ l.29: fun foo: 'a -> 'a -> 'a where 'a : int 33 | //│ ╙── ^^^^^^^^^^^^^^ 34 | //│ Parsed: {fun foo: anything} 35 | 36 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/Whitespace.mls: -------------------------------------------------------------------------------- 1 | :AllowParseErrors 2 | 3 | 4 | //│ | | 5 | //│ Parsed: {} 6 | 7 | 8 | //│ | | 9 | //│ Parsed: {} 10 | 11 | 12 | 13 | //│ | | 14 | //│ Parsed: {} 15 | 16 | 17 | false(1 , 2 , 3) 18 | //│ |false|(|1| |,| |2| |,| |3|)| 19 | //│ Parsed: {false(1, 2, 3,)} 20 | 21 | false (1 ,2 ,3) 22 | //│ |false| |(|1| |,|2| |,|3|)| 23 | //│ Parsed: {false(1, 2, 3,)} 24 | 25 | false( 1 , 2 , 3 ) 26 | //│ |false|(| |1| |,| |2| |,| |3| |)| 27 | //│ Parsed: {false(1, 2, 3,)} 28 | 29 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/boolops.mls: -------------------------------------------------------------------------------- 1 | 2 | true and false 3 | //│ |true| |and| |false| 4 | //│ Parsed: {and(true,)(false,)} 5 | 6 | a and b or c 7 | //│ |a| |and| |b| |or| |c| 8 | //│ Parsed: {or(and(a,)(b,),)(c,)} 9 | 10 | a or b and c 11 | //│ |a| |or| |b| |and| |c| 12 | //│ Parsed: {or(a,)(and(b,)(c,),)} 13 | 14 | a + 1 or b + 2 and c + 3 15 | //│ |a| |+| |1| |or| |b| |+| |2| |and| |c| |+| |3| 16 | //│ Parsed: {or(+(a,)(1,),)(and(+(b,)(2,),)(+(c,)(3,),),)} 17 | 18 | 19 | any of a, b, c 20 | //│ |any| |#of| |a|,| |b|,| |c| 21 | //│ Parsed: {any(a, b, c,)} 22 | 23 | any of 24 | a 25 | b 26 | c 27 | //│ |any| |#of|→|a|↵|b|↵|c|←| 28 | //│ Parsed: {any({a; b; c},)} 29 | 30 | all of 31 | x 32 | any of 33 | a 34 | b 35 | c 36 | y 37 | //│ |all| |#of|→|x|↵|any| |#of|→|a|↵|b|↵|c|←|↵|y|←| 38 | //│ Parsed: {all({x; any({a; b; c},); y},)} 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /shared/src/test/diff/pretyper/Repro.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :ShowPreTyperErrors 3 | -------------------------------------------------------------------------------- /shared/src/test/diff/pretyper/ucs/NamePattern.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | fun id(x) = x 4 | //│ fun id: forall 'a. 'a -> 'a 5 | 6 | if id(0) is t then t 7 | //│ 0 8 | //│ res 9 | //│ = 0 10 | -------------------------------------------------------------------------------- /shared/src/test/diff/pretyper/ucs/RecordPattern.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | :e 4 | :w 5 | fun take_1(p) = 6 | if p is 7 | { x, y } then x + y 8 | else 0 9 | //│ ╔══[ERROR] unknown pattern '{' {x: x, y: y} '}' 10 | //│ ║ l.7: { x, y } then x + y 11 | //│ ╙── ^^^^^^^^ 12 | //│ ╔══[WARNING] this case is unreachable 13 | //│ ║ l.8: else 0 14 | //│ ║ ^ 15 | //│ ╟── because it is subsumed by the branch 16 | //│ ║ l.7: { x, y } then x + y 17 | //│ ╙── ^^^^^ 18 | //│ ╔══[ERROR] identifier not found: x 19 | //│ ║ l.7: { x, y } then x + y 20 | //│ ╙── ^ 21 | //│ ╔══[ERROR] identifier not found: y 22 | //│ ║ l.7: { x, y } then x + y 23 | //│ ╙── ^ 24 | //│ fun take_1: anything -> Int 25 | //│ Code generation encountered an error: 26 | //│ unresolved symbol x 27 | -------------------------------------------------------------------------------- /shared/src/test/diff/pretyper/ucs/Symbol.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | type List[A] = Cons[A] | Nil 4 | class Cons[A](head: A, tail: List[A]) 5 | module Nil 6 | //│ type List[A] = Cons[A] | Nil 7 | //│ class Cons[A](head: A, tail: List[A]) 8 | //│ module Nil 9 | 10 | fun (::) cons(head, tail) = Cons(head, tail) 11 | //│ fun (::) cons: forall 'A. ('A, List['A]) -> Cons['A] 12 | 13 | fun map(f, xs) = if xs is 14 | Cons(head, tail) then f(head) :: map(f, tail) 15 | Nil then Nil 16 | //│ fun map: forall 'A 'A0. ('A -> 'A0, Cons['A] | Nil) -> (Cons['A0] | Nil) 17 | 18 | // fun main$$5 = () => 19 | // let obj = 20 | // let obj = '(' (new List$1)(1, (new List$1)(2, (new Nil$2)(),),) ')' in 21 | // if obj is ‹(List$1) then map$List$1(obj, {Lambda1$2$3()},); else error› 22 | // in 23 | // if obj is ‹(List$1) then map$List$1(obj, {Lambda1$3$4()},); else error› 24 | // Got: Internal Error: Symbol already set for obj 25 | fun main(f) = 26 | let obj = (let obj = Cons(1, Cons(2, Nil)) in (if obj is Cons(head, tail) then f(head) :: tail else Nil)) in 27 | if obj is Cons(head, tail) then f(head) :: tail else Nil 28 | //│ fun main: forall 'A 'A0. ((1 | 2 | 'A) -> 'A) -> (Cons['A0] | Nil) 29 | //│ where 30 | //│ 'A <: 'A0 31 | //│ 'A0 :> 1 | 2 32 | //│ <: 'A 33 | -------------------------------------------------------------------------------- /shared/src/test/diff/pretyper/ucs/Unapply.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class Point(x: Int, y: Int, z: Int) 4 | //│ class Point(x: Int, y: Int, z: Int) 5 | 6 | fun f_0(p) = if p is Point(x, _, z) then x + z 7 | //│ fun f_0: Point -> Int 8 | 9 | f_0(Point(1, 2, 3)) 10 | //│ Int 11 | //│ res 12 | //│ = 4 13 | -------------------------------------------------------------------------------- /shared/src/test/diff/pretyper/ucs/Unconditional.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class Point(x: Int, y: Int) 4 | class Rectangle(x: Int, y: Int, width: Int, height: Int) 5 | //│ class Point(x: Int, y: Int) 6 | //│ class Rectangle(x: Int, y: Int, width: Int, height: Int) 7 | 8 | fun sum(p) = if p is Point(x, y) then x + y 9 | //│ fun sum: Point -> Int 10 | 11 | sum(Point(1, 2)) 12 | //│ Int 13 | //│ res 14 | //│ = 3 15 | 16 | fun abs(x) = if x < 0 then -x else x 17 | //│ fun abs: Int -> Int 18 | 19 | fun dist(p, q) = if p is Point(x1, y1) and q is Point(x2, y2) then 20 | abs(x1 - x2) + abs(y1 - y2) 21 | //│ fun dist: (Point, Point) -> Int 22 | 23 | dist(Point(1, 2), Point(3, 4)) 24 | //│ Int 25 | //│ res 26 | //│ = 4 27 | -------------------------------------------------------------------------------- /shared/src/test/diff/pretyper/ucs/coverage/Tautology.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class Some[T](value: T) 4 | module None 5 | type Option[T] = Some[T] | None 6 | class Pair[A, B](x: A, y: B) 7 | //│ class Some[T](value: T) 8 | //│ module None 9 | //│ type Option[T] = None | Some[T] 10 | //│ class Pair[A, B](x: A, y: B) 11 | 12 | fun useless_negate_1(x) = 13 | if 14 | x is Some(y) and x is Some(z) then y + z 15 | //│ fun useless_negate_1: Some[Int] -> Int 16 | 17 | useless_negate_1(Some(1)) 18 | //│ Int 19 | //│ res 20 | //│ = 2 21 | -------------------------------------------------------------------------------- /shared/src/test/diff/pretyper/ucs/examples/List.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | // TODO 4 | abstract class List[out A]: (Cons[A] | Nil) { 5 | fun isEmpty: Bool 6 | fun map[B]: (A -> B) -> List[B] 7 | } 8 | class Cons[out A](head: A, tail: List[A]) extends List[A] { 9 | fun isEmpty: Bool = false 10 | fun map(f) = Cons(f(head), tail.map(f)) 11 | } 12 | module Nil extends List { 13 | fun isEmpty: Bool = true 14 | fun map(f) = Nil 15 | } 16 | //│ ╔══[ERROR] Indirectly-recursive member should have a type signature 17 | //│ ║ l.10: fun map(f) = Cons(f(head), tail.map(f)) 18 | //│ ╙── ^^^^ 19 | //│ abstract class List[A]: Cons[A] | Nil { 20 | //│ fun isEmpty: Bool 21 | //│ fun map: forall 'B. (A -> 'B) -> List['B] 22 | //│ } 23 | //│ class Cons[A](head: A, tail: List[A]) extends List { 24 | //│ fun isEmpty: Bool 25 | //│ fun map: forall 'A. (A -> 'A) -> Cons['A] 26 | //│ } 27 | //│ module Nil extends List { 28 | //│ fun isEmpty: Bool 29 | //│ fun map: anything -> Nil 30 | //│ } 31 | -------------------------------------------------------------------------------- /shared/src/test/diff/pretyper/ucs/examples/SimpleList.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | abstract class List[T]: (Cons[T] | Nil) 4 | class Cons[T](val head: T, val tail: List[T]) extends List[T] 5 | module Nil extends List 6 | //│ abstract class List[T]: Cons[T] | Nil 7 | //│ class Cons[T](head: T, tail: List[T]) extends List 8 | //│ module Nil extends List 9 | 10 | fun (::) cons(head, tail) = Cons(head, tail) 11 | //│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T] 12 | 13 | 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: Nil 14 | //│ Cons['T] 15 | //│ where 16 | //│ 'T :> 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 17 | //│ res 18 | //│ = Cons {} 19 | -------------------------------------------------------------------------------- /shared/src/test/diff/pretyper/ucs/examples/SimpleTree.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | // abstract class Tree[out A]: (Empty | Node[A]) 4 | // class Node[out A](value: A, left: Tree[A], right: Tree[A]) extends Tree[A] 5 | // module Empty extends Tree 6 | // //│ abstract class Tree[A]: Empty | Node[A] 7 | // //│ class Node[A](value: A, left: Tree[A], right: Tree[A]) extends Tree 8 | // //│ module Empty extends Tree 9 | 10 | // fun insert(t, v) = if t is 11 | // Node(v', l, r) and 12 | // v < v' then Node(v', insert(l, v), r) 13 | // v > v' then Node(v', l, insert(r, v)) 14 | // _ then t 15 | // Empty then Node(v, Empty, Empty) 16 | // //│ fun insert: forall 'A. (Empty | Node[Num & 'A], Num & 'A) -> (Node[nothing] | Node['A]) 17 | 18 | abstract class List[out T]: (Cons[T] | Nil) 19 | class Cons[out T](val head: T, val tail: List[T]) extends List[T] 20 | module Nil extends List 21 | //│ abstract class List[T]: Cons[T] | Nil 22 | //│ class Cons[T](head: T, tail: List[T]) extends List 23 | //│ module Nil extends List 24 | 25 | fun (::) cons(head, tail) = Cons(head, tail) 26 | //│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T] 27 | 28 | 1 :: 2 :: 3 :: 4 :: Nil 29 | //│ Cons[1 | 2 | 3 | 4] 30 | //│ res 31 | //│ = Cons {} 32 | -------------------------------------------------------------------------------- /shared/src/test/diff/qq/BadConst.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | 5 | :e 6 | // :ge 7 | code"x => y => 100 + ${Const(x + y)}" 8 | //│ ╔══[ERROR] Type mismatch in operator application: 9 | //│ ║ l.7: code"x => y => 100 + ${Const(x + y)}" 10 | //│ ║ ^^^^^ 11 | //│ ╟── reference of type `Var[?a, ?x]` is not an instance of type `Int` 12 | //│ ║ l.7: code"x => y => 100 + ${Const(x + y)}" 13 | //│ ╙── ^ 14 | //│ Code[anything -> anything -> Int, nothing] 15 | 16 | :e 17 | code"x => y => 100 + code"${Const(x + y)}"" 18 | //│ ╔══[ERROR] Nested quotation is not allowed. 19 | //│ ║ l.17: code"x => y => 100 + code"${Const(x + y)}"" 20 | //│ ╙── ^^^^^^^^^^^^^^^^^^^^^ 21 | //│ Code[anything -> anything -> Int, nothing] 22 | 23 | :e 24 | let res = code"x => code"${x}"" 25 | //│ ╔══[ERROR] Nested quotation is not allowed. 26 | //│ ║ l.24: let res = code"x => code"${x}"" 27 | //│ ╙── ^^^^^^^^^^ 28 | //│ let res: Code[anything -> error, nothing] 29 | -------------------------------------------------------------------------------- /shared/src/test/diff/qq/Multiline.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | 5 | code"let arr = [ 6 | 1 7 | ] in arr" 8 | //│ Code[[1], nothing] 9 | 10 | let res = code"let foo = (x, y) => x * y 11 | foo( 12 | 2, 13 | 3 14 | )" 15 | run(res) 16 | //│ let res: Code[Int, nothing] 17 | //│ Int 18 | 19 | 20 | let res = code"let a = 0 21 | let b = 1 22 | if a == 0 23 | then true 24 | else false 25 | " 26 | run(res) 27 | //│ let res: Code[Bool, nothing] 28 | //│ Bool 29 | 30 | let res = code"if 1 == 0 31 | then false 32 | else true 33 | " 34 | run(res) 35 | //│ let res: Code[Bool, nothing] 36 | //│ Bool 37 | 38 | let res = code"if 1 == 0 39 | then false 40 | else true 41 | " 42 | run(res) 43 | //│ let res: Code[Bool, nothing] 44 | //│ Bool 45 | 46 | let res = code"{ 47 | x: 1, 48 | y: 2, 49 | z: 3, 50 | } 51 | " 52 | run(res) 53 | //│ let res: Code[{x: 1, y: 2, z: 3}, nothing] 54 | //│ {x: 1, y: 2, z: 3} 55 | 56 | 57 | let res = code"let x = {a: 100} 58 | x 59 | .a 60 | " 61 | run(res) 62 | //│ let res: Code[100, nothing] 63 | //│ 100 64 | -------------------------------------------------------------------------------- /shared/src/test/diff/qq/WillfulExtrusion.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | 5 | fun foo(dbg) = 6 | code"x => ${let c = code"x + 1" in dbg(c), c}" 7 | //│ fun foo: (Code[Int, ??x] -> anything) -> Code[Int -> Int, nothing] 8 | 9 | foo(log) 10 | //│ Code[Int -> Int, nothing] 11 | 12 | 13 | fun (>>) compose(f, g) = x => g(f(x)) 14 | fun show: Code[anything, anything] -> Str 15 | //│ fun (>>) compose: forall 'a 'b 'c. ('a -> 'b, 'b -> 'c) -> 'a -> 'c 16 | //│ fun show: Code[anything, anything] -> Str 17 | 18 | foo(show >> log) 19 | //│ Code[Int -> Int, nothing] 20 | 21 | 22 | -------------------------------------------------------------------------------- /shared/src/test/diff/tricky/IrregularSubtypes.mls: -------------------------------------------------------------------------------- 1 | :IrregularTypes 2 | 3 | 4 | type Foo[A] = A -> Foo[Foo[A]] 5 | //│ Defined type alias Foo[=A] 6 | 7 | type Bar[A] = A -> Bar[Bar[A]] 8 | //│ Defined type alias Bar[=A] 9 | 10 | 11 | :e 12 | error: Foo[int]: Bar[int] 13 | //│ ╔══[ERROR] Subtyping constraint of the form `Foo[int] <: Bar[int]` exceeded recursion depth limit (250) 14 | //│ ║ l.12: error: Foo[int]: Bar[int] 15 | //│ ║ ^^^^^ 16 | //│ ╙── Note: use flag `:ex` to see internal error info. 17 | //│ res: Bar[int] 18 | //│ Runtime error: 19 | //│ Error: an error was thrown 20 | 21 | 22 | // * Interestingly, this is caught by the cycle checker when rectypes are disabled: 23 | :NoRecursiveTypes 24 | 25 | :e 26 | error: Foo[int]: Bar[int] 27 | //│ ╔══[ERROR] Cyclic-looking constraint while typing type ascription; a type annotation may be required 28 | //│ ║ l.26: error: Foo[int]: Bar[int] 29 | //│ ║ ^^^^^ 30 | //│ ╙── Note: use flag `:ex` to see internal error info. 31 | //│ res: Bar[int] 32 | //│ Runtime error: 33 | //│ Error: an error was thrown 34 | 35 | 36 | -------------------------------------------------------------------------------- /shared/src/test/diff/tricky/IrregularSubtypes2.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | :IrregularTypes 3 | 4 | 5 | type Lol = forall 'a. int -> ('a, Lol) 6 | //│ Defined type alias Lol 7 | 8 | def lol: Lol 9 | //│ lol: Lol 10 | //│ = 11 | 12 | :w 13 | type Oops[A] = int -> (anything, Oops[Oops[A]]) 14 | //│ Defined type alias Oops[±A] 15 | //│ ╔══[WARNING] Type definition Oops has bivariant type parameters: 16 | //│ ║ l.13: type Oops[A] = int -> (anything, Oops[Oops[A]]) 17 | //│ ║ ^^^^ 18 | //│ ╟── A is irrelevant and may be removed 19 | //│ ║ l.13: type Oops[A] = int -> (anything, Oops[Oops[A]]) 20 | //│ ╙── ^ 21 | 22 | // * The cycle is due to irregular types, which are not yet shadowed 23 | :e 24 | lol: Oops[int] 25 | //│ ╔══[ERROR] Subtyping constraint of the form `Lol <: Oops[?]` exceeded recursion depth limit (250) 26 | //│ ║ l.24: lol: Oops[int] 27 | //│ ║ ^^^ 28 | //│ ╙── Note: use flag `:ex` to see internal error info. 29 | //│ res: Oops[?] 30 | //│ = 31 | //│ lol is not implemented 32 | 33 | 34 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/ErrorMessage.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class Point(x: Int, y: Int) 4 | //│ class Point(x: Int, y: Int) 5 | 6 | :e 7 | fun f(p) = 8 | if p is 9 | Point(x, y, z) then x + y + z 10 | //│ ╔══[ERROR] Type mismatch in field selection: 11 | //│ ╟── tuple literal of type `{0: ?#x, 1: ?#y}` does not have field '2' 12 | //│ ║ l.3: class Point(x: Int, y: Int) 13 | //│ ║ ^^^^^^^^^ 14 | //│ ╟── but it flows into operator application with expected type `{2: ?a}` 15 | //│ ║ l.8: if p is 16 | //│ ║ ^^^^ 17 | //│ ║ l.9: Point(x, y, z) then x + y + z 18 | //│ ╙── ^^^^^^^^^ 19 | //│ fun f: Point -> Int 20 | 21 | :e 22 | :ge 23 | fun g(xs) = 24 | if xs is 25 | head :: _ then head 26 | //│ ╔══[ERROR] type identifier `::` not found 27 | //│ ║ l.25: head :: _ then head 28 | //│ ╙── ^^ 29 | //│ ╔══[ERROR] type identifier not found: :: 30 | //│ ║ l.25: head :: _ then head 31 | //│ ╙── ^^ 32 | //│ fun g: nothing -> error 33 | //│ Code generation encountered an error: 34 | //│ unresolved symbol :: 35 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/Hygiene.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class Some[out T](value: T) 4 | class Left[out T](value: T) 5 | class Right[out T](value: T) 6 | //│ class Some[T](value: T) 7 | //│ class Left[T](value: T) 8 | //│ class Right[T](value: T) 9 | 10 | :ducs:postprocess.result 11 | fun foo(x) = if x is 12 | Some(Left(y)) then x 13 | Some(x) then x 14 | //│ Post-processed UCS term: 15 | //│ case x*‡ of 16 | //│ Some*◊ -> 17 | //│ let ucs$args_x$Some*† = (Some).unapply(x,) 18 | //│ let x$Some_0*‡ = (ucs$args_x$Some).0 19 | //│ case x$Some_0*‡ of 20 | //│ Left*◊ -> 21 | //│ let ucs$args_x$Some_0$Left*† = (Left).unapply(x$Some_0,) 22 | //│ let y*‡ = (ucs$args_x$Some_0$Left).0 23 | //│ x 24 | //│ _ -> 25 | //│ let x*‡ = (ucs$args_x$Some).0 26 | //│ x 27 | //│ fun foo: forall 'T. Some[(Left[anything] | Object & ~#Left) & 'T] -> (Some['T] | 'T) 28 | 29 | foo(Some(Left(1))) 30 | //│ Left[1] | Some[Left[1]] 31 | //│ res 32 | //│ = Some {} 33 | 34 | foo(Some(2)) 35 | //│ 2 | Some[2] 36 | //│ res 37 | //│ = 2 38 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/LeadingAnd.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | 5 | class Some[T](value: T) 6 | //│ class Some[T](value: T) 7 | 8 | 9 | 10 | fun f(a, b) = if a is 11 | Some(av) 12 | and b is Some(bv) then av + bv 13 | //│ fun f: (Some[Int], Some[Int]) -> Int 14 | 15 | fun f(a, b) = if a is Some(av) 16 | and b is Some(bv) 17 | then av + bv 18 | //│ fun f: (Some[Int], Some[Int]) -> Int 19 | 20 | fun f(a, b) = if a is 21 | Some(av) 22 | and b is Some(bv) 23 | then av + bv 24 | //│ fun f: (Some[Int], Some[Int]) -> Int 25 | 26 | 27 | 28 | // FIXME (parser) 29 | fun f(a, b) = if a is 30 | Some(av) 31 | and b is Some(bv) then av + bv 32 | 33 | //│ fun f: (Some[Int], Some[Int]) -> Int 34 | 35 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/MultiwayIf.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | fun f(x) = 5 | if 6 | x > 0 then 0 7 | x == 0 then 1 8 | _ then 2 9 | //│ fun f: Num -> (0 | 1 | 2) 10 | 11 | 12 | fun f(x) = 13 | if 14 | x > 0 and 15 | x % 2 === 0 then true 16 | _ then false 17 | x == 0 then true 18 | _ then false 19 | //│ fun f: Int -> Bool 20 | 21 | f(0) 22 | f(2) 23 | f(3) 24 | f(0 - 1) 25 | f(0 - 2) 26 | //│ Bool 27 | //│ res 28 | //│ = true 29 | //│ res 30 | //│ = true 31 | //│ res 32 | //│ = false 33 | //│ res 34 | //│ = false 35 | //│ res 36 | //│ = false 37 | 38 | fun f(x) = 39 | if 40 | x > 0 and 41 | x % 2 === 0 then true 42 | else false 43 | x == 0 then true 44 | else false 45 | //│ fun f: Int -> Bool 46 | 47 | f(0) 48 | f(2) 49 | f(1) 50 | f(0 - 1) 51 | //│ Bool 52 | //│ res 53 | //│ = true 54 | //│ res 55 | //│ = true 56 | //│ res 57 | //│ = false 58 | //│ res 59 | //│ = false 60 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/NestedOpSplits.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | // * Note that this always to the left 5 | :e 6 | fun f(x) = 7 | if x == 8 | 1 + 9 | 2 then 0 10 | _ then 1 11 | //│ ╔══[ERROR] Type mismatch in application: 12 | //│ ║ l.8: 1 + 13 | //│ ║ ^ 14 | //│ ║ l.9: 2 then 0 15 | //│ ║ ^^^^^^^ 16 | //│ ╟── operator application of type `Bool` is not an instance of type `Int` 17 | //│ ║ l.7: if x == 18 | //│ ║ ^^^^ 19 | //│ ║ l.8: 1 + 20 | //│ ╙── ^^^^^^ 21 | //│ ╔══[ERROR] Type mismatch in type ascription: 22 | //│ ║ l.8: 1 + 23 | //│ ║ ^ 24 | //│ ║ l.9: 2 then 0 25 | //│ ║ ^^^^^^^ 26 | //│ ╙── application of type `Int` is not an instance of type `Bool` 27 | //│ fun f: Num -> (0 | 1) 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/Or.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Some[T](value: T) 5 | //│ class Some[T](value: T) 6 | 7 | 8 | // TODO support `or` in UCS 9 | fun f(a, b) = if a is 10 | Some(v) 11 | and b is Some(v') then v + v' 12 | or b is Some(v) then v 13 | else 0 14 | //│ ╔══[ERROR] cannot transform due to an illegal split operator or 15 | //│ ║ l.12: or b is Some(v) then v 16 | //│ ║ ^^ 17 | //│ ╟── the following branch will be discarded 18 | //│ ║ l.12: or b is Some(v) then v 19 | //│ ╙── ^^^^^^^^^^^^^^^^^^^^ 20 | //│ fun f: (Object & ~#Some | Some[Int], Object & ~#Some | Some[Int]) -> Int 21 | 22 | 23 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/ParseFailures.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | type Tree[A] = Node[A] | Empty 5 | module Empty 6 | class Node[A](value: Int, left: Tree[A], right: Tree[A]) 7 | //│ type Tree[A] = Empty | Node[A] 8 | //│ module Empty 9 | //│ class Node[A](value: Int, left: Tree[A], right: Tree[A]) 10 | 11 | fun contains(node, wanted) = 12 | if node is 13 | Node(value, left, right) and wanted 14 | <= value then contains(left, wanted) 15 | >= value then contains(right, wanted) 16 | else true 17 | Empty then false 18 | //│ fun contains: forall 'A. (Empty | Node['A], Num) -> Bool 19 | 20 | fun contains'(node, wanted) = 21 | if node is 22 | Node(value, left, right) and wanted 23 | <= value then contains'(left, wanted) 24 | >= value then contains'(right, wanted) 25 | _ then true 26 | Empty then false 27 | //│ fun contains': forall 'A. (Empty | Node['A], Num) -> Bool 28 | 29 | :pe 30 | class Z() 31 | class O() 32 | fun foo(x, y) = if x is 33 | Z() and y is O() then 0 else 1 34 | //│ ╔══[PARSE ERROR] Unexpected 'else' keyword here 35 | //│ ║ l.33: Z() and y is O() then 0 else 1 36 | //│ ╙── ^^^^ 37 | //│ class Z() 38 | //│ class O() 39 | //│ fun foo: (Z, O) -> 0 40 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/ParserFailures.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | // FIXME: Interleaved let bindings are not implemented in `IfOpsApp`. 5 | if x 6 | == 0 then "bad" 7 | let y = f(z) 8 | == y * y then 0 9 | //│ ╔══[PARSE ERROR] expect an operator 10 | //│ ║ l.7: let y = f(z) 11 | //│ ╙── ^^^ 12 | //│ ╔══[PARSE ERROR] Unexpected 'let' keyword here 13 | //│ ║ l.7: let y = f(z) 14 | //│ ╙── ^^^ 15 | //│ ╔══[ERROR] missing else branch 16 | //│ ║ l.6: == 0 then "bad" 17 | //│ ╙── ^^^^^ 18 | //│ ╔══[ERROR] identifier not found: x 19 | //│ ║ l.5: if x 20 | //│ ╙── ^ 21 | //│ ╔══[ERROR] Type mismatch in `case` expression: 22 | //│ ║ l.6: == 0 then "bad" 23 | //│ ║ ^^^^^ 24 | //│ ╙── expression of type `Bool` is not an instance of type `true` 25 | //│ "bad" 26 | 27 | // FIXME: Interleaved let bindings are not implemented in `IfOpsApp`. 28 | fun tt(x) = 29 | if x 30 | is A() then "A" 31 | let y = 0 32 | is B() then "B" 33 | //│ ╔══[PARSE ERROR] expect an operator 34 | //│ ║ l.31: let y = 0 35 | //│ ╙── ^^^ 36 | //│ ╔══[PARSE ERROR] Unexpected 'let' keyword here 37 | //│ ║ l.31: let y = 0 38 | //│ ╙── ^^^ 39 | //│ ╔══[ERROR] type identifier `A` not found 40 | //│ ║ l.30: is A() then "A" 41 | //│ ╙── ^ 42 | //│ ╔══[ERROR] type identifier not found: A 43 | //│ ║ l.30: is A() then "A" 44 | //│ ╙── ^ 45 | //│ fun tt: nothing -> error 46 | 47 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/SplitScrutinee.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | fun f(x) = 4 | if x + 5 | 1 is 6 | 2 then 1 7 | 3 then 2 8 | _ then "I don't know." 9 | //│ fun f: Int -> ("I don't know." | 1 | 2) 10 | 11 | [f(0), f(1), f(2), f(3)] 12 | //│ ["I don't know." | 1 | 2, "I don't know." | 1 | 2, "I don't know." | 1 | 2, "I don't know." | 1 | 2] 13 | //│ res 14 | //│ = [ "I don't know.", 1, 2, "I don't know." ] 15 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/ThenIndent.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | // FIXME 5 | x => if x == 6 | 0 7 | then "a" 8 | _ then "b" 9 | //│ ╔══[PARSE ERROR] Unexpected indented block here 10 | //│ ║ l.7: then "a" 11 | //│ ║ ^^^^^^^^^^^^ 12 | //│ ║ l.8: _ then "b" 13 | //│ ╙── ^^ 14 | //│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application instead 15 | //│ ║ l.5: x => if x == 16 | //│ ║ ^^^^ 17 | //│ ║ l.6: 0 18 | //│ ║ ^^^ 19 | //│ ╟── Note: 'if' expression starts here: 20 | //│ ║ l.5: x => if x == 21 | //│ ╙── ^^ 22 | //│ ╔══[ERROR] missing else branch 23 | //│ ║ l.6: 0 24 | //│ ╙── ^ 25 | //│ ╔══[ERROR] Type mismatch in `case` expression: 26 | //│ ║ l.6: 0 27 | //│ ║ ^ 28 | //│ ╙── expression of type `Bool` is not an instance of type `true` 29 | //│ Num -> () 30 | //│ res 31 | //│ = [Function: res] 32 | 33 | 34 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/Tree.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | type Option[out A] = Some[A] | None 4 | class Some[out A](value: A) 5 | module None 6 | //│ type Option[A] = None | Some[A] 7 | //│ class Some[A](value: A) 8 | //│ module None 9 | 10 | type Tree[out A] = Node[A] | Empty 11 | module Empty 12 | class Node[out A](value: A, left: Tree[A], right: Tree[A]) 13 | //│ type Tree[A] = Empty | Node[A] 14 | //│ module Empty 15 | //│ class Node[A](value: A, left: Tree[A], right: Tree[A]) 16 | 17 | fun find(t, v) = if t is 18 | Node(v', l, r) and 19 | v < v' then find(l, v) 20 | v > v' then find(r, v) 21 | _ then Some(v) 22 | Empty then None 23 | //│ fun find: forall 'A. (Empty | Node[Num], Num & 'A) -> (None | Some['A]) 24 | 25 | fun insert(t, v) = if t is 26 | Node(v', l, r) and 27 | v < v' then Node(v', insert(l, v), r) 28 | v > v' then Node(v', l, insert(r, v)) 29 | _ then t 30 | Empty then Node(v, Empty, Empty) 31 | //│ fun insert: forall 'A. (Empty | Node[Num & 'A], Num & 'A) -> (Node[nothing] | Node['A]) 32 | 33 | find(Empty, 0) 34 | find(Node(0, Empty, Empty), 0) 35 | find(Node(1, Empty, Empty), 0) 36 | //│ None | Some[0] 37 | //│ res 38 | //│ = None { class: [class None] } 39 | //│ res 40 | //│ = Some {} 41 | //│ res 42 | //│ = None { class: [class None] } 43 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/WeirdSplit.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class A() 4 | class B() 5 | //│ class A() 6 | //│ class B() 7 | 8 | fun f(x) = 9 | if x 10 | is 11 | A then 0 12 | B then 1 13 | //│ fun f: (A | B) -> (0 | 1) 14 | 15 | // Precedence problem: should we restruct terms when push them to the stack? 16 | :e 17 | fun f(x) = 18 | if x == 19 | 1 20 | + 2 then 0 21 | + _ then 1 22 | //│ ╔══[ERROR] Type mismatch in application: 23 | //│ ║ l.20: + 2 then 0 24 | //│ ║ ^^^ 25 | //│ ╟── operator application of type `Bool` is not an instance of type `Int` 26 | //│ ║ l.18: if x == 27 | //│ ║ ^^^^ 28 | //│ ║ l.19: 1 29 | //│ ╙── ^^^^^^ 30 | //│ ╔══[ERROR] Type mismatch in type ascription: 31 | //│ ║ l.20: + 2 then 0 32 | //│ ║ ^^^ 33 | //│ ╙── application of type `Int` is not an instance of type `Bool` 34 | //│ fun f: Num -> (0 | 1) 35 | 36 | fun f(x, s, t) = 37 | if x 38 | is A() 39 | and t then 0 40 | and s then 0 41 | is _ then 1 42 | //│ fun f: (Object, Bool, Bool) -> (0 | 1) 43 | -------------------------------------------------------------------------------- /shared/src/test/scala/mlscript/NodeTest.scala: -------------------------------------------------------------------------------- 1 | package mlscript 2 | 3 | class NodeTests extends org.scalatest.funsuite.AnyFunSuite { 4 | 5 | test("node version") { 6 | 7 | val v = os.proc("node", "-v").call().out.lines().head 8 | 9 | println(s"Detected node version: " + v) 10 | 11 | assert( 12 | v.startsWith("v16.14") 13 | || v.startsWith("v16.15") 14 | || v.startsWith("v16.16") 15 | || v.startsWith("v16.17") 16 | || v.startsWith("v17") 17 | || v.startsWith("v18") 18 | || v.startsWith("v19") 19 | || v.startsWith("v20") 20 | || v.startsWith("v21") 21 | || v.startsWith("v22") 22 | ) 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /ts/dummy.ts: -------------------------------------------------------------------------------- 1 | // This is just to work around vscode being overly needy (it reports errors in 'tsconfig.json' otherwise). 2 | -------------------------------------------------------------------------------- /ts2mls/js/src/main/scala/ts2mls/TSProgram.scala: -------------------------------------------------------------------------------- 1 | package ts2mls 2 | 3 | import scala.scalajs.js 4 | import js.DynamicImplicits._ 5 | import ts2mls.types._ 6 | 7 | class TSProgram(filenames: Seq[String]) { 8 | private val program = TypeScript.createProgram(filenames) 9 | 10 | // check if files exist 11 | filenames.foreach((fn) => if (!program.fileExists(fn)) throw new Exception(s"file ${fn} doesn't exist.")) 12 | 13 | val globalNamespace = TSNamespace() 14 | 15 | implicit val checker: TSTypeChecker = TSTypeChecker(program.getTypeChecker()) 16 | filenames.foreach(filename => TSSourceFile(program.getSourceFile(filename), globalNamespace)) 17 | 18 | def generate(writer: JSWriter): Unit = globalNamespace.generate(writer, "") 19 | } 20 | 21 | object TSProgram { 22 | def apply(filenames: Seq[String]) = new TSProgram(filenames) 23 | } 24 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/Dec.d.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :ParseOnly 3 | fun getName(id: (string) | (number)): string 4 | fun render(callback: (unit => unit) | (undefined)): string 5 | trait Get() { 6 | fun __call(id: string): string 7 | } 8 | class Person(name: string, age: number) { 9 | fun getName(id: number): string 10 | } 11 | module OOO { 12 | } 13 | //│ |#fun| |getName|(|id|#:| |(|string|)| ||| |(|number|)|)|#:| |string|↵|#fun| |render|(|callback|#:| |(|unit| |#=>| |unit|)| ||| |(|#undefined|)|)|#:| |string|↵|#trait| |Get|(||)| |{|→|#fun| |__call|(|id|#:| |string|)|#:| |string|←|↵|}|↵|#class| |Person|(|name|#:| |string|,| |age|#:| |number|)| |{|→|#fun| |getName|(|id|#:| |number|)|#:| |string|←|↵|}|↵|#module| |OOO| |{|↵|}| 14 | //│ Parsed: {fun getName: (id: string | number) -> string; fun render: (callback: unit -> unit | ()) -> string; trait Get() {fun __call: (id: string) -> string}; class Person(name: string, age: number,) {fun getName: (id: number) -> string}; module OOO {}} 15 | //│ 16 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/Enum.d.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :ParseOnly 3 | fun pass(c: int): (false) | (true) 4 | fun stop(): int 5 | fun g(x: int): int 6 | //│ |#fun| |pass|(|c|#:| |int|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|x|#:| |int|)|#:| |int| 7 | //│ Parsed: {fun pass: (c: int) -> bool; fun stop: () -> int; fun g: (x: int) -> int} 8 | //│ 9 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/HighOrderFunc.d.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :ParseOnly 3 | fun h1(inc: (number) => number, num: number): number 4 | fun h2(hint: string): unit => string 5 | fun h3(f: (number) => number, g: (number) => number): (number) => number 6 | //│ |#fun| |h1|(|inc|#:| |(|number|)| |#=>| |number|,| |num|#:| |number|)|#:| |number|↵|#fun| |h2|(|hint|#:| |string|)|#:| |unit| |#=>| |string|↵|#fun| |h3|(|f|#:| |(|number|)| |#=>| |number|,| |g|#:| |(|number|)| |#=>| |number|)|#:| |(|number|)| |#=>| |number| 7 | //│ Parsed: {fun h1: (inc: number -> number, num: number) -> number; fun h2: (hint: string) -> unit -> string; fun h3: (f: number -> number, g: number -> number) -> number -> number} 8 | //│ 9 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/Literal.d.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :ParseOnly 3 | let a: {a: "A",b: "B",} 4 | let num: {y: 114,} 5 | fun foo(x: {xx: "X",}): {yy: "Y",} 6 | //│ |#let| |a|#:| |{|a|#:| |"A"|,|b|#:| |"B"|,|}|↵|#let| |num|#:| |{|y|#:| |114|,|}|↵|#fun| |foo|(|x|#:| |{|xx|#:| |"X"|,|}|)|#:| |{|yy|#:| |"Y"|,|}| 7 | //│ Parsed: {let a: {a: "A", b: "B"}; let num: {y: 114}; fun foo: (x: {xx: "X"}) -> {yy: "Y"}} 8 | //│ 9 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/MultiFiles.d.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :ParseOnly 3 | fun multi1(x: number): number 4 | fun multi3(): unit 5 | class Foo(): Base {} 6 | trait AnotherBase() { 7 | let y: string 8 | } 9 | module N { 10 | fun f(): unit 11 | fun g(): unit 12 | fun h(): unit 13 | } 14 | fun multi2(x: string): string 15 | fun multi4(): unit 16 | trait Base() { 17 | let a: number 18 | } 19 | class AnotherFoo(): AnotherBase {} 20 | fun multi5(): unit 21 | //│ |#fun| |multi1|(|x|#:| |number|)|#:| |number|↵|#fun| |multi3|(||)|#:| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase|(||)| |{|→|#let| |y|#:| |string|←|↵|}|↵|#module| |N| |{|→|#fun| |f|(||)|#:| |unit|↵|#fun| |g|(||)|#:| |unit|↵|#fun| |h|(||)|#:| |unit|←|↵|}|↵|#fun| |multi2|(|x|#:| |string|)|#:| |string|↵|#fun| |multi4|(||)|#:| |unit|↵|#trait| |Base|(||)| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|(||)|#:| |unit| 22 | //│ Parsed: {fun multi1: (x: number) -> number; fun multi3: () -> unit; class Foo(): Base {}; trait AnotherBase() {let y: string}; module N {fun f: () -> unit; fun g: () -> unit; fun h: () -> unit}; fun multi2: (x: string) -> string; fun multi4: () -> unit; trait Base() {let a: number}; class AnotherFoo(): AnotherBase {}; fun multi5: () -> unit} 23 | //│ 24 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/Variables.d.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :ParseOnly 3 | let URI: string 4 | let URI2: string 5 | let foo: number 6 | let bar: false 7 | class FooBar() {} 8 | let fb: FooBar 9 | module ABC { 10 | class DEF() {} 11 | } 12 | let d: ABC.DEF 13 | module DD { 14 | let foo: number 15 | let bar: number 16 | } 17 | //│ |#let| |URI|#:| |string|↵|#let| |URI2|#:| |string|↵|#let| |foo|#:| |number|↵|#let| |bar|#:| |false|↵|#class| |FooBar|(||)| |{||}|↵|#let| |fb|#:| |FooBar|↵|#module| |ABC| |{|→|#class| |DEF|(||)| |{||}|←|↵|}|↵|#let| |d|#:| |ABC|.DEF|↵|#module| |DD| |{|→|#let| |foo|#:| |number|↵|#let| |bar|#:| |number|←|↵|}| 18 | //│ Parsed: {let URI: string; let URI2: string; let foo: number; let bar: false; class FooBar() {}; let fb: FooBar; module ABC {class DEF() {}}; let d: ABC.DEF; module DD {let foo: number; let bar: number}} 19 | //│ 20 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Array.ts: -------------------------------------------------------------------------------- 1 | function first(x: string[]) { 2 | return x[0]; 3 | } 4 | 5 | function getZero3() : number[] { 6 | return [0, 0, 0]; 7 | } 8 | 9 | function first2(fs: ((x: number) => number)[]): ((x: number) => number) { 10 | return fs[0]; 11 | } 12 | 13 | enum E { 14 | E, EE, EEE 15 | } 16 | 17 | function doEs(e: E[]): E[] { 18 | return e; 19 | } 20 | 21 | class C {} 22 | interface I {i: number} 23 | 24 | function doCs(c: C[]): C[] { 25 | return c; 26 | } 27 | 28 | function doIs(i: I[]): I[] { 29 | return i; 30 | } 31 | 32 | function inter(x: (U & T)[]): (U & T)[] { 33 | return x; 34 | } 35 | 36 | function clean(x: [string, number][]): [string, number][] { 37 | return []; 38 | } 39 | 40 | function translate(x: T[]): U[] { 41 | return []; 42 | } 43 | 44 | function uu(x: (number | boolean)[]): (number | boolean)[] { 45 | return x; 46 | } 47 | 48 | class Temp { 49 | x: T 50 | } 51 | 52 | function ta(ts: Temp[]): Temp[] { 53 | return []; 54 | } 55 | 56 | function tat(ts: Temp[]): Temp[] { 57 | return []; 58 | } 59 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/BasicFunctions.ts: -------------------------------------------------------------------------------- 1 | function hello() { 2 | console.log("hello") 3 | } 4 | 5 | function add(x: number, y: number): number { 6 | return x + y 7 | } 8 | 9 | function sub(x: number, y: number) { 10 | return x - y 11 | } 12 | 13 | function foo() { 14 | return 42; 15 | } 16 | 17 | function id(x) { 18 | return x; 19 | } 20 | 21 | function odd(x: number) { 22 | return (x % 2) !== 0; 23 | } 24 | 25 | function isnull(x) { 26 | return x == null; 27 | } 28 | 29 | function bar() { 30 | return undefined; 31 | } 32 | 33 | function nu(n: null): null { 34 | return n; 35 | } 36 | 37 | function un(n: undefined): undefined { 38 | return n; 39 | } 40 | 41 | function fail() : never { 42 | throw new Error("wuwuwu"); 43 | } 44 | 45 | function create(): object { 46 | return {v: 0}; 47 | } 48 | 49 | function pa(x: ((number))): number { 50 | return x + 42; 51 | } 52 | 53 | function wtf(x: unknown) {} 54 | 55 | class Foooooo { 56 | ooooooo: number 57 | } 58 | 59 | function inn(f: Foooooo) { 60 | console.log(f.ooooooo) 61 | } 62 | 63 | function out1(): Foooooo { 64 | return new Foooooo(); 65 | } 66 | 67 | interface Barrrrrrrrr { 68 | rrrrrrr: number 69 | } 70 | 71 | function inn2(b: Barrrrrrrrr) { 72 | console.log(b.rrrrrrr) 73 | } 74 | 75 | function out2(): Barrrrrrrrr { 76 | return {rrrrrrr: 42}; 77 | } 78 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/ClassMember.ts: -------------------------------------------------------------------------------- 1 | class Student { 2 | name: string 3 | 4 | constructor(s: string, age: number) {} 5 | 6 | 7 | getID() { return 114514; } 8 | 9 | addScore(sub: string, score: number) {} 10 | isFriend(other: Student) { return true; } 11 | 12 | private a: number 13 | protected b: string 14 | } 15 | 16 | class Foo { 17 | constructor() {} 18 | 19 | bar(x: T) {} 20 | } 21 | 22 | class EZ { 23 | inc(x: number) { 24 | return x + 1; 25 | } 26 | 27 | private foo() {} 28 | protected bar: undefined 29 | } 30 | 31 | class Outer { 32 | static Inner = class Inner { 33 | a: number 34 | } 35 | } 36 | 37 | class TTT { 38 | ttt(x: T): T { 39 | return x; 40 | } 41 | 42 | ttt2: (x: T) => T 43 | } 44 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Dec.d.ts: -------------------------------------------------------------------------------- 1 | decalre function getName(id: number | string): string 2 | declare function render(callback?: ()=>void): string 3 | 4 | declare interface Get{ 5 | (id: string): string 6 | } 7 | 8 | declare class Person { 9 | constructor(name: string, age: number) 10 | getName(id: number): string 11 | } 12 | 13 | declare namespace OOO{ 14 | } 15 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Enum.ts: -------------------------------------------------------------------------------- 1 | enum Color {Red, Yellow, Green} 2 | 3 | function pass(c: Color): boolean { 4 | return c == Color.Green; 5 | } 6 | 7 | function stop(): Color { 8 | return Color.Red; 9 | } 10 | 11 | enum Empty {} 12 | 13 | function g(x: Empty): Empty { 14 | return x; 15 | } 16 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Heritage.ts: -------------------------------------------------------------------------------- 1 | class A { 2 | constructor() {} 3 | 4 | foo() { 5 | console.log("foo") 6 | } 7 | } 8 | 9 | class B extends A {} 10 | 11 | class C { 12 | constructor() {} 13 | 14 | private t: T 15 | 16 | sett(x: T) { this.t = x; } // FIXME support `set` methods... 17 | get() { return this.t; } 18 | } 19 | 20 | class D extends C { 21 | } 22 | 23 | interface Wu { 24 | x: boolean 25 | } 26 | 27 | class WuWu extends Wu { 28 | y: boolean 29 | } 30 | 31 | interface WuWuWu extends WuWu { 32 | z: boolean 33 | } 34 | 35 | interface Never extends WuWuWu { 36 | w: () => never 37 | } 38 | 39 | class VG { 40 | x: T 41 | } 42 | 43 | class Home extends VG { 44 | y: T 45 | } 46 | 47 | interface O { 48 | xx: (x: I) => I 49 | } 50 | 51 | class OR implements O { 52 | xx(x: R): R { 53 | return x; 54 | } 55 | } 56 | 57 | namespace Five { 58 | export class ROTK { 59 | wu: string 60 | } 61 | 62 | export class Y extends Five.ROTK {} 63 | } 64 | 65 | class Y extends Five.ROTK {} 66 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/HighOrderFunc.ts: -------------------------------------------------------------------------------- 1 | function h1(inc: (n: number) => number, num: number) { 2 | return inc(num) 3 | } 4 | 5 | function h2(hint: string) { 6 | return function() { 7 | return "hint: " + hint 8 | } 9 | } 10 | 11 | function h3(f: (x: number) => number, g: (x: number) => number) { 12 | return function(x: number) { 13 | return f(g(x)) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/InterfaceMember.ts: -------------------------------------------------------------------------------- 1 | interface IFoo { 2 | a: string 3 | b: (x: number) => number 4 | c: () => boolean 5 | d: (x: string) => void 6 | } 7 | 8 | interface II { 9 | test: (x: T) => number 10 | } 11 | 12 | function create() { 13 | return {v: 114}; 14 | } 15 | 16 | function get(x: {t: string}): string { 17 | return x.t; 18 | } 19 | 20 | interface IEvent { 21 | callback(this: IEvent): (x: number) => void; 22 | } 23 | 24 | interface SearchFunc { 25 | (source: string, subString: string): boolean; 26 | } 27 | 28 | interface StringArray { 29 | [index: number]: string; 30 | } 31 | 32 | interface Counter { 33 | (start: number): string; 34 | interval: number; 35 | reset(): void; 36 | } 37 | 38 | interface Simple { 39 | a: number 40 | b: (x: boolean) => string 41 | } 42 | 43 | interface Simple2 { 44 | abc: T 45 | } 46 | 47 | interface Next extends Simple {} 48 | 49 | interface TTT { 50 | ttt: (x: T) => T 51 | } 52 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Intersection.ts: -------------------------------------------------------------------------------- 1 | function extend(first: T, second: U): T & U { 2 | let result = {}; 3 | return result; 4 | } 5 | 6 | function foo(x: T & U) { 7 | console.log(x) 8 | } 9 | 10 | function over(f: ((x: number) => string) & ((x: object) => string)): string { 11 | return f(42); 12 | } 13 | 14 | interface IA{ 15 | x: number 16 | } 17 | 18 | interface IB{ 19 | y: number 20 | } 21 | 22 | function iii(x: IA & IB): IA & IB { 23 | return x; 24 | } 25 | 26 | function uu(x: (U | V) & (T | P)): (U | V) & (T | P) { 27 | return x; 28 | } 29 | 30 | function iiii(x: U & (T & V)): U & (T & V) { 31 | return x; 32 | } 33 | 34 | function arr(a: U[] & T[]): U[] & T[] { 35 | return a; 36 | } 37 | 38 | function tt(x: [U, T] & [V, V]): [U, T] & [V, V] { 39 | return x; 40 | } 41 | 42 | class A{} 43 | class B{} 44 | 45 | function inter(c: A & B): A & B { 46 | return c; 47 | } 48 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Literal.ts: -------------------------------------------------------------------------------- 1 | const a = { a: "A", b: "B" } 2 | const num = { y: 114 } 3 | 4 | function foo(x: {xx: "X"}): {yy: "Y"} { 5 | const y = {yy: "Y"} 6 | return y 7 | } 8 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Multi1.ts: -------------------------------------------------------------------------------- 1 | function multi1(x: number) { 2 | return x; 3 | } 4 | 5 | function multi3() {} 6 | 7 | class Foo extends Base {} 8 | 9 | interface AnotherBase { 10 | y: string 11 | } 12 | 13 | namespace N { 14 | export function f() {} 15 | } 16 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Multi2.ts: -------------------------------------------------------------------------------- 1 | function multi2(x: string) { 2 | return x; 3 | } 4 | 5 | function multi4() { 6 | multi3() 7 | } 8 | 9 | interface Base { 10 | a: number 11 | } 12 | 13 | class AnotherFoo extends AnotherBase {} 14 | 15 | namespace N { 16 | export function g() {} 17 | } 18 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Multi3.ts: -------------------------------------------------------------------------------- 1 | function multi5() { 2 | console.log("wuwuwu") 3 | } 4 | 5 | namespace N { 6 | export function h() {} 7 | } 8 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Namespace.ts: -------------------------------------------------------------------------------- 1 | namespace N1 { 2 | export function f(x) { 3 | return 42; 4 | } 5 | 6 | function ff(y) { 7 | return 42; 8 | } 9 | 10 | export class C { 11 | f() {} 12 | } 13 | 14 | interface I { 15 | f: () => number 16 | } 17 | 18 | export namespace N2 { 19 | export function fff(x: boolean) { 20 | return 42; 21 | } 22 | 23 | class BBB extends C {} 24 | 25 | function gg(c: C): C { 26 | return new C; 27 | } 28 | } 29 | } 30 | 31 | namespace AA { 32 | export function f(x) { 33 | return "42"; 34 | } 35 | 36 | export class C { 37 | f() {} 38 | } 39 | 40 | export interface I { 41 | f: () => number 42 | } 43 | 44 | export namespace N2 {} 45 | } 46 | 47 | function f1(x: N1.C): N1.C { 48 | return x; 49 | } 50 | 51 | function f2(x: AA.C): AA.C { 52 | return x; 53 | } 54 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Optional.ts: -------------------------------------------------------------------------------- 1 | function buildName(firstName: string, lastName?: string) { 2 | return firstName + lastName; 3 | } 4 | 5 | function buildName2(firstName: string, lastName = "DIO") { 6 | return firstName + lastName; 7 | } 8 | 9 | function buildName3(firstName: string, ...lastName: string[]) { 10 | console.log(lastName) 11 | return firstName; 12 | } 13 | 14 | function buildName4(firstName: string, ...lastName) { 15 | console.log(lastName) 16 | return firstName; 17 | } 18 | 19 | interface SquareConfig { 20 | color?: string; 21 | width?: number; 22 | } 23 | 24 | function did(x: number, f?: (x: number) => number): number { 25 | if (f === undefined) return x; 26 | else return f(x); 27 | } 28 | 29 | function getOrElse(arr?: object[]): object { 30 | if (arr === undefined) return {}; 31 | else return arr[0]; 32 | } 33 | 34 | class ABC {} 35 | function testABC(abc?: ABC) {} 36 | 37 | function testSquareConfig(conf?: SquareConfig) {} 38 | 39 | function err(msg?: [number, string]): void { 40 | if (msg === undefined) return; 41 | else throw msg; 42 | } 43 | 44 | function toStr(x?: number | boolean): string { 45 | if (x === undefined) return "undefined"; 46 | else return x.toString(); 47 | } 48 | 49 | function boo(x?: T & U) {} 50 | 51 | class B { 52 | b: T 53 | } 54 | 55 | function boom(b?: B): any {} 56 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Tuple.ts: -------------------------------------------------------------------------------- 1 | function key(x: [string, boolean]): string { 2 | return x[0]; 3 | } 4 | 5 | function value(x: [string, boolean]): boolean { 6 | return x[1]; 7 | } 8 | 9 | function third(x: [number, number, number]): number { 10 | return x[2]; 11 | } 12 | 13 | function vec2(x: number, y: number): [number, number] { 14 | return [x, y]; 15 | } 16 | 17 | function twoFunctions(ff: [(x: number) => number, (x: number) => number], x: number): number { 18 | return ff[0](x) + ff[1](x); 19 | } 20 | 21 | function tupleIt(x: string): [() => string] { 22 | return [function() { return x }] 23 | } 24 | 25 | function s(flag: boolean): [string | number, number | boolean] { 26 | if (flag) { 27 | return ["abc", 12]; 28 | } 29 | else { 30 | return [24, false]; 31 | } 32 | } 33 | 34 | function s2(t: [boolean, string | number]): string | number { 35 | if (t[0]) return t[1] 36 | else return 0 37 | } 38 | 39 | function ex(x: T, y: U): [T, U, T & U] { 40 | return [x, y , {}]; 41 | } 42 | 43 | function foo(x: [T & U]) {} 44 | 45 | function conv(x: {y: number}): [{y: number}, {z: string}] { 46 | return [x, {z: x.y.toString()}]; 47 | } 48 | 49 | class A { 50 | x: number 51 | } 52 | class B {} 53 | 54 | function swap(x: [A, B]): [B, A] { 55 | return [x[1], x[0]]; 56 | } 57 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Type.ts: -------------------------------------------------------------------------------- 1 | interface None { 2 | readonly _tag: 'None' 3 | } 4 | 5 | interface Some { 6 | readonly _tag: 'Some' 7 | readonly value: A 8 | } 9 | 10 | type Option = None | Some 11 | type Func = (x: number) => number 12 | type S2 = [string, string] 13 | 14 | interface I1 {} 15 | interface I2 {} 16 | 17 | type I3 = I1 & I2 18 | type StringArray = string[] 19 | type SomeInterface = { x: number, y: number } 20 | 21 | class ABC {} 22 | type DEF = ABC 23 | type TP = [A, B, C] 24 | 25 | namespace NA { 26 | export type B = string 27 | function fb(b: B) {} 28 | } 29 | 30 | class NC { 31 | constructor() {} 32 | b: NA.B 33 | } 34 | 35 | type G = DEF 36 | 37 | const none: Option = { _tag: 'None' } 38 | const some = (a: A): Option => ({ _tag: 'Some', value: a }) 39 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/TypeParameter.ts: -------------------------------------------------------------------------------- 1 | function inc(x: T) { 2 | return x + 1 3 | } 4 | 5 | class CC { 6 | constructor() {} 7 | 8 | print(s: T) { console.log(s) } 9 | } 10 | 11 | function con(t: T): U { 12 | return t; 13 | } 14 | 15 | class Printer { 16 | constructor() {} 17 | 18 | print(t: T) { console.log(t) } 19 | } 20 | 21 | function setStringPrinter(p: Printer) {} 22 | 23 | function getStringPrinter(): Printer { return new Printer(); } 24 | 25 | function foo(p: Printer, x: T): T { 26 | return null; 27 | } 28 | 29 | // TODO: `extends` is still not supported yet. 30 | function foo2(p: Printer, x: T): T { 31 | return null; 32 | } 33 | 34 | class F { 35 | x: T 36 | 37 | GG(y: U): T { 38 | return this.x; 39 | } 40 | } 41 | 42 | interface I { 43 | x: T 44 | GG(y: U): T 45 | } 46 | 47 | class FFF { 48 | constructor() {} 49 | fff(x: T) {} 50 | } 51 | 52 | function fff(p: FFF, s: string) { 53 | p.fff(s); 54 | } 55 | 56 | function getFFF(): FFF { 57 | return new FFF(); 58 | } 59 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Union.ts: -------------------------------------------------------------------------------- 1 | function getString(x: string | number | boolean): string { 2 | return x.toString() 3 | } 4 | 5 | function test(x: boolean): (string | number) { 6 | if (x) return "foo"; 7 | else return 42; 8 | } 9 | 10 | function run(f: ((x: number) => number) | ((x: number) => string)): any { 11 | return f(42); 12 | } 13 | 14 | function get(arr: number[] | string[]) { 15 | console.log(arr[0]) 16 | } 17 | 18 | function get2(t: [string, string] | [number, string]): string { 19 | return t[1]; 20 | } 21 | 22 | function typeVar(x: T | U): T | U { 23 | return x 24 | } 25 | 26 | function uuuu(x: string | (number | boolean)): string | (number | boolean) { 27 | return x; 28 | } 29 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/typescript/Variables.ts: -------------------------------------------------------------------------------- 1 | const URI: string = "Option" 2 | let URI2: string = "Option" 3 | let foo: number 4 | const bar = false 5 | 6 | class FooBar {} 7 | const fb = new FooBar 8 | 9 | namespace ABC { 10 | export class DEF {} 11 | } 12 | 13 | const d = new ABC.DEF 14 | 15 | namespace DD { 16 | export const foo: number = 42 17 | const bar = 42 18 | } 19 | -------------------------------------------------------------------------------- /ts2mls/jvm/src/test/scala/ts2mls/TsTypeDiffTests.scala: -------------------------------------------------------------------------------- 1 | package ts2mls 2 | 3 | import mlscript.DiffTests 4 | 5 | class TsTypeDiffTests extends DiffTests { 6 | override protected lazy val files = 7 | os.walk(os.pwd/"ts2mls"/"js"/"src"/"test"/"diff").filter(_.toIO.isFile) 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2016", 5 | "jsx": "preserve", 6 | "sourceMap": true 7 | }, 8 | "include": [ 9 | "ts" 10 | ], 11 | "exclude": [ 12 | "node_modules", 13 | "**/node_modules/*" 14 | ], 15 | "[typescript]": { 16 | "editor.showUnused": false 17 | }, 18 | "[typescriptreact]": { 19 | "editor.showUnused": false 20 | }, 21 | } 22 | --------------------------------------------------------------------------------