Skip to content

Commit

Permalink
Make new hera/symtab.py module
Browse files Browse the repository at this point in the history
  • Loading branch information
iafisher committed Dec 14, 2018
1 parent d30166b commit 91a6c2d
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 100 deletions.
34 changes: 2 additions & 32 deletions hera/preprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@
from lark import Token

from .parser import Op
from .symtab import get_symtab
from .utils import copy_token, emit_error, is_symbol, to_u16


# Arbitrary value copied over from HERA-C.
HERA_DATA_START = 16743


def preprocess(program):
"""Preprocess the program (a list of Op objects) into valid input for the
exec_many method on the VirtualMachine class.
Expand All @@ -23,7 +20,7 @@ def preprocess(program):
"""
program = [op for old_op in program for op in convert(old_op)]

labels = get_labels(program)
labels = get_symtab(program)

program = [substitute_label(op, labels) for op in program]
program = [op for op in program if op.name not in ("LABEL", "DLABEL", "CONSTANT")]
Expand Down Expand Up @@ -52,33 +49,6 @@ def substitute_label(op, labels):
return op


def get_labels(program):
"""Return a dictionary mapping all labels and constants to their values."""
labels = {}
pc = 0
dc = HERA_DATA_START
for op in program:
odc = dc
if op.name == "LABEL":
labels[op.args[0]] = pc
elif op.name == "DLABEL":
labels[op.args[0]] = dc
elif op.name == "CONSTANT":
labels[op.args[0]] = op.args[1]
elif op.name == "INTEGER":
dc += 1
elif op.name == "DSKIP":
dc += op.args[0]
elif op.name == "LP_STRING":
dc += len(op.args[0]) + 1
else:
pc += 1

if dc >= 0xFFFF and odc < 0xFFFF:
emit_error("past the end of available memory", line=op.name.line)
return labels


def convert(op):
"""Convert a pseudo-instruction into a list of real instructions."""
if op.name.startswith("B") and is_symbol(op.args[0]):
Expand Down
32 changes: 32 additions & 0 deletions hera/symtab.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from .utils import emit_error


# Arbitrary value copied over from HERA-C.
HERA_DATA_START = 16743


def get_symtab(program):
"""Return a dictionary mapping all labels and constants to their values."""
labels = {}
pc = 0
dc = HERA_DATA_START
for op in program:
odc = dc
if op.name == "LABEL":
labels[op.args[0]] = pc
elif op.name == "DLABEL":
labels[op.args[0]] = dc
elif op.name == "CONSTANT":
labels[op.args[0]] = op.args[1]
elif op.name == "INTEGER":
dc += 1
elif op.name == "DSKIP":
dc += op.args[0]
elif op.name == "LP_STRING":
dc += len(op.args[0]) + 1
else:
pc += 1

if dc >= 0xFFFF and odc < 0xFFFF:
emit_error("past the end of available memory", line=op.name.line)
return labels
2 changes: 1 addition & 1 deletion hera/vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import functools
import sys

from .preprocessor import HERA_DATA_START
from .symtab import HERA_DATA_START
from .utils import (
from_u16,
to_u16,
Expand Down
2 changes: 1 addition & 1 deletion test/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from unittest.mock import patch

from hera.main import main, execute_program
from hera.preprocessor import HERA_DATA_START
from hera.symtab import HERA_DATA_START
from hera.vm import VirtualMachine


Expand Down
2 changes: 1 addition & 1 deletion test/test_op/test_data_statements.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest

from hera.parser import Op
from hera.preprocessor import HERA_DATA_START
from hera.symtab import HERA_DATA_START
from hera.vm import VirtualMachine


Expand Down
65 changes: 0 additions & 65 deletions test/test_preprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
from hera.preprocessor import (
convert,
convert_set,
get_labels,
HERA_DATA_START,
preprocess,
substitute_label,
)
Expand Down Expand Up @@ -168,69 +166,6 @@ def test_convert_not():
]


