From c7552c2a9560d8ef3c8a7c401b50c4ee14ed6246 Mon Sep 17 00:00:00 2001 From: rnentjes Date: Thu, 14 Aug 2025 16:04:13 +0200 Subject: [PATCH] Remove legacy JVM-specific file system, shell, and related implementations; migrate to platform-agnostic and common main modules. --- .idea/misc.xml | 2 +- build.gradle.kts | 107 ++++--- .../kotlin/mtmc/asm/ASMElement.kt | 3 +- .../kotlin/mtmc/asm/ASMError.kt | 5 +- .../kotlin/mtmc/asm/Assembler.kt | 114 ++++--- .../kotlin/mtmc/asm/AssemblyResult.kt | 7 +- .../kotlin/mtmc/asm/HasLocation.kt | 0 .../kotlin/mtmc/asm/data/Data.kt | 0 .../kotlin/mtmc/asm/graphics/Graphic.kt | 45 +++ .../mtmc/asm/instructions/ALUInstruction.kt | 6 +- .../kotlin/mtmc/asm/instructions/ALUOp.kt | 11 +- .../mtmc/asm/instructions/ErrorInstruction.kt | 0 .../mtmc/asm/instructions/Instruction.kt | 5 +- .../mtmc/asm/instructions/InstructionType.kt | 9 +- .../mtmc/asm/instructions/JumpInstruction.kt | 0 .../instructions/JumpRegisterInstruction.kt | 0 .../asm/instructions/LoadStoreInstruction.kt | 0 .../LoadStoreRegisterInstruction.kt | 0 .../mtmc/asm/instructions/MetaInstruction.kt | 0 .../mtmc/asm/instructions/MiscInstruction.kt | 0 .../mtmc/asm/instructions/StackInstruction.kt | 0 .../mtmc/asm/instructions/TestInstruction.kt | 0 .../kotlin/mtmc/emulator/DebugInfo.kt | 47 +++ .../kotlin/mtmc/emulator/MTMCClock.kt | 18 +- .../kotlin/mtmc/emulator/MTMCConsole.kt | 13 +- .../kotlin/mtmc/emulator/MTMCDisplay.kt | 0 .../kotlin/mtmc/emulator/MTMCIO.kt | 6 +- .../kotlin/mtmc/emulator/MTMCObserver.kt | 0 .../mtmc/emulator/MonTanaMiniComputer.kt | 94 +++--- .../kotlin/mtmc/emulator/Register.kt | 2 +- .../kotlin/mtmc/emulator/RewindStep.kt | 4 +- .../kotlin/mtmc/os/MTOS.kt | 52 +-- .../kotlin/mtmc/os/SysCall.kt | 11 +- .../kotlin/mtmc/os/exec/Executable.kt | 58 ++++ src/commonMain/kotlin/mtmc/os/fs/Console.kt | 11 + .../os/fs/ExecutableFileTypeDetector.java | 0 src/commonMain/kotlin/mtmc/os/fs/File.kt | 47 +++ .../kotlin/mtmc/os/fs/FileSystem.kt | 213 +++++++++++++ src/commonMain/kotlin/mtmc/os/fs/Listing.kt | 45 +++ src/commonMain/kotlin/mtmc/os/fs/Path.kt | 15 + .../mtmc/os/fs/PlainTextFileTypeDetector.java | 0 src/commonMain/kotlin/mtmc/os/shell/Shell.kt | 295 +++++++++--------- .../kotlin/mtmc/os/shell/ShellCommand.kt | 0 .../kotlin/mtmc/os/shell/UsageException.kt | 17 +- .../mtmc/os/shell/builtins/AssembleCommand.kt | 45 +++ .../mtmc/os/shell/builtins/DisplayCommand.kt | 23 +- .../mtmc/os/shell/builtins/ExitCommand.kt | 2 +- .../mtmc/os/shell/builtins/GetCommand.kt | 0 .../mtmc/os/shell/builtins/HelpCommand.kt | 0 .../mtmc/os/shell/builtins/LoadCommand.kt | 4 +- .../mtmc/os/shell/builtins/PauseCommand.kt | 0 .../mtmc/os/shell/builtins/RunCommand.kt | 0 .../mtmc/os/shell/builtins/SeacCommand.kt | 19 +- .../mtmc/os/shell/builtins/SetCommand.kt | 5 +- .../mtmc/os/shell/builtins/SpeedCommand.kt | 5 +- .../mtmc/os/shell/builtins/StepCommand.kt | 0 .../mtmc/os/shell/builtins/WebCommand.kt | 0 .../kotlin/mtmc/tokenizer/MTMCScanner.kt | 12 +- .../kotlin/mtmc/tokenizer/MTMCToken.kt | 9 +- .../kotlin/mtmc/tokenizer/MTMCTokenizer.kt | 11 +- .../kotlin/mtmc/util/BinaryUtils.kt | 12 +- .../kotlin/mtmc/util/PlatformSpecific.kt | 3 + src/commonMain/kotlin/mtmc/util/Runnable.kt | 3 + .../kotlin/mtmc/util/PlatformSpecific.js.kt | 5 + .../mtmc/lang/CompilationException.java | 0 .../{kotlin => java}/mtmc/lang/Language.java | 0 .../{kotlin => java}/mtmc/lang/Location.java | 0 .../mtmc/lang/ParseException.java | 0 .../{kotlin => java}/mtmc/lang/Span.java | 0 .../{kotlin => java}/mtmc/lang/Token.java | 0 .../mtmc/lang/sea/SeaCompiler.java | 0 .../mtmc/lang/sea/SeaLanguage.java | 0 .../mtmc/lang/sea/SeaParser.java | 0 .../mtmc/lang/sea/SeaType.java | 0 .../mtmc/lang/sea/Symbol.java | 0 .../{kotlin => java}/mtmc/lang/sea/Token.java | 0 .../mtmc/lang/sea/ast/Ast.java | 0 .../mtmc/lang/sea/ast/Declaration.java | 0 .../mtmc/lang/sea/ast/DeclarationFunc.java | 0 .../mtmc/lang/sea/ast/DeclarationStruct.java | 0 .../lang/sea/ast/DeclarationSyntaxError.java | 0 .../mtmc/lang/sea/ast/DeclarationTypedef.java | 0 .../mtmc/lang/sea/ast/DeclarationVar.java | 0 .../mtmc/lang/sea/ast/Error.java | 0 .../mtmc/lang/sea/ast/Expression.java | 0 .../mtmc/lang/sea/ast/ExpressionAccess.java | 0 .../mtmc/lang/sea/ast/ExpressionBin.java | 0 .../mtmc/lang/sea/ast/ExpressionCall.java | 0 .../mtmc/lang/sea/ast/ExpressionCast.java | 0 .../mtmc/lang/sea/ast/ExpressionChar.java | 0 .../mtmc/lang/sea/ast/ExpressionIdent.java | 0 .../mtmc/lang/sea/ast/ExpressionIndex.java | 0 .../lang/sea/ast/ExpressionInitializer.java | 0 .../mtmc/lang/sea/ast/ExpressionInteger.java | 0 .../mtmc/lang/sea/ast/ExpressionParens.java | 0 .../mtmc/lang/sea/ast/ExpressionPostfix.java | 0 .../mtmc/lang/sea/ast/ExpressionPrefix.java | 0 .../mtmc/lang/sea/ast/ExpressionString.java | 0 .../lang/sea/ast/ExpressionSyntaxError.java | 0 .../mtmc/lang/sea/ast/ExpressionTernary.java | 0 .../lang/sea/ast/ExpressionTypeError.java | 0 .../mtmc/lang/sea/ast/Statement.java | 0 .../mtmc/lang/sea/ast/StatementBlock.java | 0 .../mtmc/lang/sea/ast/StatementBreak.java | 0 .../mtmc/lang/sea/ast/StatementContinue.java | 0 .../mtmc/lang/sea/ast/StatementDoWhile.java | 0 .../lang/sea/ast/StatementExpression.java | 0 .../mtmc/lang/sea/ast/StatementFor.java | 0 .../mtmc/lang/sea/ast/StatementGoto.java | 0 .../mtmc/lang/sea/ast/StatementIf.java | 0 .../mtmc/lang/sea/ast/StatementReturn.java | 0 .../lang/sea/ast/StatementSyntaxError.java | 0 .../mtmc/lang/sea/ast/StatementVar.java | 0 .../mtmc/lang/sea/ast/StatementWhile.java | 0 .../mtmc/lang/sea/ast/SyntaxError.java | 0 .../mtmc/lang/sea/ast/TypeDeclaration.java | 0 .../mtmc/lang/sea/ast/TypeExpr.java | 0 .../mtmc/lang/sea/ast/TypeExprArray.java | 0 .../mtmc/lang/sea/ast/TypeExprChar.java | 0 .../mtmc/lang/sea/ast/TypeExprInt.java | 0 .../mtmc/lang/sea/ast/TypeExprRef.java | 0 .../mtmc/lang/sea/ast/TypeExprVoid.java | 0 .../mtmc/lang/sea/ast/TypePointer.java | 0 .../mtmc/lang/sea/ast/Unit.java | 0 .../kotlin/mtmc/asm/graphics/Graphic.kt | 51 --- src/jvmMain/kotlin/mtmc/emulator/DebugInfo.kt | 45 --- src/jvmMain/kotlin/mtmc/os/exec/Executable.kt | 60 ---- src/jvmMain/kotlin/mtmc/os/fs/FileSystem.java | 199 ------------ src/jvmMain/kotlin/mtmc/os/fs/Listing.java | 52 --- .../mtmc/os/shell/builtins/AssembleCommand.kt | 45 --- .../kotlin/mtmc/util/PlatformSpecific.jvm.kt | 3 + src/jvmMain/kotlin/mtmc/util/SafeClosable.kt | 2 +- .../kotlin/mtmc/util/StringEscapeUtils.kt | 2 +- 133 files changed, 981 insertions(+), 898 deletions(-) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/ASMElement.kt (90%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/ASMError.kt (69%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/Assembler.kt (88%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/AssemblyResult.kt (74%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/HasLocation.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/data/Data.kt (100%) create mode 100644 src/commonMain/kotlin/mtmc/asm/graphics/Graphic.kt rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/ALUInstruction.kt (95%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/ALUOp.kt (72%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/ErrorInstruction.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/Instruction.kt (95%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/InstructionType.kt (92%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/JumpInstruction.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/JumpRegisterInstruction.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/LoadStoreInstruction.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/LoadStoreRegisterInstruction.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/MetaInstruction.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/MiscInstruction.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/StackInstruction.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/asm/instructions/TestInstruction.kt (100%) create mode 100644 src/commonMain/kotlin/mtmc/emulator/DebugInfo.kt rename src/{jvmMain => commonMain}/kotlin/mtmc/emulator/MTMCClock.kt (73%) rename src/{jvmMain => commonMain}/kotlin/mtmc/emulator/MTMCConsole.kt (91%) rename src/{jvmMain => commonMain}/kotlin/mtmc/emulator/MTMCDisplay.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/emulator/MTMCIO.kt (69%) rename src/{jvmMain => commonMain}/kotlin/mtmc/emulator/MTMCObserver.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/emulator/MonTanaMiniComputer.kt (93%) rename src/{jvmMain => commonMain}/kotlin/mtmc/emulator/Register.kt (99%) rename src/{jvmMain => commonMain}/kotlin/mtmc/emulator/RewindStep.kt (67%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/MTOS.kt (93%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/SysCall.kt (82%) create mode 100644 src/commonMain/kotlin/mtmc/os/exec/Executable.kt create mode 100644 src/commonMain/kotlin/mtmc/os/fs/Console.kt rename src/{jvmMain => commonMain}/kotlin/mtmc/os/fs/ExecutableFileTypeDetector.java (100%) create mode 100644 src/commonMain/kotlin/mtmc/os/fs/File.kt create mode 100644 src/commonMain/kotlin/mtmc/os/fs/FileSystem.kt create mode 100644 src/commonMain/kotlin/mtmc/os/fs/Listing.kt create mode 100644 src/commonMain/kotlin/mtmc/os/fs/Path.kt rename src/{jvmMain => commonMain}/kotlin/mtmc/os/fs/PlainTextFileTypeDetector.java (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/ShellCommand.kt (100%) create mode 100644 src/commonMain/kotlin/mtmc/os/shell/builtins/AssembleCommand.kt rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/DisplayCommand.kt (83%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/ExitCommand.kt (94%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/GetCommand.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/HelpCommand.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/LoadCommand.kt (92%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/PauseCommand.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/RunCommand.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/SeacCommand.kt (66%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/SetCommand.kt (93%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/SpeedCommand.kt (90%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/StepCommand.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/os/shell/builtins/WebCommand.kt (100%) rename src/{jvmMain => commonMain}/kotlin/mtmc/tokenizer/MTMCScanner.kt (97%) rename src/{jvmMain => commonMain}/kotlin/mtmc/tokenizer/MTMCToken.kt (92%) rename src/{jvmMain => commonMain}/kotlin/mtmc/tokenizer/MTMCTokenizer.kt (90%) rename src/{jvmMain => commonMain}/kotlin/mtmc/util/BinaryUtils.kt (71%) create mode 100644 src/commonMain/kotlin/mtmc/util/PlatformSpecific.kt create mode 100644 src/commonMain/kotlin/mtmc/util/Runnable.kt create mode 100644 src/jsMain/kotlin/mtmc/util/PlatformSpecific.js.kt rename src/jvmMain/{kotlin => java}/mtmc/lang/CompilationException.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/Language.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/Location.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/ParseException.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/Span.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/Token.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/SeaCompiler.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/SeaLanguage.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/SeaParser.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/SeaType.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/Symbol.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/Token.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/Ast.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/Declaration.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/DeclarationFunc.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/DeclarationStruct.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/DeclarationSyntaxError.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/DeclarationTypedef.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/DeclarationVar.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/Error.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/Expression.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionAccess.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionBin.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionCall.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionCast.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionChar.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionIdent.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionIndex.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionInitializer.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionInteger.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionParens.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionPostfix.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionPrefix.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionString.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionSyntaxError.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionTernary.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/ExpressionTypeError.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/Statement.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementBlock.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementBreak.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementContinue.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementDoWhile.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementExpression.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementFor.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementGoto.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementIf.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementReturn.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementSyntaxError.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementVar.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/StatementWhile.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/SyntaxError.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/TypeDeclaration.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/TypeExpr.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/TypeExprArray.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/TypeExprChar.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/TypeExprInt.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/TypeExprRef.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/TypeExprVoid.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/TypePointer.java (100%) rename src/jvmMain/{kotlin => java}/mtmc/lang/sea/ast/Unit.java (100%) delete mode 100644 src/jvmMain/kotlin/mtmc/asm/graphics/Graphic.kt delete mode 100644 src/jvmMain/kotlin/mtmc/emulator/DebugInfo.kt delete mode 100644 src/jvmMain/kotlin/mtmc/os/exec/Executable.kt delete mode 100644 src/jvmMain/kotlin/mtmc/os/fs/FileSystem.java delete mode 100644 src/jvmMain/kotlin/mtmc/os/fs/Listing.java delete mode 100644 src/jvmMain/kotlin/mtmc/os/shell/builtins/AssembleCommand.kt create mode 100644 src/jvmMain/kotlin/mtmc/util/PlatformSpecific.jvm.kt diff --git a/.idea/misc.xml b/.idea/misc.xml index 2ac0fd5..c621e3a 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,7 +3,7 @@ - + diff --git a/build.gradle.kts b/build.gradle.kts index 276852b..84bd6d3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,70 +1,75 @@ @file:OptIn(ExperimentalDistributionDsl::class) -import org.codehaus.groovy.tools.shell.util.Logger.io import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalDistributionDsl plugins { - kotlin("multiplatform") version "2.1.20" + kotlin("multiplatform") version "2.1.20" } group = "nl.astraeus" version = "0.1.0-SNAPSHOT" repositories { - mavenCentral() - maven { - url = uri("https://gitea.astraeus.nl/api/packages/rnentjes/maven") - } - maven { - url = uri("https://gitea.astraeus.nl:8443/api/packages/rnentjes/maven") - } + mavenCentral() + maven { + url = uri("https://gitea.astraeus.nl/api/packages/rnentjes/maven") + } + maven { + url = uri("https://gitea.astraeus.nl:8443/api/packages/rnentjes/maven") + } } kotlin { - jvmToolchain(17) - jvm() - js { - binaries.executable() - browser { - distribution { - outputDirectory.set(File("$projectDir/web/")) - } - } + jvmToolchain(21) + jvm() + js { + binaries.executable() + browser { + distribution { + outputDirectory.set(File("$projectDir/web/")) + } } - sourceSets { - val commonMain by getting { - dependencies { - api("nl.astraeus:kotlin-simple-logging:1.1.1") - api("nl.astraeus:kotlin-css-generator:1.0.10") + } - implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0") - } - } - val commonTest by getting - val jvmMain by getting { - dependencies { - implementation("io.undertow:undertow-core:2.3.14.Final") - implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.11.0") + // Add this to enable ExperimentalStdlibApi globally + sourceSets.all { + languageSettings.optIn("kotlin.ExperimentalStdlibApi") + } - implementation("org.xerial:sqlite-jdbc:3.32.3.2") - implementation("com.zaxxer:HikariCP:4.0.3") - implementation("nl.astraeus:simple-jdbc-stats:1.6.1") { - exclude(group = "org.slf4j", module = "slf4j-api") - } + sourceSets { + val commonMain by getting { + dependencies { + api("nl.astraeus:kotlin-simple-logging:1.1.1") + api("nl.astraeus:kotlin-css-generator:1.0.10") - implementation("io.pebbletemplates:pebble:3.2.3") - implementation("com.google.code.gson:gson:2.12.1") - } - } - val jvmTest by getting { - dependencies { - } - } - val jsMain by getting { - dependencies { - implementation("nl.astraeus:kotlin-komponent:1.2.5") - } - } - val jsTest by getting + implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0") + } } -} \ No newline at end of file + val commonTest by getting + val jvmMain by getting { + dependencies { + implementation("io.undertow:undertow-core:2.3.14.Final") + implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.11.0") + + implementation("org.xerial:sqlite-jdbc:3.32.3.2") + implementation("com.zaxxer:HikariCP:4.0.3") + implementation("nl.astraeus:simple-jdbc-stats:1.6.1") { + exclude(group = "org.slf4j", module = "slf4j-api") + } + + implementation("io.pebbletemplates:pebble:3.2.3") + implementation("com.google.code.gson:gson:2.12.1") + } + } + val jvmTest by getting { + dependencies { + } + } + val jsMain by getting { + dependencies { + implementation("nl.astraeus:kotlin-komponent:1.2.5") + } + } + val jsTest by getting + } +} diff --git a/src/jvmMain/kotlin/mtmc/asm/ASMElement.kt b/src/commonMain/kotlin/mtmc/asm/ASMElement.kt similarity index 90% rename from src/jvmMain/kotlin/mtmc/asm/ASMElement.kt rename to src/commonMain/kotlin/mtmc/asm/ASMElement.kt index 9deb269..e5887c7 100644 --- a/src/jvmMain/kotlin/mtmc/asm/ASMElement.kt +++ b/src/commonMain/kotlin/mtmc/asm/ASMElement.kt @@ -4,9 +4,8 @@ import mtmc.tokenizer.MTMCToken abstract class ASMElement( val labels: List, - @JvmField var lineNumber: Int + var lineNumber: Int ) : HasLocation { - @JvmField var errors: MutableList = ArrayList() override var location: Int = 0 override var sizeInBytes: Int = 0 diff --git a/src/jvmMain/kotlin/mtmc/asm/ASMError.kt b/src/commonMain/kotlin/mtmc/asm/ASMError.kt similarity index 69% rename from src/jvmMain/kotlin/mtmc/asm/ASMError.kt rename to src/commonMain/kotlin/mtmc/asm/ASMError.kt index e6f692e..e20b46c 100644 --- a/src/jvmMain/kotlin/mtmc/asm/ASMError.kt +++ b/src/commonMain/kotlin/mtmc/asm/ASMError.kt @@ -2,10 +2,9 @@ package mtmc.asm import mtmc.tokenizer.MTMCToken -@JvmRecord data class ASMError( - @JvmField val token: MTMCToken, - @JvmField val error: String + val token: MTMCToken, + val error: String ) { fun formattedErrorMessage(): String { return "Line " + token.line + ": " + error diff --git a/src/jvmMain/kotlin/mtmc/asm/Assembler.kt b/src/commonMain/kotlin/mtmc/asm/Assembler.kt similarity index 88% rename from src/jvmMain/kotlin/mtmc/asm/Assembler.kt rename to src/commonMain/kotlin/mtmc/asm/Assembler.kt index 67c06f8..02d4588 100644 --- a/src/jvmMain/kotlin/mtmc/asm/Assembler.kt +++ b/src/commonMain/kotlin/mtmc/asm/Assembler.kt @@ -25,12 +25,16 @@ import mtmc.emulator.Register.Companion.isReadable import mtmc.emulator.Register.Companion.isWriteable import mtmc.os.SysCall import mtmc.os.exec.Executable +import mtmc.os.fs.File import mtmc.tokenizer.MTMCToken import mtmc.tokenizer.MTMCTokenizer -import java.io.File -import java.nio.charset.StandardCharsets -import java.util.* -import java.util.stream.Collectors + +fun MutableList.poll() = this.removeFirst() +fun MutableList.peekFirst() = if (this.isEmpty()) { + null +} else { + this[0] +} class Assembler { var instructions: MutableList = ArrayList() @@ -88,7 +92,7 @@ class Assembler { var location = 0 var originalLineNumber = 0 - val currentLocals: MutableMap = TreeMap() + val currentLocals: MutableMap = mutableMapOf() for (instruction in instructions) { val asmLineNumber = instruction.lineNumber if (instruction is MetaInstruction) { @@ -145,10 +149,8 @@ class Assembler { val result = assemble(srcName, asm) if (!result.errors.isEmpty()) { throw RuntimeException( - "Errors:\n" + result.errors - .stream() - .map { e: ASMError? -> " - " + e!!.formattedErrorMessage() } - .collect(Collectors.joining("\n"))) + "Errors:\n" + result.errors.joinToString("\n") { e: ASMError? -> " - " + e!!.formattedErrorMessage() } + ) } return Executable( @@ -261,7 +263,10 @@ class Assembler { for (labelToken in labelTokens) { val labelData = Data(labelTokens, labelToken.line) if (hasLabel(labelToken.stringValue)) { - labelData.addError(tokens.poll(), "Label already defined: " + labelToken.stringValue) + labelData.addError( + tokens.removeFirst(), + "Label already defined: " + labelToken.stringValue + ) } else { this.labels.put(labelToken.labelValue(), labelData) } @@ -274,7 +279,7 @@ class Assembler { } } - private fun parseMetaDirective(tokens: LinkedList): Boolean { + private fun parseMetaDirective(tokens: MutableList): Boolean { if (tokens.size >= 2 && tokens.get(0).type == MTMCToken.TokenType.AT) { tokens.removeFirst() val metaInstruction = MetaInstruction(tokens.removeFirst()) @@ -306,26 +311,26 @@ class Assembler { return false } - private fun parseModeFlag(tokens: LinkedList): ASMMode? { + private fun parseModeFlag(tokens: MutableList): ASMMode? { if (tokens.size >= 2 && tokens.get(0).type == MTMCToken.TokenType.DOT && tokens.get(1).type == MTMCToken.TokenType.IDENTIFIER && tokens.get( 0 ).end == tokens.get(1).start && (tokens.get(1).stringValue == "data" || tokens.get(1).stringValue == "text") ) { - return ASMMode.valueOf(tokens.get(1).stringValue.uppercase(Locale.getDefault())) + return ASMMode.valueOf(tokens.get(1).stringValue.uppercase()) } return null } - private fun parseData(tokens: LinkedList, labelTokens: MutableList) { + private fun parseData(tokens: MutableList, labelTokens: MutableList) { lastLabels = mutableListOf() - var dataToken = tokens.poll() + var dataToken = tokens.removeFirst() var dataElt = Data(labelTokens, if (dataToken == null) 0 else dataToken.line) if (dataToken != null) { if (dataToken.type == MTMCToken.TokenType.STRING) { - val stringBytes = dataToken.stringValue.toByteArray(StandardCharsets.US_ASCII) + val stringBytes = dataToken.stringValue.encodeToByteArray() val nullTerminated = ByteArray(stringBytes.size + 1) - System.arraycopy(stringBytes, 0, nullTerminated, 0, stringBytes.size) + stringBytes.copyInto(nullTerminated, 0, 0, stringBytes.size) nullTerminated[stringBytes.size] = '\u0000'.code.toByte() dataElt.setValue(dataToken, nullTerminated) } else if (isInteger(dataToken)) { @@ -338,7 +343,7 @@ class Assembler { byteArrayOf((integerValue ushr 8).toByte(), integerValue.toByte()) ) } else if (dataToken.type == MTMCToken.TokenType.DOT) { - dataToken = tokens.poll() + dataToken = tokens.removeFirst() dataElt = Data(labelTokens, dataToken.line) if (dataToken.stringValue == "int") { val intToken = requireIntegerToken(tokens, dataElt, MonTanaMiniComputer.MEMORY_SIZE) @@ -359,7 +364,7 @@ class Assembler { dataElt.addError(dataToken, "only data types are .int, .byte, and .image") } } else if (dataToken.type == MTMCToken.TokenType.MINUS) { - val nextToken = tokens.poll() // get next + val nextToken = tokens.removeFirst() // get next if (nextToken == null || (nextToken.type != MTMCToken.TokenType.INTEGER && nextToken.type != MTMCToken.TokenType.HEX && nextToken.type != MTMCToken.TokenType.BINARY)) { dataElt.addError(dataToken, "Number is too negative") } else { @@ -380,7 +385,7 @@ class Assembler { for (labelToken in labelTokens) { if (hasLabel(labelToken.stringValue)) { - dataElt.addError(tokens.poll(), "Label already defined: " + labelToken.stringValue) + dataElt.addError(tokens.removeFirst(), "Label already defined: " + labelToken.stringValue) } else { labels.put(labelToken.labelValue(), dataElt) } @@ -405,9 +410,16 @@ class Assembler { return graphic } - private fun parseInstruction(tokens: LinkedList, labelTokens: MutableList) { + private fun parseInstruction( + tokens: MutableList, + labelTokens: MutableList + ) { var tokens = tokens - var instructionToken = tokens.peekFirst() + var instructionToken = if (tokens.isEmpty()) { + null + } else { + tokens[0] + } if (instructionToken == null) return lastLabels = mutableListOf() @@ -510,7 +522,7 @@ class Assembler { } // if there is a stack register specified, consume it - if (!tokens.isEmpty() && tokens.peekFirst().type == MTMCToken.TokenType.IDENTIFIER) { + if (!tokens.isEmpty() && tokens.peekFirst()?.type == MTMCToken.TokenType.IDENTIFIER) { val stackReg = requireReadableRegister(tokens, stackInst) stackInst.setStackRegister(stackReg) } @@ -550,7 +562,7 @@ class Assembler { loadInst.setPointerToken(pointerReg) // if there is an offset register specified, consume it - if (!tokens.isEmpty() && tokens.peekFirst().type == MTMCToken.TokenType.IDENTIFIER) { + if (!tokens.isEmpty() && tokens.peekFirst()?.type == MTMCToken.TokenType.IDENTIFIER) { val offsetReg = requireReadableRegister(tokens, loadInst) loadInst.setOffsetToken(offsetReg) } @@ -598,7 +610,7 @@ class Assembler { //=================================================== // tokenization helper functions //=================================================== - private fun requireSysCall(tokens: LinkedList, inst: Instruction): MTMCToken { + private fun requireSysCall(tokens: MutableList, inst: Instruction): MTMCToken { val sysCallType = tokens.poll() if (sysCallType == null) { inst.addError("Syscall required") @@ -610,7 +622,7 @@ class Assembler { return sysCallType!! } - private fun requireAluOp(tokens: LinkedList, inst: Instruction): MTMCToken { + private fun requireAluOp(tokens: MutableList, inst: Instruction): MTMCToken { val sysCallType = tokens.poll() if (sysCallType == null) { inst.addError("Syscall required") @@ -623,7 +635,7 @@ class Assembler { } private fun requireWriteableRegister( - tokens: LinkedList, + tokens: MutableList, instruction: Instruction ): MTMCToken { val nextToken = tokens.poll() @@ -638,7 +650,7 @@ class Assembler { } private fun requireReadableRegister( - tokens: LinkedList, + tokens: MutableList, instruction: Instruction ): MTMCToken { val nextToken = tokens.poll() @@ -652,7 +664,7 @@ class Assembler { return nextToken!! } - private fun requireALUOp(tokens: LinkedList, instruction: Instruction): MTMCToken { + private fun requireALUOp(tokens: MutableList, instruction: Instruction): MTMCToken { val nextToken = tokens.poll() if (nextToken == null || nextToken.type != MTMCToken.TokenType.IDENTIFIER || !isALUOp(nextToken.stringValue)) { instruction.addError("ALU operation required") @@ -660,7 +672,7 @@ class Assembler { return nextToken!! } - private fun requireString(tokens: LinkedList, instruction: ASMElement): MTMCToken { + private fun requireString(tokens: MutableList, instruction: ASMElement): MTMCToken { val nextToken = tokens.poll() if (nextToken == null || nextToken.type != MTMCToken.TokenType.STRING) { instruction.addError("String required") @@ -669,7 +681,7 @@ class Assembler { } private fun requireIntegerToken( - tokens: LinkedList, + tokens: MutableList, inst: ASMElement, max: Int ): MTMCToken { @@ -688,7 +700,7 @@ class Assembler { } private fun requireToken( - tokens: LinkedList, + tokens: MutableList, type: MTMCToken.TokenType, inst: ASMElement ): MTMCToken? { @@ -700,7 +712,7 @@ class Assembler { } private fun requireIntegerOrLabelReferenceToken( - tokens: LinkedList, + tokens: MutableList, inst: LoadStoreInstruction ): MTMCToken { val token = tokens.poll() @@ -713,9 +725,9 @@ class Assembler { } - private val tokensForLine: LinkedList + private val tokensForLine: MutableList get() { - val tokens = LinkedList() + val tokens = mutableListOf() if (tokenizer!!.more()) { val first = tokenizer!!.consume() tokens.add(first) @@ -742,51 +754,51 @@ class Assembler { } companion object { - fun transformSyntheticInstructions(tokens: LinkedList): LinkedList { + fun transformSyntheticInstructions(tokens: MutableList): MutableList { if (!tokens.isEmpty()) { - val first = tokens.peekFirst() + val first = tokens.first() if (first.type == MTMCToken.TokenType.IDENTIFIER) { val stringVal = first.stringValue if (stringVal.endsWith("i")) { val op = stringVal.substring(0, stringVal.length - 1) if (isALUOp(op)) { val syntheticImmediate = tokens.removeFirst() - tokens.addFirst(syntheticImmediate.cloneWithVal(op)) - tokens.addFirst(syntheticImmediate.cloneWithVal("imm")) + tokens.add(0, syntheticImmediate.cloneWithVal(op)) + tokens.add(0, syntheticImmediate.cloneWithVal("imm")) } } else if (stringVal.startsWith("s")) { val op = stringVal.substring(1, stringVal.length) if (isALUOp(op)) { val syntheticImmediate = tokens.removeFirst() - tokens.addFirst(syntheticImmediate.cloneWithVal(op)) - tokens.addFirst(syntheticImmediate.cloneWithVal("sop")) + tokens.add(0, syntheticImmediate.cloneWithVal(op)) + tokens.add(0, syntheticImmediate.cloneWithVal("sop")) } } else if (stringVal == "la") { val syntheticImmediate = tokens.removeFirst() - tokens.addFirst(syntheticImmediate.cloneWithVal("li")) + tokens.add(0, syntheticImmediate.cloneWithVal("li")) } else if (stringVal == "ret") { val syntheticImmediate = tokens.removeFirst() - tokens.addFirst(syntheticImmediate.cloneWithVal("ra")) - tokens.addFirst(syntheticImmediate.cloneWithVal("jr")) + tokens.add(0, syntheticImmediate.cloneWithVal("ra")) + tokens.add(0, syntheticImmediate.cloneWithVal("jr")) } } } return tokens } - private fun maybeGetLabels(tokens: LinkedList): MutableList { - val labels = LinkedList() - while (!tokens.isEmpty() && tokens.getFirst().type == MTMCToken.TokenType.LABEL) { - val label = tokens.poll() + private fun maybeGetLabels(tokens: MutableList): MutableList { + val labels = mutableListOf() + while (!tokens.isEmpty() && tokens.first().type == MTMCToken.TokenType.LABEL) { + val label = tokens.removeFirst() labels.add(label!!) } return labels } - private fun maybeGetLabelReference(tokens: LinkedList): MTMCToken? { + private fun maybeGetLabelReference(tokens: MutableList): MTMCToken? { var label: MTMCToken? = null - if (tokens.getFirst().type == MTMCToken.TokenType.IDENTIFIER) { - label = tokens.poll() + if (tokens.first().type == MTMCToken.TokenType.IDENTIFIER) { + label = tokens.removeFirst() } return label } diff --git a/src/jvmMain/kotlin/mtmc/asm/AssemblyResult.kt b/src/commonMain/kotlin/mtmc/asm/AssemblyResult.kt similarity index 74% rename from src/jvmMain/kotlin/mtmc/asm/AssemblyResult.kt rename to src/commonMain/kotlin/mtmc/asm/AssemblyResult.kt index 38e88d8..c7b18c3 100644 --- a/src/jvmMain/kotlin/mtmc/asm/AssemblyResult.kt +++ b/src/commonMain/kotlin/mtmc/asm/AssemblyResult.kt @@ -2,13 +2,12 @@ package mtmc.asm import mtmc.emulator.DebugInfo -@JvmRecord data class AssemblyResult( - @JvmField val code: ByteArray, + val code: ByteArray, val data: ByteArray, val graphics: Array, - @JvmField val debugInfo: DebugInfo?, - @JvmField val errors: MutableList + val debugInfo: DebugInfo?, + val errors: MutableList ) { fun printErrors(): String { val builder = StringBuilder("Errors:\n") diff --git a/src/jvmMain/kotlin/mtmc/asm/HasLocation.kt b/src/commonMain/kotlin/mtmc/asm/HasLocation.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/asm/HasLocation.kt rename to src/commonMain/kotlin/mtmc/asm/HasLocation.kt diff --git a/src/jvmMain/kotlin/mtmc/asm/data/Data.kt b/src/commonMain/kotlin/mtmc/asm/data/Data.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/asm/data/Data.kt rename to src/commonMain/kotlin/mtmc/asm/data/Data.kt diff --git a/src/commonMain/kotlin/mtmc/asm/graphics/Graphic.kt b/src/commonMain/kotlin/mtmc/asm/graphics/Graphic.kt new file mode 100644 index 0000000..070011c --- /dev/null +++ b/src/commonMain/kotlin/mtmc/asm/graphics/Graphic.kt @@ -0,0 +1,45 @@ +package mtmc.asm.graphics + +import mtmc.asm.ASMElement +import mtmc.tokenizer.MTMCToken + +/** + * + * @author jbanes + */ +class Graphic(labels: MutableList, lineNumber: Int) : ASMElement(labels, lineNumber) { + private var filename: String? = null + var imageData: ByteArray = ByteArray(0) + + fun setImage(filename: String) { + /* try { + var image = ImageIO.read(File(filename)) + val buffer = ByteArrayOutputStream() + + if (image.getWidth() > 1024 || image.getHeight() > 1024) { + addError(filename + " is too large. Maximum image size is 1024x1024") + } + + image = convertImage(image) + + ImageIO.write(image, "png", buffer) + + this.filename = filename + this.imageData = buffer.toByteArray() + } catch (e: FileNotFoundException) { + e.printStackTrace() + addError("$filename not found") + } catch (e: IOException) { + e.printStackTrace() + addError(e.message ?: "error in Graphic") // TODO: Verify these messages are meaningful + }*/ + } + + override fun addError(err: String) { + addError(labels.last(), err) + } + + override var sizeInBytes: Int + get() = 2 + set(value) {} +} diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/ALUInstruction.kt b/src/commonMain/kotlin/mtmc/asm/instructions/ALUInstruction.kt similarity index 95% rename from src/jvmMain/kotlin/mtmc/asm/instructions/ALUInstruction.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/ALUInstruction.kt index d70534f..0befdae 100644 --- a/src/jvmMain/kotlin/mtmc/asm/instructions/ALUInstruction.kt +++ b/src/commonMain/kotlin/mtmc/asm/instructions/ALUInstruction.kt @@ -5,7 +5,6 @@ import mtmc.emulator.Register.Companion.fromInteger import mtmc.emulator.Register.Companion.toInteger import mtmc.tokenizer.MTMCToken import mtmc.util.BinaryUtils -import java.util.Locale class ALUInstruction( type: InstructionType, @@ -38,7 +37,7 @@ class ALUInstruction( } val isBinaryOp: Boolean - get() = !ALUOp.valueOf(instructionToken.stringValue.uppercase(Locale.getDefault())).isUnary + get() = !ALUOp.valueOf(instructionToken.stringValue.uppercase()).isUnary override fun genCode(output: ByteArray, assembler: Assembler) { val opCode = ALUOp.toInteger(instructionToken.stringValue) @@ -62,13 +61,12 @@ class ALUInstruction( } companion object { - @JvmStatic fun disassemble(instruction: Short): String? { if (BinaryUtils.getBits(16, 4, instruction).toInt() == 1) { val builder = StringBuilder() val opCode = BinaryUtils.getBits(12, 4, instruction) val op = ALUOp.fromInt(opCode) - val aluOp = ALUOp.valueOf(op.uppercase(Locale.getDefault())) + val aluOp = ALUOp.valueOf(op.uppercase()) if (aluOp == ALUOp.IMM) { builder.append(op).append(" ") builder.append(fromInteger(BinaryUtils.getBits(8, 4, instruction).toInt())).append(" ") diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/ALUOp.kt b/src/commonMain/kotlin/mtmc/asm/instructions/ALUOp.kt similarity index 72% rename from src/jvmMain/kotlin/mtmc/asm/instructions/ALUOp.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/ALUOp.kt index 821897f..3f33d51 100644 --- a/src/jvmMain/kotlin/mtmc/asm/instructions/ALUOp.kt +++ b/src/commonMain/kotlin/mtmc/asm/instructions/ALUOp.kt @@ -1,7 +1,5 @@ package mtmc.asm.instructions -import java.util.* - enum class ALUOp(val opCode: Int, val isUnary: Boolean) { ADD(0x0000, false), SUB(0x0001, false), @@ -21,20 +19,17 @@ enum class ALUOp(val opCode: Int, val isUnary: Boolean) { IMM(0x000F, true); companion object { - @JvmStatic fun toInteger(instruction: String): Int { - return valueOf(instruction.uppercase(Locale.getDefault())).opCode + return valueOf(instruction.uppercase()).opCode } - @JvmStatic fun fromInt(opCode: Short): String { - return entries[opCode.toInt()].name.lowercase(Locale.getDefault()) + return entries[opCode.toInt()].name.lowercase() } - @JvmStatic fun isALUOp(op: String): Boolean { try { - val aluOp = valueOf(op.uppercase(Locale.getDefault())) + val aluOp = valueOf(op.uppercase()) return true } catch (e: IllegalArgumentException) { return false diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/ErrorInstruction.kt b/src/commonMain/kotlin/mtmc/asm/instructions/ErrorInstruction.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/asm/instructions/ErrorInstruction.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/ErrorInstruction.kt diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/Instruction.kt b/src/commonMain/kotlin/mtmc/asm/instructions/Instruction.kt similarity index 95% rename from src/jvmMain/kotlin/mtmc/asm/instructions/Instruction.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/Instruction.kt index 0f08b63..867a240 100644 --- a/src/jvmMain/kotlin/mtmc/asm/instructions/Instruction.kt +++ b/src/commonMain/kotlin/mtmc/asm/instructions/Instruction.kt @@ -7,9 +7,9 @@ import mtmc.emulator.MonTanaMiniComputer.Companion.isDoubleWordInstruction import mtmc.tokenizer.MTMCToken abstract class Instruction( - @JvmField val type: InstructionType, + val type: InstructionType, labels: List, - @JvmField val instructionToken: MTMCToken + val instructionToken: MTMCToken ) : ASMElement(labels, instructionToken.line) { open fun validateLabel(assembler: Assembler) { // default does nothing @@ -25,7 +25,6 @@ abstract class Instruction( get() = type.sizeInBytes companion object { - @JvmStatic fun isInstruction(cmd: String): Boolean { return InstructionType.fromString(cmd) != null } diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/InstructionType.kt b/src/commonMain/kotlin/mtmc/asm/instructions/InstructionType.kt similarity index 92% rename from src/jvmMain/kotlin/mtmc/asm/instructions/InstructionType.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/InstructionType.kt index 5267bdb..d557b08 100644 --- a/src/jvmMain/kotlin/mtmc/asm/instructions/InstructionType.kt +++ b/src/commonMain/kotlin/mtmc/asm/instructions/InstructionType.kt @@ -1,9 +1,7 @@ package mtmc.asm.instructions -import java.util.* - -enum class InstructionType @JvmOverloads constructor( - @JvmField val instructionClass: InstructionClass?, +enum class InstructionType constructor( + val instructionClass: InstructionClass?, val sizeInBytes: Int = 2 ) { SYS(InstructionClass.MISC), @@ -86,10 +84,9 @@ enum class InstructionType @JvmOverloads constructor( } companion object { - @JvmStatic fun fromString(string: String): InstructionType? { try { - return valueOf(string.uppercase(Locale.getDefault())) + return valueOf(string.uppercase()) } catch (e: IllegalArgumentException) { return null } diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/JumpInstruction.kt b/src/commonMain/kotlin/mtmc/asm/instructions/JumpInstruction.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/asm/instructions/JumpInstruction.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/JumpInstruction.kt diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/JumpRegisterInstruction.kt b/src/commonMain/kotlin/mtmc/asm/instructions/JumpRegisterInstruction.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/asm/instructions/JumpRegisterInstruction.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/JumpRegisterInstruction.kt diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/LoadStoreInstruction.kt b/src/commonMain/kotlin/mtmc/asm/instructions/LoadStoreInstruction.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/asm/instructions/LoadStoreInstruction.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/LoadStoreInstruction.kt diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/LoadStoreRegisterInstruction.kt b/src/commonMain/kotlin/mtmc/asm/instructions/LoadStoreRegisterInstruction.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/asm/instructions/LoadStoreRegisterInstruction.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/LoadStoreRegisterInstruction.kt diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/MetaInstruction.kt b/src/commonMain/kotlin/mtmc/asm/instructions/MetaInstruction.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/asm/instructions/MetaInstruction.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/MetaInstruction.kt diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/MiscInstruction.kt b/src/commonMain/kotlin/mtmc/asm/instructions/MiscInstruction.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/asm/instructions/MiscInstruction.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/MiscInstruction.kt diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/StackInstruction.kt b/src/commonMain/kotlin/mtmc/asm/instructions/StackInstruction.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/asm/instructions/StackInstruction.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/StackInstruction.kt diff --git a/src/jvmMain/kotlin/mtmc/asm/instructions/TestInstruction.kt b/src/commonMain/kotlin/mtmc/asm/instructions/TestInstruction.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/asm/instructions/TestInstruction.kt rename to src/commonMain/kotlin/mtmc/asm/instructions/TestInstruction.kt diff --git a/src/commonMain/kotlin/mtmc/emulator/DebugInfo.kt b/src/commonMain/kotlin/mtmc/emulator/DebugInfo.kt new file mode 100644 index 0000000..ed6ed09 --- /dev/null +++ b/src/commonMain/kotlin/mtmc/emulator/DebugInfo.kt @@ -0,0 +1,47 @@ +package mtmc.emulator + +import nl.astraeus.logger.getTimestamp + +data class DebugInfo( + val debugStrings: MutableList, + val assemblyFile: String?, + val assemblySource: String, + val assemblyLineNumbers: IntArray, + val originalFile: String, + val originalLineNumbers: IntArray, + val globals: Array, + val locals: Array> +) { + fun handleDebugString( + debugIndex: Short, + monTanaMiniComputer: MonTanaMiniComputer + ) { + val debugString = debugStrings!!.get(debugIndex.toInt()) + /* + val compile = Pattern.compile("(\\$[a-zA-Z][a-zA-Z0-9])") + val matcher = compile.matcher(debugString) + val formattedString = StringBuilder() + var start = 0 + var end: Int + while (matcher.find()) { + val match = matcher.group().substring(1) + try { + end = matcher.start() + formattedString.append(debugString, start, end) + val register = Register.valueOf(match.uppercase()) + formattedString.append(monTanaMiniComputer.getRegisterValue(register).toInt()) + start = matcher.end() + } catch (e: Exception) { + formattedString.append(match) + } + } + formattedString.append(debugString.substring(start)) + println("DEBUG[" + getTimestamp() + "] : " + formattedString) + */ + println("DEBUG[" + getTimestamp() + "] : " + debugString) + } + + data class GlobalInfo(val name: String?, val location: Int, val type: String?) + + data class LocalInfo(val name: String?, val offset: Int, val type: String?) +} \ No newline at end of file diff --git a/src/jvmMain/kotlin/mtmc/emulator/MTMCClock.kt b/src/commonMain/kotlin/mtmc/emulator/MTMCClock.kt similarity index 73% rename from src/jvmMain/kotlin/mtmc/emulator/MTMCClock.kt rename to src/commonMain/kotlin/mtmc/emulator/MTMCClock.kt index d440874..4b91a06 100644 --- a/src/jvmMain/kotlin/mtmc/emulator/MTMCClock.kt +++ b/src/commonMain/kotlin/mtmc/emulator/MTMCClock.kt @@ -1,21 +1,23 @@ package mtmc.emulator import mtmc.emulator.MonTanaMiniComputer.ComputerStatus +import mtmc.util.currentTimeMillis import kotlin.math.max /** * * @author jbanes */ -class MTMCClock - (private val computer: MonTanaMiniComputer) { +class MTMCClock( + private val computer: MonTanaMiniComputer +) { fun run() { var instructions: Long = 0 var ips: Long = 0 var expected: Long = 0 var virtual: Long = 0 - var startTime = System.currentTimeMillis() + var startTime = currentTimeMillis() var deltaStart: Long var delta: Long @@ -28,8 +30,8 @@ class MTMCClock pulse = (if (speed <= 0) 1000000 else max(speed / 100, 1)) ms = (if (pulse < 10) 1000 / speed else 10) - deltaStart = System.currentTimeMillis() - delta = ms - (System.currentTimeMillis() - deltaStart) + deltaStart = currentTimeMillis() + delta = ms - (currentTimeMillis() - deltaStart) /* We've lost more than a second. Recalibrate. */ @@ -50,11 +52,11 @@ class MTMCClock instructions += computer.pulse(pulse) virtual += pulse - ips = (virtual * 1000) / max(1, System.currentTimeMillis() - startTime) - expected = (System.currentTimeMillis() - startTime) * speed / 1000 + ips = (virtual * 1000) / max(1, currentTimeMillis() - startTime) + expected = (currentTimeMillis() - startTime) * speed / 1000 } - System.err.println("Executed " + instructions + " instructions at a rate of " + ips + " ips (speed = " + speed + ")") + //println("Executed " + instructions + " instructions at a rate of " + ips + " ips (speed = " + speed + ")") } fun step() { diff --git a/src/jvmMain/kotlin/mtmc/emulator/MTMCConsole.kt b/src/commonMain/kotlin/mtmc/emulator/MTMCConsole.kt similarity index 91% rename from src/jvmMain/kotlin/mtmc/emulator/MTMCConsole.kt rename to src/commonMain/kotlin/mtmc/emulator/MTMCConsole.kt index 75fb03f..64cba70 100644 --- a/src/jvmMain/kotlin/mtmc/emulator/MTMCConsole.kt +++ b/src/commonMain/kotlin/mtmc/emulator/MTMCConsole.kt @@ -1,16 +1,17 @@ package mtmc.emulator +import mtmc.os.fs.Console +import mtmc.os.fs.System import mtmc.os.shell.Shell import mtmc.tokenizer.MTMCScanner import mtmc.tokenizer.MTMCToken -import java.io.Console class MTMCConsole(private val computer: MonTanaMiniComputer) { var mode: Mode = Mode.NON_INTERACTIVE var sysConsole: Console? = null // non-interactive data - private val output = StringBuffer() + private val output = StringBuilder() private var shortValueSet = false private var shortValue: Short = 0 private var stringValue: String? = null @@ -18,7 +19,7 @@ class MTMCConsole(private val computer: MonTanaMiniComputer) { // TODO invert so shell is driving and console is just IO fun start() { mode = Mode.INTERACTIVE - sysConsole = System.console() + sysConsole = System.console Shell.printShellWelcome(computer) while (true) { val cmd = sysConsole!!.readLine("mtmc > ") @@ -48,7 +49,7 @@ class MTMCConsole(private val computer: MonTanaMiniComputer) { if (mode == Mode.INTERACTIVE) { val tokens = MTMCScanner(sysConsole!!.readLine(), "#").tokenize() val token = tokens.first() - assert(token.type === MTMCToken.TokenType.CHAR) + check(token.type === MTMCToken.TokenType.CHAR) return token.charValue() } else { this.shortValueSet = false @@ -88,7 +89,7 @@ class MTMCConsole(private val computer: MonTanaMiniComputer) { val text = if (index >= 0) output.substring(0, index + 1) else "" if (index >= 0) { - output.delete(0, index + 1) + output.removeRange(0, index + 1) } return text @@ -121,7 +122,7 @@ class MTMCConsole(private val computer: MonTanaMiniComputer) { } fun resetOutput() { - output.delete(0, output.length) + output.removeRange(0, output.length) } enum class Mode { diff --git a/src/jvmMain/kotlin/mtmc/emulator/MTMCDisplay.kt b/src/commonMain/kotlin/mtmc/emulator/MTMCDisplay.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/emulator/MTMCDisplay.kt rename to src/commonMain/kotlin/mtmc/emulator/MTMCDisplay.kt diff --git a/src/jvmMain/kotlin/mtmc/emulator/MTMCIO.kt b/src/commonMain/kotlin/mtmc/emulator/MTMCIO.kt similarity index 69% rename from src/jvmMain/kotlin/mtmc/emulator/MTMCIO.kt rename to src/commonMain/kotlin/mtmc/emulator/MTMCIO.kt index 5cbec59..d71683a 100644 --- a/src/jvmMain/kotlin/mtmc/emulator/MTMCIO.kt +++ b/src/commonMain/kotlin/mtmc/emulator/MTMCIO.kt @@ -1,7 +1,5 @@ package mtmc.emulator -import java.util.* - class MTMCIO { var value: Int = 0 @@ -17,12 +15,12 @@ class MTMCIO { } fun keyPressed(key: String) { - val button = Buttons.valueOf(key.uppercase(Locale.getDefault())) + val button = Buttons.valueOf(key.uppercase()) value = value or button.mask } fun keyReleased(key: String) { - val button = Buttons.valueOf(key.uppercase(Locale.getDefault())) + val button = Buttons.valueOf(key.uppercase()) value = value and button.mask.inv() } } diff --git a/src/jvmMain/kotlin/mtmc/emulator/MTMCObserver.kt b/src/commonMain/kotlin/mtmc/emulator/MTMCObserver.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/emulator/MTMCObserver.kt rename to src/commonMain/kotlin/mtmc/emulator/MTMCObserver.kt diff --git a/src/jvmMain/kotlin/mtmc/emulator/MonTanaMiniComputer.kt b/src/commonMain/kotlin/mtmc/emulator/MonTanaMiniComputer.kt similarity index 93% rename from src/jvmMain/kotlin/mtmc/emulator/MonTanaMiniComputer.kt rename to src/commonMain/kotlin/mtmc/emulator/MonTanaMiniComputer.kt index 015d4df..79a7b2d 100644 --- a/src/jvmMain/kotlin/mtmc/emulator/MonTanaMiniComputer.kt +++ b/src/commonMain/kotlin/mtmc/emulator/MonTanaMiniComputer.kt @@ -4,19 +4,7 @@ import mtmc.asm.instructions.Instruction import mtmc.os.MTOS import mtmc.os.fs.FileSystem import mtmc.util.BinaryUtils.getBits -import java.lang.Byte -import java.util.* -import java.util.function.Consumer -import java.util.stream.IntStream -import kotlin.Array -import kotlin.Boolean -import kotlin.ByteArray -import kotlin.Int -import kotlin.IntArray -import kotlin.Long -import kotlin.Short -import kotlin.ShortArray -import kotlin.String +import mtmc.util.Runnable import kotlin.experimental.and import kotlin.experimental.inv import kotlin.experimental.or @@ -43,10 +31,10 @@ class MonTanaMiniComputer { var display: MTMCDisplay = MTMCDisplay(this) var clock: MTMCClock = MTMCClock(this) var fileSystem: FileSystem = FileSystem(this) - var rewindSteps: LinkedList? = LinkedList() + var rewindSteps = mutableListOf() // listeners - private val observers: MutableList = ArrayList() + private val observers = mutableListOf() var debugInfo: DebugInfo? = null private var currentRewindStep: RewindStep? = null @@ -58,13 +46,15 @@ class MonTanaMiniComputer { registerFile = ShortArray(Register.entries.size) memory = ByteArray(MEMORY_SIZE) breakpoints = ByteArray(MEMORY_SIZE) - rewindSteps = null + rewindSteps.clear() setRegisterValue( Register.SP, MEMORY_SIZE.toShort().toInt() ) // default the stack pointer to the top of memory - rewindSteps = LinkedList() - observers!!.forEach(Consumer { obj: MTMCObserver? -> obj!!.computerReset() }) + rewindSteps.clear() + observers.forEach { obj -> + obj.computerReset() + } } fun load(code: ByteArray, data: ByteArray, debugInfo: DebugInfo?) { @@ -79,11 +69,11 @@ class MonTanaMiniComputer { val codeBoundary = code.size - System.arraycopy(code, 0, memory, 0, codeBoundary) + code.copyInto(memory, 0, 0, codeBoundary) setRegisterValue(Register.CB, codeBoundary - 1) val dataBoundary = codeBoundary + data.size - System.arraycopy(data, 0, memory, codeBoundary, data.size) + code.copyInto(memory, codeBoundary, 0, data.size) setRegisterValue(Register.DB, dataBoundary - 1) @@ -143,7 +133,9 @@ class MonTanaMiniComputer { fun fetchAndExecute() { currentRewindStep = RewindStep() - rewindSteps!!.push(currentRewindStep) + currentRewindStep?.let { + rewindSteps.add(0, it) + } fetchCurrentInstruction() val instruction = getRegisterValue(Register.IR) if (isDoubleWordInstruction(instruction)) { @@ -158,7 +150,7 @@ class MonTanaMiniComputer { } fun execInstruction(instruction: Short) { - observers!!.forEach(Consumer { o: MTMCObserver? -> o!!.beforeExecution(instruction) }) + observers!!.forEach({ o: MTMCObserver? -> o!!.beforeExecution(instruction) }) val instructionType: Short = getBits(16, 4, instruction) if (instructionType.toInt() == 0x0000) { // MISC val topNibble: Int = getBits(12, 4, instruction).toInt() @@ -710,7 +702,9 @@ class MonTanaMiniComputer { } else { badInstruction(instruction) } - observers.forEach(Consumer { o: MTMCObserver? -> o!!.afterExecution(instruction) }) + observers.forEach { o: MTMCObserver? -> + o!!.afterExecution(instruction) + } } val isFlagTestBitSet: Boolean @@ -733,7 +727,7 @@ class MonTanaMiniComputer { private fun badInstruction(instruction: Short) { setStatus(ComputerStatus.PERMANENT_ERROR) // TODO implement flags - console.println("BAD INSTRUCTION: 0x" + Integer.toHexString(instruction.toInt() and 0xFFFF)) + console.println("BAD INSTRUCTION: 0x" + (instruction.toInt() and 0xFFFF).toHexString()) } fun fetchCurrentInstruction() { @@ -746,14 +740,16 @@ class MonTanaMiniComputer { } else { setRegisterValue(Register.DR, 0) } - observers!!.forEach(Consumer { o: MTMCObserver? -> o!!.instructionFetched(instruction) }) + observers.forEach { o: MTMCObserver? -> + o!!.instructionFetched(instruction) + } } fun fetchWordFromMemory(address: Int): Short { val upperByte = fetchByteFromMemory(address).toShort() val lowerByte = fetchByteFromMemory(address + 1) var value = (upperByte.toInt() shl 8).toShort() - val i = value.toInt() or Byte.toUnsignedInt(lowerByte) + val i = value.toInt() or lowerByte.toInt() value = i.toShort() return value } @@ -762,9 +758,8 @@ class MonTanaMiniComputer { if (address < 0 || address >= memory.size) { setStatus(ComputerStatus.PERMANENT_ERROR) console.println( - "BAD MEMORY LOCATION ON READ: " + address + " (0x" + Integer.toHexString( - address and 0xFFFF - ) + ")" + "BAD MEMORY LOCATION ON READ: $address (0x" + + (address and 0xFFFF).toHexString() + ")" ) return 0 } else { @@ -782,23 +777,24 @@ class MonTanaMiniComputer { if (address < 0 || address >= memory.size) { setStatus(ComputerStatus.PERMANENT_ERROR) console.println( - "BAD MEMORY LOCATION ON WRITE: " + address + " (0x" + Integer.toHexString( - address and 0xFFFF - ) + ")" + "BAD MEMORY LOCATION ON WRITE: " + address + " (0x" + + (address and 0xFFFF).toHexString() + ")" ) return } val currentValue = memory[address] - addRewindStep(Runnable { memory[address] = currentValue }) + addRewindStep { memory[address] = currentValue } memory[address] = value - observers!!.forEach(Consumer { o: MTMCObserver? -> o!!.memoryUpdated(address, value) }) + observers!!.forEach { o: MTMCObserver? -> + o!!.memoryUpdated(address, value) + } } private fun addRewindStep(runnable: Runnable?) { if (currentRewindStep != null && rewindSteps != null) { currentRewindStep!!.addSubStep(runnable) - if (rewindSteps!!.size > MAX_REWIND_STEPS) { - rewindSteps!!.removeLast() + if (rewindSteps.size > MAX_REWIND_STEPS) { + rewindSteps.removeLast() } } } @@ -812,11 +808,13 @@ class MonTanaMiniComputer { // TODO mark as overflow } val currentValue = registerFile[register] - addRewindStep(Runnable { + addRewindStep { registerFile[register] = currentValue - }) + } registerFile[register] = value.toShort() - observers!!.forEach(Consumer { o: MTMCObserver? -> o!!.registerUpdated(register, value) }) + observers!!.forEach { o: MTMCObserver? -> + o!!.registerUpdated(register, value) + } } fun getRegisterValue(register: Register): Short { @@ -850,7 +848,9 @@ class MonTanaMiniComputer { } fun getBytesFromMemory(address: Int, length: Int): ByteArray { - return Arrays.copyOfRange(memory, address, address + length) + val result = ByteArray(length) + memory.copyInto(result, 0, address, address + length) + return result } val oS: MTOS @@ -858,18 +858,15 @@ class MonTanaMiniComputer { val memoryAddresses: Iterable get() = Iterable { - IntStream.range( - 0, - MEMORY_SIZE - ).iterator() + (0..MEMORY_SIZE).iterator() } fun addObserver(observer: MTMCObserver?) { - observers!!.add(observer!!) + observers.add(observer!!) } fun removeObserver(observer: MTMCObserver?) { - observers!!.remove(observer!!) + observers.remove(observer!!) } fun pause() { @@ -936,7 +933,7 @@ class MonTanaMiniComputer { fun setArg(arg: String) { if (!arg.isEmpty()) { val start = getRegisterValue(Register.BP) - val bytes = arg.toByteArray() + val bytes = arg.encodeToByteArray() writeStringToMemory(start.toInt(), bytes) setRegisterValue(Register.A0, start.toInt()) setRegisterValue(Register.BP, start + bytes.size + 1) @@ -953,7 +950,7 @@ class MonTanaMiniComputer { } fun rewind() { - val latestRewindStep = rewindSteps!!.pop() + val latestRewindStep = rewindSteps.removeFirst() latestRewindStep.rewind() } @@ -1020,7 +1017,6 @@ class MonTanaMiniComputer { return false } - @JvmStatic fun main(args: Array) { val computer = MonTanaMiniComputer() computer.speed = 1 // default to 1hz diff --git a/src/jvmMain/kotlin/mtmc/emulator/Register.kt b/src/commonMain/kotlin/mtmc/emulator/Register.kt similarity index 99% rename from src/jvmMain/kotlin/mtmc/emulator/Register.kt rename to src/commonMain/kotlin/mtmc/emulator/Register.kt index 20b8a0f..82ff429 100644 --- a/src/jvmMain/kotlin/mtmc/emulator/Register.kt +++ b/src/commonMain/kotlin/mtmc/emulator/Register.kt @@ -73,4 +73,4 @@ enum class Register { } } } -} +} \ No newline at end of file diff --git a/src/jvmMain/kotlin/mtmc/emulator/RewindStep.kt b/src/commonMain/kotlin/mtmc/emulator/RewindStep.kt similarity index 67% rename from src/jvmMain/kotlin/mtmc/emulator/RewindStep.kt rename to src/commonMain/kotlin/mtmc/emulator/RewindStep.kt index bfa8b49..4de124f 100644 --- a/src/jvmMain/kotlin/mtmc/emulator/RewindStep.kt +++ b/src/commonMain/kotlin/mtmc/emulator/RewindStep.kt @@ -1,10 +1,12 @@ package mtmc.emulator +import mtmc.util.Runnable + class RewindStep { var subSteps: MutableList = ArrayList() fun rewind() { - subSteps.reversed().forEach({ obj: Runnable? -> obj!!.run() }) + subSteps.reversed().forEach({ obj: Runnable? -> obj!!.invoke() }) } fun addSubStep(subStep: Runnable?) { diff --git a/src/jvmMain/kotlin/mtmc/os/MTOS.kt b/src/commonMain/kotlin/mtmc/os/MTOS.kt similarity index 93% rename from src/jvmMain/kotlin/mtmc/os/MTOS.kt rename to src/commonMain/kotlin/mtmc/os/MTOS.kt index 756bfa6..e77f145 100644 --- a/src/jvmMain/kotlin/mtmc/os/MTOS.kt +++ b/src/commonMain/kotlin/mtmc/os/MTOS.kt @@ -3,18 +3,17 @@ package mtmc.os import mtmc.emulator.MonTanaMiniComputer import mtmc.emulator.Register import mtmc.os.SysCall.Companion.getValue +import mtmc.os.fs.File +import mtmc.os.fs.Files import mtmc.os.shell.Shell -import java.io.File -import java.io.IOException -import java.nio.file.Files -import java.util.* +import mtmc.util.currentTimeMillis import kotlin.math.max import kotlin.math.min -import kotlin.text.Charsets.US_ASCII +import kotlin.random.Random class MTOS(private val computer: MonTanaMiniComputer) { private var timer: Long = 0 - var random: Random = Random() + var random: Random = Random.Default // Editor support var currentFile: String? = null @@ -98,7 +97,7 @@ class MTOS(private val computer: MonTanaMiniComputer) { } } val string = computer.console.readString() - val bytes = string!!.toByteArray(US_ASCII) + val bytes = string!!.encodeToByteArray() val bytesToRead = min(bytes.size, maxLen.toInt()) for (i in 0..(str.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) + val lines: List = + str.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() .filter { s: String? -> !s!!.startsWith("!") } .toList() @@ -251,7 +250,7 @@ class MTOS(private val computer: MonTanaMiniComputer) { val cappedLines = min(linesTotal, maxSize2.toInt()) for (lineNum in 0.. 0) this.timer = System.currentTimeMillis() + value + if (value > 0) this.timer = currentTimeMillis() + value computer.setRegisterValue( Register.RV, - max(0, this.timer - System.currentTimeMillis()).toInt() + max(0, this.timer - currentTimeMillis()).toInt() ) } else if (syscallNumber == getValue("drawimg").toShort()) { val image = computer.getRegisterValue(Register.A0) @@ -401,10 +399,13 @@ class MTOS(private val computer: MonTanaMiniComputer) { } val file = list[offset.toInt()] - val name = file.getName() + val name = file.name val size = min(maxSizeOut - 1, name.length) - computer.writeWordToMemory(destination.toInt(), if (file.isDirectory()) 1 else 0) + computer.writeWordToMemory( + destination.toInt(), + if (file.directory) 1 else 0 + ) for (i in 0..") + /* + { + val fs = computer.fileSystem + val file = fs.getRealPath(path).toFile() + return file + } + */ } diff --git a/src/jvmMain/kotlin/mtmc/os/SysCall.kt b/src/commonMain/kotlin/mtmc/os/SysCall.kt similarity index 82% rename from src/jvmMain/kotlin/mtmc/os/SysCall.kt rename to src/commonMain/kotlin/mtmc/os/SysCall.kt index fe21f90..a577728 100644 --- a/src/jvmMain/kotlin/mtmc/os/SysCall.kt +++ b/src/commonMain/kotlin/mtmc/os/SysCall.kt @@ -1,7 +1,5 @@ package mtmc.os -import java.util.* - enum class SysCall(value: Int) { EXIT(0x00), RINT(0x01), @@ -50,25 +48,24 @@ enum class SysCall(value: Int) { companion object { fun isSysCall(call: String): Boolean { try { - valueOf(call.uppercase(Locale.getDefault())) + valueOf(call.uppercase()) return true } catch (e: IllegalArgumentException) { return false } } - @JvmStatic fun getValue(call: String): Byte { - return valueOf(call.uppercase(Locale.getDefault())).value + return valueOf(call.uppercase()).value } fun getString(syscallCode: Byte): String? { for (o in entries) { if (o.value == syscallCode) { - return o.name.lowercase(Locale.getDefault()) + return o.name.lowercase() } } return null } } -} +} \ No newline at end of file diff --git a/src/commonMain/kotlin/mtmc/os/exec/Executable.kt b/src/commonMain/kotlin/mtmc/os/exec/Executable.kt new file mode 100644 index 0000000..9342613 --- /dev/null +++ b/src/commonMain/kotlin/mtmc/os/exec/Executable.kt @@ -0,0 +1,58 @@ +package mtmc.os.exec + +import mtmc.emulator.DebugInfo +import mtmc.os.fs.Path + +data class Executable( + val format: Format, + val code: ByteArray, + val data: ByteArray, + val graphics: Array, + val sourceName: String, + val debugInfo: DebugInfo? +) { + enum class Format(val formatName: String) { + Orc1("orc1"); + } + + fun dump(): String? { + return null //Gson().toJson(this) + } + + fun dump(path: Path) { + /* + FileWriter(path.toFile()).use { fw -> + dump(fw) + } + */ + } + + /* + fun dump(writer: Writer?) { + val gson = Gson() + gson.toJson(this, writer) + } + */ + + companion object { + fun load(exe: String?): Executable? { + return null //Gson().fromJson(exe, Executable::class.java) + } + + fun load(path: Path): Executable? = null + /* + { + FileReader(path.toFile()).use { fw -> + return load(fw) + } + } + */ + + /* + fun load(reader: Reader): Executable? { + val gson = Gson() + return gson.fromJson(reader, Executable::class.java) + } + */ + } +} diff --git a/src/commonMain/kotlin/mtmc/os/fs/Console.kt b/src/commonMain/kotlin/mtmc/os/fs/Console.kt new file mode 100644 index 0000000..cd31fa7 --- /dev/null +++ b/src/commonMain/kotlin/mtmc/os/fs/Console.kt @@ -0,0 +1,11 @@ +package mtmc.os.fs + +object System { + val console: Console = Console() +} + +class Console { + fun readLine(prompt: String? = ""): String { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/src/jvmMain/kotlin/mtmc/os/fs/ExecutableFileTypeDetector.java b/src/commonMain/kotlin/mtmc/os/fs/ExecutableFileTypeDetector.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/os/fs/ExecutableFileTypeDetector.java rename to src/commonMain/kotlin/mtmc/os/fs/ExecutableFileTypeDetector.java diff --git a/src/commonMain/kotlin/mtmc/os/fs/File.kt b/src/commonMain/kotlin/mtmc/os/fs/File.kt new file mode 100644 index 0000000..5791843 --- /dev/null +++ b/src/commonMain/kotlin/mtmc/os/fs/File.kt @@ -0,0 +1,47 @@ +package mtmc.os.fs + +object Files { + fun readString(toPath: Path): String { + TODO("Not yet implemented") + } + + fun readAllBytes(toPath: Path): ByteArray { + TODO("Not yet implemented") + } + +} + +class File( + val parent: File? = null, + val name: String +) { + + var directory: Boolean = TODO("initialize me") + + constructor(name: String) : this(null, name) + + fun getParent(): File = parent ?: error("No parent") + + fun getPath(): String = if (parent == null) { + name + } else { + "${parent.getPath()}/$name" + } + + fun exists(): Boolean { + TODO("Not yet implemented") + } + + fun getAbsolutePath(): String { + TODO("Not yet implemented") + } + + fun toPath(): Path { + TODO("Not yet implemented") + } + + fun listFiles(): Array { + TODO("Not yet implemented") + } + +} \ No newline at end of file diff --git a/src/commonMain/kotlin/mtmc/os/fs/FileSystem.kt b/src/commonMain/kotlin/mtmc/os/fs/FileSystem.kt new file mode 100644 index 0000000..2f904ca --- /dev/null +++ b/src/commonMain/kotlin/mtmc/os/fs/FileSystem.kt @@ -0,0 +1,213 @@ +package mtmc.os.fs + +import mtmc.emulator.MonTanaMiniComputer +import kotlin.jvm.JvmField + +class FileSystem( + val computer: MonTanaMiniComputer +) { + private var cwd = "/home" + + init { + initFileSystem() + } + + private fun initFileSystem() { + /* + if (DISK_PATH.toFile().exists()) return + + + // Make the disk/ directory + DISK_PATH.toFile().mkdirs() + + try { + ZipInputStream(getClass().getResourceAsStream("/disk.zip")).use { `in` -> + var entry: ZipEntry? + var file: File? + + val data = ByteArray(4096) + var count: Int + while ((`in`.getNextEntry().also { entry = it }) != null) { + file = File(entry.getName()) + + if (entry.isDirectory()) { + file.mkdirs() + } else { + file.getParentFile().mkdirs() + + FileOutputStream(file).use { out -> + while ((`in`.read(data).also { count = it }) > 0) { + out.write(data, 0, count) + } + } + } + } + } + } catch (e: IOException) { + e.printStackTrace() + } + */ + } + + private fun notifyOfFileSystemUpdate() { + if (this.computer != null) { + computer.notifyOfFileSystemUpdate() + } + } + + var cWD: String + get() = this.cwd + set(cwd) { + this.cwd = resolve(cwd) + this.notifyOfFileSystemUpdate() + } + + fun exists(path: String): Boolean { + return false //File(DISK_PATH.toFile(), resolve(path)).exists() + } + + fun mkdir(path: String): Boolean { + /* + val success: Boolean = File(DISK_PATH.toFile(), resolve(path)).mkdir() + + if (success) { + computer.notifyOfFileSystemUpdate() + } + + return success + */ + return true + } + + fun delete(path: String): Boolean { + /* + val success: Boolean = File(DISK_PATH.toFile(), resolve(path)).delete() + + if (success) { + computer.notifyOfFileSystemUpdate() + } + + return success + */ + return true + } + + fun resolve(filename: String): String = filename + /* + { + val root: File = DISK_PATH.toFile() + var directory = if (filename.startsWith("/")) root else File(root, cwd) + val path: Array = filename.split("/") + + for (name in path) { + if (name.equals(".")) { + continue + } else if (name.equals("..") && directory.equals(root)) { + continue + } else if (name.equals("..")) { + directory = directory.getParentFile() + } else { + directory = File(directory, name) + } + } + + if (directory.equals(root)) { + return "/" + } + + return directory.getAbsolutePath().substring(root.getAbsolutePath().length()) + } + */ + + fun getRealPath(path: String): Path { // Resolves given path and returns /disk/ + path + val resolvedPath = resolve(path) + val slashGone: String = if (resolvedPath.length > 0) resolvedPath.substring(1) else "" + val file: File = DISK_PATH.resolve(slashGone).toFile() + + if (file.getAbsolutePath().length < DISK_PATH.toFile().getAbsolutePath().length) { + return DISK_PATH + } + + return file.toPath() + } + + fun getFileList(path: String): Array { + val resolvedPath: File = getRealPath(path).toFile() + + if (!resolvedPath.directory) return arrayOf(resolvedPath) + + return resolvedPath.listFiles() + } + + fun listFiles(path: String): Listing { + val resolvedPath: File = getRealPath(path).toFile() + + return Listing(this, resolvedPath) + } + + fun listCWD(): Listing { + return listFiles(cwd) + } + + fun listRoot(): Listing { + return listFiles("/") + } + + fun writeFile(path: String, contents: String?) { + val filePath: Path = getRealPath(path) + //Files.writeString(filePath, contents) + } + + fun readFile(path: String): String? { + val filePath: Path = getRealPath(path) + val contents = "" //Files.readString(filePath) + return contents + } + + fun getMimeType(path: String): String { + val file: Path = getRealPath(path) + val name = file.toFile().name.lowercase() + val probed = file.probeContentType() + + if (name.endsWith(".asm")) return "text/x-asm" + if (name.endsWith(".c")) return "text/x-csrc" + if (name.endsWith(".sea")) return "text/x-csrc" + if (name.endsWith(".h")) return "text/x-csrc" + if (probed != null) return probed + + return "application/octet-stream" + } + + /* + fun openFile(path: String): InputStream? { + val file: Unit */ + /* TODO: class org.jetbrains.kotlin.nj2k.types.JKJavaNullPrimitiveType *//* +? = + getRealPath(path).toFile() + + return FileInputStream(file) + } +*/ + + /* + fun saveFile(path: String, contents: InputStream) { + val file: Unit */ + /* TODO: class org.jetbrains.kotlin.nj2k.types.JKJavaNullPrimitiveType *//* +? = + getRealPath(path).toFile() + val data = ByteArray(4096) + var count: Int + + FileOutputStream(file).use { out -> + while ((contents.read(data).also { count = it }) > 0) { + out.write(data, 0, count) + } + } + } +*/ + + companion object { + @JvmField + val DISK_PATH: Path = Path() //.of(System.getProperty("user.dir"), "disk").toAbsolutePath() + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/mtmc/os/fs/Listing.kt b/src/commonMain/kotlin/mtmc/os/fs/Listing.kt new file mode 100644 index 0000000..899a76e --- /dev/null +++ b/src/commonMain/kotlin/mtmc/os/fs/Listing.kt @@ -0,0 +1,45 @@ +package mtmc.os.fs + +class Listing( + val fs: FileSystem, + val file: File +) { + val path: String + val name: String + val directory: Boolean + val root: Boolean + + init { + val root = FileSystem.DISK_PATH.toFile().getAbsolutePath().replace('\\', '/') + val path = file.getAbsolutePath().substring(root.length).replace('\\', '/') + + this.path = if (path.length > 0) path else "/" + this.name = if (path.length > 0) file.name else "/" + this.directory = file.directory + this.root = this.path.equals("/") + } + + val parent: Listing? + get() = if (file.parent != null) { + Listing(fs, file.parent) + } else { + null + } + + fun list(): List { + if (!directory) { + return ArrayList() + } + + val list = ArrayList() + val children = file.listFiles() + + list.sortBy { it.name } + + for (child in children) { + list.add(Listing(fs, child)) + } + + return list + } +} diff --git a/src/commonMain/kotlin/mtmc/os/fs/Path.kt b/src/commonMain/kotlin/mtmc/os/fs/Path.kt new file mode 100644 index 0000000..d005d17 --- /dev/null +++ b/src/commonMain/kotlin/mtmc/os/fs/Path.kt @@ -0,0 +1,15 @@ +package mtmc.os.fs + +class Path { + fun toFile(): File { + TODO("Not yet implemented") + } + + fun probeContentType(): String? { + TODO("Not yet implemented") + } + + fun resolve(filename: String): Path { + TODO("Not yet implemented") + } +} \ No newline at end of file diff --git a/src/jvmMain/kotlin/mtmc/os/fs/PlainTextFileTypeDetector.java b/src/commonMain/kotlin/mtmc/os/fs/PlainTextFileTypeDetector.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/os/fs/PlainTextFileTypeDetector.java rename to src/commonMain/kotlin/mtmc/os/fs/PlainTextFileTypeDetector.java diff --git a/src/commonMain/kotlin/mtmc/os/shell/Shell.kt b/src/commonMain/kotlin/mtmc/os/shell/Shell.kt index 450e018..4d8b057 100644 --- a/src/commonMain/kotlin/mtmc/os/shell/Shell.kt +++ b/src/commonMain/kotlin/mtmc/os/shell/Shell.kt @@ -1,160 +1,163 @@ -package mtmc.os.shell; +package mtmc.os.shell -import mtmc.asm.Assembler; -import mtmc.asm.AssemblyResult; -import mtmc.asm.instructions.Instruction; -import mtmc.emulator.DebugInfo; -import mtmc.emulator.MonTanaMiniComputer; -import mtmc.emulator.Register; -import mtmc.os.exec.Executable; -import mtmc.os.fs.FileSystem; -import mtmc.os.shell.builtins.AssembleCommand; -import mtmc.os.shell.builtins.DisplayCommand; -import mtmc.os.shell.builtins.ExitCommand; -import mtmc.os.shell.builtins.GetCommand; -import mtmc.os.shell.builtins.HelpCommand; -import mtmc.os.shell.builtins.LoadCommand; -import mtmc.os.shell.builtins.PauseCommand; -import mtmc.os.shell.builtins.RunCommand; -import mtmc.os.shell.builtins.SeacCommand; -import mtmc.os.shell.builtins.SetCommand; -import mtmc.os.shell.builtins.SpeedCommand; -import mtmc.os.shell.builtins.StepCommand; -import mtmc.os.shell.builtins.WebCommand; -import mtmc.tokenizer.MTMCToken; -import mtmc.tokenizer.MTMCTokenizer; +import mtmc.asm.Assembler +import mtmc.asm.instructions.Instruction.Companion.isInstruction +import mtmc.asm.peekFirst +import mtmc.emulator.MonTanaMiniComputer +import mtmc.emulator.Register +import mtmc.os.fs.FileSystem +import mtmc.os.shell.builtins.AssembleCommand +import mtmc.os.shell.builtins.DisplayCommand +import mtmc.os.shell.builtins.ExitCommand +import mtmc.os.shell.builtins.GetCommand +import mtmc.os.shell.builtins.HelpCommand +import mtmc.os.shell.builtins.LoadCommand +import mtmc.os.shell.builtins.PauseCommand +import mtmc.os.shell.builtins.RunCommand +import mtmc.os.shell.builtins.SeacCommand +import mtmc.os.shell.builtins.SetCommand +import mtmc.os.shell.builtins.SpeedCommand +import mtmc.os.shell.builtins.StepCommand +import mtmc.os.shell.builtins.WebCommand +import mtmc.tokenizer.MTMCToken +import mtmc.tokenizer.MTMCTokenizer -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.Map; +object Shell { + private val COMMANDS: MutableMap = LinkedHashMap() -import static mtmc.tokenizer.MTMCToken.TokenType.IDENTIFIER; -import static mtmc.tokenizer.MTMCToken.TokenType.QUESTION_MARK; + init { + COMMANDS.put("help", HelpCommand()) + COMMANDS.put("exit", ExitCommand()) + COMMANDS.put("set", SetCommand()) + COMMANDS.put("get", GetCommand()) + COMMANDS.put("web", WebCommand()) + COMMANDS.put("disp", DisplayCommand()) + COMMANDS.put("asm", AssembleCommand()) + COMMANDS.put("load", LoadCommand()) + COMMANDS.put("step", StepCommand()) + COMMANDS.put("run", RunCommand()) + COMMANDS.put("pause", PauseCommand()) + COMMANDS.put("speed", SpeedCommand()) + COMMANDS.put("sc", SeacCommand()) + } -public class Shell { - private static final Map COMMANDS = new LinkedHashMap<>(); + fun isCommand(cmd: String): Boolean { + return COMMANDS.containsKey(cmd.lowercase()) + } - static { - COMMANDS.put("help", new HelpCommand()); - COMMANDS.put("exit", new ExitCommand()); - COMMANDS.put("set", new SetCommand()); - COMMANDS.put("get", new GetCommand()); - COMMANDS.put("web", new WebCommand()); - COMMANDS.put("disp", new DisplayCommand()); - COMMANDS.put("asm", new AssembleCommand()); - COMMANDS.put("load", new LoadCommand()); - COMMANDS.put("step", new StepCommand()); - COMMANDS.put("run", new RunCommand()); - COMMANDS.put("pause", new PauseCommand()); - COMMANDS.put("speed", new SpeedCommand()); - COMMANDS.put("sc", new SeacCommand()); - } + private fun findExecutable(path: String?, fs: FileSystem): Boolean { + if (path == null || path == "") return false + //if (fs.exists(path) && !fs.listFiles(path).directory) return true + //if (fs.exists("/bin/" + path) && !fs.listFiles("/bin/" + path).directory) return true - public static boolean isCommand(String cmd) { - return COMMANDS.containsKey(cmd.toLowerCase()); - } - - private static boolean findExecutable(String path, FileSystem fs) { - if (path == null || path.equals("")) return false; - if (fs.exists(path) && !fs.listFiles(path).directory) return true; - if (fs.exists("/bin/" + path) && !fs.listFiles("/bin/" + path).directory) return true; - - return false; - } - - private static void runExecutable(String file, String command, MTMCTokenizer tokens, MonTanaMiniComputer computer) throws Exception { - FileSystem fs = computer.getFileSystem(); - Path srcPath = Path.of("disk/" + fs.resolve(file)); - if(!srcPath.toFile().exists()) { - srcPath = Path.of("disk" + fs.resolve("/bin/" + file)); + return false + } + + @Throws(Exception::class) + private fun runExecutable( + file: String, + command: String, + tokens: MTMCTokenizer, + computer: MonTanaMiniComputer + ) { + val fs = computer.fileSystem + /* + var srcPath = Path.of("disk/" + fs.resolve(file)) + if (!srcPath.toFile().exists()) { + srcPath = Path.of("disk" + fs.resolve("/bin/" + file)) } - Executable exec = Executable.load(srcPath); - computer.load(exec.code, exec.data, exec.graphics, exec.debugInfo); - tokens.consume(); - String arg = command.substring(file.length()).strip(); - computer.getOS().applyBreakpoints(); - computer.setArg(arg); - computer.run(); - } - - public static void execCommand(String command, MonTanaMiniComputer computer) { - MTMCTokenizer tokens = new MTMCTokenizer(command, "#"); - try { - MTMCToken identifier = tokens.matchAndConsume(IDENTIFIER); - String cmd; - if (identifier == null) { - MTMCToken question = tokens.matchAndConsume(QUESTION_MARK); - String executable = tokens.collapseTokensAsString(); - - // alias ? to help - if (question != null) { - cmd = "help"; - } else if (findExecutable(executable, computer.getFileSystem())) { - cmd = executable; - } else { - printShellHelp(computer); - return; - } - } else { - cmd = identifier.stringValue(); + val exec = load(srcPath) + computer.load(exec!!.code, exec.data, exec.graphics, exec.debugInfo) + tokens.consume() + val arg = command.substring(file.length).trim() + computer.oS.applyBreakpoints() + computer.setArg(arg) + computer.run() + */ + } + + fun execCommand(command: String, computer: MonTanaMiniComputer) { + val tokens = MTMCTokenizer(command, "#") + try { + val identifier = tokens.matchAndConsume(MTMCToken.TokenType.IDENTIFIER) + val cmd: String? + if (identifier == null) { + val question = tokens.matchAndConsume(MTMCToken.TokenType.QUESTION_MARK) + val executable = tokens.collapseTokensAsString() + + + // alias ? to help + if (question != null) { + cmd = "help" + } else if (findExecutable(executable, computer.fileSystem)) { + cmd = executable + } else { + printShellHelp(computer) + return + } + } else { + cmd = identifier.stringValue() + } + if (isCommand(cmd)) { + COMMANDS[cmd.lowercase()]!!.exec(tokens, computer) + } else { + tokens.reset() + val asm = mutableListOf() + asm.addAll(tokens.tokens) + val updatedAsm = Assembler.transformSyntheticInstructions(asm) + val firstToken = updatedAsm.peekFirst() + val firstTokenStr = firstToken?.stringValue() ?: error("Unexpected null token") + if (!updatedAsm.isEmpty() && isInstruction(firstTokenStr)) { + val assembler = Assembler() + val result = assembler.assemble(command) + if (result.errors.isEmpty()) { + val code = result.code + if (code.size == 4) { + val data = (code[2].toInt() shl 8) or code[3].toInt() + computer.setRegisterValue(Register.DR, data) } - if (isCommand(cmd)) { - COMMANDS.get(cmd.toLowerCase()).exec(tokens, computer); - } else { - tokens.reset(); - LinkedList asm = new LinkedList<>(tokens.stream().toList()); - LinkedList updatedAsm = Assembler.Companion.transformSyntheticInstructions(asm); - MTMCToken firstToken = updatedAsm.peekFirst(); - String firstTokenStr = firstToken.stringValue(); - if (!updatedAsm.isEmpty() && Instruction.isInstruction(firstTokenStr)) { - Assembler assembler = new Assembler(); - AssemblyResult result = assembler.assemble(command); - if (result.errors.isEmpty()) { - byte[] code = result.code; - if (code.length == 4) { - int data = (code[2] << 8) | code[3]; - computer.setRegisterValue(Register.DR, data); - } - int lower = code[1] & 0xFF; - int higher = code[0] & 0xFF; - int inst = (higher << 8) | lower; - DebugInfo originalDebugInfo = computer.getDebugInfo(); - computer.setDebugInfo(result.debugInfo); - computer.execInstruction((short) inst); - computer.setDebugInfo(originalDebugInfo); - } else { - computer.getConsole().println(result.printErrors()); - } - } else { - if (findExecutable(cmd, computer.getFileSystem())) { - runExecutable(cmd, command, tokens, computer); - } else { - printShellHelp(computer); - } - } - } - } catch (NoSuchFileException e) { - computer.getConsole().println("No such file: " + e.getFile()); - } catch (Exception e) { - computer.getConsole().println(e.getMessage()); - e.printStackTrace(); + val lower = code[1].toInt() and 0xFF + val higher = code[0].toInt() and 0xFF + val inst = (higher shl 8) or lower + val originalDebugInfo = computer.debugInfo + computer.debugInfo = result.debugInfo + computer.execInstruction(inst.toShort()) + computer.debugInfo = originalDebugInfo + } else { + computer.console.println(result.printErrors()) + } + } else { + if (findExecutable(cmd, computer.fileSystem)) { + runExecutable(cmd, command, tokens, computer) + } else { + printShellHelp(computer) + } } + } + /* + } catch (e: NoSuchFileException) { + computer.console.println("No such file: " + e.getFile()) + */ + } catch (e: Exception) { + computer.console.println(e.message!!) + e.printStackTrace() } + } - public static void printShellHelp(MonTanaMiniComputer computer) { - computer.getConsole().println("Shell BuiltIns: \n"); - for (ShellCommand value : COMMANDS.values()) { - computer.getConsole().println(value.help); - } - computer.getConsole().println("Also: "); - computer.getConsole().println(" "); - computer.getConsole().println("or \n" + - " \n\n"); + fun printShellHelp(computer: MonTanaMiniComputer) { + computer.console.println("Shell BuiltIns: \n") + for (value in COMMANDS.values) { + computer.console.println(value.help!!) } + computer.console.println("Also: ") + computer.console.println(" ") + computer.console.println( + "or \n" + + " \n\n" + ) + } - public static void printShellWelcome(MonTanaMiniComputer computer) { - computer.getConsole().println("Welcome to MtOS! Type ? for help"); - } + fun printShellWelcome(computer: MonTanaMiniComputer) { + computer.console.println("Welcome to MtOS! Type ? for help") + } } diff --git a/src/jvmMain/kotlin/mtmc/os/shell/ShellCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/ShellCommand.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/os/shell/ShellCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/ShellCommand.kt diff --git a/src/commonMain/kotlin/mtmc/os/shell/UsageException.kt b/src/commonMain/kotlin/mtmc/os/shell/UsageException.kt index 69e1bb2..deb9af5 100644 --- a/src/commonMain/kotlin/mtmc/os/shell/UsageException.kt +++ b/src/commonMain/kotlin/mtmc/os/shell/UsageException.kt @@ -1,12 +1,7 @@ -package mtmc.os.shell; +package mtmc.os.shell -public class UsageException extends RuntimeException { - private final ShellCommand cmd; - public UsageException(ShellCommand shellCommand) { - super("Usage:\n\n" + shellCommand.help); - this.cmd = shellCommand; - } - public ShellCommand getCmd() { - return cmd; - } -} +class UsageException( + cmd: ShellCommand +) : RuntimeException( + "Usage:\n\n" + cmd.help +) diff --git a/src/commonMain/kotlin/mtmc/os/shell/builtins/AssembleCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/AssembleCommand.kt new file mode 100644 index 0000000..4a3f2bd --- /dev/null +++ b/src/commonMain/kotlin/mtmc/os/shell/builtins/AssembleCommand.kt @@ -0,0 +1,45 @@ +package mtmc.os.shell.builtins + +import mtmc.emulator.MonTanaMiniComputer +import mtmc.os.shell.ShellCommand +import mtmc.tokenizer.MTMCTokenizer + +class AssembleCommand : ShellCommand() { + @Throws(Exception::class) + public override fun exec(tokens: MTMCTokenizer, computer: MonTanaMiniComputer) { + val fs = computer.fileSystem + val src = tokens.collapseTokensAsString() + require(!(src == null || src.isBlank())) { "missing or required argument 'src'" } + /* + val srcPath: Path = getDiskPath(src, fs) + + val dst = tokens.collapseTokensAsString() + require(!(dst == null || dst.isBlank())) { "missing required argument 'dst'" } + val dstPath: Path = getDiskPath(dst, fs) + + val contents = Files.readString(srcPath) + val assembler = Assembler() + val file_name = + fs.resolve(src) // srcPath.toString().substring(DISK_PATH.toString().length()).replaceAll("\\\\", "/"); + val executable = assembler.assembleExecutable(file_name, contents) + executable.dump(dstPath) + computer.notifyOfFileSystemUpdate() + */ + } + + override val help: String + get() = """ + asm + - src : path to a .asm file + - dst : path to a target output binary + """.trimIndent() + + companion object { + /* + fun getDiskPath(pathString: String, fs: FileSystem): Path { + val path = Path.of("disk" + fs.resolve(pathString)) + return path.toAbsolutePath() + } + */ + } +} diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/DisplayCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/DisplayCommand.kt similarity index 83% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/DisplayCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/DisplayCommand.kt index 7b7512d..1260872 100644 --- a/src/jvmMain/kotlin/mtmc/os/shell/builtins/DisplayCommand.kt +++ b/src/commonMain/kotlin/mtmc/os/shell/builtins/DisplayCommand.kt @@ -2,15 +2,14 @@ package mtmc.os.shell.builtins import mtmc.emulator.MTMCDisplay import mtmc.emulator.MonTanaMiniComputer +import mtmc.os.fs.File import mtmc.os.shell.ShellCommand import mtmc.tokenizer.MTMCToken import mtmc.tokenizer.MTMCTokenizer -import java.io.File -import java.util.* -import javax.imageio.ImageIO +import kotlin.random.Random class DisplayCommand : ShellCommand() { - var random: Random = Random() + var random: Random = Random.Default @Throws(Exception::class) public override fun exec(tokens: MTMCTokenizer, computer: MonTanaMiniComputer) { @@ -42,8 +41,8 @@ class DisplayCommand : ShellCommand() { if (tokens.more()) { val imagePath = tokens.collapseTokensAsString() val file = computer.oS.loadFile(imagePath) - val img = ImageIO.read(file) - computer.display.loadScaledImage(img) + //val img = ImageIO.read(file) + //computer.display.loadScaledImage(img) } else { usageException() } @@ -54,11 +53,15 @@ class DisplayCommand : ShellCommand() { } else if (tokens.match(MTMCToken.TokenType.INTEGER)) { val row = tokens.consumeAsInteger() val col = tokens.require( - mtmc.tokenizer.MTMCToken.TokenType.INTEGER, - java.lang.Runnable { this.usageException() })!!.intValue() + mtmc.tokenizer.MTMCToken.TokenType.INTEGER + ) { + this.usageException() + }!!.intValue() val color = tokens.require( - mtmc.tokenizer.MTMCToken.TokenType.INTEGER, - java.lang.Runnable { this.usageException() })!!.intValue() + mtmc.tokenizer.MTMCToken.TokenType.INTEGER + ) { + this.usageException() + }!!.intValue() computer.display.setPixel(row, col, color) } else { usageException() diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/ExitCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/ExitCommand.kt similarity index 94% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/ExitCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/ExitCommand.kt index 7ad6b06..fee12fc 100644 --- a/src/jvmMain/kotlin/mtmc/os/shell/builtins/ExitCommand.kt +++ b/src/commonMain/kotlin/mtmc/os/shell/builtins/ExitCommand.kt @@ -7,7 +7,7 @@ import mtmc.tokenizer.MTMCTokenizer class ExitCommand : ShellCommand() { public override fun exec(tokens: MTMCTokenizer, computer: MonTanaMiniComputer) { computer.console.println("Goodbye!") - System.exit(1) + //System.exit(1) } override val help: String diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/GetCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/GetCommand.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/GetCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/GetCommand.kt diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/HelpCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/HelpCommand.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/HelpCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/HelpCommand.kt diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/LoadCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/LoadCommand.kt similarity index 92% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/LoadCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/LoadCommand.kt index 789fe95..96387be 100644 --- a/src/jvmMain/kotlin/mtmc/os/shell/builtins/LoadCommand.kt +++ b/src/commonMain/kotlin/mtmc/os/shell/builtins/LoadCommand.kt @@ -3,13 +3,13 @@ package mtmc.os.shell.builtins import mtmc.emulator.MonTanaMiniComputer import mtmc.os.exec.Executable.Companion.load import mtmc.os.fs.FileSystem +import mtmc.os.fs.Path import mtmc.os.shell.ShellCommand import mtmc.tokenizer.MTMCTokenizer -import java.nio.file.Path class LoadCommand : ShellCommand() { @Throws(Exception::class) - public override fun exec(tokens: MTMCTokenizer, computer: MonTanaMiniComputer) { + override fun exec(tokens: MTMCTokenizer, computer: MonTanaMiniComputer) { val fs = computer.fileSystem val program = tokens.collapseTokensAsString() require(!(program == null || program.isBlank())) { "missing or required argument 'src'" } diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/PauseCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/PauseCommand.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/PauseCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/PauseCommand.kt diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/RunCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/RunCommand.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/RunCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/RunCommand.kt diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/SeacCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/SeacCommand.kt similarity index 66% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/SeacCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/SeacCommand.kt index fc6bd34..2b053e2 100644 --- a/src/jvmMain/kotlin/mtmc/os/shell/builtins/SeacCommand.kt +++ b/src/commonMain/kotlin/mtmc/os/shell/builtins/SeacCommand.kt @@ -1,10 +1,8 @@ package mtmc.os.shell.builtins import mtmc.emulator.MonTanaMiniComputer -import mtmc.lang.sea.SeaLanguage import mtmc.os.shell.ShellCommand import mtmc.tokenizer.MTMCTokenizer -import mtmc.util.StringEscapeUtils.escapeString class SeacCommand : ShellCommand() { @Throws(Exception::class) @@ -24,15 +22,18 @@ class SeacCommand : ShellCommand() { requireNotNull(filename) { "expected source file" } - require(fs.exists(filename)) { "file " + escapeString(filename) + " does not exist" } + require(fs.exists(filename)) { "file " + filename + " does not exist" } println(fs.resolve(filename)) - val lang = SeaLanguage() - val content = fs.readFile(filename) - val exec = lang.compileExecutable(fs.resolve(filename), content) - val bin = exec.dump() - computer.fileSystem.writeFile(output, bin) - computer.notifyOfFileSystemUpdate() + /* + val lang = SeaLanguage() + val content = fs.readFile(filename) + val exec = lang.compileExecutable(fs.resolve(filename), content) + + val bin = exec.dump() + computer.fileSystem.writeFile(output, bin) + computer.notifyOfFileSystemUpdate() + */ } override val help: String diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/SetCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/SetCommand.kt similarity index 93% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/SetCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/SetCommand.kt index bb93b3b..6dfffe8 100644 --- a/src/jvmMain/kotlin/mtmc/os/shell/builtins/SetCommand.kt +++ b/src/commonMain/kotlin/mtmc/os/shell/builtins/SetCommand.kt @@ -40,7 +40,10 @@ class SetCommand : ShellCommand() { if (value?.type === MTMCToken.TokenType.INTEGER || value?.type === MTMCToken.TokenType.BINARY || value?.type === MTMCToken.TokenType.HEX) { computer.writeWordToMemory(memLocation.intValue(), value.intValue()) } else { - computer.writeStringToMemory(memLocation.intValue(), value!!.stringValue().toByteArray()) + computer.writeStringToMemory( + memLocation.intValue(), + value!!.stringValue().encodeToByteArray() + ) } } } diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/SpeedCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/SpeedCommand.kt similarity index 90% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/SpeedCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/SpeedCommand.kt index 210dff7..625af06 100644 --- a/src/jvmMain/kotlin/mtmc/os/shell/builtins/SpeedCommand.kt +++ b/src/commonMain/kotlin/mtmc/os/shell/builtins/SpeedCommand.kt @@ -4,13 +4,10 @@ import mtmc.emulator.MonTanaMiniComputer import mtmc.os.shell.ShellCommand import mtmc.tokenizer.MTMCToken import mtmc.tokenizer.MTMCTokenizer -import java.util.* class SpeedCommand : ShellCommand() { - private val speeds: MutableList = Arrays.asList( - *arrayOf( + private val speeds = listOf( 1, 10, 100, 1000, 10000, 100000, 1000000 - ) ) @Throws(Exception::class) diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/StepCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/StepCommand.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/StepCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/StepCommand.kt diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/WebCommand.kt b/src/commonMain/kotlin/mtmc/os/shell/builtins/WebCommand.kt similarity index 100% rename from src/jvmMain/kotlin/mtmc/os/shell/builtins/WebCommand.kt rename to src/commonMain/kotlin/mtmc/os/shell/builtins/WebCommand.kt diff --git a/src/jvmMain/kotlin/mtmc/tokenizer/MTMCScanner.kt b/src/commonMain/kotlin/mtmc/tokenizer/MTMCScanner.kt similarity index 97% rename from src/jvmMain/kotlin/mtmc/tokenizer/MTMCScanner.kt rename to src/commonMain/kotlin/mtmc/tokenizer/MTMCScanner.kt index 27c4fae..171f2d1 100644 --- a/src/jvmMain/kotlin/mtmc/tokenizer/MTMCScanner.kt +++ b/src/commonMain/kotlin/mtmc/tokenizer/MTMCScanner.kt @@ -1,14 +1,16 @@ package mtmc.tokenizer -import java.util.* +fun Char.isHexDigit(): Boolean { + return this in '0'..'9' || this in 'a'..'f' || this in 'A'..'F' +} class MTMCScanner(private val src: String, private val lineCommentStart: String) { var position: Int = 0 var line: Int = 1 var lineOffset: Int = 0 - var tokens: LinkedList = LinkedList() + var tokens = mutableListOf() - fun tokenize(): LinkedList { + fun tokenize(): MutableList { consumeWhitespace() while (!scanEnd()) { scanToken() @@ -38,7 +40,7 @@ class MTMCScanner(private val src: String, private val lineCommentStart: String) } private fun scanLineComment(): Boolean { - val bytes = lineCommentStart.toByteArray() + val bytes = lineCommentStart.encodeToByteArray() for (i in bytes.indices) { val aChar = bytes[i] if (peek(i).code.toByte() != aChar) { @@ -188,7 +190,7 @@ class MTMCScanner(private val src: String, private val lineCommentStart: String) private fun scanHex(start: Int): Boolean { takeChar() // take leading zero takeChar() // take 'x' - while (HexFormat.isHexDigit(peek().code)) { + while (peek().isHexDigit()) { takeChar() } tokens.add(makeToken(MTMCToken.TokenType.HEX, strValueFrom(start), start)) diff --git a/src/jvmMain/kotlin/mtmc/tokenizer/MTMCToken.kt b/src/commonMain/kotlin/mtmc/tokenizer/MTMCToken.kt similarity index 92% rename from src/jvmMain/kotlin/mtmc/tokenizer/MTMCToken.kt rename to src/commonMain/kotlin/mtmc/tokenizer/MTMCToken.kt index 35efb74..e3f4f2f 100644 --- a/src/jvmMain/kotlin/mtmc/tokenizer/MTMCToken.kt +++ b/src/commonMain/kotlin/mtmc/tokenizer/MTMCToken.kt @@ -1,13 +1,12 @@ package mtmc.tokenizer -@JvmRecord data class MTMCToken( - @JvmField val start: Int, - @JvmField val end: Int, + val start: Int, + val end: Int, val line: Int, val lineOffset: Int, - @JvmField val stringValue: String, - @JvmField val type: TokenType? + val stringValue: String, + val type: TokenType? ) { override fun toString(): String { return stringValue diff --git a/src/jvmMain/kotlin/mtmc/tokenizer/MTMCTokenizer.kt b/src/commonMain/kotlin/mtmc/tokenizer/MTMCTokenizer.kt similarity index 90% rename from src/jvmMain/kotlin/mtmc/tokenizer/MTMCTokenizer.kt rename to src/commonMain/kotlin/mtmc/tokenizer/MTMCTokenizer.kt index 575a7cc..0911056 100644 --- a/src/jvmMain/kotlin/mtmc/tokenizer/MTMCTokenizer.kt +++ b/src/commonMain/kotlin/mtmc/tokenizer/MTMCTokenizer.kt @@ -1,11 +1,10 @@ package mtmc.tokenizer -import java.util.* -import java.util.stream.Stream +import mtmc.util.Runnable import kotlin.math.max class MTMCTokenizer(var source: String, lineCommentStart: String) { - var tokens: LinkedList = MTMCScanner(source, lineCommentStart).tokenize() + var tokens: MutableList = MTMCScanner(source, lineCommentStart).tokenize() var currentToken: Int = 0 fun currentToken(): MTMCToken { @@ -59,10 +58,6 @@ class MTMCTokenizer(var source: String, lineCommentStart: String) { return tokens.get(max(0, currentToken - 1)) } - fun stream(): Stream { - return tokens.stream() - } - override fun toString(): String { val sb = StringBuilder() for (i in tokens.indices) { @@ -104,7 +99,7 @@ class MTMCTokenizer(var source: String, lineCommentStart: String) { if (match(tokenType)) { return consume() } else { - notFound.run() + notFound.invoke() return null } } diff --git a/src/jvmMain/kotlin/mtmc/util/BinaryUtils.kt b/src/commonMain/kotlin/mtmc/util/BinaryUtils.kt similarity index 71% rename from src/jvmMain/kotlin/mtmc/util/BinaryUtils.kt rename to src/commonMain/kotlin/mtmc/util/BinaryUtils.kt index 01745ee..abb18dd 100644 --- a/src/jvmMain/kotlin/mtmc/util/BinaryUtils.kt +++ b/src/commonMain/kotlin/mtmc/util/BinaryUtils.kt @@ -22,27 +22,21 @@ object BinaryUtils { } fun toBinary(aByte: Byte): String { - val binaryString = Integer.toBinaryString(aByte.toInt()) - val formatted = String.format("%8s", binaryString) - val zeroed = formatted.replace(" ".toRegex(), "0") + val zeroed = aByte.toInt().toString(2).padStart(8, '0') val underScored = zeroed.replace("....".toRegex(), "$0_") val noTrailingUnderscore = underScored.substring(0, underScored.length - 1) return "0b" + noTrailingUnderscore } fun toBinary(aShort: Short): String { - val binaryString = Integer.toBinaryString(aShort.toInt()) - val formatted = String.format("%16s", binaryString) - val zeroed = formatted.replace(" ".toRegex(), "0") + val zeroed = aShort.toInt().toString(2).padStart(16, '0') val underScored = zeroed.replace("....".toRegex(), "$0_") val noTrailingUnderscore = underScored.substring(0, underScored.length - 1) return "0b" + noTrailingUnderscore } fun toBinary(anInt: Int): String { - val binaryString = Integer.toBinaryString(anInt) - val formatted = String.format("%32s", binaryString) - val zeroed = formatted.replace(" ".toRegex(), "0") + val zeroed = anInt.toString(2).padStart(32, '0') val underScored = zeroed.replace("....".toRegex(), "$0_") val noTrailingUnderscore = underScored.substring(0, underScored.length - 1) return "0b" + noTrailingUnderscore diff --git a/src/commonMain/kotlin/mtmc/util/PlatformSpecific.kt b/src/commonMain/kotlin/mtmc/util/PlatformSpecific.kt new file mode 100644 index 0000000..eb0a634 --- /dev/null +++ b/src/commonMain/kotlin/mtmc/util/PlatformSpecific.kt @@ -0,0 +1,3 @@ +package mtmc.util + +expect fun currentTimeMillis(): Long \ No newline at end of file diff --git a/src/commonMain/kotlin/mtmc/util/Runnable.kt b/src/commonMain/kotlin/mtmc/util/Runnable.kt new file mode 100644 index 0000000..4a7ff90 --- /dev/null +++ b/src/commonMain/kotlin/mtmc/util/Runnable.kt @@ -0,0 +1,3 @@ +package mtmc.util + +typealias Runnable = () -> Unit \ No newline at end of file diff --git a/src/jsMain/kotlin/mtmc/util/PlatformSpecific.js.kt b/src/jsMain/kotlin/mtmc/util/PlatformSpecific.js.kt new file mode 100644 index 0000000..8d0587b --- /dev/null +++ b/src/jsMain/kotlin/mtmc/util/PlatformSpecific.js.kt @@ -0,0 +1,5 @@ +package mtmc.util + +import kotlin.js.Date + +actual fun currentTimeMillis(): Long = Date().getTime().toLong() diff --git a/src/jvmMain/kotlin/mtmc/lang/CompilationException.java b/src/jvmMain/java/mtmc/lang/CompilationException.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/CompilationException.java rename to src/jvmMain/java/mtmc/lang/CompilationException.java diff --git a/src/jvmMain/kotlin/mtmc/lang/Language.java b/src/jvmMain/java/mtmc/lang/Language.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/Language.java rename to src/jvmMain/java/mtmc/lang/Language.java diff --git a/src/jvmMain/kotlin/mtmc/lang/Location.java b/src/jvmMain/java/mtmc/lang/Location.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/Location.java rename to src/jvmMain/java/mtmc/lang/Location.java diff --git a/src/jvmMain/kotlin/mtmc/lang/ParseException.java b/src/jvmMain/java/mtmc/lang/ParseException.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/ParseException.java rename to src/jvmMain/java/mtmc/lang/ParseException.java diff --git a/src/jvmMain/kotlin/mtmc/lang/Span.java b/src/jvmMain/java/mtmc/lang/Span.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/Span.java rename to src/jvmMain/java/mtmc/lang/Span.java diff --git a/src/jvmMain/kotlin/mtmc/lang/Token.java b/src/jvmMain/java/mtmc/lang/Token.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/Token.java rename to src/jvmMain/java/mtmc/lang/Token.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/SeaCompiler.java b/src/jvmMain/java/mtmc/lang/sea/SeaCompiler.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/SeaCompiler.java rename to src/jvmMain/java/mtmc/lang/sea/SeaCompiler.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/SeaLanguage.java b/src/jvmMain/java/mtmc/lang/sea/SeaLanguage.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/SeaLanguage.java rename to src/jvmMain/java/mtmc/lang/sea/SeaLanguage.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/SeaParser.java b/src/jvmMain/java/mtmc/lang/sea/SeaParser.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/SeaParser.java rename to src/jvmMain/java/mtmc/lang/sea/SeaParser.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/SeaType.java b/src/jvmMain/java/mtmc/lang/sea/SeaType.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/SeaType.java rename to src/jvmMain/java/mtmc/lang/sea/SeaType.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/Symbol.java b/src/jvmMain/java/mtmc/lang/sea/Symbol.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/Symbol.java rename to src/jvmMain/java/mtmc/lang/sea/Symbol.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/Token.java b/src/jvmMain/java/mtmc/lang/sea/Token.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/Token.java rename to src/jvmMain/java/mtmc/lang/sea/Token.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/Ast.java b/src/jvmMain/java/mtmc/lang/sea/ast/Ast.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/Ast.java rename to src/jvmMain/java/mtmc/lang/sea/ast/Ast.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/Declaration.java b/src/jvmMain/java/mtmc/lang/sea/ast/Declaration.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/Declaration.java rename to src/jvmMain/java/mtmc/lang/sea/ast/Declaration.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/DeclarationFunc.java b/src/jvmMain/java/mtmc/lang/sea/ast/DeclarationFunc.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/DeclarationFunc.java rename to src/jvmMain/java/mtmc/lang/sea/ast/DeclarationFunc.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/DeclarationStruct.java b/src/jvmMain/java/mtmc/lang/sea/ast/DeclarationStruct.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/DeclarationStruct.java rename to src/jvmMain/java/mtmc/lang/sea/ast/DeclarationStruct.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/DeclarationSyntaxError.java b/src/jvmMain/java/mtmc/lang/sea/ast/DeclarationSyntaxError.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/DeclarationSyntaxError.java rename to src/jvmMain/java/mtmc/lang/sea/ast/DeclarationSyntaxError.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/DeclarationTypedef.java b/src/jvmMain/java/mtmc/lang/sea/ast/DeclarationTypedef.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/DeclarationTypedef.java rename to src/jvmMain/java/mtmc/lang/sea/ast/DeclarationTypedef.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/DeclarationVar.java b/src/jvmMain/java/mtmc/lang/sea/ast/DeclarationVar.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/DeclarationVar.java rename to src/jvmMain/java/mtmc/lang/sea/ast/DeclarationVar.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/Error.java b/src/jvmMain/java/mtmc/lang/sea/ast/Error.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/Error.java rename to src/jvmMain/java/mtmc/lang/sea/ast/Error.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/Expression.java b/src/jvmMain/java/mtmc/lang/sea/ast/Expression.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/Expression.java rename to src/jvmMain/java/mtmc/lang/sea/ast/Expression.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionAccess.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionAccess.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionAccess.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionAccess.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionBin.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionBin.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionBin.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionBin.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionCall.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionCall.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionCall.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionCall.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionCast.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionCast.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionCast.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionCast.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionChar.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionChar.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionChar.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionChar.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionIdent.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionIdent.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionIdent.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionIdent.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionIndex.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionIndex.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionIndex.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionIndex.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionInitializer.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionInitializer.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionInitializer.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionInitializer.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionInteger.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionInteger.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionInteger.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionInteger.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionParens.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionParens.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionParens.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionParens.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionPostfix.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionPostfix.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionPostfix.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionPostfix.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionPrefix.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionPrefix.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionPrefix.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionPrefix.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionString.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionString.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionString.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionString.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionSyntaxError.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionSyntaxError.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionSyntaxError.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionSyntaxError.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionTernary.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionTernary.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionTernary.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionTernary.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionTypeError.java b/src/jvmMain/java/mtmc/lang/sea/ast/ExpressionTypeError.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/ExpressionTypeError.java rename to src/jvmMain/java/mtmc/lang/sea/ast/ExpressionTypeError.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/Statement.java b/src/jvmMain/java/mtmc/lang/sea/ast/Statement.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/Statement.java rename to src/jvmMain/java/mtmc/lang/sea/ast/Statement.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementBlock.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementBlock.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementBlock.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementBlock.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementBreak.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementBreak.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementBreak.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementBreak.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementContinue.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementContinue.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementContinue.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementContinue.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementDoWhile.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementDoWhile.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementDoWhile.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementDoWhile.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementExpression.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementExpression.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementExpression.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementExpression.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementFor.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementFor.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementFor.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementFor.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementGoto.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementGoto.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementGoto.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementGoto.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementIf.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementIf.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementIf.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementIf.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementReturn.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementReturn.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementReturn.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementReturn.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementSyntaxError.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementSyntaxError.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementSyntaxError.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementSyntaxError.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementVar.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementVar.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementVar.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementVar.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementWhile.java b/src/jvmMain/java/mtmc/lang/sea/ast/StatementWhile.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/StatementWhile.java rename to src/jvmMain/java/mtmc/lang/sea/ast/StatementWhile.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/SyntaxError.java b/src/jvmMain/java/mtmc/lang/sea/ast/SyntaxError.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/SyntaxError.java rename to src/jvmMain/java/mtmc/lang/sea/ast/SyntaxError.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeDeclaration.java b/src/jvmMain/java/mtmc/lang/sea/ast/TypeDeclaration.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeDeclaration.java rename to src/jvmMain/java/mtmc/lang/sea/ast/TypeDeclaration.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExpr.java b/src/jvmMain/java/mtmc/lang/sea/ast/TypeExpr.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExpr.java rename to src/jvmMain/java/mtmc/lang/sea/ast/TypeExpr.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExprArray.java b/src/jvmMain/java/mtmc/lang/sea/ast/TypeExprArray.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExprArray.java rename to src/jvmMain/java/mtmc/lang/sea/ast/TypeExprArray.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExprChar.java b/src/jvmMain/java/mtmc/lang/sea/ast/TypeExprChar.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExprChar.java rename to src/jvmMain/java/mtmc/lang/sea/ast/TypeExprChar.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExprInt.java b/src/jvmMain/java/mtmc/lang/sea/ast/TypeExprInt.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExprInt.java rename to src/jvmMain/java/mtmc/lang/sea/ast/TypeExprInt.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExprRef.java b/src/jvmMain/java/mtmc/lang/sea/ast/TypeExprRef.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExprRef.java rename to src/jvmMain/java/mtmc/lang/sea/ast/TypeExprRef.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExprVoid.java b/src/jvmMain/java/mtmc/lang/sea/ast/TypeExprVoid.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/TypeExprVoid.java rename to src/jvmMain/java/mtmc/lang/sea/ast/TypeExprVoid.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/TypePointer.java b/src/jvmMain/java/mtmc/lang/sea/ast/TypePointer.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/TypePointer.java rename to src/jvmMain/java/mtmc/lang/sea/ast/TypePointer.java diff --git a/src/jvmMain/kotlin/mtmc/lang/sea/ast/Unit.java b/src/jvmMain/java/mtmc/lang/sea/ast/Unit.java similarity index 100% rename from src/jvmMain/kotlin/mtmc/lang/sea/ast/Unit.java rename to src/jvmMain/java/mtmc/lang/sea/ast/Unit.java diff --git a/src/jvmMain/kotlin/mtmc/asm/graphics/Graphic.kt b/src/jvmMain/kotlin/mtmc/asm/graphics/Graphic.kt deleted file mode 100644 index 34adc22..0000000 --- a/src/jvmMain/kotlin/mtmc/asm/graphics/Graphic.kt +++ /dev/null @@ -1,51 +0,0 @@ -package mtmc.asm.graphics - -import mtmc.asm.ASMElement -import mtmc.emulator.MTMCDisplay.Companion.convertImage -import mtmc.tokenizer.MTMCToken -import java.io.ByteArrayOutputStream -import java.io.File -import java.io.FileNotFoundException -import java.io.IOException -import javax.imageio.ImageIO - -/** - * - * @author jbanes - */ -class Graphic(labels: MutableList, lineNumber: Int) : ASMElement(labels, lineNumber) { - private var filename: String? = null - var imageData: ByteArray = ByteArray(0) - - fun setImage(filename: String) { - try { - var image = ImageIO.read(File(filename)) - val buffer = ByteArrayOutputStream() - - if (image.getWidth() > 1024 || image.getHeight() > 1024) { - addError(filename + " is too large. Maximum image size is 1024x1024") - } - - image = convertImage(image) - - ImageIO.write(image, "png", buffer) - - this.filename = filename - this.imageData = buffer.toByteArray() - } catch (e: FileNotFoundException) { - e.printStackTrace() - addError("$filename not found") - } catch (e: IOException) { - e.printStackTrace() - addError(e.message ?: "error in Graphic") // TODO: Verify these messages are meaningful - } - } - - override fun addError(err: String) { - addError(labels.last(), err) - } - - override var sizeInBytes: Int - get() = 2 - set(value) {} -} diff --git a/src/jvmMain/kotlin/mtmc/emulator/DebugInfo.kt b/src/jvmMain/kotlin/mtmc/emulator/DebugInfo.kt deleted file mode 100644 index e40ec01..0000000 --- a/src/jvmMain/kotlin/mtmc/emulator/DebugInfo.kt +++ /dev/null @@ -1,45 +0,0 @@ -package mtmc.emulator - -import java.util.* -import java.util.regex.Pattern - -@JvmRecord -data class DebugInfo( - val debugStrings: MutableList, - val assemblyFile: String?, - val assemblySource: String, - val assemblyLineNumbers: IntArray, - val originalFile: String, - val originalLineNumbers: IntArray, - val globals: Array, - val locals: Array> -) { - fun handleDebugString(debugIndex: Short, monTanaMiniComputer: MonTanaMiniComputer) { - val debugString = debugStrings!!.get(debugIndex.toInt()) - val compile = Pattern.compile("(\\$[a-zA-Z][a-zA-Z0-9])") - val matcher = compile.matcher(debugString) - val formattedString = StringBuilder() - var start = 0 - var end: Int - while (matcher.find()) { - val match = matcher.group().substring(1) - try { - end = matcher.start() - formattedString.append(debugString, start, end) - val register = Register.valueOf(match.uppercase(Locale.getDefault())) - formattedString.append(monTanaMiniComputer.getRegisterValue(register).toInt()) - start = matcher.end() - } catch (e: Exception) { - formattedString.append(match) - } - } - formattedString.append(debugString.substring(start)) - println("DEBUG[" + System.nanoTime() + "] : " + formattedString) - } - - @JvmRecord - data class GlobalInfo(val name: String?, val location: Int, val type: String?) - - @JvmRecord - data class LocalInfo(val name: String?, val offset: Int, val type: String?) -} \ No newline at end of file diff --git a/src/jvmMain/kotlin/mtmc/os/exec/Executable.kt b/src/jvmMain/kotlin/mtmc/os/exec/Executable.kt deleted file mode 100644 index 61b370e..0000000 --- a/src/jvmMain/kotlin/mtmc/os/exec/Executable.kt +++ /dev/null @@ -1,60 +0,0 @@ -package mtmc.os.exec - -import com.google.gson.Gson -import mtmc.emulator.DebugInfo -import java.io.FileReader -import java.io.FileWriter -import java.io.IOException -import java.io.Reader -import java.io.Writer -import java.nio.file.Path - -@JvmRecord -data class Executable( - val format: Format, - @JvmField val code: ByteArray, - @JvmField val data: ByteArray, - @JvmField val graphics: Array, - val sourceName: String, - @JvmField val debugInfo: DebugInfo? -) { - enum class Format(val formatName: String) { - Orc1("orc1"); - } - - fun dump(): String? { - return Gson().toJson(this) - } - - @Throws(IOException::class) - fun dump(path: Path) { - FileWriter(path.toFile()).use { fw -> - dump(fw) - } - } - - fun dump(writer: Writer?) { - val gson = Gson() - gson.toJson(this, writer) - } - - companion object { - fun load(exe: String?): Executable? { - return Gson().fromJson(exe, Executable::class.java) - } - - @JvmStatic - @Throws(IOException::class) - fun load(path: Path): Executable? { - FileReader(path.toFile()).use { fw -> - return load(fw) - } - } - - @Throws(IOException::class) - fun load(reader: Reader): Executable? { - val gson = Gson() - return gson.fromJson(reader, Executable::class.java) - } - } -} diff --git a/src/jvmMain/kotlin/mtmc/os/fs/FileSystem.java b/src/jvmMain/kotlin/mtmc/os/fs/FileSystem.java deleted file mode 100644 index 27a0c54..0000000 --- a/src/jvmMain/kotlin/mtmc/os/fs/FileSystem.java +++ /dev/null @@ -1,199 +0,0 @@ -package mtmc.os.fs; - -import mtmc.emulator.MonTanaMiniComputer; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -public class FileSystem { - private String cwd = "/home"; - private MonTanaMiniComputer computer; - static final Path DISK_PATH = Path.of(System.getProperty("user.dir"), "disk").toAbsolutePath(); - - public FileSystem(MonTanaMiniComputer computer) { - this.computer = computer; - - initFileSystem(); - } - - private void initFileSystem() { - if (DISK_PATH.toFile().exists()) return; - - // Make the disk/ directory - DISK_PATH.toFile().mkdirs(); - - try (var in = new ZipInputStream(getClass().getResourceAsStream("/disk.zip"))) { - ZipEntry entry; - File file; - - byte[] data = new byte[4096]; - int count; - - while ((entry = in.getNextEntry()) != null) { - file = new File(entry.getName()); - - if (entry.isDirectory()) { - file.mkdirs(); - } else { - file.getParentFile().mkdirs(); - - try (var out = new FileOutputStream(file)) { - while((count = in.read(data)) > 0) { - out.write(data, 0, count); - } - } - } - } - } catch(IOException e) { - e.printStackTrace(); - } - } - - private void notifyOfFileSystemUpdate() { - if (this.computer != null) { - computer.notifyOfFileSystemUpdate(); - } - } - - public String getCWD() { - return this.cwd; - } - - public void setCWD(String cwd) { - this.cwd = resolve(cwd); - this.notifyOfFileSystemUpdate(); - } - - public boolean exists(String path) { - return new File(DISK_PATH.toFile(), resolve(path)).exists(); - } - - public boolean mkdir(String path) { - boolean success = new File(DISK_PATH.toFile(), resolve(path)).mkdir(); - - if (success) { - computer.notifyOfFileSystemUpdate(); - } - - return success; - } - - public boolean delete(String path) { - boolean success = new File(DISK_PATH.toFile(), resolve(path)).delete(); - - if (success) { - computer.notifyOfFileSystemUpdate(); - } - - return success; - } - - public String resolve(String filename) { - File root = DISK_PATH.toFile(); - File directory = filename.startsWith("/") ? root : new File(root, cwd); - String[] path = filename.split("/"); - - for (String name : path) { - if (name.equals(".")) { - continue; - } else if (name.equals("..") && directory.equals(root)) { - continue; - } else if (name.equals("..")) { - directory = directory.getParentFile(); - } else { - directory = new File(directory, name); - } - } - - if(directory.equals(root)) { - return "/"; - } - - return directory.getAbsolutePath().substring(root.getAbsolutePath().length()); - } - - public Path getRealPath(String path) { // Resolves given path and returns /disk/ + path - String resolvedPath = resolve(path); - String slashGone = resolvedPath.length() > 0 ? resolvedPath.substring(1) : ""; - File file = DISK_PATH.resolve(slashGone).toFile(); - - if (file.getAbsolutePath().length() < DISK_PATH.toFile().getAbsolutePath().length()) { - return DISK_PATH; - } - - return file.toPath(); - } - - public File[] getFileList(String path) { - File resolvedPath = getRealPath(path).toFile(); - - if (!resolvedPath.isDirectory()) return new File[]{ resolvedPath }; - - return resolvedPath.listFiles(); - } - - public Listing listFiles(String path) { - File resolvedPath = getRealPath(path).toFile(); - - return new Listing(this, resolvedPath); - } - - public Listing listCWD() { - return listFiles(cwd); - } - - public Listing listRoot() { - return listFiles("/"); - } - - public void writeFile(String path, String contents) throws IOException { - Path filePath = getRealPath(path); - Files.writeString(filePath, contents); - } - - public String readFile(String path) throws FileNotFoundException, IOException { - Path filePath = getRealPath(path); - var contents = Files.readString(filePath); - return contents; - } - - public String getMimeType(String path) throws IOException { - var file = getRealPath(path); - var name = file.toFile().getName().toLowerCase(); - var probed = Files.probeContentType(file); - - if(name.endsWith(".asm")) return "text/x-asm"; - if(name.endsWith(".c")) return "text/x-csrc"; - if(name.endsWith(".sea")) return "text/x-csrc"; - if(name.endsWith(".h")) return "text/x-csrc"; - if(probed != null) return probed; - - return "application/octet-stream"; - } - - public InputStream openFile(String path) throws IOException { - var file = getRealPath(path).toFile(); - - return new FileInputStream(file); - } - - public void saveFile(String path, InputStream contents) throws IOException { - var file = getRealPath(path).toFile(); - byte[] data = new byte[4096]; - int count; - - try(var out = new FileOutputStream(file)) { - while((count = contents.read(data)) > 0) { - out.write(data, 0, count); - } - } - } -} \ No newline at end of file diff --git a/src/jvmMain/kotlin/mtmc/os/fs/Listing.java b/src/jvmMain/kotlin/mtmc/os/fs/Listing.java deleted file mode 100644 index c2af8c5..0000000 --- a/src/jvmMain/kotlin/mtmc/os/fs/Listing.java +++ /dev/null @@ -1,52 +0,0 @@ -package mtmc.os.fs; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class Listing { - public final String path; - public final String name; - public final boolean directory; - public final boolean root; - - private FileSystem fs; - private File file; - - public Listing(FileSystem fs, File file) { - String root = FileSystem.DISK_PATH.toFile().getAbsolutePath().replace('\\', '/'); - String path = file.getAbsolutePath().substring(root.length()).replace('\\', '/'); - - this.fs = fs; - this.file = file; - - this.path = path.length() > 0 ? path : "/"; - this.name = path.length() > 0 ? file.getName() : "/"; - this.directory = file.isDirectory(); - this.root = this.path.equals("/"); - } - - public Listing getParent() { - return new Listing(fs, file.getParentFile()); - } - - public List list() { - if (!directory) { - return new ArrayList<>(); - } - - var list = new ArrayList(); - var children = file.listFiles(); - - Arrays.sort(children, (a, b) -> { - return a.getName().compareTo(b.getName()); - }); - - for (File child : children) { - list.add(new Listing(fs, child)); - } - - return list; - } -} diff --git a/src/jvmMain/kotlin/mtmc/os/shell/builtins/AssembleCommand.kt b/src/jvmMain/kotlin/mtmc/os/shell/builtins/AssembleCommand.kt deleted file mode 100644 index 007cdd4..0000000 --- a/src/jvmMain/kotlin/mtmc/os/shell/builtins/AssembleCommand.kt +++ /dev/null @@ -1,45 +0,0 @@ -package mtmc.os.shell.builtins - -import mtmc.asm.Assembler -import mtmc.emulator.MonTanaMiniComputer -import mtmc.os.fs.FileSystem -import mtmc.os.shell.ShellCommand -import mtmc.tokenizer.MTMCTokenizer -import java.nio.file.Files -import java.nio.file.Path - -class AssembleCommand : ShellCommand() { - @Throws(Exception::class) - public override fun exec(tokens: MTMCTokenizer, computer: MonTanaMiniComputer) { - val fs = computer.fileSystem - val src = tokens.collapseTokensAsString() - require(!(src == null || src.isBlank())) { "missing or required argument 'src'" } - val srcPath: Path = getDiskPath(src, fs) - - val dst = tokens.collapseTokensAsString() - require(!(dst == null || dst.isBlank())) { "missing required argument 'dst'" } - val dstPath: Path = getDiskPath(dst, fs) - - val contents = Files.readString(srcPath) - val assembler = Assembler() - val file_name = - fs.resolve(src) // srcPath.toString().substring(DISK_PATH.toString().length()).replaceAll("\\\\", "/"); - val executable = assembler.assembleExecutable(file_name, contents) - executable.dump(dstPath) - computer.notifyOfFileSystemUpdate() - } - - override val help: String - get() = """ - asm - - src : path to a .asm file - - dst : path to a target output binary - """.trimIndent() - - companion object { - fun getDiskPath(pathString: String, fs: FileSystem): Path { - val path = Path.of("disk" + fs.resolve(pathString)) - return path.toAbsolutePath() - } - } -} diff --git a/src/jvmMain/kotlin/mtmc/util/PlatformSpecific.jvm.kt b/src/jvmMain/kotlin/mtmc/util/PlatformSpecific.jvm.kt new file mode 100644 index 0000000..841f842 --- /dev/null +++ b/src/jvmMain/kotlin/mtmc/util/PlatformSpecific.jvm.kt @@ -0,0 +1,3 @@ +package mtmc.util + +actual fun currentTimeMillis(): Long = System.currentTimeMillis() \ No newline at end of file diff --git a/src/jvmMain/kotlin/mtmc/util/SafeClosable.kt b/src/jvmMain/kotlin/mtmc/util/SafeClosable.kt index d5aa578..34dfad4 100644 --- a/src/jvmMain/kotlin/mtmc/util/SafeClosable.kt +++ b/src/jvmMain/kotlin/mtmc/util/SafeClosable.kt @@ -4,4 +4,4 @@ import java.io.Closeable interface SafeClosable : Closeable { override fun close() -} +} \ No newline at end of file diff --git a/src/jvmMain/kotlin/mtmc/util/StringEscapeUtils.kt b/src/jvmMain/kotlin/mtmc/util/StringEscapeUtils.kt index 8413e79..6e43908 100644 --- a/src/jvmMain/kotlin/mtmc/util/StringEscapeUtils.kt +++ b/src/jvmMain/kotlin/mtmc/util/StringEscapeUtils.kt @@ -28,4 +28,4 @@ object StringEscapeUtils { out.append('"') return out.toString() } -} +} \ No newline at end of file