diff --git a/src-self-hosted/astgen.zig b/src-self-hosted/astgen.zig index 2365cb9b14..6f0bcf6dc5 100644 --- a/src-self-hosted/astgen.zig +++ b/src-self-hosted/astgen.zig @@ -38,6 +38,8 @@ pub fn expr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst { .Period => return field(mod, scope, node.castTag(.Period).?), .Deref => return deref(mod, scope, node.castTag(.Deref).?), .BoolNot => return boolNot(mod, scope, node.castTag(.BoolNot).?), + .FloatLiteral => return floatLiteral(mod, scope, node.castTag(.FloatLiteral).?), + .UndefinedLiteral, .BoolLiteral, .NullLiteral => return primitiveLiteral(mod, scope, node), else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}), } } @@ -405,6 +407,52 @@ fn integerLiteral(mod: *Module, scope: *Scope, int_lit: *ast.Node.IntegerLiteral } } +fn floatLiteral(mod: *Module, scope: *Scope, float_lit: *ast.Node.FloatLiteral) InnerError!*zir.Inst { + const arena = scope.arena(); + const tree = scope.tree(); + const bytes = tree.tokenSlice(float_lit.token); + if (bytes.len > 2 and bytes[1] == 'x') { + return mod.failTok(scope, float_lit.token, "TODO hex floats", .{}); + } + + const val = std.fmt.parseFloat(f128, bytes) catch |e| switch (e) { + error.InvalidCharacter => unreachable, // validated by tokenizer + }; + const float_payload = try arena.create(Value.Payload.Float_128); + float_payload.* = .{ .val = val }; + const src = tree.token_locs[float_lit.token].start; + return mod.addZIRInstConst(scope, src, .{ + .ty = Type.initTag(.comptime_float), + .val = Value.initPayload(&float_payload.base), + }); +} + +fn primitiveLiteral(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst { + const arena = scope.arena(); + const tree = scope.tree(); + const src = tree.token_locs[node.firstToken()].start; + + if (node.cast(ast.Node.BoolLiteral)) |bool_node| { + return mod.addZIRInstConst(scope, src, .{ + .ty = Type.initTag(.bool), + .val = if (tree.token_ids[bool_node.token] == .Keyword_true) + Value.initTag(.bool_true) + else + Value.initTag(.bool_false), + }); + } else if (node.tag == .UndefinedLiteral) { + return mod.addZIRInstConst(scope, src, .{ + .ty = Type.initTag(.@"undefined"), + .val = Value.initTag(.undef), + }); + } else if (node.tag == .NullLiteral) { + return mod.addZIRInstConst(scope, src, .{ + .ty = Type.initTag(.@"null"), + .val = Value.initTag(.null_value), + }); + } else unreachable; +} + fn assembly(mod: *Module, scope: *Scope, asm_node: *ast.Node.Asm) InnerError!*zir.Inst { if (asm_node.outputs.len != 0) { return mod.failNode(scope, &asm_node.base, "TODO implement asm with an output", .{}); diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig index ec69e9bc17..e54836ba11 100644 --- a/src-self-hosted/value.zig +++ b/src-self-hosted/value.zig @@ -554,13 +554,20 @@ pub const Value = extern union { }; } - /// Asserts that the value is a float. + /// Asserts that the value is a float or an integer. pub fn toF128(self: Value) f128 { return switch (self.tag()) { .float_16 => self.cast(Payload.Float_16).?.val, .float_32 => self.cast(Payload.Float_32).?.val, .float_64 => self.cast(Payload.Float_64).?.val, .float_128, .float => self.cast(Payload.Float_128).?.val, + + .zero, .the_one_possible_value => 0, + .int_u64 => @intToFloat(f128, self.cast(Payload.Int_u64).?.int), + // .int_i64 => @intToFloat(f128, self.cast(Payload.Int_i64).?.int), + .int_i64 => @panic("TODO lld: error: undefined symbol: __floatditf"), + + .int_big_positive, .int_big_negative => @panic("big int to f128"), else => unreachable, }; }