macro behaviour in compiler and interpreter

2 views
Skip to first unread message

Ralf Hemmecke

unread,
Dec 21, 2025, 6:38:13 PM (17 hours ago) Dec 21
to fricas-devel
Hi Waldek,

I just realized that macro expansion in the interpreter works
differently than in the compiler.

%%% (253) -> to(C)(x,y) ==> (x::C) + (y::C)
%%% (254) -> foo(x: Integer): Integer == to(Integer)(3+x, 2*x)
Function declaration foo : Integer -> Integer has been added to
workspace.
%%% (255) -> foo(4)
Compiling function foo with type Integer -> Integer

(255) 15
Type: PositiveInteger

That kind of macro seem to work in the interpreter.

Unfortunately, it doesn't in SPAD, see below.

Is there any way to make that work?

I actually want even something like
mac(A,B)(x,y) ==> ...

and then use mac(U,V) as an argument in another macro.

Shouldn't that be possible?
It would make me sad if this does really not work in SPAD.

Ralf

====================================================
)abbrev domain FOO Foo
Foo(): with
foo: Integer -> Integer
== add
to(C)(x,y) ==> (x::C) + (y::C)
foo(x: Integer): Integer == to(Integer)(3+x, 2*x)
====================================================

%%% (253) -> )co ../foo
Compiling FriCAS source code from file
/home/hemmecke/backup/git/qeta/tmp/../foo.spad using old system
compiler.
FOO abbreviates domain Foo
------------------------------------------------------------------------
initializing NRLIB FOO for Foo
compiling into NRLIB FOO
processing macro definition (to C)(x,y) ==> +(::(x,C),::(y,C))

>> Apparent user error:
invalid macro call, #args ~= #margs

Waldek Hebisch

unread,
Dec 21, 2025, 8:14:05 PM (16 hours ago) Dec 21
to 'Ralf Hemmecke' via FriCAS - computer algebra system
On Mon, Dec 22, 2025 at 12:38:08AM +0100, 'Ralf Hemmecke' via FriCAS - computer algebra system wrote:
> Hi Waldek,
>
> I just realized that macro expansion in the interpreter works differently
> than in the compiler.
>
> %%% (253) -> to(C)(x,y) ==> (x::C) + (y::C)
> %%% (254) -> foo(x: Integer): Integer == to(Integer)(3+x, 2*x)
> Function declaration foo : Integer -> Integer has been added to
> workspace.
> %%% (255) -> foo(4)
> Compiling function foo with type Integer -> Integer
>
> (255) 15
> Type: PositiveInteger
>
> That kind of macro seem to work in the interpreter.

IIRC this sometimes works, but not always.

> Unfortunately, it doesn't in SPAD, see below.
>
> Is there any way to make that work?
>
> I actually want even something like
> mac(A,B)(x,y) ==> ...
>
> and then use mac(U,V) as an argument in another macro.
>
> Shouldn't that be possible?
> It would make me sad if this does really not work in SPAD.

First step, very important for such things, is to define what it
should do, what is considered correct and what should signal
error. So, let me try. You want staged macro expansion.
We could say that partially expanded macro is a "macro
function". The simplest case is macro name, that is symbol
naming a macro. But also you want 'mac(A,B)' to produce
macro function which could be applied to following arguments.
When evaluating an expression first step should be to check
if it is an application of macro function to arguments. This
may require evaluating first part of an expression to get possible
value from nested macro expansions. If given expression is
an application of macro function to arguments, and number of
arguments matches we should apply macro, that is substitute
arguments into right hand side of macro definition. I assume
here that

mac(A,B)(x,y) ==>

really define macro function named 'mac' which after substituting
arguments for A and B gives new anonymous macro function which
can be applied to two arguments.

Now, what shall we do if number of arguments do not match.
AFAICS currently we signal error so we probably should do
so. Related thing is what to do when we want to evaluate
something, but we get just a macro function, it seems that
we should also signal error in such a case. Do this match
what you would like to use?

Now, considering possible uses, current Spad compiler assumes
that it can use almost as-is types appearing in 'with' part,
which means that we need to expand types. This is not a
trouble for regular compilation, but needs changes to
algebra bootstrap. This does not look very hard, but
I need to think how to do this without future maintanence
troubles.

--
Waldek Hebisch

Ralf Hemmecke

unread,
2:17 AM (9 hours ago) 2:17 AM
to fricas...@googlegroups.com
On 12/22/25 02:14, Waldek Hebisch wrote:
> On Mon, Dec 22, 2025 at 12:38:08AM +0100, 'Ralf Hemmecke' via FriCAS - computer algebra system wrote:

> IIRC this sometimes works, but not always.

Oh... good to know. Up to now I haven't run into trouble.

>> I actually want even something like
>> mac(A,B)(x,y) ==> ...
>>
> First step, very important for such things, is to define what it
> should do, what is considered correct and what should signal
> error.

Well, I basically (and maybe naively) think that it should behave like a
function that returns a function that is then applied to (x,y), only
that it is not a SPAD function, but a macro function.

> When evaluating an expression first step should be to check
> if it is an application of macro function to arguments. This
> may require evaluating first part of an expression to get possible
> value from nested macro expansions. If given expression is
> an application of macro function to arguments, and number of
> arguments matches we should apply macro, that is substitute
> arguments into right hand side of macro definition. I assume
> here that
>
> mac(A,B)(x,y) ==>
>
> really define macro function named 'mac' which after substituting
> arguments for A and B gives new anonymous macro function which
> can be applied to two arguments.

Exactly. That would be in line with the notations of functions returning
function in SPAD. I would **not** want that mac(A,B) is first expanded
and then the result is applied to (x,y). If I wanted that, I can simply
write

foo(x,y) ==...
mac2(A,B) ==> foo

where foo is a function (or a macro). But in the situation I want it,
I seem to need to consider mac as a function returning a function.

mac(A,x)(B,y) ==> fun(x,y) $ Foo(A,B)

> Now, what shall we do if number of arguments do not match.

Well, abort with an error. The problem is that in the example I sent,
the number of arguments was correct, but I still got an error.

> AFAICS currently we signal error so we probably should do
> so. Related thing is what to do when we want to evaluate
> something, but we get just a macro function, it seems that
> we should also signal error in such a case. Do this match
> what you would like to use?

Probably. I was actually only "complaining" about a situation where the
number of arguments was correct, but I still got an error. I did not
thing too much about what the consequences for the macro expansion
mechanisms were. An error in problematic cases is fine for me, but not
in cases where there is none.

> Now, considering possible uses, current Spad compiler assumes
> that it can use almost as-is types appearing in 'with' part,
> which means that we need to expand types. This is not a
> trouble for regular compilation, but needs changes to
> algebra bootstrap. This does not look very hard, but
> I need to think how to do this without future maintanence
> troubles.

Hmmmm... up to now I was thinking that macro expansions happens before
the actual compiler sees the (expanded) source code. I expect the macro
expansion producing proper SPAD code. Otherwise it should be counted as
an error. And I would also count it as an error if an exansion has left
an anonymous macro function that was not applied to something. That
means, if I define

mygcd(D)(x,y) ==> gcd(x,y) $ D

and I use it in code as

foo(mygcd(D), x,y)

where the function foo is defined as

foo(f, x, y) == f(x,y)

I would perfectly be fine if these cases lead to an error, since
I should rather have defined the macro in a simpler form like

mygcd(D) ==> gcd $ D

I hope that makes somehow sense.

Ralf
Reply all
Reply to author
Forward
0 new messages