summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen.zig144
-rw-r--r--src/main.zig25
-rw-r--r--src/parser.zig184
-rw-r--r--src/symtable.zig51
-rw-r--r--src/tokenize.zig50
5 files changed, 371 insertions, 83 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 59ef03b..3922a75 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -12,10 +12,12 @@ const CodegenError = error{
OutOfMemory,
};
-fn toLLVMtype(typ: parse.TypeIdent, sym: *symb.SymbolTable) types.LLVMTypeRef {
+fn toLLVMtype(typ: parse.TypeIdent, sym: *symb.SymbolTable, expr: ?parse.NodeExpr) types.LLVMTypeRef {
+ _ = expr;
if (sym.getType(typ)) |t| {
return switch (t) {
.Integer => core.LLVMInt32Type(),
+ .String => core.LLVMPointerType(core.LLVMInt8Type(), 0),
.Void => core.LLVMVoidType(),
else => core.LLVMVoidType(),
};
@@ -32,15 +34,16 @@ pub const Generator = struct {
currentFunc: ?types.LLVMValueRef,
currentFuncIsVoid: bool,
references: std.AutoHashMap(u32, types.LLVMValueRef),
+ stringId: u32,
- pub fn init(allocator: std.mem.Allocator, root: parse.NodeStmt) Generator {
+ pub fn init(allocator: std.mem.Allocator, root: parse.NodeStmt, filename: [*:0]const u8) Generator {
_ = target.LLVMInitializeNativeTarget();
_ = target.LLVMInitializeNativeAsmPrinter();
_ = target.LLVMInitializeNativeAsmParser();
const context = core.LLVMContextCreate();
const builder = core.LLVMCreateBuilderInContext(context);
- const module = core.LLVMModuleCreateWithNameInContext("_calico_start", context);
+ const module = core.LLVMModuleCreateWithNameInContext(filename, context);
return .{
.root = root,
@@ -51,6 +54,7 @@ pub const Generator = struct {
.currentFunc = null,
.currentFuncIsVoid = false,
.references = std.AutoHashMap(u32, types.LLVMValueRef).init(allocator),
+ .stringId = 0,
};
}
@@ -65,7 +69,7 @@ pub const Generator = struct {
fn genExit(self: *Generator, exit: parse.NodeExit) !void {
const expr = exit;
- const val = self.genExpr(expr);
+ const val = try self.genExpr(expr);
_ = core.LLVMBuildRet(self.builder, val);
}
@@ -74,8 +78,8 @@ pub const Generator = struct {
const table = stmt.symtable;
const symbol = table.getValue(nodeVar.ident.ident).?;
- const value = self.genExpr(nodeVar.expr);
- const ptr = try self.genAlloc(toLLVMtype(nodeVar.expr.typ.?, table).?, nodeVar.ident.ident);
+ const value = try self.genExpr(nodeVar.expr);
+ const ptr = try self.genAlloc(toLLVMtype(nodeVar.expr.typ.?, table, nodeVar.expr).?, nodeVar.ident.ident);
_ = core.LLVMBuildStore(self.builder, value, ptr);
try self.references.put(symbol.id, ptr);
}
@@ -85,8 +89,8 @@ 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.ident.ident);
- const value = self.genExpr(nodeVar.expr);
+ const ptr = try self.genAlloc(toLLVMtype(nodeVar.expr.typ.?, 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);
}
@@ -115,12 +119,12 @@ pub const Generator = struct {
}
fn genAssign(self: *Generator, stmt: parse.NodeStmt) !void {
- std.debug.print("assign\n", .{});
+ // std.debug.print("assign\n", .{});
const table = stmt.symtable;
const symbol = table.get(stmt.kind.assignVar.ident.ident).?;
if (!symbol.Value.mut) return CodegenError.Immutable;
const ptr = self.references.get(symbol.Value.id).?;
- const value = self.genExpr(stmt.kind.assignVar.expr);
+ const value = try self.genExpr(stmt.kind.assignVar.expr);
_ = core.LLVMBuildStore(self.builder, value, ptr);
}
@@ -129,31 +133,48 @@ pub const Generator = struct {
}
fn genFunc(self: *Generator, stmt: parse.NodeStmt) !void {
+ self.references.clearAndFree();
const fun = stmt.kind.function;
- const table = stmt.symtable;
- const block = fun.block;
- const codeSlice = block.kind.block;
+ var table: *symb.SymbolTable = stmt.symtable;
+ var block: *parse.NodeStmt = undefined;
+ var codeSlice: []const parse.NodeStmt = undefined;
+ if (fun.block != null) {
+ table = fun.block.?.symtable;
+ block = fun.block.?;
+ codeSlice = block.kind.block;
+ }
const funcName: [*:0]const u8 = try self.allocator.dupeZ(u8, fun.ident.ident);
- const retType = toLLVMtype(fun.retType.?, table);
- var params = [0]types.LLVMTypeRef{};
- const funcType = core.LLVMFunctionType(retType, @ptrCast(&params), 0, 0);
- const func = core.LLVMAddFunction(self.module, funcName, funcType);
- self.currentFunc = func;
- self.currentFuncIsVoid = switch (table.getType(fun.retType.?).?) {
- .Void => true,
- else => false,
- };
+ const retType = toLLVMtype(fun.retType.?, table, null);
+ var params = std.ArrayList(types.LLVMTypeRef).init(self.allocator);
+ for (fun.args) |arg| {
+ try params.append(toLLVMtype(arg.typ, table, null));
+ }
- const function: types.LLVMValueRef = self.currentFunc.?;
- const codeBlock = core.LLVMAppendBasicBlockInContext(self.context, function, "entry");
- core.LLVMPositionBuilderAtEnd(self.builder, codeBlock);
- const bodyTable = block.symtable;
- _ = bodyTable;
- //TODO: codegen for args
+ const funcType = core.LLVMFunctionType(retType, @ptrCast(params.items), @intCast(params.items.len), 0);
+ const func = core.LLVMAddFunction(self.module, funcName, funcType);
+ for (fun.args, 0..) |arg, i| {
+ const symbol = table.get(arg.ident).?;
+ const ptr: types.LLVMValueRef = core.LLVMGetParam(func, @intCast(i));
+ try self.references.put(symbol.Value.id, ptr);
+ }
- try self.genBlock(codeSlice);
- _ = if (self.currentFuncIsVoid) core.LLVMBuildRetVoid(self.builder);
+ if (fun.block != null) {
+ self.currentFunc = func;
+ self.currentFuncIsVoid = switch (table.getType(fun.retType.?).?) {
+ .Void => true,
+ else => false,
+ };
+
+ const function: types.LLVMValueRef = func;
+ const codeBlock = core.LLVMAppendBasicBlockInContext(self.context, function, "entry");
+ core.LLVMPositionBuilderAtEnd(self.builder, codeBlock);
+ const bodyTable = block.symtable;
+ _ = bodyTable;
+
+ try self.genBlock(codeSlice);
+ _ = if (self.currentFuncIsVoid) core.LLVMBuildRetVoid(self.builder);
+ }
}
fn genStmt(self: *Generator, stmt: parse.NodeStmt) !void {
@@ -163,19 +184,74 @@ pub const Generator = struct {
.defValue => self.genValue(stmt),
.defVar => self.genVar(stmt),
.assignVar => self.genAssign(stmt),
+ .expr => |expression| {
+ _ = try self.genExpr(expression);
+ },
+
else => {},
};
}
- fn genExpr(self: *Generator, expr: parse.NodeExpr) types.LLVMValueRef {
+ fn genExpr(self: *Generator, expr: parse.NodeExpr) !types.LLVMValueRef {
return switch (expr.kind) {
- .ident => blk: {
+ .ident => |id| blk: {
+ // std.debug.print("getValue({s})\n", .{id.ident});
const table = expr.symtable;
- const symbol = table.getValue(expr.kind.ident.ident).?;
+
+ // std.debug.print("\n\nEXPERTABLE\n\n", .{});
+ // var iterTable = table.scope.?.symbs.iterator();
+ // while (iterTable.next()) |entry| {
+ // // std.debug.print("{s} -> {any}\n", .{ entry.key_ptr.*, entry.value_ptr.* });
+ // }
+ // std.debug.print("\n\nEXPERTABLE\n\n", .{});
+ const symbol = table.getValue(id.ident).?;
const ptr = self.references.get(symbol.id).?;
- break :blk core.LLVMBuildLoad2(self.builder, toLLVMtype(expr.typ.?, table), ptr, "");
+ if (core.LLVMIsAArgument(ptr)) |_|
+ break :blk ptr;
+
+ break :blk core.LLVMBuildLoad2(self.builder, toLLVMtype(expr.typ.?, table, expr), ptr, "");
},
.intLit => |int| core.LLVMConstInt(core.LLVMInt32TypeInContext(self.context), @intCast(int.intLit), 1),
+ .stringLit => |str| blk: {
+ const vref = core.LLVMAddGlobal(
+ self.module,
+ core.LLVMArrayType(core.LLVMInt8Type(), @intCast(str.stringLit.len + 1)),
+ try self.allocator.dupeZ(u8, try std.fmt.allocPrint(
+ self.allocator,
+ ".str.{d}",
+ .{self.stringId},
+ )),
+ );
+ self.stringId += 1;
+ const sref = core.LLVMConstString(try self.allocator.dupeZ(u8, str.stringLit), @intCast(str.stringLit.len), 0);
+ core.LLVMSetInitializer(vref, sref);
+ core.LLVMSetGlobalConstant(vref, 1);
+ core.LLVMSetLinkage(vref, .LLVMPrivateLinkage);
+ core.LLVMSetUnnamedAddr(vref, 1);
+ break :blk vref;
+ },
+
+ .call => |call| blk: {
+ const ident = try self.allocator.dupeZ(u8, call.ident.ident);
+ const function = core.LLVMGetNamedFunction(self.module, ident);
+ var args = std.ArrayList(types.LLVMValueRef).init(self.allocator);
+ for (call.args) |arg|
+ try args.append(try self.genExpr(arg));
+ const funcType = core.LLVMGlobalGetValueType(function);
+ // std.debug.print("FUNCTYPE: {s}\n", .{call.ident.ident});
+
+ const llvmCall = core.LLVMBuildCall2(
+ self.builder,
+ funcType,
+ function,
+ @ptrCast(args.items),
+ @intCast(call.args.len),
+ ident,
+ );
+ // std.debug.print("CALL\n", .{});
+
+ break :blk llvmCall;
+ },
};
}
diff --git a/src/main.zig b/src/main.zig
index 1e54dec..a326685 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -47,22 +47,27 @@ pub fn main() !void {
const tokens = try tokenizer.tokenize();
// Parse
- var symbTable = try initSymbolTable(allocator);
- defer symbTable.deinit();
+ var arena = std.heap.ArenaAllocator.init(allocator);
+ defer arena.deinit();
+ const symbTable = try initSymbolTable(arena.allocator());
- var parser = parse.Parser.init(allocator, tokens, symbTable);
- defer parser.deinit();
+ var parser = parse.Parser.init(arena.allocator(), tokens, symbTable);
const tree = try parser.parse();
var treeNode = tree.asNode();
- var pop = symb.Populator.init(allocator);
+ var pop = symb.Populator.init(arena.allocator());
try pop.populateSymtable(&treeNode);
+ // var iter = symbTable.scope.?.symbs.iterator();
+ // while (iter.next()) |entry| {
+ // std.debug.print("{s} -> {any}\n", .{ entry.key_ptr.*, entry.value_ptr.* });
+ // }
// Codegen
- var arena = std.heap.ArenaAllocator.init(allocator);
- defer arena.deinit();
- var generator = gen.Generator.init(arena.allocator(), tree);
+ const fname = try allocator.dupeZ(u8, inputFileName.?);
+ defer allocator.free(fname);
+ var generator = gen.Generator.init(arena.allocator(), tree, @ptrCast(fname));
defer generator.deinit();
const code = try generator.generate();
+ std.debug.print("{s}\n", .{code});
try outWriter.writeAll(code);
const binFile = try getFileName(allocator, out_name, "");
@@ -83,6 +88,10 @@ inline fn getFileName(allocator: std.mem.Allocator, out_name: []const u8, fileTy
pub fn initSymbolTable(allocator: std.mem.Allocator) !*symb.SymbolTable {
var table = try symb.SymbolTable.init(allocator);
const intSymb: symb.SymbType = symb.SymbType.Integer;
+ const charSymb: symb.SymbType = symb.SymbType.Character;
+ const strSymb: symb.SymbType = symb.SymbType.String;
if (!try table.insert("i32", intSymb.toSymb())) return error.FailedToInsert;
+ if (!try table.insert("u8", charSymb.toSymb())) return error.FailedToInsert;
+ if (!try table.insert("[u8]", strSymb.toSymb())) return error.FailedToInsert;
return table;
}
diff --git a/src/parser.zig b/src/parser.zig
index 08f098c..2e6bd85 100644
--- a/src/parser.zig
+++ b/src/parser.zig
@@ -16,8 +16,13 @@ const ParsingError = error{
UnexpectedEOF,
ExpectedToken,
OutOfMemory,
+ TokenIteratorOnly,
};
+fn errcast(err: anytype) ParsingError {
+ return err[0];
+}
+
pub const Node = union(enum) {
Expr: NodeExpr,
Stmt: NodeStmt,
@@ -84,7 +89,8 @@ pub const NodeStmt = struct {
const blockChildren = map(Node, NodeStmt, block, NodeStmt.asNode);
for (blockChildren) |child| try childrenArray.append(child);
},
- .function => |fun| try childrenArray.append(fun.block.*.asNode()),
+ .function => |fun| if (fun.block == null) {} else try childrenArray.append(fun.block.?.asNode()),
+ .expr => |expr| try childrenArray.append(expr.asNode()),
}
return try childrenArray.toOwnedSlice();
}
@@ -126,7 +132,9 @@ pub const Parser = struct {
const children = try node.children(self.allocator);
defer self.allocator.free(children);
for (children) |child| try self.dinitHelper(child.Stmt);
- self.allocator.destroy(fun.block);
+ self.allocator.free(fun.args);
+ if (fun.block != null)
+ self.allocator.destroy(fun.block.?);
},
else => {},
}
@@ -154,12 +162,39 @@ pub const Parser = struct {
},
.ident => {
const ident = (try self.tokens.consume(.ident)).?;
+ if (tok.checkType(self.tokens.peek().?, .openParen)) {
+ _ = try self.tokens.consume(.openParen);
+
+ break :blk ExprKind{
+ .call = .{
+ .ident = ident,
+ .args = innerblk: {
+ var argExprs = std.ArrayList(NodeExpr).init(self.allocator);
+ while (!tok.checkType(self.tokens.peek().?, .closeParen)) {
+ try argExprs.append(try self.parseExpr());
+ if (tok.checkType(self.tokens.peek().?, .closeParen)) break;
+ _ = try self.tokens.consume(.comma);
+ }
+ _ = try self.tokens.consume(.closeParen);
+
+ break :innerblk try argExprs.toOwnedSlice();
+ },
+ },
+ };
+ }
typ = TypeIdent{
.ident = "i32",
.list = false,
};
break :blk ExprKind{ .ident = ident };
},
+ .stringLit => {
+ typ = TypeIdent{
+ .ident = "[u8]",
+ .list = true,
+ };
+ break :blk ExprKind{ .stringLit = (try self.tokens.consume(.stringLit)).? };
+ },
else => break :blk ParsingError.InvalidExpression,
};
};
@@ -177,22 +212,67 @@ pub const Parser = struct {
.exit => try self.parseExit(),
.constant => try self.parseConstant(),
.variable => try self.parseVariable(),
- .ident => try self.parseAssign(),
- .fun => try self.parseFunc(),
- else => ParsingError.InvalidStatement,
+ .ident => blk: {
+ if (!tok.checkType(self.tokens.peekAhead(1).?, .openParen))
+ break :blk try self.parseAssign();
+ break :blk try self.parseExprStmt();
+ },
+ .fun => try self.parseFunc(false),
+ .import => try self.parseFunc(true),
+ else => self.parseExprStmt(),
+ };
+ }
+
+ fn parseExprStmt(self: *Parser) ParsingError!NodeStmt {
+ const kind: StmtKind = StmtKind{ .expr = try self.parseExpr() };
+ _ = try self.tokens.consume(.semiCol);
+ return NodeStmt{
+ .id = self.reserveId(),
+ .symtable = self.top,
+ .kind = kind,
};
}
- fn parseFunc(self: *Parser) ParsingError!NodeStmt {
+ fn parseFunc(self: *Parser, external: bool) ParsingError!NodeStmt {
+ if (external) _ = try self.tokens.consume(.import);
var typ: ?TypeIdent = null;
_ = try self.tokens.consume(.fun);
const ident = (try self.tokens.consume(.ident)).?;
_ = try self.tokens.consume(.openParen);
- //TODO: Argument Parsing
+ var args = std.ArrayList(FunctionArg).init(self.allocator);
+ defer args.deinit();
+ while (!tok.checkType(self.tokens.peek().?, .closeParen)) {
+ const argIdent: Token = (try self.tokens.consume(.ident)).?;
+ _ = try self.tokens.consume(.colon);
+ const argTypIdent: TypeIdent = try self.parseType();
+ const funcArg: FunctionArg = .{
+ .ident = argIdent.ident,
+ .typ = argTypIdent,
+ };
+ try args.append(funcArg);
+ if (!tok.checkType(self.tokens.peek().?, .comma)) break;
+ _ = try self.tokens.consume(.comma);
+ }
_ = try self.tokens.consume(.closeParen);
if (tok.checkType(self.tokens.peek().?, .arrow)) {
self.tokens.skip();
- typ = TypeIdent{ .ident = (try self.tokens.consume(.ident)).?.ident, .list = false };
+ typ = try self.parseType();
+ }
+
+ if (external) {
+ _ = try self.tokens.consume(.semiCol);
+ return NodeStmt{
+ .id = self.reserveId(),
+ .kind = StmtKind{
+ .function = .{
+ .ident = ident,
+ .args = try args.toOwnedSlice(),
+ .retType = typ,
+ .block = null,
+ },
+ },
+ .symtable = self.top,
+ };
}
const block = try self.allocator.create(NodeStmt);
@@ -201,7 +281,7 @@ pub const Parser = struct {
const kind = StmtKind{
.function = .{
.ident = ident,
- .args = &[_]TypeIdent{},
+ .args = try args.toOwnedSlice(),
.retType = typ,
.block = block,
},
@@ -214,11 +294,14 @@ pub const Parser = struct {
};
}
- fn parseBlock(self: *Parser) !NodeStmt {
+ fn parseBlock(self: *Parser) ParsingError!NodeStmt {
_ = try self.tokens.consume(.openBrace);
var stmtArr = std.ArrayList(NodeStmt).init(self.allocator);
+ const child = try self.top.makeChild();
+ self.top = child;
while (!tok.checkType(self.tokens.peek().?, .closeBrace))
try stmtArr.append(try self.parseStmt());
+ self.top = self.top.parent().?;
_ = try self.tokens.consume(.closeBrace);
const kind = StmtKind{
.block = try stmtArr.toOwnedSlice(),
@@ -227,11 +310,11 @@ pub const Parser = struct {
return NodeStmt{
.id = self.reserveId(),
.kind = kind,
- .symtable = try self.top.makeChild(),
+ .symtable = child,
};
}
- fn parseAssign(self: *Parser) !NodeStmt {
+ fn parseAssign(self: *Parser) ParsingError!NodeStmt {
const ident = (try self.tokens.consume(.ident)).?;
_ = try self.tokens.consume(.equal);
const expr = try self.parseExpr();
@@ -250,7 +333,7 @@ pub const Parser = struct {
}
fn parseExit(self: *Parser) ParsingError!NodeStmt {
- _ = try self.tokens.consume(.exit);
+ _ = self.tokens.consume(.exit) catch |err| return errcast(.{err});
const expr = try self.parseExpr();
_ = try self.tokens.consume(.semiCol);
const kind = StmtKind{ .exit = expr };
@@ -261,8 +344,17 @@ pub const Parser = struct {
};
}
- fn parseVariable(self: *Parser) !NodeStmt {
+ fn parseVariable(self: *Parser) ParsingError!NodeStmt {
_ = try self.tokens.consume(.variable);
+ var typ: TypeIdent = undefined;
+ 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});
+ }
const ident = (try self.tokens.consume(.ident)).?;
_ = try self.tokens.consume(.equal);
const expr = try self.parseExpr();
@@ -270,7 +362,13 @@ pub const Parser = struct {
const kind = StmtKind{
.defVar = NodeVar{
.ident = ident,
- .expr = expr,
+ .expr = NodeExpr{
+ .typ = typ,
+ .id = expr.id,
+ .kind = expr.kind,
+ .isConst = expr.isConst,
+ .symtable = expr.symtable,
+ },
},
};
return NodeStmt{
@@ -280,16 +378,46 @@ pub const Parser = struct {
};
}
- fn parseConstant(self: *Parser) !NodeStmt {
+ fn parseType(self: *Parser) ParsingError!TypeIdent {
+ const list = tok.checkType(self.tokens.peek().?, .openBracket);
+ if (list) {
+ _ = try self.tokens.consume(.openBracket);
+ const typ = (try self.parseType()).ident;
+ _ = try self.tokens.consume(.closeBracket);
+ return .{
+ .ident = try std.fmt.allocPrint(self.allocator, "[{s}]", .{typ}),
+ .list = true,
+ };
+ }
+ return .{
+ .ident = (try self.tokens.consume(.ident)).?.ident,
+ .list = false,
+ };
+ }
+
+ fn parseConstant(self: *Parser) ParsingError!NodeStmt {
_ = try self.tokens.consume(.constant);
+ var typ: ?TypeIdent = null;
+ _ = if (self.tokens.consume(.colon)) |_| {
+ typ = try self.parseType();
+ } else |err| {
+ if (err != tok.TokenizeError.ExpectedToken) return err;
+ };
+
const ident = (try self.tokens.consume(.ident)).?;
_ = try self.tokens.consume(.equal);
- const expr = try self.parseExpr();
+ const expr: NodeExpr = try self.parseExpr();
_ = try self.tokens.consume(.semiCol);
const kind = StmtKind{
.defValue = NodeValue{
.ident = ident,
- .expr = expr,
+ .expr = NodeExpr{
+ .typ = typ orelse expr.typ,
+ .id = expr.id,
+ .kind = expr.kind,
+ .isConst = expr.isConst,
+ .symtable = expr.symtable,
+ },
},
};
return NodeStmt{
@@ -316,11 +444,16 @@ pub const TypeIdent = struct {
list: bool,
};
+pub const FunctionArg = struct {
+ ident: []const u8,
+ typ: TypeIdent,
+};
+
pub const NodeFunction = struct {
ident: Token,
- args: []const TypeIdent,
+ args: []const FunctionArg,
retType: ?TypeIdent,
- block: *NodeStmt,
+ block: ?*NodeStmt,
};
pub const NodeAssign = struct {
@@ -340,9 +473,15 @@ pub const NodeVar = struct {
pub const NodeExit = NodeExpr;
pub const NodeIntlit = Token;
+pub const NodeStringlit = Token;
pub const NodeIdent = Token;
pub const NodeBlock = []const NodeStmt;
+pub const NodeCall = struct {
+ ident: Token,
+ args: []const NodeExpr,
+};
+
pub const StmtKind = union(enum) {
function: NodeFunction,
exit: NodeExit,
@@ -350,16 +489,21 @@ pub const StmtKind = union(enum) {
defVar: NodeVar,
assignVar: NodeAssign,
block: NodeBlock,
+ expr: NodeExpr,
};
pub const ExprKind = union(enum) {
intLit: NodeIntlit,
+ stringLit: NodeStringlit,
ident: NodeIdent,
+ call: NodeCall,
pub fn isConstant(self: ExprKind) bool {
return switch (self) {
.intLit => true,
+ .stringLit => true,
.ident => false,
+ .call => false,
};
}
};
diff --git a/src/symtable.zig b/src/symtable.zig
index 60e871c..6ddee01 100644
--- a/src/symtable.zig
+++ b/src/symtable.zig
@@ -14,6 +14,7 @@ pub const Symbol = union(enum) {
pub const SymbType = union(enum) {
Void,
Integer,
+ Character,
String,
Function: struct {
input: []const SymbType,
@@ -25,6 +26,7 @@ pub const SymbType = union(enum) {
pub fn toString(self: SymbType) []const u8 {
return switch (self) {
.Integer => "i32",
+ .Character => "u8",
else => "void",
};
}
@@ -40,6 +42,7 @@ pub const SymbValue = struct {
};
pub const SymbolTable = struct {
+ par: ?*SymbolTable,
scope: ?*Scope = null,
allocator: std.mem.Allocator,
@@ -49,6 +52,7 @@ pub const SymbolTable = struct {
scope.symbs = std.StringHashMap(Symbol).init(allocator);
const table = try allocator.create(SymbolTable);
table.* = SymbolTable{
+ .par = null,
.scope = scope,
.allocator = allocator,
};
@@ -79,9 +83,10 @@ pub const SymbolTable = struct {
pub fn makeChild(self: *SymbolTable) !*SymbolTable {
const scope = try self.allocator.create(Scope);
scope.par = self.scope;
- scope.symbs = std.StringHashMap(Symbol).init(self.allocator);
+ scope.symbs = try self.scope.?.symbs.clone();
const stable: *SymbolTable = try self.allocator.create(SymbolTable);
stable.* = .{
+ .par = self,
.scope = scope,
.allocator = self.allocator,
};
@@ -89,9 +94,8 @@ pub const SymbolTable = struct {
}
pub fn parent(self: SymbolTable) ?*SymbolTable {
- if (self.scope) |scope|
- if (scope.par) |par|
- return par;
+ if (self.par) |par|
+ return par;
return null;
}
@@ -130,6 +134,7 @@ pub const SymbolTable = struct {
}
pub fn insert(self: *SymbolTable, ident: []const u8, symbol: Symbol) !bool {
+ // std.debug.print("Inserted {s} as {any}\n", .{ ident, symbol });
if (self.scope) |scope| {
if (scope.symbs.getEntry(ident)) |_| return false;
try scope.symbs.put(ident, symbol);
@@ -150,7 +155,7 @@ pub const Populator = struct {
pub fn init(allocator: std.mem.Allocator) Populator {
return .{
- .id = 0,
+ .id = 1,
.allocator = allocator,
};
}
@@ -179,20 +184,29 @@ pub const Populator = struct {
.block => {
const children = try stmt.children(self.allocator);
defer self.allocator.free(children);
- for (children) |child| {
- try self.populateSymtable(&child);
- }
+ for (children) |child| try self.populateSymtable(&child);
},
.function => |fun| {
+ const bodyTable = if (fun.block == null) stmt.symtable else fun.block.?.symtable;
const symbol: Symbol = try self.buildFunctionSymb(
- table,
+ bodyTable,
fun.args,
fun.retType,
);
if (!try table.insert(fun.ident.ident, symbol)) return error.FailedToInsert;
- const children = try stmt.children(self.allocator);
- defer self.allocator.free(children);
- for (children) |child| try self.populateSymtable(&child);
+ if (fun.block == null) return;
+ // var iter = fun.block.?.symtable.scope.?.symbs.iterator();
+ // while (iter.next()) |val| {
+ // // std.debug.print("{s}\n", .{val.key_ptr.*});
+ // }
+
+ const block = fun.block.?.asNode();
+ try self.populateSymtable(&block);
+
+ // var iterTable = bodyTable.scope.?.symbs.iterator();
+ // while (iterTable.next()) |entry| {
+ // // std.debug.print("{s} -> {any}\n", .{ entry.key_ptr.*, entry.value_ptr.* });
+ // }
},
else => {},
@@ -208,11 +222,16 @@ pub const Populator = struct {
fn buildFunctionSymb(
self: *Populator,
table: *SymbolTable,
- args: []const pars.TypeIdent,
+ args: []const pars.FunctionArg,
retType: ?pars.TypeIdent,
) !Symbol {
var inputArr = std.ArrayList(SymbType).init(self.allocator);
- for (args) |arg| try inputArr.append(table.getType(arg) orelse SymbType.Void);
+ for (args) |arg| {
+ // std.debug.print("{s}: {s}\n", .{ arg.ident, arg.typ.ident });
+ const argSymb = try self.buildValueSymb(table, arg.typ, false);
+ if (!try table.insert(arg.ident, argSymb)) return error.FailedToInsert;
+ try inputArr.append(table.getType(arg.typ) orelse SymbType.Void);
+ }
const input = try inputArr.toOwnedSlice();
const output = try self.allocator.create(SymbType);
@@ -225,7 +244,8 @@ pub const Populator = struct {
};
const id = self.reserveId();
- _ = try table.insert("func_" ++ .{@as(u8, @truncate(id))}, typ.toSymb());
+ const name = try std.fmt.allocPrint(self.allocator, "func_{d}", .{id});
+ _ = try table.insert(name, typ.toSymb());
return Symbol{
.Value = SymbValue{
@@ -245,6 +265,7 @@ pub const Populator = struct {
};
return value.toSymb();
}
+ // std.debug.print("{s}: ", .{typ.ident});
return error.UnknownType;
}
};
diff --git a/src/tokenize.zig b/src/tokenize.zig
index 770f483..aa3788c 100644
--- a/src/tokenize.zig
+++ b/src/tokenize.zig
@@ -4,17 +4,21 @@ pub const TokenizeError = error{
UnknownToken,
UnexpectedEOF,
ExpectedToken,
+ TokenIteratorOnly,
};
pub const TokenType = enum {
// Runtime Values
ident,
+ stringLit,
intLit,
+ charLit,
// Keywords
constant,
variable,
exit,
fun,
+ import,
// Operators
plus,
minus,
@@ -27,18 +31,25 @@ pub const TokenType = enum {
closeBrace,
openParen,
closeParen,
+ openBracket,
+ closeBracket,
+ colon,
+ comma,
arrow,
};
pub const Token = union(TokenType) {
//RuntimeVar
ident: []const u8,
+ stringLit: []const u8,
intLit: i32,
+ charLit: u8,
// Keywords
constant,
variable,
exit,
fun,
+ import,
// Operators
plus,
minus,
@@ -51,6 +62,10 @@ pub const Token = union(TokenType) {
closeBrace,
openParen,
closeParen,
+ openBracket,
+ closeBracket,
+ colon,
+ comma,
arrow,
pub fn fromChar(char: u8) !Token {
@@ -65,7 +80,14 @@ pub const Token = union(TokenType) {
'}' => .closeBrace,
'(' => .openParen,
')' => .closeParen,
- else => TokenizeError.UnknownToken,
+ '[' => .openBracket,
+ ']' => .closeBracket,
+ ':' => .colon,
+ ',' => .comma,
+ else => {
+ // std.debug.print("{c}: ", .{char});
+ return TokenizeError.UnknownToken;
+ },
};
}
@@ -73,8 +95,9 @@ pub const Token = union(TokenType) {
const eql = std.mem.eql;
if (eql(u8, str, "return")) return .exit;
if (eql(u8, str, "const")) return .constant;
- if (eql(u8, str, "var")) return .variable;
+ if (eql(u8, str, "varbl")) return .variable;
if (eql(u8, str, "fn")) return .fun;
+ if (eql(u8, str, "import")) return .import;
return Token{ .ident = str };
}
};
@@ -114,10 +137,12 @@ pub fn Iterator(comptime typ: type) type {
return ret;
}
- pub fn consume(self: *Iterator(typ), comptime expected: TokenType) !?typ {
- if (typ != Token) return error.TokenIteratorOnly;
- if (!checkType(self.peek().?, expected))
+ pub fn consume(self: *Iterator(typ), comptime expected: TokenType) error{ ExpectedToken, TokenIteratorOnly }!?typ {
+ if (typ != Token) return TokenizeError.TokenIteratorOnly;
+ if (!checkType(self.peek().?, expected)) {
+ // std.debug.print("Got {}, expected {}\n", .{ self.peek().?, expected });
return TokenizeError.ExpectedToken;
+ }
return self.next();
}
@@ -147,8 +172,10 @@ pub const Tokenizer = struct {
/// Releases allocated memory
pub fn deinit(self: *Tokenizer) void {
for (self.toks.items) |token| {
- if (checkType(token, TokenType.ident))
+ if (checkType(token, .ident))
self.allocator.free(token.ident);
+ if (checkType(token, .stringLit))
+ self.allocator.free(token.stringLit);
}
self.toks.deinit();
}
@@ -187,6 +214,17 @@ pub const Tokenizer = struct {
if (!checkType(token, TokenType.ident)) self.allocator.free(str);
buff.clearAndFree();
},
+ '"' => {
+ _ = self.src.next();
+ while (self.src.peek().? != '"')
+ try buff.append(self.src.next().?);
+
+ _ = self.src.next();
+ // std.debug.print("{c}\n", .{self.src.peek().?});
+ const token = Token{ .stringLit = try buff.toOwnedSlice() };
+ try self.toks.append(token);
+ buff.clearAndFree();
+ },
else => self.toks.append(try Token.fromChar(self.src.next().?)),
};
}