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

Functions #114

Merged
merged 5 commits into from
Aug 7, 2023
Merged
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
2 changes: 2 additions & 0 deletions src/builtins.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const Intern = interner.Intern;
const Interned = interner.Interned;

pub const Builtins = struct {
fn_: Interned,
enum_: Interned,
struct_: Interned,
block: Interned,
Expand Down Expand Up @@ -33,6 +34,7 @@ pub const Builtins = struct {

pub fn init(intern: *Intern) !Builtins {
return Builtins{
.fn_ = try intern.store("fn"),
.enum_ = try intern.store("enum"),
.struct_ = try intern.store("struct"),
.block = try intern.store("block"),
Expand Down
20 changes: 11 additions & 9 deletions src/code_generator/lower.zig
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ fn expressionAlloc(context: Context, e: type_checker.types.Expression) !*const t
return ptr;
}

fn function(allocator: Allocator, builtins: Builtins, data_segment: *types.DataSegment, uses_memory: *bool, intrinsics: *types.Intrinsics, intern: *Intern, name: Interned, f: type_checker.types.Function) !types.Function {
fn function(allocator: Allocator, builtins: Builtins, data_segment: *types.DataSegment, uses_memory: *bool, intrinsics: *types.Intrinsics, intern: *Intern, f: type_checker.types.Function) !types.Function {
var locals = List(types.Local).init(allocator);
const parameters = try allocator.alloc(types.Parameter, f.parameters.len);
var body = List(types.Expression).init(allocator);
Expand Down Expand Up @@ -779,7 +779,7 @@ fn function(allocator: Allocator, builtins: Builtins, data_segment: *types.DataS
try body.append(expr);
}
return types.Function{
.name = name,
.name = f.name.value,
.parameters = parameters,
.return_type = mapType(f.return_type),
.locals = try locals.toOwnedSlice(),
Expand Down Expand Up @@ -823,10 +823,6 @@ pub fn module(allocator: Allocator, builtins: Builtins, m: type_checker.types.Mo
.define => |d| {
const name_symbol = d.name.value;
switch (d.value.*) {
.function => |f| {
const lowered = try function(allocator, builtins, &data_segment, &uses_memory, &intrinsics, intern, name_symbol, f);
try functions.append(lowered);
},
.foreign_import => |i| {
const lowered = try foreignImport(allocator, name_symbol, i);
try imports.append(lowered);
Expand All @@ -843,13 +839,19 @@ pub fn module(allocator: Allocator, builtins: Builtins, m: type_checker.types.Mo
const trimmed = try intern.store(name_string);
switch (e.value.*) {
.function => |f| {
const lowered = try function(allocator, builtins, &data_segment, &uses_memory, &intrinsics, intern, trimmed, f);
const lowered = try function(allocator, builtins, &data_segment, &uses_memory, &intrinsics, intern, f);
try functions.append(lowered);
try exports.append(.{ .name = f.name.value, .alias = trimmed });
},
.symbol => {
try exports.append(.{ .name = trimmed, .alias = trimmed });
},
.symbol => {},
else => |k| std.debug.panic("\nForeign export kind {} no yet supported", .{k}),
}
try exports.append(.{ .name = trimmed, .alias = trimmed });
},
.function => |f| {
const lowered = try function(allocator, builtins, &data_segment, &uses_memory, &intrinsics, intern, f);
try functions.append(lowered);
},
else => std.debug.panic("\nTop level kind {} no yet supported", .{top_level}),
}
Expand Down
181 changes: 74 additions & 107 deletions src/parser/parse.zig
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,67 @@ fn array(context: Context, begin: tokenizer.types.Pos) !types.Array {
};
}

fn functionParameters(context: Context, parameters: *List(types.Parameter)) !void {
fn group(context: Context, left_paren: LeftParen) !types.Group {
const begin = left_paren.span.begin;
context.tokens.consumeNewLines();
const expr = try expressionAlloc(withPrecedence(context, DEFINE + 1));
const end = tokenizer.span.token(context.tokens.consume(.right_paren)).end;
return .{
.expression = expr,
.span = .{ .begin = begin, .end = end },
};
}

fn branch(context: Context, if_token: IfToken) !types.Branch {
const begin = if_token.span.begin;
const lowest = withPrecedence(context, LOWEST);
var arms = List(types.Arm).init(context.allocator);
try arms.append(types.Arm{
.condition = try expression(lowest),
.then = try block(lowest, tokenizer.span.token(context.tokens.consume(.left_brace)).begin),
});
context.tokens.consumeNewLines();
while (context.tokens.peek()) |t| {
switch (t) {
.else_ => {
context.tokens.advance();
switch (context.tokens.next().?) {
.left_brace => |l| {
const else_ = try block(lowest, l.span.begin);
const end = else_.span.end;
return types.Branch{
.arms = try arms.toOwnedSlice(),
.else_ = else_,
.span = .{ .begin = begin, .end = end },
};
},
.if_ => {
try arms.append(types.Arm{
.condition = try expression(lowest),
.then = try block(lowest, tokenizer.span.token(context.tokens.consume(.left_brace)).begin),
});
context.tokens.consumeNewLines();
},
else => |k| std.debug.panic("\nExpected (delimiter '{{') found {}", .{k}),
}
},
else => {
const pos = arms.items[0].then.span.end;
const else_ = types.Block{ .expressions = &.{}, .span = .{ .begin = pos, .end = pos } };
return types.Branch{
.arms = try arms.toOwnedSlice(),
.else_ = else_,
.span = .{ .begin = begin, .end = pos },
};
},
}
}
std.debug.panic("\nExpected else token", .{});
}

fn functionParameters(context: Context) ![]types.Parameter {
_ = context.tokens.consume(.left_paren);
var parameters = List(types.Parameter).init(context.allocator);
while (context.tokens.peek()) |t| {
switch (t) {
.new_line => context.tokens.advance(),
Expand Down Expand Up @@ -186,10 +246,13 @@ fn functionParameters(context: Context, parameters: *List(types.Parameter)) !voi
}
}
_ = context.tokens.consume(.right_paren);
return try parameters.toOwnedSlice();
}

fn function(context: Context, begin: types.Pos, parameters: *List(types.Parameter)) !types.Expression {
try functionParameters(context, parameters);
fn function(context: Context, begin: types.Pos) !types.Expression {
const name = context.tokens.consume(.symbol).symbol;
const parameters = try functionParameters(context);
_ = context.tokens.consume(.right_arrow);
const return_type = try expressionAlloc(withPrecedence(context, DEFINE + 1));
if (context.tokens.peek()) |t| {
if (t == .left_brace) {
Expand All @@ -200,7 +263,8 @@ fn function(context: Context, begin: types.Pos, parameters: *List(types.Paramete
const end = body.span.end;
return types.Expression{
.function = .{
.parameters = try parameters.toOwnedSlice(),
.name = name,
.parameters = parameters,
.return_type = return_type,
.body = body,
.span = types.Span{ .begin = begin, .end = end },
Expand All @@ -211,107 +275,14 @@ fn function(context: Context, begin: types.Pos, parameters: *List(types.Paramete
const end = spanOf(return_type.*).end;
return types.Expression{
.prototype = .{
.parameters = try parameters.toOwnedSlice(),
.name = name,
.parameters = parameters,
.return_type = return_type,
.span = types.Span{ .begin = begin, .end = end },
},
};
}

fn groupOrFunction(context: Context, left_paren: LeftParen) !types.Expression {
const begin = left_paren.span.begin;
context.tokens.consumeNewLines();
switch (context.tokens.peek().?) {
.right_paren, .mut => {
var parameters = List(types.Parameter).init(context.allocator);
return try function(context, begin, &parameters);
},
else => {
const expr = try expression(withPrecedence(context, DEFINE + 1));
switch (expr) {
.symbol => |name| {
switch (context.tokens.peek().?) {
.colon => {
context.tokens.advance();
var parameters = List(types.Parameter).init(context.allocator);
const type_ = try expression(withPrecedence(context, DEFINE + 1));
context.tokens.consumeNewLines();
context.tokens.maybeConsume(.comma);
try parameters.append(types.Parameter{
.name = name,
.type = type_,
.mutable = false,
.span = .{ .begin = name.span.begin, .end = spanOf(type_).end },
});
return try function(context, begin, &parameters);
},
.right_paren => {
unreachable;
},
else => |k| std.debug.panic("\nExpected colon or right paren, found {}", .{k}),
}
},
else => {
const allocated = try context.allocator.create(types.Expression);
allocated.* = expr;
const end = tokenizer.span.token(context.tokens.consume(.right_paren)).end;
return .{ .group = .{
.expression = allocated,
.span = .{ .begin = begin, .end = end },
} };
},
}
},
}
}

fn branch(context: Context, if_token: IfToken) !types.Branch {
const begin = if_token.span.begin;
const lowest = withPrecedence(context, LOWEST);
var arms = List(types.Arm).init(context.allocator);
try arms.append(types.Arm{
.condition = try expression(lowest),
.then = try block(lowest, tokenizer.span.token(context.tokens.consume(.left_brace)).begin),
});
context.tokens.consumeNewLines();
while (context.tokens.peek()) |t| {
switch (t) {
.else_ => {
context.tokens.advance();
switch (context.tokens.next().?) {
.left_brace => |l| {
const else_ = try block(lowest, l.span.begin);
const end = else_.span.end;
return types.Branch{
.arms = try arms.toOwnedSlice(),
.else_ = else_,
.span = .{ .begin = begin, .end = end },
};
},
.if_ => {
try arms.append(types.Arm{
.condition = try expression(lowest),
.then = try block(lowest, tokenizer.span.token(context.tokens.consume(.left_brace)).begin),
});
context.tokens.consumeNewLines();
},
else => |k| std.debug.panic("\nExpected (delimiter '{{') found {}", .{k}),
}
},
else => {
const pos = arms.items[0].then.span.end;
const else_ = types.Block{ .expressions = &.{}, .span = .{ .begin = pos, .end = pos } };
return types.Branch{
.arms = try arms.toOwnedSlice(),
.else_ = else_,
.span = .{ .begin = begin, .end = pos },
};
},
}
}
std.debug.panic("\nExpected else token", .{});
}

fn enumeration(context: Context, enum_: EnumToken) !types.Enumeration {
const begin = enum_.span.begin;
_ = context.tokens.consume(.left_brace);
Expand Down Expand Up @@ -414,8 +385,9 @@ fn prefix(context: Context) !types.Expression {
.symbol => |s| return .{ .symbol = s },
.string => |s| return .{ .string = s },
.bool => |b| return .{ .bool = b },
.left_paren => |l| return try groupOrFunction(context, l),
.left_paren => |l| return .{ .group = try group(context, l) },
.if_ => |i| return .{ .branch = try branch(context, i) },
.fn_ => |f| return try function(context, f.span.begin),
.enum_ => |e| return .{ .enumeration = try enumeration(context, e) },
.struct_ => |s| return .{ .structure = try structure(context, s) },
.block => |b| return .{ .block = try explicitBlock(context, b) },
Expand Down Expand Up @@ -800,7 +772,7 @@ pub fn parse(allocator: Allocator, builtins: Builtins, tokens: []const tokenizer
var structures = List(types.TopLevelStructure).init(allocator);
var enumerations = List(types.TopLevelEnumeration).init(allocator);
var defines = List(types.Define).init(allocator);
var functions = List(types.TopLevelFunction).init(allocator);
var functions = List(types.Function).init(allocator);
var foreign_exports = List(types.Call).init(allocator);
var ignored = List(types.Expression).init(allocator);
while (iterator.peek()) |t| {
Expand All @@ -824,12 +796,6 @@ pub fn parse(allocator: Allocator, builtins: Builtins, tokens: []const tokenizer
.enumeration = en,
.span = d.span,
}),
.function => |f| try functions.append(.{
.name = d.name,
.type = d.type,
.function = f,
.span = d.span,
}),
.call => |c| {
switch (c.function.*) {
.symbol => |s| {
Expand All @@ -850,6 +816,7 @@ pub fn parse(allocator: Allocator, builtins: Builtins, tokens: []const tokenizer
else => try defines.append(d),
}
},
.function => |f| try functions.append(f),
.call => |c| {
switch (c.function.*) {
.symbol => |s| {
Expand Down
17 changes: 3 additions & 14 deletions src/parser/pretty_print.zig
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub fn timesEqual(t: types.TimesEqual, indent: Indent, writer: Writer) !void {
}

pub fn function(f: types.Function, indent: Indent, writer: Writer) !void {
try writer.writeAll("(fn [");
try writer.print("(fn {s} [", .{f.name.value.string()});
for (f.parameters, 0..) |param, j| {
if (j > 0) try writer.writeAll(" ");
try writer.writeAll("(");
Expand All @@ -54,7 +54,7 @@ pub fn function(f: types.Function, indent: Indent, writer: Writer) !void {
}
try writer.writeAll("] ");
try expression(f.return_type.*, indent, writer);
try block(f.body, indent, writer);
try block(f.body, indent + 1, writer);
try writer.writeAll(")");
}

Expand Down Expand Up @@ -283,17 +283,6 @@ pub fn topLevelEnumeration(e: types.TopLevelEnumeration, indent: Indent, writer:
try writer.writeAll(")");
}

pub fn topLevelFunction(f: types.TopLevelFunction, indent: Indent, writer: Writer) !void {
try writer.print("(def {s}", .{f.name.value.string()});
if (f.type) |t| {
try writer.writeAll(" ");
try expression(t.*, indent, writer);
}
try writer.writeAll(" ");
try function(f.function, indent + 1, writer);
try writer.writeAll(")");
}

pub fn module(m: types.Module, writer: Writer) !void {
var i: usize = 0;
for (m.foreign_imports) |f| {
Expand All @@ -313,7 +302,7 @@ pub fn module(m: types.Module, writer: Writer) !void {
}
for (m.functions) |f| {
if (i > 0) try writer.writeAll("\n\n");
try topLevelFunction(f, 0, writer);
try function(f, 0, writer);
i += 1;
}
for (m.defines) |d| {
Expand Down
11 changes: 3 additions & 8 deletions src/parser/types.zig
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,15 @@ pub const Array = struct {
};

pub const Function = struct {
name: Symbol,
parameters: []const Parameter,
return_type: *const Expression,
body: Block,
span: Span,
};

pub const Prototype = struct {
name: Symbol,
parameters: []const Parameter,
return_type: *const Expression,
span: Span,
Expand Down Expand Up @@ -208,13 +210,6 @@ pub const TopLevelEnumeration = struct {
span: Span,
};

pub const TopLevelFunction = struct {
name: Symbol,
type: ?*const Expression,
function: Function,
span: Span,
};

pub const TopLevelForeignImport = struct {
name: Symbol,
type: ?*const Expression,
Expand All @@ -226,7 +221,7 @@ pub const Module = struct {
foreign_imports: []const TopLevelForeignImport,
structures: []const TopLevelStructure,
enumerations: []const TopLevelEnumeration,
functions: []const TopLevelFunction,
functions: []const Function,
defines: []const Define,
foreign_exports: []const Call,
ignored: []const Expression,
Expand Down
Loading
Loading