From 732c273ca7325aab7b60d2f56473323704274972 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Sat, 31 Jan 2004 02:53:32 +0000 Subject: [PATCH] Ready to try optimizing. --- mad | 117 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 31 deletions(-) diff --git a/mad b/mad index 84588da..8a48df9 100755 --- a/mad +++ b/mad @@ -1,10 +1,10 @@ #!/usr/bin/env python -reserved = ('CONDITIONAL', 'CONTINUE', 'DIMENSION', 'END', 'ENTRY', 'EXECUTE', - 'EXTERNAL', 'FOR', 'FORMAT', 'FUNCTION', 'INTEGER', - 'INTERNAL', 'OF', 'PAUSE', 'PRINT', 'PROGRAM', 'READ', - 'RETURN', 'THROUGH', 'TO', 'TRANSFER', 'VALUES', 'VECTOR', - 'WHENEVER', +reserved = ('BOOLEAN', 'CONDITIONAL', 'CONTINUE', 'DIMENSION', 'END', + 'ENTRY', 'EXECUTE', 'EXTERNAL', 'FOR', 'FORMAT', + 'FUNCTION', 'INTEGER', 'INTERNAL', 'OF', 'PAUSE', 'PRINT', + 'PROGRAM', 'READ', 'RETURN', 'THROUGH', 'TO', 'TRANSFER', + 'VALUES', 'VECTOR', 'WHENEVER', # This is a pseudo-keyword generated early in compilation. 'COMMENT') @@ -18,6 +18,9 @@ tokens = reserved + ( 'ABS', 'POW', ) +logops = ('NOT', 'OR', 'AND', 'THEN', 'EQV', + 'EQ', 'NE', 'LT', 'LE', 'GT', 'GE',) + # Tokens t_SEMI = r';' @@ -105,6 +108,7 @@ deck = [] scopes = [] targets = {} headers = [] +funcnames = [] currentfunc = 'main.' typedict = {'main.':{}} @@ -125,6 +129,19 @@ def p_labeled_card(t): # Statement level +## BOOLEAN +def p_boolean(t): + 'statement : BOOLEAN boollist' + t[0] = ('boolean',) + tuple(t[2]) +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[1]] = 'bool' + ## CONTINUE def p_statement_continue(t): 'statement : CONTINUE' @@ -159,6 +176,7 @@ def p_entry(t): currentfunc = t[3] t[0] = ('entry', currentfunc) typedict[currentfunc] = {} + funcnames.append(currentfunc) ## EXECUTE def p_execute(t): @@ -188,19 +206,22 @@ def p_function_return_void(t): ## INTEGER def p_integer(t): - 'statement : INTEGER varlist' + 'statement : INTEGER intlist' t[0] = ('integer',) + tuple(t[2]) -def p_varlist(t): - 'varlist : NAME' +def p_intlist(t): + 'intlist : NAME' t[0] = [t[1]] -def p_varlist_continue(t): - 'varlist : varlist COMMA NAME' + 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): "statement : INTERNAL FUNCTION FUNCALL application EQUALS expression" t[0] = ('internal', t[3], tuple(t[4]), t[6]) + funcnames.append(t[3]) ## PAUSE def p_pause(t): @@ -234,6 +255,13 @@ def p_remark2(t): def p_read_format(t): 'statement : READ FORMAT NAME COMMA varlist' t[0] = ('read', t[3]) + tuple(t[5]) +def p_varlist(t): + 'varlist : NAME' + t[0] = [t[1]] +def p_varlist_continue(t): + 'varlist : varlist COMMA NAME' + t[0] = t[1] + [t[3]] + ## THROUGH def p_through_for(t): @@ -278,7 +306,6 @@ def p_statement_substitution(t): 'statement : NAME EQUALS expression' newvar = t[1] t[0] = ('substitution', newvar, t[3]) - typedict[currentfunc][newvar] = 'double' # Expression parsing @@ -341,8 +368,6 @@ def p_expression_subscript(t): t[0] = ('variable', t[1], tuple(t[2])) var = t[1] refcount[var] = refcount.get(var, 0) + 1 - if not var in typedict[currentfunc]: - typedict[currentfunc][var] = 'double' def p_function_application(t): 'expression : FUNCALL application' @@ -368,8 +393,6 @@ def p_expression_name(t): var = t[1] t[0] = ('variable', var) refcount[var] = refcount.get(var, 0) + 1 - if not var in typedict[currentfunc]: - typedict[currentfunc][var] = 'double' # Error handling @@ -413,13 +436,12 @@ def analyze(): dimensions[var] = dimlist elif statement == 'entry': currentfunc = statement[1] + funcline = line elif statement[0] == 'integer': for var in statement[1:]: typedict[currentfunc][var] = 'int' elif statement[0] == 'substitution': typedict[currentfunc][statement[1]] = 'double' - elif statement[0] in ('read', 'print'): - pass elif statement[0] == 'values': var = statement[1] if var in refcount: @@ -427,6 +449,16 @@ def analyze(): untyped.remove(var) else: format[var] = statement[2] + # Do type deductions from format fields + for card in deck: + (file, line, label, statement) = card + if 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 (type, var) in zip(types, statement[2:]): + typedict[currentfunc][var] = type # Now associate entry point names with function definitions: for i in range(len(deck)): (file, line, label, statement) = deck[i] @@ -442,6 +474,15 @@ def analyze(): else: croak(deck[i], 'no EXTERNAL declaration matches this ENTRY') +def mode(t): + "Compute the return type of an expression" + if t[0] == 'variable': + return typedict[currentfunc].get(t[1], 'double') + elif t[0] in logops: + return 'bool' + else: + return 'double' + def prin1(t): if t[0] == 'variable': res = t[1] @@ -489,7 +530,11 @@ def prin1(t): elif t[0] == 'eqv': return '(%s == %s)' % (print_expr(t[1]), print_expr(t[2])) elif t[0] == 'abs': - return 'abs(%s)' % print_expr(t[1]) + argmode = mode(t[1]) + if argmode == 'double': + return 'fabs(%s)' % print_expr(t[1]) + else: + return 'abs(%s)' % print_expr(t[1]) # int or bool elif t[0] in ('intnum', 'floatnum'): return t[1] else: @@ -505,6 +550,7 @@ def print_expr(t): def fmt_convert(fmt, write=True): "Convert MAD format string to C printf/scanf" res = '' + types = [] str = fmt[1:-1] while True: if str[0] == '*': @@ -541,16 +587,19 @@ def fmt_convert(fmt, write=True): i += 1 res += ('%' + str[1:i] + 'g') * count str = str[i:] + types += ['double'] * count elif str[0] == 'H': if write: res += str[1:count+1] str = str[count+1:] + types += ['string'] elif str[0] == 'I': i = 1 while str[i] in '0123456789': i += 1 res += ('%' + str[1:i] + 'd') * count str = str[i:] + types += ['int'] * count else: sys.stderr.write('"%s", line %d: invalid field code %s at %d in format string %s!\n' % (sourcefile, sourceline, `str[0]`, len(fmt)-len(str), `fmt`)) sys.exit(1) @@ -558,12 +607,12 @@ def fmt_convert(fmt, write=True): if write: res = res[1:] res = res + '\\n' - return res + return (res, types) def print_statement(statement): - if statement[0] in ('dimension', + if statement[0] in ('boolean', + 'dimension', 'external_function', - 'internal', 'integer', 'values'): pass @@ -585,7 +634,7 @@ def print_statement(statement): rep = rep[:-2] rep = rep + ") {" declarations = "" - for type in ('double', 'int'): + for type in ('double', 'int', 'bool'): vars = filter(lambda x: types[x] == type, types.keys()) if vars: declarations += type + " " + ", ".join(vars) + "; " @@ -603,10 +652,14 @@ def print_statement(statement): return 'goto ' + statement[1] + ';' elif statement[0] == 'if': return 'if (' + print_expr(statement[1]) + ') ' + print_statement(statement[2]) + elif statement[0] == 'internal': + return ' double %s {return %s;}\n' % \ + (print_expr(('apply', statement[1], statement[2])), print_expr(statement[3])) elif statement[0] == 'pause': return('printf("%o", ' + print_expr(statement[1]) + '); getchar();') elif statement[0] == 'read': - return 'scanf("' + fmt_convert(format[statement[1]], write=False) + '", ' + ', '.join(map(lambda x: '&'+x, statement[2:])) + ');' + (fmt, types) = fmt_convert(format[statement[1]], write=False) + return 'scanf("' + fmt + '", ' + ', '.join(map(lambda x: '&'+x, statement[2:])) + ');' elif statement[0] == 'remark': if len(statement) == 1: return "\n" @@ -622,7 +675,7 @@ def print_statement(statement): elif statement[0] == 'otherwise': return 'else {' elif statement[0] == 'print': - fmt = fmt_convert(format[statement[1]]) + (fmt, types) = fmt_convert(format[statement[1]]) if len(statement) < 3: return 'printf("' + fmt + '");' else: @@ -635,17 +688,18 @@ def print_statement(statement): return('// ' + `statement`) def generate(out): - out.write("/* generated by the MAD compiler */\n\n") + out.write("/* generated by the MAD compiler */\n") for header in headers: out.write('#include <%s.h>\n\n' % header) + needbool = False + for funvars in typedict.values(): + if 'bool' in funvars.values(): + needbool = True + if needbool: + out.write("typedef int bool;\n") for (id, value) in static.items(): out.write('static const char *%s\t= "%s";\n' % (id,fmt_convert(value))) - for (file, line, label, statement) in deck: - if statement[0] == 'internal': - # FIXME: someday, deduce when return is of integral type - out.write('double %s {return %s;}\n' % \ - (print_expr(('apply', statement[1], statement[2])), print_expr(statement[3]))) indent = 0 global sourceline @@ -730,7 +784,8 @@ if __name__ == '__main__': out.close() srclist = " ".join(map(lambda x: x[:-4] + ".c", arguments)) if binary: - compile = "cc %s -lm -o %s" % (srclist, target) + # Must be gcc, else compilation of internal functions will fail + compile = "gcc %s -lm -o %s" % (srclist, target) if os.system(compile) == 0: os.system("rm -f " + srclist) -- 2.43.0