| author | |
| committer | |
| log | e5aea03cb9a838606c8f77e0c6fd49108fca70b7 |
| tree | e8fcf2e5974c6ec39dd8884d60f43d8f0fda13af |
| parent | b39e21f0ab49d3879f7106ab75b1db30b41227e1 |
| signature | Commit is signed but in an unrecognized format. |
9 files changed, 56 insertions(+), 25 deletions(-)
CHANGELOG.md+1| ... | ... | @@ -16,6 +16,7 @@ |
| 16 | 16 | - fix: crash when analyzing an empty array without a result type |
| 17 | 17 | - fix: binary operands with float and float would not resolve |
| 18 | 18 | - fix: assertion false-positive when using an extern global more than once |
| 19 | - fix: do not emit direct eval | |
| 19 | 20 | |
| 20 | 21 | ## 0.1.5 |
| 21 | 22 |
src/core/Air.Dump.zig+12| ... | ... | @@ -249,6 +249,18 @@ pub const State = struct { |
| 249 | 249 | try w.writeAll(">"); |
| 250 | 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 | 264 | .string => |data| { |
| 253 | 265 | try w.writeAll("<"); |
| 254 | 266 | try tty.setColor(w, .blue); |
src/core/InternPool.zig+10-1| ... | ... | @@ -127,6 +127,8 @@ pub const Tag = enum(u8) { |
| 127 | 127 | array_value, |
| 128 | 128 | /// An extern reference. For JS, this can be a property access |
| 129 | 129 | external_value, |
| 130 | /// A value masked as "opaque" type | |
| 131 | opaque_value, | |
| 130 | 132 | |
| 131 | 133 | pub fn Data(comptime tag: Tag) type { |
| 132 | 134 | return switch (tag) { |
| ... | ... | @@ -135,6 +137,7 @@ pub const Tag = enum(u8) { |
| 135 | 137 | .simple_type => SimpleType, |
| 136 | 138 | .simple_value => SimpleValue, |
| 137 | 139 | .int32 => i32, |
| 140 | .opaque_value => Value, | |
| 138 | 141 | |
| 139 | 142 | else => ExtraIndex(tag.Payload()), |
| 140 | 143 | }; |
| ... | ... | @@ -147,6 +150,7 @@ pub const Tag = enum(u8) { |
| 147 | 150 | .simple_type, |
| 148 | 151 | .simple_value, |
| 149 | 152 | .int32, |
| 153 | .opaque_value, | |
| 150 | 154 | => unreachable, // does not have a payload |
| 151 | 155 | .float, .comptime_float => Float, |
| 152 | 156 | .func => FuncDecl, |
| ... | ... | @@ -327,7 +331,7 @@ pub const Value = enum(u32) { |
| 327 | 331 | .func => value.toKey(ip).func.ty, |
| 328 | 332 | .struct_value => value.toKey(ip).struct_value.ty, |
| 329 | 333 | .array_value => value.toKey(ip).array_value.type, |
| 330 | .external_value => .@"opaque", | |
| 334 | .external_value, .opaque_value => .@"opaque", | |
| 331 | 335 | }; |
| 332 | 336 | } |
| 333 | 337 | |
| ... | ... | @@ -871,6 +875,7 @@ pub const Key = union(enum) { |
| 871 | 875 | struct_value: StructValue, |
| 872 | 876 | func: Func, |
| 873 | 877 | array_value: ArrayValue, |
| 878 | opaque_value: Value, | |
| 874 | 879 | // Types |
| 875 | 880 | simple_type: SimpleType, |
| 876 | 881 | function_type: FunctionType, |
| ... | ... | @@ -991,6 +996,7 @@ pub const Key = union(enum) { |
| 991 | 996 | inline .int32, |
| 992 | 997 | .simple_value, |
| 993 | 998 | .simple_type, |
| 999 | .opaque_value, | |
| 994 | 1000 | => |x| Hash.hash(seed, asBytes(&x)), |
| 995 | 1001 | .string, |
| 996 | 1002 | => |x| Hash.hash(seed, x), |
| ... | ... | @@ -1023,6 +1029,7 @@ pub const Key = union(enum) { |
| 1023 | 1029 | inline .int32, |
| 1024 | 1030 | .simple_value, |
| 1025 | 1031 | .simple_type, |
| 1032 | .opaque_value, | |
| 1026 | 1033 | => |x, tag| x == @field(b, @tagName(tag)), |
| 1027 | 1034 | .string, |
| 1028 | 1035 | => |x| std.mem.eql(u8, x, b.string), |
| ... | ... | @@ -1272,6 +1279,7 @@ pub fn valueToKey(ip: *const InternPool, index: Value) Key { |
| 1272 | 1279 | |
| 1273 | 1280 | .simple_type => .{ .simple_type = data.decode(.simple_type, item.tag) }, |
| 1274 | 1281 | .simple_value => .{ .simple_value = data.decode(.simple_value, item.tag) }, |
| 1282 | .opaque_value => .{ .opaque_value = data.decode(.opaque_value, item.tag) }, | |
| 1275 | 1283 | .int32 => .{ .int32 = data.decode(.int32, item.tag) }, |
| 1276 | 1284 | .float => .{ .float = data.decode(.float, item.tag).get(ip).decode() }, |
| 1277 | 1285 | .comptime_float => .{ |
| ... | ... | @@ -1350,6 +1358,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) !Value { |
| 1350 | 1358 | inline .int32, |
| 1351 | 1359 | .simple_type, |
| 1352 | 1360 | .simple_value, |
| 1361 | .opaque_value, | |
| 1353 | 1362 | => |s, tag| Item.encode(@field(Tag, @tagName(tag)), s), |
| 1354 | 1363 | .string => |s| Item.encode( |
| 1355 | 1364 | .string, |
src/core/Report.zig+5-13| ... | ... | @@ -1202,19 +1202,11 @@ pub const LazyNode = struct { |
| 1202 | 1202 | else => {}, |
| 1203 | 1203 | } |
| 1204 | 1204 | |
| 1205 | if (builtin.mode == .Debug) { | |
| 1206 | std.debug.panic("TODO: operand lookup: .{s} + .{s} + {}", .{ | |
| 1207 | @tagName(teg.instTag(lazy.inst)), | |
| 1208 | @tagName(ctx.ast.nodeTag(base_node)), | |
| 1209 | lazy.operand, | |
| 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 | } | |
| 1205 | std.debug.print("TODO: operand lookup: .{s} + .{s} + {}\n", .{ | |
| 1206 | @tagName(teg.instTag(lazy.inst)), | |
| 1207 | @tagName(ctx.ast.nodeTag(base_node)), | |
| 1208 | lazy.operand, | |
| 1209 | }); | |
| 1218 | 1210 | |
| 1219 | 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 | 1548 | } |
| 1549 | 1549 | switch (to) { |
| 1550 | 1550 | .@"opaque" => { |
| 1551 | // TODO: | |
| 1551 | return try s.makeValue(.{ .opaque_value = value }); | |
| 1552 | 1552 | }, |
| 1553 | 1553 | .bool => { |
| 1554 | 1554 | // TODO: |
src/core/Transform.zig+1| ... | ... | @@ -366,6 +366,7 @@ const built_in_ids = std.StaticStringMap(Inst.Ref).initComptime(.{ |
| 366 | 366 | .{ "int", .int32_type }, |
| 367 | 367 | .{ "float", .float_type }, |
| 368 | 368 | .{ "string", .string_type }, |
| 369 | .{ "opaque", .opaque_type }, | |
| 369 | 370 | // .{ "bigint", .bigint_type }, |
| 370 | 371 | .{ "bool", .bool_type }, |
| 371 | 372 | .{ "never", .never_type }, |
src/core/js/Link.zig+12-1| ... | ... | @@ -482,7 +482,18 @@ fn printExprLevel( |
| 482 | 482 | const call: Tree.Call = tree.nodeData(.call, node); |
| 483 | 483 | const args = call.args.get(tree); |
| 484 | 484 | |
| 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 | 497 | try writer.writeAll("("); |
| 487 | 498 | |
| 488 | 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 | 137 | |
| 138 | 138 | .block => try c.codeGenBlock(inst), |
| 139 | 139 | |
| 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 | 140 | .memory => { |
| 149 | 141 | const i = @intFromEnum(inst); |
| 150 | 142 | const data: Air.Memory = c.air.instData(.memory, inst); |
| ... | ... | @@ -574,9 +566,16 @@ fn valueToExpression(c: *NodeGen, v: Value) !Node.Index { |
| 574 | 566 | .simple_value, |
| 575 | 567 | .struct_value, |
| 576 | 568 | .array_value, |
| 577 | .external_value, | |
| 578 | 569 | => return try c.add(.plain_value, .{ .value = v }), |
| 579 | 570 | |
| 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 | 579 | // Hoist functions as top level values |
| 581 | 580 | // TODO: Consider hoisting large values too |
| 582 | 581 | .func => { |
test/behavior/direct_eval created+6| ... | ... | @@ -0,0 +1,6 @@ |
| 1 | let eval = @extern("eval"); | |
| 2 | ||
| 3 | fn main { | |
| 4 | eval("var x = 1"); | |
| 5 | eval("if (globalThis.x != 1) throw new Error('Emitted as direct eval');"); | |
| 6 | } |