Skip to content

Commit 2f8490b

Browse files
committed
Get more tests working
1 parent 8532296 commit 2f8490b

14 files changed

Lines changed: 6253 additions & 6317 deletions

File tree

meta/src/meta/codegen_templates.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class BuiltinTemplate:
108108
"get_at": BuiltinTemplate("{0}[{1}]"),
109109
# Provenance tracking
110110
"span_start": BuiltinTemplate("self.span_start()"),
111-
"record_span": BuiltinTemplate("None", ["self.record_span({0})"]),
111+
"record_span": BuiltinTemplate("None", ["self.record_span({0}, {1})"]),
112112
}
113113

114114

@@ -196,7 +196,7 @@ class BuiltinTemplate:
196196
"get_at": BuiltinTemplate("{0}[{1} + 1]"),
197197
# Provenance tracking
198198
"span_start": BuiltinTemplate("span_start(parser)"),
199-
"record_span": BuiltinTemplate("nothing", ["record_span!(parser, {0})"]),
199+
"record_span": BuiltinTemplate("nothing", ["record_span!(parser, {0}, {1})"]),
200200
}
201201

202202

@@ -288,7 +288,7 @@ class BuiltinTemplate:
288288
"get_at": BuiltinTemplate("{0}[{1}]"),
289289
# Provenance tracking
290290
"span_start": BuiltinTemplate("int64(p.spanStart())"),
291-
"record_span": BuiltinTemplate("nil", ["p.recordSpan(int({0}))"]),
291+
"record_span": BuiltinTemplate("nil", ["p.recordSpan(int({0}), {1})"]),
292292
}
293293

