--output cmdline argument, serialize() returns an array of bytes.
Chris Pressey
3 years ago
4 | 4 | ---- |
5 | 5 | |
6 | 6 | * Split TODO off into own file. |
7 | * `sixtypical` no longer writes the compiled binary to standard | |
8 | output. The `--output` command-line argument should be given. | |
9 | * Many tests pass when `sixtypical` is run with Python 3. | |
7 | 10 | |
8 | 11 | 0.16 |
9 | 12 | ---- |
0 | #!/usr/bin/env python3 | |
0 | #!/usr/bin/env python | |
1 | 1 | |
2 | 2 | """Usage: sixtypical [OPTIONS] FILES |
3 | 3 | |
78 | 78 | if options.analyze_only: |
79 | 79 | return |
80 | 80 | |
81 | fh = sys.stdout | |
81 | fh = open(options.output, 'wb') | |
82 | 82 | |
83 | 83 | if options.output_format == 'raw': |
84 | 84 | start_addr = 0x0000 |
110 | 110 | # If we are outputting a .PRG, we output the load address first. |
111 | 111 | # We don't use the Emitter for this b/c not part of addr space. |
112 | 112 | if options.output_format in ('prg', 'c64-basic-prg', 'vic20-basic-prg'): |
113 | fh.write(Word(start_addr).serialize(0)) | |
113 | fh.write(bytearray(Word(start_addr).serialize())) | |
114 | 114 | |
115 | 115 | emitter = Emitter(start_addr) |
116 | 116 | for byte in prelude: |
139 | 139 | help="The SixtyPical source files to compile." |
140 | 140 | ) |
141 | 141 | |
142 | argparser.add_argument( | |
143 | "--output", "-o", type=str, metavar='FILENAME', | |
144 | help="File to which generated 6502 code will be written." | |
145 | ) | |
142 | 146 | argparser.add_argument( |
143 | 147 | "--origin", type=str, default=None, |
144 | 148 | help="Location in memory where the `main` routine will be " |
23 | 23 | elif [ "X$arch" = "Xapple2" ]; then |
24 | 24 | src="$1" |
25 | 25 | out=/tmp/a-out.bin |
26 | bin/sixtypical --traceback --origin=0x2000 --output-format=raw $src > $out || exit 1 | |
26 | bin/sixtypical --traceback --origin=0x2000 --output-format=raw $src --output $out || exit 1 | |
27 | 27 | ls -la $out |
28 | 28 | cp ~/scratchpad/linapple/res/Master.dsk sixtypical.dsk |
29 | 29 | # TODO: replace HELLO with something that does like |
52 | 52 | ### do it ### |
53 | 53 | |
54 | 54 | out=/tmp/a-out.prg |
55 | bin/sixtypical --traceback --output-format=$output_format $src > $out || exit 1 | |
55 | bin/sixtypical --traceback --output-format=$output_format $src --output $out || exit 1 | |
56 | 56 | ls -la $out |
57 | 57 | $emu $out |
58 | 58 | rm -f $out |
7 | 7 | raise NotImplementedError |
8 | 8 | |
9 | 9 | def serialize(self, addr): |
10 | """Should return an array of unsigned bytes (integers from 0 to 255.)""" | |
10 | 11 | raise NotImplementedError |
11 | 12 | |
12 | 13 | |
24 | 25 | return 1 |
25 | 26 | |
26 | 27 | def serialize(self, addr=None): |
27 | return chr(self.value) | |
28 | return [self.value] | |
28 | 29 | |
29 | 30 | def __repr__(self): |
30 | 31 | return "%s(%r)" % (self.__class__.__name__, self.value) |
42 | 43 | word = self.value |
43 | 44 | low = word & 255 |
44 | 45 | high = (word >> 8) & 255 |
45 | return chr(low) + chr(high) | |
46 | return [low, high] | |
46 | 47 | |
47 | 48 | def __repr__(self): |
48 | 49 | return "%s(%r)" % (self.__class__.__name__, self.value) |
59 | 60 | return self._size |
60 | 61 | |
61 | 62 | def serialize(self, addr=None): |
62 | buf = ''.join([emittable.serialize() for emittable in self.value]) | |
63 | buf = [] | |
64 | for emittable in self.value: | |
65 | buf.extend(emittable.serialize()) | |
63 | 66 | while len(buf) < self.size(): |
64 | buf += chr(0) | |
67 | buf.append(0) | |
65 | 68 | return buf |
66 | 69 | |
67 | 70 | def __repr__(self): |
129 | 132 | return 1 |
130 | 133 | |
131 | 134 | def serialize(self, addr=None): |
132 | return self.label.serialize()[0] | |
135 | return [self.label.serialize()[0]] | |
133 | 136 | |
134 | 137 | def __repr__(self): |
135 | 138 | return "%s(%r)" % (self.__class__.__name__, self.label) |
144 | 147 | return 1 |
145 | 148 | |
146 | 149 | def serialize(self, addr=None): |
147 | return self.label.serialize()[1] | |
150 | return [self.label.serialize()[1]] | |
148 | 151 | |
149 | 152 | def __repr__(self): |
150 | 153 | return "%s(%r)" % (self.__class__.__name__, self.label) |
166 | 169 | self.addr += thing.size() |
167 | 170 | |
168 | 171 | def serialize(self, stream): |
172 | """`stream` should be a file opened in binary mode.""" | |
169 | 173 | addr = self.start_addr |
170 | 174 | for emittable in self.accum: |
171 | 175 | chunk = emittable.serialize(addr) |
172 | stream.write(chunk) | |
176 | stream.write(bytearray(chunk)) | |
173 | 177 | addr += len(chunk) |
174 | 178 | |
175 | 179 | def make_label(self, name=None): |
19 | 19 | return 0 |
20 | 20 | |
21 | 21 | def serialize(self, addr=None): |
22 | return '' | |
22 | return [] | |
23 | 23 | |
24 | 24 | def __repr__(self): |
25 | 25 | return "%s()" % (self.__class__.__name__) |
108 | 108 | return 1 + self.operand.size() if self.operand else 0 |
109 | 109 | |
110 | 110 | def serialize(self, addr=None): |
111 | return ( | |
112 | chr(self.opcodes[self.operand.__class__]) + | |
113 | self.operand.serialize(addr) | |
114 | ) | |
111 | serialized_operand = self.operand.serialize(addr) | |
112 | assert isinstance(serialized_operand, list), self.operand.__class__ | |
113 | return [self.opcodes[self.operand.__class__]] + serialized_operand | |
115 | 114 | |
116 | 115 | def __repr__(self): |
117 | 116 | return "%s(%r)" % (self.__class__.__name__, self.operand) |
2275 | 2275 | |
2276 | 2276 | a, z, and n are trashed, and must be declared as such. |
2277 | 2277 | |
2278 | (Note, both n and z are forbidden writes in this tests.) | |
2278 | (Note, both n and z are forbidden writes in this test.) | |
2279 | 2279 | |
2280 | 2280 | | byte lives |
2281 | 2281 | | routine main |
2287 | 2287 | |
2288 | 2288 | a, z, and n are trashed, and must not be declared as outputs. |
2289 | 2289 | |
2290 | (Note, both n and a are unmeaningful outputs in this test.) | |
2291 | ||
2290 | 2292 | | byte lives |
2291 | 2293 | | routine main |
2292 | 2294 | | outputs lives, a, z, n |
2293 | 2295 | | { |
2294 | 2296 | | copy 0, lives |
2295 | 2297 | | } |
2296 | ? UnmeaningfulOutputError: n | |
2298 | ? UnmeaningfulOutputError | |
2297 | 2299 | |
2298 | 2300 | Unless of course you subsequently initialize them. |
2299 | 2301 |
6 | 6 | [Falderal]: http://catseye.tc/node/Falderal |
7 | 7 | |
8 | 8 | -> Functionality "Compile SixtyPical program" is implemented by |
9 | -> shell command "bin/sixtypical --output-format=c64-basic-prg --traceback %(test-body-file) >/tmp/foo && tests/appliances/bin/dcc6502-adapter </tmp/foo" | |
9 | -> shell command "bin/sixtypical --output-format=c64-basic-prg --traceback %(test-body-file) --output /tmp/foo && tests/appliances/bin/dcc6502-adapter </tmp/foo" | |
10 | 10 | |
11 | 11 | -> Tests for functionality "Compile SixtyPical program" |
12 | 12 |
47 | 47 | - Remove all elements occurring in C, from R. |
48 | 48 | - Repeat until R is empty. |
49 | 49 | |
50 | When times comes to generate code, generate it in the order given by L. | |
50 | When time comes to generate code, generate it in the order given by L. | |
51 | 51 | In addition, each sublist in L represents a number of routines to |
52 | 52 | generate; all except the final routine in such a sublist need not have |
53 | 53 | any jump instruction generated for its final `goto`. |
64 | 64 | -> shell command "bin/sixtypical --optimize-fallthru --dump-fallthru-info --analyze-only --traceback %(test-body-file)" |
65 | 65 | |
66 | 66 | -> Functionality "Compile SixtyPical program with fallthru optimization" is implemented by |
67 | -> shell command "bin/sixtypical --output-format=c64-basic-prg --optimize-fallthru --traceback %(test-body-file) >/tmp/foo && tests/appliances/bin/dcc6502-adapter </tmp/foo" | |
67 | -> shell command "bin/sixtypical --output-format=c64-basic-prg --optimize-fallthru --traceback %(test-body-file) --output /tmp/foo && tests/appliances/bin/dcc6502-adapter </tmp/foo" | |
68 | 68 | |
69 | 69 | -> Tests for functionality "Dump fallthru info for SixtyPical program" |
70 | 70 |