Merge pull request #14 from catseye/support-python3
Support python3
Chris Pressey authored 2 years ago
GitHub committed 2 years ago
23 | 23 | The `test.sh` script does this. |
24 | 24 | |
25 | 25 | This distribution also contains the reference implementation of ALPACA |
26 | version 1.1, written in Python 2.7. Its source is in the `src` directory | |
26 | version 1.1, written in Python (runs under both Python 2.7 and Python 3.x). | |
27 | Its source is in the `src` directory | |
27 | 28 | and `bin/alpaca` is a script to start it from the command line (no |
28 | 29 | installation is required; just put this `bin` directory on your executable |
29 | 30 | search path.) See below for more information on the reference |
0 | #!/usr/bin/env python | |
0 | #!/usr/bin/env python3 | |
1 | 1 | |
2 | 2 | from os.path import realpath, dirname, join |
3 | 3 | import sys |
7 | 7 | |
8 | 8 | |
9 | 9 | def find_defn(alpaca, type, id): |
10 | assert isinstance(id, basestring) | |
11 | 10 | for defn in alpaca.defns: |
12 | 11 | if defn.type == type and defn.id == id: |
13 | 12 | return defn |
14 | raise KeyError, "No such %s '%s'" % (type, id) | |
13 | raise KeyError("No such %s '%s'" % (type, id)) | |
15 | 14 | |
16 | 15 | |
17 | 16 | def find_state_defn(alpaca, state_id): |
29 | 28 | def state_defn_is_a(alpaca, state_ast, class_id, verbose=False): |
30 | 29 | for class_decl in state_ast.classes: |
31 | 30 | if verbose: |
32 | print " ===> checking for {} in {}".format(class_id, repr(class_decl)) | |
31 | print(" ===> checking for {} in {}".format(class_id, repr(class_decl))) | |
33 | 32 | assert class_decl.type == 'ClassDecl' |
34 | 33 | if class_id == class_decl.id: |
35 | 34 | return True |
95 | 94 | state_map[defn.id] = membership |
96 | 95 | if defn.type == 'ClassDefn': |
97 | 96 | class_map[defn.id] = set() |
98 | for (state_id, class_set) in state_map.iteritems(): | |
97 | for (state_id, class_set) in state_map.items(): | |
99 | 98 | for class_id in class_set: |
100 | 99 | class_map.setdefault(class_id, set()).add(state_id) |
101 | 100 | return class_map |
49 | 49 | # write the CA's load and dump mappers |
50 | 50 | repr_map = construct_representation_map(self.alpaca) |
51 | 51 | self.file.write("function loadMapper(c) {\n") |
52 | for (char, state_id) in repr_map.iteritems(): | |
52 | for (char, state_id) in repr_map.items(): | |
53 | 53 | self.file.write(" if (c === '%s') return '%s';\n" % |
54 | 54 | (char, state_id)) |
55 | 55 | self.file.write("};\n") |
56 | 56 | |
57 | 57 | self.file.write("function dumpMapper(s) {\n") |
58 | for (char, state_id) in repr_map.iteritems(): | |
58 | for (char, state_id) in repr_map.items(): | |
59 | 59 | self.file.write(" if (s === '%s') return '%s';\n" % |
60 | 60 | (state_id, char)) |
61 | 61 | self.file.write("};\n") |
62 | 62 | |
63 | 63 | class_map = get_class_map(self.alpaca) |
64 | for (class_id, state_set) in class_map.iteritems(): | |
64 | for (class_id, state_set) in class_map.items(): | |
65 | 65 | self.file.write("function is_%s(st) {\n" % class_id) |
66 | 66 | self.file.write(" return "); |
67 | 67 | for state_id in state_set: |
78 | 78 | if pf is not None: |
79 | 79 | self.file.write("var defaultCell = '%s';\n" % pf.default) |
80 | 80 | self.file.write("var initialPlayfield = [{}];\n".format( |
81 | ','.join("[%d, %d, '%s']" % (x, y, c) for (x, y, c) in pf.iteritems()) | |
81 | ','.join("[%d, %d, '%s']" % (x, y, c) for (x, y, c) in pf.items()) | |
82 | 82 | )) |
83 | 83 | return True |
84 | 84 |
29 | 29 | state_ast = find_state_defn(alpaca, state_id) |
30 | 30 | result = state_defn_is_a(alpaca, state_ast, class_id, verbose=verbose) |
31 | 31 | if verbose: |
32 | print " => checking if {} is_a {}: {}".format(state_id, class_id, result) | |
32 | print(" => checking if {} is_a {}: {}".format(state_id, class_id, result)) | |
33 | 33 | return result |
34 | 34 | elif ast.type in ('StateRefEq', 'StateRefRel'): |
35 | 35 | pf_state_id = eval_state_ref(playfield, x, y, ast) |
64 | 64 | pf_state_id = playfield.get(x + dx, y + dy) |
65 | 65 | if eval_relation(alpaca, playfield, x, y, pf_state_id, rel, verbose=verbose): |
66 | 66 | count += 1 |
67 | #print "(%d,%d) has %d neighbours that are %r" % (x, y, count, rel) | |
67 | #print("(%d,%d) has %d neighbours that are %r" % (x, y, count, rel)) | |
68 | 68 | return count >= int(ast.count) |
69 | 69 | elif ast.type == 'Relational': |
70 | 70 | state_id = eval_state_ref(playfield, x, y, ast.lhs) |
112 | 112 | while x <= playfield.max_x - bb.min_dx: |
113 | 113 | state_id = playfield.get(x, y) |
114 | 114 | if verbose: |
115 | print "state at (%d,%d): %s" % (x, y, state_id) | |
115 | print("state at (%d,%d): %s" % (x, y, state_id)) | |
116 | 116 | state_ast = find_state_defn(alpaca, state_id) |
117 | 117 | if verbose: |
118 | print " => %r" % state_ast | |
118 | print(" => %r" % state_ast) | |
119 | 119 | classes = state_ast.classes |
120 | 120 | rules = state_ast.rules |
121 | 121 | new_state_id = apply_rules(alpaca, playfield, x, y, rules, classes, verbose=verbose) |
122 | 122 | if new_state_id is None: |
123 | 123 | new_state_id = state_id |
124 | 124 | if verbose: |
125 | print "new state: %s" % new_state_id | |
125 | print("new state: %s" % new_state_id) | |
126 | 126 | new_pf.set(x, y, new_state_id) |
127 | 127 | x += 1 |
128 | 128 | y += 1 |
90 | 90 | import doctest |
91 | 91 | (fails, something) = doctest.testmod(analysis) |
92 | 92 | if fails == 0: |
93 | print "All tests passed." | |
93 | print("All tests passed.") | |
94 | 94 | sys.exit(0) |
95 | 95 | else: |
96 | 96 | sys.exit(1) |
118 | 118 | if success: |
119 | 119 | sys.exit(0) |
120 | 120 | else: |
121 | print "unsupported backend '%s'" % options.compile_to | |
121 | print("unsupported backend '%s'" % options.compile_to) | |
122 | 122 | sys.exit(1) |
123 | 123 | |
124 | 124 | display_x1, display_y1, display_x2, display_y2 = None, None, None, None |
129 | 129 | int(match.group(1)), int(match.group(2)), int(match.group(3)), int(match.group(4)) |
130 | 130 | ) |
131 | 131 | except Exception as e: |
132 | print "Could not parse '{}'".format(options.display_window) | |
132 | print("Could not parse '{}'".format(options.display_window)) | |
133 | 133 | raise |
134 | 134 | |
135 | 135 | pf = get_defined_playfield(ast) |
136 | 136 | if pf is None: |
137 | 137 | if not options.initial_configuration: |
138 | print "source file does not define an initial configuration," | |
139 | print "and no cellular automaton configuration file given" | |
138 | print("source file does not define an initial configuration,") | |
139 | print("and no cellular automaton configuration file given") | |
140 | 140 | sys.exit(1) |
141 | 141 | with open(options.initial_configuration) as f: |
142 | 142 | pf = Playfield(default_state, repr_map) |
148 | 148 | # TODO: allow formatting string in the divider, esp. |
149 | 149 | # to show the # of this generation |
150 | 150 | if options.divider != '': |
151 | print options.divider | |
151 | print(options.divider) | |
152 | 152 | |
153 | 153 | def begin_output(): |
154 | 154 | if not options.write_discrete_files_to: |
3 | 3 | self.default = default |
4 | 4 | self.recalculate_limits() |
5 | 5 | self.repr_to_state = map |
6 | self.state_to_repr = dict([(v, k) for (k, v) in map.iteritems()]) | |
6 | self.state_to_repr = dict([(v, k) for (k, v) in map.items()]) | |
7 | 7 | |
8 | def iteritems(self): | |
8 | def items(self): | |
9 | 9 | y = self.min_y |
10 | 10 | while y <= self.max_y: |
11 | 11 | x = self.min_x |