Compare commits
No commits in common. "master" and "tuple-inator" have entirely different histories.
master
...
tuple-inat
|
@ -9,12 +9,13 @@ this time it'll work i promise it wont be like vig plrease
|
||||||
```
|
```
|
||||||
git clone https://gitdab.com/luna/rayoko
|
git clone https://gitdab.com/luna/rayoko
|
||||||
cd rayoko
|
cd rayoko
|
||||||
zig build
|
zig build install --prefix ~/.local/
|
||||||
```
|
```
|
||||||
|
|
||||||
# use
|
# use
|
||||||
|
|
||||||
```
|
```
|
||||||
./zig-cache/bin/rayoko examples/hello.ry
|
rayoko examples/hello.ry # outputs to outpath.o
|
||||||
./a.out # gives 123 as exit code which i think is epic
|
gcc outpath.o examples/hello.c -o hello
|
||||||
|
./hello
|
||||||
```
|
```
|
||||||
|
|
|
@ -7,7 +7,7 @@ pub fn build(b: *Builder) void {
|
||||||
exe.install();
|
exe.install();
|
||||||
|
|
||||||
exe.linkSystemLibrary("c");
|
exe.linkSystemLibrary("c");
|
||||||
exe.linkSystemLibrary("LLVM-10");
|
exe.linkSystemLibrary("LLVM-9");
|
||||||
exe.linkSystemLibrary("stdc++");
|
exe.linkSystemLibrary("stdc++");
|
||||||
|
|
||||||
const run_cmd = exe.run();
|
const run_cmd = exe.run();
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub const Analyzer = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setErrContext(self: *@This(), comptime fmt: ?[]const u8, args: anytype) void {
|
fn setErrContext(self: *@This(), comptime fmt: ?[]const u8, args: var) void {
|
||||||
if (fmt == null) {
|
if (fmt == null) {
|
||||||
self.err_ctx = null;
|
self.err_ctx = null;
|
||||||
return;
|
return;
|
||||||
|
@ -42,7 +42,7 @@ pub const Analyzer = struct {
|
||||||
self.err_tok = tok;
|
self.err_tok = tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doError(self: *@This(), comptime fmt: []const u8, args: anytype) void {
|
fn doError(self: *@This(), comptime fmt: []const u8, args: var) void {
|
||||||
self.hadError = true;
|
self.hadError = true;
|
||||||
|
|
||||||
std.debug.warn("analysis error", .{});
|
std.debug.warn("analysis error", .{});
|
||||||
|
@ -80,14 +80,14 @@ pub const Analyzer = struct {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return switch (sym.?.*) {
|
return switch (sym.?.value.*) {
|
||||||
.Struct => SymbolUnderlyingType{ .Struct = val },
|
.Struct => SymbolUnderlyingType{ .Struct = val },
|
||||||
.Enum => SymbolUnderlyingType{ .Enum = val },
|
.Enum => SymbolUnderlyingType{ .Enum = val },
|
||||||
|
|
||||||
else => blk: {
|
else => blk: {
|
||||||
self.doError("expected struct or enum for '{}', got {}", .{
|
self.doError("expected struct or enum for '{}', got {}", .{
|
||||||
val,
|
val,
|
||||||
@tagName(@as(comp.SymbolType, sym.?.*)),
|
@tagName(@as(comp.SymbolType, sym.?.value.*)),
|
||||||
});
|
});
|
||||||
break :blk null;
|
break :blk null;
|
||||||
},
|
},
|
||||||
|
@ -257,8 +257,8 @@ pub const Analyzer = struct {
|
||||||
var symbol = try ctx.fetchGlobalSymbol(func_name, .Function);
|
var symbol = try ctx.fetchGlobalSymbol(func_name, .Function);
|
||||||
var func_sym = symbol.Function;
|
var func_sym = symbol.Function;
|
||||||
|
|
||||||
for (call.arguments.items) |arg_expr, idx| {
|
for (call.arguments.toSlice()) |arg_expr, idx| {
|
||||||
var param_type = func_sym.parameter_list.items[idx];
|
var param_type = func_sym.parameter_list.at(idx);
|
||||||
var arg_type = try self.resolveExprType(ctx, &arg_expr);
|
var arg_type = try self.resolveExprType(ctx, &arg_expr);
|
||||||
|
|
||||||
self.expectSymUnTypeEqual(arg_type, param_type) catch {
|
self.expectSymUnTypeEqual(arg_type, param_type) catch {
|
||||||
|
@ -314,7 +314,7 @@ pub const Analyzer = struct {
|
||||||
.Enum => |enum_identifier| {
|
.Enum => |enum_identifier| {
|
||||||
// fetch an enum off symbol table, then we use the
|
// fetch an enum off symbol table, then we use the
|
||||||
// identifier map to ensure get.name exists in the enum
|
// identifier map to ensure get.name exists in the enum
|
||||||
var map = ctx.symbol_table.get(enum_identifier).?.Enum;
|
var map = ctx.symbol_table.get(enum_identifier).?.value.Enum;
|
||||||
const name = get.name.lexeme;
|
const name = get.name.lexeme;
|
||||||
|
|
||||||
var kv = map.get(name);
|
var kv = map.get(name);
|
||||||
|
@ -355,8 +355,8 @@ pub const Analyzer = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var value_type = try self.resolveExprType(ctx, assign.value);
|
var value_type = try self.resolveExprType(ctx, assign.value);
|
||||||
try self.expectSymUnTypeEqual(var_type.?, value_type);
|
try self.expectSymUnTypeEqual(var_type.?.value, value_type);
|
||||||
return var_type.?;
|
return var_type.?.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
.Set => @panic("TODO analysis of Set exprs"),
|
.Set => @panic("TODO analysis of Set exprs"),
|
||||||
|
@ -411,7 +411,7 @@ pub const Analyzer = struct {
|
||||||
|
|
||||||
try ctx.bumpScope("if_then");
|
try ctx.bumpScope("if_then");
|
||||||
|
|
||||||
for (ifstmt.then_branch.items) |then_stmt| {
|
for (ifstmt.then_branch.toSlice()) |then_stmt| {
|
||||||
try self.stmtPass(ctx, then_stmt);
|
try self.stmtPass(ctx, then_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,7 +421,7 @@ pub const Analyzer = struct {
|
||||||
try ctx.bumpScope("if_else");
|
try ctx.bumpScope("if_else");
|
||||||
defer ctx.dumpScope();
|
defer ctx.dumpScope();
|
||||||
|
|
||||||
for (else_branch.items) |else_stmt| {
|
for (else_branch.toSlice()) |else_stmt| {
|
||||||
try self.stmtPass(ctx, else_stmt);
|
try self.stmtPass(ctx, else_stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,7 +437,7 @@ pub const Analyzer = struct {
|
||||||
|
|
||||||
try ctx.bumpScope("loop");
|
try ctx.bumpScope("loop");
|
||||||
|
|
||||||
for (loop.then_branch.items) |then_stmt| {
|
for (loop.then_branch.toSlice()) |then_stmt| {
|
||||||
try self.stmtPass(ctx, then_stmt);
|
try self.stmtPass(ctx, then_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,7 +476,7 @@ pub const Analyzer = struct {
|
||||||
});
|
});
|
||||||
|
|
||||||
var parameters = comp.TypeList.init(self.allocator);
|
var parameters = comp.TypeList.init(self.allocator);
|
||||||
for (decl.params.items) |param| {
|
for (decl.params.toSlice()) |param| {
|
||||||
var param_type = self.resolveGlobalType(ctx, param.typ.lexeme);
|
var param_type = self.resolveGlobalType(ctx, param.typ.lexeme);
|
||||||
if (param_type == null) continue;
|
if (param_type == null) continue;
|
||||||
try parameters.append(param_type.?);
|
try parameters.append(param_type.?);
|
||||||
|
@ -490,14 +490,14 @@ pub const Analyzer = struct {
|
||||||
// we intentionally insert the function so that:
|
// we intentionally insert the function so that:
|
||||||
// - we can do return statement validation
|
// - we can do return statement validation
|
||||||
// - we have parameter types fully analyzed
|
// - we have parameter types fully analyzed
|
||||||
if (ret_type != null and parameters.items.len == decl.params.items.len) {
|
if (ret_type != null and parameters.len == decl.params.len) {
|
||||||
try ctx.insertFn(decl, ret_type.?, parameters, scope);
|
try ctx.insertFn(decl, ret_type.?, parameters, scope);
|
||||||
} else {
|
} else {
|
||||||
if (ret_type != null)
|
if (ret_type != null)
|
||||||
self.doError("Return type was not fully resolved", .{});
|
self.doError("Return type was not fully resolved", .{});
|
||||||
|
|
||||||
if (parameters.items.len != decl.params.items.len)
|
if (parameters.len != decl.params.len)
|
||||||
self.doError("Fully analyzed {} parameters, wanted {}", .{ parameters.items.len, decl.params.items.len });
|
self.doError("Fully analyzed {} parameters, wanted {}", .{ parameters.len, decl.params.len });
|
||||||
|
|
||||||
return CompileError.TypeError;
|
return CompileError.TypeError;
|
||||||
}
|
}
|
||||||
|
@ -507,7 +507,7 @@ pub const Analyzer = struct {
|
||||||
std.debug.assert(ctx.current_scope == null);
|
std.debug.assert(ctx.current_scope == null);
|
||||||
ctx.setScope(scope);
|
ctx.setScope(scope);
|
||||||
|
|
||||||
for (decl.body.items) |stmt| {
|
for (decl.body.toSlice()) |stmt| {
|
||||||
try self.stmtPass(ctx, stmt);
|
try self.stmtPass(ctx, stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,7 +522,7 @@ pub const Analyzer = struct {
|
||||||
|
|
||||||
var types = comp.TypeList.init(self.allocator);
|
var types = comp.TypeList.init(self.allocator);
|
||||||
|
|
||||||
for (struc.fields.items) |field| {
|
for (struc.fields.toSlice()) |field| {
|
||||||
self.setErrToken(field.name);
|
self.setErrToken(field.name);
|
||||||
var field_type = self.resolveGlobalType(ctx, field.typ.lexeme);
|
var field_type = self.resolveGlobalType(ctx, field.typ.lexeme);
|
||||||
if (field_type == null) continue;
|
if (field_type == null) continue;
|
||||||
|
@ -534,7 +534,7 @@ pub const Analyzer = struct {
|
||||||
|
|
||||||
// we don't return type errors from the main loop so we can
|
// we don't return type errors from the main loop so we can
|
||||||
// keep going and find more type errors
|
// keep going and find more type errors
|
||||||
if (types.items.len == struc.fields.items.len)
|
if (types.len == struc.fields.len)
|
||||||
try ctx.insertStruct(struc, types);
|
try ctx.insertStruct(struc, types);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -547,7 +547,7 @@ pub const Analyzer = struct {
|
||||||
},
|
},
|
||||||
|
|
||||||
.ConstDecl => |constlist| {
|
.ConstDecl => |constlist| {
|
||||||
for (constlist.items) |constdecl| {
|
for (constlist.toSlice()) |constdecl| {
|
||||||
self.setErrToken(constdecl.name);
|
self.setErrToken(constdecl.name);
|
||||||
self.setErrContext("const {}", .{constdecl.name.lexeme});
|
self.setErrContext("const {}", .{constdecl.name.lexeme});
|
||||||
|
|
||||||
|
@ -566,7 +566,7 @@ pub const Analyzer = struct {
|
||||||
pub fn pass(self: *@This(), root: *ast.Node) !comp.CompilationContext {
|
pub fn pass(self: *@This(), root: *ast.Node) !comp.CompilationContext {
|
||||||
var ctx = comp.CompilationContext.init(self.allocator);
|
var ctx = comp.CompilationContext.init(self.allocator);
|
||||||
|
|
||||||
var slice = root.Root.items;
|
var slice = root.Root.toSlice();
|
||||||
for (slice) |_, idx| {
|
for (slice) |_, idx| {
|
||||||
try self.nodePass(&ctx, &slice[idx]);
|
try self.nodePass(&ctx, &slice[idx]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,15 +14,15 @@ fn printIdent(ident: usize) void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print(ident: usize, comptime fmt: []const u8, args: anytype) void {
|
fn print(ident: usize, comptime fmt: []const u8, args: var) void {
|
||||||
printIdent(ident);
|
printIdent(ident);
|
||||||
std.debug.warn(fmt, args);
|
std.debug.warn(fmt, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printBlock(ident: usize, block: anytype, endNewline: bool) void {
|
fn printBlock(ident: usize, block: var, endNewline: bool) void {
|
||||||
std.debug.warn("(\n", .{});
|
std.debug.warn("(\n", .{});
|
||||||
|
|
||||||
for (block.items) |stmt| {
|
for (block.toSlice()) |stmt| {
|
||||||
printIdent(ident);
|
printIdent(ident);
|
||||||
printStmt(ident, &stmt);
|
printStmt(ident, &stmt);
|
||||||
std.debug.warn("\n", .{});
|
std.debug.warn("\n", .{});
|
||||||
|
@ -53,7 +53,7 @@ pub fn printNode(node: *const Node, ident: usize) void {
|
||||||
warn("(fn {} {} (", .{ name, ret_type });
|
warn("(fn {} {} (", .{ name, ret_type });
|
||||||
}
|
}
|
||||||
|
|
||||||
for (decl.params.items) |param| {
|
for (decl.params.toSlice()) |param| {
|
||||||
warn(" ({} {})", .{ param.name.lexeme, param.typ.lexeme });
|
warn(" ({} {})", .{ param.name.lexeme, param.typ.lexeme });
|
||||||
}
|
}
|
||||||
warn(") ", .{});
|
warn(") ", .{});
|
||||||
|
@ -65,7 +65,7 @@ pub fn printNode(node: *const Node, ident: usize) void {
|
||||||
.ConstDecl => |consts| {
|
.ConstDecl => |consts| {
|
||||||
print(ident, "(const (\n", .{});
|
print(ident, "(const (\n", .{});
|
||||||
|
|
||||||
for (consts.items) |const_decl| {
|
for (consts.toSlice()) |const_decl| {
|
||||||
print(ident + 1, "({} ", .{
|
print(ident + 1, "({} ", .{
|
||||||
const_decl.name.lexeme,
|
const_decl.name.lexeme,
|
||||||
});
|
});
|
||||||
|
@ -80,7 +80,7 @@ pub fn printNode(node: *const Node, ident: usize) void {
|
||||||
.Enum => |decl| {
|
.Enum => |decl| {
|
||||||
print(ident, "(enum {} (\n", .{decl.name.lexeme});
|
print(ident, "(enum {} (\n", .{decl.name.lexeme});
|
||||||
|
|
||||||
for (decl.fields.items) |field| {
|
for (decl.fields.toSlice()) |field| {
|
||||||
print(ident + 1, "{}\n", .{
|
print(ident + 1, "{}\n", .{
|
||||||
field.lexeme,
|
field.lexeme,
|
||||||
});
|
});
|
||||||
|
@ -90,14 +90,14 @@ pub fn printNode(node: *const Node, ident: usize) void {
|
||||||
},
|
},
|
||||||
|
|
||||||
.Root => {
|
.Root => {
|
||||||
for (node.Root.items) |child| {
|
for (node.Root.toSlice()) |child| {
|
||||||
printNode(&child, ident + 1);
|
printNode(&child, ident + 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.Struct => |struc| {
|
.Struct => |struc| {
|
||||||
print(ident, "(struct {} (\n", .{struc.name.lexeme});
|
print(ident, "(struct {} (\n", .{struc.name.lexeme});
|
||||||
for (struc.fields.items) |field| {
|
for (struc.fields.toSlice()) |field| {
|
||||||
print(ident + 1, "({} {})\n", .{ field.name.lexeme, field.typ.lexeme });
|
print(ident + 1, "({} {})\n", .{ field.name.lexeme, field.typ.lexeme });
|
||||||
}
|
}
|
||||||
print(ident, "))\n", .{});
|
print(ident, "))\n", .{});
|
||||||
|
@ -156,7 +156,7 @@ fn binOpToStr(op: BinaryOperator) ?[]const u8 {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printBinOp(inner: anytype) void {
|
fn printBinOp(inner: var) void {
|
||||||
std.debug.warn("({}", .{binOpToStr(inner.op)});
|
std.debug.warn("({}", .{binOpToStr(inner.op)});
|
||||||
printTwoExprs(inner.left, inner.right);
|
printTwoExprs(inner.left, inner.right);
|
||||||
std.debug.warn(")", .{});
|
std.debug.warn(")", .{});
|
||||||
|
@ -203,7 +203,7 @@ pub fn printExpr(expr: *const Expr) void {
|
||||||
.Float => |val| std.debug.warn("{}", .{val}),
|
.Float => |val| std.debug.warn("{}", .{val}),
|
||||||
.String => |val| std.debug.warn("'{}'", .{val}),
|
.String => |val| std.debug.warn("'{}'", .{val}),
|
||||||
.Array => |exprs| {
|
.Array => |exprs| {
|
||||||
parenthetize("array", exprs.items);
|
parenthetize("array", exprs.toSlice());
|
||||||
},
|
},
|
||||||
else => |typ| std.debug.warn("UnknownLiteral-{}", .{typ}),
|
else => |typ| std.debug.warn("UnknownLiteral-{}", .{typ}),
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ pub fn printExpr(expr: *const Expr) void {
|
||||||
std.debug.warn("(", .{});
|
std.debug.warn("(", .{});
|
||||||
printExpr(call.callee);
|
printExpr(call.callee);
|
||||||
|
|
||||||
for (call.arguments.items) |arg| {
|
for (call.arguments.toSlice()) |arg| {
|
||||||
std.debug.warn(" ", .{});
|
std.debug.warn(" ", .{});
|
||||||
printExpr(&arg);
|
printExpr(&arg);
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ pub fn printExpr(expr: *const Expr) void {
|
||||||
.Struct => |val| {
|
.Struct => |val| {
|
||||||
std.debug.warn("({} (", .{val.name.lexeme});
|
std.debug.warn("({} (", .{val.name.lexeme});
|
||||||
|
|
||||||
for (val.inits.items) |init| {
|
for (val.inits.toSlice()) |init| {
|
||||||
std.debug.warn(" ({} ", .{init.field.lexeme});
|
std.debug.warn(" ({} ", .{init.field.lexeme});
|
||||||
printExpr(init.expr);
|
printExpr(init.expr);
|
||||||
std.debug.warn(")", .{});
|
std.debug.warn(")", .{});
|
||||||
|
@ -345,11 +345,12 @@ fn prettyType(typ: SymbolUnderlyingType) []const u8 {
|
||||||
pub fn printScope(scope: *Scope, ident: usize) void {
|
pub fn printScope(scope: *Scope, ident: usize) void {
|
||||||
print(ident, "scope '{}' at addr {}\n", .{ scope.id, @ptrToInt(scope) });
|
print(ident, "scope '{}' at addr {}\n", .{ scope.id, @ptrToInt(scope) });
|
||||||
|
|
||||||
for (scope.env.items()) |entry| {
|
var it = scope.env.iterator();
|
||||||
print(ident + 1, "sym: {}, typ: {}\n", .{ entry.key, prettyType(entry.value) });
|
while (it.next()) |kv| {
|
||||||
|
print(ident + 1, "sym: {}, typ: {}\n", .{ kv.key, prettyType(kv.value) });
|
||||||
}
|
}
|
||||||
|
|
||||||
for (scope.children.items) |child| {
|
for (scope.children.toSlice()) |child| {
|
||||||
printScope(child, ident + 1);
|
printScope(child, ident + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,11 +366,11 @@ pub fn printContext(ctx: CompilationContext) void {
|
||||||
prettyType(fn_sym.return_type),
|
prettyType(fn_sym.return_type),
|
||||||
});
|
});
|
||||||
|
|
||||||
for (fn_sym.decl.params.items) |param| {
|
for (fn_sym.decl.params.toSlice()) |param| {
|
||||||
var actual_param = fn_sym.parameters.get(param.name.lexeme).?;
|
var param_kv = fn_sym.parameters.get(param.name.lexeme).?;
|
||||||
std.debug.warn("\tparameter {} typ {}\n", .{
|
std.debug.warn("\tparameter {} typ {}\n", .{
|
||||||
param.name.lexeme,
|
param_kv.key,
|
||||||
prettyType(actual_param.typ),
|
prettyType(param_kv.value.typ),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub const Codegen = struct {
|
||||||
},
|
},
|
||||||
|
|
||||||
.Struct, .Enum => |lex| blk: {
|
.Struct, .Enum => |lex| blk: {
|
||||||
var sym_data = self.ctx.symbol_table.get(lex).?;
|
var sym_data = self.ctx.symbol_table.get(lex).?.value;
|
||||||
break :blk switch (sym_data.*) {
|
break :blk switch (sym_data.*) {
|
||||||
.Struct => unreachable,
|
.Struct => unreachable,
|
||||||
.Enum => llvm.LLVMInt32Type(),
|
.Enum => llvm.LLVMInt32Type(),
|
||||||
|
@ -64,8 +64,8 @@ pub const Codegen = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emitForVariableType(self: *@This(), vari: anytype, get: anytype, kv: anytype) !llvm.LLVMValueRef {
|
fn emitForVariableType(self: *@This(), vari: var, get: var, kv: var) !llvm.LLVMValueRef {
|
||||||
var sym = kv;
|
var sym = kv.value;
|
||||||
|
|
||||||
switch (sym.*) {
|
switch (sym.*) {
|
||||||
.Enum => |map| {
|
.Enum => |map| {
|
||||||
|
@ -76,7 +76,7 @@ pub const Codegen = struct {
|
||||||
get.name.lexeme,
|
get.name.lexeme,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return llvm.LLVMConstInt(llvm.LLVMInt32Type(), val.?, 1);
|
return llvm.LLVMConstInt(llvm.LLVMInt32Type(), val.?.value, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
.Struct => @panic("TODO handle struct"),
|
.Struct => @panic("TODO handle struct"),
|
||||||
|
@ -89,7 +89,7 @@ pub const Codegen = struct {
|
||||||
|
|
||||||
fn emitExpr(
|
fn emitExpr(
|
||||||
self: *Codegen,
|
self: *Codegen,
|
||||||
builder: anytype,
|
builder: var,
|
||||||
expr: *const ast.Expr,
|
expr: *const ast.Expr,
|
||||||
) anyerror!llvm.LLVMValueRef {
|
) anyerror!llvm.LLVMValueRef {
|
||||||
return switch (expr.*) {
|
return switch (expr.*) {
|
||||||
|
@ -176,27 +176,25 @@ pub const Codegen = struct {
|
||||||
.Call => |call| {
|
.Call => |call| {
|
||||||
const name = call.callee.*.Variable.lexeme;
|
const name = call.callee.*.Variable.lexeme;
|
||||||
|
|
||||||
var llvm_func_entry = self.llvm_table.getEntry(name);
|
var llvm_func = self.llvm_table.get(name);
|
||||||
if (llvm_func_entry == null) {
|
if (llvm_func == null) {
|
||||||
std.debug.warn("Function '{}' not found\n", .{name});
|
std.debug.warn("Function '{}' not found\n", .{name});
|
||||||
return CompileError.EmitError;
|
return CompileError.EmitError;
|
||||||
}
|
}
|
||||||
|
|
||||||
const llvm_func = llvm_func_entry.?.value;
|
|
||||||
|
|
||||||
var args = LLVMValueList.init(self.allocator);
|
var args = LLVMValueList.init(self.allocator);
|
||||||
errdefer args.deinit();
|
errdefer args.deinit();
|
||||||
|
|
||||||
for (call.arguments.items) |arg_expr| {
|
for (call.arguments.toSlice()) |arg_expr| {
|
||||||
var arg_val = try self.emitExpr(builder, &arg_expr);
|
var arg_val = try self.emitExpr(builder, &arg_expr);
|
||||||
try args.append(arg_val);
|
try args.append(arg_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
var args_slice = args.items;
|
var args_slice = args.toSlice();
|
||||||
|
|
||||||
return llvm.LLVMBuildCall(
|
return llvm.LLVMBuildCall(
|
||||||
builder,
|
builder,
|
||||||
llvm_func,
|
llvm_func.?.value,
|
||||||
args_slice.ptr,
|
args_slice.ptr,
|
||||||
@intCast(c_uint, args_slice.len),
|
@intCast(c_uint, args_slice.len),
|
||||||
"call",
|
"call",
|
||||||
|
@ -205,10 +203,10 @@ pub const Codegen = struct {
|
||||||
|
|
||||||
.Assign => |assign| {
|
.Assign => |assign| {
|
||||||
const name = assign.name.lexeme;
|
const name = assign.name.lexeme;
|
||||||
var meta = self.ctx.current_scope.?.meta_map.get(name).?;
|
var meta = self.ctx.current_scope.?.meta_map.get(name).?.value;
|
||||||
var assign_expr = try self.emitExpr(builder, assign.value);
|
var assign_expr = try self.emitExpr(builder, assign.value);
|
||||||
var llvm_alloca: llvm.LLVMValueRef = switch (meta.using) {
|
var llvm_alloca: llvm.LLVMValueRef = switch (meta.using) {
|
||||||
.Function => meta.from_function.?.parameters.get(name).?.llvm_alloca.?,
|
.Function => meta.from_function.?.parameters.get(name).?.value.llvm_alloca.?,
|
||||||
.Scope => meta.llvm_alloca.?,
|
.Scope => meta.llvm_alloca.?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -226,7 +224,7 @@ pub const Codegen = struct {
|
||||||
// we have metadata, which means we can check if the variable
|
// we have metadata, which means we can check if the variable
|
||||||
// is coming from the scope or from the function
|
// is coming from the scope or from the function
|
||||||
|
|
||||||
var metadata = kv_opt.?;
|
var metadata = kv_opt.?.value;
|
||||||
std.debug.warn("!! LOAD FROM VAR META {}\n", .{@ptrToInt(metadata)});
|
std.debug.warn("!! LOAD FROM VAR META {}\n", .{@ptrToInt(metadata)});
|
||||||
|
|
||||||
var buf = try self.allocator.alloc(u8, 512);
|
var buf = try self.allocator.alloc(u8, 512);
|
||||||
|
@ -239,13 +237,13 @@ pub const Codegen = struct {
|
||||||
|
|
||||||
return switch (metadata.using) {
|
return switch (metadata.using) {
|
||||||
.Function => blk: {
|
.Function => blk: {
|
||||||
var param = metadata.from_function.?.parameters.get(vari.lexeme).?;
|
var param = metadata.from_function.?.parameters.get(vari.lexeme).?.value;
|
||||||
break :blk llvm.LLVMBuildLoad(builder, param.llvm_alloca.?, load_cstr.ptr);
|
break :blk llvm.LLVMBuildLoad(builder, param.llvm_alloca.?, load_cstr.ptr);
|
||||||
},
|
},
|
||||||
|
|
||||||
.Scope => blk: {
|
.Scope => blk: {
|
||||||
var llvm_alloca = metadata.llvm_alloca.?;
|
var llvm_alloca = metadata.llvm_alloca.?;
|
||||||
//var var_typ = metadata.from_scope.?.env.get(vari.lexeme).?;
|
//var var_typ = metadata.from_scope.?.env.get(vari.lexeme).?.value;
|
||||||
break :blk llvm.LLVMBuildLoad(builder, llvm_alloca, load_cstr.ptr);
|
break :blk llvm.LLVMBuildLoad(builder, llvm_alloca, load_cstr.ptr);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -262,7 +260,7 @@ pub const Codegen = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emitStmt(self: *Codegen, builder: anytype, stmt: *ast.Stmt) anyerror!void {
|
fn emitStmt(self: *Codegen, builder: var, stmt: *ast.Stmt) anyerror!void {
|
||||||
std.debug.warn("cgen: emitting stmt {}\n", .{@as(ast.StmtType, stmt.*)});
|
std.debug.warn("cgen: emitting stmt {}\n", .{@as(ast.StmtType, stmt.*)});
|
||||||
|
|
||||||
switch (stmt.*) {
|
switch (stmt.*) {
|
||||||
|
@ -296,7 +294,7 @@ pub const Codegen = struct {
|
||||||
|
|
||||||
self.ctx.setScope(self.ctx.current_scope.?.nextChild());
|
self.ctx.setScope(self.ctx.current_scope.?.nextChild());
|
||||||
|
|
||||||
var then_branch = ifstmt.then_branch.items;
|
var then_branch = ifstmt.then_branch.toSlice();
|
||||||
for (then_branch) |_, idx| {
|
for (then_branch) |_, idx| {
|
||||||
// keep emitting until branch has ret
|
// keep emitting until branch has ret
|
||||||
var then_stmt = &then_branch[idx];
|
var then_stmt = &then_branch[idx];
|
||||||
|
@ -328,7 +326,7 @@ pub const Codegen = struct {
|
||||||
if (ifstmt.else_branch) |else_block| {
|
if (ifstmt.else_branch) |else_block| {
|
||||||
self.ctx.setScope(self.ctx.current_scope.?.nextChild());
|
self.ctx.setScope(self.ctx.current_scope.?.nextChild());
|
||||||
|
|
||||||
var else_slice = else_block.items;
|
var else_slice = else_block.toSlice();
|
||||||
for (else_slice) |_, idx| {
|
for (else_slice) |_, idx| {
|
||||||
// keep emitting until branch has ret
|
// keep emitting until branch has ret
|
||||||
var else_stmt = &else_slice[idx];
|
var else_stmt = &else_slice[idx];
|
||||||
|
@ -363,7 +361,7 @@ pub const Codegen = struct {
|
||||||
// analyze pass and the current scope contains the variable's
|
// analyze pass and the current scope contains the variable's
|
||||||
// type(hopefully), so we resolve it
|
// type(hopefully), so we resolve it
|
||||||
const name = vardecl.name.lexeme;
|
const name = vardecl.name.lexeme;
|
||||||
var var_metadata = self.ctx.current_scope.?.meta_map.get(name).?;
|
var var_metadata = self.ctx.current_scope.?.meta_map.get(name).?.value;
|
||||||
|
|
||||||
var name_cstr = try std.cstr.addNullByte(self.allocator, name);
|
var name_cstr = try std.cstr.addNullByte(self.allocator, name);
|
||||||
errdefer self.allocator.free(name_cstr);
|
errdefer self.allocator.free(name_cstr);
|
||||||
|
@ -394,7 +392,7 @@ pub const Codegen = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getFnSymbol(self: *@This(), name: []const u8) *comp.FunctionSymbol {
|
fn getFnSymbol(self: *@This(), name: []const u8) *comp.FunctionSymbol {
|
||||||
var fn_sym_search = self.ctx.symbol_table.get(name).?;
|
var fn_sym_search = self.ctx.symbol_table.get(name).?.value;
|
||||||
std.debug.assert(@as(comp.SymbolType, fn_sym_search.*) == .Function);
|
std.debug.assert(@as(comp.SymbolType, fn_sym_search.*) == .Function);
|
||||||
return &fn_sym_search.Function;
|
return &fn_sym_search.Function;
|
||||||
}
|
}
|
||||||
|
@ -420,22 +418,21 @@ pub const Codegen = struct {
|
||||||
var param_types = llvm.LLVMTypeList.init(self.allocator);
|
var param_types = llvm.LLVMTypeList.init(self.allocator);
|
||||||
errdefer param_types.deinit();
|
errdefer param_types.deinit();
|
||||||
|
|
||||||
for (decl.params.items) |param| {
|
for (decl.params.toSlice()) |param| {
|
||||||
try param_types.append(try self.typeToLLVM(fn_sym.parameters.get(
|
try param_types.append(try self.typeToLLVM(fn_sym.parameters.get(
|
||||||
param.name.lexeme,
|
param.name.lexeme,
|
||||||
).?.typ));
|
).?.value.typ));
|
||||||
}
|
}
|
||||||
|
|
||||||
var llvm_ret_type = llvm.LLVMFunctionType(
|
var llvm_ret_type = llvm.LLVMFunctionType(
|
||||||
try self.typeToLLVM(fn_sym.return_type),
|
try self.typeToLLVM(fn_sym.return_type),
|
||||||
param_types.items.ptr,
|
param_types.toSlice().ptr,
|
||||||
@intCast(c_uint, param_types.items.len),
|
@intCast(c_uint, param_types.len),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
var func = llvm.LLVMAddFunction(mod, name_cstr.ptr, llvm_ret_type);
|
var func = llvm.LLVMAddFunction(mod, name_cstr.ptr, llvm_ret_type);
|
||||||
std.debug.warn("inserting function '{}' to llvm table\n", .{name});
|
_ = try self.llvm_table.put(name, func);
|
||||||
try self.llvm_table.put(name, func);
|
|
||||||
|
|
||||||
var buf = try self.allocator.alloc(u8, 512);
|
var buf = try self.allocator.alloc(u8, 512);
|
||||||
var entry_lbl = try std.fmt.bufPrint(buf, "fn_{}_entry", .{name});
|
var entry_lbl = try std.fmt.bufPrint(buf, "fn_{}_entry", .{name});
|
||||||
|
@ -447,9 +444,9 @@ pub const Codegen = struct {
|
||||||
|
|
||||||
// to have the ability to mutate parameters, we must allocate them on
|
// to have the ability to mutate parameters, we must allocate them on
|
||||||
// the stack
|
// the stack
|
||||||
var params_slice = decl.params.items;
|
var params_slice = decl.params.toSlice();
|
||||||
for (params_slice) |param_node, idx| {
|
for (params_slice) |param_node, idx| {
|
||||||
var param = fn_sym.parameters.get(param_node.name.lexeme).?;
|
var param = fn_sym.parameters.get(param_node.name.lexeme).?.value;
|
||||||
|
|
||||||
const param_name_cstr = try std.cstr.addNullByte(self.allocator, param_node.name.lexeme);
|
const param_name_cstr = try std.cstr.addNullByte(self.allocator, param_node.name.lexeme);
|
||||||
errdefer self.allocator.free(param_name_cstr);
|
errdefer self.allocator.free(param_name_cstr);
|
||||||
|
@ -470,7 +467,7 @@ pub const Codegen = struct {
|
||||||
|
|
||||||
// TODO check if stmt is return and if we already
|
// TODO check if stmt is return and if we already
|
||||||
// returned before
|
// returned before
|
||||||
var body_slice = decl.body.items;
|
var body_slice = decl.body.toSlice();
|
||||||
for (body_slice) |_, idx| {
|
for (body_slice) |_, idx| {
|
||||||
try self.emitStmt(builder, &body_slice[idx]);
|
try self.emitStmt(builder, &body_slice[idx]);
|
||||||
}
|
}
|
||||||
|
@ -483,10 +480,10 @@ pub const Codegen = struct {
|
||||||
.Enum => {},
|
.Enum => {},
|
||||||
|
|
||||||
.ConstDecl => |constdecls| {
|
.ConstDecl => |constdecls| {
|
||||||
for (constdecls.items) |constdecl| {
|
for (constdecls.toSlice()) |constdecl| {
|
||||||
const name = constdecl.name.lexeme;
|
const name = constdecl.name.lexeme;
|
||||||
|
|
||||||
var const_type = self.ctx.symbol_table.get(name).?;
|
var const_type = self.ctx.symbol_table.get(name).?.value;
|
||||||
var const_llvm_type = try self.typeToLLVM(const_type.Const);
|
var const_llvm_type = try self.typeToLLVM(const_type.Const);
|
||||||
|
|
||||||
const const_name = try std.cstr.addNullByte(self.allocator, name);
|
const const_name = try std.cstr.addNullByte(self.allocator, name);
|
||||||
|
@ -518,7 +515,7 @@ pub const Codegen = struct {
|
||||||
var mod = llvm.LLVMModuleCreateWithName("awoo").?;
|
var mod = llvm.LLVMModuleCreateWithName("awoo").?;
|
||||||
defer llvm.LLVMDisposeModule(mod);
|
defer llvm.LLVMDisposeModule(mod);
|
||||||
|
|
||||||
var root_slice = root.Root.items;
|
var root_slice = root.Root.toSlice();
|
||||||
for (root_slice) |_, idx| {
|
for (root_slice) |_, idx| {
|
||||||
try self.genNode(mod, &root_slice[idx]);
|
try self.genNode(mod, &root_slice[idx]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,14 +70,13 @@ pub const Scope = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nextChild(self: *@This()) *Scope {
|
pub fn nextChild(self: *@This()) *Scope {
|
||||||
var child = self.children.items[self.cur_child_idx];
|
var child = self.children.at(self.cur_child_idx);
|
||||||
self.cur_child_idx += 1;
|
self.cur_child_idx += 1;
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *const @This()) void {
|
pub fn deinit(self: *const @This()) void {
|
||||||
// XXX: fix this someday
|
self.env.deinit();
|
||||||
// self.env.deinit();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -272,8 +271,8 @@ pub const CompilationContext = struct {
|
||||||
pub fn insertStruct(self: *@This(), struc: ast.Struct, field_types: TypeList) !void {
|
pub fn insertStruct(self: *@This(), struc: ast.Struct, field_types: TypeList) !void {
|
||||||
var type_map = UnderlyingTypeMap.init(self.allocator);
|
var type_map = UnderlyingTypeMap.init(self.allocator);
|
||||||
|
|
||||||
for (struc.fields.items) |field, idx| {
|
for (struc.fields.toSlice()) |field, idx| {
|
||||||
_ = try type_map.put(field.name.lexeme, field_types.items[idx]);
|
_ = try type_map.put(field.name.lexeme, field_types.at(idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
var symbol = try self.allocator.create(SymbolData);
|
var symbol = try self.allocator.create(SymbolData);
|
||||||
|
@ -290,13 +289,13 @@ pub const CompilationContext = struct {
|
||||||
) !void {
|
) !void {
|
||||||
var param_map = ParameterMap.init(self.allocator);
|
var param_map = ParameterMap.init(self.allocator);
|
||||||
|
|
||||||
for (decl.params.items) |param, idx| {
|
for (decl.params.toSlice()) |param, idx| {
|
||||||
var param_sym = try self.allocator.create(Parameter);
|
var param_sym = try self.allocator.create(Parameter);
|
||||||
|
|
||||||
param_sym.* = Parameter{
|
param_sym.* = Parameter{
|
||||||
.name = param.name.lexeme,
|
.name = param.name.lexeme,
|
||||||
.idx = idx,
|
.idx = idx,
|
||||||
.typ = param_types.items[idx],
|
.typ = param_types.at(idx),
|
||||||
};
|
};
|
||||||
_ = try param_map.put(param.name.lexeme, param_sym);
|
_ = try param_map.put(param.name.lexeme, param_sym);
|
||||||
}
|
}
|
||||||
|
@ -319,7 +318,7 @@ pub const CompilationContext = struct {
|
||||||
_ = try self.symbol_table.put(lex, symbol);
|
_ = try self.symbol_table.put(lex, symbol);
|
||||||
|
|
||||||
var kv = self.symbol_table.get(lex);
|
var kv = self.symbol_table.get(lex);
|
||||||
self.cur_function = &kv.?.Function;
|
self.cur_function = &kv.?.value.Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insertEnum(self: *@This(), enu: ast.Enum) !void {
|
pub fn insertEnum(self: *@This(), enu: ast.Enum) !void {
|
||||||
|
@ -327,7 +326,7 @@ pub const CompilationContext = struct {
|
||||||
errdefer ident_map.deinit();
|
errdefer ident_map.deinit();
|
||||||
|
|
||||||
// TODO change this when enums get support for custom values
|
// TODO change this when enums get support for custom values
|
||||||
for (enu.fields.items) |token, idx| {
|
for (enu.fields.toSlice()) |token, idx| {
|
||||||
_ = try ident_map.put(token.lexeme, @intCast(u32, idx));
|
_ = try ident_map.put(token.lexeme, @intCast(u32, idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +352,7 @@ pub const CompilationContext = struct {
|
||||||
return CompilationError.TypeError;
|
return CompilationError.TypeError;
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = sym_kv.?;
|
var value = sym_kv.?.value;
|
||||||
|
|
||||||
var sym_typ = @as(SymbolType, value.*);
|
var sym_typ = @as(SymbolType, value.*);
|
||||||
if (sym_typ != typ) {
|
if (sym_typ != typ) {
|
||||||
|
@ -379,7 +378,7 @@ pub const CompilationContext = struct {
|
||||||
return try VariableMetadata.withScope(
|
return try VariableMetadata.withScope(
|
||||||
self.allocator,
|
self.allocator,
|
||||||
scope,
|
scope,
|
||||||
kv,
|
kv.value,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -409,7 +408,7 @@ pub const CompilationContext = struct {
|
||||||
return try VariableMetadata.withParam(
|
return try VariableMetadata.withParam(
|
||||||
self.allocator,
|
self.allocator,
|
||||||
cur_function,
|
cur_function,
|
||||||
kv.typ,
|
kv.value.typ,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub fn reportN(line: usize, message: []const u8) void {
|
||||||
report(line, "", message);
|
report(line, "", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reportFmt(line: usize, ctx_opt: ?[]const u8, comptime fmt: []const u8, args: anytype) void {
|
pub fn reportFmt(line: usize, ctx_opt: ?[]const u8, comptime fmt: []const u8, args: var) void {
|
||||||
if (ctx_opt) |ctx| {
|
if (ctx_opt) |ctx| {
|
||||||
std.debug.warn("[line {}] Error on {}", .{ line, ctx });
|
std.debug.warn("[line {}] Error on {}", .{ line, ctx });
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -94,7 +94,7 @@ pub const Parser = struct {
|
||||||
self.tokens.deinit();
|
self.tokens.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setErrContext(self: *Parser, comptime fmt: ?[]const u8, args: anytype) void {
|
fn setErrContext(self: *Parser, comptime fmt: ?[]const u8, args: var) void {
|
||||||
if (fmt == null) {
|
if (fmt == null) {
|
||||||
self.err_ctx = null;
|
self.err_ctx = null;
|
||||||
return;
|
return;
|
||||||
|
@ -104,7 +104,7 @@ pub const Parser = struct {
|
||||||
self.err_ctx = std.fmt.bufPrint(buf, fmt.?, args) catch unreachable;
|
self.err_ctx = std.fmt.bufPrint(buf, fmt.?, args) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn doError(self: *Parser, comptime fmt: []const u8, args: anytype) ParseError {
|
fn doError(self: *Parser, comptime fmt: []const u8, args: var) ParseError {
|
||||||
self.hadError = true;
|
self.hadError = true;
|
||||||
|
|
||||||
std.debug.warn("parser error at line {}", .{self.scanner.line});
|
std.debug.warn("parser error at line {}", .{self.scanner.line});
|
||||||
|
@ -138,11 +138,11 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek(self: *Parser) Token {
|
fn peek(self: *Parser) Token {
|
||||||
return self.tokens.items[self.tokens.items.len - 1];
|
return self.tokens.at(self.tokens.len - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn previous(self: *Parser) Token {
|
fn previous(self: *Parser) Token {
|
||||||
return self.tokens.items[self.tokens.items.len - 2];
|
return self.tokens.at(self.tokens.len - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError {
|
fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError {
|
||||||
|
@ -215,7 +215,7 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// check() against multiple tokens
|
/// check() against multiple tokens
|
||||||
fn compareAnyOf(self: *@This(), ttypes: []const TokenType) bool {
|
fn compareAnyOf(self: *@This(), ttypes: []TokenType) bool {
|
||||||
for (ttypes) |typ| {
|
for (ttypes) |typ| {
|
||||||
if (self.check(typ)) return true;
|
if (self.check(typ)) return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue