Ophis/src/Ophis/Environment.py

76 lines
2.2 KiB
Python

"""Symbol tables and environments for P65.
Implements the symbol lookup, through nested environments -
any non-temporary variable is stored at the top level."""
# Copyright 2002 Michael C. Martin.
# You may use, modify, and distribute this file under the BSD
# license: See LICENSE.txt for details.
from __future__ import nested_scopes
import Ophis.Errors as Err
class Environment:
"""Environment class.
Controls the various scopes and global abstract execution variables."""
def __init__(self):
self.dicts = [{}]
self.stack = [0]
self.pc = 0
self.segmentdict = {}
self.segment = "*text-default*"
self.scopecount = 0
def __contains__(self, item):
if item[0] == '_':
for dict in [self.dicts[i] for i in self.stack]:
if item in dict: return 1
return 0
return item in self.dicts[0]
def __getitem__(self, item):
if item[0] == '_':
for dict in [self.dicts[i] for i in self.stack]:
if item in dict: return dict[item]
else:
if item in self.dicts[0]: return self.dicts[0][item]
Err.log("Unknown label '%s'" % item)
return 0
def __setitem__(self, item, value):
if item[0] == '_':
self.dicts[self.stack[0]][item] = value
else:
self.dicts[0][item] = value
def __str__(self):
return str(self.dicts)
def getPC(self):
return self.pc
def setPC(self, value):
self.pc = value
def incPC(self, amount):
self.pc += amount
def getsegment(self):
return self.segment
def setsegment(self, segment):
self.segmentdict[self.segment] = self.pc
self.segment = segment
self.pc = self.segmentdict.get(segment, 0)
def reset(self):
"Clears out program counter, segment, and scoping information"
self.pc = 0
self.segmentdict = {}
self.segment = "*text-default*"
self.scopecount = 0
if len(self.stack) > 1:
Err.log("Unmatched .scope")
self.stack = [0]
def newscope(self):
"Enters a new scope for temporary labels."
self.scopecount += 1
self.stack.insert(0, self.scopecount)
if len(self.dicts) <= self.scopecount: self.dicts.append({})
def endscope(self):
"Leaves a scope."
if len(self.stack) == 1:
Err.log("Unmatched .scend")
self.stack.pop(0)