shithub: rgbds

Download patch

ref: fe824e00687e96180c15c659511404ca6b93f079
parent: 66512ed8d2676f4937b2c64c9fea125aeb76d1d4
parent: 8fcdcb173184115c39bc175045aa94c942959c4d
author: Eldred Habert <[email protected]>
date: Sat Mar 21 19:20:01 EDT 2020

Merge pull request #490 from ISSOtm/const

Implement `ISCONST`, reporting compile-time constness

--- a/include/asm/rpn.h
+++ b/include/asm/rpn.h
@@ -54,6 +54,7 @@
 		  const struct Expression *src2);
 void rpn_HIGH(struct Expression *expr, const struct Expression *src);
 void rpn_LOW(struct Expression *expr, const struct Expression *src);
+void rpn_ISCONST(struct Expression *expr, const struct Expression *src);
 void rpn_UNNEG(struct Expression *expr, const struct Expression *src);
 void rpn_UNNOT(struct Expression *expr, const struct Expression *src);
 void rpn_BankSymbol(struct Expression *expr, char const *tzSym);
--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -543,6 +543,7 @@
 %left	T_OP_FLOOR
 
 %token	T_OP_HIGH T_OP_LOW
+%token	T_OP_ISCONST
 
 %left	T_OP_STRCMP
 %left	T_OP_STRIN
@@ -1301,6 +1302,7 @@
 		| T_OP_NOT relocexpr %prec NEG	{ rpn_UNNOT(&$$, &$2); }
 		| T_OP_HIGH '(' relocexpr ')'	{ rpn_HIGH(&$$, &$3); }
 		| T_OP_LOW '(' relocexpr ')'	{ rpn_LOW(&$$, &$3); }
+		| T_OP_ISCONST '(' relocexpr ')'{ rpn_ISCONST(&$$, &$3); }
 		| T_OP_BANK '(' scoped_id ')' {
 			/* '@' is also a T_ID, it is handled here. */
 			rpn_BankSymbol(&$$, $3);
--- a/src/asm/globlex.c
+++ b/src/asm/globlex.c
@@ -460,6 +460,7 @@
 
 	{"high", T_OP_HIGH},
 	{"low", T_OP_LOW},
+	{"isconst", T_OP_ISCONST},
 
 	{"strcmp", T_OP_STRCMP},
 	{"strin", T_OP_STRIN},
--- a/src/asm/rgbasm.5
+++ b/src/asm/rgbasm.5
@@ -553,7 +553,7 @@
 .Pp
 One of the best features of an assembler is the ability to write macros for it.
 Macros also provide a method of passing arguments to them and they can then react to the input using
-.Sy IF
+.Ic IF
 constructs.
 .Pp
 .Bd -literal -offset indent
@@ -1317,6 +1317,9 @@
 has been defined.
 .It Fn HIGH arg Ta Returns the top 8 bits of the operand if Ar arg No is a label or constant, or the top 8-bit register if it is a 16-bit register.
 .It Fn LOW arg Ta Returns the bottom 8 bits of the operand if Ar arg No is a label or constant, or the bottom 8-bit register if it is a 16-bit register Pq Cm AF No isn't a valid register for this function .
+.It Fn ISCONST arg Ta Returns 1 if Ar arg Ns No 's value is known by RGBASM (e.g. if it can be an argument to
+.Ic IF ) ,
+or 0 if only RGBLINK can compute its value.
 .El
 .Sh MISCELLANEOUS
 .Ss Changing options while assembling
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -506,6 +506,14 @@
 	}
 }
 
+void rpn_ISCONST(struct Expression *expr, const struct Expression *src)
+{
+	rpn_Init(expr);
+	expr->nVal = rpn_isKnown(src);
+	expr->isKnown = true;
+	expr->isSymbol = false;
+}
+
 void rpn_UNNEG(struct Expression *expr, const struct Expression *src)
 {
 	*expr = *src;
--- /dev/null
+++ b/test/asm/isconst.asm
@@ -1,0 +1,29 @@
+
+TEST_NUM = 0
+
+test_expr: MACRO
+TEST_NUM = TEST_NUM + 1
+
+IS_CONST = ISCONST(\1)
+	PRINTT "Test #{d:TEST_NUM}: ISCONST reports {IS_CONST}\n"
+	IF (\1) || 1 ; Only test if the expression can be evaluated
+		WARN "Test #{d:TEST_NUM}: Compile-time constant"
+	ENDC
+ENDM
+
+	test_expr 1
+	test_expr UnknownLabel
+
+SECTION "fixed", WRAM0[$CAFE]
+
+FixedLabel:
+	ds 42
+	test_expr FixedLabel
+	test_expr @ - FixedLabel
+
+SECTION "floating", WRAMX
+
+FloatingLabel:
+	ds 69
+	test_expr FloatingLabel
+	test_expr @ - FloatingLabel
--- /dev/null
+++ b/test/asm/isconst.err
@@ -1,0 +1,13 @@
+warning: isconst.asm(14) -> isconst.asm::test_expr(10): [-Wuser]
+    Test #1: Compile-time constant
+ERROR: isconst.asm(15) -> isconst.asm::test_expr(9):
+    Expected constant expression: 'UnknownLabel' is not constant at assembly time
+warning: isconst.asm(21) -> isconst.asm::test_expr(10): [-Wuser]
+    Test #3: Compile-time constant
+warning: isconst.asm(22) -> isconst.asm::test_expr(10): [-Wuser]
+    Test #4: Compile-time constant
+ERROR: isconst.asm(28) -> isconst.asm::test_expr(9):
+    Expected constant expression: 'FloatingLabel' is not constant at assembly time
+warning: isconst.asm(29) -> isconst.asm::test_expr(10): [-Wuser]
+    Test #6: Compile-time constant
+error: Assembly aborted (2 errors)!
--- /dev/null
+++ b/test/asm/isconst.out
@@ -1,0 +1,6 @@
+Test #1: ISCONST reports $1
+Test #2: ISCONST reports $0
+Test #3: ISCONST reports $1
+Test #4: ISCONST reports $1
+Test #5: ISCONST reports $0
+Test #6: ISCONST reports $1