Skip to content

Commit 7e1d78a

Browse files
committed
Added support for <...[math]> variadic arg syntax
1 parent 14794a9 commit 7e1d78a

File tree

8 files changed

+76
-20
lines changed

8 files changed

+76
-20
lines changed

docs/changelog/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ <h3>New features:</h3>
6161
<li>Static labels (i.e. labels that don't move between passes) can now be used in more places, including if statements. (RPG Hacker)</li>
6262
<li>Asar can be built as a static library. (Atari2)</li>
6363
<li>Asar now uses named warnings and errors instead of magic numbers as identifiers. (p4plus2, RPG Hacker)</li>
64+
<li>Variadic macro parameters now use the syntax <code class="65c816_asar">&lt;...[math]&gt;</code>, which makes them less ambiguous and helps prevent syntax parsing bugs. (RPG Hacker)</li>
6465
</ul>
6566

6667
<h3>Bug fixes:</h3>
@@ -96,6 +97,7 @@ <h3>Deprecated features:</h3>
9697
<li><code>;@command</code> and <code>@command</code> notation: Use <code>command</code> instead.</li>
9798
<li>Wrapping defines to resolve in quotes (e.g. <code>db "!define"</code>): The quotes aren't needed (<code>db !define</code>).</li>
9899
<li>Single-line/inline if statements: Use full if blocks with an <code>if</code>/<code>endif</code> pair instead.</li>
100+
<li><code class="65c816_asar">&lt;math&gt;</code> syntax for variadic macro parameters: Use <code class="65c816_asar">&lt;...[math]&gt;</code> insread.</li>
99101
</ul></div>
100102

101103
<hr />

docs/manual/index.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,26 +2439,26 @@ <h4 id="built-in-defines">Built-in Defines</h4>
24392439
</code></pre>
24402440

24412441
In addition to named substitutions if the variadic token <code class="65c816_asar">...</code> is specified as the last parameter asar will allow an arbitrary number of parameters after all prior parameters have been satisfied.
2442-
To access unnamed arguments of a variadic function they are declared numerically starting from 0 up to the number of provided parameters. To access the number of provided variadic arguments one may use <code class="65c816_asar">sizeof(...)</code>.
2442+
To access unnamed parameters of a variadic macro, use the syntax <code class="65c816_asar">&lt;...[{math}]&gt;</code>, where <code class="65c816_asar">math</code> is any math expression evaluating to the index of a variadic parameter. These are declared numerically starting from 0 up to the number of provided parameters. To access the number of provided variadic arguments one may use <code class="65c816_asar">sizeof(...)</code>.
24432443
Lastly, it is important to note that while traditionally macros do not parse defines at their creation variadic macros will. This is to allow iteration of arguments by using defines.
24442444

24452445
<pre><code class="65c816_asar">
24462446
macro example0(...)
2447-
db sizeof(...), &lt;0&gt; ;04 01
2447+
db sizeof(...), &lt;...[0]&gt; ;04 01
24482448
endmacro
24492449

24502450
macro example1(...)
24512451
!a #= 0
24522452
while !a &lt; sizeof(...)
2453-
db &lt;!a&gt; ;01 02 03
2453+
db &lt;...[!a]&gt; ;01 02 03
24542454
!a #= !a+1
24552455
endif
24562456
endmacro
24572457

24582458
macro example2(named_parameter, ...)
24592459
!a #= 0
24602460
while !a &lt; sizeof(...)
2461-
db &lt;!a&gt; ;02 03 04 05 06 07
2461+
db &lt;...[!a]&gt; ;02 03 04 05 06 07
24622462
!a #= !a+1
24632463
endif
24642464
db &lt;named_parameter&gt; ;01
@@ -2467,7 +2467,7 @@ <h4 id="built-in-defines">Built-in Defines</h4>
24672467
macro macro_with_optional_arguments(required, ...)
24682468
db &lt;required&gt;
24692469
if sizeof(...) &gt; 0
2470-
db &lt;0&gt;
2470+
db &lt;...[0]&gt;
24712471
end
24722472
end
24732473

src/asar-tests/test.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,10 @@ int main(int argc, char * argv[])
10731073

10741074
free(smwrom);
10751075

1076+
#if defined(ASAR_TEST_DLL)
1077+
asar_close();
1078+
#endif
1079+
10761080
printf("%u out of %u performed tests succeeded.\n", (unsigned int)(input_files.size() - (size_t)numfailed), (unsigned int)input_files.size());
10771081

10781082
if (numfailed > 0)
@@ -1081,9 +1085,5 @@ int main(int argc, char * argv[])
10811085
return 1;
10821086
}
10831087

1084-
#if defined(ASAR_TEST_DLL)
1085-
asar_close();
1086-
#endif
1087-
10881088
return 0;
10891089
}

src/asar/errors.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,10 @@ static asar_error_mapping asar_errors[] =
284284
{ ERR(pushns_without_pullns), "pushns without matching pullns." },
285285
{ ERR(pullns_without_pushns), "pullns without matching pushns." },
286286

287-
{ ERR(label_forward), "The use of forward labels is not allowed in this context" },
287+
{ ERR(label_forward), "The use of forward labels is not allowed in this context." },
288+
289+
{ ERR(unclosed_vararg), "Variadic macro parameter wasn't closed properly." },
290+
{ ERR(invalid_vararg), "Trying to use variadic macro parameter syntax to resolve a non variadic argument." },
288291
};
289292
// RPG Hacker: Sanity check. This makes sure that the element count of asar_warnings
290293
// matches with the number of constants in asar_warning_id. This is important, because

src/asar/errors.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,9 @@ enum asar_error_id : int
259259
error_id_pullns_without_pushns,
260260

