Initial program implementation
This commit is contained in:
parent
7cbcb267dd
commit
b6982e04e4
|
@ -0,0 +1,12 @@
|
||||||
|
package net.shadowfacts.asmr.program
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
abstract class ExecutableBlock: ProgramBlock {
|
||||||
|
|
||||||
|
var nextExecutableBlock: ExecutableBlock? = null
|
||||||
|
|
||||||
|
abstract fun execute()
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package net.shadowfacts.asmr.program
|
||||||
|
|
||||||
|
import net.shadowfacts.asmr.program.blocks.StartBlock
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class Program {
|
||||||
|
|
||||||
|
var startBlock = StartBlock()
|
||||||
|
val blocks = mutableListOf<ProgramBlock>()
|
||||||
|
|
||||||
|
fun execute() {
|
||||||
|
var currentBlock: ExecutableBlock? = startBlock.nextExecutableBlock
|
||||||
|
while (currentBlock != null) {
|
||||||
|
currentBlock.execute()
|
||||||
|
|
||||||
|
currentBlock = currentBlock.nextExecutableBlock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package net.shadowfacts.asmr.program
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
interface ProgramBlock {
|
||||||
|
|
||||||
|
val inputs: Array<ProgramBlockInput<*>>
|
||||||
|
val outputs: Array<ProgramBlockOutput<*>>
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package net.shadowfacts.asmr.program
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class ProgramBlockInput<Type: Any>(
|
||||||
|
val type: ProgramType<Type>,
|
||||||
|
var source: ProgramBlockOutput<Type>? = null
|
||||||
|
) {
|
||||||
|
|
||||||
|
val value: Type?
|
||||||
|
get() = source?.value
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package net.shadowfacts.asmr.program
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class ProgramBlockOutput<Type: Any>(
|
||||||
|
val type: ProgramType<Type>
|
||||||
|
) {
|
||||||
|
|
||||||
|
lateinit var value: Type
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package net.shadowfacts.asmr.program
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class ProgramType<Type> {
|
||||||
|
companion object {
|
||||||
|
val int = ProgramType<Int>()
|
||||||
|
val float = ProgramType<Float>()
|
||||||
|
val string = ProgramType<String>()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package net.shadowfacts.asmr.program.blocks
|
||||||
|
|
||||||
|
import net.shadowfacts.asmr.program.ProgramBlock
|
||||||
|
import net.shadowfacts.asmr.program.ProgramBlockInput
|
||||||
|
import net.shadowfacts.asmr.program.ProgramBlockOutput
|
||||||
|
import net.shadowfacts.asmr.program.ProgramType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class ConstantBlock<Type: Any>(
|
||||||
|
val type: ProgramType<Type>,
|
||||||
|
val value: Type
|
||||||
|
): ProgramBlock {
|
||||||
|
|
||||||
|
val output = ProgramBlockOutput(type).apply {
|
||||||
|
value = this@ConstantBlock.value
|
||||||
|
}
|
||||||
|
|
||||||
|
override val inputs: Array<ProgramBlockInput<*>> = arrayOf()
|
||||||
|
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf(output)
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package net.shadowfacts.asmr.program.blocks
|
||||||
|
|
||||||
|
import net.shadowfacts.asmr.program.ExecutableBlock
|
||||||
|
import net.shadowfacts.asmr.program.ProgramBlockInput
|
||||||
|
import net.shadowfacts.asmr.program.ProgramBlockOutput
|
||||||
|
import net.shadowfacts.asmr.program.ProgramType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class PrintBlock<Type: Any>(
|
||||||
|
val type: ProgramType<Type>
|
||||||
|
): ExecutableBlock() {
|
||||||
|
|
||||||
|
val input = ProgramBlockInput(type, null)
|
||||||
|
|
||||||
|
override val inputs: Array<ProgramBlockInput<*>> = arrayOf(input)
|
||||||
|
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf()
|
||||||
|
|
||||||
|
override fun execute() {
|
||||||
|
println(input.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package net.shadowfacts.asmr.program.blocks
|
||||||
|
|
||||||
|
import net.shadowfacts.asmr.program.ExecutableBlock
|
||||||
|
import net.shadowfacts.asmr.program.ProgramBlock
|
||||||
|
import net.shadowfacts.asmr.program.ProgramBlockInput
|
||||||
|
import net.shadowfacts.asmr.program.ProgramBlockOutput
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class StartBlock: ProgramBlock {
|
||||||
|
|
||||||
|
override val inputs: Array<ProgramBlockInput<*>> = arrayOf()
|
||||||
|
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf()
|
||||||
|
|
||||||
|
var nextExecutableBlock: ExecutableBlock? = null
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package net.shadowfacts.asmr.program.blocks.math
|
||||||
|
|
||||||
|
import net.shadowfacts.asmr.program.ExecutableBlock
|
||||||
|
import net.shadowfacts.asmr.program.ProgramBlockInput
|
||||||
|
import net.shadowfacts.asmr.program.ProgramBlockOutput
|
||||||
|
import net.shadowfacts.asmr.program.ProgramType
|
||||||
|
import java.lang.RuntimeException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class BinaryOperatorBlock<Type: Any>(
|
||||||
|
val type: ProgramType<Type>,
|
||||||
|
val operation: Operation
|
||||||
|
): ExecutableBlock() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (type != ProgramType.int && type != ProgramType.float) {
|
||||||
|
throw RuntimeException("BinaryOperatorBlock type must be int or float")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val left = ProgramBlockInput(type)
|
||||||
|
val right = ProgramBlockInput(type)
|
||||||
|
|
||||||
|
val output = ProgramBlockOutput(type)
|
||||||
|
|
||||||
|
override val inputs: Array<ProgramBlockInput<*>> = arrayOf(left, right)
|
||||||
|
override val outputs: Array<ProgramBlockOutput<*>> = arrayOf(output)
|
||||||
|
|
||||||
|
override fun execute() {
|
||||||
|
if (type == ProgramType.int) {
|
||||||
|
val left = left.value as Int
|
||||||
|
val right = right.value as Int
|
||||||
|
output.value = when (operation) {
|
||||||
|
Operation.add -> left + right
|
||||||
|
Operation.subtract -> left - right
|
||||||
|
Operation.multiply -> left * right
|
||||||
|
Operation.divide -> left / right
|
||||||
|
} as Type
|
||||||
|
} else if (type == ProgramType.float) {
|
||||||
|
val left = left.value as Float
|
||||||
|
val right = right.value as Float
|
||||||
|
output.value = when (operation) {
|
||||||
|
Operation.add -> left + right
|
||||||
|
Operation.subtract -> left - right
|
||||||
|
Operation.multiply -> left * right
|
||||||
|
Operation.divide -> left / right
|
||||||
|
} as Type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Operation {
|
||||||
|
add, subtract, multiply, divide
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package net.shadowfacts.asmr.program
|
||||||
|
|
||||||
|
import net.shadowfacts.asmr.program.blocks.ConstantBlock
|
||||||
|
import net.shadowfacts.asmr.program.blocks.math.BinaryOperatorBlock
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author shadowfacts
|
||||||
|
*/
|
||||||
|
class ProgramTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testExecutionFlow() {
|
||||||
|
val program = Program()
|
||||||
|
val one = ConstantBlock(ProgramType.int, 3)
|
||||||
|
program.blocks.add(one)
|
||||||
|
val two = ConstantBlock(ProgramType.int, 7)
|
||||||
|
program.blocks.add(two)
|
||||||
|
val multiply = BinaryOperatorBlock(ProgramType.int, BinaryOperatorBlock.Operation.multiply)
|
||||||
|
multiply.left.source = one.output
|
||||||
|
multiply.right.source = two.output
|
||||||
|
program.blocks.add(multiply)
|
||||||
|
|
||||||
|
program.startBlock.nextExecutableBlock = multiply
|
||||||
|
|
||||||
|
program.execute()
|
||||||
|
|
||||||
|
assertEquals(21, multiply.output.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue