git @ Cat's Eye Technologies ALPACA / f022c45
Split and refactor, pass top AST node through evaluator, fix test. --HG-- rename : src/alpaca/eval.py => src/alpaca/analysis.py catseye 12 years ago
4 changed file(s) with 90 addition(s) and 84 deletion(s). Raw diff Collapse all Expand all
380380 | to Dog when not ^ is Animal
381381 | begin
382382 | dcdc
383 = -----
384 = dcdc
383 | dcdc
384 = -----
385 = cdcd
386 = c
385387 = -----
386388
387389 ### Neighbourhoods ###
0 """
1 Functions for discovering certain things about an ALPACA description
2 given its AST.
3
4 """
5
6 from alpaca.ast import AST
7 from alpaca.playfield import Playfield
8
9
10 def get_defns(alpaca):
11 assert alpaca.type == 'Alpaca'
12 defns = alpaca.children[0]
13 assert defns.type == 'Defns'
14 return defns
15
16
17 def find_defn(alpaca, type, id):
18 assert isinstance(id, basestring)
19 for defn in get_defns(alpaca).children:
20 if defn.type == type and defn.value == id:
21 return defn
22 raise KeyError, "No such %s '%s'" % (type, id)
23
24
25 def find_state_defn(alpaca, state_id):
26 return find_defn(alpaca, 'StateDefn', state_id)
27
28
29 def find_class_defn(alpaca, class_id):
30 return find_defn(alpaca, 'ClassDefn', class_id)
31
32
33 def state_defn_is_a(state_ast, class_id):
34 class_decls = state_ast.children[2]
35 assert class_decls.type == 'MembershipDecls'
36 for class_decl in class_decls.children:
37 assert class_decl.type == 'ClassDecl'
38 if class_id == class_decl.value:
39 return True
40 return False
41
42
43 def construct_representation_map(alpaca):
44 map = {}
45 for defn in get_defns(alpaca).children:
46 if defn.type == 'StateDefn':
47 repr = defn.children[0]
48 assert repr.type == 'CharRepr'
49 map[repr.value] = defn.value
50 return map
51
52
53 def get_default_state(alpaca):
54 for defn in get_defns(alpaca).children:
55 if defn.type == 'StateDefn':
56 return defn.value
57
58
59 def get_defined_playfield(alpaca):
60 assert alpaca.type == 'Alpaca'
61 playast = alpaca.children[1]
62 assert playast.type == 'Playfield'
63 repr_map = construct_representation_map(alpaca)
64 pf = Playfield(get_default_state(alpaca), repr_map)
65 for (x, y, ch) in playast.value:
66 pf.set(x, y, repr_map[ch])
67 pf.recalculate_limits()
68 return pf
00 """
11 Direct evaluator of ALPACA AST nodes.
2
3 XXX move some of these out into alpaca.analysis
42
53 """
64
75 from alpaca.ast import AST
86 from alpaca.playfield import Playfield
7 from alpaca.analysis import (
8 find_state_defn, find_class_defn, state_defn_is_a,
9 )
910
1011
1112 def eval_state_ref(playfield, x, y, ast):
1718 raise NotImplementedError
1819
1920
20 def eval_expr(playfield, x, y, ast):
21 def eval_expr(alpaca, playfield, x, y, ast):
2122 """Given a playfield and a position within it, and a boolean expression,
2223 return what the expression evaluates to at that position.
2324
2425 """
2526 if ast.type == 'BoolOp':
26 lhs = eval_expr(playfield, x, y, ast.children[0])
27 rhs = eval_expr(playfield, x, y, ast.children[1])
27 lhs = eval_expr(alpaca, playfield, x, y, ast.children[0])
28 rhs = eval_expr(alpaca, playfield, x, y, ast.children[1])
2829 op = ast.value
2930 if op == 'and':
3031 return lhs and rhs
3334 elif op == 'xor':
3435 return not (lhs == rhs)
3536 elif ast.type == 'Not':
36 return not eval_expr(playfield, x, y, ast.children[0])
37 return not eval_expr(alpaca, playfield, x, y, ast.children[0])
3738 elif ast.type == 'Adjacency':
3839 state = eval_state_ref(playfield, x, y, ast.children[0])
3940 nb = ast.children[1]
5152 return state0 == state1
5253 elif ast.type == 'RelationalClass':
5354 state_id = eval_state_ref(playfield, x, y, ast.children[0])
54 # XXX damn. should we transform the ast to something
55 # easier to work with? or just pass the program ast?
56 program_ast = 'damn'
57 state_ast = find_state_defn(state_id, program_ast)
55 state_ast = find_state_defn(alpaca, state_id)
5856 class_id = ast.children[1].value
5957 return state_defn_is_a(state_ast, class_id)
6058 elif ast.type == 'BoolLit':
7068 raise NotImplementedError
7169
7270
73 def eval_rules(playfield, x, y, ast):
71 def eval_rules(alpaca, playfield, x, y, ast):
7472 """Given a playfield and a position within it, and a set of rules,
7573 return the "to" state for the rule that applies.
7674
8280 assert rule.type == 'Rule'
8381 s = rule.children[0]
8482 e = rule.children[1]
85 if eval_expr(playfield, x, y, e):
83 if eval_expr(alpaca, playfield, x, y, e):
8684 return eval_state_ref(playfield, x, y, s)
8785 return None
8886
8987
90 def find_defn(type, id, ast):
91 assert isinstance(id, basestring)
92 assert ast.type == 'Alpaca'
93 defns = ast.children[0]
94 assert defns.type == 'Defns'
95 for defn in defns.children:
96 if defn.type == type and defn.value == id:
97 return defn
98 raise KeyError, "No such %s '%s'" % (type, id)
99
100
101 def find_state_defn(state_id, ast):
102 return find_defn('StateDefn', state_id, ast)
103
104
105 def find_class_defn(class_id, ast):
106 return find_defn('ClassDefn', class_id, ast)
107
108
109 def state_defn_is_a(state_ast, class_id):
110 class_decls = state_ast.children[2]
111 assert class_decls.type == 'MembershipDecls'
112 for class_decl in class_decls.children:
113 assert class_decl.type == 'ClassDecl'
114 if class_id == class_decl.value:
115 return True
116 return False
117
118
119 def construct_representation_map(ast):
120 map = {}
121 assert ast.type == 'Alpaca'
122 defns = ast.children[0]
123 assert defns.type == 'Defns'
124 for defn in defns.children:
125 if defn.type == 'StateDefn':
126 repr = defn.children[0]
127 assert repr.type == 'CharRepr'
128 map[repr.value] = defn.value
129 return map
130
131
132 def get_default_state(ast):
133 assert ast.type == 'Alpaca'
134 defns = ast.children[0]
135 assert defns.type == 'Defns'
136 for defn in defns.children:
137 if defn.type == 'StateDefn':
138 return defn.value
139
140
141 def get_defined_playfield(ast):
142 assert ast.type == 'Alpaca'
143 playast = ast.children[1]
144 assert playast.type == 'Playfield'
145 repr_map = construct_representation_map(ast)
146 pf = Playfield(get_default_state(ast), repr_map)
147 for (x, y, ch) in playast.value:
148 pf.set(x, y, repr_map[ch])
149 pf.recalculate_limits()
150 return pf
151
152
153 def evolve_playfield(playfield, new_pf, ast):
88 def evolve_playfield(playfield, new_pf, alpaca):
15489 # XXX TODO + 1, - 1's in here should reflect the maximum
15590 # neighbourhood used by any rule
15691 if playfield.min_y is None:
16196 while x <= playfield.max_x + 1:
16297 state_id = playfield.get(x, y)
16398 #print "state at (%d,%d): %s" % (x, y, state_id)
164 state_ast = find_state_defn(state_id, ast)
99 state_ast = find_state_defn(alpaca, state_id)
165100 #print " => %r" % state_ast
166 new_state_id = eval_rules(playfield, x, y, state_ast.children[3])
101 new_state_id = eval_rules(alpaca, playfield, x, y, state_ast.children[3])
167102 class_decls = state_ast.children[2]
168103 assert class_decls.type == 'MembershipDecls'
169104 for class_decl in class_decls.children:
171106 if new_state_id is not None:
172107 break
173108 class_id = class_decl.value
174 class_ast = find_class_defn(class_id, ast)
175 new_state_id = eval_rules(playfield, x, y, class_ast.children[0])
109 class_ast = find_class_defn(alpaca, class_id)
110 new_state_id = eval_rules(alpaca, playfield, x, y, class_ast.children[0])
176111 if new_state_id is None:
177112 new_state_id = playfield.get(x, y)
178113 #print "new state: %s" % new_state_id
88 from optparse import OptionParser
99 import sys
1010
11 from alpaca.eval import (
12 evolve_playfield,
11 from alpaca.analysis import (
1312 construct_representation_map,
1413 get_default_state,
1514 get_defined_playfield,
1615 )
16 from alpaca.eval import evolve_playfield
1717 from alpaca.parser import Parser
1818 from alpaca.playfield import Playfield
1919