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

Refactor assembler #55

Merged
merged 33 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
a15a913
Update poetry.lock
cjvth Jan 25, 2024
631a727
[cocas] Move source files to modules inside cocas
cjvth Jan 25, 2024
548e682
Add files generated by make to .gitignore
cjvth Jan 25, 2024
abca58e
[cocas] Reorganize code of object_module
cjvth Jan 26, 2024
e8bf7af
[cocas] Fix imports inside targets
cjvth Jan 26, 2024
e7e80a1
[cocas] Move target parameters for object files into module
cjvth Jan 29, 2024
3836673
[cocas] Remove passing unused target_params to linker and delete files
cjvth Jan 29, 2024
15003ad
[cocas] Move cocas/targets to cocas/assembler/targets
cjvth Jan 29, 2024
ae79f6f
[cocas] Move importing target module inside assembler
cjvth Jan 29, 2024
02bb1a2
[cocas] Move stages of assembling into module
cjvth Jan 29, 2024
1820690
[cocas] Move reading and processing multiple files to modules
cjvth Jan 29, 2024
5fbce37
[cocas] Fix circular import in cdm8e
cjvth Jan 29, 2024
ea16c44
[cocas] Move code of opening and writing to files
cjvth Jan 29, 2024
e6c9661
[cocas] Move writing image and debug information to linker module
cjvth Jan 30, 2024
6015f29
[cocas] Remove CodeSegmentsInterface, add`I` prefix to its members
cjvth Jan 30, 2024
ffc2279
[cocas] Change code segments to be based on abstract classes and prop…
cjvth Jan 30, 2024
b7234a7
[cocas] Change target instructions interface to be with abstract methods
cjvth Jan 30, 2024
6f3815c
[cocas] Make using str and Path consistent
cjvth Feb 2, 2024
869ccae
[cocas] Fix remaining warnings in cocas
cjvth Feb 2, 2024
d9defbc
[cocas] Move exception class declarations into modules
cjvth Feb 8, 2024
a9bc14c
[cocas] Rename exceptions
cjvth Feb 8, 2024
50d63d1
[cocas] Properly handle exceptions in main
cjvth Feb 8, 2024
d6718d0
[cocas] Make imports better and fix code style
cjvth Feb 8, 2024
d4f1b4e
[cocas] Add docstrings for all importable functions and modules
cjvth Feb 8, 2024
c326a69
[cocas] Add docstrings for fields of public structures
cjvth Feb 12, 2024
c1c392d
[cocas] Make cocas work on Python 3.9
cjvth Feb 13, 2024
9e62226
[cocas] Fix wrong file path in object file
cjvth Feb 13, 2024
e264347
[cocas] Fix image size check and add info for targets in linker
cjvth Feb 13, 2024
ac12e86
[cocas] Use correct name `relocatable` instead of `relative`
cjvth Feb 14, 2024
6ff563c
[cocas] Allow omitting "cdm" in -t cli argument
cjvth Feb 14, 2024
ea03730
[cocas] Fix broken exceptions for labels, break and continue
cjvth Feb 14, 2024
25a7e89
[cocas] Improve printing errors
cjvth Feb 15, 2024
3ab561f
[cocas] Make TargetInstructions to a protocol instead of abc
cjvth Feb 16, 2024
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
1 change: 1 addition & 0 deletions cocas/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import assembler, linker, object_file, object_module
86 changes: 0 additions & 86 deletions cocas/abstract_code_segments.py

This file was deleted.

23 changes: 0 additions & 23 deletions cocas/abstract_instructions.py

This file was deleted.

23 changes: 0 additions & 23 deletions cocas/abstract_params.py

This file was deleted.

