diff --git a/compiler/src/prog8/ast/processing/AstChecker.kt b/compiler/src/prog8/ast/processing/AstChecker.kt index 810e93d78..6eca98e2a 100644 --- a/compiler/src/prog8/ast/processing/AstChecker.kt +++ b/compiler/src/prog8/ast/processing/AstChecker.kt @@ -744,7 +744,7 @@ internal class AstChecker(private val program: Program, checkValueTypeAndRangeArray(array.type.typeOrElse(DataType.STRUCT), null, arrayspec, array) } - if(!array.value.all { it.constValue(program)!=null }) { + if(!array.value.all { it is NumericLiteralValue || it is AddressOf || it is StringLiteralValue }) { // TODO for now, array literals have to consist of all compile time constant values... errors.err("array literal doesn't consist of only compile time constant values", array.position) } diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index 9c1048359..fee195676 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -55,17 +55,16 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: E } } if (!conflicts) { - // move vardecls of the scope into the upper scope. Make sure the order remains the same! - val numericVarsWithValue = decls.filter { it.value != null && it.datatype in NumericDatatypes }.reversed() + // move vardecls of the scope into the upper scope. Make sure the position remains the same! + val numericVarsWithValue = decls.filter { it.value != null && it.datatype in NumericDatatypes } return numericVarsWithValue.map { val initValue = it.value!! // assume here that value has always been set by now it.value = null // make sure no value init assignment for this vardecl will be created later (would be superfluous) val target = AssignTarget(IdentifierReference(listOf(it.name), it.position), null, null, it.position) val assign = Assignment(target, initValue, it.position) initValue.parent = assign - IAstModification.InsertFirst(assign, scope) - } + decls.map { IAstModification.ReplaceNode(it, NopStatement(it.position), scope) } + - decls.map { IAstModification.InsertFirst(it, sub) } // move it up to the subroutine + IAstModification.ReplaceNode(it, assign, scope) + } + decls.map { IAstModification.InsertFirst(it, sub) } // move it up to the subroutine } } return noModifications diff --git a/examples/cx16/cobramk3-gfx.p8 b/examples/cx16/cobramk3-gfx.p8 index 4110fba2d..8f9eebc8d 100644 --- a/examples/cx16/cobramk3-gfx.p8 +++ b/examples/cx16/cobramk3-gfx.p8 @@ -38,7 +38,8 @@ main { cx16.GRAPH_draw_rect(true) cx16.GRAPH_set_colors(1, 0, 0) - draw_lines() + draw_lines_hiddenremoval() + ;draw_lines() anglex -= 505 angley += 217 @@ -128,6 +129,7 @@ main { const ubyte screen_height = 200 sub draw_lines() { + ; simple routine that draw all edges, exactly once, but no hidden line removal. ubyte @zp i for i in shipdata.totalNumberOfEdges -1 downto 0 { ubyte @zp vFrom = shipdata.edgesFrom[i] @@ -141,6 +143,45 @@ main { cx16.GRAPH_draw_line() } } + + sub draw_lines_hiddenremoval() { + ; complex routine that draws the ship model based on its faces + ; where it uses the surface normals to determine visibility. + ; TODO use a pointer to the edges instead of indexing + ubyte @zp edgeIdx = 0 + ubyte @zp i + for i in shipdata.totalNumberOfFaces -1 downto 0 { + ubyte e1 + ubyte e2 + ubyte e3 + e1 = shipdata.facesEdges[edgeIdx] + edgeIdx ++ + e2 = shipdata.facesEdges[edgeIdx] + edgeIdx ++ + e3 = shipdata.facesEdges[edgeIdx] + edgeIdx ++ + draw_edge(e1) + draw_edge(e2) + while e3!=255 { + draw_edge(e3) + e3 = shipdata.facesEdges[edgeIdx] + edgeIdx ++ + } + } + } + + sub draw_edge(ubyte edgeidx) { + ; todo: keep track of edges that are already drawn, don't redraw + ubyte vFrom = shipdata.edgesFrom[edgeidx] + ubyte vTo = shipdata.edgesTo[edgeidx] + word persp1 = 200 + rotatedz[vFrom]/256 + word persp2 = 200 + rotatedz[vTo]/256 + cx16.r0 = rotatedx[vFrom] / persp1 + screen_width/2 as uword + cx16.r1 = rotatedy[vFrom] / persp1 + screen_height/2 as uword + cx16.r2 = rotatedx[vTo] / persp2 + screen_width/2 as uword + cx16.r3 = rotatedy[vTo] / persp2 + screen_height/2 as uword + cx16.GRAPH_draw_line() + } } shipdata { diff --git a/examples/test.p8 b/examples/test.p8 index 1111c8dc0..0b9af8a89 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -16,5 +16,36 @@ main { sub start() { + + ubyte edgeIdx=0 + ubyte i + + ; TODO the following gives the correct output: + for i in 2 downto 0 { + ubyte e1 + ubyte e2 + e1 = edgeIdx + edgeIdx ++ + e2 = edgeIdx + edgeIdx ++ + txt.print_ub(e1) + c64.CHROUT(',') + txt.print_ub(e2) + c64.CHROUT('\n') + } + + c64.CHROUT('\n') + edgeIdx=0 + ; TODO however with inline vardecl initializers the result is WRONG: + for i in 2 downto 0 { + ubyte e1 = edgeIdx + edgeIdx++ + ubyte e2 = edgeIdx + edgeIdx++ + txt.print_ub(e1) + c64.CHROUT(',') + txt.print_ub(e2) + c64.CHROUT('\n') + } } }