Commits

Anonymous committed 0c9d4a2 Draft

Clean up checker a bit (no assignable, no struct_fields.)

Comments (0)

Files changed (4)

     | }
     = integer
 
-(But can it be updated?)
-
 The expression in a `typecase` cannot effectively be a global, as globals
 must be literals and there is no way (right now) to make a literal of union
 type.
 
+Inside a `typecase` the variable cannot be updated.
+
+    | main = fun() {
+    |   var a = 333 as integer|string;
+    |   typecase a is integer {
+    |     a = 700;
+    |   };
+    | }
+    ? cannot assign
+
 The union can include void.
 
     | main = fun() {
 
 Struct equality in Javascript, stackmac backends.
 
-"struct size" function in stackmac backend, for structs with no fields or
-void fields.
-
 Figure out a way to do `input`, `read`, and `write` with node.js backend.
 
 Implement `int`, `str`, `chr`, `ord` for Ruby, Javascript, stackmac.
 
 AST nodes should have source line numbers, it would be really nice.
 
-"assignable" in typechecker -- can be done more cleanly with ScopedDict?
-
-Get rid of redundant struct_fields attr in checker.
-
 C backend.  Other backends (Python? Java? CIL? Scheme?)
 
 ### Design ###

src/castile/ast.py

         self.type = type
         # typechecker may populate this.  parser will not.
         # on VarRef nodes, this is the level of the reference
-        #  ('global', 'toplevel', or None for locals)
+        #  ('global', 'toplevel', 'argument', 'local', or 'typecase')
         # on FieldInit and Index nodes, this is the position
         #  (offset) of the field within the struct
         self.aux = aux

src/castile/checker.py

 
         self.forwards = {}
         self.structs = {}  # struct name -> StructDefinition
-        self.struct_fields = {}  # struct name -> dict of field name -> pos
-        self.assignable = {}
         self.return_type = None
         self.verbose = False
 
             return
         raise CastileTypeError("type mismatch: %s != %s" % (t1, t2))
 
-    def is_assignable(self, ast):
-        assert ast.tag == 'VarRef'
-        name = ast.value
-        return name in self.assignable
-
     def collect_structs(self, ast):
         for child in ast.children:
             if child.tag == 'StructDefn':
         if name in self.structs:
             raise CastileTypeError('duplicate struct %s' % name)
         struct_fields = {}
-        self.struct_fields[name] = struct_fields
         te = []
         i = 0
         for child in ast.children:
             ast.type = Boolean()
         elif ast.tag == 'FunLit':
             save_context = self.context
-            self.context = ScopedContext({}, self.toplevel_context)
+            self.context = ScopedContext({}, self.toplevel_context,
+                                         level='argument')
             self.return_type = None
             arg_types = self.type_of(ast.children[0])  # args
             t = self.type_of(ast.children[1])  # body
             }
             ast.type = map[ast.value]
         elif ast.tag == 'Body':
-            self.context = ScopedContext({}, self.context)
+            self.context = ScopedContext({}, self.context,
+                                         level='local')
             for child in ast.children:
                 self.assert_eq(self.type_of(child), Void())
             self.context = self.context.parent
             name = ast.value
             if name in self.context:
                 raise CastileTypeError('declaration of %s shadows previous' % name)
-            self.assignable[name] = True
             self.set(name, self.type_of(ast.children[0]))
             ast.type = Void()
         elif ast.tag == 'FunType':
             ast.type = Void()
         elif ast.tag == 'Assignment':
             t1 = self.type_of(ast.children[0])
-            if not self.is_assignable(ast.children[0]):
+            if self.context.level(ast.children[0].value) != 'local':
                 raise CastileTypeError('cannot assign to non-local')
             t2 = self.type_of(ast.children[1])
             self.assert_eq(t1, t2)
         elif ast.tag == 'Index':
             t = self.type_of(ast.children[0])
             field_name = ast.value
-            struct_fields = self.struct_fields[t.name]
+            struct_fields = self.structs[t.name].field_names
             if field_name not in struct_fields:
                 raise CastileTypeError("undefined field")
             index = struct_fields[field_name]
                 raise CastileTypeError('bad typecase, %s not in %s' % (t2, t1))
             # typecheck t3 with variable in children[0] having type t2
             assert ast.children[0].tag == 'VarRef'
-            self.context = ScopedContext({}, self.context)
+            self.context = ScopedContext({}, self.context, level='typecase')
             self.context[ast.children[0].value] = t2
             ast.type = self.type_of(ast.children[2])
             self.context = self.context.parent
             ast.type = Void()
             self.resolve_structs(ast)
         elif ast.tag == 'Defn':
-            # reset assignable
-            self.assignable = {}
             t = self.type_of(ast.children[0])
             if ast.value in self.forwards:
                 self.assert_eq(self.forwards[ast.value], t)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.