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