git @ Cat's Eye Technologies ALPACA / ba7812a
Improve compiler (can translate some rules ok now.) Tweak spec. catseye 12 years ago
3 changed file(s) with 94 addition(s) and 34 deletion(s). Raw diff Collapse all Expand all
6666 string literal. The key may be drawn from a set defined by ALPACA, or it may
6767 be implementation-defined. The value may consist of essentially arbitrary
6868 string data, and may refer to a character, a colour, a graphic image, or
69 anything else. (Note that this version of the ALPACA specification does not
70 yet define any keys, leaving them all to be implementation defined; however,
71 it is likely that a near-future revision, possibly 1.1, will define some.)
69 anything else.
70
71 Note that this version of the ALPACA specification does not yet define any
72 keys. However, it reserves the following key names for future definition
73 (possibly in version 1.1).
74
75 colour
76 image
77 border
78 any key beginning with "alpaca_"
79
80 Implementations which define their own keys are encouraged to prefix them
81 with something likely to be unique.
7282
7383 Representation declarations are not required. If omitted, representation
7484 information can be supplied by the implementation, or can be defined with
7888
7989 However, if an initial configuration is included, it will be interpreted
8090 using the single ASCII character representation declarations of the states.
91
92 (TODO: this limits us to 95 states. Either allow multiple characters to
93 represent a state, or move to Unicode, or both.)
8194
8295 Example: a trivial ALPACA description with single character representation
8396 declarations:
481494 = #
482495 = -----
483496
484 (TODO: the following example is out of place. where to put it?)
497 Some More Realistic Examples
498 ----------------------------
499
500 This section is not normative.
485501
486502 Example: a glider, pointed northeast, in John Conway's Game of Life
487503 automaton:
44
55 """
66
7 from alpaca.ast import AST
7 class Compiler(object):
8 def __init__(self, alpaca, file):
9 """alpaca is an ALPACA description in AST form. file is a file-like
10 object to which the compiled code will be written.
811
12 """
13 self.alpaca = alpaca
14 self.file = file
915
10 def compile(alpaca, file):
11 """alpaca is an ALPACA description in AST form. file is a file-like
12 object to which the compiled code will be written.
13
14 """
15 file.write("""
16 def compile(self):
17 self.file.write("""\
1618 /*
1719 * This file was AUTOMATICALLY generated from an ALPACA description.
1820 * EDIT AT YOUR OWN RISK!
1921 */
2022 """)
21 defns = alpaca.children[0]
22 for defn in defns.children:
23 if defn.type == 'StateDefn':
24 compile_state_defn(alpaca, defn, file)
25 elif defn.type == 'ClassDefn':
26 pass
27 elif defn.type == 'NbhdDefn':
28 pass
23 defns = self.alpaca.children[0]
24 for defn in defns.children:
25 if defn.type == 'StateDefn':
26 self.compile_state_defn(defn)
27 elif defn.type == 'ClassDefn':
28 pass
29 elif defn.type == 'NbhdDefn':
30 pass
31 else:
32 raise NotImplementedError(repr(defn))
33
34 def compile_state_defn(self, defn):
35 char_repr = defn.children[0]
36 repr_decls = defn.children[1]
37 membership = defn.children[2]
38 rules = defn.children[3]
39 self.file.write("function eval_%s(pf, x, y) {\n" % defn.value);
40 for rule in rules.children:
41 dest = rule.children[0]
42 expr = rule.children[1]
43 self.file.write("if (")
44 self.compile_expr(expr)
45 self.file.write(") {\n return ")
46 self.compile_state_ref(dest)
47 self.file.write(";\n}\n" % (dest))
48 self.file.write("return '%s';\n}\n\n" % defn.value)
49
50 def compile_state_ref(self, ref):
51 # compare to eval_state_ref
52 if ref.type == 'StateRefEq':
53 self.file.write("'%s'" % ref.value)
54 elif ref.type == 'StateRefRel':
55 self.file.write("pf.get(x+%d,y+%d)" % (ref.value[0], ref.value[1]))
2956 else:
30 raise NotImplementedError(repr(defn))
57 raise NotImplementedError(repr(expr))
3158
32
33 def compile_state_defn(alpaca, defn, file):
34 char_repr = defn.children[0]
35 repr_decls = defn.children[1]
36 membership = defn.children[2]
37 rules = defn.children[3]
38 file.write("function eval_%s() {\n" % defn.value);
39 for rule in rules.children:
40 dest = rule.children[0]
41 expr = rule.children[1]
42 file.write("if (/*%r*/) { state = /*%r*/; }\n" % (expr, dest))
43 file.write("}\n\n")
59 def compile_expr(self, expr):
60 if expr.type == 'BoolOp':
61 self.file.write('(')
62 self.compile_expr(expr.children[0])
63 self.file.write({
64 'or': '||',
65 'and': '&&',
66 'xor': '^^', # XXX yes yes I know this does not work
67 }[expr.value])
68 self.compile_expr(expr.children[1])
69 self.file.write(')')
70 elif expr.type == 'Not':
71 self.file.write('!(')
72 self.compile_expr(expr.children[0])
73 self.file.write(')')
74 elif expr.type == 'BoolLit':
75 self.file.write(expr.value)
76 elif expr.type == 'Relational':
77 # XXX todo: class membership
78 self.file.write('(')
79 self.compile_state_ref(expr.children[0])
80 self.file.write('===')
81 self.compile_state_ref(expr.children[1])
82 self.file.write(')')
83 elif expr.type == 'Adjacency':
84 self.file.write('/* ADJACENCY */')
85 else:
86 raise NotImplementedError(repr(expr))
8383 if options.compile_to is not None:
8484 # XXX generalize
8585 if options.compile_to == 'javascript':
86 from alpaca.backends.javascript import compile
87 success = compile(ast, sys.stdout)
86 from alpaca.backends.javascript import Compiler
87 compiler = Compiler(ast, sys.stdout)
88 success = compiler.compile()
8889 if success:
8990 sys.exit(0)
9091 else: