From 91f9229b072e89a52d2bebc9865e502ca18583fc Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 27 Sep 2018 23:21:04 +0200 Subject: [PATCH] fixed memory vars in compiler, added invalid assignment check --- compiler/examples/irq.p8 | 19 +++++++++++-------- compiler/src/prog8/ast/AstChecker.kt | 10 ++-------- compiler/src/prog8/compiler/Compiler.kt | 20 ++++++++++++++++---- docs/source/programming.rst | 4 ++++ docs/source/syntaxreference.rst | 3 ++- 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/compiler/examples/irq.p8 b/compiler/examples/irq.p8 index d32004276..b06f623ca 100644 --- a/compiler/examples/irq.p8 +++ b/compiler/examples/irq.p8 @@ -1,13 +1,16 @@ +%option enable_floats + ~ main { + memory byte jiffyclockHi = $a0 + memory byte jiffyclockMid = $a1 + memory byte jiffyclockLo = $a2 + + sub start() -> () { - - byte jiffyclockHi = $a0 - byte jiffyclockMid = $a1 - byte jiffyclockLo = $a2 - - _vm_gfx_pixel(2,2,jiffyclockHi) - _vm_gfx_pixel(4,2,jiffyclockMid) - _vm_gfx_pixel(6,2,jiffyclockLo) + _vm_gfx_pixel(jiffyclockLo,190,jiffyclockHi) + _vm_gfx_pixel(jiffyclockLo,191,jiffyclockMid) + _vm_gfx_pixel(jiffyclockLo,192,jiffyclockLo) + return } } diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index 64306ed6d..923fadc0d 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -712,19 +712,13 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions: position: Position) : Boolean { if(sourceValue is RangeExpr) - return checkValueTypeAndRange(targetDatatype, null, sourceValue) + checkResult.add(SyntaxError("can't assign a range value", position)) 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 + else -> checkResult.add(SyntaxError("cannot assign new value to variable of type $targetDatatype", position)) } if(result) diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 996d5728f..0bdca21de 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -118,12 +118,10 @@ class Compiler(private val options: CompilationOptions) { // collect all the VarDecls to make them into one global list // @todo maybe keep the block structure intact and allocate them per block? this is needed eventually for the actual 6502 code generation so... override fun process(decl: VarDecl): IStatement { - if(decl.type == VarDeclType.MEMORY) - TODO("stackVm doesn't support memory vars for now") - if (decl.type == VarDeclType.VAR) { stackvmProg.blockvar(decl.scopedname, decl) } + // MEMORY variables are memory mapped and thus need no storage at all return super.process(decl) } } @@ -333,7 +331,21 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram, priva val target = expr.targetStatement(namespace) when(target) { is VarDecl -> { - stackvmProg.instr(Opcode.PUSH_VAR, Value(DataType.STR, null, target.scopedname)) + when(target.type) { + VarDeclType.VAR -> + stackvmProg.instr(Opcode.PUSH_VAR, Value(DataType.STR, null, target.scopedname)) + VarDeclType.CONST -> + throw CompilerException("const ref should have been const-folded away") + VarDeclType.MEMORY -> { + when(target.datatype){ + DataType.BYTE -> stackvmProg.instr(Opcode.PUSH_MEM, Value(DataType.WORD, (target.value as LiteralValue).asNumericValue)) + DataType.WORD -> stackvmProg.instr(Opcode.PUSH_MEM_W, Value(DataType.WORD, (target.value as LiteralValue).asNumericValue)) + DataType.FLOAT -> stackvmProg.instr(Opcode.PUSH_MEM_F, Value(DataType.WORD, (target.value as LiteralValue).asNumericValue)) + else -> TODO("invalid datatype for memory variable expression: $target") + } + } + } + } else -> throw CompilerException("expression identifierref should be a vardef, not $target") } diff --git a/docs/source/programming.rst b/docs/source/programming.rst index 627bd3e51..6b22fee73 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -364,6 +364,10 @@ Assignment statements assign a single value to a target variable or memory locat Augmented assignments (such as ``A += X``) are also available, but these are just shorthands for normal assignments (``A = A + X``). +Only register variables and variables of type byte, word and float can be assigned a new value. +It's not possible to set a new value to string or array variables etc, because they get allocated +a fixed amount of memory which will not change. + .. attention:: **Data type conversion (in assignments):** When assigning a value with a 'smaller' datatype to a register or variable with a 'larger' datatype, diff --git a/docs/source/syntaxreference.rst b/docs/source/syntaxreference.rst index c62432eea..635cea7ed 100644 --- a/docs/source/syntaxreference.rst +++ b/docs/source/syntaxreference.rst @@ -335,7 +335,8 @@ bitwise arithmetic: ``&`` ``|`` ``^`` ``~`` ``&`` is bitwise and, ``|`` is bitwise or, ``^`` is bitwise xor, ``~`` is bitwise invert (this one is an unary operator) assignment: ``=`` - Sets the target on the LHS (left hand side) of the operator to the value of the expression on the RHS (right hand side). + Sets the target on the LHS (left hand side) of the operator to the value of the expression on the RHS (right hand side). + Note that an assignment sometimes is not possible or supported. augmented assignment: ``+=`` ``-=`` ``*=`` ``/=`` ``**=`` ``&=`` ``|=`` ``^=`` Syntactic sugar; ``A += X`` is equivalent to ``A = A + X``