Skip to content

Commit

Permalink
Records and Tuples
Browse files Browse the repository at this point in the history
  • Loading branch information
gamebox committed Feb 25, 2025
1 parent 578e925 commit 4122825
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 126 deletions.
161 changes: 103 additions & 58 deletions src/check/parse/IR.zig
Original file line number Diff line number Diff line change
Expand Up @@ -424,18 +424,11 @@ pub const Node = struct {
/// * lhs - LHS DESCRIPTION
/// * rhs - RHS DESCRIPTION
record_builder,
// TODO: Add the rest of the expressions

/// A block of statements
/// Main token is newline preceding the block
/// * lhs - first statement node
/// * rhs - number of statements
block,
/// The end of a block of states
/// Main token is final newline of block
/// * lhs - ignored
/// * rhs - ignored
block_end,

/// A branch is a when expression
/// Main token is ignored
Expand Down Expand Up @@ -545,8 +538,6 @@ pub const NodeStore = struct {

/// An index for a File node. Should not be constructed externally.
pub const FileIdx = struct { id: u32 };
/// An index for a Body node. Should not be constructed externally.
pub const BodyIdx = struct { id: u32 };
/// An index for a Header node. Should not be constructed externally.
pub const HeaderIdx = struct { id: u32 };
/// An index for a Statement node. Should not be constructed externally.
Expand Down Expand Up @@ -603,31 +594,6 @@ pub const NodeStore = struct {
return FileIdx{ .id = 0 };
}

pub fn addBody(store: *NodeStore, body: Body) BodyIdx {
const start = store.extra_data.items.len;
const len = @as(u31, @intCast(body.statements.len));
if (body.whitespace) |ws| {
store.extra_data.append(ws) catch exitOnOom();
}
for (body.statements) |statement| {
store.extra_data.append(statement.id) catch exitOnOom();
}

const rhs = BodyRhs{
.has_whitespace = if (body.whitespace != null) 1 else 0,
.num_statements = len,
};
const nid = store.nodes.append(.{
.tag = .block,
.main_token = 0,
.data = .{
.lhs = @as(u32, @intCast(start)),
.rhs = @as(u32, @bitCast(rhs)),
},
});
return .{ .id = @intFromEnum(nid) };
}

pub fn addHeader(store: *NodeStore, header: Header) HeaderIdx {
var node = Node{
.tag = .statement,
Expand Down Expand Up @@ -873,8 +839,22 @@ pub const NodeStore = struct {
store.extra_data.append(item.id) catch exitOnOom();
}
},
.tuple => |_| {},
.record => |_| {},
.tuple => |t| {
node.tag = .tuple;
node.data.lhs = @as(u32, @intCast(store.extra_data.items.len));
node.data.rhs = @as(u32, @intCast(t.items.len));
for (t.items) |item| {
store.extra_data.append(item.id) catch exitOnOom();
}
},
.record => |r| {
node.tag = .record;
node.data.lhs = @as(u32, @intCast(store.extra_data.items.len));
node.data.rhs = @as(u32, @intCast(r.fields.len));
for (r.fields) |field| {
store.extra_data.append(field.id) catch exitOnOom();
}
},
.tag => |e| {
node.tag = .tag;
node.main_token = e.token;
Expand Down Expand Up @@ -974,6 +954,25 @@ pub const NodeStore = struct {
node.data.lhs = d.expr.id;
},
.record_builder => |_| {},
.block => |body| {
const start = store.extra_data.items.len;
const len = @as(u31, @intCast(body.statements.len));
if (body.whitespace) |ws| {
store.extra_data.append(ws) catch exitOnOom();
}
for (body.statements) |statement| {
store.extra_data.append(statement.id) catch exitOnOom();
}

const rhs = BodyRhs{
.has_whitespace = if (body.whitespace != null) 1 else 0,
.num_statements = len,
};
node.tag = .block;
node.main_token = 0;
node.data.lhs = @as(u32, @intCast(start));
node.data.rhs = @as(u32, @bitCast(rhs));
},
}
const nid = store.nodes.append(node);
return .{ .id = @intFromEnum(nid) };
Expand Down Expand Up @@ -1496,12 +1495,43 @@ pub const NodeStore = struct {
.region = emptyRegion(),
} };
},
.tuple => {
var extra_data_pos = @as(usize, @intCast(node.data.lhs));
const extra_data_end = extra_data_pos + node.data.rhs;
const scratch_top = store.scratch_exprs.items.len;
while (extra_data_pos < extra_data_end) {
store.scratch_exprs.append(.{ .id = @as(u32, @intCast(store.extra_data.items[extra_data_pos])) }) catch exitOnOom();
extra_data_pos += 1;
}
const items = store.scratch_exprs.items[scratch_top..];
store.scratch_exprs.shrinkRetainingCapacity(scratch_top);

return .{ .tuple = .{
.items = items,
.region = emptyRegion(),
} };
},
.record => {
var extra_data_pos = @as(usize, @intCast(node.data.lhs));
const extra_data_end = extra_data_pos + node.data.rhs;
const scratch_top = store.scratch_record_fields.items.len;
while (extra_data_pos < extra_data_end) {
store.scratch_record_fields.append(.{ .id = @as(u32, @intCast(store.extra_data.items[extra_data_pos])) }) catch exitOnOom();
extra_data_pos += 1;
}
const fields = store.scratch_record_fields.items[scratch_top..];
store.scratch_exprs.shrinkRetainingCapacity(scratch_top);
return .{ .record = .{
.fields = fields,
.region = emptyRegion(),
} };
},
.lambda => {
var extra_data_pos = @as(usize, @intCast(node.data.lhs));
const body_len = 1;
const args_len = @as(usize, @intCast(node.data.rhs));
const extra_data_end = extra_data_pos + args_len + body_len;
const body = BodyIdx{
const body = ExprIdx{
.id = @as(u32, @intCast(store.extra_data.items[extra_data_pos])),
};
extra_data_pos += 1;
Expand Down Expand Up @@ -1576,27 +1606,39 @@ pub const NodeStore = struct {
.expr = .{ .id = node.data.lhs },
} };
},
.block => {
const rhs = @as(BodyRhs, @bitCast(node.data.rhs));
const start = if (rhs.has_whitespace == 1) node.data.lhs + 1 else node.data.lhs;
const whitespace: ?TokenIdx = if (rhs.has_whitespace == 1) store.extra_data.items[node.data.lhs] else null;
const statement_data = store.extra_data.items[start..(start + rhs.num_statements)];
const scratch_top = store.scratch_statements.items.len;
for (statement_data) |i| {
store.scratch_statements.append(.{ .id = i }) catch exitOnOom();
}
const statements = store.scratch_statements.items[scratch_top..];
store.scratch_statements.shrinkRetainingCapacity(scratch_top);
return .{ .block = .{
.statements = statements,
.whitespace = whitespace,
.region = emptyRegion(),
} };
},
else => {
std.debug.panic("Expected a valid expr tag, got {s}", .{@tagName(node.tag)});
},
}
}

