mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
struct finished
This commit is contained in:
parent
7500c6efd0
commit
3e5deda46c
@ -22,6 +22,7 @@ which aims to provide many conveniences over raw assembly code (even when using
|
|||||||
- constant folding in expressions (compile-time evaluation)
|
- constant folding in expressions (compile-time evaluation)
|
||||||
- conditional branches
|
- conditional branches
|
||||||
- when statement to provide a 'jump table' alternative to if/elseif chains
|
- when statement to provide a 'jump table' alternative to if/elseif chains
|
||||||
|
- structs to group together sets of variables and manipulate them at once
|
||||||
- automatic type conversions
|
- automatic type conversions
|
||||||
- floating point operations (uses the C64 Basic ROM routines for this)
|
- floating point operations (uses the C64 Basic ROM routines for this)
|
||||||
- abstracting away low level aspects such as ZeroPage handling, program startup, explicit memory addresses
|
- abstracting away low level aspects such as ZeroPage handling, program startup, explicit memory addresses
|
||||||
|
@ -71,6 +71,21 @@ class GlobalNamespace(val modules: List<Module>): Node, INameScope {
|
|||||||
return builtinPlaceholder
|
return builtinPlaceholder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(scopedName.size>1) {
|
||||||
|
// a scoped name can a) refer to a member of a struct, or b) refer to a name in another module.
|
||||||
|
// try the struct first.
|
||||||
|
val thing = lookup(scopedName.dropLast(1), localContext) as? VarDecl
|
||||||
|
val struct = thing?.struct
|
||||||
|
if (struct != null) {
|
||||||
|
if(struct.statements.any { (it as VarDecl).name == scopedName.last()}) {
|
||||||
|
// return ref to the mangled name variable
|
||||||
|
val mangled = mangledStructMemberName(thing.name, scopedName.last())
|
||||||
|
val mangledVar = thing.definingScope().getLabelOrVariable(mangled)
|
||||||
|
return mangledVar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val stmt = localContext.definingModule().lookup(scopedName, localContext)
|
val stmt = localContext.definingModule().lookup(scopedName, localContext)
|
||||||
return when (stmt) {
|
return when (stmt) {
|
||||||
is Label, is VarDecl, is Block, is Subroutine -> stmt
|
is Label, is VarDecl, is Block, is Subroutine -> stmt
|
||||||
|
@ -137,7 +137,7 @@ interface INameScope {
|
|||||||
// - the name of a symbol somewhere else starting from the root of the namespace.
|
// - the name of a symbol somewhere else starting from the root of the namespace.
|
||||||
|
|
||||||
// check struct first
|
// check struct first
|
||||||
if(scopedName.size==2) { // TODO support for referencing structs in other scopes
|
if(scopedName.size==2) { // TODO support for referencing structs in other scopes . see GlobalNamespace?
|
||||||
val mangledname = mangledStructMemberName(scopedName[0], scopedName[1])
|
val mangledname = mangledStructMemberName(scopedName[0], scopedName[1])
|
||||||
val vardecl = localContext.definingScope().getLabelOrVariable(mangledname)
|
val vardecl = localContext.definingScope().getLabelOrVariable(mangledname)
|
||||||
if(vardecl!=null)
|
if(vardecl!=null)
|
||||||
|
@ -350,6 +350,17 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val sourceIdent = assignment.value as? IdentifierReference
|
||||||
|
val targetIdent = assignment.target.identifier
|
||||||
|
if(sourceIdent!=null && targetIdent!=null) {
|
||||||
|
val sourceVar = sourceIdent.targetVarDecl(program.namespace)
|
||||||
|
val targetVar = targetIdent.targetVarDecl(program.namespace)
|
||||||
|
if(sourceVar?.struct!=null && targetVar?.struct!=null) {
|
||||||
|
if(sourceVar.struct!==targetVar.struct)
|
||||||
|
checkResult.add(ExpressionError("assignment of different struct types", assignment.position))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var resultingAssignment = assignment
|
var resultingAssignment = assignment
|
||||||
resultingAssignment = processAssignmentTarget(resultingAssignment, assignment.target)
|
resultingAssignment = processAssignmentTarget(resultingAssignment, assignment.target)
|
||||||
return super.visit(resultingAssignment)
|
return super.visit(resultingAssignment)
|
||||||
@ -1275,8 +1286,8 @@ internal class AstChecker(private val program: Program,
|
|||||||
else {
|
else {
|
||||||
if(decl.zeropage)
|
if(decl.zeropage)
|
||||||
checkResult.add(SyntaxError("struct can not contain zeropage members", decl.position))
|
checkResult.add(SyntaxError("struct can not contain zeropage members", decl.position))
|
||||||
if(decl.datatype==DataType.STRUCT)
|
if(decl.datatype !in NumericDatatypes)
|
||||||
checkResult.add(SyntaxError("structs can not be nested", decl.position))
|
checkResult.add(SyntaxError("structs can only contain numerical types", decl.position))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,9 @@ internal class AstIdentifiersChecker(private val namespace: INameScope) : IAstMo
|
|||||||
if(decl.structHasBeenFlattened)
|
if(decl.structHasBeenFlattened)
|
||||||
return decl // don't do this multiple times
|
return decl // don't do this multiple times
|
||||||
|
|
||||||
|
if(decl.struct!!.statements.any { (it as VarDecl).datatype !in NumericDatatypes})
|
||||||
|
return decl // a non-numeric member, not supported. proper error is given by AstChecker later
|
||||||
|
|
||||||
val decls: MutableList<IStatement> = decl.struct!!.statements.withIndex().map {
|
val decls: MutableList<IStatement> = decl.struct!!.statements.withIndex().map {
|
||||||
val member = it.value as VarDecl
|
val member = it.value as VarDecl
|
||||||
val initvalue = if(decl.value!=null) (decl.value as LiteralValue).arrayvalue!![it.index] else null
|
val initvalue = if(decl.value!=null) (decl.value as LiteralValue).arrayvalue!![it.index] else null
|
||||||
@ -245,4 +248,14 @@ internal class AstIdentifiersChecker(private val namespace: INameScope) : IAstMo
|
|||||||
return super.visit(addressOf)
|
return super.visit(addressOf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visit(structDecl: StructDecl): IStatement {
|
||||||
|
for(member in structDecl.statements){
|
||||||
|
val decl = member as? VarDecl
|
||||||
|
if(decl!=null && decl.datatype !in NumericDatatypes)
|
||||||
|
checkResult.add(SyntaxError("structs can only contain numerical types", decl.position))
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.visit(structDecl)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,58 @@ package prog8.ast.processing
|
|||||||
|
|
||||||
import kotlin.comparisons.nullsLast
|
import kotlin.comparisons.nullsLast
|
||||||
import prog8.ast.*
|
import prog8.ast.*
|
||||||
import prog8.ast.base.DataType
|
import prog8.ast.base.*
|
||||||
import prog8.ast.base.FatalAstException
|
|
||||||
import prog8.ast.base.initvarsSubName
|
import prog8.ast.base.initvarsSubName
|
||||||
import prog8.ast.base.printWarning
|
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.functions.BuiltinFunctions
|
import prog8.functions.BuiltinFunctions
|
||||||
|
|
||||||
|
|
||||||
|
fun flattenStructAssignment(structAssignment: Assignment, program: Program): List<Assignment> {
|
||||||
|
val identifier = structAssignment.target.identifier!!
|
||||||
|
val identifierName = identifier.nameInSource.single()
|
||||||
|
val targetVar = identifier.targetVarDecl(program.namespace)!!
|
||||||
|
val struct = targetVar.struct!!
|
||||||
|
val sourceVar = (structAssignment.value as IdentifierReference).targetVarDecl(program.namespace)!!
|
||||||
|
if(!sourceVar.isArray && sourceVar.struct==null)
|
||||||
|
throw FatalAstException("can only assign arrays or structs to structs")
|
||||||
|
if(sourceVar.isArray) {
|
||||||
|
val sourceArray = (sourceVar.value as LiteralValue).arrayvalue!!
|
||||||
|
return struct.statements.zip(sourceArray).map { member ->
|
||||||
|
val decl = member.first as VarDecl
|
||||||
|
val mangled = mangledStructMemberName(identifierName, decl.name)
|
||||||
|
val idref = IdentifierReference(listOf(mangled), structAssignment.position)
|
||||||
|
val assign = Assignment(AssignTarget(null, idref, null, null, structAssignment.position),
|
||||||
|
null, member.second, member.second.position)
|
||||||
|
assign.linkParents(structAssignment)
|
||||||
|
assign
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// struct memberwise copy
|
||||||
|
val sourceStruct = sourceVar.struct!!
|
||||||
|
if(sourceStruct!==targetVar.struct) {
|
||||||
|
// structs are not the same in assignment
|
||||||
|
return listOf() // error will be printed elsewhere
|
||||||
|
}
|
||||||
|
return struct.statements.zip(sourceStruct.statements).map { member ->
|
||||||
|
val targetDecl = member.first as VarDecl
|
||||||
|
val sourceDecl = member.second as VarDecl
|
||||||
|
if(targetDecl.name != sourceDecl.name)
|
||||||
|
throw FatalAstException("struct member mismatch")
|
||||||
|
val mangled = mangledStructMemberName(identifierName, targetDecl.name)
|
||||||
|
val idref = IdentifierReference(listOf(mangled), structAssignment.position)
|
||||||
|
val sourcemangled = mangledStructMemberName(sourceVar.name, sourceDecl.name)
|
||||||
|
val sourceIdref = IdentifierReference(listOf(sourcemangled), structAssignment.position)
|
||||||
|
val assign = Assignment(AssignTarget(null, idref, null, null, structAssignment.position),
|
||||||
|
null, sourceIdref, member.second.position)
|
||||||
|
assign.linkParents(structAssignment)
|
||||||
|
assign
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class StatementReorderer(private val program: Program): IAstModifyingVisitor {
|
internal class StatementReorderer(private val program: Program): IAstModifyingVisitor {
|
||||||
// Reorders the statements in a way the compiler needs.
|
// Reorders the statements in a way the compiler needs.
|
||||||
// - 'main' block must be the very first statement UNLESS it has an address set.
|
// - 'main' block must be the very first statement UNLESS it has an address set.
|
||||||
@ -174,13 +218,29 @@ internal class StatementReorderer(private val program: Program): IAstModifyingVi
|
|||||||
// see if a typecast is needed to convert the value's type into the proper target type
|
// see if a typecast is needed to convert the value's type into the proper target type
|
||||||
val valuetype = assignment.value.inferType(program)
|
val valuetype = assignment.value.inferType(program)
|
||||||
val targettype = assignment.target.inferType(program, assignment)
|
val targettype = assignment.target.inferType(program, assignment)
|
||||||
if(targettype!=null && valuetype!=null && valuetype!=targettype) {
|
if(targettype!=null && valuetype!=null) {
|
||||||
if(valuetype isAssignableTo targettype) {
|
if(valuetype!=targettype) {
|
||||||
|
if (valuetype isAssignableTo targettype) {
|
||||||
assignment.value = TypecastExpression(assignment.value, targettype, true, assignment.value.position)
|
assignment.value = TypecastExpression(assignment.value, targettype, true, assignment.value.position)
|
||||||
assignment.value.linkParents(assignment)
|
assignment.value.linkParents(assignment)
|
||||||
}
|
}
|
||||||
// if they're not assignable, we'll get a proper error later from the AstChecker
|
// if they're not assignable, we'll get a proper error later from the AstChecker
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct assignments will be flattened
|
||||||
|
if(valuetype==DataType.STRUCT && targettype==DataType.STRUCT) {
|
||||||
|
val assignments = flattenStructAssignment(assignment, program)
|
||||||
|
if(assignments.isEmpty()) {
|
||||||
|
// something went wrong (probably incompatible struct types)
|
||||||
|
// we'll get an error later from the AstChecker
|
||||||
|
return assignment
|
||||||
|
} else {
|
||||||
|
val scope = AnonymousScope(assignments.toMutableList(), assignment.position)
|
||||||
|
scope.linkParents(assignment.parent)
|
||||||
|
return scope
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return super.visit(assignment)
|
return super.visit(assignment)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import prog8.ast.*
|
|||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
import prog8.ast.base.RegisterOrPair.*
|
import prog8.ast.base.RegisterOrPair.*
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
|
import prog8.ast.processing.flattenStructAssignment
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.compiler.intermediate.IntermediateProgram
|
import prog8.compiler.intermediate.IntermediateProgram
|
||||||
import prog8.compiler.intermediate.Opcode
|
import prog8.compiler.intermediate.Opcode
|
||||||
@ -1464,26 +1465,6 @@ internal class Compiler(private val program: Program) {
|
|||||||
popValueIntoTarget(stmt.target, datatype)
|
popValueIntoTarget(stmt.target, datatype)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun flattenStructAssignment(structAssignment: Assignment, program: Program): List<Assignment> {
|
|
||||||
val identifier = structAssignment.target.identifier!!
|
|
||||||
val identifierName = identifier.nameInSource.single()
|
|
||||||
val targetVar = identifier.targetVarDecl(program.namespace)!!
|
|
||||||
val struct = targetVar.struct!!
|
|
||||||
val sourceVar = (structAssignment.value as IdentifierReference).targetVarDecl(program.namespace)!!
|
|
||||||
if(!sourceVar.isArray)
|
|
||||||
throw CompilerException("can only assign arrays to structs")
|
|
||||||
val sourceArray = (sourceVar.value as LiteralValue).arrayvalue!!
|
|
||||||
return struct.statements.zip(sourceArray).map { member ->
|
|
||||||
val decl = member.first as VarDecl
|
|
||||||
val mangled = mangledStructMemberName(identifierName, decl.name)
|
|
||||||
val idref = IdentifierReference(listOf(mangled), structAssignment.position)
|
|
||||||
val assign = Assignment(AssignTarget(null, idref, null, null, structAssignment.position),
|
|
||||||
null, member.second, member.second.position)
|
|
||||||
assign.linkParents(structAssignment)
|
|
||||||
assign
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun pushHeapVarAddress(value: IExpression, removeLastOpcode: Boolean) {
|
private fun pushHeapVarAddress(value: IExpression, removeLastOpcode: Boolean) {
|
||||||
when (value) {
|
when (value) {
|
||||||
is LiteralValue -> throw CompilerException("can only push address of string or array (value on the heap)")
|
is LiteralValue -> throw CompilerException("can only push address of string or array (value on the heap)")
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package prog8.optimizer
|
package prog8.optimizer
|
||||||
|
|
||||||
import prog8.ast.*
|
import prog8.ast.*
|
||||||
|
import prog8.ast.base.DataType
|
||||||
import prog8.ast.base.ParentSentinel
|
import prog8.ast.base.ParentSentinel
|
||||||
import prog8.ast.base.VarDeclType
|
import prog8.ast.base.VarDeclType
|
||||||
import prog8.ast.base.initvarsSubName
|
import prog8.ast.base.initvarsSubName
|
||||||
@ -122,6 +123,10 @@ class CallGraph(private val program: Program): IAstVisitor {
|
|||||||
// make sure autogenerated vardecls are in the used symbols
|
// make sure autogenerated vardecls are in the used symbols
|
||||||
addNodeAndParentScopes(decl)
|
addNodeAndParentScopes(decl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(decl.datatype==DataType.STRUCT)
|
||||||
|
addNodeAndParentScopes(decl)
|
||||||
|
|
||||||
super.visit(decl)
|
super.visit(decl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,6 +201,7 @@ class CallGraph(private val program: Program): IAstVisitor {
|
|||||||
if (matches2 != null) {
|
if (matches2 != null) {
|
||||||
val target= matches2.groups[2]?.value
|
val target= matches2.groups[2]?.value
|
||||||
if (target != null && (target[0].isLetter() || target[0] == '_')) {
|
if (target != null && (target[0].isLetter() || target[0] == '_')) {
|
||||||
|
if(target.contains('.')) {
|
||||||
val node = program.namespace.lookup(listOf(target.substringBefore('.')), context)
|
val node = program.namespace.lookup(listOf(target.substringBefore('.')), context)
|
||||||
if (node is Subroutine) {
|
if (node is Subroutine) {
|
||||||
subroutinesCalling[scope] = subroutinesCalling.getValue(scope).plus(node)
|
subroutinesCalling[scope] = subroutinesCalling.getValue(scope).plus(node)
|
||||||
@ -206,4 +212,5 @@ class CallGraph(private val program: Program): IAstVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,9 +40,11 @@ class VariablesCreator(private val runtimeVariables: RuntimeVariables, private v
|
|||||||
when (decl.type) {
|
when (decl.type) {
|
||||||
// we can assume the value in the vardecl already has been converted into a constant LiteralValue here.
|
// we can assume the value in the vardecl already has been converted into a constant LiteralValue here.
|
||||||
VarDeclType.VAR -> {
|
VarDeclType.VAR -> {
|
||||||
|
if(decl.datatype!=DataType.STRUCT) {
|
||||||
val value = RuntimeValue.from(decl.value as LiteralValue, heap)
|
val value = RuntimeValue.from(decl.value as LiteralValue, heap)
|
||||||
runtimeVariables.define(decl.definingScope(), decl.name, value)
|
runtimeVariables.define(decl.definingScope(), decl.name, value)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
VarDeclType.MEMORY -> {
|
VarDeclType.MEMORY -> {
|
||||||
runtimeVariables.defineMemory(decl.definingScope(), decl.name, (decl.value as LiteralValue).asIntegerValue!!)
|
runtimeVariables.defineMemory(decl.definingScope(), decl.name, (decl.value as LiteralValue).asIntegerValue!!)
|
||||||
}
|
}
|
||||||
|
@ -273,6 +273,38 @@ you have to use the ``str_s`` variants of the string type identifier.
|
|||||||
The same is true for arrays by the way.
|
The same is true for arrays by the way.
|
||||||
|
|
||||||
|
|
||||||
|
Structs
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
A struct is a group of one or more other variables.
|
||||||
|
This allows you to reuse the definition and manipulate it as a whole.
|
||||||
|
Individual variables in the struct are accessed as you would expect, just
|
||||||
|
use a scoped name to refer to them: ``structvariable.membername``.
|
||||||
|
|
||||||
|
Structs are a bit limited in Prog8: you can only use numerical variables
|
||||||
|
as member of a struct, so strings and arrays and other structs can not be part of a struct.
|
||||||
|
Also, it is not possible to use a struct itself inside an array.
|
||||||
|
|
||||||
|
Structs are mainly syntactic sugar for repeated groups of vardecls
|
||||||
|
and assignments that belong together.
|
||||||
|
|
||||||
|
To create a variable of a struct type you need to define the struct itself,
|
||||||
|
and then create a variable with it::
|
||||||
|
|
||||||
|
struct Color {
|
||||||
|
ubyte red
|
||||||
|
ubyte green
|
||||||
|
ubyte blue
|
||||||
|
}
|
||||||
|
|
||||||
|
Color rgb = [255,122,0]
|
||||||
|
Color another ; the init value is optional, like arrays
|
||||||
|
|
||||||
|
another = rgb ; assign all of the values of rgb to another
|
||||||
|
another.blue = 255 ; set a single member
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Special types: const and memory-mapped
|
Special types: const and memory-mapped
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ Various examples::
|
|||||||
byte[5] values = 255 ; initialize with five 255 bytes
|
byte[5] values = 255 ; initialize with five 255 bytes
|
||||||
|
|
||||||
word @zp zpword = 9999 ; prioritize this when selecting vars for zeropage storage
|
word @zp zpword = 9999 ; prioritize this when selecting vars for zeropage storage
|
||||||
|
Color rgb = [1,255,0] ; a struct variable
|
||||||
|
|
||||||
|
|
||||||
Data types
|
Data types
|
||||||
@ -358,6 +358,22 @@ Syntax is familiar with brackets: ``arrayvar[x]`` ::
|
|||||||
string[4] ; the fifth character (=byte) in the string
|
string[4] ; the fifth character (=byte) in the string
|
||||||
|
|
||||||
|
|
||||||
|
Struct
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
A *struct* has to be defined to specify what its member variables are.
|
||||||
|
There are one or more members::
|
||||||
|
|
||||||
|
struct <structname> {
|
||||||
|
<vardecl>
|
||||||
|
[ <vardecl> ...]
|
||||||
|
}
|
||||||
|
|
||||||
|
You can only use numerical variables as member of a struct, so strings and arrays
|
||||||
|
and other structs can not be part of a struct. Vice versa, a struct can not occur in an array.
|
||||||
|
|
||||||
|
After defining a struct you can use the name of the struct as a data type to declare variables with.
|
||||||
|
|
||||||
|
|
||||||
Operators
|
Operators
|
||||||
---------
|
---------
|
||||||
|
@ -52,25 +52,6 @@ Allocate a fixed word in ZP that is the TOS so we can operate on TOS directly
|
|||||||
without having to to index into the stack?
|
without having to to index into the stack?
|
||||||
|
|
||||||
|
|
||||||
structs?
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
A user defined struct type would be nice to group a bunch
|
|
||||||
of values together (and use it multiple times). Something like::
|
|
||||||
|
|
||||||
struct Point {
|
|
||||||
ubyte color
|
|
||||||
word[] vec = [0,0,0]
|
|
||||||
}
|
|
||||||
|
|
||||||
Point p1
|
|
||||||
Point p2
|
|
||||||
Point p3
|
|
||||||
|
|
||||||
p1.color = 3
|
|
||||||
p1.vec[2] = 2
|
|
||||||
|
|
||||||
|
|
||||||
Misc
|
Misc
|
||||||
^^^^
|
^^^^
|
||||||
|
|
||||||
|
@ -5,20 +5,24 @@
|
|||||||
const uword width = 40
|
const uword width = 40
|
||||||
const uword height = 25
|
const uword height = 25
|
||||||
|
|
||||||
sub start() {
|
struct Ball {
|
||||||
|
|
||||||
uword anglex
|
uword anglex
|
||||||
uword angley
|
uword angley
|
||||||
ubyte color
|
ubyte color
|
||||||
|
}
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
|
||||||
|
Ball ball
|
||||||
|
|
||||||
while true {
|
while true {
|
||||||
ubyte x = msb(sin8u(msb(anglex)) as uword * width)
|
ubyte x = msb(sin8u(msb(ball.anglex)) as uword * width)
|
||||||
ubyte y = msb(cos8u(msb(angley)) as uword * height)
|
ubyte y = msb(cos8u(msb(ball.angley)) as uword * height)
|
||||||
c64scr.setcc(x, y, 81, color)
|
c64scr.setcc(x, y, 81, ball.color)
|
||||||
|
|
||||||
anglex+=800
|
ball.anglex+=800
|
||||||
angley+=947
|
ball.angley+=947
|
||||||
color++
|
ball.color++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,68 +7,18 @@
|
|||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
uword derp =44
|
Color subcol
|
||||||
ubyte[] v = [22,33,44]
|
|
||||||
|
|
||||||
Color foreground = [1,2,3]
|
A=msb(subcol.red)
|
||||||
c64scr.print_ub(foreground.red)
|
for ubyte i in 10 to 20 {
|
||||||
c64.CHROUT(':')
|
;A=subcol.red
|
||||||
c64scr.print_ub(foreground.green)
|
;A=blocklevelcolor.green
|
||||||
c64.CHROUT(':')
|
|
||||||
c64scr.print_ub(foreground.blue)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
|
;subcol.blue = Y
|
||||||
Color background
|
;blocklevelcolor.green=Y
|
||||||
Color cursor = [255,255,255]
|
A=msb(subcol.red)
|
||||||
|
|
||||||
foreground.red=99
|
|
||||||
background.blue=foreground.red
|
|
||||||
|
|
||||||
cursor = [1,2,3] ; assign all members at once
|
|
||||||
cursor = v
|
|
||||||
cursor = foreground ; @todo memberwise assignment
|
|
||||||
|
|
||||||
c64scr.print_ub(foreground.red)
|
|
||||||
c64.CHROUT(':')
|
|
||||||
c64scr.print_ub(foreground.green)
|
|
||||||
c64.CHROUT(':')
|
|
||||||
c64scr.print_ub(foreground.blue)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print_ub(background.red)
|
|
||||||
c64.CHROUT(':')
|
|
||||||
c64scr.print_ub(background.green)
|
|
||||||
c64.CHROUT(':')
|
|
||||||
c64scr.print_ub(background.blue)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print_ub(cursor.red)
|
|
||||||
c64.CHROUT(':')
|
|
||||||
c64scr.print_ub(cursor.green)
|
|
||||||
c64.CHROUT(':')
|
|
||||||
c64scr.print_ub(cursor.blue)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
foo()
|
|
||||||
foo()
|
|
||||||
foo()
|
|
||||||
foo()
|
|
||||||
foo()
|
|
||||||
foo()
|
|
||||||
foo()
|
|
||||||
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
return
|
||||||
sub foo() {
|
|
||||||
Color localcolor
|
|
||||||
localcolor.red++
|
|
||||||
c64scr.print_ub(localcolor.red)
|
|
||||||
c64.CHROUT(':')
|
|
||||||
c64scr.print_ub(localcolor.green)
|
|
||||||
c64.CHROUT(':')
|
|
||||||
c64scr.print_ub(localcolor.blue)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Color {
|
struct Color {
|
||||||
@ -77,9 +27,4 @@
|
|||||||
ubyte blue
|
ubyte blue
|
||||||
}
|
}
|
||||||
|
|
||||||
; @todo structs as sub args. After strings and arrays as sub-args.
|
|
||||||
; sub foo(Color arg) -> ubyte {
|
|
||||||
; return arg.red+arg.green+arg.blue
|
|
||||||
; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user