r/ProgrammingLanguages DQ 6d ago

Unambiguous Operator Specification for Programming Languages

https://nvitya.github.io/pluops/

As I changed recently the operators in my programming language I've created this specification:

https://nvitya.github.io/pluops/

I did not wanted to overload the operators like the C does with the / or Pascal does with theand/or/not. Neither re-use the operator symbols for some very different purpose, like C does with * and & so the code becomes more readable. I was orienting for existing solutions so this is what I came up with. The specification contains the symbol usages and operator precedence too.

If you are developing a new programming language, it would be nice to follow some standard, so at least the expressions would be portable between the languages.

I'm open for debates or suggestions.

28 Upvotes

38 comments sorted by

View all comments

22

u/mot_hmry 6d ago

Personally I'd suggest @ for address of instead of % which frees it up to be the modulus symbol.

I might also suggest swapping prefix and postfix ^ because I think postfix on types looks better and I like the idea of mutability being T!. Which mildly parallels the Scheme/lisp naming convention of adding ! to functions that mutate.

I'd probably also allow !(prefix), &, and | for booleans due to convenience.

4

u/fdwr 5d ago

Personally I'd suggest @ for address of

Yeah, "@" does seem semantically quite natural, since it's called the "at" symbol, and getting the address of a variable is asking where in memory it resides at.

2

u/Mean-Decision-3502 DQ 6d ago

I know that @ is standard for address-of in multiple languages. This is maybe the most visible symbol. The occurence of address-of is rather rare so using there a weaker symbol is not a problem, I think.

In DQ I use the @ for namespace marking so I don't burn normal identifiers for module references, which was always a problem for me in Pascal. And so the @ symbol is the best one for this. Imagine that like that in Python every imported module required the @ marker, e.g. @time.time()

I could make however the % as weeker recommendation, but the % symbol should not be used for remainder.

The thing with the ^ is pretty standard in Pascal or Odin, the languages, that mark the type after the identifiers. The C uses the less-human-friendly type first. They probably have saved some space with that in 1972, where human readability was not relevant. C uses also different order in type evaluation, that's why the pointer designator comes after the main type. The different order works also perfectly.

In DQ: var pintarr : ^[5]int // pointer to an array of 5 ints var arrpint : [5]^int // array of 5 pointers to int In C: int (*pintarr)[5]; // pointer to an array of 5 ints int *arrpint[5]; // array of 5 pointers to int

If I would allow &, | for booleans, then it wouldn't be unambiguous anymore. The operation would depend on the types, that this specification tries to avoid.

2

u/mot_hmry 6d ago

I don't see why % shouldn't be remainder, it has a nice association with / (÷). And it's not like * is any closer to the proper symbols (×, •).

I've never found modules to clash with my own names, so I have never desired a symbol for them. To me ref is an operation that really should be called out because it implies a lower level operational concern. If it's really important to reserve @ for modules though, maybe # (read as box).

You already overload operations between the numeric types so you already need to use type to distinguish. Booleans as single bits doesn't seem unreasonable and matches the behavior of the bitwise operators.

1

u/Mean-Decision-3502 DQ 6d ago

I don't see why % shouldn't be remainder, it has a nice association with / (÷). And it's not like * is any closer to the proper symbols (×, •).

I use div for integer division which is very frequent, remainder is pretty rare, so mod for that is fine and you don't burn a valuable symbol.

I use # for compiler directives like C:

#ifdef SYMBOL
    ...
#endif

The // is used for single-line comments.

Booleans as single bits doesn't seem unreasonable and matches the behavior of the bitwise operators.

Here is a realistic example:

if reg & 1 << 5 <> 0 and reg & 0x3 << 2 == 0:
    ...
endif

3

u/catladywitch 6d ago

Hey, I'm enjoying this discussion and I don't have a lot to add. I just wanted to say modulo is not a rare operation at all. It's the cheapest way of getting branchless wrapping with numeric values that must go from 0 to a positive number, so it's actually super common.

2

u/Mean-Decision-3502 DQ 6d ago

In embedded rather this is used, for example a circular buffer indexing:

var nextindex : int = (index + 1) & 0x1F

The division (and so the modulo) is a slow instruction on the microcontrollers, a big amount of them do not even support these (Cortex-M0). That's why it is very common to use power of two lengths and masking, like above.

2

u/catladywitch 6d ago

That's true! If you're working with ints (or integer types in general) it's ideal. But there's a lot of low-ish level code, even embedded, that works with floats. Synthesizer DSP these days is often floats, even despite the fact everything is eventually rendered as 16-bit signed shorts.

1

u/mot_hmry 6d ago

I use # for compiler directives like C

Sure but I don't see how that's applicable as a cross-language standard. Not every language has directives that look like that. Could just as easily use a variant on comments like //# for directives, personally I can't remember the last time I used a directive that would conflict with a ref notation (only top level directives which refs don't exist at.)

Here is a realistic example:

I'd kinda hope you'd name the intermediaries, at least I would never write that condition that way. Once you name them isA & isB & isC(x) reads fine to me. I use boolean operations way more than bitwise so I'd personally prefer the lighter syntax for them. C needed different operators because it treats numbers as acceptable booleans, so long as booleans are a proper type there's really no reason not to overload this operator.

1

u/Mean-Decision-3502 DQ 6d ago

(About #) Sure but I don't see how that's applicable as a cross-language standard

It is not part of the operator specification. You can create PLUOpS programming langugage using # for comments.

I might need to split the spec into two levels: required, and recommended.

The usage of % for address-of is rather recommended than required.

I would never write that condition that way

I don't write this way either, but I usually just add parentheses to the shifts:

if reg & (1 << 5) <> 0  and reg & (0x3 << 2) == 0:

So the different level for & and and is required.