mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
use require() more often
This commit is contained in:
parent
1d2ce2cbeb
commit
7ea7e63f44
@ -173,8 +173,7 @@ class PtPrefix(val operator: String, type: DataType, position: Position): PtExpr
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
// note: the "not" operator may no longer occur in the ast; not x should have been replaced with x==0
|
// note: the "not" operator may no longer occur in the ast; not x should have been replaced with x==0
|
||||||
if(operator !in setOf("+", "-", "~"))
|
require(operator in setOf("+", "-", "~")) { "invalid prefix operator: $operator" }
|
||||||
throw IllegalArgumentException("invalid prefix operator: $operator")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun printProperties() {
|
override fun printProperties() {
|
||||||
|
@ -544,8 +544,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun operatorModulo(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): IRCodeChunk {
|
private fun operatorModulo(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): IRCodeChunk {
|
||||||
if(vmDt==VmDataType.FLOAT)
|
require(vmDt!=VmDataType.FLOAT) {"floating-point modulo not supported"}
|
||||||
throw IllegalArgumentException("floating-point modulo not supported")
|
|
||||||
val code = IRCodeChunk(binExpr.position)
|
val code = IRCodeChunk(binExpr.position)
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
if(binExpr.right is PtNumber) {
|
if(binExpr.right is PtNumber) {
|
||||||
|
@ -3,8 +3,6 @@ TODO
|
|||||||
|
|
||||||
For next release
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
- replace throw IllegalArgumentException() by require()?
|
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@ -434,59 +434,41 @@ data class IRInstruction(
|
|||||||
val fpReg1direction: OperandDirection
|
val fpReg1direction: OperandDirection
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if(labelSymbol?.startsWith('_')==true) {
|
require(labelSymbol?.first()!='_') {"label/symbol should not start with underscore $labelSymbol"}
|
||||||
throw IllegalArgumentException("label/symbol should not start with underscore $labelSymbol")
|
require(reg1==null || reg1 in 0..65536) {"reg1 out of bounds"}
|
||||||
}
|
require(reg2==null || reg2 in 0..65536) {"reg2 out of bounds"}
|
||||||
if(reg1!=null && (reg1<0 || reg1>65536))
|
require(fpReg1==null || fpReg1 in 0..65536) {"fpReg1 out of bounds"}
|
||||||
throw IllegalArgumentException("reg1 out of bounds")
|
require(fpReg2==null || fpReg2 in 0..65536) {"fpReg2 out of bounds"}
|
||||||
if(reg2!=null && (reg2<0 || reg2>65536))
|
|
||||||
throw IllegalArgumentException("reg2 out of bounds")
|
|
||||||
if(fpReg1!=null && (fpReg1<0 || fpReg1>65536))
|
|
||||||
throw IllegalArgumentException("fpReg1 out of bounds")
|
|
||||||
if(fpReg2!=null && (fpReg2<0 || fpReg2>65536))
|
|
||||||
throw IllegalArgumentException("fpReg2 out of bounds")
|
|
||||||
if(value!=null && opcode !in OpcodesWithAddress) {
|
if(value!=null && opcode !in OpcodesWithAddress) {
|
||||||
when (type) {
|
when (type) {
|
||||||
VmDataType.BYTE -> {
|
VmDataType.BYTE -> require(value in -128..255) {"value out of range for byte: $value"}
|
||||||
if (value < -128 || value > 255)
|
VmDataType.WORD -> require(value in -32768..65535) {"value out of range for word: $value"}
|
||||||
throw IllegalArgumentException("value out of range for byte: $value")
|
|
||||||
}
|
|
||||||
VmDataType.WORD -> {
|
|
||||||
if (value < -32768 || value > 65535)
|
|
||||||
throw IllegalArgumentException("value out of range for word: $value")
|
|
||||||
}
|
|
||||||
VmDataType.FLOAT, null -> {}
|
VmDataType.FLOAT, null -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(opcode==Opcode.BINARYDATA && binaryData==null || binaryData!=null && opcode!=Opcode.BINARYDATA)
|
require((opcode==Opcode.BINARYDATA && binaryData!=null) || (opcode!=Opcode.BINARYDATA && binaryData==null)) {
|
||||||
throw IllegalArgumentException("binarydata inconsistency")
|
"binarydata inconsistency"
|
||||||
|
}
|
||||||
|
|
||||||
val formats = instructionFormats.getValue(opcode)
|
val formats = instructionFormats.getValue(opcode)
|
||||||
if(type==null && !formats.containsKey(null))
|
require (type != null || formats.containsKey(null)) { "missing type" }
|
||||||
throw IllegalArgumentException("missing type")
|
|
||||||
|
|
||||||
val format = formats.getValue(type)
|
val format = formats.getValue(type)
|
||||||
if(format.reg1 && reg1==null || format.reg2 && reg2==null)
|
if(format.reg1) require(reg1!=null) { "missing reg1" }
|
||||||
throw IllegalArgumentException("missing a register (int)")
|
if(format.reg2) require(reg2!=null) { "missing reg2" }
|
||||||
|
if(format.fpReg1) require(fpReg1!=null) { "missing fpReg1" }
|
||||||
if(format.fpReg1 && fpReg1==null || format.fpReg2 && fpReg2==null)
|
if(format.fpReg2) require(fpReg2!=null) { "missing fpReg2" }
|
||||||
throw IllegalArgumentException("missing a register (float)")
|
if(!format.reg1) require(reg1==null) { "invalid reg1" }
|
||||||
|
if(!format.reg2) require(reg2==null) { "invalid reg2" }
|
||||||
if(!format.reg1 && reg1!=null || !format.reg2 && reg2!=null)
|
if(!format.fpReg1) require(fpReg1==null) { "invalid fpReg1" }
|
||||||
throw IllegalArgumentException("too many registers (int)")
|
if(!format.fpReg2) require(fpReg2==null) { "invalid fpReg2" }
|
||||||
|
|
||||||
if(!format.fpReg1 && fpReg1!=null || !format.fpReg2 && fpReg2!=null)
|
|
||||||
throw IllegalArgumentException("too many registers (float)")
|
|
||||||
|
|
||||||
if (type==VmDataType.FLOAT) {
|
if (type==VmDataType.FLOAT) {
|
||||||
if(format.fpValue && (fpValue==null && labelSymbol==null))
|
if(format.fpValue) require(fpValue!=null || labelSymbol!=null) {"missing a fp-value or labelsymbol"}
|
||||||
throw IllegalArgumentException("missing a fp-value or labelsymbol")
|
|
||||||
} else {
|
} else {
|
||||||
if(format.value && (value==null && labelSymbol==null))
|
if(format.value) require(value!=null || labelSymbol!=null) {"missing a value or labelsymbol"}
|
||||||
throw IllegalArgumentException("missing a value or labelsymbol")
|
require(fpReg1==null && fpReg2==null) {"integer point instruction can't use floating point registers"}
|
||||||
if (fpReg1 != null || fpReg2 != null)
|
|
||||||
throw IllegalArgumentException("integer point instruction can't use floating point registers")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reg1direction = format.reg1direction
|
reg1direction = format.reg1direction
|
||||||
@ -498,9 +480,10 @@ data class IRInstruction(
|
|||||||
Opcode.SEQ, Opcode.SNE, Opcode.SLT, Opcode.SLTS,
|
Opcode.SEQ, Opcode.SNE, Opcode.SLT, Opcode.SLTS,
|
||||||
Opcode.SGT, Opcode.SGTS, Opcode.SLE, Opcode.SLES,
|
Opcode.SGT, Opcode.SGTS, Opcode.SLE, Opcode.SLES,
|
||||||
Opcode.SGE, Opcode.SGES)) {
|
Opcode.SGE, Opcode.SGES)) {
|
||||||
if((type==VmDataType.FLOAT && fpReg1==fpReg2) || reg1==reg2) {
|
if(type==VmDataType.FLOAT)
|
||||||
throw IllegalArgumentException("$opcode: reg1 and reg2 should be different")
|
require(fpReg1!=fpReg2) {"$opcode: fpReg1 and fpReg2 should be different"}
|
||||||
}
|
else
|
||||||
|
require(reg1!=reg2) {"$opcode: reg1 and reg2 should be different"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,8 +55,7 @@ class IRProgram(val name: String,
|
|||||||
|
|
||||||
fun addGlobalInits(chunk: IRCodeChunk) = globalInits.addAll(chunk.lines)
|
fun addGlobalInits(chunk: IRCodeChunk) = globalInits.addAll(chunk.lines)
|
||||||
fun addBlock(block: IRBlock) {
|
fun addBlock(block: IRBlock) {
|
||||||
if(blocks.any { it.name==block.name })
|
require(blocks.all { it.name != block.name}) { "duplicate block ${block.name} ${block.position}" }
|
||||||
throw IllegalArgumentException("duplicate block ${block.name} ${block.position}")
|
|
||||||
blocks.add(block)
|
blocks.add(block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,16 +93,12 @@ class IRSubroutine(val name: String,
|
|||||||
val chunks = mutableListOf<IRCodeChunkBase>()
|
val chunks = mutableListOf<IRCodeChunkBase>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if(!name.contains('.'))
|
require('.' in name) {"subroutine name is not scoped: $name"}
|
||||||
throw IllegalArgumentException("subroutine name is not scoped: $name")
|
require(!name.startsWith("main.main.")) {"subroutine name invalid main prefix: $name"}
|
||||||
if(name.startsWith("main.main."))
|
|
||||||
throw IllegalArgumentException("subroutine name invalid main prefix: $name")
|
|
||||||
|
|
||||||
// params and return value should not be str
|
// params and return value should not be str
|
||||||
if(parameters.any{ it.dt !in NumericDatatypes })
|
require(parameters.all{ it.dt in NumericDatatypes }) {"non-numeric parameter"}
|
||||||
throw IllegalArgumentException("non-numeric parameter")
|
require(returnType==null || returnType in NumericDatatypes) {"non-numeric returntype $returnType"}
|
||||||
if(returnType!=null && returnType !in NumericDatatypes)
|
|
||||||
throw IllegalArgumentException("non-numeric returntype $returnType")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun plusAssign(chunk: IRCodeChunkBase) { chunks+= chunk }
|
operator fun plusAssign(chunk: IRCodeChunkBase) { chunks+= chunk }
|
||||||
@ -117,10 +112,8 @@ class IRAsmSubroutine(val name: String,
|
|||||||
val returns: List<Pair<DataType, RegisterOrStatusflag>>,
|
val returns: List<Pair<DataType, RegisterOrStatusflag>>,
|
||||||
val assembly: String) {
|
val assembly: String) {
|
||||||
init {
|
init {
|
||||||
if(!name.contains('.'))
|
require('.' in name) { "subroutine name is not scoped: $name" }
|
||||||
throw IllegalArgumentException("subroutine name is not scoped: $name")
|
require(!name.startsWith("main.main.")) { "subroutine name invalid main prefix: $name" }
|
||||||
if(name.startsWith("main.main."))
|
|
||||||
throw IllegalArgumentException("subroutine name invalid main prefix: $name")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class TestInstructions: FunSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("missing registers should fail") {
|
test("missing registers should fail") {
|
||||||
shouldThrowWithMessage<IllegalArgumentException>("missing a register (int)") {
|
shouldThrowWithMessage<IllegalArgumentException>("missing reg1") {
|
||||||
IRInstruction(Opcode.BZ, VmDataType.BYTE, value=99)
|
IRInstruction(Opcode.BZ, VmDataType.BYTE, value=99)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
program = VmProgramLoader().load(irProgram, memory).toTypedArray()
|
program = VmProgramLoader().load(irProgram, memory).toTypedArray()
|
||||||
if(program.size>65536)
|
require(program.size<=65536) {"program cannot contain more than 65536 instructions"}
|
||||||
throw IllegalArgumentException("program cannot contain more than 65536 instructions")
|
|
||||||
cx16virtualregsBaseAddress = (irProgram.st.lookup("cx16.r0") as? StMemVar)?.address?.toInt() ?: 0xff02
|
cx16virtualregsBaseAddress = (irProgram.st.lookup("cx16.r0") as? StMemVar)?.address?.toInt() ?: 0xff02
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user