Skip to content

Commit 8532296

Browse files
committed
Change the identity-based dict
1 parent 47bf5b9 commit 8532296

18 files changed

Lines changed: 6366 additions & 8224 deletions

meta/src/meta/codegen_templates.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,6 @@ class BuiltinTemplate:
107107
"pp_dispatch": BuiltinTemplate("None", ["self.pprint_dispatch({0})"]),
108108
"get_at": BuiltinTemplate("{0}[{1}]"),
109109
# Provenance tracking
110-
"push_path": BuiltinTemplate("None", ["self.push_path({0})"]),
111-
"pop_path": BuiltinTemplate("None", ["self.pop_path()"]),
112110
"span_start": BuiltinTemplate("self.span_start()"),
113111
"record_span": BuiltinTemplate("None", ["self.record_span({0})"]),
114112
}
@@ -197,8 +195,6 @@ class BuiltinTemplate:
197195
"pp_dispatch": BuiltinTemplate("nothing", ["_pprint_dispatch(pp, {0})"]),
198196
"get_at": BuiltinTemplate("{0}[{1} + 1]"),
199197
# Provenance tracking
200-
"push_path": BuiltinTemplate("nothing", ["push_path!(parser, {0})"]),
201-
"pop_path": BuiltinTemplate("nothing", ["pop_path!(parser)"]),
202198
"span_start": BuiltinTemplate("span_start(parser)"),
203199
"record_span": BuiltinTemplate("nothing", ["record_span!(parser, {0})"]),
204200
}
@@ -291,8 +287,6 @@ class BuiltinTemplate:
291287
"pp_dispatch": BuiltinTemplate("nil", ["p.pprintDispatch({0})"]),
292288
"get_at": BuiltinTemplate("{0}[{1}]"),
293289
# Provenance tracking
294-
"push_path": BuiltinTemplate("nil", ["p.pushPath(int({0}))"]),
295-
"pop_path": BuiltinTemplate("nil", ["p.popPath()"]),
296290
"span_start": BuiltinTemplate("int64(p.spanStart())"),
297291
"record_span": BuiltinTemplate("nil", ["p.recordSpan(int({0}))"]),
298292
}

meta/src/meta/parser_gen.py

