mirror of
https://github.com/catseye/SixtyPical.git
synced 2025-02-19 20:30:45 +00:00
Implement local locations that aren't statically initialized.
This commit is contained in:
parent
81e28fa757
commit
dd29b6fd4a
@ -1,6 +1,14 @@
|
|||||||
History of SixtyPical
|
History of SixtyPical
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
|
0.20
|
||||||
|
----
|
||||||
|
|
||||||
|
* Fixed a bug where two local statics could be declared with
|
||||||
|
the same name.
|
||||||
|
* Local locations need no longer be static. If they are not
|
||||||
|
static, they are considered uninitialized until assigned.
|
||||||
|
|
||||||
0.19
|
0.19
|
||||||
----
|
----
|
||||||
|
|
||||||
|
20
TODO.md
20
TODO.md
@ -53,21 +53,17 @@ at different times.
|
|||||||
|
|
||||||
These can co-exist with general, non-specific-table-linked `pointer` variables.
|
These can co-exist with general, non-specific-table-linked `pointer` variables.
|
||||||
|
|
||||||
### Local non-statics
|
### Space optimization of local non-statics
|
||||||
|
|
||||||
Somewhat related to the above, it should be possible to declare a local storage
|
If there are two routines A and B, and A never calls B (even indirectly), and
|
||||||
location which is not static.
|
B never calls A (even indirectly), then their non-static locals can
|
||||||
|
|
||||||
In this case, it would be considered uninitialized each time the routine was
|
|
||||||
entered.
|
|
||||||
|
|
||||||
So, you do not have a guarantee that it has a valid value. But you are guaranteed
|
|
||||||
that no other routine can read or modify it.
|
|
||||||
|
|
||||||
It also enables a trick: if there are two routines A and B, and A never calls B
|
|
||||||
(even indirectly), and B never calls A (even indirectly), then their locals can
|
|
||||||
be allocated at the same space.
|
be allocated at the same space.
|
||||||
|
|
||||||
|
This is more an impressive trick than a really useful feature, but still.
|
||||||
|
Impressive tricks are impressive.
|
||||||
|
|
||||||
|
### Locals with explicit addresses
|
||||||
|
|
||||||
A local could also be given an explicit address. In this case, two locals in
|
A local could also be given an explicit address. In this case, two locals in
|
||||||
different routines could be given the same address, and as long as the condition
|
different routines could be given the same address, and as long as the condition
|
||||||
in the above paragraph holds, that's okay. (If it doesn't, the analyzer should
|
in the above paragraph holds, that's okay. (If it doesn't, the analyzer should
|
||||||
|
@ -183,9 +183,14 @@ class AnalysisContext(object):
|
|||||||
def assert_meaningful(self, *refs, **kwargs):
|
def assert_meaningful(self, *refs, **kwargs):
|
||||||
exception_class = kwargs.get('exception_class', UnmeaningfulReadError)
|
exception_class = kwargs.get('exception_class', UnmeaningfulReadError)
|
||||||
for ref in refs:
|
for ref in refs:
|
||||||
# statics are always meaningful
|
if self.symtab.has_local(self.routine.name, ref.name):
|
||||||
if self.symtab.has_static(self.routine.name, ref.name):
|
if ref not in self._range:
|
||||||
continue
|
message = ref.name
|
||||||
|
if kwargs.get('message'):
|
||||||
|
message += ' (%s)' % kwargs['message']
|
||||||
|
raise exception_class(self.routine, message)
|
||||||
|
else:
|
||||||
|
continue
|
||||||
if self.is_constant(ref):
|
if self.is_constant(ref):
|
||||||
pass
|
pass
|
||||||
elif isinstance(ref, LocationRef):
|
elif isinstance(ref, LocationRef):
|
||||||
@ -203,8 +208,8 @@ class AnalysisContext(object):
|
|||||||
def assert_writeable(self, *refs, **kwargs):
|
def assert_writeable(self, *refs, **kwargs):
|
||||||
exception_class = kwargs.get('exception_class', ForbiddenWriteError)
|
exception_class = kwargs.get('exception_class', ForbiddenWriteError)
|
||||||
for ref in refs:
|
for ref in refs:
|
||||||
# statics are always writeable
|
# locals are always writeable
|
||||||
if self.symtab.has_static(self.routine.name, ref.name):
|
if self.symtab.has_local(self.routine.name, ref.name):
|
||||||
continue
|
continue
|
||||||
if ref not in self._writeable:
|
if ref not in self._writeable:
|
||||||
message = ref.name
|
message = ref.name
|
||||||
@ -384,8 +389,8 @@ class AnalysisContext(object):
|
|||||||
def max_range(self, ref):
|
def max_range(self, ref):
|
||||||
if isinstance(ref, ConstantRef):
|
if isinstance(ref, ConstantRef):
|
||||||
return (ref.value, ref.value)
|
return (ref.value, ref.value)
|
||||||
elif self.symtab.has_static(self.routine.name, ref.name):
|
elif self.symtab.has_local(self.routine.name, ref.name):
|
||||||
return self.symtab.fetch_static_type(self.routine.name, ref.name).max_range
|
return self.symtab.fetch_local_type(self.routine.name, ref.name).max_range
|
||||||
else:
|
else:
|
||||||
return self.symtab.fetch_global_type(ref.name).max_range
|
return self.symtab.fetch_global_type(ref.name).max_range
|
||||||
|
|
||||||
@ -401,8 +406,8 @@ class Analyzer(object):
|
|||||||
# - - - - helper methods - - - -
|
# - - - - helper methods - - - -
|
||||||
|
|
||||||
def get_type_for_name(self, name):
|
def get_type_for_name(self, name):
|
||||||
if self.current_routine and self.symtab.has_static(self.current_routine.name, name):
|
if self.current_routine and self.symtab.has_local(self.current_routine.name, name):
|
||||||
return self.symtab.fetch_static_type(self.current_routine.name, name)
|
return self.symtab.fetch_local_type(self.current_routine.name, name)
|
||||||
return self.symtab.fetch_global_type(name)
|
return self.symtab.fetch_global_type(name)
|
||||||
|
|
||||||
def get_type(self, ref):
|
def get_type(self, ref):
|
||||||
@ -462,6 +467,14 @@ class Analyzer(object):
|
|||||||
self.current_routine = routine
|
self.current_routine = routine
|
||||||
type_ = self.get_type_for_name(routine.name)
|
type_ = self.get_type_for_name(routine.name)
|
||||||
context = AnalysisContext(self.symtab, routine, type_.inputs, type_.outputs, type_.trashes)
|
context = AnalysisContext(self.symtab, routine, type_.inputs, type_.outputs, type_.trashes)
|
||||||
|
|
||||||
|
# register any local statics as already-initialized
|
||||||
|
for local_name, local_symentry in self.symtab.locals.get(routine.name, {}).items():
|
||||||
|
ref = self.symtab.fetch_local_ref(routine.name, local_name)
|
||||||
|
if local_symentry.ast_node.initial is not None:
|
||||||
|
context.set_meaningful(ref)
|
||||||
|
context.set_range(ref, local_symentry.ast_node.initial, local_symentry.ast_node.initial)
|
||||||
|
|
||||||
self.exit_contexts = []
|
self.exit_contexts = []
|
||||||
|
|
||||||
self.analyze_block(routine.block, context)
|
self.analyze_block(routine.block, context)
|
||||||
@ -505,7 +518,7 @@ class Analyzer(object):
|
|||||||
|
|
||||||
# if something was touched, then it should have been declared to be writable.
|
# if something was touched, then it should have been declared to be writable.
|
||||||
for ref in context.each_touched():
|
for ref in context.each_touched():
|
||||||
if ref not in type_.outputs and ref not in type_.trashes and not self.symtab.has_static(routine.name, ref.name):
|
if ref not in type_.outputs and ref not in type_.trashes and not self.symtab.has_local(routine.name, ref.name):
|
||||||
raise ForbiddenWriteError(routine, ref.name)
|
raise ForbiddenWriteError(routine, ref.name)
|
||||||
|
|
||||||
self.exit_contexts = None
|
self.exit_contexts = None
|
||||||
|
@ -59,7 +59,7 @@ class Defn(AST):
|
|||||||
|
|
||||||
class Routine(AST):
|
class Routine(AST):
|
||||||
value_attrs = ('name', 'addr', 'initial',)
|
value_attrs = ('name', 'addr', 'initial',)
|
||||||
children_attrs = ('statics',)
|
children_attrs = ('locals',)
|
||||||
child_attrs = ('block',)
|
child_attrs = ('block',)
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ class Compiler(object):
|
|||||||
self.symtab = symtab
|
self.symtab = symtab
|
||||||
self.emitter = emitter
|
self.emitter = emitter
|
||||||
self.routines = {} # routine.name -> Routine
|
self.routines = {} # routine.name -> Routine
|
||||||
self.routine_statics = {} # routine.name -> { static.name -> Label }
|
self.routine_locals = {} # routine.name -> { local.name -> Label }
|
||||||
self.labels = {} # global.name -> Label ("global" includes routines)
|
self.labels = {} # global.name -> Label ("global" includes routines)
|
||||||
self.trampolines = {} # Location -> Label
|
self.trampolines = {} # Location -> Label
|
||||||
self.current_routine = None
|
self.current_routine = None
|
||||||
@ -42,8 +42,8 @@ class Compiler(object):
|
|||||||
# - - - - helper methods - - - -
|
# - - - - helper methods - - - -
|
||||||
|
|
||||||
def get_type_for_name(self, name):
|
def get_type_for_name(self, name):
|
||||||
if self.current_routine and self.symtab.has_static(self.current_routine.name, name):
|
if self.current_routine and self.symtab.has_local(self.current_routine.name, name):
|
||||||
return self.symtab.fetch_static_type(self.current_routine.name, name)
|
return self.symtab.fetch_local_type(self.current_routine.name, name)
|
||||||
return self.symtab.fetch_global_type(name)
|
return self.symtab.fetch_global_type(name)
|
||||||
|
|
||||||
def get_type(self, ref):
|
def get_type(self, ref):
|
||||||
@ -76,9 +76,9 @@ class Compiler(object):
|
|||||||
|
|
||||||
def get_label(self, name):
|
def get_label(self, name):
|
||||||
if self.current_routine:
|
if self.current_routine:
|
||||||
static_label = self.routine_statics.get(self.current_routine.name, {}).get(name)
|
local_label = self.routine_locals.get(self.current_routine.name, {}).get(name)
|
||||||
if static_label:
|
if local_label:
|
||||||
return static_label
|
return local_label
|
||||||
return self.labels[name]
|
return self.labels[name]
|
||||||
|
|
||||||
def absolute_or_zero_page(self, label):
|
def absolute_or_zero_page(self, label):
|
||||||
@ -107,16 +107,15 @@ class Compiler(object):
|
|||||||
label.set_addr(routine.addr)
|
label.set_addr(routine.addr)
|
||||||
self.labels[routine.name] = label
|
self.labels[routine.name] = label
|
||||||
|
|
||||||
if hasattr(routine, 'statics'):
|
self.current_routine = routine
|
||||||
self.current_routine = routine
|
local_labels = {}
|
||||||
static_labels = {}
|
for defn in routine.locals:
|
||||||
for defn in routine.statics:
|
length = self.compute_length_of_defn(defn)
|
||||||
length = self.compute_length_of_defn(defn)
|
label = Label(defn.name, addr=defn.addr, length=length)
|
||||||
label = Label(defn.name, addr=defn.addr, length=length)
|
local_labels[defn.name] = label
|
||||||
static_labels[defn.name] = label
|
declarations.append((defn, self.symtab.fetch_local_type(routine.name, defn.name), label))
|
||||||
declarations.append((defn, self.symtab.fetch_static_type(routine.name, defn.name), label))
|
self.routine_locals[routine.name] = local_labels
|
||||||
self.routine_statics[routine.name] = static_labels
|
self.current_routine = None
|
||||||
self.current_routine = None
|
|
||||||
|
|
||||||
if compilation_roster is None:
|
if compilation_roster is None:
|
||||||
compilation_roster = [['main']] + [[routine.name] for routine in program.routines if routine.name != 'main']
|
compilation_roster = [['main']] + [[routine.name] for routine in program.routines if routine.name != 'main']
|
||||||
|
@ -31,7 +31,7 @@ class ForwardReference(object):
|
|||||||
class SymbolTable(object):
|
class SymbolTable(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.symbols = {} # symbol name -> SymEntry
|
self.symbols = {} # symbol name -> SymEntry
|
||||||
self.statics = {} # routine name -> (symbol name -> SymEntry)
|
self.locals = {} # routine name -> (symbol name -> SymEntry)
|
||||||
self.typedefs = {} # type name -> Type AST
|
self.typedefs = {} # type name -> Type AST
|
||||||
self.consts = {} # const name -> ConstantRef
|
self.consts = {} # const name -> ConstantRef
|
||||||
|
|
||||||
@ -41,25 +41,25 @@ class SymbolTable(object):
|
|||||||
self.symbols[name] = SymEntry(None, TYPE_BIT)
|
self.symbols[name] = SymEntry(None, TYPE_BIT)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Symbols: {}\nStatics: {}\nTypedefs: {}\nConsts: {}".format(self.symbols, self.statics, self.typedefs, self.consts)
|
return "Symbols: {}\nLocals: {}\nTypedefs: {}\nConsts: {}".format(self.symbols, self.locals, self.typedefs, self.consts)
|
||||||
|
|
||||||
def has_static(self, routine_name, name):
|
def has_local(self, routine_name, name):
|
||||||
return name in self.statics.get(routine_name, {})
|
return name in self.locals.get(routine_name, {})
|
||||||
|
|
||||||
def fetch_global_type(self, name):
|
def fetch_global_type(self, name):
|
||||||
return self.symbols[name].type_
|
return self.symbols[name].type_
|
||||||
|
|
||||||
def fetch_static_type(self, routine_name, name):
|
def fetch_local_type(self, routine_name, name):
|
||||||
return self.statics[routine_name][name].type_
|
return self.locals[routine_name][name].type_
|
||||||
|
|
||||||
def fetch_global_ref(self, name):
|
def fetch_global_ref(self, name):
|
||||||
if name in self.symbols:
|
if name in self.symbols:
|
||||||
return LocationRef(name)
|
return LocationRef(name)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def fetch_static_ref(self, routine_name, name):
|
def fetch_local_ref(self, routine_name, name):
|
||||||
routine_statics = self.statics.get(routine_name, {})
|
routine_locals = self.locals.get(routine_name, {})
|
||||||
if name in routine_statics:
|
if name in routine_locals:
|
||||||
return LocationRef(name)
|
return LocationRef(name)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ class Parser(object):
|
|||||||
def lookup(self, name, allow_forward=False, routine_name=None):
|
def lookup(self, name, allow_forward=False, routine_name=None):
|
||||||
model = self.symtab.fetch_global_ref(name)
|
model = self.symtab.fetch_global_ref(name)
|
||||||
if model is None and routine_name:
|
if model is None and routine_name:
|
||||||
model = self.symtab.fetch_static_ref(routine_name, name)
|
model = self.symtab.fetch_local_ref(routine_name, name)
|
||||||
if model is None and allow_forward:
|
if model is None and allow_forward:
|
||||||
return ForwardReference(name)
|
return ForwardReference(name)
|
||||||
if model is None:
|
if model is None:
|
||||||
@ -88,10 +88,12 @@ class Parser(object):
|
|||||||
self.syntax_error('Symbol "%s" already declared' % name)
|
self.syntax_error('Symbol "%s" already declared' % name)
|
||||||
self.symtab.symbols[name] = SymEntry(ast_node, type_)
|
self.symtab.symbols[name] = SymEntry(ast_node, type_)
|
||||||
|
|
||||||
def declare_static(self, routine_name, name, ast_node, type_):
|
def declare_local(self, routine_name, name, ast_node, type_):
|
||||||
|
if self.symtab.fetch_local_ref(routine_name, name):
|
||||||
|
self.syntax_error('Symbol "%s" already declared locally' % name)
|
||||||
if self.symtab.fetch_global_ref(name):
|
if self.symtab.fetch_global_ref(name):
|
||||||
self.syntax_error('Symbol "%s" already declared' % name)
|
self.syntax_error('Symbol "%s" already declared globally' % name)
|
||||||
self.symtab.statics.setdefault(routine_name, {})[name] = SymEntry(ast_node, type_)
|
self.symtab.locals.setdefault(routine_name, {})[name] = SymEntry(ast_node, type_)
|
||||||
|
|
||||||
# ---- symbol resolution
|
# ---- symbol resolution
|
||||||
|
|
||||||
@ -306,17 +308,17 @@ class Parser(object):
|
|||||||
type_ = self.defn_type()
|
type_ = self.defn_type()
|
||||||
if not isinstance(type_, RoutineType):
|
if not isinstance(type_, RoutineType):
|
||||||
self.syntax_error("Can only define a routine, not {}".format(repr(type_)))
|
self.syntax_error("Can only define a routine, not {}".format(repr(type_)))
|
||||||
statics = []
|
locals_ = []
|
||||||
if self.scanner.consume('@'):
|
if self.scanner.consume('@'):
|
||||||
self.scanner.check_type('integer literal')
|
self.scanner.check_type('integer literal')
|
||||||
block = None
|
block = None
|
||||||
addr = int(self.scanner.token)
|
addr = int(self.scanner.token)
|
||||||
self.scanner.scan()
|
self.scanner.scan()
|
||||||
else:
|
else:
|
||||||
statics = self.statics()
|
locals_ = self.locals()
|
||||||
block = self.block()
|
block = self.block()
|
||||||
addr = None
|
addr = None
|
||||||
return type_, Routine(self.scanner.line_number, name=name, block=block, addr=addr, statics=statics)
|
return type_, Routine(self.scanner.line_number, name=name, block=block, addr=addr, locals=locals_)
|
||||||
|
|
||||||
def labels(self):
|
def labels(self):
|
||||||
accum = []
|
accum = []
|
||||||
@ -370,13 +372,19 @@ class Parser(object):
|
|||||||
loc = IndexedRef(loc, offset, index)
|
loc = IndexedRef(loc, offset, index)
|
||||||
return loc
|
return loc
|
||||||
|
|
||||||
def statics(self):
|
def locals(self):
|
||||||
defns = []
|
defns = []
|
||||||
while self.scanner.consume('static'):
|
while self.scanner.consume('static'):
|
||||||
type_, defn = self.defn()
|
type_, defn = self.defn()
|
||||||
if defn.initial is None:
|
if defn.initial is None:
|
||||||
self.syntax_error("Static definition {} must have initial value".format(defn))
|
self.syntax_error("Static definition {} must have initial value".format(defn))
|
||||||
self.declare_static(self.current_routine_name, defn.name, defn, type_)
|
self.declare_local(self.current_routine_name, defn.name, defn, type_)
|
||||||
|
defns.append(defn)
|
||||||
|
while self.scanner.consume('local'):
|
||||||
|
type_, defn = self.defn()
|
||||||
|
if defn.initial is not None:
|
||||||
|
self.syntax_error("Local definition {} may not have initial value".format(defn))
|
||||||
|
self.declare_local(self.current_routine_name, defn.name, defn, type_)
|
||||||
defns.append(defn)
|
defns.append(defn)
|
||||||
return defns
|
return defns
|
||||||
|
|
||||||
|
@ -4251,7 +4251,7 @@ The new style routine definitions support typedefs.
|
|||||||
| }
|
| }
|
||||||
= ok
|
= ok
|
||||||
|
|
||||||
### static ###
|
### locals ###
|
||||||
|
|
||||||
When memory locations are defined static to a routine, they cannot be
|
When memory locations are defined static to a routine, they cannot be
|
||||||
directly input, nor directly output; and since they are always initialized,
|
directly input, nor directly output; and since they are always initialized,
|
||||||
@ -4276,3 +4276,30 @@ they cannot be trashed. Thus, they really don't participate in the analysis.
|
|||||||
| call foo
|
| call foo
|
||||||
| }
|
| }
|
||||||
= ok
|
= ok
|
||||||
|
|
||||||
|
When memory locations are defined local to a routine, but not static,
|
||||||
|
they cannot be directly input, nor directly output; but they are considered
|
||||||
|
uninitialized from the time the routine is called to until a value is stored
|
||||||
|
in them.
|
||||||
|
|
||||||
|
| define main routine
|
||||||
|
| inputs x
|
||||||
|
| outputs x
|
||||||
|
| trashes z, n
|
||||||
|
| local byte t
|
||||||
|
| {
|
||||||
|
| st x, t
|
||||||
|
| inc t
|
||||||
|
| ld x, t
|
||||||
|
| }
|
||||||
|
= ok
|
||||||
|
|
||||||
|
| define main routine
|
||||||
|
| outputs x
|
||||||
|
| trashes z, n
|
||||||
|
| local byte t
|
||||||
|
| {
|
||||||
|
| inc t
|
||||||
|
| ld x, t
|
||||||
|
| }
|
||||||
|
? UnmeaningfulReadError: t
|
||||||
|
@ -746,13 +746,14 @@ Only routines can be defined in the new style.
|
|||||||
| }
|
| }
|
||||||
? SyntaxError
|
? SyntaxError
|
||||||
|
|
||||||
Memory locations can be defined static to a routine.
|
Memory locations can be defined local to a routine.
|
||||||
|
|
||||||
| define foo routine
|
| define foo routine
|
||||||
| inputs x
|
| inputs x
|
||||||
| outputs x
|
| outputs x
|
||||||
| trashes z, n
|
| trashes z, n
|
||||||
| static byte t : 0
|
| static byte t : 0
|
||||||
|
| local word w
|
||||||
| {
|
| {
|
||||||
| st x, t
|
| st x, t
|
||||||
| inc t
|
| inc t
|
||||||
@ -762,13 +763,14 @@ Memory locations can be defined static to a routine.
|
|||||||
| define main routine
|
| define main routine
|
||||||
| trashes a, x, z, n
|
| trashes a, x, z, n
|
||||||
| static byte t : 0
|
| static byte t : 0
|
||||||
|
| local word w
|
||||||
| {
|
| {
|
||||||
| ld x, t
|
| ld x, t
|
||||||
| call foo
|
| call foo
|
||||||
| }
|
| }
|
||||||
= ok
|
= ok
|
||||||
|
|
||||||
Static memory locations must always be given an initial value.
|
Local static memory locations must always be given an initial value.
|
||||||
|
|
||||||
| define main routine
|
| define main routine
|
||||||
| inputs x
|
| inputs x
|
||||||
@ -782,7 +784,21 @@ Static memory locations must always be given an initial value.
|
|||||||
| }
|
| }
|
||||||
? SyntaxError
|
? SyntaxError
|
||||||
|
|
||||||
Name of a static cannot shadow an existing global or static.
|
Local dynamic memory locations may not be given an initial value.
|
||||||
|
|
||||||
|
| define main routine
|
||||||
|
| inputs x
|
||||||
|
| outputs x
|
||||||
|
| trashes z, n
|
||||||
|
| local byte t : 10
|
||||||
|
| {
|
||||||
|
| st x, t
|
||||||
|
| inc t
|
||||||
|
| ld x, t
|
||||||
|
| }
|
||||||
|
? SyntaxError
|
||||||
|
|
||||||
|
Name of a local cannot shadow an existing global or local.
|
||||||
|
|
||||||
| byte t
|
| byte t
|
||||||
|
|
|
|
||||||
@ -790,7 +806,7 @@ Name of a static cannot shadow an existing global or static.
|
|||||||
| inputs x
|
| inputs x
|
||||||
| outputs x
|
| outputs x
|
||||||
| trashes z, n
|
| trashes z, n
|
||||||
| static byte t
|
| static byte t : 10
|
||||||
| {
|
| {
|
||||||
| st x, t
|
| st x, t
|
||||||
| inc t
|
| inc t
|
||||||
@ -802,11 +818,89 @@ Name of a static cannot shadow an existing global or static.
|
|||||||
| inputs x
|
| inputs x
|
||||||
| outputs x
|
| outputs x
|
||||||
| trashes z, n
|
| trashes z, n
|
||||||
| static byte t
|
| static byte t : 10
|
||||||
| static byte t
|
| static byte t : 20
|
||||||
| {
|
| {
|
||||||
| st x, t
|
| st x, t
|
||||||
| inc t
|
| inc t
|
||||||
| ld x, t
|
| ld x, t
|
||||||
| }
|
| }
|
||||||
? SyntaxError
|
? SyntaxError
|
||||||
|
|
||||||
|
| byte t
|
||||||
|
|
|
||||||
|
| define main routine
|
||||||
|
| inputs x
|
||||||
|
| outputs x
|
||||||
|
| trashes z, n
|
||||||
|
| local byte t
|
||||||
|
| {
|
||||||
|
| st x, t
|
||||||
|
| inc t
|
||||||
|
| ld x, t
|
||||||
|
| }
|
||||||
|
? SyntaxError
|
||||||
|
|
||||||
|
| define main routine
|
||||||
|
| inputs x
|
||||||
|
| outputs x
|
||||||
|
| trashes z, n
|
||||||
|
| local word w
|
||||||
|
| local word w
|
||||||
|
| {
|
||||||
|
| st x, t
|
||||||
|
| inc t
|
||||||
|
| ld x, t
|
||||||
|
| }
|
||||||
|
? SyntaxError
|
||||||
|
|
||||||
|
Since the names of locals are lexically local to a routine, they cannot
|
||||||
|
appear in the inputs, outputs, trashes list of the routine.
|
||||||
|
|
||||||
|
| define main routine
|
||||||
|
| inputs t
|
||||||
|
| static byte t : 0
|
||||||
|
| {
|
||||||
|
| inc t
|
||||||
|
| }
|
||||||
|
? SyntaxError
|
||||||
|
|
||||||
|
| define main routine
|
||||||
|
| outputs t
|
||||||
|
| static byte t : 0
|
||||||
|
| {
|
||||||
|
| inc t
|
||||||
|
| }
|
||||||
|
? SyntaxError
|
||||||
|
|
||||||
|
| define main routine
|
||||||
|
| trashes t
|
||||||
|
| static byte t : 0
|
||||||
|
| {
|
||||||
|
| inc t
|
||||||
|
| }
|
||||||
|
? SyntaxError
|
||||||
|
|
||||||
|
| define main routine
|
||||||
|
| inputs t
|
||||||
|
| local byte t
|
||||||
|
| {
|
||||||
|
| inc t
|
||||||
|
| }
|
||||||
|
? SyntaxError
|
||||||
|
|
||||||
|
| define main routine
|
||||||
|
| outputs t
|
||||||
|
| local byte t
|
||||||
|
| {
|
||||||
|
| inc t
|
||||||
|
| }
|
||||||
|
? SyntaxError
|
||||||
|
|
||||||
|
| define main routine
|
||||||
|
| trashes t
|
||||||
|
| local byte t
|
||||||
|
| {
|
||||||
|
| inc t
|
||||||
|
| }
|
||||||
|
? SyntaxError
|
||||||
|
Loading…
x
Reference in New Issue
Block a user