From 849bbc0e94207d9cecd08c69a910f71b141529c1 Mon Sep 17 00:00:00 2001 From: Luna Date: Fri, 27 Sep 2019 20:39:16 -0300 Subject: [PATCH] add support for resolving parameters in function body --- examples/hello.ry | 4 ++-- src/ast_printer.zig | 2 +- src/codegen.zig | 39 ++++++++++++++++++++++++++++++--------- src/comp_ctx.zig | 34 +++++++++++++++------------------- 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/examples/hello.ry b/examples/hello.ry index e935ddc..7be6a9a 100644 --- a/examples/hello.ry +++ b/examples/hello.ry @@ -42,8 +42,8 @@ fn multwo(num: i32, double_flag: bool) i32 { } } -fn multwo_with_one(b: i32) i32 { - return multwo(b, false) + b; +fn func_refer_param(b: i32) i32 { + return b * 231 + b; } fn add(a: i32, b: i32) i32 { diff --git a/src/ast_printer.zig b/src/ast_printer.zig index a5d23e3..48f9ae2 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), + prettyType(param_kv.value.typ), ); } diff --git a/src/codegen.zig b/src/codegen.zig index 64c7e72..0e1f0be 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -31,6 +31,8 @@ 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, @@ -218,7 +220,32 @@ pub const Codegen = struct { return llvm.LLVMBuildStore(builder, null, assign_expr); }, - .Variable => @panic("TODO emit variables"), + .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"), + }; + }, else => { std.debug.warn("Got unexpected expr {}\n", ast.ExprType(expr.*)); @@ -333,6 +360,7 @@ pub const Codegen = struct { .Root => @panic("Should not have gotten Root"), .FnDecl => |decl| { const name = decl.func_name.lexeme; + self.current_function_name = name; var fn_sym_search = self.ctx.symbol_table.get(name).?.value; std.debug.assert(comp.SymbolType(fn_sym_search) == .Function); @@ -347,7 +375,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)); + ).?.value.typ)); } var llvm_ret_type = llvm.LLVMFunctionType( @@ -372,13 +400,6 @@ pub const Codegen = struct { 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 e50a5e9..c6d7a37 100644 --- a/src/comp_ctx.zig +++ b/src/comp_ctx.zig @@ -69,6 +69,13 @@ pub const Scope = struct { } }; +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 @@ -78,24 +85,10 @@ 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: UnderlyingTypeMap, + parameters: ParameterMap, 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 @@ -264,10 +257,13 @@ pub const CompilationContext = struct { param_types: TypeList, scope: *Scope, ) !void { - var type_map = UnderlyingTypeMap.init(self.allocator); + var param_map = ParameterMap.init(self.allocator); for (decl.params.toSlice()) |param, idx| { - _ = try type_map.put(param.name.lexeme, param_types.at(idx)); + _ = try param_map.put(param.name.lexeme, Parameter{ + .idx = idx, + .typ = param_types.at(idx), + }); } const lex = decl.func_name.lexeme; @@ -276,7 +272,7 @@ pub const CompilationContext = struct { .Function = FunctionSymbol{ .decl = decl, .return_type = ret_type, - .parameters = type_map, + .parameters = param_map, .parameter_list = param_types, .scope = scope, }, @@ -353,7 +349,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); + if (kv_opt) |kv| return VariableMetadata.withParam(cur_function, kv.value.typ); } std.debug.warn("Unknown name {}\n", name);