Initial program implementation

This commit is contained in:
Shadowfacts 2019-08-08 21:44:59 -04:00
parent 7cbcb267dd
commit b6982e04e4
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
11 changed files with 237 additions and 0 deletions

View File

@ -0,0 +1,12 @@
package net.shadowfacts.asmr.program
/**
* @author shadowfacts
*/
abstract class ExecutableBlock: ProgramBlock {
var nextExecutableBlock: ExecutableBlock? = null
abstract fun execute()
}

View File

@ -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
}
}
}

View File

@ -0,0 +1,11 @@
package net.shadowfacts.asmr.program
/**
* @author shadowfacts
*/
interface ProgramBlock {
val inputs: Array<ProgramBlockInput<*>>
val outputs: Array<ProgramBlockOutput<*>>
}

View File

@ -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
}

View File

@ -0,0 +1,12 @@
package net.shadowfacts.asmr.program
/**
* @author shadowfacts
*/
class ProgramBlockOutput<Type: Any>(
val type: ProgramType<Type>
) {
lateinit var value: Type
}

View File

@ -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>()
}
}

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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)
}
}