From f7448f76f3a458794718117eabdf59c634078d4b Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Tue, 27 Jan 2004 17:27:38 +0000 Subject: [PATCH] Reduce special cases. --- mad | 84 +++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/mad b/mad index 9cdcf5a..f7747ff 100755 --- a/mad +++ b/mad @@ -1,9 +1,12 @@ #!/usr/bin/env python reserved = ('CONDITIONAL', 'CONTINUE', 'DIMENSION', 'END', 'EXECUTE', - 'FOR', 'FORMAT', 'FUNCTION', 'INTEGER', 'INTERNAL', 'OF', - 'PAUSE', 'PRINT', 'PROGRAM', 'READ', 'COMMENT', 'THROUGH', - 'TO', 'TRANSFER', 'VALUES', 'VECTOR', 'WHENEVER') + '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') tokens = reserved + ( 'SEMI', 'COMMA', @@ -154,6 +157,19 @@ def p_execute_noargs(t): 'statement : EXECUTE FUNCALL' t[0] = ('execute', ('apply', t[2], [])) +## EXTERNAL FUNCTION +def p_external(t): + "statement : INTERNAL FUNCTION FUNCALL application" + t[0] = ('external', t[3], tuple(t[4])) + +## FUNCTION RETURN +def p_function_return(t): + "statement : FUNCTION RETURN expression" + t[0] = ('return', t[3]) +def p_function_return_void(t): + "statement : FUNCTION RETURN" + t[0] = ('return') + ## INTEGER def p_integer(t): 'statement : INTEGER varlist' @@ -168,7 +184,7 @@ def p_varlist_continue(t): ## INTERNAL FUNCTION def p_internal(t): "statement : INTERNAL FUNCTION FUNCALL application EQUALS expression" - t[0] = ('function', t[3], tuple(t[4]), t[6]) + t[0] = ('internal', t[3], tuple(t[4]), t[6]) ## PAUSE def p_pause(t): @@ -355,9 +371,9 @@ def declare(var, lst): untyped.remove(var) lst.append(var) -def analyze(deck): - "Gather variable types." - global integers, floats, bools +def analyze(): + "Gather variable types and determine function boundaries." + global integers, floats, bools, deck # Mine the code for compile-time directives for (line, label, statement) in deck: if statement[0] == 'integer': @@ -379,6 +395,9 @@ def analyze(deck): untyped.remove(var) else: format[var] = statement[2] + # We may need to generate a pseudo-function call + if deck[3][0] != 'external': + deck = [(0, None, ('external', 'main.', ()))] + deck def print_expr(t): if t[0] == 'variable': @@ -493,17 +512,18 @@ def fmt_convert(fmt, write=True): def print_statement(statement): if statement[0] in ('dimension', - 'end_program', - 'function', + 'internal', 'integer', 'values'): pass elif statement[0] == 'continue': return "/* continue */;" - elif statement[0] == 'end_conditional': + elif statement[0] in ('end_program', 'end_function', 'end_conditional'): return "}" elif statement[0] == 'execute': - return print_expr(statement[1]) + ";" + return print_expr(statement[1]) + ";" + elif statement[0] == 'external': + return "\n" + print_expr(('apply', statement[1], statement[2])) + " {" elif statement[0] == 'for': (keyword, label, dummy, start, increment, predicate) = statement return 'for (%s = %s; %s; %s += %s) {' % (dummy, print_expr(start), print_expr(predicate), dummy, print_expr(increment)) @@ -519,7 +539,12 @@ def print_statement(statement): if len(statement) == 1: return "\n" else: - return "/* %s */\n" % statement[1].strip() + return "/* %s */" % statement[1].strip() + elif statement[0] == 'return': + if len(statement) == 1: + return "return;" + else: + return "return %s" % peint_expr(statement[1]) elif statement[0] == 'or': return 'else if (' + print_expr(statement[2]) + ') {' elif statement[0] == 'otherwise': @@ -540,38 +565,37 @@ def print_statement(statement): def generate(out): out.write('#include \n\n') - for (line, label, statement) in deck: - if statement[0] == 'function': - # FIXME: someday, deduce when return is of integral type - out.write('float %s {return %s;}\n' % \ - (print_expr(('apply', statement[1], statement[2])), print_expr(statement[3]))) - - out.write('\nmain(int argc, char *argv[])\n') - out.write('{\n') if integers: - out.write('\tint ' + ', '.join(integers) + ';\t/* INTEGER */\n') + out.write('int ' + ', '.join(integers) + ';\t/* INTEGER */\n') if bools: - out.write('\tint ' + ', '.join(bools) + ';\t/* boolean */\n') + out.write('int ' + ', '.join(bools) + ';\t/* boolean */\n') if untyped: - out.write('\tfloat ' + ', '.join(untyped) + ';\t/* untyped */\n') + out.write('float ' + ', '.join(untyped) + ';\t/* untyped */\n') if floats: - out.write('\tfloat ' + ', '.join(floats) + ';\n') + out.write('float ' + ', '.join(floats) + ';\n') for (id, value) in static.items(): - out.write('\tstatic const char *%s\t= "%s";\n' % (id, fmt_convert(value))) + out.write('static const char *%s\t= "%s";\n' % (id, fmt_convert(value))) + for (line, label, statement) in deck: + if statement[0] == 'internal': + # FIXME: someday, deduce when return is of integral type + out.write('float %s {return %s;}\n' % \ + (print_expr(('apply', statement[1], statement[2])), print_expr(statement[3]))) + indent = 0 global sourceline for (sourceline, label, statement) in deck: if label in targets: - out.write(label+':') + out.write(" " + label+':\n') rep = print_statement(statement) if rep: - out.write('\t' + ' '*indent + rep + '\n') + if rep[-1] == '}': + indent -= 1 + out.write(' '*indent + rep + '\n') if rep[-1] == '{': indent += 1 if label in scopes: indent -= 1 - out.write(('\t' + ' '*indent) + '}\n') - out.write('}\n') + out.write((' '*indent) + '}\n') if __name__ == '__main__': import os, getopt @@ -616,7 +640,7 @@ if __name__ == '__main__': yacc.parse(source, debug=mad_debug) # Perform global analysis - analyze(deck) + analyze() if (dump_tuples): for t in deck: -- 2.43.0