authorchloe caruso <git@paperclover.net> 2024-09-12 00:26:23-07:00
committerchloe caruso <git@paperclover.net> 2024-09-12 00:26:23-07:00
logcd425afcbd7d3d51c85e8d68cdfd2bf29e7c1b1d
treee8fcf2e5974c6ec39dd8884d60f43d8f0fda13af
parent5aa61b184fe1500707e632aad732bdad792fab93

fix: do not emit direct eval


9 files changed, 56 insertions(+), 25 deletions(-)

CHANGELOG.md+1
...@@ -16,6 +16,7 @@...@@ -16,6 +16,7 @@
16- fix: crash when analyzing an empty array without a result type16- fix: crash when analyzing an empty array without a result type
17- fix: binary operands with float and float would not resolve17- fix: binary operands with float and float would not resolve
18- fix: assertion false-positive when using an extern global more than once18- fix: assertion false-positive when using an extern global more than once
19- fix: do not emit direct eval
1920
20## 0.1.521## 0.1.5
2122
src/core/Air.Dump.zig+12
...@@ -249,6 +249,18 @@ pub const State = struct {...@@ -249,6 +249,18 @@ pub const State = struct {
249 try w.writeAll(">");249 try w.writeAll(">");
250 try tty.setColor(w, .reset);250 try tty.setColor(w, .reset);
251 },251 },
252 .opaque_value => |inner| {
253 try tty.setColor(w, .bright_black);
254 try w.writeAll("<");
255 try tty.setColor(w, .blue);
256 try w.writeAll("opaque");
257 try tty.setColor(w, .reset);
258 try tty.setColor(w, .bright_black);
259 try w.writeAll(", ");
260 try s.dumpValue(w, inner);
261 try w.writeAll(">");
262 try tty.setColor(w, .reset);
263 },
252 .string => |data| {264 .string => |data| {
253 try w.writeAll("<");265 try w.writeAll("<");
254 try tty.setColor(w, .blue);266 try tty.setColor(w, .blue);
src/core/InternPool.zig+10-1
...@@ -127,6 +127,8 @@ pub const Tag = enum(u8) {...@@ -127,6 +127,8 @@ pub const Tag = enum(u8) {
127 array_value,127 array_value,
128 /// An extern reference. For JS, this can be a property access128 /// An extern reference. For JS, this can be a property access
129 external_value,129 external_value,
130 /// A value masked as "opaque" type
131 opaque_value,
130132
131 pub fn Data(comptime tag: Tag) type {133 pub fn Data(comptime tag: Tag) type {
132 return switch (tag) {134 return switch (tag) {
...@@ -135,6 +137,7 @@ pub const Tag = enum(u8) {...@@ -135,6 +137,7 @@ pub const Tag = enum(u8) {
135 .simple_type => SimpleType,137 .simple_type => SimpleType,
136 .simple_value => SimpleValue,138 .simple_value => SimpleValue,
137 .int32 => i32,139 .int32 => i32,
140 .opaque_value => Value,
138141
139 else => ExtraIndex(tag.Payload()),142 else => ExtraIndex(tag.Payload()),
140 };143 };
...@@ -147,6 +150,7 @@ pub const Tag = enum(u8) {...@@ -147,6 +150,7 @@ pub const Tag = enum(u8) {
147 .simple_type,150 .simple_type,
148 .simple_value,151 .simple_value,
149 .int32,152 .int32,
153 .opaque_value,
150 => unreachable, // does not have a payload154 => unreachable, // does not have a payload
151 .float, .comptime_float => Float,155 .float, .comptime_float => Float,
152 .func => FuncDecl,156 .func => FuncDecl,
...@@ -327,7 +331,7 @@ pub const Value = enum(u32) {...@@ -327,7 +331,7 @@ pub const Value = enum(u32) {
327 .func => value.toKey(ip).func.ty,331 .func => value.toKey(ip).func.ty,
328 .struct_value => value.toKey(ip).struct_value.ty,332 .struct_value => value.toKey(ip).struct_value.ty,
329 .array_value => value.toKey(ip).array_value.type,333 .array_value => value.toKey(ip).array_value.type,
330 .external_value => .@"opaque",334 .external_value, .opaque_value => .@"opaque",
331 };335 };
332 }336 }
333337
...@@ -871,6 +875,7 @@ pub const Key = union(enum) {...@@ -871,6 +875,7 @@ pub const Key = union(enum) {
871 struct_value: StructValue,875 struct_value: StructValue,
872 func: Func,876 func: Func,
873 array_value: ArrayValue,877 array_value: ArrayValue,
878 opaque_value: Value,
874 // Types879 // Types
875 simple_type: SimpleType,880 simple_type: SimpleType,
876 function_type: FunctionType,881 function_type: FunctionType,
...@@ -991,6 +996,7 @@ pub const Key = union(enum) {...@@ -991,6 +996,7 @@ pub const Key = union(enum) {
991 inline .int32,996 inline .int32,
992 .simple_value,997 .simple_value,
993 .simple_type,998 .simple_type,
999 .opaque_value,
994 => |x| Hash.hash(seed, asBytes(&x)),1000 => |x| Hash.hash(seed, asBytes(&x)),
995 .string,1001 .string,
996 => |x| Hash.hash(seed, x),1002 => |x| Hash.hash(seed, x),
...@@ -1023,6 +1029,7 @@ pub const Key = union(enum) {...@@ -1023,6 +1029,7 @@ pub const Key = union(enum) {
1023 inline .int32,1029 inline .int32,
1024 .simple_value,1030 .simple_value,
1025 .simple_type,1031 .simple_type,
1032 .opaque_value,
1026 => |x, tag| x == @field(b, @tagName(tag)),1033 => |x, tag| x == @field(b, @tagName(tag)),
1027 .string,1034 .string,
1028 => |x| std.mem.eql(u8, x, b.string),1035 => |x| std.mem.eql(u8, x, b.string),
...@@ -1272,6 +1279,7 @@ pub fn valueToKey(ip: *const InternPool, index: Value) Key {...@@ -1272,6 +1279,7 @@ pub fn valueToKey(ip: *const InternPool, index: Value) Key {
12721279
1273 .simple_type => .{ .simple_type = data.decode(.simple_type, item.tag) },1280 .simple_type => .{ .simple_type = data.decode(.simple_type, item.tag) },
1274 .simple_value => .{ .simple_value = data.decode(.simple_value, item.tag) },1281 .simple_value => .{ .simple_value = data.decode(.simple_value, item.tag) },
1282 .opaque_value => .{ .opaque_value = data.decode(.opaque_value, item.tag) },
1275 .int32 => .{ .int32 = data.decode(.int32, item.tag) },1283 .int32 => .{ .int32 = data.decode(.int32, item.tag) },
1276 .float => .{ .float = data.decode(.float, item.tag).get(ip).decode() },1284 .float => .{ .float = data.decode(.float, item.tag).get(ip).decode() },
1277 .comptime_float => .{1285 .comptime_float => .{
...@@ -1350,6 +1358,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value {...@@ -1350,6 +1358,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value {
1350 inline .int32,1358 inline .int32,
1351 .simple_type,1359 .simple_type,
1352 .simple_value,1360 .simple_value,
1361 .opaque_value,
1353 => |s, tag| Item.encode(@field(Tag, @tagName(tag)), s),1362 => |s, tag| Item.encode(@field(Tag, @tagName(tag)), s),
1354 .string => |s| Item.encode(1363 .string => |s| Item.encode(
1355 .string,1364 .string,
src/core/Report.zig+5-13
...@@ -1202,19 +1202,11 @@ pub const LazyNode = struct {...@@ -1202,19 +1202,11 @@ pub const LazyNode = struct {
1202 else => {},1202 else => {},
1203 }1203 }
12041204
1205 if (builtin.mode == .Debug) {1205 std.debug.print("TODO: operand lookup: .{s} + .{s} + {}\n", .{
1206 std.debug.panic("TODO: operand lookup: .{s} + .{s} + {}", .{1206 @tagName(teg.instTag(lazy.inst)),
1207 @tagName(teg.instTag(lazy.inst)),1207 @tagName(ctx.ast.nodeTag(base_node)),
1208 @tagName(ctx.ast.nodeTag(base_node)),1208 lazy.operand,
1209 lazy.operand,1209 });
1210 });
1211 } else {
1212 std.debug.print("TODO: operand lookup: .{s} + .{s} + {}", .{
1213 @tagName(teg.instTag(lazy.inst)),
1214 @tagName(ctx.ast.nodeTag(base_node)),
1215 lazy.operand,
1216 });
1217 }
12181210
1219 return base_node;1211 return base_node;
1220 }1212 }
src/core/Sema.zig+1-1
...@@ -1548,7 +1548,7 @@ fn coerceValue(s: *Sema, src: LazyNode, value: Value, to: Type) Error!Value {...@@ -1548,7 +1548,7 @@ fn coerceValue(s: *Sema, src: LazyNode, value: Value, to: Type) Error!Value {
1548 }1548 }
1549 switch (to) {1549 switch (to) {
1550 .@"opaque" => {1550 .@"opaque" => {
1551 // TODO:1551 return try s.makeValue(.{ .opaque_value = value });
1552 },1552 },
1553 .bool => {1553 .bool => {
1554 // TODO:1554 // TODO:
src/core/Transform.zig+1
...@@ -366,6 +366,7 @@ const built_in_ids = std.StaticStringMap(Inst.Ref).initComptime(.{...@@ -366,6 +366,7 @@ const built_in_ids = std.StaticStringMap(Inst.Ref).initComptime(.{
366 .{ "int", .int32_type },366 .{ "int", .int32_type },
367 .{ "float", .float_type },367 .{ "float", .float_type },
368 .{ "string", .string_type },368 .{ "string", .string_type },
369 .{ "opaque", .opaque_type },
369 // .{ "bigint", .bigint_type },370 // .{ "bigint", .bigint_type },
370 .{ "bool", .bool_type },371 .{ "bool", .bool_type },
371 .{ "never", .never_type },372 .{ "never", .never_type },
src/core/js/Link.zig+12-1
...@@ -482,7 +482,18 @@ fn printExprLevel(...@@ -482,7 +482,18 @@ fn printExprLevel(
482 const call: Tree.Call = tree.nodeData(.call, node);482 const call: Tree.Call = tree.nodeData(.call, node);
483 const args = call.args.get(tree);483 const args = call.args.get(tree);
484484
485 try link.printExpr(tree, call.base, writer);485 if (tree.nodeTag(call.base) == .plain_value and brk: {
486 const k = tree.nodeData(.plain_value, call.base).value.toKey(&link.comp.intern_pool);
487 break :brk k == .external_value and
488 k.external_value.key.len == 1 and
489 std.mem.eql(u8, k.external_value.key[0].toSlice(&link.comp.intern_pool), "eval");
490 }) {
491 @branchHint(.unlikely);
492 try writer.writeAll("(0, eval)");
493 } else {
494 try link.printExpr(tree, call.base, writer);
495 }
496
486 try writer.writeAll("(");497 try writer.writeAll("(");
487498
488 for (args.slice(tree), 0..) |arg, i| {499 for (args.slice(tree), 0..) |arg, i| {
src/core/js/NodeGen.zig+8-9
...@@ -137,14 +137,6 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void {...@@ -137,14 +137,6 @@ fn codeGenInst(c: *NodeGen, inst: Air.Inst.Index) Error!void {
137137
138 .block => try c.codeGenBlock(inst),138 .block => try c.codeGenBlock(inst),
139139
140 // .js_global_ref => {
141 // const data: InternPool.String.WithLen = c.air.instData(.js_global_ref, inst);
142 // try c.extern_symbols.put(c.gpa, data, {});
143 // c.air_node_map[@intFromEnum(inst)] = .{
144 // .node = try c.add(.global, .{ .name = data }),
145 // };
146 // },
147
148 .memory => {140 .memory => {
149 const i = @intFromEnum(inst);141 const i = @intFromEnum(inst);
150 const data: Air.Memory = c.air.instData(.memory, inst);142 const data: Air.Memory = c.air.instData(.memory, inst);
...@@ -574,9 +566,16 @@ fn valueToExpression(c: *NodeGen, v: Value) !Node.Index {...@@ -574,9 +566,16 @@ fn valueToExpression(c: *NodeGen, v: Value) !Node.Index {
574 .simple_value,566 .simple_value,
575 .struct_value,567 .struct_value,
576 .array_value,568 .array_value,
577 .external_value,
578 => return try c.add(.plain_value, .{ .value = v }),569 => return try c.add(.plain_value, .{ .value = v }),
579570
571 .external_value => {
572 const external = v.toKey(c.ip).external_value;
573 try c.extern_symbols.put(c.gpa, external.key[0].toString().withLen(external.key[0].length(c.ip)), {});
574 return try c.add(.plain_value, .{ .value = v });
575 },
576
577 .opaque_value => return c.valueToExpression(v.toKey(c.ip).opaque_value),
578
580 // Hoist functions as top level values579 // Hoist functions as top level values
581 // TODO: Consider hoisting large values too580 // TODO: Consider hoisting large values too
582 .func => {581 .func => {
test/behavior/direct_eval created+6
...@@ -0,0 +1,6 @@
1let eval = @extern("eval");
2
3fn main {
4 eval("var x = 1");
5 eval("if (globalThis.x != 1) throw new Error('Emitted as direct eval');");
6}