diff --git a/cabal.project b/cabal.project index 19673c9cd4..dfc530465c 100644 --- a/cabal.project +++ b/cabal.project @@ -5,6 +5,11 @@ multi-repl: True package futhark ghc-options: -j -fwrite-ide-info -hiedir=.hie +source-repository-package + type: git + location: https://github.com/jyp/glpk-hs.git + tag: 1f276aa19861203ea8367dc27a6ad4c8a31c9062 + allow-newer: base, template-haskell, ghc-prim multi-repl: True diff --git a/default.nix b/default.nix index e0f840374b..489a5aa37e 100644 --- a/default.nix +++ b/default.nix @@ -34,6 +34,9 @@ let futhark-manifest = haskellPackagesNew.callPackage ./nix/futhark-manifest.nix { }; + gasp = + haskellPackagesNew.callPackage ./nix/gasp.nix {}; + futhark = # callCabal2Nix does not do a great job at determining # which files must be included as source, which causes diff --git a/docs/language-reference.rst b/docs/language-reference.rst index c7da84ee10..950567603c 100644 --- a/docs/language-reference.rst +++ b/docs/language-reference.rst @@ -1001,9 +1001,11 @@ Syntactic sugar for ``let a = a with [i] = v in a``. ............................... Bind ``f`` to a function with the given parameters and definition -(``e``) and evaluate ``body``. The function will be treated as -aliasing any free variables in ``e``. The function is not in scope of -itself, and hence cannot be recursive. +(``e``) and evaluate ``body``. The function will be treated as +aliasing any free variables in ``e``. The function is not in scope of +itself, and hence cannot be recursive. While the function can be made +polymorphic by putting in explicit size parameters, it is not +automatically generalised the way top level functions are. ``loop pat = initial for x in a do loopbody`` ............................................. diff --git a/futhark.cabal b/futhark.cabal index 470a37032f..1339a0cbae 100644 --- a/futhark.cabal +++ b/futhark.cabal @@ -421,14 +421,21 @@ library Language.Futhark.Tuple Language.Futhark.TypeChecker Language.Futhark.TypeChecker.Consumption + Language.Futhark.TypeChecker.Constraints + Language.Futhark.TypeChecker.TySolve + Language.Futhark.TypeChecker.TySolveOld + Language.Futhark.TypeChecker.UnionFind + Language.Futhark.TypeChecker.Error Language.Futhark.TypeChecker.Names Language.Futhark.TypeChecker.Match Language.Futhark.TypeChecker.Modules Language.Futhark.TypeChecker.Monad + Language.Futhark.TypeChecker.Rank Language.Futhark.TypeChecker.Terms Language.Futhark.TypeChecker.Terms.Loop Language.Futhark.TypeChecker.Terms.Monad Language.Futhark.TypeChecker.Terms.Pat + Language.Futhark.TypeChecker.Terms.Unsized Language.Futhark.TypeChecker.Types Language.Futhark.TypeChecker.Unify Language.Futhark.Warnings @@ -509,6 +516,8 @@ library futhark-testing import: common hs-source-dirs: src-testing exposed-modules: + Generated.AllFutBenchmarks + Generated.AllFutBenchmarks.Accelerate.Nbody.Nbodybh Futhark.AD.DerivativesTests Futhark.Analysis.AlgSimplifyTests Futhark.Analysis.DataDependenciesTests @@ -540,6 +549,8 @@ library futhark-testing Language.Futhark.SemanticTests Language.Futhark.SyntaxTests Language.Futhark.TypeChecker.TypesTests + Language.Futhark.TypeChecker.TySolveBenchmarks + Language.Futhark.TypeChecker.TySolveTests Language.Futhark.TypeChecker.ConsumptionTests Language.Futhark.TypeCheckerTests build-depends: @@ -551,11 +562,13 @@ library futhark-testing , free , futhark , megaparsec - , srcloc + , srcloc >=0.4 , tasty , tasty-hunit , tasty-quickcheck , text + , srcloc + , regex-tdfa ^>= 1.3.2 test-suite unit import: common diff --git a/nix/gasp.nix b/nix/gasp.nix new file mode 100644 index 0000000000..526b047bdc --- /dev/null +++ b/nix/gasp.nix @@ -0,0 +1,14 @@ +{ mkDerivation, adjunctions, base, binary, constraints, containers +, distributive, lib, mtl, QuickCheck +}: +mkDerivation { + pname = "gasp"; + version = "1.4.0.0"; + sha256 = "9a73a6ea7eb844493deb76c85c50249915e5ca29a6734a0b133a0e136c232f9f"; + libraryHaskellDepends = [ + adjunctions base binary constraints containers distributive mtl + QuickCheck + ]; + description = "A framework of algebraic classes"; + license = lib.licenses.bsd3; +} diff --git a/shell.nix b/shell.nix index 2ef9219f48..b5e520e82c 100644 --- a/shell.nix +++ b/shell.nix @@ -2,7 +2,17 @@ let sources = import ./nix/sources.nix; pkgs = import sources.nixpkgs {}; - python = pkgs.python313Packages; + python = pkgs.python313.withPackages (ps: with ps; [ + ps.mypy + black + cycler + numpy + pyopencl + matplotlib + jsonschema + sphinx + sphinxcontrib-bibtex + ]); haskell = pkgs.haskell.packages.ghc98; in pkgs.stdenv.mkDerivation { @@ -21,6 +31,7 @@ pkgs.stdenv.mkDerivation { haskell.haskell-language-server haskellPackages.graphmod haskellPackages.apply-refact + python xdot pkg-config zlib @@ -29,16 +40,6 @@ pkgs.stdenv.mkDerivation { ghcid niv ispc - python.python - python.mypy - python.black - python.cycler - python.numpy - python.pyopencl - python.matplotlib - python.jsonschema - python.sphinx - python.sphinxcontrib-bibtex imagemagick # needed for literate tests ] ++ lib.optionals (stdenv.isLinux) diff --git a/src-testing/Generated/AllFutBenchmarks.hs b/src-testing/Generated/AllFutBenchmarks.hs new file mode 100644 index 0000000000..b3f0c736e0 --- /dev/null +++ b/src-testing/Generated/AllFutBenchmarks.hs @@ -0,0 +1,24 @@ +module Generated.AllFutBenchmarks + ( allFutBenchmarkCases, + BenchmarkCaseData, + ) +where + +import Generated.AllFutBenchmarks.Accelerate.Nbody.Nbodybh qualified as AllFutBenchmarksAccelerateNbodyNbodybh +import Language.Futhark.TypeChecker.Constraints (CtTy, TyParams, TyVars) + +type BenchmarkCaseData = ([CtTy ()], TyParams, TyVars ()) + +allFutBenchmarkCases :: [(String, BenchmarkCaseData)] +allFutBenchmarkCases = + [ ("accelerate/nbody/nbody-bh.fut (Block 1/10) (Cons: 121)", head AllFutBenchmarksAccelerateNbodyNbodybh.benchmarkDataList), + ("accelerate/nbody/nbody-bh.fut (Block 2/10) (Cons: 146)", AllFutBenchmarksAccelerateNbodyNbodybh.benchmarkDataList !! 1), + ("accelerate/nbody/nbody-bh.fut (Block 3/10) (Cons: 133)", AllFutBenchmarksAccelerateNbodyNbodybh.benchmarkDataList !! 2), + ("accelerate/nbody/nbody-bh.fut (Block 4/10) (Cons: 45)", AllFutBenchmarksAccelerateNbodyNbodybh.benchmarkDataList !! 3), + ("accelerate/nbody/nbody-bh.fut (Block 5/10) (Cons: 210)", AllFutBenchmarksAccelerateNbodyNbodybh.benchmarkDataList !! 4), + ("accelerate/nbody/nbody-bh.fut (Block 6/10) (Cons: 401)", AllFutBenchmarksAccelerateNbodyNbodybh.benchmarkDataList !! 5), + ("accelerate/nbody/nbody-bh.fut (Block 7/10) (Cons: 39)", AllFutBenchmarksAccelerateNbodyNbodybh.benchmarkDataList !! 6), + ("accelerate/nbody/nbody-bh.fut (Block 8/10) (Cons: 173)", AllFutBenchmarksAccelerateNbodyNbodybh.benchmarkDataList !! 7), + ("accelerate/nbody/nbody-bh.fut (Block 9/10) (Cons: 164)", AllFutBenchmarksAccelerateNbodyNbodybh.benchmarkDataList !! 8), + ("accelerate/nbody/nbody-bh.fut (Block 10/10) (Cons: 40)", AllFutBenchmarksAccelerateNbodyNbodybh.benchmarkDataList !! 9) + ] diff --git a/src-testing/Generated/AllFutBenchmarks/Accelerate/Nbody/Nbodybh.hs b/src-testing/Generated/AllFutBenchmarks/Accelerate/Nbody/Nbodybh.hs new file mode 100644 index 0000000000..7b23719cba --- /dev/null +++ b/src-testing/Generated/AllFutBenchmarks/Accelerate/Nbody/Nbodybh.hs @@ -0,0 +1,1534 @@ +module Generated.AllFutBenchmarks.Accelerate.Nbody.Nbodybh (benchmarkDataList) where + +import Data.Map qualified as M +import Futhark.Util.Loc (Loc (NoLoc)) +import Language.Futhark.Syntax +import Language.Futhark.SyntaxTests () +import Language.Futhark.TypeChecker.Constraints + ( CtTy (..), + Reason (..), + TyParams, + TyVarInfo (..), + TyVars, + ) + +(~) :: TypeBase () NoUniqueness -> TypeBase () NoUniqueness -> CtTy () +t1 ~ t2 = CtEq (Reason mempty) t1 t2 + +type BenchmarkCaseData = ([CtTy ()], TyParams, TyVars ()) + +benchmarkDataList :: [BenchmarkCaseData] +benchmarkDataList = + [ ( [ "t_8322_8328_8326" ~ "[]t_8322_8328_8326_8322_8329_8327", + "t_8322_8328_8328" ~ "[]t_8322_8328_8328_8322_8329_8328", + "t_8321_8323_8326" ~ "[]t_8321_8323_8326_8322_8329_8329", + "t_8327_8327" ~ "[]t_8327_8327_8323_8320_8320", + "t_8321_8322_8321" ~ "[]t_8321_8322_8321_8323_8320_8321", + "b_8327_8329" ~ "[]b_8327_8329_8323_8320_8322", + "a_8327_8328" ~ "[]a_8327_8328_8323_8320_8323", + "b_8326_8328" ~ "[]b_8326_8328_8323_8320_8324", + "a_8326_8327" ~ "[]a_8326_8327_8323_8320_8325", + "i32" ~ "t_8323", + "num_8324" ~ "t_8323", + "t_8323" ~ "i32", + "t_8320" ~ "t_1", + "i32" ~ "t_8322", + "num_8321_8323" ~ "t_8322", + "i32" ~ "i32", + "t_8320" ~ "t_1", + "t_8322" ~ "t_8321", + "i32" ~ "t_8321", + "t_8322_8326" ~ "arg_8323_8325 -> res_8323_8326", + "t_8322_8327" ~ "arg_8323_8325", + "res_8323_8326" ~ "arg_8323_8329 -> res_8324_8320", + "t_8323_8321" ~ "arg_8323_8329", + "t_8322_8326" ~ "arg_8324_8323 -> res_8324_8324", + "t_8322_8328" ~ "arg_8324_8323", + "res_8324_8324" ~ "arg_8324_8327 -> res_8324_8328", + "t_8323_8322" ~ "arg_8324_8327", + "t_8322_8326" ~ "arg_8325_8321 -> res_8325_8322", + "t_8322_8329" ~ "arg_8325_8321", + "res_8325_8322" ~ "arg_8325_8325 -> res_8325_8326", + "t_8323_8323" ~ "arg_8325_8325", + "t_8322_8326" ~ "arg_8325_8329 -> res_8326_8320", + "t_8323_8320" ~ "arg_8325_8329", + "res_8326_8320" ~ "arg_8326_8323 -> res_8326_8324", + "t_8323_8324" ~ "arg_8326_8323", + "{x: t_8320} -> t_8321" ~ "a_8326_8329 -> x_8327_8320", + "[]t_1" ~ "a_8326_8327", + "{as: []a_8326_8329} -> *[]x_8327_8320" ~ "a_8326_8327 -> b_8326_8328", + "t_8327_8327" ~ "b_8326_8328", + "t_8328_8322" ~ "t_8328_8323", + "num_8328_8324" ~ "t_8328_8323", + "bool" ~ "bool", + "t_8328_8322" ~ "t_8329_8321", + "num_8329_8322" ~ "t_8329_8321", + "bool" ~ "bool", + "t_8328_8322" ~ "t_8329_8329", + "num_8321_8320_8320" ~ "t_8329_8329", + "bool" ~ "bool", + "t_8328_8322" ~ "t_8321_8320_8327", + "num_8321_8320_8328" ~ "t_8321_8320_8327", + "bool" ~ "bool", + "{x: t_8328_8322} -> (i64, i64, i64, i64)" ~ "a_8328_8320 -> x_8328_8321", + "t_8327_8327" ~ "a_8327_8328", + "{as: []a_8328_8320} -> *[]x_8328_8321" ~ "a_8327_8328 -> b_8327_8329", + "t_8321_8322_8321" ~ "b_8327_8329", + "t_8321_8322_8323 -> t_8321_8322_8323 -> t_8321_8322_8323" ~ "t_8322_8326", + "(t_8322_8327, t_8322_8328, t_8322_8329, t_8323_8320) -> (t_8323_8321, t_8323_8322, t_8323_8323, t_8323_8324) -> (res_8324_8320, res_8324_8328, res_8325_8326, res_8326_8324)" ~ "a_8321_8322_8322 -> a_8321_8322_8322 -> a_8321_8322_8322", + "(num_8321_8322_8326, num_8321_8322_8327, num_8321_8322_8328, num_8321_8322_8329)" ~ "a_8321_8322_8322", + "t_8321_8322_8321" ~ "[]a_8321_8322_8322", + "t_8321_8323_8326" ~ "[]a_8321_8322_8322", + "t_8321_8323_8326" ~ "[]t_8321_8323_8327", + "(t_8321_8324_8320, t_8321_8324_8321, t_8321_8324_8322, t_8321_8324_8323)" ~ "t_8321_8323_8327", + "t_8321_8325_8327" ~ "num_8321_8325_8326", + "t_8321_8324_8324" ~ "t_8321_8325_8329", + "num_8321_8326_8320" ~ "t_8321_8325_8329", + "bool" ~ "bool", + "t_8321_8324_8325" ~ "t_8321_8325_8328", + "i64" ~ "t_8321_8325_8328", + "num_8321_8325_8326" ~ "t_8321_8325_8325", + "t_8321_8325_8328" ~ "t_8321_8325_8325", + "t_8321_8324_8324" ~ "t_8321_8327_8326", + "num_8321_8327_8327" ~ "t_8321_8327_8326", + "bool" ~ "bool", + "t_8321_8324_8320" ~ "t_8321_8327_8325", + "i64" ~ "t_8321_8327_8325", + "t_8321_8325_8325" ~ "t_8321_8325_8324", + "t_8321_8327_8325" ~ "t_8321_8325_8324", + "t_8321_8324_8324" ~ "t_8321_8329_8323", + "num_8321_8329_8324" ~ "t_8321_8329_8323", + "bool" ~ "bool", + "t_8321_8324_8326" ~ "t_8321_8329_8322", + "i64" ~ "t_8321_8329_8322", + "t_8321_8325_8324" ~ "t_8321_8325_8323", + "t_8321_8329_8322" ~ "t_8321_8325_8323", + "t_8321_8324_8324" ~ "t_8322_8321_8320", + "num_8322_8321_8321" ~ "t_8322_8321_8320", + "bool" ~ "bool", + "t_8321_8324_8321" ~ "t_8322_8320_8329", + "i64" ~ "t_8322_8320_8329", + "t_8321_8325_8323" ~ "t_8321_8325_8322", + "t_8322_8320_8329" ~ "t_8321_8325_8322", + "t_8321_8324_8324" ~ "t_8322_8322_8327", + "num_8322_8322_8328" ~ "t_8322_8322_8327", + "bool" ~ "bool", + "t_8321_8324_8327" ~ "t_8322_8322_8326", + "i64" ~ "t_8322_8322_8326", + "t_8321_8325_8322" ~ "t_8321_8325_8321", + "t_8322_8322_8326" ~ "t_8321_8325_8321", + "t_8321_8324_8324" ~ "t_8322_8324_8324", + "num_8322_8324_8325" ~ "t_8322_8324_8324", + "bool" ~ "bool", + "t_8321_8324_8322" ~ "t_8322_8324_8323", + "i64" ~ "t_8322_8324_8323", + "t_8321_8325_8321" ~ "t_8321_8325_8320", + "t_8322_8324_8323" ~ "t_8321_8325_8320", + "t_8321_8324_8324" ~ "t_8322_8326_8321", + "num_8322_8326_8322" ~ "t_8322_8326_8321", + "bool" ~ "bool", + "t_8321_8324_8328" ~ "t_8322_8326_8320", + "i64" ~ "t_8322_8326_8320", + "t_8321_8325_8320" ~ "t_8321_8324_8329", + "t_8322_8326_8320" ~ "t_8321_8324_8329", + "{bin: t_8321_8324_8324} -> (t_8321_8324_8325, t_8321_8324_8326, t_8321_8324_8327, t_8321_8324_8328) -> t_8321_8324_8329" ~ "a_8322_8327_8327 -> b_8322_8327_8328 -> x_8322_8327_8329", + "t_8327_8327" ~ "[]a_8322_8327_8327", + "t_8321_8323_8326" ~ "[]b_8322_8327_8328", + "t_8322_8328_8326" ~ "[]x_8322_8327_8329", + "[]t_1" ~ "t_8322_8328_8328", + "t_8322_8328_8328" ~ "[]t_8322_8328_8327", + "t_8322_8328_8326" ~ "[]i64", + "[]t_1" ~ "[]t_8322_8328_8327", + "[]t_1" ~ "[]t_8322_8328_8327" + ], + M.fromList [("t_1", (0, Unlifted, NoLoc))], + M.fromList [("t_8320", (5, TyVarFree NoLoc Lifted)), ("t_8321", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8324", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8323", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8326", (5, TyVarFree NoLoc Lifted)), ("t_8322_8327", (6, TyVarFree NoLoc Lifted)), ("t_8322_8328", (6, TyVarFree NoLoc Lifted)), ("t_8322_8329", (6, TyVarFree NoLoc Lifted)), ("t_8323_8320", (6, TyVarFree NoLoc Lifted)), ("t_8323_8321", (7, TyVarFree NoLoc Lifted)), ("t_8323_8322", (7, TyVarFree NoLoc Lifted)), ("t_8323_8323", (7, TyVarFree NoLoc Lifted)), ("t_8323_8324", (7, TyVarFree NoLoc Lifted)), ("arg_8323_8325", (8, TyVarFree NoLoc Lifted)), ("res_8323_8326", (8, TyVarFree NoLoc Lifted)), ("arg_8323_8329", (8, TyVarFree NoLoc Lifted)), ("res_8324_8320", (8, TyVarFree NoLoc Lifted)), ("arg_8324_8323", (8, TyVarFree NoLoc Lifted)), ("res_8324_8324", (8, TyVarFree NoLoc Lifted)), ("arg_8324_8327", (8, TyVarFree NoLoc Lifted)), ("res_8324_8328", (8, TyVarFree NoLoc Lifted)), ("arg_8325_8321", (8, TyVarFree NoLoc Lifted)), ("res_8325_8322", (8, TyVarFree NoLoc Lifted)), ("arg_8325_8325", (8, TyVarFree NoLoc Lifted)), ("res_8325_8326", (8, TyVarFree NoLoc Lifted)), ("arg_8325_8329", (8, TyVarFree NoLoc Lifted)), ("res_8326_8320", (8, TyVarFree NoLoc Lifted)), ("arg_8326_8323", (8, TyVarFree NoLoc Lifted)), ("res_8326_8324", (8, TyVarFree NoLoc Lifted)), ("a_8326_8327", (4, TyVarFree NoLoc Lifted)), ("b_8326_8328", (4, TyVarFree NoLoc Lifted)), ("a_8326_8329", (4, TyVarFree NoLoc Unlifted)), ("x_8327_8320", (4, TyVarFree NoLoc Unlifted)), ("t_8327_8327", (5, TyVarFree NoLoc Lifted)), ("a_8327_8328", (6, TyVarFree NoLoc Lifted)), ("b_8327_8329", (6, TyVarFree NoLoc Lifted)), ("a_8328_8320", (6, TyVarFree NoLoc Unlifted)), ("x_8328_8321", (6, TyVarFree NoLoc Unlifted)), ("t_8328_8322", (7, TyVarFree NoLoc Lifted)), ("t_8328_8323", (8, TyVarFree NoLoc Unlifted)), ("num_8328_8324", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8329_8321", (8, TyVarFree NoLoc Unlifted)), ("num_8329_8322", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8329_8329", (8, TyVarFree NoLoc Unlifted)), ("num_8321_8320_8320", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8320_8327", (8, TyVarFree NoLoc Unlifted)), ("num_8321_8320_8328", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8322_8321", (7, TyVarFree NoLoc Lifted)), ("a_8321_8322_8322", (8, TyVarFree NoLoc Unlifted)), ("t_8321_8322_8323", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8322_8326", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8322_8327", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8322_8328", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8322_8329", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8323_8326", (9, TyVarFree NoLoc Lifted)), ("t_8321_8323_8327", (10, TyVarFree NoLoc Unlifted)), ("t_8321_8324_8320", (11, TyVarFree NoLoc Lifted)), ("t_8321_8324_8321", (11, TyVarFree NoLoc Lifted)), ("t_8321_8324_8322", (11, TyVarFree NoLoc Lifted)), ("t_8321_8324_8323", (11, TyVarFree NoLoc Lifted)), ("t_8321_8324_8324", (13, TyVarFree NoLoc Lifted)), ("t_8321_8324_8325", (14, TyVarFree NoLoc Lifted)), ("t_8321_8324_8326", (14, TyVarFree NoLoc Lifted)), ("t_8321_8324_8327", (14, TyVarFree NoLoc Lifted)), ("t_8321_8324_8328", (14, TyVarFree NoLoc Lifted)), ("t_8321_8324_8329", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8325_8320", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8325_8321", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8325_8322", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8325_8323", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8325_8324", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8325_8325", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8325_8326", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8325_8327", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8325_8328", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8325_8329", (15, TyVarFree NoLoc Unlifted)), ("num_8321_8326_8320", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8327_8325", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8327_8326", (15, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8327_8327", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8329_8322", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8329_8323", (15, TyVarFree NoLoc Unlifted)), ("num_8321_8329_8324", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320_8329", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8321_8320", (15, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8321_8321", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8322_8326", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8322_8327", (15, TyVarFree NoLoc Unlifted)), ("num_8322_8322_8328", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8324_8323", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8324_8324", (15, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8324_8325", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8326_8320", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8326_8321", (15, TyVarFree NoLoc Unlifted)), ("num_8322_8326_8322", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("a_8322_8327_8327", (12, TyVarFree NoLoc Unlifted)), ("b_8322_8327_8328", (12, TyVarFree NoLoc Unlifted)), ("x_8322_8327_8329", (12, TyVarFree NoLoc Unlifted)), ("t_8322_8328_8326", (13, TyVarFree NoLoc Lifted)), ("t_8322_8328_8327", (14, TyVarFree NoLoc Unlifted)), ("t_8322_8328_8328", (14, TyVarFree NoLoc Unlifted)), ("t_8322_8328_8326_8322_8329_8327", (13, TyVarFree NoLoc Lifted)), ("t_8322_8328_8328_8322_8329_8328", (14, TyVarFree NoLoc Unlifted)), ("t_8321_8323_8326_8322_8329_8329", (9, TyVarFree NoLoc Lifted)), ("t_8327_8327_8323_8320_8320", (5, TyVarFree NoLoc Lifted)), ("t_8321_8322_8321_8323_8320_8321", (7, TyVarFree NoLoc Lifted)), ("b_8327_8329_8323_8320_8322", (6, TyVarFree NoLoc Lifted)), ("a_8327_8328_8323_8320_8323", (6, TyVarFree NoLoc Lifted)), ("b_8326_8328_8323_8320_8324", (4, TyVarFree NoLoc Lifted)), ("a_8326_8327_8323_8320_8325", (4, TyVarFree NoLoc Lifted))] + ), + ( [ "t_8323_8320_8321" ~ "[]t_8323_8320_8321_8323_8323_8328", + "t_8323_8320_8323" ~ "[]t_8323_8320_8323_8323_8323_8329", + "t_8321_8323_8328" ~ "[]t_8321_8323_8328_8323_8324_8320", + "t_8327_8329" ~ "[]t_8327_8329_8323_8324_8321", + "t_8321_8322_8323" ~ "[]t_8321_8322_8323_8323_8324_8322", + "b_8328_8321" ~ "[]b_8328_8321_8323_8324_8323", + "a_8328_8320" ~ "[]a_8328_8320_8323_8324_8324", + "b_8327_8320" ~ "[]b_8327_8320_8323_8324_8325", + "a_8326_8329" ~ "[]a_8326_8329_8323_8324_8326", + "i32" ~ "t_8323", + "num_8324" ~ "t_8323", + "t_8323" ~ "i32", + "t_8320" ~ "t_1", + "i32" ~ "t_8322", + "num_8321_8323" ~ "t_8322", + "i32" ~ "i32", + "t_8320" ~ "t_1", + "t_8322" ~ "t_8321", + "i32" ~ "t_8321", + "t_8321" ~ "i32", + "t_8322_8328" ~ "arg_8323_8327 -> res_8323_8328", + "t_8322_8329" ~ "arg_8323_8327", + "res_8323_8328" ~ "arg_8324_8321 -> res_8324_8322", + "t_8323_8323" ~ "arg_8324_8321", + "t_8322_8328" ~ "arg_8324_8325 -> res_8324_8326", + "t_8323_8320" ~ "arg_8324_8325", + "res_8324_8326" ~ "arg_8324_8329 -> res_8325_8320", + "t_8323_8324" ~ "arg_8324_8329", + "t_8322_8328" ~ "arg_8325_8323 -> res_8325_8324", + "t_8323_8321" ~ "arg_8325_8323", + "res_8325_8324" ~ "arg_8325_8327 -> res_8325_8328", + "t_8323_8325" ~ "arg_8325_8327", + "t_8322_8328" ~ "arg_8326_8321 -> res_8326_8322", + "t_8323_8322" ~ "arg_8326_8321", + "res_8326_8322" ~ "arg_8326_8325 -> res_8326_8326", + "t_8323_8326" ~ "arg_8326_8325", + "{x: t_8320} -> i16" ~ "a_8327_8321 -> x_8327_8322", + "[]t_1" ~ "a_8326_8329", + "{as: []a_8327_8321} -> *[]x_8327_8322" ~ "a_8326_8329 -> b_8327_8320", + "t_8327_8329" ~ "b_8327_8320", + "t_8328_8324" ~ "t_8328_8325", + "num_8328_8326" ~ "t_8328_8325", + "bool" ~ "bool", + "t_8328_8324" ~ "t_8329_8323", + "num_8329_8324" ~ "t_8329_8323", + "bool" ~ "bool", + "t_8328_8324" ~ "t_8321_8320_8321", + "num_8321_8320_8322" ~ "t_8321_8320_8321", + "bool" ~ "bool", + "t_8328_8324" ~ "t_8321_8320_8329", + "num_8321_8321_8320" ~ "t_8321_8320_8329", + "bool" ~ "bool", + "{x: t_8328_8324} -> (i16, i16, i16, i16)" ~ "a_8328_8322 -> x_8328_8323", + "t_8327_8329" ~ "a_8328_8320", + "{as: []a_8328_8322} -> *[]x_8328_8323" ~ "a_8328_8320 -> b_8328_8321", + "t_8321_8322_8323" ~ "b_8328_8321", + "t_8321_8322_8325 -> t_8321_8322_8325 -> t_8321_8322_8325" ~ "t_8322_8328", + "(t_8322_8329, t_8323_8320, t_8323_8321, t_8323_8322) -> (t_8323_8323, t_8323_8324, t_8323_8325, t_8323_8326) -> (res_8324_8322, res_8325_8320, res_8325_8328, res_8326_8326)" ~ "a_8321_8322_8324 -> a_8321_8322_8324 -> a_8321_8322_8324", + "(num_8321_8322_8328, num_8321_8322_8329, num_8321_8323_8320, num_8321_8323_8321)" ~ "a_8321_8322_8324", + "t_8321_8322_8323" ~ "[]a_8321_8322_8324", + "t_8321_8323_8328" ~ "[]a_8321_8322_8324", + "i64" ~ "t_8321_8323_8329", + "num_8321_8324_8320" ~ "t_8321_8323_8329", + "t_8321_8323_8328" ~ "[]t_8321_8324_8329", + "bool" ~ "bool", + "(num_8321_8324_8325, num_8321_8324_8326, num_8321_8324_8327, num_8321_8324_8328)" ~ "if_t_8321_8325_8322", + "t_8321_8324_8329" ~ "if_t_8321_8325_8322", + "(t_8321_8325_8323, t_8321_8325_8324, t_8321_8325_8325, t_8321_8325_8326)" ~ "if_t_8321_8325_8322", + "t_8321_8327_8320" ~ "num_8321_8326_8329", + "t_8321_8325_8327" ~ "t_8321_8327_8322", + "num_8321_8327_8323" ~ "t_8321_8327_8322", + "bool" ~ "bool", + "t_8321_8325_8328" ~ "t_8321_8327_8321", + "i16" ~ "t_8321_8327_8321", + "num_8321_8326_8329" ~ "t_8321_8326_8328", + "t_8321_8327_8321" ~ "t_8321_8326_8328", + "t_8321_8325_8327" ~ "t_8321_8328_8329", + "num_8321_8329_8320" ~ "t_8321_8328_8329", + "bool" ~ "bool", + "t_8321_8325_8323" ~ "t_8321_8328_8328", + "i16" ~ "t_8321_8328_8328", + "t_8321_8326_8328" ~ "t_8321_8326_8327", + "t_8321_8328_8328" ~ "t_8321_8326_8327", + "t_8321_8325_8327" ~ "t_8322_8320_8326", + "num_8322_8320_8327" ~ "t_8322_8320_8326", + "bool" ~ "bool", + "t_8321_8325_8329" ~ "t_8322_8320_8325", + "i16" ~ "t_8322_8320_8325", + "t_8321_8326_8327" ~ "t_8321_8326_8326", + "t_8322_8320_8325" ~ "t_8321_8326_8326", + "t_8321_8325_8327" ~ "t_8322_8322_8323", + "num_8322_8322_8324" ~ "t_8322_8322_8323", + "bool" ~ "bool", + "t_8321_8325_8324" ~ "t_8322_8322_8322", + "i16" ~ "t_8322_8322_8322", + "t_8321_8326_8326" ~ "t_8321_8326_8325", + "t_8322_8322_8322" ~ "t_8321_8326_8325", + "t_8321_8325_8327" ~ "t_8322_8324_8320", + "num_8322_8324_8321" ~ "t_8322_8324_8320", + "bool" ~ "bool", + "t_8321_8326_8320" ~ "t_8322_8323_8329", + "i16" ~ "t_8322_8323_8329", + "t_8321_8326_8325" ~ "t_8321_8326_8324", + "t_8322_8323_8329" ~ "t_8321_8326_8324", + "t_8321_8325_8327" ~ "t_8322_8325_8327", + "num_8322_8325_8328" ~ "t_8322_8325_8327", + "bool" ~ "bool", + "t_8321_8325_8325" ~ "t_8322_8325_8326", + "i16" ~ "t_8322_8325_8326", + "t_8321_8326_8324" ~ "t_8321_8326_8323", + "t_8322_8325_8326" ~ "t_8321_8326_8323", + "t_8321_8325_8327" ~ "t_8322_8327_8324", + "num_8322_8327_8325" ~ "t_8322_8327_8324", + "bool" ~ "bool", + "t_8321_8326_8321" ~ "t_8322_8327_8323", + "i16" ~ "t_8322_8327_8323", + "t_8321_8326_8323" ~ "t_8321_8326_8322", + "t_8322_8327_8323" ~ "t_8321_8326_8322", + "t_8321_8326_8322" ~ "i16", + "{bin: t_8321_8325_8327} -> (t_8321_8325_8328, t_8321_8325_8329, t_8321_8326_8320, t_8321_8326_8321) -> i64" ~ "a_8322_8329_8322 -> b_8322_8329_8323 -> x_8322_8329_8324", + "t_8327_8329" ~ "[]a_8322_8329_8322", + "t_8321_8323_8328" ~ "[]b_8322_8329_8323", + "t_8323_8320_8321" ~ "[]x_8322_8329_8324", + "[]t_1" ~ "t_8323_8320_8323", + "t_8323_8320_8323" ~ "[]t_8323_8320_8322", + "t_8323_8320_8321" ~ "[]i64", + "[]t_1" ~ "[]t_8323_8320_8322", + "t_8321_8325_8323" ~ "et_8323_8321_8324", + "t_8321_8325_8324" ~ "et_8323_8321_8324", + "t_8321_8325_8325" ~ "et_8323_8321_8324", + "t_8321_8325_8326" ~ "et_8323_8321_8324", + "i16 -> i64" ~ "a_8323_8321_8322 -> x_8323_8321_8323", + "[]et_8323_8321_8324" ~ "[]a_8323_8321_8322", + "num_8323_8322_8320" ~ "et_8323_8321_8329", + "t_8321_8325_8323" ~ "et_8323_8321_8329", + "t_8321_8325_8323" ~ "t_8323_8322_8321", + "t_8321_8325_8324" ~ "t_8323_8322_8321", + "t_8323_8322_8321" ~ "et_8323_8321_8329", + "t_8321_8325_8323" ~ "t_8323_8322_8327", + "t_8321_8325_8324" ~ "t_8323_8322_8327", + "t_8323_8322_8327" ~ "t_8323_8322_8326", + "t_8321_8325_8325" ~ "t_8323_8322_8326", + "t_8323_8322_8326" ~ "et_8323_8321_8329", + "num_8323_8323_8326" ~ "i64", + "num_8323_8323_8327" ~ "i64", + "([]t_1, []i64, []i16)" ~ "([]t_8323_8320_8322, []x_8323_8321_8323, []et_8323_8321_8329)" + ], + M.fromList [("t_1", (0, Unlifted, NoLoc))], + M.fromList [("t_8320", (5, TyVarFree NoLoc Lifted)), ("t_8321", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8324", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8323", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8328", (5, TyVarFree NoLoc Lifted)), ("t_8322_8329", (6, TyVarFree NoLoc Lifted)), ("t_8323_8320", (6, TyVarFree NoLoc Lifted)), ("t_8323_8321", (6, TyVarFree NoLoc Lifted)), ("t_8323_8322", (6, TyVarFree NoLoc Lifted)), ("t_8323_8323", (7, TyVarFree NoLoc Lifted)), ("t_8323_8324", (7, TyVarFree NoLoc Lifted)), ("t_8323_8325", (7, TyVarFree NoLoc Lifted)), ("t_8323_8326", (7, TyVarFree NoLoc Lifted)), ("arg_8323_8327", (8, TyVarFree NoLoc Lifted)), ("res_8323_8328", (8, TyVarFree NoLoc Lifted)), ("arg_8324_8321", (8, TyVarFree NoLoc Lifted)), ("res_8324_8322", (8, TyVarFree NoLoc Lifted)), ("arg_8324_8325", (8, TyVarFree NoLoc Lifted)), ("res_8324_8326", (8, TyVarFree NoLoc Lifted)), ("arg_8324_8329", (8, TyVarFree NoLoc Lifted)), ("res_8325_8320", (8, TyVarFree NoLoc Lifted)), ("arg_8325_8323", (8, TyVarFree NoLoc Lifted)), ("res_8325_8324", (8, TyVarFree NoLoc Lifted)), ("arg_8325_8327", (8, TyVarFree NoLoc Lifted)), ("res_8325_8328", (8, TyVarFree NoLoc Lifted)), ("arg_8326_8321", (8, TyVarFree NoLoc Lifted)), ("res_8326_8322", (8, TyVarFree NoLoc Lifted)), ("arg_8326_8325", (8, TyVarFree NoLoc Lifted)), ("res_8326_8326", (8, TyVarFree NoLoc Lifted)), ("a_8326_8329", (4, TyVarFree NoLoc Lifted)), ("b_8327_8320", (4, TyVarFree NoLoc Lifted)), ("a_8327_8321", (4, TyVarFree NoLoc Unlifted)), ("x_8327_8322", (4, TyVarFree NoLoc Unlifted)), ("t_8327_8329", (5, TyVarFree NoLoc Lifted)), ("a_8328_8320", (6, TyVarFree NoLoc Lifted)), ("b_8328_8321", (6, TyVarFree NoLoc Lifted)), ("a_8328_8322", (6, TyVarFree NoLoc Unlifted)), ("x_8328_8323", (6, TyVarFree NoLoc Unlifted)), ("t_8328_8324", (7, TyVarFree NoLoc Lifted)), ("t_8328_8325", (8, TyVarFree NoLoc Unlifted)), ("num_8328_8326", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8329_8323", (8, TyVarFree NoLoc Unlifted)), ("num_8329_8324", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8320_8321", (8, TyVarFree NoLoc Unlifted)), ("num_8321_8320_8322", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8320_8329", (8, TyVarFree NoLoc Unlifted)), ("num_8321_8321_8320", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8322_8323", (7, TyVarFree NoLoc Lifted)), ("a_8321_8322_8324", (8, TyVarFree NoLoc Unlifted)), ("t_8321_8322_8325", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8322_8328", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8322_8329", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8323_8320", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8323_8321", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8323_8328", (9, TyVarFree NoLoc Lifted)), ("t_8321_8323_8329", (10, TyVarFree NoLoc Unlifted)), ("num_8321_8324_8320", (10, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8324_8325", (10, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8324_8326", (10, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8324_8327", (10, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8324_8328", (10, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8324_8329", (10, TyVarFree NoLoc Unlifted)), ("if_t_8321_8325_8322", (10, TyVarFree NoLoc SizeLifted)), ("t_8321_8325_8323", (11, TyVarFree NoLoc Lifted)), ("t_8321_8325_8324", (11, TyVarFree NoLoc Lifted)), ("t_8321_8325_8325", (11, TyVarFree NoLoc Lifted)), ("t_8321_8325_8326", (11, TyVarFree NoLoc Lifted)), ("t_8321_8325_8327", (13, TyVarFree NoLoc Lifted)), ("t_8321_8325_8328", (14, TyVarFree NoLoc Lifted)), ("t_8321_8325_8329", (14, TyVarFree NoLoc Lifted)), ("t_8321_8326_8320", (14, TyVarFree NoLoc Lifted)), ("t_8321_8326_8321", (14, TyVarFree NoLoc Lifted)), ("t_8321_8326_8322", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326_8323", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326_8324", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326_8325", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326_8326", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326_8327", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326_8328", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8326_8329", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8327_8320", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8327_8321", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8327_8322", (15, TyVarFree NoLoc Unlifted)), ("num_8321_8327_8323", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8328_8328", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8328_8329", (15, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8329_8320", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320_8325", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320_8326", (15, TyVarFree NoLoc Unlifted)), ("num_8322_8320_8327", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8322_8322", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8322_8323", (15, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8322_8324", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8323_8329", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8324_8320", (15, TyVarFree NoLoc Unlifted)), ("num_8322_8324_8321", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8325_8326", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8325_8327", (15, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8325_8328", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8327_8323", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8327_8324", (15, TyVarFree NoLoc Unlifted)), ("num_8322_8327_8325", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("a_8322_8329_8322", (12, TyVarFree NoLoc Unlifted)), ("b_8322_8329_8323", (12, TyVarFree NoLoc Unlifted)), ("x_8322_8329_8324", (12, TyVarFree NoLoc Unlifted)), ("t_8323_8320_8321", (13, TyVarFree NoLoc Lifted)), ("t_8323_8320_8322", (14, TyVarFree NoLoc Unlifted)), ("t_8323_8320_8323", (14, TyVarFree NoLoc Unlifted)), ("a_8323_8321_8322", (14, TyVarFree NoLoc Unlifted)), ("x_8323_8321_8323", (14, TyVarFree NoLoc Unlifted)), ("et_8323_8321_8324", (14, TyVarFree NoLoc Unlifted)), ("et_8323_8321_8329", (14, TyVarFree NoLoc Unlifted)), ("num_8323_8322_8320", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8322_8321", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8322_8326", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8322_8327", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8323_8326", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8323_8327", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8320_8321_8323_8323_8328", (13, TyVarFree NoLoc Lifted)), ("t_8323_8320_8323_8323_8323_8329", (14, TyVarFree NoLoc Unlifted)), ("t_8321_8323_8328_8323_8324_8320", (9, TyVarFree NoLoc Lifted)), ("t_8327_8329_8323_8324_8321", (5, TyVarFree NoLoc Lifted)), ("t_8321_8322_8323_8323_8324_8322", (7, TyVarFree NoLoc Lifted)), ("b_8328_8321_8323_8324_8323", (6, TyVarFree NoLoc Lifted)), ("a_8328_8320_8323_8324_8324", (6, TyVarFree NoLoc Lifted)), ("b_8327_8320_8323_8324_8325", (4, TyVarFree NoLoc Lifted)), ("a_8326_8329_8323_8324_8326", (4, TyVarFree NoLoc Lifted))] + ), + ( [ "t_8328_8325" ~ "[]t_8328_8325_8322_8321_8328", + "t_8322_8321_8320" ~ "[]t_8322_8321_8320_8322_8321_8329", + "index_8321_8327_8326" ~ "[]index_8321_8327_8326_8322_8322_8320", + "t_8329_8322" ~ "[][]t_8329_8322_8322_8322_8321", + "index_elem_8321_8327_8327" ~ "[]index_elem_8321_8327_8327_8322_8322_8322", + "index_8321_8326_8329" ~ "[]index_8321_8326_8329_8322_8322_8323", + "t_8321_8323_8324" ~ "[][]t_8321_8323_8324_8322_8322_8324", + "index_elem_8321_8327_8320" ~ "[]index_elem_8321_8327_8320_8322_8322_8325", + "b_8329_8324" ~ "[][]b_8329_8324_8322_8322_8326", + "a_8329_8323" ~ "[][]a_8329_8323_8322_8322_8327", + "b_8329_8326" ~ "[][]b_8329_8326_8322_8322_8328", + "a_8329_8325" ~ "[]a_8329_8325_8322_8322_8329", + "b_8329_8328" ~ "[]b_8329_8328_8322_8323_8320", + "a_8329_8327" ~ "[]a_8329_8327_8322_8323_8321", + "b_8321_8320_8320" ~ "[]b_8321_8320_8320_8322_8323_8322", + "a_8329_8329" ~ "[][]a_8329_8329_8322_8323_8323", + "b_8321_8320_8322" ~ "[][]b_8321_8320_8322_8322_8323_8324", + "a_8321_8320_8321" ~ "[][]a_8321_8320_8321_8322_8323_8325", + "t_8326_8321" ~ "[][]t_8326_8321_8322_8323_8326", + "t_8328_8326" ~ "[]t_8328_8326_8322_8323_8327", + "et_8328_8327" ~ "[]et_8328_8327_8322_8323_8328", + "t_8325_8324" ~ "[][]t_8325_8324_8322_8323_8329", + "t_8322_8324" ~ "[]t_8322_8324_8322_8324_8320", + "t_8322_8322" ~ "[]t_8322_8322_8322_8324_8321", + "t_8325_8322" ~ "[][]t_8325_8322_8322_8324_8322", + "t_8325_8325" ~ "[]t_8325_8325_8322_8324_8323", + "et_8325_8326" ~ "[]et_8325_8326_8322_8324_8324", + "t_8325_8323" ~ "[][]t_8325_8323_8322_8324_8325", + "t_8322_8323" ~ "[]t_8322_8323_8322_8324_8326", + "a_8322_8325" ~ "[]a_8322_8325_8322_8324_8327", + "b_8322_8328" ~ "[]b_8322_8328_8322_8324_8328", + "a_8323_8322" ~ "[]a_8323_8322_8322_8324_8329", + "a_8322_8327" ~ "[][]a_8322_8327_8322_8325_8320", + "t_8321_8323" ~ "[]t_8321_8323_8322_8325_8321", + "t_8321_8324" ~ "[]t_8321_8324_8322_8325_8322", + "i64" ~ "t_8321", + "i64" ~ "t_8321", + "t_8321" ~ "t_8320", + "i64" ~ "t_8320", + "t_8320" ~ "i64", + "[]t_1" ~ "[]t_8321_8320", + "(t_8321_8323, t_8321_8324)" ~ "([]t_8321_8320, []t_8321_8320)", + "i32 -> t_1 -> i32" ~ "i32 -> t_8321_8325 -> i32", + "i32" ~ "i32", + "t_8321_8324" ~ "[]t_8321_8325", + "(t_8322_8322, t_8322_8323, t_8322_8324)" ~ "([]t_8321_8325, []i64, []i16)", + "t_8321_8323" ~ "[]t_8322_8329", + "i32 -> t_1 -> i32" ~ "i32 -> t_8323_8324 -> i32", + "i32" ~ "i32", + "{xs: []t_8323_8324} -> ([]t_8323_8324, []i64, []i16)" ~ "a_8323_8322 -> x_8323_8323", + "[][]t_8322_8329" ~ "a_8322_8327", + "{as: []a_8323_8322} -> *[]x_8323_8323" ~ "a_8322_8327 -> b_8322_8328", + "b_8322_8328" ~ "a_8322_8325", + "{xs: [](a_8324_8325, b_8324_8326, c_8324_8327)} -> ([]a_8324_8325, []b_8324_8326, []c_8324_8327)" ~ "a_8322_8325 -> b_8322_8326", + "(t_8325_8322, t_8325_8323, t_8325_8324)" ~ "b_8322_8326", + "t_8322_8323" ~ "et_8325_8326", + "t_8325_8323" ~ "[]t_8325_8325", + "[]et_8325_8326" ~ "[]t_8325_8325", + "t_8326_8321" ~ "[]t_8325_8325", + "i64" ~ "t_8326_8324", + "i64" ~ "t_8326_8324", + "t_8326_8324" ~ "t_8326_8323", + "i64" ~ "t_8326_8323", + "t_8325_8322" ~ "[][]t_8327_8324", + "[]t_8327_8324" ~ "[]t_8327_8323", + "t_8322_8322" ~ "[]t_8327_8323", + "t_8326_8323" ~ "i64", + "[]t_8327_8323" ~ "[]t_8326_8322", + "t_8328_8325" ~ "[]t_8326_8322", + "t_8322_8324" ~ "et_8328_8327", + "t_8325_8324" ~ "[]t_8328_8326", + "[]et_8328_8327" ~ "[]t_8328_8326", + "t_8329_8322" ~ "[]t_8328_8326", + "t_8326_8321" ~ "a_8321_8320_8321", + "{a: [][]t_8321_8320_8323} -> [][]t_8321_8320_8323" ~ "a_8321_8320_8321 -> b_8321_8320_8322", + "b_8321_8320_8322" ~ "a_8329_8329", + "{xs: [][]t_8321_8320_8328} -> []t_8321_8320_8328" ~ "a_8329_8329 -> b_8321_8320_8320", + "t_8321_8321_8324 -> t_8321_8321_8324 -> t_8321_8321_8324" ~ "update_elem_8321_8321_8323 -> update_elem_8321_8321_8323 -> update_elem_8321_8321_8323", + "num_8321_8321_8325" ~ "update_elem_8321_8321_8323", + "b_8321_8320_8320" ~ "a_8329_8327", + "{xs: []update_elem_8321_8321_8323} -> *[]update_elem_8321_8321_8323" ~ "a_8329_8327 -> b_8329_8328", + "b_8329_8328" ~ "a_8329_8325", + "{xs: []t_8321_8322_8324} -> [][]t_8321_8322_8324" ~ "a_8329_8325 -> b_8329_8326", + "b_8329_8326" ~ "a_8329_8323", + "{a: [][]t_8321_8322_8329} -> [][]t_8321_8322_8329" ~ "a_8329_8323 -> b_8329_8324", + "t_8321_8323_8324" ~ "b_8329_8324", + "i64" ~ "t_8321_8323_8327", + "i64" ~ "t_8321_8323_8327", + "t_8321_8323_8327" ~ "t_8321_8323_8326", + "i64" ~ "t_8321_8323_8326", + "t_8321_8324_8327" ~ "t_8321_8324_8326", + "index_8321_8324_8328" ~ "index_elem_8321_8324_8329", + "t_8328_8325" ~ "[]index_elem_8321_8324_8329", + "t_8321_8325_8320" ~ "index_8321_8324_8328", + "num_8321_8325_8322" ~ "i32", + "i32 -> t_1 -> i32" ~ "i32 -> t_8321_8325_8321 -> i32", + "i32" ~ "i32", + "t_8321_8325_8320" ~ "t_8321_8325_8321", + "t_8321_8326_8321" ~ "i64", + "t_8321_8324_8326" ~ "t_8321_8326_8322", + "i64" ~ "t_8321_8326_8322", + "t_8321_8326_8327" ~ "t_8321_8326_8322", + "t_8321_8326_8328" ~ "t_8321_8326_8327", + "index_8321_8326_8329" ~ "index_elem_8321_8327_8320", + "t_8321_8323_8324" ~ "[]index_elem_8321_8327_8320", + "t_8321_8327_8321" ~ "t_8321_8326_8321", + "index_8321_8327_8322" ~ "index_elem_8321_8327_8323", + "index_8321_8326_8329" ~ "[]index_elem_8321_8327_8323", + "t_8321_8327_8324" ~ "index_8321_8327_8322", + "t_8321_8327_8325" ~ "t_8321_8326_8327", + "index_8321_8327_8326" ~ "index_elem_8321_8327_8327", + "t_8329_8322" ~ "[]index_elem_8321_8327_8327", + "t_8321_8327_8328" ~ "t_8321_8326_8321", + "index_8321_8327_8329" ~ "index_elem_8321_8328_8320", + "index_8321_8327_8326" ~ "[]index_elem_8321_8328_8320", + "index_8321_8327_8329" ~ "i16", + "t_8321_8328_8323" ~ "i64", + "i64" ~ "t_8321_8328_8325", + "t_8321_8326_8327" ~ "t_8321_8328_8325", + "t_8321_8328_8325" ~ "t_8321_8328_8324", + "t_8321_8328_8323" ~ "t_8321_8328_8324", + "t_8321_8329_8324" ~ "t_8321_8328_8324", + "t_8321_8324_8326" ~ "t_8321_8329_8326", + "t_8321_8329_8324" ~ "t_8321_8329_8326", + "t_8321_8329_8326" ~ "t_8321_8329_8325", + "t_8321_8327_8324" ~ "t_8321_8329_8325", + "t_8322_8320_8325" ~ "t_8321_8329_8325", + "t_8321_8323_8326" ~ "i64", + "{i: t_8321_8324_8326} -> t_8322_8320_8325" ~ "i64 -> a_8321_8323_8325", + "t_8322_8321_8320" ~ "[]a_8321_8323_8325", + "[]t_1" ~ "[]t_8322_8321_8321", + "t_8322_8321_8320" ~ "[]i64", + "t_8328_8325" ~ "[]t_8322_8321_8321" + ], + M.fromList [("t_1", (0, Unlifted, NoLoc))], + M.fromList [("t_8320", (3, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321", (3, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8320", (4, TyVarFree NoLoc Unlifted)), ("t_8321_8323", (5, TyVarFree NoLoc Lifted)), ("t_8321_8324", (5, TyVarFree NoLoc Lifted)), ("t_8321_8325", (6, TyVarFree NoLoc Unlifted)), ("t_8322_8322", (7, TyVarFree NoLoc Lifted)), ("t_8322_8323", (7, TyVarFree NoLoc Lifted)), ("t_8322_8324", (7, TyVarFree NoLoc Lifted)), ("a_8322_8325", (8, TyVarFree NoLoc Lifted)), ("b_8322_8326", (8, TyVarFree NoLoc Lifted)), ("a_8322_8327", (8, TyVarFree NoLoc Lifted)), ("b_8322_8328", (8, TyVarFree NoLoc Lifted)), ("t_8322_8329", (8, TyVarFree NoLoc Unlifted)), ("a_8323_8322", (8, TyVarFree NoLoc Unlifted)), ("x_8323_8323", (8, TyVarFree NoLoc Unlifted)), ("t_8323_8324", (8, TyVarFree NoLoc Unlifted)), ("a_8324_8325", (8, TyVarFree NoLoc Unlifted)), ("b_8324_8326", (8, TyVarFree NoLoc Unlifted)), ("c_8324_8327", (8, TyVarFree NoLoc Unlifted)), ("t_8325_8322", (9, TyVarFree NoLoc Lifted)), ("t_8325_8323", (9, TyVarFree NoLoc Lifted)), ("t_8325_8324", (9, TyVarFree NoLoc Lifted)), ("t_8325_8325", (10, TyVarFree NoLoc Unlifted)), ("et_8325_8326", (10, TyVarFree NoLoc Unlifted)), ("t_8326_8321", (11, TyVarFree NoLoc Lifted)), ("t_8326_8322", (12, TyVarFree NoLoc Unlifted)), ("t_8326_8323", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8326_8324", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8327_8323", (12, TyVarFree NoLoc Unlifted)), ("t_8327_8324", (12, TyVarFree NoLoc Unlifted)), ("t_8328_8325", (13, TyVarFree NoLoc Lifted)), ("t_8328_8326", (14, TyVarFree NoLoc Unlifted)), ("et_8328_8327", (14, TyVarFree NoLoc Unlifted)), ("t_8329_8322", (15, TyVarFree NoLoc Lifted)), ("a_8329_8323", (16, TyVarFree NoLoc Lifted)), ("b_8329_8324", (16, TyVarFree NoLoc Lifted)), ("a_8329_8325", (16, TyVarFree NoLoc Lifted)), ("b_8329_8326", (16, TyVarFree NoLoc Lifted)), ("a_8329_8327", (16, TyVarFree NoLoc Lifted)), ("b_8329_8328", (16, TyVarFree NoLoc Lifted)), ("a_8329_8329", (16, TyVarFree NoLoc Lifted)), ("b_8321_8320_8320", (16, TyVarFree NoLoc Lifted)), ("a_8321_8320_8321", (16, TyVarFree NoLoc Lifted)), ("b_8321_8320_8322", (16, TyVarFree NoLoc Lifted)), ("t_8321_8320_8323", (16, TyVarFree NoLoc Unlifted)), ("t_8321_8320_8328", (16, TyVarFree NoLoc Unlifted)), ("update_elem_8321_8321_8323", (16, TyVarFree NoLoc Unlifted)), ("t_8321_8321_8324", (16, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8321_8325", (16, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8322_8324", (16, TyVarFree NoLoc Unlifted)), ("t_8321_8322_8329", (16, TyVarFree NoLoc Unlifted)), ("t_8321_8323_8324", (17, TyVarFree NoLoc Lifted)), ("a_8321_8323_8325", (18, TyVarFree NoLoc Unlifted)), ("t_8321_8323_8326", (18, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8323_8327", (18, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8324_8326", (19, TyVarFree NoLoc Lifted)), ("t_8321_8324_8327", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8321_8324_8328", (20, TyVarFree NoLoc Unlifted)), ("index_elem_8321_8324_8329", (20, TyVarFree NoLoc Unlifted)), ("t_8321_8325_8320", (21, TyVarFree NoLoc Lifted)), ("t_8321_8325_8321", (22, TyVarFree NoLoc Unlifted)), ("num_8321_8325_8322", (22, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326_8321", (23, TyVarFree NoLoc Lifted)), ("t_8321_8326_8322", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326_8327", (25, TyVarFree NoLoc Lifted)), ("t_8321_8326_8328", (26, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8321_8326_8329", (26, TyVarFree NoLoc Unlifted)), ("index_elem_8321_8327_8320", (26, TyVarFree NoLoc Unlifted)), ("t_8321_8327_8321", (26, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8321_8327_8322", (26, TyVarFree NoLoc Unlifted)), ("index_elem_8321_8327_8323", (26, TyVarFree NoLoc Unlifted)), ("t_8321_8327_8324", (27, TyVarFree NoLoc Lifted)), ("t_8321_8327_8325", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8321_8327_8326", (28, TyVarFree NoLoc Unlifted)), ("index_elem_8321_8327_8327", (28, TyVarFree NoLoc Unlifted)), ("t_8321_8327_8328", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8321_8327_8329", (28, TyVarFree NoLoc Unlifted)), ("index_elem_8321_8328_8320", (28, TyVarFree NoLoc Unlifted)), ("t_8321_8328_8323", (29, TyVarFree NoLoc Lifted)), ("t_8321_8328_8324", (30, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8328_8325", (30, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8329_8324", (31, TyVarFree NoLoc Lifted)), ("t_8321_8329_8325", (32, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8329_8326", (32, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320_8325", (33, TyVarFree NoLoc Lifted)), ("t_8322_8321_8320", (19, TyVarFree NoLoc Lifted)), ("t_8322_8321_8321", (20, TyVarFree NoLoc Unlifted)), ("t_8328_8325_8322_8321_8328", (13, TyVarFree NoLoc Lifted)), ("t_8322_8321_8320_8322_8321_8329", (19, TyVarFree NoLoc Lifted)), ("index_8321_8327_8326_8322_8322_8320", (28, TyVarFree NoLoc Unlifted)), ("t_8329_8322_8322_8322_8321", (15, TyVarFree NoLoc Lifted)), ("index_elem_8321_8327_8327_8322_8322_8322", (28, TyVarFree NoLoc Unlifted)), ("index_8321_8326_8329_8322_8322_8323", (26, TyVarFree NoLoc Unlifted)), ("t_8321_8323_8324_8322_8322_8324", (17, TyVarFree NoLoc Lifted)), ("index_elem_8321_8327_8320_8322_8322_8325", (26, TyVarFree NoLoc Unlifted)), ("b_8329_8324_8322_8322_8326", (16, TyVarFree NoLoc Lifted)), ("a_8329_8323_8322_8322_8327", (16, TyVarFree NoLoc Lifted)), ("b_8329_8326_8322_8322_8328", (16, TyVarFree NoLoc Lifted)), ("a_8329_8325_8322_8322_8329", (16, TyVarFree NoLoc Lifted)), ("b_8329_8328_8322_8323_8320", (16, TyVarFree NoLoc Lifted)), ("a_8329_8327_8322_8323_8321", (16, TyVarFree NoLoc Lifted)), ("b_8321_8320_8320_8322_8323_8322", (16, TyVarFree NoLoc Lifted)), ("a_8329_8329_8322_8323_8323", (16, TyVarFree NoLoc Lifted)), ("b_8321_8320_8322_8322_8323_8324", (16, TyVarFree NoLoc Lifted)), ("a_8321_8320_8321_8322_8323_8325", (16, TyVarFree NoLoc Lifted)), ("t_8326_8321_8322_8323_8326", (11, TyVarFree NoLoc Lifted)), ("t_8328_8326_8322_8323_8327", (14, TyVarFree NoLoc Unlifted)), ("et_8328_8327_8322_8323_8328", (14, TyVarFree NoLoc Unlifted)), ("t_8325_8324_8322_8323_8329", (9, TyVarFree NoLoc Lifted)), ("t_8322_8324_8322_8324_8320", (7, TyVarFree NoLoc Lifted)), ("t_8322_8322_8322_8324_8321", (7, TyVarFree NoLoc Lifted)), ("t_8325_8322_8322_8324_8322", (9, TyVarFree NoLoc Lifted)), ("t_8325_8325_8322_8324_8323", (10, TyVarFree NoLoc Unlifted)), ("et_8325_8326_8322_8324_8324", (10, TyVarFree NoLoc Unlifted)), ("t_8325_8323_8322_8324_8325", (9, TyVarFree NoLoc Lifted)), ("t_8322_8323_8322_8324_8326", (7, TyVarFree NoLoc Lifted)), ("a_8322_8325_8322_8324_8327", (8, TyVarFree NoLoc Lifted)), ("b_8322_8328_8322_8324_8328", (8, TyVarFree NoLoc Lifted)), ("a_8323_8322_8322_8324_8329", (8, TyVarFree NoLoc Unlifted)), ("a_8322_8327_8322_8325_8320", (8, TyVarFree NoLoc Lifted)), ("t_8321_8323_8322_8325_8321", (5, TyVarFree NoLoc Lifted)), ("t_8321_8324_8322_8325_8322", (5, TyVarFree NoLoc Lifted))] + ), + ( [ "b_8325_8329" ~ "[]b_8325_8329_8328_8325", + "t_8326_8326" ~ "[]t_8326_8326_8328_8326", + "a_8325_8328" ~ "[]a_8325_8328_8328_8327", + "t_8326_8323" ~ "[]t_8326_8323_8328_8328", + "t_8325_8327" ~ "[]t_8325_8327_8328_8329", + "i64" ~ "t_8320", + "num_8321" ~ "t_8320", + "i32" ~ "t_8329", + "num_8321_8320" ~ "t_8329", + "t_8329" ~ "t_8328", + "num_8321_8325" ~ "t_8328", + "t_8328" ~ "t_8327", + "num_8322_8320" ~ "t_8327", + "bool" ~ "bool", + "num_8326" ~ "if_t_8322_8325", + "t_8327" ~ "if_t_8322_8325", + "t_8322_8326" ~ "if_t_8322_8325", + "i16" ~ "i16", + "t_8322_8329" ~ "i64", + "i64" ~ "t_8323_8320", + "t_8322_8329" ~ "t_8323_8320", + "t_8323_8325" ~ "t_8323_8320", + "i64" ~ "t_8323_8326", + "t_8322_8329" ~ "t_8323_8326", + "t_8324_8321" ~ "t_8323_8326", + "t_8323_8325" ~ "t_8324_8324", + "t_8322_8329" ~ "t_8324_8324", + "t_8324_8324" ~ "t_8324_8323", + "t_8324_8321" ~ "t_8324_8323", + "t_8324_8323" ~ "i64", + "[]t_1" ~ "[]t_8324_8322", + "t_8325_8327" ~ "[]t_8324_8322", + "i64" ~ "i64", + "t_8325_8327" ~ "t_8326_8323", + "t_8326_8326" ~ "t_8326_8323", + "t_8326_8327" ~ "t_8322_8326", + "t_8322_8326" ~ "t_8326_8329", + "num_8327_8320" ~ "t_8326_8329", + "i32 -> t_1 -> i32" ~ "i32 -> t_8326_8328 -> i32", + "t_8326_8329" ~ "i32", + "t_8326_8326" ~ "[]t_8326_8328", + "t_8326_8323" ~ "[]t_8326_8328", + "{xs: []t_8326_8320} -> []t_8326_8320" ~ "a_8325_8328 -> b_8325_8329", + "t_8326_8326" ~ "a_8325_8328", + "[]t_1" ~ "b_8325_8329" + ], + M.fromList [("t_1", (0, Unlifted, NoLoc))], + M.fromList [("t_8320", (5, TyVarFree NoLoc Unlifted)), ("num_8321", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8326", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8327", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8328", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8329", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8320", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8325", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8320", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("if_t_8322_8325", (5, TyVarFree NoLoc SizeLifted)), ("t_8322_8326", (6, TyVarFree NoLoc Lifted)), ("t_8322_8329", (8, TyVarFree NoLoc Lifted)), ("t_8323_8320", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8325", (10, TyVarFree NoLoc Lifted)), ("t_8323_8326", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8321", (12, TyVarFree NoLoc Lifted)), ("t_8324_8322", (13, TyVarFree NoLoc Unlifted)), ("t_8324_8323", (13, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8324", (13, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8327", (14, TyVarFree NoLoc Lifted)), ("a_8325_8328", (15, TyVarFree NoLoc Lifted)), ("b_8325_8329", (15, TyVarFree NoLoc Lifted)), ("t_8326_8320", (15, TyVarFree NoLoc Unlifted)), ("t_8326_8323", (15, TyVarFree NoLoc Unlifted)), ("t_8326_8326", (15, TyVarFree NoLoc Lifted)), ("t_8326_8327", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64])), ("t_8326_8328", (15, TyVarFree NoLoc Unlifted)), ("t_8326_8329", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8327_8320", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("b_8325_8329_8328_8325", (15, TyVarFree NoLoc Lifted)), ("t_8326_8326_8328_8326", (15, TyVarFree NoLoc Lifted)), ("a_8325_8328_8328_8327", (15, TyVarFree NoLoc Lifted)), ("t_8326_8323_8328_8328", (15, TyVarFree NoLoc Unlifted)), ("t_8325_8327_8328_8329", (14, TyVarFree NoLoc Lifted))] + ), + ( [ "t_8324_8325_8320" ~ "[]t_8324_8325_8320_8324_8326_8326", + "t_8323_8327_8320" ~ "[]t_8323_8327_8320_8324_8326_8327", + "t_8323_8327_8322" ~ "[]t_8323_8327_8322_8324_8326_8328", + "t_8323_8327_8321" ~ "[]t_8323_8327_8321_8324_8326_8329", + "a_8323_8325_8320" ~ "[]a_8323_8325_8320_8324_8327_8320", + "t_8321" ~ "t_8323", + "num_8324" ~ "t_8323", + "i64" ~ "i64", + "t_8321" ~ "t_8329", + "i32" ~ "t_8329", + "bool" ~ "t_8322", + "bool" ~ "t_8322", + "t_8322_8320" ~ "t_8320", + "index_8322_8321" ~ "index_elem_8322_8322", + "[]u32" ~ "[]index_elem_8322_8322", + "t_8322_8323" ~ "index_8322_8321", + "t_8322_8324" ~ "t_8321", + "index_8322_8325" ~ "index_elem_8322_8326", + "[]u32" ~ "[]index_elem_8322_8326", + "t_8322_8327" ~ "index_8322_8325", + "t_8322_8323" ~ "t_8322_8328", + "t_8322_8327" ~ "t_8322_8328", + "t_8320" ~ "i32", + "t_8321" ~ "i32", + "u32" ~ "t_8323_8325", + "u32" ~ "t_8323_8325", + "t_8323_8325" ~ "u32", + "num_8323_8324" ~ "t_8323_8323", + "i32" ~ "t_8323_8323", + "t_8322_8323" ~ "t_8325_8320", + "t_8322_8327" ~ "t_8325_8320", + "t_8325_8320" ~ "u32", + "bool" ~ "bool", + "t_8323_8323" ~ "if_t_8325_8327", + "i32" ~ "if_t_8325_8327", + "t_8325_8329" ~ "num_8325_8328", + "t_8322" ~ "bool", + "if_t_8325_8327" ~ "if_t_8326_8320", + "num_8325_8328" ~ "if_t_8326_8320", + "t_8326_8321" ~ "i64", + "t_8326_8324" ~ "i32", + "t_8326_8324" ~ "t_8326_8326", + "num_8326_8327" ~ "t_8326_8326", + "(t_8326_8324, t_8326_8326)" ~ "(t_8320, t_8321)", + "t_8326_8324" ~ "t_8327_8324", + "num_8327_8325" ~ "t_8327_8324", + "(t_8326_8324, t_8327_8324)" ~ "(t_8320, t_8321)", + "if_t_8326_8320" ~ "t_8326_8325", + "if_t_8326_8320" ~ "t_8326_8325", + "t_8326_8325" ~ "i32", + "t_8328_8328" ~ "i32", + "t_8326_8324" ~ "t_8328_8329", + "t_8328_8328" ~ "t_8328_8329", + "(t_8326_8324, t_8328_8329)" ~ "(t_8320, t_8321)", + "t_8329_8326" ~ "if_t_8326_8320", + "t_8329_8328" ~ "num_8329_8327", + "t_8329_8328" ~ "t_8321_8320_8321", + "t_8328_8328" ~ "t_8321_8320_8321", + "t_8326_8324" ~ "t_8321_8320_8320", + "t_8321_8320_8321" ~ "t_8321_8320_8320", + "(t_8326_8324, t_8321_8320_8320)" ~ "(t_8320, t_8321)", + "if_t_8326_8320" ~ "t_8329_8329", + "t_8329_8326" ~ "t_8329_8329", + "t_8329_8328" ~ "t_8321_8321_8326", + "num_8321_8321_8327" ~ "t_8321_8321_8326", + "num_8329_8327" ~ "t_8321_8321_8326", + "t_8321_8322_8322" ~ "t_8329_8328", + "t_8321_8322_8322" ~ "t_8321_8322_8324", + "num_8321_8322_8325" ~ "t_8321_8322_8324", + "(t_8321_8323_8320, t_8321_8323_8321)" ~ "(num_8321_8322_8323, t_8321_8322_8324)", + "t_8321_8323_8321" ~ "t_8321_8323_8322", + "num_8321_8323_8323" ~ "t_8321_8323_8322", + "t_8321_8323_8320" ~ "t_8321_8324_8321", + "t_8321_8323_8321" ~ "t_8321_8324_8321", + "t_8321_8324_8321" ~ "t_8321_8324_8320", + "t_8328_8328" ~ "t_8321_8324_8320", + "t_8326_8324" ~ "t_8321_8323_8329", + "t_8321_8324_8320" ~ "t_8321_8323_8329", + "(t_8326_8324, t_8321_8323_8329)" ~ "(t_8320, t_8321)", + "if_t_8326_8320" ~ "t_8321_8323_8328", + "t_8329_8326" ~ "t_8321_8323_8328", + "t_8321_8323_8320" ~ "t_8321_8326_8320", + "t_8321_8323_8321" ~ "t_8321_8326_8320", + "t_8321_8323_8321" ~ "t_8321_8326_8325", + "num_8321_8326_8326" ~ "t_8321_8326_8325", + "t_8321_8323_8321" ~ "t_8321_8327_8321", + "num_8321_8327_8322" ~ "t_8321_8327_8321", + "bool" ~ "bool", + "(t_8321_8326_8320, t_8321_8326_8325)" ~ "if_t_8321_8327_8327", + "(t_8321_8323_8320, t_8321_8327_8321)" ~ "if_t_8321_8327_8327", + "(num_8321_8322_8323, t_8321_8322_8324)" ~ "if_t_8321_8327_8327", + "(t_8321_8327_8328, t_8321_8327_8329)" ~ "(t_8321_8323_8320, t_8321_8323_8321)", + "t_8321_8327_8328" ~ "t_8321_8328_8321", + "t_8328_8328" ~ "t_8321_8328_8321", + "t_8326_8324" ~ "t_8321_8328_8320", + "t_8321_8328_8321" ~ "t_8321_8328_8320", + "t_8321_8329_8320" ~ "t_8321_8328_8320", + "(t_8326_8324, t_8321_8329_8320)" ~ "(t_8320, t_8321)", + "t_8321_8329_8323" ~ "if_t_8326_8320", + "(t_8321_8329_8326, t_8321_8329_8327)" ~ "(num_8321_8329_8324, num_8321_8329_8325)", + "t_8321_8329_8327" ~ "t_8321_8329_8328", + "t_8321_8327_8328" ~ "t_8321_8329_8328", + "t_8321_8329_8327" ~ "t_8322_8320_8323", + "num_8322_8320_8324" ~ "t_8322_8320_8323", + "t_8321_8327_8328" ~ "i32", + "t_8322_8320_8323" ~ "i32", + "t_8322_8321_8323" ~ "i32", + "t_8321_8329_8326" ~ "t_8322_8321_8327", + "t_8322_8321_8323" ~ "t_8322_8321_8327", + "t_8322_8321_8327" ~ "t_8322_8321_8326", + "t_8328_8328" ~ "t_8322_8321_8326", + "t_8326_8324" ~ "t_8322_8321_8325", + "t_8322_8321_8326" ~ "t_8322_8321_8325", + "(t_8326_8324, t_8322_8321_8325)" ~ "(t_8320, t_8321)", + "if_t_8326_8320" ~ "t_8322_8321_8324", + "t_8321_8329_8323" ~ "t_8322_8321_8324", + "t_8321_8329_8326" ~ "t_8322_8323_8326", + "t_8322_8321_8323" ~ "t_8322_8323_8326", + "t_8321_8329_8327" ~ "t_8322_8324_8321", + "num_8322_8324_8322" ~ "t_8322_8324_8321", + "t_8321_8329_8327" ~ "t_8322_8324_8327", + "num_8322_8324_8328" ~ "t_8322_8324_8327", + "bool" ~ "bool", + "(t_8322_8323_8326, t_8322_8324_8321)" ~ "if_t_8322_8325_8323", + "(t_8321_8329_8326, t_8322_8324_8327)" ~ "if_t_8322_8325_8323", + "(num_8321_8329_8324, num_8321_8329_8325)" ~ "if_t_8322_8325_8323", + "(t_8322_8325_8324, t_8322_8325_8325)" ~ "(t_8321_8329_8326, t_8321_8329_8327)", + "t_8322_8325_8324" ~ "t_8322_8325_8328", + "t_8328_8328" ~ "t_8322_8325_8328", + "t_8326_8324" ~ "t_8322_8325_8327", + "t_8322_8325_8328" ~ "t_8322_8325_8327", + "t_8328_8328" ~ "i32", + "num_8322_8326_8327" ~ "i32", + "t_8322_8325_8327" ~ "t_8322_8325_8326", + "i32" ~ "t_8322_8325_8326", + "t_8322_8327_8326" ~ "t_8322_8325_8326", + "t_8326_8324" ~ "i32", + "t_8321_8329_8320" ~ "i32", + "i32" ~ "t_8322_8327_8327", + "t_8322_8327_8326" ~ "t_8322_8327_8327", + "t_8322_8328_8328" ~ "num_8322_8328_8327", + "bool" ~ "bool", + "(t_8322_8328_8326, num_8322_8328_8327)" ~ "if_t_8322_8329_8320", + "(t_8322_8328_8329, t_8322_8327_8326)" ~ "if_t_8322_8329_8320", + "(t_8322_8329_8321, t_8322_8329_8322)" ~ "if_t_8322_8329_8320", + "t_8326_8324" ~ "i32", + "t_8321_8329_8320" ~ "i32", + "t_8322_8327_8326" ~ "t_8322_8329_8328", + "num_8322_8329_8329" ~ "t_8322_8329_8328", + "i32" ~ "t_8322_8329_8323", + "t_8322_8329_8328" ~ "t_8322_8329_8323", + "t_8322_8327_8326" ~ "t_8323_8320_8328", + "num_8323_8320_8329" ~ "t_8323_8320_8328", + "t_8323_8321_8326" ~ "num_8323_8321_8325", + "t_8322_8327_8326" ~ "t_8323_8321_8327", + "num_8323_8321_8328" ~ "t_8323_8321_8327", + "t_8322_8327_8326" ~ "t_8323_8322_8324", + "num_8323_8322_8325" ~ "t_8323_8322_8324", + "bool" ~ "bool", + "(t_8323_8321_8324, num_8323_8321_8325)" ~ "if_t_8323_8323_8320", + "(t_8323_8322_8323, t_8323_8322_8324)" ~ "if_t_8323_8323_8320", + "(t_8323_8323_8321, t_8323_8323_8322)" ~ "if_t_8323_8323_8320", + "t_8323_8323_8324" ~ "t_8326_8324", + "index_8323_8323_8325" ~ "index_elem_8323_8323_8326", + "[]u32" ~ "[]index_elem_8323_8323_8326", + "t_8321_8329_8323" ~ "i32", + "num_8323_8323_8328" ~ "t_8323_8323_8327", + "u32" ~ "t_8323_8323_8327", + "index_8323_8323_8325" ~ "t_8323_8323_8323", + "t_8323_8323_8327" ~ "t_8323_8323_8323", + "t_8323_8324_8329" ~ "t_8323_8323_8323", + "i64" ~ "t_8323_8325_8323", + "num_8323_8325_8324" ~ "t_8323_8325_8323", + "t_8323_8325_8323" ~ "i64", + "{i: t_8326_8321} -> ({delta_node: t_8321_8329_8323, left: t_8322_8329_8321, right: t_8323_8323_8321, sfc_code: t_8323_8324_8329}, (t_8322_8329_8322, t_8326_8324), (t_8323_8323_8322, t_8326_8324))" ~ "i64 -> a_8323_8325_8322", + "[]a_8323_8325_8322" ~ "a_8323_8325_8320", + "{xs: [](a_8323_8326_8323, b_8323_8326_8324, c_8323_8326_8325)} -> ([]a_8323_8326_8323, []b_8323_8326_8324, []c_8323_8326_8325)" ~ "a_8323_8325_8320 -> b_8323_8325_8321", + "(t_8323_8327_8320, t_8323_8327_8321, t_8323_8327_8322)" ~ "b_8323_8325_8321", + "i64" ~ "t_8323_8327_8324", + "num_8323_8327_8325" ~ "t_8323_8327_8324", + "t_8323_8328_8321" ~ "num_8323_8328_8320", + "a_8323_8328_8328" ~ "ft_8323_8329_8320", + "a_8323_8328_8328 -> b_8323_8328_8329" ~ "a_8323_8328_8325 -> b_8323_8328_8326", + "i32 -> i64" ~ "b_8323_8328_8326 -> c_8323_8328_8327", + "{x: a_8323_8328_8325} -> c_8323_8328_8327" ~ "a_8323_8328_8323 -> x_8323_8328_8324", + "t_8323_8327_8321" ~ "[]a_8323_8328_8323", + "a_8324_8320_8324" ~ "ft_8324_8320_8326", + "a_8324_8320_8324 -> b_8324_8320_8325" ~ "a_8324_8320_8321 -> b_8324_8320_8322", + "i32 -> i64" ~ "b_8324_8320_8322 -> c_8324_8320_8323", + "{x: a_8324_8320_8321} -> c_8324_8320_8323" ~ "a_8323_8329_8329 -> x_8324_8320_8320", + "t_8323_8327_8322" ~ "[]a_8323_8329_8329", + "[]x_8323_8328_8324" ~ "[]t_8323_8328_8322", + "[]x_8324_8320_8320" ~ "[]t_8323_8328_8322", + "a_8324_8322_8322" ~ "ft_8324_8322_8324", + "a_8324_8322_8322 -> b_8324_8322_8323" ~ "a_8324_8322_8320 -> x_8324_8322_8321", + "t_8323_8327_8321" ~ "[]a_8324_8322_8320", + "a_8324_8323_8321" ~ "ft_8324_8323_8323", + "a_8324_8323_8321 -> b_8324_8323_8322" ~ "a_8324_8322_8329 -> x_8324_8323_8320", + "t_8323_8327_8322" ~ "[]a_8324_8322_8329", + "[]x_8324_8322_8321" ~ "[]t_8324_8321_8329", + "[]x_8324_8323_8320" ~ "[]t_8324_8321_8329", + "t_8323_8327_8324" ~ "i64", + "num_8323_8328_8320" ~ "t_8323_8327_8323", + "[]t_8323_8328_8322" ~ "[]i64", + "[]t_8324_8321_8329" ~ "[]t_8323_8327_8323", + "t_8324_8325_8320" ~ "[]t_8323_8327_8323", + "{delta_node: t_8324_8325_8324, left: t_8324_8325_8325, right: t_8324_8325_8326, sfc_code: t_8324_8325_8327} -> {parent: t_8324_8325_8328} -> {delta_node: t_8324_8325_8324, left: t_8324_8325_8325, parent: t_8324_8325_8328, right: t_8324_8325_8326, sfc_code: t_8324_8325_8327}" ~ "a_8324_8325_8321 -> b_8324_8325_8322 -> x_8324_8325_8323", + "t_8323_8327_8320" ~ "[]a_8324_8325_8321", + "t_8324_8325_8320" ~ "[]b_8324_8325_8322", + "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}" ~ "[]x_8324_8325_8323" + ], + M.empty, + M.fromList [("t_8320", (3, TyVarFree NoLoc Lifted)), ("t_8321", (3, TyVarFree NoLoc Lifted)), ("t_8322", (4, TyVarPrim NoLoc [Bool])), ("t_8323", (4, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8324", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8329", (4, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8322_8321", (4, TyVarFree NoLoc Unlifted)), ("index_elem_8322_8322", (4, TyVarFree NoLoc Unlifted)), ("t_8322_8323", (5, TyVarFree NoLoc Lifted)), ("t_8322_8324", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8322_8325", (6, TyVarFree NoLoc Unlifted)), ("index_elem_8322_8326", (6, TyVarFree NoLoc Unlifted)), ("t_8322_8327", (7, TyVarFree NoLoc Lifted)), ("t_8322_8328", (8, TyVarFree NoLoc Unlifted)), ("t_8323_8323", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8324", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8325", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64])), ("t_8325_8320", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64])), ("if_t_8325_8327", (8, TyVarFree NoLoc SizeLifted)), ("num_8325_8328", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8329", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("if_t_8326_8320", (4, TyVarFree NoLoc SizeLifted)), ("t_8326_8321", (3, TyVarFree NoLoc Lifted)), ("t_8326_8324", (5, TyVarFree NoLoc Lifted)), ("t_8326_8325", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8326_8326", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8326_8327", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8327_8324", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8327_8325", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8328_8328", (7, TyVarFree NoLoc Lifted)), ("t_8328_8329", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8329_8326", (9, TyVarFree NoLoc Lifted)), ("num_8329_8327", (10, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8329_8328", (10, TyVarFree NoLoc Lifted)), ("t_8329_8329", (10, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8320_8320", (10, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8320_8321", (10, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8321_8326", (10, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8321_8327", (10, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8322_8322", (11, TyVarFree NoLoc Lifted)), ("num_8321_8322_8323", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8322_8324", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8322_8325", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8323_8320", (12, TyVarFree NoLoc Lifted)), ("t_8321_8323_8321", (12, TyVarFree NoLoc Lifted)), ("t_8321_8323_8322", (12, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8323_8323", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8323_8328", (12, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8323_8329", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8324_8320", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8324_8321", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326_8320", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326_8325", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8326_8326", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8327_8321", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8327_8322", (12, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("if_t_8321_8327_8327", (12, TyVarFree NoLoc SizeLifted)), ("t_8321_8327_8328", (13, TyVarFree NoLoc Lifted)), ("t_8321_8327_8329", (13, TyVarFree NoLoc Lifted)), ("t_8321_8328_8320", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8328_8321", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8329_8320", (15, TyVarFree NoLoc Lifted)), ("t_8321_8329_8323", (17, TyVarFree NoLoc Lifted)), ("num_8321_8329_8324", (18, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8329_8325", (18, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8329_8326", (18, TyVarFree NoLoc Lifted)), ("t_8321_8329_8327", (18, TyVarFree NoLoc Lifted)), ("t_8321_8329_8328", (18, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320_8323", (18, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8320_8324", (18, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8321_8323", (19, TyVarFree NoLoc Lifted)), ("t_8322_8321_8324", (20, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8321_8325", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8321_8326", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8321_8327", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8323_8326", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8324_8321", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8324_8322", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8324_8327", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8324_8328", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("if_t_8322_8325_8323", (20, TyVarFree NoLoc SizeLifted)), ("t_8322_8325_8324", (19, TyVarFree NoLoc Lifted)), ("t_8322_8325_8325", (19, TyVarFree NoLoc Lifted)), ("t_8322_8325_8326", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8325_8327", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8325_8328", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8326_8327", (20, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8327_8326", (21, TyVarFree NoLoc Lifted)), ("t_8322_8327_8327", (22, TyVarFree NoLoc Unlifted)), ("t_8322_8328_8326", (22, TyVarSum NoLoc (M.fromList [("leaf", [Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "t_8322_8327_8326" 14782}) [])])]))), ("num_8322_8328_8327", (22, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8328_8328", (22, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8328_8329", (22, TyVarSum NoLoc (M.fromList [("inner", [Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "t_8322_8327_8326" 14782}) [])])]))), ("if_t_8322_8329_8320", (22, TyVarFree NoLoc SizeLifted)), ("t_8322_8329_8321", (23, TyVarFree NoLoc Lifted)), ("t_8322_8329_8322", (23, TyVarFree NoLoc Lifted)), ("t_8322_8329_8323", (24, TyVarFree NoLoc Unlifted)), ("t_8322_8329_8328", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8329_8329", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8320_8328", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8320_8329", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8321_8324", (24, TyVarSum NoLoc (M.fromList [("leaf", [Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "t_8323_8320_8328" 14819}) [])])]))), ("num_8323_8321_8325", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8321_8326", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8321_8327", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8321_8328", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8322_8323", (24, TyVarSum NoLoc (M.fromList [("inner", [Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "t_8323_8321_8327" 14829}) [])])]))), ("t_8323_8322_8324", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8322_8325", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("if_t_8323_8323_8320", (24, TyVarFree NoLoc SizeLifted)), ("t_8323_8323_8321", (25, TyVarFree NoLoc Lifted)), ("t_8323_8323_8322", (25, TyVarFree NoLoc Lifted)), ("t_8323_8323_8323", (26, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64])), ("t_8323_8323_8324", (26, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8323_8323_8325", (26, TyVarFree NoLoc Unlifted)), ("index_elem_8323_8323_8326", (26, TyVarFree NoLoc Unlifted)), ("t_8323_8323_8327", (26, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8323_8328", (26, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8324_8329", (27, TyVarFree NoLoc Lifted)), ("a_8323_8325_8320", (2, TyVarFree NoLoc Lifted)), ("b_8323_8325_8321", (2, TyVarFree NoLoc Lifted)), ("a_8323_8325_8322", (2, TyVarFree NoLoc Unlifted)), ("t_8323_8325_8323", (2, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8325_8324", (2, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("a_8323_8326_8323", (2, TyVarFree NoLoc Unlifted)), ("b_8323_8326_8324", (2, TyVarFree NoLoc Unlifted)), ("c_8323_8326_8325", (2, TyVarFree NoLoc Unlifted)), ("t_8323_8327_8320", (3, TyVarFree NoLoc Lifted)), ("t_8323_8327_8321", (3, TyVarFree NoLoc Lifted)), ("t_8323_8327_8322", (3, TyVarFree NoLoc Lifted)), ("t_8323_8327_8323", (4, TyVarFree NoLoc Unlifted)), ("t_8323_8327_8324", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8327_8325", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8328_8320", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8328_8321", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8328_8322", (4, TyVarFree NoLoc Unlifted)), ("a_8323_8328_8323", (4, TyVarFree NoLoc Unlifted)), ("x_8323_8328_8324", (4, TyVarFree NoLoc Unlifted)), ("a_8323_8328_8325", (4, TyVarFree NoLoc Lifted)), ("b_8323_8328_8326", (4, TyVarFree NoLoc Lifted)), ("c_8323_8328_8327", (4, TyVarFree NoLoc Lifted)), ("a_8323_8328_8328", (4, TyVarFree NoLoc Lifted)), ("b_8323_8328_8329", (4, TyVarFree NoLoc Lifted)), ("ft_8323_8329_8320", (4, TyVarRecord NoLoc (M.fromList [("0", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "b_8323_8328_8329" 14921}) []))]))), ("a_8323_8329_8329", (4, TyVarFree NoLoc Unlifted)), ("x_8324_8320_8320", (4, TyVarFree NoLoc Unlifted)), ("a_8324_8320_8321", (4, TyVarFree NoLoc Lifted)), ("b_8324_8320_8322", (4, TyVarFree NoLoc Lifted)), ("c_8324_8320_8323", (4, TyVarFree NoLoc Lifted)), ("a_8324_8320_8324", (4, TyVarFree NoLoc Lifted)), ("b_8324_8320_8325", (4, TyVarFree NoLoc Lifted)), ("ft_8324_8320_8326", (4, TyVarRecord NoLoc (M.fromList [("0", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "b_8324_8320_8325" 14941}) []))]))), ("t_8324_8321_8329", (4, TyVarFree NoLoc Unlifted)), ("a_8324_8322_8320", (4, TyVarFree NoLoc Unlifted)), ("x_8324_8322_8321", (4, TyVarFree NoLoc Unlifted)), ("a_8324_8322_8322", (4, TyVarFree NoLoc Lifted)), ("b_8324_8322_8323", (4, TyVarFree NoLoc Lifted)), ("ft_8324_8322_8324", (4, TyVarRecord NoLoc (M.fromList [("1", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "b_8324_8322_8323" 14967}) []))]))), ("a_8324_8322_8329", (4, TyVarFree NoLoc Unlifted)), ("x_8324_8323_8320", (4, TyVarFree NoLoc Unlifted)), ("a_8324_8323_8321", (4, TyVarFree NoLoc Lifted)), ("b_8324_8323_8322", (4, TyVarFree NoLoc Lifted)), ("ft_8324_8323_8323", (4, TyVarRecord NoLoc (M.fromList [("1", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "b_8324_8323_8322" 14979}) []))]))), ("t_8324_8325_8320", (5, TyVarFree NoLoc Lifted)), ("a_8324_8325_8321", (6, TyVarFree NoLoc Unlifted)), ("b_8324_8325_8322", (6, TyVarFree NoLoc Unlifted)), ("x_8324_8325_8323", (6, TyVarFree NoLoc Unlifted)), ("t_8324_8325_8324", (7, TyVarFree NoLoc Lifted)), ("t_8324_8325_8325", (7, TyVarFree NoLoc Lifted)), ("t_8324_8325_8326", (7, TyVarFree NoLoc Lifted)), ("t_8324_8325_8327", (7, TyVarFree NoLoc Lifted)), ("t_8324_8325_8328", (8, TyVarFree NoLoc Lifted)), ("t_8324_8325_8320_8324_8326_8326", (5, TyVarFree NoLoc Lifted)), ("t_8323_8327_8320_8324_8326_8327", (3, TyVarFree NoLoc Lifted)), ("t_8323_8327_8322_8324_8326_8328", (3, TyVarFree NoLoc Lifted)), ("t_8323_8327_8321_8324_8326_8329", (3, TyVarFree NoLoc Lifted)), ("a_8323_8325_8320_8324_8327_8320", (2, TyVarFree NoLoc Lifted))] + ), + ( [ "t_8326_8325_8325" ~ "[]t_8326_8325_8325_8326_8325_8327", + "t_8322_8320_8326" ~ "[]t_8322_8320_8326_8326_8325_8328", + "t_8326_8324_8326" ~ "[]t_8326_8324_8326_8326_8325_8329", + "if_t_8326_8324_8325" ~ "[]if_t_8326_8324_8325_8326_8326_8320", + "t_8324_8324_8326" ~ "[]t_8324_8324_8326_8326_8326_8321", + "t_8326_8324_8320" ~ "[]t_8326_8324_8320_8326_8326_8322", + "t_8324_8326_8325" ~ "[]t_8324_8326_8325_8326_8326_8323", + "t_8324_8326_8326" ~ "[]t_8324_8326_8326_8326_8326_8324", + "t_8326_8324_8321" ~ "[]t_8326_8324_8321_8326_8326_8325", + "t_8324_8326_8323" ~ "[]t_8324_8326_8323_8326_8326_8326", + "t_8327_8322" ~ "[]t_8327_8322_8326_8326_8327", + "t_8321_8325_8326" ~ "[]t_8321_8325_8326_8326_8326_8328", + "b_8321_8328_8321" ~ "[]b_8321_8328_8321_8326_8326_8329", + "a_8321_8328_8320" ~ "[]a_8321_8328_8320_8326_8327_8320", + "t_8321_8327_8329" ~ "[]t_8321_8327_8329_8326_8327_8321", + "t_8321_8327_8328" ~ "[]t_8321_8327_8328_8326_8327_8322", + "a_8321_8325_8327" ~ "[]a_8321_8325_8327_8326_8327_8323", + "t_8321_8321_8329" ~ "[]t_8321_8321_8329_8326_8327_8324", + "b_8327_8324" ~ "[]b_8327_8324_8326_8327_8325", + "a_8327_8323" ~ "[]a_8327_8323_8326_8327_8326", + "b_8327_8326" ~ "[]b_8327_8326_8326_8327_8327", + "a_8327_8325" ~ "[]a_8327_8325_8326_8327_8328", + "t_8321" ~ "num_8320", + "index_8322" ~ "index_elem_8323", + "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}" ~ "[]index_elem_8323", + "index_8322" ~ "t_8325", + "t_8326" ~ "kt_8324", + "t_8327" ~ "t_8321_8320", + "num_8321_8321" ~ "t_8321_8320", + "t_8328" ~ "t_8321_8326", + "num_8321_8327" ~ "t_8321_8326", + "t_8321_8320" ~ "t_8329", + "t_8321_8326" ~ "t_8329", + "i32" ~ "t_8329", + "t_8322_8328" ~ "t_8322_8326", + "i32" ~ "t_8322_8329", + "num_8323_8320" ~ "t_8322_8329", + "t_8323_8326" ~ "t_8322_8326", + "t_8323_8327" ~ "t_8323_8325", + "index_8323_8328" ~ "index_elem_8323_8329", + "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}" ~ "[]index_elem_8323_8329", + "index_8323_8328" ~ "t_8324_8321", + "t_8322_8329" ~ "kt_8324_8320", + "match_t_8324_8322" ~ "t_8322_8329", + "t_8324_8325" ~ "t_8324_8327", + "kt_8324_8326" ~ "t_8322_8326", + "t_8324_8325" ~ "t_8325_8321", + "match_t_8324_8322" ~ "t_8327", + "kt_8325_8320" ~ "t_8328", + "t_8325_8326" ~ "i32", + "t_8324_8325" ~ "t_8325_8328", + "kt_8325_8327" ~ "t_8322_8326", + "t_8324_8325" ~ "t_8326_8322", + "match_t_8324_8322" ~ "t_8327", + "kt_8326_8321" ~ "t_8328", + "t_8326_8327" ~ "i32", + "{n: t_8324_8325} -> {left: t_8325_8326, right: t_8326_8327}" ~ "a_8324_8323 -> x_8324_8324", + "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}" ~ "[]a_8324_8323", + "t_8327_8322" ~ "[]x_8324_8324", + "t_8327_8329" ~ "t_8328_8322", + "num_8328_8323" ~ "t_8328_8322", + "bool" ~ "bool", + "t_8328_8320" ~ "t_8329_8320", + "num_8329_8321" ~ "t_8329_8320", + "bool" ~ "bool", + "i32" ~ "t_8328_8321", + "i32" ~ "t_8328_8321", + "{left: t_8327_8329, right: t_8328_8320} -> t_8328_8321" ~ "a_8327_8327 -> x_8327_8328", + "t_8327_8322" ~ "a_8327_8325", + "{as: []a_8327_8327} -> *[]x_8327_8328" ~ "a_8327_8325 -> b_8327_8326", + "t_8321_8320_8329 -> t_8321_8320_8329 -> t_8321_8320_8329" ~ "a_8321_8320_8328 -> a_8321_8320_8328 -> a_8321_8320_8328", + "num_8321_8321_8320" ~ "a_8321_8320_8328", + "b_8327_8326" ~ "a_8327_8323", + "{as: []a_8321_8320_8328} -> *[]a_8321_8320_8328" ~ "a_8327_8323 -> b_8327_8324", + "t_8321_8321_8329" ~ "b_8327_8324", + "t_8321_8321_8329" ~ "[]t_8321_8322_8321", + "t_8321_8322_8321" ~ "i32", + "i64" ~ "t_8321_8322_8320", + "num_8321_8322_8326" ~ "t_8321_8322_8320", + "t_8321_8323_8321" ~ "t_8321_8322_8320", + "t_8321_8323_8326" ~ "t_8321_8323_8324", + "num_8321_8323_8325" ~ "t_8321_8323_8324", + "t_8321_8324_8323" ~ "num_8321_8324_8322", + "num_8321_8324_8322" ~ "i64", + "t_8321_8321_8329" ~ "[]t_8321_8324_8321", + "t_8321_8323_8326 -> t_8321_8323_8324" ~ "a_8321_8323_8322 -> x_8321_8323_8323", + "[]t_8321_8324_8321" ~ "[]a_8321_8323_8322", + "t_8321_8325_8323" ~ "num_8321_8325_8322", + "[]x_8321_8323_8323" ~ "[]update_elem_8321_8325_8325", + "num_8321_8325_8324" ~ "update_elem_8321_8325_8325", + "t_8321_8325_8326" ~ "[]x_8321_8323_8323", + "t_8321_8326_8321" ~ "i32", + "t_8321_8325_8326" ~ "[]t_8321_8326_8325", + "{x: t_8321_8326_8321} -> (i64, num_8321_8326_8324)" ~ "a_8321_8325_8329 -> x_8321_8326_8320", + "[]t_8321_8326_8325" ~ "[]a_8321_8325_8329", + "[]x_8321_8326_8320" ~ "a_8321_8325_8327", + "{xs: [](a_8321_8327_8322, b_8321_8327_8323)} -> ([]a_8321_8327_8322, []b_8321_8327_8323)" ~ "a_8321_8325_8327 -> b_8321_8325_8328", + "(t_8321_8327_8328, t_8321_8327_8329)" ~ "b_8321_8325_8328", + "t_8321_8328_8323 -> t_8321_8328_8323 -> t_8321_8328_8323" ~ "a_8321_8328_8322 -> a_8321_8328_8322 -> a_8321_8328_8322", + "num_8321_8328_8324" ~ "a_8321_8328_8322", + "t_8321_8323_8321" ~ "i64", + "t_8321_8327_8328" ~ "[]i64", + "t_8321_8327_8329" ~ "[]a_8321_8328_8322", + "num_8321_8329_8327" ~ "i32", + "t_8321_8329_8326 -> t_8321_8329_8326 -> t_8321_8329_8326" ~ "a_8321_8329_8325 -> a_8321_8329_8325 -> a_8321_8329_8325", + "num_8321_8329_8327" ~ "a_8321_8329_8325", + "[]a_8321_8328_8322" ~ "a_8321_8328_8320", + "{as: []a_8321_8329_8325} -> *[]a_8321_8329_8325" ~ "a_8321_8328_8320 -> b_8321_8328_8321", + "t_8322_8320_8326" ~ "b_8321_8328_8321", + "t_8322_8321_8320" ~ "i64", + "t_8322_8321_8324" ~ "i32", + "t_8322_8321_8325" ~ "t_8322_8321_8321", + "index_8322_8321_8326" ~ "index_elem_8322_8321_8327", + "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}" ~ "[]index_elem_8322_8321_8327", + "t_8322_8321_8328" ~ "index_8322_8321_8326", + "t_8322_8321_8329" ~ "t_8322_8321_8321", + "index_8322_8322_8320" ~ "index_elem_8322_8322_8321", + "t_8327_8322" ~ "[]index_elem_8322_8322_8321", + "t_8322_8322_8322" ~ "index_8322_8322_8320", + "t_8322_8322_8323" ~ "t_8322_8321_8321", + "index_8322_8322_8324" ~ "index_elem_8322_8322_8325", + "t_8321_8325_8326" ~ "[]index_elem_8322_8322_8325", + "t_8322_8322_8326" ~ "index_8322_8322_8324", + "t_8322_8321_8328" ~ "t_8322_8323_8320", + "kt_8322_8322_8329" ~ "t_8322_8322_8328", + "num_8322_8323_8321" ~ "t_8322_8322_8328", + "t_8326" ~ "t_8322_8323_8326", + "num_8322_8323_8327" ~ "t_8322_8323_8326", + "t_8322_8322_8328" ~ "t_8322_8322_8327", + "t_8322_8323_8326" ~ "t_8322_8322_8327", + "t_8322_8324_8326" ~ "t_8322_8322_8327", + "t_8322_8322_8322" ~ "t_8322_8324_8328", + "t_8322_8324_8329" ~ "kt_8322_8324_8327", + "t_8322_8324_8329" ~ "t_8322_8325_8321", + "num_8322_8325_8322" ~ "t_8322_8325_8321", + "t_8322_8322_8326" ~ "t_8322_8325_8327", + "t_8322_8321_8324" ~ "t_8322_8325_8327", + "bool" ~ "t_8322_8325_8320", + "bool" ~ "t_8322_8325_8320", + "t_8322_8326_8326" ~ "t_8322_8325_8320", + "t_8322_8321_8324" ~ "t_8322_8326_8327", + "num_8322_8326_8328" ~ "t_8322_8326_8327", + "t_8322_8322_8322" ~ "t_8322_8327_8326", + "t_8322_8326_8326" ~ "bool", + "t_8322_8324_8329" ~ "if_t_8322_8327_8327", + "kt_8322_8327_8325" ~ "if_t_8322_8327_8327", + "t_8322_8324_8326" ~ "t_8322_8327_8324", + "if_t_8322_8327_8327" ~ "t_8322_8327_8324", + "bool" ~ "bool", + "num_8322_8327_8323" ~ "if_t_8322_8328_8322", + "t_8322_8327_8324" ~ "if_t_8322_8328_8322", + "t_8322_8328_8323" ~ "if_t_8322_8328_8322", + "t_8322_8321_8328" ~ "t_8322_8328_8325", + "t_8322_8321_8328" ~ "t_8322_8328_8327", + "t_8322_8326_8326" ~ "bool", + "kt_8322_8328_8324" ~ "if_t_8322_8328_8328", + "kt_8322_8328_8326" ~ "if_t_8322_8328_8328", + "t_8322_8328_8329" ~ "if_t_8322_8328_8328", + "t_8322_8321_8324" ~ "t_8322_8329_8321", + "num_8322_8329_8322" ~ "t_8322_8329_8321", + "t_8322_8329_8328" ~ "t_8322_8328_8329", + "t_8323_8320_8320" ~ "t_8322_8328_8329", + "match_t_8323_8320_8321" ~ "bool", + "bool" ~ "t_8322_8329_8320", + "match_t_8323_8320_8321" ~ "t_8322_8329_8320", + "t_8323_8320_8326" ~ "t_8322_8329_8320", + "t_8323_8320_8329" ~ "t_8323_8320_8327", + "t_8323_8321_8321" ~ "t_8323_8320_8327", + "t_8323_8320_8328" ~ "t_8323_8321_8320", + "match_t_8323_8321_8322" ~ "t_8323_8320_8328", + "i32" ~ "match_t_8323_8321_8322", + "t_8322_8328_8329" ~ "t_8323_8320_8327", + "t_8323_8321_8325" ~ "i32", + "index_8323_8321_8326" ~ "index_elem_8323_8321_8327", + "[]{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}" ~ "[]index_elem_8323_8321_8327", + "t_8323_8321_8328" ~ "index_8323_8321_8326", + "t_8323_8321_8328" ~ "t_8323_8322_8320", + "t_8323_8321_8328" ~ "t_8323_8322_8322", + "kt_8323_8321_8329" ~ "f32", + "kt_8323_8322_8321" ~ "{x: f32, y: f32, z: f32}", + "t_8323_8321_8328" ~ "ft_8323_8322_8327", + "(num_8323_8322_8328, num_8323_8322_8329, num_8323_8323_8320)" ~ "(f32, f32, f32)", + "(num_8323_8323_8324, num_8323_8323_8325, num_8323_8323_8326)" ~ "(f32, f32, f32)", + "t_8323_8320_8326" ~ "bool", + "t_8323_8321_8328" ~ "if_t_8323_8323_8329", + "{mass: float_8323_8323_8323, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}" ~ "if_t_8323_8323_8329", + "t_8323_8324_8320" ~ "if_t_8323_8323_8329", + "t_8322_8321_8324" ~ "t_8323_8324_8321", + "num_8323_8324_8322" ~ "t_8323_8324_8321", + "t_8323_8324_8328" ~ "num_8323_8324_8327", + "t_8323_8324_8329" ~ "t_8322_8321_8321", + "t_8323_8325_8321" ~ "num_8323_8325_8320", + "t_8323_8325_8322" ~ "num_8323_8325_8320", + "(t_8323_8325_8323, t_8323_8325_8324)" ~ "(t_8323_8325_8322, t_8323_8324_8329)", + "t_8323_8325_8327" ~ "num_8323_8325_8326", + "t_8323_8325_8323" ~ "t_8323_8325_8325", + "num_8323_8325_8326" ~ "t_8323_8325_8325", + "t_8323_8326_8322" ~ "t_8323_8325_8324", + "index_8323_8326_8323" ~ "index_elem_8323_8326_8324", + "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}" ~ "[]index_elem_8323_8326_8324", + "index_8323_8326_8323" ~ "t_8323_8326_8326", + "t_8323_8326_8327" ~ "kt_8323_8326_8325", + "t_8323_8327_8320" ~ "num_8323_8326_8329", + "t_8323_8326_8327" ~ "t_8323_8326_8328", + "num_8323_8326_8329" ~ "t_8323_8326_8328", + "t_8323_8327_8326" ~ "t_8323_8326_8327", + "index_8323_8327_8327" ~ "index_elem_8323_8327_8328", + "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}" ~ "[]index_elem_8323_8327_8328", + "index_8323_8327_8327" ~ "t_8323_8328_8320", + "kt_8323_8327_8329" ~ "t_8323_8320_8327", + "t_8323_8328_8323" ~ "i32", + "t_8323_8328_8324" ~ "t_8323_8326_8327", + "index_8323_8328_8325" ~ "index_elem_8323_8328_8326", + "t_8327_8322" ~ "[]index_elem_8323_8328_8326", + "t_8323_8328_8327" ~ "index_8323_8328_8325", + "t_8323_8328_8323" ~ "t_8323_8328_8328", + "t_8323_8325_8324" ~ "t_8323_8328_8328", + "t_8323_8329_8323" ~ "bool", + "t_8323_8328_8327" ~ "t_8323_8329_8325", + "t_8323_8328_8327" ~ "t_8323_8329_8327", + "t_8323_8329_8323" ~ "bool", + "kt_8323_8329_8324" ~ "if_t_8323_8329_8328", + "kt_8323_8329_8326" ~ "if_t_8323_8329_8328", + "t_8323_8329_8329" ~ "if_t_8323_8329_8328", + "t_8323_8329_8329" ~ "t_8324_8320_8320", + "num_8324_8320_8321" ~ "t_8324_8320_8320", + "t_8324_8320_8326" ~ "t_8323_8326_8327", + "index_8324_8320_8327" ~ "index_elem_8324_8320_8328", + "t_8321_8325_8326" ~ "[]index_elem_8324_8320_8328", + "t_8324_8320_8329" ~ "index_8324_8320_8327", + "t_8323_8328_8327" ~ "t_8324_8321_8325", + "kt_8324_8321_8324" ~ "t_8324_8321_8323", + "num_8324_8321_8326" ~ "t_8324_8321_8323", + "bool" ~ "bool", + "num_8324_8321_8322" ~ "t_8324_8321_8321", + "i32" ~ "t_8324_8321_8321", + "t_8324_8320_8329" ~ "t_8324_8321_8320", + "t_8324_8321_8321" ~ "t_8324_8321_8320", + "t_8323_8329_8323" ~ "bool", + "t_8324_8320_8329" ~ "if_t_8324_8323_8321", + "t_8324_8321_8320" ~ "if_t_8324_8323_8321", + "bool" ~ "bool", + "(if_t_8324_8323_8321, t_8323_8326_8327)" ~ "if_t_8324_8323_8322", + "(t_8323_8325_8323, t_8323_8326_8327)" ~ "if_t_8324_8323_8322", + "bool" ~ "bool", + "(num_8323_8327_8325, t_8323_8326_8327)" ~ "if_t_8324_8323_8323", + "if_t_8324_8323_8322" ~ "if_t_8324_8323_8323", + "(t_8323_8325_8322, t_8323_8324_8329)" ~ "if_t_8324_8323_8323", + "(t_8324_8323_8324, t_8324_8323_8325)" ~ "(t_8323_8325_8323, t_8323_8325_8324)", + "bool" ~ "bool", + "num_8323_8324_8327" ~ "if_t_8324_8323_8326", + "t_8324_8323_8324" ~ "if_t_8324_8323_8326", + "t_8324_8323_8327" ~ "if_t_8324_8323_8326", + "t_8324_8323_8329" ~ "num_8324_8323_8328", + "i32" ~ "num_8324_8323_8328", + "num_8324_8324_8321" ~ "i64", + "i32" ~ "t_8324_8324_8320", + "t_8324_8324_8326" ~ "[]t_8324_8324_8320", + "t_8322_8321_8324" ~ "t_8324_8324_8327", + "num_8324_8324_8328" ~ "t_8324_8324_8327", + "t_8322_8328_8329" ~ "t_8323_8320_8327", + "bool" ~ "bool", + "num_8324_8325_8323" ~ "if_t_8324_8325_8326", + "i32" ~ "if_t_8324_8325_8326", + "t_8324_8325_8327" ~ "if_t_8324_8325_8326", + "i32" ~ "num_8324_8325_8328", + "num_8324_8326_8320" ~ "et_8324_8325_8329", + "num_8324_8326_8321" ~ "et_8324_8325_8329", + "num_8324_8326_8322" ~ "et_8324_8325_8329", + "t_8324_8326_8323" ~ "[]et_8324_8325_8329", + "i32" ~ "num_8324_8326_8324", + "(t_8324_8326_8325, t_8324_8326_8326, t_8324_8326_8327, t_8324_8326_8328, t_8324_8326_8329)" ~ "(t_8324_8324_8326, t_8324_8326_8323, i32, t_8324_8325_8327, i32)", + "t_8324_8327_8322" ~ "num_8324_8327_8321", + "index_8324_8327_8323" ~ "index_elem_8324_8327_8324", + "t_8324_8326_8326" ~ "[]index_elem_8324_8327_8324", + "index_8324_8327_8323" ~ "t_8324_8327_8320", + "num_8324_8327_8325" ~ "t_8324_8327_8320", + "t_8324_8328_8321" ~ "t_8324_8326_8329", + "index_8324_8328_8322" ~ "index_elem_8324_8328_8323", + "t_8324_8326_8326" ~ "[]index_elem_8324_8328_8323", + "index_8324_8328_8322" ~ "t_8324_8328_8320", + "num_8324_8328_8324" ~ "t_8324_8328_8320", + "t_8324_8329_8320" ~ "t_8324_8326_8328", + "index_8324_8329_8321" ~ "index_elem_8324_8329_8322", + "t_8327_8322" ~ "[]index_elem_8324_8329_8322", + "index_8324_8329_8321" ~ "t_8324_8329_8324", + "kt_8324_8329_8323" ~ "t_8324_8328_8329", + "num_8324_8329_8325" ~ "t_8324_8328_8329", + "t_8325_8320_8320" ~ "t_8324_8326_8328", + "index_8325_8320_8321" ~ "index_elem_8325_8320_8322", + "t_8321_8325_8326" ~ "[]index_elem_8325_8320_8322", + "t_8325_8320_8323" ~ "index_8325_8320_8321", + "t_8325_8320_8324" ~ "t_8324_8326_8327", + "t_8324_8326_8325" ~ "[]update_elem_8325_8320_8325", + "t_8325_8320_8323" ~ "update_elem_8325_8320_8325", + "t_8324_8326_8327" ~ "t_8325_8320_8326", + "num_8325_8320_8327" ~ "t_8325_8320_8326", + "t_8325_8321_8322" ~ "t_8325_8320_8326", + "t_8325_8321_8323" ~ "t_8324_8326_8329", + "t_8324_8326_8326" ~ "[]update_elem_8325_8321_8325", + "num_8325_8321_8324" ~ "update_elem_8325_8321_8325", + "t_8325_8321_8326" ~ "t_8324_8326_8328", + "index_8325_8321_8327" ~ "index_elem_8325_8321_8328", + "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}" ~ "[]index_elem_8325_8321_8328", + "index_8325_8321_8327" ~ "t_8325_8322_8320", + "kt_8325_8321_8329" ~ "t_8323_8320_8327", + "t_8325_8322_8323" ~ "i32", + "t_8324_8326_8329" ~ "t_8325_8322_8324", + "num_8325_8322_8325" ~ "t_8325_8322_8324", + "t_8325_8323_8320" ~ "t_8325_8322_8324", + "t_8325_8323_8321" ~ "t_8325_8323_8320", + "t_8324_8326_8326" ~ "[]update_elem_8325_8323_8323", + "num_8325_8323_8322" ~ "update_elem_8325_8323_8323", + "bool" ~ "bool", + "(t_8324_8326_8325, t_8324_8326_8326, t_8325_8321_8322, t_8324_8326_8328, t_8324_8326_8329)" ~ "if_t_8325_8323_8324", + "(t_8324_8326_8325, t_8324_8326_8326, t_8324_8326_8327, t_8325_8322_8323, t_8325_8323_8320)" ~ "if_t_8325_8323_8324", + "t_8325_8323_8326" ~ "t_8324_8326_8329", + "index_8325_8323_8327" ~ "index_elem_8325_8323_8328", + "t_8324_8326_8326" ~ "[]index_elem_8325_8323_8328", + "index_8325_8323_8327" ~ "t_8325_8323_8325", + "num_8325_8323_8329" ~ "t_8325_8323_8325", + "t_8325_8324_8325" ~ "t_8324_8326_8328", + "index_8325_8324_8326" ~ "index_elem_8325_8324_8327", + "t_8327_8322" ~ "[]index_elem_8325_8324_8327", + "index_8325_8324_8326" ~ "t_8325_8324_8329", + "kt_8325_8324_8328" ~ "t_8325_8324_8324", + "num_8325_8325_8320" ~ "t_8325_8324_8324", + "t_8325_8325_8325" ~ "t_8324_8326_8328", + "index_8325_8325_8326" ~ "index_elem_8325_8325_8327", + "t_8321_8325_8326" ~ "[]index_elem_8325_8325_8327", + "t_8325_8325_8328" ~ "index_8325_8325_8326", + "t_8325_8325_8329" ~ "t_8324_8326_8327", + "t_8325_8326_8323" ~ "t_8324_8326_8328", + "index_8325_8326_8324" ~ "index_elem_8325_8326_8325", + "t_8327_8322" ~ "[]index_elem_8325_8326_8325", + "index_8325_8326_8324" ~ "t_8325_8326_8327", + "kt_8325_8326_8326" ~ "t_8325_8326_8322", + "num_8325_8326_8328" ~ "t_8325_8326_8322", + "bool" ~ "bool", + "i32" ~ "t_8325_8326_8321", + "num_8325_8327_8325" ~ "t_8325_8326_8321", + "t_8325_8325_8328" ~ "t_8325_8326_8320", + "t_8325_8326_8321" ~ "t_8325_8326_8320", + "t_8324_8326_8325" ~ "[]update_elem_8325_8328_8324", + "t_8325_8326_8320" ~ "update_elem_8325_8328_8324", + "t_8324_8326_8327" ~ "t_8325_8328_8325", + "num_8325_8328_8326" ~ "t_8325_8328_8325", + "t_8325_8329_8321" ~ "t_8325_8328_8325", + "t_8325_8329_8322" ~ "t_8324_8326_8329", + "t_8324_8326_8326" ~ "[]update_elem_8325_8329_8324", + "num_8325_8329_8323" ~ "update_elem_8325_8329_8324", + "t_8325_8329_8325" ~ "t_8324_8326_8328", + "index_8325_8329_8326" ~ "index_elem_8325_8329_8327", + "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}" ~ "[]index_elem_8325_8329_8327", + "index_8325_8329_8326" ~ "t_8325_8329_8329", + "kt_8325_8329_8328" ~ "t_8323_8320_8327", + "t_8326_8320_8322" ~ "i32", + "t_8324_8326_8329" ~ "t_8326_8320_8323", + "num_8326_8320_8324" ~ "t_8326_8320_8323", + "t_8326_8320_8329" ~ "t_8326_8320_8323", + "t_8326_8321_8320" ~ "t_8326_8320_8329", + "t_8324_8326_8326" ~ "[]update_elem_8326_8321_8322", + "num_8326_8321_8321" ~ "update_elem_8326_8321_8322", + "bool" ~ "bool", + "(t_8324_8326_8325, t_8324_8326_8326, t_8325_8329_8321, t_8324_8326_8328, t_8324_8326_8329)" ~ "if_t_8326_8321_8323", + "(t_8324_8326_8325, t_8324_8326_8326, t_8324_8326_8327, t_8326_8320_8322, t_8326_8320_8329)" ~ "if_t_8326_8321_8323", + "t_8326_8321_8324" ~ "t_8324_8326_8328", + "index_8326_8321_8325" ~ "index_elem_8326_8321_8326", + "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}" ~ "[]index_elem_8326_8321_8326", + "index_8326_8321_8325" ~ "t_8326_8321_8328", + "t_8326_8321_8329" ~ "kt_8326_8321_8327", + "t_8324_8326_8329" ~ "t_8326_8322_8320", + "num_8326_8322_8321" ~ "t_8326_8322_8320", + "t_8326_8322_8326" ~ "t_8326_8322_8320", + "t_8326_8322_8327" ~ "t_8326_8322_8326", + "t_8326_8322_8329" ~ "t_8326_8322_8326", + "index_8326_8323_8320" ~ "index_elem_8326_8323_8321", + "t_8324_8326_8326" ~ "[]index_elem_8326_8323_8321", + "num_8326_8323_8322" ~ "i32", + "index_8326_8323_8320" ~ "t_8326_8322_8328", + "num_8326_8323_8322" ~ "t_8326_8322_8328", + "t_8324_8326_8326" ~ "[]update_elem_8326_8323_8327", + "t_8326_8322_8328" ~ "update_elem_8326_8323_8327", + "bool" ~ "bool", + "if_t_8326_8321_8323" ~ "if_t_8326_8323_8328", + "(t_8324_8326_8325, t_8324_8326_8326, t_8324_8326_8327, t_8326_8321_8329, t_8326_8322_8326)" ~ "if_t_8326_8323_8328", + "bool" ~ "bool", + "if_t_8325_8323_8324" ~ "if_t_8326_8323_8329", + "if_t_8326_8323_8328" ~ "if_t_8326_8323_8329", + "(t_8324_8324_8326, t_8324_8326_8323, i32, t_8324_8325_8327, i32)" ~ "if_t_8326_8323_8329", + "(t_8326_8324_8320, t_8326_8324_8321, t_8326_8324_8322, t_8326_8324_8323, t_8326_8324_8324)" ~ "(t_8324_8326_8325, t_8324_8326_8326, t_8324_8326_8327, t_8324_8326_8328, t_8324_8326_8329)", + "t_8323_8320_8326" ~ "bool", + "t_8324_8324_8326" ~ "if_t_8326_8324_8325", + "t_8326_8324_8320" ~ "if_t_8326_8324_8325", + "t_8326_8324_8326" ~ "if_t_8326_8324_8325", + "t_8321_8323_8321" ~ "i64", + "{i: t_8322_8321_8320} -> {rp: t_8322_8321_8321} -> {body: t_8323_8324_8320, children: t_8326_8324_8326, is_leaf: t_8323_8320_8326, parent: t_8324_8323_8327, tree_level: t_8322_8328_8323}" ~ "a_8322_8320_8327 -> b_8322_8320_8328 -> x_8322_8320_8329", + "[]i64" ~ "[]a_8322_8320_8327", + "t_8322_8320_8326" ~ "[]b_8322_8320_8328", + "t_8326_8325_8325" ~ "[]x_8322_8320_8329", + "[]{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}" ~ "t_8326_8325_8325" + ], + M.empty, + M.fromList [("num_8320", (3, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321", (3, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8322", (3, TyVarFree NoLoc Unlifted)), ("index_elem_8323", (3, TyVarFree NoLoc Unlifted)), ("kt_8324", (3, TyVarFree NoLoc Lifted)), ("t_8325", (3, TyVarRecord NoLoc (M.fromList [("delta_node", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8324" 15206}) []))]))), ("t_8326", (4, TyVarFree NoLoc Lifted)), ("t_8327", (6, TyVarFree NoLoc Lifted)), ("t_8328", (7, TyVarFree NoLoc Lifted)), ("t_8329", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8320", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8321", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8327", (8, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8326", (6, TyVarFree NoLoc Lifted)), ("t_8322_8327", (7, TyVarFree NoLoc Lifted)), ("t_8322_8328", (7, TyVarSum NoLoc (M.fromList [("leaf", [Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "t_8322_8327" 15232}) [])])]))), ("t_8322_8329", (7, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8320", (7, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8325", (7, TyVarFree NoLoc Lifted)), ("t_8323_8326", (7, TyVarSum NoLoc (M.fromList [("inner", [Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "t_8323_8325" 15241}) [])])]))), ("t_8323_8327", (7, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8323_8328", (7, TyVarFree NoLoc Unlifted)), ("index_elem_8323_8329", (7, TyVarFree NoLoc Unlifted)), ("kt_8324_8320", (7, TyVarFree NoLoc Lifted)), ("t_8324_8321", (7, TyVarRecord NoLoc (M.fromList [("delta_node", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8324_8320" 15247}) []))]))), ("match_t_8324_8322", (7, TyVarFree NoLoc SizeLifted)), ("a_8324_8323", (5, TyVarFree NoLoc Unlifted)), ("x_8324_8324", (5, TyVarFree NoLoc Unlifted)), ("t_8324_8325", (6, TyVarFree NoLoc Lifted)), ("kt_8324_8326", (7, TyVarFree NoLoc Lifted)), ("t_8324_8327", (7, TyVarRecord NoLoc (M.fromList [("left", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8324_8326" 15255}) []))]))), ("kt_8325_8320", (7, TyVarFree NoLoc Lifted)), ("t_8325_8321", (7, TyVarRecord NoLoc (M.fromList [("delta_node", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8325_8320" 15260}) []))]))), ("t_8325_8326", (8, TyVarFree NoLoc Lifted)), ("kt_8325_8327", (9, TyVarFree NoLoc Lifted)), ("t_8325_8328", (9, TyVarRecord NoLoc (M.fromList [("right", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8325_8327" 15268}) []))]))), ("kt_8326_8321", (9, TyVarFree NoLoc Lifted)), ("t_8326_8322", (9, TyVarRecord NoLoc (M.fromList [("delta_node", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8326_8321" 15273}) []))]))), ("t_8326_8327", (10, TyVarFree NoLoc Lifted)), ("t_8327_8322", (6, TyVarFree NoLoc Lifted)), ("a_8327_8323", (7, TyVarFree NoLoc Lifted)), ("b_8327_8324", (7, TyVarFree NoLoc Lifted)), ("a_8327_8325", (7, TyVarFree NoLoc Lifted)), ("b_8327_8326", (7, TyVarFree NoLoc Lifted)), ("a_8327_8327", (7, TyVarFree NoLoc Unlifted)), ("x_8327_8328", (7, TyVarFree NoLoc Unlifted)), ("t_8327_8329", (8, TyVarFree NoLoc Lifted)), ("t_8328_8320", (8, TyVarFree NoLoc Lifted)), ("t_8328_8321", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8328_8322", (9, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8328_8323", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8329_8320", (9, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8329_8321", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("a_8321_8320_8328", (7, TyVarFree NoLoc Unlifted)), ("t_8321_8320_8329", (7, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8321_8320", (7, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8321_8329", (8, TyVarFree NoLoc Lifted)), ("t_8321_8322_8320", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8322_8321", (9, TyVarFree NoLoc Unlifted)), ("num_8321_8322_8326", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8323_8321", (10, TyVarFree NoLoc Lifted)), ("a_8321_8323_8322", (11, TyVarFree NoLoc Unlifted)), ("x_8321_8323_8323", (11, TyVarFree NoLoc Unlifted)), ("t_8321_8323_8324", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8323_8325", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8323_8326", (11, TyVarFree NoLoc Lifted)), ("t_8321_8324_8321", (11, TyVarFree NoLoc Unlifted)), ("num_8321_8324_8322", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8324_8323", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8325_8322", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8325_8323", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("num_8321_8325_8324", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("update_elem_8321_8325_8325", (11, TyVarFree NoLoc Unlifted)), ("t_8321_8325_8326", (12, TyVarFree NoLoc Lifted)), ("a_8321_8325_8327", (13, TyVarFree NoLoc Lifted)), ("b_8321_8325_8328", (13, TyVarFree NoLoc Lifted)), ("a_8321_8325_8329", (13, TyVarFree NoLoc Unlifted)), ("x_8321_8326_8320", (13, TyVarFree NoLoc Unlifted)), ("t_8321_8326_8321", (14, TyVarFree NoLoc Lifted)), ("num_8321_8326_8324", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8326_8325", (13, TyVarFree NoLoc Unlifted)), ("a_8321_8327_8322", (13, TyVarFree NoLoc Unlifted)), ("b_8321_8327_8323", (13, TyVarFree NoLoc Unlifted)), ("t_8321_8327_8328", (14, TyVarFree NoLoc Lifted)), ("t_8321_8327_8329", (14, TyVarFree NoLoc Lifted)), ("a_8321_8328_8320", (15, TyVarFree NoLoc Lifted)), ("b_8321_8328_8321", (15, TyVarFree NoLoc Lifted)), ("a_8321_8328_8322", (15, TyVarFree NoLoc Unlifted)), ("t_8321_8328_8323", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8328_8324", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("a_8321_8329_8325", (15, TyVarFree NoLoc Unlifted)), ("t_8321_8329_8326", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8329_8327", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320_8326", (16, TyVarFree NoLoc Lifted)), ("a_8322_8320_8327", (17, TyVarFree NoLoc Unlifted)), ("b_8322_8320_8328", (17, TyVarFree NoLoc Unlifted)), ("x_8322_8320_8329", (17, TyVarFree NoLoc Unlifted)), ("t_8322_8321_8320", (18, TyVarFree NoLoc Lifted)), ("t_8322_8321_8321", (19, TyVarFree NoLoc Lifted)), ("t_8322_8321_8324", (21, TyVarFree NoLoc Lifted)), ("t_8322_8321_8325", (22, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8322_8321_8326", (22, TyVarFree NoLoc Unlifted)), ("index_elem_8322_8321_8327", (22, TyVarFree NoLoc Unlifted)), ("t_8322_8321_8328", (23, TyVarFree NoLoc Lifted)), ("t_8322_8321_8329", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8322_8322_8320", (24, TyVarFree NoLoc Unlifted)), ("index_elem_8322_8322_8321", (24, TyVarFree NoLoc Unlifted)), ("t_8322_8322_8322", (25, TyVarFree NoLoc Lifted)), ("t_8322_8322_8323", (26, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8322_8322_8324", (26, TyVarFree NoLoc Unlifted)), ("index_elem_8322_8322_8325", (26, TyVarFree NoLoc Unlifted)), ("t_8322_8322_8326", (27, TyVarFree NoLoc Lifted)), ("t_8322_8322_8327", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8322_8328", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8322_8322_8329", (28, TyVarFree NoLoc Lifted)), ("t_8322_8323_8320", (28, TyVarRecord NoLoc (M.fromList [("delta_node", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8322_8329" 15494}) []))]))), ("num_8322_8323_8321", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8323_8326", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8323_8327", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8324_8326", (29, TyVarFree NoLoc Lifted)), ("kt_8322_8324_8327", (30, TyVarFree NoLoc Lifted)), ("t_8322_8324_8328", (30, TyVarRecord NoLoc (M.fromList [("left", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8324_8327" 15515}) []))]))), ("t_8322_8324_8329", (31, TyVarFree NoLoc Lifted)), ("t_8322_8325_8320", (32, TyVarPrim NoLoc [Bool])), ("t_8322_8325_8321", (32, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8325_8322", (32, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8325_8327", (32, TyVarFree NoLoc Unlifted)), ("t_8322_8326_8326", (33, TyVarFree NoLoc Lifted)), ("t_8322_8326_8327", (34, TyVarFree NoLoc Unlifted)), ("num_8322_8326_8328", (34, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8327_8323", (34, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8327_8324", (34, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8322_8327_8325", (34, TyVarFree NoLoc Lifted)), ("t_8322_8327_8326", (34, TyVarRecord NoLoc (M.fromList [("right", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8327_8325" 15547}) []))]))), ("if_t_8322_8327_8327", (34, TyVarFree NoLoc SizeLifted)), ("if_t_8322_8328_8322", (34, TyVarFree NoLoc SizeLifted)), ("t_8322_8328_8323", (35, TyVarFree NoLoc Lifted)), ("kt_8322_8328_8324", (36, TyVarFree NoLoc Lifted)), ("t_8322_8328_8325", (36, TyVarRecord NoLoc (M.fromList [("left", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8328_8324" 15557}) []))]))), ("kt_8322_8328_8326", (36, TyVarFree NoLoc Lifted)), ("t_8322_8328_8327", (36, TyVarRecord NoLoc (M.fromList [("right", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8328_8326" 15559}) []))]))), ("if_t_8322_8328_8328", (36, TyVarFree NoLoc SizeLifted)), ("t_8322_8328_8329", (37, TyVarFree NoLoc Lifted)), ("t_8322_8329_8320", (38, TyVarPrim NoLoc [Bool])), ("t_8322_8329_8321", (38, TyVarFree NoLoc Unlifted)), ("num_8322_8329_8322", (38, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8329_8327", (38, TyVarFree NoLoc Lifted)), ("t_8322_8329_8328", (38, TyVarSum NoLoc (M.fromList [("leaf", [Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "t_8322_8329_8327" 15571}) [])])]))), ("t_8322_8329_8329", (38, TyVarFree NoLoc Lifted)), ("t_8323_8320_8320", (38, TyVarSum NoLoc (M.fromList [("inner", [Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "t_8322_8329_8329" 15573}) [])])]))), ("match_t_8323_8320_8321", (38, TyVarFree NoLoc SizeLifted)), ("t_8323_8320_8326", (39, TyVarFree NoLoc Lifted)), ("t_8323_8320_8327", (41, TyVarFree NoLoc Lifted)), ("t_8323_8320_8328", (42, TyVarFree NoLoc Lifted)), ("t_8323_8320_8329", (42, TyVarSum NoLoc (M.fromList [("inner", [Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "t_8323_8320_8328" 15583}) [])])]))), ("t_8323_8321_8320", (42, TyVarFree NoLoc Lifted)), ("t_8323_8321_8321", (42, TyVarSum NoLoc (M.fromList [("leaf", [Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "t_8323_8321_8320" 15585}) [])])]))), ("match_t_8323_8321_8322", (42, TyVarFree NoLoc SizeLifted)), ("t_8323_8321_8325", (40, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8323_8321_8326", (40, TyVarFree NoLoc Unlifted)), ("index_elem_8323_8321_8327", (40, TyVarFree NoLoc Unlifted)), ("t_8323_8321_8328", (41, TyVarFree NoLoc Lifted)), ("kt_8323_8321_8329", (42, TyVarFree NoLoc Lifted)), ("t_8323_8322_8320", (42, TyVarRecord NoLoc (M.fromList [("mass", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8323_8321_8329" 15596}) []))]))), ("kt_8323_8322_8321", (42, TyVarFree NoLoc Lifted)), ("t_8323_8322_8322", (42, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8323_8322_8321" 15598}) []))]))), ("ft_8323_8322_8327", (42, TyVarRecord NoLoc (M.fromList [("position", Scalar (Record (M.fromList [("x", Scalar (Prim (FloatType Float32))), ("y", Scalar (Prim (FloatType Float32))), ("z", Scalar (Prim (FloatType Float32)))])))]))), ("num_8323_8322_8328", (40, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8322_8329", (40, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8323_8320", (40, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("float_8323_8323_8323", (40, TyVarPrim NoLoc [FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8323_8324", (40, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8323_8325", (40, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8323_8326", (40, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("if_t_8323_8323_8329", (40, TyVarFree NoLoc SizeLifted)), ("t_8323_8324_8320", (41, TyVarFree NoLoc Lifted)), ("t_8323_8324_8321", (42, TyVarFree NoLoc Unlifted)), ("num_8323_8324_8322", (42, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8324_8327", (42, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8324_8328", (42, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8324_8329", (43, TyVarFree NoLoc Lifted)), ("num_8323_8325_8320", (44, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8325_8321", (44, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8325_8322", (45, TyVarFree NoLoc Lifted)), ("t_8323_8325_8323", (46, TyVarFree NoLoc Lifted)), ("t_8323_8325_8324", (46, TyVarFree NoLoc Lifted)), ("t_8323_8325_8325", (46, TyVarFree NoLoc Unlifted)), ("num_8323_8325_8326", (46, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8325_8327", (46, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8326_8322", (46, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8323_8326_8323", (46, TyVarFree NoLoc Unlifted)), ("index_elem_8323_8326_8324", (46, TyVarFree NoLoc Unlifted)), ("kt_8323_8326_8325", (46, TyVarFree NoLoc Lifted)), ("t_8323_8326_8326", (46, TyVarRecord NoLoc (M.fromList [("parent", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8323_8326_8325" 15648}) []))]))), ("t_8323_8326_8327", (47, TyVarFree NoLoc Lifted)), ("t_8323_8326_8328", (48, TyVarFree NoLoc Unlifted)), ("num_8323_8326_8329", (48, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8327_8320", (48, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8327_8325", (48, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8327_8326", (48, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8323_8327_8327", (48, TyVarFree NoLoc Unlifted)), ("index_elem_8323_8327_8328", (48, TyVarFree NoLoc Unlifted)), ("kt_8323_8327_8329", (48, TyVarFree NoLoc Lifted)), ("t_8323_8328_8320", (48, TyVarRecord NoLoc (M.fromList [("left", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8323_8327_8329" 15664}) []))]))), ("t_8323_8328_8323", (49, TyVarFree NoLoc Lifted)), ("t_8323_8328_8324", (50, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8323_8328_8325", (50, TyVarFree NoLoc Unlifted)), ("index_elem_8323_8328_8326", (50, TyVarFree NoLoc Unlifted)), ("t_8323_8328_8327", (51, TyVarFree NoLoc Lifted)), ("t_8323_8328_8328", (52, TyVarFree NoLoc Unlifted)), ("t_8323_8329_8323", (53, TyVarFree NoLoc Lifted)), ("kt_8323_8329_8324", (54, TyVarFree NoLoc Lifted)), ("t_8323_8329_8325", (54, TyVarRecord NoLoc (M.fromList [("left", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8323_8329_8324" 15681}) []))]))), ("kt_8323_8329_8326", (54, TyVarFree NoLoc Lifted)), ("t_8323_8329_8327", (54, TyVarRecord NoLoc (M.fromList [("right", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8323_8329_8326" 15683}) []))]))), ("if_t_8323_8329_8328", (54, TyVarFree NoLoc SizeLifted)), ("t_8323_8329_8329", (55, TyVarFree NoLoc Lifted)), ("t_8324_8320_8320", (56, TyVarFree NoLoc Unlifted)), ("num_8324_8320_8321", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8320_8326", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8324_8320_8327", (56, TyVarFree NoLoc Unlifted)), ("index_elem_8324_8320_8328", (56, TyVarFree NoLoc Unlifted)), ("t_8324_8320_8329", (57, TyVarFree NoLoc Lifted)), ("t_8324_8321_8320", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8321_8321", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8324_8321_8322", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8321_8323", (58, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8324_8321_8324", (58, TyVarFree NoLoc Lifted)), ("t_8324_8321_8325", (58, TyVarRecord NoLoc (M.fromList [("left", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8324_8321_8324" 15702}) []))]))), ("num_8324_8321_8326", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("if_t_8324_8323_8321", (58, TyVarFree NoLoc SizeLifted)), ("if_t_8324_8323_8322", (56, TyVarFree NoLoc SizeLifted)), ("if_t_8324_8323_8323", (48, TyVarFree NoLoc SizeLifted)), ("t_8324_8323_8324", (47, TyVarFree NoLoc Lifted)), ("t_8324_8323_8325", (47, TyVarFree NoLoc Lifted)), ("if_t_8324_8323_8326", (42, TyVarFree NoLoc SizeLifted)), ("t_8324_8323_8327", (43, TyVarFree NoLoc Lifted)), ("num_8324_8323_8328", (44, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8323_8329", (44, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8324_8320", (46, TyVarFree NoLoc Unlifted)), ("num_8324_8324_8321", (46, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8324_8326", (47, TyVarFree NoLoc Lifted)), ("t_8324_8324_8327", (48, TyVarFree NoLoc Unlifted)), ("num_8324_8324_8328", (48, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8324_8325_8323", (48, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("if_t_8324_8325_8326", (48, TyVarFree NoLoc SizeLifted)), ("t_8324_8325_8327", (49, TyVarFree NoLoc Lifted)), ("num_8324_8325_8328", (50, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("et_8324_8325_8329", (52, TyVarFree NoLoc Unlifted)), ("num_8324_8326_8320", (52, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8324_8326_8321", (52, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8324_8326_8322", (52, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8326_8323", (53, TyVarFree NoLoc Lifted)), ("num_8324_8326_8324", (54, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8326_8325", (56, TyVarFree NoLoc Lifted)), ("t_8324_8326_8326", (56, TyVarFree NoLoc Lifted)), ("t_8324_8326_8327", (56, TyVarFree NoLoc Lifted)), ("t_8324_8326_8328", (56, TyVarFree NoLoc Lifted)), ("t_8324_8326_8329", (56, TyVarFree NoLoc Lifted)), ("t_8324_8327_8320", (56, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8324_8327_8321", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8327_8322", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8324_8327_8323", (56, TyVarFree NoLoc Unlifted)), ("index_elem_8324_8327_8324", (56, TyVarFree NoLoc Unlifted)), ("num_8324_8327_8325", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8328_8320", (56, TyVarFree NoLoc Unlifted)), ("t_8324_8328_8321", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8324_8328_8322", (56, TyVarFree NoLoc Unlifted)), ("index_elem_8324_8328_8323", (56, TyVarFree NoLoc Unlifted)), ("num_8324_8328_8324", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8328_8329", (56, TyVarFree NoLoc Unlifted)), ("t_8324_8329_8320", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8324_8329_8321", (56, TyVarFree NoLoc Unlifted)), ("index_elem_8324_8329_8322", (56, TyVarFree NoLoc Unlifted)), ("kt_8324_8329_8323", (56, TyVarFree NoLoc Lifted)), ("t_8324_8329_8324", (56, TyVarRecord NoLoc (M.fromList [("left", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8324_8329_8323" 15791}) []))]))), ("num_8324_8329_8325", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8320_8320", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8325_8320_8321", (56, TyVarFree NoLoc Unlifted)), ("index_elem_8325_8320_8322", (56, TyVarFree NoLoc Unlifted)), ("t_8325_8320_8323", (57, TyVarFree NoLoc Lifted)), ("t_8325_8320_8324", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("update_elem_8325_8320_8325", (58, TyVarFree NoLoc Unlifted)), ("t_8325_8320_8326", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8325_8320_8327", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8321_8322", (59, TyVarFree NoLoc Lifted)), ("t_8325_8321_8323", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("num_8325_8321_8324", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("update_elem_8325_8321_8325", (60, TyVarFree NoLoc Unlifted)), ("t_8325_8321_8326", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8325_8321_8327", (56, TyVarFree NoLoc Unlifted)), ("index_elem_8325_8321_8328", (56, TyVarFree NoLoc Unlifted)), ("kt_8325_8321_8329", (56, TyVarFree NoLoc Lifted)), ("t_8325_8322_8320", (56, TyVarRecord NoLoc (M.fromList [("left", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8325_8321_8329" 15820}) []))]))), ("t_8325_8322_8323", (57, TyVarFree NoLoc Lifted)), ("t_8325_8322_8324", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8325_8322_8325", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8323_8320", (59, TyVarFree NoLoc Lifted)), ("t_8325_8323_8321", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("num_8325_8323_8322", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("update_elem_8325_8323_8323", (60, TyVarFree NoLoc Unlifted)), ("if_t_8325_8323_8324", (56, TyVarFree NoLoc SizeLifted)), ("t_8325_8323_8325", (56, TyVarFree NoLoc Unlifted)), ("t_8325_8323_8326", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8325_8323_8327", (56, TyVarFree NoLoc Unlifted)), ("index_elem_8325_8323_8328", (56, TyVarFree NoLoc Unlifted)), ("num_8325_8323_8329", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8324_8324", (56, TyVarFree NoLoc Unlifted)), ("t_8325_8324_8325", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8325_8324_8326", (56, TyVarFree NoLoc Unlifted)), ("index_elem_8325_8324_8327", (56, TyVarFree NoLoc Unlifted)), ("kt_8325_8324_8328", (56, TyVarFree NoLoc Lifted)), ("t_8325_8324_8329", (56, TyVarRecord NoLoc (M.fromList [("right", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8325_8324_8328" 15852}) []))]))), ("num_8325_8325_8320", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8325_8325", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8325_8325_8326", (56, TyVarFree NoLoc Unlifted)), ("index_elem_8325_8325_8327", (56, TyVarFree NoLoc Unlifted)), ("t_8325_8325_8328", (57, TyVarFree NoLoc Lifted)), ("t_8325_8325_8329", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("t_8325_8326_8320", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8326_8321", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8326_8322", (58, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8326_8323", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8325_8326_8324", (58, TyVarFree NoLoc Unlifted)), ("index_elem_8325_8326_8325", (58, TyVarFree NoLoc Unlifted)), ("kt_8325_8326_8326", (58, TyVarFree NoLoc Lifted)), ("t_8325_8326_8327", (58, TyVarRecord NoLoc (M.fromList [("left", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8325_8326_8326" 15871}) []))]))), ("num_8325_8326_8328", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8325_8327_8325", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("update_elem_8325_8328_8324", (58, TyVarFree NoLoc Unlifted)), ("t_8325_8328_8325", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8325_8328_8326", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8329_8321", (59, TyVarFree NoLoc Lifted)), ("t_8325_8329_8322", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("num_8325_8329_8323", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("update_elem_8325_8329_8324", (60, TyVarFree NoLoc Unlifted)), ("t_8325_8329_8325", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8325_8329_8326", (56, TyVarFree NoLoc Unlifted)), ("index_elem_8325_8329_8327", (56, TyVarFree NoLoc Unlifted)), ("kt_8325_8329_8328", (56, TyVarFree NoLoc Lifted)), ("t_8325_8329_8329", (56, TyVarRecord NoLoc (M.fromList [("right", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8325_8329_8328" 15909}) []))]))), ("t_8326_8320_8322", (57, TyVarFree NoLoc Lifted)), ("t_8326_8320_8323", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8326_8320_8324", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8326_8320_8329", (59, TyVarFree NoLoc Lifted)), ("t_8326_8321_8320", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("num_8326_8321_8321", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("update_elem_8326_8321_8322", (60, TyVarFree NoLoc Unlifted)), ("if_t_8326_8321_8323", (56, TyVarFree NoLoc SizeLifted)), ("t_8326_8321_8324", (56, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8326_8321_8325", (56, TyVarFree NoLoc Unlifted)), ("index_elem_8326_8321_8326", (56, TyVarFree NoLoc Unlifted)), ("kt_8326_8321_8327", (56, TyVarFree NoLoc Lifted)), ("t_8326_8321_8328", (56, TyVarRecord NoLoc (M.fromList [("parent", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8326_8321_8327" 15931}) []))]))), ("t_8326_8321_8329", (57, TyVarFree NoLoc Lifted)), ("t_8326_8322_8320", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8326_8322_8321", (58, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8326_8322_8326", (59, TyVarFree NoLoc Lifted)), ("t_8326_8322_8327", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("t_8326_8322_8328", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8326_8322_8329", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8326_8323_8320", (60, TyVarFree NoLoc Unlifted)), ("index_elem_8326_8323_8321", (60, TyVarFree NoLoc Unlifted)), ("num_8326_8323_8322", (60, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("update_elem_8326_8323_8327", (60, TyVarFree NoLoc Unlifted)), ("if_t_8326_8323_8328", (56, TyVarFree NoLoc SizeLifted)), ("if_t_8326_8323_8329", (56, TyVarFree NoLoc SizeLifted)), ("t_8326_8324_8320", (57, TyVarFree NoLoc Lifted)), ("t_8326_8324_8321", (57, TyVarFree NoLoc Lifted)), ("t_8326_8324_8322", (57, TyVarFree NoLoc Lifted)), ("t_8326_8324_8323", (57, TyVarFree NoLoc Lifted)), ("t_8326_8324_8324", (57, TyVarFree NoLoc Lifted)), ("if_t_8326_8324_8325", (48, TyVarFree NoLoc SizeLifted)), ("t_8326_8324_8326", (47, TyVarFree NoLoc Lifted)), ("t_8326_8325_8325", (18, TyVarFree NoLoc Lifted)), ("t_8326_8325_8325_8326_8325_8327", (18, TyVarFree NoLoc Lifted)), ("t_8322_8320_8326_8326_8325_8328", (16, TyVarFree NoLoc Lifted)), ("t_8326_8324_8326_8326_8325_8329", (47, TyVarFree NoLoc Lifted)), ("if_t_8326_8324_8325_8326_8326_8320", (48, TyVarFree NoLoc SizeLifted)), ("t_8324_8324_8326_8326_8326_8321", (47, TyVarFree NoLoc Lifted)), ("t_8326_8324_8320_8326_8326_8322", (57, TyVarFree NoLoc Lifted)), ("t_8324_8326_8325_8326_8326_8323", (56, TyVarFree NoLoc Lifted)), ("t_8324_8326_8326_8326_8326_8324", (56, TyVarFree NoLoc Lifted)), ("t_8326_8324_8321_8326_8326_8325", (57, TyVarFree NoLoc Lifted)), ("t_8324_8326_8323_8326_8326_8326", (53, TyVarFree NoLoc Lifted)), ("t_8327_8322_8326_8326_8327", (6, TyVarFree NoLoc Lifted)), ("t_8321_8325_8326_8326_8326_8328", (12, TyVarFree NoLoc Lifted)), ("b_8321_8328_8321_8326_8326_8329", (15, TyVarFree NoLoc Lifted)), ("a_8321_8328_8320_8326_8327_8320", (15, TyVarFree NoLoc Lifted)), ("t_8321_8327_8329_8326_8327_8321", (14, TyVarFree NoLoc Lifted)), ("t_8321_8327_8328_8326_8327_8322", (14, TyVarFree NoLoc Lifted)), ("a_8321_8325_8327_8326_8327_8323", (13, TyVarFree NoLoc Lifted)), ("t_8321_8321_8329_8326_8327_8324", (8, TyVarFree NoLoc Lifted)), ("b_8327_8324_8326_8327_8325", (7, TyVarFree NoLoc Lifted)), ("a_8327_8323_8326_8327_8326", (7, TyVarFree NoLoc Lifted)), ("b_8327_8326_8326_8327_8327", (7, TyVarFree NoLoc Lifted)), ("a_8327_8325_8326_8327_8328", (7, TyVarFree NoLoc Lifted))] + ), + ( [ "t_8320" ~ "t_8323", + "num_8324" ~ "t_8323", + "t_8323" ~ "f32", + "num_8329" ~ "f32", + "f32" ~ "f32", + "num_8321_8324" ~ "f32", + "t_8321_8329" ~ "f32", + "t_8321" ~ "t_8322_8320", + "num_8322_8321" ~ "t_8322_8320", + "t_8322_8320" ~ "f32", + "num_8322_8326" ~ "f32", + "f32" ~ "f32", + "num_8323_8321" ~ "f32", + "t_8323_8326" ~ "f32", + "t_8322" ~ "t_8323_8327", + "num_8323_8328" ~ "t_8323_8327", + "t_8323_8327" ~ "f32", + "num_8324_8323" ~ "f32", + "f32" ~ "f32", + "num_8324_8328" ~ "f32", + "t_8325_8323" ~ "f32", + "t_8321_8329" ~ "f32", + "u32" ~ "u32", + "t_8325_8328" ~ "u32", + "t_8323_8326" ~ "f32", + "u32" ~ "u32", + "t_8326_8323" ~ "u32", + "t_8325_8323" ~ "f32", + "u32" ~ "u32", + "t_8326_8328" ~ "u32", + "t_8325_8328" ~ "t_8327_8321", + "num_8327_8322" ~ "t_8327_8321", + "t_8326_8323" ~ "t_8327_8327", + "num_8327_8328" ~ "t_8327_8327", + "t_8327_8321" ~ "t_8327_8320", + "t_8327_8327" ~ "t_8327_8320", + "t_8327_8320" ~ "t_8326_8329", + "t_8326_8328" ~ "t_8326_8329", + "u32" ~ "t_8326_8329" + ], + M.empty, + M.fromList [("t_8320", (1, TyVarFree NoLoc Lifted)), ("t_8321", (1, TyVarFree NoLoc Lifted)), ("t_8322", (1, TyVarFree NoLoc Lifted)), ("t_8323", (2, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8324", (2, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8329", (2, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8324", (2, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8329", (3, TyVarFree NoLoc Lifted)), ("t_8322_8320", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8321", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8326", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8321", (4, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8326", (5, TyVarFree NoLoc Lifted)), ("t_8323_8327", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8328", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8324_8323", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8324_8328", (6, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8323", (7, TyVarFree NoLoc Lifted)), ("t_8325_8328", (9, TyVarFree NoLoc Lifted)), ("t_8326_8323", (11, TyVarFree NoLoc Lifted)), ("t_8326_8328", (13, TyVarFree NoLoc Lifted)), ("t_8326_8329", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8327_8320", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8327_8321", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8327_8322", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8327_8327", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8327_8328", (14, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64]))] + ), + ( [ "t_8323_8321_8325" ~ "[]t_8323_8321_8325_8323_8323_8326", + "t_8321_8325_8327" ~ "[]t_8321_8325_8327_8323_8323_8327", + "t_8322_8321_8328" ~ "[]t_8322_8321_8328_8323_8323_8328", + "t_8321_8327_8329" ~ "[]t_8321_8327_8329_8323_8323_8329", + "kt_8322_8326_8329" ~ "[]kt_8322_8326_8329_8323_8324_8320", + "kt_8322_8325_8324" ~ "[]kt_8322_8325_8324_8323_8324_8321", + "range_8322_8322_8327" ~ "[]range_8322_8322_8327_8323_8324_8322", + "t_8321_8327_8324" ~ "[]t_8321_8327_8324_8323_8324_8323", + "t_8321_8327_8321" ~ "[]t_8321_8327_8321_8323_8324_8324", + "ft_8324" ~ "ft_8326", + "a_8322" ~ "rt_8325", + "a_8322 -> b_8323" ~ "a_8320 -> x_8321", + "[]{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}" ~ "[]a_8320", + "[]x_8321" ~ "[]f32", + "t_8321_8323" ~ "f32", + "ft_8321_8328" ~ "ft_8322_8320", + "a_8321_8326" ~ "rt_8321_8329", + "a_8321_8326 -> b_8321_8327" ~ "a_8321_8324 -> x_8321_8325", + "[]{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}" ~ "[]a_8321_8324", + "[]x_8321_8325" ~ "[]f32", + "t_8322_8327" ~ "f32", + "ft_8323_8322" ~ "ft_8323_8324", + "a_8323_8320" ~ "rt_8323_8323", + "a_8323_8320 -> b_8323_8321" ~ "a_8322_8328 -> x_8322_8329", + "[]{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}" ~ "[]a_8322_8328", + "[]x_8322_8329" ~ "[]f32", + "t_8324_8321" ~ "f32", + "ft_8324_8326" ~ "ft_8324_8328", + "a_8324_8324" ~ "rt_8324_8327", + "a_8324_8324 -> b_8324_8325" ~ "a_8324_8322 -> x_8324_8323", + "[]{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}" ~ "[]a_8324_8322", + "[]x_8324_8323" ~ "[]f32", + "t_8325_8325" ~ "f32", + "ft_8326_8320" ~ "ft_8326_8322", + "a_8325_8328" ~ "rt_8326_8321", + "a_8325_8328 -> b_8325_8329" ~ "a_8325_8326 -> x_8325_8327", + "[]{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}" ~ "[]a_8325_8326", + "[]x_8325_8327" ~ "[]f32", + "t_8326_8329" ~ "f32", + "ft_8327_8324" ~ "ft_8327_8326", + "a_8327_8322" ~ "rt_8327_8325", + "a_8327_8322 -> b_8327_8323" ~ "a_8327_8320 -> x_8327_8321", + "[]{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}" ~ "[]a_8327_8320", + "[]x_8327_8321" ~ "[]f32", + "t_8328_8323" ~ "f32", + "t_8328_8324" ~ "t_8328_8328", + "t_8325_8325" ~ "t_8328_8328", + "t_8321_8323" ~ "t_8329_8323", + "t_8325_8325" ~ "t_8329_8323", + "t_8328_8328" ~ "t_8328_8327", + "t_8329_8323" ~ "t_8328_8327", + "t_8328_8325" ~ "t_8321_8320_8323", + "t_8326_8329" ~ "t_8321_8320_8323", + "t_8322_8327" ~ "t_8321_8320_8328", + "t_8326_8329" ~ "t_8321_8320_8328", + "t_8321_8320_8323" ~ "t_8321_8320_8322", + "t_8321_8320_8328" ~ "t_8321_8320_8322", + "t_8328_8326" ~ "t_8321_8321_8328", + "t_8328_8323" ~ "t_8321_8321_8328", + "t_8324_8321" ~ "t_8321_8322_8323", + "t_8328_8323" ~ "t_8321_8322_8323", + "t_8321_8321_8328" ~ "t_8321_8321_8327", + "t_8321_8322_8323" ~ "t_8321_8321_8327", + "{x: t_8328_8324, y: t_8328_8325, z: t_8328_8326} -> {x: t_8328_8327, y: t_8321_8320_8322, z: t_8321_8321_8327}" ~ "a_8321_8323_8322 -> b_8321_8323_8323", + "{x: f32, y: f32, z: f32} -> u32" ~ "b_8321_8323_8323 -> c_8321_8323_8324", + "t_8321_8323_8329" ~ "{x: a_8321_8323_8322} -> c_8321_8323_8324", + "t_8321_8324_8322" ~ "t_8321_8324_8324", + "t_8321_8323_8329" ~ "arg_8321_8324_8325 -> res_8321_8324_8326", + "kt_8321_8324_8323" ~ "arg_8321_8324_8325", + "{p: t_8321_8324_8322} -> res_8321_8324_8326" ~ "t_8321_8324_8320 -> k_8321_8324_8321", + "i32" ~ "i32", + "i32 -> u32 -> i32" ~ "i32 -> k_8321_8324_8321 -> i32", + "[]{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}" ~ "[]t_8321_8324_8320", + "t_8321_8325_8327" ~ "[]t_8321_8324_8320", + "t_8321_8326_8320" ~ "t_8321_8326_8322", + "t_8321_8323_8329" ~ "arg_8321_8326_8323 -> res_8321_8326_8324", + "kt_8321_8326_8321" ~ "arg_8321_8326_8323", + "{p: t_8321_8326_8320} -> res_8321_8326_8324" ~ "a_8321_8325_8328 -> x_8321_8325_8329", + "t_8321_8325_8327" ~ "[]a_8321_8325_8328", + "t_8321_8327_8321" ~ "[]x_8321_8325_8329", + "t_8321_8327_8321" ~ "[]u32", + "t_8321_8327_8324" ~ "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}", + "t_8321_8325_8327" ~ "[]{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}", + "t_8321_8327_8324" ~ "[]{delta_node: i32, left: #inner i32 | #leaf i32, parent: i32, right: #inner i32 | #leaf i32, sfc_code: u32}", + "t_8321_8327_8329" ~ "[]{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}", + "t_8321_8328_8321" ~ "num_8321_8328_8320", + "index_8321_8328_8322" ~ "index_elem_8321_8328_8323", + "t_8321_8327_8324" ~ "[]index_elem_8321_8328_8323", + "index_8321_8328_8322" ~ "t_8321_8328_8325", + "t_8321_8328_8326" ~ "kt_8321_8328_8324", + "i32" ~ "t_8321_8328_8328", + "num_8321_8328_8329" ~ "t_8321_8328_8328", + "t_8321_8328_8328" ~ "t_8321_8328_8327", + "t_8321_8328_8326" ~ "t_8321_8328_8327", + "t_8321_8329_8328" ~ "t_8321_8328_8327", + "t_8321_8329_8328" ~ "t_8322_8320_8321", + "num_8322_8320_8322" ~ "t_8322_8320_8321", + "t_8322_8320_8321" ~ "t_8322_8320_8320", + "num_8322_8320_8327" ~ "t_8322_8320_8320", + "t_8322_8320_8320" ~ "t_8321_8329_8329", + "num_8322_8321_8322" ~ "t_8321_8329_8329", + "t_8322_8321_8327" ~ "t_8321_8329_8329", + "t_8322_8321_8328" ~ "t_8321_8327_8329", + "t_8322_8321_8329" ~ "t_8322_8321_8327", + "t_8322_8321_8327" ~ "t_8322_8322_8320", + "num_8322_8322_8321" ~ "t_8322_8322_8320", + "t_8322_8321_8327" ~ "t_8322_8322_8320", + "t_8322_8321_8327" ~ "num_8322_8322_8326", + "range_8322_8322_8327" ~ "[]t_8322_8321_8327", + "range_8322_8322_8327" ~ "[]elem_8322_8322_8328", + "t_8322_8322_8329" ~ "elem_8322_8322_8328", + "{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}" ~ "t_8322_8323_8324", + "kt_8322_8323_8323" ~ "t_8322_8323_8322", + "t_8322_8322_8329" ~ "t_8322_8323_8322", + "t_8322_8324_8320" ~ "num_8322_8323_8329", + "{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}" ~ "t_8322_8324_8322", + "t_8322_8324_8323" ~ "kt_8322_8324_8321", + "(t_8322_8324_8324, t_8322_8324_8325)" ~ "(t_8322_8324_8323, t_8322_8324_8320)", + "t_8322_8324_8325" ~ "t_8322_8324_8327", + "num_8322_8324_8328" ~ "t_8322_8324_8327", + "{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}" ~ "t_8322_8325_8325", + "t_8322_8325_8326" ~ "t_8322_8324_8325", + "index_8322_8325_8327" ~ "index_elem_8322_8325_8328", + "kt_8322_8325_8324" ~ "[]index_elem_8322_8325_8328", + "t_8322_8326_8320" ~ "num_8322_8325_8329", + "index_8322_8325_8327" ~ "t_8322_8325_8323", + "num_8322_8325_8329" ~ "t_8322_8325_8323", + "bool" ~ "t_8322_8324_8326", + "bool" ~ "t_8322_8324_8326", + "{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}" ~ "t_8322_8327_8320", + "t_8322_8327_8321" ~ "t_8322_8324_8325", + "index_8322_8327_8322" ~ "index_elem_8322_8327_8323", + "kt_8322_8326_8329" ~ "[]index_elem_8322_8327_8323", + "t_8322_8327_8324" ~ "index_8322_8327_8322", + "index_8322_8327_8325" ~ "index_elem_8322_8327_8326", + "t_8322_8321_8328" ~ "[]index_elem_8322_8327_8326", + "index_8322_8327_8325" ~ "t_8322_8327_8328", + "t_8322_8327_8329" ~ "kt_8322_8327_8327", + "t_8322_8324_8324" ~ "t_8322_8328_8321", + "t_8322_8327_8329" ~ "t_8322_8328_8323", + "kt_8322_8328_8320" ~ "{x: f32, y: f32, z: f32}", + "kt_8322_8328_8322" ~ "{x: f32, y: f32, z: f32}", + "t_8322_8328_8328" ~ "{x: f32, y: f32, z: f32}", + "t_8322_8324_8324" ~ "t_8322_8329_8321", + "t_8322_8327_8329" ~ "t_8322_8329_8323", + "kt_8322_8329_8320" ~ "t_8322_8328_8329", + "kt_8322_8329_8322" ~ "t_8322_8328_8329", + "t_8322_8329_8328" ~ "t_8322_8328_8329", + "t_8322_8324_8324" ~ "t_8323_8320_8320", + "t_8322_8324_8325" ~ "t_8323_8320_8321", + "num_8323_8320_8322" ~ "t_8323_8320_8321", + "(t_8322_8324_8323, t_8322_8324_8320)" ~ "({mass: t_8322_8329_8328, position: t_8322_8328_8328, velocity: kt_8322_8329_8329}, t_8323_8320_8321)", + "(t_8323_8320_8327, t_8323_8320_8328)" ~ "(t_8322_8324_8324, t_8322_8324_8325)", + "{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}" ~ "ft_8323_8320_8329", + "bool" ~ "bool", + "{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}" ~ "if_t_8323_8321_8320", + "{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}" ~ "if_t_8323_8321_8320", + "{n: {body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}} -> if_t_8323_8321_8320" ~ "a_8322_8323_8320 -> x_8322_8323_8321", + "t_8322_8321_8328" ~ "[]a_8322_8323_8320", + "t_8321_8327_8329" ~ "[]x_8322_8323_8321", + "t_8323_8321_8325" ~ "t_8322_8321_8328", + "t_8321_8323" ~ "t_8323_8321_8327", + "t_8325_8325" ~ "t_8323_8321_8327", + "t_8323_8321_8327" ~ "et_8323_8321_8326", + "t_8322_8327" ~ "t_8323_8322_8322", + "t_8326_8329" ~ "t_8323_8322_8322", + "t_8323_8322_8322" ~ "et_8323_8321_8326", + "t_8324_8321" ~ "t_8323_8322_8327", + "t_8328_8323" ~ "t_8323_8322_8327", + "t_8323_8322_8327" ~ "et_8323_8321_8326", + "[]et_8323_8321_8326" ~ "[]f32", + "t_8323_8323_8324" ~ "f32", + "([]{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}, f32, i32, []{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32})}" ~ "(t_8323_8321_8325, t_8323_8323_8324, t_8321_8328_8326, t_8321_8325_8327)" + ], + M.empty, + M.fromList [("a_8320", (2, TyVarFree NoLoc Unlifted)), ("x_8321", (2, TyVarFree NoLoc Unlifted)), ("a_8322", (2, TyVarFree NoLoc Lifted)), ("b_8323", (2, TyVarFree NoLoc Lifted)), ("ft_8324", (2, TyVarFree NoLoc Lifted)), ("rt_8325", (2, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "ft_8324" 16341}) []))]))), ("ft_8326", (2, TyVarRecord NoLoc (M.fromList [("x", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "b_8323" 16340}) []))]))), ("t_8321_8323", (3, TyVarFree NoLoc Lifted)), ("a_8321_8324", (4, TyVarFree NoLoc Unlifted)), ("x_8321_8325", (4, TyVarFree NoLoc Unlifted)), ("a_8321_8326", (4, TyVarFree NoLoc Lifted)), ("b_8321_8327", (4, TyVarFree NoLoc Lifted)), ("ft_8321_8328", (4, TyVarFree NoLoc Lifted)), ("rt_8321_8329", (4, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "ft_8321_8328" 16361}) []))]))), ("ft_8322_8320", (4, TyVarRecord NoLoc (M.fromList [("y", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "b_8321_8327" 16360}) []))]))), ("t_8322_8327", (5, TyVarFree NoLoc Lifted)), ("a_8322_8328", (6, TyVarFree NoLoc Unlifted)), ("x_8322_8329", (6, TyVarFree NoLoc Unlifted)), ("a_8323_8320", (6, TyVarFree NoLoc Lifted)), ("b_8323_8321", (6, TyVarFree NoLoc Lifted)), ("ft_8323_8322", (6, TyVarFree NoLoc Lifted)), ("rt_8323_8323", (6, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "ft_8323_8322" 16381}) []))]))), ("ft_8323_8324", (6, TyVarRecord NoLoc (M.fromList [("z", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "b_8323_8321" 16380}) []))]))), ("t_8324_8321", (7, TyVarFree NoLoc Lifted)), ("a_8324_8322", (8, TyVarFree NoLoc Unlifted)), ("x_8324_8323", (8, TyVarFree NoLoc Unlifted)), ("a_8324_8324", (8, TyVarFree NoLoc Lifted)), ("b_8324_8325", (8, TyVarFree NoLoc Lifted)), ("ft_8324_8326", (8, TyVarFree NoLoc Lifted)), ("rt_8324_8327", (8, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "ft_8324_8326" 16401}) []))]))), ("ft_8324_8328", (8, TyVarRecord NoLoc (M.fromList [("x", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "b_8324_8325" 16400}) []))]))), ("t_8325_8325", (9, TyVarFree NoLoc Lifted)), ("a_8325_8326", (10, TyVarFree NoLoc Unlifted)), ("x_8325_8327", (10, TyVarFree NoLoc Unlifted)), ("a_8325_8328", (10, TyVarFree NoLoc Lifted)), ("b_8325_8329", (10, TyVarFree NoLoc Lifted)), ("ft_8326_8320", (10, TyVarFree NoLoc Lifted)), ("rt_8326_8321", (10, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "ft_8326_8320" 16421}) []))]))), ("ft_8326_8322", (10, TyVarRecord NoLoc (M.fromList [("y", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "b_8325_8329" 16420}) []))]))), ("t_8326_8329", (11, TyVarFree NoLoc Lifted)), ("a_8327_8320", (12, TyVarFree NoLoc Unlifted)), ("x_8327_8321", (12, TyVarFree NoLoc Unlifted)), ("a_8327_8322", (12, TyVarFree NoLoc Lifted)), ("b_8327_8323", (12, TyVarFree NoLoc Lifted)), ("ft_8327_8324", (12, TyVarFree NoLoc Lifted)), ("rt_8327_8325", (12, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "ft_8327_8324" 16441}) []))]))), ("ft_8327_8326", (12, TyVarRecord NoLoc (M.fromList [("z", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "b_8327_8323" 16440}) []))]))), ("t_8328_8323", (13, TyVarFree NoLoc Lifted)), ("t_8328_8324", (15, TyVarFree NoLoc Lifted)), ("t_8328_8325", (15, TyVarFree NoLoc Lifted)), ("t_8328_8326", (15, TyVarFree NoLoc Lifted)), ("t_8328_8327", (16, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8328_8328", (16, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8329_8323", (16, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8320_8322", (16, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8320_8323", (16, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8320_8328", (16, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8321_8327", (16, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8321_8328", (16, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8322_8323", (16, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("a_8321_8323_8322", (14, TyVarFree NoLoc Lifted)), ("b_8321_8323_8323", (14, TyVarFree NoLoc Lifted)), ("c_8321_8323_8324", (14, TyVarFree NoLoc Lifted)), ("t_8321_8323_8329", (15, TyVarFree NoLoc Lifted)), ("t_8321_8324_8320", (16, TyVarFree NoLoc Unlifted)), ("k_8321_8324_8321", (16, TyVarFree NoLoc Unlifted)), ("t_8321_8324_8322", (17, TyVarFree NoLoc Lifted)), ("kt_8321_8324_8323", (18, TyVarFree NoLoc Lifted)), ("t_8321_8324_8324", (18, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8324_8323" 16528}) []))]))), ("arg_8321_8324_8325", (18, TyVarFree NoLoc Lifted)), ("res_8321_8324_8326", (18, TyVarFree NoLoc Lifted)), ("t_8321_8325_8327", (17, TyVarFree NoLoc Lifted)), ("a_8321_8325_8328", (18, TyVarFree NoLoc Unlifted)), ("x_8321_8325_8329", (18, TyVarFree NoLoc Unlifted)), ("t_8321_8326_8320", (19, TyVarFree NoLoc Lifted)), ("kt_8321_8326_8321", (20, TyVarFree NoLoc Lifted)), ("t_8321_8326_8322", (20, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8326_8321" 16552}) []))]))), ("arg_8321_8326_8323", (20, TyVarFree NoLoc Lifted)), ("res_8321_8326_8324", (20, TyVarFree NoLoc Lifted)), ("t_8321_8327_8321", (19, TyVarFree NoLoc Lifted)), ("t_8321_8327_8324", (21, TyVarFree NoLoc Lifted)), ("t_8321_8327_8329", (23, TyVarFree NoLoc Lifted)), ("num_8321_8328_8320", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8328_8321", (24, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8321_8328_8322", (24, TyVarFree NoLoc Unlifted)), ("index_elem_8321_8328_8323", (24, TyVarFree NoLoc Unlifted)), ("kt_8321_8328_8324", (24, TyVarFree NoLoc Lifted)), ("t_8321_8328_8325", (24, TyVarRecord NoLoc (M.fromList [("delta_node", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8328_8324" 16585}) []))]))), ("t_8321_8328_8326", (25, TyVarFree NoLoc Lifted)), ("t_8321_8328_8327", (26, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8328_8328", (26, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321_8328_8329", (26, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8329_8328", (27, TyVarFree NoLoc Lifted)), ("t_8321_8329_8329", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320_8320", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320_8321", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8320_8322", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8320_8327", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8321_8322", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8321_8327", (29, TyVarFree NoLoc Lifted)), ("t_8322_8321_8328", (30, TyVarFree NoLoc Lifted)), ("t_8322_8321_8329", (30, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64])), ("t_8322_8322_8320", (30, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8322_8321", (30, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8322_8326", (30, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("range_8322_8322_8327", (30, TyVarFree NoLoc Unlifted)), ("elem_8322_8322_8328", (30, TyVarFree NoLoc Unlifted)), ("t_8322_8322_8329", (30, TyVarFree NoLoc Lifted)), ("a_8322_8323_8320", (30, TyVarFree NoLoc Unlifted)), ("x_8322_8323_8321", (30, TyVarFree NoLoc Unlifted)), ("t_8322_8323_8322", (32, TyVarFree NoLoc Unlifted)), ("kt_8322_8323_8323", (32, TyVarFree NoLoc Lifted)), ("t_8322_8323_8324", (32, TyVarRecord NoLoc (M.fromList [("tree_level", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8323_8323" 16643}) []))]))), ("num_8322_8323_8329", (32, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8324_8320", (33, TyVarFree NoLoc Lifted)), ("kt_8322_8324_8321", (34, TyVarFree NoLoc Lifted)), ("t_8322_8324_8322", (34, TyVarRecord NoLoc (M.fromList [("body", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8324_8321" 16654}) []))]))), ("t_8322_8324_8323", (35, TyVarFree NoLoc Lifted)), ("t_8322_8324_8324", (36, TyVarFree NoLoc Lifted)), ("t_8322_8324_8325", (36, TyVarFree NoLoc Lifted)), ("t_8322_8324_8326", (36, TyVarPrim NoLoc [Bool])), ("t_8322_8324_8327", (36, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8324_8328", (36, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8325_8323", (36, TyVarFree NoLoc Unlifted)), ("kt_8322_8325_8324", (36, TyVarFree NoLoc Lifted)), ("t_8322_8325_8325", (36, TyVarRecord NoLoc (M.fromList [("children", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8325_8324" 16669}) []))]))), ("t_8322_8325_8326", (36, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8322_8325_8327", (36, TyVarFree NoLoc Unlifted)), ("index_elem_8322_8325_8328", (36, TyVarFree NoLoc Unlifted)), ("num_8322_8325_8329", (36, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8326_8320", (36, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8322_8326_8329", (36, TyVarFree NoLoc Lifted)), ("t_8322_8327_8320", (36, TyVarRecord NoLoc (M.fromList [("children", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8326_8329" 16687}) []))]))), ("t_8322_8327_8321", (36, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8322_8327_8322", (36, TyVarFree NoLoc Unlifted)), ("index_elem_8322_8327_8323", (36, TyVarFree NoLoc Unlifted)), ("t_8322_8327_8324", (36, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8322_8327_8325", (36, TyVarFree NoLoc Unlifted)), ("index_elem_8322_8327_8326", (36, TyVarFree NoLoc Unlifted)), ("kt_8322_8327_8327", (36, TyVarFree NoLoc Lifted)), ("t_8322_8327_8328", (36, TyVarRecord NoLoc (M.fromList [("body", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8327_8327" 16695}) []))]))), ("t_8322_8327_8329", (37, TyVarFree NoLoc Lifted)), ("kt_8322_8328_8320", (38, TyVarFree NoLoc Lifted)), ("t_8322_8328_8321", (38, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8328_8320" 16698}) []))]))), ("kt_8322_8328_8322", (38, TyVarFree NoLoc Lifted)), ("t_8322_8328_8323", (38, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8328_8322" 16700}) []))]))), ("t_8322_8328_8328", (39, TyVarFree NoLoc Lifted)), ("t_8322_8328_8329", (40, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8322_8329_8320", (40, TyVarFree NoLoc Lifted)), ("t_8322_8329_8321", (40, TyVarRecord NoLoc (M.fromList [("mass", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8329_8320" 16709}) []))]))), ("kt_8322_8329_8322", (40, TyVarFree NoLoc Lifted)), ("t_8322_8329_8323", (40, TyVarRecord NoLoc (M.fromList [("mass", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8329_8322" 16711}) []))]))), ("t_8322_8329_8328", (41, TyVarFree NoLoc Lifted)), ("kt_8322_8329_8329", (42, TyVarFree NoLoc Lifted)), ("t_8323_8320_8320", (42, TyVarRecord NoLoc (M.fromList [("velocity", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8329_8329" 16719}) []))]))), ("t_8323_8320_8321", (42, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8320_8322", (42, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8320_8327", (37, TyVarFree NoLoc Lifted)), ("t_8323_8320_8328", (37, TyVarFree NoLoc Lifted)), ("ft_8323_8320_8329", (38, TyVarRecord NoLoc (M.fromList [("body", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "t_8323_8320_8327" 16731}) []))]))), ("if_t_8323_8321_8320", (32, TyVarFree NoLoc SizeLifted)), ("t_8323_8321_8325", (27, TyVarFree NoLoc Lifted)), ("et_8323_8321_8326", (28, TyVarFree NoLoc Unlifted)), ("t_8323_8321_8327", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8322_8322", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8322_8327", (28, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8323_8324", (29, TyVarFree NoLoc Lifted)), ("t_8323_8321_8325_8323_8323_8326", (27, TyVarFree NoLoc Lifted)), ("t_8321_8325_8327_8323_8323_8327", (17, TyVarFree NoLoc Lifted)), ("t_8322_8321_8328_8323_8323_8328", (30, TyVarFree NoLoc Lifted)), ("t_8321_8327_8329_8323_8323_8329", (23, TyVarFree NoLoc Lifted)), ("kt_8322_8326_8329_8323_8324_8320", (36, TyVarFree NoLoc Lifted)), ("kt_8322_8325_8324_8323_8324_8321", (36, TyVarFree NoLoc Lifted)), ("range_8322_8322_8327_8323_8324_8322", (30, TyVarFree NoLoc Unlifted)), ("t_8321_8327_8324_8323_8324_8323", (21, TyVarFree NoLoc Lifted)), ("t_8321_8327_8321_8323_8324_8324", (19, TyVarFree NoLoc Lifted))] + ), + ( [ "t_8322_8326_8324" ~ "[]t_8322_8326_8324_8323_8322_8320", + "a_8322_8326_8325" ~ "[]a_8322_8326_8325_8323_8322_8321", + "kt_8322_8326_8322" ~ "[]kt_8322_8326_8322_8323_8322_8322", + "kt_8329_8321" ~ "[]kt_8329_8321_8323_8322_8323", + "kt_8326_8328" ~ "[]kt_8326_8328_8323_8322_8324", + "kt_8324_8324" ~ "[]kt_8324_8324_8323_8322_8325", + "t_8322" ~ "num_8321", + "(t_8324, t_8325, t_8326, t_8327)" ~ "({x: f32, y: f32, z: f32}, num_8320, num_8321, num_8323)", + "t_8327" ~ "t_8328", + "num_8329" ~ "t_8328", + "t_8321_8327" ~ "num_8321_8326", + "t_8326" ~ "t_8321_8325", + "num_8321_8326" ~ "t_8321_8325", + "t_8322_8323" ~ "t_8326", + "index_8322_8324" ~ "index_elem_8322_8325", + "[]{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}" ~ "[]index_elem_8322_8325", + "index_8322_8324" ~ "t_8322_8327", + "kt_8322_8326" ~ "t_8322_8322", + "t_8325" ~ "t_8322_8322", + "bool" ~ "t_8321_8324", + "bool" ~ "t_8321_8324", + "t_8323_8326" ~ "t_8321_8324", + "t_8323_8327" ~ "t_8325", + "index_8323_8328" ~ "index_elem_8323_8329", + "[]{body: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}, children: []i32, is_leaf: bool, parent: i32, tree_level: i32}" ~ "[]index_elem_8323_8329", + "t_8324_8320" ~ "index_8323_8328", + "t_8324_8322" ~ "num_8324_8321", + "t_8324_8320" ~ "t_8324_8325", + "t_8324_8326" ~ "t_8324_8322", + "index_8324_8327" ~ "index_elem_8324_8328", + "kt_8324_8324" ~ "[]index_elem_8324_8328", + "index_8324_8327" ~ "t_8324_8323", + "t_8326" ~ "t_8324_8323", + "t_8324_8322" ~ "t_8325_8323", + "num_8325_8324" ~ "t_8325_8323", + "num_8324_8321" ~ "t_8325_8323", + "t_8325_8329" ~ "t_8324_8322", + "t_8325_8329" ~ "t_8326_8321", + "num_8326_8322" ~ "t_8326_8321", + "t_8324_8320" ~ "t_8326_8329", + "t_8325_8329" ~ "t_8327_8320", + "num_8327_8321" ~ "t_8327_8320", + "t_8327_8326" ~ "t_8327_8320", + "index_8327_8327" ~ "index_elem_8327_8328", + "kt_8326_8328" ~ "[]index_elem_8327_8328", + "t_8328_8320" ~ "num_8327_8329", + "index_8327_8327" ~ "t_8326_8327", + "num_8327_8329" ~ "t_8326_8327", + "bool" ~ "t_8326_8320", + "bool" ~ "t_8326_8320", + "t_8324_8320" ~ "t_8329_8320", + "t_8324_8320" ~ "t_8329_8322", + "t_8325_8329" ~ "t_8329_8323", + "num_8329_8324" ~ "t_8329_8323", + "t_8329_8329" ~ "t_8329_8323", + "index_8321_8320_8320" ~ "index_elem_8321_8320_8321", + "kt_8329_8321" ~ "[]index_elem_8321_8320_8321", + "t_8326_8320" ~ "bool", + "kt_8328_8329" ~ "if_t_8321_8320_8322", + "index_8321_8320_8320" ~ "if_t_8321_8320_8322", + "t_8321_8320_8323" ~ "if_t_8321_8320_8322", + "t_8324_8320" ~ "t_8321_8320_8327", + "i32" ~ "t_8321_8320_8325", + "kt_8321_8320_8326" ~ "t_8321_8320_8325", + "t_8321_8320_8325" ~ "i32", + "f32" ~ "t_8321_8320_8324", + "f32" ~ "t_8321_8320_8324", + "t_8321_8321_8328" ~ "t_8321_8320_8324", + "t_8324_8320" ~ "t_8321_8322_8320", + "kt_8321_8321_8329" ~ "t_8321_8322_8322", + "t_8321_8322_8323" ~ "kt_8321_8322_8321", + "t_8324_8320" ~ "t_8321_8322_8325", + "kt_8321_8322_8324" ~ "t_8321_8322_8327", + "t_8321_8322_8328" ~ "kt_8321_8322_8326", + "f32" ~ "t_8321_8322_8329", + "t_8321_8322_8328" ~ "t_8321_8322_8329", + "t_8321_8322_8329" ~ "f32", + "t_8321_8322_8323" ~ "{x: f32, y: f32, z: f32}", + "t_8321_8323_8328" ~ "{x: f32, y: f32, z: f32}", + "{mass: f32, position: {x: f32, y: f32, z: f32}}" ~ "t_8321_8324_8320", + "t_8321_8324_8321" ~ "kt_8321_8323_8329", + "t_8321_8324_8321" ~ "t_8321_8324_8324", + "t_8321_8323_8328" ~ "t_8321_8324_8326", + "kt_8321_8324_8323" ~ "t_8321_8324_8322", + "kt_8321_8324_8325" ~ "t_8321_8324_8322", + "t_8321_8325_8321" ~ "t_8321_8324_8322", + "t_8321_8324_8321" ~ "t_8321_8325_8324", + "t_8321_8323_8328" ~ "t_8321_8325_8326", + "kt_8321_8325_8323" ~ "t_8321_8325_8322", + "kt_8321_8325_8325" ~ "t_8321_8325_8322", + "t_8321_8326_8321" ~ "t_8321_8325_8322", + "t_8321_8324_8321" ~ "t_8321_8326_8324", + "t_8321_8323_8328" ~ "t_8321_8326_8326", + "kt_8321_8326_8323" ~ "t_8321_8326_8322", + "kt_8321_8326_8325" ~ "t_8321_8326_8322", + "t_8321_8327_8321" ~ "t_8321_8326_8322", + "t_8321_8325_8321" ~ "t_8321_8327_8324", + "t_8321_8325_8321" ~ "t_8321_8327_8324", + "t_8321_8326_8321" ~ "t_8321_8327_8329", + "t_8321_8326_8321" ~ "t_8321_8327_8329", + "t_8321_8327_8324" ~ "t_8321_8327_8323", + "t_8321_8327_8329" ~ "t_8321_8327_8323", + "t_8321_8327_8321" ~ "t_8321_8328_8328", + "t_8321_8327_8321" ~ "t_8321_8328_8328", + "t_8321_8327_8323" ~ "t_8321_8327_8322", + "t_8321_8328_8328" ~ "t_8321_8327_8322", + "t_8321_8329_8327" ~ "t_8321_8327_8322", + "t_8321_8329_8327" ~ "f32", + "t_8321_8321_8328" ~ "t_8321_8329_8328", + "f32" ~ "t_8321_8329_8328", + "t_8322_8320_8325" ~ "t_8321_8329_8328", + "i32" ~ "t_8322_8320_8328", + "num_8322_8320_8329" ~ "t_8322_8320_8328", + "t_8324_8320" ~ "t_8322_8321_8325", + "t_8322_8320_8328" ~ "t_8322_8320_8327", + "kt_8322_8321_8324" ~ "t_8322_8320_8327", + "t_8322_8320_8327" ~ "t_8322_8320_8326", + "num_8322_8322_8320" ~ "t_8322_8320_8326", + "t_8322_8322_8325" ~ "bool", + "t_8324_8320" ~ "t_8322_8322_8329", + "kt_8322_8322_8328" ~ "t_8322_8322_8327", + "t_8322_8322_8325" ~ "t_8322_8322_8327", + "t_8322_8320_8325" ~ "t_8322_8323_8324", + "f32" ~ "t_8322_8323_8324", + "t_8322_8322_8327" ~ "t_8322_8322_8326", + "bool" ~ "t_8322_8322_8326", + "f32" ~ "f32", + "{mass: f32, position: {x: f32, y: f32, z: f32}}" ~ "{mass: f32, position: {x: f32, y: f32, z: f32}}", + "{mass: t_8321_8322_8328, position: t_8321_8323_8328}" ~ "{mass: f32, position: {x: f32, y: f32, z: f32}}", + "t_8322_8324_8329" ~ "{x: f32, y: f32, z: f32}", + "t_8324" ~ "{x: f32, y: f32, z: f32}", + "t_8322_8324_8329" ~ "{x: f32, y: f32, z: f32}", + "t_8324_8320" ~ "t_8322_8325_8325", + "t_8327" ~ "t_8322_8325_8326", + "num_8322_8325_8327" ~ "t_8322_8325_8326", + "t_8324_8320" ~ "t_8322_8326_8323", + "t_8322_8326_8324" ~ "kt_8322_8326_8322", + "t_8322_8327_8324" ~ "t_8322_8327_8322", + "num_8322_8327_8323" ~ "t_8322_8327_8322", + "bool -> i32" ~ "b_8322_8327_8320 -> c_8322_8327_8321", + "t_8322_8327_8324 -> bool" ~ "a_8322_8326_8329 -> b_8322_8327_8320", + "{x: a_8322_8326_8329} -> c_8322_8327_8321" ~ "a_8322_8326_8327 -> x_8322_8326_8328", + "t_8322_8326_8324" ~ "[]a_8322_8326_8327", + "t_8322_8328_8328 -> t_8322_8328_8328 -> t_8322_8328_8328" ~ "a_8322_8328_8327 -> a_8322_8328_8327 -> a_8322_8328_8327", + "num_8322_8328_8329" ~ "a_8322_8328_8327", + "[]x_8322_8326_8328" ~ "a_8322_8326_8325", + "{as: []a_8322_8328_8327} -> a_8322_8328_8327" ~ "a_8322_8326_8325 -> b_8322_8326_8326", + "t_8322_8329_8328" ~ "b_8322_8326_8326", + "t_8323_8320_8320" ~ "num_8322_8329_8329", + "index_8323_8320_8321" ~ "index_elem_8323_8320_8322", + "t_8322_8326_8324" ~ "[]index_elem_8323_8320_8322", + "t_8327" ~ "t_8323_8320_8324", + "t_8322_8329_8328" ~ "t_8323_8320_8324", + "t_8323_8320_8324" ~ "t_8323_8320_8323", + "num_8323_8320_8329" ~ "t_8323_8320_8323", + "t_8322_8322_8326" ~ "bool", + "({x: f32, y: f32, z: f32}, kt_8322_8325_8324, t_8325, t_8322_8325_8326)" ~ "if_t_8323_8321_8324", + "(t_8324, index_8323_8320_8321, t_8325, t_8323_8320_8323)" ~ "if_t_8323_8321_8324", + "t_8323_8326" ~ "bool", + "(t_8324, t_8321_8320_8323, t_8325, t_8327)" ~ "if_t_8323_8321_8325", + "if_t_8323_8321_8324" ~ "if_t_8323_8321_8325", + "({x: f32, y: f32, z: f32}, num_8320, num_8321, num_8323)" ~ "if_t_8323_8321_8325", + "(t_8323_8321_8326, t_8323_8321_8327, t_8323_8321_8328, t_8323_8321_8329)" ~ "(t_8324, t_8325, t_8326, t_8327)", + "{x: f32, y: f32, z: f32}" ~ "t_8323_8321_8326" + ], + M.empty, + M.fromList [("num_8320", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8321", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324", (5, TyVarFree NoLoc Lifted)), ("t_8325", (5, TyVarFree NoLoc Lifted)), ("t_8326", (5, TyVarFree NoLoc Lifted)), ("t_8327", (5, TyVarFree NoLoc Lifted)), ("t_8328", (5, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8329", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8324", (5, TyVarPrim NoLoc [Bool])), ("t_8321_8325", (5, TyVarFree NoLoc Unlifted)), ("num_8321_8326", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8327", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8322", (5, TyVarFree NoLoc Unlifted)), ("t_8322_8323", (5, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8322_8324", (5, TyVarFree NoLoc Unlifted)), ("index_elem_8322_8325", (5, TyVarFree NoLoc Unlifted)), ("kt_8322_8326", (5, TyVarFree NoLoc Lifted)), ("t_8322_8327", (5, TyVarRecord NoLoc (M.fromList [("parent", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8326" 17047}) []))]))), ("t_8323_8326", (6, TyVarFree NoLoc Lifted)), ("t_8323_8327", (7, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8323_8328", (7, TyVarFree NoLoc Unlifted)), ("index_elem_8323_8329", (7, TyVarFree NoLoc Unlifted)), ("t_8324_8320", (8, TyVarFree NoLoc Lifted)), ("num_8324_8321", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8324_8322", (9, TyVarFree NoLoc Lifted)), ("t_8324_8323", (9, TyVarFree NoLoc Unlifted)), ("kt_8324_8324", (9, TyVarFree NoLoc Lifted)), ("t_8324_8325", (9, TyVarRecord NoLoc (M.fromList [("children", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8324_8324" 17068}) []))]))), ("t_8324_8326", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8324_8327", (9, TyVarFree NoLoc Unlifted)), ("index_elem_8324_8328", (9, TyVarFree NoLoc Unlifted)), ("t_8325_8323", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8325_8324", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8325_8329", (10, TyVarFree NoLoc Lifted)), ("t_8326_8320", (11, TyVarPrim NoLoc [Bool])), ("t_8326_8321", (11, TyVarFree NoLoc Unlifted)), ("num_8326_8322", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8326_8327", (11, TyVarFree NoLoc Unlifted)), ("kt_8326_8328", (11, TyVarFree NoLoc Lifted)), ("t_8326_8329", (11, TyVarRecord NoLoc (M.fromList [("children", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8326_8328" 17095}) []))]))), ("t_8327_8320", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8327_8321", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8327_8326", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8327_8327", (11, TyVarFree NoLoc Unlifted)), ("index_elem_8327_8328", (11, TyVarFree NoLoc Unlifted)), ("num_8327_8329", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8328_8320", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8328_8329", (11, TyVarFree NoLoc Lifted)), ("t_8329_8320", (11, TyVarRecord NoLoc (M.fromList [("parent", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8328_8329" 17119}) []))]))), ("kt_8329_8321", (11, TyVarFree NoLoc Lifted)), ("t_8329_8322", (11, TyVarRecord NoLoc (M.fromList [("children", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8329_8321" 17121}) []))]))), ("t_8329_8323", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8329_8324", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8329_8329", (11, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8321_8320_8320", (11, TyVarFree NoLoc Unlifted)), ("index_elem_8321_8320_8321", (11, TyVarFree NoLoc Unlifted)), ("if_t_8321_8320_8322", (11, TyVarFree NoLoc SizeLifted)), ("t_8321_8320_8323", (12, TyVarFree NoLoc Lifted)), ("t_8321_8320_8324", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8320_8325", (9, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8321_8320_8326", (9, TyVarFree NoLoc Lifted)), ("t_8321_8320_8327", (9, TyVarRecord NoLoc (M.fromList [("tree_level", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8320_8326" 17137}) []))]))), ("t_8321_8321_8328", (10, TyVarFree NoLoc Lifted)), ("kt_8321_8321_8329", (11, TyVarFree NoLoc Lifted)), ("t_8321_8322_8320", (11, TyVarRecord NoLoc (M.fromList [("body", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8321_8329" 17153}) []))]))), ("kt_8321_8322_8321", (11, TyVarFree NoLoc Lifted)), ("t_8321_8322_8322", (11, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8322_8321" 17155}) []))]))), ("t_8321_8322_8323", (12, TyVarFree NoLoc Lifted)), ("kt_8321_8322_8324", (13, TyVarFree NoLoc Lifted)), ("t_8321_8322_8325", (13, TyVarRecord NoLoc (M.fromList [("body", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8322_8324" 17158}) []))]))), ("kt_8321_8322_8326", (13, TyVarFree NoLoc Lifted)), ("t_8321_8322_8327", (13, TyVarRecord NoLoc (M.fromList [("mass", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8322_8326" 17160}) []))]))), ("t_8321_8322_8328", (14, TyVarFree NoLoc Lifted)), ("t_8321_8322_8329", (15, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8323_8328", (16, TyVarFree NoLoc Lifted)), ("kt_8321_8323_8329", (17, TyVarFree NoLoc Lifted)), ("t_8321_8324_8320", (17, TyVarRecord NoLoc (M.fromList [("position", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8323_8329" 17175}) []))]))), ("t_8321_8324_8321", (18, TyVarFree NoLoc Lifted)), ("t_8321_8324_8322", (19, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8321_8324_8323", (19, TyVarFree NoLoc Lifted)), ("t_8321_8324_8324", (19, TyVarRecord NoLoc (M.fromList [("x", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8324_8323" 17179}) []))]))), ("kt_8321_8324_8325", (19, TyVarFree NoLoc Lifted)), ("t_8321_8324_8326", (19, TyVarRecord NoLoc (M.fromList [("x", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8324_8325" 17181}) []))]))), ("t_8321_8325_8321", (20, TyVarFree NoLoc Lifted)), ("t_8321_8325_8322", (21, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8321_8325_8323", (21, TyVarFree NoLoc Lifted)), ("t_8321_8325_8324", (21, TyVarRecord NoLoc (M.fromList [("y", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8325_8323" 17190}) []))]))), ("kt_8321_8325_8325", (21, TyVarFree NoLoc Lifted)), ("t_8321_8325_8326", (21, TyVarRecord NoLoc (M.fromList [("y", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8325_8325" 17192}) []))]))), ("t_8321_8326_8321", (22, TyVarFree NoLoc Lifted)), ("t_8321_8326_8322", (23, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8321_8326_8323", (23, TyVarFree NoLoc Lifted)), ("t_8321_8326_8324", (23, TyVarRecord NoLoc (M.fromList [("z", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8326_8323" 17201}) []))]))), ("kt_8321_8326_8325", (23, TyVarFree NoLoc Lifted)), ("t_8321_8326_8326", (23, TyVarRecord NoLoc (M.fromList [("z", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8321_8326_8325" 17203}) []))]))), ("t_8321_8327_8321", (24, TyVarFree NoLoc Lifted)), ("t_8321_8327_8322", (25, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8327_8323", (25, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8327_8324", (25, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8327_8329", (25, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8328_8328", (25, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321_8329_8327", (20, TyVarFree NoLoc Lifted)), ("t_8321_8329_8328", (21, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320_8325", (22, TyVarFree NoLoc Lifted)), ("t_8322_8320_8326", (23, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320_8327", (23, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8320_8328", (23, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8320_8329", (23, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8322_8321_8324", (23, TyVarFree NoLoc Lifted)), ("t_8322_8321_8325", (23, TyVarRecord NoLoc (M.fromList [("tree_level", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8321_8324" 17264}) []))]))), ("num_8322_8322_8320", (23, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8322_8325", (24, TyVarFree NoLoc Lifted)), ("t_8322_8322_8326", (25, TyVarPrim NoLoc [Bool])), ("t_8322_8322_8327", (25, TyVarPrim NoLoc [Bool])), ("kt_8322_8322_8328", (25, TyVarFree NoLoc Lifted)), ("t_8322_8322_8329", (25, TyVarRecord NoLoc (M.fromList [("is_leaf", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8322_8328" 17280}) []))]))), ("t_8322_8323_8324", (25, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8324_8329", (26, TyVarFree NoLoc Lifted)), ("kt_8322_8325_8324", (27, TyVarFree NoLoc Lifted)), ("t_8322_8325_8325", (27, TyVarRecord NoLoc (M.fromList [("parent", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8325_8324" 17311}) []))]))), ("t_8322_8325_8326", (27, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8325_8327", (27, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("kt_8322_8326_8322", (25, TyVarFree NoLoc Lifted)), ("t_8322_8326_8323", (25, TyVarRecord NoLoc (M.fromList [("children", Scalar (TypeVar NoUniqueness (QualName {qualQuals = [], qualLeaf = VName "kt_8322_8326_8322" 17322}) []))]))), ("t_8322_8326_8324", (26, TyVarFree NoLoc Lifted)), ("a_8322_8326_8325", (27, TyVarFree NoLoc Lifted)), ("b_8322_8326_8326", (27, TyVarFree NoLoc Lifted)), ("a_8322_8326_8327", (27, TyVarFree NoLoc Unlifted)), ("x_8322_8326_8328", (27, TyVarFree NoLoc Unlifted)), ("a_8322_8326_8329", (27, TyVarFree NoLoc Lifted)), ("b_8322_8327_8320", (27, TyVarFree NoLoc Lifted)), ("c_8322_8327_8321", (27, TyVarFree NoLoc Lifted)), ("t_8322_8327_8322", (27, TyVarPrim NoLoc [Bool, Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8327_8323", (27, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8327_8324", (27, TyVarFree NoLoc Lifted)), ("a_8322_8328_8327", (27, TyVarFree NoLoc Unlifted)), ("t_8322_8328_8328", (27, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8322_8328_8329", (27, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8322_8329_8328", (28, TyVarFree NoLoc Lifted)), ("num_8322_8329_8329", (29, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8320_8320", (29, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), ("index_8323_8320_8321", (29, TyVarFree NoLoc Unlifted)), ("index_elem_8323_8320_8322", (29, TyVarFree NoLoc Unlifted)), ("t_8323_8320_8323", (29, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8323_8320_8324", (29, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("num_8323_8320_8329", (29, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), ("if_t_8323_8321_8324", (25, TyVarFree NoLoc SizeLifted)), ("if_t_8323_8321_8325", (9, TyVarFree NoLoc SizeLifted)), ("t_8323_8321_8326", (6, TyVarFree NoLoc Lifted)), ("t_8323_8321_8327", (6, TyVarFree NoLoc Lifted)), ("t_8323_8321_8328", (6, TyVarFree NoLoc Lifted)), ("t_8323_8321_8329", (6, TyVarFree NoLoc Lifted)), ("t_8322_8326_8324_8323_8322_8320", (26, TyVarFree NoLoc Lifted)), ("a_8322_8326_8325_8323_8322_8321", (27, TyVarFree NoLoc Lifted)), ("kt_8322_8326_8322_8323_8322_8322", (25, TyVarFree NoLoc Lifted)), ("kt_8329_8321_8323_8322_8323", (11, TyVarFree NoLoc Lifted)), ("kt_8326_8328_8323_8322_8324", (11, TyVarFree NoLoc Lifted)), ("kt_8324_8324_8323_8322_8325", (9, TyVarFree NoLoc Lifted))] + ), + ( [ "t_8326_8327" ~ "[]t_8326_8327_8327_8328", + "t_8326_8328" ~ "[]t_8326_8328_8327_8329", + "t_8326_8329" ~ "[]t_8326_8329_8328_8320", + "t_8326_8320" ~ "[]t_8326_8320_8328_8321", + "t_8327_8325" ~ "[]t_8327_8325_8328_8322", + "t_8327_8326" ~ "[]t_8327_8326_8328_8323", + "t_8327_8327" ~ "[]t_8327_8327_8328_8324", + "t_8326_8321" ~ "[]t_8326_8321_8328_8325", + "t_8325_8329" ~ "[]t_8325_8329_8328_8326", + "a_8324_8324" ~ "[]a_8324_8324_8328_8327", + "t_8324_8323" ~ "[]t_8324_8323_8328_8328", + "t_8323_8322" ~ "[]t_8323_8322_8328_8329", + "t_8321" ~ "float_8320", + "[]f32" ~ "[]a_8326", + "[]f32" ~ "[]b_8327", + "[]f32" ~ "[]c_8328", + "[]f32" ~ "[]a_8321_8325", + "[]f32" ~ "[]b_8321_8326", + "[]f32" ~ "[]c_8321_8327", + "(f32, f32, f32) -> {mass: f32} -> (f32, f32, f32) -> {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}" ~ "a_8322 -> b_8323 -> c_8324 -> x_8325", + "[](a_8326, b_8327, c_8328)" ~ "[]a_8322", + "[]f32" ~ "[]b_8323", + "[](a_8321_8325, b_8321_8326, c_8321_8327)" ~ "[]c_8324", + "t_8323_8322" ~ "[]x_8325", + "i32" ~ "i32", + "t_8321" ~ "f32", + "f32" ~ "f32", + "f32" ~ "f32", + "t_8323_8322" ~ "[]{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}", + "t_8324_8323" ~ "[]{mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}", + "{b: {mass: f32, position: {x: f32, y: f32, z: f32}, velocity: {x: f32, y: f32, z: f32}}} -> ((f32, f32, f32), f32, (f32, f32, f32))" ~ "a_8324_8326 -> x_8324_8327", + "t_8324_8323" ~ "[]a_8324_8326", + "[]x_8324_8327" ~ "a_8324_8324", + "{xs: [](a_8325_8322, b_8325_8323, c_8325_8324)} -> ([]a_8325_8322, []b_8325_8323, []c_8325_8324)" ~ "a_8324_8324 -> b_8324_8325", + "(t_8325_8329, t_8326_8320, t_8326_8321)" ~ "b_8324_8325", + "t_8325_8329" ~ "[](a_8326_8322, b_8326_8323, c_8326_8324)", + "(t_8326_8327, t_8326_8328, t_8326_8329)" ~ "([]a_8326_8322, []b_8326_8323, []c_8326_8324)", + "t_8326_8321" ~ "[](a_8327_8320, b_8327_8321, c_8327_8322)", + "(t_8327_8325, t_8327_8326, t_8327_8327)" ~ "([]a_8327_8320, []b_8327_8321, []c_8327_8322)", + "([]f32, []f32, []f32, []f32, []f32, []f32, []f32)" ~ "(t_8326_8327, t_8326_8328, t_8326_8329, t_8326_8320, t_8327_8325, t_8327_8326, t_8327_8327)" + ], + M.empty, + M.fromList [("float_8320", (11, TyVarPrim NoLoc [FloatType Float16, FloatType Float32, FloatType Float64])), ("t_8321", (12, TyVarFree NoLoc Lifted)), ("a_8322", (13, TyVarFree NoLoc Unlifted)), ("b_8323", (13, TyVarFree NoLoc Unlifted)), ("c_8324", (13, TyVarFree NoLoc Unlifted)), ("x_8325", (13, TyVarFree NoLoc Unlifted)), ("a_8326", (13, TyVarFree NoLoc Unlifted)), ("b_8327", (13, TyVarFree NoLoc Unlifted)), ("c_8328", (13, TyVarFree NoLoc Unlifted)), ("a_8321_8325", (13, TyVarFree NoLoc Unlifted)), ("b_8321_8326", (13, TyVarFree NoLoc Unlifted)), ("c_8321_8327", (13, TyVarFree NoLoc Unlifted)), ("t_8323_8322", (14, TyVarFree NoLoc Lifted)), ("t_8324_8323", (16, TyVarFree NoLoc Lifted)), ("a_8324_8324", (17, TyVarFree NoLoc Lifted)), ("b_8324_8325", (17, TyVarFree NoLoc Lifted)), ("a_8324_8326", (17, TyVarFree NoLoc Unlifted)), ("x_8324_8327", (17, TyVarFree NoLoc Unlifted)), ("a_8325_8322", (17, TyVarFree NoLoc Unlifted)), ("b_8325_8323", (17, TyVarFree NoLoc Unlifted)), ("c_8325_8324", (17, TyVarFree NoLoc Unlifted)), ("t_8325_8329", (18, TyVarFree NoLoc Lifted)), ("t_8326_8320", (18, TyVarFree NoLoc Lifted)), ("t_8326_8321", (18, TyVarFree NoLoc Lifted)), ("a_8326_8322", (19, TyVarFree NoLoc Unlifted)), ("b_8326_8323", (19, TyVarFree NoLoc Unlifted)), ("c_8326_8324", (19, TyVarFree NoLoc Unlifted)), ("t_8326_8327", (20, TyVarFree NoLoc Lifted)), ("t_8326_8328", (20, TyVarFree NoLoc Lifted)), ("t_8326_8329", (20, TyVarFree NoLoc Lifted)), ("a_8327_8320", (21, TyVarFree NoLoc Unlifted)), ("b_8327_8321", (21, TyVarFree NoLoc Unlifted)), ("c_8327_8322", (21, TyVarFree NoLoc Unlifted)), ("t_8327_8325", (22, TyVarFree NoLoc Lifted)), ("t_8327_8326", (22, TyVarFree NoLoc Lifted)), ("t_8327_8327", (22, TyVarFree NoLoc Lifted)), ("t_8326_8327_8327_8328", (20, TyVarFree NoLoc Lifted)), ("t_8326_8328_8327_8329", (20, TyVarFree NoLoc Lifted)), ("t_8326_8329_8328_8320", (20, TyVarFree NoLoc Lifted)), ("t_8326_8320_8328_8321", (18, TyVarFree NoLoc Lifted)), ("t_8327_8325_8328_8322", (22, TyVarFree NoLoc Lifted)), ("t_8327_8326_8328_8323", (22, TyVarFree NoLoc Lifted)), ("t_8327_8327_8328_8324", (22, TyVarFree NoLoc Lifted)), ("t_8326_8321_8328_8325", (18, TyVarFree NoLoc Lifted)), ("t_8325_8329_8328_8326", (18, TyVarFree NoLoc Lifted)), ("a_8324_8324_8328_8327", (17, TyVarFree NoLoc Lifted)), ("t_8324_8323_8328_8328", (16, TyVarFree NoLoc Lifted)), ("t_8323_8322_8328_8329", (14, TyVarFree NoLoc Lifted))] + ) + ] diff --git a/src-testing/Language/Futhark/SyntaxTests.hs b/src-testing/Language/Futhark/SyntaxTests.hs index dddc3c45e5..f3e5541444 100644 --- a/src-testing/Language/Futhark/SyntaxTests.hs +++ b/src-testing/Language/Futhark/SyntaxTests.hs @@ -51,7 +51,7 @@ instance Arbitrary PrimValue where instance IsString VName where fromString s = - let (s', '_' : tag) = span (/= '_') s + let (tag, s') = bimap reverse (reverse . tail) $ span (/= '_') $ reverse s in VName (fromString s') (read tag) instance (IsString v) => IsString (QualName v) where @@ -112,78 +112,84 @@ pPrimType = pUniqueness :: Parser Uniqueness pUniqueness = choice [lexeme "*" $> Unique, pure Nonunique] +pDim :: Parser d -> Parser d +pDim = brackets + pSize :: Parser Size pSize = - brackets $ - choice - [ flip sizeFromInteger mempty <$> lexeme L.decimal, - flip sizeFromName mempty <$> pQualName - ] + choice + [ flip sizeFromInteger mempty <$> lexeme L.decimal, + flip sizeFromName mempty <$> pQualName + ] -pScalarNonFun :: Parser (ScalarTypeBase Size Uniqueness) -pScalarNonFun = +pScalarNonFun :: Parser d -> Parser (ScalarTypeBase d Uniqueness) +pScalarNonFun pd = choice [ Prim <$> pPrimType, pTypeVar, - tupleRecord <$> parens (pType `sepBy` lexeme ","), + tupleRecord <$> parens (pType pd `sepBy` lexeme ","), Record . M.fromList <$> braces (pField `sepBy1` lexeme ",") ] where - pField = (,) <$> pName <* lexeme ":" <*> pType + pField = (,) <$> pName <* lexeme ":" <*> pType pd pTypeVar = TypeVar <$> pUniqueness <*> pQualName <*> many pTypeArg pTypeArg = choice - [ TypeArgDim <$> pSize, + [ TypeArgDim <$> pDim pd, TypeArgType . second (const NoUniqueness) <$> pTypeArgType ] pTypeArgType = choice [ Scalar . Prim <$> pPrimType, - parens pType + parens $ pType pd ] -pArrayType :: Parser ResType -pArrayType = +pArrayType :: Parser d -> Parser (TypeBase d Uniqueness) +pArrayType pd = Array <$> pUniqueness - <*> (Shape <$> some pSize) - <*> (second (const NoUniqueness) <$> pScalarNonFun) + <*> (Shape <$> some (pDim pd)) + <*> (second (const NoUniqueness) <$> pScalarNonFun pd) -pNonFunType :: Parser ResType -pNonFunType = +pNonFunType :: Parser d -> Parser (TypeBase d Uniqueness) +pNonFunType pd = choice - [ try pArrayType, - try $ parens pType, - Scalar <$> pScalarNonFun + [ try $ pArrayType pd, + try $ parens $ pType pd, + Scalar <$> pScalarNonFun pd ] -pScalarType :: Parser (ScalarTypeBase Size Uniqueness) -pScalarType = choice [try pFun, pScalarNonFun] +uniquenessToDiet :: Uniqueness -> Diet +uniquenessToDiet Unique = Consume +uniquenessToDiet Nonunique = Observe + +pScalarType :: Parser d -> Parser (ScalarTypeBase d Uniqueness) +pScalarType pd = choice [try pFun, pScalarNonFun pd] where pFun = - pParam <* lexeme "->" <*> pRetType + pParam <* lexeme "->" <*> pRetType pd pParam = choice [ try pNamedParam, do - t <- pNonFunType - pure $ Arrow Nonunique Unnamed (diet $ resToParam t) (toStruct t) + t <- pNonFunType pd + pure $ Arrow Nonunique Unnamed (diet $ second uniquenessToDiet t) (toStruct t) ] pNamedParam = parens $ do v <- pVName <* lexeme ":" - t <- pType - pure $ Arrow Nonunique (Named v) (diet $ resToParam t) (toStruct t) + t <- pType pd + pure $ Arrow Nonunique (Named v) (diet $ second uniquenessToDiet t) (toStruct t) -pRetType :: Parser ResRetType -pRetType = +pRetType :: Parser d -> Parser (RetTypeBase d Uniqueness) +pRetType pd = choice - [ lexeme "?" *> (RetType <$> some (brackets pVName) <* lexeme "." <*> pType), - RetType [] <$> pType + [ lexeme "?" *> (RetType <$> some (brackets pVName) <* lexeme "." <*> pType pd), + RetType [] <$> pType pd ] -pType :: Parser ResType -pType = - choice [try $ Scalar <$> pScalarType, pArrayType, parens pType] +pType :: Parser d -> Parser (TypeBase d Uniqueness) +pType pd = + choice [try $ Scalar <$> pScalarType pd, pArrayType pd, parens (pType pd)] fromStringParse :: Parser a -> String -> String -> a fromStringParse p what s = @@ -194,26 +200,38 @@ fromStringParse p what s = instance IsString (ScalarTypeBase Size NoUniqueness) where fromString = - fromStringParse (second (const NoUniqueness) <$> pScalarType) "ScalarType" + fromStringParse + (second (const NoUniqueness) <$> pScalarType pSize) + "ScalarType" + +instance IsString (ScalarTypeBase () NoUniqueness) where + fromString = + fromStringParse + (second (const NoUniqueness) <$> pScalarType (pure ())) + "ScalarType" + +instance IsString (TypeBase () NoUniqueness) where + fromString = + fromStringParse (second (const NoUniqueness) <$> pType (pure ())) "Type" instance IsString StructType where fromString = - fromStringParse (second (const NoUniqueness) <$> pType) "StructType" + fromStringParse (second (const NoUniqueness) <$> pType pSize) "StructType" instance IsString ParamType where fromString = - fromStringParse (resToParam <$> pType) "ParamType" + fromStringParse (resToParam <$> pType pSize) "ParamType" instance IsString ResType where fromString = - fromStringParse pType "ResType" + fromStringParse (pType pSize) "ResType" instance IsString StructRetType where fromString = - fromStringParse (second (pure NoUniqueness) <$> pRetType) "StructRetType" + fromStringParse (second (pure NoUniqueness) <$> pRetType pSize) "StructRetType" instance IsString ResRetType where - fromString = fromStringParse pRetType "ResRetType" + fromString = fromStringParse (pRetType pSize) "ResRetType" instance IsString UncheckedExp where fromString = diff --git a/src-testing/Language/Futhark/TypeChecker/TySolveBenchmarks.hs b/src-testing/Language/Futhark/TypeChecker/TySolveBenchmarks.hs new file mode 100644 index 0000000000..6f477375d7 --- /dev/null +++ b/src-testing/Language/Futhark/TypeChecker/TySolveBenchmarks.hs @@ -0,0 +1,99 @@ +module Language.Futhark.TypeChecker.TySolveBenchmarks (benchmarks) where + +import Criterion (Benchmark, bench, bgroup, whnf) +import Data.Map qualified as M +import Generated.AllFutBenchmarks +import Language.Futhark (qualName) +import Language.Futhark.Syntax +import Language.Futhark.SyntaxTests () +import Language.Futhark.TypeChecker.Constraints + ( CtTy (..), + Level, + Reason (..), + TyParams, + TyVarInfo (..), + TyVars, + ) +import Language.Futhark.TypeChecker.Monad (TypeError (..)) +import Language.Futhark.TypeChecker.TySolve as N (Solution, UnconTyVar, solve) +import Language.Futhark.TypeChecker.TySolveOld as O (solve) + +(~) :: TypeBase () NoUniqueness -> TypeBase () NoUniqueness -> CtTy () +t1 ~ t2 = CtEq (Reason mempty) t1 t2 + +tv :: VName -> Level -> (VName, (Level, TyVarInfo ())) +tv v lvl = (v, (lvl, TyVarFree mempty Unlifted)) + +solveNew :: + ( [CtTy ()], + TyParams, + TyVars () + ) -> + Either TypeError ([UnconTyVar], Solution) +solveNew (constraints, typarams, tyvars) = N.solve constraints typarams tyvars + +solveOld :: + ( [CtTy ()], + TyParams, + TyVars () + ) -> + Either TypeError ([UnconTyVar], Solution) +solveOld (constraints, typarams, tyvars) = O.solve constraints typarams tyvars + +generateContraints :: Int -> ([CtTy ()], TyParams, TyVars ()) +generateContraints num_vars + | num_vars <= 0 = + ([], mempty, mempty) + | num_vars == 1 = + let v0_name = VName (nameFromString "v_0") 0 + ty_vars = M.fromList [tv v0_name 0] + in ([], mempty, ty_vars) + | otherwise = + let var_names = + [ VName (nameFromString ("v_" ++ show i)) i + | i <- [0 .. num_vars - 1] + ] + + ty_vars = M.fromList $ map (`tv` 0) var_names + + mkTy :: VName -> TypeBase () NoUniqueness + mkTy v = Scalar (TypeVar NoUniqueness (qualName v) []) + + cts = + zipWith + (\v_i v_j -> mkTy v_i ~ mkTy v_j) + (init var_names) + (tail var_names) + ++ ["v_0" ~ "i32"] + + ty_params = mempty + in (cts, ty_params, ty_vars) + +benchmarks :: Benchmark +benchmarks = + bgroup + "TySolve" + [ bgroup "Synthetic" $ + concatMap + ( \n -> + [ bench (show n ++ " variables (new)") $ + whnf solveNew (generateContraints n), + bench (show n ++ " variables (old)") $ + whnf solveOld (generateContraints n) + ] + ) + sizes, + bgroup "Converted" $ + concatMap + ( \(name, dataCase) -> + [ bench (name <> " (new)") $ whnf solveNew dataCase, + bench (name <> " (old)") $ whnf solveOld dataCase + ] + ) + allFutBenchmarkCases + ] + where + start = 100 + end = 1000 + i = 100 + sizes = [start, start + i .. end] diff --git a/src-testing/Language/Futhark/TypeChecker/TySolveTests.hs b/src-testing/Language/Futhark/TypeChecker/TySolveTests.hs new file mode 100644 index 0000000000..e154e32bad --- /dev/null +++ b/src-testing/Language/Futhark/TypeChecker/TySolveTests.hs @@ -0,0 +1,415 @@ +module Language.Futhark.TypeChecker.TySolveTests (tests) where + +import Data.Loc (Loc (NoLoc)) +import Data.Map qualified as M +import Futhark.Util.Pretty (docString) +import Language.Futhark.Syntax +import Language.Futhark.SyntaxTests () +import Language.Futhark.TypeChecker.Constraints + ( CtTy (..), + Level, + Reason (..), + TyParams, + TyVarInfo (..), + TyVars, + ) +import Language.Futhark.TypeChecker.Monad (TypeError (TypeError), prettyTypeError) +import Language.Futhark.TypeChecker.TySolve +import Test.Tasty (TestTree, testGroup) +import Test.Tasty.HUnit (Assertion, assertBool, assertFailure, testCase, (@?=)) +import Text.Regex.TDFA ((=~)) + +testSolve :: + [CtTy ()] -> + TyParams -> + TyVars () -> + ([UnconTyVar], Solution) -> + Assertion +testSolve constraints typarams tyvars expected = + case solve constraints typarams tyvars of + Right s -> s @?= expected + Left e -> assertFailure $ docString $ prettyTypeError e + +testSolveFail :: + [CtTy ()] -> + TyParams -> + TyVars () -> + String -> + Assertion +testSolveFail constraints typarams tyvars expected = + case solve constraints typarams tyvars of + Left (TypeError _ _ actualMsg) -> + let regexMatch :: Bool = docString actualMsg =~ expected + in assertBool "Regex doesn't match" regexMatch + Right _ -> assertFailure "Expected type error, but got a solution" + +-- When writing type variables/names here (a_0, b_1), make *sure* that +-- the numbers are distinct. These are all that actually matter for +-- determining identity. + +(~) :: TypeBase () NoUniqueness -> TypeBase () NoUniqueness -> CtTy () +t1 ~ t2 = CtEq (Reason mempty) t1 t2 + +tvFree :: VName -> Level -> (VName, (Level, TyVarInfo ())) +tvFree v lvl = (v, (lvl, TyVarFree mempty Unlifted)) + +-- tvPrim :: VName -> Level -> [PrimType] -> (VName, (Level, TyVarInfo ())) +-- tvPrim v lvl types = (v, (lvl, TyVarPrim mempty types)) + +tvRecord :: VName -> Level -> M.Map Name (TypeBase () NoUniqueness) -> (VName, (Level, TyVarInfo ())) +tvRecord v lvl fields = (v, (lvl, TyVarRecord mempty fields)) + +-- tvSum :: VName -> Level -> M.Map Name [TypeBase () NoUniqueness] -> (VName, (Level, TyVarInfo ())) +-- tvSum v lvl fields = (v, (lvl, TyVarSum mempty fields)) + +typaram :: VName -> Level -> Liftedness -> (VName, (Level, Liftedness, Loc)) +typaram v lvl liftedness = (v, (lvl, liftedness, noLoc)) + +tests :: TestTree +tests = + testGroup + "Unsized constraint solver" + [ testCase "infer unlifted" $ + testSolve + [ "t\8320_9896" ~ "if_t\8322_9898", + "t\8321_9897" ~ "if_t\8322_9898", + "t\8323_9899" ~ "if_t\8322_9898" + ] + mempty + ( M.fromList + [ ("t\8320_9896", (2, TyVarFree NoLoc Lifted)), + ("t\8321_9897", (3, TyVarFree NoLoc Lifted)), + ("if_t\8322_9898", (4, TyVarFree NoLoc SizeLifted)), + ("t\8323_9899", (5, TyVarFree NoLoc Lifted)) + ] + ) + ( [("if_t\8322_9898", SizeLifted)], + M.fromList + [ ("t\8320_9896", Right "if_t\8322_9898"), + ("t\8321_9897", Right "if_t\8322_9898"), + ("t\8323_9899", Right "if_t\8322_9898") + ] + ), + testCase "empty" $ + testSolve [] mempty mempty ([], mempty), + testCase "b_1 ~ a_0" $ + testSolve + ["b_1" ~ "a_0"] + mempty + (M.fromList [tvFree "b_1" 0]) + ([], M.fromList [("b_1", Right "a_0")]), + testCase "a_0 ~ b_1" $ + testSolve + ["a_0" ~ "b_1"] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0]) + ([("b_1", Unlifted)], M.fromList [("a_0", Right "b_1")]), + testCase "multiple" $ + testSolve + ["b_1" ~ "a_0", "d_3" ~ "c_2", "e_4" ~ "c_2", "c_2" ~ "a_0"] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0, tvFree "c_2" 0, tvFree "d_3" 0, tvFree "e_4" 0]) + ([("a_0", Unlifted)], M.fromList [("b_1", Right "a_0"), ("c_2", Right "a_0"), ("d_3", Right "a_0"), ("e_4", Right "a_0")]), + testCase "Two variables" $ + testSolve + ["a_0" ~ "b_1", "c_2" ~ "d_3"] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "c_2" 0]) + ([], M.fromList [("a_0", Right "b_1"), ("c_2", Right "d_3")]), + testCase "i32 + (i32 + i32)" $ + testSolve + [ "i32 -> i32 -> a_0" ~ "i32 -> i32 -> i32", + "i32 -> a_0 -> b_1" ~ "i32 -> i32 -> i32" + ] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0]) + ([], M.fromList [("a_0", Right "i32"), ("b_1", Right "i32")]), + testCase "((λx -> λy -> x * y) i32) i32" $ + testSolve + [ "a_0 -> b_1 -> c_2" ~ "i32 -> i32 -> i32", + "a_0 -> b_1 -> c_2" ~ "i32 -> d_3", + "d_3" ~ "i32 -> e_4" + ] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0, tvFree "c_2" 0, tvFree "d_3" 0, tvFree "e_4" 0]) + ( [], + M.fromList + [ ("a_0", Right "i32"), + ("b_1", Right "i32"), + ("c_2", Right "i32"), + ("d_3", Right "i32 -> i32"), + ("e_4", Right "i32") + ] + ), + testCase "rec λf -> λn -> if n == 0 then 1 else n * (f (n - 1))" $ + testSolve + [ "b_1 -> i32 -> c_2" ~ "i32 -> i32 -> bool", + "b_1 -> i32 -> d_3" ~ "i32 -> i32 -> i32", + "a_0" ~ "d_3 -> e_4", + "b_1 -> e_4 -> f_5" ~ "i32 -> i32 -> i32", + "c_2" ~ "bool", + "i32" ~ "f_5", + "g_6 -> g_6" ~ "a_0 -> b_1 -> i32" + ] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0, tvFree "c_2" 0, tvFree "d_3" 0, tvFree "e_4" 0, tvFree "f_5" 0, tvFree "g_6" 0]) + ( [], + M.fromList + [ ("a_0", Right "i32 -> i32"), + ("b_1", Right "i32"), + ("c_2", Right "bool"), + ("d_3", Right "i32"), + ("e_4", Right "i32"), + ("f_5", Right "i32"), + ("g_6", Right "i32 -> i32") + ] + ), + testCase "let id = λx -> x in id id" $ + testSolve + ["b_1 -> b_1" ~ "(c_2 -> c_2) -> d_3"] + mempty + (M.fromList [tvFree "b_1" 0, tvFree "c_2" 0, tvFree "d_3" 0]) + ( [("c_2", Unlifted)], + M.fromList + [ ("b_1", Right "c_2 -> c_2"), + ("d_3", Right "c_2 -> c_2") + ] + ), + testCase "a_0 ~ i32" $ + testSolve + ["a_0" ~ "i32"] + mempty + (M.fromList [tvFree "a_0" 0]) + ([], M.fromList [("a_0", Right "i32")]), + testCase "a_0 ~ a_0" $ + testSolve + ["a_0" ~ "a_0"] + mempty + (M.fromList [tvFree "a_0" 0]) + ([("a_0", Unlifted)], mempty), + testCase "non-unifiable types" $ + testSolveFail + ["a_0" ~ "i32", "a_0" ~ "bool"] + mempty + (M.fromList [tvFree "a_0" 0]) + ".?([Cc]annot unify).?", + testCase "infinite type (function) 1" $ + testSolveFail + ["a_0" ~ "a_0 -> b_1"] + mempty + (M.fromList [tvFree "a_0" 0]) + ".?([Oo]ccurs check).?", + -- ! This case acts weird for the original implementation. + testCase "infinite type (function) 2" $ + testSolveFail + ["a_0" ~ "b_1 -> i32", "b_1" ~ "c_2", "b_1" ~ "d_3", "a_0" ~ "d_3"] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0, tvFree "c_2" 0, tvFree "d_3" 0]) + ".?([Oo]ccurs check).?", + testCase "infinite type (list)" $ + testSolveFail + ["a_0" ~ "[]a_0"] + mempty + (M.fromList [tvFree "a_0" 0]) + ".?([Oo]ccurs check).?", + testCase "infinite type (tuple)" $ + testSolveFail + ["a_0" ~ "(a_0, bool)"] + mempty + (M.fromList [tvFree "a_0" 0]) + ".?([Oo]ccurs check).?", + testCase "infinite type (record) 1" $ + testSolveFail + ["a_0" ~ "{foo: a_0, bar: f32}"] + mempty + (M.fromList [tvFree "a_0" 0]) + ".?([Oo]ccurs check).?", + -- ! This case never finishes for the original implementation. + testCase "infinite type (record) 2" $ + testSolveFail + ["a_0" ~ "{foo: b_1}", "b_1" ~ "c_2", "a_0" ~ "c_2"] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0, tvFree "c_2" 0]) + ".?([Oo]ccurs check).?", + testCase "infinite type (record) 3" $ + testSolveFail + ["a_0" ~ "{foo: b_1}", "c_2" ~ "b_1", "a_0" ~ "c_2"] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0, tvFree "c_2" 0]) + ".?([Oo]ccurs check).?", + testCase "infinite type (record) 4" $ + testSolveFail + ["a_0" ~ "{foo: b_1}", "c_2" ~ "b_1", "d_3" ~ "c_2", "a_0" ~ "c_2"] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0, tvFree "c_2" 0, tvFree "d_3" 0]) + ".?([Oo]ccurs check).?", + -- testCase "infinite type (sum type)" $ + -- testSolveFail + -- ["a_0" ~ "#foo a_0"] + -- mempty + -- (M.fromList [tvFree "a_0" 0]) + -- ".?([Oo]ccurs check).?", + + testCase "infinite type (consuming array param)" $ + testSolveFail + ["a_0" ~ "*[]a_0"] + mempty + (M.fromList [tvFree "a_0" 0]) + ".?([Oo]ccurs check).?", + -- ! This case acts weird for the original implementation. + testCase "infinite type (nested)" $ + testSolveFail + ["a_0" ~ "{foo: i32, bar: b_1}", "b_1" ~ "c_2", "c_2" ~ "i32 -> []a_0"] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0, tvFree "c_2" 0]) + ".?([Oo]ccurs check).?", + testCase "vector and 2D matrix" $ + testSolveFail + ["a_0" ~ "[]i32", "a_0" ~ "[][]i32"] + mempty + (M.fromList [tvFree "a_0" 0]) + ".?([Cc]annot unify).?", + testCase "different array types" $ + testSolveFail + ["a_0" ~ "[]f64", "a_0" ~ "[]i64"] + mempty + (M.fromList [tvFree "a_0" 0]) + ".?([Cc]annot unify).?", + testCase "simple record" $ + testSolve + ["a_0" ~ "{foo: i32, bar: bool}"] + mempty + (M.fromList [tvFree "a_0" 0]) + ([], M.fromList [("a_0", Right "{foo: i32, bar: bool}")]), + testCase "record 2" $ + testSolve + ["a_0" ~ "{foo: b_1, bar: c_2}", "b_1" ~ "c_2", "c_2" ~ "i64"] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0, tvFree "c_2" 0]) + ( [], + M.fromList + [ ("a_0", Right "{foo: i64, bar: i64}"), + ("b_1", Right "i64"), + ("c_2", Right "i64") + ] + ), + testCase "record 3" $ + testSolve + ["a_0" ~ "{foo: b_1, bar: c_2}", "b_1" ~ "c_2"] + (M.fromList [typaram "c_2" 0 Lifted]) + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0]) + ( [], + M.fromList + [ ("a_0", Right "{foo: c_2, bar: c_2}"), + ("b_1", Right "c_2") + ] + ), + testCase "tuple" $ + testSolve + ["a_0" ~ "(b_1, c_2, d_3)", "c_2" ~ "d_3"] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0, tvFree "c_2" 0, tvFree "d_3" 0]) + ( [("b_1", Unlifted), ("d_3", Unlifted)], + M.fromList + [ ("a_0", Right "(b_1, d_3, d_3)"), + ("c_2", Right "d_3") + ] + ), + testCase "compatible levels" $ + testSolve + ["a_0" ~ "b_1"] + (M.fromList [typaram "a_0" 0 Unlifted]) + (M.fromList [tvFree "b_1" 1]) + ([], M.fromList [("b_1", Right "a_0")]), + testCase "scope violation 1" $ + testSolveFail + ["a_0" ~ "b_1"] + (M.fromList [typaram "b_1" 1 Unlifted]) + (M.fromList [tvFree "a_0" 0]) + ".?(scope violation).?", + testCase "scope violation 2" $ + testSolveFail + ["a_0" ~ "b_1", "b_1" ~ "c_2"] + (M.fromList [typaram "c_2" 1 Unlifted]) + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 1]) + ".?(scope violation).?", + testCase "differently sized tuples" $ + testSolveFail + ["a_0" ~ "(i32, c_2)", "b_1" ~ "(i32, c_2, bool)", "a_0" ~ "b_1"] + mempty + (M.fromList [tvFree "a_0" 0, tvFree "b_1" 0]) + ".?([Cc]annot unify).?", + testCase "Prim type last substitution" $ + testSolve + [ "t\8321_8321" ~ "num\8320_8320", + "index\8322_8322" ~ "index_elem\8323_8323", + "[]t_0" ~ "[]index_elem\8323_8323" + ] + (M.fromList [typaram "t_0" 0 Unlifted]) + ( M.fromList + [ ("num\8320_8320", (2, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64, Unsigned Int8, Unsigned Int16, Unsigned Int32, Unsigned Int64, FloatType Float16, FloatType Float32, FloatType Float64])), + ("t\8321_8321", (2, TyVarPrim NoLoc [Signed Int8, Signed Int16, Signed Int32, Signed Int64])), + ("index\8322_8322", (2, TyVarFree NoLoc Unlifted)), + ("index_elem\8323_8323", (2, TyVarFree NoLoc Unlifted)) + ] + ) + ( [], + M.fromList + [ ("num\8320_8320", Left [Signed Int8, Signed Int16, Signed Int32, Signed Int64]), + ("t\8321_8321", Left [Signed Int8, Signed Int16, Signed Int32, Signed Int64]), + ("index\8322_8322", Right "t_0"), + ("index_elem\8323_8323", Right "t_0") + ] + ), + testCase "record with polymorphic fields" $ + testSolve + [ "d_3" ~ "{foo: e_4, bar: f_5}", + "e_4" ~ "i32", + "f64" ~ "f_5", + "a_0" ~ "d_3" + ] + mempty + ( M.fromList + [ tvRecord "a_0" 0 $ + M.fromList + [ ("foo", Scalar (Prim (Signed Int32))), + ("bar", Scalar (Prim (FloatType Float64))) + ], + tvFree "d_3" 0, + tvFree "e_4" 0, + tvFree "f_5" 0 + ] + ) + ( [], + M.fromList + [ ("a_0", Right "{foo: i32, bar: f64}"), + ("d_3", Right "{foo: i32, bar: f64}"), + ("e_4", Right "i32"), + ("f_5", Right "f64") + ] + ), + testCase "opaque type" $ + testSolveFail + ["a_0" ~ "i32"] + mempty + mempty + ".?([Cc]annot unify).?", + testCase "liftedness propagation (Lifted -> SizeLifted)" $ + testSolve + ["a_0" ~ "b_1"] + mempty + (M.fromList [("a_0", (0, TyVarFree mempty SizeLifted)), ("b_1", (0, TyVarFree mempty Lifted))]) + ([("b_1", SizeLifted)], M.fromList [("a_0", Right "b_1")]), + testCase "liftedness propagation (Lifted -> Unlifted)" $ + testSolve + ["a_0" ~ "b_1"] + mempty + (M.fromList [("a_0", (0, TyVarFree mempty Unlifted)), ("b_1", (0, TyVarFree mempty Lifted))]) + ([("b_1", Unlifted)], M.fromList [("a_0", Right "b_1")]), + testCase "liftedness propagation (SizeLifted -> Unlifted)" $ + testSolve + ["a_0" ~ "b_1"] + mempty + (M.fromList [("a_0", (0, TyVarFree mempty Unlifted)), ("b_1", (0, TyVarFree mempty SizeLifted))]) + ([("b_1", Unlifted)], M.fromList [("a_0", Right "b_1")]) + ] diff --git a/src-testing/Language/Futhark/TypeCheckerTests.hs b/src-testing/Language/Futhark/TypeCheckerTests.hs index 519099e866..c487ace12a 100644 --- a/src-testing/Language/Futhark/TypeCheckerTests.hs +++ b/src-testing/Language/Futhark/TypeCheckerTests.hs @@ -1,6 +1,7 @@ module Language.Futhark.TypeCheckerTests (tests) where import Language.Futhark.TypeChecker.ConsumptionTests qualified +import Language.Futhark.TypeChecker.TySolveTests qualified import Language.Futhark.TypeChecker.TypesTests qualified import Test.Tasty @@ -9,5 +10,6 @@ tests = testGroup "Source type checker tests" [ Language.Futhark.TypeChecker.TypesTests.tests, + Language.Futhark.TypeChecker.TySolveTests.tests, Language.Futhark.TypeChecker.ConsumptionTests.tests ] diff --git a/src-testing/futhark_benchmarks.hs b/src-testing/futhark_benchmarks.hs index c2ad20b150..c4836ac3fe 100644 --- a/src-testing/futhark_benchmarks.hs +++ b/src-testing/futhark_benchmarks.hs @@ -2,9 +2,11 @@ module Main (main) where import Criterion.Main import Language.Futhark.ParserBenchmarks qualified +import Language.Futhark.TypeChecker.TySolveBenchmarks qualified main :: IO () main = defaultMain - [ Language.Futhark.ParserBenchmarks.benchmarks + [ Language.Futhark.ParserBenchmarks.benchmarks, + Language.Futhark.TypeChecker.TySolveBenchmarks.benchmarks ] diff --git a/src/Futhark/Internalise/Defunctionalise.hs b/src/Futhark/Internalise/Defunctionalise.hs index 104998feb9..0eebec1713 100644 --- a/src/Futhark/Internalise/Defunctionalise.hs +++ b/src/Futhark/Internalise/Defunctionalise.hs @@ -756,7 +756,7 @@ etaExpand e_t e = do M.fromList . zip (retDims ret) $ map (ExpSubst . flip sizeFromName mempty . qualName) ext' ret' = applySubst (`M.lookup` extsubst) ret - e' = mkApply e (map (Nothing,) vars) $ AppRes (toStruct $ retType ret') ext' + e' = mkApply e (map (\v -> (Nothing, mempty, v)) vars) $ AppRes (toStruct $ retType ret') ext' pure (params, e', ret) where getType (RetType _ (Scalar (Arrow _ p d t1 t2))) = @@ -863,7 +863,7 @@ unRetType (RetType ext t) = do defuncApplyFunction :: Exp -> Int -> DefM (Exp, StaticVal) defuncApplyFunction e@(Var qn (Info t) loc) num_args = do - let (argtypes, rettype) = unfoldFunType t + let (argtypes, rettype) = first (map snd) $ unfoldFunType t sv <- lookupVar (toStruct t) (qualLeaf qn) case sv of @@ -916,9 +916,9 @@ liftedName _ _ = "defunc" defuncApplyArg :: (Name, SrcLoc) -> (Exp, StaticVal) -> - ((Maybe VName, Exp), [ParamType]) -> + (((Maybe VName, AutoMap), Exp), [ParamType]) -> DefM (Exp, StaticVal) -defuncApplyArg (fname_s, floc) (f', LambdaSV pat lam_e_t lam_e closure_env) ((argext, arg), _) = do +defuncApplyArg (fname_s, floc) (f', LambdaSV pat lam_e_t lam_e closure_env) (((argext, _), arg), _) = do (arg', arg_sv) <- defuncExp arg let env' = alwaysMatchPatSV closure_env pat arg_sv dims = mempty @@ -969,18 +969,18 @@ defuncApplyArg (fname_s, floc) (f', LambdaSV pat lam_e_t lam_e closure_env) ((ar callret <- unRetType lifted_rettype pure - ( mkApply fname' [(Nothing, f'), (argext, arg')] callret, + ( mkApply fname' [(Nothing, mempty, f'), (argext, mempty, arg')] callret, sv ) -- If 'f' is a dynamic function, we just leave the application in -- place, but we update the types since it may be partially -- applied or return a higher-order value. -defuncApplyArg _ (f', DynamicFun _ sv) ((argext, arg), argtypes) = do +defuncApplyArg _ (f', DynamicFun _ sv) (((argext, _), arg), argtypes) = do (arg', _) <- defuncExp arg let (argtypes', rettype) = dynamicFunType sv argtypes restype = foldFunType argtypes' (RetType [] rettype) callret = AppRes restype [] - apply_e = mkApply f' [(argext, arg')] callret + apply_e = mkApply f' [(argext, mempty, arg')] callret pure (apply_e, sv) -- defuncApplyArg (fname_s, _) (_, sv) ((_, arg), _) = @@ -997,7 +997,7 @@ updateReturn (AppRes ret1 ext1) (AppExp apply (Info (AppRes ret2 ext2))) = AppExp apply $ Info $ AppRes (combineTypeShapes ret1 ret2) (ext1 <> ext2) updateReturn _ e = e -defuncApply :: Exp -> NE.NonEmpty (Maybe VName, Exp) -> AppRes -> SrcLoc -> DefM (Exp, StaticVal) +defuncApply :: Exp -> NE.NonEmpty ((Maybe VName, AutoMap), Exp) -> AppRes -> SrcLoc -> DefM (Exp, StaticVal) defuncApply f args appres loc = do (f', f_sv) <- defuncApplyFunction f (length args) case f_sv of @@ -1014,8 +1014,8 @@ defuncApply f args appres loc = do (argtypes, _) = unfoldFunType $ typeOf f fmap (first $ updateReturn appres) $ foldM (defuncApplyArg (fname, loc)) (f', f_sv) $ - NE.zip args $ - NE.tails argtypes + NE.zip args . NE.tails . map snd $ + argtypes where intrinsicOrHole e' = do -- If the intrinsic is fully applied, then we are done. diff --git a/src/Futhark/Internalise/Exps.hs b/src/Futhark/Internalise/Exps.hs index 6005473623..c957627147 100644 --- a/src/Futhark/Internalise/Exps.hs +++ b/src/Futhark/Internalise/Exps.hs @@ -363,21 +363,6 @@ internaliseAppExp desc (E.AppRes et ext) e@E.Apply {} = -- Some functions are magical (overloaded) and we handle that here. case () of () - -- Short-circuiting operators are magical. - | baseTag (qualLeaf qfname) <= maxIntrinsicTag, - baseName (qualLeaf qfname) == "&&", - [(x, _), (y, _)] <- args -> - internaliseExp desc $ - E.AppExp - (E.If x y (E.Literal (E.BoolValue False) mempty) mempty) - (Info $ AppRes (E.Scalar $ E.Prim E.Bool) []) - | baseTag (qualLeaf qfname) <= maxIntrinsicTag, - baseName (qualLeaf qfname) == "||", - [(x, _), (y, _)] <- args -> - internaliseExp desc $ - E.AppExp - (E.If x (E.Literal (E.BoolValue True) mempty) y mempty) - (Info $ AppRes (E.Scalar $ E.Prim E.Bool) []) -- Overloaded and intrinsic functions never take array -- arguments (except equality, but those cannot be -- existential), so we can safely ignore the existential @@ -1513,7 +1498,7 @@ findFuncall (E.Apply f args _) | E.Hole (Info _) loc <- f = (FunctionHole loc, map onArg $ NE.toList args) where - onArg (Info argext, e) = (e, argext) + onArg (Info (argext, _), e) = (e, argext) findFuncall e = error $ "Invalid function expression in application:\n" ++ prettyString e @@ -1613,12 +1598,15 @@ isOverloadedFunction qname desc = do ((name ==) . nameFromText . prettyText) [minBound .. maxBound :: E.BinOp] = Just $ \[(x_t, [x']), (y_t, [y'])] -> - case (x_t, y_t) of + case (arrayElem x_t, arrayElem y_t) of (E.Scalar (E.Prim t1), E.Scalar (E.Prim t2)) -> internaliseBinOp desc bop x' y' t1 t2 _ -> error "Futhark.Internalise.internaliseExp: non-primitive type in BinOp." handle _ = Nothing + arrayElem (E.Array _ _ t) = E.Scalar t + arrayElem t = t + scatterF :: Int -> E.Exp -> E.Exp -> E.Exp -> Name -> InternaliseM [SubExp] scatterF rank dest is v desc = do is' <- internaliseExpToVars "write_arg_i" is @@ -1634,7 +1622,7 @@ isIntrinsicFunction :: E.QualName VName -> [E.Exp] -> Maybe (Name -> InternaliseM [SubExp]) -isIntrinsicFunction qname args = do +isIntrinsicFunction qname all_args = do guard $ baseTag (qualLeaf qname) <= maxIntrinsicTag let handlers = [ handleSign, @@ -1644,7 +1632,7 @@ isIntrinsicFunction qname args = do handleAD, handleRest ] - msum [h args $ baseName $ qualLeaf qname | h <- handlers] + msum [h all_args $ baseName $ qualLeaf qname | h <- handlers] where handleSign [x] "sign_i8" = Just $ toSigned I.Int8 x handleSign [x] "sign_i16" = Just $ toSigned I.Int16 x @@ -1675,12 +1663,23 @@ isIntrinsicFunction qname args = do fmap pure $ letSubExp desc $ I.BasicOp $ I.ConvOp conv x' handleOps _ _ = Nothing - handleSOACs [lam, arr] "map" = Just $ \desc -> do - arr' <- internaliseExpToVars "map_arr" arr - arr_ts <- mapM lookupType arr' - lam' <- internaliseLambdaCoerce lam $ map rowType arr_ts - let w = arraysSize 0 arr_ts - letTupExp' desc $ I.Op $ I.Screma w arr' (I.mapSOAC lam') + handleSOACs (lam : args) "map" = Just $ \desc -> do + arg_ses <- concat <$> mapM (internaliseExp "arg") args + arg_ts <- mapM subExpType arg_ses + let param_ts = map rowType arg_ts + map_dim = head $ I.shapeDims $ I.arrayShape $ head arg_ts + + arg_ses' <- + zipWithM + (\p a -> ensureShape "" (arrayOfRow p map_dim) "" a) + param_ts + arg_ses + + args_v'' <- mapM (letExp "" . BasicOp . SubExp) arg_ses' + + lambda <- internaliseLambdaCoerce lam param_ts + + letTupExp' desc $ Op $ Screma map_dim args_v'' $ mapSOAC lambda handleSOACs [k, lam, arr] "partition" = do k' <- fromIntegral <$> fromInt32 k Just $ \_desc -> do diff --git a/src/Futhark/Internalise/FullNormalise.hs b/src/Futhark/Internalise/FullNormalise.hs index 80f98e7926..a5db7b4521 100644 --- a/src/Futhark/Internalise/FullNormalise.hs +++ b/src/Futhark/Internalise/FullNormalise.hs @@ -20,16 +20,21 @@ -- still needed in monomorphisation for now. module Futhark.Internalise.FullNormalise (transformProg) where +import Control.Monad import Control.Monad.Reader import Control.Monad.State import Data.Bifunctor +import Data.List (zip4) import Data.List.NonEmpty qualified as NE import Data.Map qualified as M +import Data.Maybe import Data.Text qualified as T import Futhark.MonadFreshNames import Futhark.Util (showText) import Futhark.Util.Loc (srcspan) +import Futhark.Util.Pretty import Language.Futhark +import Language.Futhark.Primitive (intValue) import Language.Futhark.Traversals import Language.Futhark.TypeChecker.Types @@ -214,13 +219,13 @@ getOrdering final (Lambda params body mte ret loc) = do nameExp final $ Lambda params body' mte ret loc getOrdering _ (OpSection qn ty loc) = pure $ Var qn ty loc -getOrdering final (OpSectionLeft op ty e (Info (xp, _, xext), Info (yp, yty)) (Info (RetType dims ret), Info exts) loc) = do +getOrdering final (OpSectionLeft op ty e (Info (xp, _, xext, _), Info (yp, yty)) (Info (RetType dims ret), Info exts) loc) = do x <- getOrdering False e yn <- newVName "y" let y = Var (qualName yn) (Info $ toStruct yty) mempty ret' = applySubst (pSubst x y) ret body = - mkApply (Var op ty loc) [(xext, x), (Nothing, y)] $ + mkApply (Var op ty loc) [(xext, mempty, x), (Nothing, mempty, y)] $ AppRes (toStruct ret') exts nameExp final $ Lambda [Id yn (Info yty) mempty] body Nothing (Info (RetType dims ret')) loc where @@ -228,12 +233,12 @@ getOrdering final (OpSectionLeft op ty e (Info (xp, _, xext), Info (yp, yty)) (I | Named p <- xp, p == vn = Just $ ExpSubst x | Named p <- yp, p == vn = Just $ ExpSubst y | otherwise = Nothing -getOrdering final (OpSectionRight op ty e (Info (xp, xty), Info (yp, _, yext)) (Info (RetType dims ret)) loc) = do +getOrdering final (OpSectionRight op ty e (Info (xp, xty), Info (yp, _, yext, _)) (Info (RetType dims ret)) loc) = do xn <- newVName "x" y <- getOrdering False e let x = Var (qualName xn) (Info $ toStruct xty) mempty ret' = applySubst (pSubst x y) ret - body = mkApply (Var op ty loc) [(Nothing, x), (yext, y)] $ AppRes (toStruct ret') [] + body = mkApply (Var op ty loc) [(Nothing, mempty, x), (yext, mempty, y)] $ AppRes (toStruct ret') [] nameExp final $ Lambda [Id xn (Info xty) mempty] body Nothing (Info (RetType dims ret')) loc where pSubst x y vn @@ -309,7 +314,10 @@ getOrdering final (AppExp (Loop sizes pat einit form body loc) resT) = do While e -> While <$> transformBody e body' <- transformBody body nameExp final $ AppExp (Loop sizes pat (LoopInitExplicit einit') form' body' loc) resT -getOrdering final (AppExp (BinOp (op, oloc) opT (el, Info elp) (er, Info erp) loc) (Info resT)) = do +getOrdering final (AppExp (BinOp (op, oloc) opT (el, Info (elp, _)) (er, Info (erp, _)) loc) (Info resT)) = do + -- Rewrite short-circuiting boolean operators on scalars to explicit + -- if-then-else. Automapped cases are turned into applications of + -- intrinsic functions. expr' <- case (isOr, isAnd) of (True, _) -> do el' <- naming "or_lhs" $ getOrdering True el @@ -320,9 +328,9 @@ getOrdering final (AppExp (BinOp (op, oloc) opT (el, Info elp) (er, Info erp) lo er' <- naming "and_rhs" $ transformBody er pure $ AppExp (If el' er' (Literal (BoolValue False) mempty) loc) (Info resT) (False, False) -> do - el' <- naming (nameFromText (prettyText op) <> "_lhs") $ getOrdering False el - er' <- naming (nameFromText (prettyText op) <> "_rhs") $ getOrdering False er - pure $ mkApply (Var op opT oloc) [(elp, el'), (erp, er')] resT + el' <- naming (baseName (qualLeaf op) <> "_lhs") $ getOrdering False el + er' <- naming (baseName (qualLeaf op) <> "_rhs") $ getOrdering False er + pure $ mkApply (Var op opT oloc) [(elp, mempty, el'), (erp, mempty, er')] resT nameExp final expr' where isOr = baseName (qualLeaf op) == "||" @@ -358,7 +366,7 @@ getOrdering final (AppExp (Match expr cs loc) resT) = do -- a complete separtion of states. transformBody :: (MonadFreshNames m) => Exp -> m Exp transformBody e = do - (e', pre_eval) <- runOrdering (getOrdering True e) + (e', pre_eval) <- runOrdering $ getOrdering True e pure $ foldl f e' pre_eval where appRes = case e of @@ -372,9 +380,325 @@ transformBody e = do transformValBind :: (MonadFreshNames m) => ValBind -> m ValBind transformValBind valbind = do - body' <- transformBody $ valBindBody valbind + body' <- transformBody <=< expandAMAnnotations $ valBindBody valbind pure $ valbind {valBindBody = body'} -- | Fully normalise top level bindings. transformProg :: (MonadFreshNames m) => [ValBind] -> m [ValBind] transformProg = mapM transformValBind + +--- | Expansion of 'AutoMap'-annotated applications. +--- +--- Each application @f x@ has an annotation with @AutoMap R M F@ where +--- @R, M, F@ are the autorep, automap, and frame shapes, +--- respectively. +--- +--- The application @f x@ will have type @F t@ for some @t@, i.e. @(f +--- x) : F t@. The frame @F@ is a prefix of the type of @f x@; namely +--- it is the total accumulated shape that is due to implicit maps. +--- Another way of thinking about that is that @|F|@ is is the level +--- of the automap-nest that @f x@ is in. For example, if @|F| = 2@ +--- then we know that @f x@ implicitly stands for +--- +--- > map (\x' -> map (\x'' -> f x'') x') x +--- +--- For an application with a non-empty autorep annotation, the frame +--- tells about how many dimensions of the replicate can be eliminated. +--- For example, @[[1,2],[3,4]] + 5@ will yield the following annotations: +--- +--- > ([[1,2],[3,4]] +) -- AutoMap {R = mempty, M = [2][2], F = [2][2]} +--- > (([[1,2],[3,4]] +) 5) -- AutoMap {R = [2][2], M = mempty, F = [2][2]} +--- +--- All replicated arguments are pushed down the auto-map nest. Each +--- time a replicated argument is pushed down a level of an +--- automap-nest, one fewer replicates is needed (i.e., the outermost +--- dimension of @R@ can be dropped). Replicated arguments are pushed +--- down the nest until either 1) the bottom of the nest is encountered +--- or 2) no replicate dimensions remain. For example, in the second +--- application above @R@ = @F@, so we can push the replicated argument +--- down two levels. Since each level effectively removes a dimension +--- of the replicate, no replicates will be required: +--- +--- > map (\xs -> map (\x -> f x'' 5) xs) [[1,2],[3,4]] +--- +--- The number of replicates that are actually required is given by +--- max(|R| - |F|, 0). +--- +--- An expression's "true level" is the level at which that expression +--- will appear in the automap-nest. The bottom of a mapnest is level 0. +--- +--- * For annotations with @R = mempty@, the true level is @|F|@. +--- * For annotations with @M = mempty@, the true level is @|F| - |R|@. +--- +--- If @|R| > |F|@ then actual replicates (namely @|R| - |F|@ of them) +--- will be required at the bottom of the mapnest. +--- +--- Note that replicates can only appear at the bottom of a mapnest; any +--- expression of the form +--- +--- > map (\ls x' rs -> e) (replicate x) +--- +--- can always be written as +--- +--- > map (\ls rs -> e[x' -> x]) +--- +--- Let's look at another example. Consider (with exact sizes omitted for brevity) +--- +--- > f : a -> a -> a -> []a -> [][][]a -> a +--- > xss : [][]a +--- > ys : []a +--- > zsss : [][][]a +--- > w : a +--- > vss : [][]a +--- +--- and the application +--- +--- > f xss ys zsss w vss +--- +--- which will have the following annotations +--- +--- > (f xss) -- AutoMap {R = mempty, M = [][], F = [][]} (1) +--- > ((f xss) ys) -- AutoMap {R = [], M = mempty, F = [][]} (2) +--- > (((f xss) ys) zsss) -- AutoMap {R = mempty, M = [], F = [][][]} (3) +--- > ((((f xss) ys) zsss) w) -- AutoMap {R = [][][][], M = mempty, F = [][][]} (4) +--- > (((((f xss) ys) zsss) w) vss) -- AutoMap {R = [], M = mempty, F = [][][]} (5) +--- +--- This will yield the following mapnest. +--- +--- > map (\zss -> +--- > map (\xs zs vs -> +--- > map (\x y z v -> f x y z (replicate w) v) xs ys zs v) xss zss vss) zsss +--- +--- Let's see how we'd construct this mapnest from the annotations. We construct +--- the nest bottom-up. We have: +--- +--- Application | True level +--- --------------------------- +--- (1) | |[][]| = 2 +--- (2) | |[][]| - |[]| = 1 +--- (3) | |[][][]| = 3 +--- (4) | |[][][]| - |[][][][]| = -1 +--- (5) | |[][][]| - |[]| = 2 +--- +--- We start at level 0. +--- * Any argument with a negative true level of @-n@ will be replicated @n@ times; +--- the exact shapes can be found by removing the @F@ postfix from @R@, +--- i.e. @R = shapes_to_rep_by <> F@. +--- * Any argument with a 0 true level will be included. +--- * For any argument @arg@ with a positive true level, we construct a new parameter +--- whose type is @arg@ with the leading @n@ dimensions (where @n@ is the true level) +--- removed. +--- +--- Following the rules above, @w@ will be replicated once. For the remaining arguments, +--- we create new parameters @x : a, y : a, z : a , v : a@. Hence, level 0 becomes +--- +--- > f x y z (replicate w) v +--- +--- At level l > 0: +--- * There are no replicates. +--- * Any argument with l true level will be included verbatim. +--- * Any argument with true level > l will have a new parameter constructed for it, +--- whose type has the leading @n - l@ dimensions (where @n@ is the true level) removed. +--- * We surround the previous level with a map that binds that levels' new parameters +--- and is passed the current levels' arguments. +--- +--- Following the above recipe for level 1, we create parameters +--- @xs : []a, zs : []a, vs :[]a@ and obtain +--- +--- > map (\x y z v -> f x y z (replicate w) v) xs ys zs vs +--- +--- This process continues until the level is greater than the maximum +--- true level of any application, at which we terminate. + +-- | Expands 'AutoMap' annotations into explicit @map@s and @replicates@. +expandAMAnnotations :: (MonadFreshNames m) => Exp -> m Exp +expandAMAnnotations e = + case e of + (AppExp (Apply f args _) (Info res)) + | ((exts, ams), arg_es) <- + first unzip $ unzip $ map (first unInfo) $ NE.toList args, + any (/= mempty) ams -> do + f' <- expandAMAnnotations f + arg_es' <- mapM expandAMAnnotations arg_es + let diets = funDiets $ typeOf f + withMapNest (zip4 exts ams arg_es' diets) $ \args' -> do + let rettype = + case unfoldFunTypeWithRet $ typeOf f' of + Nothing -> error "Function type expected." + Just (ptypes, f_ret) -> + let parsubsts = mapMaybe parSub $ zip ptypes args' + in applySubst (`lookup` parsubsts) $ + foldFunType (drop (length args') $ map snd ptypes) f_ret + when (appResExt res /= []) $ + error "expandAMAnnotations: cannot handle existential yet." + pure $ + mkApply f' (zip3 exts (repeat mempty) args') $ + res {appResType = rettype} + (AppExp (BinOp op (Info t) (x, Info (xext, xam)) (y, Info (yext, yam)) loc) (Info res)) -> do + x' <- expandAMAnnotations x + y' <- expandAMAnnotations y + withMapNest [(xext, xam, x', Observe), (yext, yam, y', Observe)] $ \[x'', y''] -> + pure $ + AppExp + ( BinOp + op + (Info t) + (x'', Info (xext, mempty)) + (y'', Info (yext, mempty)) + loc + ) + (Info res {appResType = stripArray (shapeRank $ autoFrame yam) (appResType res)}) + _ -> astMap identityMapper {mapOnExp = expandAMAnnotations} e + where + parSub ((Named v, Scalar (Prim (Signed Int64))), arg) = + Just (v, ExpSubst arg) + parSub _ = Nothing + + funDiets :: TypeBase dim as -> [Diet] + funDiets (Scalar (Arrow _ _ d _ (RetType _ t2))) = d : funDiets t2 + funDiets _ = [] + +type Level = Int + +newtype AutoMapArg = AutoMapArg + { amArg :: Exp + } + deriving (Show) + +data AutoMapParam = AutoMapParam + { amParam :: Pat ParamType, + amMapDim :: Size, + amDiet :: Diet + } + deriving (Show) + +-- | Builds a map-nest based on the 'AutoMap' annotations. +withMapNest :: + forall m. + (MonadFreshNames m) => + [(Maybe VName, AutoMap, Exp, Diet)] -> + ([Exp] -> m Exp) -> + m Exp +withMapNest nest_args f = do + (param_map, arg_map) <- + bimap combineMaps combineMaps . unzip <$> mapM buildArgMap nest_args + buildMapNest param_map arg_map $ maximum $ M.keys arg_map + where + combineMaps :: (Ord k) => [M.Map k v] -> M.Map k [v] + combineMaps = M.unionsWith (<>) . (fmap . fmap) pure + + buildMapNest :: + M.Map Level [AutoMapParam] -> + M.Map Level [AutoMapArg] -> + Level -> + m Exp + buildMapNest _ arg_map 0 = + f $ map amArg $ arg_map M.! 0 + buildMapNest param_map arg_map l = + case map amMapDim $ param_map M.! l of + [] -> error "Malformed param map." + (map_dim : _) -> do + let params = map (\p -> (amDiet p, amParam p)) $ param_map M.! l + args = map amArg $ arg_map M.! l + body <- buildMapNest param_map arg_map (l - 1) + pure $ + mkMap params body args $ + RetType [] $ + arrayOfWithAliases Nonunique (Shape [map_dim]) (typeOf body) + + buildArgMap :: + (Maybe VName, AutoMap, Exp, Diet) -> + m (M.Map Level AutoMapParam, M.Map Level AutoMapArg) + buildArgMap (_ext, am, arg, arg_diet) = + foldM mkArgsAndParams mempty $ reverse [0 .. trueLevel am] + where + mkArgsAndParams (p_map, a_map) l + | l == 0 = do + let arg' = maybe arg (paramToExp . amParam) (p_map M.!? 1) + rarg <- mkReplicateShape (autoRep am `shapePrefix` autoFrame am) arg' + pure (p_map, M.insert 0 (AutoMapArg rarg) a_map) + | l == trueLevel am = do + p <- mkAMParam (typeOf arg) l + let d = outerDim am l + pure + ( M.insert l (AutoMapParam p d arg_diet) p_map, + M.insert l (AutoMapArg arg) a_map + ) + | l < trueLevel am && l > 0 = do + p <- mkAMParam (typeOf arg) l + let d = outerDim am l + let arg' = + paramToExp $ + amParam $ + p_map M.! (l + 1) + pure + ( M.insert l (AutoMapParam p d arg_diet) p_map, + M.insert l (AutoMapArg arg') a_map + ) + | otherwise = error "Impossible." + + mkAMParam t level = + mkParam ("p_" <> nameFromText (showText level)) $ argType (level - 1) am t + + trueLevel :: AutoMap -> Int + trueLevel am + | autoMap am == mempty = + max 0 $ shapeRank (autoFrame am) - shapeRank (autoRep am) + | otherwise = + shapeRank $ autoFrame am + + outerDim :: AutoMap -> Int -> Size + outerDim am level = + (!! (trueLevel am - level)) $ shapeDims $ autoFrame am + + argType level am = stripArray (trueLevel am - level) + +mkParam :: (MonadFreshNames m) => Name -> TypeBase Size u -> m (Pat ParamType) +mkParam desc t = do + x <- newVName desc + pure $ Id x (Info $ toParam Observe t) mempty + +mkReplicateShape :: (MonadFreshNames m) => Shape Size -> Exp -> m Exp +mkReplicateShape s e = foldM (flip mkReplicate) e s + +mkReplicate :: (MonadFreshNames m) => Exp -> Exp -> m Exp +mkReplicate dim e = do + x <- mkParam "x" (Scalar $ Prim $ Unsigned Int64) + pure $ + mkMap [(Observe, x)] e [xs] $ + RetType mempty (arrayOfWithAliases Unique (Shape [dim]) (typeOf e)) + where + xs = + AppExp + ( Range + (Literal (UnsignedValue $ intValue Int64 (0 :: Int)) mempty) + Nothing + (UpToExclusive dim) + mempty + ) + ( Info $ AppRes (arrayOf (Shape [dim]) (Scalar $ Prim $ Unsigned Int64)) [] + ) + +mkMap :: [(Diet, Pat ParamType)] -> Exp -> [Exp] -> ResRetType -> Exp +mkMap params body arrs rettype = + mkApply mapN args (AppRes (toStruct $ retType rettype) []) + where + args = map (Nothing,mempty,) $ lambda : arrs + mapt = foldFunType (zipWith toParam (Observe : map fst params) (typeOf lambda : map typeOf arrs)) rettype + mapN = Var (QualName [] $ VName "map" 0) (Info mapt) mempty + lambda = + Lambda + (map snd params) + body + Nothing + ( Info $ + RetType + (retDims rettype) + (typeOf body `setUniqueness` uniqueness (retType rettype)) + ) + mempty + +paramToExp :: Pat ParamType -> Exp +paramToExp (Id vn (Info t) loc) = + Var (QualName [] vn) (Info $ toStruct t) loc +paramToExp p = error $ prettyString p diff --git a/src/Futhark/Internalise/LiftLambdas.hs b/src/Futhark/Internalise/LiftLambdas.hs index dca54e0f5b..91c4dbfbb4 100644 --- a/src/Futhark/Internalise/LiftLambdas.hs +++ b/src/Futhark/Internalise/LiftLambdas.hs @@ -139,7 +139,7 @@ liftFunction fname tparams params (RetType dims ret) funbody = do apply _ f [] = f apply orig_type f (p : rem_ps) = let inner_ret = AppRes (augType rem_ps orig_type) mempty - inner = mkApply f [(Nothing, freeVar p)] inner_ret + inner = mkApply f [(Nothing, mempty, freeVar p)] inner_ret in apply orig_type inner rem_ps transformSubExps :: ASTMapper LiftM diff --git a/src/Futhark/Internalise/Monomorphise.hs b/src/Futhark/Internalise/Monomorphise.hs index a7310ca0ef..491c881873 100644 --- a/src/Futhark/Internalise/Monomorphise.hs +++ b/src/Futhark/Internalise/Monomorphise.hs @@ -125,10 +125,10 @@ entryAssert (x : xs) body = andop = Var (qualName (intrinsicVar "&&")) (Info opt) mempty eqop = Var (qualName (intrinsicVar "==")) (Info opt) mempty logAnd x' y = - mkApply andop [(Nothing, x'), (Nothing, y)] $ + mkApply andop [(Nothing, mempty, x'), (Nothing, mempty, y)] $ AppRes bool [] cmpExp (ReplacedExp x', y) = - mkApply eqop [(Nothing, x'), (Nothing, y')] $ + mkApply eqop [(Nothing, mempty, x'), (Nothing, mempty, y')] $ AppRes bool [] where y' = Var (qualName y) (Info i64) mempty @@ -418,7 +418,7 @@ transformFName loc fname ft = do ( i - 1, mkApply f - [(Nothing, size_arg)] + [(Nothing, mempty, size_arg)] (AppRes (foldFunType (replicate i i64) (RetType [] t)) []) ) @@ -525,7 +525,7 @@ transformAppExp (Apply fe args _) res = <*> mapM onArg (NE.toList args) <*> transformAppRes res where - onArg (Info ext, e) = (ext,) <$> transformExp e + onArg (Info (ext, am), e) = (ext,am,) <$> transformExp e transformAppExp (Loop sparams pat loopinit form body loc) res = do e1' <- transformExp $ loopInitExp loopinit @@ -554,7 +554,7 @@ transformAppExp (Loop sparams pat loopinit form body loc) res = do (pat_sizes, pat'') <- sizesForPat pat' res' <- transformAppRes res pure $ AppExp (Loop (sparams' ++ pat_sizes) pat'' (LoopInitExplicit e1') form' body' loc) (Info res') -transformAppExp (BinOp (fname, _) (Info t) (e1, d1) (e2, d2) loc) res = do +transformAppExp (BinOp (fname, _) (Info t) (e1, Info (d1, _)) (e2, Info (d2, _)) loc) res = do (AppRes ret ext) <- transformAppRes res fname' <- transformFName loc fname (toStruct t) e1' <- transformExp e1 @@ -589,8 +589,8 @@ transformAppExp (BinOp (fname, _) (Info t) (e1, d1) (e2, d2) loc) res = do where applyOp ret ext fname' x y = mkApply - (mkApply fname' [(unInfo d1, x)] (AppRes ret mempty)) - [(unInfo d2, y)] + (mkApply fname' [(d1, mempty, x)] (AppRes ret mempty)) + [(d2, mempty, y)] (AppRes ret ext) makeVarParam arg = do @@ -676,7 +676,7 @@ transformExp (Lambda {}) = transformExp (OpSection qn t loc) = transformExp $ Var qn t loc transformExp (OpSectionLeft fname (Info t) e arg (Info rettype, Info retext) loc) = do - let (Info (xp, xtype, xargext), Info (yp, ytype)) = arg + let (Info (xp, xtype, xargext, _), Info (yp, ytype)) = arg e' <- transformExp e desugarBinOpSection fname @@ -688,7 +688,7 @@ transformExp (OpSectionLeft fname (Info t) e arg (Info rettype, Info retext) loc (rettype, retext) loc transformExp (OpSectionRight fname (Info t) e arg (Info rettype) loc) = do - let (Info (xp, xtype), Info (yp, ytype, yargext)) = arg + let (Info (xp, xtype), Info (yp, ytype, yargext, _)) = arg e' <- transformExp e desugarBinOpSection fname @@ -760,7 +760,7 @@ desugarBinOpSection fname e_left e_right t (xp, xtype, xext) (yp, ytype, yext) ( let apply_left = mkApply op - [(xext, e1)] + [(xext, mempty, e1)] (AppRes (Scalar $ Arrow mempty yp (diet ytype) (toStruct ytype) (RetType [] $ toRes Nonunique t')) []) onDim (Var d typ _) | Named p <- xp, qualLeaf d == p = Var (qualName v1) typ loc @@ -769,7 +769,7 @@ desugarBinOpSection fname e_left e_right t (xp, xtype, xext) (yp, ytype, yext) ( rettype' = first onDim rettype body <- scoping (S.fromList [v1, v2]) $ - mkApply apply_left [(yext, e2)] + mkApply apply_left [(yext, mempty, e2)] <$> transformAppRes (AppRes (toStruct rettype') retext) rettype'' <- transformRetTypeSizes (S.fromList [v1, v2]) $ RetType dims rettype' pure . wrap_left . wrap_right $ diff --git a/src/Language/Futhark/Interpreter.hs b/src/Language/Futhark/Interpreter.hs index 80b39de389..6e9e5f485e 100644 --- a/src/Language/Futhark/Interpreter.hs +++ b/src/Language/Futhark/Interpreter.hs @@ -463,6 +463,11 @@ fromArray :: Value -> (ValueShape, [Value]) fromArray (ValueArray shape as) = (shape, elems as) fromArray v = error $ "Expected array value, but found: " <> show v +fromArrayR :: Int -> Value -> [Value] +fromArrayR 0 v = [v] +fromArrayR 1 v = snd $ fromArray v +fromArrayR n v = concatMap (fromArrayR (n - 1)) $ snd $ fromArray v + project :: Name -> Value -> Value project f (ValueRecord fs) | Just v' <- M.lookup f fs = v' @@ -477,6 +482,34 @@ apply2 loc env f x y = stacking loc env $ do f' <- apply noLoc mempty f x apply noLoc mempty f' y +data AutoMapArg + = AutoMapArg [Int64] [Int64] [Int64] + deriving (Eq, Ord, Show) + +applyAM :: + SrcLoc -> + Env -> + (Value, StructType) -> + AutoMapArg -> + Value -> + EvalM Value +applyAM loc env (f, _) (AutoMapArg [] [] []) v = + apply loc env f v +applyAM loc env (f, ft) am@(AutoMapArg repshape mapshape frame) v = do + let v' = repArray repshape v + f' = repArray mapshape f + rank = length frame + vs = fromArrayR rank v' + fs = fromArrayR rank f' + t' <- evalTypeFully $ expandType env ft + case t' of + Scalar (Arrow _ _ _ _ (RetType _ ret_t)) -> + toArrayR frame (typeShape $ toStruct ret_t) <$> zipWithM (apply loc env) fs vs + _ -> + error $ + "Invalid automap arguments:\n" + ++ unlines [prettyString ft, show f, show v, show am] + matchPat :: Env -> Pat (TypeBase Size u) -> Value -> EvalM Env matchPat env p v = do m <- runMaybeT $ patternMatch env p v @@ -801,13 +834,15 @@ evalFunctionBinding env tparams ps ret fbody = do returned env (retType ret) retext =<< evalFunction env' missing_sizes ps fbody (retType ret) -evalArg :: Env -> Exp -> Maybe VName -> EvalM Value -evalArg env e ext = do +evalArg :: Env -> Exp -> Maybe VName -> AutoMap -> EvalM (Value, AutoMapArg) +evalArg env e ext (AutoMap rshape mshape frame) = do v <- eval env e case ext of Just ext' -> putExtSize ext' v _ -> pure () - pure v + let evalShape = mapM (fmap asInt64 . eval env) . shapeDims + am' <- AutoMapArg <$> evalShape rshape <*> evalShape mshape <*> evalShape frame + pure (v, am') returned :: Env -> TypeBase Size u -> [VName] -> Value -> EvalM Value returned _ _ [] v = pure v @@ -877,22 +912,31 @@ evalAppExp env (LetPat sizes p e body _) = do evalAppExp env (LetFun (f, _) (tparams, ps, _, Info ret, fbody) body _) = do binding <- evalFunctionBinding env tparams ps ret fbody eval (env {envTerm = M.insert f binding $ envTerm env}) body -evalAppExp env (BinOp (op, _) op_t (x, Info xext) (y, Info yext) loc) - | baseName (qualLeaf op) == "&&" = do +evalAppExp env (BinOp (op, _) (Info op_t) (x, Info (xext, xam)) (y, Info (yext, yam)) loc) + | baseName (qualLeaf op) == "&&", + noAutoMap = do x' <- asBool <$> eval env x if x' then eval env y else pure $ ValuePrim $ BoolValue False - | baseName (qualLeaf op) == "||" = do + | baseName (qualLeaf op) == "||", + noAutoMap = do x' <- asBool <$> eval env x if x' then pure $ ValuePrim $ BoolValue True else eval env y | otherwise = do - x' <- evalArg env x xext - y' <- evalArg env y yext - op' <- eval env $ Var op op_t loc - apply2 loc env op' x' y' + (x', xam') <- evalArg env x xext xam + (y', yam') <- evalArg env y yext yam + op' <- evalTermVar env op op_t + op'' <- applyAM loc env (op', op_t) xam' x' + applyAM loc env (op'', op_ret) yam' y' + where + op_ret = case op_t of + Scalar (Arrow _ _ _ _ (RetType _ t)) -> + toStruct t + _ -> error $ "Nonsensical binop type: " <> prettyString op_t + noAutoMap = xam == mempty && yam == mempty evalAppExp env (If cond e1 e2 _) = do cond' <- asBool <$> eval env cond if cond' then eval env e1 else eval env e2 @@ -902,9 +946,10 @@ evalAppExp env (Apply f args loc) = do -- type of the functions. args' <- reverse <$> mapM evalArg' (reverse $ NE.toList args) f' <- eval env f - foldM (apply loc env) f' args' + foldM apply' f' args' where - evalArg' (Info ext, x) = evalArg env x ext + apply' f' (v', am') = applyAM loc env (f', typeOf f) am' v' + evalArg' (Info (ext, am), x) = evalArg env x ext am evalAppExp env (Index e is loc) = do is' <- mapM (evalDimIndex env) is arr <- eval env e @@ -1075,16 +1120,21 @@ eval env (Lambda ps body _ (Info (RetType _ rt)) _) = evalFunction env [] ps body rt eval env (OpSection qv (Info t) _) = evalTermVar env qv $ toStruct t -eval env (OpSectionLeft qv _ e (Info (_, _, argext), _) (Info (RetType _ t), _) loc) = do - v <- evalArg env e argext - f <- evalTermVar env qv (toStruct t) - apply loc env f v -eval env (OpSectionRight qv _ e (Info _, Info (_, _, argext)) (Info (RetType _ t)) loc) = do - y <- evalArg env e argext +eval env (OpSectionLeft qv _ e (Info (_, _, argext, am), _) (Info (RetType _ t), _) loc) = do + (v, am') <- evalArg env e argext am + f <- evalTermVar env qv t' + applyAM loc env (f, t') am' v + where + t' = toStruct t +eval env (OpSectionRight qv _ e (Info _, Info (_, _, argext, am)) (Info (RetType _ t)) loc) = do + (y, am') <- evalArg env e argext am pure $ ValueFun $ \x -> do - f <- evalTermVar env qv $ toStruct t - apply2 loc env f x y + f <- evalTermVar env qv t' + f' <- apply loc env f x + applyAM loc env (f', t') am' y + where + t' = toStruct t eval env (IndexSection is _ loc) = do is' <- mapM (evalDimIndex env) is pure $ ValueFun $ evalIndex loc env is' @@ -2217,7 +2267,7 @@ checkEntryArgs entry args entry_t "Got input of types" indent 2 (stack (map pretty args_ts)) where - (param_ts, _) = unfoldFunType entry_t + param_ts = map snd $ fst $ unfoldFunType entry_t args_ts = map (valueStructType . valueType) args expected | null param_ts = diff --git a/src/Language/Futhark/Interpreter/Values.hs b/src/Language/Futhark/Interpreter/Values.hs index 4fd6fab264..ccf8055deb 100644 --- a/src/Language/Futhark/Interpreter/Values.hs +++ b/src/Language/Futhark/Interpreter/Values.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE LambdaCase #-} + -- | The value representation used in the interpreter. -- -- Kept simple and free of unnecessary operational details (in @@ -23,7 +25,9 @@ module Language.Futhark.Interpreter.Values prettyEmptyArray, toArray, toArray', + toArrayR, toTuple, + repArray, -- * Conversion fromDataValue, @@ -32,7 +36,7 @@ where import Control.Monad.Identity import Data.Array -import Data.List (genericLength) +import Data.List (genericLength, genericReplicate) import Data.Map qualified as M import Data.Maybe import Data.Monoid hiding (Sum) @@ -256,6 +260,17 @@ toArray' rowshape vs = ValueArray shape (listArray (0, length vs - 1) vs) where shape = ShapeDim (genericLength vs) rowshape +-- | Produce multidimensional array from a flat list of values. +toArrayR :: [Int64] -> ValueShape -> [Value m] -> Value m +toArrayR [] _ = \case + [v] -> v + _ -> error "toArrayR: empty shape" +toArrayR [_] elemshape = toArray' elemshape +toArrayR (n : ns) elemshape = + toArray (foldr ShapeDim elemshape (n : ns)) + . map (toArrayR ns elemshape) + . chunk (fromIntegral (product ns)) + arrayLength :: (Integral int) => Array Int (Value m) -> int arrayLength = fromIntegral . (+ 1) . snd . bounds @@ -287,6 +302,13 @@ fromDataValueWith f shape vector where shape' = SVec.tail shape +repArray :: [Int64] -> Value m -> Value m +repArray [] v = v +repArray (n : ns) v = + toArray' (valueShape v') (genericReplicate n v') + where + v' = repArray ns v + -- | Convert a Futhark value in the externally observable data format -- to an interpreter value. fromDataValue :: V.Value -> Value m diff --git a/src/Language/Futhark/Pretty.hs b/src/Language/Futhark/Pretty.hs index b1aaf3d1c3..336ca5e7cc 100644 --- a/src/Language/Futhark/Pretty.hs +++ b/src/Language/Futhark/Pretty.hs @@ -8,6 +8,7 @@ module Language.Futhark.Pretty leadingOperator, symbolName, IsName (..), + prettyNameText, prettyNameString, Annot (..), ) @@ -56,9 +57,13 @@ instance IsName Name where prettyName = pretty toName = id +-- | Prettyprint name as text. +prettyNameText :: (IsName v) => v -> T.Text +prettyNameText = docText . prettyName + -- | Prettyprint name as string. Only use this for debugging. prettyNameString :: (IsName v) => v -> String -prettyNameString = T.unpack . docText . prettyName +prettyNameString = T.unpack . prettyNameText -- | Class for type constructors that represent annotations. Used in -- the prettyprinter to either print the original AST, or the computed @@ -154,7 +159,7 @@ instance (Pretty (Shape dim), Pretty u) => Pretty (ScalarTypeBase dim u) where prettyType :: (Pretty (Shape dim), Pretty u) => Int -> TypeBase dim u -> Doc a prettyType _ (Array u shape at) = - pretty u <> pretty shape <> align (prettyScalarType 1 at) + pretty u <> pretty shape <> align (prettyScalarType 2 at) prettyType p (Scalar t) = prettyScalarType p t @@ -230,7 +235,13 @@ letBody body@(AppExp LetFun {} _) = pretty body letBody body = "in" <+> align (pretty body) prettyAppExp :: (IsName vn, Annot f) => Int -> AppExpBase f vn -> Doc a -prettyAppExp p (BinOp (bop, _) _ (x, _) (y, _) _) = prettyBinOp p bop x y +prettyAppExp p (BinOp (bop, _) _ (x, xi) (y, yi) _) = + case (unAnnot xi, unAnnot yi) of + (Just (_, xam), Just (_, yam)) + | isEnvVarAtLeast "FUTHARK_COMPILER_DEBUGGING" 3 -> + -- fix + parens $ align $ prettyBinOp p bop x y "Δ" <+> pretty xam "Δ" <+> pretty yam + _ -> prettyBinOp p bop x y prettyAppExp _ (Match e cs _) = "match" <+> pretty e (stack . map pretty) (NE.toList cs) prettyAppExp _ (Loop sizeparams pat initexp form loopbody _) = "loop" @@ -307,11 +318,21 @@ prettyAppExp _ (If c t f _) = prettyAppExp p (Apply f args _) = parensIf (p >= 10) $ prettyExp 0 f - <+> hsep (map (prettyExp 10 . snd) $ NE.toList args) + <+> hsep (map prettyArg $ NE.toList args) + where + prettyArg (i, e) = + case unAnnot i of + Just (_, am) + | isEnvVarAtLeast "FUTHARK_COMPILER_DEBUGGING" 3 -> + parens (prettyExp 10 e <+> "Δ" <+> pretty am) + _ -> prettyExp 10 e instance (IsName vn, Annot f) => Pretty (AppExpBase f vn) where pretty = prettyAppExp (-1) +instance Pretty AutoMap where + pretty (AutoMap r m f) = encloseSep lparen rparen comma $ map pretty [r, m, f] + prettyInst :: (Annot f, Pretty t) => f t -> Doc a prettyInst t = case unAnnot t of diff --git a/src/Language/Futhark/Prop.hs b/src/Language/Futhark/Prop.hs index 8ede87ed0a..5e2ed24149 100644 --- a/src/Language/Futhark/Prop.hs +++ b/src/Language/Futhark/Prop.hs @@ -33,6 +33,9 @@ module Language.Futhark.Prop subExps, similarExps, sameExp, + frameOf, + shapePrefix, + typeShapePrefix, -- * Queries on patterns and params patIdents, @@ -51,9 +54,11 @@ module Language.Futhark.Prop arrayShape, orderZero, unfoldFunType, + unfoldFunTypeWithRet, foldFunType, typeVars, isAccType, + recordField, -- * Operations on types peelArray, @@ -247,6 +252,14 @@ diet (Array d _ _) = d diet (Scalar (TypeVar d _ _)) = d diet (Scalar (Sum cs)) = foldl max Observe $ foldMap (map diet) cs +-- | Look up this record field if it exists. +recordField :: [Name] -> TypeBase dim u -> Maybe (TypeBase dim u) +recordField [] t = Just t +recordField (f : fs) (Scalar (Record fts)) + | Just ft <- M.lookup f fts = + recordField fs ft +recordField _ _ = Nothing + -- | Convert any type to one that has rank information, no alias -- information, and no embedded names. toStructural :: @@ -315,7 +328,9 @@ arrayOfWithAliases :: arrayOfWithAliases u shape2 (Array _ shape1 et) = Array u (shape2 <> shape1) et arrayOfWithAliases u shape (Scalar t) = - Array u shape (second (const mempty) t) + if shapeRank shape == 0 + then Scalar t `setUniqueness` u + else Array u shape (second (const mempty) t) -- | @stripArray n t@ removes the @n@ outermost layers of the array. -- Essentially, it is the type of indexing an array of type @t@ with @@ -498,7 +513,7 @@ typeOf (Attr _ e _) = typeOf e typeOf (AppExp _ (Info res)) = appResType res -- | The type of a function with the given parameters and return type. -funType :: [Pat ParamType] -> ResRetType -> StructType +funType :: [Pat (TypeBase d Diet)] -> RetTypeBase d Uniqueness -> TypeBase d NoUniqueness funType params ret = let RetType _ t = foldr (arrow . patternParam) ret params in toStruct t @@ -508,7 +523,7 @@ funType params ret = -- | @foldFunType ts ret@ creates a function type ('Arrow') that takes -- @ts@ as parameters and returns @ret@. -foldFunType :: [ParamType] -> ResRetType -> StructType +foldFunType :: [TypeBase d Diet] -> RetTypeBase d Uniqueness -> TypeBase d NoUniqueness foldFunType ps ret = let RetType _ t = foldr arrow ret ps in toStruct t @@ -518,12 +533,24 @@ foldFunType ps ret = -- | Extract the parameter types and return type from a type. -- If the type is not an arrow type, the list of parameter types is empty. -unfoldFunType :: TypeBase dim as -> ([TypeBase dim Diet], TypeBase dim NoUniqueness) -unfoldFunType (Scalar (Arrow _ _ d t1 (RetType _ t2))) = +unfoldFunType :: TypeBase dim as -> ([(PName, TypeBase dim Diet)], TypeBase dim NoUniqueness) +unfoldFunType (Scalar (Arrow _ p d t1 (RetType _ t2))) = let (ps, r) = unfoldFunType t2 - in (second (const d) t1 : ps, r) + in ((p, second (const d) t1) : ps, r) unfoldFunType t = ([], toStruct t) +-- | Extract the parameter types and 'RetTypeBase' from a function type. +-- If the type is not an arrow type, returns 'Nothing'. +unfoldFunTypeWithRet :: + TypeBase dim as -> + Maybe ([(PName, TypeBase dim Diet)], RetTypeBase dim Uniqueness) +unfoldFunTypeWithRet (Scalar (Arrow _ p d t1 (RetType _ t2@(Scalar Arrow {})))) = do + (ps, r) <- unfoldFunTypeWithRet t2 + pure ((p, second (const d) t1) : ps, r) +unfoldFunTypeWithRet (Scalar (Arrow _ p d t1 r@RetType {})) = + Just ([(p, second (const d) t1)], r) +unfoldFunTypeWithRet _ = Nothing + -- | The type scheme of a value binding, comprising the type -- parameters and the actual type. valBindTypeScheme :: ValBindBase Info VName -> ([TypeParamBase VName], StructType) @@ -614,7 +641,7 @@ patternStructType = toStruct . patternType -- | When viewed as a function parameter, does this pattern correspond -- to a named parameter of some type? -patternParam :: Pat ParamType -> (PName, Diet, StructType) +patternParam :: Pat (TypeBase d Diet) -> (PName, Diet, TypeBase d NoUniqueness) patternParam (PatParens p _) = patternParam p patternParam (PatAttr _ p _) = @@ -687,8 +714,8 @@ mkBinOp op t x y = ( BinOp (qualName (intrinsicVar op), mempty) (Info t) - (x, Info Nothing) - (y, Info Nothing) + (x, Info (Nothing, mempty)) + (y, Info (Nothing, mempty)) mempty ) (Info $ AppRes t []) @@ -1469,6 +1496,23 @@ sameExp e1 e2 all (uncurry sameExp) es | otherwise = False +frameOf :: Exp -> Shape Size +frameOf (AppExp (Apply _ args _) _) = + ((\(_, am) -> autoFrame am) . unInfo . fst) $ NE.last args +frameOf _ = mempty + +-- | @s1 `shapePrefix` s2@ assumes @s1 = prefix <> s2@ and +-- returns @prefix@. +shapePrefix :: Shape dim -> Shape dim -> Shape dim +shapePrefix (Shape ss1) (Shape ss2) = + Shape $ take (length ss1 - length ss2) ss1 + +typeShapePrefix :: TypeBase dim as1 -> TypeBase dim as2 -> Shape dim +typeShapePrefix (Array _ s _) Scalar {} = s +typeShapePrefix (Array _ s1 _) (Array _ s2 _) = + s1 `shapePrefix` s2 +typeShapePrefix _ _ = mempty + -- | An identifier with type- and aliasing information. type Ident = IdentBase Info VName diff --git a/src/Language/Futhark/Syntax.hs b/src/Language/Futhark/Syntax.hs index 8f8c98f4c0..4eb6ee59ad 100644 --- a/src/Language/Futhark/Syntax.hs +++ b/src/Language/Futhark/Syntax.hs @@ -23,6 +23,10 @@ module Language.Futhark.Syntax Shape (..), shapeRank, stripDims, + AutoMap (..), + autoRepRank, + autoMapRank, + autoFrameRank, TypeBase (..), TypeArg (..), SizeExp (..), @@ -263,6 +267,28 @@ stripDims i (Shape l) | i < length l = Just $ Shape $ drop i l | otherwise = Nothing +data AutoMap = AutoMap + { autoRep :: Shape Size, + autoMap :: Shape Size, + autoFrame :: Shape Size + } + deriving (Eq, Show, Ord) + +autoRepRank :: AutoMap -> Int +autoRepRank = shapeRank . autoRep + +autoMapRank :: AutoMap -> Int +autoMapRank = shapeRank . autoMap + +autoFrameRank :: AutoMap -> Int +autoFrameRank = shapeRank . autoFrame + +instance Semigroup AutoMap where + (AutoMap r1 m1 f1) <> (AutoMap r2 m2 f2) = AutoMap (r1 <> r2) (m1 <> m2) (f1 <> f2) + +instance Monoid AutoMap where + mempty = AutoMap mempty mempty mempty + -- | The name (if any) of a function parameter. The 'Eq' and 'Ord' -- instances always compare values of this type equal. data PName = Named VName | Unnamed @@ -699,7 +725,7 @@ data AppExpBase f vn -- identical). Apply (ExpBase f vn) - (NE.NonEmpty (f (Maybe VName), ExpBase f vn)) + (NE.NonEmpty (f (Maybe VName, AutoMap), ExpBase f vn)) SrcLoc | Range (ExpBase f vn) @@ -733,8 +759,8 @@ data AppExpBase f vn | BinOp (QualName vn, SrcLoc) (f StructType) - (ExpBase f vn, f (Maybe VName)) - (ExpBase f vn, f (Maybe VName)) + (ExpBase f vn, f (Maybe VName, AutoMap)) + (ExpBase f vn, f (Maybe VName, AutoMap)) SrcLoc | LetWith (IdentBase f vn StructType) @@ -843,7 +869,7 @@ data ExpBase f vn (QualName vn) (f StructType) (ExpBase f vn) - (f (PName, ParamType, Maybe VName), f (PName, ParamType)) + (f (PName, ParamType, Maybe VName, AutoMap), f (PName, ParamType)) (f ResRetType, f [VName]) SrcLoc | -- | @+2@; first type is operand, second is result. @@ -851,7 +877,7 @@ data ExpBase f vn (QualName vn) (f StructType) (ExpBase f vn) - (f (PName, ParamType), f (PName, ParamType, Maybe VName)) + (f (PName, ParamType), f (PName, ParamType, Maybe VName, AutoMap)) (f ResRetType) SrcLoc | -- | Field projection as a section: @(.x.y.z)@. @@ -1356,7 +1382,7 @@ deriving instance Show (ProgBase Info VName) deriving instance Show (ProgBase NoInfo Name) -- | Construct an 'Apply' node, with type information. -mkApply :: ExpBase Info vn -> [(Maybe VName, ExpBase Info vn)] -> AppRes -> ExpBase Info vn +mkApply :: ExpBase Info vn -> [(Maybe VName, AutoMap, ExpBase Info vn)] -> AppRes -> ExpBase Info vn mkApply f args (AppRes t ext) | Just args' <- NE.nonEmpty $ map onArg args = case f of @@ -1368,7 +1394,7 @@ mkApply f args (AppRes t ext) AppExp (Apply f args' (srcspan f $ snd $ NE.last args')) (Info (AppRes t ext)) | otherwise = f where - onArg (v, x) = (Info v, x) + onArg (v, am, x) = (Info (v, am), x) -- | Construct an 'Apply' node, without type information. mkApplyUT :: ExpBase NoInfo vn -> ExpBase NoInfo vn -> ExpBase NoInfo vn diff --git a/src/Language/Futhark/Traversals.hs b/src/Language/Futhark/Traversals.hs index cea5be0d3d..ec8304904b 100644 --- a/src/Language/Futhark/Traversals.hs +++ b/src/Language/Futhark/Traversals.hs @@ -61,6 +61,13 @@ class ASTMappable x where -- into subexpressions. The mapping is done left-to-right. astMap :: (Monad m) => ASTMapper m -> x -> m x +mapOnAutoMap :: (Monad m) => ASTMapper m -> AutoMap -> m AutoMap +mapOnAutoMap tv (AutoMap r m f) = + AutoMap + <$> traverse (mapOnExp tv) r + <*> traverse (mapOnExp tv) m + <*> traverse (mapOnExp tv) f + instance ASTMappable (AppExpBase Info VName) where astMap tv (Range start next end loc) = Range @@ -74,7 +81,7 @@ instance ASTMappable (AppExpBase Info VName) where Match <$> mapOnExp tv e <*> astMap tv cases <*> pure loc astMap tv (Apply f args loc) = do f' <- mapOnExp tv f - args' <- traverse (traverse $ mapOnExp tv) args + args' <- traverse onArg args -- Safe to disregard return type because existentials cannot be -- instantiated here, as the return is necessarily a function. pure $ case f' of @@ -82,6 +89,9 @@ instance ASTMappable (AppExpBase Info VName) where Apply f_inner (args_inner <> args') loc _ -> Apply f' args' loc + where + onArg (Info (ext, am), e) = + (,) <$> (Info . (ext,) <$> mapOnAutoMap tv am) <*> mapOnExp tv e astMap tv (LetPat sizes pat e body loc) = LetPat sizes <$> astMap tv pat <*> mapOnExp tv e <*> mapOnExp tv body <*> pure loc astMap tv (LetFun name (tparams, params, ret, t, e) body loc) = @@ -102,13 +112,16 @@ instance ASTMappable (AppExpBase Info VName) where <*> mapOnExp tv vexp <*> mapOnExp tv body <*> pure loc - astMap tv (BinOp (fname, fname_loc) t (x, xext) (y, yext) loc) = + astMap tv (BinOp (fname, fname_loc) t x y loc) = BinOp <$> ((,) <$> mapOnName tv fname <*> pure fname_loc) <*> traverse (mapOnStructType tv) t - <*> ((,) <$> mapOnExp tv x <*> pure xext) - <*> ((,) <$> mapOnExp tv y <*> pure yext) + <*> onArg x + <*> onArg y <*> pure loc + where + onArg (e, Info (ext, am)) = + (,) <$> mapOnExp tv e <*> (Info . (ext,) <$> mapOnAutoMap tv am) astMap tv (Loop sparams mergepat loopinit form loopbody loc) = Loop sparams <$> astMap tv mergepat @@ -187,25 +200,25 @@ instance ASTMappable (ExpBase Info VName) where <$> mapOnName tv name <*> traverse (mapOnStructType tv) t <*> pure loc - astMap tv (OpSectionLeft name t arg (Info (pa, t1a, argext), Info (pb, t1b)) (ret, retext) loc) = + astMap tv (OpSectionLeft name t arg (Info (pa, t1a, argext, am), Info (pb, t1b)) (ret, retext) loc) = OpSectionLeft <$> mapOnName tv name <*> traverse (mapOnStructType tv) t <*> mapOnExp tv arg <*> ( (,) - <$> (Info <$> ((pa,,) <$> mapOnParamType tv t1a <*> pure argext)) + <$> (Info <$> ((pa,,,) <$> mapOnParamType tv t1a <*> pure argext <*> pure am)) <*> (Info <$> ((pb,) <$> mapOnParamType tv t1b)) ) <*> ((,) <$> traverse (mapOnResRetType tv) ret <*> pure retext) <*> pure loc - astMap tv (OpSectionRight name t arg (Info (pa, t1a), Info (pb, t1b, argext)) t2 loc) = + astMap tv (OpSectionRight name t arg (Info (pa, t1a), Info (pb, t1b, argext, am)) t2 loc) = OpSectionRight <$> mapOnName tv name <*> traverse (mapOnStructType tv) t <*> mapOnExp tv arg <*> ( (,) <$> (Info <$> ((pa,) <$> mapOnParamType tv t1a)) - <*> (Info <$> ((pb,,) <$> mapOnParamType tv t1b <*> pure argext)) + <*> (Info <$> ((pb,,,) <$> mapOnParamType tv t1b <*> pure argext <*> pure am)) ) <*> traverse (mapOnResRetType tv) t2 <*> pure loc diff --git a/src/Language/Futhark/TypeChecker.hs b/src/Language/Futhark/TypeChecker.hs index 104eb7691f..a3f264bb2a 100644 --- a/src/Language/Futhark/TypeChecker.hs +++ b/src/Language/Futhark/TypeChecker.hs @@ -27,6 +27,7 @@ import Data.Maybe import Data.Ord import Data.Set qualified as S import Futhark.FreshNames hiding (newName) +import Futhark.Util (debugTraceM) import Futhark.Util.Pretty hiding (space) import Language.Futhark import Language.Futhark.Semantic @@ -671,7 +672,7 @@ checkEntryPoint loc tparams params rettype where (RetType _ rettype_t) = rettype (rettype_params, rettype') = unfoldFunType rettype_t - param_ts = map patternType params ++ rettype_params + param_ts = map patternType params ++ map snd rettype_params checkValBind :: ValBindBase NoInfo Name -> TypeM (Env, ValBind) checkValBind vb = do @@ -689,11 +690,14 @@ checkValBind vb = do checkFunDef (fname, maybe_tdecl, tparams, params, body, loc) let entry' = Info (entryPoint params' maybe_tdecl' rettype) <$ entry + vb' = ValBind entry' fname maybe_tdecl' (Info rettype) tparams' params' body' doc attrs' loc + + debugTraceM 3 $ unlines ["# Inferred:", prettyString vb'] + case entry' of Just _ -> checkEntryPoint loc tparams' params' rettype _ -> pure () - let vb' = ValBind entry' fname maybe_tdecl' (Info rettype) tparams' params' body' doc attrs' loc pure ( mempty { envVtable = diff --git a/src/Language/Futhark/TypeChecker/Constraints.hs b/src/Language/Futhark/TypeChecker/Constraints.hs new file mode 100644 index 0000000000..3eb0674097 --- /dev/null +++ b/src/Language/Futhark/TypeChecker/Constraints.hs @@ -0,0 +1,154 @@ +-- | Constraints produced (and solved) by the type checker. +module Language.Futhark.TypeChecker.Constraints + ( Reason (..), + SVar, + SComp (..), + CtType, + CtTy (..), + CtAM (..), + TyVarInfo (..), + Level, + TyVar, + TyVars, + TyParams, + ) +where + +import Data.Bifunctor +import Data.Loc +import Data.Map qualified as M +import Futhark.Util.Pretty +import Language.Futhark + +-- | A shape variable. +type SVar = VName + +-- | A shape component. `SDim` is a single dimension of unspecified +-- size, `SVar` is a shape variable. A list of shape components should +-- then be understood as concatenation of shapes (meaning you can't +-- just take the length to determine the rank of the array). +data SComp + = SDim + | SVar SVar + deriving (Eq, Ord, Show) + +instance Pretty SComp where + pretty SDim = "[]" + pretty (SVar x) = brackets $ prettyName x + +instance Pretty (Shape SComp) where + pretty = mconcat . map pretty . shapeDims + +-- | The type representation used by the constraint solver. +type CtType d = TypeBase d NoUniqueness + +-- | The reason for a type constraint. Used to generate type error +-- messages. The expected type is always the first one. +data Reason t + = -- | No particular reason. + Reason Loc + | -- | Arising from pattern match. + ReasonPatMatch Loc (PatBase NoInfo VName StructType) t + | -- | Arising from explicit ascription. + ReasonAscription Loc t t + | ReasonRetType Loc t t + | ReasonApply Loc (Maybe (QualName VName), Int) Exp t t + | -- | Used when unifying a type with a function type in a function + -- application. If this unification fails, it means the supposed + -- function was not a function after all. + ReasonApplySplit Loc (Maybe (QualName VName), Int) Exp t + | ReasonBranches Loc t t + deriving (Eq, Show, Functor, Foldable, Traversable) + +instance Located (Reason t) where + locOf (Reason l) = l + locOf (ReasonPatMatch l _ _) = l + locOf (ReasonAscription l _ _) = l + locOf (ReasonRetType l _ _) = l + locOf (ReasonApply l _ _ _ _) = l + locOf (ReasonApplySplit l _ _ _) = l + locOf (ReasonBranches l _ _) = l + +-- | A type constraint. +data CtTy d = CtEq (Reason (CtType d)) (TypeBase d NoUniqueness) (TypeBase d NoUniqueness) + deriving (Show) + +instance Functor CtTy where + fmap f (CtEq r x y) = CtEq (fmap (first f) r) (first f x) (first f y) + +ctReason :: CtTy d -> Reason (CtType d) +ctReason (CtEq r _ _) = r + +instance Located (CtTy d) where + locOf = locOf . ctReason + +instance Pretty (CtTy Size) where + pretty (CtEq _ t1 t2) = pretty t1 <+> "~" <+> pretty t2 + +instance Pretty (CtTy SComp) where + pretty (CtEq _ t1 t2) = pretty t1 <+> "~" <+> pretty t2 + +instance Pretty (CtTy ()) where + pretty (CtEq _ t1 t2) = pretty t1 <+> "~" <+> pretty t2 + +-- | Information about a flexible type variable. Every type variable +-- is associated with a location, which is the original syntax element +-- that it is the type of. +data TyVarInfo d + = -- | Can be substituted with anything. + TyVarFree Loc Liftedness + | -- | Can only be substituted with these primitive types. + TyVarPrim Loc [PrimType] + | -- | Must be a record with these fields. + TyVarRecord Loc (M.Map Name (CtType d)) + | -- | Must be a sum type with these fields. + TyVarSum Loc (M.Map Name [CtType d]) + deriving (Show, Eq) + +instance Functor TyVarInfo where + fmap _ (TyVarFree loc l) = TyVarFree loc l + fmap _ (TyVarPrim loc ts) = TyVarPrim loc ts + fmap f (TyVarRecord loc m) = TyVarRecord loc $ M.map (first f) m + fmap f (TyVarSum loc m) = TyVarSum loc $ M.map (map (first f)) m + +prettyTyVarInfo :: (Pretty (Shape d)) => TyVarInfo d -> Doc a +prettyTyVarInfo (TyVarFree _ l) = "free" <+> pretty l +prettyTyVarInfo (TyVarPrim _ pts) = "∈" <+> pretty pts +prettyTyVarInfo (TyVarRecord _ fs) = pretty $ Scalar $ Record fs +prettyTyVarInfo (TyVarSum _ cs) = pretty $ Scalar $ Sum cs + +instance Pretty (TyVarInfo ()) where + pretty = prettyTyVarInfo + +instance Pretty (TyVarInfo SComp) where + pretty = prettyTyVarInfo + +instance Located (TyVarInfo d) where + locOf (TyVarFree loc _) = loc + locOf (TyVarPrim loc _) = loc + locOf (TyVarRecord loc _) = loc + locOf (TyVarSum loc _) = loc + +-- | The name of a type variable. +type TyVar = VName + +-- | The level at which a type variable is bound. Higher means +-- deeper. We can only unify a type variable at level @i@ with a type +-- @t@ if all type names that occur in @t@ are at most at level @i@. +type Level = Int + +-- | If a VName is not in this map, it should be in the 'TyParams' - +-- the exception is abstract types, which are just missing (and +-- assumed to have smallest possible level). +type TyVars d = M.Map TyVar (Level, TyVarInfo d) + +-- | Explicit type parameters. +type TyParams = M.Map TyVar (Level, Liftedness, Loc) + +data CtAM = CtAM (Reason (CtType SComp)) SVar SVar (Shape SComp) + +instance Located CtAM where + locOf (CtAM r _ _ _) = locOf r + +instance Pretty CtAM where + pretty (CtAM _ r m _) = prettyName r <+> "=" <+> "•" <+> "∨" <+> prettyName m <+> "=" <+> "•" diff --git a/src/Language/Futhark/TypeChecker/Consumption.hs b/src/Language/Futhark/TypeChecker/Consumption.hs index 94592faaf7..54c611f530 100644 --- a/src/Language/Futhark/TypeChecker/Consumption.hs +++ b/src/Language/Futhark/TypeChecker/Consumption.hs @@ -496,9 +496,10 @@ consumeAsNeeded loc (Scalar (Record fs1)) (Scalar (Record fs2)) = consumeAsNeeded loc pt t = when (diet pt == Consume) $ consumeAliases loc $ aliases t -checkArg :: [(Exp, TypeAliases)] -> ParamType -> Exp -> CheckM (Exp, TypeAliases) -checkArg prev p_t e = do - ((e', e_als), e_cons) <- contain $ checkExp e +checkArg :: [(Exp, TypeAliases)] -> ParamType -> AutoMap -> Exp -> CheckM (Exp, TypeAliases) +checkArg prev p_t am e = do + ((e', e_als), e_cons) <- + contain $ if autoRep am /= mempty then noAliases e else checkExp e consumed e_cons let e_t = typeOf e' when (e_cons /= mempty && not (orderZero e_t)) $ @@ -552,9 +553,11 @@ returnType appres (Scalar (Arrow _ v pd t1 (RetType dims t2))) Observe arg = returnType appres (Scalar (Sum cs)) d arg = Scalar $ Sum $ (fmap . fmap) (\et -> returnType appres et d arg) cs -applyArg :: TypeAliases -> TypeAliases -> TypeAliases -applyArg (Scalar (Arrow closure_als _ d _ (RetType _ rettype))) arg_als = - returnType closure_als rettype d arg_als +applyArg :: TypeAliases -> (AutoMap, TypeAliases) -> TypeAliases +applyArg (Scalar (Arrow closure_als _ d _ (RetType _ rettype))) (am, arg_als) = + if autoMap am /= mempty + then second (const mempty) rettype + else returnType closure_als rettype d arg_als applyArg t _ = error $ "applyArg: " <> show t boundFreeInExp :: Exp -> CheckM (M.Map VName TypeAliases) @@ -680,9 +683,9 @@ checkLoop loop_loc (param, arg, form, body) = do let param_t = patternType param' ((arg', arg_als), arg_cons) <- case arg of LoopInitImplicit (Info e) -> - contain $ first (LoopInitImplicit . Info) <$> checkArg [] param_t e + contain $ first (LoopInitImplicit . Info) <$> checkArg [] param_t mempty e LoopInitExplicit e -> - contain $ first LoopInitExplicit <$> checkArg [] param_t e + contain $ first LoopInitExplicit <$> checkArg [] param_t mempty e consumed arg_cons let checkFree what e = do @@ -712,7 +715,7 @@ checkLoop loop_loc (param, arg, form, body) = do `setAliases` S.singleton (AliasFree v) pure ( (param', arg', form', body'), - applyArg loopt arg_als `combineAliases` body_als + applyArg loopt (mempty, arg_als) `combineAliases` body_als ) checkFuncall :: @@ -720,7 +723,7 @@ checkFuncall :: SrcLoc -> Maybe (QualName VName) -> TypeAliases -> - f TypeAliases -> + f (AutoMap, TypeAliases) -> CheckM TypeAliases checkFuncall loc fname f_als arg_als = do v <- VName "internal_app_result" <$> incCounter @@ -734,15 +737,17 @@ checkExp :: Exp -> CheckM (Exp, TypeAliases) checkExp (AppExp (Apply f args loc) appres) = do (f', f_als) <- checkExp f (args', args_als) <- NE.unzip <$> checkArgs (toRes Nonunique f_als) args - res_als <- checkFuncall loc (fname f) f_als args_als + res_als <- + checkFuncall loc (fname f) f_als $ + NE.zip (fmap (snd . unInfo . fst) args') args_als pure (AppExp (Apply f' args' loc) appres, res_als) where fname (Var v _ _) = Just v fname (AppExp (Apply e _ _) _) = fname e fname _ = Nothing - checkArg' prev d (Info p, e) = do - (e', e_als) <- checkArg prev (second (const d) (typeOf e)) e - pure ((Info p, e'), e_als) + checkArg' prev d (Info (p, am), e) = do + (e', e_als) <- checkArg prev (second (const d) (typeOf e)) am e + pure ((Info (p, am), e'), e_als) checkArgs (Scalar (Arrow _ _ d _ (RetType _ rt))) (x NE.:| args') = do -- Note Futhark uses right-to-left evaluation of applications. @@ -833,10 +838,10 @@ checkExp (AppExp (LetFun fname (typarams, params, te, Info (RetType ext ret), fu -- checkExp (AppExp (BinOp (op, oploc) opt (x, xp) (y, yp) loc) appres) = do op_als <- observeVar (locOf oploc) (qualLeaf op) (unInfo opt) - let at1 : at2 : _ = fst $ unfoldFunType op_als - (x', x_als) <- checkArg [] at1 x - (y', y_als) <- checkArg [(x', x_als)] at2 y - res_als <- checkFuncall loc (Just op) op_als [x_als, y_als] + let (_, at1) : (_, at2) : _ = fst $ unfoldFunType op_als + (x', x_als) <- checkArg [] at1 mempty x + (y', y_als) <- checkArg [(x', x_als)] at2 mempty y + res_als <- checkFuncall loc (Just op) op_als [(mempty, x_als), (mempty, y_als)] pure ( AppExp (BinOp (op, oploc) opt (x', xp) (y', yp) loc) appres, res_als diff --git a/src/Language/Futhark/TypeChecker/Error.hs b/src/Language/Futhark/TypeChecker/Error.hs new file mode 100644 index 0000000000..d4fbc70aad --- /dev/null +++ b/src/Language/Futhark/TypeChecker/Error.hs @@ -0,0 +1,79 @@ +-- | Fundamental facilities for constructing type error messages. +module Language.Futhark.TypeChecker.Error + ( -- * Breadcrumbs + BreadCrumbs, + hasNoBreadCrumbs, + matchingField, + matchingConstructor, + matchingTypes, + matching, + ) +where + +import Futhark.Util.Pretty +import Language.Futhark + +-- | A piece of information that describes what process the type +-- checker currently performing. This is used to give better error +-- messages for unification errors. +data BreadCrumb + = MatchingTypes StructType StructType + | MatchingFields [Name] + | MatchingConstructor Name + | Matching (Doc ()) + +instance Pretty BreadCrumb where + pretty (MatchingTypes t1 t2) = + "When matching type" + indent 2 (pretty t1) + "with" + indent 2 (pretty t2) + pretty (MatchingFields fields) = + "When matching types of record field" + <+> dquotes (mconcat $ punctuate "." $ map pretty fields) + <> dot + pretty (MatchingConstructor c) = + "When matching types of constructor" <+> dquotes (pretty c) <> dot + pretty (Matching s) = + unAnnotate s + +-- | Unification failures can occur deep down inside complicated types +-- (consider nested records). We leave breadcrumbs behind us so we can +-- report the path we took to find the mismatch. When combining +-- breadcrumbs with the 'Semigroup' instance, put the innermost +-- breadcrumbs to the left. +newtype BreadCrumbs = BreadCrumbs [BreadCrumb] + +instance Semigroup BreadCrumbs where + BreadCrumbs (MatchingFields xs : bcs1) <> BreadCrumbs (MatchingFields ys : bcs2) = + BreadCrumbs $ MatchingFields (ys <> xs) : bcs1 <> bcs2 + BreadCrumbs bcs1 <> BreadCrumbs bcs2 = + BreadCrumbs $ bcs1 <> bcs2 + +instance Monoid BreadCrumbs where + mempty = BreadCrumbs [] + +-- | Is the path empty? +hasNoBreadCrumbs :: BreadCrumbs -> Bool +hasNoBreadCrumbs (BreadCrumbs []) = True +hasNoBreadCrumbs _ = False + +-- | Matching a record field. +matchingField :: Name -> BreadCrumbs +matchingField f = BreadCrumbs [MatchingFields [f]] + +-- | Matching two types. +matchingTypes :: StructType -> StructType -> BreadCrumbs +matchingTypes t1 t2 = BreadCrumbs [MatchingTypes t1 t2] + +-- | Matching a constructor. +matchingConstructor :: Name -> BreadCrumbs +matchingConstructor c = BreadCrumbs [MatchingConstructor c] + +-- | Matching anything. +matching :: Doc () -> BreadCrumbs +matching d = BreadCrumbs [Matching d] + +instance Pretty BreadCrumbs where + pretty (BreadCrumbs []) = mempty + pretty (BreadCrumbs bcs) = line <> stack (map pretty bcs) diff --git a/src/Language/Futhark/TypeChecker/Rank.hs b/src/Language/Futhark/TypeChecker/Rank.hs new file mode 100644 index 0000000000..8b2f6c0be3 --- /dev/null +++ b/src/Language/Futhark/TypeChecker/Rank.hs @@ -0,0 +1,66 @@ +module Language.Futhark.TypeChecker.Rank + ( rankAnalysis, + rankAnalysis1, + ) +where + +import Control.Monad (void) +import Data.Bifunctor +import Data.Map qualified as M +import Futhark.IR.Pretty () +import Language.Futhark hiding (ScalarType) +import Language.Futhark.TypeChecker.Constraints + +rankAnalysis1 :: + (Monad m) => + SrcLoc -> + ([CtTy SComp], [CtAM]) -> + TyVars SComp -> + M.Map TyVar (CtType SComp) -> + [Pat ParamType] -> + Exp -> + Maybe (TypeExp Exp VName) -> + m + ( ([CtTy ()], M.Map TyVar (CtType ()), TyVars ()), + [Pat ParamType], + Exp, + Maybe (TypeExp Exp VName) + ) +rankAnalysis1 _loc (cs, _cs_am) tyVars artificial params body retdecl = + pure + ( ( map void cs, + M.map (first (const ())) artificial, + fmap (second void) tyVars + ), + params, + body, + retdecl + ) + +rankAnalysis :: + (Monad m) => + SrcLoc -> + ([CtTy SComp], [CtAM]) -> + TyVars SComp -> + M.Map TyVar (CtType SComp) -> + [Pat ParamType] -> + Exp -> + Maybe (TypeExp Exp VName) -> + m + [ ( ([CtTy ()], M.Map TyVar (CtType ()), TyVars ()), + [Pat ParamType], + Exp, + Maybe (TypeExp Exp VName) + ) + ] +rankAnalysis _loc (cs, _cs_am) tyVars artificial params body retdecl = do + pure + [ ( ( map void cs, + M.map (first (const ())) artificial, + fmap (second void) tyVars + ), + params, + body, + retdecl + ) + ] diff --git a/src/Language/Futhark/TypeChecker/Terms.hs b/src/Language/Futhark/TypeChecker/Terms.hs index 3d53a501fa..5e5e8ccfd9 100644 --- a/src/Language/Futhark/TypeChecker/Terms.hs +++ b/src/Language/Futhark/TypeChecker/Terms.hs @@ -6,6 +6,21 @@ -- number of built-in language constructs, as well as uniqueness -- types. This is mostly done in an ad hoc way, and many programs -- will require the programmer to fall back on type annotations. +-- +-- The strategy is to split type checking into sveral (main) passes: +-- +-- 1) A size-agnostic pass implemented in +-- "Language.Futhark.TypeChecker.Terms.Unsized". +-- +-- 2) Pass (1) has given us a program where we know the types of +-- everything, but the sizes of nothing. Pass (2) then does +-- essentially size inference, with the benefit of already knowing the +-- full unsized type of everything. This is done using a syntax-driven +-- approach, similar to Algorithm W. +-- +-- 3) The program is then checked for violation of uniqueness +-- properties, which is implemented in +-- "Language.Futhark.TypeChecker.Consumption". module Language.Futhark.TypeChecker.Terms ( checkOneExp, checkSizeExp, @@ -27,7 +42,7 @@ import Data.Map.Strict qualified as M import Data.Maybe import Data.Set qualified as S import Data.Text qualified as T -import Futhark.Util (mapAccumLM, nubOrd) +import Futhark.Util (debugTraceM, mapAccumLM, nubOrd) import Futhark.Util.Pretty hiding (space) import Language.Futhark import Language.Futhark.Primitive (intByteSize) @@ -38,6 +53,7 @@ import Language.Futhark.TypeChecker.Monad hiding (BoundV, lookupMod) import Language.Futhark.TypeChecker.Terms.Loop import Language.Futhark.TypeChecker.Terms.Monad import Language.Futhark.TypeChecker.Terms.Pat +import Language.Futhark.TypeChecker.Terms.Unsized qualified as Unsized import Language.Futhark.TypeChecker.Types import Language.Futhark.TypeChecker.Unify import Prelude hiding (mod) @@ -54,12 +70,6 @@ hasBinding e = isNothing $ astMap m e m = identityMapper {mapOnExp = \e' -> if hasBinding e' then Nothing else Just e'} -overloadedTypeVars :: Constraints -> Names -overloadedTypeVars = mconcat . map f . M.elems - where - f (_, HasFields _ fs _) = mconcat $ map typeVars $ M.elems fs - f _ = mempty - --- Basic checking -- | Determine if the two types are identical, ignoring uniqueness. @@ -168,8 +178,8 @@ sliceShape r slice t@(Array u (Shape orig_dims) et) = ( BinOp (qualName (intrinsicVar "-"), mempty) sizeBinOpInfo - (j, Info Nothing) - (i, Info Nothing) + (j, Info (Nothing, mempty)) + (i, Info (Nothing, mempty)) mempty ) $ Info @@ -182,8 +192,8 @@ sliceShape _ _ t = pure (t, []) checkAscript :: SrcLoc -> - TypeExp (ExpBase NoInfo VName) VName -> - ExpBase NoInfo VName -> + TypeExp Exp VName -> + Exp -> TermTypeM (TypeExp Exp VName, Exp) checkAscript loc te e = do (te', decl_t, _) <- checkTypeExpNonrigid te @@ -197,8 +207,8 @@ checkAscript loc te e = do checkCoerce :: SrcLoc -> - TypeExp (ExpBase NoInfo VName) VName -> - ExpBase NoInfo VName -> + TypeExp Exp VName -> + Exp -> TermTypeM (TypeExp Exp VName, StructType, Exp) checkCoerce loc te e = do (te', te_t, ext) <- checkTypeExpNonrigid te @@ -261,48 +271,33 @@ unscopeType :: unscopeType tloc unscoped = sizeFree tloc $ find (`elem` unscoped) . fvVars . freeInExp -checkExp :: ExpBase NoInfo VName -> TermTypeM Exp +checkExp :: Exp -> TermTypeM Exp +checkExp (Var qn (Info t) loc) = do + t' <- lookupVar loc qn t + pure $ Var qn (Info t') loc checkExp (Literal val loc) = pure $ Literal val loc -checkExp (Hole _ loc) = do - t <- newTypeVar loc "t" - pure $ Hole (Info t) loc +checkExp (Hole (Info t) loc) = do + t' <- replaceTyVars loc t + pure $ Hole (Info t') loc checkExp (StringLit vs loc) = pure $ StringLit vs loc -checkExp (IntLit val NoInfo loc) = do - t <- newTypeVar loc "t" - mustBeOneOf anyNumberType (mkUsage loc "integer literal") t - pure $ IntLit val (Info t) loc -checkExp (FloatLit val NoInfo loc) = do - t <- newTypeVar loc "t" - mustBeOneOf anyFloatType (mkUsage loc "float literal") t - pure $ FloatLit val (Info t) loc +checkExp (IntLit val (Info t) loc) = do + t' <- replaceTyVars loc t + pure $ IntLit val (Info t') loc +checkExp (FloatLit val (Info t) loc) = do + t' <- replaceTyVars loc t + pure $ FloatLit val (Info t') loc checkExp (TupLit es loc) = TupLit <$> mapM checkExp es <*> pure loc checkExp (RecordLit fs loc) = - RecordLit <$> evalStateT (mapM checkField fs) mempty <*> pure loc + RecordLit <$> mapM checkField fs <*> pure loc where - checkField (RecordFieldExplicit f e rloc) = do - errIfAlreadySet (unLoc f) rloc - modify $ M.insert (unLoc f) rloc - RecordFieldExplicit f <$> lift (checkExp e) <*> pure rloc - checkField (RecordFieldImplicit name NoInfo rloc) = do - errIfAlreadySet (baseName (unLoc name)) rloc - t <- lift $ lookupVar rloc $ qualName $ unLoc name - modify $ M.insert (baseName (unLoc name)) rloc - pure $ RecordFieldImplicit name (Info t) rloc - - errIfAlreadySet f rloc = do - maybe_sloc <- gets $ M.lookup f - case maybe_sloc of - Just sloc -> - lift . typeError rloc mempty $ - "Field" - <+> dquotes (pretty f) - <+> "previously defined at" - <+> pretty (locStrRel rloc sloc) - <> "." - Nothing -> pure () + checkField (RecordFieldExplicit f e rloc) = + RecordFieldExplicit f <$> checkExp e <*> pure rloc + checkField (RecordFieldImplicit name (Info t) rloc) = do + t' <- lookupVar rloc (qualName (unLoc name)) t + pure $ RecordFieldImplicit name (Info t') rloc -- No need to type check this, as these are only produced by the -- parser if the elements are monomorphic and all match. checkExp (ArrayVal vs t loc) = @@ -317,15 +312,17 @@ checkExp (ArrayLit all_es _ loc) = [] -> do et <- newTypeVar loc "t" t <- arrayOfM loc et (Shape [sizeFromInteger 0 mempty]) + mustBeUnlifted (locOf loc) et pure $ ArrayLit [] (Info t) loc e : es -> do e' <- checkExp e et <- expType e' es' <- mapM (unifies "type of first array element" et <=< checkExp) es t <- arrayOfM loc et (Shape [sizeFromInteger (genericLength all_es) mempty]) + mustBeUnlifted (locOf loc) et pure $ ArrayLit (e' : es') (Info t) loc checkExp (AppExp (Range start maybe_step end loc) _) = do - start' <- require "use in range expression" anySignedType =<< checkExp start + start' <- checkExp start start_t <- expType start' maybe_step' <- case maybe_step of Nothing -> pure Nothing @@ -389,8 +386,8 @@ checkExp (AppExp (Range start maybe_step end loc) _) = do ( BinOp (qualName (intrinsicVar op), mempty) sizeBinOpInfo - (x, Info Nothing) - (y, Info Nothing) + (x, Info (Nothing, mempty)) + (y, Info (Nothing, mempty)) mempty ) (Info $ AppRes t []) @@ -402,54 +399,57 @@ checkExp (AppExp (Range start maybe_step end loc) _) = do checkExp (Ascript e te loc) = do (te', e') <- checkAscript loc te e pure $ Ascript e' te' loc -checkExp (Coerce e te NoInfo loc) = do +checkExp (Coerce e te _ loc) = do (te', te_t, e') <- checkCoerce loc te e t <- expTypeFully e' t' <- matchDims (const . const pure) t te_t pure $ Coerce e' te' (Info t') loc -checkExp (AppExp (BinOp (op, oploc) NoInfo (e1, _) (e2, _) loc) NoInfo) = do - ftype <- lookupVar oploc op +checkExp (AppExp (Apply fe args loc) _) = do + fe' <- checkExp fe + let ams = fmap (snd . unInfo . fst) args + args' <- mapM (checkExp . snd) args + t <- expType fe' + let fname = + case fe' of + Var v _ _ -> Just v + _ -> Nothing + ((_, exts, rt), args'') <- mapAccumLM (onArg fname) (0, [], t) (NE.zip args' ams) + + pure $ AppExp (Apply fe' args'' loc) $ Info $ AppRes rt exts + where + onArg fname (i, all_exts, t) (arg', am) = do + (_, rt, argext, exts, am') <- checkApply loc (fname, i) t arg' am + pure + ( (i + 1, all_exts <> exts, rt), + (Info (argext, am'), arg') + ) +checkExp (AppExp (BinOp (op, oploc) (Info op_t) (e1, Info (_, xam)) (e2, Info (_, yam)) loc) _) = do + ftype <- lookupVar oploc op op_t e1' <- checkExp e1 e2' <- checkExp e2 - -- Note that the application to the first operand cannot fix any -- existential sizes, because it must by necessity be a function. - (_, rt, p1_ext, _) <- checkApply loc (Just op, 0) ftype e1' - (_, rt', p2_ext, retext) <- checkApply loc (Just op, 1) rt e2' + (_, rt, p1_ext, _, am1) <- checkApply loc (Just op, 0) ftype e1' xam + (_, rt', p2_ext, retext, am2) <- checkApply loc (Just op, 1) rt e2' yam pure $ AppExp ( BinOp (op, oploc) (Info ftype) - (e1', Info p1_ext) - (e2', Info p2_ext) + (e1', Info (p1_ext, am1)) + (e2', Info (p2_ext, am2)) loc ) (Info (AppRes rt' retext)) -checkExp (Project k e NoInfo loc) = do +checkExp (Project k e _ loc) = do e' <- checkExp e t <- expType e' - kt <- mustHaveField (mkUsage loc $ docText $ "projection of field " <> dquotes (pretty k)) k t - pure $ Project k e' (Info kt) loc -checkExp (AppExp (If e1 e2 e3 loc) _) = do - e1' <- checkExp e1 - e2' <- checkExp e2 - e3' <- checkExp e3 - - let bool = Scalar $ Prim Bool - e1_t <- expType e1' - onFailure (CheckingRequired [bool] e1_t) $ - unify (mkUsage e1' "use as 'if' condition") bool e1_t - - (brancht, retext) <- unifyBranches loc e2' e3' - - zeroOrderType - (mkUsage loc "returning value of this type from 'if' expression") - "type returned from branch" - brancht - - pure $ AppExp (If e1' e2' e3' loc) (Info $ AppRes brancht retext) + case t of + Scalar (Record fs) + | Just kt <- M.lookup k fs -> + pure $ Project k e' (Info kt) loc + _ -> error $ "checkExp Project: " <> show t checkExp (Parens e loc) = Parens <$> checkExp e <*> pure loc checkExp (QualParens (modname, modnameloc) e loc) = do @@ -461,33 +461,12 @@ checkExp (QualParens (modname, modnameloc) e loc) = do ModFun {} -> typeError loc mempty . withIndexLink "module-is-parametric" $ "Module" <+> pretty modname <+> " is a parametric module." -checkExp (Var qn NoInfo loc) = do - t <- lookupVar loc qn - pure $ Var qn (Info t) loc checkExp (Negate arg loc) = do - arg' <- require "numeric negation" anyNumberType =<< checkExp arg + arg' <- checkExp arg pure $ Negate arg' loc checkExp (Not arg loc) = do - arg' <- require "logical negation" (Bool : anyIntType) =<< checkExp arg + arg' <- checkExp arg pure $ Not arg' loc -checkExp (AppExp (Apply fe args loc) NoInfo) = do - fe' <- checkExp fe - args' <- mapM (checkExp . snd) args - t <- expType fe' - let fname = - case fe' of - Var v _ _ -> Just v - _ -> Nothing - ((_, exts, rt), args'') <- mapAccumLM (onArg fname) (0, [], t) args' - - pure $ AppExp (Apply fe' args'' loc) $ Info $ AppRes rt exts - where - onArg fname (i, all_exts, t) arg' = do - (_, rt, argext, exts) <- checkApply loc (fname, i) t arg' - pure - ( (i + 1, all_exts <> exts, rt), - (Info argext, arg') - ) checkExp (AppExp (LetPat sizes pat e body loc) _) = do e' <- checkExp e @@ -516,7 +495,7 @@ checkExp (AppExp (LetPat sizes pat e body loc) _) = do AppExp (LetPat sizes (fmap toStruct pat') e' body' loc) (Info $ AppRes body_t' retext) -checkExp (AppExp (LetFun name (tparams, params, maybe_retdecl, NoInfo, e) body loc) _) = do +checkExp (AppExp (LetFun name (tparams, params, maybe_retdecl, _, e) body loc) _) = do (tparams', params', maybe_retdecl', rettype, e') <- checkBinding (fst name, maybe_retdecl, tparams, params, e, loc) @@ -539,16 +518,18 @@ checkExp (AppExp (LetFun name (tparams, params, maybe_retdecl, NoInfo, e) body l ) (Info $ AppRes body_t ext) checkExp (AppExp (LetWith dest src slice ve body loc) _) = do - src' <- checkIdent src + src_t <- lookupVar loc (qualName (identName src)) (unInfo (identType src)) + let src' = src {identType = Info src_t} + dest' = dest {identType = Info src_t} slice' <- checkSlice slice - (t, _) <- newArrayType (mkUsage src "type of source array") "src" $ sliceDims slice' + (t, _) <- newArrayType (mkUsage src' "type of source array") "src" $ sliceDims slice' unify (mkUsage loc "type of target array") t $ unInfo $ identType src' (elemt, _) <- sliceShape (Just (loc, Nonrigid)) slice' =<< normTypeFully t ve' <- unifies "type of target array" elemt =<< checkExp ve - bindingIdent dest (unInfo (identType src')) $ \dest' -> do + bindingIdent dest' $ do body' <- checkExp body (body_t, ext) <- unscopeType loc [identName dest'] =<< expTypeFully body' pure $ AppExp (LetWith dest' src' slice' ve' body' loc) (Info $ AppRes body_t ext) @@ -563,11 +544,9 @@ checkExp (Update src slice ve loc) = do -- Record updates are a bit hacky, because we do not have row typing -- (yet?). For now, we only permit record updates where we know the -- full type up to the field we are updating. -checkExp (RecordUpdate src fields ve NoInfo loc) = do +checkExp (RecordUpdate src fields ve _ loc) = do src' <- checkExp src ve' <- checkExp ve - a <- expTypeFully src' - foldM_ (flip $ mustHaveField usage) a fields ve_t <- expType ve' updated_t <- updateField fields ve_t =<< expTypeFully src' pure $ RecordUpdate src' fields ve' (Info updated_t) loc @@ -599,30 +578,35 @@ checkExp (AppExp (Index e slice loc) _) = do =<< expTypeFully e' pure $ AppExp (Index e' slice' loc) (Info $ AppRes t' retext) -checkExp (Assert e1 e2 NoInfo loc) = do - e1' <- require "being asserted" [Bool] =<< checkExp e1 +checkExp (Assert e1 e2 _ loc) = do + e1' <- checkExp e1 e2' <- checkExp e2 pure $ Assert e1' e2' (Info (prettyText e1)) loc -checkExp (Lambda params body rettype_te NoInfo loc) = do +checkExp (Lambda params body rettype_te (Info (RetType _ rt)) loc) = do (params', body', rettype', RetType dims ty) <- incLevel . bindingParams [] params $ \params' -> do + rt' <- replaceTyVars loc rt rettype_checked <- traverse checkTypeExpNonrigid rettype_te - let declared_rettype = - case rettype_checked of - Just (_, st, _) -> Just st - Nothing -> Nothing + declared_rettype <- + case rettype_checked of + Just (_, st, _) -> do + unify (mkUsage body "lambda return type ascription") (toStruct rt') (toStruct st) + pure $ Just st + Nothing -> pure Nothing body' <- checkFunBody params' body declared_rettype loc body_t <- expTypeFully body' + unify (mkUsage body "inferred return type") (toStruct rt') body_t + params'' <- mapM updateTypes params' - (rettype', rettype_st) <- - case rettype_checked of - Just (te, st, ext) -> - pure (Just te, RetType ext st) - Nothing -> do - ret <- inferReturnSizes params'' $ toRes Nonunique body_t - pure (Nothing, ret) + (rettype', rettype_st) <- case rettype_checked of + Just (te, ret, ext) -> do + ret' <- normTypeFully ret + pure (Just te, RetType ext ret') + Nothing -> do + ret <- inferReturnSizes params'' $ toRes Nonunique body_t + pure (Nothing, ret) pure (params'', body', rettype', rettype_st) @@ -655,37 +639,38 @@ checkExp (Lambda params body rettype_te NoInfo loc) = do onDim _ = mempty pure $ RetType (S.toList $ foldMap onDim $ fvVars $ freeInType ret) ret -checkExp (OpSection op _ loc) = do - ftype <- lookupVar loc op +checkExp (OpSection op (Info op_t) loc) = do + ftype <- lookupVar loc op op_t pure $ OpSection op (Info ftype) loc -checkExp (OpSectionLeft op _ e _ _ loc) = do - ftype <- lookupVar loc op +checkExp (OpSectionLeft op (Info op_t) e (Info (_, _, _, am), _) _ loc) = do + ftype <- lookupVar loc op op_t e' <- checkExp e - (t1, rt, argext, retext) <- checkApply loc (Just op, 0) ftype e' + (t1, rt, argext, retext, am') <- checkApply loc (Just op, 0) ftype e' am case (ftype, rt) of - (Scalar (Arrow _ m1 d1 _ _), Scalar (Arrow _ m2 d2 t2 rettype)) -> + (Scalar (Arrow _ m1 d1 _ _), Scalar (Arrow _ m2 d2 t2 (RetType ds rt2))) -> pure $ OpSectionLeft op (Info ftype) e' - (Info (m1, toParam d1 t1, argext), Info (m2, toParam d2 t2)) - (Info rettype, Info retext) + (Info (m1, toParam d1 t1, argext, am'), Info (m2, toParam d2 t2)) + (Info $ RetType ds $ arrayOfWithAliases (uniqueness rt2) (autoFrame am') rt2, Info retext) loc _ -> typeError loc mempty $ "Operator section with invalid operator of type" <+> pretty ftype -checkExp (OpSectionRight op _ e _ NoInfo loc) = do - ftype <- lookupVar loc op +checkExp (OpSectionRight op (Info op_t) e (_, Info (_, _, _, am)) _ loc) = do + ftype <- lookupVar loc op op_t e' <- checkExp e case ftype of Scalar (Arrow _ m1 d1 t1 (RetType [] (Scalar (Arrow _ m2 d2 t2 (RetType dims2 ret))))) -> do - (t2', arrow', argext, _) <- + (t2', arrow', argext, _, am') <- checkApply loc (Just op, 1) (Scalar $ Arrow mempty m2 d2 t2 $ RetType [] $ Scalar $ Arrow Nonunique m1 d1 t1 $ RetType dims2 ret) e' + am case arrow' of Scalar (Arrow _ _ _ t1' (RetType dims2' ret')) -> pure $ @@ -693,20 +678,22 @@ checkExp (OpSectionRight op _ e _ NoInfo loc) = do op (Info ftype) e' - (Info (m1, toParam d1 t1'), Info (m2, toParam d2 t2', argext)) - (Info $ RetType dims2' ret') + (Info (m1, toParam d1 t1'), Info (m2, toParam d2 t2', argext, am')) + (Info $ RetType dims2' $ arrayOfWithAliases (uniqueness ret') (autoFrame am') ret') loc _ -> error $ "OpSectionRight: impossible type\n" <> prettyString arrow' _ -> typeError loc mempty $ "Operator section with invalid operator of type" <+> pretty ftype -checkExp (ProjectSection fields NoInfo loc) = do - a <- newTypeVar loc "a" - let usage = mkUsage loc "projection at" - b <- foldM (flip $ mustHaveField usage) a fields - let ft = Scalar $ Arrow mempty Unnamed Observe a $ RetType [] $ toRes Nonunique b - pure $ ProjectSection fields (Info ft) loc -checkExp (IndexSection slice NoInfo loc) = do +checkExp (ProjectSection fields (Info t) loc) = do + t' <- replaceTyVars loc t + case t' of + Scalar (Arrow _ _ _ t'' (RetType _ rt)) + | Just ft <- recordField fields t'' -> + unify (mkUsage loc "result of projection") ft $ toStruct rt + _ -> error $ "checkExp ProjectSection: " <> show t' + pure $ ProjectSection fields (Info t') loc +checkExp (IndexSection slice _ loc) = do slice' <- checkSlice slice (t, _) <- newArrayType (mkUsage' loc) "e" $ sliceDims slice' (t', retext) <- sliceShape Nothing slice' t @@ -719,27 +706,57 @@ checkExp (AppExp (Loop _ mergepat loopinit form loopbody loc) _) = do AppExp (Loop sparams mergepat' loopinit' form' loopbody' loc) (Info appres) -checkExp (Constr name es NoInfo loc) = do - t <- newTypeVar loc "t" +checkExp (Constr name es (Info t) loc) = do + t' <- replaceTyVars loc t es' <- mapM checkExp es - ets <- mapM expType es' - mustHaveConstr (mkUsage loc "use of constructor") name t ets - pure $ Constr name es' (Info t) loc + case t' of + Scalar (Sum cs) + | Just name_ts <- M.lookup name cs -> + zipWithM_ (unify $ mkUsage loc "inferred variant") name_ts $ + map typeOf es' + _ -> + error $ "checkExp Constr: " <> prettyString t' + pure $ Constr name es' (Info t') loc +checkExp (AppExp (If e1 e2 e3 loc) _) = do + e1' <- checkExp e1 + e2' <- checkExp e2 + e3' <- checkExp e3 + + let bool = Scalar $ Prim Bool + e1_t <- expType e1' + onFailure (CheckingRequired [bool] e1_t) $ + unify (mkUsage e1' "use as 'if' condition") bool e1_t + + (t, retext) <- unifyBranches loc e2' e3' + + mustBeOrderZero (locOf loc) t + + pure $ AppExp (If e1' e2' e3' loc) (Info $ AppRes t retext) checkExp (AppExp (Match e cs loc) _) = do e' <- checkExp e mt <- expType e' (cs', t, retext) <- checkCases mt cs - zeroOrderType - (mkUsage loc "being returned 'match'") - "type returned from pattern match" - t + + mustBeOrderZero (locOf loc) t + pure $ AppExp (Match e' cs' loc) (Info $ AppRes t retext) checkExp (Attr info e loc) = Attr <$> checkAttr info <*> checkExp e <*> pure loc +checkCase :: + StructType -> + CaseBase Info VName -> + TermTypeM (CaseBase Info VName, StructType, [VName]) +checkCase mt (CasePat p e loc) = + bindingPat [] p mt $ \p' -> do + e' <- checkExp e + e_t <- expTypeFully e' + (e_t', retext) <- unscopeType loc (patNames p') e_t + pure (CasePat (fmap toStruct p') e' loc, e_t', retext) + checkCases :: StructType -> - NE.NonEmpty (CaseBase NoInfo VName) -> + NE.NonEmpty (CaseBase Info VName) -> TermTypeM (NE.NonEmpty (CaseBase Info VName), StructType, [VName]) checkCases mt rest_cs = case NE.uncons rest_cs of @@ -752,17 +769,6 @@ checkCases mt rest_cs = (brancht, retext) <- unifyBranchTypes (srclocOf c) c_t cs_t pure (NE.cons c' cs', brancht, retext) -checkCase :: - StructType -> - CaseBase NoInfo VName -> - TermTypeM (CaseBase Info VName, StructType, [VName]) -checkCase mt (CasePat p e loc) = - bindingPat [] p mt $ \p' -> do - e' <- checkExp e - e_t <- expTypeFully e' - (e_t', retext) <- unscopeType loc (patNames p') e_t - pure (CasePat (fmap toStruct p') e' loc, e_t', retext) - -- | An unmatched pattern. Used in in the generation of -- unmatched pattern warnings by the type checker. data Unmatched p @@ -791,22 +797,13 @@ instance Pretty (Unmatched (Pat StructType)) where pretty' (PatLit e _ _) = pretty e pretty' (PatConstr n _ ps _) = "#" <> pretty n <+> sep (map pretty' ps) -checkIdent :: IdentBase NoInfo VName StructType -> TermTypeM (Ident StructType) -checkIdent (Ident name _ loc) = do - vt <- lookupVar loc $ qualName name - pure $ Ident name (Info vt) loc - -checkSlice :: SliceBase NoInfo VName -> TermTypeM [DimIndex] +checkSlice :: SliceBase Info VName -> TermTypeM [DimIndex] checkSlice = mapM checkDimIndex where - checkDimIndex (DimFix i) = do - DimFix <$> (require "use as index" anySignedType =<< checkExp i) + checkDimIndex (DimFix i) = + DimFix <$> checkExp i checkDimIndex (DimSlice i j s) = - DimSlice <$> check i <*> check j <*> check s - - check = - maybe (pure Nothing) $ - fmap Just . unifies "use as index" (Scalar $ Prim $ Signed Int64) <=< checkExp + DimSlice <$> traverse checkExp i <*> traverse checkExp j <*> traverse checkExp s -- The number of dimensions affected by this slice (so the minimum -- rank of the array we are slicing). @@ -869,16 +866,55 @@ dimUses = flip execState mempty . traverseDims f where fv = freeInExp e `freeWithout` bound +splitArrayAt :: Int -> StructType -> (Shape Size, StructType) +splitArrayAt x t = + (Shape $ take x $ shapeDims $ arrayShape t, stripArray x t) + checkApply :: SrcLoc -> ApplyOp -> StructType -> Exp -> - TermTypeM (StructType, StructType, Maybe VName, [VName]) -checkApply loc (fname, _) (Scalar (Arrow _ pname _ tp1 tp2)) argexp = do + AutoMap -> + TermTypeM (StructType, StructType, Maybe VName, [VName], AutoMap) +checkApply loc fn@(fname, _) ft@(Scalar (Arrow _ pname _ tp1 tp2)) argexp am = do let argtype = typeOf argexp onFailure (CheckingApply fname argexp tp1 argtype) $ do - unify (mkUsage argexp "use as function argument") tp1 argtype + -- argtype = arg_frame argtype' + -- tp1 = f_frame tp1' + -- + -- Rep case: + -- R arg_frame argtype' = f_frame tp1' + -- ==> R = (autoRepRank am)-length prefix of tp1 + -- ==> frame = f_frame = (autoFrameRank am)-length prefix of tp1 + -- + -- Map case: + -- arg_frame argtype' = M f_frame tp1' + -- ==> M = (autoMapRank am)-length prefix of argtype + -- ==> frame = M f_frame = (autoFrameRank am)-length prefix of argtype + (am_map_shape, argtype_with_frame) <- splitArrayAt (autoMapRank am) <$> normTypeFully argtype + (am_rep_shape, tp1_with_frame) <- splitArrayAt (autoRepRank am) <$> normTypeFully tp1 + (am_frame_shape, _) <- + if autoMapRank am == 0 + then splitArrayAt (autoFrameRank am) <$> normTypeFully tp1 + else splitArrayAt (autoFrameRank am) <$> normTypeFully argtype + + debugTraceM 3 $ + unlines + [ "## checkApply", + "## fn", + prettyString fn, + "## ft", + prettyString ft, + "## tp1_with_frame", + prettyString tp1_with_frame, + "## argtype_with_frame", + prettyString argtype_with_frame, + "## am", + show am + ] + + unify (mkUsage argexp "use as function argument") tp1_with_frame argtype_with_frame -- Perform substitutions of instantiated variables in the types. (tp2', ext) <- instantiateDimsInReturnType loc fname =<< normTypeFully tp2 @@ -918,68 +954,60 @@ checkApply loc (fname, _) (Scalar (Arrow _ pname _ tp1 tp2)) argexp = do in pure (Nothing, applySubst parsubst $ toStruct tp2') _ -> pure (Nothing, toStruct tp2') - pure (tp1, tp2'', argext, ext) -checkApply loc fname tfun@(Scalar TypeVar {}) arg = do - tv <- newTypeVar loc "b" - unify (mkUsage loc "use as function") tfun $ - Scalar (Arrow mempty Unnamed Observe (typeOf arg) $ RetType [] $ paramToRes tv) - tfun' <- normType tfun - checkApply loc fname tfun' arg -checkApply loc (fname, prev_applied) ftype argexp = do - let fname' = maybe "expression" (dquotes . pretty) fname - - typeError loc mempty $ - if prev_applied == 0 - then - "Cannot apply" - <+> fname' - <+> "as function, as it has type:" - indent 2 (pretty ftype) - else - "Cannot apply" - <+> fname' - <+> "to argument #" - <> pretty (prev_applied + 1) - <+> dquotes (shorten $ group $ pretty argexp) - <> "," - "as" - <+> fname' - <+> "only takes" - <+> pretty prev_applied - <+> arguments - <> "." + let am' = + AutoMap + { autoRep = am_rep_shape, + autoMap = am_map_shape, + autoFrame = am_frame_shape + } + + pure (tp1, distribute (arrayOf (autoMap am') tp2''), argext, ext, am') where - arguments - | prev_applied == 1 = "argument" - | otherwise = "arguments" + distribute :: TypeBase dim u -> TypeBase dim u + distribute (Array u s (Arrow _ _ _ ta (RetType rd tr))) = + Scalar $ + Arrow + u + Unnamed + mempty + (arrayOf s ta) + (RetType rd $ distribute (arrayOfWithAliases (uniqueness tr) s tr)) + distribute t = t +checkApply _ _ _ _ _ = + error "checkApply: array" -- | Type-check a single expression in isolation. This expression may -- turn out to be polymorphic, in which case the list of type -- parameters will be non-empty. checkOneExp :: ExpBase NoInfo VName -> TypeM ([TypeParam], Exp) -checkOneExp e = runTermTypeM checkExp $ do - e' <- checkExp e - (tparams, _, RetType _ t') <- - letGeneralise (nameFromString "") (srclocOf e) [] [] $ - toRes Nonunique $ - typeOf e' - fixOverloadedTypes $ typeVars t' - e'' <- normTypeFully e' - localChecks e'' - causalityCheck e'' - pure (tparams, e'') +checkOneExp e = do + (maybe_tysubsts, e') <- Unsized.checkSingleExp e + case maybe_tysubsts of + Left err -> throwError err + Right (_generalised, tysubsts) -> runTermTypeM checkExp tysubsts $ do + e'' <- checkExp e' + let t = typeOf e'' + (tparams, _, RetType _ t') <- + letGeneralise (nameFromString "") (srclocOf e) [] [] $ toRes Nonunique t + fixOverloadedTypes $ typeVars t' + e''' <- normTypeFully e'' + localChecks e''' + causalityCheck e''' + pure (tparams, e''') -- | Type-check a single size expression in isolation. This expression may -- turn out to be polymorphic, in which case it is unified with i64. checkSizeExp :: ExpBase NoInfo VName -> TypeM Exp -checkSizeExp e = runTermTypeM checkExp $ do - e' <- checkExp e - let t = typeOf e' - when (hasBinding e') $ - typeError (srclocOf e') mempty . withIndexLink "size-expression-bind" $ - "Size expression with binding is forbidden." - unify (mkUsage e' "Size expression") t (Scalar (Prim (Signed Int64))) - normTypeFully e' +checkSizeExp e = do + (maybe_tysubsts, e') <- Unsized.checkSizeExp e + case maybe_tysubsts of + Left err -> throwError err + Right (_generalised, tysubsts) -> runTermTypeM checkExp tysubsts $ do + e'' <- checkExp e' + when (hasBinding e'') $ + typeError (srclocOf e'') mempty . withIndexLink "size-expression-bind" $ + "Size expression with binding is forbidden." + normTypeFully e'' -- Verify that all sum type constructors and empty array literals have -- a size that is known (rigid or a type parameter). This is to @@ -1049,7 +1077,7 @@ causalityCheck binding_body = do seqArgs known' [] = do void $ onExp known' f modify (S.fromList (appResExt res) <>) - seqArgs known' ((Info p, x) : xs) = do + seqArgs known' ((Info (p, _), x) : xs) = do new_known <- collectingNewKnown $ onExp known' x void $ seqArgs (new_known <> known') xs modify ((new_known <> S.fromList (maybeToList p)) <>) @@ -1068,7 +1096,7 @@ causalityCheck binding_body = do modify (new_known <>) onExp known - e@(AppExp (BinOp (f, floc) ft (x, Info xp) (y, Info yp) _) (Info res)) = do + e@(AppExp (BinOp (f, floc) ft (x, Info (xp, _)) (y, Info (yp, _)) _) (Info res)) = do args_known <- collectingNewKnown $ sequencePoint known x y $ catMaybes [xp, yp] void $ onExp (args_known <> known) (Var f ft floc) @@ -1131,6 +1159,14 @@ mustBeIrrefutable p = do "Refutable pattern not allowed here.\nUnmatched cases:" indent 2 (stack (map pretty ps')) +supportsEquality :: TypeBase dim u -> Bool +supportsEquality (Array _ _ t) = supportsEquality $ Scalar t +supportsEquality (Scalar Prim {}) = True +supportsEquality (Scalar TypeVar {}) = False +supportsEquality (Scalar (Record fs)) = all supportsEquality fs +supportsEquality (Scalar (Sum fs)) = all (all supportsEquality) fs +supportsEquality (Scalar Arrow {}) = False + -- | Traverse the expression, emitting warnings and errors for various -- problems: -- @@ -1151,6 +1187,12 @@ localChecks = void . check indent 2 (stack (map pretty ps')) check e@(AppExp (LetPat _ p _ _ _) _) = mustBeIrrefutable p *> recurse e + check e@(AppExp (BinOp (v, loc) _ (x, _) _ _) _) + | qualLeaf v == intrinsicVar "==" = + checkEquality loc (typeOf x) *> recurse e + check e@(Var v (Info t) loc) + | qualLeaf v == intrinsicVar "==" = + checkEquality loc t *> recurse e check e@(Lambda ps _ _ _ _) = mapM_ (mustBeIrrefutable . fmap toStruct) ps *> recurse e check e@(AppExp (LetFun _ (_, ps, _, _, _) _ _) _) = @@ -1184,6 +1226,13 @@ localChecks = void . check check e = recurse e recurse = astMap identityMapper {mapOnExp = check} + checkEquality loc t = + unless (supportsEquality t) $ + typeError loc mempty $ + "Comparing equality of values of type" + indent 2 (pretty t) + "which does not support equality." + bitWidth ty = 8 * intByteSize ty :: Int inBoundsI x (Signed t) = x >= -2 ^ (bitWidth t - 1) && x < 2 ^ (bitWidth t - 1) @@ -1205,107 +1254,18 @@ localChecks = void . check <> pretty ty <> "." --- | Type-check a top-level (or module-level) function definition. --- Despite the name, this is also used for checking constant --- definitions, by treating them as 0-ary functions. -checkFunDef :: - ( VName, - Maybe (TypeExp (ExpBase NoInfo VName) VName), - [TypeParam], - [PatBase NoInfo VName ParamType], - ExpBase NoInfo VName, - SrcLoc - ) -> - TypeM - ( [TypeParam], - [Pat ParamType], - Maybe (TypeExp Exp VName), - ResRetType, - Exp - ) -checkFunDef (fname, maybe_retdecl, tparams, params, body, loc) = - runTermTypeM checkExp $ do - (tparams', params', maybe_retdecl', RetType dims rettype', body') <- - checkBinding (fname, maybe_retdecl, tparams, params, body, loc) - - -- Since this is a top-level function, we also resolve overloaded - -- types, using either defaults or complaining about ambiguities. - fixOverloadedTypes $ - typeVars rettype' <> foldMap (typeVars . patternType) params' - - -- Then replace all inferred types in the body and parameters. - body'' <- normTypeFully body' - params'' <- mapM normTypeFully params' - maybe_retdecl'' <- traverse updateTypes maybe_retdecl' - rettype'' <- normTypeFully rettype' - - -- Check if the function body can actually be evaluated. - causalityCheck body'' - - -- Check for various problems. - mapM_ (mustBeIrrefutable . fmap toStruct) params' - localChecks body'' - - let ((body''', updated_ret), errors) = - Consumption.checkValDef - ( fname, - params'', - body'', - RetType dims rettype'', - maybe_retdecl'', - loc - ) - - mapM_ throwError errors - - pure (tparams', params'', maybe_retdecl'', updated_ret, body''') - -- | This is "fixing" as in "setting them", not "correcting them". We -- only make very conservative fixing. fixOverloadedTypes :: Names -> TermTypeM () fixOverloadedTypes tyvars_at_toplevel = getConstraints >>= mapM_ fixOverloaded . M.toList . M.map snd where - fixOverloaded (v, Overloaded ots usage) - | Signed Int32 `elem` ots = do - unify usage (Scalar (TypeVar mempty (qualName v) [])) $ - Scalar (Prim $ Signed Int32) - when (v `S.member` tyvars_at_toplevel) $ - warn usage "Defaulting ambiguous type to i32." - | FloatType Float64 `elem` ots = do - unify usage (Scalar (TypeVar mempty (qualName v) [])) $ - Scalar (Prim $ FloatType Float64) - when (v `S.member` tyvars_at_toplevel) $ - warn usage "Defaulting ambiguous type to f64." - | otherwise = - typeError usage mempty . withIndexLink "ambiguous-type" $ - "Type is ambiguous (could be one of" - <+> commasep (map pretty ots) - <> ")." - "Add a type annotation to disambiguate the type." fixOverloaded (v, NoConstraint _ usage) = do -- See #1552. unify usage (Scalar (TypeVar mempty (qualName v) [])) $ Scalar (tupleRecord []) when (v `S.member` tyvars_at_toplevel) $ warn usage "Defaulting ambiguous type to ()." - fixOverloaded (_, Equality usage) = - typeError usage mempty . withIndexLink "ambiguous-type" $ - "Type is ambiguous (must be equality type)." - "Add a type annotation to disambiguate the type." - fixOverloaded (_, HasFields _ fs usage) = - typeError usage mempty . withIndexLink "ambiguous-type" $ - "Type is ambiguous. Must be record with fields:" - indent 2 (stack $ map field $ M.toList fs) - "Add a type annotation to disambiguate the type." - where - field (l, t) = pretty l <> colon <+> align (pretty t) - fixOverloaded (_, HasConstrs _ cs usage) = - typeError usage mempty . withIndexLink "ambiguous-type" $ - "Type is ambiguous (must be a sum type with constructors:" - <+> pretty (Sum cs) - <> ")." - "Add a type annotation to disambiguate the type." fixOverloaded (v, Size Nothing (Usage Nothing loc)) = typeError loc mempty . withIndexLink "ambiguous-size" $ "Ambiguous size" <+> dquotes (prettyName v) <> "." @@ -1337,10 +1297,10 @@ inferredReturnType loc params t = do checkBinding :: ( VName, - Maybe (TypeExp (ExpBase NoInfo VName) VName), + Maybe (TypeExp Exp VName), [TypeParam], - [PatBase NoInfo VName ParamType], - ExpBase NoInfo VName, + [PatBase Info VName ParamType], + ExpBase Info VName, SrcLoc ) -> TermTypeM @@ -1378,7 +1338,8 @@ checkBinding (fname, maybe_retdecl, tparams, params, body, loc) = verifyFunctionParams (Just fname) params'' (tparams', params''', rettype') <- - letGeneralise (baseName fname) loc tparams params'' =<< unscopeUnknown rettype + letGeneralise (baseName fname) loc tparams params'' + =<< unscopeUnknown rettype when ( null params @@ -1494,15 +1455,18 @@ closeOverTypes defname defloc tparams paramts ret substs = do case M.lookup v substs of Just (_, UnknownSize {}) -> Just v _ -> Nothing + pure - ( tparams ++ more_tparams, + ( tparams + ++ more_tparams, injectExt (nubOrd $ retext ++ mapMaybe mkExt (S.toList $ fvVars $ freeInType ret)) ret ) where -- Diet does not matter here. t = foldFunType (map (toParam Observe) paramts) $ RetType [] ret - to_close_over = M.filterWithKey (\k _ -> k `S.member` visible) substs visible = typeVars t <> fvVars (freeInType t) + to_close_over = + M.filterWithKey (\k _ -> k `S.member` visible) substs (produced_sizes, param_sizes) = dimUses t @@ -1549,19 +1513,13 @@ letGeneralise defname defloc tparams params restype = -- -- (2) are not used in the (new) definition of any type variables -- known before we checked this function. - -- - -- (3) are not referenced from an overloaded type (for example, - -- are the element types of an incompletely resolved record type). - -- This is a bit more restrictive than I'd like, and SML for - -- example does not have this restriction. - -- + -- Criteria (1) and (2) is implemented by looking at the binding -- level of the type variables. - let keep_type_vars = overloadedTypeVars now_substs cur_lvl <- curLevel - let candidate k (lvl, _) = (k `S.notMember` keep_type_vars) && lvl >= (cur_lvl - length params) - new_substs = M.filterWithKey candidate now_substs + let candidate (lvl, _) = lvl >= (cur_lvl - length params) + new_substs = M.filter candidate now_substs (tparams', RetType ret_dims restype') <- closeOverTypes @@ -1589,7 +1547,7 @@ letGeneralise defname defloc tparams params restype = checkFunBody :: [Pat ParamType] -> - ExpBase NoInfo VName -> + Exp -> Maybe ResType -> SrcLoc -> TermTypeM Exp @@ -1632,3 +1590,67 @@ arrayOfM :: arrayOfM loc t shape = do arrayElemType (mkUsage loc "use as array element") "type used in array" t pure $ arrayOf shape t + +-- | Type-check a top-level (or module-level) function definition. +-- Despite the name, this is also used for checking constant +-- definitions, by treating them as 0-ary functions. +checkFunDef :: + ( VName, + Maybe (TypeExp (ExpBase NoInfo VName) VName), + [TypeParam], + [PatBase NoInfo VName ParamType], + ExpBase NoInfo VName, + SrcLoc + ) -> + TypeM + ( [TypeParam], + [Pat ParamType], + Maybe (TypeExp Exp VName), + ResRetType, + Exp + ) +checkFunDef (fname, retdecl, tparams, params, body, loc) = + doChecks =<< Unsized.checkValDef (fname, retdecl, tparams, params, body, loc) + where + -- TODO: Print out the possibilities. (And also potentially eliminate + --- some of the possibilities to disambiguate). + + doChecks (maybe_tysubsts, params', retdecl', body') = + case maybe_tysubsts of + Left err -> throwError err + Right (generalised, tysubsts) -> + runTermTypeM checkExp tysubsts $ do + (tparams', params'', retdecl'', RetType dims rettype', body'') <- + checkBinding (fname, retdecl', generalised <> tparams, params', body', loc) + + -- Since this is a top-level function, we also resolve overloaded + -- types, using either defaults or complaining about ambiguities. + fixOverloadedTypes $ + typeVars rettype' <> foldMap (typeVars . patternType) params'' + + -- Then replace all inferred types in the body and parameters. + body''' <- normTypeFully body'' + params''' <- mapM normTypeFully params'' + retdecl''' <- traverse updateTypes retdecl'' + rettype'' <- normTypeFully rettype' + + -- Check if the function body can actually be evaluated. + causalityCheck body''' + + -- Check for various problems. + mapM_ (mustBeIrrefutable . fmap toStruct) params'' + localChecks body''' + + let ((body'''', updated_ret), errors) = + Consumption.checkValDef + ( fname, + params''', + body''', + RetType dims rettype'', + retdecl''', + loc + ) + + mapM_ throwError errors + + pure (tparams', params''', retdecl''', updated_ret, body'''') diff --git a/src/Language/Futhark/TypeChecker/Terms/Loop.hs b/src/Language/Futhark/TypeChecker/Terms/Loop.hs index 51067a6537..781b989b6f 100644 --- a/src/Language/Futhark/TypeChecker/Terms/Loop.hs +++ b/src/Language/Futhark/TypeChecker/Terms/Loop.hs @@ -102,7 +102,7 @@ wellTypedLoopArg src sparams pat arg = do -- | An un-checked loop. type UncheckedLoop = - (PatBase NoInfo VName ParamType, LoopInitBase NoInfo VName, LoopFormBase NoInfo VName, ExpBase NoInfo VName) + (Pat ParamType, LoopInitBase Info VName, LoopFormBase Info VName, Exp) -- | A loop that has been type-checked. type CheckedLoop = @@ -129,22 +129,14 @@ checkForImpossible loc known_before pat_t = do -- | Type-check a @loop@ expression, passing in a function for -- type-checking subexpressions. checkLoop :: - (ExpBase NoInfo VName -> TermTypeM Exp) -> + (Exp -> TermTypeM Exp) -> UncheckedLoop -> SrcLoc -> TermTypeM (CheckedLoop, AppRes) checkLoop checkExp (mergepat, loopinit, form, loopbody) loc = do - loopinit' <- checkExp $ case loopinit of - LoopInitExplicit e -> e - LoopInitImplicit _ -> - -- Should have been filled out in Names - error "Unspected LoopInitImplicit" + loopinit' <- checkExp $ loopInitExp loopinit known_before <- M.keysSet <$> getConstraints - zeroOrderType - (mkUsage loopinit' "use as loop variable") - "type used as loop variable" - . toStruct - =<< expTypeFully loopinit' + mustBeOrderZero (locOf loopinit') =<< expTypeFully loopinit' -- The handling of dimension sizes is a bit intricate, but very -- similar to checking a function, followed by checking a call to @@ -245,20 +237,18 @@ checkLoop checkExp (mergepat, loopinit, form, loopbody) loc = do (sparams, mergepat', form', loopbody') <- case form of For i uboundexp -> do - uboundexp' <- - require "being the bound in a 'for' loop" anySignedType - =<< checkExp uboundexp - bound_t <- expTypeFully uboundexp' - bindingIdent i bound_t $ \i' -> - bindingPat [] mergepat merge_t $ \mergepat' -> incLevel $ do - loopbody' <- checkExp loopbody - (sparams, mergepat'') <- checkLoopReturnSize mergepat' loopbody' - pure - ( sparams, - mergepat'', - For i' uboundexp', - loopbody' - ) + uboundexp' <- checkExp uboundexp + it <- expType uboundexp' + let i' = i {identType = Info it} + bindingIdent i' . bindingParam mergepat merge_t $ \mergepat' -> incLevel $ do + loopbody' <- checkExp loopbody + (sparams, mergepat'') <- checkLoopReturnSize mergepat' loopbody' + pure + ( sparams, + mergepat'', + For i' uboundexp', + loopbody' + ) ForIn xpat e -> do (arr_t, _) <- newArrayType (mkUsage' (srclocOf e)) "e" 1 e' <- unifies "being iterated in a 'for-in' loop" arr_t =<< checkExp e @@ -267,7 +257,7 @@ checkLoop checkExp (mergepat, loopinit, form, loopbody) loc = do _ | Just t' <- peelArray 1 t -> bindingPat [] xpat t' $ \xpat' -> - bindingPat [] mergepat merge_t $ \mergepat' -> incLevel $ do + bindingParam mergepat merge_t $ \mergepat' -> incLevel $ do loopbody' <- checkExp loopbody (sparams, mergepat'') <- checkLoopReturnSize mergepat' loopbody' pure @@ -281,7 +271,7 @@ checkLoop checkExp (mergepat, loopinit, form, loopbody) loc = do "Iteratee of a for-in loop must be an array, but expression has type" <+> pretty t While cond -> - bindingPat [] mergepat merge_t $ \mergepat' -> + bindingParam mergepat merge_t $ \mergepat' -> incLevel $ do cond' <- checkExp cond diff --git a/src/Language/Futhark/TypeChecker/Terms/Monad.hs b/src/Language/Futhark/TypeChecker/Terms/Monad.hs index f21ef02699..ba30adbaeb 100644 --- a/src/Language/Futhark/TypeChecker/Terms/Monad.hs +++ b/src/Language/Futhark/TypeChecker/Terms/Monad.hs @@ -25,12 +25,15 @@ module Language.Futhark.TypeChecker.Terms.Monad constrain, newArrayType, allDimsFreshInType, + instTyVars, + replaceTyVars, updateTypes, Names, + mustBeOrderZero, + mustBeUnlifted, -- * Primitive checking unifies, - require, checkTypeExpNonrigid, lookupVar, lookupMod, @@ -50,8 +53,9 @@ import Control.Monad import Control.Monad.Except import Control.Monad.Reader import Control.Monad.State.Strict +import Data.Bifunctor import Data.Bitraversable -import Data.Char (isAscii) +import Data.Foldable import Data.Map.Strict qualified as M import Data.Maybe import Data.Set qualified as S @@ -61,6 +65,8 @@ import Futhark.FreshNames qualified import Futhark.Util.Pretty hiding (space) import Language.Futhark import Language.Futhark.Traversals +import Language.Futhark.TypeChecker.Constraints (TyVar) +import Language.Futhark.TypeChecker.Error import Language.Futhark.TypeChecker.Monad hiding (BoundV, lookupMod, stateNameSource) import Language.Futhark.TypeChecker.Monad qualified as TypeM import Language.Futhark.TypeChecker.Types @@ -83,6 +89,7 @@ unusedSize p = data Inferred t = NoneInferred | Ascribed t + deriving (Show) instance Functor Inferred where fmap _ NoneInferred = NoneInferred @@ -94,7 +101,7 @@ data Checking | CheckingAscription StructType StructType | CheckingLetGeneralise Name | CheckingParams (Maybe Name) - | CheckingPat (PatBase NoInfo VName StructType) (Inferred StructType) + | CheckingPat (PatBase Info VName StructType) (Inferred StructType) | CheckingLoopBody StructType StructType | CheckingLoopInitial StructType StructType | CheckingRecordUpdate [Name] StructType StructType @@ -196,8 +203,9 @@ data TermEnv = TermEnv { termScope :: TermScope, termChecking :: Maybe Checking, termLevel :: Level, - termChecker :: ExpBase NoInfo VName -> TermTypeM Exp, + termCheckExp :: ExpBase Info VName -> TermTypeM Exp, termOuterEnv :: Env, + termTyVars :: M.Map TyVar (TypeBase () NoUniqueness), termImportName :: ImportName } @@ -345,43 +353,120 @@ instance MonadUnify TermTypeM where indent 2 (pretty t2) "do not match." --- | Instantiate a type scheme with fresh type variables for its type --- parameters. Returns the names of the fresh type variables, the --- instance list, and the instantiated type. -instantiateTypeScheme :: +replaceTyVars :: SrcLoc -> TypeBase Size u -> TermTypeM (TypeBase Size u) +replaceTyVars loc orig_t = do + tyvars <- asks termTyVars + let f :: TypeBase Size u -> TermTypeM (TypeBase Size u) + f (Scalar (Prim t)) = pure $ Scalar $ Prim t + f + (Scalar (TypeVar u (QualName [] v) [])) + | Just t <- M.lookup v tyvars = + fst <$> allDimsFreshInType (mkUsage loc "replaceTyVars") Nonrigid "dv" (second (const u) t) + | otherwise = + pure $ Scalar (TypeVar u (QualName [] v) []) + f (Scalar (TypeVar u qn targs)) = + Scalar . TypeVar u qn <$> mapM onTyArg targs + where + onTyArg (TypeArgDim e) = pure $ TypeArgDim e + onTyArg (TypeArgType t) = TypeArgType <$> f t + f (Scalar (Record fs)) = + Scalar . Record <$> traverse f fs + f (Scalar (Sum fs)) = + Scalar . Sum <$> traverse (mapM f) fs + f (Scalar (Arrow u pname d ta (RetType ext tr))) = do + ta' <- f ta + tr' <- f tr + pure $ Scalar $ Arrow u pname d ta' $ RetType ext tr' + f (Array u shape t) = + arrayOfWithAliases u shape <$> f (Scalar t) + + f orig_t + +instTyVars :: + SrcLoc -> + [VName] -> + TypeBase () u -> + TypeBase Size u -> + TermTypeM (TypeBase Size u) +instTyVars loc names orig_t1 orig_t2 = do + tyvars <- asks termTyVars + let f :: + TypeBase d u -> + TypeBase Size u -> + StateT (M.Map VName (TypeBase Size NoUniqueness)) TermTypeM (TypeBase Size u) + f + (Scalar (TypeVar u (QualName [] v1) [])) + t2 + | Just t <- M.lookup v1 tyvars = + f (second (const u) t) t2 + f (Scalar (Record fs1)) (Scalar (Record fs2)) = + Scalar . Record <$> sequence (M.intersectionWith f fs1 fs2) + f (Scalar (Sum fs1)) (Scalar (Sum fs2)) = + Scalar . Sum <$> sequence (M.intersectionWith (zipWithM f) fs1 fs2) + f + (Scalar (Arrow u _ _ t1a (RetType _ t1r))) + (Scalar (Arrow _ pname d t2a (RetType ext t2r))) = do + ta <- f t1a t2a + tr <- f t1r t2r + pure $ Scalar $ Arrow u pname d ta $ RetType ext tr + f + (Array u (Shape (_ : ds1)) t1) + (Array _ (Shape (d : ds2)) t2) = + arrayOfWithAliases u (Shape [d]) + <$> f (arrayOf (Shape ds1) (Scalar t1)) (arrayOf (Shape ds2) (Scalar t2)) + f + (Scalar (TypeVar u v1 targs1)) + (Scalar (TypeVar _ _ targs2)) + | length targs1 == length targs2 = + Scalar . TypeVar u v1 <$> zipWithM g targs1 targs2 + where + g (TypeArgType t1) (TypeArgType t2) = + TypeArgType <$> f t1 t2 + g _ targ = pure targ + f t1 t2 = do + let mkNew = + fst <$> lift (allDimsFreshInType (mkUsage loc "instantiation") Nonrigid "dv" t1) + case t2 of + Scalar (TypeVar u (QualName [] v2) []) + | v2 `elem` names -> do + seen <- get + case M.lookup v2 seen of + Nothing -> do + t <- mkNew + modify $ M.insert v2 $ second (const NoUniqueness) t + pure t + Just t -> + pure $ second (const u) t + _ -> mkNew + + evalStateT (f orig_t1 orig_t2) mempty + +-- | Instantiate a type scheme with fresh variables for its size and +-- type parameters. Returns the names of the fresh size and type +-- variables and the instantiated type. +instTypeScheme :: QualName VName -> SrcLoc -> [TypeParam] -> StructType -> TermTypeM ([VName], StructType) -instantiateTypeScheme qn loc tparams t = do - let tnames = map typeParamName tparams - (tparam_names, tparam_substs) <- mapAndUnzipM (instantiateTypeParam qn loc) tparams - let substs = M.fromList $ zip tnames tparam_substs - t' = applySubst (`M.lookup` substs) t - pure (tparam_names, t') - --- | Create a new type name and insert it (unconstrained) in the --- substitution map. -instantiateTypeParam :: - (Monoid as) => - QualName VName -> - SrcLoc -> - TypeParam -> - TermTypeM (VName, Subst (RetTypeBase dim as)) -instantiateTypeParam qn loc tparam = do - i <- incCounter - let name = nameFromText (T.takeWhile isAscii (baseText (typeParamName tparam))) - v <- newID $ mkTypeVarName name i - case tparam of - TypeParamType x _ _ -> do - constrain v . NoConstraint x . mkUsage loc . docText $ - "instantiated type parameter of " <> dquotes (pretty qn) - pure (v, Subst [] $ RetType [] $ Scalar $ TypeVar mempty (qualName v) []) - TypeParamDim {} -> do - constrain v . Size Nothing . mkUsage loc . docText $ - "instantiated size parameter of " <> dquotes (pretty qn) - pure (v, ExpSubst $ sizeFromName (qualName v) loc) +instTypeScheme qn loc tparams scheme_t = do + (names, substs) <- fmap unzip . forM tparams $ \tparam -> do + case tparam of + TypeParamType l v _ -> do + i <- incCounter + v' <- newID $ mkTypeVarName (baseName v) i + constrain v' . NoConstraint l . mkUsage loc . docText $ + "instantiated type parameter of " <> dquotes (pretty qn) + pure (v', (v, Subst [] $ RetType [] $ Scalar $ TypeVar mempty (qualName v') [])) + TypeParamDim v _ -> do + i <- incCounter + v' <- newID $ mkTypeVarName (baseName v) i + constrain v' . Size Nothing . mkUsage loc . docText $ + "instantiated size parameter of " <> dquotes (pretty qn) + pure (v', (v, ExpSubst $ sizeFromName (qualName v') loc)) + + pure (names, applySubst (`lookup` substs) scheme_t) lookupQualNameEnv :: QualName VName -> TermTypeM TermScope lookupQualNameEnv (QualName [q] _) @@ -446,41 +531,23 @@ instance MonadTypeChecker TermTypeM where Nothing -> throwError $ TypeError (locOf loc) notes s -lookupVar :: SrcLoc -> QualName VName -> TermTypeM StructType -lookupVar loc qn@(QualName qs name) = do +lookupVar :: SrcLoc -> QualName VName -> StructType -> TermTypeM StructType +lookupVar loc qn@(QualName qs name) inst_t = do scope <- lookupQualNameEnv qn - let usage = mkUsage loc $ docText $ "use of " <> dquotes (pretty qn) - case M.lookup name $ scopeVtable scope of Nothing -> error $ "lookupVar: " <> show qn - Just (BoundV tparams t) -> do + Just (BoundV tparams bound_t) -> if null tparams && null qs - then pure t + then pure bound_t else do - (tnames, t') <- instantiateTypeScheme qn loc tparams t + (tnames, t) <- instTypeScheme qn loc tparams bound_t outer_env <- asks termOuterEnv - pure $ qualifyTypeVars outer_env tnames qs t' - Just EqualityF -> do - argtype <- newTypeVar loc "t" - equalityType usage argtype - pure $ - Scalar . Arrow mempty Unnamed Observe argtype . RetType [] $ - Scalar $ - Arrow mempty Unnamed Observe argtype $ - RetType [] $ - Scalar $ - Prim Bool - Just (OverloadedF ts pts rt) -> do - argtype <- newTypeVar loc "t" - mustBeOneOf ts usage argtype - let (pts', rt') = instOverloaded argtype pts rt - pure $ foldFunType (map (toParam Observe) pts') $ RetType [] $ toRes Nonunique rt' - where - instOverloaded argtype pts rt = - ( map (maybe (toStruct argtype) (Scalar . Prim)) pts, - maybe (toStruct argtype) (Scalar . Prim) rt - ) + pure $ qualifyTypeVars outer_env tnames qs t + Just EqualityF -> + replaceTyVars loc inst_t + Just OverloadedF {} -> + replaceTyVars loc inst_t onFailure :: Checking -> TermTypeM a -> TermTypeM a onFailure c = local $ \env -> env {termChecking = Just c} @@ -531,8 +598,8 @@ allDimsFreshInType :: Usage -> Rigidity -> Name -> - TypeBase Size als -> - TermTypeM (TypeBase Size als, M.Map VName Size) + TypeBase d als -> + TermTypeM (TypeBase Size als, M.Map VName d) allDimsFreshInType usage r desc t = runStateT (bitraverse onDim pure t) mempty where @@ -554,6 +621,33 @@ updateTypes = astMap tv mapOnResRetType = normTypeFully } +mustBeOrderZero :: Loc -> StructType -> TermTypeM () +mustBeOrderZero loc t = do + constraints <- getConstraints + let liftedType v = + case M.lookup v constraints of + Just (_, ParamType Lifted _) -> True + _ -> False + when (not (orderZero t) || any liftedType (typeVars t)) $ + typeError loc mempty $ + textwrap "This expression may not be of function type, but is inferred to be of type" + indent 2 (align (pretty t)) + "which may be a function." + +mustBeUnlifted :: Loc -> StructType -> TermTypeM () +mustBeUnlifted loc t = do + constraints <- getConstraints + let liftedType v = + case M.lookup v constraints of + Just (_, ParamType Lifted _) -> True + Just (_, ParamType SizeLifted _) -> True + _ -> False + when (not (orderZero t) || any liftedType (typeVars t)) $ + typeError loc mempty $ + textwrap "This expression must be of unlifted type, but is inferred to be of type" + indent 2 (align (pretty t)) + "which may be a function or a value with hidden sizes." + --- Basic checking unifies :: T.Text -> StructType -> Exp -> TermTypeM Exp @@ -561,24 +655,15 @@ unifies why t e = do unify (mkUsage (srclocOf e) why) t . toStruct =<< expType e pure e --- | @require ts e@ causes a 'TypeError' if @expType e@ is not one of --- the types in @ts@. Otherwise, simply returns @e@. -require :: T.Text -> [PrimType] -> Exp -> TermTypeM Exp -require why ts e = do - mustBeOneOf ts (mkUsage (srclocOf e) why) . toStruct =<< expType e - pure e - -checkExpForSize :: ExpBase NoInfo VName -> TermTypeM Exp +checkExpForSize :: ExpBase Info VName -> TermTypeM Exp checkExpForSize e = do - checker <- asks termChecker + checker <- asks termCheckExp e' <- checker e let t = toStruct $ typeOf e' unify (mkUsage (locOf e') "Size expression") t (Scalar (Prim (Signed Int64))) updateTypes e' -checkTypeExpNonrigid :: - TypeExp (ExpBase NoInfo VName) VName -> - TermTypeM (TypeExp Exp VName, ResType, [VName]) +checkTypeExpNonrigid :: TypeExp Exp VName -> TermTypeM (TypeExp Exp VName, ResType, [VName]) checkTypeExpNonrigid te = do (te', svars, rettype, _l) <- checkTypeExp checkExpForSize te @@ -632,8 +717,8 @@ initialTermScope = Just (name, EqualityF) addIntrinsicF _ = Nothing -runTermTypeM :: (ExpBase NoInfo VName -> TermTypeM Exp) -> TermTypeM a -> TypeM a -runTermTypeM checker (TermTypeM m) = do +runTermTypeM :: (ExpBase Info VName -> TermTypeM Exp) -> M.Map TyVar (TypeBase () NoUniqueness) -> TermTypeM a -> TypeM a +runTermTypeM checker tyvars (TermTypeM m) = do initial_scope <- (initialTermScope <>) . envToTermScope <$> askEnv name <- askImportName outer_env <- askEnv @@ -643,9 +728,10 @@ runTermTypeM checker (TermTypeM m) = do { termScope = initial_scope, termChecking = Nothing, termLevel = 0, - termChecker = checker, + termCheckExp = checker, termImportName = name, - termOuterEnv = outer_env + termOuterEnv = outer_env, + termTyVars = tyvars } initial_state = TermTypeState diff --git a/src/Language/Futhark/TypeChecker/Terms/Pat.hs b/src/Language/Futhark/TypeChecker/Terms/Pat.hs index 3f29b3972e..4a30f81834 100644 --- a/src/Language/Futhark/TypeChecker/Terms/Pat.hs +++ b/src/Language/Futhark/TypeChecker/Terms/Pat.hs @@ -2,6 +2,7 @@ module Language.Futhark.TypeChecker.Terms.Pat ( binding, bindingParams, + bindingParam, bindingPat, bindingIdent, bindingSizes, @@ -11,7 +12,7 @@ where import Control.Monad import Data.Bifunctor import Data.Either -import Data.List (find, isPrefixOf, sort, sortBy) +import Data.List (find, isPrefixOf, sortBy) import Data.Map.Strict qualified as M import Data.Maybe import Data.Ord (comparing) @@ -100,48 +101,30 @@ bindingSizes sizes m = binding (map sizeWithType sizes) m Ident (sizeName size) (Info (Scalar (Prim (Signed Int64)))) (srclocOf size) -- | Bind a single term-level identifier. -bindingIdent :: - IdentBase NoInfo VName StructType -> - StructType -> - (Ident StructType -> TermTypeM a) -> - TermTypeM a -bindingIdent (Ident v NoInfo vloc) t m = do - let ident = Ident v (Info t) vloc - binding [ident] $ m ident - --- All this complexity is just so we can handle un-suffixed numeric --- literals in patterns. -patLitMkType :: PatLit -> SrcLoc -> TermTypeM ParamType -patLitMkType (PatLitInt _) loc = do - t <- newTypeVar loc "t" - mustBeOneOf anyNumberType (mkUsage loc "integer literal") (toStruct t) - pure t -patLitMkType (PatLitFloat _) loc = do - t <- newTypeVar loc "t" - mustBeOneOf anyFloatType (mkUsage loc "float literal") (toStruct t) - pure t -patLitMkType (PatLitPrim v) _ = - pure $ Scalar $ Prim $ primValueType v +bindingIdent :: Ident StructType -> TermTypeM a -> TermTypeM a +bindingIdent ident = binding [ident] checkPat' :: [(SizeBinder VName, QualName VName)] -> - PatBase NoInfo VName ParamType -> + Pat ParamType -> Inferred ParamType -> TermTypeM (Pat ParamType) checkPat' sizes (PatParens p loc) t = PatParens <$> checkPat' sizes p t <*> pure loc checkPat' sizes (PatAttr attr p loc) t = PatAttr <$> checkAttr attr <*> checkPat' sizes p t <*> pure loc -checkPat' _ (Id name NoInfo loc) (Ascribed t) = - pure $ Id name (Info t) loc -checkPat' _ (Id name NoInfo loc) NoneInferred = do - t <- newTypeVar loc "t" - pure $ Id name (Info t) loc -checkPat' _ (Wildcard _ loc) (Ascribed t) = - pure $ Wildcard (Info t) loc -checkPat' _ (Wildcard NoInfo loc) NoneInferred = do - t <- newTypeVar loc "t" - pure $ Wildcard (Info t) loc +checkPat' _ (Id name (Info t) loc) NoneInferred = do + t' <- replaceTyVars loc t + pure $ Id name (Info t') loc +checkPat' _ (Id name (Info t1) loc) (Ascribed t2) = do + t' <- instTyVars loc [] (first (const ()) t1) t2 + pure $ Id name (Info t') loc +checkPat' _ (Wildcard (Info t) loc) NoneInferred = do + t' <- replaceTyVars loc t + pure $ Wildcard (Info t') loc +checkPat' _ (Wildcard (Info t1) loc) (Ascribed t2) = do + t' <- instTyVars loc [] (first (const ()) t1) t2 + pure $ Wildcard (Info t') loc checkPat' sizes p@(TuplePat ps loc) (Ascribed t) | Just ts <- isTupleRecord t, length ts == length ps = @@ -169,11 +152,6 @@ checkPat' sizes p@(RecordPat p_fs loc) (Ascribed t) RecordPat <$> zipWithM check p_fs' t_fs' <*> pure loc | otherwise = do p_fs' <- traverse (const $ newTypeVar loc "t") $ M.fromList $ map (first unLoc) p_fs - - when (sort (M.keys p_fs') /= sort (map (unLoc . fst) p_fs)) $ - typeError loc mempty $ - "Duplicate fields in record pattern" <+> pretty p <> "." - unify (mkUsage loc "matching a record pattern") (Scalar (Record p_fs')) (toStruct t) checkPat' sizes p $ Ascribed $ toParam Observe $ Scalar (Record p_fs') where @@ -199,54 +177,33 @@ checkPat' sizes (PatAscription p t loc) maybe_outer_t = do <$> checkPat' sizes p (Ascribed (resToParam st)) <*> pure t' <*> pure loc -checkPat' _ (PatLit l NoInfo loc) (Ascribed t) = do - t' <- patLitMkType l loc - unify (mkUsage loc "matching against literal") (toStruct t') (toStruct t) - pure $ PatLit l (Info t') loc -checkPat' _ (PatLit l NoInfo loc) NoneInferred = do - t' <- patLitMkType l loc +checkPat' _ (PatLit l (Info t) loc) _ = do + t' <- replaceTyVars loc t pure $ PatLit l (Info t') loc -checkPat' sizes (PatConstr n NoInfo ps loc) (Ascribed (Scalar (Sum cs))) +checkPat' sizes (PatConstr n info ps loc) NoneInferred = do + ps' <- mapM (\p -> checkPat' sizes p NoneInferred) ps + pure $ PatConstr n info ps' loc +checkPat' sizes (PatConstr n _ ps loc) (Ascribed (Scalar (Sum cs))) | Just ts <- M.lookup n cs = do - when (length ps /= length ts) $ - typeError loc mempty $ - "Pattern #" - <> pretty n - <> " expects" - <+> pretty (length ps) - <+> "constructor arguments, but type provides" - <+> pretty (length ts) - <+> "arguments." - ps' <- zipWithM (checkPat' sizes) ps $ map Ascribed ts + ps' <- zipWithM (\p t -> checkPat' sizes p (Ascribed t)) ps ts pure $ PatConstr n (Info (Scalar (Sum cs))) ps' loc -checkPat' sizes (PatConstr n NoInfo ps loc) (Ascribed t) = do - t' <- newTypeVar loc "t" - ps' <- forM ps $ \p -> do - p_t <- newTypeVar (srclocOf p) "t" - checkPat' sizes p $ Ascribed p_t - mustHaveConstr usage n (toStruct t') (patternStructType <$> ps') - unify usage t' (toStruct t) - pure $ PatConstr n (Info t) ps' loc - where - usage = mkUsage loc "matching against constructor" -checkPat' sizes (PatConstr n NoInfo ps loc) NoneInferred = do - ps' <- mapM (\p -> checkPat' sizes p NoneInferred) ps - t <- newTypeVar loc "t" - mustHaveConstr usage n (toStruct t) (patternStructType <$> ps') - pure $ PatConstr n (Info t) ps' loc - where - usage = mkUsage loc "matching against constructor" +checkPat' _ p t = + error . unlines $ + [ "checkPat': bad case", + prettyString p, + show t + ] checkPat :: [(SizeBinder VName, QualName VName)] -> - PatBase NoInfo VName (TypeBase Size u) -> + Pat ParamType -> Inferred StructType -> (Pat ParamType -> TermTypeM a) -> TermTypeM a checkPat sizes p t m = do p' <- onFailure (CheckingPat (fmap toStruct p) t) $ - checkPat' sizes (fmap (toParam Observe) p) (fmap (toParam Observe) t) + checkPat' sizes p (fmap (toParam Observe) t) let explicit = mustBeExplicitInType $ patternStructType p' @@ -259,19 +216,30 @@ checkPat sizes p t m = do [] -> m p' +-- | Check and bind a single parameter. +bindingParam :: + Pat ParamType -> + StructType -> + (Pat ParamType -> TermTypeM a) -> + TermTypeM a +bindingParam p t m = do + checkPat mempty p (Ascribed t) $ \p' -> + binding (patIdents (fmap toStruct p')) $ m p' + -- | Check and bind a @let@-pattern. bindingPat :: [SizeBinder VName] -> - PatBase NoInfo VName (TypeBase Size u) -> + Pat (TypeBase Size u) -> StructType -> (Pat ParamType -> TermTypeM a) -> TermTypeM a bindingPat sizes p t m = do substs <- mapM mkSizeSubst sizes - checkPat substs p (Ascribed t) $ \p' -> binding (patIdents (fmap toStruct p')) $ - case filter ((`S.notMember` fvVars (freeInPat p')) . sizeName) sizes of - [] -> m p' - size : _ -> unusedSize size + checkPat substs (fmap (toParam Observe) p) (Ascribed t) $ \p' -> + binding (patIdents (fmap toStruct p')) $ + case filter ((`S.notMember` fvVars (freeInPat p')) . sizeName) sizes of + [] -> m p' + size : _ -> unusedSize size where mkSizeSubst v = do v' <- newID $ baseName $ sizeName v @@ -282,13 +250,15 @@ bindingPat sizes p t m = do -- | Check and bind type and value parameters. bindingParams :: [TypeParam] -> - [PatBase NoInfo VName ParamType] -> + [Pat ParamType] -> ([Pat ParamType] -> TermTypeM a) -> TermTypeM a bindingParams tps orig_ps m = bindingTypeParams tps $ do let descend ps' (p : ps) = checkPat [] p NoneInferred $ \p' -> - binding (patIdents $ fmap toStruct p') $ incLevel $ descend (p' : ps') ps + binding (patIdents $ fmap toStruct p') $ + incLevel $ + descend (p' : ps') ps descend ps' [] = m $ reverse ps' incLevel $ descend [] orig_ps diff --git a/src/Language/Futhark/TypeChecker/Terms/Unsized.hs b/src/Language/Futhark/TypeChecker/Terms/Unsized.hs new file mode 100644 index 0000000000..f35969ce7a --- /dev/null +++ b/src/Language/Futhark/TypeChecker/Terms/Unsized.hs @@ -0,0 +1,1406 @@ +-- | Unsized type checking. +-- +-- This checker generates type constraints (type 'CtTy') and AUTOMAP +-- constraints (type 'CtAM') which are then solved to find a solution. +-- The result is a decorated AST where most of the type annotations +-- are just references to type variables. Further, all the +-- size-specific annotations (e.g. existential sizes) just contain +-- dummy values, such as empty lists. +-- +-- If Futhark had no fancy type system features, then this pass would +-- essentially be all you needed. +module Language.Futhark.TypeChecker.Terms.Unsized + ( checkValDef, + checkSingleExp, + checkSizeExp, + Solution, + ) +where + +import Control.Monad +import Control.Monad.Except +import Control.Monad.Reader +import Control.Monad.State +import Data.Bifunctor +import Data.Bitraversable +import Data.Char (isAscii) +import Data.Either (partitionEithers) +import Data.List qualified as L +import Data.List.NonEmpty qualified as NE +import Data.Loc (Loc (NoLoc)) +import Data.Map qualified as M +import Data.Maybe +import Data.Ord (comparing) +import Data.Set qualified as S +import Data.Text qualified as T +import Futhark.FreshNames qualified as FreshNames +import Futhark.MonadFreshNames hiding (newName) +import Futhark.Util (debugTraceM, mapAccumLM, nubOrd) +import Futhark.Util.Pretty +import Language.Futhark +import Language.Futhark.TypeChecker.Constraints +import Language.Futhark.TypeChecker.Monad hiding (BoundV, lookupMod) +import Language.Futhark.TypeChecker.Monad qualified as TypeM +import Language.Futhark.TypeChecker.Rank +import Language.Futhark.TypeChecker.TySolve hiding (Type) +import Language.Futhark.TypeChecker.Types +import Language.Futhark.TypeChecker.Unify (mkUsage) +import Prelude hiding (mod) + +type Type = CtType SComp + +-- | Careful when using this on something that already has an SComp +-- size: it will throw away information by converting them to SDim. +toType :: TypeBase Size u -> TypeBase SComp u +toType = first (const SDim) + +data ValBinding + = BoundV [TypeParam] Type + | OverloadedF [PrimType] [Maybe PrimType] (Maybe PrimType) + | EqualityF + deriving (Show) + +data TermScope = TermScope + { scopeVtable :: M.Map VName ValBinding, + scopeTypeTable :: M.Map VName TypeBinding, + scopeModTable :: M.Map VName Mod + } + deriving (Show) + +instance Semigroup TermScope where + TermScope vt1 tt1 mt1 <> TermScope vt2 tt2 mt2 = + TermScope (vt2 `M.union` vt1) (tt2 `M.union` tt1) (mt1 `M.union` mt2) + +-- | Type checking happens with access to this environment. The +-- 'TermScope' will be extended during type-checking as bindings come into +-- scope. +data TermEnv = TermEnv + { termScope :: TermScope, + termLevel :: Level, + termOuterEnv :: Env, + termImportName :: ImportName + } + +-- | The state is a set of constraints and a counter for generating +-- type names. This is distinct from the usual counter we use for +-- generating unique names, as these will be user-visible. +data TermState = TermState + { termConstraints :: [CtTy SComp], + termAM :: [CtAM], + termTyVars :: TyVars SComp, + termTyParams :: TyParams, + termCounter :: !Int, + termWarnings :: Warnings, + termNameSource :: VNameSource, + -- | Mapping from artificial type variables to the actual types they represent. + termArtificial :: M.Map TyVar Type + } + +newtype TermM a + = TermM + ( ReaderT + TermEnv + (StateT TermState (Except (Warnings, TypeError))) + a + ) + deriving + ( Monad, + Functor, + Applicative, + MonadReader TermEnv, + MonadState TermState + ) + +envToTermScope :: Env -> TermScope +envToTermScope env = + TermScope + { scopeVtable = vtable, + scopeTypeTable = envTypeTable env, + scopeModTable = envModTable env + } + where + vtable = M.map valBinding $ envVtable env + valBinding (TypeM.BoundV tps v) = BoundV tps $ toType v + +initialTermScope :: TermScope +initialTermScope = + TermScope + { scopeVtable = initialVtable, + scopeTypeTable = mempty, + scopeModTable = mempty + } + where + initialVtable = M.fromList $ mapMaybe addIntrinsicF $ M.toList intrinsics + + prim = Scalar . Prim + arrow x y = Scalar $ Arrow mempty Unnamed Observe x y + + addIntrinsicF (name, IntrinsicMonoFun pts t) = + Just (name, BoundV [] $ arrow pts' $ RetType [] $ prim t) + where + pts' = case pts of + [pt] -> prim pt + _ -> Scalar $ tupleRecord $ map prim pts + addIntrinsicF (name, IntrinsicOverloadedFun ts pts rts) = + Just (name, OverloadedF ts pts rts) + addIntrinsicF (name, IntrinsicPolyFun tvs pts rt) = + Just + ( name, + BoundV tvs $ toType $ foldFunType pts rt + ) + addIntrinsicF (name, IntrinsicEquality) = + Just (name, EqualityF) + addIntrinsicF _ = Nothing + +runTermM :: TermM a -> TypeM a +runTermM (TermM m) = do + initial_scope <- (initialTermScope <>) . envToTermScope <$> askEnv + name <- askImportName + outer_env <- askEnv + src <- gets stateNameSource + let initial_env = + TermEnv + { termScope = initial_scope, + termLevel = 0, + termImportName = name, + termOuterEnv = outer_env + } + initial_state = + TermState + { termConstraints = mempty, + termAM = mempty, + termTyVars = mempty, + termTyParams = mempty, + termWarnings = mempty, + termNameSource = src, + termCounter = 0, + termArtificial = mempty + } + case runExcept (runStateT (runReaderT m initial_env) initial_state) of + Left (ws, e) -> do + warnings ws + throwError e + Right (a, TermState {termNameSource, termWarnings}) -> do + warnings termWarnings + modify $ \s -> s {stateNameSource = termNameSource} + pure a + +incLevel :: TermM a -> TermM a +incLevel = local $ \env -> env {termLevel = termLevel env + 1} + +curLevel :: TermM Int +curLevel = asks termLevel + +incCounter :: TermM Int +incCounter = do + s <- get + put s {termCounter = termCounter s + 1} + pure $ termCounter s + +tyVarType :: u -> TyVar -> TypeBase dim u +tyVarType u v = Scalar $ TypeVar u (qualName v) [] + +newTyVarWith :: Name -> TyVarInfo SComp -> TermM TyVar +newTyVarWith desc info = do + i <- incCounter + v <- newID $ mkTypeVarName desc i + lvl <- curLevel + modify $ \s -> s {termTyVars = M.insert v (lvl, info) $ termTyVars s} + pure v + +newTyVar :: (Located loc) => loc -> Liftedness -> Name -> TermM TyVar +newTyVar loc l desc = newTyVarWith desc $ TyVarFree (locOf loc) l + +newType :: (Located loc) => loc -> Liftedness -> Name -> u -> TermM (TypeBase dim u) +newType loc l desc u = tyVarType u <$> newTyVar loc l desc + +-- | New type that must be allowed as an array element. +newElemType :: (Located loc) => loc -> Name -> u -> TermM (TypeBase dim u) +newElemType loc desc u = tyVarType u <$> newTyVar loc Unlifted desc + +newTypeWithField :: SrcLoc -> Name -> Name -> Type -> TermM Type +newTypeWithField loc desc k t = + tyVarType NoUniqueness + <$> newTyVarWith desc (TyVarRecord (locOf loc) $ M.singleton k t) + +newTypeWithConstr :: SrcLoc -> Name -> u -> Name -> [TypeBase SComp u] -> TermM (TypeBase d u) +newTypeWithConstr loc desc u k ts = + tyVarType u <$> newTyVarWith desc (TyVarSum (locOf loc) $ M.singleton k ts') + where + ts' = map (`setUniqueness` NoUniqueness) ts + +newTypeOverloaded :: SrcLoc -> Name -> [PrimType] -> TermM (TypeBase d NoUniqueness) +newTypeOverloaded loc name pts = + tyVarType NoUniqueness <$> newTyVarWith name (TyVarPrim (locOf loc) pts) + +newArtificial :: u -> TypeBase SComp u -> TermM (TypeBase Size u) +newArtificial u t = do + v <- newID "artificial" + let t' = tyVarType u v + modify $ \s -> s {termArtificial = M.insert v (second (const NoUniqueness) t) $ termArtificial s} + pure t' + +-- The AST requires annotations to be StructTypes, but the type +-- checker works with Types. This creates artificial type "variables" +-- that allow us to connect the AST annotations with the actual +-- inferred types. The artificial variables should never occur in +-- constraints - they can be substituted away with asType. +asStructType :: TypeBase SComp u -> TermM (TypeBase Size u) +asStructType (Scalar (Prim pt)) = pure $ Scalar $ Prim pt +asStructType (Scalar (TypeVar u v [])) = pure $ Scalar $ TypeVar u v [] +asStructType (Scalar (Arrow u pname d t1 (RetType ext t2))) = do + t1' <- asStructType t1 + t2' <- asStructType t2 + pure $ Scalar $ Arrow u pname d t1' $ RetType ext t2' +asStructType (Scalar (Record fs)) = + Scalar . Record <$> traverse asStructType fs +asStructType (Scalar (Sum cs)) = + Scalar . Sum <$> traverse (mapM asStructType) cs +asStructType t@(Scalar (TypeVar u _ _)) = + newArtificial u t +asStructType t@(Array u _ _) = do + newArtificial u t + +asType :: (Monoid u) => TypeBase Size u -> TermM (TypeBase SComp u) +asType t = do + artificial <- gets termArtificial + pure $ substTyVars (`M.lookup` artificial) (toType t) + +expType :: Exp -> TermM Type +expType = asType . typeOf -- NOTE: Only place you should use typeOf. + +addCt :: CtTy SComp -> TermM () +addCt ct = modify $ \s -> s {termConstraints = ct : termConstraints s} + +ctEq :: Reason (CtType SComp) -> TypeBase SComp u1 -> TypeBase SComp u2 -> TermM () +ctEq reason t1 t2 = + -- As a minor optimisation, do not add constraint if the types are + -- equal. + unless (t1' == t2') $ addCt $ CtEq reason t1' t2' + where + t1' = t1 `setUniqueness` NoUniqueness + t2' = t2 `setUniqueness` NoUniqueness + +localScope :: (TermScope -> TermScope) -> TermM a -> TermM a +localScope f = local $ \tenv -> tenv {termScope = f $ termScope tenv} + +withEnv :: TermEnv -> Env -> TermEnv +withEnv tenv env = tenv {termScope = termScope tenv <> envToTermScope env} + +lookupQualNameEnv :: QualName VName -> TermM TermScope +lookupQualNameEnv (QualName [q] _) + | baseTag q <= maxIntrinsicTag = asks termScope -- Magical intrinsic module. +lookupQualNameEnv qn@(QualName quals _) = do + scope <- asks termScope + descend scope quals + where + descend scope [] = pure scope + descend scope (q : qs) + | Just (ModEnv q_scope) <- M.lookup q $ scopeModTable scope = + descend (envToTermScope q_scope) qs + | otherwise = + error $ "lookupQualNameEnv " <> show qn + +instance MonadError TypeError TermM where + throwError e = TermM $ do + ws <- gets termWarnings + throwError (ws, e) + + catchError (TermM m) f = + TermM $ m `catchError` f' + where + f' (_, e) = let TermM m' = f e in m' + +instance MonadTypeChecker TermM where + warnings ws = modify $ \s -> s {termWarnings = termWarnings s <> ws} + + warn loc problem = warnings $ singleWarning (locOf loc) problem + + newName v = do + s <- get + let (v', src') = FreshNames.newName (termNameSource s) v + put $ s {termNameSource = src'} + pure v' + + newID s = newName $ VName s 0 + + newTypeName name = do + i <- incCounter + newID $ mkTypeVarName name i + + bindVal v (TypeM.BoundV tps t) m = do + t' <- asType t + let f scope = scope {scopeVtable = M.insert v (BoundV tps t') $ scopeVtable scope} + localScope f m + + lookupType qn = do + outer_env <- asks termOuterEnv + scope <- lookupQualNameEnv qn + case M.lookup (qualLeaf qn) $ scopeTypeTable scope of + Nothing -> error $ "lookupType: " <> show qn + Just (TypeAbbr l ps (RetType dims def)) -> + pure + ( ps, + RetType dims $ qualifyTypeVars outer_env (map typeParamName ps) (qualQuals qn) def, + l + ) + + typeError loc notes s = + throwError $ TypeError (locOf loc) notes s + +--- All the general machinery goes above. + +arrayOfRank :: Int -> Type -> Type +arrayOfRank n = arrayOf $ Shape $ replicate n SDim + +require :: T.Text -> [PrimType] -> Exp -> TermM Exp +require _why [pt] e = do + e_t <- expType e + ctEq (Reason (locOf e)) (Scalar $ Prim pt) e_t + pure e +require _why pts e = do + t :: Type <- newTypeOverloaded (srclocOf e) "t" pts + e_t <- expType e + ctEq (Reason (locOf e)) t e_t + pure e + +-- | Instantiate a type scheme with fresh type variables for its type +-- parameters. Returns the names of the fresh type variables, the +-- instance list, and the instantiated type. +instTypeScheme :: + QualName VName -> + SrcLoc -> + [TypeParam] -> + Type -> + TermM ([VName], Type) +instTypeScheme _qn loc tparams t = do + (names, substs) <- fmap (unzip . catMaybes) $ + forM tparams $ \tparam -> + case tparam of + TypeParamType l v _ -> do + v' <- newTyVar loc l $ nameFromText $ T.takeWhile isAscii $ nameToText $ baseName v + pure $ Just (v, (typeParamName tparam, tyVarType NoUniqueness v')) + TypeParamDim {} -> + pure Nothing + let t' = substTyVars (`lookup` substs) t + pure (names, t') + +lookupMod :: QualName VName -> TermM Mod +lookupMod qn@(QualName _ name) = do + scope <- lookupQualNameEnv qn + case M.lookup name $ scopeModTable scope of + Nothing -> error $ "lookupMod: " <> show qn + Just m -> pure m + +lookupVar :: SrcLoc -> QualName VName -> TermM Type +lookupVar loc qn@(QualName qs name) = do + scope <- lookupQualNameEnv qn + case M.lookup name $ scopeVtable scope of + Nothing -> + error $ "lookupVar: " <> show qn + Just (BoundV tparams t) -> do + if null tparams && null qs + then pure t + else do + (_tnames, t') <- instTypeScheme qn loc tparams t + -- TODO - qualify type names, like in the old type checker. + pure t' + Just EqualityF -> do + argtype <- tyVarType Observe <$> newTyVarWith "t" (TyVarFree (locOf loc) Unlifted) + pure $ foldFunType [argtype, argtype] $ RetType [] $ Scalar $ Prim Bool + Just (OverloadedF ts pts rt) -> do + argtype <- newTypeOverloaded loc "t" ts + let (pts', rt') = instOverloaded argtype pts rt + pure $ foldFunType (map (second $ const Observe) pts') $ RetType [] $ second (const Nonunique) rt' + where + instOverloaded argtype pts rt = + ( map (maybe argtype (Scalar . Prim)) pts, + maybe argtype (Scalar . Prim) rt + ) + +bind :: + [Ident StructType] -> + TermM a -> + TermM a +bind idents m = do + let names = map identName idents + ts <- mapM (asType . unInfo . identType) idents + localScope (`bindVars` zip names ts) m + where + bindVars = foldl bindVar + + bindVar scope (name, t) = + scope + { scopeVtable = M.insert name (BoundV [] t) $ scopeVtable scope + } + +-- All this complexity is just so we can handle un-suffixed numeric +-- literals in patterns. +patLitMkType :: PatLit -> SrcLoc -> TermM ParamType +patLitMkType (PatLitInt _) loc = + toParam Observe <$> newTypeOverloaded loc "t" anyNumberType +patLitMkType (PatLitFloat _) loc = + toParam Observe <$> newTypeOverloaded loc "t" anyFloatType +patLitMkType (PatLitPrim v) _ = + pure $ Scalar $ Prim $ primValueType v + +checkSizeExp' :: ExpBase NoInfo VName -> TermM Exp +checkSizeExp' e = do + e' <- checkExp e + e_t <- expType e' + ctEq (Reason (locOf e)) e_t (Scalar (Prim (Signed Int64))) + pure e' + +-- | During type checking a pattern, we might find an explicit +-- ascription. These contain complete type information (although they +-- must of course still be checked against what remains of the +-- pattern). +data Inferred + = NoneInferred + | Ascribed ParamType + +checkPat' :: + PatBase NoInfo VName ParamType -> + Inferred -> + TermM (Pat ParamType) +checkPat' (PatParens p loc) t = + PatParens <$> checkPat' p t <*> pure loc +checkPat' (PatAttr attr p loc) t = + PatAttr <$> checkAttr attr <*> checkPat' p t <*> pure loc +checkPat' (Id name NoInfo loc) (Ascribed t) = + pure $ Id name (Info t) loc +checkPat' (Id name NoInfo loc) NoneInferred = do + t <- newType loc Lifted "t" Observe + pure $ Id name (Info t) loc +checkPat' (Wildcard _ loc) (Ascribed t) = do + pure $ Wildcard (Info t) loc +checkPat' (Wildcard NoInfo loc) NoneInferred = do + t <- newType loc Lifted "t" Observe + pure $ Wildcard (Info t) loc +checkPat' p@(TuplePat ps loc) (Ascribed t) + | Just ts <- isTupleRecord t, + length ts == length ps = + TuplePat + <$> zipWithM checkPat' ps (map Ascribed ts) + <*> pure loc + | otherwise = + typeError loc mempty $ + "Pattern" + indent 2 (pretty p) + "cannot match ascribed type" + indent 2 (pretty t) +checkPat' (TuplePat ps loc) NoneInferred = + TuplePat <$> mapM (`checkPat'` NoneInferred) ps <*> pure loc +checkPat' p@(RecordPat p_fs loc) _ + | Just (L floc f, _) <- L.find (("_" `T.isPrefixOf`) . nameToText . unLoc . fst) p_fs = + typeError floc mempty $ + "Underscore-prefixed fields are not allowed." + "Did you mean" + <> dquotes (pretty (T.drop 1 (nameToText f)) <> "=_") + <> "?" + | length (nubOrd (map fst p_fs)) /= length (map fst p_fs) = + typeError loc mempty $ + "Duplicate fields in record pattern" <+> pretty p <> "." +checkPat' p@(RecordPat p_fs loc) (Ascribed t) + | Scalar (Record t_fs) <- t, + p_fs' <- L.sortBy (comparing fst) p_fs, + t_fs' <- L.sortBy (comparing fst) (M.toList t_fs), + map fst t_fs' == map (unLoc . fst) p_fs' = + RecordPat <$> zipWithM check p_fs' t_fs' <*> pure loc + | otherwise = do + typeError loc mempty $ + "Pattern" + indent 2 (pretty p) + "cannot match ascribed type" + indent 2 (pretty t) + where + check (L f_loc f, p_f) (_, t_f) = + (L f_loc f,) <$> checkPat' p_f (Ascribed t_f) +checkPat' (RecordPat fs loc) NoneInferred = + RecordPat . M.toList + <$> traverse (`checkPat'` NoneInferred) (M.fromList fs) + <*> pure loc +checkPat' (PatAscription p t loc) maybe_outer_t = do + (t', _, RetType _ st, _) <- checkTypeExp checkSizeExp' t + + let st' = resToParam st + + case maybe_outer_t of + Ascribed outer_t -> do + unless (toType st' == toType outer_t) $ + typeError loc mempty $ + "Ascribed type" + indent 2 (pretty st) + "cannot match outer ascribed type" + indent 2 (pretty outer_t) + PatAscription + <$> checkPat' p (Ascribed st') + <*> pure t' + <*> pure loc + NoneInferred -> + PatAscription + <$> checkPat' p (Ascribed st') + <*> pure t' + <*> pure loc +checkPat' (PatLit l NoInfo loc) (Ascribed t) = do + t' <- patLitMkType l loc + ctEq (Reason (locOf loc)) (toType t') (toType t) + pure $ PatLit l (Info t') loc +checkPat' (PatLit l NoInfo loc) NoneInferred = do + t' <- patLitMkType l loc + pure $ PatLit l (Info t') loc +checkPat' (PatConstr n NoInfo ps loc) (Ascribed (Scalar (Sum cs))) + | Just ts <- M.lookup n cs, + length ps == length ts = do + ps' <- zipWithM checkPat' ps $ map Ascribed ts + pure $ PatConstr n (Info (Scalar (Sum cs))) ps' loc +checkPat' p@(PatConstr {}) (Ascribed t) = + typeError (locOf p) mempty $ + "Pattern" + indent 2 (pretty p) + "cannot match ascribed type" + indent 2 (pretty t) +checkPat' (PatConstr n NoInfo ps loc) NoneInferred = do + ps' <- mapM (`checkPat'` NoneInferred) ps + t <- newTypeWithConstr loc "t" Observe n =<< mapM (asType . patternType) ps' + pure $ PatConstr n (Info $ toParam Observe t) ps' loc + +checkPat :: + PatBase NoInfo VName (TypeBase Size u) -> + (Pat ParamType -> TermM a) -> + TermM a +checkPat p m = + m =<< checkPat' (fmap (toParam Observe) p) NoneInferred + +-- | Bind @let@-bound sizes. This is usually followed by 'bindLetPat' +-- immediately afterwards. +bindSizes :: [SizeBinder VName] -> TermM a -> TermM a +bindSizes [] m = m -- Minor optimisation. +bindSizes sizes m = bind (map sizeWithType sizes) m + where + sizeWithType size = + Ident (sizeName size) (Info (Scalar (Prim (Signed Int64)))) (srclocOf size) + +bindLetPat :: + PatBase NoInfo VName (TypeBase Size u) -> + Type -> + (Pat ParamType -> TermM a) -> + TermM a +bindLetPat p t m = do + checkPat p $ \p' -> do + pt <- asType $ patternType p' + ctEq (ReasonPatMatch (locOf p) (fmap toStruct p) t) pt t + bind (patIdents (fmap toStruct p')) $ m p' + +typeParamIdent :: TypeParam -> Maybe (Ident StructType) +typeParamIdent (TypeParamDim v loc) = + Just $ Ident v (Info $ Scalar $ Prim $ Signed Int64) loc +typeParamIdent _ = Nothing + +bindTypes :: + [(VName, TypeBinding)] -> + TermM a -> + TermM a +bindTypes tbinds = localScope extend + where + extend scope = + scope + { scopeTypeTable = M.fromList tbinds <> scopeTypeTable scope + } + +bindTypeParams :: [TypeParam] -> TermM a -> TermM a +bindTypeParams tparams m = + bind idents . bindTypes types $ do + lvl <- curLevel + modify $ \s -> + s + { termTyParams = + termTyParams s + <> M.fromList (mapMaybe (typeParam lvl) tparams) + } + m + where + idents = mapMaybe typeParamIdent tparams + types = mapMaybe typeParamType tparams + typeParamType (TypeParamType l v _) = + Just (v, TypeAbbr l [] $ RetType [] $ Scalar (TypeVar mempty (qualName v) [])) + typeParamType TypeParamDim {} = Nothing + typeParam lvl (TypeParamType l v loc) = Just (v, (lvl, l, locOf loc)) + typeParam _ _ = Nothing + +bindParams :: + [TypeParam] -> + [PatBase NoInfo VName ParamType] -> + ([Pat ParamType] -> TermM a) -> + TermM a +bindParams tps orig_ps m = bindTypeParams tps $ do + let descend ps' (p : ps) = + checkPat p $ \p' -> + bind (patIdents $ fmap toStruct p') $ incLevel $ descend (p' : ps') ps + descend ps' [] = m $ reverse ps' + + incLevel $ descend [] orig_ps + +checkApplyOne :: + SrcLoc -> + (Maybe (QualName VName), Int) -> + (Shape Size, Type) -> + (Maybe Exp, Shape Size, Type) -> + TermM (Type, AutoMap) +checkApplyOne loc fname (_fframe, ftype) (arg, _argframe, argtype) = do + (a, b) <- split ftype + let lhs = argtype + rhs = a + let reason = case arg of + Just arg' -> ReasonApply (locOf arg) fname arg' lhs rhs + Nothing -> Reason (locOf loc) + ctEq reason lhs rhs + pure + ( b, + AutoMap + { autoRep = mempty, + autoMap = mempty, + autoFrame = mempty + } + ) + where + split (Scalar (Arrow _ _ _ a (RetType _ b))) = + pure (a, b `setUniqueness` NoUniqueness) + split (Array _u s t) = do + (a, b) <- split $ Scalar t + pure (arrayOf s a, arrayOf s b) + split ftype' = do + a <- newType loc Lifted "arg" NoUniqueness + b <- newType loc Lifted "res" Nonunique + let reason = case arg of + Just arg' -> ReasonApplySplit (locOf loc) fname arg' ftype' + Nothing -> Reason $ locOf loc + ctEq reason ftype' $ Scalar $ Arrow NoUniqueness Unnamed Observe a $ RetType [] b + pure (a, b `setUniqueness` NoUniqueness) + +checkApply :: + SrcLoc -> + Maybe (QualName VName) -> + (Shape Size, Type) -> + NE.NonEmpty (Maybe Exp, Shape Size, Type) -> + TermM (Type, NE.NonEmpty AutoMap) +checkApply loc fname (fframe, ftype) args = do + ((_, _, rt), argts) <- mapAccumLM onArg (0, fframe, ftype) args + pure (rt, argts) + where + onArg (i, f_f, f_t) arg = do + (rt, am) <- checkApplyOne loc (fname, i) (f_f, f_t) arg + pure + ( (i + 1, autoFrame am, rt), + am + ) + +checkSlice :: SliceBase NoInfo VName -> TermM [DimIndex] +checkSlice = mapM checkDimIndex + where + checkDimIndex (DimFix i) = + DimFix <$> (require "use as index" anySignedType =<< checkExp i) + checkDimIndex (DimSlice i j s) = + DimSlice <$> traverse check i <*> traverse check j <*> traverse check s + + check = require "use in slice" [Signed Int64] <=< checkExp + +isSlice :: DimIndexBase f vn -> Bool +isSlice DimSlice {} = True +isSlice DimFix {} = False + +-- Add constraints saying that the first type has a (potentially +-- nested) field containing the second type. +mustHaveFields :: SrcLoc -> Type -> [Name] -> Type -> TermM () +mustHaveFields loc t [] ve_t = + -- This case is probably never reached. + ctEq (Reason (locOf loc)) t ve_t +mustHaveFields loc t [f] ve_t = do + rt :: Type <- newTypeWithField loc "ft" f ve_t + ctEq (Reason (locOf loc)) t rt +mustHaveFields loc t (f : fs) ve_t = do + ft <- newType loc Lifted "ft" NoUniqueness + rt <- newTypeWithField loc "rt" f ft + mustHaveFields loc ft fs ve_t + ctEq (Reason (locOf loc)) t rt + +checkCase :: + Type -> + CaseBase NoInfo VName -> + TermM (CaseBase Info VName, Type) +checkCase mt (CasePat p e loc) = + bindLetPat p mt $ \p' -> do + e' <- checkExp e + e_t <- expType e' + pure (CasePat (fmap toStruct p') e' loc, e_t) + +checkCases :: + Type -> + NE.NonEmpty (CaseBase NoInfo VName) -> + TermM (NE.NonEmpty (CaseBase Info VName), Type) +checkCases mt rest_cs = do + let (c, rest_cs') = NE.uncons rest_cs + (c', c_t) <- checkCase mt c + case rest_cs' of + Nothing -> + pure (NE.singleton c', c_t) + Just cs -> do + (cs', cs_t) <- checkCases mt cs + ctEq (ReasonBranches (locOf c) c_t cs_t) c_t cs_t + pure (NE.cons c' cs', c_t) + +-- | An unmatched pattern. Used in in the generation of +-- unmatched pattern warnings by the type checker. +data Unmatched p + = UnmatchedNum p [PatLit] + | UnmatchedBool p + | UnmatchedConstr p + | Unmatched p + deriving (Functor, Show) + +instance Pretty (Unmatched (Pat StructType)) where + pretty um = case um of + (UnmatchedNum p nums) -> pretty' p <+> "where p is not one of" <+> pretty nums + (UnmatchedBool p) -> pretty' p + (UnmatchedConstr p) -> pretty' p + (Unmatched p) -> pretty' p + where + pretty' (PatAscription p t _) = pretty p <> ":" <+> pretty t + pretty' (PatParens p _) = parens $ pretty' p + pretty' (PatAttr _ p _) = parens $ pretty' p + pretty' (Id v _ _) = prettyName v + pretty' (TuplePat pats _) = parens $ commasep $ map pretty' pats + pretty' (RecordPat fs _) = braces $ commasep $ map ppField fs + where + ppField (name, t) = prettyName (unLoc name) <> equals <> pretty' t + pretty' Wildcard {} = "_" + pretty' (PatLit e _ _) = pretty e + pretty' (PatConstr n _ ps _) = "#" <> pretty n <+> sep (map pretty' ps) + +checkRetDecl :: + Exp -> + Maybe (TypeExp (ExpBase NoInfo VName) VName) -> + TermM (Type, Maybe (TypeExp Exp VName)) +checkRetDecl body Nothing = (,Nothing) <$> expType body +checkRetDecl body (Just te) = do + (te', _, RetType _ st, _) <- checkTypeExp checkSizeExp' te + body_t <- expType body + st' <- toStruct <$> asType st + ctEq (ReasonRetType (locOf body) st' body_t) st' body_t + pure (st', Just te') + +checkExp :: ExpBase NoInfo VName -> TermM (ExpBase Info VName) +-- +checkExp (Var qn _ loc) = do + t <- asStructType =<< lookupVar loc qn + pure $ Var qn (Info t) loc +checkExp (OpSection op _ loc) = do + ftype <- asStructType =<< lookupVar loc op + pure $ OpSection op (Info ftype) loc +checkExp (Negate arg loc) = do + arg' <- require "numeric negation" anyNumberType =<< checkExp arg + pure $ Negate arg' loc +checkExp (Not arg loc) = do + arg' <- require "logical negation" (Bool : anyIntType) =<< checkExp arg + pure $ Not arg' loc +checkExp (Hole NoInfo loc) = + Hole <$> (Info <$> newType loc Lifted "hole" NoUniqueness) <*> pure loc +checkExp (Parens e loc) = + Parens <$> checkExp e <*> pure loc +checkExp (TupLit es loc) = + TupLit <$> mapM checkExp es <*> pure loc +checkExp (QualParens (modname, modnameloc) e loc) = do + mod <- lookupMod modname + case mod of + ModEnv env -> local (`withEnv` env) $ do + e' <- checkExp e + pure $ QualParens (modname, modnameloc) e' loc + ModFun {} -> + typeError loc mempty . withIndexLink "module-is-parametric" $ + "Module" <+> pretty modname <+> " is a parametric module." +-- +checkExp (IntLit x NoInfo loc) = do + t <- newTypeOverloaded loc "num" anyNumberType + pure $ IntLit x (Info t) loc +checkExp (FloatLit x NoInfo loc) = do + t <- newTypeOverloaded loc "float" anyFloatType + pure $ FloatLit x (Info t) loc +checkExp (Literal v loc) = + pure $ Literal v loc +checkExp (StringLit vs loc) = + pure $ StringLit vs loc +-- No need to type check this, as these are only produced by the +-- parser if the elements are monomorphic and all match. +checkExp (ArrayVal vs t loc) = + pure $ ArrayVal vs t loc +checkExp (ArrayLit es _ loc) = do + -- TODO: this will produce an enormous number of constraints and + -- type variables for pathologically large arrays with + -- type-unsuffixed integers. Add some special case that handles that + -- more efficiently. + et <- newElemType loc "et" NoUniqueness + es' <- forM es $ \e -> do + e' <- checkExp e + e_t <- expType e' + et' <- asType et + ctEq (Reason (locOf loc)) e_t et' + pure e' + let arr_t = arrayOf (Shape [sizeFromInteger (L.genericLength es) loc]) et + pure $ ArrayLit es' (Info arr_t) loc +checkExp (RecordLit fs loc) = + RecordLit <$> evalStateT (mapM checkField fs) mempty <*> pure loc + where + checkField (RecordFieldExplicit f e rloc) = do + errIfAlreadySet (unLoc f) rloc + modify $ M.insert (unLoc f) rloc + RecordFieldExplicit f <$> lift (checkExp e) <*> pure rloc + checkField (RecordFieldImplicit name NoInfo rloc) = do + errIfAlreadySet (baseName (unLoc name)) rloc + t <- lift $ asStructType =<< lookupVar rloc (qualName (unLoc name)) + modify $ M.insert (baseName (unLoc name)) rloc + pure $ RecordFieldImplicit name (Info t) rloc + + errIfAlreadySet f rloc = do + maybe_sloc <- gets $ M.lookup f + case maybe_sloc of + Just sloc -> + lift . typeError rloc mempty $ + "Field" + <+> dquotes (pretty f) + <+> "previously defined at" + <+> pretty (locStrRel rloc sloc) + <> "." + Nothing -> pure () + +-- +checkExp (Attr info e loc) = + Attr <$> checkAttr info <*> checkExp e <*> pure loc +checkExp (Assert e1 e2 NoInfo loc) = do + e1' <- require "being asserted" [Bool] =<< checkExp e1 + e2' <- checkExp e2 + pure $ Assert e1' e2' (Info (prettyText e1)) loc +-- +checkExp (Constr name es NoInfo loc) = do + es' <- mapM checkExp es + es_ts <- mapM expType es' + t <- newTypeWithConstr loc "t" NoUniqueness name es_ts + pure $ Constr name es' (Info t) loc +-- +checkExp (AppExp (Apply fe args loc) NoInfo) = do + fe' <- checkExp fe + (args', apply_args) <- + fmap NE.unzip . forM args $ \(_, arg) -> do + arg' <- checkExp arg + arg_t <- expType arg' + pure (arg', (Just arg', frameOf arg', arg_t)) + fe_t <- expType fe' + (rt, ams) <- checkApply loc fname (frameOf fe', fe_t) apply_args + rt' <- asStructType rt + let args'' = + NE.zipWith (\am arg -> (Info (Nothing, am), arg)) ams args' + pure $ AppExp (Apply fe' args'' loc) $ Info (AppRes rt' []) + where + fname = + case fe of + Var v _ _ -> Just v + _ -> Nothing +checkExp (AppExp (BinOp (op, oploc) NoInfo (e1, _) (e2, _) loc) NoInfo) = do + ftype <- lookupVar oploc op + e1' <- checkExp e1 + e1_t <- expType e1' + e2' <- checkExp e2 + e2_t <- expType e2' + + (rt, ams) <- + checkApply + loc + (Just op) + (mempty, ftype) + ((Just e1', frameOf e1', e1_t) NE.:| [(Just e2', frameOf e2', e2_t)]) + rt' <- asStructType rt + let (am1 NE.:| [am2]) = ams + + ftype' <- asStructType ftype + pure $ + AppExp + (BinOp (op, oploc) (Info ftype') (e1', Info (Nothing, am1)) (e2', Info (Nothing, am2)) loc) + (Info (AppRes rt' [])) +-- +checkExp (OpSectionLeft op _ e _ _ loc) = do + optype <- lookupVar loc op + e' <- checkExp e + e_t <- expType e' + t2 <- newType loc Lifted "t" NoUniqueness + t2' <- asStructType t2 + let f1 = frameOf e' + (rt, ams) <- + checkApply + loc + (Just op) + (mempty, optype) + ((Just e', f1, e_t) NE.:| [(Nothing, mempty, t2)]) + rt' <- asStructType rt + + let (am1 NE.:| _) = ams + t1 <- asStructType e_t + optype' <- asStructType optype + pure $ + OpSectionLeft + op + (Info optype') + e' + ( Info (Unnamed, toParam Observe t1, Nothing, am1), + Info (Unnamed, toParam Observe t2') + ) + (Info (RetType [] (rt' `setUniqueness` Nonunique)), Info []) + loc +checkExp (OpSectionRight op _ e _ NoInfo loc) = do + optype <- lookupVar loc op + e' <- checkExp e + e_t <- expType e' + t1 <- newType loc Lifted "t" NoUniqueness + t1' <- asStructType t1 + let f2 = frameOf e' + (rt, ams) <- + checkApply + loc + (Just op) + (mempty, optype) + ((Nothing, mempty, t1) NE.:| [(Just e', f2, e_t)]) + rt' <- asStructType rt + let (_ NE.:| [am2]) = ams + t2 <- asStructType e_t + + optype' <- asStructType optype + pure $ + OpSectionRight + op + (Info optype') + e' + -- Dummy types. + ( Info (Unnamed, toParam Observe t1'), + Info (Unnamed, toParam Observe t2, Nothing, am2) + ) + (Info $ RetType [] (rt' `setUniqueness` Nonunique)) + loc +-- +checkExp (ProjectSection fields NoInfo loc) = do + a <- newType loc Lifted "a" NoUniqueness + b <- newType loc Lifted "b" NoUniqueness + mustHaveFields loc a fields b + ft <- asStructType $ Scalar $ Arrow mempty Unnamed Observe a $ RetType [] $ b `setUniqueness` Nonunique + pure $ ProjectSection fields (Info ft) loc +-- +checkExp (Lambda params body retdecl NoInfo loc) = do + bindParams [] params $ \params' -> do + body' <- checkExp body + + (body_t, retdecl') <- checkRetDecl body' retdecl + body_t' <- asStructType body_t + let ret = RetType [] $ toRes Nonunique body_t' + pure $ Lambda params' body' retdecl' (Info ret) loc +-- +checkExp (AppExp (LetPat sizes pat e body loc) _) = do + e' <- checkExp e + e_t <- expType e' + + bindSizes sizes . incLevel . bindLetPat pat e_t $ \pat' -> do + body' <- incLevel $ checkExp body + body_t <- expType body' + + body_t' <- asStructType body_t + pure $ + AppExp + (LetPat sizes (fmap toStruct pat') e' body' loc) + (Info $ AppRes body_t' []) +-- +checkExp (AppExp (LetFun name (tparams, params, retdecl, NoInfo, e) body loc) _) = do + (tparams', params', retdecl', rettype, e') <- + bindParams tparams params $ \params' -> do + e' <- checkExp e + (e_t, retdecl') <- checkRetDecl e' retdecl + pure (tparams, params', retdecl', fmap (const Nonunique) e_t, e') + + params'' <- mapM (traverse asType) params' + + let entry = BoundV tparams' $ funType params'' $ RetType [] rettype + bindF scope = + scope + { scopeVtable = M.insert (fst name) entry $ scopeVtable scope + } + body' <- localScope bindF $ checkExp body + body_t <- expType body' + + body_t' <- asStructType body_t + rettype' <- asStructType rettype + pure $ + AppExp + ( LetFun + name + (tparams', params', retdecl', Info (RetType [] rettype'), e') + body' + loc + ) + (Info $ AppRes body_t' []) +-- +checkExp (AppExp (Range start maybe_step end loc) _) = do + start' <- require "use in range expression" anyIntType =<< checkExp start + let check e = do + e' <- checkExp e + start_t <- expType start' + e_t <- expType e' + ctEq (Reason (locOf e')) start_t e_t + pure e' + maybe_step' <- traverse check maybe_step + end' <- traverse check end + range_t <- newElemType loc "range" NoUniqueness + range_t' <- asType range_t + start_t <- expType start' + ctEq (Reason (locOf start')) range_t' (arrayOfRank 1 start_t) + pure $ AppExp (Range start' maybe_step' end' loc) $ Info $ AppRes range_t [] +-- +checkExp (Project k e NoInfo loc) = do + e' <- checkExp e + kt <- newType loc Lifted "kt" NoUniqueness + t <- newTypeWithField loc "t" k kt + e_t <- expType e' + ctEq (Reason (locOf e')) e_t t + kt' <- asStructType kt + pure $ Project k e' (Info kt') loc +-- +checkExp (RecordUpdate src fields ve NoInfo loc) = do + src' <- checkExp src + src_t <- expType src' + ve' <- checkExp ve + ve_t <- expType ve' + mustHaveFields loc src_t fields ve_t + src_t' <- asStructType src_t + pure $ RecordUpdate src' fields ve' (Info src_t') loc +-- +checkExp (IndexSection slice NoInfo loc) = do + slice' <- checkSlice slice + index_arg_t <- newElemType loc "index" NoUniqueness + index_elem_t <- newElemType loc "index_elem" NoUniqueness + index_res_t <- newElemType loc "index_res" NoUniqueness + let num_slices = length $ filter isSlice slice + ctEq (Reason (locOf loc)) index_arg_t $ arrayOfRank num_slices index_elem_t + ctEq (Reason (locOf loc)) index_res_t $ arrayOfRank (length slice) index_elem_t + ft <- asStructType $ Scalar $ Arrow mempty Unnamed Observe index_arg_t $ second (const Nonunique) $ RetType [] index_res_t + pure $ IndexSection slice' (Info ft) loc +-- +checkExp (AppExp (Index e slice loc) _) = do + e' <- checkExp e + e_t <- expType e' + slice' <- checkSlice slice + index_tv <- newTyVar loc Unlifted "index" + index_elem_t <- newElemType loc "index_elem" NoUniqueness + let num_slices = length $ filter isSlice slice + ctEq (Reason (locOf loc)) (tyVarType NoUniqueness index_tv) $ arrayOfRank num_slices index_elem_t + ctEq (Reason (locOf e')) e_t $ arrayOfRank (length slice) index_elem_t + pure $ AppExp (Index e' slice' loc) (Info $ AppRes (tyVarType NoUniqueness index_tv) []) +-- +checkExp (Update src slice ve loc) = do + src' <- checkExp src + src_t <- expType src' + slice' <- checkSlice slice + ve' <- checkExp ve + ve_t <- expType ve' + let num_slices = length $ filter isSlice slice + update_elem_t <- newElemType loc "update_elem" NoUniqueness + ctEq (Reason (locOf src')) src_t $ arrayOfRank (length slice) update_elem_t + ctEq (Reason (locOf ve')) ve_t $ arrayOfRank num_slices update_elem_t + pure $ Update src' slice' ve' loc +-- +checkExp (AppExp (LetWith dest src slice ve body loc) _) = do + src_t <- lookupVar (srclocOf src) $ qualName $ identName src + src_t' <- asStructType src_t + let src' = src {identType = Info src_t'} + dest' = dest {identType = Info src_t'} + slice' <- checkSlice slice + ve' <- checkExp ve + ve_t <- expType ve' + let num_slices = length $ filter isSlice slice + update_elem_t <- newElemType loc "update_elem" NoUniqueness + ctEq (Reason (locOf loc)) src_t $ arrayOfRank (length slice) update_elem_t + ctEq (Reason (locOf ve')) ve_t $ arrayOfRank num_slices update_elem_t + bind [dest'] $ do + body' <- checkExp body + body_t <- expType body' + body_t' <- asStructType body_t + pure $ AppExp (LetWith dest' src' slice' ve' body' loc) (Info $ AppRes body_t' []) +-- +checkExp (AppExp (If e1 e2 e3 loc) _) = do + e1' <- checkExp e1 + e1_t <- expType e1' + e2' <- checkExp e2 + e2_t <- expType e2' + e3' <- checkExp e3 + e3_t <- expType e3' + if_t <- newType loc SizeLifted "if_t" NoUniqueness + + ctEq (Reason (locOf e1')) e1_t (Scalar (Prim Bool)) + ctEq (ReasonBranches (locOf loc) e2_t e3_t) e2_t if_t + ctEq (ReasonBranches (locOf loc) e2_t e3_t) e3_t if_t + + if_t' <- asStructType if_t + pure $ AppExp (If e1' e2' e3' loc) (Info $ AppRes if_t' []) +-- +checkExp (AppExp (Match e cs loc) _) = do + e' <- checkExp e + e_t <- expType e' + (cs', t) <- checkCases e_t cs + + match_t <- newType loc SizeLifted "match_t" NoUniqueness + ctEq (Reason (locOf loc)) match_t t + + match_t' <- asStructType match_t + pure $ AppExp (Match e' cs' loc) (Info $ AppRes match_t' []) +-- +checkExp (AppExp (Loop _ pat arg form body loc) _) = do + arg' <- checkExp $ case arg of + LoopInitExplicit e -> e + LoopInitImplicit _ -> + -- Should have been filled out in Names + error "Unspected LoopInitImplicit" + arg_t <- expType arg' + bindLetPat pat arg_t $ \pat' -> do + (form', body') <- + case form of + For (Ident i _ iloc) bound -> do + bound' <- require "loop bound" anyIntType =<< checkExp bound + bound_t <- expType bound' + bound_t' <- asStructType bound_t + let i' = Ident i (Info bound_t') iloc + bind [i'] $ do + body' <- checkExp body + pure (For i' bound', body') + While cond -> do + cond' <- checkExp cond + body' <- checkExp body + pure (While cond', body') + ForIn elemp arr -> do + arr' <- checkExp arr + elem_t <- newElemType elemp "elem" NoUniqueness + arr_t <- expType arr' + elem_t' <- asType elem_t + ctEq (Reason (locOf arr')) arr_t $ arrayOfRank 1 elem_t' + bindLetPat elemp elem_t' $ \elemp' -> do + body' <- checkExp body + pure (ForIn (toStruct <$> elemp') arr', body') + body_t <- expType body' + ctEq (Reason (locOf loc)) arg_t body_t + pure $ + AppExp + (Loop [] pat' (LoopInitExplicit arg') form' body' loc) + (Info (AppRes (patternStructType pat') [])) +-- +checkExp (Ascript e te loc) = do + e' <- checkExp e + (te', _, RetType _ st, _) <- checkTypeExp checkSizeExp' te + e_t <- expType e' + st' <- asType st + ctEq (ReasonAscription (locOf e') (toStruct st') (toStruct e_t)) e_t st' + pure $ Ascript e' te' loc +checkExp (Coerce e te NoInfo loc) = do + e' <- checkExp e + (te', _, RetType _ st, _) <- checkTypeExp checkSizeExp' te + e_t <- expType e' + st' <- asType st + ctEq (Reason (locOf e')) e_t st' + pure $ Coerce e' te' (Info (toStruct st)) loc + +doDefault :: + [VName] -> + VName -> + Either [PrimType] (TypeBase () NoUniqueness) -> + TermM (TypeBase () NoUniqueness) +doDefault tyvars_at_toplevel v (Left pts) + | [pt] <- pts = + pure $ Scalar $ Prim pt + | Signed Int32 `elem` pts = do + when (v `elem` tyvars_at_toplevel) $ + warn usage "Defaulting ambiguous type to i32." + pure $ Scalar $ Prim $ Signed Int32 + | FloatType Float64 `elem` pts = do + when (v `elem` tyvars_at_toplevel) $ + warn usage "Defaulting ambiguous type to f64." + pure $ Scalar $ Prim $ FloatType Float64 + | otherwise = + typeError usage mempty . withIndexLink "ambiguous-type" $ + "Type is ambiguous (could be one of" + <+> commasep (map pretty pts) + <> ")." + "Add a type annotation to disambiguate the type." + where + usage = mkUsage NoLoc "overload" +doDefault _ _ (Right t) = pure t + +-- | Apply defaults on otherwise ambiguous types. This may result in +-- some type variables becoming known, so we have to perform +-- substitutions on the RHS of the substitutions afterwards. +doDefaults :: + [VName] -> + M.Map TyVar (Either [PrimType] (TypeBase () NoUniqueness)) -> + TermM (M.Map TyVar (TypeBase () NoUniqueness)) +doDefaults tyvars_at_toplevel substs = do + substs' <- M.traverseWithKey (doDefault tyvars_at_toplevel) substs + pure $ M.map (substTyVars (`M.lookup` substs')) substs' + +generalise :: + TypeBase () NoUniqueness -> + [UnconTyVar] -> + Solution -> + ([TypeParam], [VName]) +generalise fun_t unconstrained solution = + -- Candidates for let-generalisation are those type variables that + -- are used in fun_t. + let visible = foldMap expandTyVars $ typeVars fun_t + onTyVar (v, l) + | v `S.member` visible = Left $ TypeParamType l v mempty + | otherwise = Right v + in partitionEithers $ map onTyVar unconstrained + where + expandTyVars v = + case M.lookup v solution of + Just (Right t) -> foldMap expandTyVars $ typeVars t + _ -> S.singleton v + +generaliseAndDefaults :: + [UnconTyVar] -> + Solution -> + TypeBase () NoUniqueness -> + TermM ([TypeParam], M.Map VName (TypeBase () NoUniqueness)) +generaliseAndDefaults unconstrained solution t = do + let (generalised, unconstrained') = + generalise t unconstrained solution + solution' <- doDefaults (S.toList $ typeVars t) solution + pure + ( generalised, + -- See #1552 for why we resolve unconstrained and + -- un-generalised type variables to (). + M.fromList (map (,Scalar (Record mempty)) unconstrained') <> solution' + ) + +-- | Type check a single value definition. +checkValDef :: + ( VName, + Maybe (TypeExp (ExpBase NoInfo VName) VName), + [TypeParam], + [PatBase NoInfo VName ParamType], + ExpBase NoInfo VName, + SrcLoc + ) -> + TypeM + ( Either TypeError ([TypeParam], M.Map TyVar (TypeBase () NoUniqueness)), + [Pat ParamType], + Maybe (TypeExp Exp VName), + Exp + ) +checkValDef (fname, retdecl, tparams, params, body, loc) = runTermM $ do + (params', body', retdecl') <- + bindParams tparams params $ \params' -> do + body' <- checkExp body + (_, retdecl') <- checkRetDecl body' retdecl + pure (params', body', retdecl') + + cts <- gets termConstraints + cts_am <- gets termAM + tyvars <- gets termTyVars + typarams <- gets termTyParams + artificial <- gets termArtificial + + debugTraceM 3 $ "\n# function " <> prettyNameString fname <> "\n# " <> locStr loc <> "\n" + + debugTraceM 3 $ + unlines + [ "## cts:", + unlines $ map prettyString cts, + "## body:", + prettyString body', + "## tyvars:", + unlines $ map (prettyString . first prettyNameString) $ M.toList tyvars, + "## artificial:", + unlines $ map (\(v, t) -> prettyNameString v <> " => " <> prettyString t) (M.toList artificial) + ] + + onRankSolution typarams + =<< rankAnalysis1 loc (cts, cts_am) tyvars artificial params' body' retdecl' + where + onRankSolution typarams ((cts', artificial, tyvars'), params', body'', retdecl') = do + solution <- + bitraverse + pure + (fmap (second (onArtificial artificial)) . onTySolution params' body'') + $ solve (reverse cts') typarams tyvars' + debugTraceM 3 $ + unlines + [ "## constraints:", + unlines $ map prettyString cts', + "## typarams:", + let f (lvl, l, _) = (lvl, l) + in unlines (map (prettyString . bimap prettyNameString f) (M.toList typarams)), + "## tyvars':", + unlines $ map (prettyString . first prettyNameString) $ M.toList tyvars', + "## solution:", + let p (v, t) = prettyNameString v <> " => " <> prettyString t + in either (docString . prettyTypeError) (unlines . map p . M.toList . snd) solution, + either (const mempty) (unlines . ("## generalised:" :) . map prettyString . fst) solution + ] + pure (solution, params', retdecl', body'') + + onTySolution params' body' (unconstrained, solution) = do + body_t <- expType body' + let fun_t = + foldFunType + (map (first (const ()) . patternType) params') + (RetType [] $ bimap (const ()) (const Nonunique) body_t) + generaliseAndDefaults unconstrained solution fun_t + + onArtificial artificial solution = + M.map (substTyVars (`M.lookup` solution) . first (const ())) artificial <> solution + +-- | Type check a single expression, which may have a polymorphic +-- type. +checkSingleExp :: + ExpBase NoInfo VName -> + TypeM (Either TypeError ([TypeParam], M.Map TyVar (TypeBase () NoUniqueness)), Exp) +checkSingleExp e = runTermM $ do + e' <- checkExp e + cts <- gets termConstraints + cts_am <- gets termAM + tyvars <- gets termTyVars + typarams <- gets termTyParams + artificial <- gets termArtificial + ((cts', _artificial', tyvars'), _, e'', _) <- + rankAnalysis1 (srclocOf e') (cts, cts_am) tyvars artificial [] e' Nothing + case solve cts' typarams tyvars' of + Left err -> pure (Left err, e'') + Right (unconstrained, solution) -> do + e_t <- expType e'' + x <- generaliseAndDefaults unconstrained solution $ first (const ()) e_t + pure (Right x, e'') + +-- | Type-check a single size expression in isolation, which must have +-- type @i64@. +checkSizeExp :: + ExpBase NoInfo VName -> + TypeM (Either TypeError ([UnconTyVar], M.Map TyVar (TypeBase () NoUniqueness)), Exp) +checkSizeExp e = runTermM $ do + e' <- checkSizeExp' e + cts <- gets termConstraints + cts_am <- gets termAM + tyvars <- gets termTyVars + typarams <- gets termTyParams + artificial <- gets termArtificial + + (cts_tyvars', _, es', _) <- + L.unzip4 <$> rankAnalysis (srclocOf e) (cts, cts_am) tyvars artificial [] e' Nothing + + solutions <- + forM cts_tyvars' $ \(cts', _artificial', tyvars') -> + bitraverse pure (traverse (doDefaults mempty)) $ solve cts' typarams tyvars' + + case (solutions, es') of + ([solution], [e'']) -> + pure (solution, e'') + _ -> pure (Left $ TypeError (locOf e) mempty "Ambiguous size expression", e') diff --git a/src/Language/Futhark/TypeChecker/TySolve.hs b/src/Language/Futhark/TypeChecker/TySolve.hs new file mode 100644 index 0000000000..82afb9e190 --- /dev/null +++ b/src/Language/Futhark/TypeChecker/TySolve.hs @@ -0,0 +1,827 @@ +module Language.Futhark.TypeChecker.TySolve + ( Type, + Solution, + UnconTyVar, + solve, + ) +where + +import Control.Monad +import Control.Monad.Except +import Control.Monad.Reader +import Control.Monad.ST +import Data.Bifunctor +import Data.List qualified as L +import Data.Loc +import Data.Map qualified as M +import Data.Maybe +import Data.Set qualified as S +import Debug.Trace (trace) +import Futhark.Util (isEnvVarAtLeast) +import Futhark.Util.Pretty +import Language.Futhark +import Language.Futhark.TypeChecker.Constraints +import Language.Futhark.TypeChecker.Error +import Language.Futhark.TypeChecker.Monad (Notes, TypeError (..), aNote, prettyTypeError) +import Language.Futhark.TypeChecker.UnionFind + +-- | The type representation used by the constraint solver. Agnostic +-- to sizes and uniqueness. +type Type = CtType () + +type UF s = M.Map TyVar (TyVarNode s) + +newtype SolverState s = SolverState {solverTyVars :: UF s} + +newtype SolveM s a = SolveM + { runSolveM :: ExceptT TypeError (ReaderT (SolverState s) (ST s)) a + } + deriving (Functor, Applicative, Monad, MonadError TypeError, MonadReader (SolverState s)) + +-- | A solution maps a type variable to its substitution. This +-- substitution is complete, in the sense there are no right-hand +-- sides that contain a type variable. +type Solution = M.Map TyVar (Either [PrimType] (TypeBase () NoUniqueness)) + +-- | An unconstrained type variable comprises a name and (ironically) +-- a constraint on how it can be instantiated. +type UnconTyVar = (VName, Liftedness) + +liftST :: ST s a -> SolveM s a +liftST = SolveM . lift . lift + +getSol' :: TyVarNode s -> SolveM s TyVarSol +getSol' = liftST . getSol + +union' :: TyVarNode s -> TyVarNode s -> SolveM s () +union' tv1 tv2 = liftST $ union tv1 tv2 + +unionNewSol' tv1 tv2 new_sol = liftST $ unionNewSol tv1 tv2 new_sol + +unionNewSol' :: TyVarNode s -> TyVarNode s -> TyVarSol -> SolveM s () +getKey' :: TyVarNode s -> SolveM s TyVar +getKey' = liftST . getKey + +initializeState :: TyParams -> TyVars () -> ST s (SolverState s) +initializeState typarams tyvars = do + tyvars' <- M.traverseWithKey f tyvars + typarams' <- M.traverseWithKey g typarams + pure $ SolverState $ typarams' <> tyvars' + where + f tv (_lvl, info) = makeTyVarNode tv info + g tv (lvl, lft, loc) = makeTyParamNode tv lvl lft loc + +typeError :: Loc -> Notes -> Doc () -> SolveM s () +typeError loc notes msg = + throwError $ TypeError loc notes msg + +typeVar :: (Monoid u) => VName -> TypeBase dim u +typeVar v = Scalar $ TypeVar mempty (qualName v) [] + +cannotUnify :: + Reason Type -> + Notes -> + BreadCrumbs -> + Type -> + Type -> + SolveM s () +cannotUnify reason notes bcs t1 t2 = do + t1' <- substTyVars t1 + t2' <- substTyVars t2 + case reason of + Reason loc -> + typeError loc notes . stack $ + [ "Cannot unify", + indent 2 (pretty t1'), + "with", + indent 2 (pretty t2') + ] + <> [pretty bcs | not $ hasNoBreadCrumbs bcs] + ReasonPatMatch loc pat value_t -> + typeError loc notes . stack $ + [ "Pattern", + indent 2 $ align $ pretty pat, + "cannot match value of type", + indent 2 $ align $ pretty value_t + ] + <> [pretty bcs | not $ hasNoBreadCrumbs bcs] + ReasonAscription loc expected actual -> + typeError loc notes . stack $ + [ "Expression does not have expected type from type ascription.", + "Expected:" <+> align (pretty expected), + "Actual: " <+> align (pretty actual) + ] + <> [pretty bcs | not $ hasNoBreadCrumbs bcs] + ReasonRetType loc expected actual -> do + expected' <- substTyVars expected + actual' <- substTyVars actual + typeError loc notes . stack $ + [ "Function body does not have expected type.", + "Expected:" <+> align (pretty expected'), + "Actual: " <+> align (pretty actual') + ] + <> [pretty bcs | not $ hasNoBreadCrumbs bcs] + ReasonApply loc f e expected actual -> do + expected' <- substTyVars expected + actual' <- substTyVars actual + typeError loc notes . stack $ + [ header, + "Expected:" <+> align (pretty expected'), + "Actual: " <+> align (pretty actual') + ] + where + header = + case f of + (Nothing, _) -> + "Cannot apply function to" + <+> dquotes (shorten $ group $ pretty e) + <> " (invalid type)." + (Just fname, _) -> + "Cannot apply" + <+> dquotes (pretty fname) + <+> "to" + <+> dquotes (align $ shorten $ group $ pretty e) + <> " (invalid type)." + ReasonApplySplit loc (fname, 0) _ ftype -> + typeError loc notes $ + stack + [ "Cannot apply" + <+> fname' + <+> "as function, as it has non-function type:" + indent 2 (align $ pretty ftype) + ] + where + fname' = maybe "expression" (dquotes . pretty) fname + ReasonApplySplit loc (fname, i) e _ -> + typeError loc notes $ + stack + [ "Cannot apply" + <+> fname' + <+> "to" + <+> dquotes (align $ shorten $ group $ pretty e) + <> ".", + "Function accepts only" <+> pretty i <+> "arguments." + ] + where + fname' = maybe "expression" (dquotes . pretty) fname + ReasonBranches loc former latter -> do + former' <- substTyVars former + latter' <- substTyVars latter + typeError loc notes . stack $ + [ "Branches differ in type.", + "Former:" <+> pretty former', + "Latter:" <+> pretty latter' + ] + +unsharedConstructorsMsg :: M.Map Name t -> M.Map Name t -> Doc a +unsharedConstructorsMsg cs1 cs2 = + "Unshared constructors:" <+> commasep (map (("#" <>) . pretty) missing) <> "." + where + missing = + filter (`notElem` M.keys cs1) (M.keys cs2) + ++ filter (`notElem` M.keys cs2) (M.keys cs1) + +substTyVars :: (Monoid u) => TypeBase () u -> SolveM s (TypeBase () u) +substTyVars (Scalar (TypeVar u qn args)) = do + mb_node <- maybeLookupUF $ qualLeaf qn + case mb_node of + Just node -> do + sol <- getSol' node + qn_k <- qualName <$> getKey' node + case sol of + Solved t -> do + t' <- substTyVars t + pure $ second (const mempty) t' + _ -> makeTyVar qn_k + _ -> makeTyVar qn + where + makeTyVar qn' = do + args' <- mapM onArg args + pure $ Scalar $ TypeVar u qn' args' + onArg (TypeArgType t) = TypeArgType <$> substTyVars t + onArg d@(TypeArgDim _) = pure d +substTyVars p@(Scalar (Prim _)) = pure p +substTyVars (Scalar (Record fs)) = + Scalar . Record <$> traverse substTyVars fs +substTyVars (Scalar (Sum cs)) = + Scalar . Sum <$> traverse (mapM substTyVars) cs +substTyVars (Scalar (Arrow u pname d t1 (RetType ext t2))) = do + t1' <- substTyVars t1 + t2' <- substTyVars t2 + pure $ + Scalar $ + Arrow u pname d t1' $ + RetType ext $ + t2' `setUniqueness` uniqueness t2 +substTyVars (Array u shape elemt) = do + elemt' <- substTyVars $ Scalar elemt + pure $ arrayOfWithAliases u shape elemt' + +occursCheck :: Reason Type -> VName -> VName -> Type -> SolveM s () +occursCheck reason v k tp = do + let vars = typeVars tp + when (k `S.member` vars) . typeError (locOf reason) mempty $ + "Occurs check: cannot instantiate" + <+> prettyName v + <+> "with" + <+> pretty tp + <> "." + +bindTyVar :: + Reason Type -> + BreadCrumbs -> + VName -> + TyVarNode s -> + Type -> + SolveM s () +bindTyVar reason bcs v v_node t' = do + t <- substTyVars t' + k <- getKey' v_node + occursCheck reason v k t + + v_info <- getSol' v_node + + setInfo v_node $ Solved t + + case (v_info, t) of + (Unsolved TyVarFree {}, _) -> pure () + (Unsolved (TyVarPrim _ v_pts), _) -> + if t `elem` map (Scalar . Prim) v_pts + then pure () + else cannotUnify reason notes bcs (typeVar v) t + where + notes = + aNote $ + "Cannot instantiate type that must be one of" + indent 2 (pretty v_pts) + "with" + indent 2 (pretty t) + (Unsolved (TyVarSum _ cs1), Scalar (Sum cs2)) -> + if all (`elem` M.keys cs2) (M.keys cs1) + then unifySharedConstructors reason bcs cs1 cs2 + else cannotUnify reason notes bcs (typeVar v) t + where + notes = + aNote $ + "Cannot match type with constructors" + indent 2 (stack (map (("#" <>) . pretty) (M.keys cs1))) + "with type with constructors" + indent 2 (stack (map (("#" <>) . pretty) (M.keys cs2))) + unsharedConstructorsMsg cs1 cs2 + (Unsolved (TyVarSum _ cs1), _) -> + typeError (locOf reason) mempty $ + "Cannot unify type with constructors" + indent 2 (pretty (Sum cs1)) + "with type" + indent 2 (pretty t) + (Unsolved (TyVarRecord _ fs1), Scalar (Record fs2)) -> + if all (`elem` M.keys fs2) (M.keys fs1) + then unifySharedFields reason bcs fs1 fs2 + else + typeError (locOf reason) mempty $ + "Cannot unify record type with fields" + indent 2 (pretty (Record fs1)) + "with record type" + indent 2 (pretty (Record fs2)) + (Unsolved (TyVarRecord _ fs1), _) -> + typeError (locOf reason) mempty $ + "Cannot unify record type with fields" + indent 2 (pretty (Record fs1)) + "with type" + indent 2 (pretty t) + -- + -- Internal error cases + (Solved {}, _) -> + error $ "Type variable already solved: " <> prettyNameString v + (Param {}, _) -> + error $ "Cannot substitute type parameter: " <> prettyNameString v + +solveCt :: CtTy () -> SolveM s () +solveCt (CtEq reason t1 t2) = solveEq reason mempty t1 t2 + +solveEq :: Reason Type -> BreadCrumbs -> Type -> Type -> SolveM s () +solveEq reason obcs orig_t1 orig_t2 = do + solveCt' (obcs, (orig_t1, orig_t2)) + where + flexible :: VName -> SolveM s (Maybe (TyVarNode s)) + flexible v = do + uf <- asks solverTyVars + case M.lookup v uf of + j_n@(Just node) -> do + sol <- getSol' node + pure $ case sol of + Unsolved _ -> j_n + _ -> Nothing + Nothing -> pure Nothing + + normalize :: TypeBase () NoUniqueness -> SolveM s (TypeBase () NoUniqueness) + normalize t@(Scalar (TypeVar _ (QualName [] v) [])) = do + uf <- asks solverTyVars + case M.lookup v uf of + Just node -> do + sol <- getSol' node + case sol of + Solved t' -> normalize t' + _ -> typeVar <$> getKey' node + Nothing -> pure t + normalize t = pure t + + solveCt' :: (BreadCrumbs, (Type, Type)) -> SolveM s () + solveCt' (bcs, (t1, t2)) = do + t1' <- normalize t1 + t2' <- normalize t2 + case (t1', t2') of + ( Scalar (TypeVar _ (QualName [] v1) []), + Scalar (TypeVar _ (QualName [] v2) []) + ) + | v1 == v2 -> pure () + | otherwise -> do + mb_node1 <- flexible v1 + mb_node2 <- flexible v2 + case (mb_node1, mb_node2) of + (Nothing, Nothing) -> + cannotUnify reason mempty bcs t1 t2 + (Just v1_node, Nothing) -> + bindTyVar reason bcs v1 v1_node t2' + (Nothing, Just v2_node) -> + bindTyVar reason bcs v2 v2_node t1' + (Just v1_node, Just v2_node) -> + unionTyVars reason bcs v1 v1_node v2_node + (Scalar (TypeVar _ (QualName [] v1) []), _) -> do + mb_node <- flexible v1 + case mb_node of + Just node -> bindTyVar reason bcs v1 node t2' + Nothing -> tryUnify t1' t2' reason bcs + (_, Scalar (TypeVar _ (QualName [] v2) [])) -> do + mb_node <- flexible v2 + case mb_node of + Just node -> bindTyVar reason bcs v2 node t1' + Nothing -> tryUnify t1' t2' reason bcs + (_, _) -> tryUnify t1' t2' reason bcs + + tryUnify :: Type -> Type -> Reason Type -> BreadCrumbs -> SolveM s () + tryUnify t1 t2 r bcs = + case unify t1 t2 of + Left details -> cannotUnify r (aNote details) bcs t1 t2 + Right eqs -> mapM_ solveCt' eqs + +-- | Unify at the root, emitting new equalities that must hold. +unify :: Type -> Type -> Either (Doc a) [(BreadCrumbs, (Type, Type))] +unify (Scalar (Prim pt1)) (Scalar (Prim pt2)) + | pt1 == pt2 = Right [] +unify + (Scalar (TypeVar _ (QualName _ v1) targs1)) + (Scalar (TypeVar _ (QualName _ v2) targs2)) + | v1 == v2 = + Right $ mapMaybe f $ zip targs1 targs2 + where + f (TypeArgType t1, TypeArgType t2) = Just (mempty, (t1, t2)) + f _ = Nothing +unify + (Scalar (Arrow _ _ _ t1a (RetType _ t1r))) + (Scalar (Arrow _ _ _ t2a (RetType _ t2r))) = + Right [(mempty, (t1a, t2a)), (mempty, (t1r', t2r'))] + where + t1r' = t1r `setUniqueness` NoUniqueness + t2r' = t2r `setUniqueness` NoUniqueness +unify (Scalar (Record fs1)) (Scalar (Record fs2)) + | M.keys fs1 == M.keys fs2 = + Right $ + map (first matchingField) $ + M.toList $ + M.intersectionWith (,) fs1 fs2 + | Just n1 <- length <$> areTupleFields fs1, + Just n2 <- length <$> areTupleFields fs2, + n1 /= n2 = + Left $ + "Tuples have" + <+> pretty n1 + <+> "and" + <+> pretty n2 + <+> "elements respectively." + | otherwise = + let missing = + filter (`notElem` M.keys fs1) (M.keys fs2) + <> filter (`notElem` M.keys fs2) (M.keys fs1) + in Left $ + "unshared fields:" <+> commasep (map pretty missing) <> "." +unify (Scalar (Sum cs1)) (Scalar (Sum cs2)) + | M.keys cs1 == M.keys cs2 = + fmap concat . forM cs' $ \(c, (ts1, ts2)) -> do + if length ts1 == length ts2 + then Right $ zipWith (curry (matchingConstructor c,)) ts1 ts2 + else Left mempty + | otherwise = + Left $ unsharedConstructorsMsg cs1 cs2 + where + cs' = M.toList $ M.intersectionWith (,) cs1 cs2 +unify t1 t2 + | Just t1' <- peelArray 1 t1, + Just t2' <- peelArray 1 t2 = + Right [(mempty, (t1', t2'))] +unify _ _ = Left mempty + +maybeLookupTyVarSol :: TyVar -> SolveM s (Maybe TyVarSol) +maybeLookupTyVarSol tv = do + tyvars <- asks solverTyVars + case M.lookup tv tyvars of + Nothing -> pure Nothing + Just node -> do + sol <- getSol' node + pure $ Just sol + +lookupTyVar :: TyVar -> SolveM s (Either (TyVarInfo ()) Type) +lookupTyVar tv = + maybe bad unpack <$> maybeLookupTyVarSol tv + where + bad = error $ "Unknown tyvar: " <> prettyNameString tv + unpack (Param {}) = error $ "Is a type param: " <> prettyNameString tv + unpack (Solved t) = Right t + unpack (Unsolved info) = Left info + +lookupTyVarInfo :: TyVarNode s -> SolveM s (TyVarInfo ()) +lookupTyVarInfo v_node = do + r <- getSol' v_node + case r of + Unsolved info -> pure info + _ -> do + v <- getKey' v_node + error $ "Tyvar is nonflexible: " <> prettyNameString v + +lookupUF :: TyVar -> SolveM s (TyVarNode s) +lookupUF tv = do + uf <- asks solverTyVars + case M.lookup tv uf of + Nothing -> error $ "Unknown tyvar: " <> prettyNameString tv + Just node -> pure node + +unifySharedFields :: + Reason Type -> + BreadCrumbs -> + M.Map Name Type -> + M.Map Name Type -> + SolveM s () +unifySharedFields reason bcs fs1 fs2 = + forM_ (M.toList $ M.intersectionWith (,) fs1 fs2) $ \(f, (ts1, ts2)) -> + solveEq reason (matchingField f <> bcs) ts1 ts2 + +unifySharedConstructors :: + Reason Type -> + BreadCrumbs -> + M.Map Name [Type] -> + M.Map Name [Type] -> + SolveM s () +unifySharedConstructors reason bcs cs1 cs2 = + forM_ (M.toList $ M.intersectionWith (,) cs1 cs2) $ \(c, (ts1, ts2)) -> + if length ts1 == length ts2 + then zipWithM_ (solveEq reason $ matchingConstructor c <> bcs) ts1 ts2 + else + typeError (locOf reason) mempty $ + "Cannot unify type with constructor" + indent 2 (pretty (Sum (M.singleton c ts1))) + "with type of constructor" + indent 2 (pretty (Sum (M.singleton c ts2))) + "because they differ in arity." + +setInfo :: TyVarNode s -> TyVarSol -> SolveM s () +setInfo node sol = liftST $ assignNewSol node sol + +unionTyVars :: + Reason Type -> + BreadCrumbs -> + VName -> + TyVarNode s -> + TyVarNode s -> + SolveM s () +unionTyVars reason bcs v v_node t_node = do + v_sol <- getSol' v_node + t_info <- lookupTyVarInfo t_node + c <- check v_sol t_info + case c of + Left (loc, notes, msg) -> typeError loc notes msg + Right (Just new_sol) -> unionNewSol' v_node t_node new_sol + Right Nothing -> union' v_node t_node + where + check :: + TyVarSol -> + TyVarInfo () -> + SolveM s (Either (Loc, Notes, Doc ()) (Maybe TyVarSol)) + check v_sol t_info = + case (v_sol, t_info) of + (Unsolved (TyVarFree _ v_l), TyVarFree t_loc t_l) + | v_l /= t_l -> + pure $ Right $ Just $ Unsolved $ TyVarFree t_loc (min v_l t_l) + (Unsolved info, TyVarFree {}) -> do + pure $ Right $ Just $ Unsolved info + -- + -- TyVarPrim cases + ( Unsolved (TyVarPrim _ v_pts), + TyVarPrim t_loc t_pts + ) -> + let pts = L.intersect v_pts t_pts + in case pts of + [] -> + pure $ + Left + ( locOf reason, + mempty, + "Cannot unify type that must be one of" + indent 2 (pretty v_pts) + "with type that must be one of" + indent 2 (pretty t_pts) + ) + _ -> pure $ Right $ Just $ Unsolved $ TyVarPrim t_loc pts + (Unsolved (TyVarPrim _ v_pts), TyVarRecord {}) -> + pure $ + Left + ( locOf reason, + mempty, + "Cannot unify type that must be one of" + indent 2 (pretty v_pts) + "with type that must be a record." + ) + (Unsolved (TyVarPrim _ v_pts), TyVarSum {}) -> + pure $ + Left + ( locOf reason, + mempty, + "Cannot unify type that must be one of" + indent 2 (pretty v_pts) + "with type that must be sum." + ) + -- + -- TyVarSum cases + ( Unsolved (TyVarSum _ cs1), + TyVarSum loc cs2 + ) -> do + unifySharedConstructors reason bcs cs1 cs2 + let cs3 = cs1 <> cs2 + pure $ Right $ Just $ Unsolved $ TyVarSum loc cs3 + ( Unsolved TyVarSum {}, + TyVarPrim _ pts + ) -> + pure $ + Left + ( locOf reason, + mempty, + "A sum type cannot be one of" + indent 2 (pretty pts) + ) + ( Unsolved (TyVarSum _ cs1), + TyVarRecord _ fs + ) -> + pure $ + Left + ( locOf reason, + mempty, + "Cannot unify type with constructors" + indent 2 (pretty (Sum cs1)) + "with type" + indent 2 (pretty (Scalar (Record fs))) + ) + -- + -- TyVarRecord cases + ( Unsolved (TyVarRecord _ fs1), + TyVarRecord loc fs2 + ) -> do + unifySharedFields reason bcs fs1 fs2 + let fs3 = fs1 <> fs2 + pure $ Right $ Just $ Unsolved $ TyVarRecord loc fs3 + ( Unsolved TyVarRecord {}, + TyVarPrim _ pts + ) -> + pure $ + Left + ( locOf reason, + mempty, + "A record type cannot be one of" + indent 2 (pretty pts) + ) + ( Unsolved (TyVarRecord _ fs1), + TyVarSum _ cs + ) -> + pure $ + Left + ( locOf reason, + mempty, + "Cannot unify record type" + indent 2 (pretty (Record fs1)) + "with type" + indent 2 (pretty (Scalar (Sum cs))) + ) + -- + -- Internal error cases + (Solved {}, _) -> alreadySolved + (Param {}, _) -> isParam + _ -> pure $ Right Nothing + + alreadySolved = error $ "Type variable already solved: " <> prettyNameString v + isParam = error $ "Type name is a type parameter: " <> prettyNameString v + +scopeViolation :: Reason Type -> VName -> Type -> VName -> SolveM s () +scopeViolation reason v1 ty v2 = + typeError (locOf reason) mempty $ + "Cannot unify type" + indent 2 (pretty ty) + "with" + <+> dquotes (prettyName v1) + <+> "(scope violation)." + "This is because" + <+> dquotes (prettyName v2) + <+> "is rigidly bound in a deeper scope." + +scopeCheck :: Reason Type -> TyVar -> Level -> Type -> SolveM s () +scopeCheck reason v v_lvl ty = mapM_ check $ typeVars ty + where + check :: TyVar -> SolveM s () + check ty_v = do + maybe (pure ()) checkNode =<< maybeLookupUF ty_v + + checkNode :: TyVarNode s -> SolveM s () + checkNode node = do + sol <- getSol' node + case sol of + Param ty_v_lvl _ _ + | ty_v_lvl > v_lvl -> do + k <- getKey' node + ty' <- substTyVars ty + scopeViolation reason v ty' k + Solved ty' -> do + mapM_ check $ typeVars ty' + _ -> pure () + +-- | If a type variable has a liftedness constraint, we propagate that +-- constraint to its solution. The actual checking for correct usage +-- is done later. +liftednessCheck :: Liftedness -> Type -> SolveM s () +liftednessCheck l (Scalar (TypeVar _ (QualName [] v) _)) = do + v_info <- maybeLookupTyVarSol v + case v_info of + Nothing -> + -- Is an opaque type. + pure () + Just (Solved v_ty) -> + liftednessCheck l v_ty + Just Param {} -> pure () + Just (Unsolved (TyVarFree loc v_l)) + | l < v_l -> do + node <- lookupUF v + setInfo node $ Unsolved $ TyVarFree loc l + Just Unsolved {} -> pure () +liftednessCheck _ (Scalar Prim {}) = pure () +liftednessCheck Lifted _ = pure () +liftednessCheck _ Array {} = pure () +liftednessCheck _ (Scalar Arrow {}) = pure () +liftednessCheck l (Scalar (Record fs)) = + mapM_ (liftednessCheck l) fs +liftednessCheck l (Scalar (Sum cs)) = + mapM_ (mapM_ $ liftednessCheck l) cs +liftednessCheck _ (Scalar TypeVar {}) = pure () + +solveTyVar :: (VName, (Level, TyVarInfo ())) -> SolveM s () +solveTyVar (tv, (lvl, TyVarFree loc l)) = do + tv_t <- lookupTyVar tv + case tv_t of + Right ty -> do + scopeCheck (Reason loc) tv lvl ty + liftednessCheck l ty + _ -> pure () +solveTyVar (tv, (_, TyVarPrim loc pts)) = do + tv_t <- lookupTyVar tv + case tv_t of + Right ty + | ty `elem` map (Scalar . Prim) pts -> pure () + | otherwise -> + typeError loc mempty $ + "Numeric constant inferred to be of type" + indent 2 (align (pretty ty)) + "which is not possible." + _ -> pure () +solveTyVar (tv, (_, TyVarRecord loc fs1)) = do + tv_t <- lookupTyVar tv + case tv_t of + Left _ -> + typeError loc mempty $ + "Type" + <+> prettyName tv + <+> "is ambiguous." + "Must be a record with fields" + indent 2 (pretty (Scalar (Record fs1))) + Right _ -> pure () +solveTyVar (tv, (_, TyVarSum loc cs1)) = do + tv_t <- lookupTyVar tv + case tv_t of + Left _ -> + typeError loc mempty $ + "Type is ambiguous." + "Must be a sum type with constructors" + indent 2 (pretty (Scalar (Sum cs1))) + Right _ -> pure () + +maybeLookupUF :: TyVar -> SolveM s (Maybe (TyVarNode s)) +maybeLookupUF tv = do + uf <- asks solverTyVars + pure . M.lookup tv $ uf + +getSolution :: SolveM s ([UnconTyVar], Solution) +getSolution = do + uf <- asks solverTyVars + resolved <- M.traverseWithKey resolve uf + let unconstrained = M.foldrWithKey unconstr [] resolved + sol = M.mapMaybeWithKey mkSubst resolved + pure (unconstrained, sol) + where + resolve :: + TyVar -> + TyVarNode s -> + SolveM s (Either [PrimType] (TypeBase () NoUniqueness), Maybe Liftedness) + resolve tv node = do + sol <- getSol' node + case sol of + Unsolved (TyVarFree _ l) -> do + k <- getKey' node + let tv' = typeVar k + -- If the current type variable and root type variable are + -- different, this variable is unconstrained, so we save the + -- liftedness constraint for later. + pure (Right tv', if k == tv then Just l else Nothing) + Unsolved (TyVarPrim _ pts) -> pure (Left pts, Nothing) + Solved t -> do + t' <- substTyVars t + pure (Right $ first (const ()) t', Nothing) + _ -> do + k <- getKey' node + pure (Right $ typeVar k, Nothing) + + unconstr :: + TyVar -> + (Either [PrimType] (TypeBase () NoUniqueness), Maybe Liftedness) -> + [UnconTyVar] -> + [UnconTyVar] + unconstr tv (_, Just l) acc = (tv, l) : acc + unconstr _ _ acc = acc + + mkSubst :: + TyVar -> + (Either [PrimType] (TypeBase () NoUniqueness), Maybe Liftedness) -> + Maybe (Either [PrimType] (TypeBase () NoUniqueness)) + mkSubst _ (_, Just _) = Nothing + mkSubst tv (s@(Right (Scalar (TypeVar _ (QualName [] tv') _))), _) = + if tv /= tv' then Just s else Nothing + mkSubst _ (s, _) = Just s + +-- | Print in a way helpful for writing a test case for TySolveTests. +logSolution :: + [CtTy ()] -> + TyParams -> + TyVars () -> + Either TypeError ([UnconTyVar], Solution) -> + String +logSolution constraints typarams tyvars s = + unlines $ + ["# TySolve.solve", "## constraints"] + <> map ppConstraint constraints + <> [ "## typarams", + if typarams == mempty then "mempty" else show $ map ppTyParam (M.toList typarams) + ] + <> [ "## tyvars", + show $ map (bimap prettyNameString (second onTyVar)) $ M.toList tyvars, + either + (("## error\n" <>) . docString . prettyTypeError) + ( ("## solution\n" <>) + . show + . bimap + (map (first prettyNameString)) + (map (bimap prettyNameString $ bimap prettyString prettyString) . M.toList) + ) + s + ] + where + ppConstraint (CtEq _ t1 t2) = + unwords [show (prettyString t1), "~", show (prettyString t2)] + ppTyParam (p, (lvl, info, _)) = show (prettyNameString p, (lvl, info, NoLoc)) + onTyVar (TyVarFree _ l) = TyVarFree NoLoc l + onTyVar (TyVarPrim _ pts) = TyVarPrim NoLoc pts + onTyVar (TyVarRecord _ ts) = TyVarRecord NoLoc ts + onTyVar (TyVarSum _ ts) = TyVarSum NoLoc ts + +-- | Solve type constraints, producing either an error or a solution, +-- alongside a list of unconstrained type variables. +solve :: + [CtTy ()] -> + TyParams -> + TyVars () -> + Either TypeError ([UnconTyVar], Solution) +solve constraints typarams tyvars = + maybeLog $ runST $ do + r <- initializeState typarams tyvars + flip runReaderT r $ runExceptT $ runSolveM $ do + mapM_ solveCt constraints + mapM_ solveTyVar $ M.toList tyvars + getSolution + where + maybeLog + | isEnvVarAtLeast "FUTHARK_LOG_TYSOLVE" 0 = \s -> + trace (logSolution constraints typarams tyvars s) s + | otherwise = id +{-# NOINLINE solve #-} diff --git a/src/Language/Futhark/TypeChecker/TySolveOld.hs b/src/Language/Futhark/TypeChecker/TySolveOld.hs new file mode 100644 index 0000000000..de5311e151 --- /dev/null +++ b/src/Language/Futhark/TypeChecker/TySolveOld.hs @@ -0,0 +1,703 @@ +-- | The constraint solver for unsized type equality constraints. +module Language.Futhark.TypeChecker.TySolveOld + ( Type, + Solution, + UnconTyVar, + solve, + ) +where + +import Control.Monad +import Control.Monad.Except +import Control.Monad.State +import Data.Bifunctor +import Data.List qualified as L +import Data.Loc +import Data.Map qualified as M +import Data.Maybe +import Data.Set qualified as S +import Debug.Trace +import Futhark.Util (isEnvVarAtLeast) +import Futhark.Util.Pretty +import Language.Futhark +import Language.Futhark.TypeChecker.Constraints +import Language.Futhark.TypeChecker.Error +import Language.Futhark.TypeChecker.Monad (Notes, TypeError (..), aNote, prettyTypeError) +import Language.Futhark.TypeChecker.Types (substTyVars) + +-- | The type representation used by the constraint solver. Agnostic +-- to sizes and uniqueness. +type Type = CtType () + +-- | A (partial) solution for a type variable. +data TyVarSol + = -- | Has been substituted with this. + TyVarSol Type + | -- | Is an explicit (rigid) type parameter in the source program. + TyVarParam Level Liftedness Loc + | -- | Not substituted yet; has this constraint. + TyVarUnsol (TyVarInfo ()) + deriving (Show) + +newtype SolverState = SolverState + { -- | Left means linked to this other type variable. + solverTyVars :: M.Map TyVar (Either VName TyVarSol) + } + +initialState :: TyParams -> TyVars () -> SolverState +initialState typarams tyvars = SolverState $ M.map g typarams <> M.map f tyvars + where + f (_lvl, info) = Right $ TyVarUnsol info + g (lvl, l, loc) = Right $ TyVarParam lvl l loc + +substTyVar :: (Monoid u) => M.Map TyVar (Either VName TyVarSol) -> VName -> Maybe (TypeBase () u) +substTyVar m v = + case M.lookup v m of + Just (Left v') -> substTyVar m v' + Just (Right (TyVarSol t')) -> Just $ second (const mempty) $ substTyVars (substTyVar m) t' + Just (Right TyVarParam {}) -> Nothing + Just (Right (TyVarUnsol {})) -> Nothing + Nothing -> Nothing + +maybeLookupTyVar :: TyVar -> SolveM (Maybe TyVarSol) +maybeLookupTyVar orig = do + tyvars <- gets solverTyVars + let f v = case M.lookup v tyvars of + Nothing -> pure Nothing + Just (Left v') -> f v' + Just (Right info) -> pure $ Just info + f orig + +lookupTyVar :: TyVar -> SolveM (Either (TyVarInfo ()) Type) +lookupTyVar orig = + maybe bad unpack <$> maybeLookupTyVar orig + where + bad = error $ "Unknown tyvar: " <> prettyNameString orig + unpack (TyVarParam {}) = error $ "Is a type param: " <> prettyNameString orig + unpack (TyVarSol t) = Right t + unpack (TyVarUnsol info) = Left info + +-- | Variable must be flexible. +lookupTyVarInfo :: TyVar -> SolveM (TyVarInfo ()) +lookupTyVarInfo v = do + r <- lookupTyVar v + case r of + Left info -> pure info + Right _ -> error $ "Tyvar is nonflexible: " <> prettyNameString v + +setLink :: TyVar -> VName -> SolveM () +setLink v info = modify $ \s -> s {solverTyVars = M.insert v (Left info) $ solverTyVars s} + +setInfo :: TyVar -> TyVarSol -> SolveM () +setInfo v info = modify $ \s -> s {solverTyVars = M.insert v (Right info) $ solverTyVars s} + +-- | A solution maps a type variable to its substitution. This +-- substitution is complete, in the sense there are no right-hand +-- sides that contain a type variable. +type Solution = M.Map TyVar (Either [PrimType] (TypeBase () NoUniqueness)) + +-- | An unconstrained type variable comprises a name and (ironically) +-- a constraint on how it can be instantiated. +type UnconTyVar = (VName, Liftedness) + +typeVar :: (Monoid u) => VName -> TypeBase dim u +typeVar v = Scalar $ TypeVar mempty (qualName v) [] + +solution :: SolverState -> ([UnconTyVar], Solution) +solution s = + ( mapMaybe unconstrained $ M.toList $ solverTyVars s, + M.mapMaybe mkSubst $ solverTyVars s + ) + where + mkSubst (Right (TyVarSol t)) = + Just $ Right $ first (const ()) $ substTyVars (substTyVar (solverTyVars s)) t + mkSubst (Left v') = + Just . fromMaybe (Right $ Scalar $ TypeVar mempty (qualName v') []) $ + mkSubst =<< M.lookup v' (solverTyVars s) + mkSubst (Right (TyVarUnsol (TyVarPrim _ pts))) = Just $ Left pts + mkSubst _ = Nothing + + unconstrained (v, Right (TyVarUnsol (TyVarFree _ l))) = Just (v, l) + unconstrained _ = Nothing + +newtype SolveM a = SolveM {runSolveM :: StateT SolverState (Except TypeError) a} + deriving (Functor, Applicative, Monad, MonadState SolverState, MonadError TypeError) + +-- Try to substitute as much information as we have. +enrichType :: Type -> SolveM Type +enrichType t = do + s <- get + pure $ substTyVars (substTyVar (solverTyVars s)) t + +typeError :: Loc -> Notes -> Doc () -> SolveM () +typeError loc notes msg = + throwError $ TypeError loc notes msg + +occursCheck :: Reason Type -> VName -> Type -> SolveM () +occursCheck reason v tp = do + vars <- gets solverTyVars + let tp' = substTyVars (substTyVar vars) tp + when (v `S.member` typeVars tp') . typeError (locOf reason) mempty $ + "Occurs check: cannot instantiate" + <+> prettyName v + <+> "with" + <+> pretty tp + <> "." + +unifySharedConstructors :: + Reason Type -> + BreadCrumbs -> + M.Map Name [Type] -> + M.Map Name [Type] -> + SolveM () +unifySharedConstructors reason bcs cs1 cs2 = + forM_ (M.toList $ M.intersectionWith (,) cs1 cs2) $ \(c, (ts1, ts2)) -> + if length ts1 == length ts2 + then zipWithM_ (solveEq reason $ matchingConstructor c <> bcs) ts1 ts2 + else + typeError (locOf reason) mempty $ + "Cannot unify type with constructor" + indent 2 (pretty (Sum (M.singleton c ts1))) + "with type of constructor" + indent 2 (pretty (Sum (M.singleton c ts2))) + "because they differ in arity." + +unifySharedFields :: + Reason Type -> + BreadCrumbs -> + M.Map Name Type -> + M.Map Name Type -> + SolveM () +unifySharedFields reason bcs fs1 fs2 = + forM_ (M.toList $ M.intersectionWith (,) fs1 fs2) $ \(f, (ts1, ts2)) -> + solveEq reason (matchingField f <> bcs) ts1 ts2 + +scopeViolation :: Reason Type -> VName -> Type -> VName -> SolveM () +scopeViolation reason v1 ty v2 = + typeError (locOf reason) mempty $ + "Cannot unify type" + indent 2 (pretty ty) + "with" + <+> dquotes (prettyName v1) + <+> "(scope violation)." + "This is because" + <+> dquotes (prettyName v2) + <+> "is rigidly bound in a deeper scope." + +cannotUnify :: + Reason Type -> + Notes -> + BreadCrumbs -> + Type -> + Type -> + SolveM () +cannotUnify reason notes bcs t1 t2 = do + t1' <- enrichType t1 + t2' <- enrichType t2 + case reason of + Reason loc -> + typeError loc notes . stack $ + [ "Cannot unify", + indent 2 (pretty t1'), + "with", + indent 2 (pretty t2') + ] + <> [pretty bcs | not $ hasNoBreadCrumbs bcs] + ReasonPatMatch loc pat value_t -> + typeError loc notes . stack $ + [ "Pattern", + indent 2 $ align $ pretty pat, + "cannot match value of type", + indent 2 $ align $ pretty value_t + ] + <> [pretty bcs | not $ hasNoBreadCrumbs bcs] + ReasonAscription loc expected actual -> + typeError loc notes . stack $ + [ "Expression does not have expected type from type ascription.", + "Expected:" <+> align (pretty expected), + "Actual: " <+> align (pretty actual) + ] + <> [pretty bcs | not $ hasNoBreadCrumbs bcs] + ReasonRetType loc expected actual -> do + expected' <- enrichType expected + actual' <- enrichType actual + typeError loc notes . stack $ + [ "Function body does not have expected type.", + "Expected:" <+> align (pretty expected'), + "Actual: " <+> align (pretty actual') + ] + <> [pretty bcs | not $ hasNoBreadCrumbs bcs] + ReasonApply loc f e expected actual -> do + expected' <- enrichType expected + actual' <- enrichType actual + typeError loc notes . stack $ + [ header, + "Expected:" <+> align (pretty expected'), + "Actual: " <+> align (pretty actual') + ] + where + header = + case f of + (Nothing, _) -> + "Cannot apply function to" + <+> dquotes (shorten $ group $ pretty e) + <> " (invalid type)." + (Just fname, _) -> + "Cannot apply" + <+> dquotes (pretty fname) + <+> "to" + <+> dquotes (align $ shorten $ group $ pretty e) + <> " (invalid type)." + ReasonApplySplit loc (fname, 0) _ ftype -> + typeError loc notes $ + stack + [ "Cannot apply" + <+> fname' + <+> "as function, as it has non-function type:" + indent 2 (align $ pretty ftype) + ] + where + fname' = maybe "expression" (dquotes . pretty) fname + ReasonApplySplit loc (fname, i) e _ -> + typeError loc notes $ + stack + [ "Cannot apply" + <+> fname' + <+> "to" + <+> dquotes (align $ shorten $ group $ pretty e) + <> ".", + "Function accepts only" <+> pretty i <+> "arguments." + ] + where + fname' = maybe "expression" (dquotes . pretty) fname + ReasonBranches loc former latter -> do + former' <- enrichType former + latter' <- enrichType latter + typeError loc notes . stack $ + [ "Branches differ in type.", + "Former:" <+> pretty former', + "Latter:" <+> pretty latter' + ] + +-- Precondition: 'v' is currently flexible. +subTyVar :: Reason Type -> BreadCrumbs -> VName -> Type -> SolveM () +subTyVar reason bcs v t = do + occursCheck reason v t + v_info <- gets $ M.lookup v . solverTyVars + + -- Set a solution for v, then update info for t in case v has any + -- odd constraints. + setInfo v (TyVarSol t) + + case (v_info, t) of + (Just (Right (TyVarUnsol TyVarFree {})), _) -> pure () + (Just (Right (TyVarUnsol (TyVarPrim _ v_pts))), _) -> + if t `elem` map (Scalar . Prim) v_pts + then pure () + else cannotUnify reason notes bcs (typeVar v) t + where + notes = + aNote $ + "Cannot instantiate type that must be one of" + indent 2 (pretty v_pts) + "with" + indent 2 (pretty t) + (Just (Right (TyVarUnsol (TyVarSum _ cs1))), Scalar (Sum cs2)) -> + if all (`elem` M.keys cs2) (M.keys cs1) + then unifySharedConstructors reason bcs cs1 cs2 + else cannotUnify reason notes bcs (typeVar v) t + where + notes = + aNote $ + "Cannot match type with constructors" + indent 2 (stack (map (("#" <>) . pretty) (M.keys cs1))) + "with type with constructors" + indent 2 (stack (map (("#" <>) . pretty) (M.keys cs2))) + unsharedConstructorsMsg cs1 cs2 + (Just (Right (TyVarUnsol (TyVarSum _ cs1))), _) -> + typeError (locOf reason) mempty $ + "Cannot unify type with constructors" + indent 2 (pretty (Sum cs1)) + "with type" + indent 2 (pretty t) + (Just (Right (TyVarUnsol (TyVarRecord _ fs1))), Scalar (Record fs2)) -> + if all (`elem` M.keys fs2) (M.keys fs1) + then unifySharedFields reason bcs fs1 fs2 + else + typeError (locOf reason) mempty $ + "Cannot unify record type with fields" + indent 2 (pretty (Record fs1)) + "with record type" + indent 2 (pretty (Record fs2)) + (Just (Right (TyVarUnsol (TyVarRecord _ fs1))), _) -> + typeError (locOf reason) mempty $ + "Cannot unify record type with fields" + indent 2 (pretty (Record fs1)) + "with type" + indent 2 (pretty t) + -- + -- Internal error cases + (Just (Right TyVarSol {}), _) -> + error $ "Type variable already solved: " <> prettyNameString v + (Just (Right TyVarParam {}), _) -> + error $ "Cannot substitute type parameter: " <> prettyNameString v + (Just Left {}, _) -> + error $ "Type variable already linked: " <> prettyNameString v + (Nothing, _) -> + error $ "subTyVar: Nothing v: " <> prettyNameString v + +-- Precondition: 'v' and 't' are both currently flexible. +-- +-- The purpose of this function is to combine the partial knowledge we +-- may have about these two type variables. +unionTyVars :: Reason Type -> BreadCrumbs -> VName -> VName -> SolveM () +unionTyVars reason bcs v t = do + v_info <- gets $ either alreadyLinked id . fromMaybe unknown . M.lookup v . solverTyVars + t_info <- lookupTyVarInfo t + + -- Insert the link from v to t, and then update the info of t based + -- on the existing info of v and t. + setLink v t + + case (v_info, t_info) of + ( TyVarUnsol (TyVarFree _ v_l), + TyVarFree t_loc t_l + ) + | v_l /= t_l -> + setInfo t $ TyVarUnsol $ TyVarFree t_loc (min v_l t_l) + -- When either is completely unconstrained. + (TyVarUnsol TyVarFree {}, _) -> + pure () + ( TyVarUnsol info, + TyVarFree {} + ) -> + setInfo t (TyVarUnsol info) + -- + -- TyVarPrim cases + ( TyVarUnsol (TyVarPrim _ v_pts), + TyVarPrim t_loc t_pts + ) -> + let pts = L.intersect v_pts t_pts + in if null pts + then + typeError (locOf reason) mempty $ + "Cannot unify type that must be one of" + indent 2 (pretty v_pts) + "with type that must be one of" + indent 2 (pretty t_pts) + else setInfo t (TyVarUnsol (TyVarPrim t_loc pts)) + ( TyVarUnsol (TyVarPrim _ v_pts), + TyVarRecord {} + ) -> + typeError (locOf reason) mempty $ + "Cannot unify type that must be one of" + indent 2 (pretty v_pts) + "with type that must be a record." + ( TyVarUnsol (TyVarPrim _ v_pts), + TyVarSum {} + ) -> + typeError (locOf reason) mempty $ + "Cannot unify type that must be one of" + indent 2 (pretty v_pts) + "with type that must be sum." + -- + -- TyVarSum cases + ( TyVarUnsol (TyVarSum _ cs1), + TyVarSum loc cs2 + ) -> do + unifySharedConstructors reason bcs cs1 cs2 + let cs3 = cs1 <> cs2 + setInfo t (TyVarUnsol (TyVarSum loc cs3)) + ( TyVarUnsol TyVarSum {}, + TyVarPrim _ pts + ) -> + typeError (locOf reason) mempty $ + "A sum type cannot be one of" + indent 2 (pretty pts) + ( TyVarUnsol (TyVarSum _ cs1), + TyVarRecord _ fs + ) -> + typeError (locOf reason) mempty $ + "Cannot unify type with constructors" + indent 2 (pretty (Sum cs1)) + "with type" + indent 2 (pretty (Scalar (Record fs))) + -- + -- TyVarRecord cases + ( TyVarUnsol (TyVarRecord _ fs1), + TyVarRecord loc fs2 + ) -> do + unifySharedFields reason bcs fs1 fs2 + let fs3 = fs1 <> fs2 + setInfo t (TyVarUnsol (TyVarRecord loc fs3)) + ( TyVarUnsol TyVarRecord {}, + TyVarPrim _ pts + ) -> + typeError (locOf reason) mempty $ + "A record type cannot be one of" + indent 2 (pretty pts) + ( TyVarUnsol (TyVarRecord _ fs1), + TyVarSum _ cs + ) -> + typeError (locOf reason) mempty $ + "Cannot unify record type" + indent 2 (pretty (Record fs1)) + "with type" + indent 2 (pretty (Scalar (Sum cs))) + -- + -- Internal error cases + (TyVarSol {}, _) -> + alreadySolved + (TyVarParam {}, _) -> + isParam + where + unknown = error $ "unionTyVars: Nothing v: " <> prettyNameString v + alreadyLinked = error $ "Type variable already linked: " <> prettyNameString v + alreadySolved = error $ "Type variable already solved: " <> prettyNameString v + isParam = error $ "Type name is a type parameter: " <> prettyNameString v + +unsharedConstructorsMsg :: M.Map Name t -> M.Map Name t -> Doc a +unsharedConstructorsMsg cs1 cs2 = + "Unshared constructors:" <+> commasep (map (("#" <>) . pretty) missing) <> "." + where + missing = + filter (`notElem` M.keys cs1) (M.keys cs2) + ++ filter (`notElem` M.keys cs2) (M.keys cs1) + +-- Unify at the root, emitting new equalities that must hold. +unify :: Type -> Type -> Either (Doc a) [(BreadCrumbs, (Type, Type))] +unify (Scalar (Prim pt1)) (Scalar (Prim pt2)) + | pt1 == pt2 = Right [] +unify + (Scalar (TypeVar _ (QualName _ v1) targs1)) + (Scalar (TypeVar _ (QualName _ v2) targs2)) + | v1 == v2 = + Right $ mapMaybe f $ zip targs1 targs2 + where + f (TypeArgType t1, TypeArgType t2) = Just (mempty, (t1, t2)) + f _ = Nothing +unify (Scalar (Arrow _ _ _ t1a (RetType _ t1r))) (Scalar (Arrow _ _ _ t2a (RetType _ t2r))) = + Right [(mempty, (t1a, t2a)), (mempty, (t1r', t2r'))] + where + t1r' = t1r `setUniqueness` NoUniqueness + t2r' = t2r `setUniqueness` NoUniqueness +unify (Scalar (Record fs1)) (Scalar (Record fs2)) + | M.keys fs1 == M.keys fs2 = + Right $ + map (first matchingField) $ + M.toList $ + M.intersectionWith (,) fs1 fs2 + | Just n1 <- length <$> areTupleFields fs1, + Just n2 <- length <$> areTupleFields fs2, + n1 /= n2 = + Left $ + "Tuples have" + <+> pretty n1 + <+> "and" + <+> pretty n2 + <+> "elements respectively." + | otherwise = + let missing = + filter (`notElem` M.keys fs1) (M.keys fs2) + <> filter (`notElem` M.keys fs2) (M.keys fs1) + in Left $ + "unshared fields:" <+> commasep (map pretty missing) <> "." +unify (Scalar (Sum cs1)) (Scalar (Sum cs2)) + | M.keys cs1 == M.keys cs2 = + fmap concat . forM cs' $ \(c, (ts1, ts2)) -> do + if length ts1 == length ts2 + then Right $ zipWith (curry (matchingConstructor c,)) ts1 ts2 + else Left mempty + | otherwise = + Left $ unsharedConstructorsMsg cs1 cs2 + where + cs' = M.toList $ M.intersectionWith (,) cs1 cs2 +unify t1 t2 + | Just t1' <- peelArray 1 t1, + Just t2' <- peelArray 1 t2 = + Right [(mempty, (t1', t2'))] +unify _ _ = Left mempty + +solveEq :: Reason Type -> BreadCrumbs -> Type -> Type -> SolveM () +solveEq reason obcs orig_t1 orig_t2 = do + solveCt' (obcs, (orig_t1, orig_t2)) + where + solveCt' (bcs, (t1, t2)) = do + tyvars <- gets solverTyVars + let flexible v = case M.lookup v tyvars of + Just (Left v') -> flexible v' + Just (Right (TyVarUnsol _)) -> True + Just (Right TyVarSol {}) -> False + Just (Right TyVarParam {}) -> False + Nothing -> False + normalize t@(Scalar (TypeVar u (QualName [] v) [])) = + case M.lookup v tyvars of + Just (Left v') -> normalize $ Scalar (TypeVar u (QualName [] v') []) + Just (Right (TyVarSol t')) -> normalize t' + _ -> t + normalize t = t + case (normalize t1, normalize t2) of + ( t1'@(Scalar (TypeVar _ (QualName [] v1) [])), + t2'@(Scalar (TypeVar _ (QualName [] v2) [])) + ) + | v1 == v2 -> pure () + | otherwise -> + case (flexible v1, flexible v2) of + (False, False) -> cannotUnify reason mempty bcs t1 t2 + (True, False) -> subTyVar reason bcs v1 t2' + (False, True) -> subTyVar reason bcs v2 t1' + (True, True) -> unionTyVars reason bcs v1 v2 + (Scalar (TypeVar _ (QualName [] v1) []), t2') + | flexible v1 -> subTyVar reason bcs v1 t2' + (t1', Scalar (TypeVar _ (QualName [] v2) [])) + | flexible v2 -> subTyVar reason bcs v2 t1' + (t1', t2') -> case unify t1' t2' of + Left details -> cannotUnify reason (aNote details) bcs t1' t2' + Right eqs -> mapM_ solveCt' eqs + +solveCt :: CtTy () -> SolveM () +solveCt ct = + case ct of + CtEq reason t1 t2 -> solveEq reason mempty t1 t2 + +scopeCheck :: Reason Type -> TyVar -> Int -> Type -> SolveM () +scopeCheck reason v v_lvl ty = mapM_ check $ typeVars ty + where + check ty_v = do + ty_v_info <- gets $ M.lookup ty_v . solverTyVars + case ty_v_info of + Just (Right (TyVarParam ty_v_lvl _ _)) + -- Type parameter has a higher level than the (free) type variable. + | ty_v_lvl > v_lvl -> scopeViolation reason v ty ty_v + Just (Right (TyVarSol ty')) -> + mapM_ check $ typeVars ty' + _ -> pure () + +-- If a type variable has a liftedness constraint, we propagate that +-- constraint to its solution. The actual checking for correct usage +-- is done later. +liftednessCheck :: Liftedness -> Type -> SolveM () +liftednessCheck l (Scalar (TypeVar _ (QualName [] v) _)) = do + v_info <- maybeLookupTyVar v + case v_info of + Nothing -> + -- Is an opaque type. + pure () + Just (TyVarSol v_ty) -> + liftednessCheck l v_ty + Just TyVarParam {} -> pure () + Just (TyVarUnsol (TyVarFree loc v_l)) + | l /= v_l -> + setInfo v $ TyVarUnsol $ TyVarFree loc (min l v_l) + Just TyVarUnsol {} -> pure () +liftednessCheck _ (Scalar Prim {}) = pure () +liftednessCheck Lifted _ = pure () +liftednessCheck _ Array {} = pure () +liftednessCheck _ (Scalar Arrow {}) = pure () +liftednessCheck l (Scalar (Record fs)) = + mapM_ (liftednessCheck l) fs +liftednessCheck l (Scalar (Sum cs)) = + mapM_ (mapM_ $ liftednessCheck l) cs +liftednessCheck _ (Scalar TypeVar {}) = pure () + +solveTyVar :: (VName, (Level, TyVarInfo ())) -> SolveM () +solveTyVar (tv, (_, TyVarRecord loc fs1)) = do + tv_t <- lookupTyVar tv + case tv_t of + Left _ -> + typeError loc mempty $ + "Type" + <+> prettyName tv + <+> "is ambiguous." + "Must be a record with fields" + indent 2 (pretty (Scalar (Record fs1))) + Right _ -> + pure () +solveTyVar (tv, (_, TyVarSum loc cs1)) = do + tv_t <- lookupTyVar tv + case tv_t of + Left _ -> + typeError loc mempty $ + "Type is ambiguous." + "Must be a sum type with constructors" + indent 2 (pretty (Scalar (Sum cs1))) + Right _ -> pure () +solveTyVar (tv, (lvl, TyVarFree loc l)) = do + tv_t <- lookupTyVar tv + case tv_t of + Right ty -> do + scopeCheck (Reason loc) tv lvl ty + liftednessCheck l ty + _ -> pure () +solveTyVar (tv, (_, TyVarPrim loc pts)) = do + tv_t <- lookupTyVar tv + case tv_t of + Right (Scalar (Prim ty)) + | [ty] == pts -> + setInfo tv $ TyVarSol $ Scalar $ Prim ty + Right ty + | ty `elem` map (Scalar . Prim) pts -> pure () + | otherwise -> + typeError loc mempty $ + "Numeric constant inferred to be of type" + indent 2 (align (pretty ty)) + "which is not possible." + _ -> pure () + +-- Print in a way helpful for writing a test case for TySolveTests. +logSolution :: + [CtTy ()] -> + TyParams -> + TyVars () -> + Either TypeError ([UnconTyVar], Solution) -> + String +logSolution constraints typarams tyvars s = + unlines $ + ["# TySolve.solve", "## constraints"] + <> map ppConstraint constraints + <> [ "## typarams", + if typarams == mempty then "mempty" else show $ map ppTyParam (M.toList typarams) + ] + <> [ "## tyvars", + show $ map (bimap prettyNameString (second onTyVar)) $ M.toList tyvars, + either + (("## error\n" <>) . docString . prettyTypeError) + ( ("## solution\n" <>) + . show + . bimap + (map (first prettyNameString)) + (map (bimap prettyNameString $ bimap prettyString prettyString) . M.toList) + ) + s + ] + where + ppConstraint (CtEq _ t1 t2) = + unwords [show (prettyString t1), "~", show (prettyString t2)] + ppTyParam (p, (lvl, info, _)) = show (prettyNameString p, (lvl, info, NoLoc)) + onTyVar (TyVarFree _ l) = TyVarFree NoLoc l + onTyVar (TyVarPrim _ pts) = TyVarPrim NoLoc pts + onTyVar (TyVarRecord _ ts) = TyVarRecord NoLoc ts + onTyVar (TyVarSum _ ts) = TyVarSum NoLoc ts + +-- | Solve type constraints, producing either an error or a solution, +-- alongside a list of unconstrained type variables. +solve :: + [CtTy ()] -> + TyParams -> + TyVars () -> + Either TypeError ([UnconTyVar], Solution) +solve constraints typarams tyvars = + maybeLog + . second solution + . runExcept + . flip execStateT (initialState typarams tyvars) + . runSolveM + $ do + mapM_ solveCt constraints + mapM_ solveTyVar (M.toList tyvars) + where + maybeLog + | isEnvVarAtLeast "FUTHARK_LOG_TYSOLVE" 0 = \s -> + trace (logSolution constraints typarams tyvars s) s + | otherwise = id +{-# NOINLINE solve #-} diff --git a/src/Language/Futhark/TypeChecker/Types.hs b/src/Language/Futhark/TypeChecker/Types.hs index 3bfb48f7a1..d6383c74e9 100644 --- a/src/Language/Futhark/TypeChecker/Types.hs +++ b/src/Language/Futhark/TypeChecker/Types.hs @@ -8,6 +8,7 @@ module Language.Futhark.TypeChecker.Types TypeSubs, Substitutable (..), substTypesAny, + substTyVars, -- * Witnesses mustBeExplicitInType, @@ -59,7 +60,7 @@ mustBeExplicitInBinding :: StructType -> S.Set VName mustBeExplicitInBinding bind_t = let (ts, ret) = unfoldFunType bind_t alsoRet = M.unionWith (&&) $ M.fromList $ map (,True) (S.toList (fvVars (freeInType ret))) - in S.fromList $ M.keys $ M.filter id $ alsoRet $ L.foldl' onType mempty $ map toStruct ts + in S.fromList $ M.keys $ M.filter id $ alsoRet $ L.foldl' onType mempty $ map (toStruct . snd) ts where onType uses t = uses <> mustBeExplicitAux t -- Left-biased union. @@ -442,6 +443,32 @@ applyType ps t args = substTypesAny (`M.lookup` substs) t mkSubst p a = error $ "applyType mkSubst: cannot substitute " ++ prettyString a ++ " for " ++ prettyString p +-- In case we are substituting the same RetType in multiple +-- places, we must ensure each instance is given distinct +-- dimensions. E.g. substituting 'a ↦ ?[n].[n]bool' into '(a,a)' +-- should give '?[n][m].([n]bool,[m]bool)'. +-- +-- XXX: the size names we invent here not globally unique. This +-- is _probably_ not a problem, since substituting types with +-- outermost non-null existential sizes is done only when type +-- checking modules and monomorphising. +freshDims :: + (Monoid as) => + RetTypeBase Size as -> + State [VName] (RetTypeBase Size as) +freshDims (RetType [] t) = pure $ RetType [] t +freshDims (RetType ext t) = do + seen_ext <- get + if not $ any (`elem` seen_ext) ext + then pure $ RetType ext t + else do + let start = maximum $ map baseTag seen_ext + ext' = zipWith VName (map baseName ext) [start + 1 ..] + mkSubst = ExpSubst . flip sizeFromName mempty . qualName + extsubsts = M.fromList $ zip ext $ map mkSubst ext' + RetType [] t' = substTypesRet (`M.lookup` extsubsts) t + pure $ RetType ext' t' + substTypesRet :: (Monoid u) => (VName -> Maybe (Subst (RetTypeBase Size u))) -> @@ -450,28 +477,6 @@ substTypesRet :: substTypesRet lookupSubst ot = uncurry (flip RetType) $ runState (onType ot) [] where - -- In case we are substituting the same RetType in multiple - -- places, we must ensure each instance is given distinct - -- dimensions. E.g. substituting 'a ↦ ?[n].[n]bool' into '(a,a)' - -- should give '?[n][m].([n]bool,[m]bool)'. - -- - -- XXX: the size names we invent here not globally unique. This - -- is _probably_ not a problem, since substituting types with - -- outermost non-null existential sizes is done only when type - -- checking modules and monomorphising. - freshDims (RetType [] t) = pure $ RetType [] t - freshDims (RetType ext t) = do - seen_ext <- get - if not $ any (`elem` seen_ext) ext - then pure $ RetType ext t - else do - let start = maximum $ map baseTag seen_ext - ext' = zipWith VName (map baseName ext) [start + 1 ..] - mkSubst = ExpSubst . flip sizeFromName mempty . qualName - extsubsts = M.fromList $ zip ext $ map mkSubst ext' - RetType [] t' = substTypesRet (`M.lookup` extsubsts) t - pure $ RetType ext' t' - onType :: forall as. (Monoid as) => @@ -539,6 +544,26 @@ substTypesAny lookupSubst ot = toAny d = d in first toAny ot' +-- | Substitution without caring about sizes. +substTyVars :: (Monoid u) => (VName -> Maybe (TypeBase d NoUniqueness)) -> TypeBase d u -> TypeBase d u +substTyVars f (Scalar (TypeVar u qn args)) = + case f $ qualLeaf qn of + Just t' -> second (const mempty) $ substTyVars f t' + Nothing -> Scalar (TypeVar u qn (map onArg args)) + where + onArg (TypeArgType t) = TypeArgType $ substTyVars f t + onArg (TypeArgDim e) = TypeArgDim e +substTyVars _ (Scalar (Prim pt)) = Scalar $ Prim pt +substTyVars f (Scalar (Record fs)) = Scalar $ Record $ M.map (substTyVars f) fs +substTyVars f (Scalar (Sum cs)) = Scalar $ Sum $ M.map (map $ substTyVars f) cs +substTyVars f (Scalar (Arrow u pname d t1 (RetType ext t2))) = + Scalar $ + Arrow u pname d (substTyVars f t1) $ + RetType ext $ + substTyVars f t2 `setUniqueness` uniqueness t2 +substTyVars f (Array u shape elemt) = + arrayOfWithAliases u shape $ substTyVars f $ Scalar elemt + -- Note [AnySize] -- -- Consider a program: diff --git a/src/Language/Futhark/TypeChecker/Unify.hs b/src/Language/Futhark/TypeChecker/Unify.hs index 11e7beeef4..7292ae2638 100644 --- a/src/Language/Futhark/TypeChecker/Unify.hs +++ b/src/Language/Futhark/TypeChecker/Unify.hs @@ -12,15 +12,8 @@ module Language.Futhark.TypeChecker.Unify RigidSource (..), BreadCrumbs, sizeFree, - noBreadCrumbs, - hasNoBreadCrumbs, dimNotes, - zeroOrderType, arrayElemType, - mustHaveConstr, - mustHaveField, - mustBeOneOf, - equalityType, normType, normTypeFully, unify, @@ -43,57 +36,11 @@ import Futhark.Util (topologicalSort) import Futhark.Util.Pretty import Language.Futhark import Language.Futhark.Traversals +import Language.Futhark.TypeChecker.Constraints (Level) +import Language.Futhark.TypeChecker.Error import Language.Futhark.TypeChecker.Monad hiding (BoundV) import Language.Futhark.TypeChecker.Types --- | A piece of information that describes what process the type --- checker currently performing. This is used to give better error --- messages for unification errors. -data BreadCrumb - = MatchingTypes StructType StructType - | MatchingFields [Name] - | MatchingConstructor Name - | Matching (Doc ()) - -instance Pretty BreadCrumb where - pretty (MatchingTypes t1 t2) = - "When matching type" - indent 2 (pretty t1) - "with" - indent 2 (pretty t2) - pretty (MatchingFields fields) = - "When matching types of record field" - <+> dquotes (mconcat $ punctuate "." $ map pretty fields) - <> dot - pretty (MatchingConstructor c) = - "When matching types of constructor" <+> dquotes (pretty c) <> dot - pretty (Matching s) = - unAnnotate s - --- | Unification failures can occur deep down inside complicated types --- (consider nested records). We leave breadcrumbs behind us so we --- can report the path we took to find the mismatch. -newtype BreadCrumbs = BreadCrumbs [BreadCrumb] - --- | An empty path. -noBreadCrumbs :: BreadCrumbs -noBreadCrumbs = BreadCrumbs [] - --- | Is the path empty? -hasNoBreadCrumbs :: BreadCrumbs -> Bool -hasNoBreadCrumbs (BreadCrumbs xs) = null xs - --- | Drop a breadcrumb on the path behind you. -breadCrumb :: BreadCrumb -> BreadCrumbs -> BreadCrumbs -breadCrumb (MatchingFields xs) (BreadCrumbs (MatchingFields ys : bcs)) = - BreadCrumbs $ MatchingFields (ys ++ xs) : bcs -breadCrumb bc (BreadCrumbs bcs) = - BreadCrumbs $ bc : bcs - -instance Pretty BreadCrumbs where - pretty (BreadCrumbs []) = mempty - pretty (BreadCrumbs bcs) = line <> stack (map pretty bcs) - -- | A usage that caused a type constraint. data Usage = Usage (Maybe T.Text) Loc deriving (Show) @@ -114,20 +61,11 @@ instance Pretty Usage where instance Located Usage where locOf (Usage _ loc) = locOf loc --- | The level at which a type variable is bound. Higher means --- deeper. We can only unify a type variable at level @i@ with a type --- @t@ if all type names that occur in @t@ are at most at level @i@. -type Level = Int - -- | A constraint on a yet-ambiguous type variable. data Constraint = NoConstraint Liftedness Usage | ParamType Liftedness Loc | Constraint StructRetType Usage - | Overloaded [PrimType] Usage - | HasFields Liftedness (M.Map Name StructType) Usage - | Equality Usage - | HasConstrs Liftedness (M.Map Name [StructType]) Usage | ParamSize Loc | -- | Is not actually a type, but a term-level size, -- possibly already set to something specific. @@ -143,10 +81,6 @@ instance Located Constraint where locOf (NoConstraint _ usage) = locOf usage locOf (ParamType _ usage) = locOf usage locOf (Constraint _ usage) = locOf usage - locOf (Overloaded _ usage) = locOf usage - locOf (HasFields _ _ usage) = locOf usage - locOf (Equality usage) = locOf usage - locOf (HasConstrs _ _ usage) = locOf usage locOf (ParamSize loc) = locOf loc locOf (Size _ usage) = locOf usage locOf (UnknownSize loc _) = locOf loc @@ -235,7 +169,7 @@ prettySource ctx loc (RigidOutOfScope boundloc v) = <> pretty (locStrRel ctx boundloc) <> "." prettySource _ _ RigidUnify = - "is an artificial size invented during unification of functions with anonymous sizes." + textwrap "is an artificial size invented during unification of functions with anonymous sizes." prettySource ctx loc (RigidCond t1 t2) = "is unknown due to conditional expression at " <> pretty (locStrRel ctx loc) @@ -266,27 +200,6 @@ typeNotes ctx = . fvVars . freeInType -typeVarNotes :: (MonadUnify m) => VName -> m Notes -typeVarNotes v = maybe mempty (note . snd) . M.lookup v <$> getConstraints - where - note (HasConstrs _ cs _) = - aNote $ - prettyName v - <+> "=" - <+> hsep (map ppConstr (M.toList cs)) - <+> "..." - note (Overloaded ts _) = - aNote $ prettyName v <+> "must be one of" <+> mconcat (punctuate ", " (map pretty ts)) - note (HasFields _ fs _) = - aNote $ - prettyName v - <+> "=" - <+> braces (mconcat (punctuate ", " (map ppField (M.toList fs)))) - note _ = mempty - - ppConstr (c, _) = "#" <> pretty c <+> "..." <+> "|" - ppField (f, _) = prettyName f <> ":" <+> "..." - -- | Monads that which to perform unification must implement this type -- class. class (Monad m) => MonadUnify m where @@ -352,12 +265,6 @@ unsharedConstructorsMsg cs1 cs2 = filter (`notElem` M.keys cs1) (M.keys cs2) ++ filter (`notElem` M.keys cs2) (M.keys cs1) --- | Is the given type variable the name of an abstract type or type --- parameter, which we cannot substitute? -isRigid :: VName -> Constraints -> Bool -isRigid v constraints = - maybe True (rigidConstraint . snd) $ M.lookup v constraints - -- | If the given type variable is nonrigid, what is its level? isNonRigid :: VName -> Constraints -> Maybe Level isNonRigid v constraints = do @@ -368,10 +275,6 @@ isNonRigid v constraints = do type UnifySizes m = BreadCrumbs -> [VName] -> (VName -> Maybe Int) -> Exp -> Exp -> m () -flipUnifySizes :: UnifySizes m -> UnifySizes m -flipUnifySizes onDims bcs bound nonrigid t1 t2 = - onDims bcs bound nonrigid t2 t1 - unifyWith :: (MonadUnify m) => UnifySizes m -> @@ -396,14 +299,7 @@ unifyWith onDims usage = subunify False failure = matchError (srclocOf usage) mempty bcs t1' t2' - link ord' = - linkVarToType linkDims usage bound bcs - where - -- We may have to flip the order of future calls to - -- onDims inside linkVarToType. - linkDims - | ord' = flipUnifySizes onDims - | otherwise = onDims + link = linkVarToType usage bound bcs unifyTypeArg bcs' (TypeArgDim d1) (TypeArgDim d2) = onDims' bcs' (swap ord d1 d2) @@ -443,24 +339,24 @@ unifyWith onDims usage = subunify False ) | tn == arg_tn, length targs == length arg_targs -> do - let bcs' = breadCrumb (Matching "When matching type arguments.") bcs + let bcs' = matching "When matching type arguments." <> bcs zipWithM_ (unifyTypeArg bcs') targs arg_targs ( Scalar (TypeVar _ (QualName [] v1) []), Scalar (TypeVar _ (QualName [] v2) []) ) -> case (nonrigid v1, nonrigid v2) of (Nothing, Nothing) -> failure - (Just lvl1, Nothing) -> link ord v1 lvl1 t2' - (Nothing, Just lvl2) -> link (not ord) v2 lvl2 t1' + (Just lvl1, Nothing) -> link v1 lvl1 t2' + (Nothing, Just lvl2) -> link v2 lvl2 t1' (Just lvl1, Just lvl2) - | lvl1 <= lvl2 -> link ord v1 lvl1 t2' - | otherwise -> link (not ord) v2 lvl2 t1' + | lvl1 <= lvl2 -> link v1 lvl1 t2' + | otherwise -> link v2 lvl2 t1' (Scalar (TypeVar _ (QualName [] v1) []), _) | Just lvl <- nonrigid v1 -> - link ord v1 lvl t2' + link v1 lvl t2' (_, Scalar (TypeVar _ (QualName [] v2) [])) | Just lvl <- nonrigid v2 -> - link (not ord) v2 lvl t1' + link v2 lvl t1' ( Scalar (Arrow _ p1 d1 a1 (RetType b1_dims b1)), Scalar (Arrow _ p2 d2 a2 (RetType b2_dims b2)) ) @@ -495,13 +391,13 @@ unifyWith onDims usage = subunify False subunify (not ord) bound - (breadCrumb (Matching "When matching parameter types.") bcs) + (matching "When matching parameter types." <> bcs) a1 a2 subunify ord bound' - (breadCrumb (Matching "When matching return types.") bcs) + (matching "When matching return types." <> bcs) (toStruct b1') (toStruct b2') @@ -567,7 +463,7 @@ unifySizes usage bcs _ _ e1 e2 = do -- | Unifies two types. unify :: (MonadUnify m) => Usage -> StructType -> StructType -> m () -unify usage = unifyWith (unifySizes usage) usage mempty noBreadCrumbs +unify usage = unifyWith (unifySizes usage) usage mempty mempty occursCheck :: (MonadUnify m) => @@ -691,7 +587,6 @@ sizeFree tloc expKiller orig_t = do linkVarToType :: (MonadUnify m) => - UnifySizes m -> Usage -> [VName] -> BreadCrumbs -> @@ -699,7 +594,7 @@ linkVarToType :: Level -> StructType -> m () -linkVarToType onDims usage bound bcs vn lvl tp_unnorm = do +linkVarToType usage bound bcs vn lvl tp_unnorm = do -- We have to expand anyway for the occurs check, so we might as -- well link the fully expanded type. tp <- normTypeFully tp_unnorm @@ -726,14 +621,13 @@ linkVarToType onDims usage bound bcs vn lvl tp_unnorm = do M.insert vn (lvl, Constraint (RetType (ext_new <> ext_witnessed) tp') usage) let unliftedBcs unlifted_usage = - breadCrumb - ( Matching $ - "When verifying that" - <+> dquotes (prettyName vn) - <+> textwrap "is not instantiated with a function type, due to" - <+> pretty unlifted_usage + matching + ( "When verifying that" + <+> dquotes (prettyName vn) + <+> textwrap "is not instantiated with a function type, due to" + <+> pretty unlifted_usage ) - bcs + <> bcs constraints <- getConstraints case snd <$> M.lookup vn constraints of @@ -748,125 +642,7 @@ linkVarToType onDims usage bound bcs vn lvl tp_unnorm = do <+> "cannot be instantiated with type containing anonymous sizes:" indent 2 (pretty tp) textwrap "This is usually because the size of an array returned by a higher-order function argument cannot be determined statically. This can also be due to the return size being a value parameter. Add type annotation to clarify." - Just (Equality _) -> do - link - equalityType usage tp - Just (Overloaded ts old_usage) - | tp `notElem` map (Scalar . Prim) ts -> do - link - case tp of - Scalar (TypeVar _ (QualName [] v) []) - | not $ isRigid v constraints -> - linkVarToTypes usage v ts - _ -> - unifyError usage mempty bcs $ - "Cannot instantiate" - <+> dquotes (prettyName vn) - <+> "with type" - indent 2 (pretty tp) - "as" - <+> dquotes (prettyName vn) - <+> "must be one of" - <+> commasep (map pretty ts) - "due to" - <+> pretty old_usage - <> "." - Just (HasFields l required_fields old_usage) -> do - when (l == Unlifted) $ arrayElemTypeWith usage (unliftedBcs old_usage) tp - case tp of - Scalar (Record tp_fields) - | all (`M.member` tp_fields) $ M.keys required_fields -> do - required_fields' <- mapM normTypeFully required_fields - let tp' = Scalar $ Record $ required_fields <> tp_fields -- Crucially left-biased. - ext = filter (`S.member` fvVars (freeInType tp')) bound - modifyConstraints $ - M.insert vn (lvl, Constraint (RetType ext tp') usage) - unifySharedFields onDims usage bound bcs required_fields' tp_fields - Scalar (TypeVar _ (QualName [] v) []) -> do - case M.lookup v constraints of - Just (_, HasFields _ tp_fields _) -> - unifySharedFields onDims usage bound bcs required_fields tp_fields - Just (_, NoConstraint {}) -> pure () - Just (_, Equality {}) -> pure () - _ -> do - notes <- (<>) <$> typeVarNotes vn <*> typeVarNotes v - noRecordType notes - link - modifyConstraints $ - M.insertWith - combineFields - v - (lvl, HasFields l required_fields old_usage) - where - combineFields (_, HasFields l1 fs1 usage1) (_, HasFields l2 fs2 _) = - (lvl, HasFields (l1 `min` l2) (M.union fs1 fs2) usage1) - combineFields hasfs _ = hasfs - _ -> - unifyError usage mempty bcs $ - "Cannot instantiate" - <+> dquotes (prettyName vn) - <+> "with type" - indent 2 (pretty tp) - "as" - <+> dquotes (prettyName vn) - <+> "must be a record with fields" - indent 2 (pretty (Record required_fields)) - "due to" - <+> pretty old_usage - <> "." - -- See Note [Linking variables to sum types] - Just (HasConstrs l required_cs old_usage) -> do - when (l == Unlifted) $ arrayElemTypeWith usage (unliftedBcs old_usage) tp - case tp of - Scalar (Sum ts) - | all (`M.member` ts) $ M.keys required_cs -> do - let tp' = Scalar $ Sum $ required_cs <> ts -- Crucially left-biased. - ext = filter (`S.member` fvVars (freeInType tp')) bound - modifyConstraints $ - M.insert vn (lvl, Constraint (RetType ext tp') usage) - unifySharedConstructors onDims usage bound bcs required_cs ts - | otherwise -> - unsharedConstructors required_cs ts =<< typeVarNotes vn - Scalar (TypeVar _ (QualName [] v) []) -> do - case M.lookup v constraints of - Just (_, HasConstrs _ v_cs _) -> - unifySharedConstructors onDims usage bound bcs required_cs v_cs - Just (_, NoConstraint {}) -> pure () - Just (_, Equality {}) -> pure () - _ -> do - notes <- (<>) <$> typeVarNotes vn <*> typeVarNotes v - noSumType notes - link - modifyConstraints $ - M.insertWith - combineConstrs - v - (lvl, HasConstrs l required_cs old_usage) - where - combineConstrs (_, HasConstrs l1 cs1 usage1) (_, HasConstrs l2 cs2 _) = - (lvl, HasConstrs (l1 `min` l2) (M.union cs1 cs2) usage1) - combineConstrs hasCs _ = hasCs - _ -> noSumType =<< typeVarNotes vn _ -> link - where - unsharedConstructors cs1 cs2 notes = - unifyError - usage - notes - bcs - (unsharedConstructorsMsg cs1 cs2) - noSumType notes = - unifyError - usage - notes - bcs - "Cannot unify a sum type with a non-sum type." - noRecordType notes = - unifyError - usage - notes - bcs - "Cannot unify a record type with a non-record type." linkVarToDim :: (MonadUnify m) => @@ -912,138 +688,6 @@ linkVarToDim usage bcs vn lvl e = do _ -> modifyConstraints $ M.insert dim' (lvl, c) checkVar _ _ = pure () --- | Assert that this type must be one of the given primitive types. -mustBeOneOf :: (MonadUnify m) => [PrimType] -> Usage -> StructType -> m () -mustBeOneOf [req_t] usage t = unify usage (Scalar (Prim req_t)) t -mustBeOneOf ts usage t = do - t' <- normType t - constraints <- getConstraints - let isRigid' v = isRigid v constraints - - case t' of - Scalar (TypeVar _ (QualName [] v) []) - | not $ isRigid' v -> linkVarToTypes usage v ts - Scalar (Prim pt) | pt `elem` ts -> pure () - _ -> failure - where - failure = - unifyError usage mempty noBreadCrumbs $ - "Cannot unify type" - <+> dquotes (pretty t) - <+> "with any of " - <> commasep (map pretty ts) - <> "." - -linkVarToTypes :: (MonadUnify m) => Usage -> VName -> [PrimType] -> m () -linkVarToTypes usage vn ts = do - vn_constraint <- M.lookup vn <$> getConstraints - case vn_constraint of - Just (lvl, Overloaded vn_ts vn_usage) -> - case ts `L.intersect` vn_ts of - [] -> - unifyError usage mempty noBreadCrumbs $ - "Type constrained to one of" - <+> commasep (map pretty ts) - <+> "but also one of" - <+> commasep (map pretty vn_ts) - <+> "due to" - <+> pretty vn_usage - <> "." - ts' -> modifyConstraints $ M.insert vn (lvl, Overloaded ts' usage) - Just (_, HasConstrs _ _ vn_usage) -> - unifyError usage mempty noBreadCrumbs $ - "Type constrained to one of" - <+> commasep (map pretty ts) - <> ", but also inferred to be sum type due to" - <+> pretty vn_usage - <> "." - Just (_, HasFields _ _ vn_usage) -> - unifyError usage mempty noBreadCrumbs $ - "Type constrained to one of" - <+> commasep (map pretty ts) - <> ", but also inferred to be record due to" - <+> pretty vn_usage - <> "." - Just (lvl, _) -> modifyConstraints $ M.insert vn (lvl, Overloaded ts usage) - Nothing -> - unifyError usage mempty noBreadCrumbs $ - "Cannot constrain type to one of" <+> commasep (map pretty ts) - --- | Assert that this type must support equality. -equalityType :: - (MonadUnify m, Pretty (Shape dim), Pretty u) => - Usage -> - TypeBase dim u -> - m () -equalityType usage t = do - unless (orderZero t) $ - unifyError usage mempty noBreadCrumbs $ - "Type " <+> dquotes (pretty t) <+> "does not support equality (may contain function)." - mapM_ mustBeEquality $ typeVars t - where - mustBeEquality vn = do - constraints <- getConstraints - case M.lookup vn constraints of - Just (_, Constraint (RetType [] (Scalar (TypeVar _ (QualName [] vn') []))) _) -> - mustBeEquality vn' - Just (_, Constraint (RetType _ vn_t) cusage) - | not $ orderZero vn_t -> - unifyError usage mempty noBreadCrumbs $ - "Type" - <+> dquotes (pretty t) - <+> "does not support equality." - "Constrained to be higher-order due to" - <+> pretty cusage - <+> "." - | otherwise -> pure () - Just (lvl, NoConstraint _ _) -> - modifyConstraints $ M.insert vn (lvl, Equality usage) - Just (_, Overloaded _ _) -> - pure () -- All primtypes support equality. - Just (_, Equality {}) -> - pure () - _ -> - unifyError usage mempty noBreadCrumbs $ - "Type" <+> prettyName vn <+> "does not support equality." - -zeroOrderTypeWith :: - (MonadUnify m) => - Usage -> - BreadCrumbs -> - StructType -> - m () -zeroOrderTypeWith usage bcs t = do - unless (orderZero t) $ - unifyError usage mempty bcs $ - "Type" indent 2 (pretty t) "found to be functional." - mapM_ mustBeZeroOrder . S.toList . typeVars =<< normType t - where - mustBeZeroOrder vn = do - constraints <- getConstraints - case M.lookup vn constraints of - Just (lvl, NoConstraint _ _) -> - modifyConstraints $ M.insert vn (lvl, NoConstraint Unlifted usage) - Just (lvl, HasFields _ fs _) -> - modifyConstraints $ M.insert vn (lvl, HasFields Unlifted fs usage) - Just (lvl, HasConstrs _ cs _) -> - modifyConstraints $ M.insert vn (lvl, HasConstrs Unlifted cs usage) - Just (_, ParamType Lifted ploc) -> - unifyError usage mempty bcs $ - "Type parameter" - <+> dquotes (prettyName vn) - <+> "at" - <+> pretty (locStr ploc) - <+> "may be a function." - _ -> pure () - --- | Assert that this type must be zero-order. -zeroOrderType :: - (MonadUnify m) => Usage -> T.Text -> StructType -> m () -zeroOrderType usage desc = - zeroOrderTypeWith usage $ breadCrumb bc noBreadCrumbs - where - bc = Matching $ "When checking" <+> textwrap desc - arrayElemTypeWith :: (MonadUnify m, Pretty (Shape dim), Pretty u) => Usage -> @@ -1079,9 +723,7 @@ arrayElemType :: TypeBase dim u -> m () arrayElemType usage desc = - arrayElemTypeWith usage $ breadCrumb bc noBreadCrumbs - where - bc = Matching $ "When checking" <+> textwrap desc + arrayElemTypeWith usage $ matching $ "When checking" <+> textwrap desc unifySharedFields :: (MonadUnify m) => @@ -1094,7 +736,7 @@ unifySharedFields :: m () unifySharedFields onDims usage bound bcs fs1 fs2 = forM_ (M.toList $ M.intersectionWith (,) fs1 fs2) $ \(f, (t1, t2)) -> - unifyWith onDims usage bound (breadCrumb (MatchingFields [f]) bcs) t1 t2 + unifyWith onDims usage bound (matchingField f <> bcs) t1 t2 unifySharedConstructors :: (MonadUnify m) => @@ -1111,102 +753,12 @@ unifySharedConstructors onDims usage bound bcs cs1 cs2 = where unifyConstructor c f1 f2 | length f1 == length f2 = do - let bcs' = breadCrumb (MatchingConstructor c) bcs + let bcs' = matchingConstructor c <> bcs zipWithM_ (unifyWith onDims usage bound bcs') f1 f2 | otherwise = unifyError usage mempty bcs $ "Cannot unify constructor" <+> dquotes (prettyName c) <> "." --- | In @mustHaveConstr usage c t fs@, the type @t@ must have a --- constructor named @c@ that takes arguments of types @ts@. -mustHaveConstr :: - (MonadUnify m) => - Usage -> - Name -> - StructType -> - [StructType] -> - m () -mustHaveConstr usage c t fs = do - constraints <- getConstraints - case t of - Scalar (TypeVar _ (QualName _ tn) []) - | Just (lvl, NoConstraint l _) <- M.lookup tn constraints -> do - mapM_ (scopeCheck usage noBreadCrumbs tn lvl) fs - modifyConstraints $ M.insert tn (lvl, HasConstrs l (M.singleton c fs) usage) - | Just (lvl, HasConstrs l cs _) <- M.lookup tn constraints -> - case M.lookup c cs of - Nothing -> - modifyConstraints $ - M.insert tn (lvl, HasConstrs l (M.insert c fs cs) usage) - Just fs' - | length fs == length fs' -> zipWithM_ (unify usage) fs fs' - | otherwise -> - unifyError usage mempty noBreadCrumbs $ - "Different arity for constructor" <+> dquotes (pretty c) <> "." - Scalar (Sum cs) -> - case M.lookup c cs of - Nothing -> - unifyError usage mempty noBreadCrumbs $ - "Constuctor" <+> dquotes (pretty c) <+> "not present in type." - Just fs' - | length fs == length fs' -> zipWithM_ (unify usage) fs fs' - | otherwise -> - unifyError usage mempty noBreadCrumbs $ - "Different arity for constructor" <+> dquotes (pretty c) <+> "." - _ -> - unify usage t $ Scalar $ Sum $ M.singleton c fs - -mustHaveFieldWith :: - (MonadUnify m) => - UnifySizes m -> - Usage -> - [VName] -> - BreadCrumbs -> - Name -> - StructType -> - m StructType -mustHaveFieldWith onDims usage bound bcs l t = do - constraints <- getConstraints - l_type <- newTypeVar (locOf usage) "t" - case t of - Scalar (TypeVar _ (QualName _ tn) []) - | Just (lvl, NoConstraint {}) <- M.lookup tn constraints -> do - scopeCheck usage bcs tn lvl l_type - modifyConstraints $ M.insert tn (lvl, HasFields Lifted (M.singleton l l_type) usage) - pure l_type - | Just (lvl, HasFields lifted fields _) <- M.lookup tn constraints -> do - case M.lookup l fields of - Just t' -> unifyWith onDims usage bound bcs l_type t' - Nothing -> - modifyConstraints $ - M.insert - tn - (lvl, HasFields lifted (M.insert l l_type fields) usage) - pure l_type - Scalar (Record fields) - | Just t' <- M.lookup l fields -> do - unify usage l_type t' - pure t' - | otherwise -> - unifyError usage mempty bcs $ - "Attempt to access field" - <+> dquotes (pretty l) - <+> " of value of type" - <+> pretty (toStructural t) - <> "." - _ -> do - unify usage t $ Scalar $ Record $ M.singleton l l_type - pure l_type - --- | Assert that some type must have a field with this name and type. -mustHaveField :: - (MonadUnify m) => - Usage -> - Name -> - StructType -> - m StructType -mustHaveField usage = mustHaveFieldWith (unifySizes usage) usage mempty noBreadCrumbs - newDimOnMismatch :: (MonadUnify m) => Loc -> @@ -1242,10 +794,33 @@ unifyMostCommon :: StructType -> m (StructType, [VName]) unifyMostCommon usage t1 t2 = do - -- We are ignoring the dimensions here, because any mismatches - -- should be turned into fresh size variables. - let allOK _ _ _ _ _ = pure () - unifyWith allOK usage mempty noBreadCrumbs t1 t2 + -- Like 'unifySizes', except we do not fail on mismatches - these + -- are instead turned into fresh existential sizes in + -- 'newDimOnMismatch'. The most annoying thing is that we have to + -- replicate scope checking, because we don't want to link if it + -- would fail. + constraints <- getConstraints + + let varLevel v = fst <$> M.lookup v constraints + expLevel e = + L.foldl' max 0 $ mapMaybe varLevel $ S.toList $ fvVars $ freeInExp e + + onDims bcs bound nonrigid e1 e2 + | Just es <- similarExps e1 e2 = + mapM_ (uncurry $ onDims bcs bound nonrigid) es + onDims bcs _ nonrigid (Var v1 _ _) e2 + | Just lvl1 <- nonrigid (qualLeaf v1), + expLevel e2 <= lvl1, + not $ qualLeaf v1 `S.member` fvVars (freeInExp e2) = + linkVarToDim usage bcs (qualLeaf v1) lvl1 e2 + onDims bcs _ nonrigid e1 (Var v2 _ _) + | Just lvl2 <- nonrigid (qualLeaf v2), + expLevel e1 <= lvl2, + not $ qualLeaf v2 `S.member` fvVars (freeInExp e1) = + linkVarToDim usage bcs (qualLeaf v2) lvl2 e1 + onDims _ _ _ _ _ = pure () + + unifyWith onDims usage mempty mempty t1 t2 t1' <- normTypeFully t1 t2' <- normTypeFully t2 newDimOnMismatch (locOf usage) t1' t2' @@ -1332,22 +907,3 @@ doUnification loc rigid_tparams nonrigid_tparams t1 t2 = runUnifyM rigid_tparams nonrigid_tparams $ do unify (Usage Nothing (locOf loc)) t1 t2 normTypeFully t2 - --- Note [Linking variables to sum types] --- --- Consider the case when unifying a result type --- --- i32 -> ?[n].(#foo [n]bool) --- --- with --- --- i32 -> ?[k].a --- --- where 'a' has a HasConstrs constraint saying that it must have at --- least a constructor of type '#foo [0]bool'. --- --- This unification should succeed, but we must not merely link 'a' to --- '#foo [n]bool', as 'n' is not free. Instead we should instantiate --- 'a' to be a concrete sum type (because now we know exactly which --- constructor labels it must have), and unify each of its constructor --- payloads with the corresponding expected payload. diff --git a/src/Language/Futhark/TypeChecker/UnionFind.hs b/src/Language/Futhark/TypeChecker/UnionFind.hs new file mode 100644 index 0000000000..e718c6db2b --- /dev/null +++ b/src/Language/Futhark/TypeChecker/UnionFind.hs @@ -0,0 +1,137 @@ +module Language.Futhark.TypeChecker.UnionFind + ( TyVarNode, + TyVarSol (..), + makeTyVarNode, + makeTyParamNode, + find, + getSol, + getKey, + assignNewSol, + union, + unionNewSol, + ) +where + +import Control.Monad (when) +import Control.Monad.ST (ST) +import Data.STRef + ( STRef, + modifySTRef', + newSTRef, + readSTRef, + writeSTRef, + ) +import Language.Futhark (Liftedness, Loc) +import Language.Futhark.TypeChecker.Constraints + ( CtType, + Level, + TyVar, + TyVarInfo, + ) + +type Type = CtType () + +-- | A (partial) solution for a type variable. +data TyVarSol + = -- | Has been assigned this type. + Solved Type + | -- | Is an explicit (rigid) type parameter in the source program. + Param Level Liftedness Loc + | -- | Is unsolved but has this constraint. + Unsolved (TyVarInfo ()) + deriving (Show, Eq) + +-- | A node in the union-find graph containing information about a type +-- variable. +newtype TyVarNode s = Node (STRef s (NodeInfo s)) deriving (Eq) + +data NodeInfo s + = Link !(TyVarNode s) + | Repr !ReprInfo + +data ReprInfo = ReprInfo + { solution :: !TyVarSol, + key :: !TyVar + } + +-- | Create a fresh node of a type variable and return it. A fresh node +-- is in the equivalence class that contains only itself. +makeTyVarNode :: TyVar -> TyVarInfo () -> ST s (TyVarNode s) +makeTyVarNode tv constraint = do + let r = + ReprInfo + { solution = Unsolved constraint, + key = tv + } + ref <- newSTRef $ Repr r + pure $ Node ref + +-- | Create a fresh node of a type parameter and return it. A fresh node +-- is in the equivalence class that contains only itself. +makeTyParamNode :: TyVar -> Level -> Liftedness -> Loc -> ST s (TyVarNode s) +makeTyParamNode tv lvl lft loc = do + let r = + ReprInfo + { solution = Param lvl lft loc, + key = tv + } + ref <- newSTRef $ Repr r + pure $ Node ref + +-- | @find node@ returns the representative of @node@'s +-- equivalence class and the information associated with +-- this equivalence class. +-- +-- This method performs the path compresssion. +find :: TyVarNode s -> ST s (TyVarNode s, ReprInfo) +find node@(Node ref) = do + node_info <- readSTRef ref + case node_info of + -- Input node is representative. + Repr repr_info -> pure (node, repr_info) + -- Input node's parent is another node. + Link parent -> do + a@(repr, _) <- find parent + when (repr /= parent) $ + -- Performing path compression. + writeSTRef ref $ + Link repr + pure a + +-- | Return the solution associated with the argument node's +-- equivalence class. +getSol :: TyVarNode s -> ST s TyVarSol +getSol node = solution . snd <$> find node + +-- | Return the name of the representative type variable. +getKey :: TyVarNode s -> ST s TyVar +getKey node = key . snd <$> find node + +-- | Assign a new solution/type to the node's equivalence class. +-- +-- Precondition: The node is in an equivalence class representing an +-- unsolved/flexible type variable. +assignNewSol :: TyVarNode s -> TyVarSol -> ST s () +assignNewSol node new_sol = do + (Node ref, repr_info) <- find node + modifySTRef' ref $ const . Repr $ repr_info {solution = new_sol} + +-- | Join the equivalence classes of the nodes. The resulting equivalence +-- class has the same solution and key as the second argument. +union :: TyVarNode s -> TyVarNode s -> ST s () +union n1 n2 = do + Node ref <- fst <$> find n1 + root2 <- fst <$> find n2 + + writeSTRef ref $ Link root2 + +-- | Join the equivalence classes of the nodes. The resulting equivalence +-- class has the same key as the second argument while @new_sol@ is the +-- new solution. +unionNewSol :: TyVarNode s -> TyVarNode s -> TyVarSol -> ST s () +unionNewSol n1 n2 new_sol = do + Node ref1 <- fst <$> find n1 + (root2@(Node ref2), repr_info) <- find n2 + + modifySTRef' ref2 $ const . Repr $ repr_info {solution = new_sol} + writeSTRef ref1 $ Link root2 diff --git a/tests/ascription0.fut b/tests/ascription0.fut index f00243cfea..7d03d59ab4 100644 --- a/tests/ascription0.fut +++ b/tests/ascription0.fut @@ -1,7 +1,7 @@ -- Make sure type errors due to invalid type ascriptions are caught. -- -- == --- error: match +-- error: ascription def main (x: i32, y: i32) : i32 = let (((a): i32), b: i32): (bool, bool) = (x, y) diff --git a/tests/funcall-error1.fut b/tests/funcall-error1.fut index 0bfedc7bd4..c9791213af 100644 --- a/tests/funcall-error1.fut +++ b/tests/funcall-error1.fut @@ -1,6 +1,6 @@ -- Test that functions accept only the right number of arguments. -- == --- error: Cannot apply "f" +-- error: 2 arguments def f (x: i32) (y: f64) : f64 = f64.i32 (x) + y diff --git a/tests/higher-order-functions/conditional-function0.fut b/tests/higher-order-functions/conditional-function0.fut index 2ffc489e59..00f1b441bd 100644 --- a/tests/higher-order-functions/conditional-function0.fut +++ b/tests/higher-order-functions/conditional-function0.fut @@ -1,6 +1,6 @@ -- We cannot return a function from a conditional. -- == --- error: returned from branch +-- error: may not be of function type def f (x: i32) : i32 = x + x def g (x: i32) : i32 = x + 1 diff --git a/tests/higher-order-functions/loops0.fut b/tests/higher-order-functions/loops0.fut index 3bf97683b4..8001a3a7c0 100644 --- a/tests/higher-order-functions/loops0.fut +++ b/tests/higher-order-functions/loops0.fut @@ -1,6 +1,6 @@ -- The merge parameter in a loop cannot have function type. -- == --- error: used as loop variable +-- error: may not be of function def id 'a (x: a) : a = x diff --git a/tests/higher-order-functions/match-function0.fut b/tests/higher-order-functions/match-function0.fut index 59617cfc2d..30d43c8736 100644 --- a/tests/higher-order-functions/match-function0.fut +++ b/tests/higher-order-functions/match-function0.fut @@ -1,6 +1,6 @@ -- We cannot return a function from a pattern match. -- == --- error: returned from pattern match +-- error: may not be of function type def f (x: i32) : i32 = x + x def g (x: i32) : i32 = x + 1 diff --git a/tests/issue1783.fut b/tests/issue1783.fut index 7440b1dd57..41408ccb7f 100644 --- a/tests/issue1783.fut +++ b/tests/issue1783.fut @@ -1,5 +1,5 @@ -- == --- error: cannot match +-- error: differ in arity type surface = #asphere {curvature: f64} diff --git a/tests/issue1787.fut b/tests/issue1787.fut index 6bea58c253..31d2e5958b 100644 --- a/tests/issue1787.fut +++ b/tests/issue1787.fut @@ -1,5 +1,5 @@ -- == --- error: found to be functional +-- error: function type entry main : i32 -> i32 -> i32 = ((true, (.0)), (false, (.1))) diff --git a/tests/issue1926.fut b/tests/issue1926.fut index b77626a259..63df4afd2f 100644 --- a/tests/issue1926.fut +++ b/tests/issue1926.fut @@ -1,5 +1,5 @@ -- == --- error: cannot match value +-- error: Cannot unify type with constructors type found = #found i32 | #not_found diff --git a/tests/record-update1.fut b/tests/record-update1.fut index aa08582f4e..d4a24afc99 100644 --- a/tests/record-update1.fut +++ b/tests/record-update1.fut @@ -1,6 +1,6 @@ -- Type-changing record update. -- == --- error: i32.*bool +-- error: bool.*i32 def main (x: i32) (y: i32) : (bool, i32) = let r0 = {x, y} diff --git a/tests/record-update6.fut b/tests/record-update6.fut index 09eeeeb024..0599fb79ef 100644 --- a/tests/record-update6.fut +++ b/tests/record-update6.fut @@ -1,10 +1,9 @@ -- Inference of record in lambda. -- == --- error: Full type of type octnode = {body: i32} -def f (octree: []octnode) (i: i32) = +entry f (octree: []octnode) (i: i32) = map (\n -> if n.body != i then n diff --git a/tests/records-error3.fut b/tests/records-error3.fut index 0863d08f17..4261d1b035 100644 --- a/tests/records-error3.fut +++ b/tests/records-error3.fut @@ -1,7 +1,7 @@ -- A record value must have at least the fields of its corresponding -- type. -- == --- error: match +-- error: unshared fields def main () = let r: {a: i32, b: i32} = {a = 0} diff --git a/tests/records-error4.fut b/tests/records-error4.fut index b75f64ec5e..c21797bbc1 100644 --- a/tests/records-error4.fut +++ b/tests/records-error4.fut @@ -1,7 +1,7 @@ -- A record value must not have more fields than its corresponding -- type. -- == --- error: match +-- error: unshared fields def main () = let r: {a: i32} = {a = 0, b = 0} diff --git a/tests/records-error7.fut b/tests/records-error7.fut index 8d397ebaf2..122d539878 100644 --- a/tests/records-error7.fut +++ b/tests/records-error7.fut @@ -1,5 +1,5 @@ -- Specific error message on record field mismatches. -- == --- error: Unshared fields: d, c. +-- error: unshared fields: c, d. def f (v: {a: i32, b: i32, c: i32}) : {a: i32, b: i32, d: i32} = v diff --git a/tests/records-error8.fut b/tests/records-error8.fut index d23c668f7f..c872d18d18 100644 --- a/tests/records-error8.fut +++ b/tests/records-error8.fut @@ -1,6 +1,6 @@ -- Unification of variables with incompletely known and distinct fields. -- == --- error: must be a record with fields +-- error: Cannot unify record type def sameconst '^a (_: a) (y: a) = y diff --git a/tests/records-error9.fut b/tests/records-error9.fut index 086ee3f9f0..7515695a02 100644 --- a/tests/records-error9.fut +++ b/tests/records-error9.fut @@ -1,6 +1,6 @@ -- Unification of incomplete record variable with non-record. -- == --- error: Cannot unify a record type with a non-record type +-- error: with type that must be a record def sameconst '^a (_: a) (y: a) = y diff --git a/tests/shapes/error4.fut b/tests/shapes/error4.fut index 0fb7472f25..24931c69ab 100644 --- a/tests/shapes/error4.fut +++ b/tests/shapes/error4.fut @@ -2,7 +2,7 @@ -- == -- error: Sizes.*"n".*do not match -def f (g: (n: i64) -> [n]i32) (l: i64) : i32 = +def f (g: (n: i64) -> [n]i64) (l: i64) : i64 = (g l)[0] def main = f (\n : []i64 -> iota (n + 1)) diff --git a/tests/shapes/error6.fut b/tests/shapes/error6.fut index 8b94eee5f1..635889d74f 100644 --- a/tests/shapes/error6.fut +++ b/tests/shapes/error6.fut @@ -2,7 +2,7 @@ -- == -- error: "n" -def ap (f: (n: i64) -> [n]i32) (k: i64) : [k]i32 = +def ap (f: (n: i64) -> [n]i64) (k: i64) : [k]i64 = f k def main = ap (\n -> iota (n + 1)) 10 diff --git a/tests/shapes/funshape2.fut b/tests/shapes/funshape2.fut index b77b0339c9..dc17af92aa 100644 --- a/tests/shapes/funshape2.fut +++ b/tests/shapes/funshape2.fut @@ -1,4 +1,4 @@ -- == --- error: scope violation +-- error: causality def main xs = (\f' -> f' (filter (> 0) xs)) (\_ -> 0) diff --git a/tests/shapes/polymorphic4.fut b/tests/shapes/polymorphic4.fut index b44af86c34..acab851f67 100644 --- a/tests/shapes/polymorphic4.fut +++ b/tests/shapes/polymorphic4.fut @@ -2,6 +2,6 @@ -- == -- error: do not match -def foo f x : [1]i32 = +def foo (f : (n: i64) -> [n]i32) x : [1]i32 = let r = if true then f x : []i32 else [1i32] in r diff --git a/tests/shapes/shape_duplicate.fut b/tests/shapes/shape_duplicate.fut index 689d1ad5ca..fb85961d55 100644 --- a/tests/shapes/shape_duplicate.fut +++ b/tests/shapes/shape_duplicate.fut @@ -4,7 +4,7 @@ -- == -- error: do not match -def f [n] [m] ((_, elems: [n]i32): (i32, [m]i32)) : i32 = +def f [n] [m] ((_, elems: [n]i64): (i64, [m]i64)) : i64 = n + m + elems[0] -def main (x: i32, y: []i32) : i32 = f (x, y) +def main (x: i64, y: []i64) : i64 = f (x, y) diff --git a/tests/shapes/size-inference2.fut b/tests/shapes/size-inference2.fut index b6f59d4a9a..2804383f72 100644 --- a/tests/shapes/size-inference2.fut +++ b/tests/shapes/size-inference2.fut @@ -2,4 +2,4 @@ -- == -- error: Sizes.*do not match -def main [n] (xs: [n]i32) : [n]i32 = iota (length xs) +def main [n] (xs: [n]i32) : [n]i64 = iota (length xs) diff --git a/tests/sumtypes/coerce1.fut b/tests/sumtypes/coerce1.fut index eeff92a2a3..b6bfe42f3d 100644 --- a/tests/sumtypes/coerce1.fut +++ b/tests/sumtypes/coerce1.fut @@ -1,5 +1,4 @@ -- == --- error: Ambiguous size.*anonymous size type opt 't = #some t | #none diff --git a/tests/sumtypes/sumtype32.fut b/tests/sumtypes/sumtype32.fut index ca5f22c91f..b5255b580c 100644 --- a/tests/sumtypes/sumtype32.fut +++ b/tests/sumtypes/sumtype32.fut @@ -1,5 +1,5 @@ -- Specific error message on constructor mismatches. -- == --- error: Unshared constructors: #d, #c. +-- error: Unshared constructors: #c, #d. def f (v: #a i32 | #b i32 | #c i32) : #a i32 | #b i32 | #d i32 = v diff --git a/tests/sumtypes/sumtype46.fut b/tests/sumtypes/sumtype46.fut index dac4e4671f..8abc3278fb 100644 --- a/tests/sumtypes/sumtype46.fut +++ b/tests/sumtypes/sumtype46.fut @@ -1,5 +1,5 @@ -- == --- error: cannot match +-- error: differ in arity type t = #foo f64 diff --git a/tests/sumtypes/sumtype47.fut b/tests/sumtypes/sumtype47.fut index b3fb9c7ce5..c0039bfc43 100644 --- a/tests/sumtypes/sumtype47.fut +++ b/tests/sumtypes/sumtype47.fut @@ -1,5 +1,5 @@ -- == --- error: cannot match +-- error: differ in arity type t = #foo f64 diff --git a/tests/tridag.fut b/tests/tridag.fut index 92f92a72a9..eda3611dfd 100644 --- a/tests/tridag.fut +++ b/tests/tridag.fut @@ -33,9 +33,9 @@ -- 2.726331, -1.618253, 1.472878] -- } -def tridag ( nn: i32 - , b: *[]f64 - , d: *[]f64 +def tridag [nn] + ( b: *[]f64 + , d: *[nn]f64 , a: []f64 , c: []f64 ) : ([]f64, []f64) = @@ -62,4 +62,4 @@ def main : ([]f64, []f64) = let b = map (\x -> f64.i64 (x) + 1.0) (iota (nn)) let c = map (\x -> 1.11 * f64.i64 (x) + 0.5) (iota (nn)) let d = map (\x -> 1.01 * f64.i64 (x) + 0.25) (iota (nn)) - in tridag (i32.i64 nn, b, d, a, c) + in tridag (b, d, a, c) diff --git a/tests/types/inference-error12.fut b/tests/types/inference-error12.fut index cade8c9c0d..01e499f875 100644 --- a/tests/types/inference-error12.fut +++ b/tests/types/inference-error12.fut @@ -1,6 +1,6 @@ -- A record turns out to be missing a field. -- == --- error: expected type +-- error: unify record type def f r = let y = r.l2 diff --git a/tests/types/inference-error3.fut b/tests/types/inference-error3.fut index 7a2da29bd6..6eda032d42 100644 --- a/tests/types/inference-error3.fut +++ b/tests/types/inference-error3.fut @@ -1,5 +1,5 @@ -- If something is applied, it cannot later be put in an array. -- == --- error: -> b +-- error: -> def f x = (x 2, [x]) diff --git a/tests/types/inference-error4.fut b/tests/types/inference-error4.fut index 809b98302a..0ff781f33a 100644 --- a/tests/types/inference-error4.fut +++ b/tests/types/inference-error4.fut @@ -1,6 +1,6 @@ -- If something is used in a loop, it cannot later be inferred as a -- function. -- == --- error: functional +-- error: function type def f x = (loop x = x for i < 10 do x, x 2) diff --git a/tests/types/inference-error7.fut b/tests/types/inference-error7.fut index 0c424be153..c3a5a0fcce 100644 --- a/tests/types/inference-error7.fut +++ b/tests/types/inference-error7.fut @@ -1,5 +1,5 @@ -- Ambiguous equality type. -- == --- error: ambiguous +-- error: does not support equality def add x y = x == y diff --git a/tests/types/inference-error9.fut b/tests/types/inference-error9.fut index 0c6886c881..6cead89cec 100644 --- a/tests/types/inference-error9.fut +++ b/tests/types/inference-error9.fut @@ -2,4 +2,4 @@ -- == -- error: equality -def main 't (x: t) = x == x +def f 't (x: t) = x == x diff --git a/tests/types/inference22.fut b/tests/types/inference22.fut index a8c18e3364..c90261a60d 100644 --- a/tests/types/inference22.fut +++ b/tests/types/inference22.fut @@ -2,5 +2,5 @@ -- == def main (x: i32) (y: bool) = - let f x y = (y, x) + let f 'a 'b (x: a) (y: b) = (y, x) in (f x y, f y x) diff --git a/tests/types/inference5.fut b/tests/types/inference5.fut index 900704f21a..d05b9084aa 100644 --- a/tests/types/inference5.fut +++ b/tests/types/inference5.fut @@ -1,6 +1,6 @@ --- Inference for a local function. +-- let should not be generalised -- == --- input { 2 } output { 4 } +-- error: Cannot apply "apply" def main x = let apply f x = f x diff --git a/tests/types/occurs.fut b/tests/types/occurs.fut new file mode 100644 index 0000000000..c37b1448c4 --- /dev/null +++ b/tests/types/occurs.fut @@ -0,0 +1,5 @@ +-- Simple instance of an occurs check. +-- == +-- error: Occurs + +let bad a f = f a f