This commit is contained in:
Irmen de Jong 2018-09-14 01:24:12 +02:00
parent ea94063689
commit 3228fa4c76
6 changed files with 99 additions and 7 deletions

View File

@ -103,14 +103,10 @@
const byte equalQQ2 = (4+hopla)>0
equalQQ++
cos(2) ; @todo warning statement has no effect (returnvalue of builtin function not used) (remove statement)
cos(A) ; @todo warning statement has no effect (returnvalue of builtin function not used) (remove statement)
AX++
A=X + round(sin(Y))
equalQQ= X
equalQQ= len([X, Y, AX])
len([X, Y, AX]) ; @todo warning statement has no effect (returnvalue of builtin function not used) (remove statement)
sin(1) ; @todo warning statement has no effect (returnvalue of builtin function not used) (remove statement)
P_carry(1)
P_irqd(0)

29
il65/examples/todos.ill Normal file
View File

@ -0,0 +1,29 @@
%output prg
%launcher basic
~ main {
; memory byte derp = max([$ffdd]) ; @todo implement memory vars in stackvm
; memory byte derpA = abs(-20000)
; memory byte derpB = max([1, 2.2, 4.4, 100])
; memory byte cderp = min([$ffdd])+ (1/1)
; memory byte cderpA = min([$ffdd, 10, 20, 30])
; memory byte cderpB = min([1, 2.2, 4.4, 100])
; memory byte derp2 = 2+$ffdd+round(10*sin(3.1))
sub start() -> () {
P_irqd(1) ; is okay. (has side-effects, is not a pure function)
word dinges = 0
word blerp1 =999
word blerp3 = 1
byte blerp2 =99
dinges=blerp1
blerp3 = blerp2
A=blerp2
A=X
XY=X
XY=AX
return
}
}

View File

@ -117,7 +117,7 @@ interface IAstProcessor {
}
fun process(subroutine: Subroutine): IStatement {
subroutine.statements = subroutine.statements.asSequence().map { it.process(this) }.toMutableList()
subroutine.statements = subroutine.statements.map { it.process(this) }.toMutableList()
return subroutine
}
@ -630,6 +630,7 @@ interface IExpression: Node {
fun constValue(namespace: INameScope): LiteralValue?
fun process(processor: IAstProcessor): IExpression
fun referencesIdentifier(name: String): Boolean
// TODO fun resultingDatatype(): DataType
}
@ -771,6 +772,10 @@ class RegisterExpr(val register: Register) : IExpression {
override fun constValue(namespace: INameScope): LiteralValue? = null
override fun process(processor: IAstProcessor) = this
override fun referencesIdentifier(name: String): Boolean = false
override fun toString(): String {
return "RegisterExpr(register=$register, pos=$position)"
}
}

View File

@ -160,13 +160,35 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
}
}
if(assignment.value is LiteralValue) {
val targetDatatype = assignment.target.determineDatatype(namespace, assignment)
val targetDatatype = assignment.target.determineDatatype(namespace, assignment)
val constVal = assignment.value.constValue(namespace)
if(constVal!=null) {
checkValueTypeAndRange(targetDatatype, null, assignment.value as LiteralValue, assignment.position)
} else {
val sourceDatatype: DataType = when(assignment.value) {
is RegisterExpr -> {
when((assignment.value as RegisterExpr).register) {
Register.A, Register.X, Register.Y -> DataType.BYTE
Register.AX, Register.AY, Register.XY -> DataType.WORD
}
}
is IdentifierReference -> {
val targetStmt = (assignment.value as IdentifierReference).targetStatement(namespace)
if(targetStmt is VarDecl) {
targetStmt.datatype
} else {
throw FatalAstException("cannot get datatype from assignment value ${assignment.value}, pos=${assignment.position}")
}
}
else -> TODO("check assignment compatibility for value ${assignment.value}, pos=${assignment.position}")
}
checkAssignmentCompatible(targetDatatype, sourceDatatype, assignment.position)
}
return super.process(assignment)
}
/**
* Check the variable declarations (values within range etc)
*/
@ -499,4 +521,25 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
}
return true
}
private fun checkAssignmentCompatible(targetDatatype: DataType, sourceDatatype: DataType, position: Position?) : Boolean {
val result = when(targetDatatype) {
DataType.BYTE -> sourceDatatype==DataType.BYTE
DataType.WORD -> sourceDatatype==DataType.BYTE || sourceDatatype==DataType.WORD
DataType.FLOAT -> sourceDatatype==DataType.BYTE || sourceDatatype==DataType.WORD || sourceDatatype==DataType.FLOAT
DataType.STR -> sourceDatatype==DataType.STR
DataType.STR_P -> sourceDatatype==DataType.STR_P
DataType.STR_S -> sourceDatatype==DataType.STR_S
DataType.STR_PS -> sourceDatatype==DataType.STR_PS
DataType.ARRAY -> sourceDatatype==DataType.ARRAY
DataType.ARRAY_W -> sourceDatatype==DataType.ARRAY_W
DataType.MATRIX -> sourceDatatype==DataType.MATRIX
}
if(result)
return true
checkResult.add(ExpressionError("cannot assign ${sourceDatatype.toString().toLowerCase()} to ${targetDatatype.toString().toLowerCase()}", position))
return false
}
}

View File

@ -11,6 +11,8 @@ val BuiltinFunctionNames = setOf(
"log", "log10", "sqrt", "rad", "deg", "round", "floor", "ceil",
"max", "min", "avg", "sum", "len", "any", "all", "lsb", "msb")
val BuiltinFunctionsWithoutSideEffects = BuiltinFunctionNames - setOf("P_carry", "P_irqd")
class NotConstArgumentException: AstException("not a const argument to a built-in function")

View File

@ -1,6 +1,8 @@
package il65.optimizing
import il65.ast.*
import il65.functions.BuiltinFunctionNames
import il65.functions.BuiltinFunctionsWithoutSideEffects
fun Module.optimizeStatements(globalNamespace: INameScope, allScopedSymbolDefinitions: MutableMap<String, IStatement>) {
@ -33,6 +35,8 @@ class StatementOptimizer(private val globalNamespace: INameScope) : IAstProcesso
var optimizationsDone: Int = 0
private set
private var statementsToRemove = mutableListOf<IStatement>()
fun reset() {
optimizationsDone = 0
}
@ -48,6 +52,15 @@ class StatementOptimizer(private val globalNamespace: INameScope) : IAstProcesso
val target = globalNamespace.lookup(functionCall.target.nameInSource, functionCall)
if(target!=null)
used(target)
if(functionCall.target.nameInSource.size==1 && BuiltinFunctionNames.contains(functionCall.target.nameInSource[0])) {
val functionName = functionCall.target.nameInSource[0]
if (BuiltinFunctionsWithoutSideEffects.contains(functionName)) {
println("${functionCall.position} Warning: statement has no effect (function return value is discarded)")
statementsToRemove.add(functionCall)
}
}
return super.process(functionCall)
}
@ -99,5 +112,9 @@ class StatementOptimizer(private val globalNamespace: INameScope) : IAstProcesso
optimizationsDone++
}
}
for(stmt in statementsToRemove) {
stmt.definingScope().removeStatement(stmt)
}
}
}