From 9180944805b0a28172b3e320abb4bcd35dae7cfb Mon Sep 17 00:00:00 2001 From: Ken Gorab Date: Sun, 27 Oct 2024 20:02:53 -0400 Subject: [PATCH] Selfhost: independent test runner (#477) * Selfhost: independent test runner This adds a new test runner (in nodejs, for convenience) which uses the current installation of `abra` to run the lexer, parser, typechecker, and compiler tests against the assertion files. Once we start using features in the compiler that are _not_ supported by the reference implementation (for example, tuple destructuring, which is already an example of the selfhosted compiler advancing beyond the initial reference implementation), we will no longer rely on the original rust-based implementation. * Tar flags... * Tar flags... * github action debugging * github action debugging 2 * github action debugging 3 * github action debugging 4 * github action debugging 5 * github action debugging 6 * Cleanup, and adding colors to selfhost test runner * Selfhost: adding tuple destructuring Now that tuple destructuring is supported by the compiler (selfhosted) and we're bootstrapping using the initial selfhosted compiler, update the compiler to use tuple destructuring. Also, add a separate testing pass to build the next compiler and ensure the tests pass against that compiler too. * Removing old rust-based selfhosted test suite * Updating release gh actions script to not depend on reference rust+llvm compiler --- .github/workflows/release.yml | 35 +- .github/workflows/selfhost.yml | 53 ++ Cargo.lock | 16 - Cargo.toml | 1 - selfhost/gen-pkg/abraw | 9 +- selfhost/src/compiler.abra | 459 ++++--------- selfhost/src/lexer.abra | 8 +- selfhost/src/parser.abra | 10 +- selfhost/src/qbe.abra | 25 +- selfhost/src/test_utils.abra | 20 +- selfhost/src/typechecker.abra | 290 ++------ selfhost/src/typechecker_test_utils.abra | 6 +- selfhost/test/run-tests.js | 824 +++++++++++++++++++++++ selfhost/test/test-runner.js | 172 +++++ selfhost_test/Cargo.toml | 12 - selfhost_test/src/lib.rs | 5 - selfhost_test/src/test_utils.rs | 323 --------- selfhost_test/src/tests.rs | 800 ---------------------- 18 files changed, 1307 insertions(+), 1761 deletions(-) create mode 100644 .github/workflows/selfhost.yml create mode 100644 selfhost/test/run-tests.js create mode 100644 selfhost/test/test-runner.js delete mode 100644 selfhost_test/Cargo.toml delete mode 100644 selfhost_test/src/lib.rs delete mode 100644 selfhost_test/src/test_utils.rs delete mode 100644 selfhost_test/src/tests.rs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1821c29c..abe12f4a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,38 +11,12 @@ jobs: steps: - name: Checkout source uses: actions/checkout@v2 - - name: Cache Cargo - uses: actions/cache@v3 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - name: Cache LLVM - id: cache-llvm - uses: actions/cache@v3 - with: - path: ./llvm - key: llvm-11.1.0 - name: Cache QBE id: cache-qbe uses: actions/cache@v3 with: path: ./qbe/qbe-1.2 key: qbe-1.2 - - name: Install LLVM (11.1.0) - run: | - mkdir -p llvm - curl -L "https://github.com/llvm/llvm-project/releases/download/llvmorg-11.1.0/clang+llvm-11.1.0-x86_64-linux-gnu-ubuntu-20.10.tar.xz" > llvm.tar.xz - tar x --xz -C llvm --strip-components=1 -f llvm.tar.xz - if: steps.cache-llvm.outputs.cache-hit != 'true' - - name: Setup LLVM - run: | - sudo apt-get update - sudo apt-get install -y libtinfo6 - echo "PATH=$(pwd)/llvm/bin:$PATH" >> $GITHUB_ENV - echo "LLVM_CONFIG=$(pwd)/llvm/bin/llvm-config" >> $GITHUB_ENV - name: Install QBE run: | mkdir -p qbe @@ -55,10 +29,15 @@ jobs: - name: Setup QBE run: | echo "PATH=$(pwd)/qbe/qbe-1.2:$PATH" >> $GITHUB_ENV - - name: Build reference compiler - run: cargo build - name: Install ext dependencies run: ./configure-libgc.sh + - name: Install abra + run: | + mkdir abra-linux + wget https://github.com/kengorab/abra-lang/releases/latest/download/abra-linux.tar.gz + tar -xzf abra-linux.tar.gz -C abra-linux + echo "PATH=$(pwd)/abra-linux:$PATH" >> $GITHUB_ENV + echo "ABRA_HOME=`realpath $(pwd)/abra-linux/std`" >> $GITHUB_ENV - name: Build package run: | cd selfhost diff --git a/.github/workflows/selfhost.yml b/.github/workflows/selfhost.yml new file mode 100644 index 00000000..45a927d6 --- /dev/null +++ b/.github/workflows/selfhost.yml @@ -0,0 +1,53 @@ +name: Test selfhosted + +on: + push: + branches: + - master + pull_request: + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-22.04 + steps: + - name: Checkout source + uses: actions/checkout@v2 + - name: Cache QBE + id: cache-qbe + uses: actions/cache@v3 + with: + path: ./qbe/qbe-1.2 + key: qbe-1.2 + - name: Install QBE + run: | + mkdir -p qbe + cd qbe + wget https://c9x.me/compile/release/qbe-1.2.tar.xz + tar -xf qbe-1.2.tar.xz + cd qbe-1.2 + make + if: steps.cache-qbe.outputs.cache-hit != 'true' + - name: Setup QBE + run: | + echo "PATH=$(pwd)/qbe/qbe-1.2:$PATH" >> $GITHUB_ENV + - name: Install ext dependencies + run: ./configure-libgc.sh + - name: Install abra + run: | + mkdir abra-linux + wget https://github.com/kengorab/abra-lang/releases/latest/download/abra-linux.tar.gz + tar -xzf abra-linux.tar.gz -C abra-linux + echo "PATH=$(pwd)/abra-linux:$PATH" >> $GITHUB_ENV + echo "ABRA_HOME=`realpath $(pwd)/abra-linux/std`" >> $GITHUB_ENV + - name: Run tests + run: | + cd selfhost + node test/run-tests.js + - name: Run tests against compiler-next + run: | + cd selfhost + abra build -o compiler_next ./src/compiler.test.abra + COMPILER_BIN=./._abra/compiler_next node test/run-tests.js diff --git a/Cargo.lock b/Cargo.lock index 9be6289a..5a2ab4b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1194,16 +1194,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "selfhost_test" -version = "0.1.0" -dependencies = [ - "abra_core", - "assert_cmd", - "itertools 0.9.0", - "similar", -] - [[package]] name = "semver" version = "0.11.0" @@ -1264,12 +1254,6 @@ dependencies = [ "syn 1.0.58", ] -[[package]] -name = "similar" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" - [[package]] name = "slab" version = "0.4.2" diff --git a/Cargo.toml b/Cargo.toml index b6b2197e..0e854f4c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,4 @@ members = [ "abra_lsp", "abra_native", "abra_wasm", - "selfhost_test", ] \ No newline at end of file diff --git a/selfhost/gen-pkg/abraw b/selfhost/gen-pkg/abraw index 7e12792b..6379608b 100755 --- a/selfhost/gen-pkg/abraw +++ b/selfhost/gen-pkg/abraw @@ -73,8 +73,13 @@ mkdir -p "$dotabradir" touch "$dotabradir/$outfile.ssa" : > "$dotabradir/$outfile.ssa" # truncate file -export ABRA_HOME="$abra_root/std" -$(echo "$abra_root/compiler $filepath $outfile") +if [[ -z "$ABRA_HOME" ]]; then + echo "Cannot determine ABRA_HOME. Ensure the environment variable exists and points to the std/ dir of the installation" + exit 1 +fi + +compiler_bin="${COMPILER_BIN:-"$abra_root/compiler"}" +$(echo "$compiler_bin $filepath $outfile") qbe -o "$dotabradir/$outfile.s" "$dotabradir/$outfile.ssa" diff --git a/selfhost/src/compiler.abra b/selfhost/src/compiler.abra index 13c1de45..3cd1c5d3 100644 --- a/selfhost/src/compiler.abra +++ b/selfhost/src/compiler.abra @@ -79,10 +79,10 @@ type ResolvedGenerics { func toString(self): String { val parts = ["ResolvedGenerics(_layers: ["] - for layer, idx in self._layers { - parts.push("(\"${layer[0]}\", { ") - for _p in layer[1] { - parts.push("\"${_p[0]}\": \"${_p[1].repr()}\", ") + for (layerName, generics), idx in self._layers { + parts.push("(\"$layerName\", { ") + for (name, ty) in generics { + parts.push("\"$name\": \"${ty.repr()}\", ") } parts.push("}") @@ -95,8 +95,8 @@ type ResolvedGenerics { func resolveGeneric(self, name: String): Type? { var idx = self._layers.length - 1 - while self._layers[idx] |layer| { - if layer[1][name] |ty| return Some(ty) + while self._layers[idx] |(_, generics)| { + if generics[name] |ty| return Some(ty) idx -= 1 } @@ -128,10 +128,9 @@ type ResolvedGenerics { } TypeKind.Func(paramTypes, returnType) => { val resolvedParams: (Type, Bool)[] = [] - for _p in paramTypes { - // TODO: destructuring - val ty = match self._resolveType(_p[0]) { Ok(v) => v, Err(e) => return Err(e) } - resolvedParams.push((ty, _p[1])) + for (paramType, paramIsRequired) in paramTypes { + val ty = match self._resolveType(paramType) { Ok(v) => v, Err(e) => return Err(e) } + resolvedParams.push((ty, paramIsRequired)) } val resolvedReturn = match self._resolveType(returnType) { Ok(v) => v, Err(e) => return Err(e) } @@ -143,11 +142,7 @@ type ResolvedGenerics { func addLayer(self, context: String, given: Map): Result { val newLayer: Map = {} - for _p in given { - // TODO: destructuring - val name = _p[0] - val ty = _p[1] - + for (name, ty) in given { newLayer[name] = match self._resolveType(ty) { Ok(v) => v, Err(e) => return Err(e) } } @@ -282,10 +277,7 @@ export type Compiler { } self._currentFn.block.registerLabel(labelThen) - if conditionBinding |_p| { - // TODO: destructuring - val bindingPattern = _p[0] - val vars = _p[1] + if conditionBinding |(bindingPattern, vars)| { val variables = vars.keyBy(v => v.label.name) val bindingVal = if condExprIsOpt |innerTy| { @@ -339,10 +331,7 @@ export type Compiler { } self._currentFn.block.registerLabel(loopBodyLabel) - if conditionBinding |_p| { - // TODO: destructuring - val bindingPattern = _p[0] - val vars = _p[1] + if conditionBinding |(bindingPattern, vars)| { val variables = vars.keyBy(v => v.label.name) val bindingVal = if condExprIsOpt |innerTy| { @@ -370,14 +359,11 @@ export type Compiler { } TypedAstNodeKind.For(typedIterator, itemBindingPattern, indexBinding, block) => { val forLabelPrefix = "for_${node.token.position.line}_${node.token.position.col}" - val _t = match self._getInstanceTypeForType(typedIterator.ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val instTy = _t[0] - val typeArgs = _t[1] + val (instTy, typeArgs) = match self._getInstanceTypeForType(typedIterator.ty) { Ok(v) => v, Err(e) => return Err(e) } - val _p = match instTy { + val (iterVal, iterTy, nextFn, popAdditionalResolvedGenericsLayer) = match instTy { StructOrEnum.Struct(s) => { - val _p = if s == self._project.preludeArrayStruct { + if s == self._project.preludeArrayStruct { val innerTy = if typeArgs[0] |t| t else return unreachable("Array has 1 required type argument") match self._resolvedGenerics.addLayer("array literal", { "T": innerTy }) { Ok => {}, Err(e) => return Err(CompileError(position: node.token.position, kind: CompileErrorKind.ResolvedGenericsError(context: "array literal", message: e))) } @@ -389,15 +375,14 @@ export type Compiler { val iter = match self._currentFn.block.buildCall(Callable.Function(iteratorFnVal), [arrayVal], Some("${forLabelPrefix}_iterator")) { Ok(v) => v, Err(e) => return qbeError(e) } - val _t = match self._getInstanceTypeForType(iteratorFn.returnType) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val instanceMethods = match _t[0] { + val (structOrEnum, typeArgs) = match self._getInstanceTypeForType(iteratorFn.returnType) { Ok(v) => v, Err(e) => return Err(e) } + val instanceMethods = match structOrEnum { StructOrEnum.Struct(s) => s.instanceMethods StructOrEnum.Enum(e) => e.instanceMethods } val nextFn = if instanceMethods.find(m => m.label.name == "next") |fn| fn else return unreachable("a type must have a 'next' method if it's to be iterable") - val iterTy = Type(kind: TypeKind.Instance(_t[0], _t[1])) + val iterTy = Type(kind: TypeKind.Instance(structOrEnum, typeArgs)) (iter, iterTy, nextFn, true) } else if s == self._project.preludeSetStruct { val innerTy = if typeArgs[0] |t| t else return unreachable("Set has 1 required type argument") @@ -411,15 +396,14 @@ export type Compiler { val iter = match self._currentFn.block.buildCall(Callable.Function(iteratorFnVal), [mapVal], Some("${forLabelPrefix}_iterator")) { Ok(v) => v, Err(e) => return qbeError(e) } - val _t = match self._getInstanceTypeForType(iteratorFn.returnType) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val instanceMethods = match _t[0] { + val (structOrEnum, typeArgs) = match self._getInstanceTypeForType(iteratorFn.returnType) { Ok(v) => v, Err(e) => return Err(e) } + val instanceMethods = match structOrEnum { StructOrEnum.Struct(s) => s.instanceMethods StructOrEnum.Enum(e) => e.instanceMethods } val nextFn = if instanceMethods.find(m => m.label.name == "next") |fn| fn else return unreachable("a type must have a 'next' method if it's to be iterable") - val iterTy = Type(kind: TypeKind.Instance(_t[0], _t[1])) + val iterTy = Type(kind: TypeKind.Instance(structOrEnum, typeArgs)) (iter, iterTy, nextFn, true) } else if s == self._project.preludeMapStruct { val keyTy = if typeArgs[0] |t| t else return unreachable("Map has 2 required type arguments") @@ -434,15 +418,14 @@ export type Compiler { val iter = match self._currentFn.block.buildCall(Callable.Function(iteratorFnVal), [mapVal], Some("${forLabelPrefix}_iterator")) { Ok(v) => v, Err(e) => return qbeError(e) } - val _t = match self._getInstanceTypeForType(iteratorFn.returnType) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val instanceMethods = match _t[0] { + val (structOrEnum, typeArgs) = match self._getInstanceTypeForType(iteratorFn.returnType) { Ok(v) => v, Err(e) => return Err(e) } + val instanceMethods = match structOrEnum { StructOrEnum.Struct(s) => s.instanceMethods StructOrEnum.Enum(e) => e.instanceMethods } val nextFn = if instanceMethods.find(m => m.label.name == "next") |fn| fn else return unreachable("a type must have a 'next' method if it's to be iterable") - val iterTy = Type(kind: TypeKind.Instance(_t[0], _t[1])) + val iterTy = Type(kind: TypeKind.Instance(structOrEnum, typeArgs)) (iter, iterTy, nextFn, true) } else { val iter = match self._compileExpression(typedIterator) { Ok(v) => v, Err(e) => return Err(e) } @@ -450,15 +433,9 @@ export type Compiler { (iter, typedIterator.ty, nextFn, false) } - _p } StructOrEnum.Enum(_enum) => return todo("enum as for-loop target") } - // TODO: destructuring - val iterVal = _p[0] - val iterTy = _p[1] - val nextFn = _p[2] - val popAdditionalResolvedGenericsLayer = _p[3] val nextItemTy = if self._typeIsOption(nextFn.returnType) |innerTy| innerTy else return unreachable("a 'next' method must return an Option type") val iterInstTy = match self._addResolvedGenericsLayerForInstanceMethod(iterTy, "next", node.token.position) { Ok(v) => v, Err(e) => return Err(e) } @@ -484,9 +461,7 @@ export type Compiler { } self._currentFn.block.registerLabel(loopStartLabel) - // TODO: destructuring - val iterateePattern = itemBindingPattern[0] - val iterateeBindingVars = itemBindingPattern[1] + val (iterateePattern, iterateeBindingVars) = itemBindingPattern val iterateeBindingVariables = iterateeBindingVars.keyBy(v => v.label.name) val nextRet = match self._currentFn.block.buildCall(Callable.Function(nextFnVal), [iterVal], Some("next_ret")) { Ok(v) => v, Err(e) => return qbeError(e) } @@ -557,9 +532,7 @@ export type Compiler { } TypedAstNodeKind.EnumDeclaration => Ok(None) TypedAstNodeKind.Break => { - if self._loopStack[-1] |currentLoop| { - // TODO: destructuring - val loopEndLabel = currentLoop[1] + if self._loopStack[-1] |(_, loopEndLabel)| { self._currentFn.block.buildJmp(loopEndLabel) Ok(None) @@ -568,9 +541,7 @@ export type Compiler { } } TypedAstNodeKind.Continue => { - if self._loopStack[-1] |currentLoop| { - // TODO: destructuring - val loopStartLabel = currentLoop[0] + if self._loopStack[-1] |(loopStartLabel, _)| { self._currentFn.block.buildJmp(loopStartLabel) Ok(None) @@ -616,9 +587,8 @@ export type Compiler { val idxExprVal = match self._compileExpression(idxExpr) { Ok(v) => v, Err(e) => return Err(e) } val instType = match self._addResolvedGenericsLayerForInstanceMethod(expr.ty, "set", expr.token.position) { Ok(v) => v, Err(e) => return Err(e) } - val _t = match self._getInstanceTypeForType(expr.ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val struct = match _t[0] { + val (structOrEnum, _) = match self._getInstanceTypeForType(expr.ty) { Ok(v) => v, Err(e) => return Err(e) } + val struct = match structOrEnum { StructOrEnum.Struct(struct) => struct StructOrEnum.Enum => return unreachable("index-assignment only implemented for arrays") } @@ -638,9 +608,8 @@ export type Compiler { val idxExprVal = match self._compileExpression(idxExpr) { Ok(v) => v, Err(e) => return Err(e) } val instType = match self._addResolvedGenericsLayerForInstanceMethod(expr.ty, "set", expr.token.position) { Ok(v) => v, Err(e) => return Err(e) } - val _t = match self._getInstanceTypeForType(expr.ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val struct = match _t[0] { + val (structOrEnum, _) = match self._getInstanceTypeForType(expr.ty) { Ok(v) => v, Err(e) => return Err(e) } + val struct = match structOrEnum { StructOrEnum.Struct(struct) => struct StructOrEnum.Enum => return unreachable("index-assignment only implemented for maps") } @@ -684,9 +653,8 @@ export type Compiler { val res: Result = match node.kind { TypedAstNodeKind.Literal(lit) => { - val _p = match self._compileLiteral(lit) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - Ok(_p[0]) + val (value, _) = match self._compileLiteral(lit) { Ok(v) => v, Err(e) => return Err(e) } + Ok(value) } TypedAstNodeKind.StringInterpolation(exprs) => { self._currentFn.block.addComment("begin string interpolation...") @@ -796,19 +764,18 @@ export type Compiler { return Ok(newString) } - val vals = match self._compileBinaryOperands(left, right, "+") { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val res = match self._currentFn.block.buildAdd(vals[0], vals[1], resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } + val (lval, rval) = match self._compileBinaryOperands(left, right, "+") { Ok(v) => v, Err(e) => return Err(e) } + val res = match self._currentFn.block.buildAdd(lval, rval, resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } Ok(res) } BinaryOp.Sub => { - val vals = match self._compileBinaryOperands(left, right, "-") { Ok(v) => v, Err(e) => return Err(e) } - val res = match self._currentFn.block.buildSub(vals[0], vals[1], resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } + val (lval, rval) = match self._compileBinaryOperands(left, right, "-") { Ok(v) => v, Err(e) => return Err(e) } + val res = match self._currentFn.block.buildSub(lval, rval, resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } Ok(res) } BinaryOp.Mul => { - val vals = match self._compileBinaryOperands(left, right, "*") { Ok(v) => v, Err(e) => return Err(e) } - val res = match self._currentFn.block.buildMul(vals[0], vals[1], resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } + val (lval, rval) = match self._compileBinaryOperands(left, right, "*") { Ok(v) => v, Err(e) => return Err(e) } + val res = match self._currentFn.block.buildMul(lval, rval, resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } Ok(res) } BinaryOp.Div => { @@ -986,13 +953,13 @@ export type Compiler { BinaryOp.Eq => self._compileBinaryEq(left, right) BinaryOp.Neq => self._compileBinaryEq(left: left, right: right, negate: true) BinaryOp.LT => { - val vals = match self._compileBinaryOperands(left, right, "<") { Ok(v) => v, Err(e) => return Err(e) } - val res = match self._currentFn.block.buildCompareLt(vals[0], vals[1], resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } + val (lval, rval) = match self._compileBinaryOperands(left, right, "<") { Ok(v) => v, Err(e) => return Err(e) } + val res = match self._currentFn.block.buildCompareLt(lval, rval, resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } Ok(self._currentFn.block.buildExt(res, false)) } BinaryOp.LTE => { - val vals = match self._compileBinaryOperands(left, right, "<=") { Ok(v) => v, Err(e) => return Err(e) } - val res = match self._currentFn.block.buildCompareLte(vals[0], vals[1], resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } + val (lval, rval) = match self._compileBinaryOperands(left, right, "<=") { Ok(v) => v, Err(e) => return Err(e) } + val res = match self._currentFn.block.buildCompareLte(lval, rval, resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } Ok(self._currentFn.block.buildExt(res, false)) } BinaryOp.Shl => { @@ -1003,13 +970,13 @@ export type Compiler { Ok(res) } BinaryOp.GT => { - val vals = match self._compileBinaryOperands(left, right, ">") { Ok(v) => v, Err(e) => return Err(e) } - val res = match self._currentFn.block.buildCompareGt(vals[0], vals[1], resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } + val (lval, rval) = match self._compileBinaryOperands(left, right, ">") { Ok(v) => v, Err(e) => return Err(e) } + val res = match self._currentFn.block.buildCompareGt(lval, rval, resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } Ok(self._currentFn.block.buildExt(res, false)) } BinaryOp.GTE => { - val vals = match self._compileBinaryOperands(left, right, ">=") { Ok(v) => v, Err(e) => return Err(e) } - val res = match self._currentFn.block.buildCompareGte(vals[0], vals[1], resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } + val (lval, rval) = match self._compileBinaryOperands(left, right, ">=") { Ok(v) => v, Err(e) => return Err(e) } + val res = match self._currentFn.block.buildCompareGte(lval, rval, resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } Ok(self._currentFn.block.buildExt(res, false)) } BinaryOp.Shr => { @@ -1091,7 +1058,7 @@ export type Compiler { var closureEnvCtx: (Value, Bool)? = None var closureSelfCtx: Value? = None - val _p = match invokee { + val (fnVal, argMetadata) = match invokee { TypedInvokee.Function(fn) => { match self._resolvedGenerics.addLayer(fn.label.name, resolvedGenerics) { Ok => {}, Err(e) => return Err(CompileError(position: node.token.position, kind: CompileErrorKind.ResolvedGenericsError(context: fn.label.name, message: e))) } @@ -1249,19 +1216,14 @@ export type Compiler { (Callable.Value(fnValPtr, retTypeQbe), []) } } - // TODO: destructuring - val fnVal = _p[0] - val argMetadata = _p[1] var defaultValueParamIdx = -1 var defaultValueFlags = 0 for arg, idx in arguments { - var argHasDefaultValue = false - var argTy: Type? = None - if argMetadata[idx] |_m| { - // TODO: destructuring - argHasDefaultValue = _m[0] - argTy = Some(_m[1]) + var (argHasDefaultValue, argTy) = if argMetadata[idx] |(argHasDefaultValue, ty)| { + (argHasDefaultValue, Some(ty)) + } else { + (false, None) } if argHasDefaultValue { @@ -1287,11 +1249,8 @@ export type Compiler { // TODO: yikes... var res = if fnVal.returnType() { - if closureEnvCtx |_ctx| { - // TODO: destructuring - val closureEnvPtr = _ctx[0] - val needsNullCheck = _ctx[1] - val res = if needsNullCheck { + if closureEnvCtx |(closureEnvPtr, needsNullCheck)| { + if needsNullCheck { val labelCallWithEnv = self._currentFn.block.addLabel("call_fn_val_with_env") val labelCallWithoutEnv = self._currentFn.block.addLabel("call_fn_val_without_env") val labelCont = self._currentFn.block.addLabel("call_fn_val_cont") @@ -1319,11 +1278,9 @@ export type Compiler { self._currentFn.block.registerLabel(labelCont) val phiCases = [(resWithSelfLabel, resWithSelf), (resWithoutSelfLabel, resWithoutSelf)] - val res = match self._currentFn.block.buildPhi(phiCases) { Ok(v) => v, Err(e) => return qbeError(e) } - res + match self._currentFn.block.buildPhi(phiCases) { Ok(v) => v, Err(e) => return qbeError(e) } } else { - val res = match self._currentFn.block.buildCall(fnVal, args, resultLocalName, Some(closureEnvPtr)) { Ok(v) => v, Err(e) => return qbeError(e) } - res + match self._currentFn.block.buildCall(fnVal, args, resultLocalName, Some(closureEnvPtr)) { Ok(v) => v, Err(e) => return qbeError(e) } } val resWithEnvLabel = self._currentFn.block.currentLabel self._currentFn.block.buildJmp(labelCont) @@ -1349,11 +1306,9 @@ export type Compiler { self._currentFn.block.registerLabel(labelCont) val phiCases = [(resWithSelfLabel, resWithSelf), (resWithoutSelfLabel, resWithoutSelf)] - val res = match self._currentFn.block.buildPhi(phiCases) { Ok(v) => v, Err(e) => return qbeError(e) } - res + match self._currentFn.block.buildPhi(phiCases) { Ok(v) => v, Err(e) => return qbeError(e) } } else { - val res = match self._currentFn.block.buildCall(fnVal, args, resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } - res + match self._currentFn.block.buildCall(fnVal, args, resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } } val resWithoutEnvLabel = self._currentFn.block.currentLabel self._currentFn.block.buildJmp(labelCont) @@ -1362,22 +1317,15 @@ export type Compiler { val phiCases = [(resWithEnvLabel, resWithEnv), (resWithoutEnvLabel, resWithoutEnv)] - val res = match self._currentFn.block.buildPhi(phiCases) { Ok(v) => v, Err(e) => return qbeError(e) } - res + match self._currentFn.block.buildPhi(phiCases) { Ok(v) => v, Err(e) => return qbeError(e) } } else { - val res = match self._currentFn.block.buildCall(fnVal, args, resultLocalName, Some(closureEnvPtr)) { Ok(v) => v, Err(e) => return qbeError(e) } - res + match self._currentFn.block.buildCall(fnVal, args, resultLocalName, Some(closureEnvPtr)) { Ok(v) => v, Err(e) => return qbeError(e) } } - res } else { - val res = match self._currentFn.block.buildCall(fnVal, args, resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } - res + match self._currentFn.block.buildCall(fnVal, args, resultLocalName) { Ok(v) => v, Err(e) => return qbeError(e) } } } else { - if closureEnvCtx |_ctx| { - // TODO: destructuring - val closureEnvPtr = _ctx[0] - val needsNullCheck = _ctx[1] + if closureEnvCtx |(closureEnvPtr, needsNullCheck)| { if needsNullCheck { val labelCallWithEnv = self._currentFn.block.addLabel("call_fn_val_with_env") val labelCallWithoutEnv = self._currentFn.block.addLabel("call_fn_val_without_env") @@ -1458,12 +1406,7 @@ export type Compiler { Value.Ident("bogus", QbeType.F32) } - if optSafeCtx |_ctx| { - val labelIsNone = _ctx[0] - val noneRes = _ctx[1] - val someVariantFn = _ctx[2] - val labelCont = _ctx[3] - + if optSafeCtx |(labelIsNone, noneRes, someVariantFn, labelCont)| { val labelIsSome = if noneRes |noneRes| { val labelIsSome = self._currentFn.block.currentLabel val someRes = match self._currentFn.block.buildCall(Callable.Function(someVariantFn), [res]) { Ok(v) => v, Err(e) => return qbeError(e) } @@ -1474,11 +1417,7 @@ export type Compiler { self._currentFn.block.addComment("...opt-safe call end") self._currentFn.block.registerLabel(labelCont) - if labelIsSome |_p| { - // TODO: destructuring - val labelIsSome = _p[0] - val someRes = _p[1] - val noneRes = _p[2] + if labelIsSome |(labelIsSome, someRes, noneRes)| { val phiCases = [(labelIsNone, noneRes), (labelIsSome, someRes)] res = match self._currentFn.block.buildPhi(phiCases) { Ok(v) => v, Err(e) => return qbeError(e) } } @@ -1561,9 +1500,9 @@ export type Compiler { val mapInsertFn = if self._project.preludeMapStruct.instanceMethods.find(m => m.label.name == "insert") |fn| fn else return unreachable("Map#insert must exist") val mapInsertFnVal = match self._getOrCompileMethod(node.ty, mapInsertFn) { Ok(v) => v, Err(e) => return Err(e) } - for _item in items { - val keyVal = match self._compileExpression(_item[0]) { Ok(v) => v, Err(e) => return Err(e) } - val valueVal = match self._compileExpression(_item[1]) { Ok(v) => v, Err(e) => return Err(e) } + for (keyExpr, valExpr) in items { + val keyVal = match self._compileExpression(keyExpr) { Ok(v) => v, Err(e) => return Err(e) } + val valueVal = match self._compileExpression(valExpr) { Ok(v) => v, Err(e) => return Err(e) } match self._currentFn.block.buildCall(Callable.Function(mapInsertFnVal), [mapInstance, keyVal, valueVal]) { Ok(v) => v, Err(e) => return qbeError(e) } } @@ -1577,8 +1516,8 @@ export type Compiler { val resolvedGenerics: Map = {} val template = Type(kind: TypeKind.Instance(StructOrEnum.Struct(tupleStruct), tupleStruct.typeParams.map(name => Type(kind: TypeKind.Generic(name))))) - for _p in selfType.extractGenerics(template) { - resolvedGenerics[_p[0]] = _p[1] + for (name, ty) in selfType.extractGenerics(template) { + resolvedGenerics[name] = ty } match self._resolvedGenerics.addLayer(tupleStruct.label.name, resolvedGenerics) { Ok => {}, Err(e) => return Err(CompileError(position: node.token.position, kind: CompileErrorKind.ResolvedGenericsError(context: tupleStruct.label.name, message: e))) } val fnVal = match self._getOrCompileStructInitializer(tupleStruct) { Ok(v) => v, Err(e) => return Err(e) } @@ -1604,9 +1543,8 @@ export type Compiler { val idxExprVal = match self._compileExpression(idxExpr) { Ok(v) => v, Err(e) => return Err(e) } val instType = match self._addResolvedGenericsLayerForInstanceMethod(expr.ty, "get", expr.token.position) { Ok(v) => v, Err(e) => return Err(e) } - val _t = match self._getInstanceTypeForType(expr.ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val getFn = match _t[0] { + val (structOrEnum, _) = match self._getInstanceTypeForType(expr.ty) { Ok(v) => v, Err(e) => return Err(e) } + val getFn = match structOrEnum { StructOrEnum.Struct(struct) => if struct.instanceMethods.find(m => m.label.name == "get") |fn| fn else return unreachable("#get must exist for array-like indexing") StructOrEnum.Enum => return unreachable("array-like indexing never applies to enum instances") } @@ -1634,9 +1572,8 @@ export type Compiler { } val instType = match self._addResolvedGenericsLayerForInstanceMethod(expr.ty, "getRange", expr.token.position) { Ok(v) => v, Err(e) => return Err(e) } - val _t = match self._getInstanceTypeForType(expr.ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val getRangeFn = match _t[0] { + val (structOrEnum, _) = match self._getInstanceTypeForType(expr.ty) { Ok(v) => v, Err(e) => return Err(e) } + val getRangeFn = match structOrEnum { StructOrEnum.Struct(struct) => if struct.instanceMethods.find(m => m.label.name == "getRange") |fn| fn else return unreachable("#getRange must exist for array-like indexing") StructOrEnum.Enum => return unreachable("array-like indexing never applies to enum instances") } @@ -1653,9 +1590,8 @@ export type Compiler { val idxExprVal = match self._compileExpression(idxExpr) { Ok(v) => v, Err(e) => return Err(e) } val instType = match self._addResolvedGenericsLayerForInstanceMethod(expr.ty, "get", expr.token.position) { Ok(v) => v, Err(e) => return Err(e) } - val _t = match self._getInstanceTypeForType(expr.ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val struct = match _t[0] { + val (structOrEnum, _) = match self._getInstanceTypeForType(expr.ty) { Ok(v) => v, Err(e) => return Err(e) } + val struct = match structOrEnum { StructOrEnum.Struct(struct) => struct StructOrEnum.Enum => return unreachable("map indexing never applies to enum instances") } @@ -1671,19 +1607,18 @@ export type Compiler { TypedIndexingNode.Tuple(tupleExpr, idx) => { val exprVal = match self._compileExpression(tupleExpr) { Ok(v) => v, Err(e) => return Err(e) } - val _t = match self._getInstanceTypeForType(tupleExpr.ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val struct = match _t[0] { + val (structOrEnum, typeArgs) = match self._getInstanceTypeForType(tupleExpr.ty) { Ok(v) => v, Err(e) => return Err(e) } + val struct = match structOrEnum { StructOrEnum.Struct(struct) => struct StructOrEnum.Enum => return unreachable("tuples are represented as structs") } - val selfType = Type(kind: TypeKind.Instance(StructOrEnum.Struct(struct), _t[1])) + val selfType = Type(kind: TypeKind.Instance(StructOrEnum.Struct(struct), typeArgs)) val resolvedGenerics: Map = {} val template = Type(kind: TypeKind.Instance(StructOrEnum.Struct(struct), struct.typeParams.map(name => Type(kind: TypeKind.Generic(name))))) - for _p in selfType.extractGenerics(template) { - resolvedGenerics[_p[0]] = _p[1] + for (name, ty) in selfType.extractGenerics(template) { + resolvedGenerics[name] = ty } match self._resolvedGenerics.addLayer(struct.label.name, resolvedGenerics) { Ok => {}, Err(e) => return Err(CompileError(position: node.token.position, kind: CompileErrorKind.ResolvedGenericsError(context: struct.label.name, message: e))) } @@ -1744,10 +1679,7 @@ export type Compiler { val phiCases: (Label, Value)[] = [] self._currentFn.block.registerLabel(labelThen) - if conditionBinding |_p| { - // TODO: destructuring - val bindingPattern = _p[0] - val vars = _p[1] + if conditionBinding |(bindingPattern, vars)| { val variables = vars.keyBy(v => v.label.name) val bindingVal = if condExprIsOpt |innerTy| { @@ -1843,11 +1775,11 @@ export type Compiler { } else None for case, idx in cases { - val _p = match case.kind { + val (nextCaseLabel, exprVal, exprType) = match case.kind { TypedMatchCaseKind.Literal(lit) => { val nextCaseLabel = self._currentFn.block.addLabel("${matchLabelPrefix}_case_${idx}__next") - val _e = if exprTypeIsOpt |innerTy| { + val (exprVal, exprType) = if exprTypeIsOpt |innerTy| { val innerQbeType = match self._getQbeTypeForTypeExpect(innerTy, "unacceptable type", None) { Ok(v) => v, Err(e) => return Err(e) } if seenNoneCase { val optInnerValue = match self._emitOptValueGetValue(innerQbeType, exprVal) { Ok(v) => v, Err(e) => return Err(e) } @@ -1863,14 +1795,8 @@ export type Compiler { } else { (exprVal, expr.ty) } - // TODO: destructuring - val exprVal = _e[0] - val exprType = _e[1] - val _p = match self._compileLiteral(lit) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val litVal = _p[0] - val litType = _p[1] + val (litVal, litType) = match self._compileLiteral(lit) { Ok(v) => v, Err(e) => return Err(e) } if !self._project.typesAreEquivalent(exprType, litType) return unreachable("equality operators require matching types", node.token.position) @@ -1896,7 +1822,7 @@ export type Compiler { } TypedMatchCaseKind.EnumVariant(enum_, variant, variantIdx, destructuredVariables) => { val nextCaseLabel = self._currentFn.block.addLabel("${matchLabelPrefix}_case_${idx}__next") - val _e = if exprTypeIsOpt |innerTy| { + val (exprVal, exprType) = if exprTypeIsOpt |innerTy| { val innerQbeType = match self._getQbeTypeForTypeExpect(innerTy, "unacceptable type", None) { Ok(v) => v, Err(e) => return Err(e) } if seenNoneCase { val optInnerValue = match self._emitOptValueGetValue(innerQbeType, exprVal) { Ok(v) => v, Err(e) => return Err(e) } @@ -1912,9 +1838,6 @@ export type Compiler { } else { (exprVal, expr.ty) } - // TODO: destructuring - val exprVal = _e[0] - val exprType = _e[1] val exprValVariantIdxVal = self._emitGetEnumVariantIdx(exprVal) val cond = match self._currentFn.block.buildCompareEq(exprValVariantIdxVal, Value.Int(variantIdx)) { Ok(v) => v, Err(e) => return qbeError(e) } @@ -1952,26 +1875,22 @@ export type Compiler { (Some(nextCaseLabel), exprVal, exprType) } TypedMatchCaseKind.Else => { - val _e = if exprTypeIsOpt |innerTy| { + val (exprVal, exprType) = if exprTypeIsOpt |innerTy| { if seenNoneCase { val innerQbeType = match self._getQbeTypeForTypeExpect(innerTy, "unacceptable type", None) { Ok(v) => v, Err(e) => return Err(e) } val optInnerValue = match self._emitOptValueGetValue(innerQbeType, exprVal) { Ok(v) => v, Err(e) => return Err(e) } (optInnerValue, innerTy) - } else (exprVal, expr.ty) + } else { + (exprVal, expr.ty) + } } else (exprVal, expr.ty) - val exprVal = _e[0] - val exprType = _e[1] // No nextCaseLabel, since the `else` case will always be the last case if present (None, exprVal, exprType) } _ => return todo("other match case types", node.token.position) } - // TODO: destructuring - val nextCaseLabel = _p[0] - val exprVal = _p[1] - val exprType = _p[2] if case.binding |v| { val slotName = self._currentFn.block.addVar(variableToVar(v)) @@ -1983,11 +1902,8 @@ export type Compiler { for node, idx in case.body { val res = match self._compileStatement(node) { Ok(v) => v, Err(e) => return Err(e) } if idx == case.body.length - 1 { - if resValSlotCtx |_p| { + if resValSlotCtx |(slot, slotTy)| { if res |res| { - // TODO: destructuring - val slot = _p[0] - val slotTy = _p[1] self._currentFn.block.buildStore(slotTy, res, slot) } } @@ -2004,9 +1920,7 @@ export type Compiler { self._currentFn.block.registerLabel(endLabel) - val result = if resValSlotCtx |_p| { - val slot = _p[0] - val slotTy = _p[1] + val result = if resValSlotCtx |(slot, slotTy)| { val res = self._currentFn.block.buildLoad(slotTy, slot) Some(res) } else { @@ -2159,10 +2073,7 @@ export type Compiler { val res = if !fnInvocationIsAtDeclaredScope { val currentFunc = if self._currentFunction |currentFn| currentFn else return unreachable("we must be within a function to enter this case", fn.label.position) - val _p = if currentFunc.capturedClosures.findIndex(f => f.label.name == fn.label.name) |_p| _p else return unreachable("closure '${fn.label.name}' called within function '${currentFunc.label.name}', but not tracked in its capturedClosures", fn.label.position) - // TODO: destructuring - val idx = _p[1] - + val idx = if currentFunc.capturedClosures.findIndex(f => f.label.name == fn.label.name) |(_, idx)| idx else return unreachable("closure '${fn.label.name}' called within function '${currentFunc.label.name}', but not tracked in its capturedClosures", fn.label.position) val env = if self._currentFn._env |env| env else return unreachable("expected currentFn ('${self._currentFn.name}') to have an `_env`, but it didn't") val offset = QbeType.Pointer.size() * (currentFunc.captures.length + idx) @@ -2172,14 +2083,13 @@ export type Compiler { // If the closure is being called in the same scope in which it was declared, then the `*.captures` value is visible as a stack local. val prefix = match fn.kind { FunctionKind.InstanceMethod(structOrEnum) => { - val v = if structOrEnum |structOrEnum| { + if structOrEnum |structOrEnum| { val typeName = match structOrEnum { StructOrEnum.Struct(struct) => struct.label.name StructOrEnum.Enum(enum_) => enum_.label.name } "$typeName.." } else return unreachable("an instance method should have a structOrEnum", fn.label.position) - v } FunctionKind.StaticMethod(structOrEnum) => { val typeName = match structOrEnum { @@ -2262,16 +2172,12 @@ export type Compiler { ): Result { val closureEnvPtr = capturesPtr ?: Value.Int(0) - val _s = if capturedSelf |_p| { - val selfVal = _p[0] - val selfTy = match self._getQbeTypeForTypeExpect(_p[1], "unacceptable type for param", Some(position)) { Ok(v) => v, Err(e) => return Err(e) } + val (selfVal, selfTy) = if capturedSelf |(selfVal, selfType)| { + val selfTy = match self._getQbeTypeForTypeExpect(selfType, "unacceptable type for param", Some(position)) { Ok(v) => v, Err(e) => return Err(e) } (selfVal, Some(selfTy)) } else { (Value.Int(0), None) } - // TODO: destructuring - val selfVal = _s[0] - val selfTy = _s[1] val numParams = fn.params.length var fnNumReqParams = 0 @@ -2399,8 +2305,8 @@ export type Compiler { val resolvedGenerics: Map = {} val template = Type(kind: TypeKind.Instance(StructOrEnum.Struct(struct), struct.typeParams.map(name => Type(kind: TypeKind.Generic(name))))) - for _p in selfType.extractGenerics(template) { - resolvedGenerics[_p[0]] = _p[1] + for (name, ty) in selfType.extractGenerics(template) { + resolvedGenerics[name] = ty } match self._resolvedGenerics.addLayer(struct.label.name, resolvedGenerics) { Ok => {}, Err(e) => return Err(CompileError(position: position, kind: CompileErrorKind.ResolvedGenericsError(context: struct.label.name, message: e))) } val initFnVal = match self._getOrCompileStructInitializer(struct) { Ok(v) => v, Err(e) => return Err(e) } @@ -2426,10 +2332,7 @@ export type Compiler { val discardedParamTypeReprs: String[] = [] for paramTy, idx in fnValParamTypes[numParams:] { discardedParamTypeReprs.push(paramTy.repr()) - val _t = match self._getInstanceTypeForType(paramTy) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val instTy = _t[0] - val typeArgs = _t[1] + val (instTy, typeArgs) = match self._getInstanceTypeForType(paramTy) { Ok(v) => v, Err(e) => return Err(e) } val instType = Type(kind: TypeKind.Instance(instTy, typeArgs)) val resolvedGenerics: Map = {} @@ -2438,8 +2341,8 @@ export type Compiler { StructOrEnum.Enum(e) => e.typeParams } val template = Type(kind: TypeKind.Instance(instTy, typeParams.map(name => Type(kind: TypeKind.Generic(name))))) - for _p in instType.extractGenerics(template) { - resolvedGenerics[_p[0]] = _p[1] + for (name, ty) in instType.extractGenerics(template) { + resolvedGenerics[name] = ty } match self._resolvedGenerics.addLayer("discarded param $idx", resolvedGenerics) { Ok => {}, Err(e) => return Err(CompileError(position: position, kind: CompileErrorKind.ResolvedGenericsError(context: "discarded param $idx", message: e))) } @@ -2540,17 +2443,14 @@ export type Compiler { func _followAccessorPath(self, head: TypedAstNode, middle: AccessorPathSegment[], tail: AccessorPathSegment, loadFinal: Bool, localName: String? = None): Result { val segs = middle.concat([tail]) - // val bogusValue = (StructOrEnum.Struct(self._project.preludeBoolStruct), Type(kind: TypeKind.Instance(StructOrEnum.Struct(self._project.preludeBoolStruct), [])), Value.Ident("bogus", QbeType.F32)) var instTy = StructOrEnum.Struct(self._project.preludeBoolStruct) var instType = Type(kind: TypeKind.Instance(StructOrEnum.Struct(self._project.preludeBoolStruct), [])) var curVal = Value.Ident("bogus", QbeType.F32) match segs[0] { AccessorPathSegment.Field => { // TODO: assert that `head.ty` is a pointer type (attempting to do pointer arithmetic later on will fail otherwise) - val _t = match self._getInstanceTypeForType(head.ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - instTy = _t[0] - val typeArgs = _t[1] + val (_instTy, typeArgs) = match self._getInstanceTypeForType(head.ty) { Ok(v) => v, Err(e) => return Err(e) } + instTy = _instTy instType = Type(kind: TypeKind.Instance(instTy, typeArgs)) curVal = match self._compileExpression(head) { Ok(v) => v, Err(e) => return Err(e) } @@ -2560,10 +2460,8 @@ export type Compiler { match fn.kind { FunctionKind.InstanceMethod => { // TODO: assert that `head.ty` is a pointer type (attempting to do pointer arithmetic later on will fail otherwise) - val _t = match self._getInstanceTypeForType(head.ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - instTy = _t[0] - val typeArgs = _t[1] + val (_instTy, typeArgs) = match self._getInstanceTypeForType(head.ty) { Ok(v) => v, Err(e) => return Err(e) } + instTy = _instTy instType = Type(kind: TypeKind.Instance(instTy, typeArgs)) curVal = match self._compileExpression(head) { Ok(v) => v, Err(e) => return Err(e) } @@ -2627,9 +2525,8 @@ export type Compiler { val innerTy = if self._typeIsOption(ty) |innerTy| innerTy else return unreachable("an opt-safe field accessor needs to have an Option type as its lhs") val unwrappedInstType = if self._typeIsOption(instType) |innerTy| innerTy else return unreachable("an opt-safe field accessor needs to have an Option type as its lhs") instType = unwrappedInstType - val _t = match self._getInstanceTypeForType(unwrappedInstType) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - instTy = _t[0] + val (_instTy, _) = match self._getInstanceTypeForType(unwrappedInstType) { Ok(v) => v, Err(e) => return Err(e) } + instTy = _instTy val variantIsOptionSome = match self._emitOptValueIsSomeVariant(curVal) { Ok(v) => v, Err(e) => return Err(e) } val labelIsSome = self._currentFn.block.addLabel("optsafe_field_is_some") @@ -2692,12 +2589,7 @@ export type Compiler { StructOrEnum.Enum(_enum) => return todo("enum field accessor") } - if optSafeCtx |_ctx| { - val labelIsNone = _ctx[0] - val noneRes = _ctx[1] - val someVariantFn = _ctx[2] - val labelCont = _ctx[3] - + if optSafeCtx |(labelIsNone, noneRes, someVariantFn, labelCont)| { val labelIsSome = self._currentFn.block.currentLabel val someRes = match self._currentFn.block.buildCall(Callable.Function(someVariantFn), [curVal]) { Ok(v) => v, Err(e) => return qbeError(e) } self._currentFn.block.buildJmp(labelCont) @@ -2709,10 +2601,8 @@ export type Compiler { curVal = match self._currentFn.block.buildPhi(phiCases, localName) { Ok(v) => v, Err(e) => return qbeError(e) } } - val _t = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - instTy = _t[0] - val typeArgs = _t[1] + val (_instTy, typeArgs) = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } + instTy = _instTy instType = Type(kind: TypeKind.Instance(instTy, typeArgs)) } } @@ -2822,7 +2712,7 @@ export type Compiler { val memLocal = match fn.block.buildCall(Callable.Function(self._malloc), [Value.Int(size)], Some("enum_variant.mem")) { Ok(v) => v, Err(e) => return qbeError(e) } - val variantIdx = if enum_.variants.findIndex(v => v.label.name == variant.label.name) |_v| _v[1] else return unreachable("variant '${variant.label.name}' must exist") + val variantIdx = if enum_.variants.findIndex(v => v.label.name == variant.label.name) |(_, idx)| idx else return unreachable("variant '${variant.label.name}' must exist") fn.block.buildStoreW(Value.Int(variantIdx), memLocal) // Store variant idx at designated slot var offset = QbeType.U64.size() // begin inserting any fields after that variant idx slot @@ -3262,11 +3152,7 @@ export type Compiler { if isInstanceMethod && fn.label.name == "eq" && fn.isGenerated return self._getOrCompileEqMethod(selfType) if isInstanceMethod && fn.label.name == "hash" && fn.isGenerated return self._getOrCompileHashMethod(selfType) - val _t = match self._getInstanceTypeForType(selfType) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val selfTy = _t[0] - val _typeArgs = _t[1] - + val (selfTy, _) = match self._getInstanceTypeForType(selfType) { Ok(v) => v, Err(e) => return Err(e) } val methodName = match self._methodFnName(selfTy, fn) { Ok(v) => v, Err(e) => return Err(e) } if self._builder.getFunction(methodName) |fn| return Ok(fn) @@ -3355,12 +3241,8 @@ export type Compiler { } func _getOrCompileToStringMethod(self, ty: Type): Result { - val _t = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val selfTy = _t[0] - val typeArgs = _t[1] - - val _p = match selfTy { + val (selfTy, typeArgs) = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } + val (methodName, fn) = match selfTy { StructOrEnum.Struct(struct) => { if struct == self._project.preludeIntStruct return self._getOrCompileIntToStringMethod() if struct == self._project.preludeFloatStruct return self._getOrCompileFloatToStringMethod() @@ -3379,9 +3261,6 @@ export type Compiler { (match self._enumMethodFnName(enum_, fn) { Ok(v) => v, Err(e) => return Err(e) }, fn) } } - // TODO: destructuring - val methodName = _p[0] - val fn = _p[1] if self._builder.getFunction(methodName) |fn| return Ok(fn) if fn.isGenerated return self._compileGeneratedToStringMethod(ty, fn) @@ -3392,10 +3271,7 @@ export type Compiler { func _compileGeneratedToStringMethod(self, selfType: Type, fn: Function): Result { val stringTypeQbe = match self._getQbeTypeForTypeExpect(Type(kind: TypeKind.PrimitiveString), "string qbe type should exist") { Ok(v) => v, Err(e) => return Err(e) } - val _t = match self._getInstanceTypeForType(selfType) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val selfTy = _t[0] - val typeArgs = _t[1] + val (selfTy, typeArgs) = match self._getInstanceTypeForType(selfType) { Ok(v) => v, Err(e) => return Err(e) } val selfInstanceTy = Type(kind: TypeKind.Instance(selfTy, typeArgs)) val methodName = match self._methodFnName(selfTy, fn) { Ok(v) => v, Err(e) => return Err(e) } @@ -3493,12 +3369,7 @@ export type Compiler { val reprVals: (String, Value, Bool)[] = [] var offset = 0 - for _p, idx in data { - // TODO: destructuring - val itemName = _p[0] - val itemPosition = _p[1] - val itemType = _p[2] - + for (itemName, itemPosition, itemType), idx in data { // If the item label is meant to be output, account for the label as well as ':' and ' ' between the label and the value if !itemName.isEmpty() { len += (itemName.length + 2) } @@ -3540,12 +3411,7 @@ export type Compiler { self._currentFn.block.buildStoreB(Value.Int(40), cursor) cursor = match self._currentFn.block.buildAdd(cursor, Value.Int(1), Some("str_cursor")) { Ok(v) => v, Err(e) => return qbeError(e) } - for _p, idx in reprVals { - // TODO: destructuring - val fieldName = _p[0] - val strVal = _p[1] - val isString = _p[2] - + for (fieldName, strVal, isString), idx in reprVals { if !fieldName.isEmpty() { val fieldNameStr = self._builder.buildGlobalString(fieldName) self._currentFn.block.buildVoidCall(Callable.Function(self._memcpy), [cursor, fieldNameStr, Value.Int(fieldName.length)]) @@ -3712,12 +3578,8 @@ export type Compiler { } func _getOrCompileEqMethod(self, ty: Type): Result { - val _t = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val selfTy = _t[0] - val _typeArgs = _t[1] - - val _p = match selfTy { + val (selfTy, _) = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } + val (methodName, fn) = match selfTy { StructOrEnum.Struct(struct) => { val boolTypeQbe = match self._getQbeTypeForTypeExpect(Type(kind: TypeKind.PrimitiveBool), "bool qbe type should exist") { Ok(v) => v, Err(e) => return Err(e) } @@ -3799,9 +3661,6 @@ export type Compiler { (match self._enumMethodFnName(enum_, fn) { Ok(v) => v, Err(e) => return Err(e) }, fn) } } - // TODO: destructuring - val methodName = _p[0] - val fn = _p[1] if self._builder.getFunction(methodName) |fn| return Ok(fn) if fn.isGenerated return self._compileGeneratedEqMethod(ty, fn) @@ -3812,10 +3671,7 @@ export type Compiler { func _compileGeneratedEqMethod(self, selfType: Type, fn: Function): Result { val boolTypeQbe = match self._getQbeTypeForTypeExpect(Type(kind: TypeKind.PrimitiveBool), "bool qbe type should exist") { Ok(v) => v, Err(e) => return Err(e) } - val _t = match self._getInstanceTypeForType(selfType) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val selfTy = _t[0] - val typeArgs = _t[1] + val (selfTy, typeArgs) = match self._getInstanceTypeForType(selfType) { Ok(v) => v, Err(e) => return Err(e) } val selfInstanceTy = Type(kind: TypeKind.Instance(selfTy, typeArgs)) val methodName = match self._methodFnName(selfTy, fn) { Ok(v) => v, Err(e) => return Err(e) } @@ -3911,12 +3767,7 @@ export type Compiler { func _emitEqLogicForStructuredData(self, selfPtr: Value, otherPtr: Value, data: (String, Position, Type)[]): Result { var offset = 0 - for _p in data { - // TODO: destructuring - val itemName = _p[0] - val itemPosition = _p[1] - val itemType = _p[2] - + for (itemName, itemPosition, itemType) in data { val itemTy = match self._getQbeTypeForTypeExpect(itemType, "unacceptable type for item", Some(itemPosition)) { Ok(v) => v, Err(e) => return Err(e) } val selfMemCursor = match self._currentFn.block.buildAdd(Value.Int(offset), selfPtr, Some("self_mem_offset_$itemName")) { Ok(v) => v, Err(e) => return qbeError(e) } @@ -3946,12 +3797,8 @@ export type Compiler { } func _getOrCompileHashMethod(self, ty: Type): Result { - val _t = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val selfTy = _t[0] - val _typeArgs = _t[1] - - val _p = match selfTy { + val (selfTy, _) = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } + val (methodName, fn) = match selfTy { StructOrEnum.Struct(struct) => { val intTypeQbe = match self._getQbeTypeForTypeExpect(Type(kind: TypeKind.PrimitiveInt), "int qbe type should exist") { Ok(v) => v, Err(e) => return Err(e) } @@ -4029,9 +3876,6 @@ export type Compiler { (match self._enumMethodFnName(enum_, fn) { Ok(v) => v, Err(e) => return Err(e) }, fn) } } - // TODO: destructuring - val methodName = _p[0] - val fn = _p[1] if self._builder.getFunction(methodName) |fn| return Ok(fn) if fn.isGenerated return self._compileGeneratedHashMethod(ty, fn) @@ -4042,10 +3886,7 @@ export type Compiler { func _compileGeneratedHashMethod(self, selfType: Type, fn: Function): Result { val intTypeQbe = match self._getQbeTypeForTypeExpect(Type(kind: TypeKind.PrimitiveInt), "int qbe type should exist") { Ok(v) => v, Err(e) => return Err(e) } - val _t = match self._getInstanceTypeForType(selfType) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val selfTy = _t[0] - val typeArgs = _t[1] + val (selfTy, typeArgs) = match self._getInstanceTypeForType(selfType) { Ok(v) => v, Err(e) => return Err(e) } val selfInstanceTy = Type(kind: TypeKind.Instance(selfTy, typeArgs)) val methodName = match self._methodFnName(selfTy, fn) { Ok(v) => v, Err(e) => return Err(e) } @@ -4125,12 +3966,7 @@ export type Compiler { func _emitHashLogicForStructuredData(self, selfPtr: Value, data: (String, Position, Type)[]): Result { var retVal = Value.Int(1) var offset = 0 - for _p in data { - // TODO: destructuring - val itemName = _p[0] - val itemPosition = _p[1] - val itemType = _p[2] - + for (itemName, itemPosition, itemType) in data { val itemTy = match self._getQbeTypeForTypeExpect(itemType, "unacceptable type for item", Some(itemPosition)) { Ok(v) => v, Err(e) => return Err(e) } val memCursor = match self._currentFn.block.buildAdd(Value.Int(offset), selfPtr, Some("self_mem_offset_$itemName")) { Ok(v) => v, Err(e) => return qbeError(e) } @@ -4172,7 +4008,7 @@ export type Compiler { func _emitOptValueIsSomeVariant(self, exprVal: Value, negate = false): Result { val variantIdx = self._emitGetEnumVariantIdx(exprVal) - val optionSomeVariantIdx = if self._project.preludeOptionEnum.variants.findIndex(v => v.label.name == "Some") |_p| _p[1] else return unreachable("Option.Some must exist") + val optionSomeVariantIdx = if self._project.preludeOptionEnum.variants.findIndex(v => v.label.name == "Some") |(_, idx)| idx else return unreachable("Option.Some must exist") if negate { val res = match self._currentFn.block.buildCompareNeq(variantIdx, Value.Int(optionSomeVariantIdx)) { Ok(v) => v, Err(e) => return qbeError(e) } Ok(res) @@ -4190,29 +4026,25 @@ export type Compiler { } func _addResolvedGenericsLayerForInstanceMethod(self, ty: Type, methodName: String, position: Position, resolvedGenerics: Map = {}): Result { - val _t = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } - val _p = match _t[0] { + val (structOrEnum, typeArgs) = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } + val (template, selfInstanceType) = match structOrEnum { StructOrEnum.Struct(struct) => { - val template = Type(kind: TypeKind.Instance(_t[0], struct.typeParams.map(name => Type(kind: TypeKind.Generic(name))))) - val inst = Type(kind: TypeKind.Instance(_t[0], _t[1])) + val template = Type(kind: TypeKind.Instance(structOrEnum, struct.typeParams.map(name => Type(kind: TypeKind.Generic(name))))) + val inst = Type(kind: TypeKind.Instance(structOrEnum, typeArgs)) (template, inst) } StructOrEnum.Enum(enum_) => { - val template = Type(kind: TypeKind.Instance(_t[0], enum_.typeParams.map(name => Type(kind: TypeKind.Generic(name))))) - val inst = Type(kind: TypeKind.Instance(_t[0], _t[1])) + val template = Type(kind: TypeKind.Instance(structOrEnum, enum_.typeParams.map(name => Type(kind: TypeKind.Generic(name))))) + val inst = Type(kind: TypeKind.Instance(structOrEnum, typeArgs)) (template, inst) } } - // TODO: destructuring - val template = _p[0] - val selfInstanceType = _p[1] - for _p in selfInstanceType.extractGenerics(template) { - resolvedGenerics[_p[0]] = _p[1] + for (name, ty) in selfInstanceType.extractGenerics(template) { + resolvedGenerics[name] = ty } - // TODO: destructuring - val layerName = match _t[0] { + val layerName = match structOrEnum { StructOrEnum.Struct(struct) => "${struct.label.name}.$methodName" StructOrEnum.Enum(enum_) => "${enum_.label.name}.$methodName" } @@ -4222,15 +4054,15 @@ export type Compiler { } func _addResolvedGenericsLayerForEnumVariant(self, ty: Type, variantName: String, position: Position, resolvedGenerics: Map = {}): Result { - val _t = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } - match _t[0] { + val (structOrEnum, typeArgs) = match self._getInstanceTypeForType(ty) { Ok(v) => v, Err(e) => return Err(e) } + match structOrEnum { StructOrEnum.Struct => unreachable("type should always be an enum here") StructOrEnum.Enum(enum_) => { - val template = Type(kind: TypeKind.Instance(_t[0], enum_.typeParams.map(name => Type(kind: TypeKind.Generic(name))))) - val selfInstanceType = Type(kind: TypeKind.Instance(_t[0], _t[1])) + val template = Type(kind: TypeKind.Instance(structOrEnum, enum_.typeParams.map(name => Type(kind: TypeKind.Generic(name))))) + val selfInstanceType = Type(kind: TypeKind.Instance(structOrEnum, typeArgs)) - for _p in selfInstanceType.extractGenerics(template) { - resolvedGenerics[_p[0]] = _p[1] + for (name, ty) in selfInstanceType.extractGenerics(template) { + resolvedGenerics[name] = ty } val layerName = "${enum_.label.name}.$variantName" @@ -4391,8 +4223,7 @@ export type Compiler { val parts: String[] = [] for name in struct.typeParams { val repr = if self._resolvedGenerics.resolveGeneric(name) |ty| { - val r = match self._getNameForType(ty) { Ok(v) => v, Err(e) => return Err(e) } - r + match self._getNameForType(ty) { Ok(v) => v, Err(e) => return Err(e) } } else { return unreachable("could not resolve '$name'") } @@ -4429,8 +4260,7 @@ export type Compiler { val parts: String[] = [] for name in enum_.typeParams { val repr = if self._resolvedGenerics.resolveGeneric(name) |ty| { - val r = match self._getNameForType(ty) { Ok(v) => v, Err(e) => return Err(e) } - r + match self._getNameForType(ty) { Ok(v) => v, Err(e) => return Err(e) } } else { return unreachable("could not resolve '$name'") } @@ -4523,9 +4353,8 @@ export type Compiler { parts.push(fn.label.name) if !fn.typeParams.isEmpty() { parts.push("<") - for _p, idx in fn.typeParams { - // TODO: destructuring - val name = _p[1].name + for (_, typeParamLabel), idx in fn.typeParams { + val name = typeParamLabel.name val resolvedGeneric = if self._resolvedGenerics.resolveGeneric(name) |ty| ty else return unreachable("_fnSignature:fn, could not resolve generic '$name'") parts.push(resolvedGeneric.repr()) diff --git a/selfhost/src/lexer.abra b/selfhost/src/lexer.abra index 2ec94d85..47820c18 100644 --- a/selfhost/src/lexer.abra +++ b/selfhost/src/lexer.abra @@ -326,10 +326,10 @@ export type Lexer { func _multiCharToken(self, default: TokenKind, cases: (String, TokenKind)[]): TokenKind { val peekCursor = self._cursor + 1 - for case in cases { - if self._input[peekCursor:(peekCursor + case[0].length)] == case[0] { - self._advance(by: case[0].length) - return case[1] + for (str, tokenKind) in cases { + if self._input[peekCursor:(peekCursor + str.length)] == str { + self._advance(by: str.length) + return tokenKind } } diff --git a/selfhost/src/parser.abra b/selfhost/src/parser.abra index a9560a57..d91a2903 100644 --- a/selfhost/src/parser.abra +++ b/selfhost/src/parser.abra @@ -751,10 +751,7 @@ export type Parser { } } - val tuple = match self._parseBodyForTypeOrEnum() { Ok(v) => v, Err(e) => return Err(e) } - val methods = tuple[0] - val types = tuple[1] - val enums = tuple[2] + val (methods, types, enums) = match self._parseBodyForTypeOrEnum() { Ok(v) => v, Err(e) => return Err(e) } match self._expectNextTokenKind(TokenKind.RBrace) { Ok(v) => v, Err(e) => return Err(e) } @@ -831,10 +828,7 @@ export type Parser { variants.push(variant) } - val tuple = match self._parseBodyForTypeOrEnum() { Ok(v) => v, Err(e) => return Err(e) } - val methods = tuple[0] - val types = tuple[1] - val enums = tuple[2] + val (methods, types, enums) = match self._parseBodyForTypeOrEnum() { Ok(v) => v, Err(e) => return Err(e) } match self._expectNextTokenKind(TokenKind.RBrace) { Ok(v) => v, Err(e) => return Err(e) } diff --git a/selfhost/src/qbe.abra b/selfhost/src/qbe.abra index e906a1c6..68662f95 100644 --- a/selfhost/src/qbe.abra +++ b/selfhost/src/qbe.abra @@ -79,10 +79,7 @@ export enum QbeDataKind { file.write("z $size") } QbeDataKind.Constants(values) => { - for _p, idx in values { - val ty = _p[0] - val v = _p[1] - + for (ty, v), idx in values { file.write(ty.repr()) file.write(" ") v.encode(file) @@ -642,11 +639,11 @@ export type Block { } func buildPhi(self, cases: (Label, Value)[], dst: String? = None): Result { - var ty = if cases[0] |_c| _c[1].ty() else return Err("phi requires at least 1 label") - for case in cases { - if ty != case[1].ty() return Err("phi case type mismatch: @${case[0].name} (type: ${case[1].ty()}) doesn't match previous (type: $ty)") + var ty = if cases[0] |(_, value)| value.ty() else return Err("phi requires at least 1 label") + for (label, value) in cases { + if ty != value.ty() return Err("phi case type mismatch: @${label.name} (type: ${value.ty()}) doesn't match previous (type: $ty)") - self._usedLabels.insert(case[0]) + self._usedLabels.insert(label) } val dest = dst ?: self._nextLocal() @@ -765,9 +762,9 @@ export type QbeFunction { env.encode(file) if !self._parameters.isEmpty() file.write(", ") } - for param, idx in self._parameters { - param[1].encode(file) - file.write(" %${param[0]}") + for (name, ty), idx in self._parameters { + ty.encode(file) + file.write(" %$name") if idx != self._parameters.length - 1 { file.write(", ") } @@ -1236,9 +1233,9 @@ enum Instruction { Instruction.Phi(dst, cases) => { dst.encode(file) file.write(" phi ") - for case, idx in cases { - file.write("@${case[0].name} ") - case[1].encode(file) + for (label, value), idx in cases { + file.write("@${label.name} ") + value.encode(file) if idx != cases.length - 1 { file.write(", ") diff --git a/selfhost/src/test_utils.abra b/selfhost/src/test_utils.abra index c4e11ce4..a4a11fcb 100644 --- a/selfhost/src/test_utils.abra +++ b/selfhost/src/test_utils.abra @@ -337,7 +337,7 @@ func printAstNodeKindAsJson(kind: AstNodeKind, indentLevelStart: Int, currentInd println("$startIndent{") match kind { AstNodeKind.Literal(literal) => { - val pair = match literal { + val (kind, value) = match literal { LiteralAstNode.Int(value) => ("int", value.toString()) LiteralAstNode.Float(value) => ("float", value.toString()) LiteralAstNode.Bool(value) => ("bool", value.toString()) @@ -345,8 +345,8 @@ func printAstNodeKindAsJson(kind: AstNodeKind, indentLevelStart: Int, currentInd } println("$fieldsIndent\"name\": \"literal\",") - println("$fieldsIndent\"type\": \"${pair[0]}\",") - println("$fieldsIndent\"value\": ${pair[1]}") + println("$fieldsIndent\"type\": \"$kind\",") + println("$fieldsIndent\"value\": $value") } AstNodeKind.StringInterpolation(exprs) => { println("$fieldsIndent\"name\": \"stringInterpolation\",") @@ -401,9 +401,7 @@ func printAstNodeKindAsJson(kind: AstNodeKind, indentLevelStart: Int, currentInd println(",\n$fieldsIndent\"path\": [") val pathIndent = " ".repeat(currentIndentLevel + 2) val pathsIndent = " ".repeat(currentIndentLevel + 3) - for seg, idx in accessorNode.path { - val dotToken = seg[0] - val label = seg[1] + for (dotToken, label), idx in accessorNode.path { print("$pathIndent{\n$pathsIndent\"dotToken\": ") printTokenAsJson(dotToken, 0, currentIndentLevel + 3) println(",\n$pathsIndent\"ident\": \"${label.name}\",") @@ -485,9 +483,7 @@ func printAstNodeKindAsJson(kind: AstNodeKind, indentLevelStart: Int, currentInd println("$fieldsIndent\"items\": []") } else { println("$fieldsIndent\"items\": [") - for item, idx in items { - val key = item[0] - val value = item[1] + for (key, value), idx in items { println("$fieldsIndent {") print("$fieldsIndent \"key\": ") printAstNodeAsJson(key, 0, currentIndentLevel + 3) @@ -664,15 +660,15 @@ func printAstNodeKindAsJson(kind: AstNodeKind, indentLevelStart: Int, currentInd } MatchCaseKind.Literal(literal) => { println("$fieldsIndent \"kind\": \"literal\",") - val pair = match literal { + val (kind, value) = match literal { LiteralAstNode.Int(value) => ("int", value.toString()) LiteralAstNode.Float(value) => ("float", value.toString()) LiteralAstNode.Bool(value) => ("bool", value.toString()) LiteralAstNode.String(value) => ("string", "\"$value\"") } - println("$fieldsIndent \"type\": \"${pair[0]}\",") - println("$fieldsIndent \"value\": ${pair[1]}") + println("$fieldsIndent \"type\": \"$kind\",") + println("$fieldsIndent \"value\": $value") } MatchCaseKind.Type(path, last, args) => { println("$fieldsIndent \"kind\": \"type\",") diff --git a/selfhost/src/typechecker.abra b/selfhost/src/typechecker.abra index f2e31d65..af41d2af 100644 --- a/selfhost/src/typechecker.abra +++ b/selfhost/src/typechecker.abra @@ -459,14 +459,13 @@ export type Type { func withSubstitutedGenerics(self, resolvedGenerics: Map, retainUnknown: Bool, genericsInScope: Set): Type { val resultType = match self.kind { TypeKind.Generic(name) => { - val t = if resolvedGenerics[name] |substitute| { + if resolvedGenerics[name] |substitute| { substitute } else if retainUnknown || genericsInScope.contains(name) { self } else { Type(kind: TypeKind.Hole) } - t } TypeKind.Instance(structOrEnum, typeArgs) => { val substTypeArgs = typeArgs.map(ty => ty.withSubstitutedGenerics(resolvedGenerics, retainUnknown, genericsInScope)) @@ -1492,10 +1491,7 @@ export type Typechecker { return Some(TypeError(position: label.position, kind: TypeErrorKind.DuplicateName(original: alias))) } } - for _p in importedModule.imports { - // TODO: destructuring - val name = _p[0] - val imp = _p[1] + for (name, imp) in importedModule.imports { if name == label.name { return Some(TypeError(position: label.position, kind: TypeErrorKind.DuplicateName(original: imp.label))) } @@ -1580,10 +1576,7 @@ export type Typechecker { } func _findModuleByAlias(self, name: String): Result<(TypedModule, Label)?, TypeError> { - for _m in self.currentModuleImports { - // TODO: destructuring - val importModulePath = _m[0] - val importedModule = _m[1] + for (importModulePath, importedModule) in self.currentModuleImports { if importedModule.aliases.find(a => a.name == name) |alias| { val mod = if self.project.modules[importModulePath] |m| m else return unreachable(alias.position, "unknown module") return Ok(Some((mod, alias))) @@ -1669,10 +1662,7 @@ export type Typechecker { } for importedModule in self.currentModuleImports.values() { - for _p in importedModule.imports { - // TODO: destructuring - val name = _p[0] - val imp = _p[1] + for (name, imp) in importedModule.imports { if name == label.name { match imp.kind { TypedImportKind.Type(structOrEnum, _) => { @@ -1698,10 +1688,7 @@ export type Typechecker { TypeIdentifier.Normal(label, typeArguments, path) => { if path[0] |firstSeg| { val _mod = match self._findModuleByAlias(firstSeg.name) { Ok(v) => v, Err(e) => return Err(e) } - val _m = if _mod |mod| mod else return Err(TypeError(position: firstSeg.position, kind: TypeErrorKind.UnknownName(firstSeg.name, "module"))) - // TODO: destructuring - val mod = _m[0] - val aliasLabel = _m[1] + val (mod, aliasLabel) = if _mod |mod| mod else return Err(TypeError(position: firstSeg.position, kind: TypeErrorKind.UnknownName(firstSeg.name, "module"))) if path[1] |seg| return todo(seg.position, "qualified type paths longer than 2") @@ -1799,34 +1786,22 @@ export type Typechecker { } else { last } - val _p = match ty.kind { + + match ty.kind { TypeKind.Type(structOrEnum) => { - val _p = match structOrEnum { + match structOrEnum { StructOrEnum.Enum(enum_) => { - val t = if enum_.variants.findIndex(v => v.label.name == label.name) |_p| { - // TODO: destructuring - Some((enum_, _p)) - } else { - return Err(TypeError(position: label.position, kind: TypeErrorKind.UnknownName(label.name, "type"))) + if enum_.variants.findIndex(v => v.label.name == label.name) |(variant, variantIdx)| { + return Ok(Either.Right((enum_, variant, variantIdx))) } - t } - _ => None + _ => {} } - _p } - _ => None + _ => {} } - if _p |_p| { - // TODO: destructuring - val enum_ = _p[0] - val variant = _p[1][0] - val variantIdx = _p[1][1] - Ok(Either.Right((enum_, variant, variantIdx))) - } else { - Err(TypeError(position: label.position, kind: TypeErrorKind.UnknownName(label.name, "type"))) - } + Err(TypeError(position: label.position, kind: TypeErrorKind.UnknownName(label.name, "type"))) } _ => { return todo(first.position, "module aliases") @@ -1880,13 +1855,8 @@ export type Typechecker { } } - for _m in self.currentModuleImports { - val name = _m[0] - val importedModule = _m[1] - for _p in importedModule.imports { - // TODO: destructuring - val importedName = _p[0] - val importedValue = _p[1] + for (name, importedModule) in self.currentModuleImports { + for (importedName, importedValue) in importedModule.imports { if importedName == ident { val v = match importedValue.kind { TypedImportKind.Variable(v) => { @@ -1997,8 +1967,8 @@ export type Typechecker { func _genericsInScope(self): Set { val genericsInScope: Set = #{} if self.currentFunction |fn| { - for _p in fn.typeParams { - match _p[0].kind { + for (ty, _) in fn.typeParams { + match ty.kind { TypeKind.Generic(name) => genericsInScope.insert(name) _ => { __assertUnreachable("typeParam.kind != TypeKind.Generic") @@ -2134,10 +2104,7 @@ export type Typechecker { mod.id = moduleId mod.rootScope = moduleScope - for _p in imports { - // TODO: destructuring - val typedImportModule = _p[0] - val importNode = _p[1] + for (typedImportModule, importNode) in imports { match self._typecheckImport(typedImportModule, importNode) { Ok(v) => v Err(e) => return Err(TypecheckerError(modulePath: modulePathAbs, kind: TypecheckerErrorKind.TypeError(e))) @@ -2361,10 +2328,7 @@ export type Typechecker { } val hint = paramHints[idx] - val _p = match self._typecheckFunctionParam(param, hint, allowSelf) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val typedParam = _p[0] - val needsRevisit = _p[1] + val (typedParam, needsRevisit) = match self._typecheckFunctionParam(param, hint, allowSelf) { Ok(v) => v, Err(e) => return Err(e) } val paramName = typedParam.label.name // This is a bit messy - if param is `self` then don't add here; it's already denoted as an instance method via its FunctionKind if paramName != "self" { fn.params.push(typedParam) } @@ -2401,10 +2365,7 @@ export type Typechecker { val defaultValueNode = if paramNode.defaultValue |n| n else return unreachable(param.label.position, "the only way a parameter needs revisiting is if it has a default value") val hint = paramHints[idx] - val _p = match self._typecheckFunctionParam(param: paramNode, typeHint: hint, allowSelf: allowSelf, isRevisit: true) { Ok(v) => v, Err(e) => return Err(e) } - // TODO: destructuring - val typedParam = _p[0] - val needsRevisit = _p[1] + val (typedParam, needsRevisit) = match self._typecheckFunctionParam(param: paramNode, typeHint: hint, allowSelf: allowSelf, isRevisit: true) { Ok(v) => v, Err(e) => return Err(e) } if needsRevisit return unreachable(param.label.position, "parameters should not need to be revisited more than once") fn.params[idx] = typedParam } @@ -2528,14 +2489,10 @@ export type Typechecker { func _typecheckMethodsPass2(self, structOrEnum: StructOrEnum, funcDeclNodes: FunctionDeclarationNode[]): Result, TypeError> { val allParamsNeedingRevisit: Map = {} - val _p = match structOrEnum { + val (scope, instanceMethods, staticMethods) = match structOrEnum { StructOrEnum.Struct(struct) => (struct.scope, struct.instanceMethods, struct.staticMethods) StructOrEnum.Enum(enum_) => (enum_.scope, enum_.instanceMethods, enum_.staticMethods) } - // TODO: destructuring - val scope = _p[0] - val instanceMethods = _p[1] - val staticMethods = _p[2] val selfInstanceType = match structOrEnum { StructOrEnum.Struct(struct) => { @@ -2830,10 +2787,7 @@ export type Typechecker { ImportKind.List(importNames) => { for imp in importNames { for importedModule in self.currentModuleImports.values() { - for _p in importedModule.imports { - // TODO: destructuring - val importedName = _p[0] - val importedValue = _p[1] + for (importedName, importedValue) in importedModule.imports { if importedName == imp.name { return Err(TypeError(position: imp.position, kind: TypeErrorKind.DuplicateName(original: importedValue.label))) } @@ -2929,46 +2883,35 @@ export type Typechecker { // --- Pass 2 for types, enums, and functions val structsPass2_1: (Struct, TypeDeclarationNode)[] = [] - for pair in structsPass1 { - val struct = pair[0] - val node = pair[1] + for (struct, node) in structsPass1 { match self._typecheckStructPass2_1(struct, node) { Ok(v) => v, Err(e) => return Err(e) } structsPass2_1.push((struct, node)) } val enumsPass2_1: (Enum, EnumDeclarationNode)[] = [] - for pair in enumsPass1 { - val enum_ = pair[0] - val node = pair[1] + for (enum_, node) in enumsPass1 { match self._typecheckEnumPass2_1(enum_, node) { Ok(v) => v, Err(e) => return Err(e) } enumsPass2_1.push((enum_, node)) } val structsPass2_2: (Struct, TypeDeclarationNode, Map)[] = [] - for pair in structsPass1 { - val struct = pair[0] - val node = pair[1] + for (struct, node) in structsPass1 { val toRevisit = match self._typecheckStructPass2_2(struct, node) { Ok(v) => v, Err(e) => return Err(e) } structsPass2_2.push((struct, node, toRevisit)) } val enumsPass2_2: (Enum, EnumDeclarationNode, Map)[] = [] - for pair in enumsPass2_1 { - val enum_ = pair[0] - val node = pair[1] + for (enum_, node) in enumsPass2_1 { val toRevisit = match self._typecheckEnumPass2_2(enum_, node) { Ok(v) => v, Err(e) => return Err(e) } enumsPass2_2.push((enum_, node, toRevisit)) } val functionsPass2: (Function, FunctionDeclarationNode, Int[])[] = [] - for fnPair in functionsPass1 { - val fn = fnPair[0] - val aliasVar = fnPair[1] - val node = fnPair[2] + for (fn, aliasVar, node) in functionsPass1 { val paramsNeedingRevisit = match self._typecheckFunctionPass2(fn: fn, allowSelf: false, params: node.params) { Ok(v) => v, Err(e) => return Err(e) } aliasVar.ty = fn.getType() @@ -2983,10 +2926,7 @@ export type Typechecker { for node in nodes { val res = match node.kind { AstNodeKind.FunctionDeclaration => { - val typedNode = if functionsIter.next() |pair| { - val fn = pair[0] - val fnDeclNode = pair[1] - val paramsNeedingRevisit = pair[2] + val typedNode = if functionsIter.next() |(fn, fnDeclNode, paramsNeedingRevisit)| { match self._typecheckFunctionPass3(fn: fn, allowSelf: false, params: fnDeclNode.params, body: fnDeclNode.body, paramsNeedingRevisit: paramsNeedingRevisit) { Ok(v) => v, Err(e) => return Err(e) } TypedAstNode(token: node.token, ty: Type(kind: TypeKind.PrimitiveUnit), kind: TypedAstNodeKind.FunctionDeclaration(fn)) } else { @@ -2997,11 +2937,7 @@ export type Typechecker { continue } AstNodeKind.TypeDeclaration => { - val typedNode = if structsIter.next() |pair| { - val struct = pair[0] - val typeDeclNode = pair[1] - val toRevisit = pair[2] - + val typedNode = if structsIter.next() |(struct, typeDeclNode, toRevisit)| { match self._typecheckStructPass3(struct, typeDeclNode, toRevisit) { Ok(v) => v, Err(e) => return Err(e) } TypedAstNode(token: node.token, ty: Type(kind: TypeKind.PrimitiveUnit), kind: TypedAstNodeKind.TypeDeclaration(struct)) } else { @@ -3012,11 +2948,7 @@ export type Typechecker { continue } AstNodeKind.EnumDeclaration => { - val typedNode = if enumsIter.next() |pair| { - val enum_ = pair[0] - val enumDeclNode = pair[1] - val toRevisit = pair[2] - + val typedNode = if enumsIter.next() |(enum_, enumDeclNode, toRevisit)| { match self._typecheckEnumPass3(enum_, enumDeclNode, toRevisit) { Ok(v) => v, Err(e) => return Err(e) } TypedAstNode(token: node.token, ty: Type(kind: TypeKind.PrimitiveUnit), kind: TypedAstNodeKind.EnumDeclaration(enum_)) } else { @@ -3102,7 +3034,7 @@ export type Typechecker { None } - val _pair = if node.expr |expr| { + val (expr, ty) = if node.expr |expr| { val typedExpr = match self._typecheckExpression(expr, annType) { Ok(v) => v, Err(e) => return Err(e) } val ty = if annType |annotatedType| { if !self._typeSatisfiesRequired(ty: typedExpr.ty, required: annotatedType) { @@ -3134,9 +3066,6 @@ export type Typechecker { } return Err(err) } - // TODO: destructuring - val expr = _pair[0] - val ty = _pair[1] val variables = match self._typecheckBindingPattern(isMutable, node.bindingPattern, ty) { Ok(v) => v, Err(e) => return Err(e) } for v in variables { @@ -3155,10 +3084,7 @@ export type Typechecker { AssignmentMode.Variable(name, varToken) => { val pos = varToken.position - val variable = if self._resolveIdentifier(name) |_v| { - // TODO: destructuring - val v = _v[0] - val modExportedFrom = _v[1] + val variable = if self._resolveIdentifier(name) |(v, modExportedFrom)| { if modExportedFrom return Err(TypeError(position: pos, kind: TypeErrorKind.IllegalAssignment(kind: "variable", name: name, reason: IllegalAssignmentReason.Import))) v @@ -3199,20 +3125,17 @@ export type Typechecker { } AssignmentMode.Accessor(accessorNode) => { val typedLhs = match self._typecheckAccessor(token, accessorNode, None) { Ok(v) => v, Err(e) => return Err(e) } - val _p = match typedLhs.kind { + val (mode, fieldLabel, field) = match typedLhs.kind { TypedAstNodeKind.Accessor(head, mid, tail) => { val t = match tail { AccessorPathSegment.EnumVariant(label, _, _, variant) => { return Err(TypeError(position: label.position, kind: TypeErrorKind.IllegalAssignment("enum variant", variant.label.name, IllegalAssignmentReason.EnumVariant))) } AccessorPathSegment.Method(label, fn, _, _) => { - val _p = match fn.kind { + val (kind, reason) = match fn.kind { FunctionKind.StaticMethod => ("static method", IllegalAssignmentReason.StaticMethod) _ => ("method", IllegalAssignmentReason.Method) } - // TODO: destructuring - val kind = _p[0] - val reason = _p[1] return Err(TypeError(position: label.position, kind: TypeErrorKind.IllegalAssignment(kind, fn.label.name, reason))) } @@ -3230,10 +3153,6 @@ export type Typechecker { } _ => return unreachable(typedLhs.token.position, "_typecheckAccessor returned unexpected TypedAstNodeKind") } - // TODO: destructuring - val mode = _p[0] - val fieldLabel = _p[1] - val field = _p[2] val typedExpr = match self._typecheckExpression(expr, Some(field.ty)) { Ok(v) => v, Err(e) => return Err(e) } if !self._typeSatisfiesRequired(ty: typedExpr.ty, required: field.ty) { @@ -3547,10 +3466,7 @@ export type Typechecker { val allCasesHandled: () => Bool = () => { if seenElseCase return true - for _p in seenEnumVariants { - // TODO: destructuring - val enum_ = _p[0] - val seenVariantIdxs = _p[1] + for (enum_, seenVariantIdxs) in seenEnumVariants { val enumVariantIdxs = enum_.variants.map((_, i) => i).asSet() if seenVariantIdxs == enumVariantIdxs { if self._typeIsOption(typedExpr.ty) { @@ -3607,10 +3523,8 @@ export type Typechecker { TypedMatchCaseKind.Type(caseTy) } Either.Right(_p) => { - // TODO: destructuring - val enum_ = _p[0] - val variant = _p[1] - val variantIdx = _p[2] + // TODO: destructuring in match cases + val (enum_, variant, variantIdx) = _p if seenEnumVariants[enum_] |seenVariants| { if seenVariants.contains(variantIdx) return Err(TypeError(position: case.position, kind: TypeErrorKind.DuplicateMatchCase)) seenVariants.insert(variantIdx) @@ -3622,8 +3536,8 @@ export type Typechecker { val template = Type(kind: TypeKind.Instance(StructOrEnum.Enum(enum_), enum_.typeParams.map(name => Type(kind: TypeKind.Generic(name))))) val extractedGenerics = subjectTy.extractGenerics(template: template) val resolvedGenerics: Map = {} - for _p in extractedGenerics { - resolvedGenerics[_p[0]] = _p[1] + for (name, ty) in extractedGenerics { + resolvedGenerics[name] = ty } val caseTy = template.withSubstitutedGenerics(resolvedGenerics: resolvedGenerics, retainUnknown: false, genericsInScope: #{}) @@ -3882,12 +3796,7 @@ export type Typechecker { val handleCases: ((TypeKind, TypeKind, TypeKind)[]) => Result = (cases) => { val left = match self._typecheckExpression(node.left, None) { Ok(v) => v, Err(e) => return Err(e) } val right = match self._typecheckExpression(node.right, None) { Ok(v) => v, Err(e) => return Err(e) } - for _case in cases { - // TODO: destructuring - val lTy = _case[0] - val rTy = _case[1] - val outTy = _case[2] - + for (lTy, rTy, outTy) in cases { if (lTy == TypeKind.Hole || self._typeSatisfiesRequired(ty: left.ty, required: Type(kind: lTy))) && ((rTy == TypeKind.Hole || self._typeSatisfiesRequired(ty: right.ty, required: Type(kind: rTy)))) { return Ok(TypedAstNode(token: token, ty: Type(kind: outTy), kind: TypedAstNodeKind.Binary(left, node.op, right))) @@ -3980,7 +3889,7 @@ export type Typechecker { } func _typecheckIdentifier(self, token: Token, kind: IdentifierKind, typeHint: Type?): Result { - val _p = match kind { + val ((variable, varImportMod), name, fnTypeHint) = match kind { IdentifierKind.Named(name) => { val resolvedIdentifier = if self._resolveIdentifier(name) |_v| _v else { if self.paramDefaultValueContext |ctx| { @@ -4029,12 +3938,6 @@ export type Typechecker { (resolvedIdentifier, "self", None) } } - // TODO: destructuring - val _v = _p[0] - val name = _p[1] - val fnTypeHint = _p[2] - val variable = _v[0] - val varImportMod = _v[1] Ok(TypedAstNode(token: token, ty: variable.ty, kind: TypedAstNodeKind.Identifier(name, variable, fnTypeHint, varImportMod))) } @@ -4069,7 +3972,7 @@ export type Typechecker { TypeKind.Never => None TypeKind.Generic => self._resolveAccessorPathSegmentAny(label, optSafe, typeHint) TypeKind.Instance(structOrEnum, generics) => { - val _p = match structOrEnum { + val (instanceMethods, typeParams) = match structOrEnum { StructOrEnum.Struct(struct) => { for field in struct.fields { if field.name.name == label.name { @@ -4089,9 +3992,6 @@ export type Typechecker { } StructOrEnum.Enum(enum_) => (enum_.instanceMethods, enum_.typeParams) } - // TODO: destructuring - val instanceMethods = _p[0] - val typeParams = _p[1] for fn in instanceMethods { if fn.label.name == label.name { @@ -4121,13 +4021,13 @@ export type Typechecker { val template = Type(kind: TypeKind.Instance(StructOrEnum.Enum(enum_), typeArgs)) val extractedGenerics = hint.extractGenerics(template: template) val resolvedGenerics: Map = {} - for _p in extractedGenerics { - resolvedGenerics[_p[0]] = _p[1] + for (name, ty) in extractedGenerics { + resolvedGenerics[name] = ty } template.withSubstitutedGenerics(resolvedGenerics: resolvedGenerics, retainUnknown: false, genericsInScope: #{}) } else { - val t = match variant.kind { + match variant.kind { EnumVariantKind.Container => { Type(kind: TypeKind.Instance(StructOrEnum.Enum(enum_), typeArgs)) } @@ -4135,7 +4035,6 @@ export type Typechecker { Type(kind: TypeKind.Instance(StructOrEnum.Enum(enum_), enum_.typeParams.map(() => Type(kind: TypeKind.Hole)))) } } - t } match variant.kind { @@ -4180,14 +4079,8 @@ export type Typechecker { _ => None } - val identifierNode = if _mod |_mod| { - // TODO: destructuring - val mod = _mod[0] - val aliasLabel = _mod[1] - - // TODO: destructuring - val dotTok = field[0] - val label = field[1] + val identifierNode = if _mod |(mod, aliasLabel)| { + val (dotTok, label) = field if dotTok.kind == TokenKind.QuestionDot return Err(TypeError(position: dotTok.position, kind: TypeErrorKind.UnnecessaryOptSafety)) val exportVar = match mod.exports[label.name] { @@ -4209,8 +4102,8 @@ export type Typechecker { func _typecheckAccessor(self, token: Token, node: AccessorAstNode, typeHint: Type?): Result { var accessorPath = node.path - val _firstSeg = if accessorPath[0] |p| p else return unreachable(token.position, "path should have at least 1 segment") - val maybeModuleAccessor = match self._resolveModuleAliasAccessor(node.root, _firstSeg) { Ok(v) => v, Err(e) => return Err(e) } + val firstSeg = if accessorPath[0] |p| p else return unreachable(token.position, "path should have at least 1 segment") + val maybeModuleAccessor = match self._resolveModuleAliasAccessor(node.root, firstSeg) { Ok(v) => v, Err(e) => return Err(e) } val typedRoot = if maybeModuleAccessor |n| { if accessorPath.length == 1 return Ok(n) @@ -4226,10 +4119,7 @@ export type Typechecker { val path: AccessorPathSegment[] = [] var ty = typedRoot.ty var seenOptSafeDot = false - for _p, idx in accessorPath { - // TODO: destructuring - val token = _p[0] - val label = _p[1] + for (token, label), idx in accessorPath { val isOptSafe = token.kind == TokenKind.QuestionDot seenOptSafeDot ||= isOptSafe val optInnerTy = self._typeIsOption(ty) @@ -4283,12 +4173,10 @@ export type Typechecker { TypeKind.Instance(structOrEnum, _) => { val seg = match structOrEnum { StructOrEnum.Struct(struct) => { - val seg = match self._resolveAccessorPathSegment(Type(kind: TypeKind.Type(StructOrEnum.Struct(struct))), label, typeHint) { Ok(v) => v, Err(e) => return Err(e) } - seg + match self._resolveAccessorPathSegment(Type(kind: TypeKind.Type(StructOrEnum.Struct(struct))), label, typeHint) { Ok(v) => v, Err(e) => return Err(e) } } StructOrEnum.Enum(enum_) => { - val seg = match self._resolveAccessorPathSegment(Type(kind: TypeKind.Type(StructOrEnum.Enum(enum_))), label, typeHint) { Ok(v) => v, Err(e) => return Err(e) } - seg + match self._resolveAccessorPathSegment(Type(kind: TypeKind.Type(StructOrEnum.Enum(enum_))), label, typeHint) { Ok(v) => v, Err(e) => return Err(e) } } } @@ -4370,13 +4258,10 @@ export type Typechecker { } func _typecheckInvocationOfExpression(self, token: Token, invokeeExpr: TypedAstNode, exprPos: Position, invocationNode: InvocationAstNode): Result { - val _pair = match invokeeExpr.ty.kind { + val (paramTypes, returnType) = match invokeeExpr.ty.kind { TypeKind.Func(paramTypes, returnType) => (paramTypes.map(p => p[0]), returnType) _ => return Err(TypeError(position: exprPos, kind: TypeErrorKind.IllegalCallableType(invokeeExpr.ty))) } - // TODO: destructuring - val paramTypes = _pair[0] - val returnType = _pair[1] if self.paramDefaultValueContext |ctx| { ctx.exprContainsFunctionCall = true @@ -4442,15 +4327,15 @@ export type Typechecker { if hint.kind != TypeKind.PrimitiveUnit && fn.returnType.containsGenerics() { val extractedGenerics = hint.extractGenerics(template: fn.returnType) - for _p in extractedGenerics { - if resolvedGenerics[_p[0]] |original| { - if original != _p[1] { + for (name, ty) in extractedGenerics { + if resolvedGenerics[name] |original| { + if original != ty { val returnType = fn.returnType.withSubstitutedGenerics(resolvedGenerics: resolvedGenerics, retainUnknown: false, genericsInScope: #{}) return Err(TypeError(position: invokee.token.position, kind: TypeErrorKind.TypeMismatch([hint], returnType))) } continue } - resolvedGenerics[_p[0]] = _p[1] + resolvedGenerics[name] = ty } } } @@ -4472,11 +4357,8 @@ export type Typechecker { val variadicArgs: TypedAstNode[] = [] var mostRecentLabeledOptionalParam: Label? = None val argumentsQueue = invocationNode.arguments.map((arg, idx) => (arg, idx, 0)) - for _a in argumentsQueue { - // TODO: destructuring - val arg = _a[0] - val idx = if variadicParam |p| p[1] else _a[1] - val numAttempts = _a[2] + for (arg, argIdx, numAttempts) in argumentsQueue { + val idx = if variadicParam |(_, idx)| idx else argIdx var param = if fn.params[idx] |param| param else { return Err(TypeError(position: arg.position(), kind: TypeErrorKind.WrongInvocationArity(expected: fn.params.length, given: invocationNode.arguments.length))) @@ -4512,36 +4394,36 @@ export type Typechecker { if param.isVariadic { variadicParam = Some((param, idx)) } } - val _p = if param.ty.containsGenerics() { + val (typedArg, paramType) = if param.ty.containsGenerics() { var paramType = paramTy.withSubstitutedGenerics(resolvedGenerics: resolvedGenerics, retainUnknown: false, genericsInScope: genericsInScope) val typedArg = match self._typecheckExpression(arg.value, Some(paramType)) { Ok(v) => v, Err(e) => return Err(e) } if numAttempts < 1 && typedArg.ty.hasUnfilledHoles() { - argumentsQueue.push((_a[0], _a[1], numAttempts + 1)) + argumentsQueue.push((arg, argIdx, numAttempts + 1)) continue } val extractedGenerics = typedArg.ty.extractGenerics(template: paramTy) - for _p in extractedGenerics { - if resolvedGenerics[_p[0]] |original| { + for (name, ty) in extractedGenerics { + if resolvedGenerics[name] |original| { match original.kind { TypeKind.Generic => { - resolvedGenerics[_p[0]] = _p[1] + resolvedGenerics[name] = ty continue } TypeKind.Hole => { - resolvedGenerics[_p[0]] = _p[1] + resolvedGenerics[name] = ty continue } _ => {} } - if !self.project.typesAreEquivalent(ty: original, other: _p[1]) { + if !self.project.typesAreEquivalent(ty: original, other: ty) { return Err(TypeError(position: typedArg.token.position, kind: TypeErrorKind.ParameterTypeMismatch(Some(param.label.name), original, typedArg.ty))) } continue } - resolvedGenerics[_p[0]] = _p[1] + resolvedGenerics[name] = ty } paramType = paramTy.withSubstitutedGenerics(resolvedGenerics: resolvedGenerics, retainUnknown: false, genericsInScope: genericsInScope) @@ -4550,9 +4432,6 @@ export type Typechecker { val typedArg = match self._typecheckExpression(arg.value, Some(paramTy)) { Ok(v) => v, Err(e) => return Err(e) } (typedArg, paramTy) } - // TODO: destructuring - val typedArg = _p[0] - val paramType = _p[1] if !self._typeSatisfiesRequired(ty: typedArg.ty, required: paramType) { return Err(TypeError(position: typedArg.token.position, kind: TypeErrorKind.ParameterTypeMismatch(Some(param.label.name), paramType, typedArg.ty))) } @@ -4564,8 +4443,7 @@ export type Typechecker { } } - if variadicParam |_p| { - val param = _p[0] + if variadicParam |(param, _)| { var innerType = param.ty.withSubstitutedGenerics(resolvedGenerics: resolvedGenerics, retainUnknown: false, genericsInScope: genericsInScope) val paramType = Type(kind: TypeKind.Instance(StructOrEnum.Struct(self.project.preludeArrayStruct), [innerType])) typedArgumentsByName[param.label.name] = TypedAstNode(token: token, ty: paramType, kind: TypedAstNodeKind.Array(variadicArgs)) @@ -4617,10 +4495,7 @@ export type Typechecker { Instantiatable.EnumContainerVariant(enum_, variant, _) => TypedInvokee.EnumVariant(enum_, variant) } v - } else if selfVal |_p| { - // TODO: destructuring - val selfVal = _p[0] - val isOptSafe = _p[1] + } else if selfVal |(selfVal, isOptSafe)| { TypedInvokee.Method(fn, selfVal, isOptSafe) } else { TypedInvokee.Function(fn) @@ -4721,10 +4596,7 @@ export type Typechecker { var keyTy: Type? = None var valTy: Type? = None if typeHint |hint| { - if self._typeAsInstance2(hint, self.project.preludeMapStruct) |_p| { - // TODO: destructuring - val keyHintTy = _p[0] - val valHintTy = _p[1] + if self._typeAsInstance2(hint, self.project.preludeMapStruct) |(keyHintTy, valHintTy)| { if keyHintTy.kind != TypeKind.Hole { keyTy = Some(keyHintTy) } @@ -4735,11 +4607,7 @@ export type Typechecker { } val typedItems: (TypedAstNode, TypedAstNode)[] = [] - for _p in items { - // TODO: destructuring - val keyNode = _p[0] - val valNode = _p[1] - + for (keyNode, valNode) in items { val typedKey = match keyNode.kind { AstNodeKind.Identifier(identKind) => match identKind { IdentifierKind.Named(name) => TypedAstNode(token: keyNode.token, ty: Type(kind: TypeKind.PrimitiveString), kind: TypedAstNodeKind.Literal(LiteralAstNode.String(name))) @@ -4785,11 +4653,7 @@ export type Typechecker { val keyTyHasUnfilledHoles = kTy.hasUnfilledHoles() val valTyHasUnfilledHoles = vTy.hasUnfilledHoles() - for _p in typedItems { - // TODO: destructuring - val typedKey = _p[0] - val typedVal = _p[1] - + for (typedKey, typedVal) in typedItems { if !keyTyHasUnfilledHoles && typedKey.ty.hasUnfilledHoles() { typedKey.ty.tryFillHoles(kTy) } if !valTyHasUnfilledHoles && typedVal.ty.hasUnfilledHoles() { typedVal.ty.tryFillHoles(vTy) } } @@ -4844,11 +4708,7 @@ export type Typechecker { if self._typeAsInstance1(typedExpr.ty, self.project.preludeArrayStruct) |inner| { val innerAsOpt = Type(kind: TypeKind.Instance(StructOrEnum.Enum(self.project.preludeOptionEnum), [inner])) self._typecheckIndexingArraylike(token: token, typedExpr: typedExpr, indexMode: indexMode, singleModeType: innerAsOpt, rangeModeType: typedExpr.ty) - } else if self._typeAsInstance2(typedExpr.ty, self.project.preludeMapStruct) |_p| { - // TODO: destructuring - val keyTy = _p[0] - val valTy = _p[1] - + } else if self._typeAsInstance2(typedExpr.ty, self.project.preludeMapStruct) |(keyTy, valTy)| { match indexMode { IndexingMode.Single(idxExpr) => { val typedIdxExpr = match self._typecheckExpression(idxExpr, Some(keyTy)) { Ok(v) => v, Err(e) => return Err(e) } @@ -4937,9 +4797,7 @@ export type Typechecker { if typeHint |hint| { match hint.kind { TypeKind.Func(paramTypes, retType) => { - for _p in paramTypes { - val ty = _p[0] - val isRequired = _p[1] + for (ty, isRequired) in paramTypes { if !isRequired return unreachable(token.position, "unexpected non-required param in lambda param type hint") paramHints.push(ty) diff --git a/selfhost/src/typechecker_test_utils.abra b/selfhost/src/typechecker_test_utils.abra index 5308c8b1..54ad0e35 100644 --- a/selfhost/src/typechecker_test_utils.abra +++ b/selfhost/src/typechecker_test_utils.abra @@ -43,14 +43,10 @@ export type Jsonifier { self.println("\"exports\": [") self.indentInc() - for _e, idx in mod.exports { + for (name, exp), idx in mod.exports { self.println("{") self.indentInc() - // TODO: Destructuring - val name = _e[0] - val exp = _e[1] - match exp { Export.Variable => self.println("\"kind\": \"variable\",") Export.Function => self.println("\"kind\": \"function\",") diff --git a/selfhost/test/run-tests.js b/selfhost/test/run-tests.js new file mode 100644 index 00000000..de51794c --- /dev/null +++ b/selfhost/test/run-tests.js @@ -0,0 +1,824 @@ +const { TestRunner, red, green, magenta } = require('./test-runner') + +const LEXER_TESTS = [ + // Ints + { test: "lexer/ints.abra", assertions: "lexer/ints.out.json" }, + { test: "lexer/ints_error_leading_zero.abra", assertions: "lexer/ints_error_leading_zero.out" }, + { test: "lexer/ints_error_invalid_hex_first.abra", assertions: "lexer/ints_error_invalid_hex_first.out" }, + { test: "lexer/ints_error_invalid_hex_eof.abra", assertions: "lexer/ints_error_invalid_hex_eof.out" }, + { test: "lexer/ints_error_invalid_binary_first.abra", assertions: "lexer/ints_error_invalid_binary_first.out" }, + { test: "lexer/ints_error_invalid_binary_eof.abra", assertions: "lexer/ints_error_invalid_binary_eof.out" }, + // Floats + { test: "lexer/floats.abra", assertions: "lexer/floats.out.json" }, + { test: "lexer/floats_error_extra_period.abra", assertions: "lexer/floats_error_extra_period.out" }, + // Strings + { test: "lexer/strings.abra", assertions: "lexer/strings.out.json" }, + { test: "lexer/strings_error_unterminated_newline.abra", assertions: "lexer/strings_error_unterminated_newline.out" }, + { test: "lexer/strings_error_unterminated_eof.abra", assertions: "lexer/strings_error_unterminated_eof.out" }, + { test: "lexer/strings_error_unsupported_escape_sequence.abra", assertions: "lexer/strings_error_unsupported_escape_sequence.out" }, + { test: "lexer/strings_error_invalid_unicode_seq_length.abra", assertions: "lexer/strings_error_invalid_unicode_seq_length.out" }, + { test: "lexer/strings_error_invalid_unicode_seq_eof.abra", assertions: "lexer/strings_error_invalid_unicode_seq_eof.out" }, + { test: "lexer/strings_error_invalid_unicode_seq_char.abra", assertions: "lexer/strings_error_invalid_unicode_seq_char.out" }, + { test: "lexer/strings_interpolation.1.abra", assertions: "lexer/strings_interpolation.1.out.json" }, + { test: "lexer/strings_interpolation.2.abra", assertions: "lexer/strings_interpolation.2.out.json" }, + { test: "lexer/strings_interpolation_error_unclosed_brace.abra", assertions: "lexer/strings_interpolation_error_unclosed_brace.out" }, + // Keywords + { test: "lexer/keywords.abra", assertions: "lexer/keywords.out.json" }, + // Symbols + { test: "lexer/symbols.abra", assertions: "lexer/symbols.out.json" }, + { test: "lexer/symbols_error_ampersand_eof.abra", assertions: "lexer/symbols_error_ampersand_eof.out" }, + { test: "lexer/symbols_error_ampersand_other.abra", assertions: "lexer/symbols_error_ampersand_other.out" }, + { test: "lexer/symbols_error_hash_eof.abra", assertions: "lexer/symbols_error_hash_eof.out" }, + { test: "lexer/symbols_error_hash_other.abra", assertions: "lexer/symbols_error_hash_other.out" }, + // Comments + { test: "lexer/comments_single_line.abra", assertions: "lexer/comments_single_line.out.json" }, + { test: "lexer/comments_multiline.abra", assertions: "lexer/comments_multiline.out.json" }, + { test: "lexer/comments_error_multiline_unclosed.abra", assertions: "lexer/comments_error_multiline_unclosed.out" }, +] + +const PARSER_TESTS = [ + { test: "parser/literals.abra", assertions: "parser/literals.out.json" }, + { test: "parser/strings_interpolation.abra", assertions: "parser/strings_interpolation.out.json" }, + { test: "parser/strings_interpolation_error_invalid_expression.1.abra", assertions: "parser/strings_interpolation_error_invalid_expression.1.out" }, + { test: "parser/strings_interpolation_error_invalid_expression.2.abra", assertions: "parser/strings_interpolation_error_invalid_expression.2.out" }, + + // Binary + { test: "parser/binary.abra", assertions: "parser/binary.out.json" }, + { test: "parser/binary_error_eof.abra", assertions: "parser/binary_error_eof.out" }, + // Unary + { test: "parser/unary.abra", assertions: "parser/unary.out.json" }, + { test: "parser/unary_error_eof.abra", assertions: "parser/unary_error_eof.out" }, + // Grouped + { test: "parser/grouped.abra", assertions: "parser/grouped.out.json" }, + { test: "parser/grouped_error_eof.abra", assertions: "parser/grouped_error_eof.out" }, + { test: "parser/grouped_error_wrong_closing.abra", assertions: "parser/grouped_error_wrong_closing.out" }, + // Identifiers + { test: "parser/identifiers.abra", assertions: "parser/identifiers.out.json" }, + { test: "parser/invocation_transform_OptionSome.abra", assertions: "parser/invocation_transform_OptionSome.out.json" }, + // Accessors + { test: "parser/accessor.abra", assertions: "parser/accessor.out.json" }, + { test: "parser/accessor_error_eof.abra", assertions: "parser/accessor_error_eof.out" }, + { test: "parser/accessor_error_self.abra", assertions: "parser/accessor_error_self.out" }, + { test: "parser/accessor_error_None.abra", assertions: "parser/accessor_error_None.out" }, + // Invocation + { test: "parser/invocation.abra", assertions: "parser/invocation.out.json" }, + { test: "parser/invocation_error_eof.abra", assertions: "parser/invocation_error_eof.out" }, + { test: "parser/invocation_error_no_comma.abra", assertions: "parser/invocation_error_no_comma.out" }, + { test: "parser/invocation_error_no_rparen.abra", assertions: "parser/invocation_error_no_rparen.out" }, + { test: "parser/invocation_error_empty_typeargs.abra", assertions: "parser/invocation_error_empty_typeargs.out" }, + { test: "parser/invocation_error_invalid_typearg.abra", assertions: "parser/invocation_error_invalid_typearg.out" }, + { test: "parser/invocation_error_typeargs_eof.abra", assertions: "parser/invocation_error_typeargs_eof.out" }, + { test: "parser/invocation_error_typeargs_no_lparen.abra", assertions: "parser/invocation_error_typeargs_no_lparen.out" }, + // Array + { test: "parser/array.abra", assertions: "parser/array.out.json" }, + { test: "parser/array_error_eof.abra", assertions: "parser/array_error_eof.out" }, + { test: "parser/array_error_no_comma.abra", assertions: "parser/array_error_no_comma.out" }, + { test: "parser/array_error_no_rbrack.abra", assertions: "parser/array_error_no_rbrack.out" }, + // Set + { test: "parser/set.abra", assertions: "parser/set.out.json" }, + { test: "parser/set_error_eof.abra", assertions: "parser/set_error_eof.out" }, + { test: "parser/set_error_no_comma.abra", assertions: "parser/set_error_no_comma.out" }, + { test: "parser/set_error_no_rbrace.abra", assertions: "parser/set_error_no_rbrace.out" }, + // Map + { test: "parser/map.abra", assertions: "parser/map.out.json" }, + { test: "parser/map_error_bad_key.abra", assertions: "parser/map_error_bad_key.out" }, + { test: "parser/map_error_no_colon.abra", assertions: "parser/map_error_no_colon.out" }, + { test: "parser/map_error_no_colon_eof.abra", assertions: "parser/map_error_no_colon_eof.out" }, + { test: "parser/map_error_no_comma.abra", assertions: "parser/map_error_no_comma.out" }, + { test: "parser/map_error_no_rbrace.abra", assertions: "parser/map_error_no_rbrace.out" }, + { test: "parser/map_error_no_value.abra", assertions: "parser/map_error_no_value.out" }, + { test: "parser/map_error_no_value_eof.abra", assertions: "parser/map_error_no_value_eof.out" }, + // Tuples + { test: "parser/tuples.abra", assertions: "parser/tuples.out.json" }, + { test: "parser/tuples_error_eof.abra", assertions: "parser/tuples_error_eof.out" }, + { test: "parser/tuples_error_no_comma.abra", assertions: "parser/tuples_error_no_comma.out" }, + { test: "parser/tuples_error_no_rparen.abra", assertions: "parser/tuples_error_no_rparen.out" }, + // Lambdas + { test: "parser/lambdas.abra", assertions: "parser/lambdas.out.json" }, + { test: "parser/lambdas_error_bad_arg.abra", assertions: "parser/lambdas_error_bad_arg.out" }, + { test: "parser/lambdas_error_badparam_None.abra", assertions: "parser/lambdas_error_badparam_None.out" }, + { test: "parser/lambdas_error_badparam_nonident.abra", assertions: "parser/lambdas_error_badparam_nonident.out" }, + { test: "parser/lambdas_error_badparam_self.abra", assertions: "parser/lambdas_error_badparam_self.out" }, + { test: "parser/lambdas_error_noargs_no_arrow.abra", assertions: "parser/lambdas_error_noargs_no_arrow.out" }, + { test: "parser/lambdas_error_statement_body.abra", assertions: "parser/lambdas_error_statement_body.out" }, + // Indexing + { test: "parser/indexing.abra", assertions: "parser/indexing.out.json" }, + { test: "parser/indexing_error_eof.abra", assertions: "parser/indexing_error_eof.out" }, + { test: "parser/indexing_error_no_rbrack.abra", assertions: "parser/indexing_error_no_rbrack.out" }, + // Assignment + { test: "parser/assignment.abra", assertions: "parser/assignment.out.json" }, + { test: "parser/assignment_error_as_expr.abra", assertions: "parser/assignment_error_as_expr.out" }, + { test: "parser/assignment_error_assign_to_range.abra", assertions: "parser/assignment_error_assign_to_range.out" }, + { test: "parser/assignment_error_assignment_precedence.abra", assertions: "parser/assignment_error_assignment_precedence.out" }, + { test: "parser/assignment_error_illegal_target.abra", assertions: "parser/assignment_error_illegal_target.out" }, + // If + { test: "parser/if.abra", assertions: "parser/if.out.json" }, + { test: "parser/if_error_no_closing_pipe.abra", assertions: "parser/if_error_no_closing_pipe.out" }, + { test: "parser/if_error_no_then_block.abra", assertions: "parser/if_error_no_then_block.out" }, + // Match + { test: "parser/match.abra", assertions: "parser/match.out.json" }, + { test: "parser/match_error_case_bad_binding.abra", assertions: "parser/match_error_case_bad_binding.out" }, + { test: "parser/match_error_case_bad_path.abra", assertions: "parser/match_error_case_bad_path.out" }, + { test: "parser/match_error_case_bad_token.abra", assertions: "parser/match_error_case_bad_token.out" }, + { test: "parser/match_error_case_expr.abra", assertions: "parser/match_error_case_expr.out" }, + { test: "parser/match_error_case_no_case.abra", assertions: "parser/match_error_case_no_case.out" }, + { test: "parser/match_error_no_expr.abra", assertions: "parser/match_error_no_expr.out" }, + { test: "parser/match_error_no_lbrace.abra", assertions: "parser/match_error_no_lbrace.out" }, + { test: "parser/match_error_destructuring_case_empty_args.abra", assertions: "parser/match_error_destructuring_case_empty_args.out" }, + // Decorators + { test: "parser/decorator_error_bad_ident.abra", assertions: "parser/decorator_error_bad_ident.out" }, + { test: "parser/decorator_error_before_expr.abra", assertions: "parser/decorator_error_before_expr.out" }, + { test: "parser/decorator_error_before_invalid_stmt.abra", assertions: "parser/decorator_error_before_invalid_stmt.out" }, + { test: "parser/decorator_error_non_constant_arg.abra", assertions: "parser/decorator_error_non_constant_arg.out" }, + { test: "parser/decorator.abra", assertions: "parser/decorator.out.json" }, + + // Imports + { test: "parser/import.abra", assertions: "parser/import.out.json" }, + { test: "parser/import_error_alias_bad_alias.abra", assertions: "parser/import_error_alias_bad_alias.out" }, + { test: "parser/import_error_alias_bad_module.abra", assertions: "parser/import_error_alias_bad_module.out" }, + { test: "parser/import_error_alias_no_alias_eof.abra", assertions: "parser/import_error_alias_no_alias_eof.out" }, + { test: "parser/import_error_alias_no_as.abra", assertions: "parser/import_error_alias_no_as.out" }, + { test: "parser/import_error_alias_no_module.abra", assertions: "parser/import_error_alias_no_module.out" }, + { test: "parser/import_error_forbidden.abra", assertions: "parser/import_error_forbidden.out" }, + { test: "parser/import_error_list_2nd_nonident.abra", assertions: "parser/import_error_list_2nd_nonident.out" }, + { test: "parser/import_error_list_2nd_underscore.abra", assertions: "parser/import_error_list_2nd_underscore.out" }, + { test: "parser/import_error_list_bad_module.abra", assertions: "parser/import_error_list_bad_module.out" }, + { test: "parser/import_error_list_first_nonident.abra", assertions: "parser/import_error_list_first_nonident.out" }, + { test: "parser/import_error_list_no_comma.abra", assertions: "parser/import_error_list_no_comma.out" }, + { test: "parser/import_error_list_no_from.abra", assertions: "parser/import_error_list_no_from.out" }, + { test: "parser/import_error_list_no_module_eof.abra", assertions: "parser/import_error_list_no_module_eof.out" }, + // Exports + { test: "parser/export.abra", assertions: "parser/export.out.json" }, + { test: "parser/export_error_before_expr.abra", assertions: "parser/export_error_before_expr.out" }, + { test: "parser/export_error_before_invalid_statement.abra", assertions: "parser/export_error_before_invalid_statement.out" }, + + // While + { test: "parser/while.abra", assertions: "parser/while.out.json" }, + { test: "parser/while_error_as_expr.abra", assertions: "parser/while_error_as_expr.out" }, + // For + { test: "parser/for.abra", assertions: "parser/for.out.json" }, + { test: "parser/for_error_no_in.abra", assertions: "parser/for_error_no_in.out" }, + { test: "parser/for_error_no_iterator.abra", assertions: "parser/for_error_no_iterator.out" }, + + // Type identifiers + { test: "parser/typeidentifiers.abra", assertions: "parser/typeidentifiers.out.json" }, + { test: "parser/typeidentifiers_error_empty_typeargs.abra", assertions: "parser/typeidentifiers_error_empty_typeargs.out" }, + { test: "parser/typeidentifiers_error_empty_tuple.abra", assertions: "parser/typeidentifiers_error_empty_tuple.out" }, + { test: "parser/typeidentifiers_error_misplaced_typeargs.abra", assertions: "parser/typeidentifiers_error_misplaced_typeargs.out" }, + { test: "parser/typeidentifiers_error_no_base_ident.abra", assertions: "parser/typeidentifiers_error_no_base_ident.out" }, + { test: "parser/typeidentifiers_error_no_rbrack.abra", assertions: "parser/typeidentifiers_error_no_rbrack.out" }, + // Binding declaration + { test: "parser/bindingdecl.abra", assertions: "parser/bindingdecl.out.json" }, + { test: "parser/bindingdecl_error_bad_expr.abra", assertions: "parser/bindingdecl_error_bad_expr.out" }, + { test: "parser/bindingdecl_error_bad_ident.abra", assertions: "parser/bindingdecl_error_bad_ident.out" }, + { test: "parser/bindingdecl_error_no_expr.abra", assertions: "parser/bindingdecl_error_no_expr.out" }, + { test: "parser/bindingdecl_error_no_ident.abra", assertions: "parser/bindingdecl_error_no_ident.out" }, + // Function declaration + { test: "parser/functiondecl.abra", assertions: "parser/functiondecl.out.json" }, + { test: "parser/functiondecl_error_bad_name.abra", assertions: "parser/functiondecl_error_bad_name.out" }, + { test: "parser/functiondecl_error_no_parens.abra", assertions: "parser/functiondecl_error_no_parens.out" }, + { test: "parser/functiondecl_error_empty_typeparams.abra", assertions: "parser/functiondecl_error_empty_typeparams.out" }, + { test: "parser/functiondecl_error_typeparam_invalid.abra", assertions: "parser/functiondecl_error_typeparam_invalid.out" }, + { test: "parser/functiondecl_error_no_body.abra", assertions: "parser/functiondecl_error_no_body.out" }, + { test: "parser/functiondecl_error_self_default_value.abra", assertions: "parser/functiondecl_error_self_default_value.out" }, + { test: "parser/functiondecl_error_self_type_annotation.abra", assertions: "parser/functiondecl_error_self_type_annotation.out" }, + { test: "parser/functiondecl_error_self_variadic.abra", assertions: "parser/functiondecl_error_self_variadic.out" }, + // Type declaration + { test: "parser/typedecl.abra", assertions: "parser/typedecl.out.json" }, + { test: "parser/typedecl_error_exporting_method.abra", assertions: "parser/typedecl_error_exporting_method.out" }, + { test: "parser/typedecl_error_field_after_method.abra", assertions: "parser/typedecl_error_field_after_method.out" }, + { test: "parser/typedecl_error_illegal_body_part.abra", assertions: "parser/typedecl_error_illegal_body_part.out" }, + // Enum declaration + { test: "parser/enumdecl.abra", assertions: "parser/enumdecl.out.json" }, + { test: "parser/enumdecl_error_container_no_typeannotation.abra", assertions: "parser/enumdecl_error_container_no_typeannotation.out" }, + { test: "parser/enumdecl_error_empty_container_variant.abra", assertions: "parser/enumdecl_error_empty_container_variant.out" }, + // Returns + { test: "parser/return.abra", assertions: "parser/return.out.json" }, + { test: "parser/return_error_nonexpr.abra", assertions: "parser/return_error_nonexpr.out" }, +] + +const TYPECHECKER_TESTS = [ + { test: "typechecker/_lexer_error.abra", assertions: "typechecker/_lexer_error.out" }, + { test: "typechecker/_parser_error.abra", assertions: "typechecker/_parser_error.out" }, + // Literals + { test: "typechecker/literals/literals.abra", assertions: "typechecker/literals/literals.out.json" }, + { test: "typechecker/literals/string_interpolation.abra", assertions: "typechecker/literals/string_interpolation.out.json" }, + // Unary + { test: "typechecker/unary/unary.abra", assertions: "typechecker/unary/unary.out.json" }, + { test: "typechecker/unary/error_minus.1.abra", assertions: "typechecker/unary/error_minus.1.out" }, + { test: "typechecker/unary/error_minus.2.abra", assertions: "typechecker/unary/error_minus.2.out" }, + { test: "typechecker/unary/error_neg.1.abra", assertions: "typechecker/unary/error_neg.1.out" }, + { test: "typechecker/unary/error_neg.2.abra", assertions: "typechecker/unary/error_neg.2.out" }, + // Binary + { test: "typechecker/binary/and.abra", assertions: "typechecker/binary/and.out.json" }, + { test: "typechecker/binary/and_error.1.abra", assertions: "typechecker/binary/and_error.1.out" }, + { test: "typechecker/binary/and_error.2.abra", assertions: "typechecker/binary/and_error.2.out" }, + { test: "typechecker/binary/coalesce.1.abra", assertions: "typechecker/binary/coalesce.1.out.json" }, + { test: "typechecker/binary/coalesce.2.abra", assertions: "typechecker/binary/coalesce.2.out.json" }, + { test: "typechecker/binary/coalesce_error.1.abra", assertions: "typechecker/binary/coalesce_error.1.out" }, + { test: "typechecker/binary/coalesce_error.2.abra", assertions: "typechecker/binary/coalesce_error.2.out" }, + { test: "typechecker/binary/coalesce_error.3.abra", assertions: "typechecker/binary/coalesce_error.3.out" }, + { test: "typechecker/binary/divide.abra", assertions: "typechecker/binary/divide.out.json" }, + { test: "typechecker/binary/divide_error.1.abra", assertions: "typechecker/binary/divide_error.1.out" }, + { test: "typechecker/binary/divide_error.2.abra", assertions: "typechecker/binary/divide_error.2.out" }, + { test: "typechecker/binary/divide_error.3.abra", assertions: "typechecker/binary/divide_error.3.out" }, + { test: "typechecker/binary/eq.1.abra", assertions: "typechecker/binary/eq.1.out.json" }, + { test: "typechecker/binary/eq.2.abra", assertions: "typechecker/binary/eq.2.out.json" }, + { test: "typechecker/binary/eq_error.1.abra", assertions: "typechecker/binary/eq_error.1.out" }, + { test: "typechecker/binary/eq_error.2.abra", assertions: "typechecker/binary/eq_error.2.out" }, + { test: "typechecker/binary/eq_error.3.abra", assertions: "typechecker/binary/eq_error.3.out" }, + { test: "typechecker/binary/gt.abra", assertions: "typechecker/binary/gt.out.json" }, + { test: "typechecker/binary/gt_error.1.abra", assertions: "typechecker/binary/gt_error.1.out" }, + { test: "typechecker/binary/gt_error.2.abra", assertions: "typechecker/binary/gt_error.2.out" }, + { test: "typechecker/binary/gt_error.3.abra", assertions: "typechecker/binary/gt_error.3.out" }, + { test: "typechecker/binary/gte.abra", assertions: "typechecker/binary/gte.out.json" }, + { test: "typechecker/binary/gte_error.1.abra", assertions: "typechecker/binary/gte_error.1.out" }, + { test: "typechecker/binary/gte_error.2.abra", assertions: "typechecker/binary/gte_error.2.out" }, + { test: "typechecker/binary/gte_error.3.abra", assertions: "typechecker/binary/gte_error.3.out" }, + { test: "typechecker/binary/lt.abra", assertions: "typechecker/binary/lt.out.json" }, + { test: "typechecker/binary/lt_error.1.abra", assertions: "typechecker/binary/lt_error.1.out" }, + { test: "typechecker/binary/lt_error.2.abra", assertions: "typechecker/binary/lt_error.2.out" }, + { test: "typechecker/binary/lt_error.3.abra", assertions: "typechecker/binary/lt_error.3.out" }, + { test: "typechecker/binary/lte.abra", assertions: "typechecker/binary/lte.out.json" }, + { test: "typechecker/binary/lte_error.1.abra", assertions: "typechecker/binary/lte_error.1.out" }, + { test: "typechecker/binary/lte_error.2.abra", assertions: "typechecker/binary/lte_error.2.out" }, + { test: "typechecker/binary/lte_error.3.abra", assertions: "typechecker/binary/lte_error.3.out" }, + { test: "typechecker/binary/minus.abra", assertions: "typechecker/binary/minus.out.json" }, + { test: "typechecker/binary/minus_error.1.abra", assertions: "typechecker/binary/minus_error.1.out" }, + { test: "typechecker/binary/minus_error.2.abra", assertions: "typechecker/binary/minus_error.2.out" }, + { test: "typechecker/binary/minus_error.3.abra", assertions: "typechecker/binary/minus_error.3.out" }, + { test: "typechecker/binary/mod.abra", assertions: "typechecker/binary/mod.out.json" }, + { test: "typechecker/binary/mod_error.1.abra", assertions: "typechecker/binary/mod_error.1.out" }, + { test: "typechecker/binary/mod_error.2.abra", assertions: "typechecker/binary/mod_error.2.out" }, + { test: "typechecker/binary/mod_error.3.abra", assertions: "typechecker/binary/mod_error.3.out" }, + { test: "typechecker/binary/neq.1.abra", assertions: "typechecker/binary/neq.1.out.json" }, + { test: "typechecker/binary/neq.2.abra", assertions: "typechecker/binary/neq.2.out.json" }, + { test: "typechecker/binary/neq_error.1.abra", assertions: "typechecker/binary/neq_error.1.out" }, + { test: "typechecker/binary/neq_error.2.abra", assertions: "typechecker/binary/neq_error.2.out" }, + { test: "typechecker/binary/or.abra", assertions: "typechecker/binary/or.out.json" }, + { test: "typechecker/binary/or_error.1.abra", assertions: "typechecker/binary/or_error.1.out" }, + { test: "typechecker/binary/or_error.2.abra", assertions: "typechecker/binary/or_error.2.out" }, + { test: "typechecker/binary/plus_error.1.abra", assertions: "typechecker/binary/plus_error.1.out" }, + { test: "typechecker/binary/plus_error.2.abra", assertions: "typechecker/binary/plus_error.2.out" }, + { test: "typechecker/binary/plus_error.3.abra", assertions: "typechecker/binary/plus_error.3.out" }, + { test: "typechecker/binary/plus_numeric.abra", assertions: "typechecker/binary/plus_numeric.out.json" }, + { test: "typechecker/binary/plus_string_concat.abra", assertions: "typechecker/binary/plus_string_concat.out.json" }, + { test: "typechecker/binary/pow.abra", assertions: "typechecker/binary/pow.out.json" }, + { test: "typechecker/binary/pow_error.1.abra", assertions: "typechecker/binary/pow_error.1.out" }, + { test: "typechecker/binary/pow_error.2.abra", assertions: "typechecker/binary/pow_error.2.out" }, + { test: "typechecker/binary/pow_error.3.abra", assertions: "typechecker/binary/pow_error.3.out" }, + { test: "typechecker/binary/shl.abra", assertions: "typechecker/binary/shl.out.json" }, + { test: "typechecker/binary/shl_error.1.abra", assertions: "typechecker/binary/shl_error.1.out" }, + { test: "typechecker/binary/shl_error.2.abra", assertions: "typechecker/binary/shl_error.2.out" }, + { test: "typechecker/binary/shl_error.3.abra", assertions: "typechecker/binary/shl_error.3.out" }, + { test: "typechecker/binary/shl_error.4.abra", assertions: "typechecker/binary/shl_error.4.out" }, + { test: "typechecker/binary/shr.abra", assertions: "typechecker/binary/shr.out.json" }, + { test: "typechecker/binary/shr_error.1.abra", assertions: "typechecker/binary/shr_error.1.out" }, + { test: "typechecker/binary/shr_error.2.abra", assertions: "typechecker/binary/shr_error.2.out" }, + { test: "typechecker/binary/shr_error.3.abra", assertions: "typechecker/binary/shr_error.3.out" }, + { test: "typechecker/binary/shr_error.4.abra", assertions: "typechecker/binary/shr_error.4.out" }, + { test: "typechecker/binary/times.abra", assertions: "typechecker/binary/times.out.json" }, + { test: "typechecker/binary/times_error.1.abra", assertions: "typechecker/binary/times_error.1.out" }, + { test: "typechecker/binary/times_error.2.abra", assertions: "typechecker/binary/times_error.2.out" }, + { test: "typechecker/binary/times_error.3.abra", assertions: "typechecker/binary/times_error.3.out" }, + { test: "typechecker/binary/and_eq.abra", assertions: "typechecker/binary/and_eq.out.json" }, + { test: "typechecker/binary/and_eq_error.1.abra", assertions: "typechecker/binary/and_eq_error.1.out" }, + { test: "typechecker/binary/and_eq_error.2.abra", assertions: "typechecker/binary/and_eq_error.2.out" }, + { test: "typechecker/binary/divide_eq.abra", assertions: "typechecker/binary/divide_eq.out.json" }, + { test: "typechecker/binary/divide_eq_error.1.abra", assertions: "typechecker/binary/divide_eq_error.1.out" }, + { test: "typechecker/binary/divide_eq_error.2.abra", assertions: "typechecker/binary/divide_eq_error.2.out" }, + { test: "typechecker/binary/divide_eq_error.3.abra", assertions: "typechecker/binary/divide_eq_error.3.out" }, + { test: "typechecker/binary/minus_eq.abra", assertions: "typechecker/binary/minus_eq.out.json" }, + { test: "typechecker/binary/minus_eq_error.1.abra", assertions: "typechecker/binary/minus_eq_error.1.out" }, + { test: "typechecker/binary/minus_eq_error.2.abra", assertions: "typechecker/binary/minus_eq_error.2.out" }, + { test: "typechecker/binary/mod_eq.abra", assertions: "typechecker/binary/mod_eq.out.json" }, + { test: "typechecker/binary/mod_eq_error.1.abra", assertions: "typechecker/binary/mod_eq_error.1.out" }, + { test: "typechecker/binary/mod_eq_error.2.abra", assertions: "typechecker/binary/mod_eq_error.2.out" }, + { test: "typechecker/binary/or_eq.abra", assertions: "typechecker/binary/or_eq.out.json" }, + { test: "typechecker/binary/or_eq_error.1.abra", assertions: "typechecker/binary/or_eq_error.1.out" }, + { test: "typechecker/binary/or_eq_error.2.abra", assertions: "typechecker/binary/or_eq_error.2.out" }, + { test: "typechecker/binary/plus_eq.abra", assertions: "typechecker/binary/plus_eq.out.json" }, + { test: "typechecker/binary/plus_eq_error.1.abra", assertions: "typechecker/binary/plus_eq_error.1.out" }, + { test: "typechecker/binary/plus_eq_error.2.abra", assertions: "typechecker/binary/plus_eq_error.2.out" }, + { test: "typechecker/binary/times_eq.abra", assertions: "typechecker/binary/times_eq.out.json" }, + { test: "typechecker/binary/times_eq_error.1.abra", assertions: "typechecker/binary/times_eq_error.1.out" }, + { test: "typechecker/binary/times_eq_error.2.abra", assertions: "typechecker/binary/times_eq_error.2.out" }, + + // Identifier + { test: "typechecker/identifier/identifier.abra", assertions: "typechecker/identifier/identifier.out.json" }, + { test: "typechecker/identifier/identifier_transform_OptionNone.abra", assertions: "typechecker/identifier/identifier_transform_OptionNone.out.json" }, + { test: "typechecker/identifier/error_discard.abra", assertions: "typechecker/identifier/error_discard.out" }, + { test: "typechecker/identifier/error_type_mismatch.abra", assertions: "typechecker/identifier/error_type_mismatch.out" }, + { test: "typechecker/identifier/error_type_mismatch_None.abra", assertions: "typechecker/identifier/error_type_mismatch_None.out" }, + { test: "typechecker/identifier/error_unknown_ident.abra", assertions: "typechecker/identifier/error_unknown_ident.out" }, + // Array + { test: "typechecker/array/array.abra", assertions: "typechecker/array/array.out.json" }, + { test: "typechecker/array/error_bindingdecl_empty.abra", assertions: "typechecker/array/error_bindingdecl_empty.out" }, + { test: "typechecker/array/error_type_mismatch_bindingdecl.1.abra", assertions: "typechecker/array/error_type_mismatch_bindingdecl.1.out" }, + { test: "typechecker/array/error_type_mismatch_bindingdecl.2.abra", assertions: "typechecker/array/error_type_mismatch_bindingdecl.2.out" }, + { test: "typechecker/array/error_type_mismatch_bindingdecl.3.abra", assertions: "typechecker/array/error_type_mismatch_bindingdecl.3.out" }, + { test: "typechecker/array/error_type_mismatch_item.1.abra", assertions: "typechecker/array/error_type_mismatch_item.1.out" }, + { test: "typechecker/array/error_type_mismatch_item.2.abra", assertions: "typechecker/array/error_type_mismatch_item.2.out" }, + { test: "typechecker/array/error_type_mismatch_item.3.abra", assertions: "typechecker/array/error_type_mismatch_item.3.out" }, + { test: "typechecker/array/error_type_mismatch_item.4.abra", assertions: "typechecker/array/error_type_mismatch_item.4.out" }, + // Set + { test: "typechecker/set/set.abra", assertions: "typechecker/set/set.out.json" }, + { test: "typechecker/set/error_bindingdecl_empty.abra", assertions: "typechecker/set/error_bindingdecl_empty.out" }, + { test: "typechecker/set/error_type_mismatch_bindingdecl.1.abra", assertions: "typechecker/set/error_type_mismatch_bindingdecl.1.out" }, + { test: "typechecker/set/error_type_mismatch_bindingdecl.2.abra", assertions: "typechecker/set/error_type_mismatch_bindingdecl.2.out" }, + { test: "typechecker/set/error_type_mismatch_bindingdecl.3.abra", assertions: "typechecker/set/error_type_mismatch_bindingdecl.3.out" }, + { test: "typechecker/set/error_type_mismatch_item.1.abra", assertions: "typechecker/set/error_type_mismatch_item.1.out" }, + { test: "typechecker/set/error_type_mismatch_item.2.abra", assertions: "typechecker/set/error_type_mismatch_item.2.out" }, + { test: "typechecker/set/error_type_mismatch_item.3.abra", assertions: "typechecker/set/error_type_mismatch_item.3.out" }, + { test: "typechecker/set/error_type_mismatch_item.4.abra", assertions: "typechecker/set/error_type_mismatch_item.4.out" }, + // Map + { test: "typechecker/map/map.abra", assertions: "typechecker/map/map.out.json" }, + { test: "typechecker/map/error_bindingdecl_empty.abra", assertions: "typechecker/map/error_bindingdecl_empty.out" }, + { test: "typechecker/map/error_type_mismatch_bindingdecl.1.abra", assertions: "typechecker/map/error_type_mismatch_bindingdecl.1.out" }, + { test: "typechecker/map/error_type_mismatch_bindingdecl.2.abra", assertions: "typechecker/map/error_type_mismatch_bindingdecl.2.out" }, + { test: "typechecker/map/error_type_mismatch_bindingdecl.3.abra", assertions: "typechecker/map/error_type_mismatch_bindingdecl.3.out" }, + { test: "typechecker/map/error_type_mismatch_bindingdecl.4.abra", assertions: "typechecker/map/error_type_mismatch_bindingdecl.4.out" }, + { test: "typechecker/map/error_type_mismatch_key.1.abra", assertions: "typechecker/map/error_type_mismatch_key.1.out" }, + { test: "typechecker/map/error_type_mismatch_value.1.abra", assertions: "typechecker/map/error_type_mismatch_value.1.out" }, + { test: "typechecker/map/error_type_mismatch_value.2.abra", assertions: "typechecker/map/error_type_mismatch_value.2.out" }, + { test: "typechecker/map/error_unfilled_holes.1.abra", assertions: "typechecker/map/error_unfilled_holes.1.out" }, + { test: "typechecker/map/error_unfilled_holes.2.abra", assertions: "typechecker/map/error_unfilled_holes.2.out" }, + // Tuple + { test: "typechecker/tuple/tuple.abra", assertions: "typechecker/tuple/tuple.out.json" }, + { test: "typechecker/tuple/error_type_mismatch.1.abra", assertions: "typechecker/tuple/error_type_mismatch.1.out" }, + { test: "typechecker/tuple/error_type_mismatch.2.abra", assertions: "typechecker/tuple/error_type_mismatch.2.out" }, + { test: "typechecker/tuple/error_type_mismatch_too_big.1.abra", assertions: "typechecker/tuple/error_type_mismatch_too_big.1.out" }, + { test: "typechecker/tuple/error_type_mismatch_too_big.2.abra", assertions: "typechecker/tuple/error_type_mismatch_too_big.2.out" }, + { test: "typechecker/tuple/error_type_mismatch_too_small.1.abra", assertions: "typechecker/tuple/error_type_mismatch_too_small.1.out" }, + // Indexing + { test: "typechecker/indexing/error_indexing_array_nullable.abra", assertions: "typechecker/indexing/error_indexing_array_nullable.out" }, + { test: "typechecker/indexing/error_indexing_string_nullable.abra", assertions: "typechecker/indexing/error_indexing_string_nullable.out" }, + { test: "typechecker/indexing/error_indexing_tuple_nullable.abra", assertions: "typechecker/indexing/error_indexing_tuple_nullable.out" }, + { test: "typechecker/indexing/error_indexing_map_nullable.abra", assertions: "typechecker/indexing/error_indexing_map_nullable.out" }, + { test: "typechecker/indexing/error_unindexable_type.1.abra", assertions: "typechecker/indexing/error_unindexable_type.1.out" }, + { test: "typechecker/indexing/error_unindexable_type.2.abra", assertions: "typechecker/indexing/error_unindexable_type.2.out" }, + { test: "typechecker/indexing/array_error_idx_non_int.abra", assertions: "typechecker/indexing/array_error_idx_non_int.out" }, + { test: "typechecker/indexing/array_error_idx_nullable.abra", assertions: "typechecker/indexing/array_error_idx_nullable.out" }, + { test: "typechecker/indexing/array_error_range_non_int.1.abra", assertions: "typechecker/indexing/array_error_range_non_int.1.out" }, + { test: "typechecker/indexing/array_error_range_non_int.2.abra", assertions: "typechecker/indexing/array_error_range_non_int.2.out" }, + { test: "typechecker/indexing/array_error_range_nullable.1.abra", assertions: "typechecker/indexing/array_error_range_nullable.1.out" }, + { test: "typechecker/indexing/array_error_range_nullable.2.abra", assertions: "typechecker/indexing/array_error_range_nullable.2.out" }, + { test: "typechecker/indexing/indexing_array.abra", assertions: "typechecker/indexing/indexing_array.out.json" }, + { test: "typechecker/indexing/indexing_map.abra", assertions: "typechecker/indexing/indexing_map.out.json" }, + { test: "typechecker/indexing/indexing_string.abra", assertions: "typechecker/indexing/indexing_string.out.json" }, + { test: "typechecker/indexing/indexing_tuple.abra", assertions: "typechecker/indexing/indexing_tuple.out.json" }, + { test: "typechecker/indexing/map_error_key_type_mismatch.abra", assertions: "typechecker/indexing/map_error_key_type_mismatch.out" }, + { test: "typechecker/indexing/string_error_idx_non_int.abra", assertions: "typechecker/indexing/string_error_idx_non_int.out" }, + { test: "typechecker/indexing/string_error_idx_nullable.abra", assertions: "typechecker/indexing/string_error_idx_nullable.out" }, + { test: "typechecker/indexing/string_error_range_non_int.1.abra", assertions: "typechecker/indexing/string_error_range_non_int.1.out" }, + { test: "typechecker/indexing/string_error_range_non_int.2.abra", assertions: "typechecker/indexing/string_error_range_non_int.2.out" }, + { test: "typechecker/indexing/string_error_range_nullable.1.abra", assertions: "typechecker/indexing/string_error_range_nullable.1.out" }, + { test: "typechecker/indexing/string_error_range_nullable.2.abra", assertions: "typechecker/indexing/string_error_range_nullable.2.out" }, + { test: "typechecker/indexing/tuple_error_hole.abra", assertions: "typechecker/indexing/tuple_error_hole.out" }, + { test: "typechecker/indexing/tuple_error_negative.abra", assertions: "typechecker/indexing/tuple_error_negative.out" }, + { test: "typechecker/indexing/tuple_error_non_int_literal.abra", assertions: "typechecker/indexing/tuple_error_non_int_literal.out" }, + { test: "typechecker/indexing/tuple_error_non_literal.abra", assertions: "typechecker/indexing/tuple_error_non_literal.out" }, + { test: "typechecker/indexing/tuple_error_out_of_bounds.abra", assertions: "typechecker/indexing/tuple_error_out_of_bounds.out" }, + { test: "typechecker/indexing/tuple_error_range.abra", assertions: "typechecker/indexing/tuple_error_range.out" }, + { test: "typechecker/indexing/tuple_error_type_mismatch.abra", assertions: "typechecker/indexing/tuple_error_type_mismatch.out" }, + // If expressions & statements + { test: "typechecker/if/error_binding_invalid_destructuring_tuple.abra", assertions: "typechecker/if/error_binding_invalid_destructuring_tuple.out" }, + { test: "typechecker/if/error_bad_cond_type.abra", assertions: "typechecker/if/error_bad_cond_type.out" }, + { test: "typechecker/if/error_block_mismatch.1.abra", assertions: "typechecker/if/error_block_mismatch.1.out" }, + { test: "typechecker/if/error_block_mismatch.2.abra", assertions: "typechecker/if/error_block_mismatch.2.out" }, + { test: "typechecker/if/error_empty_else_block.abra", assertions: "typechecker/if/error_empty_else_block.out" }, + { test: "typechecker/if/error_empty_if_block.abra", assertions: "typechecker/if/error_empty_if_block.out" }, + { test: "typechecker/if/error_mismatch_bindingdecl.1.abra", assertions: "typechecker/if/error_mismatch_bindingdecl.1.out" }, + { test: "typechecker/if/error_mismatch_bindingdecl.2.abra", assertions: "typechecker/if/error_mismatch_bindingdecl.2.out" }, + { test: "typechecker/if/error_mismatch_bindingdecl.3.abra", assertions: "typechecker/if/error_mismatch_bindingdecl.3.out" }, + { test: "typechecker/if/error_no_else_block.abra", assertions: "typechecker/if/error_no_else_block.out" }, + { test: "typechecker/if/error_unfilled_holes_bindingdecl.1.abra", assertions: "typechecker/if/error_unfilled_holes_bindingdecl.1.out" }, + { test: "typechecker/if/error_unfilled_holes_bindingdecl.2.abra", assertions: "typechecker/if/error_unfilled_holes_bindingdecl.2.out" }, + { test: "typechecker/if/error_unfilled_holes_bindingdecl.3.abra", assertions: "typechecker/if/error_unfilled_holes_bindingdecl.3.out" }, + { test: "typechecker/if/error_unfilled_holes_bindingdecl.4.abra", assertions: "typechecker/if/error_unfilled_holes_bindingdecl.4.out" }, + { test: "typechecker/if/expr.abra", assertions: "typechecker/if/expr.out.json" }, + { test: "typechecker/if/stmt.abra", assertions: "typechecker/if/stmt.out.json" }, + // Match expressions & statements + { test: "typechecker/match/match_expr.abra", assertions: "typechecker/match/match_expr.out.json" }, + { test: "typechecker/match/match_stmt.abra", assertions: "typechecker/match/match_stmt.out.json" }, + { test: "typechecker/match/match_Result.abra", assertions: "typechecker/match/match_Result.out.json" }, + { test: "typechecker/match/match_expr_terminators.abra", assertions: "typechecker/match/match_expr_terminators.out.json" }, + { test: "typechecker/match/error_expr_empty_block.abra", assertions: "typechecker/match/error_expr_empty_block.out" }, + { test: "typechecker/match/error_unfilled_holes.1.abra", assertions: "typechecker/match/error_unfilled_holes.1.out" }, + { test: "typechecker/match/error_alreadycovered_None.abra", assertions: "typechecker/match/error_alreadycovered_None.out" }, + { test: "typechecker/match/error_duplicate_literal.abra", assertions: "typechecker/match/error_duplicate_literal.out" }, + { test: "typechecker/match/error_invalid_else_type.abra", assertions: "typechecker/match/error_invalid_else_type.out" }, + { test: "typechecker/match/error_nooverlap_None.abra", assertions: "typechecker/match/error_nooverlap_None.out" }, + { test: "typechecker/match/error_nooverlap_literal.1.abra", assertions: "typechecker/match/error_nooverlap_literal.1.out" }, + { test: "typechecker/match/error_nooverlap_literal.2.abra", assertions: "typechecker/match/error_nooverlap_literal.2.out" }, + { test: "typechecker/match/error_alreadycovered_literal_after_type.1.abra", assertions: "typechecker/match/error_alreadycovered_literal_after_type.1.out" }, + { test: "typechecker/match/error_alreadycovered_literal_after_type.2.abra", assertions: "typechecker/match/error_alreadycovered_literal_after_type.2.out" }, + { test: "typechecker/match/error_duplicate_Enum_variant.abra", assertions: "typechecker/match/error_duplicate_Enum_variant.out" }, + { test: "typechecker/match/error_exhaustive_Bool_literal.abra", assertions: "typechecker/match/error_exhaustive_Bool_literal.out" }, + { test: "typechecker/match/error_exhaustive_Enum_variants.1.abra", assertions: "typechecker/match/error_exhaustive_Enum_variants.1.out" }, + { test: "typechecker/match/error_exhaustive_Enum_variants.2.abra", assertions: "typechecker/match/error_exhaustive_Enum_variants.2.out" }, + { test: "typechecker/match/error_exhaustive_after_else.abra", assertions: "typechecker/match/error_exhaustive_after_else.out" }, + { test: "typechecker/match/error_exhaustive_type.1.abra", assertions: "typechecker/match/error_exhaustive_type.1.out" }, + { test: "typechecker/match/error_exhaustive_type.2.abra", assertions: "typechecker/match/error_exhaustive_type.2.out" }, + { test: "typechecker/match/error_nonexhaustive_literal.1.abra", assertions: "typechecker/match/error_nonexhaustive_literal.1.out" }, + { test: "typechecker/match/error_nonexhaustive_literal.2.abra", assertions: "typechecker/match/error_nonexhaustive_literal.2.out" }, + { test: "typechecker/match/error_nooverlap_Enum.abra", assertions: "typechecker/match/error_nooverlap_Enum.out" }, + { test: "typechecker/match/error_nooverlap_Type.abra", assertions: "typechecker/match/error_nooverlap_Type.out" }, + { test: "typechecker/match/error_destructuring_constant_variant.abra", assertions: "typechecker/match/error_destructuring_constant_variant.out" }, + { test: "typechecker/match/error_destructuring_type.abra", assertions: "typechecker/match/error_destructuring_type.out" }, + { test: "typechecker/match/error_destructuring_variant_duplicate_variable.1.abra", assertions: "typechecker/match/error_destructuring_variant_duplicate_variable.1.out" }, + { test: "typechecker/match/error_destructuring_variant_duplicate_variable.2.abra", assertions: "typechecker/match/error_destructuring_variant_duplicate_variable.2.out" }, + { test: "typechecker/match/error_destructuring_variant_too_few.abra", assertions: "typechecker/match/error_destructuring_variant_too_few.out" }, + { test: "typechecker/match/error_destructuring_variant_too_many.abra", assertions: "typechecker/match/error_destructuring_variant_too_many.out" }, + { test: "typechecker/match/error_forbidden_type_all_branches_never.abra", assertions: "typechecker/match/error_forbidden_type_all_branches_never.out" }, + + // Invocation + { test: "typechecker/invocation/invocation.1.abra", assertions: "typechecker/invocation/invocation.1.out.json" }, + { test: "typechecker/invocation/invocation.2.abra", assertions: "typechecker/invocation/invocation.2.out.json" }, + { test: "typechecker/invocation/invocation.3.abra", assertions: "typechecker/invocation/invocation.3.out.json" }, + { test: "typechecker/invocation/invocation.4.abra", assertions: "typechecker/invocation/invocation.4.out.json" }, + { test: "typechecker/invocation/invocation.5.abra", assertions: "typechecker/invocation/invocation.5.out.json" }, + { test: "typechecker/invocation/error_incorrect_label.abra", assertions: "typechecker/invocation/error_incorrect_label.out" }, + { test: "typechecker/invocation/error_mixed_label_optional.abra", assertions: "typechecker/invocation/error_mixed_label_optional.out" }, + { test: "typechecker/invocation/error_optional_param_type_mismatch.abra", assertions: "typechecker/invocation/error_optional_param_type_mismatch.out" }, + { test: "typechecker/invocation/error_optional_param_unknown.abra", assertions: "typechecker/invocation/error_optional_param_unknown.out" }, + { test: "typechecker/invocation/error_too_few_args.abra", assertions: "typechecker/invocation/error_too_few_args.out" }, + { test: "typechecker/invocation/error_too_many_args.abra", assertions: "typechecker/invocation/error_too_many_args.out" }, + { test: "typechecker/invocation/error_expr_illegal_label.abra", assertions: "typechecker/invocation/error_expr_illegal_label.out" }, + { test: "typechecker/invocation/error_expr_not_callable.abra", assertions: "typechecker/invocation/error_expr_not_callable.out" }, + { test: "typechecker/invocation/error_expr_too_few_args.abra", assertions: "typechecker/invocation/error_expr_too_few_args.out" }, + { test: "typechecker/invocation/error_expr_too_many_args.abra", assertions: "typechecker/invocation/error_expr_too_many_args.out" }, + { test: "typechecker/invocation/function_as_param.1.abra", assertions: "typechecker/invocation/function_as_param.1.out.json" }, + { test: "typechecker/invocation/function_as_param.2.abra", assertions: "typechecker/invocation/function_as_param.2.out.json" }, + { test: "typechecker/invocation/function_as_param.3.abra", assertions: "typechecker/invocation/function_as_param.3.out.json" }, + { test: "typechecker/invocation/function_as_param_generic.abra", assertions: "typechecker/invocation/function_as_param_generic.out.json" }, + { test: "typechecker/invocation/function_as_param_error_arity.abra", assertions: "typechecker/invocation/function_as_param_error_arity.out" }, + { test: "typechecker/invocation/function_value.abra", assertions: "typechecker/invocation/function_value.out.json" }, + { test: "typechecker/invocation/invocation_generics.1.abra", assertions: "typechecker/invocation/invocation_generics.1.out.json" }, + { test: "typechecker/invocation/invocation_generics.2.abra", assertions: "typechecker/invocation/invocation_generics.2.out.json" }, + { test: "typechecker/invocation/invocation_generics.3.abra", assertions: "typechecker/invocation/invocation_generics.3.out.json" }, + { test: "typechecker/invocation/invocation_generics.4.abra", assertions: "typechecker/invocation/invocation_generics.4.out.json" }, + { test: "typechecker/invocation/invocation_generics.5.abra", assertions: "typechecker/invocation/invocation_generics.5.out.json" }, + { test: "typechecker/invocation/generics_error_inferred_from_ret.1.abra", assertions: "typechecker/invocation/generics_error_inferred_from_ret.1.out" }, + { test: "typechecker/invocation/generics_error_inferred_from_ret.2.abra", assertions: "typechecker/invocation/generics_error_inferred_from_ret.2.out" }, + { test: "typechecker/invocation/generics_error_type_mismatch.abra", assertions: "typechecker/invocation/generics_error_type_mismatch.out" }, + { test: "typechecker/invocation/generics_error_unfilled_holes.abra", assertions: "typechecker/invocation/generics_error_unfilled_holes.out" }, + { test: "typechecker/invocation/generics_given_error_type_mismatch.abra", assertions: "typechecker/invocation/generics_given_error_type_mismatch.out" }, + { test: "typechecker/invocation/error_field_not_callable.abra", assertions: "typechecker/invocation/error_field_not_callable.out" }, + { test: "typechecker/invocation/error_instantiation_generics.1.abra", assertions: "typechecker/invocation/error_instantiation_generics.1.out" }, + { test: "typechecker/invocation/error_instantiation_generics.2.abra", assertions: "typechecker/invocation/error_instantiation_generics.2.out" }, + { test: "typechecker/invocation/error_instantiation_missing_labels.abra", assertions: "typechecker/invocation/error_instantiation_missing_labels.out" }, + { test: "typechecker/invocation/error_instantiation_too_few_args.1.abra", assertions: "typechecker/invocation/error_instantiation_too_few_args.1.out" }, + { test: "typechecker/invocation/error_instantiation_too_few_args.2.abra", assertions: "typechecker/invocation/error_instantiation_too_few_args.2.out" }, + { test: "typechecker/invocation/error_enum_variant_constant.abra", assertions: "typechecker/invocation/error_enum_variant_constant.out" }, + { test: "typechecker/invocation/invocation_arbitrary_expr.1.abra", assertions: "typechecker/invocation/invocation_arbitrary_expr.1.out.json" }, + { test: "typechecker/invocation/invocation_arbitrary_expr.2.abra", assertions: "typechecker/invocation/invocation_arbitrary_expr.2.out.json" }, + { test: "typechecker/invocation/invocation_field.abra", assertions: "typechecker/invocation/invocation_field.out.json" }, + { test: "typechecker/invocation/invocation_instantiation.1.abra", assertions: "typechecker/invocation/invocation_instantiation.1.out.json" }, + { test: "typechecker/invocation/invocation_instantiation_generics.1.abra", assertions: "typechecker/invocation/invocation_instantiation_generics.1.out.json" }, + { test: "typechecker/invocation/invocation_instantiation_generics.2.abra", assertions: "typechecker/invocation/invocation_instantiation_generics.2.out.json" }, + { test: "typechecker/invocation/invocation_method.1.abra", assertions: "typechecker/invocation/invocation_method.1.out.json" }, + { test: "typechecker/invocation/invocation_method.2.abra", assertions: "typechecker/invocation/invocation_method.2.out.json" }, + { test: "typechecker/invocation/generics_error_method.1.abra", assertions: "typechecker/invocation/generics_error_method.1.out" }, + { test: "typechecker/invocation/generics_error_method.2.abra", assertions: "typechecker/invocation/generics_error_method.2.out" }, + { test: "typechecker/invocation/generics_error_field.1.abra", assertions: "typechecker/invocation/generics_error_field.1.out" }, + { test: "typechecker/invocation/invocation_method_generics.1.abra", assertions: "typechecker/invocation/invocation_method_generics.1.out.json" }, + { test: "typechecker/invocation/invocation_method_generics.2.abra", assertions: "typechecker/invocation/invocation_method_generics.2.out.json" }, + { test: "typechecker/invocation/invocation_enum_variant.1.abra", assertions: "typechecker/invocation/invocation_enum_variant.1.out.json" }, + { test: "typechecker/invocation/invocation_enum_variant.2.abra", assertions: "typechecker/invocation/invocation_enum_variant.2.out.json" }, + { test: "typechecker/invocation/invocation_enum_variant.3.abra", assertions: "typechecker/invocation/invocation_enum_variant.3.out.json" }, + { test: "typechecker/invocation/invocation_enum_variant.4.abra", assertions: "typechecker/invocation/invocation_enum_variant.4.out.json" }, + { test: "typechecker/invocation/invocation_field_generics.1.abra", assertions: "typechecker/invocation/invocation_field_generics.1.out.json" }, + { test: "typechecker/invocation/error_variadic_generic_type_mismatch.abra", assertions: "typechecker/invocation/error_variadic_generic_type_mismatch.out" }, + { test: "typechecker/invocation/error_variadic_labeled_generic_type_mismatch.abra", assertions: "typechecker/invocation/error_variadic_labeled_generic_type_mismatch.out" }, + { test: "typechecker/invocation/error_variadic_labeled_too_many_args.abra", assertions: "typechecker/invocation/error_variadic_labeled_too_many_args.out" }, + { test: "typechecker/invocation/error_variadic_labeled_type_mismatch.abra", assertions: "typechecker/invocation/error_variadic_labeled_type_mismatch.out" }, + { test: "typechecker/invocation/error_variadic_type_mismatch.abra", assertions: "typechecker/invocation/error_variadic_type_mismatch.out" }, + { test: "typechecker/invocation/invocation_variadic.1.abra", assertions: "typechecker/invocation/invocation_variadic.1.out.json" }, + { test: "typechecker/invocation/invocation_variadic.2.abra", assertions: "typechecker/invocation/invocation_variadic.2.out.json" }, + // Accessor + { test: "typechecker/accessor/accessor.1.abra", assertions: "typechecker/accessor/accessor.1.out.json" }, + { test: "typechecker/accessor/accessor.2.abra", assertions: "typechecker/accessor/accessor.2.out.json" }, + { test: "typechecker/accessor/accessor.3.abra", assertions: "typechecker/accessor/accessor.3.out.json" }, + { test: "typechecker/accessor/error_unknown_field.abra", assertions: "typechecker/accessor/error_unknown_field.out" }, + { test: "typechecker/accessor/error_unknown_field_fn.abra", assertions: "typechecker/accessor/error_unknown_field_fn.out" }, + { test: "typechecker/accessor/error_unknown_field_opt_known.abra", assertions: "typechecker/accessor/error_unknown_field_opt_known.out" }, + { test: "typechecker/accessor/error_unknown_field_opt_unknown.abra", assertions: "typechecker/accessor/error_unknown_field_opt_unknown.out" }, + { test: "typechecker/accessor/error_unknown_field_unit.abra", assertions: "typechecker/accessor/error_unknown_field_unit.out" }, + { test: "typechecker/accessor/error_unnecessary_optsafe.abra", assertions: "typechecker/accessor/error_unnecessary_optsafe.out" }, + { test: "typechecker/accessor/error_unknown_field_chain_opt_known.abra", assertions: "typechecker/accessor/error_unknown_field_chain_opt_known.out" }, + { test: "typechecker/accessor/error_unknown_field_chain_opt_unknown.abra", assertions: "typechecker/accessor/error_unknown_field_chain_opt_unknown.out" }, + { test: "typechecker/accessor/error_static_member_referenced_by_instance.abra", assertions: "typechecker/accessor/error_static_member_referenced_by_instance.out" }, + { test: "typechecker/accessor/accessor.4.abra", assertions: "typechecker/accessor/accessor.4.out.json" }, + { test: "typechecker/accessor/error_unknown_enum_variant.1.abra", assertions: "typechecker/accessor/error_unknown_enum_variant.1.out" }, + // Lambda + { test: "typechecker/lambda/lambda.1.abra", assertions: "typechecker/lambda/lambda.1.out.json" }, + { test: "typechecker/lambda/lambda.2.abra", assertions: "typechecker/lambda/lambda.2.out.json" }, + { test: "typechecker/lambda/lambda_generic_inference.1.abra", assertions: "typechecker/lambda/lambda_generic_inference.1.out.json" }, + { test: "typechecker/lambda/lambda_generic_inference.2.abra", assertions: "typechecker/lambda/lambda_generic_inference.2.out.json" }, + { test: "typechecker/lambda/error_type_mismatch.1.abra", assertions: "typechecker/lambda/error_type_mismatch.1.out" }, + { test: "typechecker/lambda/error_type_mismatch.2.abra", assertions: "typechecker/lambda/error_type_mismatch.2.out" }, + { test: "typechecker/lambda/error_type_mismatch.3.abra", assertions: "typechecker/lambda/error_type_mismatch.3.out" }, + { test: "typechecker/lambda/error_type_mismatch.4.abra", assertions: "typechecker/lambda/error_type_mismatch.4.out" }, + { test: "typechecker/lambda/error_type_mismatch.5.abra", assertions: "typechecker/lambda/error_type_mismatch.5.out" }, + { test: "typechecker/lambda/error_unknown_type_for_parameter.1.abra", assertions: "typechecker/lambda/error_unknown_type_for_parameter.1.out" }, + { test: "typechecker/lambda/error_unknown_type_for_parameter.2.abra", assertions: "typechecker/lambda/error_unknown_type_for_parameter.2.out" }, + { test: "typechecker/lambda/error_unknown_type_for_parameter.3.abra", assertions: "typechecker/lambda/error_unknown_type_for_parameter.3.out" }, + + // Type identifiers + { test: "typechecker/typeidentifier/error_typearg_unknown.abra", assertions: "typechecker/typeidentifier/error_typearg_unknown.out" }, + { test: "typechecker/typeidentifier/error_typeargs_missing.abra", assertions: "typechecker/typeidentifier/error_typeargs_missing.out" }, + { test: "typechecker/typeidentifier/error_typeargs_too_few.abra", assertions: "typechecker/typeidentifier/error_typeargs_too_few.out" }, + { test: "typechecker/typeidentifier/error_typeargs_too_many.abra", assertions: "typechecker/typeidentifier/error_typeargs_too_many.out" }, + { test: "typechecker/typeidentifier/error_typeargs_unexpected.abra", assertions: "typechecker/typeidentifier/error_typeargs_unexpected.out" }, + { test: "typechecker/typeidentifier/error_unknown_type.abra", assertions: "typechecker/typeidentifier/error_unknown_type.out" }, + { test: "typechecker/typeidentifier/error_modalias_name_not_type.abra", assertions: "typechecker/typeidentifier/error_modalias_name_not_type.out" }, + { test: "typechecker/typeidentifier/error_modalias_path_too_long.abra", assertions: "typechecker/typeidentifier/error_modalias_path_too_long.out" }, + { test: "typechecker/typeidentifier/error_modalias_typeargs_missing.abra", assertions: "typechecker/typeidentifier/error_modalias_typeargs_missing.out" }, + { test: "typechecker/typeidentifier/error_modalias_typeargs_too_few.abra", assertions: "typechecker/typeidentifier/error_modalias_typeargs_too_few.out" }, + { test: "typechecker/typeidentifier/error_modalias_typeargs_too_many.abra", assertions: "typechecker/typeidentifier/error_modalias_typeargs_too_many.out" }, + { test: "typechecker/typeidentifier/error_modalias_typeargs_unexpected.abra", assertions: "typechecker/typeidentifier/error_modalias_typeargs_unexpected.out" }, + { test: "typechecker/typeidentifier/error_modalias_unknown_module.abra", assertions: "typechecker/typeidentifier/error_modalias_unknown_module.out" }, + { test: "typechecker/typeidentifier/error_modalias_unknown_type.abra", assertions: "typechecker/typeidentifier/error_modalias_unknown_type.out" }, + + // Assignment + { test: "typechecker/assignment/assignment_accessor.abra", assertions: "typechecker/assignment/assignment_accessor.out.json" }, + { test: "typechecker/assignment/assignment_indexing.abra", assertions: "typechecker/assignment/assignment_indexing.out.json" }, + { test: "typechecker/assignment/assignment_variable.abra", assertions: "typechecker/assignment/assignment_variable.out.json" }, + { test: "typechecker/assignment/accessor_error_method.1.abra", assertions: "typechecker/assignment/accessor_error_method.1.out" }, + { test: "typechecker/assignment/accessor_error_method.2.abra", assertions: "typechecker/assignment/accessor_error_method.2.out" }, + { test: "typechecker/assignment/accessor_error_enum_variant.abra", assertions: "typechecker/assignment/accessor_error_enum_variant.out" }, + { test: "typechecker/assignment/accessor_error_type_mismatch.1.abra", assertions: "typechecker/assignment/accessor_error_type_mismatch.1.out" }, + { test: "typechecker/assignment/accessor_error_type_mismatch.2.abra", assertions: "typechecker/assignment/accessor_error_type_mismatch.2.out" }, + { test: "typechecker/assignment/variable_error_alias_fn.abra", assertions: "typechecker/assignment/variable_error_alias_fn.out" }, + { test: "typechecker/assignment/indexing_error_type_mismatch.1.abra", assertions: "typechecker/assignment/indexing_error_type_mismatch.1.out" }, + { test: "typechecker/assignment/indexing_error_type_mismatch.2.abra", assertions: "typechecker/assignment/indexing_error_type_mismatch.2.out" }, + { test: "typechecker/assignment/variable_error_alias_type.abra", assertions: "typechecker/assignment/variable_error_alias_type.out" }, + { test: "typechecker/assignment/variable_error_immutable.abra", assertions: "typechecker/assignment/variable_error_immutable.out" }, + { test: "typechecker/assignment/variable_error_type_mismatch.1.abra", assertions: "typechecker/assignment/variable_error_type_mismatch.1.out" }, + { test: "typechecker/assignment/variable_error_type_mismatch.2.abra", assertions: "typechecker/assignment/variable_error_type_mismatch.2.out" }, + { test: "typechecker/assignment/variable_error_unknown.abra", assertions: "typechecker/assignment/variable_error_unknown.out" }, + + // Break + { test: "typechecker/break/break_as_expr.abra", assertions: "typechecker/break/break_as_expr.out.json" }, + { test: "typechecker/break/error_location_module.abra", assertions: "typechecker/break/error_location_module.out" }, + { test: "typechecker/break/error_location_module_func.abra", assertions: "typechecker/break/error_location_module_func.out" }, + { test: "typechecker/break/error_location_module_if.abra", assertions: "typechecker/break/error_location_module_if.out" }, + { test: "typechecker/break/error_unreachable_inside_while.abra", assertions: "typechecker/break/error_unreachable_inside_while.out" }, + { test: "typechecker/break/error_unreachable_inside_for.abra", assertions: "typechecker/break/error_unreachable_inside_for.out" }, + // Continue + { test: "typechecker/continue/continue_as_expr.abra", assertions: "typechecker/continue/continue_as_expr.out.json" }, + { test: "typechecker/continue/error_location_module.abra", assertions: "typechecker/continue/error_location_module.out" }, + { test: "typechecker/continue/error_location_module_func.abra", assertions: "typechecker/continue/error_location_module_func.out" }, + { test: "typechecker/continue/error_location_module_if.abra", assertions: "typechecker/continue/error_location_module_if.out" }, + { test: "typechecker/continue/error_unreachable_inside_while.abra", assertions: "typechecker/continue/error_unreachable_inside_while.out" }, + { test: "typechecker/continue/error_unreachable_inside_for.abra", assertions: "typechecker/continue/error_unreachable_inside_for.out" }, + // While + { test: "typechecker/while/while.1.abra", assertions: "typechecker/while/while.1.out.json" }, + { test: "typechecker/while/while.2.abra", assertions: "typechecker/while/while.2.out.json" }, + { test: "typechecker/while/while.3.abra", assertions: "typechecker/while/while.3.out.json" }, + { test: "typechecker/while/while.4.abra", assertions: "typechecker/while/while.4.out.json" }, + { test: "typechecker/while/error_bad_cond_type.abra", assertions: "typechecker/while/error_bad_cond_type.out" }, + { test: "typechecker/while/error_condition_invalid_destructuring_tuple.abra", assertions: "typechecker/while/error_condition_invalid_destructuring_tuple.out" }, + + // For + { test: "typechecker/for/for.1.abra", assertions: "typechecker/for/for.1.out.json" }, + { test: "typechecker/for/for.2.abra", assertions: "typechecker/for/for.2.out.json" }, + { test: "typechecker/for/for.3.abra", assertions: "typechecker/for/for.3.out.json" }, + { test: "typechecker/for/error_bad_iterator_option_type.abra", assertions: "typechecker/for/error_bad_iterator_option_type.out" }, + { test: "typechecker/for/error_bad_iterator.abra", assertions: "typechecker/for/error_bad_iterator.out" }, + { test: "typechecker/for/error_bad_iterator_unfilled_hole.abra", assertions: "typechecker/for/error_bad_iterator_unfilled_hole.out" }, + { test: "typechecker/for/error_duplicate_ident.abra", assertions: "typechecker/for/error_duplicate_ident.out" }, + { test: "typechecker/for/error_iteratee_invalid_destructuring_tuple.abra", assertions: "typechecker/for/error_iteratee_invalid_destructuring_tuple.out" }, + // Binding declaration + { test: "typechecker/bindingdecl/bindingdecl.abra", assertions: "typechecker/bindingdecl/bindingdecl.out.json" }, + { test: "typechecker/bindingdecl/bindingdecl_exported.abra", assertions: "typechecker/bindingdecl/bindingdecl_exported.out.json" }, + { test: "typechecker/bindingdecl/error_bare_var.abra", assertions: "typechecker/bindingdecl/error_bare_var.out" }, + { test: "typechecker/bindingdecl/error_duplicate_name.abra", assertions: "typechecker/bindingdecl/error_duplicate_name.out" }, + { test: "typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.1.abra", assertions: "typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.1.out" }, + { test: "typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.2.abra", assertions: "typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.2.out" }, + { test: "typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.3.abra", assertions: "typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.3.out" }, + { test: "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_few.1.abra", assertions: "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_few.1.out" }, + { test: "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_few.2.abra", assertions: "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_few.2.out" }, + { test: "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_many.1.abra", assertions: "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_many.1.out" }, + { test: "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_many.2.abra", assertions: "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_many.2.out" }, + { test: "typechecker/bindingdecl/error_type_mismatch_val_destructured_tuple.abra", assertions: "typechecker/bindingdecl/error_type_mismatch_val_destructured_tuple.out" }, + { test: "typechecker/bindingdecl/error_uninitialized_val_destructured_tuple_no_annotation.abra", assertions: "typechecker/bindingdecl/error_uninitialized_val_destructured_tuple_no_annotation.out" }, + { test: "typechecker/bindingdecl/error_uninitialized_val_destructured_tuple_with_annotation.abra", assertions: "typechecker/bindingdecl/error_uninitialized_val_destructured_tuple_with_annotation.out" }, + { test: "typechecker/bindingdecl/error_uninitialized_val_no_annotation.abra", assertions: "typechecker/bindingdecl/error_uninitialized_val_no_annotation.out" }, + { test: "typechecker/bindingdecl/error_uninitialized_val_with_annotation.abra", assertions: "typechecker/bindingdecl/error_uninitialized_val_with_annotation.out" }, + { test: "typechecker/bindingdecl/error_type_mismatch_val.abra", assertions: "typechecker/bindingdecl/error_type_mismatch_val.out" }, + { test: "typechecker/bindingdecl/error_type_mismatch_var.abra", assertions: "typechecker/bindingdecl/error_type_mismatch_var.out" }, + { test: "typechecker/bindingdecl/error_type_mismatch_option.abra", assertions: "typechecker/bindingdecl/error_type_mismatch_option.out" }, + { test: "typechecker/bindingdecl/error_unfilled_holes.abra", assertions: "typechecker/bindingdecl/error_unfilled_holes.out" }, + { test: "typechecker/bindingdecl/error_illegal_value_type_enum.abra", assertions: "typechecker/bindingdecl/error_illegal_value_type_enum.out" }, + { test: "typechecker/bindingdecl/error_illegal_value_type_enum_container_variant.abra", assertions: "typechecker/bindingdecl/error_illegal_value_type_enum_container_variant.out" }, + { test: "typechecker/bindingdecl/error_illegal_value_type_type.abra", assertions: "typechecker/bindingdecl/error_illegal_value_type_type.out" }, + { test: "typechecker/bindingdecl/error_export_bad_scope.abra", assertions: "typechecker/bindingdecl/error_export_bad_scope.out" }, + // Function declaration + { test: "typechecker/funcdecl/funcdecl.1.abra", assertions: "typechecker/funcdecl/funcdecl.1.out.json" }, + { test: "typechecker/funcdecl/funcdecl.2.abra", assertions: "typechecker/funcdecl/funcdecl.2.out.json" }, + { test: "typechecker/funcdecl/funcdecl.3.abra", assertions: "typechecker/funcdecl/funcdecl.3.out.json" }, + { test: "typechecker/funcdecl/funcdecl.4.abra", assertions: "typechecker/funcdecl/funcdecl.4.out.json" }, + { test: "typechecker/funcdecl/funcdecl.5.abra", assertions: "typechecker/funcdecl/funcdecl.5.out.json" }, + { test: "typechecker/funcdecl/funcdecl.6.abra", assertions: "typechecker/funcdecl/funcdecl.6.out.json" }, + { test: "typechecker/funcdecl/funcdecl.7.abra", assertions: "typechecker/funcdecl/funcdecl.7.out.json" }, + { test: "typechecker/funcdecl/funcdecl_exported.abra", assertions: "typechecker/funcdecl/funcdecl_exported.out.json" }, + { test: "typechecker/funcdecl/funcdecl_generics.abra", assertions: "typechecker/funcdecl/funcdecl_generics.out.json" }, + { test: "typechecker/funcdecl/error_duplicate_func.abra", assertions: "typechecker/funcdecl/error_duplicate_func.out" }, + { test: "typechecker/funcdecl/error_duplicate_param.abra", assertions: "typechecker/funcdecl/error_duplicate_param.out" }, + { test: "typechecker/funcdecl/error_duplicate_variable.abra", assertions: "typechecker/funcdecl/error_duplicate_variable.out" }, + { test: "typechecker/funcdecl/error_invalid_param_type.abra", assertions: "typechecker/funcdecl/error_invalid_param_type.out" }, + { test: "typechecker/funcdecl/error_invalid_req_param_position.abra", assertions: "typechecker/funcdecl/error_invalid_req_param_position.out" }, + { test: "typechecker/funcdecl/error_invalid_return_type.abra", assertions: "typechecker/funcdecl/error_invalid_return_type.out" }, + { test: "typechecker/funcdecl/error_invalid_vararg_position.abra", assertions: "typechecker/funcdecl/error_invalid_vararg_position.out" }, + { test: "typechecker/funcdecl/error_invalid_vararg_type.abra", assertions: "typechecker/funcdecl/error_invalid_vararg_type.out" }, + { test: "typechecker/funcdecl/error_param_unfilled_holes.1.abra", assertions: "typechecker/funcdecl/error_param_unfilled_holes.1.out" }, + { test: "typechecker/funcdecl/error_param_unfilled_holes.2.abra", assertions: "typechecker/funcdecl/error_param_unfilled_holes.2.out" }, + { test: "typechecker/funcdecl/error_type_mismatch_param_default_value.1.abra", assertions: "typechecker/funcdecl/error_type_mismatch_param_default_value.1.out" }, + { test: "typechecker/funcdecl/error_type_mismatch_param_default_value.2.abra", assertions: "typechecker/funcdecl/error_type_mismatch_param_default_value.2.out" }, + { test: "typechecker/funcdecl/error_type_mismatch_param_default_value.3.abra", assertions: "typechecker/funcdecl/error_type_mismatch_param_default_value.3.out" }, + { test: "typechecker/funcdecl/error_type_mismatch_param_default_value.4.abra", assertions: "typechecker/funcdecl/error_type_mismatch_param_default_value.4.out" }, + { test: "typechecker/funcdecl/error_alias_type_mismatch.abra", assertions: "typechecker/funcdecl/error_alias_type_mismatch.out" }, + { test: "typechecker/funcdecl/error_invalid_vararg_type_option.abra", assertions: "typechecker/funcdecl/error_invalid_vararg_type_option.out" }, + { test: "typechecker/funcdecl/error_param_default_value_ident.abra", assertions: "typechecker/funcdecl/error_param_default_value_ident.out" }, + { test: "typechecker/funcdecl/error_return_type_mismatch.abra", assertions: "typechecker/funcdecl/error_return_type_mismatch.out" }, + { test: "typechecker/funcdecl/error_return_type_mismatch_empty.abra", assertions: "typechecker/funcdecl/error_return_type_mismatch_empty.out" }, + { test: "typechecker/funcdecl/error_return_type_mismatch_stmt.abra", assertions: "typechecker/funcdecl/error_return_type_mismatch_stmt.out" }, + { test: "typechecker/funcdecl/default_param_value_call.1.abra", assertions: "typechecker/funcdecl/default_param_value_call.1.out.json" }, + { test: "typechecker/funcdecl/default_param_value_call.2.abra", assertions: "typechecker/funcdecl/default_param_value_call.2.out.json" }, + { test: "typechecker/funcdecl/default_param_value_call.3.abra", assertions: "typechecker/funcdecl/default_param_value_call.3.out.json" }, + { test: "typechecker/funcdecl/default_param_value_call.4.abra", assertions: "typechecker/funcdecl/default_param_value_call.4.out.json" }, + { test: "typechecker/funcdecl/default_param_value_call.5.abra", assertions: "typechecker/funcdecl/default_param_value_call.5.out.json" }, + { test: "typechecker/funcdecl/default_param_value_call.6.abra", assertions: "typechecker/funcdecl/default_param_value_call.6.out.json" }, + { test: "typechecker/funcdecl/default_param_value_call.7.abra", assertions: "typechecker/funcdecl/default_param_value_call.7.out.json" }, + { test: "typechecker/funcdecl/default_param_value_call.8.abra", assertions: "typechecker/funcdecl/default_param_value_call.8.out.json" }, + { test: "typechecker/funcdecl/default_param_value_call.9.abra", assertions: "typechecker/funcdecl/default_param_value_call.9.out.json" }, + { test: "typechecker/funcdecl/default_param_value_accessor.abra", assertions: "typechecker/funcdecl/default_param_value_accessor.out.json" }, + { test: "typechecker/funcdecl/error_self_standalone.abra", assertions: "typechecker/funcdecl/error_self_standalone.out" }, + { test: "typechecker/funcdecl/error_generics_param_type_mismatch.abra", assertions: "typechecker/funcdecl/error_generics_param_type_mismatch.out" }, + { test: "typechecker/funcdecl/error_generics_return_type_mismatch.abra", assertions: "typechecker/funcdecl/error_generics_return_type_mismatch.out" }, + { test: "typechecker/funcdecl/error_export_bad_scope.abra", assertions: "typechecker/funcdecl/error_export_bad_scope.out" }, + + // Type declaration + { test: "typechecker/typedecl/typedecl_exported.abra", assertions: "typechecker/typedecl/typedecl_exported.out.json" }, + { test: "typechecker/typedecl/typedecl.1.abra", assertions: "typechecker/typedecl/typedecl.1.out.json" }, + { test: "typechecker/typedecl/typedecl.2.abra", assertions: "typechecker/typedecl/typedecl.2.out.json" }, + { test: "typechecker/typedecl/error_duplicate_field.abra", assertions: "typechecker/typedecl/error_duplicate_field.out" }, + { test: "typechecker/typedecl/error_method_bad_self_position.abra", assertions: "typechecker/typedecl/error_method_bad_self_position.out" }, + { test: "typechecker/typedecl/error_field_initializer_type_mismatch.abra", assertions: "typechecker/typedecl/error_field_initializer_type_mismatch.out" }, + { test: "typechecker/typedecl/error_invalid_eq_signature.1.abra", assertions: "typechecker/typedecl/error_invalid_eq_signature.1.out" }, + { test: "typechecker/typedecl/error_invalid_eq_signature.2.abra", assertions: "typechecker/typedecl/error_invalid_eq_signature.2.out" }, + { test: "typechecker/typedecl/error_invalid_hash_signature.abra", assertions: "typechecker/typedecl/error_invalid_hash_signature.out" }, + { test: "typechecker/typedecl/error_invalid_tostring_signature.abra", assertions: "typechecker/typedecl/error_invalid_tostring_signature.out" }, + { test: "typechecker/typedecl/error_duplicate_type_func.abra", assertions: "typechecker/typedecl/error_duplicate_type_func.out" }, + { test: "typechecker/typedecl/error_duplicate_type_type.abra", assertions: "typechecker/typedecl/error_duplicate_type_type.out" }, + { test: "typechecker/typedecl/error_duplicate_type_enum.abra", assertions: "typechecker/typedecl/error_duplicate_type_enum.out" }, + // Enum declaration + { test: "typechecker/enumdecl/enumdecl_exported.abra", assertions: "typechecker/enumdecl/enumdecl_exported.out.json" }, + { test: "typechecker/enumdecl/enumdecl.1.abra", assertions: "typechecker/enumdecl/enumdecl.1.out.json" }, + { test: "typechecker/enumdecl/enumdecl_Result_shorthand.abra", assertions: "typechecker/enumdecl/enumdecl_Result_shorthand.out.json" }, + { test: "typechecker/enumdecl/error_duplicate_enum_enum.abra", assertions: "typechecker/enumdecl/error_duplicate_enum_enum.out" }, + { test: "typechecker/enumdecl/error_duplicate_enum_func.abra", assertions: "typechecker/enumdecl/error_duplicate_enum_func.out" }, + { test: "typechecker/enumdecl/error_duplicate_enum_type.abra", assertions: "typechecker/enumdecl/error_duplicate_enum_type.out" }, + { test: "typechecker/enumdecl/error_duplicate_variant.abra", assertions: "typechecker/enumdecl/error_duplicate_variant.out" }, + { test: "typechecker/enumdecl/error_duplicate_variant_field.abra", assertions: "typechecker/enumdecl/error_duplicate_variant_field.out" }, + { test: "typechecker/enumdecl/error_invalid_eq_signature.1.abra", assertions: "typechecker/enumdecl/error_invalid_eq_signature.1.out" }, + { test: "typechecker/enumdecl/error_invalid_eq_signature.2.abra", assertions: "typechecker/enumdecl/error_invalid_eq_signature.2.out" }, + { test: "typechecker/enumdecl/error_invalid_hash_signature.abra", assertions: "typechecker/enumdecl/error_invalid_hash_signature.out" }, + { test: "typechecker/enumdecl/error_invalid_tostring_signature.abra", assertions: "typechecker/enumdecl/error_invalid_tostring_signature.out" }, + { test: "typechecker/enumdecl/error_method_bad_self_position.abra", assertions: "typechecker/enumdecl/error_method_bad_self_position.out" }, + { test: "typechecker/enumdecl/error_variant_field_initializer_type_mismatch.abra", assertions: "typechecker/enumdecl/error_variant_field_initializer_type_mismatch.out" }, + + // Returns + { test: "typechecker/return/return.1.abra", assertions: "typechecker/return/return.1.out.json" }, + { test: "typechecker/return/return.2.abra", assertions: "typechecker/return/return.2.out.json" }, + { test: "typechecker/return/return.3.abra", assertions: "typechecker/return/return.3.out.json" }, + { test: "typechecker/return/as_expr_error_never.abra", assertions: "typechecker/return/as_expr_error_never.out" }, + { test: "typechecker/return/error_location.abra", assertions: "typechecker/return/error_location.out" }, + { test: "typechecker/return/error_type_mismatch.abra", assertions: "typechecker/return/error_type_mismatch.out" }, + { test: "typechecker/return/error_type_mismatch_unit.abra", assertions: "typechecker/return/error_type_mismatch_unit.out" }, + { test: "typechecker/return/error_unreachable_stmt_plain.abra", assertions: "typechecker/return/error_unreachable_stmt_plain.out" }, + { test: "typechecker/return/error_unreachable_stmt_if_inside.abra", assertions: "typechecker/return/error_unreachable_stmt_if_inside.out" }, + { test: "typechecker/return/error_unreachable_stmt_if_outside.abra", assertions: "typechecker/return/error_unreachable_stmt_if_outside.out" }, + { test: "typechecker/return/error_unreachable_stmt_match_inside.abra", assertions: "typechecker/return/error_unreachable_stmt_match_inside.out" }, + { test: "typechecker/return/error_unreachable_stmt_match_outside.abra", assertions: "typechecker/return/error_unreachable_stmt_match_outside.out" }, + { test: "typechecker/return/error_unreachable_stmt_while_inside.1.abra", assertions: "typechecker/return/error_unreachable_stmt_while_inside.1.out" }, + { test: "typechecker/return/error_unreachable_stmt_while_inside.2.abra", assertions: "typechecker/return/error_unreachable_stmt_while_inside.2.out" }, + { test: "typechecker/return/error_unreachable_stmt_while_outside.1.abra", assertions: "typechecker/return/error_unreachable_stmt_while_outside.1.out" }, + { test: "typechecker/return/error_unreachable_stmt_while_outside.2.abra", assertions: "typechecker/return/error_unreachable_stmt_while_outside.2.out" }, + { test: "typechecker/return/error_unreachable_stmt_for_inside.1.abra", assertions: "typechecker/return/error_unreachable_stmt_for_inside.1.out" }, + { test: "typechecker/return/error_unreachable_stmt_for_inside.2.abra", assertions: "typechecker/return/error_unreachable_stmt_for_inside.2.out" }, + { test: "typechecker/return/error_unreachable_stmt_for_outside.1.abra", assertions: "typechecker/return/error_unreachable_stmt_for_outside.1.out" }, + { test: "typechecker/return/error_unreachable_stmt_for_outside.2.abra", assertions: "typechecker/return/error_unreachable_stmt_for_outside.2.out" }, + + // Imports + { test: "typechecker/import/import.1.abra", assertions: "typechecker/import/import.1.out.json" }, + { test: "typechecker/import/import.2.abra", assertions: "typechecker/import/import.2.out.json" }, + { test: "typechecker/import/error_assignment_to_aliased_imported_variable.abra", assertions: "typechecker/import/error_assignment_to_aliased_imported_variable.out" }, + { test: "typechecker/import/error_assignment_to_imported_variable.abra", assertions: "typechecker/import/error_assignment_to_imported_variable.out" }, + + { test: "typechecker/import/error_no_file_exists.abra", assertions: "typechecker/import/error_no_file_exists.out" }, + { test: "typechecker/import/error_nonrelative_not_found.abra", assertions: "typechecker/import/error_nonrelative_not_found.out" }, + { test: "typechecker/import/error_circular_dependency.1/mod.1.abra", assertions: "typechecker/import/error_circular_dependency.1/mod.1.out" }, + { test: "typechecker/import/error_circular_dependency.2/mod.1.abra", assertions: "typechecker/import/error_circular_dependency.2/mod.1.out" }, + { test: "typechecker/import/error_duplicate_import_name.1.abra", assertions: "typechecker/import/error_duplicate_import_name.1.out" }, + { test: "typechecker/import/error_duplicate_import_name.2.abra", assertions: "typechecker/import/error_duplicate_import_name.2.out" }, + { test: "typechecker/import/error_duplicate_variable_name.1.abra", assertions: "typechecker/import/error_duplicate_variable_name.1.out" }, + { test: "typechecker/import/error_duplicate_variable_name.2.abra", assertions: "typechecker/import/error_duplicate_variable_name.2.out" }, + { test: "typechecker/import/error_duplicate_func_name.1.abra", assertions: "typechecker/import/error_duplicate_func_name.1.out" }, + { test: "typechecker/import/error_duplicate_func_name.2.abra", assertions: "typechecker/import/error_duplicate_func_name.2.out" }, + { test: "typechecker/import/error_imported_value_type_mismatch.abra", assertions: "typechecker/import/error_imported_value_type_mismatch.out" }, + { test: "typechecker/import/error_no_exported_value.abra", assertions: "typechecker/import/error_no_exported_value.out" }, + { test: "typechecker/import/error_duplicate_enum_name.1.abra", assertions: "typechecker/import/error_duplicate_enum_name.1.out" }, + { test: "typechecker/import/error_duplicate_enum_name.2.abra", assertions: "typechecker/import/error_duplicate_enum_name.2.out" }, + { test: "typechecker/import/error_duplicate_enum_name.3.abra", assertions: "typechecker/import/error_duplicate_enum_name.3.out" }, + { test: "typechecker/import/error_duplicate_enum_name.4.abra", assertions: "typechecker/import/error_duplicate_enum_name.4.out" }, + { test: "typechecker/import/error_duplicate_func_name.3.abra", assertions: "typechecker/import/error_duplicate_func_name.3.out" }, + { test: "typechecker/import/error_duplicate_func_name.4.abra", assertions: "typechecker/import/error_duplicate_func_name.4.out" }, + { test: "typechecker/import/error_duplicate_import_name.3.abra", assertions: "typechecker/import/error_duplicate_import_name.3.out" }, + { test: "typechecker/import/error_duplicate_import_name.4.abra", assertions: "typechecker/import/error_duplicate_import_name.4.out" }, + { test: "typechecker/import/error_duplicate_type_name.1.abra", assertions: "typechecker/import/error_duplicate_type_name.1.out" }, + { test: "typechecker/import/error_duplicate_type_name.2.abra", assertions: "typechecker/import/error_duplicate_type_name.2.out" }, + { test: "typechecker/import/error_duplicate_type_name.3.abra", assertions: "typechecker/import/error_duplicate_type_name.3.out" }, + { test: "typechecker/import/error_duplicate_type_name.4.abra", assertions: "typechecker/import/error_duplicate_type_name.4.out" }, + { test: "typechecker/import/error_duplicate_variable_name.3.abra", assertions: "typechecker/import/error_duplicate_variable_name.3.out" }, + { test: "typechecker/import/error_duplicate_variable_name.4.abra", assertions: "typechecker/import/error_duplicate_variable_name.4.out" }, + { test: "typechecker/import/error_imported_type_mismatch.1.abra", assertions: "typechecker/import/error_imported_type_mismatch.1.out" }, + { test: "typechecker/import/import_type_identifier.1.abra", assertions: "typechecker/import/import_type_identifier.1.out.json" }, + { test: "typechecker/import/import_type_identifier.2.abra", assertions: "typechecker/import/import_type_identifier.2.out.json" }, + { test: "typechecker/import/error_alias_duplicate_name.abra", assertions: "typechecker/import/error_alias_duplicate_name.out" }, + { test: "typechecker/import/error_alias_questiondot_access.abra", assertions: "typechecker/import/error_alias_questiondot_access.out" }, + { test: "typechecker/import/error_alias_unknown_import.abra", assertions: "typechecker/import/error_alias_unknown_import.out" }, +] + +const COMPILER_TESTS = [ + { test: "compiler/ints.abra" }, + { test: "compiler/floats.abra" }, + { test: "compiler/bools.abra" }, + { test: "compiler/strings.abra" }, + { test: "compiler/arrays.abra" }, + { test: "compiler/functions.abra" }, + { test: "compiler/optionals.abra" }, + { test: "compiler/ifs.abra" }, + { test: "compiler/loops.abra" }, + { test: "compiler/types.abra" }, + { test: "compiler/enums.abra" }, + { test: "compiler/tuples.abra" }, + { test: "compiler/maps.abra" }, + { test: "compiler/sets.abra" }, + { test: "compiler/match.abra" }, + { test: 'compiler/process.abra', args: ['-f', 'bar', '--baz', 'qux'], env: { FOO: 'bar' } } +] + +async function main() { + let numPass = 0 + let numFail = 0 + let numErr = 0 + let numTests = 0 + + const lexerPath = `${__dirname}/../src/lexer.test.abra` + const parserPath = `${__dirname}/../src/parser.test.abra` + const typecheckerPath = `${__dirname}/../src/typechecker.test.abra` + const compilerPath = `${__dirname}/../src/compiler.test.abra` + + const runners = [ + { + runner: new TestRunner('lexer_test', lexerPath), + tests: LEXER_TESTS, + }, + { + runner: new TestRunner('parser_test', parserPath), + tests: PARSER_TESTS, + }, + { + runner: new TestRunner('typechecker_test', typecheckerPath), + tests: TYPECHECKER_TESTS, + }, + { + runner: new TestRunner('compiler_test', compilerPath), + tests: COMPILER_TESTS, + }, + ] + + for (const { runner, tests } of runners) { + numTests += tests.length + const results = await runner.runTests(tests) + numPass += results.numPass + numFail += results.numFail + numErr += results.numErr + } + + console.log('\nTotals:') + const passMsg = ` Pass: ${numPass} / ${numTests}` + console.log(numPass === numTests ? green(passMsg) : passMsg) + const failMsg = ` Fail: ${numFail} / ${numTests}` + console.log(numFail > 0 ? magenta(failMsg) : failMsg) + const errMsg = ` Error: ${numErr} / ${numTests}` + console.log(numErr > 0 ? magenta(errMsg) : errMsg) + + if (numPass !== numTests) + return process.exit(1) +} + +main() diff --git a/selfhost/test/test-runner.js b/selfhost/test/test-runner.js new file mode 100644 index 00000000..0b5fe419 --- /dev/null +++ b/selfhost/test/test-runner.js @@ -0,0 +1,172 @@ +const childProcess = require('child_process') +const fs = require('fs/promises') + +class TestRunner { + constructor(runnerName, harnessPath) { + this.runnerName = runnerName + this.harnessPath = harnessPath + } + + async runTests(tests) { + console.log(`Running tests for ${this.runnerName}:`) + const runnerBin = `${process.cwd()}/._abra/${this.runnerName}` + try { + console.log(` Compiling test harness '${this.harnessPath}'\n`) + await runCommand('abra', ['build', '-o', this.runnerName, this.harnessPath]) + } catch (err) { + console.log(red(' Failed to compile test harness:')) + const errFmt = err.toString().split('\n').map(line => ` ${line}`).join('\n') + console.log(red(errFmt)) + return { numPass: 0, numFail: 0, numErr: tests.length } + } + + const results = [] + for (const { test, assertions, args, env } of tests) { + const result = !!assertions + ? await this._runTest(runnerBin, test, assertions) + : await this._runCompilerTest(runnerBin, test, args, env) + results.push(result) + } + + return this._outputResults(results) + } + + async _runTest(bin, testFile, outputFile) { + const testFilePath = `${__dirname}/${testFile}` + const outputFilePath = `${__dirname}/${outputFile}` + + try { + const [actual, expectedOutput] = await Promise.all([ + runCommand(bin, [testFilePath]), + fs.readFile(outputFilePath, { encoding: 'utf8' }), + ]) + + const expected = expectedOutput + .replaceAll('%FILE_NAME%', testFilePath) + .replaceAll('%TEST_DIR%', __dirname) + + if (actual !== expected) { + return { status: 'fail', testFile, expected, actual } + } + + return { status: 'pass', testFile } + } catch (error) { + return { status: 'error', testFile, error } + } + } + + async _runCompilerTest(bin, testFile, args = [], env = {}) { + const testFilePath = `${__dirname}/${testFile}` + + try { + const [actual, expectedOutput] = await Promise.all([ + runCommand('abra', [testFilePath, ...args], { COMPILER_BIN: bin, ...env }), + fs.readFile(testFilePath, { encoding: 'utf8' }), + ]) + + const re = /^\s*\/\/\/ Expect: (.*)$/ + const expectations = expectedOutput.split('\n') + .map((line, idx) => { + const match = re.exec(line) + if (!match) return null + + const expectation = match[1] + return [idx + 1, expectation] + }) + .filter(line => !!line) + + const actualLines = actual.trimEnd().split('\n') + let i = 0 + for (; i < actualLines.length; i++) { + const actual = actualLines[i] + const expected = expectations[i] + if (!expected || actual !== expected[1]) { + return { status: 'fail', testFile, expected, actual } + } + } + + return { status: 'pass', testFile } + } catch (error) { + return { status: 'error', testFile, error } + } + } + + _outputResults(results) { + let numPass = 0 + let numFail = 0 + let numErr = 0 + + for (const result of results) { + switch (result.status) { + case 'pass': { + numPass += 1 + console.log(green(` [PASS] ${result.testFile}`)) + break + } + case 'fail': { + numFail += 1 + console.log(magenta(` [FAIL] ${result.testFile}`)) + console.log('EXPECTED') + console.log(result.expected) + console.log('ACTUAL') + console.log(result.actual) + break + } + case 'error': { + numErr += 1 + console.log(red(` [ERROR] ${result.testFile}`)) + + const errFmt = result.error.toString().split('\n').map(line => ` ${line}`).join('\n') + console.log(red(errFmt)) + break + } + } + } + + console.log() + const passMsg = ` Pass: ${numPass} / ${results.length}` + console.log(numPass === results.length ? green(passMsg) : passMsg) + const failMsg = ` Fail: ${numFail} / ${results.length}` + console.log(numFail > 0 ? magenta(failMsg) : failMsg) + const errMsg = ` Error: ${numErr} / ${results.length}` + console.log(numErr > 0 ? magenta(errMsg) : errMsg) + + return { numPass, numFail, numErr } + } +} + +function runCommand(command, args, envVars = {}) { + const env = { ...process.env, ...envVars } + const cmd = childProcess.spawn(command, args, { env }) + return new Promise((res, rej) => { + let stdoutBuf = '' + cmd.stdout.on('data', data => { stdoutBuf += data }) + + let stderrBuf = '' + cmd.stderr.on('data', data => { stderrBuf += data }) + + cmd.on('exit', code => code === 0 ? res(stdoutBuf) : rej(stdoutBuf + '\n' + stderrBuf)) + + cmd.on('error', err => rej(err)) + }) +} + +const colors = { + reset: "\x1b[0m", + black: "\x1b[30m", + red: "\x1b[31m", + green: "\x1b[32m", + yellow: "\x1b[33m", + blue: "\x1b[34m", + magenta: "\x1b[35m", + cyan: "\x1b[36m", + white: "\x1b[37m", + gray: "\x1b[90m", + crimson: "\x1b[38m" +} + +const red = str => `${colors.red}${str}${colors.reset}` +const green = str => `${colors.green}${str}${colors.reset}` +const magenta = str => `${colors.magenta}${str}${colors.reset}` + +module.exports = { TestRunner, red, green, magenta } diff --git a/selfhost_test/Cargo.toml b/selfhost_test/Cargo.toml deleted file mode 100644 index 7b3214ce..00000000 --- a/selfhost_test/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "selfhost_test" -version = "0.1.0" -edition = "2018" - -[dependencies] -abra_core = { path = "../abra_core" } - -[dev-dependencies] -assert_cmd = "2.0.10" -similar = "2.2.1" -itertools = "0.9.0" diff --git a/selfhost_test/src/lib.rs b/selfhost_test/src/lib.rs deleted file mode 100644 index be592962..00000000 --- a/selfhost_test/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[cfg(test)] -mod test_utils; - -#[cfg(test)] -mod tests; diff --git a/selfhost_test/src/test_utils.rs b/selfhost_test/src/test_utils.rs deleted file mode 100644 index 965bf08c..00000000 --- a/selfhost_test/src/test_utils.rs +++ /dev/null @@ -1,323 +0,0 @@ -use std::fs; -use std::collections::HashMap; -use std::env::temp_dir; -use std::path::Path; -use std::process::Command; -use assert_cmd::cargo::CommandCargoExt; -use similar::{TextDiff, ChangeTag}; -use abra_core::common::util::{get_project_root, random_string}; -use itertools::{EitherOrBoth, Itertools}; - -enum TestType { - VsTxt(&'static str, &'static str), -} - -pub struct TestRunner { - runner_name: &'static str, - bin_path: String, - selfhosted_bin_path: Option, - tests: Vec, -} - -impl TestRunner { - pub fn lexer_test_runner() -> Self { - Self::test_runner("lexer", "lexer.test.abra", "lexer_test", true) - } - - pub fn parser_test_runner() -> Self { - Self::test_runner("parser", "parser.test.abra", "parser_test", true) - } - - pub fn typechecker_test_runner() -> Self { - Self::test_runner("typechecker", "typechecker.test.abra", "typechecker_test", true) - } - - pub fn compiler_test_runner() -> CompilerTestRunner { - let runner = Self::test_runner("compiler", "compiler.test.abra", "compiler_test", true); - - CompilerTestRunner { bin_path: runner.bin_path, selfhosted_bin_path: runner.selfhosted_bin_path, tests: vec![] } - } - - pub fn test_runner(runner_name: &'static str, src_file: &str, output_bin_file: &str, test_selfhosted: bool) -> Self { - let bin_path = build_test_runner_using_rust_impl(&src_file, &output_bin_file); - - let selfhosted_bin_path = if test_selfhosted { - Some(build_test_runner_using_selfhosted_impl(runner_name, src_file, output_bin_file)) - } else { - None - }; - Self { runner_name, bin_path, selfhosted_bin_path, tests: vec![] } - } - - pub fn add_test_vs_file(mut self, test_path: &'static str, txt_path: &'static str) -> Self { - self.tests.push(TestType::VsTxt(test_path, txt_path)); - self - } - - pub fn run_tests(self) { - let project_root = get_project_root().unwrap(); - - let selfhost_dir = project_root.join("selfhost"); - - let abra_std_dir = project_root.join("abra_core/std"); - let abra_std_dir = abra_std_dir.to_str().unwrap(); - - let Self { runner_name, bin_path, selfhosted_bin_path, tests } = self; - - let mut failures = vec![]; - for test in tests { - let (test_path, expected_output) = match test { - TestType::VsTxt(test_file_path, comparison_file_path) => { - let test_dir = selfhost_dir.join("test"); - let test_path = test_dir.join(test_file_path); - let test_path = test_path.to_str().unwrap().to_string(); - println!("Running {runner_name} test (vs file) {test_path}"); - - let comparison_path = test_dir.join(comparison_file_path); - let comparison = std::fs::read_to_string(&comparison_path).unwrap_or_else(|_| { - println!("No such file {}", &comparison_file_path); - panic!(); - }); - let comparison = comparison.replace("%FILE_NAME%", &test_path); - - let test_dir_path = test_dir.to_str().unwrap().to_string(); - let comparison = comparison.replace("%TEST_DIR%", &test_dir_path); - - (test_path, comparison) - } - }; - - let output = Command::new(&bin_path) - .env("ABRA_HOME", &abra_std_dir) - .arg(&test_path) - .output() - .unwrap(); - assert!(output.stderr.is_empty(), "Runtime error: {}", String::from_utf8(output.stderr).unwrap()); - let abra_output = String::from_utf8(output.stdout).unwrap(); - - if expected_output != abra_output { - eprintln!(" Difference detected between:"); - eprintln!(" (The expected output is the 'old' and abra output is the 'new')"); - let diff = TextDiff::from_lines(&expected_output, &abra_output); - for change in diff.iter_all_changes() { - let sign = match change.tag() { - ChangeTag::Equal => " ", - ChangeTag::Delete => "-", - ChangeTag::Insert => "+", - }; - eprint!(" {sign}{change}"); - } - if selfhosted_bin_path.is_some() { - failures.push(format!("{test_path} (not selfhost-compiled)")); - } else { - failures.push(test_path.clone()); - } - } - - if let Some(selfhosted_bin_path) = &selfhosted_bin_path { - let output = Command::new(&selfhosted_bin_path) - .env("ABRA_HOME", &abra_std_dir) - .arg(&test_path) - .output() - .unwrap(); - assert!(output.stderr.is_empty(), "Runtime error: {}", String::from_utf8(output.stderr).unwrap()); - let abra_output = String::from_utf8(output.stdout).unwrap(); - - if expected_output != abra_output { - eprintln!(" Difference detected between:"); - eprintln!(" (The expected output is the 'old' and abra selfhosted output is the 'new')"); - let diff = TextDiff::from_lines(&expected_output, &abra_output); - for change in diff.iter_all_changes() { - let sign = match change.tag() { - ChangeTag::Equal => " ", - ChangeTag::Delete => "-", - ChangeTag::Insert => "+", - }; - eprint!(" {sign}{change}"); - } - failures.push(format!("{test_path} (selfhost-compiled)")); - } - } - } - - if !failures.is_empty() { - eprintln!("Failures running {runner_name} tests:"); - for test_path in failures { - eprintln!(" Test path '{}' failed", &test_path) - } - panic!("Failures running {} tests!", runner_name); - } else { - println!("All tests passed for {runner_name}!") - } - } -} - -struct CompilerTest { - test_path: &'static str, - program_args: &'static [&'static str], - env: &'static [(&'static str, &'static str)], -} - -pub struct CompilerTestRunner { - bin_path: String, - selfhosted_bin_path: Option, - tests: Vec, -} - -impl CompilerTestRunner { - pub fn add_test(self, test_path: &'static str) -> Self { - self.add_test_with_args_and_env(test_path, &[], &[]) - } - - pub fn add_test_with_args_and_env(mut self, test_path: &'static str, program_args: &'static [&'static str], env: &'static [(&'static str, &'static str)]) -> Self { - self.tests.push(CompilerTest { test_path, program_args, env }); - self - } - - pub fn run_tests(self) { - let mut failures = vec![]; - let selfhost_dir = get_project_root().unwrap().join("selfhost"); - - let abra_wrapper_script = selfhost_dir.join("abra"); - - for test in self.tests { - let CompilerTest { test_path, program_args, env } = test; - let test_path = selfhost_dir.join("test").join(test_path); - let test_path = test_path.to_str().unwrap().to_string(); - let test_file = fs::read_to_string(&test_path).unwrap_or_else(|_| { - println!("No such file {}", &test_path); - panic!(); - }); - - let output = Command::new(&abra_wrapper_script) - .current_dir(&selfhost_dir) - .env("COMPILER_BIN", &self.bin_path) - .envs(env.to_vec().into_iter().collect::>()) - .arg(&test_path) - .args(program_args) - .output() - .unwrap(); - if !output.stderr.is_empty() { - eprintln!("Compilation error: {}", String::from_utf8(output.stderr).unwrap()); - failures.push((test_path, "reference")); - continue; - } - let output = String::from_utf8(output.stdout).unwrap(); - - let prefix = "/// Expect: "; - let expectations = test_file.lines() - .map(|line| line.trim()) - .enumerate() - .filter(|(_, line)| line.starts_with(prefix)) - .map(|(line_num, line)| (line_num + 1, line.replace(prefix, ""))) - .collect_vec(); - - let mut outputs = vec![(output, "reference")]; - - if let Some(selfhosted_bin_path) = &self.selfhosted_bin_path { - let project_root = get_project_root().unwrap(); - - let selfhost_dir = project_root.join("selfhost"); - - let output = Command::new(&abra_wrapper_script) - .current_dir(&selfhost_dir) - .env("COMPILER_BIN", &selfhosted_bin_path) - .envs(env.to_vec().into_iter().collect::>()) - .arg(&test_path) - .args(program_args) - .output() - .unwrap(); - assert!(output.stderr.is_empty(), "Runtime error: {}", String::from_utf8(output.stderr).unwrap()); - let output = String::from_utf8(output.stdout).unwrap(); - - outputs.push((output, "selfhosted")); - } - - for (output, implementation) in outputs { - for pair in expectations.iter().zip_longest(output.lines()) { - match pair { - EitherOrBoth::Both((line_num, expected), actual) => { - if expected != actual { - eprintln!("Expectation mismatch at {}:{} (expected '{}' but got '{}')", &test_path, line_num, expected, actual); - failures.push((test_path.clone(), implementation)); - break; - } - } - EitherOrBoth::Left((line_num, expected)) => { - eprintln!("Expected: {} (line {}), but reached end of output", expected, line_num); - failures.push((test_path.clone(), implementation)); - break; - } - EitherOrBoth::Right(actual) => { - eprintln!("Received line: {}, but there were no more expectations", actual); - failures.push((test_path.clone(), implementation)); - break; - } - } - } - } - } - - if !failures.is_empty() { - eprintln!("Failures running compiler tests:"); - for (test_path, implementation) in failures { - eprintln!(" Test path '{}' failed (testing {})", &test_path, implementation) - } - panic!("Failures running compiler tests!"); - } else { - println!("All tests passed for compiler!") - } - } -} - -fn build_test_runner_using_rust_impl(runner_src_file: &str, output_bin_file: &str) -> String { - let selfhost_dir = get_project_root().unwrap().join("selfhost"); - let build_dir = if let Some(test_temp_dir) = std::env::var("TEST_TMP_DIR").ok() { - let dir = Path::new(&test_temp_dir).join(random_string(12)); - fs::create_dir(&dir).unwrap(); - dir - } else { - temp_dir() - }; - - println!("Building {}...", &runner_src_file); - let output = Command::cargo_bin("abra").unwrap() - .arg("build") - .arg(&selfhost_dir.join("src").join(runner_src_file)) - .arg("-o") - .arg(output_bin_file) - .arg("-b") - .arg(&build_dir) - .output() - .unwrap(); - assert!(output.stderr.is_empty(), "Compilation error: {}", String::from_utf8(output.stderr).unwrap()); - - let runner_bin = build_dir.join(".abra").join(output_bin_file).to_str().unwrap().to_string(); - println!("...built {}", &runner_bin); - - runner_bin -} - -fn build_test_runner_using_selfhosted_impl(runner_name: &str, src_file: &str, output_bin_file: &str) -> String { - let selfhosted_compiler_bin = build_test_runner_using_rust_impl("compiler.test.abra", &format!("selfhosted_compiler_for_{}_tests", runner_name)); - - let project_root = get_project_root().unwrap(); - let selfhost_dir = project_root.join("selfhost"); - let src_file = &selfhost_dir.join("src").join(&src_file); - let abra_wrapper_script = selfhost_dir.join("abra"); - let output = Command::new(&abra_wrapper_script) - .current_dir(&selfhost_dir) - .env("COMPILER_BIN", &selfhosted_compiler_bin) - .arg("build") - .arg("-o") - .arg(&output_bin_file) - .arg(&src_file) - .output() - .unwrap(); - if !output.stderr.is_empty() { - eprintln!("Failed to build test runner '{runner_name}'"); - eprintln!(" Failed to compile {src_file:?} using selfhosted compiler: {}", String::from_utf8(output.stderr).unwrap()); - panic!(); - } - selfhost_dir.join("._abra").join(&output_bin_file).to_str().unwrap().to_owned() -} diff --git a/selfhost_test/src/tests.rs b/selfhost_test/src/tests.rs deleted file mode 100644 index 9a976006..00000000 --- a/selfhost_test/src/tests.rs +++ /dev/null @@ -1,800 +0,0 @@ -use crate::test_utils::TestRunner; - -#[test] -fn lexer_tests() { - TestRunner::lexer_test_runner() - // Ints - .add_test_vs_file("lexer/ints.abra", "lexer/ints.out.json") - .add_test_vs_file("lexer/ints_error_leading_zero.abra", "lexer/ints_error_leading_zero.out") - .add_test_vs_file("lexer/ints_error_invalid_hex_first.abra", "lexer/ints_error_invalid_hex_first.out") - .add_test_vs_file("lexer/ints_error_invalid_hex_eof.abra", "lexer/ints_error_invalid_hex_eof.out") - .add_test_vs_file("lexer/ints_error_invalid_binary_first.abra", "lexer/ints_error_invalid_binary_first.out") - .add_test_vs_file("lexer/ints_error_invalid_binary_eof.abra", "lexer/ints_error_invalid_binary_eof.out") - // Floats - .add_test_vs_file("lexer/floats.abra", "lexer/floats.out.json") - .add_test_vs_file("lexer/floats_error_extra_period.abra", "lexer/floats_error_extra_period.out") - // Strings - .add_test_vs_file("lexer/strings.abra", "lexer/strings.out.json") - .add_test_vs_file("lexer/strings_error_unterminated_newline.abra", "lexer/strings_error_unterminated_newline.out") - .add_test_vs_file("lexer/strings_error_unterminated_eof.abra", "lexer/strings_error_unterminated_eof.out") - .add_test_vs_file("lexer/strings_error_unsupported_escape_sequence.abra", "lexer/strings_error_unsupported_escape_sequence.out") - .add_test_vs_file("lexer/strings_error_invalid_unicode_seq_length.abra", "lexer/strings_error_invalid_unicode_seq_length.out") - .add_test_vs_file("lexer/strings_error_invalid_unicode_seq_eof.abra", "lexer/strings_error_invalid_unicode_seq_eof.out") - .add_test_vs_file("lexer/strings_error_invalid_unicode_seq_char.abra", "lexer/strings_error_invalid_unicode_seq_char.out") - .add_test_vs_file("lexer/strings_interpolation.1.abra", "lexer/strings_interpolation.1.out.json") - .add_test_vs_file("lexer/strings_interpolation.2.abra", "lexer/strings_interpolation.2.out.json") - .add_test_vs_file("lexer/strings_interpolation_error_unclosed_brace.abra", "lexer/strings_interpolation_error_unclosed_brace.out") - - .add_test_vs_file("lexer/keywords.abra", "lexer/keywords.out.json") - // Symbols - .add_test_vs_file("lexer/symbols.abra", "lexer/symbols.out.json") - .add_test_vs_file("lexer/symbols_error_ampersand_eof.abra", "lexer/symbols_error_ampersand_eof.out") - .add_test_vs_file("lexer/symbols_error_ampersand_other.abra", "lexer/symbols_error_ampersand_other.out") - .add_test_vs_file("lexer/symbols_error_hash_eof.abra", "lexer/symbols_error_hash_eof.out") - .add_test_vs_file("lexer/symbols_error_hash_other.abra", "lexer/symbols_error_hash_other.out") - // Comments - .add_test_vs_file("lexer/comments_single_line.abra", "lexer/comments_single_line.out.json") - .add_test_vs_file("lexer/comments_multiline.abra", "lexer/comments_multiline.out.json") - .add_test_vs_file("lexer/comments_error_multiline_unclosed.abra", "lexer/comments_error_multiline_unclosed.out") - .run_tests(); -} - -#[test] -fn parser_tests() { - TestRunner::parser_test_runner() - // Literals - .add_test_vs_file("parser/literals.abra", "parser/literals.out.json") - .add_test_vs_file("parser/strings_interpolation.abra", "parser/strings_interpolation.out.json") - .add_test_vs_file("parser/strings_interpolation_error_invalid_expression.1.abra", "parser/strings_interpolation_error_invalid_expression.1.out") - .add_test_vs_file("parser/strings_interpolation_error_invalid_expression.2.abra", "parser/strings_interpolation_error_invalid_expression.2.out") - - // Binary - .add_test_vs_file("parser/binary.abra", "parser/binary.out.json") - .add_test_vs_file("parser/binary_error_eof.abra", "parser/binary_error_eof.out") - // Unary - .add_test_vs_file("parser/unary.abra", "parser/unary.out.json") - .add_test_vs_file("parser/unary_error_eof.abra", "parser/unary_error_eof.out") - // Grouped - .add_test_vs_file("parser/grouped.abra", "parser/grouped.out.json") - .add_test_vs_file("parser/grouped_error_eof.abra", "parser/grouped_error_eof.out") - .add_test_vs_file("parser/grouped_error_wrong_closing.abra", "parser/grouped_error_wrong_closing.out") - // Identifiers - .add_test_vs_file("parser/identifiers.abra", "parser/identifiers.out.json") - .add_test_vs_file("parser/invocation_transform_OptionSome.abra", "parser/invocation_transform_OptionSome.out.json") - // Accessors - .add_test_vs_file("parser/accessor.abra", "parser/accessor.out.json") - .add_test_vs_file("parser/accessor_error_eof.abra", "parser/accessor_error_eof.out") - .add_test_vs_file("parser/accessor_error_self.abra", "parser/accessor_error_self.out") - .add_test_vs_file("parser/accessor_error_None.abra", "parser/accessor_error_None.out") - // Invocation - .add_test_vs_file("parser/invocation.abra", "parser/invocation.out.json") - .add_test_vs_file("parser/invocation_error_eof.abra", "parser/invocation_error_eof.out") - .add_test_vs_file("parser/invocation_error_no_comma.abra", "parser/invocation_error_no_comma.out") - .add_test_vs_file("parser/invocation_error_no_rparen.abra", "parser/invocation_error_no_rparen.out") - .add_test_vs_file("parser/invocation_error_empty_typeargs.abra", "parser/invocation_error_empty_typeargs.out") - .add_test_vs_file("parser/invocation_error_invalid_typearg.abra", "parser/invocation_error_invalid_typearg.out") - .add_test_vs_file("parser/invocation_error_typeargs_eof.abra", "parser/invocation_error_typeargs_eof.out") - .add_test_vs_file("parser/invocation_error_typeargs_no_lparen.abra", "parser/invocation_error_typeargs_no_lparen.out") - // Array - .add_test_vs_file("parser/array.abra", "parser/array.out.json") - .add_test_vs_file("parser/array_error_eof.abra", "parser/array_error_eof.out") - .add_test_vs_file("parser/array_error_no_comma.abra", "parser/array_error_no_comma.out") - .add_test_vs_file("parser/array_error_no_rbrack.abra", "parser/array_error_no_rbrack.out") - // Set - .add_test_vs_file("parser/set.abra", "parser/set.out.json") - .add_test_vs_file("parser/set_error_eof.abra", "parser/set_error_eof.out") - .add_test_vs_file("parser/set_error_no_comma.abra", "parser/set_error_no_comma.out") - .add_test_vs_file("parser/set_error_no_rbrace.abra", "parser/set_error_no_rbrace.out") - // Map - .add_test_vs_file("parser/map.abra", "parser/map.out.json") - .add_test_vs_file("parser/map_error_bad_key.abra", "parser/map_error_bad_key.out") - .add_test_vs_file("parser/map_error_no_colon.abra", "parser/map_error_no_colon.out") - .add_test_vs_file("parser/map_error_no_colon_eof.abra", "parser/map_error_no_colon_eof.out") - .add_test_vs_file("parser/map_error_no_comma.abra", "parser/map_error_no_comma.out") - .add_test_vs_file("parser/map_error_no_rbrace.abra", "parser/map_error_no_rbrace.out") - .add_test_vs_file("parser/map_error_no_value.abra", "parser/map_error_no_value.out") - .add_test_vs_file("parser/map_error_no_value_eof.abra", "parser/map_error_no_value_eof.out") - // Tuples - .add_test_vs_file("parser/tuples.abra", "parser/tuples.out.json") - .add_test_vs_file("parser/tuples_error_eof.abra", "parser/tuples_error_eof.out") - .add_test_vs_file("parser/tuples_error_no_comma.abra", "parser/tuples_error_no_comma.out") - .add_test_vs_file("parser/tuples_error_no_rparen.abra", "parser/tuples_error_no_rparen.out") - // Lambdas - .add_test_vs_file("parser/lambdas.abra", "parser/lambdas.out.json") - .add_test_vs_file("parser/lambdas_error_bad_arg.abra", "parser/lambdas_error_bad_arg.out") - .add_test_vs_file("parser/lambdas_error_badparam_None.abra", "parser/lambdas_error_badparam_None.out") - .add_test_vs_file("parser/lambdas_error_badparam_nonident.abra", "parser/lambdas_error_badparam_nonident.out") - .add_test_vs_file("parser/lambdas_error_badparam_self.abra", "parser/lambdas_error_badparam_self.out") - .add_test_vs_file("parser/lambdas_error_noargs_no_arrow.abra", "parser/lambdas_error_noargs_no_arrow.out") - .add_test_vs_file("parser/lambdas_error_statement_body.abra", "parser/lambdas_error_statement_body.out") - // Indexing - .add_test_vs_file("parser/indexing.abra", "parser/indexing.out.json") - .add_test_vs_file("parser/indexing_error_eof.abra", "parser/indexing_error_eof.out") - .add_test_vs_file("parser/indexing_error_no_rbrack.abra", "parser/indexing_error_no_rbrack.out") - // Assignment - .add_test_vs_file("parser/assignment.abra", "parser/assignment.out.json") - .add_test_vs_file("parser/assignment_error_as_expr.abra", "parser/assignment_error_as_expr.out") - .add_test_vs_file("parser/assignment_error_assign_to_range.abra", "parser/assignment_error_assign_to_range.out") - .add_test_vs_file("parser/assignment_error_assignment_precedence.abra", "parser/assignment_error_assignment_precedence.out") - .add_test_vs_file("parser/assignment_error_illegal_target.abra", "parser/assignment_error_illegal_target.out") - // If - .add_test_vs_file("parser/if.abra", "parser/if.out.json") - .add_test_vs_file("parser/if_error_no_closing_pipe.abra", "parser/if_error_no_closing_pipe.out") - .add_test_vs_file("parser/if_error_no_then_block.abra", "parser/if_error_no_then_block.out") - // Match - .add_test_vs_file("parser/match.abra", "parser/match.out.json") - .add_test_vs_file("parser/match_error_case_bad_binding.abra", "parser/match_error_case_bad_binding.out") - .add_test_vs_file("parser/match_error_case_bad_path.abra", "parser/match_error_case_bad_path.out") - .add_test_vs_file("parser/match_error_case_bad_token.abra", "parser/match_error_case_bad_token.out") - .add_test_vs_file("parser/match_error_case_expr.abra", "parser/match_error_case_expr.out") - .add_test_vs_file("parser/match_error_case_no_case.abra", "parser/match_error_case_no_case.out") - .add_test_vs_file("parser/match_error_no_expr.abra", "parser/match_error_no_expr.out") - .add_test_vs_file("parser/match_error_no_lbrace.abra", "parser/match_error_no_lbrace.out") - .add_test_vs_file("parser/match_error_destructuring_case_empty_args.abra", "parser/match_error_destructuring_case_empty_args.out") - // Decorators - .add_test_vs_file("parser/decorator_error_bad_ident.abra", "parser/decorator_error_bad_ident.out") - .add_test_vs_file("parser/decorator_error_before_expr.abra", "parser/decorator_error_before_expr.out") - .add_test_vs_file("parser/decorator_error_before_invalid_stmt.abra", "parser/decorator_error_before_invalid_stmt.out") - .add_test_vs_file("parser/decorator_error_non_constant_arg.abra", "parser/decorator_error_non_constant_arg.out") - .add_test_vs_file("parser/decorator.abra", "parser/decorator.out.json") - - // Imports - .add_test_vs_file("parser/import.abra", "parser/import.out.json") - .add_test_vs_file("parser/import_error_alias_bad_alias.abra", "parser/import_error_alias_bad_alias.out") - .add_test_vs_file("parser/import_error_alias_bad_module.abra", "parser/import_error_alias_bad_module.out") - .add_test_vs_file("parser/import_error_alias_no_alias_eof.abra", "parser/import_error_alias_no_alias_eof.out") - .add_test_vs_file("parser/import_error_alias_no_as.abra", "parser/import_error_alias_no_as.out") - .add_test_vs_file("parser/import_error_alias_no_module.abra", "parser/import_error_alias_no_module.out") - .add_test_vs_file("parser/import_error_forbidden.abra", "parser/import_error_forbidden.out") - .add_test_vs_file("parser/import_error_list_2nd_nonident.abra", "parser/import_error_list_2nd_nonident.out") - .add_test_vs_file("parser/import_error_list_2nd_underscore.abra", "parser/import_error_list_2nd_underscore.out") - .add_test_vs_file("parser/import_error_list_bad_module.abra", "parser/import_error_list_bad_module.out") - .add_test_vs_file("parser/import_error_list_first_nonident.abra", "parser/import_error_list_first_nonident.out") - .add_test_vs_file("parser/import_error_list_no_comma.abra", "parser/import_error_list_no_comma.out") - .add_test_vs_file("parser/import_error_list_no_from.abra", "parser/import_error_list_no_from.out") - .add_test_vs_file("parser/import_error_list_no_module_eof.abra", "parser/import_error_list_no_module_eof.out") - // Exports - .add_test_vs_file("parser/export.abra", "parser/export.out.json") - .add_test_vs_file("parser/export_error_before_expr.abra", "parser/export_error_before_expr.out") - .add_test_vs_file("parser/export_error_before_invalid_statement.abra", "parser/export_error_before_invalid_statement.out") - - // While - .add_test_vs_file("parser/while.abra", "parser/while.out.json") - .add_test_vs_file("parser/while_error_as_expr.abra", "parser/while_error_as_expr.out") - // For - .add_test_vs_file("parser/for.abra", "parser/for.out.json") - .add_test_vs_file("parser/for_error_no_in.abra", "parser/for_error_no_in.out") - .add_test_vs_file("parser/for_error_no_iterator.abra", "parser/for_error_no_iterator.out") - - // Type identifiers - .add_test_vs_file("parser/typeidentifiers.abra", "parser/typeidentifiers.out.json") - .add_test_vs_file("parser/typeidentifiers_error_empty_typeargs.abra", "parser/typeidentifiers_error_empty_typeargs.out") - .add_test_vs_file("parser/typeidentifiers_error_empty_tuple.abra", "parser/typeidentifiers_error_empty_tuple.out") - .add_test_vs_file("parser/typeidentifiers_error_misplaced_typeargs.abra", "parser/typeidentifiers_error_misplaced_typeargs.out") - .add_test_vs_file("parser/typeidentifiers_error_no_base_ident.abra", "parser/typeidentifiers_error_no_base_ident.out") - .add_test_vs_file("parser/typeidentifiers_error_no_rbrack.abra", "parser/typeidentifiers_error_no_rbrack.out") - // Binding declaration - .add_test_vs_file("parser/bindingdecl.abra", "parser/bindingdecl.out.json") - .add_test_vs_file("parser/bindingdecl_error_bad_expr.abra", "parser/bindingdecl_error_bad_expr.out") - .add_test_vs_file("parser/bindingdecl_error_bad_ident.abra", "parser/bindingdecl_error_bad_ident.out") - .add_test_vs_file("parser/bindingdecl_error_no_expr.abra", "parser/bindingdecl_error_no_expr.out") - .add_test_vs_file("parser/bindingdecl_error_no_ident.abra", "parser/bindingdecl_error_no_ident.out") - // Function declaration - .add_test_vs_file("parser/functiondecl.abra", "parser/functiondecl.out.json") - .add_test_vs_file("parser/functiondecl_error_bad_name.abra", "parser/functiondecl_error_bad_name.out") - .add_test_vs_file("parser/functiondecl_error_no_parens.abra", "parser/functiondecl_error_no_parens.out") - .add_test_vs_file("parser/functiondecl_error_empty_typeparams.abra", "parser/functiondecl_error_empty_typeparams.out") - .add_test_vs_file("parser/functiondecl_error_typeparam_invalid.abra", "parser/functiondecl_error_typeparam_invalid.out") - .add_test_vs_file("parser/functiondecl_error_no_body.abra", "parser/functiondecl_error_no_body.out") - .add_test_vs_file("parser/functiondecl_error_self_default_value.abra", "parser/functiondecl_error_self_default_value.out") - .add_test_vs_file("parser/functiondecl_error_self_type_annotation.abra", "parser/functiondecl_error_self_type_annotation.out") - .add_test_vs_file("parser/functiondecl_error_self_variadic.abra", "parser/functiondecl_error_self_variadic.out") - // Type declaration - .add_test_vs_file("parser/typedecl.abra", "parser/typedecl.out.json") - .add_test_vs_file("parser/typedecl_error_exporting_method.abra", "parser/typedecl_error_exporting_method.out") - .add_test_vs_file("parser/typedecl_error_field_after_method.abra", "parser/typedecl_error_field_after_method.out") - .add_test_vs_file("parser/typedecl_error_illegal_body_part.abra", "parser/typedecl_error_illegal_body_part.out") - // Enum declaration - .add_test_vs_file("parser/enumdecl.abra", "parser/enumdecl.out.json") - .add_test_vs_file("parser/enumdecl_error_container_no_typeannotation.abra", "parser/enumdecl_error_container_no_typeannotation.out") - .add_test_vs_file("parser/enumdecl_error_empty_container_variant.abra", "parser/enumdecl_error_empty_container_variant.out") - // Returns - .add_test_vs_file("parser/return.abra", "parser/return.out.json") - .add_test_vs_file("parser/return_error_nonexpr.abra", "parser/return_error_nonexpr.out") - - .run_tests(); -} - -#[test] -fn typechecker_tests() { - TestRunner::typechecker_test_runner() - // Lexer/Parser error handling - .add_test_vs_file("typechecker/_lexer_error.abra", "typechecker/_lexer_error.out") - .add_test_vs_file("typechecker/_parser_error.abra", "typechecker/_parser_error.out") - // Literals - .add_test_vs_file("typechecker/literals/literals.abra", "typechecker/literals/literals.out.json") - .add_test_vs_file("typechecker/literals/string_interpolation.abra", "typechecker/literals/string_interpolation.out.json") - // Unary - .add_test_vs_file("typechecker/unary/unary.abra", "typechecker/unary/unary.out.json") - .add_test_vs_file("typechecker/unary/error_minus.1.abra", "typechecker/unary/error_minus.1.out") - .add_test_vs_file("typechecker/unary/error_minus.2.abra", "typechecker/unary/error_minus.2.out") - .add_test_vs_file("typechecker/unary/error_neg.1.abra", "typechecker/unary/error_neg.1.out") - .add_test_vs_file("typechecker/unary/error_neg.2.abra", "typechecker/unary/error_neg.2.out") - // Binary - .add_test_vs_file("typechecker/binary/and.abra", "typechecker/binary/and.out.json") - .add_test_vs_file("typechecker/binary/and_error.1.abra", "typechecker/binary/and_error.1.out") - .add_test_vs_file("typechecker/binary/and_error.2.abra", "typechecker/binary/and_error.2.out") - .add_test_vs_file("typechecker/binary/coalesce.1.abra", "typechecker/binary/coalesce.1.out.json") - .add_test_vs_file("typechecker/binary/coalesce.2.abra", "typechecker/binary/coalesce.2.out.json") - .add_test_vs_file("typechecker/binary/coalesce_error.1.abra", "typechecker/binary/coalesce_error.1.out") - .add_test_vs_file("typechecker/binary/coalesce_error.2.abra", "typechecker/binary/coalesce_error.2.out") - .add_test_vs_file("typechecker/binary/coalesce_error.3.abra", "typechecker/binary/coalesce_error.3.out") - .add_test_vs_file("typechecker/binary/divide.abra", "typechecker/binary/divide.out.json") - .add_test_vs_file("typechecker/binary/divide_error.1.abra", "typechecker/binary/divide_error.1.out") - .add_test_vs_file("typechecker/binary/divide_error.2.abra", "typechecker/binary/divide_error.2.out") - .add_test_vs_file("typechecker/binary/divide_error.3.abra", "typechecker/binary/divide_error.3.out") - .add_test_vs_file("typechecker/binary/eq.1.abra", "typechecker/binary/eq.1.out.json") - .add_test_vs_file("typechecker/binary/eq.2.abra", "typechecker/binary/eq.2.out.json") - .add_test_vs_file("typechecker/binary/eq_error.1.abra", "typechecker/binary/eq_error.1.out") - .add_test_vs_file("typechecker/binary/eq_error.2.abra", "typechecker/binary/eq_error.2.out") - .add_test_vs_file("typechecker/binary/eq_error.3.abra", "typechecker/binary/eq_error.3.out") - .add_test_vs_file("typechecker/binary/gt.abra", "typechecker/binary/gt.out.json") - .add_test_vs_file("typechecker/binary/gt_error.1.abra", "typechecker/binary/gt_error.1.out") - .add_test_vs_file("typechecker/binary/gt_error.2.abra", "typechecker/binary/gt_error.2.out") - .add_test_vs_file("typechecker/binary/gt_error.3.abra", "typechecker/binary/gt_error.3.out") - .add_test_vs_file("typechecker/binary/gte.abra", "typechecker/binary/gte.out.json") - .add_test_vs_file("typechecker/binary/gte_error.1.abra", "typechecker/binary/gte_error.1.out") - .add_test_vs_file("typechecker/binary/gte_error.2.abra", "typechecker/binary/gte_error.2.out") - .add_test_vs_file("typechecker/binary/gte_error.3.abra", "typechecker/binary/gte_error.3.out") - .add_test_vs_file("typechecker/binary/lt.abra", "typechecker/binary/lt.out.json") - .add_test_vs_file("typechecker/binary/lt_error.1.abra", "typechecker/binary/lt_error.1.out") - .add_test_vs_file("typechecker/binary/lt_error.2.abra", "typechecker/binary/lt_error.2.out") - .add_test_vs_file("typechecker/binary/lt_error.3.abra", "typechecker/binary/lt_error.3.out") - .add_test_vs_file("typechecker/binary/lte.abra", "typechecker/binary/lte.out.json") - .add_test_vs_file("typechecker/binary/lte_error.1.abra", "typechecker/binary/lte_error.1.out") - .add_test_vs_file("typechecker/binary/lte_error.2.abra", "typechecker/binary/lte_error.2.out") - .add_test_vs_file("typechecker/binary/lte_error.3.abra", "typechecker/binary/lte_error.3.out") - .add_test_vs_file("typechecker/binary/minus.abra", "typechecker/binary/minus.out.json") - .add_test_vs_file("typechecker/binary/minus_error.1.abra", "typechecker/binary/minus_error.1.out") - .add_test_vs_file("typechecker/binary/minus_error.2.abra", "typechecker/binary/minus_error.2.out") - .add_test_vs_file("typechecker/binary/minus_error.3.abra", "typechecker/binary/minus_error.3.out") - .add_test_vs_file("typechecker/binary/mod.abra", "typechecker/binary/mod.out.json") - .add_test_vs_file("typechecker/binary/mod_error.1.abra", "typechecker/binary/mod_error.1.out") - .add_test_vs_file("typechecker/binary/mod_error.2.abra", "typechecker/binary/mod_error.2.out") - .add_test_vs_file("typechecker/binary/mod_error.3.abra", "typechecker/binary/mod_error.3.out") - .add_test_vs_file("typechecker/binary/neq.1.abra", "typechecker/binary/neq.1.out.json") - .add_test_vs_file("typechecker/binary/neq.2.abra", "typechecker/binary/neq.2.out.json") - .add_test_vs_file("typechecker/binary/neq_error.1.abra", "typechecker/binary/neq_error.1.out") - .add_test_vs_file("typechecker/binary/neq_error.2.abra", "typechecker/binary/neq_error.2.out") - .add_test_vs_file("typechecker/binary/or.abra", "typechecker/binary/or.out.json") - .add_test_vs_file("typechecker/binary/or_error.1.abra", "typechecker/binary/or_error.1.out") - .add_test_vs_file("typechecker/binary/or_error.2.abra", "typechecker/binary/or_error.2.out") - .add_test_vs_file("typechecker/binary/plus_error.1.abra", "typechecker/binary/plus_error.1.out") - .add_test_vs_file("typechecker/binary/plus_error.2.abra", "typechecker/binary/plus_error.2.out") - .add_test_vs_file("typechecker/binary/plus_error.3.abra", "typechecker/binary/plus_error.3.out") - .add_test_vs_file("typechecker/binary/plus_numeric.abra", "typechecker/binary/plus_numeric.out.json") - .add_test_vs_file("typechecker/binary/plus_string_concat.abra", "typechecker/binary/plus_string_concat.out.json") - .add_test_vs_file("typechecker/binary/pow.abra", "typechecker/binary/pow.out.json") - .add_test_vs_file("typechecker/binary/pow_error.1.abra", "typechecker/binary/pow_error.1.out") - .add_test_vs_file("typechecker/binary/pow_error.2.abra", "typechecker/binary/pow_error.2.out") - .add_test_vs_file("typechecker/binary/pow_error.3.abra", "typechecker/binary/pow_error.3.out") - .add_test_vs_file("typechecker/binary/shl.abra", "typechecker/binary/shl.out.json") - .add_test_vs_file("typechecker/binary/shl_error.1.abra", "typechecker/binary/shl_error.1.out") - .add_test_vs_file("typechecker/binary/shl_error.2.abra", "typechecker/binary/shl_error.2.out") - .add_test_vs_file("typechecker/binary/shl_error.3.abra", "typechecker/binary/shl_error.3.out") - .add_test_vs_file("typechecker/binary/shl_error.4.abra", "typechecker/binary/shl_error.4.out") - .add_test_vs_file("typechecker/binary/shr.abra", "typechecker/binary/shr.out.json") - .add_test_vs_file("typechecker/binary/shr_error.1.abra", "typechecker/binary/shr_error.1.out") - .add_test_vs_file("typechecker/binary/shr_error.2.abra", "typechecker/binary/shr_error.2.out") - .add_test_vs_file("typechecker/binary/shr_error.3.abra", "typechecker/binary/shr_error.3.out") - .add_test_vs_file("typechecker/binary/shr_error.4.abra", "typechecker/binary/shr_error.4.out") - .add_test_vs_file("typechecker/binary/times.abra", "typechecker/binary/times.out.json") - .add_test_vs_file("typechecker/binary/times_error.1.abra", "typechecker/binary/times_error.1.out") - .add_test_vs_file("typechecker/binary/times_error.2.abra", "typechecker/binary/times_error.2.out") - .add_test_vs_file("typechecker/binary/times_error.3.abra", "typechecker/binary/times_error.3.out") - .add_test_vs_file("typechecker/binary/and_eq.abra", "typechecker/binary/and_eq.out.json") - .add_test_vs_file("typechecker/binary/and_eq_error.1.abra", "typechecker/binary/and_eq_error.1.out") - .add_test_vs_file("typechecker/binary/and_eq_error.2.abra", "typechecker/binary/and_eq_error.2.out") - // .add_test_vs_txt("typechecker/binary/coalesce_eq.1.abra", "typechecker/binary/coalesce_eq.1.out.json") - // .add_test_vs_txt("typechecker/binary/coalesce_eq_error.1.abra", "typechecker/binary/coalesce_eq_error.1.out") - // .add_test_vs_txt("typechecker/binary/coalesce_eq_error.2.abra", "typechecker/binary/coalesce_eq_error.2.out") - .add_test_vs_file("typechecker/binary/divide_eq.abra", "typechecker/binary/divide_eq.out.json") - .add_test_vs_file("typechecker/binary/divide_eq_error.1.abra", "typechecker/binary/divide_eq_error.1.out") - .add_test_vs_file("typechecker/binary/divide_eq_error.2.abra", "typechecker/binary/divide_eq_error.2.out") - .add_test_vs_file("typechecker/binary/divide_eq_error.3.abra", "typechecker/binary/divide_eq_error.3.out") - .add_test_vs_file("typechecker/binary/minus_eq.abra", "typechecker/binary/minus_eq.out.json") - .add_test_vs_file("typechecker/binary/minus_eq_error.1.abra", "typechecker/binary/minus_eq_error.1.out") - .add_test_vs_file("typechecker/binary/minus_eq_error.2.abra", "typechecker/binary/minus_eq_error.2.out") - .add_test_vs_file("typechecker/binary/mod_eq.abra", "typechecker/binary/mod_eq.out.json") - .add_test_vs_file("typechecker/binary/mod_eq_error.1.abra", "typechecker/binary/mod_eq_error.1.out") - .add_test_vs_file("typechecker/binary/mod_eq_error.2.abra", "typechecker/binary/mod_eq_error.2.out") - .add_test_vs_file("typechecker/binary/or_eq.abra", "typechecker/binary/or_eq.out.json") - .add_test_vs_file("typechecker/binary/or_eq_error.1.abra", "typechecker/binary/or_eq_error.1.out") - .add_test_vs_file("typechecker/binary/or_eq_error.2.abra", "typechecker/binary/or_eq_error.2.out") - .add_test_vs_file("typechecker/binary/plus_eq.abra", "typechecker/binary/plus_eq.out.json") - .add_test_vs_file("typechecker/binary/plus_eq_error.1.abra", "typechecker/binary/plus_eq_error.1.out") - .add_test_vs_file("typechecker/binary/plus_eq_error.2.abra", "typechecker/binary/plus_eq_error.2.out") - .add_test_vs_file("typechecker/binary/times_eq.abra", "typechecker/binary/times_eq.out.json") - .add_test_vs_file("typechecker/binary/times_eq_error.1.abra", "typechecker/binary/times_eq_error.1.out") - .add_test_vs_file("typechecker/binary/times_eq_error.2.abra", "typechecker/binary/times_eq_error.2.out") - - // Identifier - .add_test_vs_file("typechecker/identifier/identifier.abra", "typechecker/identifier/identifier.out.json") - .add_test_vs_file("typechecker/identifier/identifier_transform_OptionNone.abra", "typechecker/identifier/identifier_transform_OptionNone.out.json") - .add_test_vs_file("typechecker/identifier/error_discard.abra", "typechecker/identifier/error_discard.out") - .add_test_vs_file("typechecker/identifier/error_type_mismatch.abra", "typechecker/identifier/error_type_mismatch.out") - .add_test_vs_file("typechecker/identifier/error_type_mismatch_None.abra", "typechecker/identifier/error_type_mismatch_None.out") - .add_test_vs_file("typechecker/identifier/error_unknown_ident.abra", "typechecker/identifier/error_unknown_ident.out") - // Array - .add_test_vs_file("typechecker/array/array.abra", "typechecker/array/array.out.json") - .add_test_vs_file("typechecker/array/error_bindingdecl_empty.abra", "typechecker/array/error_bindingdecl_empty.out") - .add_test_vs_file("typechecker/array/error_type_mismatch_bindingdecl.1.abra", "typechecker/array/error_type_mismatch_bindingdecl.1.out") - .add_test_vs_file("typechecker/array/error_type_mismatch_bindingdecl.2.abra", "typechecker/array/error_type_mismatch_bindingdecl.2.out") - .add_test_vs_file("typechecker/array/error_type_mismatch_bindingdecl.3.abra", "typechecker/array/error_type_mismatch_bindingdecl.3.out") - .add_test_vs_file("typechecker/array/error_type_mismatch_item.1.abra", "typechecker/array/error_type_mismatch_item.1.out") - .add_test_vs_file("typechecker/array/error_type_mismatch_item.2.abra", "typechecker/array/error_type_mismatch_item.2.out") - .add_test_vs_file("typechecker/array/error_type_mismatch_item.3.abra", "typechecker/array/error_type_mismatch_item.3.out") - .add_test_vs_file("typechecker/array/error_type_mismatch_item.4.abra", "typechecker/array/error_type_mismatch_item.4.out") - // Set - .add_test_vs_file("typechecker/set/set.abra", "typechecker/set/set.out.json") - .add_test_vs_file("typechecker/set/error_bindingdecl_empty.abra", "typechecker/set/error_bindingdecl_empty.out") - .add_test_vs_file("typechecker/set/error_type_mismatch_bindingdecl.1.abra", "typechecker/set/error_type_mismatch_bindingdecl.1.out") - .add_test_vs_file("typechecker/set/error_type_mismatch_bindingdecl.2.abra", "typechecker/set/error_type_mismatch_bindingdecl.2.out") - .add_test_vs_file("typechecker/set/error_type_mismatch_bindingdecl.3.abra", "typechecker/set/error_type_mismatch_bindingdecl.3.out") - .add_test_vs_file("typechecker/set/error_type_mismatch_item.1.abra", "typechecker/set/error_type_mismatch_item.1.out") - .add_test_vs_file("typechecker/set/error_type_mismatch_item.2.abra", "typechecker/set/error_type_mismatch_item.2.out") - .add_test_vs_file("typechecker/set/error_type_mismatch_item.3.abra", "typechecker/set/error_type_mismatch_item.3.out") - .add_test_vs_file("typechecker/set/error_type_mismatch_item.4.abra", "typechecker/set/error_type_mismatch_item.4.out") - // Map - .add_test_vs_file("typechecker/map/map.abra", "typechecker/map/map.out.json") - .add_test_vs_file("typechecker/map/error_bindingdecl_empty.abra", "typechecker/map/error_bindingdecl_empty.out") - .add_test_vs_file("typechecker/map/error_type_mismatch_bindingdecl.1.abra", "typechecker/map/error_type_mismatch_bindingdecl.1.out") - .add_test_vs_file("typechecker/map/error_type_mismatch_bindingdecl.2.abra", "typechecker/map/error_type_mismatch_bindingdecl.2.out") - .add_test_vs_file("typechecker/map/error_type_mismatch_bindingdecl.3.abra", "typechecker/map/error_type_mismatch_bindingdecl.3.out") - .add_test_vs_file("typechecker/map/error_type_mismatch_bindingdecl.4.abra", "typechecker/map/error_type_mismatch_bindingdecl.4.out") - .add_test_vs_file("typechecker/map/error_type_mismatch_key.1.abra", "typechecker/map/error_type_mismatch_key.1.out") - .add_test_vs_file("typechecker/map/error_type_mismatch_value.1.abra", "typechecker/map/error_type_mismatch_value.1.out") - .add_test_vs_file("typechecker/map/error_type_mismatch_value.2.abra", "typechecker/map/error_type_mismatch_value.2.out") - .add_test_vs_file("typechecker/map/error_unfilled_holes.1.abra", "typechecker/map/error_unfilled_holes.1.out") - .add_test_vs_file("typechecker/map/error_unfilled_holes.2.abra", "typechecker/map/error_unfilled_holes.2.out") - // Tuple - .add_test_vs_file("typechecker/tuple/tuple.abra", "typechecker/tuple/tuple.out.json") - .add_test_vs_file("typechecker/tuple/error_type_mismatch.1.abra", "typechecker/tuple/error_type_mismatch.1.out") - .add_test_vs_file("typechecker/tuple/error_type_mismatch.2.abra", "typechecker/tuple/error_type_mismatch.2.out") - .add_test_vs_file("typechecker/tuple/error_type_mismatch_too_big.1.abra", "typechecker/tuple/error_type_mismatch_too_big.1.out") - .add_test_vs_file("typechecker/tuple/error_type_mismatch_too_big.2.abra", "typechecker/tuple/error_type_mismatch_too_big.2.out") - .add_test_vs_file("typechecker/tuple/error_type_mismatch_too_small.1.abra", "typechecker/tuple/error_type_mismatch_too_small.1.out") - // Indexing - .add_test_vs_file("typechecker/indexing/error_indexing_array_nullable.abra", "typechecker/indexing/error_indexing_array_nullable.out") - .add_test_vs_file("typechecker/indexing/error_indexing_string_nullable.abra", "typechecker/indexing/error_indexing_string_nullable.out") - .add_test_vs_file("typechecker/indexing/error_indexing_tuple_nullable.abra", "typechecker/indexing/error_indexing_tuple_nullable.out") - .add_test_vs_file("typechecker/indexing/error_indexing_map_nullable.abra", "typechecker/indexing/error_indexing_map_nullable.out") - .add_test_vs_file("typechecker/indexing/error_unindexable_type.1.abra", "typechecker/indexing/error_unindexable_type.1.out") - .add_test_vs_file("typechecker/indexing/error_unindexable_type.2.abra", "typechecker/indexing/error_unindexable_type.2.out") - .add_test_vs_file("typechecker/indexing/array_error_idx_non_int.abra", "typechecker/indexing/array_error_idx_non_int.out") - .add_test_vs_file("typechecker/indexing/array_error_idx_nullable.abra", "typechecker/indexing/array_error_idx_nullable.out") - .add_test_vs_file("typechecker/indexing/array_error_range_non_int.1.abra", "typechecker/indexing/array_error_range_non_int.1.out") - .add_test_vs_file("typechecker/indexing/array_error_range_non_int.2.abra", "typechecker/indexing/array_error_range_non_int.2.out") - .add_test_vs_file("typechecker/indexing/array_error_range_nullable.1.abra", "typechecker/indexing/array_error_range_nullable.1.out") - .add_test_vs_file("typechecker/indexing/array_error_range_nullable.2.abra", "typechecker/indexing/array_error_range_nullable.2.out") - .add_test_vs_file("typechecker/indexing/indexing_array.abra", "typechecker/indexing/indexing_array.out.json") - .add_test_vs_file("typechecker/indexing/indexing_map.abra", "typechecker/indexing/indexing_map.out.json") - .add_test_vs_file("typechecker/indexing/indexing_string.abra", "typechecker/indexing/indexing_string.out.json") - .add_test_vs_file("typechecker/indexing/indexing_tuple.abra", "typechecker/indexing/indexing_tuple.out.json") - .add_test_vs_file("typechecker/indexing/map_error_key_type_mismatch.abra", "typechecker/indexing/map_error_key_type_mismatch.out") - .add_test_vs_file("typechecker/indexing/string_error_idx_non_int.abra", "typechecker/indexing/string_error_idx_non_int.out") - .add_test_vs_file("typechecker/indexing/string_error_idx_nullable.abra", "typechecker/indexing/string_error_idx_nullable.out") - .add_test_vs_file("typechecker/indexing/string_error_range_non_int.1.abra", "typechecker/indexing/string_error_range_non_int.1.out") - .add_test_vs_file("typechecker/indexing/string_error_range_non_int.2.abra", "typechecker/indexing/string_error_range_non_int.2.out") - .add_test_vs_file("typechecker/indexing/string_error_range_nullable.1.abra", "typechecker/indexing/string_error_range_nullable.1.out") - .add_test_vs_file("typechecker/indexing/string_error_range_nullable.2.abra", "typechecker/indexing/string_error_range_nullable.2.out") - .add_test_vs_file("typechecker/indexing/tuple_error_hole.abra", "typechecker/indexing/tuple_error_hole.out") - .add_test_vs_file("typechecker/indexing/tuple_error_negative.abra", "typechecker/indexing/tuple_error_negative.out") - .add_test_vs_file("typechecker/indexing/tuple_error_non_int_literal.abra", "typechecker/indexing/tuple_error_non_int_literal.out") - .add_test_vs_file("typechecker/indexing/tuple_error_non_literal.abra", "typechecker/indexing/tuple_error_non_literal.out") - .add_test_vs_file("typechecker/indexing/tuple_error_out_of_bounds.abra", "typechecker/indexing/tuple_error_out_of_bounds.out") - .add_test_vs_file("typechecker/indexing/tuple_error_range.abra", "typechecker/indexing/tuple_error_range.out") - .add_test_vs_file("typechecker/indexing/tuple_error_type_mismatch.abra", "typechecker/indexing/tuple_error_type_mismatch.out") - // If expressions & statements - .add_test_vs_file("typechecker/if/error_binding_invalid_destructuring_tuple.abra", "typechecker/if/error_binding_invalid_destructuring_tuple.out") - .add_test_vs_file("typechecker/if/error_bad_cond_type.abra", "typechecker/if/error_bad_cond_type.out") - .add_test_vs_file("typechecker/if/error_block_mismatch.1.abra", "typechecker/if/error_block_mismatch.1.out") - .add_test_vs_file("typechecker/if/error_block_mismatch.2.abra", "typechecker/if/error_block_mismatch.2.out") - .add_test_vs_file("typechecker/if/error_empty_else_block.abra", "typechecker/if/error_empty_else_block.out") - .add_test_vs_file("typechecker/if/error_empty_if_block.abra", "typechecker/if/error_empty_if_block.out") - .add_test_vs_file("typechecker/if/error_mismatch_bindingdecl.1.abra", "typechecker/if/error_mismatch_bindingdecl.1.out") - .add_test_vs_file("typechecker/if/error_mismatch_bindingdecl.2.abra", "typechecker/if/error_mismatch_bindingdecl.2.out") - .add_test_vs_file("typechecker/if/error_mismatch_bindingdecl.3.abra", "typechecker/if/error_mismatch_bindingdecl.3.out") - .add_test_vs_file("typechecker/if/error_no_else_block.abra", "typechecker/if/error_no_else_block.out") - .add_test_vs_file("typechecker/if/error_unfilled_holes_bindingdecl.1.abra", "typechecker/if/error_unfilled_holes_bindingdecl.1.out") - .add_test_vs_file("typechecker/if/error_unfilled_holes_bindingdecl.2.abra", "typechecker/if/error_unfilled_holes_bindingdecl.2.out") - .add_test_vs_file("typechecker/if/error_unfilled_holes_bindingdecl.3.abra", "typechecker/if/error_unfilled_holes_bindingdecl.3.out") - .add_test_vs_file("typechecker/if/error_unfilled_holes_bindingdecl.4.abra", "typechecker/if/error_unfilled_holes_bindingdecl.4.out") - .add_test_vs_file("typechecker/if/expr.abra", "typechecker/if/expr.out.json") - .add_test_vs_file("typechecker/if/stmt.abra", "typechecker/if/stmt.out.json") - // Match expressions & statements - .add_test_vs_file("typechecker/match/match_expr.abra", "typechecker/match/match_expr.out.json") - .add_test_vs_file("typechecker/match/match_stmt.abra", "typechecker/match/match_stmt.out.json") - .add_test_vs_file("typechecker/match/match_Result.abra", "typechecker/match/match_Result.out.json") - .add_test_vs_file("typechecker/match/match_expr_terminators.abra", "typechecker/match/match_expr_terminators.out.json") - .add_test_vs_file("typechecker/match/error_expr_empty_block.abra", "typechecker/match/error_expr_empty_block.out") - .add_test_vs_file("typechecker/match/error_unfilled_holes.1.abra", "typechecker/match/error_unfilled_holes.1.out") - .add_test_vs_file("typechecker/match/error_alreadycovered_None.abra", "typechecker/match/error_alreadycovered_None.out") - .add_test_vs_file("typechecker/match/error_duplicate_literal.abra", "typechecker/match/error_duplicate_literal.out") - .add_test_vs_file("typechecker/match/error_invalid_else_type.abra", "typechecker/match/error_invalid_else_type.out") - .add_test_vs_file("typechecker/match/error_nooverlap_None.abra", "typechecker/match/error_nooverlap_None.out") - .add_test_vs_file("typechecker/match/error_nooverlap_literal.1.abra", "typechecker/match/error_nooverlap_literal.1.out") - .add_test_vs_file("typechecker/match/error_nooverlap_literal.2.abra", "typechecker/match/error_nooverlap_literal.2.out") - .add_test_vs_file("typechecker/match/error_alreadycovered_literal_after_type.1.abra", "typechecker/match/error_alreadycovered_literal_after_type.1.out") - .add_test_vs_file("typechecker/match/error_alreadycovered_literal_after_type.2.abra", "typechecker/match/error_alreadycovered_literal_after_type.2.out") - .add_test_vs_file("typechecker/match/error_duplicate_Enum_variant.abra", "typechecker/match/error_duplicate_Enum_variant.out") - .add_test_vs_file("typechecker/match/error_exhaustive_Bool_literal.abra", "typechecker/match/error_exhaustive_Bool_literal.out") - .add_test_vs_file("typechecker/match/error_exhaustive_Enum_variants.1.abra", "typechecker/match/error_exhaustive_Enum_variants.1.out") - .add_test_vs_file("typechecker/match/error_exhaustive_Enum_variants.2.abra", "typechecker/match/error_exhaustive_Enum_variants.2.out") - .add_test_vs_file("typechecker/match/error_exhaustive_after_else.abra", "typechecker/match/error_exhaustive_after_else.out") - .add_test_vs_file("typechecker/match/error_exhaustive_type.1.abra", "typechecker/match/error_exhaustive_type.1.out") - .add_test_vs_file("typechecker/match/error_exhaustive_type.2.abra", "typechecker/match/error_exhaustive_type.2.out") - .add_test_vs_file("typechecker/match/error_nonexhaustive_literal.1.abra", "typechecker/match/error_nonexhaustive_literal.1.out") - .add_test_vs_file("typechecker/match/error_nonexhaustive_literal.2.abra", "typechecker/match/error_nonexhaustive_literal.2.out") - .add_test_vs_file("typechecker/match/error_nooverlap_Enum.abra", "typechecker/match/error_nooverlap_Enum.out") - .add_test_vs_file("typechecker/match/error_nooverlap_Type.abra", "typechecker/match/error_nooverlap_Type.out") - .add_test_vs_file("typechecker/match/error_destructuring_constant_variant.abra", "typechecker/match/error_destructuring_constant_variant.out") - .add_test_vs_file("typechecker/match/error_destructuring_type.abra", "typechecker/match/error_destructuring_type.out") - .add_test_vs_file("typechecker/match/error_destructuring_variant_duplicate_variable.1.abra", "typechecker/match/error_destructuring_variant_duplicate_variable.1.out") - .add_test_vs_file("typechecker/match/error_destructuring_variant_duplicate_variable.2.abra", "typechecker/match/error_destructuring_variant_duplicate_variable.2.out") - .add_test_vs_file("typechecker/match/error_destructuring_variant_too_few.abra", "typechecker/match/error_destructuring_variant_too_few.out") - .add_test_vs_file("typechecker/match/error_destructuring_variant_too_many.abra", "typechecker/match/error_destructuring_variant_too_many.out") - .add_test_vs_file("typechecker/match/error_forbidden_type_all_branches_never.abra", "typechecker/match/error_forbidden_type_all_branches_never.out") - - // Invocation - .add_test_vs_file("typechecker/invocation/invocation.1.abra", "typechecker/invocation/invocation.1.out.json") - .add_test_vs_file("typechecker/invocation/invocation.2.abra", "typechecker/invocation/invocation.2.out.json") - .add_test_vs_file("typechecker/invocation/invocation.3.abra", "typechecker/invocation/invocation.3.out.json") - .add_test_vs_file("typechecker/invocation/invocation.4.abra", "typechecker/invocation/invocation.4.out.json") - .add_test_vs_file("typechecker/invocation/invocation.5.abra", "typechecker/invocation/invocation.5.out.json") - .add_test_vs_file("typechecker/invocation/error_incorrect_label.abra", "typechecker/invocation/error_incorrect_label.out") - .add_test_vs_file("typechecker/invocation/error_mixed_label_optional.abra", "typechecker/invocation/error_mixed_label_optional.out") - .add_test_vs_file("typechecker/invocation/error_optional_param_type_mismatch.abra", "typechecker/invocation/error_optional_param_type_mismatch.out") - .add_test_vs_file("typechecker/invocation/error_optional_param_unknown.abra", "typechecker/invocation/error_optional_param_unknown.out") - .add_test_vs_file("typechecker/invocation/error_too_few_args.abra", "typechecker/invocation/error_too_few_args.out") - .add_test_vs_file("typechecker/invocation/error_too_many_args.abra", "typechecker/invocation/error_too_many_args.out") - .add_test_vs_file("typechecker/invocation/error_expr_illegal_label.abra", "typechecker/invocation/error_expr_illegal_label.out") - .add_test_vs_file("typechecker/invocation/error_expr_not_callable.abra", "typechecker/invocation/error_expr_not_callable.out") - .add_test_vs_file("typechecker/invocation/error_expr_too_few_args.abra", "typechecker/invocation/error_expr_too_few_args.out") - .add_test_vs_file("typechecker/invocation/error_expr_too_many_args.abra", "typechecker/invocation/error_expr_too_many_args.out") - .add_test_vs_file("typechecker/invocation/function_as_param.1.abra", "typechecker/invocation/function_as_param.1.out.json") - .add_test_vs_file("typechecker/invocation/function_as_param.2.abra", "typechecker/invocation/function_as_param.2.out.json") - .add_test_vs_file("typechecker/invocation/function_as_param.3.abra", "typechecker/invocation/function_as_param.3.out.json") - .add_test_vs_file("typechecker/invocation/function_as_param_generic.abra", "typechecker/invocation/function_as_param_generic.out.json") - .add_test_vs_file("typechecker/invocation/function_as_param_error_arity.abra", "typechecker/invocation/function_as_param_error_arity.out") - .add_test_vs_file("typechecker/invocation/function_value.abra", "typechecker/invocation/function_value.out.json") - .add_test_vs_file("typechecker/invocation/invocation_generics.1.abra", "typechecker/invocation/invocation_generics.1.out.json") - .add_test_vs_file("typechecker/invocation/invocation_generics.2.abra", "typechecker/invocation/invocation_generics.2.out.json") - .add_test_vs_file("typechecker/invocation/invocation_generics.3.abra", "typechecker/invocation/invocation_generics.3.out.json") - .add_test_vs_file("typechecker/invocation/invocation_generics.4.abra", "typechecker/invocation/invocation_generics.4.out.json") - .add_test_vs_file("typechecker/invocation/invocation_generics.5.abra", "typechecker/invocation/invocation_generics.5.out.json") - .add_test_vs_file("typechecker/invocation/generics_error_inferred_from_ret.1.abra", "typechecker/invocation/generics_error_inferred_from_ret.1.out") - .add_test_vs_file("typechecker/invocation/generics_error_inferred_from_ret.2.abra", "typechecker/invocation/generics_error_inferred_from_ret.2.out") - .add_test_vs_file("typechecker/invocation/generics_error_type_mismatch.abra", "typechecker/invocation/generics_error_type_mismatch.out") - .add_test_vs_file("typechecker/invocation/generics_error_unfilled_holes.abra", "typechecker/invocation/generics_error_unfilled_holes.out") - .add_test_vs_file("typechecker/invocation/generics_given_error_type_mismatch.abra", "typechecker/invocation/generics_given_error_type_mismatch.out") - .add_test_vs_file("typechecker/invocation/error_field_not_callable.abra", "typechecker/invocation/error_field_not_callable.out") - .add_test_vs_file("typechecker/invocation/error_instantiation_generics.1.abra", "typechecker/invocation/error_instantiation_generics.1.out") - .add_test_vs_file("typechecker/invocation/error_instantiation_generics.2.abra", "typechecker/invocation/error_instantiation_generics.2.out") - .add_test_vs_file("typechecker/invocation/error_instantiation_missing_labels.abra", "typechecker/invocation/error_instantiation_missing_labels.out") - .add_test_vs_file("typechecker/invocation/error_instantiation_too_few_args.1.abra", "typechecker/invocation/error_instantiation_too_few_args.1.out") - .add_test_vs_file("typechecker/invocation/error_instantiation_too_few_args.2.abra", "typechecker/invocation/error_instantiation_too_few_args.2.out") - .add_test_vs_file("typechecker/invocation/error_enum_variant_constant.abra", "typechecker/invocation/error_enum_variant_constant.out") - .add_test_vs_file("typechecker/invocation/invocation_arbitrary_expr.1.abra", "typechecker/invocation/invocation_arbitrary_expr.1.out.json") - .add_test_vs_file("typechecker/invocation/invocation_arbitrary_expr.2.abra", "typechecker/invocation/invocation_arbitrary_expr.2.out.json") - .add_test_vs_file("typechecker/invocation/invocation_field.abra", "typechecker/invocation/invocation_field.out.json") - .add_test_vs_file("typechecker/invocation/invocation_instantiation.1.abra", "typechecker/invocation/invocation_instantiation.1.out.json") - .add_test_vs_file("typechecker/invocation/invocation_instantiation_generics.1.abra", "typechecker/invocation/invocation_instantiation_generics.1.out.json") - .add_test_vs_file("typechecker/invocation/invocation_instantiation_generics.2.abra", "typechecker/invocation/invocation_instantiation_generics.2.out.json") - .add_test_vs_file("typechecker/invocation/invocation_method.1.abra", "typechecker/invocation/invocation_method.1.out.json") - .add_test_vs_file("typechecker/invocation/invocation_method.2.abra", "typechecker/invocation/invocation_method.2.out.json") - .add_test_vs_file("typechecker/invocation/generics_error_method.1.abra", "typechecker/invocation/generics_error_method.1.out") - .add_test_vs_file("typechecker/invocation/generics_error_method.2.abra", "typechecker/invocation/generics_error_method.2.out") - .add_test_vs_file("typechecker/invocation/generics_error_field.1.abra", "typechecker/invocation/generics_error_field.1.out") - .add_test_vs_file("typechecker/invocation/invocation_method_generics.1.abra", "typechecker/invocation/invocation_method_generics.1.out.json") - .add_test_vs_file("typechecker/invocation/invocation_method_generics.2.abra", "typechecker/invocation/invocation_method_generics.2.out.json") - .add_test_vs_file("typechecker/invocation/invocation_enum_variant.1.abra", "typechecker/invocation/invocation_enum_variant.1.out.json") - .add_test_vs_file("typechecker/invocation/invocation_enum_variant.2.abra", "typechecker/invocation/invocation_enum_variant.2.out.json") - .add_test_vs_file("typechecker/invocation/invocation_enum_variant.3.abra", "typechecker/invocation/invocation_enum_variant.3.out.json") - .add_test_vs_file("typechecker/invocation/invocation_enum_variant.4.abra", "typechecker/invocation/invocation_enum_variant.4.out.json") - .add_test_vs_file("typechecker/invocation/invocation_field_generics.1.abra", "typechecker/invocation/invocation_field_generics.1.out.json") - .add_test_vs_file("typechecker/invocation/error_variadic_generic_type_mismatch.abra", "typechecker/invocation/error_variadic_generic_type_mismatch.out") - .add_test_vs_file("typechecker/invocation/error_variadic_labeled_generic_type_mismatch.abra", "typechecker/invocation/error_variadic_labeled_generic_type_mismatch.out") - .add_test_vs_file("typechecker/invocation/error_variadic_labeled_too_many_args.abra", "typechecker/invocation/error_variadic_labeled_too_many_args.out") - .add_test_vs_file("typechecker/invocation/error_variadic_labeled_type_mismatch.abra", "typechecker/invocation/error_variadic_labeled_type_mismatch.out") - .add_test_vs_file("typechecker/invocation/error_variadic_type_mismatch.abra", "typechecker/invocation/error_variadic_type_mismatch.out") - .add_test_vs_file("typechecker/invocation/invocation_variadic.1.abra", "typechecker/invocation/invocation_variadic.1.out.json") - .add_test_vs_file("typechecker/invocation/invocation_variadic.2.abra", "typechecker/invocation/invocation_variadic.2.out.json") - // Accessor - .add_test_vs_file("typechecker/accessor/accessor.1.abra", "typechecker/accessor/accessor.1.out.json") - .add_test_vs_file("typechecker/accessor/accessor.2.abra", "typechecker/accessor/accessor.2.out.json") - .add_test_vs_file("typechecker/accessor/accessor.3.abra", "typechecker/accessor/accessor.3.out.json") - .add_test_vs_file("typechecker/accessor/error_unknown_field.abra", "typechecker/accessor/error_unknown_field.out") - .add_test_vs_file("typechecker/accessor/error_unknown_field_fn.abra", "typechecker/accessor/error_unknown_field_fn.out") - .add_test_vs_file("typechecker/accessor/error_unknown_field_opt_known.abra", "typechecker/accessor/error_unknown_field_opt_known.out") - .add_test_vs_file("typechecker/accessor/error_unknown_field_opt_unknown.abra", "typechecker/accessor/error_unknown_field_opt_unknown.out") - .add_test_vs_file("typechecker/accessor/error_unknown_field_unit.abra", "typechecker/accessor/error_unknown_field_unit.out") - .add_test_vs_file("typechecker/accessor/error_unnecessary_optsafe.abra", "typechecker/accessor/error_unnecessary_optsafe.out") - .add_test_vs_file("typechecker/accessor/error_unknown_field_chain_opt_known.abra", "typechecker/accessor/error_unknown_field_chain_opt_known.out") - .add_test_vs_file("typechecker/accessor/error_unknown_field_chain_opt_unknown.abra", "typechecker/accessor/error_unknown_field_chain_opt_unknown.out") - .add_test_vs_file("typechecker/accessor/error_static_member_referenced_by_instance.abra", "typechecker/accessor/error_static_member_referenced_by_instance.out") - .add_test_vs_file("typechecker/accessor/accessor.4.abra", "typechecker/accessor/accessor.4.out.json") - .add_test_vs_file("typechecker/accessor/error_unknown_enum_variant.1.abra", "typechecker/accessor/error_unknown_enum_variant.1.out") - // Lambda - .add_test_vs_file("typechecker/lambda/lambda.1.abra", "typechecker/lambda/lambda.1.out.json") - .add_test_vs_file("typechecker/lambda/lambda.2.abra", "typechecker/lambda/lambda.2.out.json") - .add_test_vs_file("typechecker/lambda/lambda_generic_inference.1.abra", "typechecker/lambda/lambda_generic_inference.1.out.json") - .add_test_vs_file("typechecker/lambda/lambda_generic_inference.2.abra", "typechecker/lambda/lambda_generic_inference.2.out.json") - .add_test_vs_file("typechecker/lambda/error_type_mismatch.1.abra", "typechecker/lambda/error_type_mismatch.1.out") - .add_test_vs_file("typechecker/lambda/error_type_mismatch.2.abra", "typechecker/lambda/error_type_mismatch.2.out") - .add_test_vs_file("typechecker/lambda/error_type_mismatch.3.abra", "typechecker/lambda/error_type_mismatch.3.out") - .add_test_vs_file("typechecker/lambda/error_type_mismatch.4.abra", "typechecker/lambda/error_type_mismatch.4.out") - .add_test_vs_file("typechecker/lambda/error_type_mismatch.5.abra", "typechecker/lambda/error_type_mismatch.5.out") - .add_test_vs_file("typechecker/lambda/error_unknown_type_for_parameter.1.abra", "typechecker/lambda/error_unknown_type_for_parameter.1.out") - .add_test_vs_file("typechecker/lambda/error_unknown_type_for_parameter.2.abra", "typechecker/lambda/error_unknown_type_for_parameter.2.out") - .add_test_vs_file("typechecker/lambda/error_unknown_type_for_parameter.3.abra", "typechecker/lambda/error_unknown_type_for_parameter.3.out") - - // Type identifiers - .add_test_vs_file("typechecker/typeidentifier/error_typearg_unknown.abra", "typechecker/typeidentifier/error_typearg_unknown.out") - .add_test_vs_file("typechecker/typeidentifier/error_typeargs_missing.abra", "typechecker/typeidentifier/error_typeargs_missing.out") - .add_test_vs_file("typechecker/typeidentifier/error_typeargs_too_few.abra", "typechecker/typeidentifier/error_typeargs_too_few.out") - .add_test_vs_file("typechecker/typeidentifier/error_typeargs_too_many.abra", "typechecker/typeidentifier/error_typeargs_too_many.out") - .add_test_vs_file("typechecker/typeidentifier/error_typeargs_unexpected.abra", "typechecker/typeidentifier/error_typeargs_unexpected.out") - .add_test_vs_file("typechecker/typeidentifier/error_unknown_type.abra", "typechecker/typeidentifier/error_unknown_type.out") - .add_test_vs_file("typechecker/typeidentifier/error_modalias_name_not_type.abra", "typechecker/typeidentifier/error_modalias_name_not_type.out") - .add_test_vs_file("typechecker/typeidentifier/error_modalias_path_too_long.abra", "typechecker/typeidentifier/error_modalias_path_too_long.out") - .add_test_vs_file("typechecker/typeidentifier/error_modalias_typeargs_missing.abra", "typechecker/typeidentifier/error_modalias_typeargs_missing.out") - .add_test_vs_file("typechecker/typeidentifier/error_modalias_typeargs_too_few.abra", "typechecker/typeidentifier/error_modalias_typeargs_too_few.out") - .add_test_vs_file("typechecker/typeidentifier/error_modalias_typeargs_too_many.abra", "typechecker/typeidentifier/error_modalias_typeargs_too_many.out") - .add_test_vs_file("typechecker/typeidentifier/error_modalias_typeargs_unexpected.abra", "typechecker/typeidentifier/error_modalias_typeargs_unexpected.out") - .add_test_vs_file("typechecker/typeidentifier/error_modalias_unknown_module.abra", "typechecker/typeidentifier/error_modalias_unknown_module.out") - .add_test_vs_file("typechecker/typeidentifier/error_modalias_unknown_type.abra", "typechecker/typeidentifier/error_modalias_unknown_type.out") - - // Assignment - .add_test_vs_file("typechecker/assignment/assignment_accessor.abra", "typechecker/assignment/assignment_accessor.out.json") - .add_test_vs_file("typechecker/assignment/assignment_indexing.abra", "typechecker/assignment/assignment_indexing.out.json") - .add_test_vs_file("typechecker/assignment/assignment_variable.abra", "typechecker/assignment/assignment_variable.out.json") - .add_test_vs_file("typechecker/assignment/accessor_error_method.1.abra", "typechecker/assignment/accessor_error_method.1.out") - .add_test_vs_file("typechecker/assignment/accessor_error_method.2.abra", "typechecker/assignment/accessor_error_method.2.out") - .add_test_vs_file("typechecker/assignment/accessor_error_enum_variant.abra", "typechecker/assignment/accessor_error_enum_variant.out") - .add_test_vs_file("typechecker/assignment/accessor_error_type_mismatch.1.abra", "typechecker/assignment/accessor_error_type_mismatch.1.out") - .add_test_vs_file("typechecker/assignment/accessor_error_type_mismatch.2.abra", "typechecker/assignment/accessor_error_type_mismatch.2.out") - .add_test_vs_file("typechecker/assignment/variable_error_alias_fn.abra", "typechecker/assignment/variable_error_alias_fn.out") - .add_test_vs_file("typechecker/assignment/indexing_error_type_mismatch.1.abra", "typechecker/assignment/indexing_error_type_mismatch.1.out") - .add_test_vs_file("typechecker/assignment/indexing_error_type_mismatch.2.abra", "typechecker/assignment/indexing_error_type_mismatch.2.out") - .add_test_vs_file("typechecker/assignment/variable_error_alias_type.abra", "typechecker/assignment/variable_error_alias_type.out") - .add_test_vs_file("typechecker/assignment/variable_error_immutable.abra", "typechecker/assignment/variable_error_immutable.out") - .add_test_vs_file("typechecker/assignment/variable_error_type_mismatch.1.abra", "typechecker/assignment/variable_error_type_mismatch.1.out") - .add_test_vs_file("typechecker/assignment/variable_error_type_mismatch.2.abra", "typechecker/assignment/variable_error_type_mismatch.2.out") - .add_test_vs_file("typechecker/assignment/variable_error_unknown.abra", "typechecker/assignment/variable_error_unknown.out") - - // Break - .add_test_vs_file("typechecker/break/break_as_expr.abra", "typechecker/break/break_as_expr.out.json") - .add_test_vs_file("typechecker/break/error_location_module.abra", "typechecker/break/error_location_module.out") - .add_test_vs_file("typechecker/break/error_location_module_func.abra", "typechecker/break/error_location_module_func.out") - .add_test_vs_file("typechecker/break/error_location_module_if.abra", "typechecker/break/error_location_module_if.out") - .add_test_vs_file("typechecker/break/error_unreachable_inside_while.abra", "typechecker/break/error_unreachable_inside_while.out") - .add_test_vs_file("typechecker/break/error_unreachable_inside_for.abra", "typechecker/break/error_unreachable_inside_for.out") - // Continue - .add_test_vs_file("typechecker/continue/continue_as_expr.abra", "typechecker/continue/continue_as_expr.out.json") - .add_test_vs_file("typechecker/continue/error_location_module.abra", "typechecker/continue/error_location_module.out") - .add_test_vs_file("typechecker/continue/error_location_module_func.abra", "typechecker/continue/error_location_module_func.out") - .add_test_vs_file("typechecker/continue/error_location_module_if.abra", "typechecker/continue/error_location_module_if.out") - .add_test_vs_file("typechecker/continue/error_unreachable_inside_while.abra", "typechecker/continue/error_unreachable_inside_while.out") - .add_test_vs_file("typechecker/continue/error_unreachable_inside_for.abra", "typechecker/continue/error_unreachable_inside_for.out") - // While - .add_test_vs_file("typechecker/while/while.1.abra", "typechecker/while/while.1.out.json") - .add_test_vs_file("typechecker/while/while.2.abra", "typechecker/while/while.2.out.json") - .add_test_vs_file("typechecker/while/while.3.abra", "typechecker/while/while.3.out.json") - .add_test_vs_file("typechecker/while/while.4.abra", "typechecker/while/while.4.out.json") - .add_test_vs_file("typechecker/while/error_bad_cond_type.abra", "typechecker/while/error_bad_cond_type.out") - .add_test_vs_file("typechecker/while/error_condition_invalid_destructuring_tuple.abra", "typechecker/while/error_condition_invalid_destructuring_tuple.out") - - // For - .add_test_vs_file("typechecker/for/for.1.abra", "typechecker/for/for.1.out.json") - .add_test_vs_file("typechecker/for/for.2.abra", "typechecker/for/for.2.out.json") - .add_test_vs_file("typechecker/for/for.3.abra", "typechecker/for/for.3.out.json") - .add_test_vs_file("typechecker/for/error_bad_iterator_option_type.abra", "typechecker/for/error_bad_iterator_option_type.out") - .add_test_vs_file("typechecker/for/error_bad_iterator.abra", "typechecker/for/error_bad_iterator.out") - .add_test_vs_file("typechecker/for/error_bad_iterator_unfilled_hole.abra", "typechecker/for/error_bad_iterator_unfilled_hole.out") - .add_test_vs_file("typechecker/for/error_duplicate_ident.abra", "typechecker/for/error_duplicate_ident.out") - .add_test_vs_file("typechecker/for/error_iteratee_invalid_destructuring_tuple.abra", "typechecker/for/error_iteratee_invalid_destructuring_tuple.out") - // Binding declaration - .add_test_vs_file("typechecker/bindingdecl/bindingdecl.abra", "typechecker/bindingdecl/bindingdecl.out.json") - .add_test_vs_file("typechecker/bindingdecl/bindingdecl_exported.abra", "typechecker/bindingdecl/bindingdecl_exported.out.json") - .add_test_vs_file("typechecker/bindingdecl/error_bare_var.abra", "typechecker/bindingdecl/error_bare_var.out") - .add_test_vs_file("typechecker/bindingdecl/error_duplicate_name.abra", "typechecker/bindingdecl/error_duplicate_name.out") - .add_test_vs_file("typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.1.abra", "typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.1.out") - .add_test_vs_file("typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.2.abra", "typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.2.out") - .add_test_vs_file("typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.3.abra", "typechecker/bindingdecl/error_invalid_destructuring_tuple_non_tuple.3.out") - .add_test_vs_file("typechecker/bindingdecl/error_invalid_destructuring_tuple_too_few.1.abra", "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_few.1.out") - .add_test_vs_file("typechecker/bindingdecl/error_invalid_destructuring_tuple_too_few.2.abra", "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_few.2.out") - .add_test_vs_file("typechecker/bindingdecl/error_invalid_destructuring_tuple_too_many.1.abra", "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_many.1.out") - .add_test_vs_file("typechecker/bindingdecl/error_invalid_destructuring_tuple_too_many.2.abra", "typechecker/bindingdecl/error_invalid_destructuring_tuple_too_many.2.out") - .add_test_vs_file("typechecker/bindingdecl/error_type_mismatch_val_destructured_tuple.abra", "typechecker/bindingdecl/error_type_mismatch_val_destructured_tuple.out") - .add_test_vs_file("typechecker/bindingdecl/error_uninitialized_val_destructured_tuple_no_annotation.abra", "typechecker/bindingdecl/error_uninitialized_val_destructured_tuple_no_annotation.out") - .add_test_vs_file("typechecker/bindingdecl/error_uninitialized_val_destructured_tuple_with_annotation.abra", "typechecker/bindingdecl/error_uninitialized_val_destructured_tuple_with_annotation.out") - .add_test_vs_file("typechecker/bindingdecl/error_uninitialized_val_no_annotation.abra", "typechecker/bindingdecl/error_uninitialized_val_no_annotation.out") - .add_test_vs_file("typechecker/bindingdecl/error_uninitialized_val_with_annotation.abra", "typechecker/bindingdecl/error_uninitialized_val_with_annotation.out") - .add_test_vs_file("typechecker/bindingdecl/error_type_mismatch_val.abra", "typechecker/bindingdecl/error_type_mismatch_val.out") - .add_test_vs_file("typechecker/bindingdecl/error_type_mismatch_var.abra", "typechecker/bindingdecl/error_type_mismatch_var.out") - .add_test_vs_file("typechecker/bindingdecl/error_type_mismatch_option.abra", "typechecker/bindingdecl/error_type_mismatch_option.out") - .add_test_vs_file("typechecker/bindingdecl/error_unfilled_holes.abra", "typechecker/bindingdecl/error_unfilled_holes.out") - .add_test_vs_file("typechecker/bindingdecl/error_illegal_value_type_enum.abra", "typechecker/bindingdecl/error_illegal_value_type_enum.out") - .add_test_vs_file("typechecker/bindingdecl/error_illegal_value_type_enum_container_variant.abra", "typechecker/bindingdecl/error_illegal_value_type_enum_container_variant.out") - .add_test_vs_file("typechecker/bindingdecl/error_illegal_value_type_type.abra", "typechecker/bindingdecl/error_illegal_value_type_type.out") - .add_test_vs_file("typechecker/bindingdecl/error_export_bad_scope.abra", "typechecker/bindingdecl/error_export_bad_scope.out") - // Function declaration - .add_test_vs_file("typechecker/funcdecl/funcdecl.1.abra", "typechecker/funcdecl/funcdecl.1.out.json") - .add_test_vs_file("typechecker/funcdecl/funcdecl.2.abra", "typechecker/funcdecl/funcdecl.2.out.json") - .add_test_vs_file("typechecker/funcdecl/funcdecl.3.abra", "typechecker/funcdecl/funcdecl.3.out.json") - .add_test_vs_file("typechecker/funcdecl/funcdecl.4.abra", "typechecker/funcdecl/funcdecl.4.out.json") - .add_test_vs_file("typechecker/funcdecl/funcdecl.5.abra", "typechecker/funcdecl/funcdecl.5.out.json") - .add_test_vs_file("typechecker/funcdecl/funcdecl.6.abra", "typechecker/funcdecl/funcdecl.6.out.json") - .add_test_vs_file("typechecker/funcdecl/funcdecl.7.abra", "typechecker/funcdecl/funcdecl.7.out.json") - .add_test_vs_file("typechecker/funcdecl/funcdecl_exported.abra", "typechecker/funcdecl/funcdecl_exported.out.json") - .add_test_vs_file("typechecker/funcdecl/funcdecl_generics.abra", "typechecker/funcdecl/funcdecl_generics.out.json") - .add_test_vs_file("typechecker/funcdecl/error_duplicate_func.abra", "typechecker/funcdecl/error_duplicate_func.out") - .add_test_vs_file("typechecker/funcdecl/error_duplicate_param.abra", "typechecker/funcdecl/error_duplicate_param.out") - .add_test_vs_file("typechecker/funcdecl/error_duplicate_variable.abra", "typechecker/funcdecl/error_duplicate_variable.out") - .add_test_vs_file("typechecker/funcdecl/error_invalid_param_type.abra", "typechecker/funcdecl/error_invalid_param_type.out") - .add_test_vs_file("typechecker/funcdecl/error_invalid_req_param_position.abra", "typechecker/funcdecl/error_invalid_req_param_position.out") - .add_test_vs_file("typechecker/funcdecl/error_invalid_return_type.abra", "typechecker/funcdecl/error_invalid_return_type.out") - .add_test_vs_file("typechecker/funcdecl/error_invalid_vararg_position.abra", "typechecker/funcdecl/error_invalid_vararg_position.out") - .add_test_vs_file("typechecker/funcdecl/error_invalid_vararg_type.abra", "typechecker/funcdecl/error_invalid_vararg_type.out") - .add_test_vs_file("typechecker/funcdecl/error_param_unfilled_holes.1.abra", "typechecker/funcdecl/error_param_unfilled_holes.1.out") - .add_test_vs_file("typechecker/funcdecl/error_param_unfilled_holes.2.abra", "typechecker/funcdecl/error_param_unfilled_holes.2.out") - .add_test_vs_file("typechecker/funcdecl/error_type_mismatch_param_default_value.1.abra", "typechecker/funcdecl/error_type_mismatch_param_default_value.1.out") - .add_test_vs_file("typechecker/funcdecl/error_type_mismatch_param_default_value.2.abra", "typechecker/funcdecl/error_type_mismatch_param_default_value.2.out") - .add_test_vs_file("typechecker/funcdecl/error_type_mismatch_param_default_value.3.abra", "typechecker/funcdecl/error_type_mismatch_param_default_value.3.out") - .add_test_vs_file("typechecker/funcdecl/error_type_mismatch_param_default_value.4.abra", "typechecker/funcdecl/error_type_mismatch_param_default_value.4.out") - .add_test_vs_file("typechecker/funcdecl/error_alias_type_mismatch.abra", "typechecker/funcdecl/error_alias_type_mismatch.out") - .add_test_vs_file("typechecker/funcdecl/error_invalid_vararg_type_option.abra", "typechecker/funcdecl/error_invalid_vararg_type_option.out") - .add_test_vs_file("typechecker/funcdecl/error_param_default_value_ident.abra", "typechecker/funcdecl/error_param_default_value_ident.out") - .add_test_vs_file("typechecker/funcdecl/error_return_type_mismatch.abra", "typechecker/funcdecl/error_return_type_mismatch.out") - .add_test_vs_file("typechecker/funcdecl/error_return_type_mismatch_empty.abra", "typechecker/funcdecl/error_return_type_mismatch_empty.out") - .add_test_vs_file("typechecker/funcdecl/error_return_type_mismatch_stmt.abra", "typechecker/funcdecl/error_return_type_mismatch_stmt.out") - .add_test_vs_file("typechecker/funcdecl/default_param_value_call.1.abra", "typechecker/funcdecl/default_param_value_call.1.out.json") - .add_test_vs_file("typechecker/funcdecl/default_param_value_call.2.abra", "typechecker/funcdecl/default_param_value_call.2.out.json") - .add_test_vs_file("typechecker/funcdecl/default_param_value_call.3.abra", "typechecker/funcdecl/default_param_value_call.3.out.json") - .add_test_vs_file("typechecker/funcdecl/default_param_value_call.4.abra", "typechecker/funcdecl/default_param_value_call.4.out.json") - .add_test_vs_file("typechecker/funcdecl/default_param_value_call.5.abra", "typechecker/funcdecl/default_param_value_call.5.out.json") - .add_test_vs_file("typechecker/funcdecl/default_param_value_call.6.abra", "typechecker/funcdecl/default_param_value_call.6.out.json") - .add_test_vs_file("typechecker/funcdecl/default_param_value_call.7.abra", "typechecker/funcdecl/default_param_value_call.7.out.json") - .add_test_vs_file("typechecker/funcdecl/default_param_value_call.8.abra", "typechecker/funcdecl/default_param_value_call.8.out.json") - .add_test_vs_file("typechecker/funcdecl/default_param_value_call.9.abra", "typechecker/funcdecl/default_param_value_call.9.out.json") - .add_test_vs_file("typechecker/funcdecl/default_param_value_accessor.abra", "typechecker/funcdecl/default_param_value_accessor.out.json") - .add_test_vs_file("typechecker/funcdecl/error_self_standalone.abra", "typechecker/funcdecl/error_self_standalone.out") - .add_test_vs_file("typechecker/funcdecl/error_generics_param_type_mismatch.abra", "typechecker/funcdecl/error_generics_param_type_mismatch.out") - .add_test_vs_file("typechecker/funcdecl/error_generics_return_type_mismatch.abra", "typechecker/funcdecl/error_generics_return_type_mismatch.out") - .add_test_vs_file("typechecker/funcdecl/error_export_bad_scope.abra", "typechecker/funcdecl/error_export_bad_scope.out") - - // Type declaration - .add_test_vs_file("typechecker/typedecl/typedecl_exported.abra", "typechecker/typedecl/typedecl_exported.out.json") - .add_test_vs_file("typechecker/typedecl/typedecl.1.abra", "typechecker/typedecl/typedecl.1.out.json") - .add_test_vs_file("typechecker/typedecl/typedecl.2.abra", "typechecker/typedecl/typedecl.2.out.json") - .add_test_vs_file("typechecker/typedecl/error_duplicate_field.abra", "typechecker/typedecl/error_duplicate_field.out") - .add_test_vs_file("typechecker/typedecl/error_method_bad_self_position.abra", "typechecker/typedecl/error_method_bad_self_position.out") - .add_test_vs_file("typechecker/typedecl/error_field_initializer_type_mismatch.abra", "typechecker/typedecl/error_field_initializer_type_mismatch.out") - .add_test_vs_file("typechecker/typedecl/error_invalid_eq_signature.1.abra", "typechecker/typedecl/error_invalid_eq_signature.1.out") - .add_test_vs_file("typechecker/typedecl/error_invalid_eq_signature.2.abra", "typechecker/typedecl/error_invalid_eq_signature.2.out") - .add_test_vs_file("typechecker/typedecl/error_invalid_hash_signature.abra", "typechecker/typedecl/error_invalid_hash_signature.out") - .add_test_vs_file("typechecker/typedecl/error_invalid_tostring_signature.abra", "typechecker/typedecl/error_invalid_tostring_signature.out") - .add_test_vs_file("typechecker/typedecl/error_duplicate_type_func.abra", "typechecker/typedecl/error_duplicate_type_func.out") - .add_test_vs_file("typechecker/typedecl/error_duplicate_type_type.abra", "typechecker/typedecl/error_duplicate_type_type.out") - .add_test_vs_file("typechecker/typedecl/error_duplicate_type_enum.abra", "typechecker/typedecl/error_duplicate_type_enum.out") - // Enum declaration - .add_test_vs_file("typechecker/enumdecl/enumdecl_exported.abra", "typechecker/enumdecl/enumdecl_exported.out.json") - .add_test_vs_file("typechecker/enumdecl/enumdecl.1.abra", "typechecker/enumdecl/enumdecl.1.out.json") - .add_test_vs_file("typechecker/enumdecl/enumdecl_Result_shorthand.abra", "typechecker/enumdecl/enumdecl_Result_shorthand.out.json") - .add_test_vs_file("typechecker/enumdecl/error_duplicate_enum_enum.abra", "typechecker/enumdecl/error_duplicate_enum_enum.out") - .add_test_vs_file("typechecker/enumdecl/error_duplicate_enum_func.abra", "typechecker/enumdecl/error_duplicate_enum_func.out") - .add_test_vs_file("typechecker/enumdecl/error_duplicate_enum_type.abra", "typechecker/enumdecl/error_duplicate_enum_type.out") - .add_test_vs_file("typechecker/enumdecl/error_duplicate_variant.abra", "typechecker/enumdecl/error_duplicate_variant.out") - .add_test_vs_file("typechecker/enumdecl/error_duplicate_variant_field.abra", "typechecker/enumdecl/error_duplicate_variant_field.out") - .add_test_vs_file("typechecker/enumdecl/error_invalid_eq_signature.1.abra", "typechecker/enumdecl/error_invalid_eq_signature.1.out") - .add_test_vs_file("typechecker/enumdecl/error_invalid_eq_signature.2.abra", "typechecker/enumdecl/error_invalid_eq_signature.2.out") - .add_test_vs_file("typechecker/enumdecl/error_invalid_hash_signature.abra", "typechecker/enumdecl/error_invalid_hash_signature.out") - .add_test_vs_file("typechecker/enumdecl/error_invalid_tostring_signature.abra", "typechecker/enumdecl/error_invalid_tostring_signature.out") - .add_test_vs_file("typechecker/enumdecl/error_method_bad_self_position.abra", "typechecker/enumdecl/error_method_bad_self_position.out") - .add_test_vs_file("typechecker/enumdecl/error_variant_field_initializer_type_mismatch.abra", "typechecker/enumdecl/error_variant_field_initializer_type_mismatch.out") - - // Returns - .add_test_vs_file("typechecker/return/return.1.abra", "typechecker/return/return.1.out.json") - .add_test_vs_file("typechecker/return/return.2.abra", "typechecker/return/return.2.out.json") - .add_test_vs_file("typechecker/return/return.3.abra", "typechecker/return/return.3.out.json") - .add_test_vs_file("typechecker/return/as_expr_error_never.abra", "typechecker/return/as_expr_error_never.out") - .add_test_vs_file("typechecker/return/error_location.abra", "typechecker/return/error_location.out") - .add_test_vs_file("typechecker/return/error_type_mismatch.abra", "typechecker/return/error_type_mismatch.out") - .add_test_vs_file("typechecker/return/error_type_mismatch_unit.abra", "typechecker/return/error_type_mismatch_unit.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_plain.abra", "typechecker/return/error_unreachable_stmt_plain.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_if_inside.abra", "typechecker/return/error_unreachable_stmt_if_inside.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_if_outside.abra", "typechecker/return/error_unreachable_stmt_if_outside.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_match_inside.abra", "typechecker/return/error_unreachable_stmt_match_inside.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_match_outside.abra", "typechecker/return/error_unreachable_stmt_match_outside.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_while_inside.1.abra", "typechecker/return/error_unreachable_stmt_while_inside.1.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_while_inside.2.abra", "typechecker/return/error_unreachable_stmt_while_inside.2.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_while_outside.1.abra", "typechecker/return/error_unreachable_stmt_while_outside.1.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_while_outside.2.abra", "typechecker/return/error_unreachable_stmt_while_outside.2.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_for_inside.1.abra", "typechecker/return/error_unreachable_stmt_for_inside.1.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_for_inside.2.abra", "typechecker/return/error_unreachable_stmt_for_inside.2.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_for_outside.1.abra", "typechecker/return/error_unreachable_stmt_for_outside.1.out") - .add_test_vs_file("typechecker/return/error_unreachable_stmt_for_outside.2.abra", "typechecker/return/error_unreachable_stmt_for_outside.2.out") - - // Imports - .add_test_vs_file("typechecker/import/import.1.abra", "typechecker/import/import.1.out.json") - .add_test_vs_file("typechecker/import/import.2.abra", "typechecker/import/import.2.out.json") - .add_test_vs_file("typechecker/import/error_assignment_to_aliased_imported_variable.abra", "typechecker/import/error_assignment_to_aliased_imported_variable.out") - .add_test_vs_file("typechecker/import/error_assignment_to_imported_variable.abra", "typechecker/import/error_assignment_to_imported_variable.out") - - .add_test_vs_file("typechecker/import/error_no_file_exists.abra", "typechecker/import/error_no_file_exists.out") - .add_test_vs_file("typechecker/import/error_nonrelative_not_found.abra", "typechecker/import/error_nonrelative_not_found.out") - .add_test_vs_file("typechecker/import/error_circular_dependency.1/mod.1.abra", "typechecker/import/error_circular_dependency.1/mod.1.out") - .add_test_vs_file("typechecker/import/error_circular_dependency.2/mod.1.abra", "typechecker/import/error_circular_dependency.2/mod.1.out") - .add_test_vs_file("typechecker/import/error_duplicate_import_name.1.abra", "typechecker/import/error_duplicate_import_name.1.out") - .add_test_vs_file("typechecker/import/error_duplicate_import_name.2.abra", "typechecker/import/error_duplicate_import_name.2.out") - .add_test_vs_file("typechecker/import/error_duplicate_variable_name.1.abra", "typechecker/import/error_duplicate_variable_name.1.out") - .add_test_vs_file("typechecker/import/error_duplicate_variable_name.2.abra", "typechecker/import/error_duplicate_variable_name.2.out") - .add_test_vs_file("typechecker/import/error_duplicate_func_name.1.abra", "typechecker/import/error_duplicate_func_name.1.out") - .add_test_vs_file("typechecker/import/error_duplicate_func_name.2.abra", "typechecker/import/error_duplicate_func_name.2.out") - .add_test_vs_file("typechecker/import/error_imported_value_type_mismatch.abra", "typechecker/import/error_imported_value_type_mismatch.out") - .add_test_vs_file("typechecker/import/error_no_exported_value.abra", "typechecker/import/error_no_exported_value.out") - .add_test_vs_file("typechecker/import/error_duplicate_enum_name.1.abra", "typechecker/import/error_duplicate_enum_name.1.out") - .add_test_vs_file("typechecker/import/error_duplicate_enum_name.2.abra", "typechecker/import/error_duplicate_enum_name.2.out") - .add_test_vs_file("typechecker/import/error_duplicate_enum_name.3.abra", "typechecker/import/error_duplicate_enum_name.3.out") - .add_test_vs_file("typechecker/import/error_duplicate_enum_name.4.abra", "typechecker/import/error_duplicate_enum_name.4.out") - .add_test_vs_file("typechecker/import/error_duplicate_func_name.3.abra", "typechecker/import/error_duplicate_func_name.3.out") - .add_test_vs_file("typechecker/import/error_duplicate_func_name.4.abra", "typechecker/import/error_duplicate_func_name.4.out") - .add_test_vs_file("typechecker/import/error_duplicate_import_name.3.abra", "typechecker/import/error_duplicate_import_name.3.out") - .add_test_vs_file("typechecker/import/error_duplicate_import_name.4.abra", "typechecker/import/error_duplicate_import_name.4.out") - .add_test_vs_file("typechecker/import/error_duplicate_type_name.1.abra", "typechecker/import/error_duplicate_type_name.1.out") - .add_test_vs_file("typechecker/import/error_duplicate_type_name.2.abra", "typechecker/import/error_duplicate_type_name.2.out") - .add_test_vs_file("typechecker/import/error_duplicate_type_name.3.abra", "typechecker/import/error_duplicate_type_name.3.out") - .add_test_vs_file("typechecker/import/error_duplicate_type_name.4.abra", "typechecker/import/error_duplicate_type_name.4.out") - .add_test_vs_file("typechecker/import/error_duplicate_variable_name.3.abra", "typechecker/import/error_duplicate_variable_name.3.out") - .add_test_vs_file("typechecker/import/error_duplicate_variable_name.4.abra", "typechecker/import/error_duplicate_variable_name.4.out") - .add_test_vs_file("typechecker/import/error_imported_type_mismatch.1.abra", "typechecker/import/error_imported_type_mismatch.1.out") - .add_test_vs_file("typechecker/import/import_type_identifier.1.abra", "typechecker/import/import_type_identifier.1.out.json") - .add_test_vs_file("typechecker/import/import_type_identifier.2.abra", "typechecker/import/import_type_identifier.2.out.json") - .add_test_vs_file("typechecker/import/error_alias_duplicate_name.abra", "typechecker/import/error_alias_duplicate_name.out") - .add_test_vs_file("typechecker/import/error_alias_questiondot_access.abra", "typechecker/import/error_alias_questiondot_access.out") - .add_test_vs_file("typechecker/import/error_alias_unknown_import.abra", "typechecker/import/error_alias_unknown_import.out") - - .run_tests(); -} - -#[test] -fn compiler_tests() { - let mut test_runner = TestRunner::compiler_test_runner() - .add_test("compiler/ints.abra") - .add_test("compiler/floats.abra") - .add_test("compiler/bools.abra") - .add_test("compiler/strings.abra") - .add_test("compiler/arrays.abra") - .add_test("compiler/functions.abra") - .add_test("compiler/optionals.abra") - .add_test("compiler/ifs.abra") - .add_test("compiler/loops.abra") - .add_test("compiler/types.abra") - .add_test("compiler/enums.abra") - .add_test("compiler/tuples.abra") - .add_test("compiler/maps.abra") - .add_test("compiler/sets.abra") - .add_test("compiler/match.abra") - .add_test_with_args_and_env("compiler/process.abra", &["-f", "bar", "--baz", "qux"], &[("FOO", "bar")]); - - test_runner = if cfg!(target_os = "linux") { - test_runner.add_test("compiler/process_linux.abra") - } else if cfg!(target_os = "macos") { - test_runner.add_test("compiler/process_macos.abra") - } else { - unreachable!("unsupported operating system {}", std::env::consts::OS) - }; - - test_runner.run_tests(); -} \ No newline at end of file