decide sim is not worth it-remove it again

This commit is contained in:
Irmen de Jong 2022-03-09 22:44:43 +01:00
parent 61398ee8f8
commit 240e6835c2
16 changed files with 0 additions and 800 deletions

View File

@ -14,7 +14,6 @@
<module fileurl="file://$PROJECT_DIR$/examples/examples.iml" filepath="$PROJECT_DIR$/examples/examples.iml" />
<module fileurl="file://$PROJECT_DIR$/httpCompilerService/httpCompilerService.iml" filepath="$PROJECT_DIR$/httpCompilerService/httpCompilerService.iml" />
<module fileurl="file://$PROJECT_DIR$/parser/parser.iml" filepath="$PROJECT_DIR$/parser/parser.iml" />
<module fileurl="file://$PROJECT_DIR$/simulator/simulator.iml" filepath="$PROJECT_DIR$/simulator/simulator.iml" />
</modules>
</component>
</project>

View File

@ -26,7 +26,6 @@ compileTestKotlin {
dependencies {
implementation project(':compilerInterfaces')
implementation project(':compilerAst')
implementation project(':simulator')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "com.michael-bull.kotlin-result:kotlin-result-jvm:1.1.14"

View File

@ -12,6 +12,5 @@
<orderEntry type="module" module-name="compilerAst" />
<orderEntry type="module" module-name="compilerInterfaces" />
<orderEntry type="library" name="michael.bull.kotlin.result.jvm" level="project" />
<orderEntry type="module" module-name="simulator" />
</component>
</module>

View File

@ -2,7 +2,6 @@ package prog8.codegen.experimental6502
import prog8.ast.Program
import prog8.compilerinterface.*
import prog8.sim.Simulator
class AsmGen(internal val program: Program,
internal val errors: IErrorReporter,
@ -20,9 +19,6 @@ class AsmGen(internal val program: Program,
val intermediateAst = IntermediateAstMaker(program).transform()
intermediateAst.print()
val sim = Simulator(intermediateAst, symbolTable)
sim.run()
println("..todo: create assembly code into ${options.outputDir.toAbsolutePath()}..")
return AssemblyProgram("dummy")
}

View File

@ -7,7 +7,6 @@ include(
':codeGenCpu6502',
':codeGenExperimental6502',
':compiler',
':simulator',
':dbusCompilerService',
':httpCompilerService'
)

View File

@ -1,73 +0,0 @@
plugins {
id 'java'
id 'application'
id "org.jetbrains.kotlin.jvm"
id "io.kotest" version "0.3.9"
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(javaVersion)
}
}
compileKotlin {
kotlinOptions {
jvmTarget = javaVersion
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = javaVersion
}
}
dependencies {
implementation project(':compilerInterfaces')
implementation project(':compilerAst')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation 'org.jetbrains.kotlinx:kotlinx-cli:0.3.4'
implementation "com.michael-bull.kotlin-result:kotlin-result-jvm:1.1.14"
testImplementation 'io.kotest:kotest-runner-junit5-jvm:5.1.0'
}
sourceSets {
main {
java {
srcDirs = ["${project.projectDir}/src"]
}
resources {
srcDirs = ["${project.projectDir}/res"]
}
}
test {
java {
srcDir "${project.projectDir}/test"
}
}
}
startScripts.enabled = true
application {
mainClass = 'prog8.SimulatorMainKt'
applicationName = 'p8sim'
}
test {
// Enable JUnit 5 (Gradle 4.6+).
useJUnitPlatform()
// Always run tests, even when nothing changed.
dependsOn 'cleanTest'
// Show test results.
testLogging {
events "skipped", "failed"
}
}
build.finalizedBy installDist

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
<orderEntry type="module" module-name="compilerInterfaces" />
<orderEntry type="library" name="michael.bull.kotlin.result.jvm" level="project" />
<orderEntry type="library" name="io.kotest.runner.junit5.jvm" level="project" />
<orderEntry type="library" name="io.kotest.assertions.core.jvm" level="project" />
<orderEntry type="module" module-name="compilerAst" />
</component>
</module>

View File

@ -1,45 +0,0 @@
package prog8
import prog8.ast.base.DataType
import prog8.ast.base.Position
import prog8.ast.statements.AssignmentOrigin
import prog8.compilerinterface.Encoding
import prog8.compilerinterface.SymbolTable
import prog8.compilerinterface.intermediate.*
import prog8.sim.MemSizer
import prog8.sim.Simulator
import prog8.sim.StringEncoding
fun main(args: Array<String>) {
println("\nProg8 simulator by Irmen de Jong (irmen@razorvine.net)")
println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
println("...todo: run from file...")
val program = PtProgram("test", MemSizer, StringEncoding)
val module = PtModule("test", 0u, false, Position.DUMMY)
val block = PtBlock("main", null, false, Position.DUMMY)
val sub = PtSub("start", emptyList(), emptyList(), false, Position.DUMMY)
block.add(sub)
module.add(block)
program.add(module)
val fcall = PtBuiltinFunctionCall("print", Position.DUMMY).also {
it.add(PtString("Hello, world! From the program.\n", Encoding.DEFAULT, Position.DUMMY))
}
sub.add(fcall)
val memwrite = PtAssignment(false, AssignmentOrigin.USERCODE, Position.DUMMY).also { assign ->
assign.add(PtAssignTarget(Position.DUMMY).also { tgt ->
tgt.add(PtMemoryByte(Position.DUMMY).also { mb ->
mb.add(PtNumber(DataType.UWORD, 1000.0, Position.DUMMY))
})
})
assign.add(PtNumber(DataType.UBYTE, 99.0, Position.DUMMY))
}
sub.add(memwrite)
sub.add(PtReturn(Position.DUMMY))
val symboltable = SymbolTable()
val sim = Simulator(program, symboltable)
println("memory at $1000=${sim.memory[1000u]}")
sim.run()
println("memory at $1000=${sim.memory[1000u]}")
}

View File

@ -1,43 +0,0 @@
package prog8.sim
import prog8.ast.base.*
import prog8.ast.expressions.StringLiteral
import prog8.ast.statements.VarDecl
import prog8.compilerinterface.Encoding
import prog8.compilerinterface.IMemSizer
import prog8.compilerinterface.IStringEncoding
internal object MemSizer: IMemSizer {
override fun memorySize(dt: DataType): Int {
return when(dt) {
in ByteDatatypes -> 1
in WordDatatypes, in PassByReferenceDatatypes -> 2
DataType.FLOAT -> Double.SIZE_BYTES
else -> Int.MIN_VALUE
}
}
override fun memorySize(decl: VarDecl): Int {
return when(decl.type) {
VarDeclType.CONST -> 0
VarDeclType.VAR, VarDeclType.MEMORY -> {
when(val dt = decl.datatype) {
in NumericDatatypes -> return memorySize(dt)
in ArrayDatatypes -> decl.arraysize!!.constIndex()!! * memorySize(ArrayToElementTypes.getValue(dt))
DataType.STR -> (decl.value as StringLiteral).value.length + 1
else -> 0
}
}
}
}
}
internal object StringEncoding: IStringEncoding {
override fun encodeString(str: String, encoding: Encoding): List<UByte> {
TODO("Not yet implemented")
}
override fun decodeString(bytes: List<UByte>, encoding: Encoding): String {
TODO("Not yet implemented")
}
}

View File

@ -1,162 +0,0 @@
package prog8.sim
import prog8.ast.base.DataType
import prog8.ast.base.PassByReferenceDatatypes
import prog8.ast.base.Position
import prog8.ast.expressions.AddressOf
import prog8.compilerinterface.Encoding
import prog8.compilerinterface.StNodeType
import prog8.compilerinterface.StStaticVariable
import prog8.compilerinterface.SymbolTable
import prog8.compilerinterface.intermediate.*
class Evaluator(
val symboltable: SymbolTable,
val memory: Memory,
val variables: Variables,
val simulator: Simulator
) {
fun evaluateExpression(expr: PtNode): Pair<Double, DataType> {
return when(expr) {
is PtAddressOf -> evaluate(expr)
is PtArrayIndexer -> evaluate(expr)
is PtArrayLiteral -> throw IllegalArgumentException("arrayliteral $expr")
is PtBinaryExpression -> evaluate(expr)
is PtBuiltinFunctionCall -> evaluate(expr)
is PtConstant -> Pair(expr.value, expr.type)
is PtContainmentCheck -> TODO()
is PtFunctionCall -> evaluate(expr)
is PtIdentifier -> evaluate(expr)
is PtMemoryByte -> evaluate(expr)
is PtNumber -> Pair(expr.number, expr.type)
is PtPipe -> TODO()
is PtPrefix -> TODO()
is PtRange -> throw IllegalArgumentException("range $expr")
is PtString -> throw IllegalArgumentException("string $expr")
is PtTypeCast -> TODO()
else -> TODO("missing evaluator for $expr")
}
}
private fun evaluate(memoryByte: PtMemoryByte): Pair<Double, DataType> {
val address = evaluateExpression(memoryByte.address).first.toUInt()
val value = memory[address]
return Pair(value.toDouble(), DataType.UBYTE)
}
private fun evaluate(arrayIdx: PtArrayIndexer): Pair<Double, DataType> {
val index = evaluateExpression(arrayIdx.index)
println("TODO: get array value ${arrayIdx.variable.ref}[${index.first.toInt()}]")
return Pair(0.0, DataType.UBYTE)
}
internal fun evaluate(expr: PtBinaryExpression): Pair<Double, DataType> {
val left = evaluateExpression(expr.left)
val right = evaluateExpression(expr.right)
require(left.second==right.second)
// TODO implement 8/16 bit maths
return when(expr.operator) {
"+" -> Pair(left.first+right.first, left.second)
"-" -> Pair(left.first-right.first, left.second)
"*" -> Pair(left.first*right.first, left.second)
"/" -> Pair(left.first/right.first, left.second)
"==" -> {
val bool = if(left.first==right.first) 1 else 0
Pair(bool.toDouble(), DataType.UBYTE)
}
"!=" -> {
val bool = if(left.first!=right.first) 1 else 0
Pair(bool.toDouble(), DataType.UBYTE)
}
"<" -> {
val bool = if(left.first<right.first) 1 else 0
Pair(bool.toDouble(), DataType.UBYTE)
}
">" -> {
val bool = if(left.first>right.first) 1 else 0
Pair(bool.toDouble(), DataType.UBYTE)
}
"<=" -> {
val bool = if(left.first<=right.first) 1 else 0
Pair(bool.toDouble(), DataType.UBYTE)
}
">=" -> {
val bool = if(left.first>=right.first) 1 else 0
Pair(bool.toDouble(), DataType.UBYTE)
}
else -> TODO("binexpr operator ${expr.operator}")
}
}
internal fun evaluate(fcall: PtFunctionCall): Pair<Double, DataType> {
val ref = fcall.target.ref
val args = fcall.args.children.map { evaluateExpression(it) }
return when(fcall.target.targetName) {
listOf("sys", "memset") -> {
memory.memset(args[0].first.toUInt(), args[1].first.toUInt(), args[2].first.toInt().toUByte())
Pair(0.0, DataType.UBYTE)
}
listOf("txt", "print") -> {
print(memory.getString(args.single().first.toUInt())) // strings are passed as a memory address
Pair(0.0, DataType.UBYTE)
}
listOf("txt", "print_uw") -> {
print(args.single().first.toUInt())
Pair(0.0, DataType.UBYTE)
}
else -> {
val node = findPtNode(fcall.target.targetName, fcall)
if(node is PtAsmSub)
throw NotImplementedError("simulator can't run asmsub ${node.name}")
node as PtSub
passCallArgs(node, args)
simulator.instructionPtrStack.push(simulator.ip)
simulator.ip = InstructionPointer(node.children)
}
}
}
internal fun evaluate(fcall: PtBuiltinFunctionCall): Pair<Double, DataType> {
println("TODO: builtin function call ${fcall.name}")
return Pair(0.0, DataType.UBYTE)
}
private fun passCallArgs(sub: PtSub, args: List<Pair<Double, DataType>>) {
require(sub.parameters.size==args.size)
for ((param, arg) in sub.parameters.zip(args)) {
require(param.type==arg.second)
println("ARG ${param.name} = ${arg.first}") // TODO assign arg
}
}
private fun evaluate(ident: PtIdentifier): Pair<Double, DataType> {
val target = symboltable.flat.getValue(ident.targetName)
when(target.type) {
StNodeType.STATICVAR -> {
val variable = target as StStaticVariable
val value = variables.getValue(variable)
if(value.number==null){
if(variable.dt in PassByReferenceDatatypes) {
// return the address instead
val addrof = PtAddressOf(ident.position)
addrof.add(PtIdentifier(ident.ref, ident.targetName, ident.position))
return evaluate(addrof)
} else
throw IllegalArgumentException("invalid dt")
}
return Pair(value.number, target.dt)
}
StNodeType.CONSTANT -> throw IllegalArgumentException("constants should have been const folded")
else -> throw IllegalArgumentException("weird ref target")
}
}
private fun evaluate(addressOf: PtAddressOf): Pair<Double, DataType> {
val target = symboltable.flat.getValue(addressOf.identifier.targetName) as StStaticVariable
return Pair(variables.getAddress(target).toDouble(), DataType.UWORD)
}
}

View File

@ -1,22 +0,0 @@
package prog8.sim
import prog8.compilerinterface.intermediate.PtNode
class InstructionPointer(var instructions: List<PtNode>, start: Int=0) {
var currentIdx = start
val current: PtNode
get() {
if(currentIdx<instructions.size)
return instructions[currentIdx]
else
throw IllegalArgumentException("expected Return statement at end of statement list")
}
init {
require(instructions.isNotEmpty())
}
fun next() {
currentIdx++
}
}

View File

@ -1,68 +0,0 @@
package prog8.sim
class Memory {
val mem = ByteArray(65536)
operator fun get(addresss: UInt): UByte = getSByte(addresss).toUByte()
operator fun set(address: UInt, value: UByte) = setSByte(address, value.toByte())
fun getSByte(address: UInt): Byte = mem[address.toInt()]
fun setSByte(address: UInt, value: Byte) {
mem[address.toInt()] = value
}
fun getSWord(address: UInt): Int {
val word = getWord(address).toInt()
return if(word>=32768)
-(65536-word)
else
word
}
fun setSWord(address: UInt, value: Int) = setWord(address, value.toUInt())
fun getWord(address: UInt): UInt {
val lsb = mem[address.toInt()].toUByte()
val msb = mem[address.toInt()+1].toUByte()
return lsb + msb*256u
}
fun setWord(address: UInt, value: UInt) {
val lsb = value.toByte()
val msb = (value shr 8).toByte()
mem[address.toInt()] = lsb
mem[address.toInt()+1] = msb
}
fun clear() {
for(i in 0..65535)
mem[i]=0
}
fun setString(address: UInt, str: String, zeroTerminate: Boolean=true) {
var addr = address.toInt()
for (it in str.toByteArray(Charsets.ISO_8859_1)) {
mem[addr] = it
addr++
}
if(zeroTerminate)
mem[addr] = 0
}
fun getString(address: UInt): String {
var addr = address.toInt()
while(mem[addr] != 0.toByte()) addr++
return String(mem, address.toInt(), addr-address.toInt(), Charsets.ISO_8859_1)
}
fun memset(address: UInt, length: UInt, value: UByte) {
var addr=address.toInt()
val byteval = value.toByte()
repeat(length.toInt()) {
mem[addr] = byteval
addr++
}
}
}

View File

@ -1,189 +0,0 @@
package prog8.sim
import prog8.ast.base.DataType
import prog8.compilerinterface.StStaticVariable
import prog8.compilerinterface.SymbolTable
import prog8.compilerinterface.intermediate.*
import java.util.*
sealed class FlowcontrolException : Exception()
class ExitProgram(val status: Int): FlowcontrolException()
class Simulator(val program: PtProgram, val symboltable: SymbolTable) {
val memory = Memory()
private val variables = Variables(symboltable)
private val eval = Evaluator(symboltable, memory, variables, this)
internal val instructionPtrStack = Stack<InstructionPointer>()
internal var ip = InstructionPointer(emptyList())
fun run() {
memory.clear()
val start = program.entrypoint() ?: throw NoSuchElementException("no main.start() found")
ip = InstructionPointer(start.children)
try {
while(true)
executeStatement(ip.current)
} catch (exit: ExitProgram) {
println("Program Exit! Status code: ${exit.status}")
}
}
internal fun executeStatement(node: PtNode) {
return when(node) {
is PtAsmSub -> throw NotImplementedError("can't run assembly subroutine in simulator at this time")
is PtAssignment -> execute(node)
is PtBuiltinFunctionCall -> {
eval.evaluate(node) // throw away any result
ip.next()
}
is PtConditionalBranch -> TODO()
is PtDirective -> execute(node)
is PtForLoop -> TODO()
is PtFunctionCall -> {
eval.evaluate(node) // throw away any result
ip.next()
}
is PtGosub -> execute(node)
is PtIfElse -> execute(node)
is PtInlineAssembly -> throw NotImplementedError("can't run inline assembly in simulator at this time")
is PtJump -> execute(node)
is PtLabel -> ip.next()
is PtPipe -> execute(node)
is PtPostIncrDecr -> execute(node)
is PtRepeatLoop -> execute(node)
is PtReturn -> execute(node)
is PtSub -> ip.next() // this simulator doesn't "fall through" into nested subroutines
is PtVariable -> ip.next()
is PtWhen -> TODO()
else -> TODO("missing code for node $node")
}
}
private fun execute(jump: PtJump) {
if(jump.address!=null)
throw NotImplementedError("simulator can't jump into memory machine code")
else if(jump.generatedLabel!=null)
throw NotImplementedError("simulator can't jump into generated label")
else {
ip = findTargetNode(jump.identifier!!.targetName)
}
}
internal fun findTargetNode(targetName: List<String>): InstructionPointer {
val target = findPtNode(targetName, ip.current)
val nodes = target.parent.children
return InstructionPointer(nodes, nodes.indexOf(target))
}
private fun execute(gosub: PtGosub) {
if(gosub.address!=null)
throw NotImplementedError("simulator can't jump into memory machine code")
else if(gosub.generatedLabel!=null)
throw NotImplementedError("simulator can't jump into generated label")
else {
instructionPtrStack.push(ip)
ip = findTargetNode(gosub.identifier!!.targetName)
}
}
private fun execute(post: PtPostIncrDecr) {
val identifier = post.target.identifier
val memoryAddr = post.target.memory
val array = post.target.array
if(identifier!=null) {
val variable = symboltable.lookup(identifier.targetName) as StStaticVariable
var value = variables.getValue(variable).number!!
if(post.operator=="++") value++ else value--
variables.setValue(variable, Variables.Value(value, null, null))
} else if(memoryAddr!=null) {
val addr = eval.evaluateExpression(memoryAddr.address).first.toUInt()
if(post.operator=="++")
memory[addr] = (memory[addr]+1u).toUByte()
else
memory[addr] = (memory[addr]-1u).toUByte()
} else if(array!=null) {
println("TODO: ${array.variable.ref}[] ${post.operator}")
}
ip.next()
}
private fun execute(ifelse: PtIfElse) {
val condition = eval.evaluateExpression(ifelse.condition)
ip = if(condition.first!=0.0) {
InstructionPointer(ifelse.ifScope.children)
} else {
InstructionPointer(ifelse.elseScope.children)
}
// TODO how to handle the exiting of the subscopes, and continue after the ifelse statement.
}
private fun execute(repeat: PtRepeatLoop) {
val count = eval.evaluateExpression(repeat.count).first.toInt()
// TODO how to handle the exiting of the subscopes, and continue after the repeat statement.
TODO("repeat $count ${repeat.position}")
ip.next()
}
private fun execute(pipe: PtPipe) {
TODO("pipe stmt $pipe")
ip.next()
}
private fun execute(ret: PtReturn) {
if(ret.hasValue) {
// TODO how to handle the actual return value
}
ip = instructionPtrStack.pop()
ip.next()
}
private fun execute(directive: PtDirective) {
// TODO handle directive
ip.next()
}
private fun execute(assign: PtAssignment) {
val value = eval.evaluateExpression(assign.value)
val identifier = assign.target.identifier
val memoryAddr = assign.target.memory
val array = assign.target.array
if(identifier!=null) {
val targetvar = symboltable.flat.getValue(identifier.targetName) as StStaticVariable
variables.setValue(targetvar, Variables.Value(value.first, null, null))
}
else if(memoryAddr!=null) {
val address = eval.evaluateExpression(memoryAddr.address)
require(address.second==DataType.UWORD)
require(value.second==DataType.UBYTE)
memory[address.first.toUInt()] = value.first.toInt().toUByte()
}
else if(array!=null)
TODO("assign $value to array $array")
else
throw IllegalArgumentException("missing assign target")
ip.next()
}
}
internal fun findPtNode(scopedName: List<String>, scope: PtNode): PtNode {
var root = scope
while(root !is PtProgram) {
root=root.parent
}
val block = root.allBlocks().first {
it.name == scopedName.first()
}
var node: PtNode = block
scopedName.drop(1).forEach { namepart->
val nodes = node.children.filterIsInstance<PtNamedNode>()
node = nodes.first { it.name==namepart }
}
return node
}

View File

@ -1,59 +0,0 @@
package prog8.sim
import prog8.ast.base.ArrayDatatypes
import prog8.ast.base.DataType
import prog8.ast.base.FatalAstException
import prog8.ast.base.NumericDatatypes
import prog8.compilerinterface.Encoding
import prog8.compilerinterface.StStaticVariable
import prog8.compilerinterface.SymbolTable
class Variables(symboltable: SymbolTable) {
class Value(
val number: Double?,
val string: Pair<String, Encoding>?,
val array: DoubleArray?
)
val allVars = symboltable.allVariables
val flatSymbolTable = symboltable.flat
val allocations = mutableMapOf<StStaticVariable, UInt>()
val values = mutableMapOf<StStaticVariable, Value>()
init {
var address = 0x1000u
for (variable in allVars) {
allocations[variable] = address
address += MemSizer.memorySize(variable.dt).toUInt()
when(variable.dt) {
in NumericDatatypes -> {
val number = if(variable.initialNumericValue==null) 0.0 else variable.initialNumericValue!!
values[variable] = Value(number, null, null)
}
DataType.STR -> {
values[variable] = Value(null, variable.initialStringValue!!, null)
}
in ArrayDatatypes -> {
val array = if(variable.initialArrayValue==null) DoubleArray(variable.arraysize!!) else variable.initialArrayValue!!
values[variable] = Value(null, null, array)
}
else -> throw FatalAstException("weird dt")
}
}
}
fun getAddress(variable: StStaticVariable): UInt = allocations.getValue(variable)
fun getValue(variable: StStaticVariable): Value = values.getValue(variable)
fun setValue(variable: StStaticVariable, value: Value) {
when(variable.dt) {
in NumericDatatypes-> require(value.number!=null)
DataType.STR -> require(value.string!=null)
in ArrayDatatypes -> require(value.array!=null)
else -> throw FatalAstException("weird dt")
}
values[variable] = value
}
}

View File

@ -1,67 +0,0 @@
package prog8simulatortests
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import prog8.sim.Memory
class TestMemory : FunSpec({
val mem = Memory()
test("unsigned byte") {
mem.clear()
mem[100u] shouldBe 0u
mem[100u] = 99u
mem[100u] shouldBe 99u
mem[100u] = 254u
mem[100u] shouldBe 254u
mem.getSByte(100u) shouldBe -2
}
test("signed byte") {
mem.clear()
mem.getSByte(100u) shouldBe 0
mem.setSByte(100u, 99)
mem.getSByte(100u) shouldBe 99
mem.setSByte(100u, -2)
mem.getSByte(100u) shouldBe -2
mem[100u] shouldBe 254u
}
test("unsigned word") {
mem.clear()
mem.getWord(100u) shouldBe 0u
mem.setWord(100u, 12345u)
mem.getWord(100u) shouldBe 12345u
mem.getSWord(100u) shouldBe 12345
mem.setWord(100u, 54321u)
mem.getWord(100u) shouldBe 54321u
mem.getSWord(100u) shouldBe -11215
mem[100u] shouldBe 0x31u
mem[101u] shouldBe 0xd4u
}
test("signed word") {
mem.clear()
mem.getSWord(100u) shouldBe 0
mem.setSWord(100u, 12345)
mem.getSWord(100u) shouldBe 12345
mem.getWord(100u) shouldBe 12345u
mem.setSWord(100u, -12345)
mem.getSWord(100u) shouldBe -12345
mem.getWord(100u) shouldBe 53191u
mem[100u] shouldBe 0xc7u
mem[101u] shouldBe 0xcfu
}
test("string") {
mem.clear()
mem[105u] = 1u
mem.setString(100u, "Hello")
mem[100u] shouldBe 'H'.code.toUByte()
mem[104u] shouldBe 'o'.code.toUByte()
mem[105u] shouldBe 0u
mem.getString(100u) shouldBe "Hello"
}
})

View File

@ -1,46 +0,0 @@
package prog8simulatortests
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import prog8.ast.base.DataType
import prog8.ast.base.Position
import prog8.ast.statements.AssignmentOrigin
import prog8.compilerinterface.Encoding
import prog8.compilerinterface.SymbolTable
import prog8.compilerinterface.intermediate.*
import prog8.sim.MemSizer
import prog8.sim.Simulator
import prog8.sim.StringEncoding
class TestSim : FunSpec({
test("simple program simulation") {
val program = PtProgram("test", MemSizer, StringEncoding)
val module = PtModule("test", 0u, false, Position.DUMMY)
val block = PtBlock("main", null, false, Position.DUMMY)
val sub = PtSub("start", emptyList(), emptyList(), false, Position.DUMMY)
block.add(sub)
module.add(block)
program.add(module)
val fcall = PtBuiltinFunctionCall("print", Position.DUMMY).also {
it.add(PtString("Hello, world! From the program.\n", Encoding.DEFAULT, Position.DUMMY))
}
sub.add(fcall)
val memwrite = PtAssignment(false, AssignmentOrigin.USERCODE, Position.DUMMY).also { assign ->
assign.add(PtAssignTarget(Position.DUMMY).also { tgt ->
tgt.add(PtMemoryByte(Position.DUMMY).also { mb ->
mb.add(PtNumber(DataType.UWORD, 1000.0, Position.DUMMY))
})
})
assign.add(PtNumber(DataType.UBYTE, 99.0, Position.DUMMY))
}
sub.add(memwrite)
sub.add(PtReturn(Position.DUMMY))
val symboltable = SymbolTable()
val sim = Simulator(program, symboltable)
sim.memory[1000u] shouldBe 0u
sim.run()
sim.memory[1000u] shouldBe 99u
}
})