Stack based array language (Uiua)
Timon Gehr
timon.gehr at gmx.ch
Thu Oct 5 20:47:21 UTC 2023
On 10/5/23 19:43, monkyyy wrote:
> On Wednesday, 4 October 2023 at 08:36:39 UTC, Timon Gehr wrote:
>>
>
> Oooo template code I have trouble reading
>
> Id given up on this; like I thought a stack meta-language would need to
> know the number of arguments of each function or to generate an ast to
> mixin something.
Well, technically all the functions that are actually called in my
example do specify the number of arguments on the stack (e.g. `unary`
and `binary` templates and the examples below), but that's mainly for
better error messages.
```d
auto dup(S,T...)(Tuple!(S,T) stack)=>tuple(stack.expand,stack[$-1]);
auto push(S,T...)(Tuple!T stack,S head)=>tuple(stack.expand,head);
auto flip(R,S,T...)(Tuple!(R,S,T)
stack)=>tuple(stack[0..$-2],stack[$-1],stack[$-2]);
```
Otherwise, I just use a tuple as my stack. If you don't provide the
number of arguments to `apply`, it will try to call the function with
all suffixes of the tuple and call the longest one. Then there's some
improvised broadcasting logic (may not be the sanest behavior
imaginable, didn't do much testing) in the `unary` and `binary`
templates so that ranges can combine with literals.
> Whats the base theory of how you modify a stack with
> only static if compile look ahead?
>
>
I guess you are asking about this part:
```d
auto apply(S,T...)(Tuple!(S,T) stack){
static if(__traits(compiles,f(stack.expand).expand))
return tuple(f(stack.expand).expand);
else static if(__traits(compiles,f(stack.expand)))
return tuple(f(stack.expand));
else return tuple(stack[0],apply(tuple(stack[1..$])).expand);
}
```
First I check whether `f` returns something that can be expanded when
called on the entire stack, this is so functions that return multiple
results in a tuple will push multiple results on the stack. The second
case is just to also support the case where `f` just returns a single
result when called on the entire stack. If calling on the entire stack
does not work, I preserve the first argument on the stack and recurse on
the remaining part of the stack.
Though in practice I think I have only used this branch of apply in the
code I pasted:
auto apply(S,T...)(Tuple!(S,T) stack){
static if(__traits(compiles,f(stack[$-nargs..$]).expand))
return tuple(stack[0..$-nargs],f(stack[$-nargs..$]).expand);
else return tuple(stack[0..$-nargs],f(stack[$-nargs..$]));
}
I.e., here I pass `nargs` explicitly and it just picks the correct
suffix to call, expanding it into the stack if possible.
More information about the Digitalmars-d
mailing list