Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#304] Support custom code emitters. #315

Merged
merged 1 commit into from
May 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions outfmt/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from .binary import BinaryEmitter
from .codeemitter import CodeEmitter
from .tzx import TZX
from .tap import TAP


__all__ = [
'BinaryEmitter',
'CodeEmitter',
'TZX',
'TAP',
]
25 changes: 25 additions & 0 deletions outfmt/binary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# --------------------------------------------
# KopyLeft (K) 2008
# by Jose M. Rodriguez de la Rosa
#
# This program is licensed under the
# GNU Public License v.3.0
#
# The code emission interface.
# --------------------------------------------

from .codeemitter import CodeEmitter


class BinaryEmitter(CodeEmitter):
""" Writes compiled code as raw binary data.
"""
def emit(self, output_filename, program_name, loader_bytes, entry_point,
program_bytes, aux_bin_blocks, aux_headless_bin_blocks):
""" Emits resulting binary file.
"""
with open(output_filename, 'wb') as f:
f.write(bytearray(program_bytes))
19 changes: 19 additions & 0 deletions outfmt/codeemitter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# --------------------------------------------
# KopyLeft (K) 2008
# by Jose M. Rodriguez de la Rosa
#
# This program is licensed under the
# GNU Public License v.3.0
#
# The code emission interface.
# --------------------------------------------


class CodeEmitter(object):
""" The base code emission interface.
"""

pass
20 changes: 19 additions & 1 deletion outfmt/tzx.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
# --------------------------------------------


class TZX(object):
from .codeemitter import CodeEmitter


class TZX(CodeEmitter):
""" Class to represent tzx data
"""
VERSION_MAJOR = 1
Expand Down Expand Up @@ -131,6 +134,21 @@ def save_program(self, title, bytes, line=32768):
bytes = [self.BLOCK_TYPE_DATA] + [(int(x) & 0xFF) for x in bytes] # & 0xFF truncates to bytes
self.standard_block(bytes)

def emit(self, output_filename, program_name, loader_bytes, entry_point,
program_bytes, aux_bin_blocks, aux_headless_bin_blocks):
""" Emits resulting tape file.
"""
if loader_bytes is not None:
self.save_program('loader', loader_bytes, line=1) # Put line 0 to protect against MERGE

self.save_code(program_name, entry_point, program_bytes)
for name, block in aux_bin_blocks:
self.save_code(name, 0, block)
for block in aux_headless_bin_blocks:
self.standard_block(block)

self.dump(output_filename)


if __name__ == '__main__':
""" Sample test if invoked from command line
Expand Down
1 change: 1 addition & 0 deletions zxb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
# the GNU General License
# ----------------------------------------------------------------------

from outfmt import CodeEmitter # noqa
from .zxb import main # noqa
5 changes: 3 additions & 2 deletions zxb/zxb.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def output(memory, ofile=None):
ofile.write('%s\n' % m)


def main(args=None):
def main(args=None, emitter=None):
""" Entry point when executed from command line.
You can use zxb.py as a module with import, and this
function won't be executed.
Expand Down Expand Up @@ -352,7 +352,8 @@ def main(args=None):
fout.close()
asmparse.generate_binary(OPTIONS.outputFileName.value, OPTIONS.output_file_type.value,
binary_files=options.append_binary,
headless_binary_files=options.append_headless_binary)
headless_binary_files=options.append_headless_binary,
emitter=emitter)
if gl.has_errors:
return 5 # Error in assembly

Expand Down
36 changes: 19 additions & 17 deletions zxbasm/asmparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -1467,7 +1467,8 @@ def assemble(input_):
return gl.has_errors


def generate_binary(outputfname, format_, progname='', binary_files=None, headless_binary_files=None):
def generate_binary(outputfname, format_, progname='', binary_files=None, headless_binary_files=None,
emitter=None):
""" Outputs the memory binary to the
output filename using one of the given
formats: tap, tzx or bin
Expand Down Expand Up @@ -1512,23 +1513,24 @@ def generate_binary(outputfname, format_, progname='', binary_files=None, headle
else:
program.add_line([['REM'], ['RANDOMIZE', program.token('USR'), AUTORUN_ADDR]])

if format_ in ('tap', 'tzx'):
t = {'tap': outfmt.TAP, 'tzx': outfmt.TZX}[format_]()

if OPTIONS.use_loader.value:
t.save_program('loader', program.bytes, line=1) # Put line 0 to protect against MERGE

t.save_code(progname, org, binary)
for name, block in bin_blocks:
t.save_code(name, 0, block)
for block in headless_bin_blocks:
t.standard_block(block)

t.dump(outputfname)
if emitter is None:
if format_ in ('tap', 'tzx'):
emitter = {'tap': outfmt.TAP, 'tzx': outfmt.TZX}[format_]()
else:
emitter = outfmt.BinaryEmitter()

else:
with open(outputfname, 'wb') as f:
f.write(bytearray(binary))
loader_bytes = None
if OPTIONS.use_loader.value:
loader_bytes = program.bytes

assert isinstance(emitter, outfmt.CodeEmitter)
emitter.emit(output_filename=outputfname,
program_name=progname,
loader_bytes=loader_bytes,
entry_point=AUTORUN_ADDR,
program_bytes=binary,
aux_bin_blocks=bin_blocks,
aux_headless_bin_blocks=headless_bin_blocks)


def main(argv):
Expand Down