Commits

Anonymous committed 8345ff5

Partial support for class membership checking in compiled source.

  • Participants
  • Parent commits c577e25

Comments (0)

Files changed (3)

File README.markdown

 
 ### TODO ###
 
-* compile to Javascript
+* compile to IR, optimize that IR, then output concrete code
+* compile to Javascript: write support functions
 * compile to legacy Perl
 * option to use pycurses
 * nontrivial fixpoint detection: if playfield matches any of the last n
   playfields, then halt
 * option to halt under other, even more complex circumstances
 * option to display generation #, coordinates, etc in divider string
-* implement >Moore neighbourhoods

File src/alpaca/analysis.py

     return False
 
 
+def get_state_membership(alpaca, state_id):
+    """Given a state ID, return a set of IDs of all classes of which that
+    state is a member.
+
+    """
+    membership = set()
+    state_ast = find_state_defn(alpaca, state_id)
+    class_decls = state_ast.children[2]
+    assert class_decls.type == 'MembershipDecls'
+    for class_decl in class_decls.children:
+        assert class_decl.type == 'ClassDecl'
+        class_id = class_decl.value
+        membership.add(class_id)
+        membership.union(get_class_membership(alpaca, class_id))
+    return membership
+
+
+def get_class_membership(alpaca, class_id):
+    """Given a class ID, return a set of IDs of all classes of which that
+    class is a member.
+
+    """
+    membership = set()
+    class_ast = find_class_defn(alpaca, class_id)
+    class_decls = class_ast.children[1]
+    assert class_decls.type == 'MembershipDecls'
+    for class_decl in class_decls.children:
+        assert class_decl.type == 'ClassDecl'
+        class_id = class_decl.value
+        membership.add(class_id)
+        membership.union(get_class_membership(alpaca, class_id))
+    return membership
+
+
+def get_class_map(alpaca):
+    """Given an ALPACA description, return a dictionary where the keys are
+    the IDs of classes and the values are the sets of IDs of states which are
+    members of those classes.
+
+    """
+    defns = alpaca.children[0]
+    state_map = {}
+    for defn in defns.children:
+        if defn.type == 'StateDefn':
+            state_map[defn.value] = get_state_membership(alpaca, defn.value)
+    class_map = {}
+    for (state_id, class_set) in state_map.iteritems():
+        for class_id in class_set:
+            class_map.setdefault(class_id, set()).add(state_id)
+    return class_map
+
+
 def construct_representation_map(alpaca):
     map = {}
     for defn in get_defns(alpaca).children:

File src/alpaca/backends/javascript.py

 
 """
 
+from alpaca.analysis import get_class_map
+
+
 class Compiler(object):
     def __init__(self, alpaca, file):
         """alpaca is an ALPACA description in AST form.  file is a file-like
  * EDIT AT YOUR OWN RISK!
  */
 """)
+        class_map = get_class_map(self.alpaca)
+        for (class_id, state_set) in class_map.iteritems():
+            self.file.write("function is_%s(st) {\n" % class_id)
+            self.file.write("  return ");
+            for state_id in state_set:
+                self.file.write("(st === '%s') || " % state_id)
+            self.file.write("0;\n}\n")
         defns = self.alpaca.children[0]
         for defn in defns.children:
             if defn.type == 'ClassDefn':
 
     def compile_relation(self, ref, ast):
         if ast.type == 'ClassDecl':
-            # XXX this is rather handwavy
-            self.file.write('is_member(')
+            self.file.write('is_%s(' % ast.value)
             self.compile_state_ref(ref)
-            self.file.write(", '%s')" % ast.value)
+            self.file.write(")")
         else:
             self.file.write('(')
             self.compile_state_ref(ref)