294294
__all__ = [

meta/src/meta/parser_gen.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
ListExpr,
102102
ListType,
103103
Lit,
104+
MessageType,
104105
ParseNonterminal,
105106
ParseNonterminalDef,
106107
Seq,
@@ -150,6 +151,7 @@ def _wrap_with_span(body: TargetExpr, return_type) -> TargetExpr:
150151
"""Wrap a nonterminal body with span_start/record_span."""
151152
span_var = Var(gensym("span_start"), BaseType("Int64"))
152153
result_var = Var(gensym("result"), return_type)
154+
type_name = return_type.name if isinstance(return_type, MessageType) else ""
153155
return Let(
154156
span_var,
155157
Call(make_builtin("span_start"), []),
@@ -158,7 +160,7 @@ def _wrap_with_span(body: TargetExpr, return_type) -> TargetExpr:
158160
body,
159161
Seq(
160162
[
161-
Call(make_builtin("record_span"), [span_var]),
163+
Call(make_builtin("record_span"), [span_var, Lit(type_name)]),
162164
result_var,
163165
]
164166
),
@@ -220,7 +222,8 @@ def _generate_parse_method(
220222
)
221223
rhs = Let(Var(prediction, BaseType("Int64")), predictor, tail)
222224
assert return_type is not None
223-
rhs = _wrap_with_span(rhs, return_type)
225+
if isinstance(return_type, MessageType):
226+
rhs = _wrap_with_span(rhs, return_type)
224227
return ParseNonterminalDef(lhs, [], return_type, rhs, indent)
225228

226229

meta/src/meta/target_builtins.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def is_builtin(name: str) -> bool:
251251

252252
# === Provenance tracking ===
253253
register_builtin("span_start", [], INT64)
254-
register_builtin("record_span", [INT64], VOID)
254+
register_builtin("record_span", [INT64, STRING], VOID)
255255

256256

257257
# === Validation functions ===

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

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ type Location struct {{
3131

3232
// Span represents a source span from start to stop location.
3333
type Span struct {{
34-
Start Location
35-
Stop Location
34+
Start Location
35+
Stop Location
36+
TypeName string
3637
}}
3738

3839
// ParseError represents a parse error
@@ -329,7 +330,7 @@ type Parser struct {{
329330
pos int
330331
idToDebugInfo map[string]map[relationIdKey]string
331332
currentFragmentID []byte
332-
Provenance map[string]Span
333+
Provenance map[int]Span
333334
lineStarts []int
334335
}}
335336

@@ -340,7 +341,7 @@ func NewParser(tokens []Token, input string) *Parser {{
340341
pos: 0,
341342
idToDebugInfo: make(map[string]map[relationIdKey]string),
342343
currentFragmentID: nil,
343-
Provenance: make(map[string]Span),
344+
Provenance: make(map[int]Span),
344345
lineStarts: computeLineStarts(input),
345346
}}
346347
}}
@@ -364,16 +365,22 @@ func (p *Parser) spanStart() int {{
364365
return p.lookahead(0).StartPos
365366
}}
366367

367-
func (p *Parser) recordSpan(startOffset int) {{
368+
func (p *Parser) recordSpan(startOffset int, typeName string) {{
369+
// First-wins: innermost parse function records first; outer wrappers
370+
// that share the same offset do not overwrite.
371+
if _, exists := p.Provenance[startOffset]; exists {{
372+
return
373+
}}
368374
endOffset := startOffset
369375
if p.pos > 0 {{
370376
endOffset = p.tokens[p.pos-1].EndPos
371377
}}
372378
s := Span{{
373-
Start: p.makeLocation(startOffset),
374-
Stop: p.makeLocation(endOffset),
379+
Start: p.makeLocation(startOffset),
380+
Stop: p.makeLocation(endOffset),
381+
TypeName: typeName,
375382
}}
376-
p.Provenance[""] = s
383+
p.Provenance[startOffset] = s
377384
}}
378385

379386
func (p *Parser) lookahead(k int) Token {{
@@ -565,7 +572,7 @@ func toPascalCase(s string) string {{
565572
{parse_nonterminal_defns}
566573

567574
// Parse parses the input string and returns (result, provenance, error).
568-
func Parse(input string) (result *pb.Transaction, provenance map[string]Span, err error) {{
575+
func Parse(input string) (result *pb.Transaction, provenance map[int]Span, err error) {{
569576
defer func() {{
570577
if r := recover(); r != nil {{
571578
if pe, ok := r.(ParseError); ok {{

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ end
3737
struct Span
3838
start::Location
3939
stop::Location
40+
type_name::String
4041
end
4142

4243
struct Token
@@ -189,7 +190,7 @@ mutable struct ParserState
189190
id_to_debuginfo::Dict{{Vector{{UInt8}},Vector{{Pair{{Tuple{{UInt64,UInt64}},String}}}}}}
190191
_current_fragment_id::Union{{Nothing,Vector{{UInt8}}}}
191192
_relation_id_to_name::Dict{{Tuple{{UInt64,UInt64}},String}}
192-
provenance::Dict{{Tuple{{Vararg{{Int}}}},Span}}
193+
provenance::Dict{{Int,Span}}
193194
_line_starts::Vector{{Int}}
194195

195196
function ParserState(tokens::Vector{{Token}}, input_str::String)
@@ -208,14 +209,17 @@ function span_start(parser::ParserState)::Int
208209
return lookahead(parser, 0).start_pos
209210
end
210211

211-
function record_span!(parser::ParserState, start_offset::Int)
212+
function record_span!(parser::ParserState, start_offset::Int, type_name::String="")
213+
# First-wins: innermost parse function records first; outer wrappers
214+
# that share the same offset do not overwrite.
215+
haskey(parser.provenance, start_offset) && return nothing
212216
if parser.pos > 1
213217
end_offset = parser.tokens[parser.pos - 1].end_pos
214218
else
215219
end_offset = start_offset
216220
end
217-
s = Span(_make_location(parser, start_offset), _make_location(parser, end_offset))
218-
parser.provenance[tuple()] = s
221+
s = Span(_make_location(parser, start_offset), _make_location(parser, end_offset), type_name)
222+
parser.provenance[start_offset] = s
219223
return nothing
220224
end
221225

meta/src/meta/templates/parser.py.template

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,12 @@ class Location:
4848
class Span:
4949
"""Source span from start to stop location."""
5050

51-
__slots__ = ("start", "stop")
51+
__slots__ = ("start", "stop", "type_name")
5252

53-
def __init__(self, start: Location, stop: Location):
53+
def __init__(self, start: Location, stop: Location, type_name: str = ""):
5454
self.start = start
5555
self.stop = stop
56+
self.type_name = type_name
5657

5758
def __repr__(self) -> str:
5859
return f"Span({{self.start}}, {{self.stop}})"
@@ -217,7 +218,7 @@ class Parser:
217218
self.id_to_debuginfo = {{}}
218219
self._current_fragment_id: bytes | None = None
219220
self._relation_id_to_name = {{}}
220-
self.provenance: dict[tuple[int, ...], Span] = {{}}
221+
self.provenance: dict[int, Span] = {{}}
221222
self._line_starts = _compute_line_starts(input_str)
222223

223224
def _make_location(self, offset: int) -> Location:
@@ -230,14 +231,20 @@ class Parser:
230231
"""Return the start offset of the current token."""
231232
return self.lookahead(0).start_pos
232233

233-
def record_span(self, start_offset: int) -> None:
234-
"""Record a span from start_offset to the previous token's end."""
234+
def record_span(self, start_offset: int, type_name: str = "") -> None:
235+
"""Record a span from start_offset to the previous token's end.
236+
237+
Uses first-wins semantics: the innermost parse function records first,
238+
and outer wrappers that share the same offset do not overwrite.
239+
"""
240+
if start_offset in self.provenance:
241+
return
235242
if self.pos > 0:
236243
end_offset = self.tokens[self.pos - 1].end_pos
237244
else:
238245
end_offset = start_offset
239-
span = Span(self._make_location(start_offset), self._make_location(end_offset))
240-
self.provenance[tuple()] = span
246+
span = Span(self._make_location(start_offset), self._make_location(end_offset), type_name)
247+
self.provenance[start_offset] = span
241248

242249
def lookahead(self, k: int = 0) -> Token:
243250
"""Get lookahead token at offset k."""
@@ -349,7 +356,7 @@ class Parser:
349356
# --- Parse methods ---
350357
{parse_nonterminal_defns}
351358

352-
def parse(input_str: str) -> tuple[Any, dict[tuple[int, ...], Span]]:
359+
def parse(input_str: str) -> tuple[Any, dict[int, Span]]:
353360
"""Parse input string and return (result, provenance) tuple."""
354361
lexer = Lexer(input_str)
355362
parser = Parser(lexer.tokens, input_str)

0 commit comments

Comments
 (0)