mirror of
https://github.com/irmen/prog8.git
synced 2026-10-22 20:02:27 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47dbafacd4 | ||
|
|
5b6811d073 | ||
|
|
7516116bb7 | ||
|
|
e6014ea4dd | ||
|
|
362abfe284 | ||
|
|
ad4880997a | ||
|
|
592becc126 | ||
|
|
c38765301e | ||
|
|
5f27426f59 | ||
|
|
d924f8bff8 | ||
|
|
d14c61b160 |
No files matched your search
@@ -35,13 +35,17 @@ jobs:
|
||||
name: prog8-compiler-jar-zipped
|
||||
path: compiler/build/libs/*-all.jar
|
||||
|
||||
- uses: MCJack123/ghaction-generate-release-hashes@v4
|
||||
if: "github.event_name == 'release'"
|
||||
- name: Calculate hash
|
||||
uses: MCJack123/ghaction-generate-release-hashes@v4
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
hash-type: sha256
|
||||
file-name: hashes.txt
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: "github.event_name == 'release'"
|
||||
get-assets: true
|
||||
hash-type: sha256
|
||||
file-name: hashes.txt
|
||||
|
||||
- name: Upload hashes
|
||||
uses: actions/upload-artifact@v4
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
name: Artifact Hashes
|
||||
path: hashes.txt
|
||||
name: Artifact Hashes
|
||||
path: hashes.txt
|
||||
@@ -1,6 +1,6 @@
|
||||
package prog8.code.core
|
||||
|
||||
val AssociativeOperators = setOf("+", "*", "&", "|", "^", "==", "!=", "and", "or", "xor")
|
||||
val AssociativeOperators = setOf("+", "*", "&", "|", "^", "==", "!=", "xor") // note: and,or are no longer associative because of Shortcircuit/McCarthy evaluation
|
||||
val ComparisonOperators = setOf("==", "!=", "<", ">", "<=", ">=")
|
||||
val LogicalOperators = setOf("and", "or", "xor", "not", "in")
|
||||
val BitwiseOperators = setOf("&", "|", "^", "~")
|
||||
|
||||
@@ -4,7 +4,6 @@ import prog8.ast.*
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.AnonymousScope
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.statements.IfElse
|
||||
import prog8.ast.statements.Jump
|
||||
import prog8.ast.walk.AstWalker
|
||||
@@ -109,12 +108,6 @@ class ExpressionSimplifier(private val program: Program, private val options: Co
|
||||
if (!leftIDt.isKnown || !rightIDt.isKnown)
|
||||
throw FatalAstException("can't determine datatype of both expression operands $expr")
|
||||
|
||||
// NonBinaryExpression <associativeoperator> BinaryExpression --> BinaryExpression <associativeoperator> NonBinaryExpression
|
||||
if (expr.operator in AssociativeOperators && expr.left !is BinaryExpression && expr.right is BinaryExpression) {
|
||||
if(parent !is Assignment || !(expr.left isSameAs parent.target) && maySwapOperandOrder(expr))
|
||||
return listOf(IAstModification.SwapOperands(expr))
|
||||
}
|
||||
|
||||
// X + (-A) --> X - A
|
||||
if (expr.operator == "+" && (expr.right as? PrefixExpression)?.operator == "-") {
|
||||
return listOf(IAstModification.ReplaceNode(
|
||||
|
||||
@@ -55,9 +55,11 @@ gfx2 {
|
||||
}
|
||||
else -> {
|
||||
; back to default text mode
|
||||
cx16.r15L = cx16.VERA_DC_VIDEO & %00000111 ; retain chroma + output mode
|
||||
cbm.CINT()
|
||||
cx16.VERA_DC_VIDEO = (cx16.VERA_DC_VIDEO & %11111000) | cx16.r15L
|
||||
if active_mode!=0 {
|
||||
cx16.r15L = cx16.VERA_DC_VIDEO & %00000111 ; retain chroma + output mode
|
||||
cbm.CINT()
|
||||
cx16.VERA_DC_VIDEO = (cx16.VERA_DC_VIDEO & %11111000) | cx16.r15L
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,4 +76,44 @@ string {
|
||||
return s+cx16.r0L
|
||||
}
|
||||
|
||||
sub startswith(str st, str prefix) -> bool {
|
||||
ubyte prefix_len = string.length(prefix)
|
||||
ubyte str_len = string.length(st)
|
||||
if prefix_len > str_len
|
||||
return false
|
||||
cx16.r9L = st[prefix_len]
|
||||
st[prefix_len] = 0
|
||||
cx16.r9H = string.compare(st, prefix) as ubyte
|
||||
st[prefix_len] = cx16.r9L
|
||||
return cx16.r9H==0
|
||||
}
|
||||
|
||||
sub endswith(str st, str suffix) -> bool {
|
||||
ubyte suffix_len = string.length(suffix)
|
||||
ubyte str_len = string.length(st)
|
||||
if suffix_len > str_len
|
||||
return false
|
||||
return string.compare(st + str_len - suffix_len, suffix) == 0
|
||||
}
|
||||
|
||||
sub findstr(str haystack, str needle) -> ubyte {
|
||||
; searches for needle in haystack.
|
||||
; returns index in haystack where it first occurs, and Carry set,
|
||||
; or if needle doesn't occur in haystack it returns Carry clear and 255 (an invalid index.)
|
||||
cx16.r2L = string.length(haystack)
|
||||
cx16.r3L = string.length(needle)
|
||||
if cx16.r3L <= cx16.r2L {
|
||||
cx16.r2L = cx16.r2L-cx16.r3L+1
|
||||
cx16.r3 = haystack
|
||||
repeat cx16.r2L {
|
||||
if string.startswith(cx16.r3, needle) {
|
||||
sys.set_carry()
|
||||
return cx16.r3-haystack as ubyte
|
||||
}
|
||||
cx16.r3++
|
||||
}
|
||||
}
|
||||
sys.clear_carry()
|
||||
return 255
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@ _startloop dey
|
||||
|
||||
asmsub find(uword string @AY, ubyte character @X) -> ubyte @A, bool @Pc {
|
||||
; Locates the first position of the given character in the string,
|
||||
; returns Carry set if found + index in A, or A=0 + Carry clear if not found.
|
||||
; returns Carry set if found + index in A, or Carry clear if not found (and A will be 255, an invalid index).
|
||||
%asm {{
|
||||
; need to copy the the cx16 virtual registers to zeropage to make this run on C64...
|
||||
sta P8ZP_SCRATCH_W1
|
||||
@@ -142,7 +142,7 @@ _startloop dey
|
||||
beq _found
|
||||
iny
|
||||
bne -
|
||||
_notfound lda #0
|
||||
_notfound lda #255
|
||||
clc
|
||||
rts
|
||||
_found tya
|
||||
@@ -277,26 +277,6 @@ _done rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub startswith(str st, str prefix) -> bool {
|
||||
ubyte prefix_len = length(prefix)
|
||||
ubyte str_len = length(st)
|
||||
if prefix_len > str_len
|
||||
return false
|
||||
cx16.r9L = st[prefix_len]
|
||||
st[prefix_len] = 0
|
||||
cx16.r9H = compare(st, prefix) as ubyte
|
||||
st[prefix_len] = cx16.r9L
|
||||
return cx16.r9H==0
|
||||
}
|
||||
|
||||
sub endswith(str st, str suffix) -> bool {
|
||||
ubyte suffix_len = length(suffix)
|
||||
ubyte str_len = length(st)
|
||||
if suffix_len > str_len
|
||||
return false
|
||||
return compare(st + str_len - suffix_len, suffix) == 0
|
||||
}
|
||||
|
||||
asmsub pattern_match(str string @AY, str pattern @R0) clobbers(Y) -> bool @A {
|
||||
%asm {{
|
||||
; pattern matching of a string.
|
||||
@@ -366,7 +346,6 @@ fail clc ; yes, no match found, return with c=0
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
asmsub hash(str string @R0) -> ubyte @A {
|
||||
; experimental 8 bit hashing function.
|
||||
; hash(-1)=179; clear carry; hash(i) = ROL hash(i-1) XOR string[i]
|
||||
|
||||
@@ -55,7 +55,7 @@ string {
|
||||
|
||||
sub find(str st, ubyte character) -> ubyte {
|
||||
; Locates the first position of the given character in the string,
|
||||
; returns Carry set if found + index in A, or Carry clear if not found.
|
||||
; returns Carry set if found + index in A, or Carry clear if not found (and A will be 255, an invalid index).
|
||||
ubyte ix
|
||||
for ix in 0 to length(st)-1 {
|
||||
if st[ix]==character {
|
||||
@@ -64,7 +64,7 @@ string {
|
||||
}
|
||||
}
|
||||
sys.clear_carry()
|
||||
return 0
|
||||
return 255
|
||||
}
|
||||
|
||||
sub contains(str st, ubyte character) -> bool {
|
||||
@@ -147,26 +147,6 @@ string {
|
||||
return char
|
||||
}
|
||||
|
||||
sub startswith(str st, str prefix) -> bool {
|
||||
ubyte prefix_len = length(prefix)
|
||||
ubyte str_len = length(st)
|
||||
if prefix_len > str_len
|
||||
return false
|
||||
cx16.r9L = st[prefix_len]
|
||||
st[prefix_len] = 0
|
||||
cx16.r9H = compare(st, prefix) as ubyte
|
||||
st[prefix_len] = cx16.r9L
|
||||
return cx16.r9H==0
|
||||
}
|
||||
|
||||
sub endswith(str st, str suffix) -> bool {
|
||||
ubyte suffix_len = length(suffix)
|
||||
ubyte str_len = length(st)
|
||||
if suffix_len > str_len
|
||||
return false
|
||||
return compare(st + str_len - suffix_len, suffix) == 0
|
||||
}
|
||||
|
||||
sub hash(str st) -> ubyte {
|
||||
; experimental 8 bit hashing function.
|
||||
; hash(-1)=179; hash(i) = ROL hash(i-1) XOR string[i]
|
||||
|
||||
@@ -825,7 +825,7 @@ internal class AstChecker(private val program: Program,
|
||||
err("invalid import directive, cannot import itself")
|
||||
}
|
||||
"%breakpoint" -> {
|
||||
if(directive.parent !is INameScope || directive.parent is Module)
|
||||
if(directive.parent !is INameScope && directive.parent !is AnonymousScope || directive.parent is Module)
|
||||
err("this directive can't be used here")
|
||||
if(directive.args.isNotEmpty())
|
||||
err("invalid breakpoint directive, expected no arguments")
|
||||
|
||||
@@ -214,8 +214,12 @@ internal class StatementReorderer(
|
||||
}
|
||||
}
|
||||
|
||||
if(valueType.isString && (targetType istype DataType.STR || targetType istype DataType.ARRAY_B || targetType istype DataType.ARRAY_UB))
|
||||
return copyStringValue(assignment)
|
||||
if(!assignment.isAugmentable) {
|
||||
if (valueType.isString && (targetType istype DataType.STR || targetType istype DataType.ARRAY_B || targetType istype DataType.ARRAY_UB)) {
|
||||
// replace string assignment by a call to stringcopy
|
||||
return copyStringValue(assignment)
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
@@ -935,4 +935,41 @@ main {
|
||||
funcarg3.target.nameInSource shouldBe listOf("msb")
|
||||
funcarg3.args.single() shouldBe instanceOf<BinaryExpression>()
|
||||
}
|
||||
|
||||
test("no operand swap on logical expressions with shortcircuit evaluation") {
|
||||
val src="""
|
||||
%import diskio
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
str scanline_buf = "?"* 20
|
||||
|
||||
sub start() {
|
||||
if diskio.f_open("test.prg") and diskio.f_read(scanline_buf, 2)==2
|
||||
cx16.r0++
|
||||
|
||||
if diskio.f_open("test.prg") or diskio.f_read(scanline_buf, 2)==2
|
||||
cx16.r0++
|
||||
|
||||
if diskio.f_open("test.prg") xor diskio.f_read(scanline_buf, 2)==2
|
||||
cx16.r0++
|
||||
}
|
||||
}"""
|
||||
val result = compileText(Cx16Target(), true, src, writeAssembly = false)!!
|
||||
val st = result.compilerAst.entrypoint.statements
|
||||
st.size shouldBe 3
|
||||
val ifCond1 = (st[0] as IfElse).condition as BinaryExpression
|
||||
val ifCond2 = (st[1] as IfElse).condition as BinaryExpression
|
||||
val ifCond3 = (st[2] as IfElse).condition as BinaryExpression
|
||||
(ifCond1.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_open")
|
||||
(ifCond2.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_open")
|
||||
(ifCond3.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_open")
|
||||
val right1 = ifCond1.right as BinaryExpression
|
||||
val right2 = ifCond2.right as BinaryExpression
|
||||
val right3 = ifCond3.right as BinaryExpression
|
||||
(right1.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_read")
|
||||
(right2.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_read")
|
||||
(right3.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_read")
|
||||
}
|
||||
})
|
||||
@@ -238,7 +238,6 @@ Directives
|
||||
Level: not at module scope.
|
||||
Declares that a piece of *assembly code* is inside the curly braces.
|
||||
This code will be copied as-is into the generated output assembly source file.
|
||||
The assembler syntax used should be for the 3rd party cross assembler tool that Prog8 uses (64tass).
|
||||
Note that the start and end markers are both *double curly braces* to minimize the chance
|
||||
that the assembly code itself contains either of those. If it does contain a ``}}``,
|
||||
it will confuse the parser.
|
||||
@@ -247,6 +246,9 @@ Directives
|
||||
the assembly code. Sometimes you'll have to declare a variable in prog8 with `@shared` if it
|
||||
is only used in such assembly code.
|
||||
|
||||
.. note::
|
||||
64tass syntax is required for the assembly code. As such, mnemonics need to be written in lowercase.
|
||||
|
||||
.. caution::
|
||||
Avoid using single-letter symbols in included assembly code, as they could be confused with CPU registers.
|
||||
Also, note that all prog8 symbols are prefixed in assembly code, see :ref:`symbol-prefixing`.
|
||||
|
||||
+9
-13
@@ -1,22 +1,18 @@
|
||||
%import textio
|
||||
%import diskio
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
str scanline_buf = "?"* 20
|
||||
|
||||
sub start() {
|
||||
ubyte[] ubarray = [11,22,33]
|
||||
uword[] uwarray = [1111,2222,3333]
|
||||
uword[] @split suwarray = [1111,2222,3333]
|
||||
if diskio.f_open("test.prg") and diskio.f_read(scanline_buf, 2)==2
|
||||
cx16.r0++
|
||||
|
||||
ubarray[1] *= 10
|
||||
uwarray[1] *= 10
|
||||
suwarray[1] *= 10
|
||||
if diskio.f_open("test.prg") or diskio.f_read(scanline_buf, 2)==2
|
||||
cx16.r0++
|
||||
|
||||
txt.print_ub(ubarray[1])
|
||||
txt.nl()
|
||||
txt.print_uw(uwarray[1])
|
||||
txt.nl()
|
||||
txt.print_uw(suwarray[1])
|
||||
txt.nl()
|
||||
if diskio.f_open("test.prg") xor diskio.f_read(scanline_buf, 2)==2
|
||||
cx16.r0++
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -5,4 +5,4 @@ org.gradle.daemon=true
|
||||
kotlin.code.style=official
|
||||
javaVersion=11
|
||||
kotlinVersion=1.9.22
|
||||
version=10.2
|
||||
version=10.2.1
|
||||
Reference in new issue
Block a user