6 changes: 4 additions & 2 deletions cocas/antlr-generate.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
antlr4 -Dlanguage=Python3 -visitor -no-listener -Xexact-output-dir -o generated \
./grammar/AsmLexer.g4 ./grammar/AsmParser.g4 ./grammar/Macro.g4 ./grammar/ObjectFileParser.g4 ./grammar/ObjectFileLexer.g4
antlr4 -Dlanguage=Python3 -visitor -no-listener -Xexact-output-dir -o object_file/generated \
object_file/grammar/ObjectFileParser.g4 object_file/grammar/ObjectFileLexer.g4
antlr4 -Dlanguage=Python3 -visitor -no-listener -Xexact-output-dir -o assembler/generated \
assembler/grammar/AsmLexer.g4 assembler/grammar/AsmParser.g4 assembler/grammar/Macro.g4
5 changes: 5 additions & 0 deletions cocas/assembler/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Assembler module. Converts source files into object module structures"""

from .assembler import assemble_files, assemble_module
from .exceptions import AssemblerException, AssemblerExceptionTag
from .targets import list_assembler_targets
91 changes: 91 additions & 0 deletions cocas/assembler/assembler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import codecs
from itertools import chain
from pathlib import Path
from typing import Any, Optional

import antlr4

from cocas.object_module import ObjectModule

from .ast_builder import build_ast
from .macro_processor import ExpandMacrosVisitor, process_macros, read_mlb
from .object_generator import generate_object_module
from .targets import TargetInstructions, import_target, mlb_path


def assemble_module(input_stream: antlr4.InputStream,
target_instructions: TargetInstructions,
macros_library: ExpandMacrosVisitor,
filepath: Path) -> ObjectModule:
"""
Convert lines of an assembler file to object code

:param input_stream: contents of file
:param target_instructions: information how to convert mnemonics to code segments
:param macros_library: standard macros of assembler
:param filepath: path of the file to use in error handling
"""
macro_expanded_input_stream = process_macros(input_stream, macros_library, filepath)
r = build_ast(macro_expanded_input_stream, filepath)
return generate_object_module(r, target_instructions)


def get_debug_info_path(filepath: Path,
debug: Optional[Any],
relative_path: Optional[Path],
realpath: bool) -> Optional[Path]:
if debug:
debug_info_path = filepath.expanduser().absolute()
if realpath:
debug_info_path = debug_info_path.resolve()
if relative_path:
debug_info_path = debug_info_path.relative_to(relative_path)
else:
debug_info_path = None
return debug_info_path


def assemble_files(target: str,
files: list[Path],
debug: bool,
relative_path: Optional[Path],
absolute_path: Optional[Path],
realpath: bool) -> list[tuple[Path, ObjectModule]]:
"""
Open and assemble multiple files into object modules

