summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/helloWorld.nya6
-rw-r--r--src/codegen.zig16
-rw-r--r--src/parser.zig39
-rw-r--r--src/symtable.zig34
4 files changed, 63 insertions, 32 deletions
diff --git a/examples/helloWorld.nya b/examples/helloWorld.nya
index 160d9d2..625860c 100644
--- a/examples/helloWorld.nya
+++ b/examples/helloWorld.nya
@@ -1,6 +1,8 @@
import fn puts(str: [u8]) -> i32;
fn main() -> i32 {
- puts("Hello World!");
- return 0;
+ varbl: i32 pog = puts("Hello World!");
+ pog = 8;
+ const value = pog;
+ return value;
}
diff --git a/src/codegen.zig b/src/codegen.zig
index c1fac76..8f3160e 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -11,6 +11,7 @@ const CodegenError = error{
Immutable,
OutOfMemory,
IncorrectType,
+ UnknownIdentifier,
};
fn toLLVMtype(typ: parse.TypeIdent, sym: *symb.SymbolTable, expr: ?parse.NodeExpr) types.LLVMTypeRef {
@@ -80,7 +81,14 @@ pub const Generator = struct {
const table = stmt.symtable;
const symbol = table.getValue(nodeVar.ident.ident).?;
const value = try self.genExpr(nodeVar.expr);
- const ptr = try self.genAlloc(toLLVMtype(nodeVar.expr.typ orelse try nodeVar.expr.symtable.getValue(nodeVar.ident.ident).?.typ.toTypeIdent(self.allocator), table, nodeVar.expr).?, nodeVar.ident.ident);
+ const ptr = try self.genAlloc(
+ toLLVMtype(
+ nodeVar.expr.typ orelse try nodeVar.expr.symtable.getValue(nodeVar.ident.ident).?.typ.toTypeIdent(self.allocator),
+ table,
+ nodeVar.expr,
+ ).?,
+ nodeVar.ident.ident,
+ );
_ = core.LLVMBuildStore(self.builder, value, ptr);
try self.references.put(symbol.id, ptr);
}
@@ -90,7 +98,7 @@ pub const Generator = struct {
const table = stmt.symtable;
const symbol = table.getValue(nodeVar.ident.ident).?;
- const ptr = try self.genAlloc(toLLVMtype(nodeVar.expr.typ.?, table, nodeVar.expr), nodeVar.ident.ident);
+ const ptr = try self.genAlloc(toLLVMtype(nodeVar.expr.typ orelse try nodeVar.expr.inferType(self.allocator, table), table, nodeVar.expr), nodeVar.ident.ident);
const value = try self.genExpr(nodeVar.expr);
_ = core.LLVMBuildStore(self.builder, value, ptr);
try self.references.put(symbol.id, ptr);
@@ -242,8 +250,6 @@ pub const Generator = struct {
},
.call => |call| blk: {
- std.debug.print("Function {s} requested\n", .{call.ident.ident});
-
const functype = expr.symtable.getValue(call.ident.ident).?.typ.Function;
const ident = try self.allocator.dupeZ(u8, call.ident.ident);
const function = core.LLVMGetNamedFunction(self.module, ident);
@@ -329,7 +335,7 @@ test "Codegen assign" {
const src =
\\fn main() -> i32 {
\\ const testval = 6;
- \\ varbl testvar = testval;
+ \\ varbl: i32 testvar = testval;
\\ testvar = 5;
\\ return testvar;
\\}
diff --git a/src/parser.zig b/src/parser.zig
index d4bbfc0..f2dba0a 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -17,6 +17,13 @@ const ParsingError = error{
ExpectedToken,
OutOfMemory,
TokenIteratorOnly,
+ TypeRequiredForVarbl,
+};
+
+const TypeError = error{
+ OutOfMemory,
+ IncorrectType,
+ UnknownIdentifier,
};
fn errcast(err: anytype) ParsingError {
@@ -56,6 +63,17 @@ pub const NodeExpr = struct {
}
return try childrenArray.toOwnedSlice();
}
+ pub fn inferType(self: NodeExpr, allocator: std.mem.Allocator, table: *symb.SymbolTable) TypeError!TypeIdent {
+ const expectedType = try switch (self.kind) {
+ .call => |call| if (table.getValue(call.ident.ident)) |symbol| try symbol.typ.Function.output.toTypeIdent(allocator) else TypeError.UnknownIdentifier,
+ .ident => |id| if (table.getValue(id.ident)) |symbol| try symbol.typ.toTypeIdent(allocator) else TypeError.UnknownIdentifier,
+ .intLit => TypeIdent{ .ident = "i32", .list = false },
+ .stringLit => TypeIdent{ .ident = "[u8]", .list = true },
+ };
+ if (self.typ) |typ| {
+ return if (std.mem.eql(u8, typ.ident, expectedType.ident)) expectedType else TypeError.IncorrectType;
+ } else return expectedType;
+ }
};
pub fn map(comptime T: type, comptime F: type, slice: []const F, func: fn (F) T) []const T {
@@ -182,10 +200,7 @@ pub const Parser = struct {
},
};
}
- typ = TypeIdent{
- .ident = "i32",
- .list = false,
- };
+ typ = null;
break :blk ExprKind{ .ident = ident };
},
.stringLit => {
@@ -315,7 +330,6 @@ pub const Parser = struct {
}
fn parseAssign(self: *Parser) ParsingError!NodeStmt {
- std.debug.print("{any}\n", .{self.tokens.peek().?});
const ident = (try self.tokens.consume(.ident)).?;
_ = try self.tokens.consume(.equal);
const expr = try self.parseExpr();
@@ -348,14 +362,13 @@ pub const Parser = struct {
fn parseVariable(self: *Parser) ParsingError!NodeStmt {
_ = try self.tokens.consume(.variable);
var typ: ?TypeIdent = null;
- if (self.tokens.consume(.colon)) |_| {
- typ = .{
- .ident = (try self.tokens.consume(.ident)).?.ident,
- .list = false,
- };
- } else |err| {
- if (err != tok.TokenizeError.ExpectedToken) return errcast(.{err});
- }
+ _ = self.tokens.consume(.colon) catch {
+ return ParsingError.TypeRequiredForVarbl;
+ };
+ typ = .{
+ .ident = (try self.tokens.consume(.ident)).?.ident,
+ .list = false,
+ };
const ident = (try self.tokens.consume(.ident)).?;
_ = try self.tokens.consume(.equal);
const expr = try self.parseExpr();
diff --git a/src/symtable.zig b/src/symtable.zig
index 2e6e86f..71596e2 100644
--- a/src/symtable.zig
+++ b/src/symtable.zig
@@ -23,7 +23,7 @@ pub const SymbType = union(enum) {
pub fn toSymb(self: SymbType) Symbol {
return Symbol{ .Type = self };
}
- pub fn toString(self: SymbType, allocator: std.mem.Allocator) ![]const u8 {
+ pub fn toString(self: SymbType, allocator: std.mem.Allocator) error{OutOfMemory}![]const u8 {
return switch (self) {
.Integer => "i32",
.Character => "u8",
@@ -33,15 +33,20 @@ pub const SymbType = union(enum) {
var argstring: []const u8 = "";
if (fun.input.len != 0) {
argstring = try fun.input[0].toString(allocator);
- for (1..fun.input.len) |i|
- argstring = try std.mem.join(allocator, ", ", &[_][]const u8{ argstring, try fun.input[i].toString(allocator) });
+ for (1..fun.input.len) |i| {
+ const inputTyp = [_][]const u8{
+ argstring,
+ try fun.input[i].toString(allocator),
+ };
+ argstring = try std.mem.join(allocator, ", ", &inputTyp);
+ }
}
break :blk try std.fmt.allocPrint(allocator, "fn({s})->{s}", .{ argstring, output });
},
else => "void",
};
}
- pub fn toTypeIdent(self: SymbType, allocator: std.mem.Allocator) !pars.TypeIdent {
+ pub fn toTypeIdent(self: SymbType, allocator: std.mem.Allocator) error{OutOfMemory}!pars.TypeIdent {
return pars.TypeIdent{
.ident = try self.toString(allocator),
.list = switch (self) {
@@ -66,7 +71,7 @@ pub const SymbolTable = struct {
scope: ?*Scope = null,
allocator: std.mem.Allocator,
- pub fn init(allocator: std.mem.Allocator) !*SymbolTable {
+ pub fn init(allocator: std.mem.Allocator) error{OutOfMemory}!*SymbolTable {
const scope = try allocator.create(Scope);
scope.par = null;
scope.symbs = std.StringHashMap(Symbol).init(allocator);
@@ -100,7 +105,7 @@ pub const SymbolTable = struct {
self.allocator.destroy(self);
}
- pub fn makeChild(self: *SymbolTable) !*SymbolTable {
+ pub fn makeChild(self: *SymbolTable) error{OutOfMemory}!*SymbolTable {
const scope = try self.allocator.create(Scope);
scope.par = self.scope;
scope.symbs = try self.scope.?.symbs.clone();
@@ -185,10 +190,10 @@ pub const Populator = struct {
.Stmt => |stmt| {
const table: *SymbolTable = stmt.symtable;
switch (stmt.kind) {
- .defVar => |variable| {
+ .defVar => |*variable| {
const symbol: Symbol = try self.buildValueSymb(
table,
- if (variable.expr.typ) |typ| typ else pars.TypeIdent{ .ident = "i32", .list = false },
+ try variable.expr.inferType(self.allocator, table),
true,
);
if (!try table.insert(variable.ident.ident, symbol)) return error.FailedToInsert;
@@ -196,7 +201,7 @@ pub const Populator = struct {
.defValue => |value| {
const symbol: Symbol = try self.buildValueSymb(
table,
- if (value.expr.typ) |typ| typ else pars.TypeIdent{ .ident = "i32", .list = false },
+ try value.expr.inferType(self.allocator, table),
false,
);
if (!try table.insert(value.ident.ident, symbol)) return error.FailedToInsert;
@@ -215,13 +220,19 @@ pub const Populator = struct {
);
if (!try table.insert(fun.ident.ident, symbol)) return error.FailedToInsert;
- std.debug.print("Function {s} inserted\n", .{fun.ident.ident});
if (fun.block == null) return;
const block = fun.block.?.asNode();
try self.populateSymtable(&block);
},
+ .assignVar => |assign| _ = {
+ const expectedType = try if (table.getValue(assign.ident.ident)) |symbol| try symbol.typ.toTypeIdent(self.allocator) else error.UnknownIdentifier;
+ const actualType = try assign.expr.inferType(self.allocator, table);
+ if (!std.mem.eql(u8, actualType.ident, expectedType.ident)) return error.IncorrectType;
+ },
+ .exit => |exit| _ = try exit.inferType(self.allocator, table),
+ .expr => {},
- else => {},
+ // else => return error.Unimplemented,
}
},
else => {
@@ -263,7 +274,6 @@ pub const Populator = struct {
}
const name = try std.fmt.allocPrint(self.allocator, "fn({s})->{s}", .{ argstring, try output.toString(self.allocator) });
- std.debug.print("Function type => \"{s}\"\n", .{name});
_ = try table.insert(name, typ.toSymb());
return Symbol{