small comptime interpreter refactor

This commit is contained in:
Techatrix 2023-01-20 19:28:25 +01:00
parent b4ac6142cf
commit 1e73ac91e5

View File

@ -171,17 +171,6 @@ pub fn huntItDown(
return error.IdentifierNotFound; return error.IdentifierNotFound;
} }
pub fn cast(
interpreter: *ComptimeInterpreter,
node_idx: Ast.Node.Index,
destination_ty: IPIndex,
source_ty: IPIndex,
) error{ OutOfMemory, InvalidCast }!IPIndex {
_ = node_idx;
// TODO return errors
return try interpreter.ip.cast(interpreter.allocator, destination_ty, source_ty, builtin.target);
}
// Might be useful in the future // Might be useful in the future
pub const InterpretOptions = struct {}; pub const InterpretOptions = struct {};
@ -223,7 +212,6 @@ pub fn interpret(
// .tagged_union_enum_tag, // .tagged_union_enum_tag,
// .tagged_union_enum_tag_trailing, // .tagged_union_enum_tag_trailing,
.root, .root,
// .error_set_decl, // TODO
=> { => {
const type_type = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type }); const type_type = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type });
@ -289,6 +277,10 @@ pub fn interpret(
.val = struct_type, .val = struct_type,
} }; } };
}, },
.error_set_decl => {
// TODO
return InterpretResult{ .nothing = {} };
},
.global_var_decl, .global_var_decl,
.local_var_decl, .local_var_decl,
.aligned_var_decl, .aligned_var_decl,
@ -496,10 +488,10 @@ pub fn interpret(
.@"if", .@"if",
.if_simple, .if_simple,
=> { => {
const iff = ast.ifFull(tree, node_idx); const if_info = ast.ifFull(tree, node_idx);
// TODO: Don't evaluate runtime ifs // TODO: Don't evaluate runtime ifs
// if (options.observe_values) { // if (options.observe_values) {
const ir = try interpreter.interpret(iff.ast.cond_expr, namespace, options); const ir = try interpreter.interpret(if_info.ast.cond_expr, namespace, options);
const false_value = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .bool_false }); const false_value = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .bool_false });
const true_value = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .bool_true }); const true_value = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .bool_true });
@ -507,10 +499,10 @@ pub fn interpret(
const condition = (try ir.getValue()).val; const condition = (try ir.getValue()).val;
std.debug.assert(condition == false_value or condition == true_value); std.debug.assert(condition == false_value or condition == true_value);
if (condition == true_value) { if (condition == true_value) {
return try interpreter.interpret(iff.ast.then_expr, namespace, options); return try interpreter.interpret(if_info.ast.then_expr, namespace, options);
} else { } else {
if (iff.ast.else_expr != 0) { if (if_info.ast.else_expr != 0) {
return try interpreter.interpret(iff.ast.else_expr, namespace, options); return try interpreter.interpret(if_info.ast.else_expr, namespace, options);
} else return InterpretResult{ .nothing = {} }; } else return InterpretResult{ .nothing = {} };
} }
}, },
@ -525,8 +517,6 @@ pub fn interpret(
.val = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = if (a.value.val == b.value.val) .bool_true else .bool_false }), // TODO eql function required? .val = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = if (a.value.val == b.value.val) .bool_true else .bool_false }), // TODO eql function required?
}, },
}; };
// a.getValue().eql(b.getValue())
}, },
.number_literal => { .number_literal => {
const s = tree.getNodeSource(node_idx); const s = tree.getNodeSource(node_idx);
@ -534,7 +524,7 @@ pub fn interpret(
if (nl == .failure) return error.CriticalAstFailure; if (nl == .failure) return error.CriticalAstFailure;
const comptime_int_type = try interpreter.ip.get(interpreter.allocator, IPKey{ const number_type = try interpreter.ip.get(interpreter.allocator, IPKey{
.simple = if (nl == .float) .comptime_float else .comptime_int, .simple = if (nl == .float) .comptime_float else .comptime_int,
}); });
@ -542,7 +532,7 @@ pub fn interpret(
interpreter.allocator, interpreter.allocator,
switch (nl) { switch (nl) {
.float => IPKey{ .float => IPKey{
.float_64_value = try std.fmt.parseFloat(f64, s), // shouldn't this be f128? .float_128_value = try std.fmt.parseFloat(f128, s),
}, },
.int => if (s[0] == '-') IPKey{ .int => if (s[0] == '-') IPKey{
.int_i64_value = try std.fmt.parseInt(i64, s, 0), .int_i64_value = try std.fmt.parseInt(i64, s, 0),
@ -557,7 +547,7 @@ pub fn interpret(
return InterpretResult{ .value = Value{ return InterpretResult{ .value = Value{
.interpreter = interpreter, .interpreter = interpreter,
.node_idx = node_idx, .node_idx = node_idx,
.ty = comptime_int_type, .ty = number_type,
.val = value, .val = value,
} }; } };
}, },
@ -587,7 +577,8 @@ pub fn interpret(
var to_value = try ir.getValue(); var to_value = try ir.getValue();
var from_value = (try (try interpreter.interpret(data[node_idx].rhs, namespace, options)).getValue()); var from_value = (try (try interpreter.interpret(data[node_idx].rhs, namespace, options)).getValue());
_ = try interpreter.cast(undefined, to_value.ty, from_value.ty); // TODO report error
_ = try interpreter.ip.cast(interpreter.allocator, to_value.ty, from_value.ty, builtin.target);
return InterpretResult{ .nothing = {} }; return InterpretResult{ .nothing = {} };
}, },
@ -658,7 +649,7 @@ pub fn interpret(
.fields = &.{}, .fields = &.{},
.namespace = .none, .namespace = .none,
.layout = .Auto, .layout = .Auto,
.backing_int_ty = IPIndex.none, .backing_int_ty = .none,
} }), } }),
.val = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .undefined_value }), .val = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .undefined_value }),
} }; } };
@ -675,7 +666,7 @@ pub fn interpret(
.interpreter = interpreter, .interpreter = interpreter,
.node_idx = node_idx, .node_idx = node_idx,
.ty = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type }), .ty = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .type }),
.val = undefined, // TODO .val = .none, // TODO
}, },
}; };
} }
@ -763,14 +754,12 @@ pub fn interpret(
.address_space = .generic, .address_space = .generic,
} }); } });
var val = Value{ return InterpretResult{ .value = Value{
.interpreter = interpreter, .interpreter = interpreter,
.node_idx = node_idx, .node_idx = node_idx,
.ty = string_literal_type, .ty = string_literal_type,
.val = try interpreter.ip.get(interpreter.allocator, IPKey{ .bytes = str }), .val = try interpreter.ip.get(interpreter.allocator, IPKey{ .bytes = str }),
}; } };
return InterpretResult{ .value = val };
}, },
// TODO: Add comptime autodetection; e.g. const MyArrayList = std.ArrayList(u8) // TODO: Add comptime autodetection; e.g. const MyArrayList = std.ArrayList(u8)
.@"comptime" => { .@"comptime" => {
@ -874,23 +863,22 @@ pub fn interpret(
const result = try interpreter.interpret(data[node_idx].lhs, namespace, .{}); const result = try interpreter.interpret(data[node_idx].lhs, namespace, .{});
const bool_type = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .bool }); const bool_type = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .bool });
const value = try result.getValue(); const value = try result.getValue();
if (value.ty == bool_type) {
const false_value = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .bool_false });
const true_value = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .bool_true });
const not_value = if (value.val == false_value) true_value else if (value.val == true_value) false_value else return error.InvalidOperation; if (value.ty != bool_type) {
return InterpretResult{ try interpreter.recordError(node_idx, "invalid_deref", try std.fmt.allocPrint(interpreter.allocator, "expected type `bool` but got `{}`", .{value.ty.fmtType(interpreter.ip)}));
.value = .{
.interpreter = interpreter,
.node_idx = node_idx,
.ty = bool_type,
.val = not_value,
},
};
} else {
// TODO
return error.InvalidOperation; return error.InvalidOperation;
} }
const false_value = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .bool_false });
const true_value = try interpreter.ip.get(interpreter.allocator, IPKey{ .simple = .bool_true });
std.debug.assert(value.val == false_value or value.val == true_value);
return InterpretResult{ .value = .{
.interpreter = interpreter,
.node_idx = node_idx,
.ty = bool_type,
.val = if (value.val == false_value) true_value else false_value,
} };
}, },
.address_of => { .address_of => {
// TODO: Make const pointers if we're drawing from a const; // TODO: Make const pointers if we're drawing from a const;