diff --git a/compiler/examples/assignments.p8 b/compiler/examples/assignments.p8 index eb8d27219..c5fee10b9 100644 --- a/compiler/examples/assignments.p8 +++ b/compiler/examples/assignments.p8 @@ -48,6 +48,33 @@ sub start() { str_p stringp = "hello" +; some string assignments + + str stringvar = "??????????\n\n\nnext line\r\r\rnext line after carriagereturn" + ubyte secretnumber = 0 + memory uword freadstr_arg = $22 ; argument for FREADSTR + uword testword + ubyte char1 = "@" + ubyte char2 = "\n" + ubyte char3 = "\r" + ubyte char1b = '@' + ubyte char2b = '\n' + ubyte char3b = '\r' + + testword = '@' + testword = '\n' + freadstr_arg = '@' + freadstr_arg = '\n' + secretnumber = '@' + secretnumber = '\r' + + testword = stringvar ; @todo fix str address assignment + testword = "stringstring" ; @todo fix str address assignment + freadstr_arg = stringvar ; @todo fix str address assignment + freadstr_arg = "stringstring" ; @todo fix str address assignment + secretnumber = "stringstring2222" ; @todo fix str address assignment + + ; all possible assignments to a BYTE VARIABLE (not array) diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index 9d3c00960..8d5610d54 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -16,25 +16,30 @@ sub start() { byte b1 - str stringvar = "??????????" + str stringvar = "??????????\n\n\nnext line\r\r\rnext line after carriagereturn" ubyte secretnumber = 0 memory uword freadstr_arg = $22 ; argument for FREADSTR uword testword ubyte char1 = "@" - ubyte char2 = "\n" ; @todo escapechar - ubyte char3 = "\t" ; @todo escapechar + ubyte char2 = "\n" + ubyte char3 = "\r" + ubyte char1b = '@' + ubyte char2b = '\n' + ubyte char3b = '\r' + + testword = '@' + testword = '\n' + freadstr_arg = '@' + freadstr_arg = '\n' + secretnumber = '@' + secretnumber = '\r' + + testword = stringvar ; @todo fix str address assignment + testword = "stringstring" ; @todo fix str address assignment + freadstr_arg = stringvar ; @todo fix str address assignment + freadstr_arg = "stringstring" ; @todo fix str address assignment + secretnumber = "stringstring2222" ; @todo fix str address assignment - ;testword = stringvar ; @todo fix str address - ;testword = "sadfsafsdf" ; @todo fix str address - testword = "@" ; @todo fix argument conversion to UBYTE - testword = "\n" ; @todo fix argument conversion to UBYTE (escapechar) - ;freadstr_arg = stringvar - ;freadstr_arg = "asdfasdfasdfasdf" - freadstr_arg = "@" ; @todo fix argument conversion to UBYTE - freadstr_arg = "\n" ; @todo fix argument conversion to UBYTE (escapechar) - secretnumber = "@" ; @todo fix argument conversion to UBYTE - secretnumber = "\n" ; @todo fix argument conversion to UBYTE (escapechar) - ;secretnumber = "asdfsdf" address =c64.MEMBOT(1, 40000.w) ; ok! diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index 74aab5028..b10abfc44 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -4,7 +4,6 @@ import org.antlr.v4.runtime.ParserRuleContext import org.antlr.v4.runtime.tree.TerminalNode import prog8.compiler.HeapValues import prog8.compiler.target.c64.Petscii -import prog8.compiler.unescape import prog8.functions.BuiltinFunctions import prog8.functions.NotConstArgumentException import prog8.functions.builtinFunctionReturnType @@ -1959,8 +1958,8 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression { else -> throw FatalAstException("invalid datatype for numeric literal") } litval.floatliteral()!=null -> LiteralValue(DataType.FLOAT, floatvalue = litval.floatliteral().toAst(), position = litval.toPosition()) - litval.stringliteral()!=null -> LiteralValue(DataType.STR, strvalue = litval.stringliteral().text, position = litval.toPosition()) - litval.charliteral()!=null -> LiteralValue(DataType.UBYTE, bytevalue = Petscii.encodePetscii(litval.charliteral().text.unescape(), true)[0], position = litval.toPosition()) + litval.stringliteral()!=null -> LiteralValue(DataType.STR, strvalue = unescape(litval.stringliteral().text, litval.toPosition()), position = litval.toPosition()) + litval.charliteral()!=null -> LiteralValue(DataType.UBYTE, bytevalue = Petscii.encodePetscii(unescape(litval.charliteral().text, litval.toPosition()), true)[0], position = litval.toPosition()) litval.arrayliteral()!=null -> { val array = litval.arrayliteral()?.toAst() // the actual type of the arrayspec can not yet be determined here (missing namespace & heap) @@ -2004,6 +2003,7 @@ private fun prog8Parser.ExpressionContext.toAst() : IExpression { throw FatalAstException(text) } + private fun prog8Parser.ArrayindexedContext.toAst(): ArrayIndexedExpression { return ArrayIndexedExpression(identifier()?.toAst() ?: scoped_identifier()?.toAst(), arrayspec().toAst(), @@ -2116,3 +2116,29 @@ internal fun registerSet(asmReturnvaluesRegisters: Iterable() + val iter = str.iterator() + while(iter.hasNext()) { + val c = iter.nextChar() + if(c=='\\') { + val ec = iter.nextChar() + result.add(when(ec) { + '\\' -> '\\' + 'n' -> '\n' + 'r' -> '\r' + 'u' -> { + "${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}".toInt(16).toChar() + } + else -> throw AstException("$position invalid escape char in string: \\$ec") + }) + } else { + result.add(c) + } + } + return result.joinToString("") +} diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 73d6fa11d..554e59753 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -6,7 +6,6 @@ import prog8.compiler.intermediate.IntermediateProgram import prog8.compiler.intermediate.Opcode import prog8.compiler.intermediate.Value import prog8.stackvm.Syscall -import prog8.stackvm.VmExecutionException import java.util.* import kotlin.math.abs @@ -31,32 +30,6 @@ fun Number.toHex(): String { } -fun String.unescape(): String { - val result = mutableListOf() - val iter = this.iterator() - while(iter.hasNext()) { - val c = iter.nextChar() - if(c=='\\') { - val ec = iter.nextChar() - result.add(when(ec) { - '\\' -> '\\' - 'b' -> '\b' - 'n' -> '\n' - 'r' -> '\r' - 't' -> '\t' - 'u' -> { - "${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}".toInt(16).toChar() - } - else -> throw VmExecutionException("invalid escape char: $ec") - }) - } else { - result.add(c) - } - } - return result.joinToString("") -} - - class HeapValues { data class HeapValue(val type: DataType, val str: String?, val array: IntArray?, val doubleArray: DoubleArray?) { override fun equals(other: Any?): Boolean { @@ -181,7 +154,7 @@ private class StatementTranslator(private val prog: IntermediateProgram, override fun process(block: Block): IStatement { prog.newBlock(block.scopedname, block.name, block.address) - processVariables(block) // @todo optimize initializations with same value: load the value only once + processVariables(block) // @todo optimize initializations with same value: load the value only once (sort on initalization value, datatype ?) prog.label(block.scopedname) prog.line(block.position) translate(block.statements) diff --git a/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt b/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt index 618f73e32..74d5c457e 100644 --- a/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt +++ b/compiler/src/prog8/compiler/intermediate/IntermediateProgram.kt @@ -313,7 +313,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap out.println("%end_memory") out.println("%heap") heap.allStrings().forEach { - out.println("${it.index} ${it.value.type.toString().toLowerCase()} \"${it.value.str}\"") + out.println("${it.index} ${it.value.type.toString().toLowerCase()} \"${escape(it.value.str!!)}\"") } heap.allArrays().forEach { out.println("${it.index} ${it.value.type.toString().toLowerCase()} ${it.value.array!!.toList()}") diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 00d721ddf..93d328604 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -5,7 +5,7 @@ package prog8.compiler.target.c64 import prog8.ast.DataType -import prog8.ast.Register +import prog8.ast.escape import prog8.compiler.* import prog8.compiler.intermediate.* import prog8.stackvm.Syscall @@ -235,7 +235,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, DataType.STR_PS -> { val rawStr = heap.get(v.second.heapId).str!! val bytes = encodeStr(rawStr, v.second.type).map { "$" + it.toString(16).padStart(2, '0') } - out("${v.first}\t; ${v.second.type} \"$rawStr\"") + out("${v.first}\t; ${v.second.type} \"${escape(rawStr)}\"") for (chunk in bytes.chunked(16)) out("\t.byte " + chunk.joinToString()) } diff --git a/compiler/src/prog8/optimizing/ConstantFolding.kt b/compiler/src/prog8/optimizing/ConstantFolding.kt index 60dc16e23..3546c5548 100644 --- a/compiler/src/prog8/optimizing/ConstantFolding.kt +++ b/compiler/src/prog8/optimizing/ConstantFolding.kt @@ -46,7 +46,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV // vardecl: for byte/word vars, convert char/string of length 1 initialization values to ubyte integer val literal = decl.value as? LiteralValue if (literal != null && literal.isString && literal.strvalue(heap).length == 1) { - val petscii = Petscii.encodePetscii(literal.strvalue(heap))[0] + val petscii = Petscii.encodePetscii(literal.strvalue(heap), true)[0] val newValue = LiteralValue(DataType.UBYTE, bytevalue = petscii, position = literal.position) decl.value = newValue } @@ -541,7 +541,6 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV when(targetDt) { DataType.UWORD -> { // we can convert to UWORD: any UBYTE, BYTE/WORD that are >=0, FLOAT that's an integer 0..65535, - // STR of length 1 (take the character's byte value) if(lv.type==DataType.UBYTE) assignment.value = LiteralValue(DataType.UWORD, wordvalue = lv.asIntegerValue, position=lv.position) else if(lv.type==DataType.BYTE && lv.bytevalue!!>=0) @@ -553,17 +552,9 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV if(floor(d)==d && d>=0 && d<=65535) assignment.value = LiteralValue(DataType.UWORD, wordvalue=floor(d).toInt(), position=lv.position) } - else if(lv.type in StringDatatypes) { - val str = lv.strvalue(heap) - if(str.length==1) { - val petscii = Petscii.encodePetscii(str)[0] - assignment.value = LiteralValue(DataType.UWORD, wordvalue = petscii.toInt(), position = lv.position) - } - } } DataType.UBYTE -> { // we can convert to UBYTE: UWORD <=255, BYTE >=0, FLOAT that's an integer 0..255, - // STR of length 1 (take the character's byte value) if(lv.type==DataType.UWORD && lv.wordvalue!! <= 255) assignment.value = LiteralValue(DataType.UBYTE, lv.wordvalue.toShort(), position=lv.position) else if(lv.type==DataType.BYTE && lv.bytevalue!! >=0) @@ -573,13 +564,6 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV if(floor(d)==d && d >=0 && d<=255) assignment.value = LiteralValue(DataType.UBYTE, floor(d).toShort(), position=lv.position) } - else if(lv.type in StringDatatypes) { - val str = lv.strvalue(heap) - if(str.length==1) { - val petscii = Petscii.encodePetscii(str)[0] - assignment.value = LiteralValue(DataType.UBYTE, bytevalue = petscii, position = lv.position) - } - } } DataType.BYTE -> { // we can convert to BYTE: UWORD/UBYTE <= 127, FLOAT that's an integer 0..127 @@ -595,7 +579,6 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV } DataType.WORD -> { // we can convert to WORD: any UBYTE/BYTE, UWORD <= 32767, FLOAT that's an integer -32768..32767, - // STR of length 1 (take the character's byte value) if(lv.type==DataType.UBYTE || lv.type==DataType.BYTE) assignment.value = LiteralValue(DataType.WORD, wordvalue=lv.bytevalue!!.toInt(), position=lv.position) else if(lv.type==DataType.UWORD && lv.wordvalue!! <= 32767) @@ -605,13 +588,6 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV if(floor(d)==d && d>=-32768 && d<=32767) assignment.value = LiteralValue(DataType.BYTE, floor(d).toShort(), position=lv.position) } - else if(lv.type in StringDatatypes) { - val str = lv.strvalue(heap) - if(str.length==1) { - val petscii = Petscii.encodePetscii(str)[0] - assignment.value = LiteralValue(DataType.WORD, wordvalue= petscii.toInt(), position = lv.position) - } - } } DataType.FLOAT -> { if(lv.isNumeric) diff --git a/compiler/src/prog8/parser/prog8Lexer.java b/compiler/src/prog8/parser/prog8Lexer.java index 6fc1d082f..c286843a5 100644 --- a/compiler/src/prog8/parser/prog8Lexer.java +++ b/compiler/src/prog8/parser/prog8Lexer.java @@ -1,13 +1,12 @@ // Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7 package prog8.parser; -import org.antlr.v4.runtime.Lexer; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.Token; -import org.antlr.v4.runtime.TokenStream; + import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNDeserializer; +import org.antlr.v4.runtime.atn.LexerATNSimulator; +import org.antlr.v4.runtime.atn.PredictionContextCache; import org.antlr.v4.runtime.dfa.DFA; -import org.antlr.v4.runtime.misc.*; @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) public class prog8Lexer extends Lexer { @@ -17,23 +16,23 @@ public class prog8Lexer extends Lexer { protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); public static final int - T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, - T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, - T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, - T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, - T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, - T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, - T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52, - T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, - T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, - T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73, - T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, T__78=79, T__79=80, - T__80=81, T__81=82, T__82=83, T__83=84, T__84=85, T__85=86, T__86=87, - T__87=88, T__88=89, T__89=90, T__90=91, T__91=92, T__92=93, T__93=94, - T__94=95, T__95=96, T__96=97, T__97=98, T__98=99, T__99=100, T__100=101, - T__101=102, T__102=103, T__103=104, T__104=105, T__105=106, T__106=107, - LINECOMMENT=108, COMMENT=109, WS=110, EOL=111, NAME=112, DEC_INTEGER=113, - HEX_INTEGER=114, BIN_INTEGER=115, FLOAT_NUMBER=116, STRING=117, INLINEASMBLOCK=118, + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, + T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, + T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, + T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52, + T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, + T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, + T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73, + T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, T__78=79, T__79=80, + T__80=81, T__81=82, T__82=83, T__83=84, T__84=85, T__85=86, T__86=87, + T__87=88, T__88=89, T__89=90, T__90=91, T__91=92, T__92=93, T__93=94, + T__94=95, T__95=96, T__96=97, T__97=98, T__98=99, T__99=100, T__100=101, + T__101=102, T__102=103, T__103=104, T__104=105, T__105=106, T__106=107, + LINECOMMENT=108, COMMENT=109, WS=110, EOL=111, NAME=112, DEC_INTEGER=113, + HEX_INTEGER=114, BIN_INTEGER=115, FLOAT_NUMBER=116, STRING=117, INLINEASMBLOCK=118, SINGLECHAR=119; public static String[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" @@ -44,51 +43,51 @@ public class prog8Lexer extends Lexer { }; public static final String[] ruleNames = { - "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", - "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", - "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", - "T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32", - "T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40", - "T__41", "T__42", "T__43", "T__44", "T__45", "T__46", "T__47", "T__48", - "T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56", - "T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "T__64", - "T__65", "T__66", "T__67", "T__68", "T__69", "T__70", "T__71", "T__72", - "T__73", "T__74", "T__75", "T__76", "T__77", "T__78", "T__79", "T__80", - "T__81", "T__82", "T__83", "T__84", "T__85", "T__86", "T__87", "T__88", - "T__89", "T__90", "T__91", "T__92", "T__93", "T__94", "T__95", "T__96", - "T__97", "T__98", "T__99", "T__100", "T__101", "T__102", "T__103", "T__104", - "T__105", "T__106", "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", - "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "FNUMBER", "STRING_ESCAPE_SEQ", + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", + "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", + "T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32", + "T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40", + "T__41", "T__42", "T__43", "T__44", "T__45", "T__46", "T__47", "T__48", + "T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56", + "T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "T__64", + "T__65", "T__66", "T__67", "T__68", "T__69", "T__70", "T__71", "T__72", + "T__73", "T__74", "T__75", "T__76", "T__77", "T__78", "T__79", "T__80", + "T__81", "T__82", "T__83", "T__84", "T__85", "T__86", "T__87", "T__88", + "T__89", "T__90", "T__91", "T__92", "T__93", "T__94", "T__95", "T__96", + "T__97", "T__98", "T__99", "T__100", "T__101", "T__102", "T__103", "T__104", + "T__105", "T__106", "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", + "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "FNUMBER", "STRING_ESCAPE_SEQ", "STRING", "INLINEASMBLOCK", "SINGLECHAR" }; private static final String[] _LITERAL_NAMES = { - null, "'~'", "':'", "'goto'", "'%output'", "'%launcher'", "'%zeropage'", - "'%zpreserved'", "'%address'", "'%import'", "'%breakpoint'", "'%asminclude'", - "'%asmbinary'", "'%option'", "','", "'='", "'const'", "'memory'", "'ubyte'", - "'byte'", "'uword'", "'word'", "'float'", "'str'", "'str_p'", "'str_s'", - "'str_ps'", "'['", "']'", "'+='", "'-='", "'/='", "'//='", "'*='", "'**='", - "'&='", "'|='", "'^='", "'++'", "'--'", "'('", "')'", "'+'", "'-'", "'**'", - "'*'", "'/'", "'//'", "'%'", "'<'", "'>'", "'<='", "'>='", "'=='", "'!='", - "'&'", "'^'", "'|'", "'to'", "'step'", "'and'", "'or'", "'xor'", "'not'", - "'return'", "'break'", "'continue'", "'.'", "'A'", "'X'", "'Y'", "'AX'", - "'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'", "'Pv'", "'.w'", "'true'", "'false'", - "'%asm'", "'sub'", "'->'", "'{'", "'}'", "'asmsub'", "'clobbers'", "'@'", - "'if'", "'else'", "'if_cs'", "'if_cc'", "'if_eq'", "'if_z'", "'if_ne'", - "'if_nz'", "'if_pl'", "'if_pos'", "'if_mi'", "'if_neg'", "'if_vs'", "'if_vc'", + null, "'~'", "':'", "'goto'", "'%output'", "'%launcher'", "'%zeropage'", + "'%zpreserved'", "'%address'", "'%import'", "'%breakpoint'", "'%asminclude'", + "'%asmbinary'", "'%option'", "','", "'='", "'const'", "'memory'", "'ubyte'", + "'byte'", "'uword'", "'word'", "'float'", "'str'", "'str_p'", "'str_s'", + "'str_ps'", "'['", "']'", "'+='", "'-='", "'/='", "'//='", "'*='", "'**='", + "'&='", "'|='", "'^='", "'++'", "'--'", "'('", "')'", "'+'", "'-'", "'**'", + "'*'", "'/'", "'//'", "'%'", "'<'", "'>'", "'<='", "'>='", "'=='", "'!='", + "'&'", "'^'", "'|'", "'to'", "'step'", "'and'", "'or'", "'xor'", "'not'", + "'return'", "'break'", "'continue'", "'.'", "'A'", "'X'", "'Y'", "'AX'", + "'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'", "'Pv'", "'.w'", "'true'", "'false'", + "'%asm'", "'sub'", "'->'", "'{'", "'}'", "'asmsub'", "'clobbers'", "'@'", + "'if'", "'else'", "'if_cs'", "'if_cc'", "'if_eq'", "'if_z'", "'if_ne'", + "'if_nz'", "'if_pl'", "'if_pos'", "'if_mi'", "'if_neg'", "'if_vs'", "'if_vc'", "'for'", "'in'", "'while'", "'repeat'", "'until'" }; private static final String[] _SYMBOLIC_NAMES = { - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "STRING", "INLINEASMBLOCK", "SINGLECHAR" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -169,7 +168,7 @@ public class prog8Lexer extends Lexer { // get rid of the enclosing quotes String s = getText(); setText(s.substring(1, s.length() - 1)); - + break; } } @@ -180,7 +179,7 @@ public class prog8Lexer extends Lexer { // get rid of the enclosing double braces String s = getText(); setText(s.substring(2, s.length() - 2)); - + break; } } @@ -191,7 +190,7 @@ public class prog8Lexer extends Lexer { // get rid of the enclosing quotes String s = getText(); setText(s.substring(1, s.length() - 1)); - + break; } } @@ -486,4 +485,4 @@ public class prog8Lexer extends Lexer { _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); } } -} \ No newline at end of file +} diff --git a/compiler/src/prog8/parser/prog8Parser.java b/compiler/src/prog8/parser/prog8Parser.java index 037036102..42a869d40 100644 --- a/compiler/src/prog8/parser/prog8Parser.java +++ b/compiler/src/prog8/parser/prog8Parser.java @@ -1,13 +1,15 @@ // Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7 package prog8.parser; -import org.antlr.v4.runtime.atn.*; -import org.antlr.v4.runtime.dfa.DFA; + import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.misc.*; -import org.antlr.v4.runtime.tree.*; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNDeserializer; +import org.antlr.v4.runtime.atn.ParserATNSimulator; +import org.antlr.v4.runtime.atn.PredictionContextCache; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.tree.TerminalNode; + import java.util.List; -import java.util.Iterator; -import java.util.ArrayList; @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) public class prog8Parser extends Parser { @@ -17,85 +19,85 @@ public class prog8Parser extends Parser { protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache(); public static final int - T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, - T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, - T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, - T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, - T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, - T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, - T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52, - T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, - T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, - T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73, - T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, T__78=79, T__79=80, - T__80=81, T__81=82, T__82=83, T__83=84, T__84=85, T__85=86, T__86=87, - T__87=88, T__88=89, T__89=90, T__90=91, T__91=92, T__92=93, T__93=94, - T__94=95, T__95=96, T__96=97, T__97=98, T__98=99, T__99=100, T__100=101, - T__101=102, T__102=103, T__103=104, T__104=105, T__105=106, T__106=107, - LINECOMMENT=108, COMMENT=109, WS=110, EOL=111, NAME=112, DEC_INTEGER=113, - HEX_INTEGER=114, BIN_INTEGER=115, FLOAT_NUMBER=116, STRING=117, INLINEASMBLOCK=118, + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, + T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, + T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, + T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, + T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45, + T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52, + T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59, + T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, + T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73, + T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, T__78=79, T__79=80, + T__80=81, T__81=82, T__82=83, T__83=84, T__84=85, T__85=86, T__86=87, + T__87=88, T__88=89, T__89=90, T__90=91, T__91=92, T__92=93, T__93=94, + T__94=95, T__95=96, T__96=97, T__97=98, T__98=99, T__99=100, T__100=101, + T__101=102, T__102=103, T__103=104, T__104=105, T__105=106, T__106=107, + LINECOMMENT=108, COMMENT=109, WS=110, EOL=111, NAME=112, DEC_INTEGER=113, + HEX_INTEGER=114, BIN_INTEGER=115, FLOAT_NUMBER=116, STRING=117, INLINEASMBLOCK=118, SINGLECHAR=119; public static final int - RULE_module = 0, RULE_modulestatement = 1, RULE_block = 2, RULE_statement = 3, - RULE_labeldef = 4, RULE_unconditionaljump = 5, RULE_directive = 6, RULE_directivearg = 7, - RULE_vardecl = 8, RULE_varinitializer = 9, RULE_constdecl = 10, RULE_memoryvardecl = 11, - RULE_datatype = 12, RULE_arrayspec = 13, RULE_assignment = 14, RULE_assign_targets = 15, - RULE_augassignment = 16, RULE_assign_target = 17, RULE_postincrdecr = 18, - RULE_expression = 19, RULE_arrayindexed = 20, RULE_functioncall = 21, - RULE_functioncall_stmt = 22, RULE_expression_list = 23, RULE_returnstmt = 24, - RULE_breakstmt = 25, RULE_continuestmt = 26, RULE_identifier = 27, RULE_scoped_identifier = 28, - RULE_register = 29, RULE_registerorpair = 30, RULE_statusregister = 31, - RULE_integerliteral = 32, RULE_wordsuffix = 33, RULE_booleanliteral = 34, - RULE_arrayliteral = 35, RULE_stringliteral = 36, RULE_charliteral = 37, - RULE_floatliteral = 38, RULE_literalvalue = 39, RULE_inlineasm = 40, RULE_subroutine = 41, - RULE_sub_return_part = 42, RULE_statement_block = 43, RULE_sub_params = 44, - RULE_sub_param = 45, RULE_sub_returns = 46, RULE_asmsubroutine = 47, RULE_asmsub_address = 48, - RULE_asmsub_params = 49, RULE_asmsub_param = 50, RULE_clobber = 51, RULE_asmsub_returns = 52, - RULE_asmsub_return = 53, RULE_if_stmt = 54, RULE_else_part = 55, RULE_branch_stmt = 56, + RULE_module = 0, RULE_modulestatement = 1, RULE_block = 2, RULE_statement = 3, + RULE_labeldef = 4, RULE_unconditionaljump = 5, RULE_directive = 6, RULE_directivearg = 7, + RULE_vardecl = 8, RULE_varinitializer = 9, RULE_constdecl = 10, RULE_memoryvardecl = 11, + RULE_datatype = 12, RULE_arrayspec = 13, RULE_assignment = 14, RULE_assign_targets = 15, + RULE_augassignment = 16, RULE_assign_target = 17, RULE_postincrdecr = 18, + RULE_expression = 19, RULE_arrayindexed = 20, RULE_functioncall = 21, + RULE_functioncall_stmt = 22, RULE_expression_list = 23, RULE_returnstmt = 24, + RULE_breakstmt = 25, RULE_continuestmt = 26, RULE_identifier = 27, RULE_scoped_identifier = 28, + RULE_register = 29, RULE_registerorpair = 30, RULE_statusregister = 31, + RULE_integerliteral = 32, RULE_wordsuffix = 33, RULE_booleanliteral = 34, + RULE_arrayliteral = 35, RULE_stringliteral = 36, RULE_charliteral = 37, + RULE_floatliteral = 38, RULE_literalvalue = 39, RULE_inlineasm = 40, RULE_subroutine = 41, + RULE_sub_return_part = 42, RULE_statement_block = 43, RULE_sub_params = 44, + RULE_sub_param = 45, RULE_sub_returns = 46, RULE_asmsubroutine = 47, RULE_asmsub_address = 48, + RULE_asmsub_params = 49, RULE_asmsub_param = 50, RULE_clobber = 51, RULE_asmsub_returns = 52, + RULE_asmsub_return = 53, RULE_if_stmt = 54, RULE_else_part = 55, RULE_branch_stmt = 56, RULE_branchcondition = 57, RULE_forloop = 58, RULE_whileloop = 59, RULE_repeatloop = 60; public static final String[] ruleNames = { - "module", "modulestatement", "block", "statement", "labeldef", "unconditionaljump", - "directive", "directivearg", "vardecl", "varinitializer", "constdecl", - "memoryvardecl", "datatype", "arrayspec", "assignment", "assign_targets", - "augassignment", "assign_target", "postincrdecr", "expression", "arrayindexed", - "functioncall", "functioncall_stmt", "expression_list", "returnstmt", - "breakstmt", "continuestmt", "identifier", "scoped_identifier", "register", - "registerorpair", "statusregister", "integerliteral", "wordsuffix", "booleanliteral", - "arrayliteral", "stringliteral", "charliteral", "floatliteral", "literalvalue", - "inlineasm", "subroutine", "sub_return_part", "statement_block", "sub_params", - "sub_param", "sub_returns", "asmsubroutine", "asmsub_address", "asmsub_params", - "asmsub_param", "clobber", "asmsub_returns", "asmsub_return", "if_stmt", - "else_part", "branch_stmt", "branchcondition", "forloop", "whileloop", + "module", "modulestatement", "block", "statement", "labeldef", "unconditionaljump", + "directive", "directivearg", "vardecl", "varinitializer", "constdecl", + "memoryvardecl", "datatype", "arrayspec", "assignment", "assign_targets", + "augassignment", "assign_target", "postincrdecr", "expression", "arrayindexed", + "functioncall", "functioncall_stmt", "expression_list", "returnstmt", + "breakstmt", "continuestmt", "identifier", "scoped_identifier", "register", + "registerorpair", "statusregister", "integerliteral", "wordsuffix", "booleanliteral", + "arrayliteral", "stringliteral", "charliteral", "floatliteral", "literalvalue", + "inlineasm", "subroutine", "sub_return_part", "statement_block", "sub_params", + "sub_param", "sub_returns", "asmsubroutine", "asmsub_address", "asmsub_params", + "asmsub_param", "clobber", "asmsub_returns", "asmsub_return", "if_stmt", + "else_part", "branch_stmt", "branchcondition", "forloop", "whileloop", "repeatloop" }; private static final String[] _LITERAL_NAMES = { - null, "'~'", "':'", "'goto'", "'%output'", "'%launcher'", "'%zeropage'", - "'%zpreserved'", "'%address'", "'%import'", "'%breakpoint'", "'%asminclude'", - "'%asmbinary'", "'%option'", "','", "'='", "'const'", "'memory'", "'ubyte'", - "'byte'", "'uword'", "'word'", "'float'", "'str'", "'str_p'", "'str_s'", - "'str_ps'", "'['", "']'", "'+='", "'-='", "'/='", "'//='", "'*='", "'**='", - "'&='", "'|='", "'^='", "'++'", "'--'", "'('", "')'", "'+'", "'-'", "'**'", - "'*'", "'/'", "'//'", "'%'", "'<'", "'>'", "'<='", "'>='", "'=='", "'!='", - "'&'", "'^'", "'|'", "'to'", "'step'", "'and'", "'or'", "'xor'", "'not'", - "'return'", "'break'", "'continue'", "'.'", "'A'", "'X'", "'Y'", "'AX'", - "'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'", "'Pv'", "'.w'", "'true'", "'false'", - "'%asm'", "'sub'", "'->'", "'{'", "'}'", "'asmsub'", "'clobbers'", "'@'", - "'if'", "'else'", "'if_cs'", "'if_cc'", "'if_eq'", "'if_z'", "'if_ne'", - "'if_nz'", "'if_pl'", "'if_pos'", "'if_mi'", "'if_neg'", "'if_vs'", "'if_vc'", + null, "'~'", "':'", "'goto'", "'%output'", "'%launcher'", "'%zeropage'", + "'%zpreserved'", "'%address'", "'%import'", "'%breakpoint'", "'%asminclude'", + "'%asmbinary'", "'%option'", "','", "'='", "'const'", "'memory'", "'ubyte'", + "'byte'", "'uword'", "'word'", "'float'", "'str'", "'str_p'", "'str_s'", + "'str_ps'", "'['", "']'", "'+='", "'-='", "'/='", "'//='", "'*='", "'**='", + "'&='", "'|='", "'^='", "'++'", "'--'", "'('", "')'", "'+'", "'-'", "'**'", + "'*'", "'/'", "'//'", "'%'", "'<'", "'>'", "'<='", "'>='", "'=='", "'!='", + "'&'", "'^'", "'|'", "'to'", "'step'", "'and'", "'or'", "'xor'", "'not'", + "'return'", "'break'", "'continue'", "'.'", "'A'", "'X'", "'Y'", "'AX'", + "'AY'", "'XY'", "'Pc'", "'Pz'", "'Pn'", "'Pv'", "'.w'", "'true'", "'false'", + "'%asm'", "'sub'", "'->'", "'{'", "'}'", "'asmsub'", "'clobbers'", "'@'", + "'if'", "'else'", "'if_cs'", "'if_cc'", "'if_eq'", "'if_z'", "'if_ne'", + "'if_nz'", "'if_pl'", "'if_pos'", "'if_mi'", "'if_neg'", "'if_vs'", "'if_vc'", "'for'", "'in'", "'while'", "'repeat'", "'until'" }; private static final String[] _SYMBOLIC_NAMES = { - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, null, null, null, - "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, null, null, null, null, + "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "STRING", "INLINEASMBLOCK", "SINGLECHAR" }; public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); @@ -1675,7 +1677,7 @@ public class prog8Parser extends Parser { } break; } - } + } } setState(307); _errHandler.sync(this); @@ -2090,7 +2092,7 @@ public class prog8Parser extends Parser { { setState(355); match(NAME); - setState(358); + setState(358); _errHandler.sync(this); _alt = 1; do { @@ -2108,7 +2110,7 @@ public class prog8Parser extends Parser { default: throw new NoViableAltException(this); } - setState(360); + setState(360); _errHandler.sync(this); _alt = getInterpreter().adaptivePredict(_input,26,_ctx); } while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ); @@ -4554,4 +4556,4 @@ public class prog8Parser extends Parser { _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); } } -} \ No newline at end of file +} diff --git a/compiler/src/prog8/stackvm/Program.kt b/compiler/src/prog8/stackvm/Program.kt index 8d164d43e..10ea6cc0b 100644 --- a/compiler/src/prog8/stackvm/Program.kt +++ b/compiler/src/prog8/stackvm/Program.kt @@ -3,7 +3,6 @@ package prog8.stackvm import prog8.ast.DataType import prog8.compiler.HeapValues import prog8.compiler.intermediate.* -import prog8.compiler.unescape import java.io.File import java.util.* import java.util.regex.Pattern @@ -85,7 +84,7 @@ class Program (val name: String, DataType.STR, DataType.STR_P, DataType.STR_S, - DataType.STR_PS -> heap.add(it.second, it.third.substring(1, it.third.length-1).unescape()) + DataType.STR_PS -> heap.add(it.second, it.third.substring(1, it.third.length-1)) DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> { val numbers = it.third.substring(1, it.third.length-1).split(',') diff --git a/docs/source/programming.rst b/docs/source/programming.rst index 6539fd7b3..27713f898 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -273,8 +273,6 @@ but they have some special properties because they are considered to be *text*. Strings in your source code files will be encoded (translated from ASCII/UTF-8) into either CBM PETSCII or C-64 screencodes. PETSCII is the default choice. If you need screencodes (also called 'poke' codes) instead, you have to use the ``str_s`` variants of the string type identifier. -If you assign a string literal of length 1 to a non-string variable, it is treated as an *unsigned byte* value instead -with has the PETSCII value of that single character. .. caution:: It's probably best that you don't change strings after they're created.