feat(arxjit): lower expressions to astx - #109
Open
Jaskirat-s7 wants to merge 1 commit into
Open
Conversation
Second stage of the Sprint 3 lowering work, after arxlang#107 covered the function shell. Adds parameter reads, arithmetic, and unary operators, so the wiki's own example lowers end to end: def add(a, b): return a + b Operand types propagate: both sides of an operator are lowered at the expected type, so a literal buried in an expression takes the width of its context exactly as a returned one does. A variable read carries no type, because the prototype already declares it and reconciling it with its context is IRx's to do; that is the difference from a literal, whose width this stage chooses. What the operator tables admit was read off astx and IRx rather than off the Python grammar, and this turned up two disagreements with validation: - astx maps operators to specialized nodes through _BINARY_OP_TYPES, and has no entry for ast.FloorDiv or ast.Pow. An unmapped op_code does not raise; it stays a plain BinaryOp and reaches codegen as "not implemented yet". Validation accepts both operators, so the subset currently admits two things the backend cannot express. They are rejected here, with a test reading astx's table directly so ours cannot drift from it. - IRx implements three unary operators, "++", "--" and "!", and no negation. A unary plus needs no node, being the identity, and a negated literal is folded into a single negative literal, which is the only form a negative constant takes in Python. Negating anything else is rejected. The fold also closes the trap arxlang#107 flagged and left a failing test for: a range check applied to the magnitude alone would refuse -2147483648, whose magnitude is one larger than the i32 maximum. That test is flipped here, with a boundary partner confirming the fold widens what is accepted by exactly that one value. Comparisons stay unlowered. Validation accepts them, but they only mean something with the conditionals they belong to, so they lower with those. 251 tests, arxjit coverage 100% line and branch. Every operator verified through irx.analysis.api.analyze, and lowering verified on CPython 3.10, 3.11 and 3.14.
Member
|
@Jaskirat-s7 , can you please rebase your branch ? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second stage of the Sprint 3 lowering work, after #107 covered the function
shell. Adds parameter reads, arithmetic, and unary operators, so the wiki's
own example lowers end to end:
Operand types propagate: both sides of an operator are lowered at the expected
type, so a literal buried in an expression takes the width of its context
exactly as a returned one does. A variable read carries no type of its own,
because the prototype already declares it and reconciling it with its context
is IRx's to do. That is the deliberate difference from a literal, whose width
this stage chooses.
Two disagreements between validation and the backend
I read the operator vocabulary off astx and IRx rather than off the Python
grammar, which turned up two constructs the subset admits but the backend
cannot express:
//and**have no astx operator. astx maps op_codes to specializednodes through
_BINARY_OP_TYPES, which has no entry forast.FloorDivorast.Pow. An unmapped op_code does not raise: it stays a plainBinaryOpand reaches codegen as
Binary op ** not implemented yet. Validationaccepts both, so they are rejected here rather than lowered into a module
that cannot compile. A test reads astx's table directly so ours cannot
drift from it.
unary_ops.pyimplements++,--and!,and raises for anything else. A unary plus needs no node, being the
identity, and a negated literal is folded into one negative literal, which
is the only form a negative constant takes in Python. Negating anything
else is rejected.
Both are worth a decision beyond this PR: either validation should stop
accepting these, or astx/IRx should gain the operators. Rejecting at lowering
keeps them visible as diagnostics meanwhile, but the subset and the backend
disagreeing is not a good resting state. Happy to open an issue for whichever
direction you prefer.
The negative-literal trap from #107
Folding also closes the trap #107 flagged and deliberately left a failing test
for: a range check applied to the magnitude alone would refuse
-2147483648,whose magnitude is one larger than the i32 maximum. That test is flipped here,
with a boundary partner confirming the fold widens what is accepted by exactly
that one value and no further.
Scope
Comparisons stay unlowered. Validation accepts them, but they only mean
something alongside the conditionals they belong to, so they lower with those
in the next PR.
@jitstill does not call this stage; that wiring is the lastPR of the sprint.
251 tests, arxjit coverage 100% line and branch. Every operator verified
through
irx.analysis.api.analyze, and lowering verified on CPython 3.10,3.11 and 3.14.