Commit da217fadeb

Vexu <git@vexu.eu>
2020-07-20 17:34:06
stage2: astgen for floats and other primitive literals
1 parent e77ca6a
Changed files (2)
src-self-hosted
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", .{});
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,
         };
     }