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,
|
stdout: *std.Io.Writer,
|
||||||
|
|
||||||
pub fn interpret(self: @This(), program: parser.Program) !void {
|
pub fn interpret(self: @This(), program: parser.Program) !void {
|
||||||
const main = for (program.funcs) |func| {
|
for (program.stmts) |stmt| {
|
||||||
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| {
|
|
||||||
try self.run_stmt(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 {
|
pub const Program = struct {
|
||||||
funcs: []const Func,
|
stmts: []const Stmt,
|
||||||
};
|
|
||||||
|
|
||||||
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),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Stmt = union(enum) {
|
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 {
|
pub fn parse(gpa: std.mem.Allocator, tokens: []const lexer.Token) !Program {
|
||||||
const sexprs = try parse_sexprs(gpa, tokens);
|
const sexprs = try parse_sexprs(gpa, tokens);
|
||||||
var funcs = std.ArrayList(Func).empty;
|
var stmts = std.ArrayList(Stmt).empty;
|
||||||
for (sexprs) |sexpr| {
|
for (sexprs) |sexpr| {
|
||||||
const func = try Func.from(gpa, sexpr);
|
const stmt = try Stmt.from(gpa, sexpr);
|
||||||
try funcs.append(gpa, func);
|
try stmts.append(gpa, stmt);
|
||||||
}
|
}
|
||||||
return Program{
|
return Program{
|
||||||
.funcs = try funcs.toOwnedSlice(gpa),
|
.stmts = try stmts.toOwnedSlice(gpa),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,50 +3,49 @@ const t = std.testing;
|
|||||||
|
|
||||||
const lib = @import("libneon");
|
const lib = @import("libneon");
|
||||||
|
|
||||||
test "large tree" {
|
test "program" {
|
||||||
var arena = std.heap.ArenaAllocator.init(t.allocator);
|
var arena = std.heap.ArenaAllocator.init(t.allocator);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
const gpa = arena.allocator();
|
const gpa = arena.allocator();
|
||||||
|
|
||||||
try t.expectEqualDeep(
|
try t.expectEqualDeep(
|
||||||
&[_]lib.parser.SExpr{
|
lib.parser.Program{
|
||||||
.{ .call = &.{
|
.stmts = &.{
|
||||||
.{ .identifier = "foo" },
|
.{ .expr = .{ .func_call = .{ .name = "foo", .args = &.{
|
||||||
.{ .identifier = "bar" },
|
.{ .variable = "bar" },
|
||||||
.{ .string = "baz" },
|
.{ .string = "baz" },
|
||||||
.{ .list = &.{
|
.{ .func_call = .{ .name = "+", .args = &.{
|
||||||
.{ .integer = 1 },
|
.{ .integer = 1 },
|
||||||
.{ .integer = 2 },
|
.{ .integer = 2 },
|
||||||
.{ .integer = 3 },
|
} } },
|
||||||
} },
|
} } } },
|
||||||
.{ .block = &.{} },
|
|
||||||
} },
|
|
||||||
},
|
},
|
||||||
try lib.parser.parse_sexprs(gpa, &.{
|
},
|
||||||
|
try lib.parser.parse(gpa, &.{
|
||||||
.lparen,
|
.lparen,
|
||||||
.{ .identifier = "foo" },
|
.{ .identifier = "foo" },
|
||||||
.{ .identifier = "bar" },
|
.{ .identifier = "bar" },
|
||||||
.{ .string = "baz" },
|
.{ .string = "baz" },
|
||||||
.lbracket,
|
.lparen,
|
||||||
|
.{ .identifier = "+" },
|
||||||
.{ .integer = 1 },
|
.{ .integer = 1 },
|
||||||
.{ .integer = 2 },
|
.{ .integer = 2 },
|
||||||
.{ .integer = 3 },
|
.rparen,
|
||||||
.rbracket,
|
|
||||||
.lbrace,
|
|
||||||
.rbrace,
|
|
||||||
.rparen,
|
.rparen,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "empty" {
|
test "empty program" {
|
||||||
var arena = std.heap.ArenaAllocator.init(t.allocator);
|
var arena = std.heap.ArenaAllocator.init(t.allocator);
|
||||||
defer arena.deinit();
|
defer arena.deinit();
|
||||||
const gpa = arena.allocator();
|
const gpa = arena.allocator();
|
||||||
|
|
||||||
try t.expectEqualDeep(
|
try t.expectEqualDeep(
|
||||||
&.{},
|
lib.parser.Program{
|
||||||
lib.parser.parse_sexprs(gpa, &.{}),
|
.stmts = &.{},
|
||||||
|
},
|
||||||
|
lib.parser.parse(gpa, &.{}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +56,7 @@ test "unmatched delimiters" {
|
|||||||
|
|
||||||
try t.expectError(
|
try t.expectError(
|
||||||
error.UnmatchedParen,
|
error.UnmatchedParen,
|
||||||
lib.parser.parse_sexprs(gpa, &.{
|
lib.parser.parse(gpa, &.{
|
||||||
.lbracket,
|
.lbracket,
|
||||||
.{ .integer = 34 },
|
.{ .integer = 34 },
|
||||||
.lparen,
|
.lparen,
|
||||||
@@ -67,7 +66,7 @@ test "unmatched delimiters" {
|
|||||||
|
|
||||||
try t.expectError(
|
try t.expectError(
|
||||||
error.UnmatchedBracket,
|
error.UnmatchedBracket,
|
||||||
lib.parser.parse_sexprs(gpa, &.{
|
lib.parser.parse(gpa, &.{
|
||||||
.lparen,
|
.lparen,
|
||||||
.{ .integer = 34 },
|
.{ .integer = 34 },
|
||||||
.lbracket,
|
.lbracket,
|
||||||
|
|||||||
Reference in New Issue
Block a user