feat: null-safe navigation (a?.b) and null-coalescing (a ?? b) - #707
Open
killme2008 wants to merge 1 commit into
Open
feat: null-safe navigation (a?.b) and null-coalescing (a ?? b)#707killme2008 wants to merge 1 commit into
killme2008 wants to merge 1 commit into
Conversation
Implements issue #608. - Lexer folds `?.` into the variable lexeme, keeping a per-segment '?' marker (e.g. "a?.b" -> segments ["a?", "b"]). - Reflector short-circuits to null on a null intermediate value when the segment is marked null-safe, instead of throwing NPE. - Parser recognizes the right-associative, short-circuiting `??` operator and rejects assignment to a null-safe target. - All code generators (ASM, interpreter, optimize, lambda, none) emit the short-circuit for `??`; a new BranchIfNotNilIR backs the interpreter. - Public variable-name APIs strip the '?' marker ("a?.b" reported as "a.b"). Semantics follow JS/Groovy: each `?.` guards only its own segment; use `a?.b?.c` to guard the whole chain.
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.
Closes #608.
What
Adds two operators to AviatorScript:
a?.b— if the guarded value is null, the property navigation short-circuits tonilinstead of throwing.a ?? b— returnsawhen it is not null, otherwise evaluates and returnsb(right operand is strictly short-circuited).Semantics
Follows JS / Groovy: each
?.guards only its own segment.a?.b.cguardsaonly — ifa.bis null, navigating.cstill throws. Guard the whole chain witha?.b?.c.??only tests fornil; it does not catch exceptions. The right operand is not evaluated when the left is non-null.Design
?.adds no new runtime operator. The lexer foldsa?.binto a single variable token, normalizing the lexeme to keep a per-segment?marker (a?.b→ segments["a?", "b"]). This marker rides along the existing variable-name path all the way toReflector, soAviatorJavaTypeand both code generators need no constructor changes.Reflector.fastGetPropertystrips the?, and short-circuits to null on a null intermediate value only for marked segments.??is a parser-level short-circuiting operator (like&&/||), placed at ternary precedence and right-associative. All fiveCodeGeneratorimplementations emit the short-circuit; the interpreter uses a newBranchIfNotNilIR.OptimizeCodeGeneratorrecords/replays it via delegate tokens, avoiding a newOperatorType.Public
getVariableNames()/getVariableFullNames()strip the marker, soa?.bis reported asa.b. Assignment to a null-safe target (a?.b = 1) is a syntax error.Tests
NullSafeUnitTest+NullSafeInterpretUnitTestcover both eval modes (ASM + interpreter) and both optimize levels (EVAL + COMPILE): null root / mid-chain, unguarded null throws, Java-bean getters,??value/short-circuit/right-associativity, ternary regression, assignment rejection, and variable-name normalization. Full suite green (892 existing + new).Known limitations (follow-ups)
?.combined with dynamic or mid-chain array indexing (foo.bars[0]?.name) is not supported yet (syntax error).?:— its token collides with the existing ternary"?:";??covers the default-value use case.