├── .gitattributes ├── .github └── workflows │ └── scala.yml ├── .gitignore ├── .vscode └── settings.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── bin └── mlscript-opt.js ├── build.sbt ├── compiler └── shared │ ├── main │ └── scala │ │ └── mlscript │ │ └── compiler │ │ ├── ClassLifter.scala │ │ ├── PrettyPrinter.scala │ │ ├── debug │ │ ├── Debug.scala │ │ ├── DebutOutput.scala │ │ ├── DummyDebug.scala │ │ ├── Printable.scala │ │ ├── RainbowDebug.scala │ │ └── TreeDebug.scala │ │ └── printer │ │ └── BlockPrinter.scala │ └── test │ ├── diff │ ├── LiftType.mls │ ├── Lifter.mls │ └── LifterBlks.mls │ └── scala │ └── mlscript │ └── compiler │ └── Test.scala ├── doc └── Parsing.md ├── index.css ├── index.html ├── js └── src │ └── main │ └── scala │ ├── Main.scala │ └── fansi │ └── Str.scala ├── local_testing.html ├── notes └── interpretation-of-as-types.txt ├── 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 │ │ ├── Helpers.scala │ │ ├── Polyfill.scala │ │ ├── Scope.scala │ │ ├── Symbol.scala │ │ └── typescript │ │ │ └── TsTypegen.scala │ │ ├── helpers.scala │ │ ├── package.scala │ │ ├── syntax.scala │ │ ├── ucs │ │ ├── Clause.scala │ │ ├── Conjunction.scala │ │ ├── Desugarer.scala │ │ ├── DesugaringException.scala │ │ ├── LetBinding.scala │ │ ├── MutCaseOf.scala │ │ ├── PartialTerm.scala │ │ ├── Scrutinee.scala │ │ └── helpers.scala │ │ └── utils │ │ ├── FastParseHelpers.scala │ │ ├── Identity.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 │ │ ├── Classes.mls │ │ ├── ConstructorStmt.mls │ │ ├── Declare.mls │ │ ├── Escape.mls │ │ ├── FieldOverride.mls │ │ ├── IndirectRecursion.mls │ │ ├── Inheritance.mls │ │ ├── LogInfo.mls │ │ ├── Mixin.mls │ │ ├── MixinCapture.mls │ │ ├── Nested.mls │ │ ├── New.mls │ │ ├── NewClasses.mls │ │ ├── NuClasses.mls │ │ ├── NuFuns.mls │ │ ├── OptionalParam.mls │ │ ├── ParameterPattern.mls │ │ ├── Parentheses.mls │ │ ├── PatternMatch.mls │ │ ├── Polyfill.mls │ │ ├── Recursion.mls │ │ ├── ReplHost.mls │ │ ├── Res.mls │ │ ├── Shadowing.mls │ │ ├── SortClass.mls │ │ ├── Super.mls │ │ ├── Terms.mls │ │ ├── TraitMethods.mls │ │ ├── TrickyShadowing.mls │ │ ├── TrickyTerms.mls │ │ └── TrickyWiths.mls │ ├── contys │ │ ├── AbstractBounds.mls │ │ └── ExplicitConstraints.mls │ ├── ecoop23 │ │ ├── ExpressionProblem.mls │ │ ├── Intro.mls │ │ ├── PolymorphicVariants.mls │ │ └── SimpleRegionDSL.mls │ ├── fcp-lit │ │ ├── Boxy.mls │ │ ├── CPS_LB.mls │ │ ├── FreezeML.mls │ │ ├── HMF.mls │ │ ├── HML.mls │ │ ├── Incomplete.mls │ │ ├── Jim.mls │ │ ├── LambdaForallI.mls │ │ ├── Leijen.mls │ │ ├── MLF.mls │ │ ├── Misc.mls │ │ ├── PolyML.mls │ │ ├── PolyML2.mls │ │ └── QML.mls │ ├── fcp │ │ ├── Aliases.mls │ │ ├── Basics.mls │ │ ├── Church_CT.mls │ │ ├── Church_ST.mls │ │ ├── ConstrainedTypes1.mls │ │ ├── ConstrainedTypes2.mls │ │ ├── Distrib.mls │ │ ├── DistribRight.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 │ │ ├── OverloadSimplif.mls │ │ ├── Overloads.mls │ │ ├── Paper.mls │ │ ├── PaperTable.mls │ │ ├── PolyParams.mls │ │ ├── Proofs.mls │ │ ├── QML_exist_Classes_CT.mls │ │ ├── QML_exist_Classes_ST.mls │ │ ├── QML_exist_Classes_ST_Repro.mls │ │ ├── QML_exist_Records.mls │ │ ├── QML_exist_Records_min_CT.mls │ │ ├── QML_exist_Records_min_ST.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 │ ├── 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 │ ├── mlscript │ │ ├── ADTs.mls │ │ ├── ADTsRepro.mls │ │ ├── Addable.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 │ │ ├── ByNameByValue.mls │ │ ├── David.mls │ │ ├── David2.mls │ │ ├── DavidB.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 │ │ ├── Lists.mls │ │ ├── Luyu.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 │ │ ├── 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 │ │ ├── SafeDiv.mls │ │ ├── Scratch.mls │ │ ├── SelfNeg.mls │ │ ├── SelfNegs.mls │ │ ├── Seqs.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 │ │ ├── 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 │ │ ├── Ascription.mls │ │ ├── BadAliases.mls │ │ ├── BadClassInherit.mls │ │ ├── BadClasses.mls │ │ ├── BadMixins.mls │ │ ├── BadScopes.mls │ │ ├── BadSignatures.mls │ │ ├── BadSuper.mls │ │ ├── BadUCS.mls │ │ ├── BasicClassInheritance.mls │ │ ├── BasicClasses.mls │ │ ├── BasicMixins.mls │ │ ├── ClassField.mls │ │ ├── ClassSignatures.mls │ │ ├── ClassesInMixins.mls │ │ ├── CtorStatements.mls │ │ ├── Dates.mls │ │ ├── Declarations.mls │ │ ├── DiamondInherit.mls │ │ ├── EncodedLists.mls │ │ ├── Eql.mls │ │ ├── EqlClasses.mls │ │ ├── EvalNegNeg.mls │ │ ├── ExplicitVariance.mls │ │ ├── ExpressionProblem_repro.mls │ │ ├── ExpressionProblem_small.mls │ │ ├── FieldRefinement.mls │ │ ├── FilterMap.mls │ │ ├── FunPatterns.mls │ │ ├── FunPoly.mls │ │ ├── FunSigs.mls │ │ ├── GADTMono.mls │ │ ├── GenericClassInheritance.mls │ │ ├── GenericClasses.mls │ │ ├── GenericMethods.mls │ │ ├── GenericMixins.mls │ │ ├── GenericModules.mls │ │ ├── Huawei1.mls │ │ ├── ImplicitMethodPolym.mls │ │ ├── InferredInheritanceTypeArgs.mls │ │ ├── InheritanceLevelMismatches.mls │ │ ├── InterfaceGeneric.mls │ │ ├── InterfaceMono.mls │ │ ├── Interfaces.mls │ │ ├── LetRec.mls │ │ ├── ListConsNil.mls │ │ ├── LitMatch.mls │ │ ├── LocalLets.mls │ │ ├── MemberConfusion.mls │ │ ├── MemberIntersections.mls │ │ ├── MetaWrap.mls │ │ ├── MethodSignatures.mls │ │ ├── Misc.mls │ │ ├── MixinParameters.mls │ │ ├── ModuleParameters.mls │ │ ├── Mut.mls │ │ ├── MutualRec.mls │ │ ├── NamedArgs.mls │ │ ├── NestedClasses.mls │ │ ├── New.mls │ │ ├── NewNew.mls │ │ ├── NuScratch.mls │ │ ├── Numbers.mls │ │ ├── Object.mls │ │ ├── OverrideShorthand.mls │ │ ├── ParamImplementing.mls │ │ ├── ParamOverride.mls │ │ ├── ParamOverriding.mls │ │ ├── ParamPassing.mls │ │ ├── Parens.mls │ │ ├── PolymorphicVariants_Alt.mls │ │ ├── RawUnionTraitSignatures.mls │ │ ├── SelfAppMethods.mls │ │ ├── SelfRec.mls │ │ ├── SimpleTraitImpl.mls │ │ ├── ThisRefinedClasses.mls │ │ ├── TraitParameters.mls │ │ ├── TrickyGenericInheritance.mls │ │ ├── TypeAliases.mls │ │ ├── TypeSelections.mls │ │ ├── TypeVariables.mls │ │ ├── TypingUnitTerms.mls │ │ ├── TypreMembers.mls │ │ ├── Uninstantiable.mls │ │ ├── Vals.mls │ │ ├── WeirdUnions.mls │ │ ├── With.mls │ │ ├── repro0.mls │ │ ├── repro1.mls │ │ ├── repro_EvalNegNeg.mls │ │ └── repro_PolymorphicVariants.mls │ ├── parser │ │ ├── Arrays.mls │ │ ├── BasicSyntax.mls │ │ ├── Binds.mls │ │ ├── Blocks.mls │ │ ├── Brackets.mls │ │ ├── Classes.mls │ │ ├── Comments.mls │ │ ├── ControversialIfSplits.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 │ │ ├── UserDefinedOps?.mls │ │ ├── WeirdIfs.mls │ │ ├── Where.mls │ │ ├── Whitespace.mls │ │ └── boolops.mls │ ├── tapl │ │ ├── NuSimplyTyped.mls │ │ ├── NuUntyped.mls │ │ ├── SimplyTyped.mls │ │ └── Untyped.mls │ ├── tricky │ │ ├── IrregularSubtypes.mls │ │ ├── IrregularSubtypes2.mls │ │ └── Pottier.fun │ ├── typegen │ │ ├── TypegenTerms.mls │ │ └── TypegenTypedefs.mls │ └── ucs │ │ ├── DirectLines.mls │ │ ├── ElseIf.mls │ │ ├── ErrorMessage.mls │ │ ├── Exhaustiveness.mls │ │ ├── Humiliation.mls │ │ ├── Hygiene.mls │ │ ├── HygienicBindings.mls │ │ ├── InterleavedLet.mls │ │ ├── JSON.mls │ │ ├── LeadingAnd.mls │ │ ├── LitUCS.mls │ │ ├── MultiwayIf.mls │ │ ├── NestedBranches.mls │ │ ├── NestedPattern.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 │ │ ├── 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/scala.yml: -------------------------------------------------------------------------------- 1 | name: Scala CI 2 | 3 | on: 4 | push: 5 | branches: [ mlscript ] 6 | pull_request: 7 | 8 | jobs: 9 | build: 10 | 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Set up JDK 1.8 16 | uses: actions/setup-java@v1 17 | with: 18 | java-version: 1.8 19 | - uses: actions/setup-node@v3 20 | with: 21 | node-version: '17.x' 22 | - name: Install TypeScript 23 | run: npm ci 24 | - name: Run tests 25 | run: sbt test 26 | - name: Check no changes 27 | run: git diff-files -p --exit-code 28 | -------------------------------------------------------------------------------- /.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 | }, 5 | "typescript.validate.enable": false, 6 | "files.watcherExclude": { 7 | "**/target": true 8 | }, 9 | "[typescript]": { 10 | "editor.quickSuggestions": { 11 | "comments": "off", 12 | "other": "off", 13 | "strings": "off" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /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.debug 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 | 10 | object Debug: 11 | val noPostTrace: Any => Any = _ => "" 12 | -------------------------------------------------------------------------------- /compiler/shared/main/scala/mlscript/compiler/debug/DummyDebug.scala: -------------------------------------------------------------------------------- 1 | package mlscript.compiler.debug 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 | -------------------------------------------------------------------------------- /compiler/shared/main/scala/mlscript/compiler/debug/Printable.scala: -------------------------------------------------------------------------------- 1 | package mlscript.compiler.debug 2 | 3 | trait Printable: 4 | def getDebugOutput: DebugOutput 5 | -------------------------------------------------------------------------------- /compiler/shared/main/scala/mlscript/compiler/debug/TreeDebug.scala: -------------------------------------------------------------------------------- 1 | package mlscript.compiler.debug 2 | 3 | import scala.collection.mutable.ArrayBuffer 4 | 5 | class TreeDebug extends RainbowDebug(false): 6 | private val lines = ArrayBuffer[String]() 7 | 8 | override inline def writeLine(line: String): Unit = lines += line 9 | 10 | def getLines: List[String] = lines.toList 11 | -------------------------------------------------------------------------------- /compiler/shared/main/scala/mlscript/compiler/printer/BlockPrinter.scala: -------------------------------------------------------------------------------- 1 | package mlscript.compiler.printer 2 | 3 | import scala.collection.mutable.{ArrayBuffer, Stack, StringBuilder} 4 | 5 | class BlockPrinter: 6 | import BlockPrinter.Indentation 7 | 8 | private val indent = Indentation() 9 | private val lines = ArrayBuffer[String]() 10 | private val currentLine = StringBuilder() 11 | private val scopes = Stack[Option[String]]() 12 | 13 | def endLine(): Unit = if currentLine.isEmpty then () else { 14 | lines += indent(currentLine.toString) 15 | currentLine.clear() 16 | } 17 | 18 | def enter(): Unit = 19 | endLine() 20 | indent.increase() 21 | scopes.push(None) 22 | 23 | def enter(begin: String, end: String): Unit = 24 | currentLine ++= begin 25 | endLine() 26 | indent.increase() 27 | scopes.push(Some(end)) 28 | 29 | def leave(): Unit = 30 | endLine() // ↵ 31 | indent.decrease() 32 | scopes.pop().foreach { currentLine ++= _ } 33 | endLine() // ↵ 34 | 35 | def print(content: String): Unit = currentLine ++= content 36 | 37 | def toLines: List[String] = 38 | endLine() 39 | lines.toList 40 | 41 | override def toString(): String = lines.mkString("\n") 42 | 43 | object BlockPrinter: 44 | class Indentation(mark: String = " "): 45 | private var indent = 0 46 | private var spaces = ArrayBuffer[String]("") 47 | def increase(): Unit = 48 | indent += 1 49 | spaces += spaces.last + mark 50 | def decrease(): Unit = indent -= 1 51 | def apply(content: String): String = spaces(indent) + content 52 | -------------------------------------------------------------------------------- /compiler/shared/test/scala/mlscript/compiler/Test.scala: -------------------------------------------------------------------------------- 1 | package mlscript 2 | package compiler 3 | 4 | import mlscript.utils.shorthands.* 5 | import scala.util.control.NonFatal 6 | import scala.collection.mutable.StringBuilder 7 | import mlscript.codegen.Helpers.inspect as showStructure 8 | 9 | class DiffTestCompiler extends DiffTests { 10 | import DiffTestCompiler.* 11 | override def postProcess(mode: ModeType, basePath: List[Str], testName: Str, unit: TypingUnit): List[Str] = 12 | val outputBuilder = StringBuilder() 13 | outputBuilder ++= "Parsed:\n" 14 | outputBuilder ++= showStructure(unit) 15 | 16 | outputBuilder ++= "\nLifted:\n" 17 | var rstUnit = unit; 18 | try 19 | rstUnit = ClassLifter().liftTypingUnit(unit) 20 | outputBuilder ++= PrettyPrinter.showTypingUnit(rstUnit) 21 | catch 22 | case NonFatal(err) => 23 | outputBuilder ++= "Lifting failed: " ++ err.toString() 24 | if mode.fullExceptionStack then outputBuilder ++= 25 | "\n" ++ err.getStackTrace().map(_.toString()).mkString("\n") 26 | outputBuilder.toString().linesIterator.toList 27 | 28 | override protected lazy val files = allFiles.filter { file => 29 | val fileName = file.baseName 30 | validExt(file.ext) && filter(file.relativeTo(pwd)) 31 | } 32 | } 33 | 34 | object DiffTestCompiler { 35 | 36 | private val pwd = os.pwd 37 | private val dir = pwd/"compiler"/"shared"/"test"/"diff" 38 | 39 | private val allFiles = os.walk(dir).filter(_.toIO.isFile) 40 | 41 | private val validExt = Set("fun", "mls") 42 | 43 | private def filter(file: os.RelPath) = DiffTests.filter(file) 44 | 45 | } 46 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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.7.1 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("org.wartremover" % "sbt-wartremover" % "3.0.6") 2 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.11.0") 3 | addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.2.0") 4 | -------------------------------------------------------------------------------- /shared/src/main/scala/mlscript/Message.scala: -------------------------------------------------------------------------------- 1 | package mlscript 2 | 3 | import scala.language.implicitConversions 4 | import mlscript.utils._, shorthands._ 5 | 6 | final case class Message(bits: Ls[Message.Bit]) { 7 | def show: Str = { 8 | val ctx = ShowCtx.mk(typeBits) 9 | showIn(ctx) 10 | } 11 | def typeBits: Ls[TypeLike] = bits.collect{ case Message.Code(t) => t } 12 | def showIn(ctx: ShowCtx): Str = { 13 | bits.map { 14 | case Message.Code(ty) => ty.showIn(ctx, 0) 15 | case Message.Text(txt) => txt 16 | }.mkString 17 | } 18 | def showDbg: Str = { 19 | bits.iterator.map { 20 | case Message.Code(trm) => s"$trm" 21 | case Message.Text(txt) => txt 22 | }.mkString 23 | } 24 | def +(that: Message): Message = Message(bits ++ that.bits) 25 | } 26 | object Message { 27 | 28 | def mkCtx(msgs: IterableOnce[Message], pre: Str = "'"): ShowCtx = 29 | ShowCtx.mk(msgs.iterator.flatMap(_.typeBits), pre) 30 | 31 | def join(msgs: Seq[Message]): Message = Message(msgs.iterator.flatMap(_.bits).toList) 32 | 33 | sealed abstract class Bit 34 | final case class Text(str: Str) extends Bit 35 | final case class Code(ty: TypeLike) extends Bit 36 | implicit def fromType(ty: TypeLike): Message = Message(Code(ty)::Nil) 37 | implicit def fromStr(str: Str): Message = Message(Text(str)::Nil) 38 | 39 | implicit class MessageContext(private val ctx: StringContext) { 40 | def msg(inserted: Message*): Message = { 41 | assert(inserted.length === ctx.parts.length - 1) 42 | val parts = ctx.parts.map(str => Text(StringContext(str).s())) 43 | val h = parts.head 44 | val t = parts.tail 45 | Message((h +: inserted.lazyZip(t).flatMap(_.bits :+ _)).toList) 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /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/ucs/DesugaringException.scala: -------------------------------------------------------------------------------- 1 | package mlscript.ucs 2 | 3 | import mlscript.{Diagnostic, Loc, Message, Typer} 4 | import mlscript.utils.shorthands._ 5 | 6 | class DesugaringException(val messages: Ls[Message -> Opt[Loc]]) extends Throwable { 7 | def this(message: Message, location: Opt[Loc]) = this(message -> location :: Nil) 8 | } 9 | -------------------------------------------------------------------------------- /shared/src/main/scala/mlscript/ucs/LetBinding.scala: -------------------------------------------------------------------------------- 1 | package mlscript.ucs 2 | 3 | import mlscript._ 4 | import mlscript.utils._ 5 | import mlscript.utils.shorthands._ 6 | import scala.collection.immutable.Set 7 | import scala.collection.mutable.{Set => MutSet, Buffer} 8 | 9 | final case class LetBinding(val kind: LetBinding.Kind, val recursive: Bool, val name: Var, val term: Term) 10 | 11 | object LetBinding { 12 | sealed abstract class Kind 13 | 14 | object Kind { 15 | case object ScrutineeAlias extends Kind { 16 | override def toString: String = "scrutinee alias" 17 | } 18 | case object FieldExtraction extends Kind { 19 | override def toString: String = "pattern destruction" 20 | } 21 | case object InterleavedLet extends Kind { 22 | override def toString: String = "interleaved let" 23 | } 24 | } 25 | } 26 | 27 | trait WithBindings { this: MutCaseOf => 28 | private val bindingsSet: MutSet[LetBinding] = MutSet.empty 29 | private val bindings: Buffer[LetBinding] = Buffer.empty 30 | 31 | def addBindings(newBindings: IterableOnce[LetBinding]): Unit = { 32 | newBindings.iterator.foreach { 33 | case binding if bindingsSet.contains(binding) => () 34 | case binding => 35 | bindingsSet += binding 36 | bindings += binding 37 | } 38 | } 39 | 40 | def getBindings: Iterable[LetBinding] = bindings 41 | 42 | def withBindings(newBindings: IterableOnce[LetBinding]): MutCaseOf = { 43 | addBindings(newBindings) 44 | this 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /shared/src/main/scala/mlscript/ucs/Scrutinee.scala: -------------------------------------------------------------------------------- 1 | package mlscript.ucs 2 | 3 | import mlscript.{Loc, SimpleTerm, Term, Var} 4 | import mlscript.utils.lastWords 5 | import mlscript.utils.shorthands._ 6 | 7 | // The point is to remember where the scrutinee comes from. 8 | // Is it from nested patterns? Or is it from a `IfBody`? 9 | final case class Scrutinee(var local: Opt[Var], term: Term)(val matchRootLoc: Opt[Loc]) { 10 | def reference: SimpleTerm = local.getOrElse(term match { 11 | case term: SimpleTerm => term 12 | case _ => lastWords("`term` must be a `SimpleTerm` when `local` is empty") 13 | }) 14 | 15 | /** 16 | * Create a binding for the scrutinee. If the scrutinee is a `SimpleTerm`, 17 | * it returns `None`. 18 | * 19 | * @return `Some` if the scrutinee is localized, otherwise, `None`. 20 | */ 21 | def asBinding: Opt[LetBinding] = local.map { 22 | LetBinding(LetBinding.Kind.ScrutineeAlias, false, _, term) 23 | } 24 | 25 | override def toString: String = 26 | (local match { 27 | case N => "" 28 | case S(Var(alias)) => s"$alias @ " 29 | }) + s"$term" 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 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/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/main/scala/mlscript/utils/shorthands.scala: -------------------------------------------------------------------------------- 1 | package mlscript.utils 2 | 3 | import scala.annotation.showAsInfix 4 | import scala.util.chaining._ 5 | 6 | object shorthands { 7 | 8 | /** We have Int instead of Integer; why not Bool instead of Boolean? */ 9 | type Bool = Boolean 10 | 11 | /** Dotty syntax for intersection types */ 12 | @showAsInfix 13 | type & [+A,+B] = A with B 14 | 15 | type Ls[+A] = List[A] 16 | val Ls: List.type = List 17 | 18 | type Str = String 19 | 20 | type Ite[+A] = Iterator[A] 21 | val Ite: Iterator.type = Iterator 22 | 23 | type Opt[+A] = Option[A] 24 | val Opt: Option.type = Option 25 | type S[+A] = Some[A] 26 | val S: Some.type = Some 27 | val N: None.type = None 28 | def some[A]: A => Option[A] = Some(_) 29 | def none[A]: Option[A] = None 30 | 31 | type Paf[-A,+B] = PartialFunction[A,B] 32 | 33 | type Exc = Exception 34 | type Err = Error 35 | 36 | type Ord[A] = Ordering[A] 37 | type Num[A] = Numeric[A] 38 | 39 | type \/[+A, +B] = Either[A, B] 40 | val \/ : Either.type = Either 41 | 42 | type L[+A] = Left[A, Nothing] 43 | val L: Left.type = Left 44 | 45 | type R[+B] = Right[Nothing, B] 46 | val R: Right.type = Right 47 | 48 | @showAsInfix 49 | type -> [+A,+B] = (A,B) 50 | object -> { 51 | def unapply[A, B](ab: (A, B)): Some[(A, B)] = Some(ab) 52 | } 53 | implicit class Tuple2Helper[A,B](private val self: (A,B)) extends AnyVal { 54 | @inline def mapFirst[C](f: A => C): (C,B) = (self._1 pipe f, self._2) 55 | @inline def mapSecond[C](f: B => C): (A,C) = (self._1, self._2 pipe f) 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /shared/src/test/diff/analysis/Weird.mls: -------------------------------------------------------------------------------- 1 | 2 | class Base1[A] 3 | method M1: A -> Base1[A] 4 | //│ Defined class Base1[-A] 5 | //│ Declared Base1.M1: Base1['A] -> 'A -> Base1['A] 6 | 7 | 8 | :DistributeForalls 9 | 10 | // * See [FIXME:1] — C should NOT be invariant here! (only happens with :DistributeForalls) 11 | class Derived2[C]: Base1[anything] 12 | method M1 r = Derived2{} 13 | //│ Defined class Derived2[=C] 14 | //│ Defined Derived2.M1: Derived2['C] -> anything -> Derived2['C0] 15 | 16 | Derived2.M1 17 | //│ res: Derived2['C] -> (forall 'C0. anything -> Derived2['C0]) 18 | //│ = undefined 19 | 20 | 21 | :DontDistributeForalls 22 | 23 | :w 24 | class Derived3[C]: Base1[anything] 25 | method M1 r = Derived3{} 26 | //│ Defined class Derived3[±C] 27 | //│ Defined Derived3.M1: Derived3[?] -> anything -> Derived3[?] 28 | //│ ╔══[WARNING] Type definition Derived3 has bivariant type parameters: 29 | //│ ║ l.24: class Derived3[C]: Base1[anything] 30 | //│ ║ ^^^^^^^^ 31 | //│ ╟── C is irrelevant and may be removed 32 | //│ ║ l.24: class Derived3[C]: Base1[anything] 33 | //│ ╙── ^ 34 | 35 | Derived3.M1 36 | //│ res: Derived3[?] -> anything -> Derived3[?] 37 | //│ = undefined 38 | 39 | -------------------------------------------------------------------------------- /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, L, 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, R, 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/Slashes.fun: -------------------------------------------------------------------------------- 1 | 2 | succ / 1 3 | succ / succ / 1 4 | //│ res: int 5 | //│ res: int 6 | 7 | let foo = f => f 1 8 | //│ foo: (1 -> 'a) -> 'a 9 | 10 | foo / x => x 11 | //│ res: 1 12 | 13 | foo / x => succ x 14 | //│ res: int 15 | 16 | x => succ / x + 1 17 | //│ res: int -> int 18 | 19 | x => succ / succ / x + 1 20 | //│ res: int -> int 21 | 22 | :p 23 | foo / x => succ / succ / x 24 | //│ Parsed: foo ((x) => succ (succ x)); 25 | //│ Desugared: foo ((x) => succ (succ x)) 26 | //│ AST: App(Var(foo), Lam(Var(x), App(Var(succ), App(Var(succ), Var(x))))) 27 | //│ res: int 28 | 29 | :e 30 | foo / foo / x => succ / succ / x 31 | //│ ╔══[ERROR] Type mismatch in application: 32 | //│ ║ l.30: foo / foo / x => succ / succ / x 33 | //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 34 | //│ ╟── application of type `int` is not a function 35 | //│ ║ l.30: foo / foo / x => succ / succ / x 36 | //│ ║ ^^^^^^^^^^^^^^^ 37 | //│ ╟── but it flows into application with expected type `1 -> ?a` 38 | //│ ║ l.30: foo / foo / x => succ / succ / x 39 | //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ 40 | //│ ╟── Note: constraint arises from application: 41 | //│ ║ l.7: let foo = f => f 1 42 | //│ ║ ^^^ 43 | //│ ╟── from reference: 44 | //│ ║ l.7: let foo = f => f 1 45 | //│ ╙── ^ 46 | //│ res: error 47 | 48 | :e 49 | foo / foo 50 | //│ ╔══[ERROR] Type mismatch in application: 51 | //│ ║ l.49: foo / foo 52 | //│ ║ ^^^^^^^^^ 53 | //│ ╟── integer literal of type `1` is not a function 54 | //│ ║ l.7: let foo = f => f 1 55 | //│ ║ ^ 56 | //│ ╟── Note: constraint arises from application: 57 | //│ ║ l.7: let foo = f => f 1 58 | //│ ║ ^^^ 59 | //│ ╟── from reference: 60 | //│ ║ l.7: let foo = f => f 1 61 | //│ ╙── ^ 62 | //│ res: error 63 | -------------------------------------------------------------------------------- /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/MixinCapture.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | :js 4 | class Lit(n: Int) 5 | mixin EvalAddLit { 6 | fun eval(e) = 7 | if e is 8 | Lit(n) then n 9 | } 10 | //│ class Lit(n: Int) 11 | //│ mixin EvalAddLit() { 12 | //│ fun eval: Lit -> Int 13 | //│ } 14 | //│ // Prelude 15 | //│ let res; 16 | //│ class TypingUnit { 17 | //│ #Lit; 18 | //│ constructor() { 19 | //│ } 20 | //│ EvalAddLit(base) { 21 | //│ const outer = this; 22 | //│ return (class EvalAddLit extends base { 23 | //│ constructor(...rest) { 24 | //│ super(...rest); 25 | //│ } 26 | //│ eval(e) { 27 | //│ return ((() => { 28 | //│ let a; 29 | //│ return (a = e, a instanceof outer.Lit.class ? ((n) => n)(e.n) : (() => { 30 | //│ throw new Error("non-exhaustive case expression"); 31 | //│ })()); 32 | //│ })()); 33 | //│ } 34 | //│ }); 35 | //│ } 36 | //│ get Lit() { 37 | //│ const outer = this; 38 | //│ if (this.#Lit === undefined) { 39 | //│ class Lit { 40 | //│ #n; 41 | //│ get n() { return this.#n; } 42 | //│ constructor(n) { 43 | //│ this.#n = n; 44 | //│ } 45 | //│ }; 46 | //│ this.#Lit = ((n) => Object.freeze(new Lit(n))); 47 | //│ this.#Lit.class = Lit; 48 | //│ } 49 | //│ return this.#Lit; 50 | //│ } 51 | //│ } 52 | //│ const typing_unit = new TypingUnit; 53 | //│ globalThis.Lit = typing_unit.Lit; 54 | //│ globalThis.EvalAddLit = ((base) => typing_unit.EvalAddLit(base)); 55 | //│ // End of generated code 56 | 57 | module TestLang extends EvalAddLit 58 | //│ module TestLang { 59 | //│ fun eval: Lit -> Int 60 | //│ } 61 | 62 | TestLang.eval(Lit(0)) 63 | //│ Int 64 | //│ res 65 | //│ = 0 66 | 67 | 68 | -------------------------------------------------------------------------------- /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 | fun 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 | //│ = [Function: foo1] 30 | 31 | 32 | // FIXME: returns a thunk 33 | fun main = 34 | log("Hello") 35 | main 36 | //│ fun main: undefined 37 | //│ undefined 38 | //│ res 39 | //│ = [Function: main] 40 | 41 | fun main = 42 | log("Hello") 43 | //│ fun main: undefined 44 | 45 | main 46 | //│ undefined 47 | //│ res 48 | //│ = undefined 49 | //│ // Output 50 | //│ Hello 51 | 52 | 53 | fun main = 54 | mixin B { log(1) } 55 | log(0) 56 | module M extends B 57 | log(2) 58 | main 59 | //│ fun main: undefined 60 | //│ undefined 61 | //│ res 62 | //│ = [Function: main2] 63 | 64 | -------------------------------------------------------------------------------- /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/SortClass.mls: -------------------------------------------------------------------------------- 1 | // Simple one 2 | :js 3 | class B: A 4 | class A 5 | //│ Defined class B 6 | //│ Defined class A 7 | //│ // Prelude 8 | //│ let res; 9 | //│ class A {} 10 | //│ class B extends A { 11 | //│ constructor(fields) { 12 | //│ super(fields); 13 | //│ } 14 | //│ } 15 | //│ // End of generated code 16 | 17 | :js 18 | class E: D 19 | class D: C 20 | class C 21 | //│ Defined class E 22 | //│ Defined class D 23 | //│ Defined class C 24 | //│ // Prelude 25 | //│ class C {} 26 | //│ class D extends C { 27 | //│ constructor(fields) { 28 | //│ super(fields); 29 | //│ } 30 | //│ } 31 | //│ class E extends D { 32 | //│ constructor(fields) { 33 | //│ super(fields); 34 | //│ } 35 | //│ } 36 | //│ // End of generated code 37 | 38 | :js 39 | class F: { x: int } & G 40 | class G: { y: int } & H 41 | class K 42 | class H: { b: int } 43 | class I: J 44 | class J 45 | //│ Defined class F 46 | //│ Defined class G 47 | //│ Defined class K 48 | //│ Defined class H 49 | //│ Defined class I 50 | //│ Defined class J 51 | //│ // Prelude 52 | //│ class H { 53 | //│ constructor(fields) { 54 | //│ this.b = fields.b; 55 | //│ } 56 | //│ } 57 | //│ class J {} 58 | //│ class K {} 59 | //│ class G extends H { 60 | //│ constructor(fields) { 61 | //│ super(fields); 62 | //│ this.y = fields.y; 63 | //│ } 64 | //│ } 65 | //│ class I extends J { 66 | //│ constructor(fields) { 67 | //│ super(fields); 68 | //│ } 69 | //│ } 70 | //│ class F extends G { 71 | //│ constructor(fields) { 72 | //│ super(fields); 73 | //│ this.x = fields.x; 74 | //│ } 75 | //│ } 76 | //│ // End of generated code 77 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/TrickyTerms.mls: -------------------------------------------------------------------------------- 1 | 2 | // To generate the prelude without printing it in the next test case 3 | succ 1 4 | //│ res: int 5 | //│ = 2 6 | 7 | :js 8 | fun ((x, y)) -> x 9 | //│ // Query 1 10 | //│ res = (([ 11 | //│ x, 12 | //│ y 13 | //│ ]) => x); 14 | //│ // End of generated code 15 | //│ res: ('a, anything,) -> 'a 16 | //│ = [Function: res] 17 | 18 | :js 19 | fun {x = 1} -> 0 20 | res { x = 1 } 21 | //│ // Query 1 22 | //│ res = (({ x }) => 0); 23 | //│ // Query 2 24 | //│ res = res({ x: 1 }); 25 | //│ // End of generated code 26 | //│ res: {x: 1} -> 0 27 | //│ = [Function: res] 28 | //│ res: 0 29 | //│ = 0 30 | 31 | :js 32 | def f x = case 1 of { 1 -> x } 33 | //│ // Query 1 34 | //│ globalThis.f = function f(x) { 35 | //│ let a; 36 | //│ return (a = 1, a === 1 ? x : (() => { 37 | //│ throw new Error("non-exhaustive case expression"); 38 | //│ })()); 39 | //│ }; 40 | //│ // End of generated code 41 | //│ f: 'a -> 'a 42 | //│ = [Function: f] 43 | 44 | // Top-level `def` shadowing: 45 | :js 46 | def tmp = 1 47 | def tmp = succ tmp 48 | //│ // Query 1 49 | //│ globalThis.tmp = function tmp() { 50 | //│ return 1; 51 | //│ }; 52 | //│ // Query 2 53 | //│ globalThis.tmp1 = function tmp1() { 54 | //│ return succ(tmp()); 55 | //│ }; 56 | //│ // End of generated code 57 | //│ tmp: 1 58 | //│ = [Function: tmp] 59 | //│ tmp: int 60 | //│ = [Function: tmp1] 61 | 62 | // Local shadowing: 63 | :js 64 | def tmp tmp = tmp 65 | tmp (let tmp = 1 in tmp) 66 | let t = tmp in let tmp = 1 in t tmp 67 | //│ // Query 1 68 | //│ globalThis.tmp2 = function tmp2(tmp) { 69 | //│ return tmp; 70 | //│ }; 71 | //│ // Query 2 72 | //│ res = tmp2(((tmp) => tmp)(1)); 73 | //│ // Query 3 74 | //│ res = ((t) => ((tmp) => t(tmp))(1))(tmp2); 75 | //│ // End of generated code 76 | //│ tmp: 'a -> 'a 77 | //│ = [Function: tmp2] 78 | //│ res: 1 79 | //│ = 1 80 | //│ res: 1 81 | //│ = 1 82 | 83 | -------------------------------------------------------------------------------- /shared/src/test/diff/codegen/TrickyWiths.mls: -------------------------------------------------------------------------------- 1 | 2 | () with {} 3 | //│ res: () 4 | //│ = [] 5 | 6 | :js 7 | n = 42 with { x = 1 } 8 | n + n.x 9 | //│ // Query 1 10 | //│ globalThis.n = withConstruct(42, { x: 1 }); 11 | //│ // Query 2 12 | //│ res = n + n.x; 13 | //│ // End of generated code 14 | //│ n: 42 & {x: 1} 15 | //│ = [Number: 42] { x: 1 } 16 | //│ res: int 17 | //│ = 43 18 | 19 | 20 | :js 21 | a = (1,2,3) with {} 22 | //│ // Query 1 23 | //│ globalThis.a = withConstruct([ 24 | //│ 1, 25 | //│ 2, 26 | //│ 3 27 | //│ ], {}); 28 | //│ // End of generated code 29 | //│ a: (1, 2, 3,) 30 | //│ = [ 1, 2, 3 ] 31 | 32 | :escape 33 | def a: nothing // unsound escape hatch 34 | //│ a: nothing 35 | //│ = 36 | 37 | a.length 38 | a.map(fun x -> x + 1) 39 | //│ res: nothing 40 | //│ = 3 41 | //│ res: nothing 42 | //│ = [ 2, 3, 4 ] 43 | 44 | 45 | :js 46 | ax = (1,2,3) with {x = 4} 47 | //│ // Query 1 48 | //│ globalThis.ax = withConstruct([ 49 | //│ 1, 50 | //│ 2, 51 | //│ 3 52 | //│ ], { x: 4 }); 53 | //│ // End of generated code 54 | //│ ax: (1, 2, 3,) & {x: 4} 55 | //│ = [ 1, 2, 3, x: 4 ] 56 | 57 | ax.x + 1 58 | //│ res: int 59 | //│ = 5 60 | 61 | 62 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp-lit/Jim.mls: -------------------------------------------------------------------------------- 1 | 2 | :NoRecursiveTypes 3 | 4 | 5 | // TODO also try stuff from his intersection type systems 6 | 7 | 8 | // ============ A Polar Type System (System P) ============ 9 | 10 | // λf. f (λx. x) 11 | fun f -> f (fun x -> x) 12 | //│ res: ((forall 'a. 'a -> 'a) -> 'b) -> 'b 13 | //│ = [Function: res] 14 | 15 | // λy. y y 16 | fun y -> y y 17 | //│ res: ('a -> 'b & 'a) -> 'b 18 | //│ = [Function: res] 19 | 20 | // Typeable in P; not in ML nor I2: 21 | // (λf. f (λx. x)) (λy. y y) 22 | (fun f -> f (fun x -> x)) (fun y -> y y) 23 | //│ res: 'a -> 'a 24 | //│ = [Function (anonymous)] 25 | 26 | 27 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp-lit/LambdaForallI.mls: -------------------------------------------------------------------------------- 1 | 2 | 3 | // A Dependently Typed Calculus with Polymorphic Subtyping 4 | // https://i.cs.hku.hk/~bruno/papers/scp2021.pdf 5 | 6 | // callcc’ : ∀a:⋆. ((∀b:⋆. a → b) → a) → a 7 | // callcc : ∀a:⋆.∀b:⋆. ((a → b) → a) → a 8 | // callcc = callcc’ 9 | 10 | def callcc' : ((forall 'b. 'a -> 'b) -> 'a) -> 'a 11 | //│ callcc': (('a -> nothing) -> 'a) -> 'a 12 | //│ = 13 | 14 | def callcc : (('a -> 'b) -> 'a) -> 'a 15 | //│ callcc: (('a -> nothing) -> 'a) -> 'a 16 | //│ = 17 | 18 | callcc = callcc' 19 | //│ (('a -> nothing) -> 'a) -> 'a 20 | //│ <: callcc: 21 | //│ (('a -> nothing) -> 'a) -> 'a 22 | //│ = 23 | //│ callcc' is not implemented 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /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 A1 = forall 'S. 'S -> ('S | Sid) 8 | //│ Defined type alias A1 9 | 10 | 11 | 12 | def a: Sid -> Sid 13 | //│ a: Sid -> Sid 14 | 15 | a = error : A1 16 | //│ A1 17 | //│ <: a: 18 | //│ Sid -> Sid 19 | 20 | 21 | // def f: A1 -> Sid 22 | def f: A1 -> A1 23 | //│ f: A1 -> A1 24 | 25 | def f (x: A1) = x id 26 | //│ A1 -> ('a -> 'a | Sid) 27 | //│ <: f: 28 | //│ A1 -> A1 29 | 30 | // def f: A1 -> Sid 31 | def f: A1 -> A1 32 | //│ f: A1 -> A1 33 | 34 | def f (x: Sid -> Sid) = x (fun y -> y) 35 | //│ (Sid -> Sid) -> Sid 36 | //│ <: f: 37 | //│ A1 -> A1 38 | 39 | 40 | type A2 = forall 'a. (('a | Sid) -> 'a) -> 'a -> ('a | Sid) 41 | type A3 = (Sid -> Sid) -> Sid -> Sid 42 | //│ Defined type alias A2 43 | //│ Defined type alias A3 44 | 45 | error : A2 : A3 46 | //│ res: A3 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp/FCPTony3.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | :NoConstrainedTypes 3 | :NoCycleCheck 4 | 5 | 6 | // * ========= Minimized: ========= 7 | 8 | const a b = a 9 | // const x y = y 10 | //│ const: 'a -> anything -> 'a 11 | //│ = [Function: const1] 12 | 13 | def id2: 'A -> 'A 14 | id2 = id 15 | //│ id2: 'A -> 'A 16 | //│ = 17 | //│ 'a -> 'a 18 | //│ <: id2: 19 | //│ 'A -> 'A 20 | //│ = [Function: id] 21 | 22 | def f y = (fun h -> h (h (h (const y)))) id2 23 | //│ f: 'a -> anything -> 'a 24 | //│ = [Function: f] 25 | 26 | // * This used to be accepted! 27 | :e 28 | f {} {} {} 29 | //│ ╔══[ERROR] Type mismatch in application: 30 | //│ ║ l.28: f {} {} {} 31 | //│ ║ ^^^^^^^^^^ 32 | //│ ╟── record literal of type `anything` is not a function 33 | //│ ║ l.28: f {} {} {} 34 | //│ ║ ^^ 35 | //│ ╟── but it flows into application with expected type `anything -> ?a` 36 | //│ ║ l.28: f {} {} {} 37 | //│ ╙── ^^^^^^^ 38 | //│ res: error 39 | //│ Runtime error: 40 | //│ TypeError: f(...)(...) is not a function 41 | 42 | 43 | // * ========= Original: ========= 44 | 45 | def f y = (fun h -> h (h (h (fun _ -> y)))) id {} 46 | //│ f: 'a -> 'a 47 | //│ = [Function: f1] 48 | 49 | :e 50 | f {} {} 51 | //│ ╔══[ERROR] Type mismatch in application: 52 | //│ ║ l.50: f {} {} 53 | //│ ║ ^^^^^^^ 54 | //│ ╟── record literal of type `anything` is not a function 55 | //│ ║ l.50: f {} {} 56 | //│ ║ ^^ 57 | //│ ╟── but it flows into application with expected type `anything -> ?a` 58 | //│ ║ l.50: f {} {} 59 | //│ ╙── ^^^^ 60 | //│ res: error 61 | //│ Runtime error: 62 | //│ TypeError: f1(...) is not a function 63 | 64 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp/ForallTerms.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | 3 | 4 | 5 | (forall 'A. fun (x: 'A) -> x) : forall 'X. 'X -> 'X 6 | //│ res: 'X -> 'X 7 | //│ = [Function: res] 8 | 9 | 10 | f = forall 'A. fun (x: 'A) -> x 11 | //│ f: 'A -> 'A 12 | //│ = [Function: f] 13 | 14 | f 0 15 | f true 16 | f: forall 'X. 'X -> 'X 17 | //│ res: 0 18 | //│ = 0 19 | //│ res: true 20 | //│ = true 21 | //│ res: 'X -> 'X 22 | //│ = [Function: f] 23 | 24 | 25 | r = { f = forall 'A. fun (x: 'A) -> x } 26 | //│ r: {f: forall 'A. 'A -> 'A} 27 | //│ = { f: [Function: f] } 28 | 29 | r.f 0 30 | r.f true 31 | //│ res: 0 32 | //│ = 0 33 | //│ res: true 34 | //│ = true 35 | 36 | 37 | def k1(f: forall 'X. 'X -> 'X) = (f 0, f true) 38 | //│ k1: (forall 'X. 'X -> 'X) -> (0, true,) 39 | //│ = [Function: k1] 40 | 41 | k1 f 42 | //│ res: (0, true,) 43 | //│ = [ 0, true ] 44 | 45 | k1 r.f 46 | //│ res: (0, true,) 47 | //│ = [ 0, true ] 48 | 49 | 50 | def k2(f) = (f 0, f true) 51 | //│ k2: (0 -> 'a & true -> 'b) -> ('a, 'b,) 52 | //│ = [Function: k2] 53 | 54 | k2 f 55 | //│ res: (0, true,) 56 | //│ = [ 0, true ] 57 | 58 | k2 r.f 59 | //│ res: (0, true,) 60 | //│ = [ 0, true ] 61 | 62 | 63 | 64 | // * Explicitly-bound type variables are rigid (like in OCaml) 65 | :e 66 | f = forall 'A. fun (x: 'A) -> x + 1 67 | //│ ╔══[ERROR] Type mismatch in operator application: 68 | //│ ║ l.66: f = forall 'A. fun (x: 'A) -> x + 1 69 | //│ ║ ^^^ 70 | //│ ╟── rigid type variable of type `'A` is not an instance of type `int` 71 | //│ ║ l.66: f = forall 'A. fun (x: 'A) -> x + 1 72 | //│ ║ ^^ 73 | //│ ╟── but it flows into reference with expected type `int` 74 | //│ ║ l.66: f = forall 'A. fun (x: 'A) -> x + 1 75 | //│ ╙── ^ 76 | //│ f: anything -> (error | int) 77 | //│ = [Function: f1] 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp/Inst.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | 3 | 4 | i = id! id! 5 | //│ i: 'a -> 'a 6 | //│ = [Function: id] 7 | 8 | i i! i 1 9 | //│ res: 1 10 | //│ = 1 11 | 12 | 13 | :NoJS 14 | 15 | 16 | { x = id } 17 | //│ res: {x: forall 'a. 'a -> 'a} 18 | 19 | { x = id! } 20 | //│ res: {x: 'a -> 'a} 21 | 22 | { x = id id! } 23 | //│ res: {x: 'a -> 'a} 24 | 25 | { x = id! id } 26 | //│ res: {x: forall 'a. 'a -> 'a} 27 | 28 | { x = id! id! } 29 | //│ res: {x: 'a -> 'a} 30 | 31 | :w 32 | def foo x = x! 33 | //│ ╔══[WARNING] Inferred type `?a` of this reference cannot be instantiated 34 | //│ ║ l.32: def foo x = x! 35 | //│ ╙── ^ 36 | //│ foo: 'a -> 'a 37 | 38 | 39 | type Id = forall 'a. 'a -> 'a 40 | //│ Defined type alias Id 41 | 42 | 43 | def foo (x: Id) = x! 44 | //│ foo: Id -> 'a -> 'a 45 | 46 | def foo (x: Id) = x! x! 47 | //│ foo: Id -> 'a -> 'a 48 | 49 | def foo (x: Id) = x! x 50 | //│ foo: Id -> Id 51 | 52 | def foo (x: Id) = x x! 53 | //│ foo: Id -> 'a -> 'a 54 | 55 | def foo (x: Id) = x x 56 | //│ foo: Id -> Id 57 | 58 | 59 | // * Note that `this` selections currently don't provide a concrete type in method typing 60 | :w 61 | class A: { f: Id } 62 | method F x = x 63 | method G1 = this.f 64 | method G2 = this.f! 65 | method G3 = (this.f: Id)! 66 | //│ ╔══[WARNING] Inferred type `?f` of this field selection cannot be instantiated 67 | //│ ║ l.64: method G2 = this.f! 68 | //│ ╙── ^^^^^^ 69 | //│ Defined class A 70 | //│ Defined A.F: A -> 'a -> 'a 71 | //│ Defined A.G1: A -> Id 72 | //│ Defined A.G2: A -> Id 73 | //│ Defined A.G3: A -> 'a -> 'a 74 | 75 | 76 | -------------------------------------------------------------------------------- /shared/src/test/diff/fcp/Min1_ex_shallow.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | 3 | 4 | type Sid = forall 'a. 'a -> 'a 5 | //│ Defined type alias Sid 6 | 7 | type A1' = forall 'a. (('a | Sid) -> 'a) -> anything 8 | // type A1' = (Sid -> Sid) -> Sid -> Sid 9 | //│ Defined type alias A1' 10 | 11 | def a1' : ((forall 'a. 'a -> 'a) -> anything) -> nothing 12 | //│ a1': ((forall 'a. 'a -> 'a) -> anything) -> nothing 13 | //│ = 14 | 15 | // * Fails due to premature LHS instantiation (TODO improve) 16 | // :d 17 | :e 18 | a1' : A1' 19 | //│ ╔══[ERROR] Type error in type ascription 20 | //│ ║ l.18: a1' : A1' 21 | //│ ║ ^^^ 22 | //│ ╟── type variable `'a` leaks out of its scope 23 | //│ ║ l.4: type Sid = forall 'a. 'a -> 'a 24 | //│ ║ ^^ 25 | //│ ╟── back into type variable `'a` 26 | //│ ║ l.4: type Sid = forall 'a. 'a -> 'a 27 | //│ ╙── ^^ 28 | //│ res: A1' 29 | //│ = 30 | //│ a1' is not implemented 31 | 32 | def a2' (x: A1') = 0 33 | //│ a2': A1' -> 0 34 | //│ = [Function: a2$] 35 | 36 | :e 37 | def a0' = a2' a1' 38 | //│ ╔══[ERROR] Type error in application 39 | //│ ║ l.37: def a0' = a2' a1' 40 | //│ ║ ^^^^^^^ 41 | //│ ╟── type variable `'a` leaks out of its scope 42 | //│ ║ l.4: type Sid = forall 'a. 'a -> 'a 43 | //│ ║ ^^ 44 | //│ ╟── back into type variable `'a` 45 | //│ ║ l.4: type Sid = forall 'a. 'a -> 'a 46 | //│ ╙── ^^ 47 | //│ a0': 0 | error 48 | //│ = 49 | //│ a1' is not implemented 50 | 51 | -------------------------------------------------------------------------------- /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/Paper.mls: -------------------------------------------------------------------------------- 1 | :NoJS 2 | :NoRecursiveTypes 3 | :NoConstrainedTypes 4 | 5 | 6 | I x = x 7 | K x y = x 8 | auto x = x x 9 | monster = (fun y -> (let tmp = y I in y K)) auto 10 | //│ I: 'a -> 'a 11 | //│ K: 'a -> anything -> 'a 12 | //│ auto: ('a -> 'b & 'a) -> 'b 13 | //│ monster: anything -> 'a -> anything -> 'a 14 | 15 | monster{} 16 | //│ res: 'a -> anything -> 'a 17 | 18 | fun y -> (let tmp = y I in y K) 19 | //│ res: ((forall 'a. 'a -> 'a) -> anything & (forall 'b. 'b -> anything -> 'b) -> 'c) -> 'c 20 | 21 | 22 | -------------------------------------------------------------------------------- /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._1 14 | fooid._2 15 | //│ res: 1 16 | //│ = undefined 17 | //│ res: true 18 | //│ = undefined 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/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/gadt/Exp1.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Exp[A]: Pair | Lit 5 | class Lit(n: Int) extends Exp[Int] 6 | class Pair[L, R](lhs: L, rhs: R) extends Exp[(L, R)] 7 | //│ class Exp[A]: Lit | Pair[anything, anything] 8 | //│ class Lit(n: Int) extends Exp 9 | //│ class Pair[L, R](lhs: L, rhs: R) extends Exp 10 | 11 | 12 | fun f(p: Pair['a, 'b]) = p.lhs 13 | //│ fun f: forall 'a 'b. (p: Pair['a, 'b],) -> 'a 14 | 15 | 16 | fun f(e) = if e is 17 | Pair(l, r) then [l, r] 18 | //│ fun f: forall 'lhs 'rhs. Pair['lhs, 'rhs] -> ('lhs, 'rhs,) 19 | // f: (Exp['a] & Pair) -> 0 20 | 21 | 22 | fun f(e) = if e is 23 | Pair(l, r) then [l, r] 24 | Lit(n) then n 25 | //│ fun f: forall 'lhs 'rhs. (Lit | Pair['lhs, 'rhs]) -> (('lhs, 'rhs,) | Int) 26 | 27 | (e: Exp['X]) => f(e) 28 | //│ (e: Exp['X],) -> ((??L, ??R,) | Int) 29 | //│ res 30 | //│ = [Function: res] 31 | 32 | 33 | :e // TODO support 34 | fun f(e) = if e is 35 | Pair['a, 'b](l, r) then [l, r] 36 | //│ ╔══[ERROR] illegal pattern 37 | //│ ║ l.35: Pair['a, 'b](l, r) then [l, r] 38 | //│ ╙── ^^^^^^^^^^^^^^^^^^ 39 | //│ fun f: anything -> error 40 | //│ Code generation encountered an error: 41 | //│ if expression was not desugared 42 | 43 | 44 | :e // TODO support 45 | fun f(e) = if e is 46 | Pair(l: a, r) then 47 | fun f(x: a) = x 48 | f(l) 49 | //│ ╔══[ERROR] type identifier not found: a 50 | //│ ║ l.47: fun f(x: a) = x 51 | //│ ╙── ^ 52 | //│ ╔══[ERROR] identifier not found: l 53 | //│ ║ l.48: f(l) 54 | //│ ╙── ^ 55 | //│ fun f: Pair[anything, anything] -> error 56 | //│ Code generation encountered an error: 57 | //│ unresolved symbol l 58 | // fun f: forall 'lhs 'rhs. Pair['lhs, 'rhs] -> ('lhs, 'rhs,) 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlf-examples/ex_concrete.mls: -------------------------------------------------------------------------------- 1 | :NoRecursiveTypes 2 | 3 | // type mylist ('b) = Nil | Cons of ('b * mylist ('b)) 4 | // ;; 5 | class Nil 6 | class Cons[a]: { head: a; tail: List[a] } 7 | type List[a] = Nil | Cons[a] 8 | Nil = Nil {} 9 | Cons (head, tail) = Cons { head; tail } 10 | //│ Defined class Nil 11 | //│ Defined class Cons[+a] 12 | //│ Defined type alias List[+a] 13 | //│ Nil: Nil 14 | //│ = Nil {} 15 | //│ Cons: ('head & 'a, List['a] & 'tail,) -> (Cons['a] with {head: 'head, tail: 'tail}) 16 | //│ = [Function: Cons1] 17 | 18 | // let un = Nil ;; 19 | // let deux = Nil ;; 20 | // let trois = Cons (10, un) ;; 21 | // let quatre = Cons ("ok", deux) ;; 22 | // let cinq = Cons ("zozo", quatre) ;; 23 | un = Nil 24 | deux = Nil 25 | trois = Cons (10, un) 26 | quatre = Cons ("ok", deux) 27 | cinq = Cons ("zozo", quatre) 28 | //│ un: Nil 29 | //│ = Nil {} 30 | //│ deux: Nil 31 | //│ = Nil {} 32 | //│ trois: Cons[10] with {tail: Nil} 33 | //│ = Cons { head: 10, tail: Nil {} } 34 | //│ quatre: Cons["ok"] with {tail: Nil} 35 | //│ = Cons { head: 'ok', tail: Nil {} } 36 | //│ cinq: Cons["ok" | "zozo"] with {head: "zozo", tail: Cons["ok"] with {tail: Nil}} 37 | //│ = Cons { head: 'zozo', tail: Cons { head: 'ok', tail: Nil {} } } 38 | 39 | // let id x = x 40 | def id x = x 41 | //│ id: 'a -> 'a 42 | //│ = [Function: id] 43 | 44 | // let rec mymap f l = 45 | // begin match l with 46 | // | Nil -> Nil 47 | // | Cons (car,cdr) -> Cons (f car, mymap f cdr) 48 | // end 49 | :RecursiveTypes // needed for this recursive def 50 | rec def map f l = case l of 51 | { Nil -> Nil 52 | | Cons -> Cons (f l.head, map f l.tail) 53 | } 54 | //│ map: ('head -> 'head0) -> 'a -> 'tail 55 | //│ where 56 | //│ 'tail :> (Cons['head0] with {tail: 'tail}) | Nil 57 | //│ 'a <: (Cons[?] with {head: 'head, tail: 'a}) | Nil 58 | //│ = [Function: map] 59 | :NoRecursiveTypes 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/Arrays2.mls: -------------------------------------------------------------------------------- 1 | :ShowRelativeLineNums 2 | 3 | class MyArray[A]: { size: int } 4 | method Set: (int, A) -> () 5 | method Get: int -> A 6 | //│ Defined class MyArray[=A] 7 | //│ Declared MyArray.Set: MyArray['A] -> (int, 'A,) -> () 8 | //│ Declared MyArray.Get: MyArray['A] -> int -> 'A 9 | 10 | 11 | 12 | class Dummy[A]: MyArray[A] & { size: 0 } 13 | method Set (i, a) = () 14 | method Get i = error 15 | //│ Defined class Dummy[=A] 16 | //│ Defined Dummy.Set: Dummy['A] -> (anything, anything,) -> () 17 | //│ Defined Dummy.Get: Dummy['A] -> anything -> nothing 18 | 19 | 20 | dummy = Dummy { size = 0 } 21 | //│ dummy: Dummy['A] 22 | //│ = Dummy { size: 0 } 23 | 24 | dummy: MyArray[int] 25 | //│ res: MyArray[int] 26 | //│ = Dummy { size: 0 } 27 | 28 | 29 | def ty4B: MyArray[MyArray[MyArray['a]]] as 'a 30 | //│ ty4B: 'a 31 | //│ where 32 | //│ 'a := MyArray[MyArray[MyArray['a]]] 33 | //│ = 34 | 35 | 36 | 37 | 38 | :e 39 | MyArray{ size = 0 } 40 | //│ ╔══[ERROR] Instantiation of an abstract type is forbidden 41 | //│ ║ l.+1: MyArray{ size = 0 } 42 | //│ ║ ^^^^^^^ 43 | //│ ╟── Note that class MyArray is abstract: 44 | //│ ║ l.3: class MyArray[A]: { size: int } 45 | //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^ 46 | //│ ╟── Hint: method Set is abstract 47 | //│ ║ l.4: method Set: (int, A) -> () 48 | //│ ║ ^^^^^^^^^^^^^^^^^^^ 49 | //│ ╟── Hint: method Get is abstract 50 | //│ ║ l.5: method Get: int -> A 51 | //│ ╙── ^^^^^^^^^^^^^ 52 | //│ res: error 53 | //│ = MyArray { size: 0 } 54 | 55 | 56 | -------------------------------------------------------------------------------- /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 'z 'y 'b 'c '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: ((Foo2\x with {y: 'y}) | Foo[?] & {z: 'y} & ~#Foo2) -> '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/Basics.mls: -------------------------------------------------------------------------------- 1 | 2 | x = 1 3 | //│ x: 1 4 | //│ = 1 5 | 6 | 1 7 | //│ res: 1 8 | //│ = 1 9 | 10 | 1; 11 | 2 12 | //│ res: 1 13 | //│ = 1 14 | //│ res: 2 15 | //│ = 2 16 | 17 | x = 1; 18 | 2 19 | //│ x: 1 20 | //│ = 1 21 | //│ res: 2 22 | //│ = 2 23 | 24 | x = 1;; 25 | 2 26 | //│ x: 1 27 | //│ = 1 28 | //│ res: 2 29 | //│ = 2 30 | 31 | x = 1 32 | y = 2 33 | //│ x: 1 34 | //│ = 1 35 | //│ y: 2 36 | //│ = 2 37 | 38 | 1 39 | 2 40 | 3 41 | //│ res: 1 42 | //│ = 1 43 | //│ res: 2 44 | //│ = 2 45 | //│ res: 3 46 | //│ = 3 47 | 48 | 1 49 | x = add x 1 50 | //│ res: 1 51 | //│ = 1 52 | //│ x: int 53 | //│ = 2 54 | 55 | x = 1 56 | x 57 | y = 2 58 | y 59 | z = x + y 60 | //│ x: 1 61 | //│ = 1 62 | //│ res: 1 63 | //│ = 1 64 | //│ y: 2 65 | //│ = 2 66 | //│ res: 2 67 | //│ = 2 68 | //│ z: int 69 | //│ = 3 70 | 71 | :e 72 | 1 73 | 2 74 | //│ ╔══[ERROR] Type mismatch in application: 75 | //│ ║ l.72: 1 76 | //│ ║ ^ 77 | //│ ║ l.73: 2 78 | //│ ║ ^^ 79 | //│ ╟── integer literal of type `1` is not a function 80 | //│ ║ l.72: 1 81 | //│ ╙── ^ 82 | //│ res: error 83 | //│ Runtime error: 84 | //│ TypeError: 1 is not a function 85 | 86 | def f x y z = add x y 87 | //│ f: int -> int -> anything -> int 88 | //│ = [Function: f] 89 | 90 | 91 | :e 92 | :ge 93 | def f (x y z) = add x y 94 | //│ ╔══[ERROR] Unsupported pattern shape: 95 | //│ ║ l.93: def f (x y z) = add x y 96 | //│ ╙── ^^^^^ 97 | //│ f: error -> int 98 | //│ Code generation encountered an error: 99 | //│ term App(App(Var(x), Tup(_: Var(y))), Tup(_: Var(z))) is not a valid pattern 100 | 101 | f 1 102 | //│ res: int 103 | //│ = [Function (anonymous)] 104 | -------------------------------------------------------------------------------- /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/ExplicitVariance.mls: -------------------------------------------------------------------------------- 1 | 2 | // TODO have a way of specifying the variance explicitly, 3 | // because it would be too expensive to infer it when it's needed in method implementations 4 | // (we'd have to re-type-check methods at every iteration of the fixed point) 5 | 6 | // class Covar[out A] 7 | 8 | :e 9 | :w 10 | class Covar[A] 11 | method CovarMtd = 12 | let tmp = (error : Covar[{ x: int }]) : Covar[{}] 13 | in () 14 | //│ ╔══[ERROR] Type mismatch in type ascription: 15 | //│ ║ l.12: let tmp = (error : Covar[{ x: int }]) : Covar[{}] 16 | //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 17 | //│ ╟── type `anything` does not have field 'x' 18 | //│ ║ l.12: let tmp = (error : Covar[{ x: int }]) : Covar[{}] 19 | //│ ║ ^^ 20 | //│ ╟── Note: constraint arises from record type: 21 | //│ ║ l.12: let tmp = (error : Covar[{ x: int }]) : Covar[{}] 22 | //│ ╙── ^^^^^^^^^^ 23 | //│ Defined class Covar[±A] 24 | //│ Defined Covar.CovarMtd: Covar[?] -> () 25 | //│ ╔══[WARNING] Type definition Covar has bivariant type parameters: 26 | //│ ║ l.10: class Covar[A] 27 | //│ ║ ^^^^^ 28 | //│ ╟── A is irrelevant and may be removed 29 | //│ ║ l.10: class Covar[A] 30 | //│ ╙── ^ 31 | 32 | :re 33 | (error : Covar[{ x: int }]) : Covar[{}] 34 | //│ res: Covar[?] 35 | //│ Runtime error: 36 | //│ Error: unexpected runtime error 37 | 38 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/FatNegs.mls: -------------------------------------------------------------------------------- 1 | 2 | class Lit: { n: int } 3 | //│ Defined class Lit 4 | 5 | // TODO should eventually print these differently or make them truly equivalent 6 | // by making #Lit <: Lit, i.e. making the tags include the fields implicitly. 7 | 8 | // * Q: What happens if one writes ~Lit instead of ~#Lit? 9 | def nc: ~Lit 10 | def nt: ~#Lit 11 | //│ nc: ~Lit 12 | //│ = 13 | //│ nt: ~Lit 14 | //│ = 15 | 16 | // * A: It's not equivalent. 17 | 18 | // * Demonstrates that the negated tag is a subtype of the whole negated class: 19 | nc = nt 20 | //│ ~Lit 21 | //│ <: nc: 22 | //│ ~Lit 23 | //│ = 24 | //│ nt is not implemented 25 | 26 | // * Demonstrates that the negated tag is not a supertype of the whole negated class: 27 | :e 28 | nt = nc 29 | //│ ~Lit 30 | //│ <: nt: 31 | //│ ~Lit 32 | //│ ╔══[ERROR] Type mismatch in def definition: 33 | //│ ║ l.28: nt = nc 34 | //│ ║ ^^^^^^^ 35 | //│ ╟── type `Lit` does not have field 'n' 36 | //│ ║ l.9: def nc: ~Lit 37 | //│ ║ ^^^^ 38 | //│ ╟── but it flows into reference with expected type `{n: int}` 39 | //│ ║ l.28: nt = nc 40 | //│ ║ ^^ 41 | //│ ╟── Note: constraint arises from record type: 42 | //│ ║ l.2: class Lit: { n: int } 43 | //│ ║ ^^^^^^^^^^ 44 | //│ ╟── from type negation: 45 | //│ ║ l.10: def nt: ~#Lit 46 | //│ ╙── ^^^^^ 47 | //│ = 48 | //│ nc and nt are not implemented 49 | 50 | nc = nc 51 | //│ ~Lit 52 | //│ <: nc: 53 | //│ ~Lit 54 | //│ = 55 | //│ nc and nt are not implemented 56 | 57 | nt = nt 58 | //│ ~Lit 59 | //│ <: nt: 60 | //│ ~Lit 61 | //│ = 62 | //│ nt, nc and nt are not implemented 63 | 64 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/FunnySubsumptions.mls: -------------------------------------------------------------------------------- 1 | :NoJS 2 | 3 | trait C 4 | trait D 5 | trait S 6 | trait T 7 | trait U 8 | //│ Defined trait C 9 | //│ Defined trait D 10 | //│ Defined trait S 11 | //│ Defined trait T 12 | //│ Defined trait U 13 | 14 | 15 | def A0: (C | {x:T}) & (D | {y:S}) 16 | def B0: C&{y:S} | D&{x:T} | {x: T; y: S} 17 | //│ A0: D & {x: T} | {x: T, y: S} | C & {y: S} | C & D 18 | //│ B0: {x: T, y: S} | D & {x: T} | C & {y: S} 19 | 20 | :stats 21 | A0 = B0 22 | //│ {x: T, y: S} | D & {x: T} | C & {y: S} 23 | //│ <: A0: 24 | //│ D & {x: T} | {x: T, y: S} | C & {y: S} | C & D 25 | //│ constrain calls : 1 26 | //│ annoying calls : 0 27 | //│ subtyping calls : 203 28 | 29 | :stats 30 | B0 = A0 31 | //│ D & {x: T} | {x: T, y: S} | C & {y: S} | C & D 32 | //│ <: B0: 33 | //│ {x: T, y: S} | D & {x: T} | C & {y: S} 34 | //│ constrain calls : 2 35 | //│ annoying calls : 32 36 | //│ subtyping calls : 318 37 | 38 | 39 | def A1: C & {x : T} | D & {y : U} 40 | def B1: (C | D) & (C | {y : U}) & (D | {x : T}) 41 | //│ A1: C & {x: T} | D & {y: U} 42 | //│ B1: C & {x: T} | D & {y: U} | C & D 43 | 44 | :stats 45 | A1 = B1 46 | //│ C & {x: T} | D & {y: U} | C & D 47 | //│ <: A1: 48 | //│ C & {x: T} | D & {y: U} 49 | //│ constrain calls : 2 50 | //│ annoying calls : 13 51 | //│ subtyping calls : 276 52 | 53 | :stats 54 | B1 = A1 55 | //│ C & {x: T} | D & {y: U} 56 | //│ <: B1: 57 | //│ C & {x: T} | D & {y: U} | C & D 58 | //│ constrain calls : 1 59 | //│ annoying calls : 0 60 | //│ subtyping calls : 184 61 | 62 | 63 | -------------------------------------------------------------------------------- /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/Match3.mls: -------------------------------------------------------------------------------- 1 | 2 | class N 3 | class M 4 | //│ Defined class N 5 | //│ Defined class M 6 | 7 | def eval_expr v = 8 | case v of { 9 | | M -> let tmp = v.l in v 10 | | N -> v 11 | } 12 | //│ eval_expr: (M & {l: anything} & 'a | N & 'a) -> 'a 13 | //│ = [Function: eval_expr] 14 | 15 | eval_expr (N {}) 16 | //│ res: N 17 | //│ = N {} 18 | 19 | :e 20 | eval_expr (M {}) 21 | //│ ╔══[ERROR] Type mismatch in application: 22 | //│ ║ l.20: eval_expr (M {}) 23 | //│ ║ ^^^^^^^^^^^^^^^^ 24 | //│ ╟── application of type `M` does not have field 'l' 25 | //│ ║ l.20: eval_expr (M {}) 26 | //│ ║ ^^^^ 27 | //│ ╟── Note: constraint arises from field selection: 28 | //│ ║ l.9: | M -> let tmp = v.l in v 29 | //│ ║ ^^^ 30 | //│ ╟── from reference: 31 | //│ ║ l.8: case v of { 32 | //│ ║ ^ 33 | //│ ╟── Note: class M is defined at: 34 | //│ ║ l.3: class M 35 | //│ ╙── ^ 36 | //│ res: M | error 37 | //│ = M {} 38 | 39 | def eval_expr v = 40 | case v of { 41 | | M -> let tmp = v.l in tmp 42 | | N -> v 43 | } 44 | //│ eval_expr: (M & {l: 'l} | N & 'l) -> 'l 45 | //│ = [Function: eval_expr1] 46 | 47 | eval_expr (N {}) 48 | //│ res: N 49 | //│ = N {} 50 | 51 | :e 52 | eval_expr (M {}) 53 | //│ ╔══[ERROR] Type mismatch in application: 54 | //│ ║ l.52: eval_expr (M {}) 55 | //│ ║ ^^^^^^^^^^^^^^^^ 56 | //│ ╟── application of type `M` does not have field 'l' 57 | //│ ║ l.52: eval_expr (M {}) 58 | //│ ║ ^^^^ 59 | //│ ╟── Note: constraint arises from field selection: 60 | //│ ║ l.41: | M -> let tmp = v.l in tmp 61 | //│ ║ ^^^ 62 | //│ ╟── from reference: 63 | //│ ║ l.40: case v of { 64 | //│ ║ ^ 65 | //│ ╟── Note: class M is defined at: 66 | //│ ║ l.3: class M 67 | //│ ╙── ^ 68 | //│ res: error 69 | //│ = undefined 70 | 71 | -------------------------------------------------------------------------------- /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/OtherErrors.mls: -------------------------------------------------------------------------------- 1 | :AllowTypeErrors 2 | 3 | // Multiline error: 4 | id 5 | id 6 | id 7 | 3 2 8 | //│ ╔══[ERROR] Type mismatch in application: 9 | //│ ║ l.4: id 10 | //│ ║ ^^ 11 | //│ ║ l.5: id 12 | //│ ║ ^^^^ 13 | //│ ║ l.6: id 14 | //│ ║ ^^^^ 15 | //│ ║ l.7: 3 2 16 | //│ ║ ^^^^^ 17 | //│ ╟── integer literal of type `3` is not a function 18 | //│ ║ l.7: 3 2 19 | //│ ║ ^ 20 | //│ ╟── but it flows into application with expected type `2 -> ?a` 21 | //│ ║ l.4: id 22 | //│ ║ ^^ 23 | //│ ║ l.5: id 24 | //│ ║ ^^^^ 25 | //│ ║ l.6: id 26 | //│ ║ ^^^^ 27 | //│ ║ l.7: 3 2 28 | //│ ╙── ^^^ 29 | //│ res: error 30 | 31 | 32 | 1: 1 & int: { x: int; y: string } 33 | //│ ╔══[ERROR] Type mismatch in type ascription: 34 | //│ ║ l.32: 1: 1 & int: { x: int; y: string } 35 | //│ ║ ^ 36 | //│ ╟── type `1` is not a record (expected a record with fields: x, y) 37 | //│ ║ l.32: 1: 1 & int: { x: int; y: string } 38 | //│ ║ ^^^^^^^ 39 | //│ ╟── Note: constraint arises from record type: 40 | //│ ║ l.32: 1: 1 & int: { x: int; y: string } 41 | //│ ╙── ^^^^^^^^^^^^^^^^^^^^^ 42 | //│ res: {x: int, y: string} 43 | 44 | 1: 1 & int: { x: int; y: string } | string 45 | //│ ╔══[ERROR] Type mismatch in type ascription: 46 | //│ ║ l.44: 1: 1 & int: { x: int; y: string } | string 47 | //│ ║ ^ 48 | //│ ╟── type `1` does not match type `string | {x: int, y: string}` 49 | //│ ║ l.44: 1: 1 & int: { x: int; y: string } | string 50 | //│ ║ ^^^^^^^ 51 | //│ ╟── Note: constraint arises from union type: 52 | //│ ║ l.44: 1: 1 & int: { x: int; y: string } | string 53 | //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 54 | //│ res: string | {x: int, y: string} 55 | 56 | -------------------------------------------------------------------------------- /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/PolymorphicExtension.mls: -------------------------------------------------------------------------------- 1 | // * Here we compare to OCaml's polymorphic variants, showing their limitation 2 | 3 | 4 | class Apple 5 | class Banana 6 | //│ Defined class Apple 7 | //│ Defined class Banana 8 | 9 | 10 | // utop # let foo x default otherwise = match x with `Apple -> default | y -> otherwise y ;; 11 | // val foo : ([> `Apple ] as 'a) -> 'b -> ('a -> 'b) -> 'b = 12 | 13 | def foo x default otherwise = case x of { Apple -> default | _ -> otherwise x } 14 | //│ foo: (Apple | 'a & ~#Apple) -> 'b -> ('a -> 'b) -> 'b 15 | //│ = [Function: foo] 16 | 17 | // utop # foo `Apple ;; 18 | // - : '_a -> (_[> `Apple ] -> '_a) -> '_a = 19 | 20 | foo (Apple{}) 21 | //│ res: 'a -> (nothing -> 'a) -> 'a 22 | //│ = [Function (anonymous)] 23 | 24 | // utop # foo `Banana ;; 25 | // - : '_a -> (_[> `Apple | `Banana ] -> '_a) -> '_a = 26 | 27 | foo (Banana{}) 28 | //│ res: 'a -> (Banana -> 'a) -> 'a 29 | //│ = [Function (anonymous)] 30 | 31 | // utop # foo `Banana 0 (function `Banana -> 1) ;; 32 | // Characters 9-27: 33 | // Warning 8: this pattern-matching is not exhaustive. 34 | // Here is an example of a value that is not matched: 35 | // `Apple 36 | // Characters 9-27: 37 | // Warning 8: this pattern-matching is not exhaustive. 38 | // Here is an example of a value that is not matched: 39 | // `Apple 40 | // - : int = 1 41 | 42 | foo (Banana{}) 0 (fun z -> case z of { Banana -> 1 }) 43 | //│ res: 0 | 1 44 | //│ = 1 45 | 46 | // utop # foo `Apple 0 (function `Apple -> 1) ;; 47 | // - : int = 0 48 | 49 | foo (Apple{}) 0 (fun z -> case z of { Apple -> 1 }) 50 | //│ res: 0 | 1 51 | //│ = 0 52 | 53 | foo (Apple{}) 0 (fun z -> z.lol) // z has type `nothing` so we can do whatever we want in this unreachable case 54 | //│ res: 0 55 | //│ = 0 56 | 57 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/RecursiveTypes2.mls: -------------------------------------------------------------------------------- 1 | :NoJS 2 | 3 | 4 | type T1 = { x: T1 & { x: T1 } } 5 | type T2 = { x: T2 } 6 | //│ Defined type alias T1 7 | //│ Defined type alias T2 8 | 9 | :stats 10 | error : T1 : T2 11 | //│ res: T2 12 | //│ constrain calls : 6 13 | //│ annoying calls : 4 14 | //│ subtyping calls : 29 15 | 16 | type T3 = { x: T2 & { x: T3 } | T3 & { x: T2 } } 17 | //│ Defined type alias T3 18 | 19 | :stats 20 | error : T1 : T3 21 | //│ res: T3 22 | //│ constrain calls : 7 23 | //│ annoying calls : 12 24 | //│ subtyping calls : 457 25 | 26 | :stats 27 | error : T2 : T3 28 | //│ res: T3 29 | //│ constrain calls : 10 30 | //│ annoying calls : 12 31 | //│ subtyping calls : 423 32 | 33 | def f: T3 & { x: T1 & 'a } as 'a 34 | //│ f: 'a 35 | //│ where 36 | //│ 'a :> T3 & {x: T1 & 'a} 37 | 38 | :stats 39 | f.x 40 | //│ res: 'a & (T1 & T3 & {x: T2} | T1 & T2 & {x: T3}) 41 | //│ where 42 | //│ 'a :> T3 & {x: T1 & 'a} 43 | //│ constrain calls : 4 44 | //│ annoying calls : 4 45 | //│ subtyping calls : 148 46 | 47 | g = error : T1 & { x: T2 | 'a } as 'a 48 | //│ g: 'a 49 | //│ where 50 | //│ 'a :> T1 & {x: 'a | T2} 51 | 52 | :stats 53 | g.x 54 | //│ res: T1 & {x: T1} & 'a | T1 & T2 & {x: T1} 55 | //│ where 56 | //│ 'a :> T1 & {x: 'a | T2} 57 | //│ constrain calls : 4 58 | //│ annoying calls : 4 59 | //│ subtyping calls : 94 60 | 61 | :stats 62 | f = g 63 | //│ 'a 64 | //│ where 65 | //│ 'a :> T1 & {x: 'a | T2} 66 | //│ <: f: 67 | //│ 'a 68 | //│ where 69 | //│ 'a :> T3 & {x: T1 & 'a} 70 | //│ constrain calls : 48 71 | //│ annoying calls : 60 72 | //│ subtyping calls : 2393 73 | 74 | 75 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Repro.mls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hkust-taco/superoop/29bbb1f26eea191f07a24d051a401730165f3d65/shared/src/test/diff/mlscript/Repro.mls -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Scratch.mls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hkust-taco/superoop/29bbb1f26eea191f07a24d051a401730165f3d65/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._1 fa._2 10 | //│ foo: (~'a -> 'a, 'a,) -> 'a 11 | //│ = [Function: foo1] 12 | 13 | :ns 14 | foo 15 | //│ res: forall 'b 'c 'a. (~'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/Simple.mls: -------------------------------------------------------------------------------- 1 | 2 | a = 1 3 | b = 2 4 | c = 3 5 | //│ a: 1 6 | //│ = 1 7 | //│ b: 2 8 | //│ = 2 9 | //│ c: 3 10 | //│ = 3 11 | 12 | if true then if true then a else b else a 13 | //│ res: 1 | 2 14 | //│ = 1 15 | 16 | if true then if true then id a else id b else a 17 | //│ res: 1 | 2 18 | //│ = 1 19 | 20 | class Foo[A]: { field: A } 21 | class Bar: {} 22 | //│ Defined class Foo[+A] 23 | //│ Defined class Bar 24 | 25 | foo = Foo { field = id 1 } 26 | //│ foo: Foo[1] 27 | //│ = Foo { field: 1 } 28 | 29 | (if true then foo else { field = 2 }).field 30 | //│ res: 1 | 2 31 | //│ = 1 32 | 33 | Foo { field = id 1 } 34 | //│ res: Foo[1] 35 | //│ = Foo { field: 1 } 36 | 37 | def test x = case x of { Bar -> 1 | Foo -> 2 } 38 | //│ test: (Bar | Foo[?]) -> (1 | 2) 39 | //│ = [Function: test] 40 | 41 | test foo 42 | //│ res: 1 | 2 43 | //│ = 2 44 | 45 | def test x = case x of { Bar -> 1 | Foo -> x.field } 46 | //│ test: (Bar | Foo[?] & {field: 'field}) -> (1 | 'field) 47 | //│ = [Function: test1] 48 | 49 | test foo 50 | //│ res: 1 51 | //│ = 1 52 | 53 | test (Foo { field = 2 }) 54 | //│ res: 1 | 2 55 | //│ = 2 56 | 57 | def test x = case x of { Foo -> x.field | _ -> 1 } 58 | //│ test: (Foo[?] & {field: 'field} | ~Foo[?]) -> (1 | 'field) 59 | //│ = [Function: test2] 60 | 61 | 62 | def f x = x.u 63 | //│ f: {u: 'u} -> 'u 64 | //│ = [Function: f] 65 | 66 | f { u = 1 } 67 | //│ res: 1 68 | //│ = 1 69 | 70 | f { u = 1; v = 2 } 71 | //│ res: 1 72 | //│ = 1 73 | 74 | f (if true then { u = 1; v = 2 } else { u = 1 }) 75 | //│ res: 1 76 | //│ = 1 77 | 78 | if true then { u = 1; v = 2 } else { u = 2 } 79 | //│ res: {u: 1 | 2} 80 | //│ = { u: 1, v: 2 } 81 | 82 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/StressUgly.mls: -------------------------------------------------------------------------------- 1 | 2 | class Lit: { val: int } 3 | class Add[E]: { lhs: E; rhs: E } 4 | method In: E -> E 5 | method In = id 6 | //│ Defined class Lit 7 | //│ Defined class Add[=E] 8 | //│ Declared Add.In: Add['E] -> 'E -> 'E 9 | //│ Defined Add.In: Add['E] -> 'a -> 'a 10 | 11 | 12 | 13 | def eval1_ty_ugly: Add['b] | 'a & ~Lit as 'b 14 | //│ eval1_ty_ugly: 'b 15 | //│ where 16 | //│ 'b := 'a & ~Lit | Add['b] 17 | //│ = 18 | 19 | // def eval1_ty: Add['b] 20 | def eval1_ty: Add[int] // ~500 21 | // def eval1_ty: Add['b] | 'a // ~800 22 | // def eval1_ty: Add['b] 23 | //│ eval1_ty: Add[int] 24 | //│ = 25 | 26 | // :stdout 27 | // :d 28 | :stats 29 | :e 30 | eval1_ty = eval1_ty_ugly 31 | //│ 'b 32 | //│ where 33 | //│ 'b := 'a & ~Lit | Add['b] 34 | //│ <: eval1_ty: 35 | //│ Add[int] 36 | //│ ╔══[ERROR] Type mismatch in def definition: 37 | //│ ║ l.30: eval1_ty = eval1_ty_ugly 38 | //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^ 39 | //│ ╟── type `Add['b]` is not an instance of type `int` 40 | //│ ║ l.13: def eval1_ty_ugly: Add['b] | 'a & ~Lit as 'b 41 | //│ ║ ^^^^^^^ 42 | //│ ╟── Note: constraint arises from type reference: 43 | //│ ║ l.20: def eval1_ty: Add[int] // ~500 44 | //│ ╙── ^^^ 45 | //│ = 46 | //│ eval1_ty_ugly is not implemented 47 | //│ constrain calls : 49 48 | //│ annoying calls : 42 49 | //│ subtyping calls : 477 50 | 51 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Test.mls: -------------------------------------------------------------------------------- 1 | 2 | class Person: { name: string; age: int } 3 | def Person = fun n -> fun a -> Person { name = n; age = a } 4 | //│ Defined class Person 5 | //│ Person: (string & 'name) -> (int & 'age) -> (Person with {age: 'age, name: 'name}) 6 | //│ = [Function: Person1] 7 | 8 | class Animal: {} 9 | //│ Defined class Animal 10 | 11 | def test = fun x -> case x of 12 | { Person -> x.age 13 | | Animal -> 0 14 | } 15 | //│ test: (Animal | (Person\name with {age: 'age})) -> (0 | 'age) 16 | //│ = [Function: test] 17 | 18 | test: Person & {age: 'a} | Animal -> 'a | 0 19 | //│ res: Animal -> 0 | 0 | Person & {age: 0} 20 | //│ = [Function: test] 21 | 22 | test: (Person & {age: int} | Animal) -> int 23 | //│ res: (Animal | Person) -> int 24 | //│ = [Function: test] 25 | 26 | a = Animal{} 27 | //│ a: Animal 28 | //│ = Animal {} 29 | 30 | a: {} 31 | //│ res: anything 32 | //│ = Animal {} 33 | 34 | p = Person "Bob" 42 35 | //│ p: Person & {age: 42, name: "Bob"} 36 | //│ = Person { name: 'Bob', age: 42 } 37 | 38 | p: { age: int } 39 | //│ res: {age: int} 40 | //│ = Person { name: 'Bob', age: 42 } 41 | 42 | test a 43 | //│ res: 0 44 | //│ = 0 45 | 46 | test p 47 | //│ res: 0 | 42 48 | //│ = 42 49 | 50 | 1: int 51 | //│ res: int 52 | //│ = 1 53 | 54 | 55 | def f: 'a -> 'a & string 56 | //│ f: nothing 57 | //│ = 58 | 59 | def f: 'a -> ('a & string) 60 | //│ f: 'a -> (string & 'a) 61 | //│ = 62 | 63 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Trans.mls: -------------------------------------------------------------------------------- 1 | 2 | class A 3 | class B: A 4 | class C: B 5 | c = C{} 6 | //│ Defined class A 7 | //│ Defined class B 8 | //│ Defined class C 9 | //│ c: C 10 | //│ = C {} 11 | 12 | c: C 13 | //│ res: C 14 | //│ = C {} 15 | 16 | c: B 17 | //│ res: B 18 | //│ = C {} 19 | 20 | res: A 21 | //│ res: A 22 | //│ = C {} 23 | 24 | c: A 25 | //│ res: A 26 | //│ = C {} 27 | 28 | a = res 29 | //│ a: A 30 | //│ = C {} 31 | 32 | :e 33 | a: B 34 | //│ ╔══[ERROR] Type mismatch in type ascription: 35 | //│ ║ l.33: a: B 36 | //│ ║ ^ 37 | //│ ╟── type `A` is not an instance of `B` 38 | //│ ║ l.24: c: A 39 | //│ ║ ^ 40 | //│ ╟── but it flows into reference with expected type `B` 41 | //│ ║ l.33: a: B 42 | //│ ║ ^ 43 | //│ ╟── Note: constraint arises from type reference: 44 | //│ ║ l.33: a: B 45 | //│ ╙── ^ 46 | //│ res: B 47 | //│ = C {} 48 | 49 | :e 50 | a: C 51 | //│ ╔══[ERROR] Type mismatch in type ascription: 52 | //│ ║ l.50: a: C 53 | //│ ║ ^ 54 | //│ ╟── type `A` is not an instance of `C` 55 | //│ ║ l.24: c: A 56 | //│ ║ ^ 57 | //│ ╟── but it flows into reference with expected type `C` 58 | //│ ║ l.50: a: C 59 | //│ ║ ^ 60 | //│ ╟── Note: constraint arises from type reference: 61 | //│ ║ l.50: a: C 62 | //│ ╙── ^ 63 | //│ res: C 64 | //│ = C {} 65 | 66 | 67 | // Transitivity is currently broken for primitive literals: 68 | 69 | 42: int 70 | res: number 71 | //│ res: int 72 | //│ = 42 73 | //│ res: number 74 | //│ = 42 75 | 76 | 42: number 77 | //│ res: number 78 | //│ = 42 79 | 80 | -------------------------------------------------------------------------------- /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 <: string -> string | int 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/Under.mls: -------------------------------------------------------------------------------- 1 | 2 | _ = 1 3 | //│ _: 1 4 | //│ = 1 5 | 6 | :e 7 | _ 8 | //│ ╔══[ERROR] Widlcard in expression position. 9 | //│ ║ l.7: _ 10 | //│ ╙── ^ 11 | //│ res: error 12 | //│ = 1 13 | 14 | def foo _ = 1 15 | //│ foo: anything -> 1 16 | //│ = [Function: foo] 17 | 18 | :e 19 | def foo _ = _ 20 | //│ ╔══[ERROR] Widlcard in expression position. 21 | //│ ║ l.19: def foo _ = _ 22 | //│ ╙── ^ 23 | //│ foo: anything -> error 24 | //│ = [Function: foo1] 25 | 26 | // :js 27 | def foo(_, _) = 1 28 | //│ foo: (anything, anything,) -> 1 29 | //│ = [Function: foo2] 30 | 31 | def foo { _ } = 1 32 | //│ foo: {_: anything} -> 1 33 | //│ = [Function: foo3] 34 | 35 | :e 36 | def foo { _ } = { _ } 37 | //│ ╔══[ERROR] Widlcard in expression position. 38 | //│ ║ l.36: def foo { _ } = { _ } 39 | //│ ╙── ^ 40 | //│ foo: {_: anything} -> {_: error} 41 | //│ = [Function: foo4] 42 | 43 | { _ = 1 }._ 44 | //│ res: 1 45 | //│ = 1 46 | 47 | :e 48 | def foo { _ ; _ } = 1 49 | //│ ╔══[ERROR] Multiple declarations of field name _ in record literal 50 | //│ ║ l.48: def foo { _ ; _ } = 1 51 | //│ ║ ^^^^^^^^^ 52 | //│ ╟── Declared at 53 | //│ ║ l.48: def foo { _ ; _ } = 1 54 | //│ ║ ^ 55 | //│ ╟── Declared at 56 | //│ ║ l.48: def foo { _ ; _ } = 1 57 | //│ ╙── ^ 58 | //│ foo: {_: anything, _: anything} -> 1 59 | //│ = [Function: foo5] 60 | 61 | // :js 62 | def foo { _ = _ ; __ = _ } = 1 63 | //│ foo: {_: anything, __: anything} -> 1 64 | //│ = [Function: foo6] 65 | 66 | _ = 1 67 | //│ _: 1 68 | //│ = 1 69 | 70 | def _ = 1 71 | //│ _: 1 72 | //│ = [Function: _2] 73 | 74 | rec def _ = 1 75 | //│ _: 1 76 | //│ = [Function: _3] 77 | 78 | 79 | -------------------------------------------------------------------------------- /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] Cyclic-looking constraint while typing application; a type annotation may be required 50 | //│ ║ l.48: bar foo 51 | //│ ║ ^^^^^^^ 52 | //│ ╙── Note: use flag `:ex` to see internal error info. 53 | //│ res: () | error 54 | //│ = 55 | //│ bar is not implemented 56 | 57 | 58 | f 1 + 2 59 | //│ res: int 60 | //│ = 3 61 | 62 | 63 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Variant-sub-ad-hoc.mls: -------------------------------------------------------------------------------- 1 | class None 2 | class Some 3 | //│ Defined class None 4 | //│ Defined class Some 5 | 6 | def Some v = Some{} with {v} 7 | def None = None{} 8 | //│ Some: 'a -> (Some & {v: 'a}) 9 | //│ = [Function: Some1] 10 | //│ None: None 11 | //│ = [Function: None1] 12 | 13 | def flatMap = fun f -> fun opt -> 14 | case opt of { Some -> f opt.v | _ -> opt } 15 | //│ flatMap: ('v -> 'a) -> (Some & {v: 'v} | 'a & ~#Some) -> 'a 16 | //│ = [Function: flatMap] 17 | 18 | f = fun x -> Some x 19 | res = flatMap f (Some 1) 20 | res = flatMap f None 21 | //│ f: 'a -> (Some & {v: 'a}) 22 | //│ = [Function: f] 23 | //│ res: Some & {v: 1} 24 | //│ = Some { v: 1 } 25 | //│ res: None | Some & {v: nothing} 26 | //│ = None {} 27 | 28 | class Lit 29 | class Neg 30 | class Var 31 | class Plus 32 | //│ Defined class Lit 33 | //│ Defined class Neg 34 | //│ Defined class Var 35 | //│ Defined class Plus 36 | 37 | :stats 38 | rec def evalOpt = fun x -> case x of { 39 | | Lit -> 40 | Some x.v 41 | | Neg -> 42 | flatMap (fun s -> Some (0 - s)) (evalOpt x.sub) 43 | | Var -> 44 | None with {err = concat "free var: " x.nme} 45 | | Plus -> 46 | flatMap (fun l -> flatMap (fun r -> 47 | Some (l + r) 48 | ) (evalOpt x.rhs)) (evalOpt x.lhs) 49 | } 50 | //│ evalOpt: 'a -> (None & {err: string} | Some & {v: int}) 51 | //│ where 52 | //│ 'a <: Lit & {v: int} | Neg & {sub: 'a} | Plus & {lhs: 'a, rhs: 'a} | Var & {nme: string} 53 | //│ = [Function: evalOpt] 54 | //│ constrain calls : 630 55 | //│ annoying calls : 156 56 | //│ subtyping calls : 4810 57 | 58 | :stats 59 | evalOpt (Plus{} with {lhs = Lit{} with {v=2}; rhs = Lit{} with {v=2}}) 60 | //│ res: None & {err: string} | Some & {v: int} 61 | //│ = Some { v: 4 } 62 | //│ constrain calls : 105 63 | //│ annoying calls : 34 64 | //│ subtyping calls : 1163 65 | 66 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/Weird.mls: -------------------------------------------------------------------------------- 1 | :AllowRuntimeErrors 2 | // Weird features to eventually remove 3 | 4 | 5 | :ge 6 | anything 7 | //│ res: anything 8 | //│ Code generation encountered an error: 9 | //│ type alias anything is not a valid expression 10 | 11 | :ge 12 | nothing 13 | //│ res: nothing 14 | //│ Code generation encountered an error: 15 | //│ type alias nothing is not a valid expression 16 | 17 | :ge 18 | Nothing 19 | //│ res: nothing 20 | //│ Code generation encountered an error: 21 | //│ unresolved symbol Nothing 22 | 23 | :ge 24 | int 25 | //│ res: int 26 | //│ Code generation encountered an error: 27 | //│ type alias int is not a valid expression 28 | 29 | :ge 30 | int + 1 31 | //│ res: int 32 | //│ Code generation encountered an error: 33 | //│ type alias int is not a valid expression 34 | 35 | 36 | class C 37 | //│ Defined class C 38 | 39 | :p 40 | def n: C{} 41 | //│ Parsed: rec def n: C; {}; 42 | //│ Desugared: rec def n: C 43 | //│ AST: Def(true, n, PolyType(List(),TypeName(C)), true) 44 | //│ Desugared: {} 45 | //│ AST: Rcd() 46 | //│ n: C 47 | //│ = 48 | //│ res: anything 49 | //│ = {} 50 | 51 | -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/i26.mls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hkust-taco/superoop/29bbb1f26eea191f07a24d051a401730165f3d65/shared/src/test/diff/mlscript/i26.mls -------------------------------------------------------------------------------- /shared/src/test/diff/mlscript/i56.mls: -------------------------------------------------------------------------------- 1 | // https://github.com/hkust-taco/mlscript/issues/56 2 | 3 | 4 | def test3 x = case x of 5 | { 1 -> true 6 | | true -> true 7 | | _ -> false 8 | } 9 | //│ test3: anything -> Bool 10 | //│ = [Function: test3] 11 | 12 | :ns 13 | test3 14 | //│ res: forall 'a 'b 'c 'd. 'a -> Bool 15 | //│ where 16 | //│ 'a <: 1 & 'b | (true & 'c | 'd & ~true) & ~1 17 | //│ = [Function: test3] 18 | 19 | 20 | def test3 x = case x of 21 | { 1 -> x 22 | | true -> true 23 | | _ -> false 24 | } 25 | //│ test3: (1 & 'a | ~1) -> (Bool | 'a) 26 | //│ = [Function: test31] 27 | 28 | 29 | def ty_1: (1 & 'a | true | ~1 & ~true) -> (false | true | 'a) 30 | //│ ty_1: (1 & 'a | true | ~1 & ~true) -> ('a | false | true) 31 | //│ = 32 | 33 | ty_1 = test3 34 | //│ (1 & 'a | ~1) -> (Bool | 'a) 35 | //│ <: ty_1: 36 | //│ (1 & 'a | true | ~1 & ~true) -> ('a | false | true) 37 | //│ = [Function: test31] 38 | 39 | def ty_2: (1 & 'a | ~1) -> (false | true | 'a) 40 | //│ ty_2: (1 & 'a | ~1) -> ('a | false | true) 41 | //│ = 42 | 43 | ty_2 = ty_1 44 | //│ (1 & 'a | true | ~1 & ~true) -> ('a | false | true) 45 | //│ <: ty_2: 46 | //│ (1 & 'a | ~1) -> ('a | false | true) 47 | //│ = [Function: test31] 48 | 49 | 50 | // * Note: it is a bit counter-intuitive that we have: 51 | // * (1 & 'a | ~1) <: (1 & 'a | true | ~1 & ~true) 52 | // * and in particular: 53 | // * ~1 <: (1 & 'a | true | ~1 & ~true) 54 | // * but the latter can be understood by seeing that it's equivalent (by swapping) to: 55 | // * (1 | true) <: (1 & 'a | true | 1) 56 | // * ie 57 | // * (1 | true) <: (true | 1) 58 | 59 | -------------------------------------------------------------------------------- /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 | :e 15 | 1 : Int : Int 16 | //│ ╔══[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 | foo(123:Int):Int 35 | //│ Int 36 | //│ res 37 | //│ = 124 38 | 39 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 Foo(x: Int) 30 | class Bar { x } 31 | //│ ╔══[ERROR] identifier not found: x 32 | //│ ║ l.30: class Bar { x } 33 | //│ ╙── ^ 34 | //│ class Foo(x: Int) 35 | //│ class Bar 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 | //│ fun f: Foo 47 | //│ } 48 | //│ Syntax error: 49 | //│ 'super' keyword unexpected here 50 | 51 | 52 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/BasicClassInheritance.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class A 5 | //│ class A 6 | 7 | class B(m: Int) extends A 8 | //│ class B(m: Int) extends A 9 | 10 | 11 | class A(n: Int) 12 | //│ class A(n: Int) 13 | 14 | class B(m: Int) extends A(m + 1) 15 | //│ class B(m: Int) extends A 16 | 17 | 18 | class A { 19 | fun a1: Int 20 | fun a1 = 1 21 | fun a2 = 2 22 | } 23 | //│ class A { 24 | //│ fun a1: Int 25 | //│ fun a2: 2 26 | //│ } 27 | 28 | class B extends A 29 | //│ class B extends A { 30 | //│ fun a1: Int 31 | //│ fun a2: 2 32 | //│ } 33 | 34 | 35 | // * Interestingly, we can currently inherit from modules... 36 | 37 | module C { fun test = 0 } 38 | //│ module C { 39 | //│ fun test: 0 40 | //│ } 41 | 42 | class D() extends C 43 | //│ class D() extends C { 44 | //│ fun test: 0 45 | //│ } 46 | 47 | D().test 48 | //│ 0 49 | //│ res 50 | //│ = 0 51 | 52 | 53 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/ClassField.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | 5 | class Foo(x: Int) 6 | //│ class Foo(x: Int) 7 | 8 | Foo 9 | //│ (x: Int,) -> Foo 10 | //│ res 11 | //│ = [Function (anonymous)] { class: [class Foo] } 12 | 13 | typeof(Foo) 14 | //│ Str 15 | //│ res 16 | //│ = 'function' 17 | 18 | let f = Foo(123) 19 | //│ let f: Foo 20 | //│ f 21 | //│ = Foo {} 22 | 23 | typeof(f) 24 | //│ Str 25 | //│ res 26 | //│ = 'object' 27 | 28 | :e 29 | let cls = Foo.class 30 | //│ ╔══[ERROR] Type mismatch in field selection: 31 | //│ ║ l.29: let cls = Foo.class 32 | //│ ║ ^^^^^^^^^ 33 | //│ ╟── reference of type `(x: Int,) -> Foo` does not have field 'class' 34 | //│ ║ l.29: let cls = Foo.class 35 | //│ ╙── ^^^ 36 | //│ let cls: error 37 | //│ cls 38 | //│ = [class Foo] 39 | 40 | typeof(cls) 41 | //│ Str 42 | //│ res 43 | //│ = 'function' 44 | 45 | 46 | 47 | mixin Base 48 | //│ mixin Base() 49 | 50 | class Derived() extends Base 51 | //│ class Derived() 52 | 53 | // * Strangely, we now get `{ class: [Function: Derived] }` 54 | Derived 55 | //│ () -> Derived 56 | //│ res 57 | //│ = [Function (anonymous)] { class: [Function: Derived] } 58 | 59 | :e 60 | let cls = Derived.class 61 | //│ ╔══[ERROR] Type mismatch in field selection: 62 | //│ ║ l.60: let cls = Derived.class 63 | //│ ║ ^^^^^^^^^^^^^ 64 | //│ ╟── reference of type `() -> Derived` does not have field 'class' 65 | //│ ║ l.60: let cls = Derived.class 66 | //│ ╙── ^^^^^^^ 67 | //│ let cls: error 68 | //│ cls 69 | //│ = [Function: Derived] 70 | 71 | typeof(cls) 72 | //│ Str 73 | //│ res 74 | //│ = 'function' 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/CtorStatements.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | log("Hello!") 5 | //│ undefined 6 | //│ res 7 | //│ = undefined 8 | //│ // Output 9 | //│ Hello! 10 | 11 | 12 | module Test0 { 13 | log("Hello!") 14 | } 15 | //│ module Test0 16 | 17 | Test0 18 | //│ Test0 19 | //│ res 20 | //│ = Test0 { class: [class Test0] } 21 | //│ // Output 22 | //│ Hello! 23 | 24 | 25 | -------------------------------------------------------------------------------- /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 | //│ fun toLocaleString: (locales: Array[Str] | Str, options: anything,) -> Str 11 | //│ fun toString: () -> Str 12 | //│ } 13 | 14 | :e // TODO ctor typing 15 | let date1 = new Date(12345678) 16 | //│ ╔══[ERROR] Type mismatch in application: 17 | //│ ║ l.15: let date1 = new Date(12345678) 18 | //│ ║ ^^^^^^^^^^^^^^ 19 | //│ ╟── argument of type `(12345678,)` does not match type `()` 20 | //│ ║ l.15: let date1 = new Date(12345678) 21 | //│ ╙── ^^^^^^^^^^ 22 | //│ let date1: Date | error 23 | //│ date1 24 | //│ = 1970-01-01T03:25:45.678Z 25 | 26 | date1.toLocaleString("en-US", { timeZone: "America/New_York" }) 27 | //│ Str | error 28 | //│ res 29 | //│ = '12/31/1969, 10:25:45 PM' 30 | 31 | -------------------------------------------------------------------------------- /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 | let Nil: List 10 | let Cons: (head: 'a, tail: List<'a>) => List<'a> 11 | //│ class List[A] { 12 | //│ fun match: forall 'res. (ifNil: () -> 'res, ifCons: ('res, List[A],) -> 'res,) -> 'res 13 | //│ } 14 | //│ let Nil: List[nothing] 15 | //│ let Cons: forall 'a. (head: 'a, tail: List['a],) -> List['a] 16 | 17 | let x: List 18 | //│ let x: List[Int] 19 | 20 | // FIXME 21 | x: List 22 | //│ ╔══[ERROR] Type mismatch in type ascription: 23 | //│ ║ l.21: x: List 24 | //│ ║ ^ 25 | //│ ╙── expression of type `anything` is not an instance of type `Int` 26 | //│ List[anything] 27 | 28 | 29 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/EvalNegNeg.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Add(lhs: E, rhs: E) 5 | class Lit(n: Int) 6 | //│ class Add[E](lhs: E, rhs: E) 7 | //│ class Lit(n: Int) 8 | 9 | 10 | mixin EvalBase { 11 | fun eval(e) = 12 | if e is 13 | Lit(n) then n: Int 14 | Add(l, r) then this.eval(l) + this.eval(r) 15 | } 16 | //│ mixin EvalBase() { 17 | //│ this: {eval: 'lhs -> Int} 18 | //│ fun eval: (Add['lhs] | Lit) -> Int 19 | //│ } 20 | 21 | 22 | class Neg(expr: A) 23 | //│ class Neg[A](expr: A) 24 | 25 | 26 | mixin EvalNeg { 27 | fun eval(e) = 28 | if e is Neg(d) then 0 - this.eval(d) 29 | else super.eval(e) 30 | } 31 | //│ mixin EvalNeg() { 32 | //│ super: {eval: 'a -> 'b} 33 | //│ this: {eval: 'expr -> Int} 34 | //│ fun eval: (Neg['expr] | Object & 'a & ~#Neg) -> (Int | 'b) 35 | //│ } 36 | 37 | 38 | mixin EvalNegNeg { 39 | fun eval(e) = 40 | if e is Neg(Neg(d)) then this.eval(d) 41 | else super.eval(e) 42 | } 43 | //│ mixin EvalNegNeg() { 44 | //│ super: {eval: (Neg[nothing] | 'a) -> 'b} 45 | //│ this: {eval: 'expr -> 'b} 46 | //│ fun eval: (Neg[Neg['expr] | Object & ~#Neg] | Object & 'a & ~#Neg) -> 'b 47 | //│ } 48 | 49 | 50 | module TestLang extends EvalBase, EvalNeg, EvalNegNeg 51 | //│ module TestLang { 52 | //│ fun eval: 'a -> Int 53 | //│ } 54 | //│ where 55 | //│ 'a <: Neg['A] | Object & 'b & ~#Neg 56 | //│ 'A <: Neg['a & 'A] | Neg['A] & ~#Neg | Object & 'b & ~#Neg 57 | //│ 'b <: Add['a] | Lit | Neg['a] 58 | 59 | 60 | fun mk(n) = if n is 61 | 0 then Lit(3) 62 | 1 then Neg(mk(n - 1)) 63 | _ then Add(mk(n - 1), mk(n - 1)) 64 | //│ fun mk: forall 'E. (0 | 1 | Int & ~0 & ~1) -> 'E 65 | //│ where 66 | //│ 'E :> Add['E] | Lit | Neg['E] 67 | 68 | TestLang.eval(mk(0)) 69 | //│ Int 70 | //│ res 71 | //│ = 3 72 | 73 | TestLang.eval(mk(11)) 74 | //│ Int 75 | //│ res 76 | //│ = -3072 77 | 78 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/ExpressionProblem_small.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | 5 | class Neg[A](expr: A) 6 | class Add[E](lhs: E, rhs: E) 7 | class Lit(n: Int) 8 | //│ class Neg[A](expr: A) 9 | //│ class Add[E](lhs: E, rhs: E) 10 | //│ class Lit(n: Int) 11 | 12 | let add11 = Add(Lit(1), Lit(2)) 13 | let add2negadd11 = Add(Lit(2), Neg(add11)) 14 | //│ let add11: Add[Lit] 15 | //│ let add2negadd11: Add[Lit | Neg[Add[Lit]]] 16 | 17 | mixin EvalNothing { 18 | fun eval(e: nothing) = e 19 | } 20 | mixin EvalAddLit { 21 | fun eval(e) = 22 | if e is 23 | Lit(n) then n 24 | Add(l, r) then this.eval(l) + this.eval(r) 25 | else super.eval(e) 26 | } 27 | mixin EvalNeg { 28 | fun eval(e) = 29 | if e is Neg(d) then 0 - this.eval(d) 30 | else super.eval(e) 31 | } 32 | //│ mixin EvalNothing() { 33 | //│ fun eval: (e: nothing,) -> nothing 34 | //│ } 35 | //│ mixin EvalAddLit() { 36 | //│ super: {eval: 'a -> 'b} 37 | //│ this: {eval: 'lhs -> Int} 38 | //│ fun eval: (Add['lhs] | Lit | Object & 'a & ~#Add & ~#Lit) -> (Int | 'b) 39 | //│ } 40 | //│ mixin EvalNeg() { 41 | //│ super: {eval: 'c -> 'd} 42 | //│ this: {eval: 'expr -> Int} 43 | //│ fun eval: (Neg['expr] | Object & 'c & ~#Neg) -> (Int | 'd) 44 | //│ } 45 | 46 | module TestLang extends EvalNothing, EvalAddLit, EvalNeg 47 | //│ module TestLang { 48 | //│ fun eval: (Neg['a] | Object & 'b & ~#Neg) -> Int 49 | //│ } 50 | //│ where 51 | //│ 'a <: Neg['a] | Object & 'b & ~#Neg 52 | //│ 'b <: Add['a] | Lit 53 | 54 | TestLang.eval 55 | //│ (Neg['a] | Object & 'b & ~#Neg) -> Int 56 | //│ where 57 | //│ 'a <: Neg['a] | Object & 'b & ~#Neg 58 | //│ 'b <: Add['a] | Lit 59 | 60 | 61 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/FieldRefinement.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | 5 | class Foo(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 | let foo: Foo & { x: 0 | 1, bar: 0 | 1, baz: 0 | 1, y: Bool } 15 | //│ let 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/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 | 17 | class Pair(lhs: Int, rhs: Int) 18 | //│ class Pair(lhs: Int, rhs: Int) 19 | 20 | // TODO 21 | fun f(Pair(x, y)) = x + y 22 | //│ ╔══[ERROR] Unsupported pattern shape: 23 | //│ ║ l.21: fun f(Pair(x, y)) = x + y 24 | //│ ╙── ^^^^^^^^^^ 25 | //│ ╔══[ERROR] identifier not found: x 26 | //│ ║ l.21: fun f(Pair(x, y)) = x + y 27 | //│ ╙── ^ 28 | //│ ╔══[ERROR] identifier not found: y 29 | //│ ║ l.21: fun f(Pair(x, y)) = x + y 30 | //│ ╙── ^ 31 | //│ fun f: error -> Int 32 | 33 | 34 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/FunPoly.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | 5 | fun id(x) = x 6 | //│ fun id: forall 'a. 'a -> 'a 7 | 8 | [id(1), id(true)] 9 | //│ (1, true,) 10 | //│ res 11 | //│ = [ 1, true ] 12 | 13 | not(id(true)) 14 | //│ Bool 15 | //│ res 16 | //│ = false 17 | 18 | 19 | 20 | fun id(x) = x 21 | [id(1), id(true)] 22 | //│ fun id: forall 'a. 'a -> 'a 23 | //│ (1, true,) 24 | //│ res 25 | //│ = [Function: id1] 26 | 27 | 28 | 29 | // * Currently, we type entire typing units monomorphically; 30 | // * later we should try to separate mutually-recursive components and generalize them independently. 31 | fun test = [id(1), id(true)] 32 | fun id(x) = x 33 | //│ fun test: forall 'a 'b. (1 | true | 'b, 1 | true | 'a,) 34 | //│ fun id: forall 'a 'b. ('a & 'b) -> (1 | true | 'b) 35 | 36 | [id(1), id(true)] 37 | //│ (1 | true, 1 | true,) 38 | //│ res 39 | //│ = [ 1, true ] 40 | 41 | :e 42 | not(id(true)) 43 | //│ ╔══[ERROR] Type mismatch in application: 44 | //│ ║ l.42: not(id(true)) 45 | //│ ║ ^^^^^^^^^^^^^ 46 | //│ ╟── integer literal of type `1` is not an instance of type `Bool` 47 | //│ ║ l.31: fun test = [id(1), id(true)] 48 | //│ ║ ^ 49 | //│ ╟── but it flows into application with expected type `Bool` 50 | //│ ║ l.42: not(id(true)) 51 | //│ ╙── ^^^^^^^^ 52 | //│ error | false | true 53 | //│ res 54 | //│ = false 55 | 56 | 57 | 58 | fun test = [Helper.id(1), Helper.id(true)] 59 | module Helper { 60 | fun id(x) = x 61 | } 62 | //│ fun test: (1, true,) 63 | //│ module Helper { 64 | //│ fun id: 'a -> 'a 65 | //│ } 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/FunSigs.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | fun log(msg: Str): unit 5 | //│ fun log: (msg: Str,) -> unit 6 | 7 | let f = 8 | log("ok") 9 | 123 10 | //│ let f: 123 11 | //│ f 12 | //│ = 13 | //│ log is not implemented 14 | 15 | fun log: Str -> unit 16 | //│ fun log: Str -> unit 17 | 18 | fun log: Str => unit 19 | //│ fun log: Str -> unit 20 | 21 | log("ok") 22 | //│ unit 23 | //│ res 24 | //│ = 25 | //│ log is not implemented 26 | 27 | 28 | fun con: Str => Str => Str 29 | //│ fun con: Str -> Str -> Str 30 | 31 | fun con = concat 32 | //│ fun con: Str -> Str -> Str 33 | 34 | 35 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Huawei1.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class C[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 | 19 | fun bar(c) = if c is 20 | C(y) then y 21 | B then 0 22 | //│ fun bar: forall 'x. (B | C['x]) -> (0 | 'x) 23 | 24 | bar(c) 25 | //│ 0 | 123 26 | //│ res 27 | //│ = 123 28 | 29 | fun bar(c) = if c is 30 | C(y) then y + 1 31 | B then 0 32 | else 1 33 | //│ fun bar: (C[Int] | Object & ~#C) -> Int 34 | 35 | bar(c) 36 | //│ Int 37 | //│ res 38 | //│ = 124 39 | 40 | :e 41 | bar(C(true)) 42 | //│ ╔══[ERROR] Type mismatch in application: 43 | //│ ║ l.41: bar(C(true)) 44 | //│ ║ ^^^^^^^^^^^^ 45 | //│ ╟── reference of type `true` is not an instance of type `Int` 46 | //│ ║ l.41: bar(C(true)) 47 | //│ ║ ^^^^ 48 | //│ ╟── Note: constraint arises from reference: 49 | //│ ║ l.30: C(y) then y + 1 50 | //│ ║ ^ 51 | //│ ╟── from reference: 52 | //│ ║ l.29: fun bar(c) = if c is 53 | //│ ║ ^ 54 | //│ ╟── Note: type parameter A is defined at: 55 | //│ ║ l.4: class C[A](x: A) { 56 | //│ ╙── ^ 57 | //│ Int | error 58 | //│ res 59 | //│ = 2 60 | 61 | -------------------------------------------------------------------------------- /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 | //│ fun x: 1 18 | //│ } 19 | //│ trait T2 { 20 | //│ fun x: 1 | 2 21 | //│ } 22 | //│ } 23 | 24 | 25 | mixin Foo { fun f = this.x } 26 | //│ mixin Foo() { 27 | //│ this: {x: 'x} 28 | //│ fun f: 'x 29 | //│ } 30 | 31 | module Bar { 32 | class C(x: Int) extends Foo 33 | } 34 | //│ module Bar { 35 | //│ class C(x: Int) { 36 | //│ fun f: Int 37 | //│ } 38 | //│ } 39 | 40 | 41 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/InterfaceGeneric.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | trait Into[T] { 5 | fun Into: T 6 | } 7 | //│ trait Into[T] { 8 | //│ fun Into: T 9 | //│ } 10 | 11 | trait Nat extends Into[Int] 12 | //│ trait Nat extends Into { 13 | //│ fun Into: 'T 14 | //│ } 15 | //│ where 16 | //│ 'T := Int 17 | 18 | trait Product[A, B] extends Into[A] { 19 | let pair: (A, B) 20 | } 21 | //│ trait Product[A, B] extends Into { 22 | //│ fun Into: 'T 23 | //│ let pair: (A, B,) 24 | //│ } 25 | //│ where 26 | //│ 'T := A 27 | 28 | class TwoInts(pair: (Int, Int)) extends Product[Int, Int] { 29 | fun Into = pair._1 + pair._2 30 | } 31 | //│ class TwoInts(pair: (Int, Int,)) extends Into, Product { 32 | //│ fun Into: Int 33 | //│ } 34 | 35 | let i2 = TwoInts((1,2)) 36 | //│ let i2: TwoInts 37 | 38 | i2: Product[Int, Int] 39 | //│ Product[Int, Int] 40 | 41 | i2: Into[Int] 42 | //│ Into[Int] 43 | 44 | i2.pair 45 | //│ (Int, Int,) 46 | 47 | i2.Into 48 | //│ Int 49 | 50 | let p1: Product[Int, Int] 51 | //│ let p1: Product[Int, Int] 52 | 53 | :e 54 | p1: Product[Bool, Int] 55 | //│ ╔══[ERROR] Type mismatch in type ascription: 56 | //│ ║ l.54: p1: Product[Bool, Int] 57 | //│ ║ ^^ 58 | //│ ╙── expression of type `Int` is not an instance of type `Bool` 59 | //│ Product[Bool, Int] 60 | 61 | p1: Into[Int] 62 | //│ Into[Int] 63 | 64 | :e 65 | p1: Into[Bool] 66 | //│ ╔══[ERROR] Type mismatch in type ascription: 67 | //│ ║ l.65: p1: Into[Bool] 68 | //│ ║ ^^ 69 | //│ ╙── expression of type `Int` is not an instance of type `Bool` 70 | //│ Into[Bool] 71 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/ListConsNil.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | 5 | type List[out A] = Cons[A] | Nil 6 | class Cons[out A](head: A, tail: List[A]) { 7 | fun size : Int 8 | fun size = 1 + tail.size 9 | } 10 | module Nil { fun size = 0 } 11 | //│ type List[A] = Cons[A] | Nil 12 | //│ class Cons[A](head: A, tail: List[A]) { 13 | //│ fun size: Int 14 | //│ } 15 | //│ module Nil { 16 | //│ fun size: 0 17 | //│ } 18 | 19 | 20 | 21 | // TODO should better simplify these types (reduce the List refinement) 22 | 23 | :ng 24 | let test0: Cons[Int] & List[Num] 25 | let test1: Nil & List[Int] 26 | //│ let test0: Cons[Int] & List[Num] 27 | //│ let test1: Nil & List[Int] 28 | 29 | 30 | 31 | fun list_assoc(s, l) = 32 | if l is 33 | Cons(h, t) then 34 | if eq(s)(h._1) then Cons(h._2, Nil) 35 | else list_assoc(s, t) 36 | Nil then Nil 37 | //│ fun list_assoc: forall 'A. (anything, Cons[{_1: anything, _2: 'A}] | Nil,) -> (Cons['A] | Nil) 38 | 39 | fun test(x, l) = list_assoc(42, Cons(x, l)) 40 | //│ fun test: forall 'A. ({_1: anything, _2: 'A}, List[{_1: anything, _2: 'A}],) -> (Cons['A] | Nil) 41 | 42 | fun test(x, l) = if l is 43 | Nil then list_assoc(42, Cons(x, l)) 44 | Cons(h, t) then list_assoc(42, Cons(h, t)) 45 | //│ fun test: forall 'A. ({_1: anything, _2: 'A}, Cons[{_1: anything, _2: 'A}] | Nil,) -> (Cons['A] | Nil) 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/LitMatch.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | false : Bool 5 | //│ Bool 6 | //│ res 7 | //│ = false 8 | 9 | // FIXME parsing! 10 | let b = true | false : Bool 11 | //│ let b: (Bool,) 12 | //│ b 13 | //│ = 1 14 | 15 | let b = false : Bool 16 | //│ let b: Bool 17 | //│ b 18 | //│ = false 19 | 20 | b : true | false 21 | //│ Bool 22 | //│ res 23 | //│ = false 24 | 25 | if false is false then 0 26 | //│ 0 27 | //│ res 28 | //│ = 0 29 | 30 | fun foo(x) = if x is 31 | false then 0 32 | //│ fun foo: nothing -> 0 33 | 34 | fun foo(x) = if x is 35 | false then 0 36 | true then 1 37 | //│ fun foo: nothing -> (0 | 1) 38 | 39 | 40 | -------------------------------------------------------------------------------- /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 | let x : Int | string 13 | let x = 1 14 | //│ let x: Int | string 15 | //│ let x: 1 16 | //│ x 17 | //│ = 18 | //│ x 19 | //│ = 1 20 | 21 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/MemberConfusion.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | mixin T { fun a = "hi" } 5 | //│ mixin T() { 6 | //│ fun a: "hi" 7 | //│ } 8 | 9 | class C(a: Int) extends T 10 | //│ class C(a: Int) { 11 | //│ fun a: "hi" 12 | //│ } 13 | 14 | class B { let a = "hi" } 15 | //│ class B { 16 | //│ let a: "hi" 17 | //│ } 18 | 19 | :e 20 | class C(a: Int) extends B 21 | //│ ╔══[ERROR] Type mismatch in type reference: 22 | //│ ║ l.20: class C(a: Int) extends B 23 | //│ ║ ^^^ 24 | //│ ╟── type `Int` does not match type `"hi"` 25 | //│ ╟── Note: constraint arises from string literal: 26 | //│ ║ l.14: class B { let a = "hi" } 27 | //│ ╙── ^^^^ 28 | //│ class C(a: Int) extends B 29 | 30 | 31 | mixin M { let b = "hi" } 32 | //│ mixin M() { 33 | //│ let b: "hi" 34 | //│ } 35 | 36 | class B { let a = 1 : Int } 37 | //│ class B { 38 | //│ let a: Int 39 | //│ } 40 | 41 | class C(a: Int, b: Int) extends B, M 42 | //│ class C(a: Int, b: Int) extends B { 43 | //│ let b: "hi" 44 | //│ } 45 | 46 | let c = C(2, 3) 47 | (c.a, c.b) 48 | //│ let c: C 49 | //│ (Int, "hi",) 50 | //│ c 51 | //│ = C {} 52 | //│ res 53 | //│ = [ 2, 3 ] 54 | 55 | class C(a: Int) { let a = 1 } 56 | //│ class C(a: Int) { 57 | //│ let a: 1 58 | //│ } 59 | 60 | class C(a: Int) { fun a = 1 } 61 | //│ class C(a: Int) { 62 | //│ fun a: 1 63 | //│ } 64 | 65 | class C(a: Int) { fun a = a } 66 | //│ class C(a: Int) { 67 | //│ fun a: nothing 68 | //│ } 69 | 70 | class C(a: Int, b: Int) extends B, M { let b = "hi" } 71 | //│ class C(a: Int, b: Int) extends B { 72 | //│ let b: "hi" 73 | //│ } 74 | 75 | 76 | -------------------------------------------------------------------------------- /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 | // TODO 12 | mixin BaseTest(x) { 13 | fun test = x 14 | } 15 | //│ ╔══[ERROR] Mixin parameters currently need type annotations 16 | //│ ║ l.12: mixin BaseTest(x) { 17 | //│ ╙── ^ 18 | //│ mixin BaseTest(x: error) { 19 | //│ fun test: error 20 | //│ } 21 | 22 | 23 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/ModuleParameters.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | :e 5 | module A(x: Int) { fun y = x } 6 | //│ ╔══[ERROR] module parameters are not supported 7 | //│ ║ l.5: module A(x: Int) { fun y = x } 8 | //│ ╙── ^ 9 | //│ module A(x: Int) { 10 | //│ fun y: Int 11 | //│ } 12 | 13 | A.x 14 | //│ Int 15 | //│ res 16 | //│ = undefined 17 | 18 | A.y 19 | //│ Int 20 | //│ res 21 | //│ = undefined 22 | 23 | 24 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/NamedArgs.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Foo(x: Int) 5 | //│ class Foo(x: Int) 6 | 7 | Foo(1) 8 | //│ Foo 9 | //│ res 10 | //│ = Foo {} 11 | 12 | Foo(x: 1) 13 | //│ Foo 14 | //│ res 15 | //│ = Foo {} 16 | 17 | Foo(y: 1) 18 | //│ Foo 19 | //│ res 20 | //│ = Foo {} 21 | 22 | 23 | :e // TODO: Here `x` is not currently treated as a field name 24 | class Bar(x) 25 | //│ ╔══[ERROR] Class parameters currently need type annotations 26 | //│ ║ l.24: class Bar(x) 27 | //│ ╙── ^ 28 | //│ class Bar(x: error) 29 | 30 | Bar(1) 31 | //│ Bar 32 | //│ res 33 | //│ = Bar {} 34 | 35 | Bar(x: 1) 36 | //│ Bar 37 | //│ res 38 | //│ = Bar {} 39 | 40 | :e 41 | Bar(y: 1) 42 | //│ ╔══[ERROR] Wrong tuple field name: found 'y' instead of 'x' 43 | //│ ║ l.41: Bar(y: 1) 44 | //│ ╙── ^^^^^^ 45 | //│ Bar | error 46 | //│ res 47 | //│ = Bar {} 48 | 49 | -------------------------------------------------------------------------------- /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)] { class: [class NC0] } 24 | 25 | 26 | module M0 { 27 | class NC0 28 | } 29 | //│ module M0 { 30 | //│ class NC0 31 | //│ } 32 | 33 | :e 34 | M0.NC0 35 | //│ ╔══[ERROR] access to class member not yet supported 36 | //│ ║ l.34: M0.NC0 37 | //│ ╙── ^^^^ 38 | //│ error 39 | //│ res 40 | //│ = [class NC0] 41 | 42 | 43 | module M1 { 44 | module NM1 45 | } 46 | //│ module M1 { 47 | //│ module NM1 48 | //│ } 49 | 50 | :e 51 | M1.NM1 52 | //│ ╔══[ERROR] access to module member not yet supported 53 | //│ ║ l.51: M1.NM1 54 | //│ ╙── ^^^^ 55 | //│ error 56 | //│ res 57 | //│ = NM1 { class: [class NM1] } 58 | 59 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/New.mls: -------------------------------------------------------------------------------- 1 | :NewParser 2 | 3 | 4 | class Foo(x) 5 | //│ Defined class Foo 6 | //│ Foo: 'x -> (Foo & {x: 'x}) 7 | //│ = [Function: Foo1] 8 | 9 | let f = Foo(1) 10 | //│ f: Foo & {x: 1} 11 | //│ = Foo { x: 1 } 12 | 13 | let f = new Foo(1) 14 | //│ f: Foo & {x: 1} 15 | //│ = Foo { x: 1 } 16 | 17 | if f is Foo then 1 else 0 18 | //│ res: 0 | 1 19 | //│ = 1 20 | 21 | if f is Foo(a) then a else 0 22 | //│ res: 0 | 1 23 | //│ = 1 24 | 25 | // case f of 26 | // { Foo -> 27 | // let a = f.x 28 | // a 29 | // | _ -> 0 30 | // } 31 | 32 | // Foo(A) =:= Foo & { x: A } 33 | 34 | 35 | fun test(x) = if x is Foo(a) then a 36 | //│ test: (Foo & {x: 'x}) -> 'x 37 | //│ = [Function: test] 38 | 39 | test(f) 40 | //│ res: 1 41 | //│ = 1 42 | 43 | class PoInt(x, y) 44 | //│ Defined class PoInt 45 | //│ PoInt: ('x, 'y,) -> (PoInt & {x: 'x, y: 'y}) 46 | //│ = [Function: PoInt1] 47 | 48 | let origin = new PoInt(0, 0) 49 | //│ origin: PoInt & {x: 0, y: 0} 50 | //│ = PoInt { x: 0, y: 0 } 51 | -------------------------------------------------------------------------------- /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 `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/OverrideShorthand.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | 5 | class Pair(lhs: Int, rhs: Int) 6 | //│ class Pair(lhs: Int, rhs: Int) 7 | 8 | 9 | :p 10 | :e 11 | fun f(override Pair(x, y)) = x + y 12 | //│ |#fun| |f|(|#override| |Pair|(|x|,| |y|)|)| |#=| |x| |+| |y| 13 | //│ Parsed: fun f = (_$0,) => if _$0 is (Pair (x, y,)) then + (x,) (y,) else (super).f (_$0,); 14 | //│ ╔══[ERROR] identifier not found: super 15 | //│ ║ l.11: fun f(override Pair(x, y)) = x + y 16 | //│ ╙── ^^^^^^^^ 17 | //│ fun f: Object -> (Int | error) 18 | //│ Syntax error: 19 | //│ 'super' keyword unexpected here 20 | 21 | 22 | mixin Test { 23 | fun f(override Pair(x, y)) = x + y 24 | } 25 | //│ mixin Test() { 26 | //│ super: {f: 'a -> 'b} 27 | //│ fun f: (Object & 'a & ~#Pair | Pair) -> (Int | 'b) 28 | //│ } 29 | 30 | 31 | :pe 32 | :e 33 | fun f(override Pair(x, y), z) = x + y 34 | //│ ╔══[PARSE ERROR] Unsupported 'override' parameter list shape 35 | //│ ║ l.33: fun f(override Pair(x, y), z) = x + y 36 | //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^ 37 | //│ ╔══[ERROR] Unsupported pattern shape: 38 | //│ ║ l.33: fun f(override Pair(x, y), z) = x + y 39 | //│ ╙── ^^^^^^^^^^ 40 | //│ ╔══[ERROR] identifier not found: x 41 | //│ ║ l.33: fun f(override Pair(x, y), z) = x + y 42 | //│ ╙── ^ 43 | //│ ╔══[ERROR] identifier not found: y 44 | //│ ║ l.33: fun f(override Pair(x, y), z) = x + y 45 | //│ ╙── ^ 46 | //│ fun f: (error, anything,) -> Int 47 | //│ Code generation encountered an error: 48 | //│ term App(Var(Pair), Tup(_: Var(x), _: Var(y))) is not a valid pattern 49 | 50 | 51 | // TODO 52 | // :pe 53 | // fun f(override Pair(x, y)): Int 54 | 55 | 56 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/ParamImplementing.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | trait T { fun x: Int } 5 | //│ trait T { 6 | //│ fun x: Int 7 | //│ } 8 | 9 | mixin M(x: Bool) 10 | //│ mixin M(x: Bool) 11 | 12 | :e 13 | class C extends T, M(false) 14 | //│ ╔══[ERROR] Type mismatch in reference: 15 | //│ ║ l.13: class C extends T, M(false) 16 | //│ ║ ^^^^^ 17 | //│ ╟── reference of type `false` is not an instance of type `Int` 18 | //│ ╟── Note: constraint arises from type reference: 19 | //│ ║ l.4: trait T { fun x: Int } 20 | //│ ║ ^^^ 21 | //│ ╟── from signature of member `x`: 22 | //│ ║ l.4: trait T { fun x: Int } 23 | //│ ╙── ^^^^^^ 24 | //│ class C extends T 25 | 26 | 27 | trait T { fun x: Int } 28 | mixin M(x: Num) 29 | //│ trait T { 30 | //│ fun x: Int 31 | //│ } 32 | //│ mixin M(x: Num) 33 | 34 | class C extends T, M(0) 35 | //│ class C extends T 36 | 37 | 38 | -------------------------------------------------------------------------------- /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(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/ParamPassing.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class Foo(x: Int) 5 | //│ class Foo(x: Int) 6 | 7 | 8 | class Bar(x: Int, y: Int) extends Foo(x + y) 9 | //│ class Bar(x: Int, y: Int) extends Foo 10 | 11 | 12 | 13 | mixin AA(a: Int) { 14 | } 15 | //│ mixin AA(a: Int) 16 | 17 | mixin BB {} 18 | //│ mixin BB() 19 | 20 | 21 | class C(x: Int) extends BB 22 | //│ class C(x: Int) 23 | 24 | class D(x: Int) extends AA(x) 25 | //│ class D(x: Int) 26 | 27 | class E(x: Int) extends BB, AA(x) 28 | //│ class E(x: Int) 29 | 30 | 31 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Parens.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | () 5 | //│ () 6 | //│ res 7 | //│ = [] 8 | 9 | :pe 10 | (,) 11 | //│ ╔══[PARSE ERROR] Unexpected comma in expression position 12 | //│ ║ l.10: (,) 13 | //│ ╙── ^ 14 | //│ ╔══[PARSE ERROR] Unexpected end of parenthesis section; an expression was expected here 15 | //│ ║ l.10: (,) 16 | //│ ╙── ^ 17 | //│ undefined 18 | //│ res 19 | //│ = undefined 20 | 21 | (1) 22 | //│ 1 23 | //│ res 24 | //│ = 1 25 | 26 | (1,) 27 | //│ 1 28 | //│ res 29 | //│ = 1 30 | 31 | (1, 2) 32 | //│ (1, 2,) 33 | //│ res 34 | //│ = [ 1, 2 ] 35 | 36 | (1, 2,) 37 | //│ (1, 2,) 38 | //│ res 39 | //│ = [ 1, 2 ] 40 | 41 | 42 | let x: () 43 | //│ let x: () 44 | //│ x 45 | //│ = 46 | 47 | :pe 48 | let x: (,) 49 | //│ ╔══[PARSE ERROR] Unexpected comma in expression position 50 | //│ ║ l.48: let x: (,) 51 | //│ ╙── ^ 52 | //│ ╔══[PARSE ERROR] Unexpected end of parenthesis section; an expression was expected here 53 | //│ ║ l.48: let x: (,) 54 | //│ ╙── ^ 55 | //│ let x: undefined 56 | //│ x 57 | //│ = 58 | 59 | let x: (1) 60 | //│ let x: 1 61 | //│ x 62 | //│ = 63 | 64 | let x: (1,) 65 | //│ let x: 1 66 | //│ x 67 | //│ = 68 | 69 | let x: (1, 2) 70 | //│ let x: (1, 2,) 71 | //│ x 72 | //│ = 73 | 74 | let x: (1, 2,) 75 | //│ let x: (1, 2,) 76 | //│ x 77 | //│ = 78 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/SelfAppMethods.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | class A { 5 | 6 | fun f = f(f) 7 | 8 | fun g : A 9 | fun g = g(g) // * FIXME not using the signature 10 | 11 | } 12 | //│ class A { 13 | //│ fun f: nothing 14 | //│ fun g: A 15 | //│ } 16 | 17 | module A { 18 | fun i(x) = x 19 | fun f = f(f) 20 | fun g(x) = x(x) 21 | fun h = g(g) 22 | } 23 | //│ module A { 24 | //│ fun f: nothing 25 | //│ fun g: 'a -> 'b 26 | //│ fun h: 'b 27 | //│ fun i: 'c -> 'c 28 | //│ } 29 | //│ where 30 | //│ 'a := 'a -> 'b 31 | 32 | :ns 33 | A.i 34 | //│ 'i 35 | //│ where 36 | //│ 'i :> 'a -> 'a 37 | //│ res 38 | //│ = [Function: i] 39 | 40 | :re 41 | :ns 42 | A.f 43 | //│ 'f 44 | //│ res 45 | //│ Runtime error: 46 | //│ RangeError: Maximum call stack size exceeded 47 | 48 | :ns 49 | A.g 50 | //│ 'g 51 | //│ where 52 | //│ 'g :> 'a -> 'b 53 | //│ 'a := 'a -> 'b 54 | //│ 'b <: 'c 55 | //│ res 56 | //│ = [Function: g] 57 | 58 | :ns 59 | :re 60 | A.h 61 | //│ 'h 62 | //│ res 63 | //│ Runtime error: 64 | //│ RangeError: Maximum call stack size exceeded 65 | 66 | 67 | -------------------------------------------------------------------------------- /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/TypeAliases.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | type I = Int 5 | //│ type I = Int 6 | 7 | class CI1 8 | //│ class CI1 9 | 10 | // :e 11 | type AI1 = Array[Int] 12 | //│ type AI1 = Array[Int] 13 | 14 | type AI2 = Array 15 | //│ type AI2 = Array[Int] 16 | 17 | :e 18 | type AI3(n) = Array[Int] 19 | //│ ╔══[ERROR] Type alias definitions cannot have value parameters 20 | //│ ║ l.18: type AI3(n) = Array[Int] 21 | //│ ╙── ^^^ 22 | //│ type AI3 = Array[Int] 23 | 24 | // :e 25 | type AI3[A] = Array 26 | //│ type AI3[A] = Array[A] 27 | 28 | type AI4 = Array 29 | //│ type AI4[A] = Array[A] 30 | 31 | let r = 123 32 | //│ let r: 123 33 | //│ r 34 | //│ = 123 35 | 36 | r: I 37 | //│ I 38 | //│ res 39 | //│ = 123 40 | 41 | let a = [r, r, r] 42 | //│ let a: (123, 123, 123,) 43 | //│ a 44 | //│ = [ 123, 123, 123 ] 45 | 46 | a : AI1 47 | //│ AI1 48 | //│ res 49 | //│ = [ 123, 123, 123 ] 50 | 51 | a : AI2 52 | //│ AI2 53 | //│ res 54 | //│ = [ 123, 123, 123 ] 55 | 56 | a : AI3[Int] 57 | //│ AI3[Int] 58 | //│ res 59 | //│ = [ 123, 123, 123 ] 60 | 61 | a : AI4 62 | //│ AI4[Int] 63 | //│ res 64 | //│ = [ 123, 123, 123 ] 65 | 66 | -------------------------------------------------------------------------------- /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 | 24 | -------------------------------------------------------------------------------- /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 | //│ type T = Int 7 | //│ } 8 | 9 | 1 : Test.T 10 | //│ Int 11 | //│ res 12 | //│ = 1 13 | 14 | 15 | trait Test { type T = Int } 16 | //│ trait Test { 17 | //│ type T = Int 18 | //│ } 19 | 20 | :e 21 | 1 : Test.T 22 | //│ ╔══[ERROR] Illegal prefix of type selection: Test 23 | //│ ║ l.21: 1 : Test.T 24 | //│ ╙── ^^^^ 25 | //│ error 26 | //│ res 27 | //│ = 1 28 | 29 | 30 | -------------------------------------------------------------------------------- /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 | //│ () -> Int 10 | //│ Code generation encountered an error: 11 | //│ unresolved symbol Int 12 | 13 | :e 14 | Int() 15 | //│ ╔══[ERROR] Class Int is abstract and cannot be instantiated 16 | //│ ║ l.14: Int() 17 | //│ ╙── ^^^ 18 | //│ Int 19 | //│ Code generation encountered an error: 20 | //│ unresolved symbol Int 21 | 22 | :e 23 | new Int 24 | //│ ╔══[ERROR] Class Int is abstract and cannot be instantiated 25 | //│ ║ l.23: new Int 26 | //│ ╙── ^^^ 27 | //│ Int 28 | //│ Code generation encountered an error: 29 | //│ unresolved symbol Int 30 | 31 | 32 | // FIXME forbid statically 33 | module A extends Int 34 | //│ module A extends Int, Num 35 | //│ Code generation encountered an error: 36 | //│ unresolved parent Int. 37 | 38 | 39 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/Vals.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | 4 | val a = 1 5 | val b = a + 1 6 | //│ let a: 1 7 | //│ let 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 | //│ let c: Int 19 | //│ let d: 1 20 | //│ Code generation encountered an error: 21 | //│ unresolved symbol d 22 | 23 | 24 | // :e // FIXME should not type check 25 | val a = a 26 | //│ let a: nothing 27 | //│ a 28 | //│ = 1 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /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[E](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 | //│ let add11: 'E 14 | //│ module EvalAddLit { 15 | //│ fun eval: (e: 'lhs,) -> nothing 16 | //│ } 17 | //│ let res: nothing 18 | //│ where 19 | //│ 'lhs <: Add['A] 20 | //│ 'A <: 'lhs 21 | //│ 'E :> Add['E] 22 | 23 | 24 | -------------------------------------------------------------------------------- /shared/src/test/diff/nu/repro1.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | 5 | class Union[out Region](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: 'expr -> 'a & ('expr0 | 'lhs) -> Int} 23 | //│ fun eval: (Add['lhs] | Lit | Neg['expr0 & (Neg['expr] | Object & ~#Neg)]) -> (Int | 'a) 24 | //│ } 25 | 26 | // module TestLang extends EvalBase, EvalNeg 27 | module TestLang extends EvalBase 28 | //│ module TestLang { 29 | //│ fun eval: forall 'E. (Add['E] | Lit | Neg['a & (Neg['a] | Object & ~#Neg)]) -> Int 30 | //│ } 31 | //│ where 32 | //│ 'E <: 'a 33 | //│ 'a <: Add['E] | Lit | Neg['a & (Neg['a] | Object & ~#Neg)] 34 | 35 | 36 | fun mk(n) = if n is 37 | 0 then Lit(0) 38 | 1 then Neg(mk(n)) 39 | _ then Add(mk(n), mk(n)) 40 | //│ fun mk: forall 'E. Object -> 'E 41 | //│ where 42 | //│ 'E :> Add['E] | Lit | Neg['E] 43 | 44 | :stats 45 | TestLang.eval(mk(0)) 46 | //│ Int 47 | //│ res 48 | //│ = 0 49 | //│ constrain calls : 203 50 | //│ annoying calls : 64 51 | //│ subtyping calls : 1785 52 | 53 | 54 | -------------------------------------------------------------------------------- /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,) -> anything} 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/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: {'(' ')'} 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: {'(' ')'} 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 = '(' ')'} 50 | 51 | -------------------------------------------------------------------------------- /shared/src/test/diff/parser/Comments.mls: -------------------------------------------------------------------------------- 1 | 2 | // TODO comments 3 | 1 // whoops 4 | //│ |1| |/* whoops*/| 5 | //│ Parsed: {1} 6 | 7 | 2 /* whoops */ 8 | //│ |2| |/* whoops */| 9 | //│ Parsed: {2} 10 | -------------------------------------------------------------------------------- /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/Subscripts.mls: -------------------------------------------------------------------------------- 1 | 2 | a[0] 3 | //│ |a|[|0|]| 4 | //│ Parsed: {a‹0›} 5 | 6 | a[0][1] 7 | //│ |a|[|0|]|[|1|]| 8 | //│ Parsed: {a‹0›‹1›} 9 | 10 | a.x[0].y[1].z 11 | //│ |a|.x|[|0|]|.y|[|1|]|.z| 12 | //│ Parsed: {(((a).x‹0›).y‹1›).z} 13 | 14 | a + b [0] * 2 15 | //│ |a| |+| |b| |[|0|]| |*| |2| 16 | //│ Parsed: {+ (a,) (* (b‹0›,) (2,),)} 17 | 18 | foo 19 | [1] 20 | //│ |foo|→|[|1|]|←| 21 | //│ Parsed: {foo‹1›} 22 | 23 | Foo(bar) + 1 24 | ["hello"] 25 | //│ |Foo|(|bar|)| |+| |1|→|[|"hello"|]|←| 26 | //│ Parsed: {+ (Foo (bar,),) (1,)‹"hello"›} 27 | 28 | Foo(bar) + 29 | 1["hello"] 30 | //│ |Foo|(|bar|)| |+|→|1|[|"hello"|]|←| 31 | //│ Parsed: {+ (Foo (bar,),) ({1‹"hello"›},)} 32 | 33 | Foo(bar) + 34 | 1 35 | ["hello"] 36 | //│ |Foo|(|bar|)| |+|→|1|→|[|"hello"|]|←|←| 37 | //│ Parsed: {+ (Foo (bar,),) ({1‹"hello"›},)} 38 | 39 | Foo(bar) + 1 40 | [1] 41 | [2] 42 | //│ |Foo|(|bar|)| |+| |1|→|[|1|]|↵|[|2|]|←| 43 | //│ Parsed: {+ (Foo (bar,),) (1,)‹1›‹2›} 44 | 45 | Foo(bar) + 1 46 | [1] 47 | [2] 48 | //│ |Foo|(|bar|)| |+| |1|→|[|1|]|→|[|2|]|←|←| 49 | //│ Parsed: {+ (Foo (bar,),) (1,)‹1›‹2›} 50 | 51 | a + 52 | 111 53 | [22] 54 | [333] 55 | //│ |a| |+|→|111|→|[|22|]|←|↵|[|333|]|←| 56 | //│ Parsed: {+ (a,) ({111‹22›; '(' 333, ')'},)} 57 | 58 | Foo(bar) + 59 | 1 60 | [1] 61 | [2] 62 | //│ |Foo|(|bar|)| |+|→|1|→|[|1|]|←|↵|[|2|]|←| 63 | //│ Parsed: {+ (Foo (bar,),) ({1‹1›; '(' 2, ')'},)} 64 | 65 | a of [333] 66 | //│ |a| |#of| |[|333|]| 67 | //│ Parsed: {a ('(' 333, ')',)} 68 | 69 | a of 70 | [333] 71 | //│ |a| |#of|→|[|333|]|←| 72 | //│ Parsed: {a ('(' 333, ')',)} 73 | 74 | a of 75 | 111 76 | [22] 77 | [333] 78 | //│ |a| |#of|→|111|→|[|22|]|←|↵|[|333|]|←| 79 | //│ Parsed: {a ({111‹22›; '(' 333, ')'},)} 80 | 81 | a( 82 | 111 83 | [22] 84 | [333] 85 | ) 86 | //│ |a|(|→|111|→|[|22|]|←|↵|[|333|]|←|↵|)| 87 | //│ Parsed: {a ({111‹22›; '(' 333, ')'},)} 88 | 89 | -------------------------------------------------------------------------------- /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 | fun foo: 'a + 'a + 'a where 'a : int 21 | //│ |#fun| |foo|#:| |'a| |+| |'a| |+| |'a| |#where| |'a| |#:| |int| 22 | //│ Parsed: {fun foo: +[(+[('a,), ('a,)],), ('a,)] 23 | //│ where 24 | //│ 'a <: int} 25 | 26 | fun foo: 'a -> 'a -> 'a where 'a : int 27 | //│ |#fun| |foo|#:| |'a| |->| |'a| |->| |'a| |#where| |'a| |#:| |int| 28 | //│ Parsed: {fun foo: 'a -> 'a -> 'a 29 | //│ where 30 | //│ 'a <: int} 31 | 32 | -------------------------------------------------------------------------------- /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/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: unexpected runtime error 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: unexpected runtime error 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/tricky/Pottier.fun: -------------------------------------------------------------------------------- 1 | 2 | 3 | // Inspired by [Pottier 98, chap 13.4] 4 | 5 | let rec f = x => y => add (f x.tail y) (f x y) 6 | let rec f = x => y => add (f x.tail y) (f y x) 7 | let rec f = x => y => add (f x.tail y) (f x y.tail) 8 | let rec f = x => y => add (f x.tail y.tail) (f x.tail y.tail) 9 | let rec f = x => y => add (f x.tail x.tail) (f y.tail y.tail) 10 | let rec f = x => y => add (f x.tail x) (f y.tail y) 11 | let rec f = x => y => add (f x.tail y) (f y.tail x) 12 | //│ f: 'a -> anything -> int 13 | //│ where 14 | //│ 'a <: {tail: 'a} 15 | //│ f: 'a -> 'a -> int 16 | //│ where 17 | //│ 'a <: {tail: 'a} 18 | //│ f: 'a -> 'a -> int 19 | //│ where 20 | //│ 'a <: {tail: 'a} 21 | //│ f: 'a -> 'a -> int 22 | //│ where 23 | //│ 'a <: {tail: 'a} 24 | //│ f: 'a -> 'a -> int 25 | //│ where 26 | //│ 'a <: {tail: 'a} 27 | //│ f: 'a -> 'a -> int 28 | //│ where 29 | //│ 'a <: {tail: 'a} 30 | //│ f: 'a -> 'a -> int 31 | //│ where 32 | //│ 'a <: {tail: 'a} 33 | 34 | let f = x => y => if true then { l: x; r: y } else { l: y; r: x } // 2-crown 35 | //│ f: 'a -> 'a -> {l: 'a, r: 'a} 36 | 37 | 38 | // Inspired by [Pottier 98, chap 13.5] 39 | 40 | let rec f = x => y => if true then x else { t: f x.t y.t } 41 | //│ f: 'a -> 'b -> 'c 42 | //│ where 43 | //│ 'b <: {t: 'b} 44 | //│ 'a <: {t: 'a} & 'c 45 | //│ 'c :> {t: 'c} 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/DirectLines.mls: -------------------------------------------------------------------------------- 1 | :NewParser 2 | 3 | fun f(x, y) = 4 | if 5 | x == 0 then "x" 6 | y == 0 then "y" 7 | _ then "nah" 8 | //│ f: (number, number,) -> ("nah" | "x" | "y") 9 | //│ = [Function: f] 10 | 11 | class Option 12 | class Some(value): Option 13 | class None: Option 14 | //│ Defined class Option 15 | //│ Defined class Some 16 | //│ Defined class None 17 | //│ Option: () -> Option 18 | //│ = [Function: Option1] 19 | //│ Some: 'value -> (Some & {value: 'value}) 20 | //│ = [Function: Some1] 21 | //│ None: () -> None 22 | //│ = [Function: None1] 23 | 24 | fun isValid(x) = if x then false else true 25 | //│ isValid: anything -> Bool 26 | //│ = [Function: isValid] 27 | 28 | fun f(x, allowNone) = 29 | if x 30 | is Some(x) and isValid(x) then "good" 31 | is None() and allowNone then "okay" 32 | is _ then "bad" 33 | //│ f: (anything, anything,) -> ("bad" | "good" | "okay") 34 | //│ = [Function: f1] 35 | 36 | fun f(x, y, z) = 37 | if 38 | x == 0 then "x" 39 | y == 40 | 1 then "y = 1" 41 | 2 and z == 42 | 0 then "z = 0" 43 | 9 then "z = 9" 44 | _ then "bruh" 45 | 3 then "y = 3" 46 | _ then "bruh" 47 | //│ f: (number, number, number,) -> ("bruh" | "x" | "y = 1" | "y = 3" | "z = 0" | "z = 9") 48 | //│ = [Function: f2] 49 | 50 | :w 51 | fun f(a, b) = 52 | if 53 | a == 0 then 0 54 | b == 55 | 1 then 1 56 | 2 then 2 57 | _ then 7 58 | else 3 59 | //│ ╔══[WARNING] Found a redundant else branch 60 | //│ ║ l.58: else 3 61 | //│ ╙── ^ 62 | //│ f: (number, number,) -> (0 | 1 | 2 | 7) 63 | //│ = [Function: f3] 64 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/ErrorMessage.mls: -------------------------------------------------------------------------------- 1 | :NewParser 2 | 3 | class Point(x, y) 4 | //│ Defined class Point 5 | //│ Point: ('x, 'y,) -> (Point & {x: 'x, y: 'y}) 6 | //│ = [Function: Point1] 7 | 8 | :e 9 | :ge 10 | fun f(p) = 11 | if p is 12 | Point(x, y, z) then x + y + z 13 | //│ ╔══[ERROR] class Point expects 2 parameters but found 3 parameters 14 | //│ ║ l.12: Point(x, y, z) then x + y + z 15 | //│ ╙── ^^^^^^^^^^^^^^ 16 | //│ f: anything -> error 17 | //│ Code generation encountered an error: 18 | //│ if expression was not desugared 19 | 20 | :e 21 | :ge 22 | fun g(xs) = 23 | if xs is 24 | head :: _ then head 25 | //│ ╔══[ERROR] Cannot find operator `::` in the context 26 | //│ ║ l.24: head :: _ then head 27 | //│ ╙── ^^ 28 | //│ g: anything -> error 29 | //│ Code generation encountered an error: 30 | //│ if expression was not desugared 31 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/Hygiene.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | class Some[T](value: T) 4 | class Left[T](value: T) 5 | class Right[T](value: T) 6 | //│ class Some[T](value: T) 7 | //│ class Left[T](value: T) 8 | //│ class Right[T](value: T) 9 | 10 | // FIXME unhygienic, the `x` in the second branch shadows parameter `x` 11 | fun foo(x) = if x is 12 | Some(Left(y)) then x 13 | Some(x) then x 14 | //│ fun foo: forall 'value. Some['value & (Left[anything] | Object & ~#Left)] -> 'value 15 | 16 | foo(Some(Left(1))) 17 | //│ Left[1] 18 | //│ res 19 | //│ = Left {} 20 | 21 | foo(Some(2)) 22 | //│ 2 23 | //│ res 24 | //│ = 2 25 | -------------------------------------------------------------------------------- /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 | // TODO 11 | fun f(a, b) = if a is 12 | Some(av) 13 | and b is Some(bv) then av + bv 14 | //│ ╔══[ERROR] Cannot find operator `and` in the context 15 | //│ ║ l.13: and b is Some(bv) then av + bv 16 | //│ ╙── ^^^ 17 | //│ fun f: (anything, anything,) -> error 18 | //│ Code generation encountered an error: 19 | //│ if expression was not desugared 20 | 21 | :p 22 | fun f(a, b) = if a is Some(av) 23 | and b is Some(bv) 24 | then av + bv 25 | //│ |#fun| |f|(|a|,| |b|)| |#=| |#if| |a| |is| |Some|(|av|)|→|and| |b| |is| |Some|(|bv|)|↵|#then| |av| |+| |bv|←| 26 | //│ Parsed: fun f = (a, b,) => if a is Some (av,) ‹· and (is (b,) (Some (bv,),)) then + (av,) (bv,)›; 27 | //│ fun f: (Some[Int], Some[Int],) -> Int 28 | 29 | // TODO 30 | :p 31 | fun f(a, b) = if a is 32 | Some(av) 33 | and b is Some(bv) 34 | then av + bv 35 | //│ |#fun| |f|(|a|,| |b|)| |#=| |#if| |a| |is|→|Some|(|av|)|→|and| |b| |is| |Some|(|bv|)|↵|#then| |av| |+| |bv|←|←| 36 | //│ Parsed: fun f = (a, b,) => if a is ‹Some (av,) ‹· and (is (b,) (Some (bv,),)) then + (av,) (bv,)››; 37 | //│ ╔══[ERROR] Cannot find operator `and` in the context 38 | //│ ║ l.33: and b is Some(bv) 39 | //│ ╙── ^^^ 40 | //│ fun f: (anything, anything,) -> error 41 | //│ Code generation encountered an error: 42 | //│ if expression was not desugared 43 | 44 | 45 | 46 | // FIXME (parser) 47 | fun f(a, b) = if a is 48 | Some(av) 49 | and b is Some(bv) then av + bv 50 | 51 | //│ /!!!\ Uncaught error: scala.NotImplementedError: an implementation is missing 52 | 53 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/LitUCS.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | module A 4 | //│ module A 5 | 6 | // This one is easy to fix but what about the next one? 7 | // The following example can better reveal the essence of the problem. 8 | fun test(x: 0 | A) = if x is 9 | 0 then 0 10 | A then A 11 | //│ fun test: (x: 0 | A,) -> (0 | A) 12 | 13 | :e 14 | // case === (x,) (0,) of { true => 0; _ => case x of { A => A } } 15 | fun test(x: 0 | A) = 16 | if 17 | x === 0 then 0 18 | x is A then A 19 | //│ ╔══[ERROR] Type mismatch in `case` expression: 20 | //│ ║ l.18: x is A then A 21 | //│ ║ ^^^^^^^^^^^^^ 22 | //│ ╟── type `0` is not an instance of type `A` 23 | //│ ║ l.15: fun test(x: 0 | A) = 24 | //│ ║ ^ 25 | //│ ╟── but it flows into reference with expected type `A` 26 | //│ ║ l.18: x is A then A 27 | //│ ║ ^ 28 | //│ ╟── Note: constraint arises from class pattern: 29 | //│ ║ l.18: x is A then A 30 | //│ ╙── ^ 31 | //│ fun test: (x: 0 | A,) -> (0 | A) 32 | 33 | fun test2(x) = 34 | if 35 | x === 0 then 0 36 | x is A then A 37 | //│ fun test2: (A & Eql[0]) -> (0 | A) 38 | 39 | :e 40 | test2(0) 41 | //│ ╔══[ERROR] Type mismatch in application: 42 | //│ ║ l.40: test2(0) 43 | //│ ║ ^^^^^^^^ 44 | //│ ╟── integer literal of type `0` is not an instance of type `A` 45 | //│ ║ l.40: test2(0) 46 | //│ ║ ^ 47 | //│ ╟── Note: constraint arises from class pattern: 48 | //│ ║ l.36: x is A then A 49 | //│ ║ ^ 50 | //│ ╟── from reference: 51 | //│ ║ l.36: x is A then A 52 | //│ ╙── ^ 53 | //│ 0 | A | error 54 | //│ res 55 | //│ = 0 56 | 57 | test2(A) 58 | //│ 0 | A 59 | //│ res 60 | //│ = A { class: [class A] } 61 | -------------------------------------------------------------------------------- /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/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 find operator `and` in the context 15 | //│ ║ l.11: and b is Some(v') then v + v' 16 | //│ ╙── ^^^ 17 | //│ fun f: (anything, anything,) -> error 18 | //│ Code generation encountered an error: 19 | //│ if expression was not desugared 20 | 21 | 22 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/ParseFailures.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | :NoJS 3 | 4 | // FIXME 5 | type Tree[A] = Node[A] | Empty 6 | module Empty { 7 | fun contains(wanted) = false 8 | } 9 | class Node[A](value: int, left: Tree[A], right: Tree[A]) { 10 | fun contains(wanted) = if wanted 11 | <= value then left.find(wanted) 12 | >= value then right.find(wanted) 13 | else true 14 | } 15 | //│ /!!!\ Uncaught error: scala.NotImplementedError: an implementation is missing 16 | 17 | // FIXME 18 | type Tree[A] = Node[A] | Empty 19 | module Empty { 20 | fun contains(wanted) = false 21 | } 22 | class Node[A](value: int, left: Tree[A], right: Tree[A]) { 23 | fun contains(wanted) = if wanted 24 | <= value then left.find(wanted) 25 | >= value then right.find(wanted) 26 | _ true 27 | } 28 | //│ /!!!\ Uncaught error: scala.NotImplementedError: an implementation is missing 29 | 30 | // FIXME 31 | fun foo(x, y) = if x is 32 | Z() and y is O() then 0 else 1 33 | //│ ╔══[PARSE ERROR] Unexpected 'else' keyword here 34 | //│ ║ l.32: Z() and y is O() then 0 else 1 35 | //│ ╙── ^^^^ 36 | //│ ╔══[ERROR] Illegal pattern `Z` 37 | //│ ║ l.32: Z() and y is O() then 0 else 1 38 | //│ ╙── ^ 39 | //│ fun foo: (anything, anything,) -> error 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 | //│ /!!!\ Uncaught error: scala.NotImplementedError: an implementation is missing 10 | 11 | // FIXME: Interleaved let bindings are not implemented in `IfOpsApp`. 12 | fun tt(x) = 13 | if x 14 | is A() then "A" 15 | let y = 0 16 | is B() then "B" 17 | //│ /!!!\ Uncaught error: scala.NotImplementedError: an implementation is missing 18 | 19 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/SplitAnd.mls: -------------------------------------------------------------------------------- 1 | :NewParser 2 | 3 | fun f(x, y) = 4 | if x == 0 and 5 | y == 0 then "bruh" 6 | y == 1 then "lol" 7 | else "okay" 8 | //│ f: (number, number,) -> ("bruh" | "lol" | "okay") 9 | //│ = [Function: f] 10 | 11 | class A() 12 | class B() 13 | //│ Defined class A 14 | //│ Defined class B 15 | //│ A: () -> A 16 | //│ = [Function: A1] 17 | //│ B: () -> B 18 | //│ = [Function: B1] 19 | 20 | :e 21 | :ge 22 | fun f(x) = 23 | if x == 0 and 24 | x is 25 | A() then "A" 26 | B() then "B" 27 | x == 0 then "lol" 28 | else "bruh" 29 | //│ ╔══[ERROR] The case when this is false is not handled: == (x,) (0,) 30 | //│ ║ l.23: if x == 0 and 31 | //│ ╙── ^^^^^^ 32 | //│ f: anything -> error 33 | //│ Code generation encountered an error: 34 | //│ if expression was not desugared 35 | 36 | :e 37 | :ge 38 | fun f(x, y) = 39 | if 40 | x == 0 and 41 | y == 0 then "bruh" 42 | else "lol" 43 | //│ ╔══[ERROR] The case when this is false is not handled: == (x,) (0,) 44 | //│ ║ l.40: x == 0 and 45 | //│ ╙── ^^^^^^ 46 | //│ f: (anything, anything,) -> error 47 | //│ Code generation encountered an error: 48 | //│ if expression was not desugared 49 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/SplitAroundOp.mls: -------------------------------------------------------------------------------- 1 | :NewParser 2 | :NewDefs 3 | 4 | fun f(x, b) = 5 | if x 6 | === 7 | 0 and b then "n0" 8 | 1 and b then "n1" 9 | 2 then "n2" 10 | === 11 | "0" then "s0" 12 | "1" then "s1" 13 | "2" then "s2" 14 | else ":p" 15 | //│ fun f: (Eql[nothing], Object,) -> (":p" | "n0" | "n1" | "n2" | "s0" | "s1" | "s2") 16 | 17 | fun f(x, y, a, b) = 18 | if x === 0 19 | and 20 | y === 0 then "x, y" 21 | a === 0 then "x, a" 22 | b === 0 then "x, b" 23 | else "nah" 24 | //│ fun f: (Eql[0], Eql[0], Eql[0], Eql[0],) -> ("nah" | "x, a" | "x, b" | "x, y") 25 | 26 | class A() 27 | class B() 28 | //│ class A() 29 | //│ class B() 30 | 31 | fun f(x) = 32 | if x 33 | is 34 | A() then 0 35 | B() then 1 36 | //│ fun f: (A | B) -> (0 | 1) 37 | 38 | // It fails because we interpret == as a constructor. 39 | :e 40 | :ge 41 | if x is 42 | A() 43 | === 0 then 0 44 | > 0 then 1 45 | < 0 then 2 46 | //│ ╔══[ERROR] Cannot find operator `===` in the context 47 | //│ ║ l.43: === 0 then 0 48 | //│ ╙── ^^^ 49 | //│ error 50 | //│ Code generation encountered an error: 51 | //│ if expression was not desugared 52 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/SplitBeforeOp.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | :e 4 | :ge 5 | if x 6 | == 0 then 0 7 | //│ ╔══[ERROR] The case when this is false is not handled: == (x,) (0,) 8 | //│ ║ l.5: if x 9 | //│ ║ ^ 10 | //│ ║ l.6: == 0 then 0 11 | //│ ╙── ^^^^^^ 12 | //│ error 13 | //│ Code generation encountered an error: 14 | //│ if expression was not desugared 15 | 16 | :e 17 | :ge 18 | if x 19 | is A and 20 | y then 0 21 | //│ ╔══[ERROR] Cannot find constructor `A` in scope 22 | //│ ║ l.19: is A and 23 | //│ ╙── ^ 24 | //│ error 25 | //│ Code generation encountered an error: 26 | //│ if expression was not desugared 27 | 28 | :e 29 | :ge 30 | if x 31 | is A and 32 | y then 0 33 | else 1 34 | //│ ╔══[ERROR] Cannot find constructor `A` in scope 35 | //│ ║ l.31: is A and 36 | //│ ╙── ^ 37 | //│ error 38 | //│ Code generation encountered an error: 39 | //│ if expression was not desugared 40 | 41 | :e 42 | :ge 43 | if x 44 | == 0 then 0 45 | is 46 | A() then "A" 47 | B() then "B" 48 | //│ ╔══[ERROR] Illegal pattern `A` 49 | //│ ║ l.46: A() then "A" 50 | //│ ╙── ^ 51 | //│ error 52 | //│ Code generation encountered an error: 53 | //│ if expression was not desugared 54 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/SplitScrutinee.mls: -------------------------------------------------------------------------------- 1 | :NewParser 2 | :NoJS 3 | 4 | fun f(x) = 5 | if x + 6 | 1 is 7 | 2 then 1 8 | 3 then 2 9 | _ then "I don't know." 10 | //│ f: int -> ("I don't know." | 1 | 2) 11 | -------------------------------------------------------------------------------- /shared/src/test/diff/ucs/Tree.mls: -------------------------------------------------------------------------------- 1 | :NewDefs 2 | 3 | type Option[A] = Some[A] | None 4 | class Some[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[A] = Node[A] | Empty 11 | module Empty 12 | class Node[A](value: Int, left: Tree[A], right: Tree[A]) 13 | //│ type Tree[A] = Empty | Node[A] 14 | //│ module Empty 15 | //│ class Node[A](value: Int, 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 'A0. (Empty | Node['A], Num & 'A0,) -> (None | Some['A0]) 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['A], Int,) -> 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 | :NewParser 2 | 3 | class A() 4 | class B() 5 | //│ Defined class A 6 | //│ Defined class B 7 | //│ A: () -> A 8 | //│ = [Function: A1] 9 | //│ B: () -> B 10 | //│ = [Function: B1] 11 | 12 | fun f(x) = 13 | if x 14 | is 15 | A then 0 16 | B then 1 17 | //│ f: (A | B) -> (0 | 1) 18 | //│ = [Function: f] 19 | 20 | // Precedence problem: should we restruct terms when push them to the stack? 21 | :e 22 | fun f(x) = 23 | if x == 24 | 1 25 | + 2 then 0 26 | + _ then 1 27 | //│ ╔══[ERROR] Type mismatch in operator application: 28 | //│ ║ l.23: if x == 29 | //│ ║ ^^^^ 30 | //│ ║ l.24: 1 31 | //│ ║ ^^^^^^ 32 | //│ ║ l.25: + 2 then 0 33 | //│ ║ ^^^^^^^ 34 | //│ ╟── operator application of type `bool` is not an instance of type `int` 35 | //│ ║ l.23: if x == 36 | //│ ║ ^^^^ 37 | //│ ║ l.24: 1 38 | //│ ╙── ^^^^^^ 39 | //│ f: number -> (0 | 1) 40 | //│ = [Function: f1] 41 | 42 | fun f(x, s, t) = 43 | if x 44 | is A() 45 | and t then 0 46 | and s then 0 47 | is _ then 1 48 | //│ f: (anything, anything, anything,) -> (0 | 1) 49 | //│ = [Function: f2] 50 | -------------------------------------------------------------------------------- /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 | ) 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /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/JSWriter.scala: -------------------------------------------------------------------------------- 1 | package ts2mls 2 | 3 | import scala.scalajs.js 4 | import js.Dynamic.{global => g} 5 | import js.DynamicImplicits._ 6 | import mlscript.utils._ 7 | 8 | class JSWriter(filename: String) { 9 | import JSWriter._ 10 | 11 | // Create an empty file if it does not exists. 12 | if (!fs.existsSync(filename)) fs.writeFileSync(filename, "") 13 | 14 | // r+: Open file for reading and writing. An exception occurs if the file does not exist. 15 | // See https://nodejs.org/api/fs.html#file-system-flags to get more details. 16 | private val out = fs.openSync(filename, "r+") 17 | 18 | private var fileSize = 0 // how many bytes we've written in the file 19 | private var needTruncate = false 20 | 21 | writeln(":NewParser\n:ParseOnly") 22 | 23 | def writeln(str: String) = { 24 | val strln = str + "\n" 25 | val buffer = createBuffer(strln.length) 26 | fs.readSync(out, buffer, 0, strln.length) 27 | 28 | // override when the content is different 29 | if (strln =/= buffer.toString()) { 30 | fs.writeSync(out, strln, fileSize) // `fileSize` is the offset from the beginning of the file 31 | needTruncate = true // if the file has been modified, we need to truncate the file to keep it clean 32 | } 33 | 34 | fileSize += strln.length 35 | } 36 | 37 | def close() = { 38 | if (needTruncate) fs.truncateSync(out, fileSize) // remove other content to keep the file from chaos 39 | 40 | fs.closeSync(out) 41 | } 42 | } 43 | 44 | object JSWriter { 45 | private val fs = g.require("fs") // must use fs module to manipulate files in JS 46 | 47 | def apply(filename: String) = new JSWriter(filename) 48 | 49 | private def createBuffer(length: Int) = g.Buffer.alloc(length) 50 | } 51 | -------------------------------------------------------------------------------- /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(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/ClassMember.d.mls: -------------------------------------------------------------------------------- 1 | :NewParser 2 | :ParseOnly 3 | class Student(s: string, age: number) { 4 | let name: string 5 | fun isFriend(other: Student): (false) | (true) 6 | fun addScore(sub: string, score: number): unit 7 | fun getID(): number 8 | } 9 | class Foo() { 10 | fun bar(x: T): unit 11 | } 12 | class EZ() { 13 | fun inc(x: number): number 14 | } 15 | class Outer() { 16 | class Inner() { 17 | let a: number 18 | } 19 | } 20 | class TTT() { 21 | fun ttt(x: T): T 22 | fun ttt2(x: T): T 23 | } 24 | //│ |#class| |Student|(|s|#:| |string|,| |age|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|(|other|#:| |Student|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |addScore|(|sub|#:| |string|,| |score|#:| |number|)|#:| |unit|↵|#fun| |getID|(||)|#:| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|(|x|#:| |T|)|#:| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|(|x|#:| |number|)|#:| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|x|#:| |T|)|#:| |T|↵|#fun| |ttt2|(|x|#:| |T|)|#:| |T|←|↵|}| 25 | //│ Parsed: {class Student(s: string, age: number,) {let name: string; fun isFriend: (other: Student,) -> bool; fun addScore: (sub: string, score: number,) -> unit; fun getID: () -> number}; class Foo‹T›() {fun bar: (x: T,) -> unit}; class EZ() {fun inc: (x: number,) -> number}; class Outer() {class Inner() {let a: number}}; class TTT‹T›() {fun ttt: (x: T,) -> T; fun ttt2: (x: T,) -> T}} 26 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/Dec.d.mls: -------------------------------------------------------------------------------- 1 | :NewParser 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 | undefined,) -> string; trait Get() {fun __call: (id: string,) -> string}; class Person(name: string, age: number,) {fun getName: (id: number,) -> string}; module OOO() {}} 15 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/Enum.d.mls: -------------------------------------------------------------------------------- 1 | :NewParser 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 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/HighOrderFunc.d.mls: -------------------------------------------------------------------------------- 1 | :NewParser 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 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/Literal.d.mls: -------------------------------------------------------------------------------- 1 | :NewParser 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 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/MultiFiles.d.mls: -------------------------------------------------------------------------------- 1 | :NewParser 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 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/Namespace.d.mls: -------------------------------------------------------------------------------- 1 | :NewParser 2 | :ParseOnly 3 | module N1 { 4 | fun f(x: anything): number 5 | fun ff(y: anything): number 6 | class C() { 7 | fun f(): unit 8 | } 9 | trait I() { 10 | fun f(): number 11 | } 12 | module N2 { 13 | fun fff(x: (false) | (true)): number 14 | fun gg(c: N1.C): N1.C 15 | class BBB(): N1.C {} 16 | } 17 | } 18 | module AA { 19 | fun f(x: anything): string 20 | class C() { 21 | fun f(): unit 22 | } 23 | trait I() { 24 | fun f(): number 25 | } 26 | module N2 { 27 | } 28 | } 29 | fun f1(x: N1.C): N1.C 30 | fun f2(x: AA.C): AA.C 31 | //│ |#module| |N1| |{|→|#fun| |f|(|x|#:| |anything|)|#:| |number|↵|#fun| |ff|(|y|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#module| |N2| |{|→|#fun| |fff|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |number|↵|#fun| |gg|(|c|#:| |N1|.C|)|#:| |N1|.C|↵|#class| |BBB|(||)|#:| |N1|.C| |{||}|←|↵|}|←|↵|}|↵|#module| |AA| |{|→|#fun| |f|(|x|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#module| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|x|#:| |N1|.C|)|#:| |N1|.C|↵|#fun| |f2|(|x|#:| |AA|.C|)|#:| |AA|.C| 32 | //│ Parsed: {module N1() {fun f: (x: anything,) -> number; fun ff: (y: anything,) -> number; class C() {fun f: () -> unit}; trait I() {fun f: () -> number}; module N2() {fun fff: (x: bool,) -> number; fun gg: (c: N1.C,) -> N1.C; class BBB(): N1.C {}}}; module AA() {fun f: (x: anything,) -> string; class C() {fun f: () -> unit}; trait I() {fun f: () -> number}; module N2() {}}; fun f1: (x: N1.C,) -> N1.C; fun f2: (x: AA.C,) -> AA.C} 33 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/Union.d.mls: -------------------------------------------------------------------------------- 1 | :NewParser 2 | :ParseOnly 3 | fun getString(x: (((string) | (number)) | (false)) | (true)): string 4 | fun test(x: (false) | (true)): (string) | (number) 5 | fun run(f: ((number) => number) | ((number) => string)): anything 6 | fun get(arr: (MutArray) | (MutArray)): unit 7 | fun get2(t: ((string, string, )) | ((number, string, ))): string 8 | fun typeVar(x: (T) | (U)): (T) | (U) 9 | fun uuuu(x: (((string) | (number)) | (false)) | (true)): (((string) | (number)) | (false)) | (true) 10 | //│ |#fun| |getString|(|x|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |string|↵|#fun| |test|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|f|#:| |(|(|number|)| |=>| |number|)| ||| |(|(|number|)| |=>| |string|)|)|#:| |anything|↵|#fun| |get|(|arr|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|t|#:| |(|(|string|,| |string|,| |)|)| ||| |(|(|number|,| |string|,| |)|)|)|#:| |string|↵|#fun| |typeVar|‹|T|,| |U|›|(|x|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|x|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)| 11 | //│ Parsed: {fun getString: (x: string | number | false | true,) -> string; fun test: (x: bool,) -> (string | number); fun run: (f: number -> number | number -> string,) -> anything; fun get: (arr: MutArray[number] | MutArray[string],) -> unit; fun get2: (t: (string, string,) | (number, string,),) -> string; fun typeVar: (x: T | U,) -> (T | U); fun uuuu: (x: string | number | false | true,) -> (string | number | false | true)} 12 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/diff/Variables.d.mls: -------------------------------------------------------------------------------- 1 | :NewParser 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 | -------------------------------------------------------------------------------- /ts2mls/js/src/test/scala/ts2mls/TSTypeGenerationTests.scala: -------------------------------------------------------------------------------- 1 | package ts2mls 2 | 3 | import org.scalatest.funsuite.AnyFunSuite 4 | 5 | class TSTypeGenerationTest extends AnyFunSuite { 6 | import TSTypeGenerationTest._ 7 | 8 | testsData.foreach((data) => test(data._2) { 9 | val program = TSProgram(tsPath(data._1)) 10 | var writer = JSWriter(diffPath(data._2)) 11 | program.generate(writer) 12 | writer.close() 13 | }) 14 | } 15 | 16 | object TSTypeGenerationTest { 17 | private def tsPath(filenames: Seq[String]) = filenames.map((fn) => s"ts2mls/js/src/test/typescript/$fn") 18 | private def diffPath(filename: String) = s"ts2mls/js/src/test/diff/$filename" 19 | 20 | private val testsData = List( 21 | (Seq("Array.ts"), "Array.d.mls"), 22 | (Seq("BasicFunctions.ts"), "BasicFunctions.d.mls"), 23 | (Seq("ClassMember.ts"), "ClassMember.d.mls"), 24 | (Seq("Dec.d.ts"), "Dec.d.mls"), 25 | (Seq("Enum.ts"), "Enum.d.mls"), 26 | (Seq("Heritage.ts"), "Heritage.d.mls"), 27 | (Seq("HighOrderFunc.ts"), "HighOrderFunc.d.mls"), 28 | (Seq("InterfaceMember.ts"), "InterfaceMember.d.mls"), 29 | (Seq("Intersection.ts"), "Intersection.d.mls"), 30 | (Seq("Literal.ts"), "Literal.d.mls"), 31 | (Seq("Multi1.ts", "Multi2.ts", "Multi3.ts"), "MultiFiles.d.mls"), 32 | (Seq("Namespace.ts"), "Namespace.d.mls"), 33 | (Seq("Optional.ts"), "Optional.d.mls"), 34 | (Seq("Overload.ts"), "Overload.d.mls"), 35 | (Seq("Tuple.ts"), "Tuple.d.mls"), 36 | (Seq("Type.ts"), "Type.d.mls"), 37 | (Seq("TypeParameter.ts"), "TypeParameter.d.mls"), 38 | (Seq("Union.ts"), "Union.d.mls"), 39 | (Seq("Variables.ts"), "Variables.d.mls"), 40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /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 | set(x: T) { this.t = x; } 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 | --------------------------------------------------------------------------------