tweak error reporting, expanded lines and circles example

This commit is contained in:
Irmen de Jong 2020-03-22 00:43:46 +01:00
parent 9409f17372
commit 4929c198ba
5 changed files with 172 additions and 117 deletions

View File

@ -565,14 +565,9 @@ asmsub clear_screenchars (ubyte char @ A) clobbers(Y) {
%asm {{
ldy #0
_loop sta c64.Screen,y
sta c64.Screen+1,y
sta c64.Screen+$0100,y
sta c64.Screen+$0101,y
sta c64.Screen+$0200,y
sta c64.Screen+$0201,y
sta c64.Screen+$02e8,y
sta c64.Screen+$02e9,y
iny
iny
bne _loop
rts
@ -585,14 +580,9 @@ asmsub clear_screencolors (ubyte color @ A) clobbers(Y) {
%asm {{
ldy #0
_loop sta c64.Colors,y
sta c64.Colors+1,y
sta c64.Colors+$0100,y
sta c64.Colors+$0101,y
sta c64.Colors+$0200,y
sta c64.Colors+$0201,y
sta c64.Colors+$02e8,y
sta c64.Colors+$02e9,y
iny
iny
bne _loop
rts

View File

@ -156,32 +156,22 @@ internal class ConstantFoldingOptimizer(private val program: Program, private va
if(forloop!=null && identifier===forloop.loopVar)
return identifier
return try {
val cval = identifier.constValue(program) ?: return identifier
return when (cval.type) {
in NumericDatatypes -> {
val copy = NumericLiteralValue(cval.type, cval.number, identifier.position)
copy.parent = identifier.parent
copy
}
in PassByReferenceDatatypes -> throw FatalAstException("pass-by-reference type should not be considered a constant")
else -> identifier
val cval = identifier.constValue(program) ?: return identifier
return when (cval.type) {
in NumericDatatypes -> {
val copy = NumericLiteralValue(cval.type, cval.number, identifier.position)
copy.parent = identifier.parent
copy
}
} catch (ax: AstException) {
errors.err("unhandled AST error: $ax", identifier.position)
identifier
in PassByReferenceDatatypes -> throw FatalAstException("pass-by-reference type should not be considered a constant")
else -> identifier
}
}
override fun visit(functionCall: FunctionCall): Expression {
super.visit(functionCall)
typeCastConstArguments(functionCall)
return try {
functionCall.constValue(program) ?: functionCall
} catch (ax: AstException) {
errors.err("unhandled AST error: $ax", functionCall.position)
functionCall
}
return functionCall.constValue(program) ?: functionCall
}
override fun visit(functionCallStatement: FunctionCallStatement): Statement {
@ -237,46 +227,41 @@ internal class ConstantFoldingOptimizer(private val program: Program, private va
* For instance, the expression for "- 4.5" will be optimized into the float literal -4.5
*/
override fun visit(expr: PrefixExpression): Expression {
return try {
val prefixExpr=super.visit(expr)
if(prefixExpr !is PrefixExpression)
return prefixExpr
val subexpr = prefixExpr.expression
if (subexpr is NumericLiteralValue) {
// accept prefixed literal values (such as -3, not true)
return when (prefixExpr.operator) {
"+" -> subexpr
"-" -> when (subexpr.type) {
in IntegerDatatypes -> {
optimizationsDone++
NumericLiteralValue.optimalNumeric(-subexpr.number.toInt(), subexpr.position)
}
DataType.FLOAT -> {
optimizationsDone++
NumericLiteralValue(DataType.FLOAT, -subexpr.number.toDouble(), subexpr.position)
}
else -> throw ExpressionError("can only take negative of int or float", subexpr.position)
}
"~" -> when (subexpr.type) {
in IntegerDatatypes -> {
optimizationsDone++
NumericLiteralValue.optimalNumeric(subexpr.number.toInt().inv(), subexpr.position)
}
else -> throw ExpressionError("can only take bitwise inversion of int", subexpr.position)
}
"not" -> {
optimizationsDone++
NumericLiteralValue.fromBoolean(subexpr.number.toDouble() == 0.0, subexpr.position)
}
else -> throw ExpressionError(prefixExpr.operator, subexpr.position)
}
}
val prefixExpr=super.visit(expr)
if(prefixExpr !is PrefixExpression)
return prefixExpr
} catch (ax: AstException) {
errors.err("unhandled AST error: $ax", expr.position)
expr
val subexpr = prefixExpr.expression
if (subexpr is NumericLiteralValue) {
// accept prefixed literal values (such as -3, not true)
return when (prefixExpr.operator) {
"+" -> subexpr
"-" -> when (subexpr.type) {
in IntegerDatatypes -> {
optimizationsDone++
NumericLiteralValue.optimalNumeric(-subexpr.number.toInt(), subexpr.position)
}
DataType.FLOAT -> {
optimizationsDone++
NumericLiteralValue(DataType.FLOAT, -subexpr.number.toDouble(), subexpr.position)
}
else -> throw ExpressionError("can only take negative of int or float", subexpr.position)
}
"~" -> when (subexpr.type) {
in IntegerDatatypes -> {
optimizationsDone++
NumericLiteralValue.optimalNumeric(subexpr.number.toInt().inv(), subexpr.position)
}
else -> throw ExpressionError("can only take bitwise inversion of int", subexpr.position)
}
"not" -> {
optimizationsDone++
NumericLiteralValue.fromBoolean(subexpr.number.toDouble() == 0.0, subexpr.position)
}
else -> throw ExpressionError(prefixExpr.operator, subexpr.position)
}
}
return prefixExpr
}
/**
@ -297,45 +282,40 @@ internal class ConstantFoldingOptimizer(private val program: Program, private va
* (X + c1) - c2 -> X + (c1-c2)
*/
override fun visit(expr: BinaryExpression): Expression {
return try {
super.visit(expr)
super.visit(expr)
if(expr.left is StringLiteralValue || expr.left is ArrayLiteralValue
|| expr.right is StringLiteralValue || expr.right is ArrayLiteralValue)
throw FatalAstException("binexpr with reference litval instead of numeric")
if(expr.left is StringLiteralValue || expr.left is ArrayLiteralValue
|| expr.right is StringLiteralValue || expr.right is ArrayLiteralValue)
throw FatalAstException("binexpr with reference litval instead of numeric")
val leftconst = expr.left.constValue(program)
val rightconst = expr.right.constValue(program)
val leftconst = expr.left.constValue(program)
val rightconst = expr.right.constValue(program)
val subExpr: BinaryExpression? = when {
leftconst!=null -> expr.right as? BinaryExpression
rightconst!=null -> expr.left as? BinaryExpression
else -> null
val subExpr: BinaryExpression? = when {
leftconst!=null -> expr.right as? BinaryExpression
rightconst!=null -> expr.left as? BinaryExpression
else -> null
}
if(subExpr!=null) {
val subleftconst = subExpr.left.constValue(program)
val subrightconst = subExpr.right.constValue(program)
if ((subleftconst != null && subrightconst == null) || (subleftconst==null && subrightconst!=null)) {
// try reordering.
return groupTwoConstsTogether(expr, subExpr,
leftconst != null, rightconst != null,
subleftconst != null, subrightconst != null)
}
if(subExpr!=null) {
val subleftconst = subExpr.left.constValue(program)
val subrightconst = subExpr.right.constValue(program)
if ((subleftconst != null && subrightconst == null) || (subleftconst==null && subrightconst!=null)) {
// try reordering.
return groupTwoConstsTogether(expr, subExpr,
leftconst != null, rightconst != null,
subleftconst != null, subrightconst != null)
}
}
// const fold when both operands are a const
return when {
leftconst != null && rightconst != null -> {
optimizationsDone++
val evaluator = ConstExprEvaluator()
evaluator.evaluate(leftconst, expr.operator, rightconst)
}
// const fold when both operands are a const
return when {
leftconst != null && rightconst != null -> {
optimizationsDone++
val evaluator = ConstExprEvaluator()
evaluator.evaluate(leftconst, expr.operator, rightconst)
}
else -> expr
}
} catch (ax: AstException) {
errors.err("unhandled AST error: $ax", expr.position)
expr
else -> expr
}
}

View File

@ -4,11 +4,20 @@ TODO
- remove statements after an exit() or return
- fix warnings about that unreachable code?
- why are some programs for example cube3d increasing in size when compiling with optimizations???
- create real assembly routines for the bresenham line and circle code
- also add assembly routines in c64scr for drawing rectangles (filled/open)
- add these routines for bitmap screen modes as well
- add a turtle example once we have highres drawing routines
- aliases for imported symbols for example perhaps '%alias print = c64scr.print'
- option to load library files from a directory instead of the embedded ones
Memory Block Operations integrated in language?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -8,23 +8,63 @@ main {
sub start() {
c64scr.print("mid-point\ncircle\n and\nbresenham\nline\nalgorithms.\n")
const ubyte xcenter = 20
const ubyte ycenter = 12
ubyte r
for r in 3 to 12 step 3 {
circle(r)
circle(20, 12, r)
}
;line(5,3, 30,3)
;line(5,3, 5, 24)
;line(30,3,30,24)
;line(5,24,30,24)
c64scr.print("enter for disc:")
void c64.CHRIN()
c64.CHROUT('\n')
c64scr.clear_screen(' ', 1)
disc(20, 12, 12)
c64scr.print("enter for lines:")
void c64.CHRIN()
c64.CHROUT('\n')
c64scr.clear_screen(' ', 1)
line(1, 10, 38, 24)
line(1, 20, 38, 2)
line(20, 4, 10, 24)
line(39, 16, 12, 0)
c64scr.print("enter for rectangles:")
void c64.CHRIN()
c64.CHROUT('\n')
c64scr.clear_screen(' ', 1)
rect(4, 8, 37, 23, false)
rect(20, 12, 30, 20, true)
rect(10, 10, 10, 10, false)
rect(6, 0, 16, 20, true)
sub rect(ubyte x1, ubyte y1, ubyte x2, ubyte y2, ubyte fill) {
ubyte x
ubyte y
if fill {
for y in y1 to y2 {
for x in x1 to x2 {
c64scr.setcc(x, y, 42, x+y)
}
}
} else {
for x in x1 to x2 {
c64scr.setcc(x, y1, 42, 8)
c64scr.setcc(x, y2, 42, 8)
}
if y2>y1 {
for y in y1+1 to y2-1 {
c64scr.setcc(x1, y, 42, 7)
c64scr.setcc(x2, y, 42, 7)
}
}
}
}
sub line(ubyte x1, ubyte y1, ubyte x2, ubyte y2) {
; Bresenham algorithm
byte d = 0
ubyte dx = abs(x2 - x1)
ubyte dy = abs(y2 - y1)
@ -62,20 +102,55 @@ main {
}
}
sub circle(ubyte radius) {
sub circle(ubyte xcenter, ubyte ycenter, ubyte radius) {
; Midpoint algorithm
byte x = radius as byte
byte y = 0
byte decisionOver2 = 1-x
while x>=y {
c64scr.setcc(xcenter + x as ubyte, ycenter + y as ubyte, 81, 1)
c64scr.setcc(xcenter - x as ubyte, ycenter + y as ubyte, 81, 1)
c64scr.setcc(xcenter + x as ubyte, ycenter - y as ubyte, 81, 1)
c64scr.setcc(xcenter - x as ubyte, ycenter - y as ubyte, 81, 1)
c64scr.setcc(xcenter + y as ubyte, ycenter + x as ubyte, 81, 1)
c64scr.setcc(xcenter - y as ubyte, ycenter + x as ubyte, 81, 1)
c64scr.setcc(xcenter + y as ubyte, ycenter - x as ubyte, 81, 1)
c64scr.setcc(xcenter - y as ubyte, ycenter - x as ubyte, 81, 1)
c64scr.setcc(xcenter - x as ubyte, ycenter + y as ubyte, 81, 2)
c64scr.setcc(xcenter + x as ubyte, ycenter - y as ubyte, 81, 3)
c64scr.setcc(xcenter - x as ubyte, ycenter - y as ubyte, 81, 4)
c64scr.setcc(xcenter + y as ubyte, ycenter + x as ubyte, 81, 5)
c64scr.setcc(xcenter - y as ubyte, ycenter + x as ubyte, 81, 6)
c64scr.setcc(xcenter + y as ubyte, ycenter - x as ubyte, 81, 7)
c64scr.setcc(xcenter - y as ubyte, ycenter - x as ubyte, 81, 8)
y++
if decisionOver2<=0
decisionOver2 += 2*y+1
else {
x--
decisionOver2 += 2*(y-x)+1
}
}
}
sub disc(ubyte cx, ubyte cy, ubyte radius) {
; Midpoint algorithm, filled
byte x = radius as byte
byte y = 0
byte decisionOver2 = 1-x
byte xx
while x>=y {
for xx in cx to cx+x {
c64scr.setcc(xx as ubyte, cy + y as ubyte, 81, 1)
c64scr.setcc(xx as ubyte, cy - y as ubyte, 81, 2)
}
for xx in cx-x to cx-1 {
c64scr.setcc(xx as ubyte, cy + y as ubyte, 81, 3)
c64scr.setcc(xx as ubyte, cy - y as ubyte, 81, 4)
}
for xx in cx to cx+y {
c64scr.setcc(xx as ubyte, cy + x as ubyte, 81, 5)
c64scr.setcc(xx as ubyte, cy - x as ubyte, 81, 6)
}
for xx in cx-y to cx {
c64scr.setcc(xx as ubyte, cy + x as ubyte, 81, 7)
c64scr.setcc(xx as ubyte, cy - x as ubyte, 81, 8)
}
y++
if decisionOver2<=0
decisionOver2 += 2*y+1

View File

@ -6,8 +6,9 @@
main {
sub start() {
str input="???????"
c64scr.clear_screen('*',7)
c64.CHRIN()
c64scr.clear_screen('.',2)
ubyte guess = lsb(c64utils.str2uword(input))
}
}