]> thyrsus.com Git - mad.git/commitdiff
Before generating dummy variables.
authorEric S. Raymond <esr@thyrsus,com>
Tue, 10 Feb 2004 04:00:38 +0000 (04:00 +0000)
committerEric S. Raymond <esr@thyrsus,com>
Tue, 10 Feb 2004 04:00:38 +0000 (04:00 +0000)
mad

diff --git a/mad b/mad
index 4f495443420c42a0b53ab617813f7e444d285d6a..ac44b357ff83efa4e684642cb54c6bc923194463 100755 (executable)
--- a/mad
+++ b/mad
@@ -11,7 +11,7 @@ reserved = ('BOOLEAN', 'CONDITIONAL', 'CONTINUE', 'DIMENSION', 'END',
 
 tokens = reserved + (
     'SEMI', 'COMMA',
-    'NAME','INTNUM', 'FLOATNUM', 'BOOLNUM', 'STRING', 'FUNCALL',
+    'NAME','INTNUM', 'DOUBLENUM', 'BOOLNUM', 'STRING', 'FUNCALL',
     'LPAREN','RPAREN',
     'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
     'NOT', 'OR', 'AND', 'THEN', 'EQV',
@@ -60,7 +60,7 @@ def t_NAME(t):
     t.value = t.value.lower()
     return t
 
-def t_FLOATNUM(t):
+def t_DOUBLENUM(t):
     r'\d+\.\d*'
     if t.value[-1] == '.':
         t.value += "0"
@@ -290,11 +290,9 @@ def p_varlist_continue(t):
 def p_through_for(t):
     'statement : THROUGH NAME COMMA FOR NAME EQUALS expression COMMA expression COMMA expression'
     t[0] = ('for', t[2], t[5], t[7], t[9], t[11])
-    scopes.append(t[2])
 def p_through_map(t):
     'statement : THROUGH NAME COMMA FOR VALUES OF NAME EQUALS value_list'
     t[0] = ('map', t[2], t[7], t[9])
-    scopes.append(t[2])
 def p_map(t):
     'value_list : expression'
     t[0] = [t[1]]
@@ -387,8 +385,8 @@ def p_expression_integer(t):
     t[0] = ('intnum', t[1])
 
 def p_expression_float(t):
-    'expression : FLOATNUM'
-    t[0] = ('floatnum', t[1])
+    'expression : DOUBLENUM'
+    t[0] = ('doublenum', t[1])
 
 def p_expression_subscript(t):
     'expression : NAME application'
@@ -484,7 +482,7 @@ def analyze():
                 static[var] = statement[2]
                 untyped.remove(var)
             else:
-                format[var] = statement[2]
+                format[var] = statement[2][1:-1]
     # Reorder code tuples so internal functions are just after entry points
     for i in range(len(deck)):
         (file, line, label, statement) = deck[i]
@@ -561,7 +559,7 @@ def mode(t):
     elif t[0] == 'intnum':
         #print "<-mode of integer constant", t[1]
         return 'int'
-    elif t[0] == 'floatnum':
+    elif t[0] == 'doublenum':
         #print "<-mode of float constant", t[1]
         return 'double'
     elif t[0] == 'boolnum':
@@ -599,50 +597,52 @@ def prin1(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(prin1, t[2])) + ')'
     elif t[0] == '+':
         if len(t) == 2:
-            return '%s' % print_expr(t[1])
+            return '%s' % prin1(t[1])
         else:
-            return '(%s + %s)' % (print_expr(t[1]), print_expr(t[2]))
+            return '(%s + %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == '-':
         if len(t) == 2:
-            return '-%s' % print_expr(t[1])
+            return '-%s' % prin1(t[1])
         else:
-            return '(%s - %s)' % (print_expr(t[1]), print_expr(t[2]))
+            return '(%s - %s)' % (prin1(t[1]), prin1(t[2]))
+    elif t[0] == 'not':
+        return "!%s" % prin1(t[1])
     elif t[0] == '*':
-        return '(%s * %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return '(%s * %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == '/':
-        return '(%s / %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return '(%s / %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'l':
-        return '(%s < %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return '(%s < %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'g':
-        return '(%s > %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return '(%s > %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'le':
-        return '(%s <= %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return '(%s <= %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'ge':
-        return '(%s >= %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return '(%s >= %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'e':
-        return '(%s == %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return '(%s == %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'ne':
-        return '(%s != %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return '(%s != %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'p':
-        return 'pow(%s, %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return 'pow(%s, %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'and':
-        return '(%s && %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return '(%s && %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'or':
-        return '(%s || %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return '(%s || %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'then':
-        return '!(%s && !(%s))' % (print_expr(t[1]), print_expr(t[2]))
+        return '!(%s && !(%s))' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'eqv':
-        return '(%s == %s)' % (print_expr(t[1]), print_expr(t[2]))
+        return '(%s == %s)' % (prin1(t[1]), prin1(t[2]))
     elif t[0] == 'abs':
         argmode = mode(t[1])
         if argmode == 'double':
-            return 'fabs(%s)' % print_expr(t[1])
+            return 'fabs(%s)' % prin1(t[1])
         else:
-            return 'abs(%s)' % print_expr(t[1])        # int or bool
-    elif t[0] in ('intnum', 'floatnum'):
+            return 'abs(%s)' % prin1(t[1])     # int or bool
+    elif t[0] in ('intnum', 'doublenum'):
         return t[1]
     else:
         return '***'+`t`
@@ -654,15 +654,15 @@ def print_expr(t):
         res = res[1:-1]
     return res
 
-def fmt_convert(fmt, write=True):
+def fmt_convert(str, write=True):
     "Convert MAD format string to C printf/scanf"
+    #print "->fmt_convert(%s)" % str
     res = ''
     types = []
-    str = fmt[1:-1]
     while True:
         if str[0] == '*':
             break
-        if str[0] == '/':
+        elif str[0] == '/':
             res += '\\n'
             break
         elif str[0] in (' ', '\n', ','):
@@ -676,8 +676,7 @@ def fmt_convert(fmt, write=True):
                 sys.stderr.write('"%s", line %d: invalid spacer in %s\n' % (sourcefile, sourceline, str))
                 sys.exit(1)
             count = int(str[1:i])
-            if write:
-                res += ' ' * count
+            res += ' ' * count
             str = str[i:]
             continue
         # All other format codes may take a prefix.
@@ -688,7 +687,15 @@ def fmt_convert(fmt, write=True):
         if i > 0:
             count = int(str[:i])
             str = str[i:]
-        if str[0] == 'F':
+        # Now process the actual format item
+        if str[0] == '(':
+            i = str.find(')')
+            (innerfmt, innertypes) = fmt_convert(str[1:i]+"*", write=False)
+            res += innerfmt * count
+            str = str[i+1:]
+            for i in range(count):
+                types += innertypes * count
+        elif str[0] == 'F':
             i = 1
             while str[i] in '0123456789.':
                 i += 1
@@ -704,7 +711,10 @@ def fmt_convert(fmt, write=True):
             i = 1
             while str[i] in '0123456789':
                 i += 1
-            res += ('%' + str[1:i] + 'd') * count
+            lenprefix = str[1:i]
+            if lenprefix == '1':
+                lenprefix = ''
+            res += ('%' + lenprefix + 'd') * count
             str = str[i:]
             types += ['int'] * count
         else:
@@ -714,6 +724,7 @@ def fmt_convert(fmt, write=True):
     if write:
         res = res[1:]
         res = res + '\\n'
+    #print "<-fmt_convert() = %s" % res
     return (res, types)
 
 def print_statement(statement):
@@ -765,10 +776,17 @@ def print_statement(statement):
     elif statement[0] == 'goto':
         return 'goto ' + statement[1] + ';' 
     elif statement[0] == 'if':
+        scopes.append(t[1])
         return 'if (' + print_expr(statement[1]) + ') ' + print_statement(statement[2])
     elif statement[0] == 'internal':
-        return '    %s %s {return %s;}' % \
+        return '%s %s {return %s;}' % \
                       (returntypes.get(statement[1], normalmode), print_expr(('apply', statement[1], statement[2])), print_expr(statement[3]))
+    elif statement[0] == 'map':
+        scopes.append(statement[1])
+        count = len(statement[3])
+        rep='for (i = 0; i < %d; i++) { %s = '%(count ,statement[2])
+        rep += "((%s [%d]){%s})[i];" % (statement[3][0][0][:-3], count, ", ".join(map(lambda x: `x[1]`, statement[3])))
+        return rep
     elif statement[0] == 'otherwise':
         return 'else {'
     elif statement[0] == 'pause':
@@ -822,12 +840,16 @@ def generate(out):
             out.write("  " + label+':\n')
         rep = print_statement(statement)
         if rep:
-            indent -= rep.count('}')
+            indentchange = rep.count('{') - rep.count('}')
+            if indentchange < 0:
+                indent += indentchange
             out.write('    '*indent + rep + '\n')
-            indent += rep.count('{')
-        if label in scopes:
+            if indentchange > 0:
+                indent += indentchange
+        while scopes and label == scopes[-1]:
             indent -= 1
             out.write(('    '*indent) + '}\n')
+            scopes.pop()
 
 if __name__ == '__main__':
     import os, getopt