From 824fae5cbeb0119a6c2194796bf118de91e3711a Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Mon, 9 Feb 2004 18:55:11 +0000 Subject: [PATCH] Type inference is working -- we compile hello, maxfunc, newton[12] and quadratic now. --- mad | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/mad b/mad index ac3e8d6..25b33e7 100755 --- 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': -- 2.43.0