shithub: rgbds

Download patch

ref: 8e4ba8d2e436a985c77e08212b65dd31157dea3f
parent: ee67f1039cf8a690263dbf485b0c1720341b67d0
author: Rangi <[email protected]>
date: Sun Apr 25 17:06:19 EDT 2021

Allow REDEF for EQU constants

Fixes #853

--- a/include/asm/symbol.h
+++ b/include/asm/symbol.h
@@ -120,6 +120,7 @@
 void sym_WriteAnonLabelName(char buf[MIN_NB_ELMS(MAXSYMLEN + 1)], uint32_t ofs, bool neg);
 void sym_Export(char const *symName);
 struct Symbol *sym_AddEqu(char const *symName, int32_t value);
+struct Symbol *sym_RedefEqu(char const *symName, int32_t value);
 struct Symbol *sym_AddSet(char const *symName, int32_t value);
 uint32_t sym_GetPCValue(void);
 uint32_t sym_GetConstantSymValue(struct Symbol const *sym);
--- a/src/asm/parser.y
+++ b/src/asm/parser.y
@@ -851,6 +851,7 @@
 		| warn
 		| assert
 		| def_equ
+		| redef_equ
 		| def_set
 		| def_rb
 		| def_rw
@@ -1115,6 +1116,11 @@
 
 def_equ		: def_id T_POP_EQU const {
 			sym_AddEqu($1, $3);
+		}
+;
+
+redef_equ	: redef_id T_POP_EQU const {
+			sym_RedefEqu($1, $3);
 		}
 ;
 
--- a/src/asm/rgbasm.5
+++ b/src/asm/rgbasm.5
@@ -967,6 +967,26 @@
 Note that colons
 .Ql \&:
 following the name are not allowed.
+.Pp
+If you
+.Em really
+need to, the
+.Ic REDEF
+keyword will define or redefine a constant symbol.
+This can be used, for example, to update a constant using a macro, without making it mutable in general.
+.Bd -literal -offset indent
+    def NUM_ITEMS equ 0
+MACRO add_item
+    redef NUM_ITEMS equ NUM_ITEMS + 1
+    def ITEM_{02x:NUM_ITEMS} equ \1
+ENDM
+    add_item 1
+    add_item 4
+    add_item 9
+    add_item 16
+    assert NUM_ITEMS == 4
+    assert ITEM_04 == 16
+.Ed
 .Ss Mutable constants
 .Ic SET ,
 or its synonym
--- a/src/asm/symbol.c
+++ b/src/asm/symbol.c
@@ -397,6 +397,30 @@
 	return sym;
 }
 
+struct Symbol *sym_RedefEqu(char const *symName, int32_t value)
+{
+	struct Symbol *sym = sym_FindExactSymbol(symName);
+
+	if (!sym)
+		return sym_AddEqu(symName, value);
+
+	if (sym_IsDefined(sym) && sym->type != SYM_EQU) {
+		error("'%s' already defined as non-EQU at ", symName);
+		dumpFilename(sym);
+		putc('\n', stderr);
+		return NULL;
+	} else if (sym->isBuiltin) {
+		error("Built-in symbol '%s' cannot be redefined\n", symName);
+		return NULL;
+	}
+
+	updateSymbolFilename(sym);
+	sym->type = SYM_EQU;
+	sym->value = value;
+
+	return sym;
+}
+
 /*
  * Add a string equated symbol.
  *
--- a/test/asm/def.asm
+++ b/test/asm/def.asm
@@ -26,4 +26,5 @@
 redef string equs "there"
 	println "{string}"
 
-redef constant equ 6*9 ; syntax error
+redef constant equ 6*9
+	println constant
--- a/test/asm/def.err
+++ b/test/asm/def.err
@@ -1,5 +1,3 @@
 ERROR: def.asm(23):
     'constant' already defined at def.asm(10)
-ERROR: def.asm(29):
-    syntax error, unexpected EQU, expecting SET or = or EQUS
-error: Assembly aborted (2 errors)!
+error: Assembly aborted (1 error)!
--- a/test/asm/def.out
+++ b/test/asm/def.out
@@ -7,3 +7,4 @@
 $0 $1 $5 $9
 $2A
 there
+$36
--- /dev/null
+++ b/test/asm/redef-equ.asm
@@ -1,0 +1,23 @@
+DEF n EQU 0
+REDEF n EQU 1
+; prints "$1"
+PRINTLN n
+
+list: MACRO
+LIST_NAME EQUS "\1"
+DEF LENGTH_{LIST_NAME} EQU 0
+ENDM
+
+item: MACRO
+REDEF LENGTH_{LIST_NAME} EQU LENGTH_{LIST_NAME} + 1
+DEF {LIST_NAME}_{d:LENGTH_{LIST_NAME}} EQU \1
+ENDM
+
+	list SQUARES
+	item 1
+	item 4
+	item 9
+	println LENGTH_SQUARES, SQUARES_1, SQUARES_2, SQUARES_3
+
+N EQUS "X"
+REDEF N EQU 42
--- /dev/null
+++ b/test/asm/redef-equ.err
@@ -1,0 +1,3 @@
+ERROR: redef-equ.asm(23):
+    'N' already defined as non-EQU at redef-equ.asm(22)
+error: Assembly aborted (1 error)!
--- /dev/null
+++ b/test/asm/redef-equ.out
@@ -1,0 +1,2 @@
+$1
+$3$1$4$9
--- /dev/null
+++ b/test/asm/reference-undefined-equs.asm
@@ -1,0 +1,5 @@
+SECTION "sec", ROM0[0]
+	db s1, s2
+
+def s1 equs "1"
+redef s2 equs "2"
--- /dev/null
+++ b/test/asm/reference-undefined-equs.err
@@ -1,0 +1,5 @@
+ERROR: reference-undefined-equs.asm(4):
+    's1' already referenced at reference-undefined-equs.asm(2)
+ERROR: reference-undefined-equs.asm(5):
+    's2' already referenced at reference-undefined-equs.asm(2)
+error: Assembly aborted (2 errors)!
--- a/test/asm/reference-undefined-sym.asm
+++ b/test/asm/reference-undefined-sym.asm
@@ -1,4 +1,7 @@
 SECTION "sec", ROM0[0]
-	db X
+	db x1, x2, y1, y2
 
-X = 2
+def x1 = 1
+redef x2 = 2
+def y1 equ 3
+redef y2 equ 4
--- a/test/asm/reference-undefined-sym.out.bin
+++ b/test/asm/reference-undefined-sym.out.bin
@@ -1,0 +1,1 @@
+
\ No newline at end of file