The AddCarry primitive was introduced to Pancake in #1398, and given concrete syntax that looked like this:
x = __add_with_carry__(y,z,w);
Because it looks so much like a function call, its parsing implementation piggybacks on the parsing of functions like this: during PEG parsing, nothing special is done so it becomes an ordinary CallNT node. Then during ptree conversion, the conversion of CallNT nodes has a hack special case for function calls of the precise form above, where they get replaced with the AddCarry primitive.
But function calls are allowed in many positions where \_\_add_with_carry\_\_ is not: as stand-alone calls f(args), as tail calls return f(args), as calls with exception handlers, and so on. Ptree conversion needs to decide what do do when confronted with this. Prior to #1450, the behaviour in such cases was inconsistent: it would either fail during ptree conversion, or succeed and produce a Call to a function named \_\_add_with_carry\_\_. Both behaviours are bad: ptree conversion should never fail on the PEG parser's output, and it is confusing that nothing stops people from writing functions like this:
fun 1 __add_with_carry__(1 y, 1 w, 1 x) { ... }
...that is only callable on tuesdays.
In #1450 I made sure all out-of-place __add_with_carry__ calls always fail ptree conversion, which is still bad, but at least consistent.
My proposed fix is to treat __add_with_carry__ as a keyword during lexing, and handle it with its own kind of NT node in the PEG. Misusing the name would then produce (more) useful error messages.
The
AddCarryprimitive was introduced to Pancake in #1398, and given concrete syntax that looked like this:x = __add_with_carry__(y,z,w);
Because it looks so much like a function call, its parsing implementation piggybacks on the parsing of functions like this: during PEG parsing, nothing special is done so it becomes an ordinary
CallNTnode. Then during ptree conversion, the conversion ofCallNTnodes has ahackspecial case for function calls of the precise form above, where they get replaced with theAddCarryprimitive.But function calls are allowed in many positions where
\_\_add_with_carry\_\_is not: as stand-alone callsf(args), as tail callsreturn f(args), as calls with exception handlers, and so on. Ptree conversion needs to decide what do do when confronted with this. Prior to #1450, the behaviour in such cases was inconsistent: it would either fail during ptree conversion, or succeed and produce aCallto a function named\_\_add_with_carry\_\_. Both behaviours are bad: ptree conversion should never fail on the PEG parser's output, and it is confusing that nothing stops people from writing functions like this:fun 1 __add_with_carry__(1 y, 1 w, 1 x) { ... }
...that is only callable on tuesdays.
In #1450 I made sure all out-of-place
__add_with_carry__calls always fail ptree conversion, which is still bad, but at least consistent.My proposed fix is to treat
__add_with_carry__as a keyword during lexing, and handle it with its own kind ofNTnode in the PEG. Misusing the name would then produce (more) useful error messages.