)
refcount = {}
-sourcefile = ""
-sourceline = 0
-deck = []
-scopes = []
-targets = {}
-headers = []
-funcnames = []
-typedict = {}
-arraydepths = {}
-returntypes = {}
-normalmode = 'double'
-dummycount = 0
-dimensions = {}
-static = {}
-format = {}
-hasmain = False
+sourcefile = "" # Current source file for error messages
+sourceline = 0 # Current source line for error messages
+deck = [] # List of tuples generated by parsing
+scopes = [] # THROUGH scopes that are pending
+targets = {} # Dictionary of targets of TRANSFERs
+headers = [] # Required .h file basenames
+funcnames = [] # List of function names
+dimensions = {} # Dictionary of array depths
+arraydepths = {} # Dictionary of array dimensions
+returntypes = {} # Dictionary of function returntypes
+normalmode = 'double' # Default type as set by NORMAL statement
+dummycount = 0 # Count of FOR VALUES statements
+static = {} # Dictionary of static char variables
+format = {} # Dictionary of format strings
+hasmain = False # Does this program have a main line?
def initfunc(f):
global currentfunc
currentfunc = f
- typedict[currentfunc] = {}
funcnames.append(currentfunc)
initfunc("main.")
def p_boollist(t):
'boollist : NAME'
t[0] = [t[1]]
- typedict[currentfunc][t[1]] = 'bool'
def p_boollist_continue(t):
'boollist : boollist COMMA NAME'
t[0] = t[1] + [t[3]]
- typedict[currentfunc][t[3]] = 'bool'
## CONTINUE
def p_statement_continue(t):
## ENTRY
def p_entry(t):
"statement : ENTRY TO FUNCALL"
- global currentfunc
initfunc(t[3])
- t[0] = ('entry', currentfunc)
+ t[0] = ('entry', t[3])
## EXECUTE
def p_execute(t):
def p_intlist(t):
'intlist : NAME'
t[0] = [t[1]]
- typedict[currentfunc][t[1]] = 'int'
def p_intlist_continue(t):
'intlist : intlist COMMA NAME'
t[0] = t[1] + [t[3]]
- typedict[currentfunc][t[3]] = 'int'
## INTERNAL FUNCTION
def p_internal(t):
(file, line, label, statement) = t
sys.stderr.write('"%s", line %d: %s\n' % (file, line, msg))
+# All MAD variables are global, you have to simulate locals using SAVE DATA and
+# RETURN DATA. Thus most of the variable lookup tables about are straight
+# dictionaries not qualified by current function name. typedict is an
+# exception; we use this to generate per-function variables as C auto
+# variables and get nicer C code. This would break if two MAD external
+# functions deliberately shared a global, but this doesn't happen in
+# any of the examples.
+typedict = {} # Dictionary of per-function dictionaries of locals
+
def analyze():
"Gather variable types and determine function boundaries."
global deck, currentfunc, hasmain
elif statement[0] == 'dimension':
for (var, dimlist) in statement[1]:
dimensions[var] = dimlist
- elif statement == 'entry':
+ elif statement[0] == 'entry':
currentfunc = statement[1]
funcline = line
+ typedict[currentfunc] = {}
elif statement[0] == 'integer':
for var in statement[1:]:
typedict[currentfunc][var] = 'int'
# Do type deductions from format fields
for card in deck:
(file, line, label, statement) = card
- if statement[0] == 'read':
+ if statement[0] == 'entry':
+ currentfunc = statement[1]
+ funcline = line
+ elif statement[0] == 'read':
if statement[1] not in format:
croak(card, "uninitialized format string" +`statement[1]`)
else:
deductions = 0
for card in deck:
(file, line, label, statement) = card
- if statement == 'entry':
+ if statement[0] == 'entry':
# Bookkeeping, so we know what function we're in
currentfunc = statement[1]
funcline = line
deductions += 1
elif statement[0] == 'substitution':
# Propagate type markers through assignment
+ var = statement[1]
m = mode(statement[2])
- typedict[currentfunc][statement[1]] = m
+ typedict[currentfunc][var] = m
if m != normalmode and typedict[currentfunc][statement[1]]!=m:
deductions += 1
if deductions == 0:
return (res, types)
def print_statement(statement):
+ global currentfunc
if statement[0] in ('boolean',
'dimension',
'external_function',
elif statement[0] in ('end_program', 'end_function', 'end_conditional'):
return "}"
elif statement[0] == 'entry':
- func = statement[1]
- types = typedict[func]
- rep = "\n" + returntypes.get(func, normalmode) + " " + func[:-1] + "("
+ currentfunc = statement[1]
+ types = typedict[currentfunc]
+ rep = "\n" + returntypes.get(currentfunc, normalmode) + " " + currentfunc[:-1] + "("
defaulted = []
if statement[2]:
for (dummy, var) in statement[2]: