Commits

Anonymous committed 8bf0d19

Read and write locals rel baseptr. "Only" 27 fails for stackmac.

Comments (0)

Files changed (6)

eg/simple.castile

 fun main() {
+  var x = 12;
   if 4 < 5 {
-    return 2 * 3 + 4
+    x = 2 * 3 + 4
   } else {
-    return 0
+    x = 0
   }
+  return x
 }

src/castile/ast.py

         for child in self.children:
             assert isinstance(child, AST), \
               "child %r of %r is not an AST node" % (child, self)
+        self.aux = None  # typechecker may populate this
         #print "created %r" % self
 
     @property

src/castile/backends/stackmac.py

 # Compile to some hypothetical stack-based machine.
 # Not yet in a good way.
 
+# In a function like this:
+#
+# fun(x,y,z) {
+#   var a = 0;
+#   var b = 0;
+#   ...
+# }
+#
+# x is at baseptr - 3
+# y is at baseptr - 2
+# z is at baseptr - 1
+# a is at baseptr + 0
+# b is at baseptr + 1
+
 OPS = {
     '+': 'add',
     '-': 'sub',
         self.current_loop_end = None
         self.current_fun_lit = None
         self.global_pos = 0     # globals at the bottom of the stack
+        self.local_pos = 0      # locals after the passed arguments
 
     def get_label(self, pref):
         count = self.labels.get(pref, 0)
                 self.compile(child)
             self.out.write("""\
 ; call main
-global main_index
+get_global main_index
 call
 """)
         elif ast.type == 'Defn':
             save = self.current_fun_lit
             self.current_fun_lit = self.get_label('fun_lit')
             f = self.current_fun_lit
+            self.local_pos = 0  # XXX not quite.  arguments?
             self.out.write('%s:\n' % f)
+            self.out.write('set_baseptr\n')
             self.compile(ast.children[0])
             self.compile(ast.children[1])
             self.out.write('%s:\n' % l)
             self.current_fun_lit = save
         elif ast.type == 'Args':
             # first arg passed is DEEPEST, so go backwards.
-            pos = len(ast.children) - 1
+            pos = 0 - len(ast.children)
             for child in ast.children:
                 assert child.type == 'Arg'
-                self.out.write('%s_local_%s=%s\n' %
+                self.out.write('%s_local_%s=%d\n' %
                     (self.current_fun_lit, child.value, pos))
-                pos -= 1
+                pos += 1
         elif ast.type == 'Block':
             for child in ast.children:
                 self.compile(child)
         elif ast.type == 'VarDecl':
-            self.out.write('; push variable %s onto stack\n' % ast.value)
             self.compile(ast.children[0])
+            self.out.write('%s_local_%s=%s\n' %
+                (self.current_fun_lit, ast.value, self.local_pos))
+            self.local_pos += 1
         elif ast.type == 'While':
             start = self.get_label('loop_start')
             end = self.get_label('loop_end')
             self.compile(ast.children[1])
             self.out.write('%s\n' % OPS.get(ast.value, ast.value))
         elif ast.type == 'VarRef':
-            # TODO determine whether global or local!
-            self.out.write('pick %s_local_%s\n' % (self.current_fun_lit, ast.value))
+            if ast.aux == 'toplevel':
+                self.out.write('get_global %s_index\n' % (ast.value))
+            else:
+                self.out.write('get_local %s_local_%s\n' % (self.current_fun_lit, ast.value))
         elif ast.type == 'FunCall':
             for child in ast.children[1:]:
                 self.out.write('; push argument\n')
         elif ast.type == 'Assignment':
             self.compile(ast.children[1])
             self.out.write('; assign to...\n')
-            self.compile(ast.children[0])
-            self.out.write('assign\n')
+            assert ast.children[0].type == 'VarRef'
+            self.out.write('set_local %s_local_%s\n' % (self.current_fun_lit, ast.children[0].value))
         elif ast.type == 'Make':
             #~ self.out.write('{')
             #~ self.commas(ast.children[1:])

src/castile/checker.py

         global_context = {}
         for (name, (value, type)) in BUILTINS.iteritems():
             global_context[name] = type
-        self.context = ScopedContext(global_context)
-        self.toplevel_context = ScopedContext({}, self.context)
+        self.context = ScopedContext(global_context, level='global')
+        self.toplevel_context = ScopedContext({}, self.context, level='toplevel')
         self.context = self.toplevel_context
 
         self.forwards = {}
             self.set(name, self.type_of(ast.children[0]))
             return Void()
         elif ast.type == 'VarRef':
-            return self.context[ast.value]
+            v = self.context[ast.value]
+            ast.aux = self.context.level(ast.value)
+            return v
         elif ast.type == 'None':
             return Void()
         elif ast.type == 'FunCall':

src/castile/context.py

     False
 
     """
-    def __init__(self, dict, parent=None):
+    def __init__(self, dict, parent=None, level=None):
         self._dict = dict
         self.parent = parent
+        self._level = level
+
+    def level(self, key):
+        if key in self._dict:
+            return self._level
+        return self.parent.level(key)
 
     def __getitem__(self, key):
         if key in self._dict:

src/castile/stackmac.py

     iter = 0
     stack = []
     callstack = []
+    baseptr = 0
     while ip < len(program):
         (op, arg) = program[ip]
-        # print ip, op, arg, stack, callstack
+        #print ip, op, arg, stack, callstack
         if op == 'push':
             stack.append(arg)
         elif op == 'jmp':
             b = stack.pop()
             a = stack.pop()
             stack.append(a + b)
+        elif op == 'sub':
+            b = stack.pop()
+            a = stack.pop()
+            stack.append(a - b)
         elif op == 'gt':
             b = stack.pop()
             a = stack.pop()
             b = stack.pop()
             a = stack.pop()
             stack.append(boo(a < b))
+        elif op == 'eq':
+            b = stack.pop()
+            a = stack.pop()
+            stack.append(boo(a == b))
         elif op == 'bzero':
             a = stack.pop()
             if a == 0:
                 ip = arg - 1
-        elif op == 'global':
+        elif op == 'set_baseptr':
+            baseptr = len(stack)
+        elif op == 'get_global':
             stack.append(stack[arg])
-        elif op == 'pick':
-            # TODO should be relative to baseptr
-            stack.append(stack[-(arg+1)])
+        elif op == 'get_local':
+            stack.append(stack[baseptr + arg])
+        elif op == 'set_local':
+            stack[baseptr + arg] = stack.pop()
         else:
             raise NotImplementedError((op, arg))
         ip += 1
                 # print label, address
                 labels[label] = address
                 continue
-            match = re.match(r'^(.*?)\=(\d+)$', line)
+            match = re.match(r'^(.*?)\=(-?\d+)$', line)
             if match:
                 label = match.group(1)
                 pos = int(match.group(2))