From 6e592e7d9b6b73f446cbe0dbbac28b5665e4fd68 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Thu, 13 Mar 2025 22:24:41 +0000 Subject: [PATCH] feat: functional single-threaded imports --- extension/examples/valid/imports/basic.wacc | 1 + .../examples/valid/imports/manyMains.wacc | 1 - .../{mutliFunc.wacc => multiFunc.wacc} | 0 src/main/wacc/Main.scala | 56 ++++--- src/main/wacc/backend/LabelGenerator.scala | 2 +- src/main/wacc/frontend/Error.scala | 22 +-- src/main/wacc/frontend/ast.scala | 2 +- src/main/wacc/frontend/renamer.scala | 152 +++++++++--------- src/main/wacc/frontend/typeChecker.scala | 73 ++++----- src/test/wacc/examples.scala | 12 +- 10 files changed, 166 insertions(+), 155 deletions(-) rename extension/examples/valid/imports/{mutliFunc.wacc => multiFunc.wacc} (100%) diff --git a/extension/examples/valid/imports/basic.wacc b/extension/examples/valid/imports/basic.wacc index aae959b..d34a34a 100644 --- a/extension/examples/valid/imports/basic.wacc +++ b/extension/examples/valid/imports/basic.wacc @@ -2,6 +2,7 @@ # Output: # -33 +# # Exit: # 0 diff --git a/extension/examples/valid/imports/manyMains.wacc b/extension/examples/valid/imports/manyMains.wacc index d52997f..fc3bc7c 100644 --- a/extension/examples/valid/imports/manyMains.wacc +++ b/extension/examples/valid/imports/manyMains.wacc @@ -2,7 +2,6 @@ # Output: # 15 -# 0 # -33 # 0 # -33 diff --git a/extension/examples/valid/imports/mutliFunc.wacc b/extension/examples/valid/imports/multiFunc.wacc similarity index 100% rename from extension/examples/valid/imports/mutliFunc.wacc rename to extension/examples/valid/imports/multiFunc.wacc diff --git a/src/main/wacc/Main.scala b/src/main/wacc/Main.scala index 3fef6dc..e78d4bd 100644 --- a/src/main/wacc/Main.scala +++ b/src/main/wacc/Main.scala @@ -71,21 +71,23 @@ val outputOpt: Opts[Option[Path]] = def frontend( contents: String, file: File -): Either[NonEmptyList[Error], microWacc.Program] = +): IO[Either[NonEmptyList[Error], microWacc.Program]] = parser.parse(contents) match { - case Failure(msg) => Left(NonEmptyList.one(Error.SyntaxError(file, msg))) + case Failure(msg) => IO.pure(Left(NonEmptyList.one(Error.SyntaxError(file, msg)))) case Success(fn) => - val ast.PartialProgram(_, prog) = fn(file) + val partialProg = fn(file) given errors: mutable.Builder[Error, List[Error]] = List.newBuilder - val (names, funcs) = renamer.rename(prog) - given ctx: typeChecker.TypeCheckerCtx = typeChecker.TypeCheckerCtx(names, funcs, errors) - val typedProg = typeChecker.check(prog) + for { + (prog, renameErrors) <- renamer.rename(partialProg) + _ = errors.addAll(renameErrors.toList) + typedProg = typeChecker.check(prog, errors) - NonEmptyList.fromList(errors.result) match { - case Some(errors) => Left(errors) - case None => Right(typedProg) - } + res = NonEmptyList.fromList(errors.result) match { + case Some(errors) => Left(errors) + case None => Right(typedProg) + } + } yield res } def backend(typedProg: microWacc.Program): Chain[asm.AsmLine] = @@ -109,23 +111,25 @@ def compile( logger.info(s"Success: ${outputPath.toAbsolutePath}") def processProgram(contents: String, file: File, outDir: Path): IO[Int] = - frontend(contents, file) match { - case Left(errors) => - val code = errors.map(err => err.exitCode).toList.min - given errorContent: String = contents - val errorMsg = errors.map(formatError).toIterable.mkString("\n") - for { - _ <- logAction(s"Compilation failed for $filePath\nExit code: $code") - _ <- IO.blocking( - // Explicit println since we want this to always show without logger thread info e.t.c. - println(s"Compilation failed for ${file.getCanonicalPath}:\n$errorMsg") - ) - } yield code + for { + frontendResult <- frontend(contents, file) + res <- frontendResult match { + case Left(errors) => + val code = errors.map(err => err.exitCode).toList.min + val errorMsg = errors.map(formatError).toIterable.mkString("\n") + for { + _ <- logAction(s"Compilation failed for $filePath\nExit code: $code") + _ <- IO.blocking( + // Explicit println since we want this to always show without logger thread info e.t.c. + println(s"Compilation failed for ${file.getCanonicalPath}:\n$errorMsg") + ) + } yield code - case Right(typedProg) => - val outputFile = outDir.resolve(filePath.getFileName.toString.stripSuffix(".wacc") + ".s") - writeOutputFile(typedProg, outputFile).as(SUCCESS) - } + case Right(typedProg) => + val outputFile = outDir.resolve(filePath.getFileName.toString.stripSuffix(".wacc") + ".s") + writeOutputFile(typedProg, outputFile).as(SUCCESS) + } + } yield res for { contents <- readSourceFile diff --git a/src/main/wacc/backend/LabelGenerator.scala b/src/main/wacc/backend/LabelGenerator.scala index 3b5169b..29d03db 100644 --- a/src/main/wacc/backend/LabelGenerator.scala +++ b/src/main/wacc/backend/LabelGenerator.scala @@ -18,7 +18,7 @@ private class LabelGenerator { } private def getLabel(target: CallTarget | RuntimeError): String = target match { - case Ident(v, _) => s"wacc_$v" + case Ident(v, guid) => s"wacc_${v}_$guid" case Builtin(name) => s"_$name" case err: RuntimeError => s".L.${err.name}" } diff --git a/src/main/wacc/frontend/Error.scala b/src/main/wacc/frontend/Error.scala index 7c2ab7e..188e91c 100644 --- a/src/main/wacc/frontend/Error.scala +++ b/src/main/wacc/frontend/Error.scala @@ -36,7 +36,7 @@ extension (e: Error) { * @param errorContent * Contents of the file to generate code snippets */ -def formatError(error: Error)(using errorContent: String): String = { +def formatError(error: Error): String = { val sb = new StringBuilder() /** Format the file of an error @@ -66,7 +66,7 @@ def formatError(error: Error)(using errorContent: String): String = { * Size(in chars) of section to highlight */ def formatHighlight(pos: Position, size: Int): Unit = { - val lines = errorContent.split("\n") + val lines = os.read(os.Path(pos.file.getCanonicalPath)).split("\n") val preLine = if (pos.line > 1) lines(pos.line - 2) else "" val midLine = lines(pos.line - 1) val postLine = if (pos.line < lines.size) lines(pos.line) else "" @@ -87,38 +87,38 @@ def formatError(error: Error)(using errorContent: String): String = { error match { case Error.DuplicateDeclaration(ident) => formatPosition(ident.pos) - sb.append(s"Duplicate declaration of identifier ${ident.v}") + sb.append(s"Duplicate declaration of identifier ${ident.v}\n") formatHighlight(ident.pos, ident.v.length) case Error.UndeclaredVariable(ident) => formatPosition(ident.pos) - sb.append(s"Undeclared variable ${ident.v}") + sb.append(s"Undeclared variable ${ident.v}\n") formatHighlight(ident.pos, ident.v.length) case Error.UndefinedFunction(ident) => formatPosition(ident.pos) - sb.append(s"Undefined function ${ident.v}") + sb.append(s"Undefined function ${ident.v}\n") formatHighlight(ident.pos, ident.v.length) case Error.FunctionParamsMismatch(id, expected, got, funcType) => formatPosition(id.pos) - sb.append(s"Function expects $expected parameters, got $got") + sb.append(s"Function expects $expected parameters, got $got\n") sb.append( - s"(function ${id.v} has type (${funcType.params.mkString(", ")}) -> ${funcType.returnType})" + s"(function ${id.v} has type (${funcType.params.mkString(", ")}) -> ${funcType.returnType})\n" ) formatHighlight(id.pos, 1) case Error.TypeMismatch(pos, expected, got, msg) => formatPosition(pos) - sb.append(s"Type mismatch: $msg\nExpected: $expected\nGot: $got") + sb.append(s"Type mismatch: $msg\nExpected: $expected\nGot: $got\n") formatHighlight(pos, 1) case Error.SemanticError(pos, msg) => formatPosition(pos) - sb.append(msg) + sb.append(msg + "\n") formatHighlight(pos, 1) case wacc.Error.InternalError(pos, msg) => formatPosition(pos) - sb.append(s"Internal error: $msg") + sb.append(s"Internal error: $msg\n") formatHighlight(pos, 1) case Error.SyntaxError(file, msg) => formatFile(file) - sb.append(msg) + sb.append(msg + "\n") sb.append("\n") } diff --git a/src/main/wacc/frontend/ast.scala b/src/main/wacc/frontend/ast.scala index 7e15c60..e39f931 100644 --- a/src/main/wacc/frontend/ast.scala +++ b/src/main/wacc/frontend/ast.scala @@ -32,7 +32,7 @@ object ast { object StrLiter extends ParserBridgePos1Atom[String, StrLiter] case class PairLiter()(val pos: Position) extends Expr6 object PairLiter extends ParserBridgePos0[PairLiter] - case class Ident(v: String, var guid: Int = -1, var ty: types.RenamerType = types.?)( + case class Ident(var v: String, var guid: Int = -1, var ty: types.RenamerType = types.?)( val pos: Position ) extends Expr6 with LValue diff --git a/src/main/wacc/frontend/renamer.scala b/src/main/wacc/frontend/renamer.scala index 3d5c917..bbce1bb 100644 --- a/src/main/wacc/frontend/renamer.scala +++ b/src/main/wacc/frontend/renamer.scala @@ -6,12 +6,8 @@ import cats.effect.IO import cats.syntax.all._ import cats.implicits._ import cats.data.Chain -import cats.Foldable -import cats.Functor import cats.data.NonEmptyList import parsley.{Failure, Success} -import cats.data.NonEmptyChain -import cats.NonEmptyParallel private val MAIN = "$main" @@ -54,7 +50,8 @@ object renamer { * A new scope with an empty current scope, and this scope flattened into the parent scope. */ def withSubscope[T](f: Scope => T): T = { - val subscope = Scope(mutable.Map.empty, Map.empty.withDefault(current.withDefault(parent)), guid, guidInc) + val subscope = + Scope(mutable.Map.empty, Map.empty.withDefault(current.withDefault(parent)), guid, guidInc) immutable = true val result = f(subscope) guid = subscope.guid // Sync GUID @@ -64,7 +61,7 @@ object renamer { /** Create new scopes with the current scope as its parent and GUID numbering adjusted * correctly. - * + * * This will permanently mark the current scope as immutable, for thread safety. * * To be used for multi-threaded applications. @@ -115,10 +112,10 @@ object renamer { /** Attempt to add a new identifier as an alias to another to the existing scope. * * @param alias - * The (new) alias identifier. + * The (new) alias identifier. * @param orig - * The (existing) original identifier. - * + * The (existing) original identifier. + * * @return * An error, if one occurred. */ @@ -150,15 +147,21 @@ object renamer { case _: NoSuchElementException => None } - def getVar(name: Ident): Option[Ident] = get(name.pos.file.getCanonicalPath, name.v, IdentType.Var).map(_.id) - def getFunc(name: Ident): Option[Ident] = get(name.pos.file.getCanonicalPath, name.v, IdentType.Func).map(_.id) + def getVar(name: Ident): Option[Ident] = + get(name.pos.file.getCanonicalPath, name.v, IdentType.Var).map(_.id) + def getFunc(name: Ident): Option[Ident] = + get(name.pos.file.getCanonicalPath, name.v, IdentType.Func).map(_.id) } - private def prepareGlobalScope(partialProg: PartialProgram)(using scope: Scope): IO[(FuncDecl, Chain[FuncDecl], Chain[Error])] = { + private def prepareGlobalScope( + partialProg: PartialProgram + )(using scope: Scope): IO[(FuncDecl, Chain[FuncDecl], Chain[Error])] = { def readImportFile(file: File): IO[String] = IO.blocking(os.read(os.Path(file.getCanonicalPath))) - def prepareImport(contents: String, file: File)(using scope: Scope): IO[(Chain[FuncDecl], Chain[Error])] = { + def prepareImport(contents: String, file: File)(using + scope: Scope + ): IO[(Chain[FuncDecl], Chain[Error])] = { parser.parse(contents) match { case Failure(msg) => IO.pure(Chain.empty, Chain.one(Error.SyntaxError(file, msg))) @@ -168,15 +171,27 @@ object renamer { (main, chunks, errors) <- prepareGlobalScope(partialProg) } yield (main +: chunks, errors) } - } + def addImportsToScope(importFile: File, funcs: NonEmptyList[ImportedFunc])(using + scope: Scope + ): Chain[Error] = + funcs.foldMap { case ImportedFunc(srcName, aliasName) => + scope.get(importFile.getCanonicalPath, srcName.v, IdentType.Func) match { + case Some(src) if src.public => + aliasName.ty = src.id.ty + scope.addAlias(aliasName, src) + case _ => + Chain.one(Error.UndefinedFunction(srcName)) + } + } + val PartialProgram(imports, prog) = partialProg // First prepare this file's functions... val Program(funcs, main) = prog val (funcChunks, funcErrors) = funcs.foldLeft((Chain.empty[FuncDecl], Chain.empty[Error])) { - case ((chunks, errors), func@FuncDecl(retType, name, params, body)) => + case ((chunks, errors), func @ FuncDecl(retType, name, params, body)) => val paramTypes = params.map { param => val paramType = SemType(param.paramType) param.name.ty = paramType @@ -192,20 +207,49 @@ object renamer { // Now handle imports val file = prog.pos.file - val preparedImports = imports.foldLeftM[IO, (Chain[FuncDecl], Chain[Error])]((Chain.empty[FuncDecl], Chain.empty[Error])) { - case ((chunks, errors), Import(name, funcs)) => - val importFile = File(file.getParent, name.v) + val preparedImports = imports.foldLeftM[IO, (Chain[FuncDecl], Chain[Error])]( + (Chain.empty[FuncDecl], Chain.empty[Error]) + ) { case ((chunks, errors), Import(name, funcs)) => + val importFile = File(file.getParent, name.v) + if (!importFile.exists()) { + IO.pure( + ( + chunks, + errors :+ Error.SemanticError( + name.pos, + s"File not found: ${importFile.getCanonicalPath}" + ) + ) + ) + } else if (!importFile.canRead()) { + IO.pure( + ( + chunks, + errors :+ Error.SemanticError( + name.pos, + s"File not readable: ${importFile.getCanonicalPath}" + ) + ) + ) + } else if (importFile.getCanonicalPath == file.getCanonicalPath) { + IO.pure( + ( + chunks, + errors :+ Error.SemanticError( + name.pos, + s"Cannot import self: ${importFile.getCanonicalPath}" + ) + ) + ) + } else if (scope.get(importFile.getCanonicalPath, MAIN, IdentType.Func).isDefined) { + IO.pure(chunks, errors ++ addImportsToScope(importFile, funcs)) + } else { for { contents <- readImportFile(importFile) (importChunks, importErrors) <- prepareImport(contents, importFile) - importAliasErrors = funcs.foldMap { case ImportedFunc(srcName, aliasName) => - scope.get(importFile.getCanonicalPath, srcName.v, IdentType.Func) match { - case Some(src) if src.public => scope.addAlias(aliasName, src) - case _ => Chain.one(Error.UndefinedFunction(srcName)) - } - - } + importAliasErrors = addImportsToScope(importFile, funcs) } yield (chunks ++ importChunks, errors ++ importErrors) + } } for { @@ -228,55 +272,15 @@ object renamer { for { (main, chunks, errors) <- prepareGlobalScope(partialProg) toRename = (main +: chunks).toList - res = (toRename zip scope.subscopes(toRename.size)).parTraverse { case (func@FuncDecl(retType, name, params, body), subscope) => - val paramErrors = params.foldMap { param => subscope.add(param.name) } - val bodyErrors = subscope.withSubscope { s => body.foldMap(rename(s)) } - paramErrors ++ bodyErrors + res = (toRename zip scope.subscopes(toRename.size)).foldMap { + case (func @ FuncDecl(retType, name, params, body), subscope) => + val paramErrors = params.foldMap { param => subscope.add(param.name) } + val bodyErrors = subscope.withSubscope { s => body.foldMap(rename(s)) } + paramErrors ++ bodyErrors } - } yield (Program(chunks.toList, main.body)(main.pos), errors) + } yield (Program(chunks.toList, main.body)(main.pos), errors ++ res) } - // /** Check scoping of all variables and functions in the program. Also generate semantic types for - // * all identifiers. - // * - // * @param prog - // * AST of the program - // * @param errors - // * List of errors to append to - // * @return - // * Map of all (renamed) identifies to their semantic types - // */ - // def rename(prog: Program)(using - // errors: mutable.Builder[Error, List[Error]] - // ): (Map[Ident, SemType], Map[Ident, FuncType]) = { - // given globalNames: mutable.Map[Ident, SemType] = mutable.Map.empty - // given globalFuncs: mutable.Map[Ident, FuncType] = mutable.Map.empty - // given globalNumbering: mutable.Map[String, Int] = mutable.Map.empty - // val scope = Scope(mutable.Map.empty, Map.empty) - // val Program(funcs, main) = prog - // funcs - // // First add all function declarations to the scope - // .map { case FuncDecl(retType, name, params, body) => - // val paramTypes = params.map { param => - // val paramType = SemType(param.paramType) - // paramType - // } - // scope.add(FuncType(SemType(retType), paramTypes), name) - // (params zip paramTypes, body) - // } - // // Only then rename the function bodies - // // (functions can call one-another regardless of order of declaration) - // .foreach { case (params, body) => - // val functionScope = scope.subscope - // params.foreach { case (param, paramType) => - // functionScope.add(paramType, param.name) - // } - // body.toList.foreach(rename(functionScope.subscope)) // body can shadow function params - // } - // main.toList.foreach(rename(scope)) - // (globalNames.toMap, globalFuncs.toMap) - // } - /** Check scoping of all identifies in a given AST node. * * @param scope @@ -326,7 +330,8 @@ object renamer { } case Call(name, args) => { val nameErrors = scope.getFunc(name) match { - case Some(Ident(_, guid, ty)) => + case Some(Ident(realName, guid, ty)) => + name.v = realName name.ty = ty name.guid = guid Chain.empty @@ -365,6 +370,7 @@ object renamer { } } // These literals cannot contain identifies, exit immediately. - case IntLiter(_) | BoolLiter(_) | CharLiter(_) | StrLiter(_) | PairLiter() | Skip() => Chain.empty + case IntLiter(_) | BoolLiter(_) | CharLiter(_) | StrLiter(_) | PairLiter() | Skip() => + Chain.empty } } diff --git a/src/main/wacc/frontend/typeChecker.scala b/src/main/wacc/frontend/typeChecker.scala index a628b69..6f5804b 100644 --- a/src/main/wacc/frontend/typeChecker.scala +++ b/src/main/wacc/frontend/typeChecker.scala @@ -8,13 +8,8 @@ object typeChecker { import wacc.types._ case class TypeCheckerCtx( - globalNames: Map[ast.Ident, SemType], - globalFuncs: Map[ast.Ident, FuncType], errors: mutable.Builder[Error, List[Error]] ) { - def typeOf(ident: ast.Ident): SemType = globalNames(ident) - def funcType(ident: ast.Ident): FuncType = globalFuncs(ident) - def error(err: Error): SemType = errors += err ? @@ -99,18 +94,17 @@ object typeChecker { * The type checker context which includes the global names and functions, and an errors * builder. */ - def check(prog: ast.Program)(using - ctx: TypeCheckerCtx - ): microWacc.Program = + def check(prog: ast.Program, errors: mutable.Builder[Error, List[Error]]): microWacc.Program = + given ctx: TypeCheckerCtx = TypeCheckerCtx(errors) microWacc.Program( // Ignore function syntax types for return value and params, since those have been converted // to SemTypes by the renamer. prog.funcs.map { case ast.FuncDecl(_, name, params, stmts) => - val FuncType(retType, paramTypes) = ctx.funcType(name) + val FuncType(retType, paramTypes) = name.ty.asInstanceOf[FuncType] microWacc.FuncDecl( - microWacc.Ident(name.v, name.uid)(retType), + microWacc.Ident(name.v, name.guid)(retType), params.zip(paramTypes).map { case (ast.Param(_, ident), ty) => - microWacc.Ident(ident.v, ident.uid)(ty) + microWacc.Ident(ident.v, ident.guid)(ty) }, stmts.toList .flatMap( @@ -134,15 +128,20 @@ object typeChecker { ): List[microWacc.Stmt] = stmt match { // Ignore the type of the variable, since it has been converted to a SemType by the renamer. case ast.VarDecl(_, name, value) => - val expectedTy = ctx.typeOf(name) + val expectedTy = name.ty val typedValue = checkValue( value, Constraint.Is( - expectedTy, + expectedTy.asInstanceOf[SemType], s"variable ${name.v} must be assigned a value of type $expectedTy" ) ) - List(microWacc.Assign(microWacc.Ident(name.v, name.uid)(expectedTy), typedValue)) + List( + microWacc.Assign( + microWacc.Ident(name.v, name.guid)(expectedTy.asInstanceOf[SemType]), + typedValue + ) + ) case ast.Assign(lhs, rhs) => val lhsTyped = checkLValue(lhs, Constraint.Unconstrained) val rhsTyped = @@ -315,7 +314,7 @@ object typeChecker { KnownType.Pair(fstTyped.ty, sndTyped.ty).satisfies(constraint, l.pos) ) case ast.Call(id, args) => - val funcTy @ FuncType(retTy, paramTys) = ctx.funcType(id) + val funcTy @ FuncType(retTy, paramTys) = id.ty.asInstanceOf[FuncType] if (args.length != paramTys.length) { ctx.error(Error.FunctionParamsMismatch(id, paramTys.length, args.length, funcTy)) } @@ -324,7 +323,7 @@ object typeChecker { val argsTyped = args.zip(paramTys).map { case (arg, paramTy) => checkValue(arg, Constraint.Is(paramTy, s"argument type mismatch in function ${id.v}")) } - microWacc.Call(microWacc.Ident(id.v, id.uid)(retTy.satisfies(constraint, id.pos)), argsTyped) + microWacc.Call(microWacc.Ident(id.v, id.guid)(retTy.satisfies(constraint, id.pos)), argsTyped) // Unary operators case ast.Negate(x) => @@ -416,30 +415,32 @@ object typeChecker { private def checkLValue(value: ast.LValue, constraint: Constraint)(using ctx: TypeCheckerCtx ): microWacc.LValue = value match { - case id @ ast.Ident(name, uid) => - microWacc.Ident(name, uid)(ctx.typeOf(id).satisfies(constraint, id.pos)) + case id @ ast.Ident(name, guid, ty) => + microWacc.Ident(name, guid)(ty.asInstanceOf[SemType].satisfies(constraint, id.pos)) case ast.ArrayElem(id, indices) => - val arrayTy = ctx.typeOf(id) - val (elemTy, indicesTyped) = indices.mapAccumulate(arrayTy) { (acc, elem) => - val idxTyped = checkValue(elem, Constraint.Is(KnownType.Int, "array index must be an int")) - val next = acc match { - case KnownType.Array(innerTy) => innerTy - case ? => ? // we can keep indexing an unknown type - case nonArrayTy => - ctx.error( - Error.TypeMismatch( - elem.pos, - KnownType.Array(?), - acc, - "cannot index into a non-array" + val arrayTy = id.ty.asInstanceOf[SemType] + val (elemTy, indicesTyped) = indices.mapAccumulate(arrayTy.asInstanceOf[SemType]) { + (acc, elem) => + val idxTyped = + checkValue(elem, Constraint.Is(KnownType.Int, "array index must be an int")) + val next = acc match { + case KnownType.Array(innerTy) => innerTy + case ? => ? // we can keep indexing an unknown type + case nonArrayTy => + ctx.error( + Error.TypeMismatch( + elem.pos, + KnownType.Array(?), + acc, + "cannot index into a non-array" + ) ) - ) - ? - } - (next, idxTyped) + ? + } + (next, idxTyped) } val firstArrayElem = microWacc.ArrayElem( - microWacc.Ident(id.v, id.uid)(arrayTy), + microWacc.Ident(id.v, id.guid)(arrayTy), indicesTyped.head )(elemTy.satisfies(constraint, value.pos)) val arrayElem = indicesTyped.tail.foldLeft(firstArrayElem) { (acc, idx) => diff --git a/src/test/wacc/examples.scala b/src/test/wacc/examples.scala index 13a3352..a0f4564 100644 --- a/src/test/wacc/examples.scala +++ b/src/test/wacc/examples.scala @@ -101,16 +101,16 @@ class ParallelExamplesSpec extends AsyncFreeSpec with AsyncIOSpec with BeforeAnd private def fileIsPendingFrontend(filename: String): Boolean = List( - "^.*extension/examples/invalid/syntax/imports/importBadSyntax.*$", - "^.*extension/examples/invalid/semantics/imports.*$", - "^.*extension/examples/valid/imports.*$" + // "^.*extension/examples/invalid/syntax/imports/importBadSyntax.*$", + // "^.*extension/examples/invalid/semantics/imports.*$", + // "^.*extension/examples/valid/imports.*$" ).exists(filename.matches) private def fileIsPendingBackend(filename: String): Boolean = List( - "^.*extension/examples/invalid/syntax/imports.*$", - "^.*extension/examples/invalid/semantics/imports.*$", - "^.*extension/examples/valid/imports.*$" + // "^.*extension/examples/invalid/syntax/imports.*$", + // "^.*extension/examples/invalid/semantics/imports.*$", + // "^.*extension/examples/valid/imports.*$" ).exists(filename.matches) private def extractInput(contents: List[String]): String =