diff --git a/README.md b/README.md index 434dec4..6eb90c3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # rayoko -a toy programming language and compiler +a programming language this time it'll work i promise it wont be like vig plrease @@ -11,11 +11,3 @@ git clone https://gitdab.com/luna/rayoko cd rayoko zig build install --prefix ~/.local/ ``` - -# use - -``` -rayoko examples/hello.ry # outputs to outpath.o -gcc outpath.o examples/hello.c -o hello -./hello -``` diff --git a/examples/hello.c b/examples/hello.c deleted file mode 100644 index fff2531..0000000 --- a/examples/hello.c +++ /dev/null @@ -1,5 +0,0 @@ -#include - -int main(void) { - printf("add(2, 2) = %d\n", add(2, 2)); -} diff --git a/examples/hello.ry b/examples/hello.ry index 0f97d4f..e935ddc 100644 --- a/examples/hello.ry +++ b/examples/hello.ry @@ -32,21 +32,22 @@ fn test_function() B { } fn multwo(num: i32, double_flag: bool) i32 { - if (double_flag) { + // TODO resolve expr variables + if (true) { var truthy = true; - return num * 2; + return 1 * 2; } else { var falsey = false; - return num; + return 1; } } -fn func_refer_param(b: i32) i32 { - return b * 231 + b; +fn multwo_with_one(b: i32) i32 { + return multwo(b, false) + b; } fn add(a: i32, b: i32) i32 { - return a + b; + return 69 + 69; } fn and_fn() bool { diff --git a/src/analysis.zig b/src/analysis.zig index 4081d43..f5c4897 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -458,7 +458,7 @@ pub const TypeSolver = struct { // for a function, we always create a new root scope for it // and force-set it into the current context - var scope = try comp.Scope.create(self.allocator, null, name); + var scope = try comp.Scope.create(self.allocator, null, "function"); errdefer scope.deinit(); // we intentionally insert the function so that: diff --git a/src/ast_printer.zig b/src/ast_printer.zig index 48f9ae2..a5d23e3 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -401,7 +401,7 @@ pub fn printContext(ctx: CompilationContext) void { std.debug.warn( "\tparameter {} typ {}\n", param_kv.key, - prettyType(param_kv.value.typ), + prettyType(param_kv.value), ); } diff --git a/src/codegen.zig b/src/codegen.zig index 45d369d..64c7e72 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -31,8 +31,6 @@ pub const Codegen = struct { ctx: *comp.CompilationContext, llvm_table: LLVMTable, - current_function_name: ?[]const u8 = null, - pub fn init(allocator: *std.mem.Allocator, ctx: *comp.CompilationContext) Codegen { return Codegen{ .allocator = allocator, @@ -220,32 +218,7 @@ pub const Codegen = struct { return llvm.LLVMBuildStore(builder, null, assign_expr); }, - .Variable => |vari| { - var kv_opt = self.ctx.metadata_map.get(expr); - - if (kv_opt == null) { - std.debug.warn("variable {} not fully analyzed\n", vari); - return CompileError.EmitError; - } - - // we have metadata, which means we can check if the variable - // is coming from the scope or from the function - - var metadata = kv_opt.?.value; - - return switch (metadata.using) { - .Function => blk: { - var param = metadata.from_function.?.parameters.get(vari.lexeme).?.value; - var llvm_func = self.llvm_table.get(self.current_function_name.?).?.value; - - // may i thank all the demons in hell for giving me - // good energies to make this work - break :blk llvm.LLVMGetParam(llvm_func, @intCast(c_uint, param.idx)); - }, - - .Scope => @panic("TODO local variables"), - }; - }, + .Variable => @panic("TODO emit variables"), else => { std.debug.warn("Got unexpected expr {}\n", ast.ExprType(expr.*)); @@ -284,8 +257,6 @@ pub const Codegen = struct { var then_rets = false; var else_rets = false; - self.ctx.setScope(self.ctx.current_scope.?.nextChild()); - for (ifstmt.then_branch.toSlice()) |then_stmt| { // keep emitting until branch has ret @@ -298,8 +269,6 @@ pub const Codegen = struct { } } - self.ctx.dumpScope(); - // only build the br instruction if we didn't ret, because // there can't be any instruction after a terminator // same applies for the else branch @@ -313,7 +282,6 @@ pub const Codegen = struct { // roughly translating to kaleidoscope's // 'Else *ElseV = Else->codegen();' if (ifstmt.else_branch) |else_block| { - self.ctx.setScope(self.ctx.current_scope.?.nextChild()); for (else_block.toSlice()) |else_stmt| { // keep emitting until branch has ret if (!else_rets) @@ -324,8 +292,6 @@ pub const Codegen = struct { else => {}, } } - - self.ctx.dumpScope(); } if (!else_rets) @@ -337,30 +303,18 @@ pub const Codegen = struct { if (then_rets and else_rets) _ = llvm.LLVMBuildUnreachable(builder); + + // phis aren't needed since our ifs arent expressions + + //var phi = llvm.LLVMBuildPhi(builder, llvm.LLVMVoidType(), c"iftmp"); + //var then_bb_val = llvm.LLVMBasicBlockAsValue(then_bb); + //var else_bb_val = llvm.LLVMBasicBlockAsValue(else_bb); + //llvm.LLVMAddIncoming(phi, &then_bb_val, &then_bb, 1); + //llvm.LLVMAddIncoming(phi, &else_bb_val, &else_bb, 1); }, - .VarDecl => |vardecl| { - // we alaready inferred the type of the variable in the - // analyze pass and the current scope contains the variable's - // type(hopefully), so we resolve it - const name = vardecl.name.lexeme; - var var_metadata = try self.ctx.resolveVarType(name); - - var name_cstr = try std.cstr.addNullByte(self.allocator, name); - errdefer self.allocator.free(name_cstr); - - var fn_symbol = self.getFnSymbol(self.current_function_name.?); - - // TODO add llvm value ref to var metadata as well - var variable = llvm.LLVMBuildAlloca( - builder, - try self.typeToLLVM(var_metadata.typ), - name_cstr.ptr, - ); - - var llvm_expr = try self.emitExpr(builder, vardecl.value); - _ = llvm.LLVMBuildStore(builder, llvm_expr, variable); - }, + // TODO + .VarDecl => {}, else => { std.debug.warn("Got unexpected stmt {}\n", stmt.*); @@ -369,12 +323,6 @@ pub const Codegen = struct { } } - fn getFnSymbol(self: *@This(), name: []const u8) comp.FunctionSymbol { - var fn_sym_search = self.ctx.symbol_table.get(name).?.value; - std.debug.assert(comp.SymbolType(fn_sym_search) == .Function); - return fn_sym_search.Function; - } - /// Emit LLVM ir for the given node. fn genNode( self: *Codegen, @@ -385,10 +333,10 @@ pub const Codegen = struct { .Root => @panic("Should not have gotten Root"), .FnDecl => |decl| { const name = decl.func_name.lexeme; - self.current_function_name = name; - std.debug.warn("cgen: genning function '{}'\n", name); - var fn_sym = self.getFnSymbol(name); + var fn_sym_search = self.ctx.symbol_table.get(name).?.value; + std.debug.assert(comp.SymbolType(fn_sym_search) == .Function); + var fn_sym = fn_sym_search.Function; const name_cstr = try std.cstr.addNullByte(self.allocator, name); errdefer self.allocator.free(name_cstr); @@ -399,7 +347,7 @@ pub const Codegen = struct { for (decl.params.toSlice()) |param| { try param_types.append(try self.typeToLLVM(fn_sym.parameters.get( param.name.lexeme, - ).?.value.typ)); + ).?.value)); } var llvm_ret_type = llvm.LLVMFunctionType( @@ -420,13 +368,17 @@ pub const Codegen = struct { var builder = llvm.LLVMCreateBuilder(); llvm.LLVMPositionBuilderAtEnd(builder, entry); - self.ctx.setScope(fn_sym.scope); - defer self.ctx.dumpScope(); - for (decl.body.toSlice()) |stmt| { try self.emitStmt(builder, &stmt); } + //var tmp = llvm.LLVMBuildAdd( + // builder, + // llvm.LLVMGetParam(func, 0), + // llvm.LLVMGetParam(func, 1), + // c"tmp", + //); + std.debug.warn("cgen: generated function '{}'\n", name); }, diff --git a/src/comp_ctx.zig b/src/comp_ctx.zig index b22768c..e50a5e9 100644 --- a/src/comp_ctx.zig +++ b/src/comp_ctx.zig @@ -39,9 +39,8 @@ pub const Scope = struct { parent: ?*Scope, env: UnderlyingTypeMap, - /// List of children in the scope. + /// Used for debug information. children: ScopeList, - cur_child_idx: usize = 0, allocator: *std.mem.Allocator, id: ?[]const u8 = null, @@ -65,24 +64,11 @@ pub const Scope = struct { return child; } - pub fn nextChild(self: *@This()) *Scope { - var child = self.children.at(self.cur_child_idx); - self.cur_child_idx += 1; - return child; - } - pub fn deinit(self: *const @This()) void { self.env.deinit(); } }; -pub const Parameter = struct { - idx: usize, - typ: SymbolUnderlyingType, -}; - -pub const ParameterMap = std.StringHashMap(Parameter); - // functions, for our purposes, other than symbols, have: // - a return type // - parameters @@ -92,10 +78,24 @@ pub const FunctionSymbol = struct { /// Parameters for a function are also a table instead of an ArrayList /// because we want to resolve identifiers to them. - parameters: ParameterMap, + parameters: UnderlyingTypeMap, parameter_list: TypeList, scope: *Scope, + + /// Find a given identifier in the function. Can resolve to either a parameter + pub fn findSymbol(self: *const @This(), identifier: []const u8) ?SymbolData { + // try to find it on overall variable symbols + + // TODO + + //var var_sym = self.symbols.get(identifier); + //if (var_sym != null) return var_sym.?.value; + + //var param_sym = self.parameters.get(identifier); + //if (param_sym != null) return param_sym.?.value; + return null; + } }; // structs are hashmaps pointing to SymbolUnderlyingType @@ -191,7 +191,6 @@ pub const CompilationContext = struct { /// Set a given scope as the current scope. pub fn setScope(self: *@This(), scope: *Scope) void { - std.debug.warn("==set== set scope to {}\n", scope.id); self.current_scope = scope; } @@ -265,13 +264,10 @@ pub const CompilationContext = struct { param_types: TypeList, scope: *Scope, ) !void { - var param_map = ParameterMap.init(self.allocator); + var type_map = UnderlyingTypeMap.init(self.allocator); for (decl.params.toSlice()) |param, idx| { - _ = try param_map.put(param.name.lexeme, Parameter{ - .idx = idx, - .typ = param_types.at(idx), - }); + _ = try type_map.put(param.name.lexeme, param_types.at(idx)); } const lex = decl.func_name.lexeme; @@ -280,7 +276,7 @@ pub const CompilationContext = struct { .Function = FunctionSymbol{ .decl = decl, .return_type = ret_type, - .parameters = param_map, + .parameters = type_map, .parameter_list = param_types, .scope = scope, }, @@ -357,7 +353,7 @@ pub const CompilationContext = struct { if (self.cur_function) |cur_function| { var kv_opt = cur_function.parameters.get(name); - if (kv_opt) |kv| return VariableMetadata.withParam(cur_function, kv.value.typ); + if (kv_opt) |kv| return VariableMetadata.withParam(cur_function, kv.value); } std.debug.warn("Unknown name {}\n", name);