Add if (var x = expr) and map[k].field op= rhs#19
Conversation
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
… and SPEC Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
…resence checks Signed-off-by: Cong Wang <cwang@multikernel.io>
00ad003 to
d5f25c1
Compare
1. Scoping Issue: Branch-Local Binding and ShadowingI have identified a high-risk scoping issue regarding the This approach appears to lose the then-branch-only scoping semantics, which is particularly problematic when Proposed Solutions:
2. Semantic Mismatch: Truthiness and Evaluation RulesThere appears to be a significant semantic mismatch in how This creates a discrepancy for values like Proposed Solutions:
|
Summary
Two new statement forms for ergonomic map access, plus the doc and test work pinning them down.
if (var x = expr) { ... } else { ... }— declaration-as-condition. Bindsxonly inside the truthy branch; the branch is taken iffexprproduces a present value (map hit, non-null pointer return). Lowers to a singlebpf_map_lookup_elemplus a null check; for struct-valued maps the body's field operations mutate the entry in place via the underlying lookup pointer (no manual write-back).m[k].field op= rhs— compound assignment on a struct-field of a map value. Lowers to a presence-checkedif (p) { p->field = p->field op rhs; }against the same single lookup. Absent entries are a no-op (no creation), distinguishing it from the existing scalarm[k] op= rhswhich creates on first use.Bundled deliverables:
examples/maps_demo.ksandexamples/map_operations_demo.ks: rewrite the read-modify-write blocks to use the new idiom (drops 13 LoC, removes redundant write-backs).README.md: replace the misleadinglookup_or_createsnippet with paired examples; add an "Ergonomic map idioms" bullet to the solution checklist.SPEC.md: new §6.2.5 (compound assignment with map indexing — scalar and struct-field forms with full semantics: LHS shape, type rules, presence/creation semantics, lowering shape), new §7.5.1.2 (declaration-as-condition with single-evaluation, scoping, and lowering);assignment_statementandif_statementEBNF productions expanded from the prior shorthand into the seven forms the parser actually implements. Also fixes the §6.2.3 example, which usedstats.field += 1on a value-boundstats— a shape the parser has never accepted.tests/test_iflet.ml(new): 10 tests across parse, type-check, and codegen-string layers — covers struct/scalar bindings, else,else if (var ...)chains, binding-leak rejections (then-branch only), and the in-place-mutation codegen shape.tests/test_compound_index_assignment.ml: extend the Phase 2 test with a codegen-string check pinning the synthetic-pointer-binding path that the codegen-fix in this PR repaired (verified by temporarily reverting the fix — test flips red on "synthetic binding does NOT use deref-load init").84 alcotest suites pass (was 83); the new
test_ifletsuite is the +1.Test plan
eval \$(opam env) && dune build && dune runtest --force— 84 suites greencd /tmp && cp <example>.ks . && kernelscript compile <example>.ks -o out && cd out && make— example end-to-end build formaps_demo.ks(clean) and a minimalm[k].field += 1source (clean)bpf_map_lookup_elemhappens once, presence is checked againstNULL, and the mutation isptr->field = ...tests/test_iflet.ml::codegen_struct_value_binding_shape)🤖 Generated with Claude Code