From 3280993e2acc8a7fb57d998cef9fc6d47812b6d0 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 2 Jun 2020 21:27:38 +0200 Subject: [PATCH] stricter type checking in assignments (less implicit typecasts) --- .../prog8/ast/processing/TypecastsAdder.kt | 4 +- .../prog8/optimizer/ExpressionSimplifier.kt | 2 + examples/c64graphics.p8 | 177 ++++++++++++------ examples/line-circle-txt.p8 | 8 +- examples/strings.p8 | 36 ++++ examples/test.p8 | 54 ++++-- 6 files changed, 202 insertions(+), 79 deletions(-) create mode 100644 examples/strings.p8 diff --git a/compiler/src/prog8/ast/processing/TypecastsAdder.kt b/compiler/src/prog8/ast/processing/TypecastsAdder.kt index 9c3b841df..b014979f6 100644 --- a/compiler/src/prog8/ast/processing/TypecastsAdder.kt +++ b/compiler/src/prog8/ast/processing/TypecastsAdder.kt @@ -42,13 +42,11 @@ class TypecastsAdder(val program: Program, val errors: ErrorReporter) : AstWalke if(targetItype.isKnown && valueItype.isKnown) { val targettype = targetItype.typeOrElse(DataType.STRUCT) val valuetype = valueItype.typeOrElse(DataType.STRUCT) - if (valuetype != targettype) { - if(valuetype.isAssignableTo(targettype)) { + if (valuetype != targettype && valuetype isAssignableTo targettype) { return listOf(IAstModification.ReplaceNode( assignment.value, TypecastExpression(assignment.value, targettype, true, assignment.value.position), assignment)) - } } } return emptyList() diff --git a/compiler/src/prog8/optimizer/ExpressionSimplifier.kt b/compiler/src/prog8/optimizer/ExpressionSimplifier.kt index 7bdb25df1..9332f4b36 100644 --- a/compiler/src/prog8/optimizer/ExpressionSimplifier.kt +++ b/compiler/src/prog8/optimizer/ExpressionSimplifier.kt @@ -19,6 +19,8 @@ import kotlin.math.pow x + x + x -> ???? x*3 ??? words/bytes? x - x -> 0 + x < 0 (for word, byte as well?): just test the most significant bit for 1 + x >= 0 (for word, byte as well?): just test the most significant bit for 0 Investigate what optimizations binaryen has, also see https://egorbo.com/peephole-optimizations.html diff --git a/examples/c64graphics.p8 b/examples/c64graphics.p8 index 7f9e7d1b5..84d14321f 100644 --- a/examples/c64graphics.p8 +++ b/examples/c64graphics.p8 @@ -17,79 +17,134 @@ graphics { c64scr.clear_screen($10, 0) ; pixel color $1 (white) backround $0 (black) } - sub line(uword x1, ubyte y1, uword x2, ubyte y2) { ; Bresenham algorithm - word dx - word dy - byte ix = 1 - byte iy = 1 - if x2>x1 { - dx = x2-x1 - } else { - ix = -1 - dx = x1-x2 - } - if y2>y1 { - dy = y2-y1 - } else { - iy = -1 - dy = y1-y2 - } - word dx2 = 2 * dx - word dy2 = 2 * dy + ; This code is a bit long because each of the 8 different octants has a dedicated loop. + ; This minimizes the number of actual math operations, and allows usins simple ++ and -- operations. + ; TODO sort X/Y coordinates to eliminate some of the special cases word d = 0 + ubyte positive_ix = true + ubyte positive_iy = true + word dx = x2 - x1 as word + word dy = y2 as word - y1 as word + if dx < 0 { + dx = -dx + positive_ix = false + } + if dy < 0 { + dy = -dy + positive_iy = false + } + dx *= 2 + dy *= 2 plotx = x1 if dx >= dy { - if ix<0 { - forever { - graphics.plot(y1) - if plotx==x2 - return - plotx-- - d += dy2 - if d > dx { - y1 += iy - d -= dx2 + if positive_ix { + if positive_iy { + forever { + graphics.plot(y1) + if plotx==x2 + return + plotx++ + d += dy + if d > dx { + y1++ + d -= dx + } + } + } else { + forever { + graphics.plot(y1) + if plotx==x2 + return + plotx++ + d += dy + if d > dx { + y1-- + d -= dx + } } } } else { - forever { - graphics.plot(y1) - if plotx==x2 - return - plotx++ - d += dy2 - if d > dx { - y1 += iy - d -= dx2 + if positive_iy { + forever { + graphics.plot(y1) + if plotx==x2 + return + plotx-- + d += dy + if d > dx { + y1++ + d -= dx + } + } + } else { + forever { + graphics.plot(y1) + if plotx==x2 + return + plotx-- + d += dy + if d > dx { + y1-- + d -= dx + } } } } - } else { - if iy<0 { - forever { - plot(y1) - if y1 == y2 - return - y1-- - d += dx2 - if d > dy { - plotx += ix as word - d -= dy2 + } + else { + if positive_iy { + if positive_ix { + forever { + plot(y1) + if y1 == y2 + return + y1++ + d += dx + if d > dy { + plotx++ + d -= dy + } + } + } else { + forever { + plot(y1) + if y1 == y2 + return + y1++ + d += dx + if d > dy { + plotx-- + d -= dy + } } } } else { - forever { - plot(y1) - if y1 == y2 - return - y1++ - d += dx2 - if d > dy { - plotx += ix as word - d -= dy2 + if positive_ix { + forever { + plot(y1) + if y1 == y2 + return + y1-- + d += dx + if d > dy { + plotx++ + d -= dy + } + } + } else { + forever { + plot(y1) + if y1 == y2 + return + y1-- + d += dx + if d > dy { + plotx-- + d -= dy + } } } } @@ -101,7 +156,7 @@ graphics { ubyte ploty ubyte xx = radius ubyte yy = 0 - byte decisionOver2 = 1-xx + byte decisionOver2 = 1-xx as byte while xx>=yy { plotx = xcenter + xx @@ -138,7 +193,7 @@ graphics { ; Midpoint algorithm, filled ubyte xx = radius ubyte yy = 0 - byte decisionOver2 = 1-xx + byte decisionOver2 = 1-xx as byte while xx>=yy { ubyte cy_plus_yy = cy + yy @@ -180,7 +235,7 @@ graphics { ; @(addr) |= ormask[lsb(px) & 7] ; } - uword plotx ; 0..319 + uword plotx ; 0..319 ; separate 'parameter' for plot() asmsub plot(ubyte ploty @A) { ; plotx is 16 bits 0 to 319... doesn't fit in a register %asm {{ diff --git a/examples/line-circle-txt.p8 b/examples/line-circle-txt.p8 index 091444335..366dc6b4a 100644 --- a/examples/line-circle-txt.p8 +++ b/examples/line-circle-txt.p8 @@ -71,8 +71,8 @@ main { ubyte dy = abs(y2 - y1) ubyte dx2 = 2 * dx ubyte dy2 = 2 * dy - byte ix = sgn(x2 as byte - x1 as byte) - byte iy = sgn(y2 as byte - y1 as byte) + ubyte ix = sgn(x2 as byte - x1 as byte) as ubyte + ubyte iy = sgn(y2 as byte - y1 as byte) as ubyte ubyte x = x1 ubyte y = y1 @@ -107,7 +107,7 @@ main { ; Midpoint algorithm ubyte x = radius ubyte y = 0 - byte decisionOver2 = 1-x + byte decisionOver2 = 1-x as byte while x>=y { c64scr.setcc(xcenter + x, ycenter + y as ubyte, 81, 1) @@ -132,7 +132,7 @@ main { ; Midpoint algorithm, filled ubyte x = radius ubyte y = 0 - byte decisionOver2 = 1-x + byte decisionOver2 = 1-x as byte ubyte xx while x>=y { diff --git a/examples/strings.p8 b/examples/strings.p8 new file mode 100644 index 000000000..e6c02e3c7 --- /dev/null +++ b/examples/strings.p8 @@ -0,0 +1,36 @@ +%import c64lib +%zeropage basicsafe + +main { + +sub start() { + + str s1 = "apple" + str s2 = "banana" + byte[] a1 = [66,77,88,0] + ubyte i1 = 101 + uword w1 = 000 + + c64.STROUT(s1) + c64.CHROUT('\n') + c64.STROUT(a1) + c64.CHROUT('\n') + + c64scr.print("will play the music from boulderdash,\nmade in 1984 by peter liepa.\npress enter to start: ") ; XXX TODO FIX PRINT OUTPUT + +; c64scr.print_uwhex(s1, true) +; w1 = &s1 +; c64scr.print_uwhex(w1, true) +; +; c64scr.print_uwhex(a1, true) +; w1 = &a1 +; c64scr.print_uwhex(w1, true) +; +; s1 = s1 +; s1 = s2 +; s2 = "zzz" + +} +} + + diff --git a/examples/test.p8 b/examples/test.p8 index f728d4a14..53d908891 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,19 +6,51 @@ main { sub start() { - ubyte ubb = 44 - byte bbb=44 - uword uww = 4444 - word www = 4444 - float flt = 4.4 + line(1111,22,3333,22) + line(1111,22,1111,22) + line(1111,22,666,22) - A = ubb - A = ubb as byte - A = bbb - A = bbb as ubyte - - str foo = "foo" + line(1111,22,1111,33) + line(1111,22,1111,22) + line(1111,22,1111,11) } + + sub line(uword x1, ubyte y1, uword x2, ubyte y2) { + word dx + word dy + byte ix = 1 + byte iy = 1 + if x2>x1 { + dx = x2-x1 as word + } else { + ix = -1 + dx = x1-x2 as word + } + if y2>y1 { + dy = y2-y1 + } else { + iy = -1 + dy = y1-y2 + } + word dx2 = 2 * dx + word dy2 = 2 * dy + word d = 0 + plotx = x1 + + c64scr.print("dx=") + c64scr.print_w(dx) + c64scr.print(" ix=") + c64scr.print_b(ix) + c64.CHROUT('\n') + c64scr.print("dy=") + c64scr.print_w(dy) + c64scr.print(" iy=") + c64scr.print_b(iy) + c64.CHROUT('\n') + } + + uword plotx + }