mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
vars init
This commit is contained in:
parent
faa08133a8
commit
ee9a5716b0
@ -16,7 +16,7 @@ from .plyparse import parse_file, ParseError, Module, Directive, Block, Subrouti
|
||||
SymbolName, Dereference, AddressOf
|
||||
from .plylex import SourceRef, print_bold
|
||||
from .optimize import optimize
|
||||
from .datatypes import DataType, VarType, STRING_DATATYPES
|
||||
from .datatypes import DataType, VarType
|
||||
|
||||
|
||||
class CompileError(Exception):
|
||||
@ -42,7 +42,6 @@ class PlyParser:
|
||||
# these shall only be done on the main module after all imports have been done:
|
||||
self.apply_directive_options(module)
|
||||
self.determine_subroutine_usage(module)
|
||||
# XXX merge zero page from imported modules??? do we still have to do that?
|
||||
self.allocate_zeropage_vars(module)
|
||||
except ParseError as x:
|
||||
self.handle_parse_error(x)
|
||||
@ -85,6 +84,8 @@ class PlyParser:
|
||||
return
|
||||
zeropage = Zeropage(module.zp_options)
|
||||
for vardef in zpnode.scope.filter_nodes(VarDef):
|
||||
if vardef.datatype.isstring():
|
||||
raise ParseError("cannot put strings in the zeropage", vardef.sourceref)
|
||||
try:
|
||||
if vardef.vartype == VarType.VAR:
|
||||
vardef.zp_address = zeropage.allocate(vardef)
|
||||
@ -293,7 +294,7 @@ class PlyParser:
|
||||
if len(splits) == 2:
|
||||
for match in re.finditer(r"(?P<symbol>[a-zA-Z_$][a-zA-Z0-9_\.]+)", splits[1]):
|
||||
name = match.group("symbol")
|
||||
if name[0] == '$' or "." not in name:
|
||||
if name[0] == '$':
|
||||
continue
|
||||
try:
|
||||
symbol = parent_scope[name]
|
||||
@ -301,8 +302,11 @@ class PlyParser:
|
||||
pass
|
||||
else:
|
||||
if isinstance(symbol, Subroutine):
|
||||
namespace, name = name.rsplit(".", maxsplit=2)
|
||||
usages[(namespace, name)].add(str(asmnode.sourceref))
|
||||
if symbol.scope:
|
||||
namespace = symbol.scope.parent_scope.name
|
||||
else:
|
||||
namespace, name = name.rsplit(".", maxsplit=2)
|
||||
usages[(namespace, symbol.name)].add(str(asmnode.sourceref))
|
||||
|
||||
def check_directives(self, module: Module) -> None:
|
||||
for node, parent in module.all_scopes():
|
||||
@ -460,7 +464,7 @@ class Zeropage:
|
||||
elif vardef.datatype == DataType.MATRIX:
|
||||
print_bold("warning: {}: allocating a large datatype in zeropage".format(vardef.sourceref))
|
||||
size = vardef.size[0] * vardef.size[1]
|
||||
elif vardef.datatype in STRING_DATATYPES:
|
||||
elif vardef.datatype.isstring():
|
||||
print_bold("warning: {}: allocating a large datatype in zeropage".format(vardef.sourceref))
|
||||
size = vardef.size[0]
|
||||
else:
|
||||
|
@ -46,9 +46,19 @@ class DataType(enum.Enum):
|
||||
return self.value < other.value
|
||||
return NotImplemented
|
||||
|
||||
def isnumeric(self) -> bool:
|
||||
return self.value in (1, 2, 3)
|
||||
|
||||
def isarray(self) -> bool:
|
||||
return self.value in (4, 5, 6)
|
||||
|
||||
def isstring(self) -> bool:
|
||||
return self.value in (7, 8, 9, 10)
|
||||
|
||||
|
||||
STRING_DATATYPES = {DataType.STRING, DataType.STRING_P, DataType.STRING_S, DataType.STRING_PS}
|
||||
|
||||
|
||||
REGISTER_SYMBOLS = {"A", "X", "Y", "AX", "AY", "XY", "SC", "SI"}
|
||||
REGISTER_SYMBOLS_RETURNVALUES = REGISTER_SYMBOLS | {"SZ"}
|
||||
REGISTER_BYTES = {"A", "X", "Y"}
|
||||
|
@ -223,40 +223,55 @@ class AssemblyGenerator:
|
||||
# @todo add a block initializer subroutine that can contain custom reset/init code? (static initializer)
|
||||
|
||||
def _memset(varname: str, value: int, size: int) -> None:
|
||||
value = value or 0
|
||||
self.p("\vlda #<" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1")
|
||||
self.p("\vlda #>" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1+1")
|
||||
self.p("\vlda #" + to_hex(value))
|
||||
self.p("\vldx #" + to_hex(size))
|
||||
self.p("\vjsr il65_lib.memset")
|
||||
if size > 6:
|
||||
self.p("\vlda #<" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1")
|
||||
self.p("\vlda #>" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1+1")
|
||||
self.p("\vlda #" + to_hex(value))
|
||||
self.p("\vldx #<" + to_hex(size))
|
||||
self.p("\vldy #>" + to_hex(size))
|
||||
self.p("\vjsr il65_lib.memset")
|
||||
else:
|
||||
self.p("\vlda #" + to_hex(value))
|
||||
for i in range(size):
|
||||
self.p("\vsta {:s}+{:d}".format(varname, i))
|
||||
|
||||
def _memsetw(varname: str, value: int, size: int) -> None:
|
||||
value = value or 0
|
||||
self.p("\vlda #<" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1")
|
||||
self.p("\vlda #>" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1+1")
|
||||
self.p("\vlda #<" + to_hex(value))
|
||||
self.p("\vldy #>" + to_hex(value))
|
||||
self.p("\vldx #" + to_hex(size))
|
||||
self.p("\vjsr il65_lib.memsetw")
|
||||
if size > 4:
|
||||
self.p("\vlda #<" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1")
|
||||
self.p("\vlda #>" + varname)
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD1+1")
|
||||
self.p("\vlda #<" + to_hex(size))
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD2")
|
||||
self.p("\vlda #>" + to_hex(size))
|
||||
self.p("\vsta il65_lib.SCRATCH_ZPWORD2+1")
|
||||
self.p("\vlda #<" + to_hex(value))
|
||||
self.p("\vldx #>" + to_hex(value))
|
||||
self.p("\vjsr il65_lib.memsetw")
|
||||
else:
|
||||
self.p("\vlda #<" + to_hex(value))
|
||||
self.p("\vldy #>" + to_hex(value))
|
||||
for i in range(size):
|
||||
self.p("\vsta {:s}+{:d}".format(varname, i*2))
|
||||
self.p("\vsty {:s}+{:d}".format(varname, i*2+1))
|
||||
|
||||
self.p("_il65_init_block\v; (re)set vars to initial values")
|
||||
float_inits = {}
|
||||
string_inits = [] # type: List[VarDef]
|
||||
prev_value_a, prev_value_x = None, None
|
||||
vars_by_datatype = defaultdict(list) # type: Dict[DataType, List[VarDef]]
|
||||
for vardef in block.scope.filter_nodes(VarDef):
|
||||
if vardef.vartype == VarType.VAR:
|
||||
vars_by_datatype[vardef.datatype].append(vardef)
|
||||
for bytevar in sorted(vars_by_datatype[DataType.BYTE], key=lambda vd: vd.value):
|
||||
assert isinstance(bytevar.value, int)
|
||||
if bytevar.value != prev_value_a:
|
||||
self.p("\vlda #${:02x}".format(bytevar.value))
|
||||
prev_value_a = bytevar.value
|
||||
self.p("\vsta {:s}".format(bytevar.name))
|
||||
for wordvar in sorted(vars_by_datatype[DataType.WORD], key=lambda vd: vd.value):
|
||||
assert isinstance(wordvar.value, int)
|
||||
v_hi, v_lo = divmod(wordvar.value, 256)
|
||||
if v_hi != prev_value_a:
|
||||
self.p("\vlda #${:02x}".format(v_hi))
|
||||
@ -267,15 +282,18 @@ class AssemblyGenerator:
|
||||
self.p("\vsta {:s}".format(wordvar.name))
|
||||
self.p("\vstx {:s}+1".format(wordvar.name))
|
||||
for floatvar in vars_by_datatype[DataType.FLOAT]:
|
||||
assert isinstance(floatvar.value, (int, float))
|
||||
fpbytes = to_mflpt5(floatvar.value) # type: ignore
|
||||
float_inits[floatvar.name] = (floatvar.name, fpbytes, floatvar.value)
|
||||
for arrayvar in vars_by_datatype[DataType.BYTEARRAY]:
|
||||
assert isinstance(arrayvar.value, int)
|
||||
_memset(arrayvar.name, arrayvar.value, arrayvar.size[0])
|
||||
for arrayvar in vars_by_datatype[DataType.WORDARRAY]:
|
||||
assert isinstance(arrayvar.value, int)
|
||||
_memsetw(arrayvar.name, arrayvar.value, arrayvar.size[0])
|
||||
for arrayvar in vars_by_datatype[DataType.MATRIX]:
|
||||
assert isinstance(arrayvar.value, int)
|
||||
_memset(arrayvar.name, arrayvar.value, arrayvar.size[0] * arrayvar.size[1])
|
||||
# @todo string datatype inits with 1 memcopy
|
||||
if float_inits:
|
||||
self.p("\vldx #4")
|
||||
self.p("-")
|
||||
@ -287,11 +305,12 @@ class AssemblyGenerator:
|
||||
self.p("\vrts\n")
|
||||
for varname, (vname, fpbytes, fpvalue) in sorted(float_inits.items()):
|
||||
self.p("_init_float_{:s}\t\t.byte ${:02x}, ${:02x}, ${:02x}, ${:02x}, ${:02x}\t; {}".format(varname, *fpbytes, fpvalue))
|
||||
if string_inits:
|
||||
self.p("_init_strings_start")
|
||||
for svar in sorted(string_inits, key=lambda v: v.name):
|
||||
self._generate_string_var(svar, init=True)
|
||||
self.p("_init_strings_size = * - _init_strings_start")
|
||||
all_string_vars = []
|
||||
for svtype in STRING_DATATYPES:
|
||||
all_string_vars.extend(vars_by_datatype[svtype])
|
||||
for strvar in all_string_vars:
|
||||
# string vars are considered to be a constant, and are statically initialized.
|
||||
self._generate_string_var(strvar)
|
||||
self.p("")
|
||||
|
||||
def _numeric_value_str(self, value: Any, as_hex: bool=False) -> str:
|
||||
@ -320,7 +339,7 @@ class AssemblyGenerator:
|
||||
self.p("\v{:s} = {}".format(vardef.name, self._numeric_value_str(vardef.value)))
|
||||
elif vardef.datatype in (DataType.BYTE, DataType.WORD):
|
||||
self.p("\v{:s} = {:s}".format(vardef.name, self._numeric_value_str(vardef.value, True)))
|
||||
elif vardef.datatype in STRING_DATATYPES:
|
||||
elif vardef.datatype.isstring():
|
||||
# a const string is just a string variable in the generated assembly
|
||||
self._generate_string_var(vardef)
|
||||
else:
|
||||
@ -328,7 +347,7 @@ class AssemblyGenerator:
|
||||
self.p("; memory mapped variables")
|
||||
for vardef in vars_by_vartype.get(VarType.MEMORY, []):
|
||||
# create a definition for variables at a specific place in memory (memory-mapped)
|
||||
if vardef.datatype in (DataType.BYTE, DataType.WORD, DataType.FLOAT):
|
||||
if vardef.datatype.isnumeric():
|
||||
assert vardef.size == [1]
|
||||
self.p("\v{:s} = {:s}\t; {:s}".format(vardef.name, to_hex(vardef.value), vardef.datatype.name.lower()))
|
||||
elif vardef.datatype == DataType.BYTEARRAY:
|
||||
@ -353,7 +372,9 @@ class AssemblyGenerator:
|
||||
# zeropage uses the zp_address we've allocated, instead of allocating memory here
|
||||
for vardef in vars_by_vartype.get(VarType.VAR, []):
|
||||
assert vardef.zp_address is not None
|
||||
if vardef.datatype in (DataType.WORDARRAY, DataType.BYTEARRAY, DataType.MATRIX):
|
||||
if vardef.datatype.isstring():
|
||||
raise CodeError("cannot put strings in the zeropage", vardef.sourceref)
|
||||
if vardef.datatype.isarray():
|
||||
size_str = "size " + str(vardef.size)
|
||||
else:
|
||||
size_str = ""
|
||||
@ -363,7 +384,7 @@ class AssemblyGenerator:
|
||||
# create definitions for the variables that takes up empty space and will be initialized at startup
|
||||
string_vars = []
|
||||
for vardef in vars_by_vartype.get(VarType.VAR, []):
|
||||
if vardef.datatype in (DataType.BYTE, DataType.WORD, DataType.FLOAT):
|
||||
if vardef.datatype.isnumeric():
|
||||
assert vardef.size == [1]
|
||||
if vardef.datatype == DataType.BYTE:
|
||||
self.p("{:s}\v.byte ?".format(vardef.name))
|
||||
@ -385,33 +406,29 @@ class AssemblyGenerator:
|
||||
assert len(vardef.size) == 2
|
||||
self.p("{:s}\v.fill {:d}\t\t; matrix {:d}*{:d} bytes"
|
||||
.format(vardef.name, vardef.size[0] * vardef.size[1], vardef.size[0], vardef.size[1]))
|
||||
elif vardef.datatype in STRING_DATATYPES:
|
||||
elif vardef.datatype.isstring():
|
||||
string_vars.append(vardef)
|
||||
else:
|
||||
raise CodeError("unknown variable type " + str(vardef.datatype))
|
||||
if string_vars:
|
||||
self.p("il65_string_vars_start")
|
||||
for svar in sorted(string_vars, key=lambda v: v.name): # must be the same order as in the init routine!!!
|
||||
self.p("{:s}\v.fill {:d}+1\t\t; {}".format(svar.name, len(svar.value), svar.datatype.name.lower()))
|
||||
# string vars are considered to be a constant, and are not re-initialized.
|
||||
self.p("")
|
||||
|
||||
def _generate_string_var(self, vardef: VarDef, init: bool=False) -> None:
|
||||
prefix = "_init_str_" if init else ""
|
||||
def _generate_string_var(self, vardef: VarDef) -> None:
|
||||
if vardef.datatype == DataType.STRING:
|
||||
# 0-terminated string
|
||||
self.p("{:s}{:s}\n\v.null {:s}".format(prefix, vardef.name, self.output_string(str(vardef.value))))
|
||||
self.p("{:s}\n\v.null {:s}".format(vardef.name, self.output_string(str(vardef.value))))
|
||||
elif vardef.datatype == DataType.STRING_P:
|
||||
# pascal string
|
||||
self.p("{:s}{:s}\n\v.ptext {:s}".format(prefix, vardef.name, self.output_string(str(vardef.value))))
|
||||
self.p("{:s}\n\v.ptext {:s}".format(vardef.name, self.output_string(str(vardef.value))))
|
||||
elif vardef.datatype == DataType.STRING_S:
|
||||
# 0-terminated string in screencode encoding
|
||||
self.p(".enc 'screen'")
|
||||
self.p("{:s}{:s}\n\v.null {:s}".format(prefix, vardef.name, self.output_string(str(vardef.value), True)))
|
||||
self.p("{:s}\n\v.null {:s}".format(vardef.name, self.output_string(str(vardef.value), True)))
|
||||
self.p(".enc 'none'")
|
||||
elif vardef.datatype == DataType.STRING_PS:
|
||||
# 0-terminated pascal string in screencode encoding
|
||||
self.p(".enc 'screen'")
|
||||
self.p("{:s}{:s}n\v.ptext {:s}".format(prefix, vardef.name, self.output_string(str(vardef.value), True)))
|
||||
self.p("{:s}n\v.ptext {:s}".format(vardef.name, self.output_string(str(vardef.value), True)))
|
||||
self.p(".enc 'none'")
|
||||
|
||||
def generate_statement(self, stmt: AstNode) -> None:
|
||||
|
@ -1035,7 +1035,7 @@ sub input_chars (buffer: AX) -> (A?, Y) {
|
||||
|
||||
|
||||
;sub memcopy_basic () -> (?) {
|
||||
; ; ---- copy a memory block by using a BASIC ROM routine @todo fix code
|
||||
; ; ---- copy a memory block by using a BASIC ROM routine
|
||||
; ; it calls a function from the basic interpreter, so:
|
||||
; ; - BASIC ROM must be banked in
|
||||
; ; - the source block must be readable (so no RAM hidden under BASIC, Kernal, or I/O)
|
||||
@ -1043,7 +1043,6 @@ sub input_chars (buffer: AX) -> (A?, Y) {
|
||||
; ; higher addresses are copied first, so:
|
||||
; ; - moving data to higher addresses works even if areas overlap
|
||||
; ; - moving data to lower addresses only works if areas do not overlap
|
||||
; ; @todo fix this
|
||||
; %asm {
|
||||
; lda #<src_start
|
||||
; ldx #>src_start
|
||||
@ -1061,7 +1060,7 @@ sub input_chars (buffer: AX) -> (A?, Y) {
|
||||
; }
|
||||
;}
|
||||
|
||||
; macro version of the above memcopy_basic routine: @todo macro support?
|
||||
; macro version of the above memcopy_basic routine:
|
||||
; MACRO PARAMS src_start, src_end, target_start
|
||||
; lda #<src_start
|
||||
; ldx #>src_start
|
||||
|
@ -431,7 +431,7 @@ class VarDef(AstNode):
|
||||
assert self.size is None
|
||||
self.size = self.datatype.dimensions or [1]
|
||||
self.datatype = self.datatype.to_enum()
|
||||
if self.datatype in {DataType.BYTEARRAY, DataType.WORDARRAY, DataType.MATRIX} and sum(self.size) in (0, 1):
|
||||
if self.datatype.isarray() and sum(self.size) in (0, 1):
|
||||
print("warning: {}: array/matrix with size 1, use normal byte/word instead for efficiency".format(self.sourceref))
|
||||
if self.vartype == VarType.CONST and self.value is None:
|
||||
raise ParseError("constant value assignment is missing",
|
||||
@ -439,7 +439,7 @@ class VarDef(AstNode):
|
||||
# if the value is an expression, mark it as a *constant* expression here
|
||||
if isinstance(self.value, AstNode):
|
||||
self.value.processed_expr_must_be_constant = True
|
||||
elif self.value is None and self.datatype in (DataType.BYTE, DataType.WORD, DataType.FLOAT):
|
||||
elif self.value is None and self.datatype.isnumeric():
|
||||
self.value = 0
|
||||
# if it's a matrix with interleave, it must be memory mapped
|
||||
if self.datatype == DataType.MATRIX and len(self.size) == 3:
|
||||
@ -688,9 +688,9 @@ def process_constant_expression(expr: Any, sourceref: SourceRef, symbolscope: Sc
|
||||
else:
|
||||
raise ExpressionEvaluationError("can only use math- or builtin function", expr.sourceref)
|
||||
elif isinstance(target, Dereference): # '[...](1,2,3)'
|
||||
raise NotImplementedError("dereferenced call") # XXX
|
||||
raise ExpressionEvaluationError("dereferenced value call is not a constant value", expr.sourceref)
|
||||
elif isinstance(target, int): # '64738()'
|
||||
raise NotImplementedError("immediate address call") # XXX
|
||||
raise ExpressionEvaluationError("immediate address call is not a constant value", expr.sourceref)
|
||||
else:
|
||||
raise NotImplementedError("weird call target", target)
|
||||
else:
|
||||
|
@ -247,13 +247,18 @@ logic and several utility routines that do I/O, such as ``print_string``.
|
||||
The ``%asm {`` and ``}`` start and end markers each have to be on their own unique line.
|
||||
|
||||
|
||||
### Program Entry Point
|
||||
### Program Start and Entry Point
|
||||
|
||||
Every program has to have one entry point where code execution begins.
|
||||
The compiler looks for the ``start`` label in the ``main`` block for this.
|
||||
For proper program termination, this block has to end with a ``return`` statement (or a ``goto`` call).
|
||||
Blocks and other details are described below.
|
||||
|
||||
The initial values of your variables will be restored automatically when the program is (re)started,
|
||||
*except for string variables*. It is assumed they are unchanged by your program.
|
||||
If you do modify them in-place, you should take care yourself that they work as
|
||||
expected when the program is restarted.
|
||||
|
||||
|
||||
### Blocks
|
||||
|
||||
|
@ -6,6 +6,14 @@ from il65.plylex import SourceRef
|
||||
|
||||
def test_datatypes():
|
||||
assert all(isinstance(s, datatypes.DataType) for s in datatypes.STRING_DATATYPES)
|
||||
assert all(s.isstring() for s in datatypes.STRING_DATATYPES)
|
||||
assert not any(s.isarray() or s.isnumeric() for s in datatypes.STRING_DATATYPES)
|
||||
assert datatypes.DataType.WORDARRAY.isarray()
|
||||
assert not datatypes.DataType.WORDARRAY.isnumeric()
|
||||
assert not datatypes.DataType.WORDARRAY.isstring()
|
||||
assert not datatypes.DataType.WORD.isarray()
|
||||
assert datatypes.DataType.WORD.isnumeric()
|
||||
assert not datatypes.DataType.WORD.isstring()
|
||||
|
||||
|
||||
def test_sourceref():
|
||||
|
@ -34,7 +34,6 @@ bar: goto $c000
|
||||
; ----
|
||||
|
||||
goto sub1
|
||||
;goto sub2 (1 ) ; @todo error, must be return sub2(1) -> optimized in 'tail call'
|
||||
return sub2 ( )
|
||||
return sub2 ()
|
||||
return sub2 (1 )
|
||||
@ -47,13 +46,12 @@ bar: goto $c000
|
||||
return sub4 (string="hello", other = 42)
|
||||
return bar ()
|
||||
goto [AX]
|
||||
; goto [AX()] % ; @todo error, must be return()
|
||||
goto [var1]
|
||||
goto [mem1] ; comment
|
||||
goto $c000
|
||||
goto 64738
|
||||
64738(1,2) ; @todo jsr $64738 ??
|
||||
return 9999() ; @todo jsr 9999 ??
|
||||
64738(1,2) ; @todo should be jsr $64738
|
||||
return 9999() ; @todo should be jmp 9999 ?
|
||||
return [AX]()
|
||||
return [var1] () ; comment
|
||||
return [mem1] ()
|
||||
@ -63,13 +61,12 @@ bar: goto $c000
|
||||
return $c2()
|
||||
goto [$c2.word]
|
||||
return 33
|
||||
return [$c2.word] ; @todo this as rvalue
|
||||
; [ $c2.word (4) ] ;@ todo parse precedence
|
||||
return [$c2.word]
|
||||
return [$c2.word] (4)
|
||||
return [$c2.word] (4)
|
||||
return [$c2.word] (4)
|
||||
return [$c2.word] (4)
|
||||
; return [$c2dd.word] ( ) ;@ todo parse precedence
|
||||
return [$c2dd.word] ( )
|
||||
goto [$c2dd.word]
|
||||
|
||||
%asm {
|
||||
@ -128,9 +125,8 @@ bar: goto $c000
|
||||
[AX]()
|
||||
[var1] ( )
|
||||
[mem1] ()
|
||||
A= [$c2.word(4)]
|
||||
;A= [$c2.word() ] ; @todo Precedence?
|
||||
;A= [$c2dd.word() ] ; @todo Precedence?
|
||||
A= [$c2.word]
|
||||
A= [$c2dd.word ]
|
||||
$c000()
|
||||
$c2()
|
||||
|
||||
|
@ -78,7 +78,7 @@
|
||||
var .stext stext = 'screencodes-null'
|
||||
var .pstext pstext = "screencodes-pascal"
|
||||
|
||||
var .matrix( 2, 400 ) uninitmatrix
|
||||
var .matrix( 2, 128 ) uninitmatrix
|
||||
var .matrix(10, 20) initmatrix1 = $12
|
||||
var .matrix(10, 20) initmatrix1b = true
|
||||
var .matrix(10, 20) initmatrix1c = '@'
|
||||
@ -305,7 +305,7 @@ start:
|
||||
AY = "text-immediate" ; reuses existing
|
||||
AX = "another"
|
||||
AX = ""
|
||||
;*$c000.word = "another" ; reuse @ todo precedence?
|
||||
;*$c100.word = "text-immediate" ; reuse @ todo precedence?
|
||||
;*$c200.word = "" ; reuse @ todo precedence?
|
||||
[$c000.word] = "another" ; must reuse string
|
||||
[$c100.word] = "text-immediate" ; must reuse string
|
||||
[$c200.word] = "" ; must reuse string
|
||||
}
|
||||
|
@ -13,8 +13,9 @@ start:
|
||||
c64.init_system()
|
||||
|
||||
A = c64.VMCSB
|
||||
A |= 2 ; @todo c64.VMCSB |= 2
|
||||
A |= 2
|
||||
c64.VMCSB = A
|
||||
c64.VMCSB |= 2 ; @todo when this works it replaces the three lines above
|
||||
|
||||
; greeting
|
||||
c64scr.print_string("Enter your name: ")
|
||||
@ -58,7 +59,8 @@ ask_guess:
|
||||
[$22.word] = guess
|
||||
c64.FREADSTR(A)
|
||||
AY = c64flt.GETADRAY()
|
||||
A -= secretnumber ; @todo condition so we can do if guess > secretnumber....
|
||||
A -= secretnumber ; @todo condition so we can do if guess > secretnumber.... # @todo "removed statement that has no effect" is WRONG!!
|
||||
A -= secretnumber ; # @todo "removed statement that has no effect" is WRONG!!
|
||||
if_zero goto correct_guess
|
||||
if_gt goto too_high
|
||||
c64scr.print_string("That is too ")
|
||||
@ -87,9 +89,12 @@ game_over:
|
||||
return
|
||||
|
||||
sub goodbye ()->() {
|
||||
;var x ; @todo vars in sub
|
||||
;memory y = $c000 ; @todo vars in sub
|
||||
;const q = 22 ; @todo const in sub
|
||||
var xxxxxx ; @todo vars in sub
|
||||
memory y = $c000 ; @todo vars in sub
|
||||
const q = 22 ; @todo const in sub
|
||||
|
||||
xxxxxx = q *4
|
||||
xxxxxx = qqqqq *44 ;@todo symbol error
|
||||
|
||||
c64scr.print_string("\nThanks for playing. Bye!\n")
|
||||
return
|
||||
|
92
todo.ill
92
todo.ill
@ -1,67 +1,47 @@
|
||||
%output basic
|
||||
%zp clobber,restore
|
||||
|
||||
~ ZP {
|
||||
var zp1_1 = 200
|
||||
var zp1_2 = 200
|
||||
var .word zp1_3 = $ff99
|
||||
var .word zp1_4 = $ee88
|
||||
const zpc1_1 = 55
|
||||
const .word zpc1_2 = 2333.54566
|
||||
const .float zpc1_3 = 6.54566
|
||||
}
|
||||
|
||||
~ ZP {
|
||||
var zp2_1 = 100
|
||||
var zp2_2 = 100
|
||||
var .word zp2_3 = $55aa
|
||||
var .word zp2_4 = $66bb
|
||||
var .word zp2_5 = $66bc
|
||||
var .word zp2_6 = $66bd
|
||||
var .word zp2_7 = $66be
|
||||
var .word zp2_8 = $67be
|
||||
var .word zp2_9 = $68be
|
||||
var .word zp2_10 = $69be
|
||||
var .word zp2_11 = $69be
|
||||
var .array(4) array1
|
||||
var .wordarray(4) warray1
|
||||
var .matrix(3,3) matrix1
|
||||
var .text string = "bye"
|
||||
const .text zpc2_1 = "hello"
|
||||
const zpc2_2 = 0
|
||||
}
|
||||
%import c64lib
|
||||
|
||||
|
||||
~ main {
|
||||
|
||||
var .float float1 = 3.14
|
||||
var .float float2 = 3.14
|
||||
var .float float3 = 3.14
|
||||
var .float float4 = 3.14
|
||||
var .float float5 = 3.14
|
||||
var .array(10) array1
|
||||
var .wordarray(10) warray1
|
||||
var .matrix(4,4) matrix1
|
||||
var b1 = 10
|
||||
var b2 = 20
|
||||
var b3 = 10
|
||||
var b4 = 20
|
||||
var b5 = 10
|
||||
var b6 = 20
|
||||
var b7 = 10
|
||||
var b8 = 30
|
||||
var b9 = 30
|
||||
var b10 = 40
|
||||
var b11 = 40
|
||||
var b12 = 30
|
||||
var b13 = 40
|
||||
var b14 = 0
|
||||
var b15 = 0
|
||||
var b16 = 0
|
||||
var zp1_1 = 200
|
||||
var zp1_2 = 200
|
||||
var .text zp_s1 = "hello\n"
|
||||
var .ptext zp_s2 = "goodbye\n"
|
||||
var .stext zp_s3 = "welcome\n"
|
||||
var .pstext zp_s4 = "go away\n"
|
||||
const .text ctext = "constant\n"
|
||||
|
||||
var .array(20) arr1 = $ea
|
||||
var .wordarray(20) arr2 = $ea
|
||||
|
||||
start:
|
||||
%asm {
|
||||
|
||||
return 1.22, 46
|
||||
lda zp1_1
|
||||
jsr c64scr.print_byte_decimal0
|
||||
inc zp1_1
|
||||
lda zp1_1
|
||||
jsr c64scr.print_byte_decimal0
|
||||
inc zp1_1
|
||||
lda zp1_1
|
||||
jsr c64scr.print_byte_decimal0
|
||||
inc zp1_1
|
||||
lda zp1_1
|
||||
jsr c64scr.print_byte_decimal0
|
||||
inc zp1_1
|
||||
|
||||
;ldx #<zp_s1
|
||||
;ldy #>zp_s1
|
||||
;jsr c64scr.print_string
|
||||
;ldx #<zp_s2
|
||||
;ldy #>zp_s2
|
||||
;jsr c64scr.print_pstring
|
||||
|
||||
;ldx #<ctext
|
||||
;ldy #>ctext
|
||||
;jsr c64scr.print_string
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user