mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
concerns with in
for strings
This commit is contained in:
parent
e98e951834
commit
08a079a96e
@ -12,10 +12,11 @@ import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.AssociativeOperators
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.IErrorReporter
|
||||
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> {
|
||||
// @( &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) {
|
||||
// mutiply a string.
|
||||
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)
|
||||
return listOf(IAstModification.ReplaceNode(expr, newStr, parent))
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilationTarget)
|
||||
if(errors.noErrors()) {
|
||||
valuetypefixer.applyModifications()
|
||||
|
||||
val optimizer = ConstantFoldingOptimizer(this)
|
||||
val optimizer = ConstantFoldingOptimizer(this, errors)
|
||||
optimizer.visit(this)
|
||||
while (errors.noErrors() && optimizer.applyModifications() > 0) {
|
||||
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))
|
||||
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 {
|
||||
|
@ -928,7 +928,7 @@ internal class AstChecker(private val program: Program,
|
||||
try { // just *try* if it can be encoded, don't actually do it
|
||||
val bytes = compilerOptions.compTarget.encodeString(string.value, string.encoding)
|
||||
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) {
|
||||
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::
|
||||
|
||||
$ ./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``
|
||||
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.
|
||||
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``
|
||||
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>`_
|
||||
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")
|
||||
}
|
||||
|
||||
.. 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: ``&``
|
||||
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``
|
||||
|
@ -2,6 +2,9 @@
|
||||
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 ....
|
||||
|
||||
...
|
||||
@ -25,6 +28,11 @@ Compiler:
|
||||
- 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)
|
||||
|
||||
- [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?
|
||||
- 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
|
||||
@ -78,6 +86,5 @@ What if we were to re-introduce Structs in prog8? Some thoughts:
|
||||
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)
|
||||
- postincrdecr as expression, preincrdecr expression (`y = x++`, `y = ++x`) .... is this even possible, expression with side effects like this?
|
||||
- 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)
|
||||
- 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
|
||||
javaVersion=11
|
||||
kotlinVersion=1.9.20
|
||||
version=9.7
|
||||
version=9.8-SNAPSHOT
|
||||
|
Loading…
x
Reference in New Issue
Block a user