]> thyrsus.com Git - mad.git/commitdiff
Type inference is working -- we compile hello, maxfunc, newton[12] and
authorEric S. Raymond <esr@thyrsus,com>
Mon, 9 Feb 2004 18:55:11 +0000 (18:55 +0000)
committerEric S. Raymond <esr@thyrsus,com>
Mon, 9 Feb 2004 18:55:11 +0000 (18:55 +0000)
quadratic now.

mad

diff --git a/mad b/mad
index ac3e8d6fed4f41a0631038ab5cd328ecc37745a7..25b33e7573f9621080475007e11a8a70549f394e 100755 (executable)
--- a/mad
+++ b/mad
@@ -443,7 +443,10 @@ def analyze():
                 deck.insert(i, (file, line, None, ('entry', 'main.', ())))
     # Mine the code for compile-time directives
     for (file, line, label, statement) in deck:
-        if statement[0] == 'dimension':
+        if statement[0] == 'boolean':
+            for var in statement[1:]:
+                typedict[currentfunc][var] = 'bool'
+        elif statement[0] == 'dimension':
             for (var, dimlist) in statement[1]:
                 dimensions[currentfunc][var] = dimlist
         elif statement == 'entry':
@@ -453,12 +456,6 @@ def analyze():
         elif statement[0] == 'integer':
             for var in statement[1:]:
                 typedict[currentfunc][var] = 'int'
-        elif statement[0] == 'return':
-            # Crude type inference -- give the function the type of the
-            # last return.
-            returntypes[currentfunc] = mode(statement[1])
-        elif statement[0] == 'substitution':
-            typedict[currentfunc][statement[1]] = 'double'
         elif statement[0] == 'values':
             var = statement[1]
             if var in refcount:
@@ -485,6 +482,36 @@ def analyze():
                 (fmt, types) = fmt_convert(format[statement[1]])
                 for (type, var) in zip(types, statement[2:]):
                     typedict[currentfunc][var] = type
+    # Type inference loop.  We initialized for this by deducing types
+    # from READ FORMAT statements. INTEGER, and BOOLEAN declarations
+    # above.  Now propagate int and bool type markers 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 == '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 in ('int','bool') and returntypes[currentfunc] != m:
+                    deductions += 1
+            elif statement[0] == 'substitution':
+                # Propagate type markers through assignment
+                m = mode(statement[2])
+                typedict[currentfunc][statement[1]] = m
+                if m in ('int','bool') 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]
@@ -524,6 +551,8 @@ def mode(t):
         # constants that fit in a 36-bit machine word.
         #print "<-mode of string ", t[1]
         return 'int'
+    elif t[0] == 'apply':
+        return returntypes.get(t[1], "double")
     elif t[0] in logops:
         #print "<-bool (logical operator)", t[1]
         return 'bool'
@@ -716,7 +745,7 @@ def print_statement(statement):
         return 'if (' + print_expr(statement[1]) + ') ' + print_statement(statement[2])
     elif statement[0] == 'internal':
         return '    %s %s {return %s;}' % \
-                      (mode(statement[3]), print_expr(('apply', statement[1], statement[2])), print_expr(statement[3]))
+                      (returntypes.get(statement[1], "double"), 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':