Skip to content

Commit afebe4b

Browse files
committed
wip
1 parent b13017a commit afebe4b

File tree

173 files changed

+1960
-2092
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

173 files changed

+1960
-2092
lines changed

src/fmt/fmt2.zig

Lines changed: 109 additions & 434 deletions
Large diffs are not rendered by default.

src/parse/AST2.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ pub fn binOp(self: *const Ast, idx: Node.Idx) collections.NodeSlices(Node.Idx).B
237237

238238
/// Special accessor for arrow nodes which may have multiple parameters
239239
/// Returns the first parameter and return type as a BinOp for compatibility
240-
pub fn arrowBinOp(self: *const Ast, idx: Node.Idx) collections.NodeSlices(Node.Idx).BinOp {
240+
fn arrowBinOp(self: *const Ast, idx: Node.Idx) collections.NodeSlices(Node.Idx).BinOp {
241241
const node_tag = self.tag(idx);
242242
std.debug.assert(node_tag == .binop_thin_arrow or node_tag == .binop_thick_arrow);
243243

@@ -275,7 +275,7 @@ pub fn arrowBinOp(self: *const Ast, idx: Node.Idx) collections.NodeSlices(Node.I
275275

276276
/// Returns an iterator over all parameters and return type of an arrow node
277277
/// The last node in the iteration is the return type, all others are parameters
278-
pub fn arrowNodes(self: *const Ast, idx: Node.Idx) collections.NodeSlices(Node.Idx).Iterator {
278+
fn arrowNodes(self: *const Ast, idx: Node.Idx) collections.NodeSlices(Node.Idx).Iterator {
279279
const node_tag = self.tag(idx);
280280
std.debug.assert(node_tag == .binop_thin_arrow or node_tag == .binop_thick_arrow);
281281

@@ -291,15 +291,15 @@ pub fn arrowNodes(self: *const Ast, idx: Node.Idx) collections.NodeSlices(Node.I
291291
}
292292

293293
/// Given the idx to a lambda, return the region of just its args (the `| ... |` including the pipes)
294-
pub fn lambdaArgsRegion(self: *const Ast, idx: Node.Idx) Region {
294+
fn lambdaArgsRegion(self: *const Ast, idx: Node.Idx) Region {
295295
// This function returns the region of lambda args
296296
// Since we now store complete regions, just return the lambda's region
297297
// This function isn't actually used anywhere in the codebase
298298
return self.getRegion(idx);
299299
}
300300

301301
/// Given the idx to a BinOp, return the region of just its symbol (e.g. "*" or "==") etc.
302-
pub fn binOpSymbolRegion(self: *const Ast, idx: Node.Idx) Region {
302+
fn binOpSymbolRegion(self: *const Ast, idx: Node.Idx) Region {
303303
const binop = self.binOp(idx);
304304

305305
// To find the binop symbol itself, we scan from lhs_end to either rhs_start or first whitespace.

src/parse/Parser2.zig

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,15 @@ const Ident = base.Ident;
2424
const MAX_PARSE_DIAGNOSTICS: usize = 1_000;
2525
const MAX_PARSE_STACK_SIZE: usize = 10_000;
2626

27-
/// Temporary helper to create a Region from start and end positions
28-
/// TODO: Update all callers to compute proper end positions
27+
/// Helper to create a Region from start and end positions
2928
fn makeRegion(start: Position, end: Position) Region {
29+
// In debug mode, catch bugs where end is before start
30+
if (std.debug.runtime_safety) {
31+
if (end.offset < start.offset) {
32+
std.debug.print("makeRegion error: end.offset ({}) < start.offset ({})\n", .{ end.offset, start.offset });
33+
std.debug.assert(end.offset >= start.offset);
34+
}
35+
}
3036
return Region{ .start = start, .end = end };
3137
}
3238

@@ -564,7 +570,7 @@ fn parseModuleApply(self: *Parser) Error!Node.Idx {
564570
close_paren_region = self.currentRegion();
565571
self.advance();
566572
} else {
567-
// Use last position as approximation
573+
// Use current position for missing close paren
568574
close_paren_region = makeRegion(self.currentPosition(), self.currentPosition());
569575
}
570576

@@ -689,12 +695,15 @@ pub fn pushMalformed(self: *Parser, tag: AST.Diagnostic.Tag, start_pos: Position
689695
}
690696
} else start_pos;
691697

692-
const end_pos = self.currentPosition();
698+
var end_pos = self.currentPosition();
693699

694700
if (self.peek() != .EndOfFile) {
695701
self.advance();
702+
end_pos = self.currentPosition();
696703
}
697704

705+
std.debug.assert(end_pos.offset >= actual_start_pos.offset);
706+
698707
// Only add diagnostics if we haven't hit the limit
699708
if (self.diagnostics.items.len < MAX_PARSE_DIAGNOSTICS) {
700709
try self.pushDiagnostic(tag, actual_start_pos, end_pos);
@@ -860,6 +869,7 @@ fn parseAppHeader(self: *Parser, start_pos: Position) Error!AST.Header {
860869
self.advance(); // consume 'platform' keyword
861870

862871
// Parse provides list after platform keyword
872+
const provides_start = self.currentPosition();
863873
self.expect(.OpenSquare) catch {
864874
try self.pushDiagnostic(.header_expected_open_square, field_start, self.currentPosition());
865875
continue;
@@ -872,8 +882,7 @@ fn parseAppHeader(self: *Parser, start_pos: Position) Error!AST.Header {
872882
};
873883

874884
// Create the provides list node (use block as a container for the exposed items)
875-
// The region for the provides list spans from the current position to the last exposed item
876-
const provides_start = self.currentPosition();
885+
// The region for the provides list spans from the start to the last exposed item
877886
const provides_region = if (provides_idx != @as(collections.NodeSlices(Node.Idx).Idx, @enumFromInt(0))) blk: {
878887
// Get the region of the provides list (should have items)
879888
var iter = self.ast.node_slices.nodes(&provides_idx);
@@ -885,9 +894,15 @@ fn parseAppHeader(self: *Parser, start_pos: Position) Error!AST.Header {
885894
const last_region = self.ast.nodes.fieldItem(.region, @as(collections.SafeMultiList(Node).Idx, @enumFromInt(@intFromEnum(last))));
886895
break :blk makeRegion(provides_start, last_region.end);
887896
} else {
888-
break :blk makeRegion(provides_start, provides_start);
897+
// Empty list, use current position for end
898+
const end_pos = self.currentPosition();
899+
break :blk makeRegion(provides_start, end_pos);
889900
}
890-
} else makeRegion(provides_start, provides_start);
901+
} else blk: {
902+
// No items, use current position for end
903+
const end_pos = self.currentPosition();
904+
break :blk makeRegion(provides_start, end_pos);
905+
};
891906
const provides_node = try self.ast.appendNode(self.gpa, provides_region, .block, .{ .nodes = provides_idx });
892907

893908
// Create the platform binop: string_value platform provides_node
@@ -1850,7 +1865,7 @@ fn parseListLiteral(self: *Parser) Error!Node.Idx {
18501865
self.advance();
18511866
} else {
18521867
try self.pushDiagnostic(.expected_expr_close_square_or_comma, start_pos, self.currentPosition());
1853-
// Use the current position as an approximation for error recovery
1868+
// Use current position for missing close bracket
18541869
close_bracket_region = makeRegion(self.currentPosition(), self.currentPosition());
18551870
}
18561871

@@ -2183,10 +2198,10 @@ fn parseMatch(self: *Parser) Error!Node.Idx {
21832198
const branch_node = self.ast.nodes.get(branch_idx);
21842199

21852200
if (branch_node.tag != .binop_thick_arrow) {
2186-
// Not a branch - restore position and break
2187-
// Actually we can't easily restore position, so just break
2188-
// This means we might have consumed a token that's not part of the match
2189-
// TODO: Better error recovery here
2201+
// Not a branch - we've parsed something that's not a valid match branch
2202+
// Since we don't backtrack, treat it as a malformed branch and report error
2203+
// Then break out of branch parsing
2204+
_ = try self.pushMalformed(.expr_unexpected_token, branch_node.region.start);
21902205
break;
21912206
}
21922207

@@ -2387,12 +2402,12 @@ pub fn parseTypeAnno(self: *Parser) Error!Node.Idx {
23872402
}
23882403

23892404
// Operator precedence
2390-
const BindingPower = struct {
2405+
pub const BindingPower = struct {
23912406
left: u8,
23922407
right: u8,
23932408
};
23942409

2395-
fn getBindingPower(tag: Token.Tag) BindingPower {
2410+
pub fn getBindingPower(tag: Token.Tag) BindingPower {
23962411
return switch (tag) {
23972412
.OpBar => .{ .left = 10, .right = 11 },
23982413
.OpOr => .{ .left = 20, .right = 21 },
@@ -2412,7 +2427,7 @@ fn getBindingPower(tag: Token.Tag) BindingPower {
24122427
};
24132428
}
24142429

2415-
fn tokenToBinOpTag(tag: Token.Tag) ?Node.Tag {
2430+
pub fn tokenToBinOpTag(tag: Token.Tag) ?Node.Tag {
24162431
return switch (tag) {
24172432
.OpAssign => .binop_equals,
24182433
.OpEquals => .binop_double_equals,

src/parse/tokenize_iter.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,6 @@ pub const Cursor = struct {
522522
pos: u32,
523523
messages: []Diagnostic,
524524
message_count: u32,
525-
tab_width: u8 = 4, // TODO: make this configurable
526525

527526
/// Initialize a Cursor with the given input buffer and a pre-allocated messages slice.
528527
pub fn init(buf: []const u8, messages: []Diagnostic) Cursor {

test/snapshots/app_header__nonempty_multiline.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@ KwApp OpenCurly LowerIdent OpColon String KwPlatform OpenSquare LowerIdent OpBan
1717
~~~
1818
# FORMATTED
1919
~~~roc
20-
app # This comment is here
21-
{
22-
pf: "../main.roc" platform [main],
23-
somePkg: "../main.roc",
24-
}
20+
app { pf: "../main.roc" platform [main], somePkg: "../main.roc" }
2521
2622
~~~
2723
# EXPECTED

test/snapshots/app_header__nonempty_multiline__commented.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ app # Comment after keyword
2626
{
2727
# Comment after packages open
2828
pf: "../main.roc" platform [ # Comment after provides open
29-
main],
29+
main
30+
],
3031
# Comment after platform
3132
other: "../../other/main.roc",
3233
}

test/snapshots/app_header_nonempty_singleline.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@ KwApp OpenCurly LowerIdent OpColon String KwPlatform OpenSquare LowerIdent OpBan
1616
~~~
1717
# FORMATTED
1818
~~~roc
19-
app
20-
{
21-
pf: "../main.roc" platform [main],
22-
other: "../../other/main.roc",
23-
}
19+
app { pf: "../main.roc" platform [main], other: "../../other/main.roc" }
2420
2521
~~~
2622
# EXPECTED

test/snapshots/binops.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ OpenRound Int OpPlus Int Comma Int OpBinaryMinus Int Comma Int OpStar Int Comma
122122
NIL
123123
# PROBLEMS
124124
**Parse Error**
125-
at 16:1 to 16:1
125+
at 16:1 to 16:2
126126

127127
**Parse Error**
128128
at 16:2 to 16:2

test/snapshots/can_import_comprehensive.md

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -162,23 +162,14 @@ main = {
162162
result2 = Http.post
163163
result3 = get
164164
result4 = post
165-
combined = Str.concat((
166-
client,
167-
parser,
168-
helper,
169-
result1,
170-
result2,
171-
result3,
172-
result4,
173-
combined,
174-
))
165+
combined = Str.concat((client, parser, helper, result1, result2, result3, result4, combined))
175166
}
176167
~~~
177168
# EXPECTED
178169
NIL
179170
# PROBLEMS
180171
**Parse Error**
181-
at 34:5 to 34:5
172+
at 34:5 to 35:1
182173

183174
**Parse Error**
184175
at 23:16 to 35:1

0 commit comments

Comments
 (0)