261261
error_id_label_forward,
262+
263+
error_id_unclosed_vararg,
264+
error_id_invalid_vararg,
262265

263266
error_id_end,
264267
error_id_count = error_id_end - error_id_start - 1,

src/asar/macro.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "assembleblock.h"
77
#include "macro.h"
88
#include "asar_math.h"
9+
#include "warnings.h"
910

1011
assocarr<macrodata*> macros;
1112
static string thisname;
@@ -169,6 +170,17 @@ void callmacro(const char * data)
169170
out+=*(in++);
170171
continue;
171172
}
173+
174+
bool proper_variadic = false;
175+
if (in[1] == '.' && in[2] == '.' && in[3] == '.' && in[4] == '[')
176+
{
177+
if (end[-1] != ']')
178+
asar_throw_error(0, error_type_block, error_id_unclosed_vararg);
179+
180+
proper_variadic = true;
181+
in += 4;
182+
end[-1]=0;
183+
}
172184

173185
*end=0;
174186
in++;
@@ -178,7 +190,7 @@ void callmacro(const char * data)
178190
bool valid_named_param = confirmname(in);
179191
if (!valid_named_param && !thismacro->variadic) asar_throw_error(0, error_type_block, error_id_invalid_macro_param_name);
180192
bool found=false;
181-
for (int j=0;thismacro->arguments[j];j++)
193+
for (int j=0;thismacro->arguments[j]&&!proper_variadic;j++)
182194
{
183195
if (!strcmp(in, thismacro->arguments[j]))
184196
{
@@ -195,8 +207,17 @@ void callmacro(const char * data)
195207
if (!found)
196208
{
197209
snes_label ret;
198-
if(valid_named_param && !thismacro->variadic) asar_throw_error(0, error_type_block, error_id_macro_param_not_found, in);
199-
if(thismacro->variadic && valid_named_param && !labelval(in, &ret, false)) asar_throw_error(0, error_type_block, error_id_macro_param_not_found, in);
210+
if(valid_named_param && !thismacro->variadic)
211+
{
212+
if (proper_variadic) asar_throw_error(0, error_type_block, error_id_invalid_vararg, in);
213+
else asar_throw_error(0, error_type_block, error_id_macro_param_not_found, in);
214+
}
215+
if(thismacro->variadic && valid_named_param && !labelval(in, &ret, false))
216+
{
217+
if (proper_variadic) asar_throw_error(0, error_type_block, error_id_invalid_vararg, in);
218+
else asar_throw_error(0, error_type_block, error_id_macro_param_not_found, in);
219+
}
220+
if(!proper_variadic) asar_throw_warning(0, warning_id_feature_deprecated, "'<math>' syntax for variadic macro parameters", "Use '<...[math]>' instead.");
200221
int arg_num = getnum(in);
201222

202223
if(forwardlabel) asar_throw_error(0, error_type_block, error_id_label_forward);

tests/variadic_errors.asm

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
;`errEvararg_must_be_last
22
;`errEinvalid_macro_param_name
3+
;`warnWfeature_deprecated
4+
;`errEunclosed_vararg
5+
;`errEinvalid_vararg
6+
;`errEinvalid_vararg
37
;`errEvararg_sizeof_nomacro
48
;`errEmacro_not_varadic
59
;`errEvararg_out_of_bounds
@@ -19,11 +23,11 @@ macro asd(..., dfg)
1923
endmacro
2024

2125
macro sorry(...)
22-
db <-1>
26+
db <...[-1]>
2327
endmacro
2428

2529
macro sorry2(asd, ...)
26-
db <10>
30+
db <...[10]>
2731
endmacro
2832

2933
macro normal()
@@ -46,3 +50,24 @@ db $FF, $FF
4650
%sorry2(0)
4751
%sorry3()
4852

53+
54+
macro deprecated(...)
55+
db <0>
56+
endmacro
57+
58+
macro unclosed(...)
59+
db <...[0>
60+
endmacro
61+
62+
macro invalid(named, ...)
63+
db <...[named]>
64+
endmacro
65+
66+
macro invalid_2(named)
67+
db <...[named]>
68+
endmacro
69+
70+
%deprecated($01)
71+
%unclosed($01)
72+
%invalid($01, $01)
73+
%invalid_2($01)

tests/variadic_syntax.asm

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
;`01 01 01 FF FF 05 01 01 FF FF 01 02 03 04 05 06 07 FF FF 02 03 04 05 06 07 01 01 02 03
2+
;`warnWfeature_deprecated
3+
;`warnWfeature_deprecated
24
lorom
35
org $008000
46

57
!a = 0
68
macro asd(...)
7-
db sizeof(...), <0>, <!a>
9+
db sizeof(...), <...[0]>, <!a> ; Intentionally uses deprecated syntax, to make sure it still works
810
endmacro
911

1012
macro sorry(...)
1113
!a = 0
1214
while !a < sizeof(...)
13-
db <!a>
15+
db <...[!a]>
1416
!a #= !a+1
1517
endwhile
1618
endmacro
1719

1820
macro sorry2(asd, ...)
1921
!a = 0
20-
db <0>
22+
db <...[0]>
2123
while !a < sizeof(...)-1
22-
db <!a+1>
24+
db <...[!a+1]>
2325
!a #= !a+1
2426
endwhile
2527
db <asd>
@@ -28,7 +30,7 @@ endmacro
2830
macro optional(required, ...)
2931
db <required>
3032
if sizeof(...) > 0
31-
db <0>
33+
db <...[0]>
3234
endif
3335
endmacro
3436

0 commit comments

Comments
 (0)