mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
add $< and $> operators to get the lsb and msb addresses of a @split array respectively.
document the new split array things.
This commit is contained in:
parent
02f3f5d0f5
commit
e7a0cb636c
@ -137,7 +137,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
|
||||
*/
|
||||
}
|
||||
|
||||
class PtAddressOf(position: Position) : PtExpression(DataType.forDt(BaseDataType.UWORD), position) {
|
||||
class PtAddressOf(position: Position, val isMsbForSplitArray: Boolean=false) : PtExpression(DataType.forDt(BaseDataType.UWORD), position) {
|
||||
val identifier: PtIdentifier
|
||||
get() = children[0] as PtIdentifier
|
||||
val arrayIndexExpr: PtExpression?
|
||||
|
@ -19,7 +19,9 @@ fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Uni
|
||||
is PtBreakpoint -> "%breakpoint"
|
||||
is PtConditionalBranch -> "if_${node.condition.name.lowercase()}"
|
||||
is PtAddressOf -> {
|
||||
if(node.isFromArrayElement)
|
||||
if(node.isMsbForSplitArray)
|
||||
"&>"
|
||||
else if(node.isFromArrayElement)
|
||||
"& array-element"
|
||||
else
|
||||
"&"
|
||||
|
@ -440,10 +440,13 @@ internal class AssignmentAsmGen(
|
||||
when(val value = assign.source.expression!!) {
|
||||
is PtAddressOf -> {
|
||||
val arrayDt = value.identifier.type
|
||||
val sourceName = if(arrayDt.isSplitWordArray)
|
||||
asmgen.asmSymbolName(value.identifier) + "_lsb" // the _lsb split array comes first in memory
|
||||
else
|
||||
asmgen.asmSymbolName(value.identifier)
|
||||
val sourceName =
|
||||
if(value.isMsbForSplitArray)
|
||||
asmgen.asmSymbolName(value.identifier) + "_msb"
|
||||
else if(arrayDt.isSplitWordArray)
|
||||
asmgen.asmSymbolName(value.identifier) + "_lsb" // the _lsb split array comes first in memory
|
||||
else
|
||||
asmgen.asmSymbolName(value.identifier)
|
||||
assignAddressOf(assign.target, sourceName, arrayDt, value.arrayIndexExpr)
|
||||
}
|
||||
is PtBool -> throw AssemblyError("source kind should have been literalboolean")
|
||||
|
@ -156,7 +156,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(expr.identifier.type.isSplitWordArray) {
|
||||
if(expr.isMsbForSplitArray) {
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol+"_msb"), null)
|
||||
} else if(expr.identifier.type.isSplitWordArray) {
|
||||
// the _lsb split array comes first in memory
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol+"_lsb"), null)
|
||||
} else
|
||||
|
@ -422,7 +422,7 @@ extsub $ff41 = GRAPH_put_next_char(ubyte character @A) clobbers(A,X,Y) ; al
|
||||
; framebuffer
|
||||
extsub $fef6 = FB_init() clobbers(A,X,Y)
|
||||
extsub $fef9 = FB_get_info() clobbers(X,Y) -> byte @A, uword @R0, uword @R1 ; width=r0, height=r1
|
||||
extsub $fefc = FB_set_palette(uword pointer @R0, ubyte index @A, ubyte colorcount @X) clobbers(A,X,Y)
|
||||
extsub $fefc = FB_set_palette(uword pointer @R0, ubyte index @A, ubyte colorcount @X) clobbers(A,X,Y) ; note: palette array must be @nosplit
|
||||
extsub $feff = FB_cursor_position(uword x @R0, uword y @R1) clobbers(A,X,Y)
|
||||
extsub $ff02 = FB_cursor_next_line(uword x @R0) clobbers(A,X,Y)
|
||||
extsub $ff05 = FB_get_pixel() clobbers(X,Y) -> ubyte @A
|
||||
|
@ -707,6 +707,13 @@ internal class AstChecker(private val program: Program,
|
||||
super.visit(addressOf)
|
||||
}
|
||||
|
||||
override fun visit(addressOfMsb: AddressOfMsb) {
|
||||
val target = addressOfMsb.identifier.targetVarDecl(program)
|
||||
if(target==null || !target.datatype.isSplitWordArray) {
|
||||
errors.err("&> can only be used on split word arrays", addressOfMsb.position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visit(ifExpr: IfExpression) {
|
||||
if(!ifExpr.condition.inferType(program).isBool)
|
||||
errors.err("condition should be a boolean", ifExpr.condition.position)
|
||||
|
@ -79,6 +79,7 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr
|
||||
private fun transformExpression(expr: Expression): PtExpression {
|
||||
return when(expr) {
|
||||
is AddressOf -> transform(expr)
|
||||
is AddressOfMsb -> transform(expr)
|
||||
is ArrayIndexedExpression -> transform(expr)
|
||||
is ArrayLiteral -> transform(expr)
|
||||
is BinaryExpression -> transform(expr)
|
||||
@ -606,6 +607,12 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr
|
||||
return addr
|
||||
}
|
||||
|
||||
private fun transform(src: AddressOfMsb): PtAddressOf {
|
||||
val addr = PtAddressOf(src.position, true)
|
||||
addr.add(transform(src.identifier))
|
||||
return addr
|
||||
}
|
||||
|
||||
private fun transform(srcArr: ArrayIndexedExpression): PtArrayIndexer {
|
||||
val dt = srcArr.arrayvar.targetVarDecl(program)!!.datatype
|
||||
if(!dt.isArray && !dt.isString)
|
||||
|
@ -472,6 +472,11 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
|
||||
}
|
||||
}
|
||||
|
||||
override fun visit(addressOfMsb: AddressOfMsb) {
|
||||
output("&>")
|
||||
addressOfMsb.identifier.accept(this)
|
||||
}
|
||||
|
||||
override fun visit(inlineAssembly: InlineAssembly) {
|
||||
outputlni("%asm {{")
|
||||
outputln(inlineAssembly.assembly)
|
||||
|
@ -592,11 +592,21 @@ private fun ExpressionContext.toAst(insideParentheses: Boolean=false) : Expressi
|
||||
if(addressof()!=null) {
|
||||
val addressOf = addressof()
|
||||
val identifier = addressOf.scoped_identifier()
|
||||
val array = addressOf.arrayindexed()
|
||||
return if(identifier!=null)
|
||||
AddressOf(addressof().scoped_identifier().toAst(), null, toPosition())
|
||||
else
|
||||
AddressOf(array.scoped_identifier().toAst(), array.arrayindex().toAst(), toPosition())
|
||||
if(addressOf.ADDRESS_OF_LSB()!=null && identifier==null)
|
||||
throw SyntaxError("&< is only valid on array variables", toPosition())
|
||||
if(addressOf.ADDRESS_OF_MSB()!=null) {
|
||||
return if (identifier != null)
|
||||
AddressOfMsb(addressof().scoped_identifier().toAst(), toPosition())
|
||||
else
|
||||
throw SyntaxError("&> is only valid on array variables", toPosition())
|
||||
} else {
|
||||
return if (identifier != null)
|
||||
AddressOf(addressof().scoped_identifier().toAst(), null, toPosition())
|
||||
else {
|
||||
val array = addressOf.arrayindexed()
|
||||
AddressOf(array.scoped_identifier().toAst(), array.arrayindex().toAst(), toPosition())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(if_expression()!=null) {
|
||||
|
@ -478,6 +478,47 @@ data class AddressOf(var identifier: IdentifierReference, var arrayIndex: ArrayI
|
||||
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
|
||||
}
|
||||
|
||||
data class AddressOfMsb(var identifier: IdentifierReference, override val position: Position) : Expression() {
|
||||
override lateinit var parent: Node
|
||||
|
||||
override fun linkParents(parent: Node) {
|
||||
this.parent = parent
|
||||
identifier.linkParents(this)
|
||||
}
|
||||
|
||||
override val isSimple = true
|
||||
|
||||
override fun replaceChildNode(node: Node, replacement: Node) {
|
||||
if(node===identifier) {
|
||||
require(replacement is IdentifierReference)
|
||||
identifier = replacement
|
||||
replacement.parent = this
|
||||
} else {
|
||||
throw FatalAstException("invalid replace, no child node $node")
|
||||
}
|
||||
}
|
||||
|
||||
override fun copy() = AddressOfMsb(identifier.copy(), position)
|
||||
override fun constValue(program: Program): NumericLiteral? {
|
||||
val target = this.identifier.targetStatement(program)
|
||||
val targetVar = target as? VarDecl
|
||||
if(targetVar!=null) {
|
||||
if (targetVar.type == VarDeclType.MEMORY || targetVar.type == VarDeclType.CONST) {
|
||||
var address = targetVar.value?.constValue(program)?.number
|
||||
if (address != null) {
|
||||
TODO("RETURN CONSTVALUE ADDROF_MSB ")
|
||||
// return NumericLiteral(BaseDataType.UWORD, address, position)
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
override fun referencesIdentifier(nameInSource: List<String>) = identifier.nameInSource==nameInSource
|
||||
override fun inferType(program: Program) = InferredTypes.knownFor(BaseDataType.UWORD)
|
||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
|
||||
}
|
||||
|
||||
class DirectMemoryRead(var addressExpression: Expression, override val position: Position) : Expression() {
|
||||
override lateinit var parent: Node
|
||||
|
||||
|
@ -95,6 +95,7 @@ abstract class AstWalker {
|
||||
protected val noModifications = emptyList<IAstModification>()
|
||||
|
||||
open fun before(addressOf: AddressOf, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(addressOfMsb: AddressOfMsb, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(array: ArrayLiteral, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(assignTarget: AssignTarget, parent: Node): Iterable<IAstModification> = noModifications
|
||||
@ -140,6 +141,7 @@ abstract class AstWalker {
|
||||
open fun before(whileLoop: WhileLoop, parent: Node): Iterable<IAstModification> = noModifications
|
||||
|
||||
open fun after(addressOf: AddressOf, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(addressOfMsb: AddressOfMsb, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(array: ArrayLiteral, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(assignTarget: AssignTarget, parent: Node): Iterable<IAstModification> = noModifications
|
||||
@ -470,6 +472,12 @@ abstract class AstWalker {
|
||||
track(after(addressOf, parent), addressOf, parent)
|
||||
}
|
||||
|
||||
fun visit(addressOfMsb: AddressOfMsb, parent: Node) {
|
||||
track(before(addressOfMsb, parent), addressOfMsb, parent)
|
||||
addressOfMsb.identifier.accept(this, addressOfMsb)
|
||||
track(after(addressOfMsb, parent), addressOfMsb, parent)
|
||||
}
|
||||
|
||||
fun visit(ifExpr: IfExpression, parent: Node) {
|
||||
track(before(ifExpr, parent), ifExpr, parent)
|
||||
ifExpr.condition.accept(this, ifExpr)
|
||||
|
@ -182,6 +182,10 @@ interface IAstVisitor {
|
||||
addressOf.arrayIndex?.accept(this)
|
||||
}
|
||||
|
||||
fun visit(addressOfMsb: AddressOfMsb) {
|
||||
addressOfMsb.identifier.accept(this)
|
||||
}
|
||||
|
||||
fun visit(inlineAssembly: InlineAssembly) {
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ Data types
|
||||
- strings and arrays are allocated once, statically, and never resized.
|
||||
- strings and arrays are mutable: you can change their contents, but always keep the original storage size in mind to avoid overwriting memory outside of the buffer.
|
||||
- maximum string length is 255 characters + a trailing 0 byte.
|
||||
- word arrays are split into 2 separate arrays by default (this is configurable): one for the LSBs and one for the MSBs of the words. This enables efficient 6502 instructions to access the words.
|
||||
- maximum storage size for arrays is 256 bytes (512 for split word arrays) , the maximum number of elements in the array depends on the size of a single element value.
|
||||
you can use larger "arrays" via pointer indexing, see below at Pointers. One way of obtaining a piece of memory to store
|
||||
such an "array" is by using ``memory()`` builtin function.
|
||||
|
@ -123,6 +123,8 @@ peek (address)
|
||||
|
||||
peekw (address)
|
||||
reads the word value at the given address in memory. Word is read as usual little-endian lsb/msb byte order.
|
||||
Caution: when using peekw to get words out of an array pointer, make sure the array is *not* a split word array
|
||||
(peekw requires the LSB and MSB of the word value to be consecutive in memory).
|
||||
|
||||
peekf (address)
|
||||
reads the float value at the given address in memory. On CBM machines, this reads 5 bytes.
|
||||
|
@ -942,7 +942,7 @@ containment check: ``in``
|
||||
}
|
||||
|
||||
|
||||
address of: ``&``
|
||||
address of: ``&``, ``&<``, ``&>``
|
||||
This is a prefix operator that can be applied to a string or array variable or literal value.
|
||||
It results in the memory address (UWORD) of that string or array in memory: ``uword a = &stringvar``
|
||||
Sometimes the compiler silently inserts this operator to make it easier for instance
|
||||
@ -951,6 +951,11 @@ address of: ``&``
|
||||
it is a memory-mapped variable (for instance: ``&ubyte screencolor = $d021``). This is explained
|
||||
in the :ref:`variables` chapter.
|
||||
|
||||
``&<`` and ``&>`` are for use on split word arrays, they give you the address of the LSB byte array
|
||||
and MSB byte array separately, respectively. Note that ``&<`` is just the same as ``&`` in this case.
|
||||
For more details on split word arrays, see :ref:`arrayvars`.
|
||||
|
||||
|
||||
ternary:
|
||||
Prog8 doesn't have a ternary operator to choose one of two values (``x? y : z`` in many other languages)
|
||||
instead it provides this feature in the form of an *if expression*. See below under "Conditional Execution".
|
||||
|
@ -1,17 +1,14 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- add &< and &> operators to get the address of the lsb-array and msb-array, respectively.
|
||||
|
||||
- DONE: make word arrays split by default (remove @split tag) and use new @nosplit tag to make an array use the old storage format
|
||||
- DONE: make word arrays split by default and add new @nosplit tag to make an array use the old linear storage format
|
||||
- DONE: &splitarray will give you the start address of the lsb-array (which is immediately followed by the msb-array)
|
||||
- DONE: add &< and &> operators to get the address of the lsb-array and msb-array, respectively. (&< is just syntactic sugar for &)
|
||||
- DONE: invert -splitarrays command line option: -dontsplitarrays and remove "splitarrays" %option switch
|
||||
- DONE: added sprites.pos_batch_nosplit when the x/y arrays are linear instead of split word arrays
|
||||
- DONE: add palette.set_rgb_nosplit() and set_rbg_be_nosplit() for linear instead of split word arrays
|
||||
- DONE: removed anyall module
|
||||
- DONE: removed anyall module (unoptimized and didn't work on split arrays)
|
||||
- DONE: @split does now always splits a word array even when the dontsplit option is enabled (and @nosplit does the inverse)
|
||||
- update Syntax files + Document all of this (also that word arrays can then have length 256 by default as well, and that @nosplit will reduce it to half.) + warning about using peekw that it may depend on array storage format
|
||||
- also document that kernal routines such as FB_set_palette() expect a @nosplit word array otherwise colors turn up bad
|
||||
|
||||
- announce prog8 on the 6502.org site?
|
||||
|
||||
|
@ -258,6 +258,7 @@ You can use underscores to group digits in floating point literals to make long
|
||||
any underscores in the number are ignored by the compiler.
|
||||
For instance ``30_000.999_999`` is a valid floating point number 30000.999999.
|
||||
|
||||
.. _arrayvars:
|
||||
|
||||
Arrays
|
||||
^^^^^^
|
||||
@ -278,9 +279,11 @@ always have to be constants. Here are some examples of arrays::
|
||||
char = string[-2] ; the second-to-last character in the string (Python-style indexing from the end)
|
||||
|
||||
.. note::
|
||||
Right now, the array should be small enough to be indexable by a single byte index.
|
||||
This means byte arrays should be <= 256 elements, word arrays <= 128 elements (256 if
|
||||
it's a split array - see below), and float arrays <= 51 elements.
|
||||
To allow the 6502 CPU to efficiently access values in an array, the array should be small enough to be
|
||||
indexable by a single byte index.
|
||||
This means byte arrays should be <= 256 elements, word arrays <= 256 elements as well (if split, which
|
||||
is the default. When not split, the maximum length is 128. See below for details about this disctinction).t
|
||||
Float arrays should be <= 51 elements.
|
||||
|
||||
Arrays can be initialized with a range expression or an array literal value.
|
||||
You can write out such an initializer value over several lines if you want to improve readability.
|
||||
@ -302,6 +305,7 @@ Using the ``in`` operator you can easily check if a value is present in an array
|
||||
example: ``if choice in [1,2,3,4] {....}``
|
||||
|
||||
**Arrays at a specific memory location:**
|
||||
|
||||
Using the memory-mapped syntax it is possible to define an array to be located at a specific memory location.
|
||||
For instance to reference the first 5 rows of the Commodore 64's screen matrix as an array, you can define::
|
||||
|
||||
@ -312,6 +316,7 @@ This way you can set the second character on the second row from the top like th
|
||||
top5screenrows[41] = '!'
|
||||
|
||||
**Array indexing on a pointer variable:**
|
||||
|
||||
An uword variable can be used in limited scenarios as a 'pointer' to a byte in memory at a specific,
|
||||
dynamic, location. You can use array indexing on a pointer variable to use it as a byte array at
|
||||
a dynamic location in memory: currently this is equivalent to directly referencing the bytes in
|
||||
@ -321,16 +326,38 @@ Instead, it simply addresses memory that lies *before* the pointer variable.
|
||||
See also :ref:`pointervars`
|
||||
|
||||
**LSB/MSB split word arrays:**
|
||||
For (u)word arrays, you can make the compiler layout the array in memory as two separate arrays,
|
||||
one with the LSBs and one with the MSBs of the word values. This makes it more efficient to access
|
||||
values from the array (smaller and faster code). It also doubles the maximum size of the array from 128 words to 256 words!
|
||||
The ``@split`` tag should be added to the variable declaration to do this.
|
||||
In the assembly code, the array will then be generated as two byte arrays namely ``name_lsb`` and ``name_msb``.
|
||||
|
||||
As an optimization, (u)word arrays are split by the compiler in memory as two separate arrays,
|
||||
one with the LSBs and one with the MSBs of the word values. This is more efficient to access by the 6502 cpu.
|
||||
It also enables a maximum length of 256 for word arrays, where normally it would have been 128.
|
||||
In the assembly code, the array is generated as two byte arrays namely ``name_lsb`` and ``name_msb``, immediately following eachother in memory.
|
||||
|
||||
The ``@split`` tag can be added to the variable declaration to *always* split the array even when the command line option -dontsplitarrays is set
|
||||
The ``@nosplit`` tag can be added to the variable declaration to *never* split the array. This is useful for compatibility with
|
||||
code that expects the words to be sequentially in memory (such as the cx16.FB_set_palette routine).
|
||||
|
||||
There is a command line option ``-dontsplitarrays`` that avoids splitting word arrays by default,
|
||||
so every word array is layed out sequentially in memory (this is what older versions of Prog8 used to do).immediately
|
||||
It reduces the maximum word array length to 128. You can still override this by adding ``@split`` explicitly.
|
||||
|
||||
.. note::
|
||||
Most but not all array operations are supported yet on "split word arrays".
|
||||
If you get a compiler error message, simply revert to a regular sequential word array using ``@nosplit``,
|
||||
and please report the issue.
|
||||
|
||||
.. note::
|
||||
Array literals are stored as split arrays if they're initializing a split word array, otherwise,
|
||||
they are stored as sequential words! So if you pass one directly to a subroutine (like ``func([1111,2222,3333])``),
|
||||
the array values are sequential in memory. If this is undesiarable (i.e. the subroutine expects a split word array),
|
||||
you have to create a normal array variable first and then pass that to the subroutine.
|
||||
|
||||
.. caution::
|
||||
Not all array operations are supported yet on "split word arrays".
|
||||
If you get an error message, simply revert to a regular word array and please report the issue,
|
||||
so that more support can be added in the future where it is needed.
|
||||
Be aware that the default is to split word arrays. Normal array access is taken care of by Prog8, so you won't
|
||||
notice this optimization. However if you are accessing the array's values using other ways (for example via a pointer,
|
||||
and then using ``peekw`` to get the value) you have to be aware of this. In that ``peekw`` example you have
|
||||
to make sure to use ``@nosplit`` on the word array so that the words stay sequentially in memory which is what ``peekw`` needs.
|
||||
Also be careful when passing arrays to library routines (this is via a pointer!): you have to make sure
|
||||
the library routine can deal with the split array otherwise you have to use ``@nosplit`` as well.
|
||||
|
||||
|
||||
.. _encodings:
|
||||
|
@ -4,15 +4,14 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
uword[] @split splitarray = [1000,2000,3000]
|
||||
uword[] @nosplit nosplitarray = [1001,2002,3003]
|
||||
uword[] wordarray = [1111,2222,3333]
|
||||
uword[] @split targetcolors = [$f00] * 16
|
||||
uword[] @nosplit xtargetcolors = [$f00] * 16
|
||||
|
||||
txt.print_uw(splitarray[2])
|
||||
txt.spc()
|
||||
txt.print_uw(nosplitarray[2])
|
||||
txt.spc()
|
||||
txt.print_uw(wordarray[2])
|
||||
txt.print_uwhex(&targetcolors, true)
|
||||
txt.nl()
|
||||
txt.print_uwhex(&<targetcolors, true)
|
||||
txt.nl()
|
||||
txt.print_uwhex(&>targetcolors, true)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ DEC_INTEGER : DEC_DIGIT (DEC_DIGIT | '_')* ;
|
||||
HEX_INTEGER : '$' HEX_DIGIT (HEX_DIGIT | '_')* ;
|
||||
BIN_INTEGER : '%' BIN_DIGIT (BIN_DIGIT | '_')* ;
|
||||
ADDRESS_OF: '&' ;
|
||||
ADDRESS_OF_MSB: '&>' ;
|
||||
ADDRESS_OF_LSB: '&<' ;
|
||||
INVALID_AND_COMPOSITE: '&&' ;
|
||||
|
||||
fragment HEX_DIGIT: ('a'..'f') | ('A'..'F') | ('0'..'9') ;
|
||||
@ -230,7 +232,7 @@ typecast : 'as' datatype;
|
||||
|
||||
directmemory : '@' '(' expression ')';
|
||||
|
||||
addressof : <assoc=right> ADDRESS_OF (scoped_identifier | arrayindexed) ;
|
||||
addressof : <assoc=right> (ADDRESS_OF | ADDRESS_OF_LSB | ADDRESS_OF_MSB) (scoped_identifier | arrayindexed) ;
|
||||
|
||||
functioncall : scoped_identifier '(' expression_list? ')' ;
|
||||
|
||||
|
@ -11,8 +11,8 @@
|
||||
<option name="HAS_PARENS" value="true" />
|
||||
<option name="HAS_STRING_ESCAPES" value="true" />
|
||||
</options>
|
||||
<keywords keywords="&;->;@;alias;and;as;asmsub;break;clobbers;continue;do;downto;else;extsub;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;step;sub;to;true;unroll;until;when;while;xor;~" ignore_case="false" />
|
||||
<keywords2 keywords="%address;%align;%asm;%asmbinary;%asminclude;%breakpoint;%encoding;%import;%ir;%launcher;%memtop;%option;%output;%zeropage;%zpallowed;%zpreserved;@align64;@alignpage;@alignword;@bank;@dirty;@nozp;@requirezp;@shared;@split;@zp;atascii:;cp437:;default:;iso16:;iso5:;iso:;kata:;petscii:;sc:" />
|
||||
<keywords keywords="&;&<;&>;->;@;alias;and;as;asmsub;break;clobbers;continue;do;downto;else;extsub;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;step;sub;to;true;unroll;until;when;while;xor;~" ignore_case="false" />
|
||||
<keywords2 keywords="%address;%align;%asm;%asmbinary;%asminclude;%breakpoint;%encoding;%import;%ir;%launcher;%memtop;%option;%output;%zeropage;%zpallowed;%zpreserved;@align64;@alignpage;@alignword;@bank;@dirty;@nosplit;@nozp;@requirezp;@shared;@split;@zp;atascii:;cp437:;default:;iso16:;iso5:;iso:;kata:;petscii:;sc:" />
|
||||
<keywords3 keywords="bool;byte;const;float;long;str;ubyte;uword;void;word" />
|
||||
<keywords4 keywords="abs;call;callfar;callfar2;clamp;cmp;defer;divmod;len;lsb;lsw;max;memory;min;mkword;msb;msw;peek;peekf;peekw;poke;pokef;pokew;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;setlsb;setmsb;sgn;sizeof;sqrt" />
|
||||
</highlighting>
|
||||
|
@ -13,7 +13,7 @@
|
||||
<Keywords name="Numbers, suffix1"></Keywords>
|
||||
<Keywords name="Numbers, suffix2"></Keywords>
|
||||
<Keywords name="Numbers, range"></Keywords>
|
||||
<Keywords name="Operators1">@ & | ^ ~ >> << += -= *= = **= &= |= ^= <<= >>= -> = == != < > <= >= , + ++ - -- * ** / ( ) [ ]</Keywords>
|
||||
<Keywords name="Operators1">@ & &< &> | ^ ~ >> << += -= *= = **= &= |= ^= <<= >>= -> = == != < > <= >= , + ++ - -- * ** / ( ) [ ]</Keywords>
|
||||
<Keywords name="Operators2"></Keywords>
|
||||
<Keywords name="Folders in code1, open">{ {{</Keywords>
|
||||
<Keywords name="Folders in code1, middle"></Keywords>
|
||||
@ -24,7 +24,7 @@
|
||||
<Keywords name="Folders in comment, open"></Keywords>
|
||||
<Keywords name="Folders in comment, middle"></Keywords>
|
||||
<Keywords name="Folders in comment, close"></Keywords>
|
||||
<Keywords name="Keywords1">void const
str
byte ubyte bool
long word uword
float
zp shared split requirezp nozp</Keywords>
|
||||
<Keywords name="Keywords1">void const
str
byte ubyte bool
long word uword
float
zp shared split nosplit requirezp nozp</Keywords>
|
||||
<Keywords name="Keywords2">%address
%asm
%ir
%asmbinary
%asminclude
%align
%breakpoint
%encoding
%import
%memtop
%launcher
%option
%output
%zeropage
%zpreserved
%zpallowed</Keywords>
|
||||
<Keywords name="Keywords3">inline sub asmsub extsub
clobbers
asm
if
when else
if_cc if_cs if_eq if_mi if_neg if_nz if_pl if_pos if_vc if_vs if_z
for in step do while repeat unroll
break continue return goto</Keywords>
|
||||
<Keywords name="Keywords4">alias abs call callfar callfar2 clamp cmp defer divmod len lsb lsw lsl lsr memory mkword min max msb msw peek peekw peekf poke pokew pokef rsave rsavex rrestore rrestorex rnd rndw rol rol2 ror ror2 setlsb setmsb sgn sizeof sqrtw</Keywords>
|
||||
|
@ -43,7 +43,7 @@ syn region prog8ArrayType matchgroup=prog8Type
|
||||
\ start="\<\%(u\?byte\|u\?word\|float\|str\|bool\)\[" end="\]"
|
||||
\ transparent
|
||||
syn keyword prog8StorageClass const
|
||||
syn match prog8StorageClass "\(^\|\s\)\(@zp\|@bank\|@shared\|@split\|@nozp\|@requirezp\|@align64\|@alignword\|@alignpage\|@dirty\)\>"
|
||||
syn match prog8StorageClass "\(^\|\s\)\(@zp\|@bank\|@shared\|@split\|@nosplit\|@nozp\|@requirezp\|@align64\|@alignword\|@alignpage\|@dirty\)\>"
|
||||
|
||||
syn region prog8Block start="{" end="}" transparent
|
||||
syn region prog8Expression start="(" end=")" transparent
|
||||
|
Loading…
Reference in New Issue
Block a user