More builtins, use stage2 because we can
This commit is contained in:
parent
d2e166bb0b
commit
e6b691e447
12
build.zig
12
build.zig
@ -7,19 +7,19 @@ const zls_version = std.builtin.Version{ .major = 0, .minor = 11, .patch = 0 };
|
|||||||
pub fn build(b: *std.build.Builder) !void {
|
pub fn build(b: *std.build.Builder) !void {
|
||||||
const current_zig = builtin.zig_version;
|
const current_zig = builtin.zig_version;
|
||||||
const min_zig = std.SemanticVersion.parse("0.10.0-dev.4458+b120c819d") catch return; // builtins changed to @min / @max
|
const min_zig = std.SemanticVersion.parse("0.10.0-dev.4458+b120c819d") catch return; // builtins changed to @min / @max
|
||||||
if (current_zig.order(min_zig).compare(.lt)) @panic(b.fmt("Your Zig version v{} does not meet the minimum build requirement of v{}", .{current_zig, min_zig}));
|
if (current_zig.order(min_zig).compare(.lt)) @panic(b.fmt("Your Zig version v{} does not meet the minimum build requirement of v{}", .{ current_zig, min_zig }));
|
||||||
|
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
const mode = b.standardReleaseOptions();
|
const mode = b.standardReleaseOptions();
|
||||||
const exe = b.addExecutable("zls", "src/main.zig");
|
const exe = b.addExecutable("zls", "src/main.zig");
|
||||||
exe.use_stage1 = true;
|
// exe.use_stage1 = true;
|
||||||
const exe_options = b.addOptions();
|
const exe_options = b.addOptions();
|
||||||
exe.addOptions("build_options", exe_options);
|
exe.addOptions("build_options", exe_options);
|
||||||
|
|
||||||
const enable_tracy = b.option(bool, "enable_tracy", "Whether tracy should be enabled.") orelse false;
|
const enable_tracy = b.option(bool, "enable_tracy", "Whether tracy should be enabled.") orelse false;
|
||||||
const coverage = b.option(bool, "generate_coverage", "Generate coverage data with kcov") orelse false;
|
const coverage = b.option(bool, "generate_coverage", "Generate coverage data with kcov") orelse false;
|
||||||
const coverage_output_dir = b.option([]const u8, "coverage_output_dir", "Output directory for coverage data") orelse b.pathJoin(&.{b.install_prefix, "kcov"});
|
const coverage_output_dir = b.option([]const u8, "coverage_output_dir", "Output directory for coverage data") orelse b.pathJoin(&.{ b.install_prefix, "kcov" });
|
||||||
|
|
||||||
exe_options.addOption(
|
exe_options.addOption(
|
||||||
shared.ZigVersion,
|
shared.ZigVersion,
|
||||||
@ -122,10 +122,10 @@ pub fn build(b: *std.build.Builder) !void {
|
|||||||
|
|
||||||
var tests = b.addTest("tests/tests.zig");
|
var tests = b.addTest("tests/tests.zig");
|
||||||
|
|
||||||
if(coverage) {
|
if (coverage) {
|
||||||
const src_dir = b.pathJoin(&.{b.build_root, "src"});
|
const src_dir = b.pathJoin(&.{ b.build_root, "src" });
|
||||||
const include_pattern = b.fmt("--include-pattern={s}", .{src_dir});
|
const include_pattern = b.fmt("--include-pattern={s}", .{src_dir});
|
||||||
|
|
||||||
tests.setExecCmd(&[_]?[]const u8{
|
tests.setExecCmd(&[_]?[]const u8{
|
||||||
"kcov",
|
"kcov",
|
||||||
include_pattern,
|
include_pattern,
|
||||||
|
@ -30,7 +30,7 @@ pub const InterpreterError = struct {
|
|||||||
message: []const u8,
|
message: []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn recordError(interpreter: *ComptimeInterpreter, node_idx: Ast.Node.Index, code: []const u8, message: []const u8) !void {
|
pub fn recordError(interpreter: *ComptimeInterpreter, node_idx: Ast.Node.Index, code: []const u8, message: []const u8) error{OutOfMemory}!void {
|
||||||
try interpreter.errors.put(interpreter.allocator, node_idx, .{
|
try interpreter.errors.put(interpreter.allocator, node_idx, .{
|
||||||
.code = code,
|
.code = code,
|
||||||
.message = message,
|
.message = message,
|
||||||
@ -212,13 +212,19 @@ pub const ValueData = union(enum) {
|
|||||||
// @"struct": struct {
|
// @"struct": struct {
|
||||||
|
|
||||||
// },
|
// },
|
||||||
// one_ptr: *anyopaque,
|
/// This is what a pointer is; we don't need to map
|
||||||
|
/// this to anything because @ptrToInt is comptime-illegal
|
||||||
|
/// Pointer equality scares me though :( (but that's for later)
|
||||||
|
one_ptr: *ValueData,
|
||||||
/// Special case slice; this is extremely common at comptime so it makes sense
|
/// Special case slice; this is extremely common at comptime so it makes sense
|
||||||
string: []const u8,
|
slice_of_const_u8: []const u8,
|
||||||
|
|
||||||
@"comptime_int": std.math.big.int.Managed,
|
|
||||||
unsigned_int: u64,
|
unsigned_int: u64,
|
||||||
signed_int: i64,
|
signed_int: i64,
|
||||||
|
/// If the int does not fit into the previous respective slots,
|
||||||
|
/// use a bit int to store it
|
||||||
|
big_int: std.math.big.int.Managed,
|
||||||
|
|
||||||
float: f64,
|
float: f64,
|
||||||
|
|
||||||
@"fn",
|
@"fn",
|
||||||
@ -231,7 +237,7 @@ pub const ValueData = union(enum) {
|
|||||||
// std.meta.activeTag(u: anytype)
|
// std.meta.activeTag(u: anytype)
|
||||||
switch (data) {
|
switch (data) {
|
||||||
.@"bool" => return data.@"bool" == other_data.@"bool",
|
.@"bool" => return data.@"bool" == other_data.@"bool",
|
||||||
.@"comptime_int" => return data.@"comptime_int".eq(other_data.@"comptime_int"),
|
.big_int => return data.big_int.eq(other_data.big_int),
|
||||||
.unsigned_int => return data.unsigned_int == other_data.unsigned_int,
|
.unsigned_int => return data.unsigned_int == other_data.unsigned_int,
|
||||||
.signed_int => return data.signed_int == other_data.signed_int,
|
.signed_int => return data.signed_int == other_data.signed_int,
|
||||||
.float => return data.float == other_data.float,
|
.float => return data.float == other_data.float,
|
||||||
@ -239,6 +245,16 @@ pub const ValueData = union(enum) {
|
|||||||
else => return false,
|
else => return false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the bit count required to store a certain integer
|
||||||
|
pub fn bitCount(data: ValueData) ?u16 {
|
||||||
|
return switch (data) {
|
||||||
|
// TODO: Implement for signed ints
|
||||||
|
.unsigned_int => |i| std.math.log2_int(@TypeOf(i), i),
|
||||||
|
.big_int => |bi| @intCast(u16, bi.bitCountAbs()),
|
||||||
|
else => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const FieldDefinition = struct {
|
pub const FieldDefinition = struct {
|
||||||
@ -515,6 +531,49 @@ pub fn huntItDown(
|
|||||||
return error.IdentifierNotFound;
|
return error.IdentifierNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cast(
|
||||||
|
interpreter: *ComptimeInterpreter,
|
||||||
|
node_idx: Ast.Node.Index,
|
||||||
|
dest_type: Type,
|
||||||
|
value: Value,
|
||||||
|
) error{ OutOfMemory, InvalidCast }!Value {
|
||||||
|
const value_data = value.value_data;
|
||||||
|
|
||||||
|
const to_type_info = dest_type.getTypeInfo();
|
||||||
|
const from_type_info = value.@"type".getTypeInfo();
|
||||||
|
|
||||||
|
const err = switch (from_type_info) {
|
||||||
|
.@"comptime_int" => switch (to_type_info) {
|
||||||
|
.int => {
|
||||||
|
if (value_data.bitCount().? > to_type_info.int.bits) {
|
||||||
|
switch (value_data) {
|
||||||
|
inline .unsigned_int, .signed_int, .big_int => |bi| {
|
||||||
|
try interpreter.recordError(node_idx, "invalid_cast", try std.fmt.allocPrint(interpreter.allocator, "integer value {d} cannot be coerced to type '{s}'", .{ bi, interpreter.formatTypeInfo(to_type_info) }));
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
return error.InvalidCast;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => error.InvalidCast,
|
||||||
|
},
|
||||||
|
else => error.InvalidCast,
|
||||||
|
};
|
||||||
|
|
||||||
|
err catch |e| {
|
||||||
|
try interpreter.recordError(node_idx, "invalid_cast", "invalid cast");
|
||||||
|
return e;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Value{
|
||||||
|
.handle = interpreter.handle,
|
||||||
|
|
||||||
|
.node_idx = node_idx,
|
||||||
|
.@"type" = dest_type,
|
||||||
|
.value_data = value.value_data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Might be useful in the future
|
// Might be useful in the future
|
||||||
pub const InterpretOptions = struct {};
|
pub const InterpretOptions = struct {};
|
||||||
|
|
||||||
@ -528,6 +587,7 @@ pub const InterpretError = std.mem.Allocator.Error || std.fmt.ParseIntError || s
|
|||||||
IdentifierNotFound,
|
IdentifierNotFound,
|
||||||
MissingArguments,
|
MissingArguments,
|
||||||
ImportFailure,
|
ImportFailure,
|
||||||
|
InvalidCast,
|
||||||
};
|
};
|
||||||
pub fn interpret(
|
pub fn interpret(
|
||||||
interpreter: *ComptimeInterpreter,
|
interpreter: *ComptimeInterpreter,
|
||||||
@ -624,7 +684,7 @@ pub fn interpret(
|
|||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{ .value = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = {} }),
|
||||||
.value_data = .{ .@"type" = cont_type },
|
.value_data = .{ .@"type" = cont_type },
|
||||||
} };
|
} };
|
||||||
},
|
},
|
||||||
@ -636,21 +696,21 @@ pub fn interpret(
|
|||||||
// TODO: Add 0 check
|
// TODO: Add 0 check
|
||||||
const name = analysis.getDeclName(tree, node_idx).?;
|
const name = analysis.getDeclName(tree, node_idx).?;
|
||||||
if (scope.?.declarations.contains(name))
|
if (scope.?.declarations.contains(name))
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = {} };
|
||||||
|
|
||||||
const decl = ast.varDecl(tree, node_idx).?;
|
const decl = ast.varDecl(tree, node_idx).?;
|
||||||
if (decl.ast.init_node == 0)
|
if (decl.ast.init_node == 0)
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = {} };
|
||||||
|
|
||||||
// We should have a value when a var is defined
|
// We should have a value when a var is defined
|
||||||
// var value = try (try interpreter.interpret(decl.ast.init_node, scope, options)).getValue();
|
// var value = try (try interpreter.interpret(decl.ast.init_node, scope, options)).getValue();
|
||||||
var value = (try interpreter.interpret(decl.ast.init_node, scope, options)).maybeGetValue() orelse return InterpretResult{ .nothing = .{} };
|
var value = (try interpreter.interpret(decl.ast.init_node, scope, options)).maybeGetValue() orelse return InterpretResult{ .nothing = {} };
|
||||||
|
|
||||||
// Is this redundant? im too afraid to change it rn tbh
|
// Is this redundant? im too afraid to change it rn tbh
|
||||||
var @"type" = if (decl.ast.type_node == 0) Value{
|
var @"type" = if (decl.ast.type_node == 0) Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = std.math.maxInt(Ast.Node.Index),
|
.node_idx = std.math.maxInt(Ast.Node.Index),
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = {} }),
|
||||||
.value_data = .{ .@"type" = value.@"type" },
|
.value_data = .{ .@"type" = value.@"type" },
|
||||||
} else try (try interpreter.interpret(decl.ast.type_node, scope, options)).getValue();
|
} else try (try interpreter.interpret(decl.ast.type_node, scope, options)).getValue();
|
||||||
|
|
||||||
@ -661,7 +721,7 @@ pub fn interpret(
|
|||||||
.@"value" = value,
|
.@"value" = value,
|
||||||
});
|
});
|
||||||
|
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = {} };
|
||||||
},
|
},
|
||||||
.block,
|
.block,
|
||||||
.block_semicolon,
|
.block_semicolon,
|
||||||
@ -687,11 +747,11 @@ pub fn interpret(
|
|||||||
if (lllll) |l| {
|
if (lllll) |l| {
|
||||||
if (maybe_block_label_string) |ls| {
|
if (maybe_block_label_string) |ls| {
|
||||||
if (std.mem.eql(u8, l, ls)) {
|
if (std.mem.eql(u8, l, ls)) {
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = {} };
|
||||||
} else return ret;
|
} else return ret;
|
||||||
} else return ret;
|
} else return ret;
|
||||||
} else {
|
} else {
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = {} };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.break_with_value => |bwv| {
|
.break_with_value => |bwv| {
|
||||||
@ -712,7 +772,7 @@ pub fn interpret(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = {} };
|
||||||
},
|
},
|
||||||
.identifier => {
|
.identifier => {
|
||||||
var value = tree.getNodeSource(node_idx);
|
var value = tree.getNodeSource(node_idx);
|
||||||
@ -720,19 +780,19 @@ pub fn interpret(
|
|||||||
if (std.mem.eql(u8, "bool", value)) return InterpretResult{ .value = Value{
|
if (std.mem.eql(u8, "bool", value)) return InterpretResult{ .value = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = {} }),
|
||||||
.value_data = .{ .@"type" = try interpreter.createType(node_idx, .{ .@"bool" = .{} }) },
|
.value_data = .{ .@"type" = try interpreter.createType(node_idx, .{ .@"bool" = {} }) },
|
||||||
} };
|
} };
|
||||||
if (std.mem.eql(u8, "true", value)) return InterpretResult{ .value = Value{
|
if (std.mem.eql(u8, "true", value)) return InterpretResult{ .value = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"bool" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"bool" = {} }),
|
||||||
.value_data = .{ .@"bool" = true },
|
.value_data = .{ .@"bool" = true },
|
||||||
} };
|
} };
|
||||||
if (std.mem.eql(u8, "false", value)) return InterpretResult{ .value = Value{
|
if (std.mem.eql(u8, "false", value)) return InterpretResult{ .value = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"bool" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"bool" = {} }),
|
||||||
.value_data = .{ .@"bool" = false },
|
.value_data = .{ .@"bool" = false },
|
||||||
} };
|
} };
|
||||||
|
|
||||||
@ -740,7 +800,7 @@ pub fn interpret(
|
|||||||
.value = Value{
|
.value = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = {} }),
|
||||||
.value_data = .{
|
.value_data = .{
|
||||||
.@"type" = try interpreter.createType(node_idx, .{
|
.@"type" = try interpreter.createType(node_idx, .{
|
||||||
.int = .{
|
.int = .{
|
||||||
@ -756,14 +816,14 @@ pub fn interpret(
|
|||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{ .value = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = {} }),
|
||||||
.value_data = .{ .@"type" = try interpreter.createType(node_idx, .{ .@"type" = .{} }) },
|
.value_data = .{ .@"type" = try interpreter.createType(node_idx, .{ .@"type" = {} }) },
|
||||||
} };
|
} };
|
||||||
} else if (value.len >= 2 and (value[0] == 'u' or value[0] == 'i')) int: {
|
} else if (value.len >= 2 and (value[0] == 'u' or value[0] == 'i')) int: {
|
||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{ .value = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = {} }),
|
||||||
.value_data = .{ .@"type" = try interpreter.createType(node_idx, .{
|
.value_data = .{ .@"type" = try interpreter.createType(node_idx, .{
|
||||||
.int = .{
|
.int = .{
|
||||||
.signedness = if (value[0] == 'u') .unsigned else .signed,
|
.signedness = if (value[0] == 'u') .unsigned else .signed,
|
||||||
@ -833,7 +893,7 @@ pub fn interpret(
|
|||||||
} else {
|
} else {
|
||||||
if (iff.ast.else_expr != 0) {
|
if (iff.ast.else_expr != 0) {
|
||||||
return try interpreter.interpret(iff.ast.else_expr, scope, options);
|
return try interpreter.interpret(iff.ast.else_expr, scope, options);
|
||||||
} else return InterpretResult{ .nothing = .{} };
|
} else return InterpretResult{ .nothing = {} };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.equal_equal => {
|
.equal_equal => {
|
||||||
@ -842,7 +902,7 @@ pub fn interpret(
|
|||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{ .value = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"bool" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"bool" = {} }),
|
||||||
.value_data = .{ .@"bool" = (try a.getValue()).eql(try b.getValue()) },
|
.value_data = .{ .@"bool" = (try a.getValue()).eql(try b.getValue()) },
|
||||||
} };
|
} };
|
||||||
// a.getValue().eql(b.getValue())
|
// a.getValue().eql(b.getValue())
|
||||||
@ -850,22 +910,24 @@ pub fn interpret(
|
|||||||
.number_literal => {
|
.number_literal => {
|
||||||
const s = tree.getNodeSource(node_idx);
|
const s = tree.getNodeSource(node_idx);
|
||||||
const nl = std.zig.parseNumberLiteral(s);
|
const nl = std.zig.parseNumberLiteral(s);
|
||||||
// if (nl == .failure) ;
|
|
||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{
|
||||||
.handle = interpreter.handle,
|
.value = Value{
|
||||||
.node_idx = node_idx,
|
.handle = interpreter.handle,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"comptime_int" = .{} }),
|
.node_idx = node_idx,
|
||||||
.value_data = switch (nl) {
|
.@"type" = try interpreter.createType(node_idx, .{ .@"comptime_int" = {} }),
|
||||||
.float => .{ .float = try std.fmt.parseFloat(f64, s) },
|
.value_data = switch (nl) {
|
||||||
.int => if (s[0] == '-') ValueData{ .signed_int = try std.fmt.parseInt(i64, s, 0) } else ValueData{ .unsigned_int = try std.fmt.parseInt(u64, s, 0) },
|
.float => .{ .float = try std.fmt.parseFloat(f64, s) },
|
||||||
.big_int => |bii| ppp: {
|
.int => if (s[0] == '-') ValueData{ .signed_int = try std.fmt.parseInt(i64, s, 0) } else ValueData{ .unsigned_int = try std.fmt.parseInt(u64, s, 0) },
|
||||||
var bi = try std.math.big.int.Managed.init(interpreter.allocator);
|
.big_int => |bii| ppp: {
|
||||||
try bi.setString(@enumToInt(bii), s[if (bii != .decimal) @as(usize, 2) else @as(usize, 0)..]);
|
var bi = try std.math.big.int.Managed.init(interpreter.allocator);
|
||||||
break :ppp .{ .@"comptime_int" = bi };
|
try bi.setString(@enumToInt(bii), s[if (bii != .decimal) @as(usize, 2) else @as(usize, 0)..]);
|
||||||
|
break :ppp .{ .big_int = bi };
|
||||||
|
},
|
||||||
|
.failure => return error.CriticalAstFailure,
|
||||||
},
|
},
|
||||||
.failure => return error.CriticalAstFailure,
|
|
||||||
},
|
},
|
||||||
} };
|
};
|
||||||
},
|
},
|
||||||
.assign,
|
.assign,
|
||||||
.assign_bit_and,
|
.assign_bit_and,
|
||||||
@ -893,7 +955,7 @@ pub fn interpret(
|
|||||||
decl.value_ptr.value = try (try interpreter.interpret(data[node_idx].rhs, scope.?, options)).getValue();
|
decl.value_ptr.value = try (try interpreter.interpret(data[node_idx].rhs, scope.?, options)).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = {} };
|
||||||
},
|
},
|
||||||
// .@"switch",
|
// .@"switch",
|
||||||
// .switch_comma,
|
// .switch_comma,
|
||||||
@ -920,11 +982,11 @@ pub fn interpret(
|
|||||||
const call_name = tree.tokenSlice(main_tokens[node_idx]);
|
const call_name = tree.tokenSlice(main_tokens[node_idx]);
|
||||||
|
|
||||||
if (std.mem.eql(u8, call_name, "@compileLog")) {
|
if (std.mem.eql(u8, call_name, "@compileLog")) {
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = {} };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std.mem.eql(u8, call_name, "@compileError")) {
|
if (std.mem.eql(u8, call_name, "@compileError")) {
|
||||||
return InterpretResult{ .@"return" = .{} };
|
return InterpretResult{ .@"return" = {} };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std.mem.eql(u8, call_name, "@import")) {
|
if (std.mem.eql(u8, call_name, "@import")) {
|
||||||
@ -944,7 +1006,7 @@ pub fn interpret(
|
|||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{ .value = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = {} }),
|
||||||
.value_data = .{ .@"type" = handle.interpreter.?.root_type.? },
|
.value_data = .{ .@"type" = handle.interpreter.?.root_type.? },
|
||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
@ -956,7 +1018,7 @@ pub fn interpret(
|
|||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{ .value = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"type" = {} }),
|
||||||
.value_data = .{ .@"type" = value.@"type" },
|
.value_data = .{ .@"type" = value.@"type" },
|
||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
@ -976,11 +1038,22 @@ pub fn interpret(
|
|||||||
return InterpretResult{ .value = Value{
|
return InterpretResult{ .value = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, .{ .@"bool" = .{} }),
|
.@"type" = try interpreter.createType(node_idx, .{ .@"bool" = {} }),
|
||||||
.value_data = .{ .@"bool" = ti.getScopeOfType().?.declarations.contains(field_name.value_data.string) },
|
.value_data = .{ .@"bool" = ti.getScopeOfType().?.declarations.contains(field_name.value_data.slice_of_const_u8) },
|
||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (std.mem.eql(u8, call_name, "@as")) {
|
||||||
|
if (params.len != 2) return error.InvalidBuiltin;
|
||||||
|
|
||||||
|
const as_type = try (try interpreter.interpret(params[0], scope, options)).getValue();
|
||||||
|
const value = try (try interpreter.interpret(params[1], scope, options)).getValue();
|
||||||
|
|
||||||
|
if (as_type.@"type".getTypeInfo() != .@"type") return error.InvalidBuiltin;
|
||||||
|
|
||||||
|
return InterpretResult{ .value = try interpreter.cast(node_idx, as_type.value_data.@"type", value) };
|
||||||
|
}
|
||||||
|
|
||||||
std.log.info("Builtin not implemented: {s}", .{call_name});
|
std.log.info("Builtin not implemented: {s}", .{call_name});
|
||||||
// @panic("Builtin not implemented");
|
// @panic("Builtin not implemented");
|
||||||
return error.InvalidBuiltin;
|
return error.InvalidBuiltin;
|
||||||
@ -990,6 +1063,9 @@ pub fn interpret(
|
|||||||
var val = Value{
|
var val = Value{
|
||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
|
// TODO: This is literally the wrong type lmao
|
||||||
|
// the actual type is *[len:0]u8 because we're pointing
|
||||||
|
// to a fixed size value in the data(?) section (when we're compilign zig code)
|
||||||
.@"type" = try interpreter.createType(node_idx, .{
|
.@"type" = try interpreter.createType(node_idx, .{
|
||||||
.pointer = .{
|
.pointer = .{
|
||||||
.size = .slice,
|
.size = .slice,
|
||||||
@ -1004,7 +1080,7 @@ pub fn interpret(
|
|||||||
.sentinel = .{ .unsigned_int = 0 },
|
.sentinel = .{ .unsigned_int = 0 },
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
.value_data = .{ .string = value },
|
.value_data = .{ .slice_of_const_u8 = value },
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Add type casting, sentinel
|
// TODO: Add type casting, sentinel
|
||||||
@ -1061,7 +1137,7 @@ pub fn interpret(
|
|||||||
.handle = interpreter.handle,
|
.handle = interpreter.handle,
|
||||||
.node_idx = node_idx,
|
.node_idx = node_idx,
|
||||||
.@"type" = try interpreter.createType(node_idx, type_info),
|
.@"type" = try interpreter.createType(node_idx, type_info),
|
||||||
.value_data = .{ .@"fn" = .{} },
|
.value_data = .{ .@"fn" = {} },
|
||||||
};
|
};
|
||||||
|
|
||||||
const name = analysis.getDeclName(tree, node_idx).?;
|
const name = analysis.getDeclName(tree, node_idx).?;
|
||||||
@ -1072,7 +1148,7 @@ pub fn interpret(
|
|||||||
.@"value" = value,
|
.@"value" = value,
|
||||||
});
|
});
|
||||||
|
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = {} };
|
||||||
},
|
},
|
||||||
.call,
|
.call,
|
||||||
.call_comma,
|
.call_comma,
|
||||||
@ -1123,7 +1199,7 @@ pub fn interpret(
|
|||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
std.log.err("Unhandled {any}", .{tags[node_idx]});
|
std.log.err("Unhandled {any}", .{tags[node_idx]});
|
||||||
return InterpretResult{ .nothing = .{} };
|
return InterpretResult{ .nothing = {} };
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user