Implementing New Operators

Some time ago, maybe 1.18.0, as an alternative to the standard range syntax, I implemented

i .. j :: k

and I think

i .. j .:. k

to get a bit closer to the Fortran syntax for a range

i : j : k

and the Fortran user seemed happy.

I simply mapped :: to the same token as by, i.e. TBY.

I tried to use it with 1.33.0 and while the syntax analysis works, it now wants a procedure called '::' or .:.. How is such a thing handled now?

Also, I tried to implement a new operator +@' to mean the same (for now) as addition. But it wants a procedure +@` now. I cannot just map that symbol to TPLUS. How does this work. Eventually I will make it do augmented addition.

Ditto for new comparison predicates ?? and !??

Where is this sort of stuff explained?

Thanks - Damian

Hi Damian,

I'm not sure there's a nice explanation of how the parser works that I can link you. However, I did note a couple of productions in the parser that use the string value of the token, which would correspond to the behavior you're seeing with wanting a procedure called '::'.

Here's the production for 'by' in chpl.ypp:

| expr TBY expr            { $$ = context->buildBinOp(@$, $1, $2, $3); }
//               the string in TBY is passed as argument here ^
//               this is the string "by" or ".:." depending on which token was used

The same is true for all the other binary operations you're trying to define.

A quick-and-dirty solution since you already have it emitting TBY tokens (e.g.) would be to create a new production instead of using TBY directly, and force it to always return the string "by".

by_operator:
  TBY { $$ = PODUniqueString::get(context->context(), "by"); }
;

// ...

| expr by_operator expr    { $$ = context->buildBinOp(@$, $1, $2, $3); }

Which should achieve your goal of making .:. literally mean the by token.

The next-less-quick step is to define your own tokens for these new operators in the same way the TBY tokens etc. are defined, and then convert them into the production AST after parsing. This way, you can still eventually convert the .:. operator into by, but for your other operators (+@, for example), you can treat them as regular operators and even allow overloading etc. Let me know if you would like guidance on how to do that, as it involves a couple more spots in the compiler.

Note sure this is the right place but let's go.

Does Chapel map the less than (or equal to) and greater than (or equal to) comparison operators to operators which do (or do not) raise IEEE 754 floating point exceptions? And where is this done please?

Is it possible to overload the .. operator to do the same task as by so one can write 1..n..2 to mean the same thing as Fortran's (and numerous technical papers) and likely soon C++'s and C's array syntax 1:n:2. I will not go anywhere near Julia's twisted variant. If so, where does one begin inside the compiler.

IEEE 754 has long supported the concept of unordered pairs of floating point numbers x and y and total ordering. The former can be written as either of the two operations

x != x || y != y

Where does one start to incorporate operators ?? and its negation !? to reflect that operation concisely as

x ?? y

To almost complete this internal task, what compiler hacking (and where) is required to implement operators ?> and ?< (or even |> and |<) to replace the bivariate argument cases of min(x,y) and max(x,y).

And finally, where are the conversion operators to an integral type of some real(w) number x defined so I can tweak them to do something like

proc convertToInteger(x : real(?w), type T : integral) where 
{
   return if x != x || abs(x) > max(T) then -min(T) else x:T;
}

How do I easily limit T to being signed or unsigned integral please?

Can somebody remind me of the tricks to make the flex and yacc tools play nicely together please? The last time I did this sort of thing was a long time ago and from memory, there was some tricks needed.

Thanks in advance.

There was some advice on Github #18629 but I was curious whether it is still current because I was under the impression that some of the insides of the compiler have changed since that response.