1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2025-04-06 17:39:38 +00:00

Statics are always writeable. Statics are always meaningful.

This commit is contained in:
Chris Pressey 2018-02-09 13:35:59 +00:00
parent b829836cdc
commit 55331e9c54
4 changed files with 53 additions and 8 deletions

View File

@ -53,6 +53,12 @@ class IncompatibleConstraintsError(ConstraintsError):
pass
def routine_has_static(routine, ref):
if not hasattr(routine, 'statics'):
return False
return ref in [static.location for static in routine.statics]
class Context(object):
"""
A location is touched if it was changed (or even potentially
@ -112,6 +118,9 @@ class Context(object):
def assert_meaningful(self, *refs, **kwargs):
exception_class = kwargs.get('exception_class', UnmeaningfulReadError)
for ref in refs:
# statics are always meaningful
if routine_has_static(self.routine, ref):
continue
if ref.is_constant() or ref in self.routines:
pass
elif isinstance(ref, LocationRef):
@ -129,6 +138,9 @@ class Context(object):
def assert_writeable(self, *refs, **kwargs):
exception_class = kwargs.get('exception_class', ForbiddenWriteError)
for ref in refs:
# statics are always writeable
if routine_has_static(self.routine, ref):
continue
if ref not in self._writeable:
message = '%s in %s' % (ref.name, self.routine.name)
if kwargs.get('message'):
@ -231,7 +243,7 @@ class Analyzer(object):
for ref in type_.outputs:
context.assert_meaningful(ref, exception_class=UnmeaningfulOutputError)
for ref in context.each_touched():
if ref not in type_.outputs and ref not in type_.trashes:
if ref not in type_.outputs and ref not in type_.trashes and not routine_has_static(routine, ref):
message = '%s in %s' % (ref.name, routine.name)
raise ForbiddenWriteError(message)
self.current_routine = None

View File

@ -145,7 +145,7 @@ class LocationRef(Ref):
# just to be sure.
equal = isinstance(other, self.__class__) and other.name == self.name
if equal:
assert other.type == self.type
assert other.type == self.type, repr((self, other))
return equal
def __hash__(self):

View File

@ -14,6 +14,9 @@ class SymEntry(object):
self.ast_node = ast_node
self.model = model
def __repr__(self):
return "%s(%r, %r)" % (self.__class__.__name__, self.ast_node, self.model)
class Parser(object):
def __init__(self, text):
@ -221,12 +224,7 @@ class Parser(object):
else:
statics = self.statics()
self.current_statics = {}
for defn in statics:
name = defn.name
if name in self.symbols or name in self.current_statics:
raise SyntaxError('Symbol "%s" already declared' % name)
self.current_statics[name] = SymEntry(defn, defn.location)
self.current_statics = self.compose_statics_dict(statics)
block = self.block()
self.current_statics = {}
@ -237,6 +235,15 @@ class Parser(object):
location=location, statics=statics
)
def compose_statics_dict(self, statics):
c = {}
for defn in statics:
name = defn.name
if name in self.symbols or name in self.current_statics:
raise SyntaxError('Symbol "%s" already declared' % name)
c[name] = SymEntry(defn, defn.location)
return c
def labels(self):
accum = []
accum.append(self.label())

View File

@ -2283,3 +2283,29 @@ The new style routine definitions support typedefs.
| copy foo, vec
| }
= ok
### static ###
When memory locations are defined static to a routine, they cannot be
directly input, nor directly output; and since they are always initialized,
they cannot be trashed. Thus, they really don't participate in the analysis.
| define foo routine
| inputs x
| outputs x
| trashes z, n
| static byte t : 0
| {
| st x, t
| inc t
| ld x, t
| }
|
| define main routine
| trashes a, x, z, n
| static byte t : 0
| {
| ld x, t
| call foo
| }
= ok