Lines changed: 2 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
Terminal,
9191
)
9292
from .grammar_utils import is_epsilon, rhs_elements
93-
from .proto_ast import ProtoField, ProtoMessage
93+
from .proto_ast import ProtoMessage
9494
from .target import (
9595
Assign,
9696
BaseType,
@@ -101,8 +101,6 @@
101101
ListExpr,
102102
ListType,
103103
Lit,
104-
NewMessage,
105-
OneOf,
106104
ParseNonterminal,
107105
ParseNonterminalDef,
108106
Seq,
@@ -134,105 +132,6 @@ class AmbiguousGrammarError(Exception):
134132
pass
135133

136134

137-
def _proto_fields_by_name(
138-
proto_messages: dict[tuple[str, str], ProtoMessage] | None,
139-
module: str,
140-
name: str,
141-
) -> dict[str, ProtoField]:
142-
"""Return a name->ProtoField map for a proto message, or {} if not found."""
143-
if proto_messages is None:
144-
return {}
145-
proto_msg = proto_messages.get((module, name))
146-
if proto_msg is None:
147-
return {}
148-
result: dict[str, ProtoField] = {}
149-
for f in proto_msg.fields:
150-
result[f.name] = f
151-
for oneof in proto_msg.oneofs:
152-
for f in oneof.fields:
153-
result[f.name] = f
154-
return result
155-
156-
157-
def _build_param_proto_fields(
158-
action: Lambda,
159-
proto_messages: dict[tuple[str, str], ProtoMessage] | None,
160-
) -> dict[int, ProtoField]:
161-
"""Map lambda parameter indices to protobuf ProtoField descriptors.
162-
163-
Inspects the semantic action's body. When it is a NewMessage, cross-references
164-
field names with proto_messages to find proto fields.
165-
166-
As a fallback, when the action's return type is a known proto message,
167-
matches parameter names to proto field names.
168-
169-
Returns dict mapping parameter index to ProtoField.
170-
"""
171-
if proto_messages is None:
172-
return {}
173-
body = action.body
174-
if isinstance(body, NewMessage):
175-
fields_by_name = _proto_fields_by_name(proto_messages, body.module, body.name)
176-
if not fields_by_name:
177-
return {}
178-
param_names = [p.name for p in action.params]
179-
result: dict[int, ProtoField] = {}
180-
for field_name, field_expr in body.fields:
181-
pf = fields_by_name.get(field_name)
182-
if pf is None:
183-
continue
184-
param_name = _extract_param_name(field_expr, param_names)
185-
if param_name is not None and param_name in param_names:
186-
param_idx = param_names.index(param_name)
187-
result.setdefault(param_idx, pf)
188-
return result
189-
# Fallback: match parameter names against the return type's proto fields.
190-
return _build_param_proto_fields_by_return_type(action, proto_messages)
191-
192-
193-
def _build_param_proto_fields_by_return_type(
194-
action: Lambda,
195-
proto_messages: dict[tuple[str, str], ProtoMessage] | None,
196-
) -> dict[int, ProtoField]:
197-
"""Fallback: match parameter names to proto fields via the return type."""
198-
from .target import MessageType
199-
200-
if proto_messages is None:
201-
return {}
202-
rt = action.return_type
203-
if not isinstance(rt, MessageType):
204-
return {}
205-
fields_by_name = _proto_fields_by_name(proto_messages, rt.module, rt.name)
206-
if not fields_by_name:
207-
return {}
208-
result: dict[int, ProtoField] = {}
209-
for i, param in enumerate(action.params):
210-
pf = fields_by_name.get(param.name)
211-
if pf is not None:
212-
result[i] = pf
213-
return result
214-
215-
216-
def _extract_param_name(expr: TargetExpr, param_names: list[str]) -> str | None:
217-
"""Extract the parameter name from a field expression.
218-
219-
Handles:
220-
- Direct Var reference
221-
- Call(OneOf(...), [Var(...)]) wrapper
222-
- Call(Builtin(...), [Var(...), ...]) e.g. unwrap_option_or
223-
"""
224-
from .target import Builtin
225-
226-
if isinstance(expr, Var) and expr.name in param_names:
227-
return expr.name
228-
if isinstance(expr, Call):
229-
if isinstance(expr.func, OneOf) and expr.args:
230-
return _extract_param_name(expr.args[0], param_names)
231-
if isinstance(expr.func, Builtin) and expr.args:
232-
return _extract_param_name(expr.args[0], param_names)
233-
return None
234-
235-
236135
def generate_parse_functions(
237136
grammar: Grammar,
238137
indent: str = "",
@@ -544,15 +443,6 @@ def _generate_parse_rhs_ir(
544443
return Seq([parse_expr, apply_lambda(action, [])])
545444
var_name = gensym(action.params[0].name)
546445
var = Var(var_name, rhs.target_type())
547-
# Wrap with push_path when the action maps this param to a proto
548-
# field (e.g., oneof dispatch: formula -> atom pushes the atom
549-
# field number onto the provenance path).
550-
if proto_messages is not None:
551-
pf = _build_param_proto_fields(action, proto_messages).get(0)
552-
if pf is not None:
553-
stmts = _wrap_with_path(pf.number, var, parse_expr)
554-
stmts.append(apply_lambda(action, [var]))
555-
return Seq(stmts)
556446
return Let(var, parse_expr, apply_lambda(action, [var]))
557447
return parse_expr
558448
elif isinstance(rhs, Option):
@@ -587,15 +477,6 @@ def _generate_parse_rhs_ir(
587477
raise NotImplementedError(f"Unsupported Rhs type: {type(rhs)}")
588478

589479

590-
def _wrap_with_path(field_num: int, var: Var, inner: TargetExpr) -> list[TargetExpr]:
591-
"""Return statements that push path, assign inner to var, then pop path."""
592-
return [
593-
Call(make_builtin("push_path"), [Lit(field_num)]),
594-
Assign(var, inner),
595-
Call(make_builtin("pop_path"), []),
596-
]
597-
598-
599480
def _generate_parse_rhs_ir_sequence(
600481
rhs: Sequence,
601482
grammar: Grammar,
@@ -607,11 +488,6 @@ def _generate_parse_rhs_ir_sequence(
607488
if is_epsilon(rhs):
608489
return Lit(None)
609490

610-
# Compute param->proto field mapping for provenance
611-
param_proto_fields: dict[int, ProtoField] = {}
612-
if action is not None and proto_messages is not None:
613-
param_proto_fields = _build_param_proto_fields(action, proto_messages)
614-
615491
exprs = []
616492
arg_vars = []
617493
elems = list(rhs_elements(rhs))
@@ -639,25 +515,7 @@ def _generate_parse_rhs_ir_sequence(
639515
)
640516
var_name = gensym("arg")
641517
var = Var(var_name, elem.target_type())
642-
pf = param_proto_fields.get(non_literal_count)
643-
if pf is not None and pf.is_repeated and isinstance(elem, Star):
644-
# Repeated proto field parsed as a Star: push field number
645-
# around the whole loop and push/pop an index per element.
646-
stmts = _wrap_star_with_index_path(
647-
elem, var, grammar, follow_set_i, pf.number, proto_messages
648-
)
649-
exprs.extend(stmts)
650-
elif isinstance(elem, Star) and proto_messages is not None:
651-
# Star without a repeated proto field (helper rule): still
652-
# push/pop an index per element for provenance.
653-
stmts = _wrap_star_with_index_path(
654-
elem, var, grammar, follow_set_i, None, proto_messages
655-
)
656-
exprs.extend(stmts)
657-
elif pf is not None:
658-
exprs.extend(_wrap_with_path(pf.number, var, elem_ir))
659-
else:
660-
exprs.append(Assign(var, elem_ir))
518+
exprs.append(Assign(var, elem_ir))
661519
arg_vars.append(var)
662520
non_literal_count += 1
663521
if apply_action and action:
@@ -674,55 +532,3 @@ def _generate_parse_rhs_ir_sequence(
674532
return exprs[0]
675533
else:
676534
return Seq(exprs)
677-
678-
679-
def _wrap_star_with_index_path(
680-
star: Star,
681-
result_var: Var,
682-
grammar: Grammar,
683-
follow_set: TerminalSequenceSet,
684-
field_num: int | None,
685-
proto_messages: dict[tuple[str, str], ProtoMessage] | None = None,
686-
) -> list[TargetExpr]:
687-
"""Return statements for a Star loop with push_path(index)/pop_path()
688-
around each element. When field_num is provided, the entire loop is
689-
also wrapped with push_path(field_num)/pop_path().
690-
Assigns the resulting list to result_var."""
691-
xs = Var(gensym("xs"), ListType(star.rhs.target_type()))
692-
cond = Var(gensym("cond"), BaseType("Boolean"))
693-
idx = Var(gensym("idx"), BaseType("Int64"))
694-
predictor = _build_option_predictor(grammar, star.rhs, follow_set)
695-
parse_item = _generate_parse_rhs_ir(
696-
star.rhs, grammar, follow_set, False, None, proto_messages
697-
)
698-
item = Var(gensym("item"), star.rhs.target_type())
699-
loop_body = Seq(
700-
[
701-
Call(make_builtin("push_path"), [idx]),
702-
Assign(item, parse_item),
703-
Call(make_builtin("pop_path"), []),
704-
Call(make_builtin("list_push"), [xs, item]),
705-
Assign(idx, Call(make_builtin("add"), [idx, Lit(1)])),
706-
Assign(cond, predictor),
707-
]
708-
)
709-
inner = Let(
710-
xs,
711-
ListExpr([], star.rhs.target_type()),
712-
Let(
713-
cond,
714-
predictor,
715-
Let(
716-
idx,
717-
Lit(0),
718-
Seq([While(cond, loop_body), xs]),
719-
),
720-
),
721-
)
722-
if field_num is not None:
723-
return [
724-
Call(make_builtin("push_path"), [Lit(field_num)]),
725-
Assign(result_var, inner),
726-
Call(make_builtin("pop_path"), []),
727-
]
728-
return [Assign(result_var, inner)]

meta/src/meta/target_builtins.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,6 @@ def is_builtin(name: str) -> bool:
250250
register_builtin("get_at", [SequenceType(T), INT64], T)
251251

252252
# === Provenance tracking ===
253-
register_builtin("push_path", [INT64], VOID)
254-
register_builtin("pop_path", [], VOID)
255253
register_builtin("span_start", [], INT64)
256254
register_builtin("record_span", [INT64], VOID)
257255

meta/src/meta/templates/parser.go.template

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,6 @@ type Parser struct {{
330330
idToDebugInfo map[string]map[relationIdKey]string
331331
currentFragmentID []byte
332332
Provenance map[string]Span
333-
path []int
334333
lineStarts []int
335334
}}
336335

@@ -342,7 +341,6 @@ func NewParser(tokens []Token, input string) *Parser {{
342341
idToDebugInfo: make(map[string]map[relationIdKey]string),
343342
currentFragmentID: nil,
344343
Provenance: make(map[string]Span),
345-
path: nil,
346344
lineStarts: computeLineStarts(input),
347345
}}
348346
}}
@@ -362,14 +360,6 @@ func (p *Parser) makeLocation(offset int) Location {{
362360
return Location{{Line: lineIdx + 1, Column: col + 1, Offset: offset}}
363361
}}
364362

365-
func (p *Parser) pushPath(n int) {{
366-
p.path = append(p.path, n)
367-
}}
368-
369-
func (p *Parser) popPath() {{
370-
p.path = p.path[:len(p.path)-1]
371-
}}
372-
373363
func (p *Parser) spanStart() int {{
374364
return p.lookahead(0).StartPos
375365
}}
@@ -383,15 +373,7 @@ func (p *Parser) recordSpan(startOffset int) {{
383373
Start: p.makeLocation(startOffset),
384374
Stop: p.makeLocation(endOffset),
385375
}}
386-
// Build comma-separated path key
387-
key := ""
388-
for i, v := range p.path {{
389-
if i > 0 {{
390-
key += ","
391-
}}
392-
key += fmt.Sprintf("%d", v)
393-
}}
394-
p.Provenance[key] = s
376+
p.Provenance[""] = s
395377
}}
396378

397379
func (p *Parser) lookahead(k int) Token {{

meta/src/meta/templates/parser.jl.template

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,10 @@ mutable struct ParserState
190190
_current_fragment_id::Union{{Nothing,Vector{{UInt8}}}}
191191
_relation_id_to_name::Dict{{Tuple{{UInt64,UInt64}},String}}
192192
provenance::Dict{{Tuple{{Vararg{{Int}}}},Span}}
193-
_path::Vector{{Int}}
194193
_line_starts::Vector{{Int}}
195194

196195
function ParserState(tokens::Vector{{Token}}, input_str::String)
197-
return new(tokens, 1, Dict(), nothing, Dict(), Dict(), Int[], _compute_line_starts(input_str))
196+
return new(tokens, 1, Dict(), nothing, Dict(), Dict(), _compute_line_starts(input_str))
198197
end
199198
end
200199

@@ -205,16 +204,6 @@ function _make_location(parser::ParserState, offset::Int)::Location
205204
return Location(line_idx, col + 1, offset)
206205
end
207206

208-
function push_path!(parser::ParserState, n::Int)
209-
push!(parser._path, n)
210-
return nothing
211-
end
212-
213-
function pop_path!(parser::ParserState)
214-
pop!(parser._path)
215-
return nothing
216-
end
217-
218207
function span_start(parser::ParserState)::Int
219208
return lookahead(parser, 0).start_pos
220209
end
@@ -226,7 +215,7 @@ function record_span!(parser::ParserState, start_offset::Int)
226215
end_offset = start_offset
227216
end
228217
s = Span(_make_location(parser, start_offset), _make_location(parser, end_offset))
229-
parser.provenance[Tuple(parser._path)] = s
218+
parser.provenance[tuple()] = s
230219
return nothing
231220
end
232221

0 commit comments

Comments
 (0)