]> thyrsus.com Git - mad.git/commitdiff
Aarrgghh...must deduce types for function arguments.
authorEric S. Raymond <esr@thyrsus,com>
Fri, 30 Jan 2004 21:48:14 +0000 (21:48 +0000)
committerEric S. Raymond <esr@thyrsus,com>
Fri, 30 Jan 2004 21:48:14 +0000 (21:48 +0000)
mad

diff --git a/mad b/mad
index f7747ffb4e16d7293906f2b1421c991e6325fb1c..b3169302d60376db98235723800ff88a87eea776 100755 (executable)
--- 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)