Skip to content

Commit 5675692

Browse files
fixed bug with parsing labels starting with BYTE
1 parent daa964c commit 5675692

File tree

7 files changed

+58
-7
lines changed

7 files changed

+58
-7
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ Changes that are planned but not implemented yet:
1515
* unknown labels
1616
* Add named label scopes. This would allow a label to be defined in a specific scope that can be shared across files.
1717
* Create a "align if needed" preprocessor directive paid that generates an `.align` directive if the bytecode in between the pair isn't naturally on the same page and can fit on the same page if aligned. An error would be benerated if the block of code can't fit on the same page regardless of alignment.
18+
* Update the `#ifdef` and related preprocessor directives to include detection of labels and constants.
1819

1920
## [Unreleased]
2021
* Upgrade python version requirements to 3.11
2122
* Fixed a bug where embedded stringsd weren't properly parsed if they contained a newline character or there were multiple embedded strings per line
23+
* Fixed a bug where parsing properly discriminate between labels starting with `BYTE` string and the `BYTEx()` operator.
2224

2325
## [0.4.2]
2426
* Added support for The Minimal 64x4 Home Computer with an example and updated assembler functionality to support it.

src/bespokeasm/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
BESPOKEASM_VERSION_STR = '0.4.3b1'
1+
BESPOKEASM_VERSION_STR = '0.4.3b2'
22

33
# if a cconfig file requires a certain bespoke ASM version, it should be at least this version.
44
BESPOKEASM_MIN_REQUIRED_STR = '0.3.0'

src/bespokeasm/assembler/bytecode/generator/macro.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def generate_bytecode_parts(
3939
if assembled_instruction is not None:
4040
return assembled_instruction
4141

42-
sys.exit(f'ERROR: {line_id} - Instruction "{mnemonic}" has no valid operands configured.')
42+
sys.exit(f'ERROR: {line_id} - Macro "{mnemonic}" has no valid operands configured.')
4343

4444
@classmethod
4545
def generate_variant_bytecode_parts(

src/bespokeasm/expression/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ def _lexical_analysis(line_id: LineIdentifier, s: str) -> list[ExpressionNode]:
185185
if part in TOKEN_MAPPINGS:
186186
token_type = TOKEN_MAPPINGS[part]
187187
token = ExpressionNode(token_type, value=part)
188-
elif part.startswith('BYTE'):
188+
elif re.match(r'^BYTE\d\(', part):
189189
token = ExpressionNode(TokenType.T_BYTE, value=part)
190190
elif is_string_numeric(part):
191191
token = ExpressionNode(TokenType.T_NUM, value=parse_numeric_string(part))

test/config_files/test_instruction_operands.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ operand_sets:
3131
bytecode:
3232
value: 3
3333
size: 4
34+
immediate_8bit:
35+
# one byte is interpreted as an immediate value
36+
operand_values:
37+
int8:
38+
type: numeric
39+
argument:
40+
size: 8
41+
byte_align: true
42+
endian: little
3443
enums:
3544
operand_values:
3645
register_enum:
@@ -141,3 +150,13 @@ instructions:
141150
byte_align: true
142151
max: 128
143152
min: -127
153+
adi:
154+
# Add immediate to A: A += imm
155+
bytecode:
156+
value: 0xa2
157+
size: 8
158+
operands:
159+
count: 1
160+
operand_sets:
161+
list:
162+
- immediate_8bit

test/test_expression.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ class TestExpression(unittest.TestCase):
1111
@classmethod
1212
def setUpClass(cls):
1313
cls.label_values = GlobalLabelScope(set())
14-
cls.label_values.set_label_value('value_1', 12, 1)
15-
cls.label_values.set_label_value('the_8_ball', 8, 2)
16-
cls.label_values.set_label_value('MixedCase', 2, 3)
17-
cls.label_values.set_label_value('MAX_N', 20, 1)
14+
line = LineIdentifier(0, 'setUpClass')
15+
cls.label_values.set_label_value('value_1', 12, line)
16+
cls.label_values.set_label_value('the_8_ball', 8, line)
17+
cls.label_values.set_label_value('MixedCase', 2, line)
18+
cls.label_values.set_label_value('MAX_N', 20, line)
19+
cls.label_values.set_label_value('BYTECODE_LL0', 0x07, line)
1820

1921
def test_expression_parsing(self):
2022
line_id = LineIdentifier(1212, 'test_expression_parsing')
@@ -59,6 +61,10 @@ def test_expression_parsing(self):
5961
parse_expression(line_id, '(MAX_N + 3) % %101').get_value(TestExpression.label_values, line_id),
6062
3, 'test handling of modulo: (MAX_N + 3) % %101 = 3'
6163
)
64+
self.assertEqual(
65+
parse_expression(line_id, 'BYTECODE_LL0').get_value(TestExpression.label_values, line_id),
66+
0x07, 'test handling of label with prefix: BYTECODE_LL0'
67+
)
6268

6369
with self.assertRaises(SyntaxError, msg='only integer numeric values are supported'):
6470
parse_expression(1212, '(value_1/5)/2.4').get_value(TestExpression.label_values, 100)

test/test_instruction_parsing.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,30 @@ def test_operand_order(self):
695695
t3.generate_bytes()
696696
self.assertEqual(list(t3.get_bytes()), [0x81, 0x32, 0x10], 'instruction byte should match')
697697

698+
def test_operand_expression(self):
699+
fp = pkg_resources.files(config_files).joinpath('test_instruction_operands.yaml')
700+
isa_model = AssemblerModel(str(fp), 0)
701+
memzone_mngr = MemoryZoneManager(
702+
isa_model.address_size,
703+
isa_model.default_origin,
704+
isa_model.predefined_memory_zones,
705+
)
706+
707+
lineid = LineIdentifier(42, 'test_operand_order')
708+
709+
t1 = InstructionLine.factory(
710+
lineid,
711+
'ADI var1w+0',
712+
'comment',
713+
isa_model,
714+
memzone_mngr.global_zone,
715+
memzone_mngr,
716+
)
717+
718+
t1.label_scope = TestInstructionParsing.label_values
719+
self.assertIsInstance(t1, InstructionLine)
720+
self.assertEqual(t1.byte_size, 2, 'has 2 bytes')
721+
698722
def test_relative_address_operand(self):
699723
fp = pkg_resources.files(config_files).joinpath('test_instruction_operands.yaml')
700724
isa_model = AssemblerModel(str(fp), 0)

0 commit comments

Comments
 (0)