]> thyrsus.com Git - mad.git/commitdiff
Declarations are local now. Next, deduce and extract local variables.
authorEric S. Raymond <esr@thyrsus,com>
Sat, 31 Jan 2004 00:11:06 +0000 (00:11 +0000)
committerEric S. Raymond <esr@thyrsus,com>
Sat, 31 Jan 2004 00:11:06 +0000 (00:11 +0000)
mad

diff --git a/mad b/mad
index 6b44f905c66c24ed1b6745a4dc30f0a3e829b326..03e1f073c45b84c6128216453039d7bea6d99eca 100755 (executable)
--- a/mad
+++ b/mad
@@ -104,9 +104,11 @@ sourceline = 0
 deck = []
 scopes = []
 targets = {}
-untyped = []
 headers = []
 
+currentfunc = 'main.'
+typedict = {'main.':{}}
+
 # Program level
 
 def p_program(t):
@@ -153,7 +155,10 @@ def p_end_of_functions(t):
 ## ENTRY
 def p_entry(t):
     "statement : ENTRY TO FUNCALL"
-    t[0] = ('entry', t[3])
+    global currentfunc
+    currentfunc = t[3]
+    t[0] = ('entry', currentfunc)
+    typedict[currentfunc] = {}
 
 ## EXECUTE
 def p_execute(t):
@@ -271,9 +276,9 @@ def p_vector_values(t):
 ## Assignment
 def p_statement_substitution(t):
     'statement : NAME EQUALS expression'
-    t[0] = ('substitution', t[1], t[3])
-    if t[1] not in untyped:
-        untyped.append(t[1])
+    newvar = t[1]
+    t[0] = ('substitution', newvar, t[3])
+    typedict[currentfunc][newvar] = 'double'
 
 # Expression parsing
 
@@ -335,7 +340,9 @@ def p_expression_subscript(t):
     'expression : NAME application'
     t[0] = ('variable', t[1], tuple(t[2]))
     var = t[1]
-    refcount[var] = refcount.get(var, 0) + 1 
+    refcount[var] = refcount.get(var, 0) + 1
+    if not var in typedict[currentfunc]:
+        typedict[currentfunc][var] = 'double'
 
 def p_function_application(t):
     'expression : FUNCALL application'
@@ -361,8 +368,8 @@ def p_expression_name(t):
     var = t[1]
     t[0] = ('variable', var)
     refcount[var] = refcount.get(var, 0) + 1 
-    if var not in integers + bools + doubles + untyped:
-        untyped.append(var)
+    if not var in typedict[currentfunc]:
+        typedict[currentfunc][var] = 'double'
 
 # Error handling
 
@@ -374,9 +381,6 @@ yacc.yacc()
 
 import sys, re
 
-integers = []
-doubles = []
-bools = []
 dimensions = {}
 static = {}
 format = {}
@@ -384,21 +388,19 @@ format = {}
 # Map MAD intrinsics to C library functions
 madfunc_map = {'elog':'log'}
 
-def declare(var, lst):
-    if var in untyped:
-        untyped.remove(var)
-    lst.append(var)
-
 def croak(t, msg):
     (file, line, label, statement) = t
     sys.stderr.write('"%s", line %d: %s\n' % (file, line, msg))
 
 def analyze():
     "Gather variable types and determine function boundaries."
-    global integers, doubles, bools, deck
+    global deck, currentfunc
     # 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
+    for i in range(len(deck)):
+        if deck[i][3][0] != 'remark':
+            break
+    if deck[i][3][0] != 'external_function':
+        deck.insert(i, (deck[i][0], i, None, ('entry', ('apply', 'main.',()))))
     else:
         for i in range(len(deck)):
             (file, line, label, statement) = deck[i]
@@ -409,13 +411,13 @@ def analyze():
         if statement[0] == 'dimension':
             for (var, dimlist) in statement[1]:
                 dimensions[var] = dimlist
+        elif statement == 'entry':
+            currentfunc = statement[1][0]
         elif statement[0] == 'integer':
             for var in statement[1:]:
-                declare(var, integers)
+                typedict[currentfunc][var] = 'integer'
         elif statement[0] == 'substitution':
-            var = statement[1]
-            if var not in integers + bools + doubles + untyped:
-                untyped.append(var)
+            typedict[currentfunc][statement[1]] = 'double'
         elif statement[0] in ('read', 'print'):
             pass
         elif statement[0] == 'values':
@@ -572,7 +574,14 @@ def print_statement(statement):
     elif statement[0] in ('end_program', 'end_function', 'end_conditional'):
         return "}"
     elif statement[0] == 'entry':
-        return "\n" + print_expr(statement[1]) + " {"
+        rep = "\n" + print_expr(statement[1]) + " {"
+        funcname = statement[1][1]
+        localvars = typedict[funcname].keys()
+       for type in ('double', 'integer'):
+            vars = filter(lambda x: typedict[funcname][x] == type, localvars)
+            if vars: 
+                rep += "\n    " + type + " " + ", ".join(vars) + ";"
+        return rep
     elif statement[0] == 'execute':
         return print_expr(statement[1]) + ";"
     elif statement[0] == 'external_call':
@@ -620,14 +629,6 @@ def generate(out):
     for header in headers:
         out.write('#include <%s.h>\n\n' % header)
 
-    if integers:
-        out.write('int ' + ', '.join(integers) + ';\t/* INTEGER */\n')
-    if bools:
-        out.write('int ' + ', '.join(bools) + ';\t/* boolean */\n')
-    if untyped:
-        out.write('double ' + ', '.join(untyped) + ';\t/* untyped */\n')
-    if doubles:
-        out.write('double ' + ', '.join(doubles) + ';\n')
     for (id, value) in static.items():
         out.write('static const char *%s\t= "%s";\n' % (id,fmt_convert(value)))
     for (file, line, label, statement) in deck:
@@ -643,11 +644,9 @@ def generate(out):
             out.write("  " + label+':\n')
         rep = print_statement(statement)
         if rep:
-            if rep[-1] == '}':
-                indent -= 1
+            indent -= rep.count('}')
             out.write('    '*indent + rep + '\n')
-            if rep[-1] == '{':
-                indent += 1
+            indent += rep.count('{')
         if label in scopes:
             indent -= 1
             out.write(('    '*indent) + '}\n')