:param target: name of processor, should be valid
:param files: list of assembler files' paths to process
:param debug: if debug information should be collected
:param relative_path: if debug paths should be relative to some path
:param absolute_path: if relative paths should be converted to absolute
:param realpath: if paths should be converted to canonical
:return: list of pairs [source file path, object module]
"""
_ = absolute_path
target_instructions = import_target(target)
macros_library = read_mlb(mlb_path(target))
objects = []

for filepath in files:
with filepath.open('rb') as file:
data = file.read()
data = codecs.decode(data, 'utf8', 'strict')
if not data.endswith('\n'):
data += '\n'
input_stream = antlr4.InputStream(data)
obj = assemble_module(input_stream, target_instructions, macros_library, filepath)

debug_info_path = get_debug_info_path(filepath, debug, relative_path, realpath)
if debug_info_path:
obj.source_file_path = debug_info_path
fp = filepath.absolute().as_posix()
dip = debug_info_path.as_posix()
for i in chain(obj.asects, obj.rsects):
for j in i.code_locations.values():
if j.file == fp:
j.file = dip
else:
j.file = get_debug_info_path(Path(j.file), debug, relative_path, realpath)
objects.append((filepath, obj))
return objects
29 changes: 15 additions & 14 deletions cocas/ast_builder.py → cocas/assembler/ast_builder.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from base64 import b64decode
from pathlib import Path

from antlr4 import CommonTokenStream, InputStream

from cocas.ast_nodes import (
from cocas.object_module import CodeLocation

from .ast_nodes import (
AbsoluteSectionNode,
BreakStatementNode,
ConditionalStatementNode,
Expand All @@ -21,11 +24,8 @@
UntilLoopNode,
WhileLoopNode,
)
from cocas.error import AntlrErrorListener, CdmException, CdmExceptionTag
from cocas.generated.AsmLexer import AsmLexer
from cocas.generated.AsmParser import AsmParser
from cocas.generated.AsmParserVisitor import AsmParserVisitor
from cocas.location import CodeLocation
from .exceptions import AntlrErrorListener, AssemblerException, AssemblerExceptionTag
from .generated import AsmLexer, AsmParser, AsmParserVisitor


# noinspection PyPep8Naming
Expand Down Expand Up @@ -126,8 +126,8 @@ def visitConnective_condition(self, ctx: AsmParser.Connective_conditionContext):
cond = self.visitCondition(ctx.condition())
cond.conjunction = ctx.conjunction().getText()
if cond.conjunction != 'and' and cond.conjunction != 'or':
raise CdmException(CdmExceptionTag.ASM, self.source_path, ctx.start.line - self.line_offset,
'Expected "and" or "or" in compound condition')
raise AssemblerException(AssemblerExceptionTag.ASM, self.source_path, ctx.start.line - self.line_offset,
'Expected "and" or "or" in compound condition')
return cond

def visitCondition(self, ctx: AsmParser.ConditionContext):
Expand Down Expand Up @@ -218,8 +218,8 @@ def visitStandaloneLabel(self, ctx: AsmParser.StandaloneLabelContext) -> LabelDe
label_decl = self.visitLabel_declaration(ctx.label_declaration())
label_decl.external = ctx.Ext() is not None
if label_decl.entry and label_decl.external:
raise CdmException(CdmExceptionTag.ASM, self.source_path, ctx.start.line - self.line_offset,
f'Label {label_decl.label.name} cannot be both external and entry')
raise AssemblerException(AssemblerExceptionTag.ASM, self.source_path, ctx.start.line - self.line_offset,
f'Label {label_decl.label.name} cannot be both external and entry')
return label_decl

def visitLabel_declaration(self, ctx: AsmParser.Label_declarationContext) -> LabelDeclarationNode:
Expand Down Expand Up @@ -253,16 +253,17 @@ def visitArguments(self, ctx: AsmParser.ArgumentsContext):
return [self.visitArgument(i) for i in ctx.children if isinstance(i, AsmParser.ArgumentContext)]


def build_ast(input_stream: InputStream, filepath: str):
def build_ast(input_stream: InputStream, filepath: Path):
str_path = filepath.absolute().as_posix()
lexer = AsmLexer(input_stream)
lexer.removeErrorListeners()
lexer.addErrorListener(AntlrErrorListener(CdmExceptionTag.ASM, filepath))
lexer.addErrorListener(AntlrErrorListener(AssemblerExceptionTag.ASM, str_path))
token_stream = CommonTokenStream(lexer)
token_stream.fill()
parser = AsmParser(token_stream)
parser.removeErrorListeners()
parser.addErrorListener(AntlrErrorListener(CdmExceptionTag.ASM, filepath))
parser.addErrorListener(AntlrErrorListener(AssemblerExceptionTag.ASM, str_path))
cst = parser.program()
bav = BuildAstVisitor(filepath)
bav = BuildAstVisitor(str_path)
result = bav.visit(cst)
return result
4 changes: 2 additions & 2 deletions cocas/ast_nodes.py → cocas/assembler/ast_nodes.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dataclasses import dataclass
from typing import Optional

from cocas.location import CodeLocation
from cocas.object_module import CodeLocation


@dataclass
Expand Down Expand Up @@ -40,7 +40,7 @@ class RelocatableExpressionNode(LocatableNode):


@dataclass
class LabelDeclarationNode(Node):
class LabelDeclarationNode(LocatableNode):
label: LabelNode
entry: bool
external: bool
Expand Down
Loading
Loading