Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 100 additions & 38 deletions src/v2/compiler/body_lowering_fold.dag
Original file line number Diff line number Diff line change
Expand Up @@ -811,10 +811,29 @@ fn body_lower_operand_ref_optional(node: Node) -> Optional<Node> {
}
}

fn body_lower_is_block_delimiter_token(id: Symbol) -> Bool {
(id == ^dag_token_lbrace) || (id == ^dag_token_rbrace)
}

fn body_lower_sequence_left_is_lbrace(captured: Node) -> Bool {
match sugar_sequence_pair_optional(
node: body_lower_unwrap_surface_shell(node: captured)
) {
Absent => false
Present { value: pair } =>
match node_atom_identity_optional(
node: body_lower_deep_unwrap_optional(node: pair.left)
) {
Present { value: id } => id == ^dag_token_lbrace
Absent => false
}
}
}

fn body_lower_operator_atom_optional(node: Node) -> Optional<Node> {
match node_atom_identity_optional(node: node) {
Present { value: id } =>
if dag_lex_token_symbol(sym: id) {
if dag_lex_token_symbol(sym: id) && !body_lower_is_block_delimiter_token(id: id) {
optional_present(
value: node_synthetic(
kind: TypeNode { connective: Atom { identity: id } },
Expand Down Expand Up @@ -1474,9 +1493,16 @@ fn body_lower_try_fold_behavior_optional(node: Node) -> Outcome<Optional<Node>>
}
}

// A brace-headed sequence is a block delimiter. This matcher must not
// claim it as a call or infix: those arms would mint Transform with `{`
// as operator and drop the interior. Absent here means not this strategy;
// every call site then walks the interior. `{` is also unwritable as an
// infix operator in body_lower_operator_atom_optional.
fn body_lower_try_body_lowered(node: Node) -> Outcome<Optional<Node>> {
if body_lower_is_core_substrate(node: node) {
outcome_accepted(value: optional_present(value: node))
} else if body_lower_sequence_left_is_lbrace(captured: node) {
outcome_accepted(value: optional_absent())
} else {
match body_lower_try_fold_behavior_optional(node: node) {
Rejected { diagnostics: r } => Rejected { diagnostics: r }
Expand Down Expand Up @@ -1832,50 +1858,54 @@ fn body_lower_body_subtree_lower(captured: Node) -> Outcome<Optional<Node>> {
}
}

fn body_lower_body_subtree_lower_rest(captured: Node) -> Outcome<Optional<Node>> {
match body_lower_try_body_lowered(node: captured) {
Rejected { diagnostics: r } => Rejected { diagnostics: r }
Accepted { value: found, diagnostics: _ } =>
match found {
Present { value: lowered } => outcome_accepted(value: optional_present(value: lowered))
Absent =>
match body_lower_find_captured(
root: captured,
emitted: ^dag_surface_if_expr
) {
ParseSubtreeFound { captured: if_capture } =>
body_lower_try_if_from_captured(captured: if_capture)
ParseSubtreeAbsent =>
match body_lower_find_captured(
root: captured,
emitted: ^dag_surface_match_expr
) {
ParseSubtreeFound { captured: match_capture } =>
body_lower_try_match_from_captured(captured: match_capture)
ParseSubtreeAbsent =>
fn body_lower_body_subtree_lower_control_forms(captured: Node) -> Outcome<Optional<Node>> {
match body_lower_find_captured(
root: captured,
emitted: ^dag_surface_if_expr
) {
ParseSubtreeFound { captured: if_capture } =>
body_lower_try_if_from_captured(captured: if_capture)
ParseSubtreeAbsent =>
match body_lower_find_captured(
root: captured,
emitted: ^dag_surface_match_expr
) {
ParseSubtreeFound { captured: match_capture } =>
body_lower_try_match_from_captured(captured: match_capture)
ParseSubtreeAbsent =>
match body_lower_find_captured(
root: captured,
emitted: ^dag_surface_loop_expr
) {
ParseSubtreeFound { captured: loop_capture } =>
body_lower_try_loop_expr_from_captured(captured: loop_capture)
ParseSubtreeAbsent =>
match body_lower_find_captured(
root: captured,
emitted: ^dag_surface_let_expr
) {
ParseSubtreeFound { captured: let_capture } =>
body_lower_try_let_in_from_captured(captured: let_capture)
ParseSubtreeAbsent =>
body_lower_body_subtree_lower_from_binary(captured: captured)
}
}
}
match body_lower_find_captured(
root: captured,
emitted: ^dag_surface_let_expr
) {
ParseSubtreeFound { captured: let_capture } =>
body_lower_try_let_in_from_captured(captured: let_capture)
ParseSubtreeAbsent =>
body_lower_body_subtree_lower_from_binary(captured: captured)
}
}
}
}
}

fn body_lower_body_subtree_lower_rest(captured: Node) -> Outcome<Optional<Node>> {
match body_lower_try_body_lowered(node: captured) {
Rejected { diagnostics: r } => Rejected { diagnostics: r }
Accepted { value: found, diagnostics: _ } =>
match found {
Present { value: lowered } =>
outcome_accepted(value: optional_present(value: lowered))
Absent => body_lower_body_subtree_lower_control_forms(captured: captured)
}
}
}

fn body_lower_node_is_eq_token(n: Node) -> Bool {
match node_atom_identity_optional(node: body_lower_deep_unwrap_optional(node: n)) {
Present { value: id } => id == ^dag_token_eq
Expand Down Expand Up @@ -2437,12 +2467,44 @@ fn body_lower_primary_call_suffix_optional(root: Node) -> Optional<Node> {
}
}

fn body_lower_try_primary_ident_call(node: Node) -> Outcome<Optional<Node>> {
fn body_lower_call_sequence_node(node: Node) -> Node {
let stripped = body_lower_unwrap_surface_shell(node: node)
match parse_production_emitted_identity_optional(node: stripped) {
Present { value: emitted } =>
if emitted == ^dag_surface_primary_expr {
match parse_production_captured_child_optional(node: stripped) {
Present { value: captured } => captured
Absent => stripped
}
} else {
stripped
}
Absent => stripped
}
}

fn body_lower_call_callee_optional(node: Node) -> Optional<Node> {
match body_lower_operand_ref_optional(node: node) {
Absent => optional_absent()
Present { value: callee } =>
match node_atom_identity_optional(node: callee) {
Present { value: id } =>
if dag_lex_token_symbol(sym: id) {
optional_absent()
} else {
optional_present(value: callee)
}
Absent => optional_present(value: callee)
}
}
}

fn body_lower_try_primary_ident_call(node: Node) -> Outcome<Optional<Node>> {
let stripped = body_lower_call_sequence_node(node: node)
match sugar_sequence_pair_optional(node: stripped) {
Absent => outcome_accepted(value: optional_absent())
Present { value: pair } =>
match body_lower_operand_ref_optional(node: pair.left) {
match body_lower_call_callee_optional(node: pair.left) {
Absent => outcome_accepted(value: optional_absent())
Present { value: callee_atom } =>
match body_lower_primary_call_suffix_optional(root: pair.right) {
Expand Down Expand Up @@ -4626,16 +4688,16 @@ fn body_lower_primary_expr(shell: Node) -> Outcome<Node> {
Present { value: loop_node } =>
Accepted { value: loop_node, diagnostics: ld }
Absent =>
match body_lower_pattern_first_atom_optional(node: captured) {
Present { value: atom } => outcome_accepted(value: atom)
Absent =>
match body_lower_try_primary_ident_call(node: captured) {
Rejected { diagnostics: r } => Rejected { diagnostics: r }
Accepted { value: primary_call, diagnostics: d } =>
match primary_call {
Present { value: transform } =>
Accepted { value: transform, diagnostics: d }
Absent =>
match body_lower_pattern_first_atom_optional(node: captured) {
Present { value: atom } => outcome_accepted(value: atom)
Absent =>
match body_lower_try_postfix_projection(node: captured) {
Rejected { diagnostics: r } =>
match body_lower_literal_bool_atom_optional(node: captured) {
Expand Down
98 changes: 98 additions & 0 deletions src/v2/test/claim/body_lowering_block_body_call_test.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
module v2.test.claim.body_lowering_block_body_call

import v2.compiler.normalize { normalize }
import v2.compiler.parse { parse_module_prepared }
import v2.compiler.program_assembly { dag_prepared_grammar }
import v2.compiler.tokenize { tokenize }
import v2.extdeps.languages.dag { dag_lex }
import v2.std.diagnostic { Accepted, Outcome, Rejected, bind_outcome }
import v2.std.grammar { node_atom_identity_optional }
import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly }
import v2.std.logic { Bool }
import v2.std.node { Node }
import v2.std.node_query {
call_callee_target,
find_arrow_body_child,
find_named_child,
node_is_call
}
import v2.std.optional { Absent, Present }

data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly

data body_lowering_block_call_source: String = "module wall.same\n\nfn leaf() -> Bool = true\n\nfn rollup() -> Bool {\n leaf()\n}\n"

fn body_lowering_block_call_parsed() -> Outcome<Node> {
match dag_prepared_grammar() {
Rejected { diagnostics: d } => Rejected { diagnostics: d }
Accepted { value: prepared, diagnostics: residue } =>
bind_outcome(
o: tokenize(
text: body_lowering_block_call_source,
file: ^body_lowering_block_call_file,
rules: dag_lex()
),
f: fn(token_stream) {
match parse_module_prepared(
tokens: token_stream,
prepared: prepared,
validation_residue: residue
) {
Rejected { diagnostics: r } => Rejected { diagnostics: r }
Accepted { value: artifact, diagnostics: d } =>
Accepted { value: artifact.tree, diagnostics: d }
}
}
)
}
}

test fn body_lowering_block_call_parses_holds() -> Bool {
match body_lowering_block_call_parsed() {
Accepted { value: _, diagnostics: _ } => true
Rejected { diagnostics: _ } => false
}
}

test fn body_lowering_block_body_call_reaches_arrow_body() -> Bool {
match body_lowering_block_call_parsed() {
Rejected { diagnostics: _ } => false
Accepted { value: parsed, diagnostics: _ } =>
match normalize(parse_tree: parsed) {
Rejected { diagnostics: _ } => false
Accepted { value: tree, diagnostics: _ } =>
match find_named_child(root: tree.root, name: ^grammar_production_captured_node_projection) {
Rejected { diagnostics: _ } => false
Accepted { value: captured, diagnostics: _ } =>
match find_named_child(root: captured, name: ^wall) {
Rejected { diagnostics: _ } => false
Accepted { value: wall_n, diagnostics: _ } =>
match find_named_child(root: wall_n, name: ^same) {
Rejected { diagnostics: _ } => false
Accepted { value: members, diagnostics: _ } =>
match find_named_child(root: members, name: ^rollup) {
Rejected { diagnostics: _ } => false
Accepted { value: rollup_member, diagnostics: _ } =>
match find_arrow_body_child(root: rollup_member) {
Rejected { diagnostics: _ } => false
Accepted { value: body, diagnostics: _ } =>
if node_is_call(node: body) {
match call_callee_target(node: body) {
Rejected { diagnostics: _ } => false
Accepted { value: callee, diagnostics: _ } =>
match node_atom_identity_optional(node: callee) {
Present { value: id } => id == ^leaf
Absent => false
}
}
} else {
false
}
}
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -383,15 +383,15 @@ test fn an_unbound_type_position_name_is_unresolvable_today() -> Bool {
}
}

test fn a_callee_name_is_absent_from_the_census_today() -> Bool {
test fn a_callee_name_reaches_the_census_holds() -> Bool {
match census_of(
path: call_only_path,
unit: ^xl3_call_only
) {
Present { value: census } =>
census_unreadable_roots_empty(census: census)
&& authored_is(census: census, spelling: "LocalParam")
&& !authored_is(census: census, spelling: "helper")
&& authored_is(census: census, spelling: "helper")
Absent => false
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,10 @@ test fn a_call_argument_mention_is_absent_from_the_denominator_today() -> Bool {
!sites_mention(sites: fixture_sites(), spelling: "xl0_call_only")
}

// MEASURED DEFICIENCY 2: the CALLEE name of a call does not reach the collector either, so the
// erasure is of the whole call expression rather than of its arguments alone.
test fn a_callee_name_is_absent_from_the_denominator_today() -> Bool {
!sites_mention(sites: fixture_sites(), spelling: "xl0_callee")
// The brace-body call lowering repair keeps the callee in the normalized tree, so the collector
// now sees it. The argument-only miss above is a separate class and stays asserted-absent.
test fn a_callee_name_reaches_the_denominator_holds() -> Bool {
sites_mention(sites: fixture_sites(), spelling: "xl0_callee")
}

// WHAT "Bool REACHES THE COLLECTOR" ACTUALLY MEASURES, AND IT IS NOT WHAT ITS FIRST NAME CLAIMED.
Expand Down
1 change: 1 addition & 0 deletions src/v2/workflow/floor_pure_producer_share.dag
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ data floor_cross_claim_pure_producers_warm: List<String> = [
"v2.test.parse.expression_bodied_fn_decl_parse.expression_bodied_fn_parsed",
"v2.test.parse.expression_bodied_fn_decl_parse.expression_bodied_literal_fn_parsed",
"v2.test.parse.expression_bodied_fn_decl_parse.braced_fn_control_parsed",
"v2.test.claim.body_lowering_block_body_call.body_lowering_block_call_parsed",
"v2.test.claim.namespace_xl0.call_argument_mention_survival.call_argument_fixture_normalized"
]

Expand Down
Loading