pub fn getBody(store: *NodeStore, body: BodyIdx) Body {
const node = store.nodes.get(@enumFromInt(body.id));
const rhs = @as(BodyRhs, @bitCast(node.data.rhs));
const start = if (rhs.has_whitespace == 1) node.data.lhs + 1 else node.data.lhs;
const whitespace: ?TokenIdx = if (rhs.has_whitespace == 1) store.extra_data.items[node.data.lhs] else null;
const statement_data = store.extra_data.items[start..(start + rhs.num_statements)];
const scratch_top = store.scratch_statements.items.len;
for (statement_data) |i| {
store.scratch_statements.append(.{ .id = i }) catch exitOnOom();
}
const statements = store.scratch_statements.items[scratch_top..];
store.scratch_statements.shrinkRetainingCapacity(scratch_top);
pub fn getRecordField(store: *NodeStore, fieldIdx: RecordFieldIdx) RecordField {
const node = store.nodes.get(@enumFromInt(fieldIdx.id));
const name = node.main_token;
const value = if (node.data.lhs > 0) ExprIdx{ .id = node.data.lhs } else null;
const optional = node.data.rhs == 1;
return .{
.statements = statements,
.whitespace = whitespace,
.name = name,
.value = value,
.optional = optional,
.region = emptyRegion(),
};
}

Expand Down Expand Up @@ -1768,6 +1810,7 @@ pub const NodeStore = struct {
statements: []const StatementIdx,
/// The token that represents the newline preceding this block, if any
whitespace: ?TokenIdx,
region: Region,
};

/// Represents a module header.
Expand Down Expand Up @@ -1804,7 +1847,7 @@ pub const NodeStore = struct {
pub const Statement = union(enum) {
decl: struct {
pattern: PatternIdx,
body: BodyIdx,
body: ExprIdx,
region: Region,
},
expr: struct {
Expand All @@ -1816,7 +1859,7 @@ pub const NodeStore = struct {
region: Region,
},
expect: struct {
body: BodyIdx,
body: ExprIdx,
region: Region,
},
@"return": struct {
Expand Down Expand Up @@ -1972,14 +2015,15 @@ pub const NodeStore = struct {
},
record: struct {
fields: []const RecordFieldIdx,
region: Region,
},
tag: struct {
token: TokenIdx,
region: Region,
},
lambda: struct {
args: []const PatternIdx,
body: BodyIdx,
body: ExprIdx,
region: Region,
},
apply: struct {
Expand Down Expand Up @@ -2009,8 +2053,8 @@ pub const NodeStore = struct {
unary_not: Unary,
if_then_else: struct {
condition: ExprIdx,
then: BodyIdx,
@"else": BodyIdx,
then: ExprIdx,
@"else": ExprIdx,
region: Region,
},
match: struct {
Expand All @@ -2031,6 +2075,7 @@ pub const NodeStore = struct {
mapper: ExprIdx,
fields: RecordFieldIdx,
},
block: Body,
};

pub const PatternRecordField = struct {
Expand All @@ -2048,12 +2093,12 @@ pub const NodeStore = struct {

pub const IfElse = struct {
condition: ExprIdx,
body: BodyIdx,
body: ExprIdx,
region: Region,
};
pub const WhenBranch = struct {
pattern: PatternIdx,
body: BodyIdx,
body: ExprIdx,
region: Region,
};

Expand Down
Loading

0 comments on commit 4122825

Please sign in to comment.