Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Records and Tuples #7638

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
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
Loading