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