From: Eric S. Raymond Date: Fri, 30 Jan 2004 21:48:14 +0000 (+0000) Subject: Aarrgghh...must deduce types for function arguments. X-Git-Tag: 1.0~160 X-Git-Url: http://thyrsus.com/gitweb/?a=commitdiff_plain;h=6b044f0b8e9be5980077c067260e38cf61b1f514;p=mad.git Aarrgghh...must deduce types for function arguments. --- diff --git a/mad b/mad index f7747ff..b316930 100755 --- a/mad +++ b/mad @@ -1,6 +1,6 @@ #!/usr/bin/env python -reserved = ('CONDITIONAL', 'CONTINUE', 'DIMENSION', 'END', 'EXECUTE', +reserved = ('CONDITIONAL', 'CONTINUE', 'DIMENSION', 'END', 'ENTRY', 'EXECUTE', 'EXTERNAL', 'FOR', 'FORMAT', 'FUNCTION', 'INTEGER', 'INTERNAL', 'OF', 'PAUSE', 'PRINT', 'PROGRAM', 'READ', 'RETURN', 'THROUGH', 'TO', 'TRANSFER', 'VALUES', 'VECTOR', @@ -114,11 +114,11 @@ def p_program(t): def p_card(t): 'card : statement SEMI' - deck.append((t.lineno(1), None, t[1])) + deck.append((sourcefile, t.lineno(1), None, t[1])) def p_labeled_card(t): 'card : NAME statement SEMI' - deck.append((t.lineno(1), t[1], t[2])) + deck.append((sourcefile, t.lineno(1), t[1], t[2])) # Statement level @@ -149,6 +149,11 @@ def p_end_of_functions(t): 'statement : END OF FUNCTION' t[0] = ('end_function',) +## ENTRY +def p_entry(t): + "statement : ENTRY TO FUNCALL" + t[0] = ('entry', t[3]) + ## EXECUTE def p_execute(t): 'statement : EXECUTE FUNCALL application' @@ -157,10 +162,15 @@ def p_execute_noargs(t): 'statement : EXECUTE FUNCALL' t[0] = ('execute', ('apply', t[2], [])) +## EXTERNAL +def p_external_call(t): + "statement : EXTERNAL FUNCALL application" + t[0] = ('external_call', t[2], tuple(t[3])) + ## EXTERNAL FUNCTION -def p_external(t): - "statement : INTERNAL FUNCTION FUNCALL application" - t[0] = ('external', t[3], tuple(t[4])) +def p_external_function(t): + "statement : EXTERNAL FUNCTION application" + t[0] = ('external_function', tuple(t[3])) ## FUNCTION RETURN def p_function_return(t): @@ -374,14 +384,22 @@ def declare(var, lst): def analyze(): "Gather variable types and determine function boundaries." global integers, floats, bools, deck + # We may need to generate a pseudo-function call + if deck[0][3][0] != 'external_function': + deck = [(deck[0][0], 0, None, ('entry', ('apply', 'main.',())))] + deck + else: + for i in range(len(deck)): + (file, line, label, statement) = deck[i] + if statement[0] == 'end_function' and i < len(deck)-1 and deck[i+1][2][0] != 'extern': + deck.insert(i, (file, line, None, ('entry', ('apply', 'main.', ())))) # Mine the code for compile-time directives - for (line, label, statement) in deck: - if statement[0] == 'integer': - for var in statement[1:]: - declare(var, integers) - elif statement[0] == 'dimension': + for (file, line, label, statement) in deck: + if statement[0] == 'dimension': for (var, dimlist) in statement[1]: dimensions[var] = dimlist + elif statement[0] == 'integer': + for var in statement[1:]: + declare(var, integers) elif statement[0] == 'substitution': var = statement[1] if var not in integers + bools + floats + untyped: @@ -395,11 +413,20 @@ def analyze(): 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 + # 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 type(statement[1]) == type(""): + name = statement[1] + for j in range(i): + if deck[i-j-1][3][0] == 'external_function': + deck[i] = (file, line, label, + ('entry', ('apply', name, deck[i-j-1][3][1]))) + break + else: + sys.stderr.write('"%s", line %d: no EXTERNAL declaration matches this ENTRY\n' % (file, line)) -def print_expr(t): +def prin1(t): if t[0] == 'variable': res = t[1] if len(t) > 2: @@ -408,7 +435,7 @@ def print_expr(t): return res elif t[0] == 'apply': madfunc = t[1][:-1] - return madfunc_map.get(madfunc, madfunc) + '(' + ' ,'.join(map(print_expr, t[2])) + ')' + return madfunc_map.get(madfunc, madfunc) + '(' + ', '.join(map(print_expr, t[2])) + ')' elif t[0] == '+': if len(t) == 2: return '%s' % print_expr(t[1]) @@ -452,6 +479,13 @@ def print_expr(t): else: return '***'+`t` +def print_expr(t): + "Cosmetic wrapper round prin1" + res = prin1(t) + if res[0] == "(" and res[-1] == ")": + res = res[1:-1] + return res + def fmt_convert(fmt, write=True): "Convert MAD format string to C printf/scanf" res = '' @@ -512,6 +546,7 @@ def fmt_convert(fmt, write=True): def print_statement(statement): if statement[0] in ('dimension', + 'external_function', 'internal', 'integer', 'values'): @@ -520,10 +555,12 @@ def print_statement(statement): return "/* continue */;" elif statement[0] in ('end_program', 'end_function', 'end_conditional'): return "}" + elif statement[0] == 'entry': + return "\n" + print_expr(statement[1]) + " {" elif statement[0] == 'execute': return print_expr(statement[1]) + ";" - elif statement[0] == 'external': - return "\n" + print_expr(('apply', statement[1], statement[2])) + " {" + elif statement[0] == 'external_call': + 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)) @@ -544,7 +581,7 @@ def print_statement(statement): if len(statement) == 1: return "return;" else: - return "return %s" % peint_expr(statement[1]) + return "return %s" % print_expr(statement[1]) elif statement[0] == 'or': return 'else if (' + print_expr(statement[2]) + ') {' elif statement[0] == 'otherwise': @@ -574,8 +611,8 @@ def generate(out): if floats: out.write('float ' + ', '.join(floats) + ';\n') for (id, value) in static.items(): - out.write('static const char *%s\t= "%s";\n' % (id, fmt_convert(value))) - for (line, label, statement) in deck: + 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('float %s {return %s;}\n' % \ @@ -583,7 +620,7 @@ def generate(out): indent = 0 global sourceline - for (sourceline, label, statement) in deck: + for (file, sourceline, label, statement) in deck: if label in targets: out.write(" " + label+':\n') rep = print_statement(statement)