From 27d9a0e111f57a4cd8c4ad587c1ed9534328a6a4 Mon Sep 17 00:00:00 2001 From: Ian Atha Date: Mon, 4 Dec 2023 14:29:56 +0200 Subject: [PATCH] feat: support KILL stmt to delete files fixes #96 --- .../io/atha/libbababasic/grammar/BabaBASIC.g4 | 18 +++++++ .../java/io/atha/libbababasic/file/BBFiles.kt | 49 ++++++++++++++++++- .../java/io/atha/libbababasic/parser/IR.kt | 2 +- .../io/atha/libbababasic/parser/IRListener.kt | 21 ++++++++ .../io/atha/libbababasic/runtime/BBRuntime.kt | 2 + .../io/atha/libbababasic/runtime/Functions.kt | 6 +++ 6 files changed, 96 insertions(+), 2 deletions(-) diff --git a/libbababasic/src/main/antlr/io/atha/libbababasic/grammar/BabaBASIC.g4 b/libbababasic/src/main/antlr/io/atha/libbababasic/grammar/BabaBASIC.g4 index cc155ef..08b624e 100644 --- a/libbababasic/src/main/antlr/io/atha/libbababasic/grammar/BabaBASIC.g4 +++ b/libbababasic/src/main/antlr/io/atha/libbababasic/grammar/BabaBASIC.g4 @@ -51,6 +51,8 @@ stmt | functionreturnstmt | functionendstmt | importstmt + | killstmt + | namestmt | libtagstmt | dimstmt | reallocstmt @@ -372,6 +374,14 @@ importstmt : IMPORT filename=string ; +namestmt + : NAME oldfilename=expr AS newfilename=expr + ; + +killstmt + : KILL filespec=expr + ; + libtagstmt : LIBTAG tag=string ; @@ -743,6 +753,14 @@ FUNCTION : F U N C T I O N ; +NAME + : N A M E + ; + +KILL + : K I L L + ; + LIBTAG : L I B T A G ; diff --git a/libbababasic/src/main/java/io/atha/libbababasic/file/BBFiles.kt b/libbababasic/src/main/java/io/atha/libbababasic/file/BBFiles.kt index f8de02d..fedd10f 100644 --- a/libbababasic/src/main/java/io/atha/libbababasic/file/BBFiles.kt +++ b/libbababasic/src/main/java/io/atha/libbababasic/file/BBFiles.kt @@ -4,6 +4,14 @@ import io.atha.libbababasic.error.RuntimeError import io.atha.libbababasic.file.BBFile.FileAccessMode import io.atha.libbababasic.file.BBFile.FileOpenMode import io.atha.libbababasic.runtime.Environment +import java.nio.file.FileVisitOption +import java.nio.file.FileVisitResult +import java.nio.file.Files +import java.nio.file.SimpleFileVisitor +import java.nio.file.attribute.BasicFileAttributes +import java.nio.file.Path +import kotlin.io.path.Path +import kotlin.io.path.PathWalkOption class BBFiles(@JvmField val sys: BBUIFile, val env: Environment) { private val files: MutableMap = mutableMapOf() @@ -80,4 +88,43 @@ class BBFiles(@JvmField val sys: BBUIFile, val env: Environment) { } } } -} \ No newline at end of file + + fun kill(filespec: String) { + // TODO: implement + // delete files from the storage folder that match filespec + val storageFolder = getMappedPath("") + val matcher = FileMatcher(filespec) + Files.walkFileTree( + Path(storageFolder), + setOf(FileVisitOption.FOLLOW_LINKS), + Int.MAX_VALUE, + matcher + ) + + matcher.matchedFiles.forEach { file -> + try { + Files.delete(file) + println("Deleted file: $file") + } catch (e: Exception) { + println("Failed to delete file: $file") + e.printStackTrace() + } + } + } +} + +class FileMatcher(private val spec: String) : SimpleFileVisitor() { + val matchedFiles = mutableListOf() + + override fun visitFile(file: Path?, attrs: BasicFileAttributes?): FileVisitResult { + if (file != null && Files.isRegularFile(file) && matchesSpec(file.fileName.toString(), spec)) { + matchedFiles.add(file) + } + return FileVisitResult.CONTINUE + } +} + +fun matchesSpec(fileName: String, spec: String): Boolean { + return fileName.matches(spec.replace(".", "\\.").replace("*", ".*").toRegex()) +} + diff --git a/libbababasic/src/main/java/io/atha/libbababasic/parser/IR.kt b/libbababasic/src/main/java/io/atha/libbababasic/parser/IR.kt index 22c5b4d..390268c 100644 --- a/libbababasic/src/main/java/io/atha/libbababasic/parser/IR.kt +++ b/libbababasic/src/main/java/io/atha/libbababasic/parser/IR.kt @@ -143,7 +143,7 @@ class IR(@JvmField val symbolTable: SymbolTable) { MOUSEBUTTONPRESSED("mousebuttonpressed"), MOUSEBUTTONRELEASED("mousebuttonreleased"), ISKEYPRESSED( "iskeypressed" ), - LTRIMDLR("ltrim$"), RTRIMDLR("rtrim$"), DATEDLR("date$"), TIMEDLR("date$") + LTRIMDLR("ltrim$"), RTRIMDLR("rtrim$"), DATEDLR("date$"), TIMEDLR("date$"), KILL("kill"), NAME("name") } class InputRef( diff --git a/libbababasic/src/main/java/io/atha/libbababasic/parser/IRListener.kt b/libbababasic/src/main/java/io/atha/libbababasic/parser/IRListener.kt index d5896c7..10fb758 100644 --- a/libbababasic/src/main/java/io/atha/libbababasic/parser/IRListener.kt +++ b/libbababasic/src/main/java/io/atha/libbababasic/parser/IRListener.kt @@ -4938,6 +4938,27 @@ class IRListener( ) } + override fun exitNamestmt(ctx: BabaBASICParser.NamestmtContext) { + val oldfilenameExpr = lookupInstruction(ctx.expr()) + Types.assertString(ir.symbolTable[oldfilenameExpr.result]!!.type!!.atomTypeId) { getCtxString(ctx) } + val newfilenameExpr = lookupInstruction(ctx.expr()) + Types.assertString(ir.symbolTable[newfilenameExpr.result]!!.type!!.atomTypeId) { getCtxString(ctx) } + // TODO + ir.addInstruction( + sourceFile, currentLineNumber, ctx.start.startIndex, ctx.stop.stopIndex, + OpCode.NAME, SymbolTable.NULL_ID, oldfilenameExpr.result, newfilenameExpr.result + ) + } + + override fun exitKillstmt(ctx: BabaBASICParser.KillstmtContext) { + val filespecExpr = lookupInstruction(ctx.expr()) + Types.assertString(ir.symbolTable[filespecExpr.result]!!.type!!.atomTypeId) { getCtxString(ctx) } + ir.addInstruction( + sourceFile, currentLineNumber, ctx.start.startIndex, ctx.stop.stopIndex, + OpCode.KILL, filespecExpr.result, SymbolTable.NULL_ID, SymbolTable.NULL_ID + ) + } + private fun assertGraphics() { if (!graphics) { throw InternalError( diff --git a/libbababasic/src/main/java/io/atha/libbababasic/runtime/BBRuntime.kt b/libbababasic/src/main/java/io/atha/libbababasic/runtime/BBRuntime.kt index dc40e85..212b4a9 100644 --- a/libbababasic/src/main/java/io/atha/libbababasic/runtime/BBRuntime.kt +++ b/libbababasic/src/main/java/io/atha/libbababasic/runtime/BBRuntime.kt @@ -60,6 +60,7 @@ import io.atha.libbababasic.runtime.Functions.fnint import io.atha.libbababasic.runtime.Functions.hexdlr import io.atha.libbababasic.runtime.Functions.inputdlr import io.atha.libbababasic.runtime.Functions.instr +import io.atha.libbababasic.runtime.Functions.kill import io.atha.libbababasic.runtime.Functions.leftdlr import io.atha.libbababasic.runtime.Functions.len import io.atha.libbababasic.runtime.Functions.loc @@ -771,6 +772,7 @@ class BBRuntime( OpCode.LTRIMDLR -> ltrimdlr(ir.symbolTable, instruction) OpCode.RTRIMDLR -> rtrimdlr(ir.symbolTable, instruction) + OpCode.KILL -> kill(files!!, ir.symbolTable, instruction) OpCode.COMMENT -> {} OpCode.VARIABLE -> {} OpCode.VALUE -> {} diff --git a/libbababasic/src/main/java/io/atha/libbababasic/runtime/Functions.kt b/libbababasic/src/main/java/io/atha/libbababasic/runtime/Functions.kt index 10c382c..5478c94 100644 --- a/libbababasic/src/main/java/io/atha/libbababasic/runtime/Functions.kt +++ b/libbababasic/src/main/java/io/atha/libbababasic/runtime/Functions.kt @@ -404,6 +404,12 @@ object Functions { symbolTable[instruction.result]!!.value!!.string = rtrim } + @JvmStatic + fun kill(files: BBFiles, symbolTable: SymbolTable, instruction: IR.Instruction) { + var filespec = symbolTable[instruction.op1]!!.value!!.string + files.kill(filespec!!) + } + @JvmStatic fun `val`(symbolTable: SymbolTable, instruction: IR.Instruction) { val str = symbolTable[instruction.op1]!!.value!!.string