def test_get_labels_with_example():
labels = get_labels(
[
Op("DLABEL", ["data"]),
Op("INTEGER", [42]),
Op("INTEGER", [43]),
Op("DLABEL", ["data2"]),
Op("INTEGER", [100]),
Op("LABEL", ["top"]),
Op("ADD", ["R0", "R0", "R0"]),
Op("LABEL", ["bottom"]),
]
)
assert len(labels) == 4
assert labels["data"] == HERA_DATA_START
assert labels["data2"] == HERA_DATA_START + 2
assert labels["top"] == 0
assert labels["bottom"] == 1


def test_get_labels_with_dskip():
labels = get_labels(
[
Op("DLABEL", ["data"]),
Op("INTEGER", [42]),
Op("DSKIP", [10]),
Op("DLABEL", ["data2"]),
Op("INTEGER", [84]),
]
)
assert len(labels) == 2
assert labels["data"] == HERA_DATA_START
assert labels["data2"] == HERA_DATA_START + 11


def test_get_labels_with_lp_string():
labels = get_labels(
[
Op("DLABEL", ["S"]),
Op("LP_STRING", ["hello"]),
Op("DLABEL", ["X"]),
Op("INTEGER", [42]),
]
)
assert len(labels) == 2
assert labels["S"] == HERA_DATA_START
assert labels["X"] == HERA_DATA_START + 6


def test_get_labels_with_empty_lp_string():
labels = get_labels(
[
Op("DLABEL", ["S"]),
Op("LP_STRING", [""]),
Op("DLABEL", ["X"]),
Op("INTEGER", [42]),
]
)
assert len(labels) == 2
assert labels["S"] == HERA_DATA_START
assert labels["X"] == HERA_DATA_START + 1


def test_preprocess_constant():
program = [
Op(Token("SYMBOL", "CONSTANT"), [Token("SYMBOL", "n"), IntToken(100)]),
Expand Down
65 changes: 65 additions & 0 deletions test/test_symtab.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from hera.parser import Op
from hera.symtab import get_symtab, HERA_DATA_START


def test_get_symtab_with_example():
labels = get_symtab(
[
Op("DLABEL", ["data"]),
Op("INTEGER", [42]),
Op("INTEGER", [43]),
Op("DLABEL", ["data2"]),
Op("INTEGER", [100]),
Op("LABEL", ["top"]),
Op("ADD", ["R0", "R0", "R0"]),
Op("LABEL", ["bottom"]),
]
)
assert len(labels) == 4
assert labels["data"] == HERA_DATA_START
assert labels["data2"] == HERA_DATA_START + 2
assert labels["top"] == 0
assert labels["bottom"] == 1


def test_get_symtab_with_dskip():
labels = get_symtab(
[
Op("DLABEL", ["data"]),
Op("INTEGER", [42]),
Op("DSKIP", [10]),
Op("DLABEL", ["data2"]),
Op("INTEGER", [84]),
]
)
assert len(labels) == 2
assert labels["data"] == HERA_DATA_START
assert labels["data2"] == HERA_DATA_START + 11


def test_get_symtab_with_lp_string():
labels = get_symtab(
[
Op("DLABEL", ["S"]),
Op("LP_STRING", ["hello"]),
Op("DLABEL", ["X"]),
Op("INTEGER", [42]),
]
)
assert len(labels) == 2
assert labels["S"] == HERA_DATA_START
assert labels["X"] == HERA_DATA_START + 6


def test_get_symtab_with_empty_lp_string():
labels = get_symtab(
[
Op("DLABEL", ["S"]),
Op("LP_STRING", [""]),
Op("DLABEL", ["X"]),
Op("INTEGER", [42]),
]
)
assert len(labels) == 2
assert labels["S"] == HERA_DATA_START
assert labels["X"] == HERA_DATA_START + 1

0 comments on commit 91a6c2d

Please sign in to comment.