mirror of
https://github.com/irmen/prog8.git
synced 2025-08-15 14:27:37 +00:00
concerns with in
for strings
This commit is contained in:
@@ -12,10 +12,11 @@ import prog8.ast.walk.AstWalker
|
|||||||
import prog8.ast.walk.IAstModification
|
import prog8.ast.walk.IAstModification
|
||||||
import prog8.code.core.AssociativeOperators
|
import prog8.code.core.AssociativeOperators
|
||||||
import prog8.code.core.DataType
|
import prog8.code.core.DataType
|
||||||
|
import prog8.code.core.IErrorReporter
|
||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
|
|
||||||
|
|
||||||
class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
|
class ConstantFoldingOptimizer(private val program: Program, private val errors: IErrorReporter) : AstWalker() {
|
||||||
|
|
||||||
override fun before(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> {
|
override fun before(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> {
|
||||||
// @( &thing ) --> thing (but only if thing is a byte type!)
|
// @( &thing ) --> thing (but only if thing is a byte type!)
|
||||||
@@ -79,6 +80,8 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
|
|||||||
else if(expr.operator=="*" && rightconst!=null && expr.left is StringLiteral) {
|
else if(expr.operator=="*" && rightconst!=null && expr.left is StringLiteral) {
|
||||||
// mutiply a string.
|
// mutiply a string.
|
||||||
val part = expr.left as StringLiteral
|
val part = expr.left as StringLiteral
|
||||||
|
if(part.value.isEmpty())
|
||||||
|
errors.warn("resulting string has length zero", part.position)
|
||||||
val newStr = StringLiteral(part.value.repeat(rightconst.number.toInt()), part.encoding, expr.position)
|
val newStr = StringLiteral(part.value.repeat(rightconst.number.toInt()), part.encoding, expr.position)
|
||||||
return listOf(IAstModification.ReplaceNode(expr, newStr, parent))
|
return listOf(IAstModification.ReplaceNode(expr, newStr, parent))
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilationTarget)
|
|||||||
if(errors.noErrors()) {
|
if(errors.noErrors()) {
|
||||||
valuetypefixer.applyModifications()
|
valuetypefixer.applyModifications()
|
||||||
|
|
||||||
val optimizer = ConstantFoldingOptimizer(this)
|
val optimizer = ConstantFoldingOptimizer(this, errors)
|
||||||
optimizer.visit(this)
|
optimizer.visit(this)
|
||||||
while (errors.noErrors() && optimizer.applyModifications() > 0) {
|
while (errors.noErrors() && optimizer.applyModifications() > 0) {
|
||||||
optimizer.visit(this)
|
optimizer.visit(this)
|
||||||
|
@@ -125,7 +125,7 @@ private fun builtinSizeof(args: List<Expression>, position: Position, program: P
|
|||||||
val elementDt = ArrayToElementTypes.getValue(dt.getOr(DataType.UNDEFINED))
|
val elementDt = ArrayToElementTypes.getValue(dt.getOr(DataType.UNDEFINED))
|
||||||
NumericLiteral.optimalInteger(program.memsizer.memorySize(elementDt) * length, position)
|
NumericLiteral.optimalInteger(program.memsizer.memorySize(elementDt) * length, position)
|
||||||
}
|
}
|
||||||
dt istype DataType.STR -> throw SyntaxError("sizeof str is undefined, did you mean len?", position)
|
dt istype DataType.STR -> throw SyntaxError("sizeof(str) is undefined, did you mean len, or perhaps string.length?", position)
|
||||||
else -> NumericLiteral(DataType.UBYTE, program.memsizer.memorySize(dt.getOr(DataType.UNDEFINED)).toDouble(), position)
|
else -> NumericLiteral(DataType.UBYTE, program.memsizer.memorySize(dt.getOr(DataType.UNDEFINED)).toDouble(), position)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -928,7 +928,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
try { // just *try* if it can be encoded, don't actually do it
|
try { // just *try* if it can be encoded, don't actually do it
|
||||||
val bytes = compilerOptions.compTarget.encodeString(string.value, string.encoding)
|
val bytes = compilerOptions.compTarget.encodeString(string.value, string.encoding)
|
||||||
if(0u in bytes)
|
if(0u in bytes)
|
||||||
errors.warn("a character in the string encodes into the 0-byte, which will terminate the string prematurely", string.position)
|
errors.warn("a character in the string encodes as 0-byte, which will terminate the string prematurely", string.position)
|
||||||
} catch (cx: CharConversionException) {
|
} catch (cx: CharConversionException) {
|
||||||
errors.err(cx.message ?: "can't encode string", string.position)
|
errors.err(cx.message ?: "can't encode string", string.position)
|
||||||
}
|
}
|
||||||
|
BIN
docs/source/_static/curious.png
Normal file
BIN
docs/source/_static/curious.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 126 KiB |
@@ -348,5 +348,5 @@ to compile and run the Commodore 64 rasterbars example program, use this command
|
|||||||
|
|
||||||
or::
|
or::
|
||||||
|
|
||||||
$ ./p8compile.sh -target c64 -emu examples/rasterbars.p8
|
$ /path/to/p8compile -target c64 -emu examples/rasterbars.p8
|
||||||
|
|
||||||
|
@@ -238,6 +238,11 @@ Provides string manipulation routines.
|
|||||||
``find (string, char) -> ubyte index + carry bit``
|
``find (string, char) -> ubyte index + carry bit``
|
||||||
Locates the first position of the given character in the string, returns carry bit set if found
|
Locates the first position of the given character in the string, returns carry bit set if found
|
||||||
and the index in the string. Or 0+carry bit clear if the character was not found.
|
and the index in the string. Or 0+carry bit clear if the character was not found.
|
||||||
|
You can consider this a safer way of checking if a character occurs
|
||||||
|
in a string than using an `in` containment check - because the find routine
|
||||||
|
properly stops at the first 0-byte string terminator it encounters.
|
||||||
|
Simply call this and only act on the carry status with ``if_cc`` for example.
|
||||||
|
Much like the difference between len(str) and length(str).
|
||||||
|
|
||||||
``compare (string1, string2) -> ubyte result``
|
``compare (string1, string2) -> ubyte result``
|
||||||
Returns -1, 0 or 1 depending on whether string1 sorts before, equal or after string2.
|
Returns -1, 0 or 1 depending on whether string1 sorts before, equal or after string2.
|
||||||
|
@@ -44,3 +44,7 @@ Various things:
|
|||||||
|
|
||||||
`Prog8 code for ZSMkit <https://github.com/mooinglemur/zsmkit/tree/main/p8demo>`_
|
`Prog8 code for ZSMkit <https://github.com/mooinglemur/zsmkit/tree/main/p8demo>`_
|
||||||
ZSMkit is an advanced music and sound effects engine for the Commander X16.
|
ZSMkit is an advanced music and sound effects engine for the Commander X16.
|
||||||
|
|
||||||
|
.. image:: _static/curious.png
|
||||||
|
:align: center
|
||||||
|
:alt: Curious
|
||||||
|
@@ -616,6 +616,12 @@ containment check: ``in``
|
|||||||
txt.print("email address seems ok")
|
txt.print("email address seems ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.. caution::
|
||||||
|
This check compares the needle against *all* elements in the haystack.
|
||||||
|
For byte arrays and strings(!), this means it considers *all* elements in the array or string with the length as it was declared.
|
||||||
|
Even when a string was changed and is terminated early with a 0-byte early.
|
||||||
|
Consider using ``string.find`` followed by ``if_cs`` (for instance) to do a "safer" containment check in such strings.
|
||||||
|
|
||||||
address of: ``&``
|
address of: ``&``
|
||||||
This is a prefix operator that can be applied to a string or array variable or literal value.
|
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``
|
It results in the memory address (UWORD) of that string or array in memory: ``uword a = &stringvar``
|
||||||
|
@@ -2,6 +2,9 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
|
- [on branch: call-pointers] allow calling a subroutine via a pointer variable (indirect JSR, optimized form of callfar())
|
||||||
|
modify programs (shell, paint) that now use callfar
|
||||||
|
|
||||||
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....
|
||||||
|
|
||||||
...
|
...
|
||||||
@@ -25,6 +28,11 @@ Compiler:
|
|||||||
- OR.... make all this more generic and use some %segment option to create real segments for 64tass?
|
- OR.... make all this more generic and use some %segment option to create real segments for 64tass?
|
||||||
- (need separate step in codegen and IR to write the "golden" variables)
|
- (need separate step in codegen and IR to write the "golden" variables)
|
||||||
|
|
||||||
|
- [on branch: no-vardecls]
|
||||||
|
remove astNode from StNode in the symboltable
|
||||||
|
remove IPtVariable and the 3 derived types (var, constant, memmapped) in the codegen ast
|
||||||
|
remove VarDecls in compiler ast
|
||||||
|
|
||||||
- do we need (array)variable alignment tag instead of block alignment tag? You want to align the data, not the code in the block?
|
- do we need (array)variable alignment tag instead of block alignment tag? You want to align the data, not the code in the block?
|
||||||
- ir: getting it in shape for code generation
|
- ir: getting it in shape for code generation
|
||||||
- ir: related to the one above: block alignment doesn't translate well to variables in the block (the actual stuff that needs to be aligned in memory) but: need variable alignment tag instead of block alignment tag, really
|
- ir: related to the one above: block alignment doesn't translate well to variables in the block (the actual stuff that needs to be aligned in memory) but: need variable alignment tag instead of block alignment tag, really
|
||||||
@@ -78,6 +86,5 @@ What if we were to re-introduce Structs in prog8? Some thoughts:
|
|||||||
Other language/syntax features to think about
|
Other language/syntax features to think about
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
- chained comparisons `10<x<20` , `x==y==z` (desugars to `10<x and x<20`, `x==y and y==z`) BUT this changes the semantics of what it is right now ! (x==(y==z) 0> x==true)
|
- chained comparisons `10<x<20` , `x==y==z` (desugars to `10<x and x<20`, `x==y and y==z`) BUT this changes the semantics of what it is right now ! (x==(y==z) --> x==true)
|
||||||
- postincrdecr as expression, preincrdecr expression (`y = x++`, `y = ++x`) .... is this even possible, expression with side effects like this?
|
|
||||||
- negative array index to refer to an element from the end of the array. Python `[-1]` or Raku syntax `[\*-1]` , `[\*/2]` .... \*=size of the array
|
- negative array index to refer to an element from the end of the array. Python `[-1]` or Raku syntax `[\*-1]` , `[\*/2]` .... \*=size of the array
|
||||||
|
@@ -5,4 +5,4 @@ org.gradle.daemon=true
|
|||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
javaVersion=11
|
javaVersion=11
|
||||||
kotlinVersion=1.9.20
|
kotlinVersion=1.9.20
|
||||||
version=9.7
|
version=9.8-SNAPSHOT
|
||||||
|
Reference in New Issue
Block a user