Compare commits
2 Commits
d7e71d58e1
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
374a221e94
|
|||
|
a42770f4cc
|
@@ -1,3 +1 @@
|
||||
(func main [] {
|
||||
(print_int (+ 1 (* 2 34)))
|
||||
})
|
||||
(print_int (+ 1 (* 2 34)))
|
||||
|
||||
@@ -6,17 +6,9 @@ pub const Interpreter = struct {
|
||||
stdout: *std.Io.Writer,
|
||||
|
||||
pub fn interpret(self: @This(), program: parser.Program) !void {
|
||||
const main = for (program.funcs) |func| {
|
||||
if (std.mem.eql(u8, func.name, "main")) break func;
|
||||
} else return error.NoMain;
|
||||
|
||||
try self.run_func(main);
|
||||
try self.stdout.flush();
|
||||
}
|
||||
|
||||
fn run_func(self: @This(), func: parser.Func) !void {
|
||||
for (func.body) |stmt| {
|
||||
for (program.stmts) |stmt| {
|
||||
try self.run_stmt(stmt);
|
||||
try self.stdout.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,40 +81,7 @@ fn parse_sexprs(gpa: std.mem.Allocator, tokens: []const lexer.Token) ![]const SE
|
||||
}
|
||||
|
||||
pub const Program = struct {
|
||||
funcs: []const Func,
|
||||
};
|
||||
|
||||
pub const Func = struct {
|
||||
name: []const u8,
|
||||
args: []const []const u8,
|
||||
body: []const Stmt,
|
||||
|
||||
fn from(gpa: std.mem.Allocator, sexpr: SExpr) !Func {
|
||||
if (sexpr != .call or sexpr.call.len != 4) {
|
||||
return error.InvalidFunc;
|
||||
}
|
||||
const call = sexpr.call;
|
||||
if (call[0] != .identifier or !std.mem.eql(u8, call[0].identifier, "func") or call[1] != .identifier) {
|
||||
return error.InvalidFunc;
|
||||
}
|
||||
if (call[2] != .list or call[3] != .block) {
|
||||
return error.InvalidFunc;
|
||||
}
|
||||
var args = std.ArrayList([]const u8).empty;
|
||||
for (call[2].list) |arg| {
|
||||
if (arg != .identifier) return error.InvalidFuncArg;
|
||||
try args.append(gpa, arg.identifier);
|
||||
}
|
||||
var body = std.ArrayList(Stmt).empty;
|
||||
for (call[3].block) |inner| {
|
||||
try body.append(gpa, try Stmt.from(gpa, inner));
|
||||
}
|
||||
return Func{
|
||||
.name = call[1].identifier,
|
||||
.args = try args.toOwnedSlice(gpa),
|
||||
.body = try body.toOwnedSlice(gpa),
|
||||
};
|
||||
}
|
||||
stmts: []const Stmt,
|
||||
};
|
||||
|
||||
pub const Stmt = union(enum) {
|
||||
@@ -218,12 +185,12 @@ pub const Expr = union(enum) {
|
||||
|
||||
pub fn parse(gpa: std.mem.Allocator, tokens: []const lexer.Token) !Program {
|
||||
const sexprs = try parse_sexprs(gpa, tokens);
|
||||
var funcs = std.ArrayList(Func).empty;
|
||||
var stmts = std.ArrayList(Stmt).empty;
|
||||
for (sexprs) |sexpr| {
|
||||
const func = try Func.from(gpa, sexpr);
|
||||
try funcs.append(gpa, func);
|
||||
const stmt = try Stmt.from(gpa, sexpr);
|
||||
try stmts.append(gpa, stmt);
|
||||
}
|
||||
return Program{
|
||||
.funcs = try funcs.toOwnedSlice(gpa),
|
||||
.stmts = try stmts.toOwnedSlice(gpa),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,50 +3,49 @@ const t = std.testing;
|
||||
|
||||
const lib = @import("libneon");
|
||||
|
||||
test "large tree" {
|
||||
test "program" {
|
||||
var arena = std.heap.ArenaAllocator.init(t.allocator);
|
||||
defer arena.deinit();
|
||||
const gpa = arena.allocator();
|
||||
|
||||
try t.expectEqualDeep(
|
||||
&[_]lib.parser.SExpr{
|
||||
.{ .call = &.{
|
||||
.{ .identifier = "foo" },
|
||||
.{ .identifier = "bar" },
|
||||
.{ .string = "baz" },
|
||||
.{ .list = &.{
|
||||
.{ .integer = 1 },
|
||||
.{ .integer = 2 },
|
||||
.{ .integer = 3 },
|
||||
} },
|
||||
.{ .block = &.{} },
|
||||
} },
|
||||
lib.parser.Program{
|
||||
.stmts = &.{
|
||||
.{ .expr = .{ .func_call = .{ .name = "foo", .args = &.{
|
||||
.{ .variable = "bar" },
|
||||
.{ .string = "baz" },
|
||||
.{ .func_call = .{ .name = "+", .args = &.{
|
||||
.{ .integer = 1 },
|
||||
.{ .integer = 2 },
|
||||
} } },
|
||||
} } } },
|
||||
},
|
||||
},
|
||||
try lib.parser.parse_sexprs(gpa, &.{
|
||||
try lib.parser.parse(gpa, &.{
|
||||
.lparen,
|
||||
.{ .identifier = "foo" },
|
||||
.{ .identifier = "bar" },
|
||||
.{ .string = "baz" },
|
||||
.lbracket,
|
||||
.lparen,
|
||||
.{ .identifier = "+" },
|
||||
.{ .integer = 1 },
|
||||
.{ .integer = 2 },
|
||||
.{ .integer = 3 },
|
||||
.rbracket,
|
||||
.lbrace,
|
||||
.rbrace,
|
||||
.rparen,
|
||||
.rparen,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
test "empty" {
|
||||
test "empty program" {
|
||||
var arena = std.heap.ArenaAllocator.init(t.allocator);
|
||||
defer arena.deinit();
|
||||
const gpa = arena.allocator();
|
||||
|
||||
try t.expectEqualDeep(
|
||||
&.{},
|
||||
lib.parser.parse_sexprs(gpa, &.{}),
|
||||
lib.parser.Program{
|
||||
.stmts = &.{},
|
||||
},
|
||||
lib.parser.parse(gpa, &.{}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -57,7 +56,7 @@ test "unmatched delimiters" {
|
||||
|
||||
try t.expectError(
|
||||
error.UnmatchedParen,
|
||||
lib.parser.parse_sexprs(gpa, &.{
|
||||
lib.parser.parse(gpa, &.{
|
||||
.lbracket,
|
||||
.{ .integer = 34 },
|
||||
.lparen,
|
||||
@@ -67,7 +66,7 @@ test "unmatched delimiters" {
|
||||
|
||||
try t.expectError(
|
||||
error.UnmatchedBracket,
|
||||
lib.parser.parse_sexprs(gpa, &.{
|
||||
lib.parser.parse(gpa, &.{
|
||||
.lparen,
|
||||
.{ .integer = 34 },
|
||||
.lbracket,
|
||||
|
||||
Reference in New Issue
Block a user