return t
def t_FUNCALL(t):
- r'[A-Z][A-Z0-9]*\.(?=\s*(\(|eos))'
+ r'[A-Z][A-Z0-9]*\.(?=\s*(\(|eos|,|\)))'
t.type = reserved_map.get(t.value, 'FUNCALL')
t.value = t.value.lower()
return t
if t[1] in ('elog.', 'sqrt.') and "math" not in headers:
headers.append("math")
+def p_expression_funcall0(t):
+ 'expression : FUNCALL'
+ var = t[1]
+ t[0] = ('variable', var)
+ refcount[var] = refcount.get(var, 0) + 1
+
def p_expression_name(t):
'expression : NAME'
var = t[1]
if statement[0] == 'end_function' and i < len(deck)-1 and deck[i+1][3][0] != 'extern':
deck.insert(i+1, (file, line, None, ('entry', 'main.', ())))
hasmain = True
- # Mine the code for compile-time directives
- for (file, line, label, statement) in deck:
- if statement[0] == 'boolean':
- for var in statement[1:]:
- typedict[currentfunc][var] = 'bool'
- elif statement[0] == 'dimension':
- for (var, dimlist) in statement[1]:
- dimensions[var] = dimlist
- elif statement[0] == 'entry':
- currentfunc = statement[1]
- funcline = line
- typedict[currentfunc] = {}
- elif statement[0] == 'integer':
- for var in statement[1:]:
- typedict[currentfunc][var] = 'int'
- elif statement[0] == 'normal':
- global normalmode
- normalmode = statement[1]
- elif statement[0] in ("print", "read"):
- if "stdio" not in headers:
- headers.append("stdio")
- elif statement[0] == 'values':
- var = statement[1]
- if var in refcount:
- static[var] = statement[2]
- else:
- format[var] = statement[2]
- # Reorder code tuples so internal functions are just after entry points
- lastentry = -1
- savelist = []
- internalcount = 0
- for i in range(len(deck)):
- (file, line, label, statement) = deck[i]
- if statement[0] == 'entry':
- lastentry = i
- internalcount = 1
- for line in savelist:
- deck.insert(i, deck.pop(line))
- savelist = []
- elif statement[0] == 'internal':
- if lastentry != -1:
- deck.insert(lastentry + internalcount, deck.pop(i))
- else:
- savelist.append(i)
- internalcount += 1
- # Reorder code tuples so SET LIST arrays are global.
- firstentry = -1
- for i in range(len(deck)):
- (file, line, label, statement) = deck[i]
- if statement[0] == 'entry' and firstentry == -1:
- firstentry = i
- elif statement[0] == 'set_list_to':
- deck.insert(firstentry, deck.pop(i))
- # Do type deductions from format fields
- for card in deck:
- (file, line, label, statement) = card
- 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:
- (fmt, types) = fmt_convert(format[statement[1]])
- for (vtype, var) in zip(types, statement[2:]):
- if type(var) == type(()) and var[0] == 'range':
- typedict[currentfunc][var[1]] = vtype
- else:
- typedict[currentfunc][var] = vtype
- # Type inference loop. We initialized for this by deducing types
- # from READ FORMAT statements. INTEGER, and BOOLEAN declarations
- # above. Now propagate markers of non-normalmode type through
- # expression evaluation until we can't deduce any more int or bool
- # type bindings for variables. Everything else just defaults to
- # double.
- while True:
- deductions = 0
+ try:
+ # Mine the code for compile-time directives
+ for (file, line, label, statement) in deck:
+ if statement[0] == 'boolean':
+ for var in statement[1:]:
+ typedict[currentfunc][var] = 'bool'
+ elif statement[0] == 'dimension':
+ for (var, dimlist) in statement[1]:
+ dimensions[var] = dimlist
+ elif statement[0] == 'entry':
+ currentfunc = statement[1]
+ funcline = line
+ typedict[currentfunc] = {}
+ elif statement[0] == 'integer':
+ for var in statement[1:]:
+ typedict[currentfunc][var] = 'int'
+ elif statement[0] == 'normal':
+ global normalmode
+ normalmode = statement[1]
+ elif statement[0] in ("print", "read"):
+ if "stdio" not in headers:
+ headers.append("stdio")
+ elif statement[0] == 'values':
+ var = statement[1]
+ if var in refcount:
+ static[var] = statement[2]
+ else:
+ format[var] = statement[2]
+ # Reorder code tuples so internal functions are just after entry points
+ lastentry = -1
+ savelist = []
+ internalcount = 0
+ for i in range(len(deck)):
+ (file, line, label, statement) = deck[i]
+ if statement[0] == 'entry':
+ lastentry = i
+ internalcount = 1
+ for line in savelist:
+ deck.insert(i, deck.pop(line))
+ savelist = []
+ elif statement[0] == 'internal':
+ if lastentry != -1:
+ deck.insert(lastentry + internalcount, deck.pop(i))
+ else:
+ savelist.append(i)
+ internalcount += 1
+ # Reorder code tuples so SET LIST arrays are global.
+ firstentry = -1
+ for i in range(len(deck)):
+ (file, line, label, statement) = deck[i]
+ if statement[0] == 'entry' and firstentry == -1:
+ firstentry = i
+ elif statement[0] == 'set_list_to':
+ deck.insert(firstentry, deck.pop(i))
+ # Do type deductions from format fields
for card in deck:
(file, line, label, statement) = card
if statement[0] == 'entry':
- # Bookkeeping, so we know what function we're in
currentfunc = statement[1]
funcline = line
- elif statement[0] == 'return':
- # Give the function the type of the last return statement.
- # We're screwed if two different returns in a function have
- # different modes.
- m = mode(statement[1])
- returntypes[currentfunc] = m
- if m != normalmode and returntypes[currentfunc] != m:
- deductions += 1
- elif statement[0] == 'restore':
- for var in statement[1]:
- typedict[currentfunc][var] = normalmode
- elif statement[0] == 'substitution':
- # Propagate type markers through assignment
- var = statement[1]
- m = mode(statement[2])
- typedict[currentfunc][var] = m
- if m != normalmode and typedict[currentfunc][statement[1]]!=m:
- deductions += 1
- if deductions == 0:
- break
- # Now associate entry point names with function definitions:
- for i in range(len(deck)):
- (file, line, label, statement) = deck[i]
- if statement[0] == 'entry' and len(statement) == 2:
- name = statement[1]
- for j in range(i):
- prev = deck[i-j-1][3]
- if prev[0] == 'external_function':
- deck[i] = (file, line, label, ('entry', name, prev[1]))
- break
- elif prev[0] == 'entry':
- croak(deck[i-j-1],"multiple ENTRY points are not supported")
- else:
- croak(deck[i], 'no EXTERNAL declaration matches this ENTRY')
+ elif statement[0] == 'read':
+ if statement[1] not in format:
+ croak(card, "uninitialized format string" +`statement[1]`)
+ else:
+ (fmt, types) = fmt_convert(format[statement[1]])
+ for (vtype, var) in zip(types, statement[2:]):
+ if type(var) == type(()) and var[0] == 'range':
+ typedict[currentfunc][var[1]] = vtype
+ else:
+ typedict[currentfunc][var] = vtype
+ # Type inference loop. We initialized for this by deducing types
+ # from READ FORMAT statements. INTEGER, and BOOLEAN declarations
+ # above. Now propagate markers of non-normalmode type through
+ # expression evaluation until we can't deduce any more int or bool
+ # type bindings for variables. Everything else just defaults to
+ # double.
+ while True:
+ deductions = 0
+ for card in deck:
+ (file, line, label, statement) = card
+ if statement[0] == 'entry':
+ # Bookkeeping, so we know what function we're in
+ currentfunc = statement[1]
+ funcline = line
+ elif statement[0] == 'return':
+ # Give the function the type of the last return statement.
+ # We're screwed if two different returns in a function have
+ # different modes.
+ m = mode(statement[1])
+ returntypes[currentfunc] = m
+ if m != normalmode and returntypes[currentfunc] != m:
+ deductions += 1
+ elif statement[0] == 'restore':
+ for var in statement[1]:
+ typedict[currentfunc][var] = normalmode
+ elif statement[0] == 'substitution':
+ # Propagate type markers through assignment
+ var = statement[1]
+ m = mode(statement[2])
+ typedict[currentfunc][var] = m
+ if m != normalmode and typedict[currentfunc][statement[1]]!=m:
+ deductions += 1
+ if deductions == 0:
+ break
+ # Now associate entry point names with function definitions:
+ for i in range(len(deck)):
+ (file, line, label, statement) = deck[i]
+ if statement[0] == 'entry' and len(statement) == 2:
+ name = statement[1]
+ for j in range(i):
+ prev = deck[i-j-1][3]
+ if prev[0] == 'external_function':
+ deck[i] = (file, line, label, ('entry', name, prev[1]))
+ break
+ elif prev[0] == 'entry':
+ croak(deck[i-j-1],"multiple ENTRY points are not supported")
+ else:
+ croak(deck[i], 'no EXTERNAL declaration matches this ENTRY')
+ except:
+ sys.stderr.write("mad: internal error while analyzing code for line %d\n" % line)
+ (exc_type, exc_value, exc_traceback) = sys.exc_info()
+ raise exc_type, exc_value, exc_traceback
def mode(t):
"Compute the return type of an expression"
types = typedict[currentfunc]
rep = "\n" + returntypes.get(currentfunc, normalmode) + " " + currentfunc[:-1] + "("
defaulted = []
- if statement[2]:
+ if len(statement) > 2:
for (dummy, var) in statement[2]:
declarator = ("*" * arraydepths.get(var, 0)) + var
if var in types:
rep = rep + ") {"
#if defaulted:
# sys.stderr.write("warning: defaulted base type for %s\n" % ", ".join(defaulted))
- declarations = ""
+ declarations = "\n"
for vtype in ('double', 'int', 'bool', 'char'):
vars = filter(lambda x: types[x] == vtype, types.keys())
if vars: