shithub: rgbds

Download patch

ref: 7a314e7aff2a6e9a0f82cc7f98269276fcc167cb
parent: 637bbbdf4312ca6efb6eb4ad6ae4ad7f06d9357e
author: Rangi <[email protected]>
date: Sun Apr 18 19:47:10 EDT 2021

Support numeric symbol names in \(parentheses)

For example, \(_NARG) will get the last argument

--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -724,6 +724,8 @@
 static int peek(void);
 static void shiftChar(void);
 static uint32_t readNumber(int radix, uint32_t baseValue);
+static bool startsIdentifier(int c);
+static bool continuesIdentifier(int c);
 
 static uint32_t readParentheticMacroArgNum(void)
 {
@@ -736,15 +738,42 @@
 
 	uint32_t num = 0;
 	int c = peek();
-	bool hasDigit = c >= '0' && c <= '9';
+	bool empty = false;
 
-	if (hasDigit)
+	if (c >= '0' && c <= '9') {
 		num = readNumber(10, 0);
+	} else if (startsIdentifier(c)) {
+		char symName[MAXSYMLEN + 1];
+		size_t i = 0;
 
+		for (; continuesIdentifier(c); c = peek()) {
+			if (i < sizeof(symName))
+				symName[i++] = c;
+			shiftChar();
+		}
+
+		if (i == sizeof(symName)) {
+			warning(WARNING_LONG_STR, "Symbol name too long\n");
+			i--;
+		}
+		symName[i] = '\0';
+
+		struct Symbol const *sym = sym_FindScopedSymbol(symName);
+
+		if (!sym)
+			fatalerror("Parenthetic symbol \"%s\" does not exist\n", symName);
+		else if (!sym_IsNumeric(sym))
+			fatalerror("Parenthetic symbol \"%s\" is not numeric\n", symName);
+
+		num = sym_GetConstantSymValue(sym);
+	} else {
+		empty = true;
+	}
+
 	c = peek();
 	if (c != ')')
 		fatalerror("Invalid character in parenthetic macro argument %s\n", printChar(c));
-	else if (!hasDigit)
+	else if (empty)
 		fatalerror("Empty parenthetic macro argument\n");
 	else if (num == 0)
 		fatalerror("Invalid parenthetic macro argument '\\(0)'\n");
--- a/src/asm/rgbasm.5
+++ b/src/asm/rgbasm.5
@@ -1569,7 +1569,10 @@
 Since there are only nine digits, you can only access the first nine macro arguments like this.
 To use the rest, you need to put the multi-digit argument number in parentheses, like
 .Ql \[rs](10) .
-This parenthetic syntax only supports decimal numbers.
+This parenthetic syntax supports decimal numbers and numeric symbol names.
+For example,
+.Ql \[rs](_NARG)
+will get the last argument.
 .Pp
 Other macro arguments and symbol interpolations will be expanded inside the parentheses.
 For example, if
@@ -1580,10 +1583,12 @@
 .Ql \[rs](\[rs]1)
 will expand to
 .Ql \[rs](13) .
-And if
-.Ql x = 42 ,
+Or if
+.Ql v10 = 42
+and
+.Ql x = 10 ,
 then
-.Ql \[rs]({d:x})
+.Ql \[rs](v{d:x})
 will expand to
 .Ql \[rs](42) .
 .Pp
--- /dev/null
+++ b/test/asm/invalid-macro-arg-symbol.asm
@@ -1,0 +1,1 @@
+\(foo)
--- /dev/null
+++ b/test/asm/invalid-macro-arg-symbol.err
@@ -1,0 +1,2 @@
+FATAL: invalid-macro-arg-symbol.asm(1):
+    Parenthetic symbol "foo" does not exist
--- a/test/asm/parenthetic-macro-args.asm
+++ b/test/asm/parenthetic-macro-args.asm
@@ -12,6 +12,8 @@
 	println \(2__) + \(1_2) + \(\1)
 x = 2
 	println \({d:x}) + \(1_{d:x}) + \(\(\(13)))
+y equs "NARG"
+	println \(x) + \(1_{d:x}_) + \(\(\(_{y})))
 ENDM
 
 	mac 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 1
--- a/test/asm/parenthetic-macro-args.out
+++ b/test/asm/parenthetic-macro-args.out
@@ -4,3 +4,4 @@
 last = D
 $F0
 $F0
+$F0