| author | |
| committer | |
| log | 84de5f3373a98b314e681e6e7d5ac259071c50c4 |
| tree | cb69168284b422a4d88568479c0b8898b5e096b3 |
| parent | 2c270c7666f2ab4fab17392bffe2c2f64ef782a5 |
| signature | Commit is signed but in an unrecognized format. |
10 files changed, 342 insertions(+), 106 deletions(-)
demo.ix created+1| ... | @@ -0,0 +1 @@ | ||
| 1 | let x: int = 1.5; | ||
demo.wl deleted-1| ... | @@ -1 +0,0 @@ | ||
| 1 | let x: int = 1.5; | ||
src/compiler/Air.Dump.zig+2-2| ... | @@ -157,14 +157,14 @@ pub const State = struct { | ... | @@ -157,14 +157,14 @@ pub const State = struct { |
| 157 | 157 | ||
| 158 | fn dumpRef(s: *State, w: anytype, ref: Inst.Ref) !void { | 158 | fn dumpRef(s: *State, w: anytype, ref: Inst.Ref) !void { |
| 159 | switch (ref.decode()) { | 159 | switch (ref.decode()) { |
| 160 | .inst => |i| try s.dumpInstRef(w, i), | 160 | .index => |i| try s.dumpInstRef(w, i), |
| 161 | .value => |v| try s.dumpValue(w, v), | 161 | .value => |v| try s.dumpValue(w, v), |
| 162 | } | 162 | } |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | fn dumpRefRecurse(s: *State, w: anytype, ref: Inst.Ref) !void { | 165 | fn dumpRefRecurse(s: *State, w: anytype, ref: Inst.Ref) !void { |
| 166 | switch (ref.decode()) { | 166 | switch (ref.decode()) { |
| 167 | .inst => |i| try s.dumpInst(w, i), | 167 | .index => |i| try s.dumpInst(w, i), |
| 168 | .value => |v| try s.dumpValue(w, v), | 168 | .value => |v| try s.dumpValue(w, v), |
| 169 | } | 169 | } |
| 170 | } | 170 | } |
src/compiler/Air.zig+5-5| ... | @@ -68,17 +68,17 @@ pub const Inst = struct { | ... | @@ -68,17 +68,17 @@ pub const Inst = struct { |
| 68 | kind: Kind, | 68 | kind: Kind, |
| 69 | data: u31, | 69 | data: u31, |
| 70 | 70 | ||
| 71 | pub const Kind = enum(u1) { value, inst }; | 71 | pub const Kind = enum(u1) { value, index }; |
| 72 | 72 | ||
| 73 | pub const Decoded = union(enum) { | 73 | pub const Decoded = union(enum) { |
| 74 | value: Value, | 74 | value: Value, |
| 75 | inst: Index, | 75 | index: Index, |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | pub fn decode(ref: Ref) Decoded { | 78 | pub fn decode(ref: Ref) Decoded { |
| 79 | return switch (ref.kind) { | 79 | return switch (ref.kind) { |
| 80 | .value => .{ .value = @enumFromInt(ref.data) }, | 80 | .value => .{ .value = @enumFromInt(ref.data) }, |
| 81 | .inst => .{ .inst = @enumFromInt(ref.data) }, | 81 | .index => .{ .index = @enumFromInt(ref.data) }, |
| 82 | }; | 82 | }; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| ... | @@ -113,7 +113,7 @@ pub const Inst = struct { | ... | @@ -113,7 +113,7 @@ pub const Inst = struct { |
| 113 | 113 | ||
| 114 | pub fn toRef(index: Index) Ref { | 114 | pub fn toRef(index: Index) Ref { |
| 115 | return .{ | 115 | return .{ |
| 116 | .kind = .inst, | 116 | .kind = .index, |
| 117 | .data = @intCast(@intFromEnum(index)), | 117 | .data = @intCast(@intFromEnum(index)), |
| 118 | }; | 118 | }; |
| 119 | } | 119 | } |
| ... | @@ -252,7 +252,7 @@ pub fn instPayload(air: *const Air, comptime tag: Inst.Tag, index: Inst.Index) t | ... | @@ -252,7 +252,7 @@ pub fn instPayload(air: *const Air, comptime tag: Inst.Tag, index: Inst.Index) t |
| 252 | pub fn typeOf(air: *const Air, ref: Inst.Ref, ip: *InternPool) InternPool.Type { | 252 | pub fn typeOf(air: *const Air, ref: Inst.Ref, ip: *InternPool) InternPool.Type { |
| 253 | return switch (ref.decode()) { | 253 | return switch (ref.decode()) { |
| 254 | .value => |v| v.typeOf(ip), | 254 | .value => |v| v.typeOf(ip), |
| 255 | .inst => |i| air.typeOfIndex(i, ip), | 255 | .index => |i| air.typeOfIndex(i, ip), |
| 256 | }; | 256 | }; |
| 257 | } | 257 | } |
| 258 | 258 |
src/compiler/Ast.zig+85| ... | @@ -520,6 +520,91 @@ pub fn nodeToken(ast: Ast, node: NodeIndex) TokenIndex { | ... | @@ -520,6 +520,91 @@ pub fn nodeToken(ast: Ast, node: NodeIndex) TokenIndex { |
| 520 | return ast.nodes.items(.main_token)[node]; | 520 | return ast.nodes.items(.main_token)[node]; |
| 521 | } | 521 | } |
| 522 | 522 | ||
| 523 | // pub fn operandNode(ast: Ast, node: NodeIndex, operand: OperandId) NodeIndex { | ||
| 524 | // if (operand == .main_node) return node; | ||
| 525 | |||
| 526 | // switch (ast.nodeTag(node)) { | ||
| 527 | // .root => unreachable, | ||
| 528 | // .block_void => unreachable, | ||
| 529 | // .block_implicit_return => unreachable, | ||
| 530 | // .var_decl, | ||
| 531 | // => return switch (operand) { | ||
| 532 | // .type => ast.nodeData(node).var_decl.type.unwrap().?, | ||
| 533 | // .initializer => ast.nodeData(node).var_decl.init, | ||
| 534 | // else => unreachable, | ||
| 535 | // }, | ||
| 536 | |||
| 537 | // .label, | ||
| 538 | // .group, | ||
| 539 | // .negate, | ||
| 540 | // .bit_not, | ||
| 541 | // .bool_not, | ||
| 542 | // .@"comptime", | ||
| 543 | // => return switch (operand) { | ||
| 544 | // .base => ast.nodeData(node).un.expr, | ||
| 545 | // else => unreachable, // Invalid unary operand | ||
| 546 | // }, | ||
| 547 | |||
| 548 | // .add, | ||
| 549 | // .sub, | ||
| 550 | // .mul, | ||
| 551 | // .div, | ||
| 552 | // .rem, | ||
| 553 | // .pow, | ||
| 554 | // .@"and", | ||
| 555 | // .@"or", | ||
| 556 | // .bit_and, | ||
| 557 | // .bit_or, | ||
| 558 | // .bit_xor, | ||
| 559 | // .shl, | ||
| 560 | // .shr, | ||
| 561 | // .eq, | ||
| 562 | // .ne, | ||
| 563 | // .lt, | ||
| 564 | // .le, | ||
| 565 | // .gt, | ||
| 566 | // .ge, | ||
| 567 | // .assign, | ||
| 568 | // .add_assign, | ||
| 569 | // .sub_assign, | ||
| 570 | // .mul_assign, | ||
| 571 | // .div_assign, | ||
| 572 | // .rem_assign, | ||
| 573 | // .pow_assign, | ||
| 574 | // .and_assign, | ||
| 575 | // .or_assign, | ||
| 576 | // .bit_and_assign, | ||
| 577 | // .bit_or_assign, | ||
| 578 | // .bit_xor_assign, | ||
| 579 | // .shl_assign, | ||
| 580 | // .shr_assign, | ||
| 581 | // => { | ||
| 582 | // const bin = ast.nodeData(node).bin; | ||
| 583 | // return switch (operand) { | ||
| 584 | // .lhs => bin.lhs, | ||
| 585 | // .rhs => bin.rhs, | ||
| 586 | // else => unreachable, // Not a valid operand for binary node | ||
| 587 | // }; | ||
| 588 | // }, | ||
| 589 | |||
| 590 | // .fn_decl, | ||
| 591 | // .param_decl, | ||
| 592 | // .id, | ||
| 593 | // .number_int, | ||
| 594 | // .number_float, | ||
| 595 | // .string, | ||
| 596 | // .multiline_string, | ||
| 597 | // .call, | ||
| 598 | // .builtin_call, | ||
| 599 | // .@"if", | ||
| 600 | // .field, | ||
| 601 | // .index, | ||
| 602 | // .@"return", | ||
| 603 | // .@"break", | ||
| 604 | // => |tag| std.debug.panic("TODO: operandNode .{s}", .{@tagName(tag)}), | ||
| 605 | // } | ||
| 606 | // } | ||
| 607 | |||
| 523 | pub fn fullFnDecl(ast: Ast, node: NodeIndex) full.FnDecl { | 608 | pub fn fullFnDecl(ast: Ast, node: NodeIndex) full.FnDecl { |
| 524 | const tok_tags = ast.tokens.items(.tag); | 609 | const tok_tags = ast.tokens.items(.tag); |
| 525 | 610 |
src/compiler/JsNodeGen.zig+6-6| ... | @@ -185,8 +185,8 @@ fn codeGenInst(c: *JsNodeGen, inst: Air.Inst.Index) Error!void { | ... | @@ -185,8 +185,8 @@ fn codeGenInst(c: *JsNodeGen, inst: Air.Inst.Index) Error!void { |
| 185 | 185 | ||
| 186 | const target = try c.fetchInstExpression(data.memory); | 186 | const target = try c.fetchInstExpression(data.memory); |
| 187 | 187 | ||
| 188 | if (data.operand.kind == .inst) { | 188 | if (data.operand.kind == .index) { |
| 189 | const index = data.operand.decode().inst; | 189 | const index = data.operand.decode().index; |
| 190 | switch (c.air.instTag(index)) { | 190 | switch (c.air.instTag(index)) { |
| 191 | inline .add, | 191 | inline .add, |
| 192 | .sub, | 192 | .sub, |
| ... | @@ -418,7 +418,7 @@ fn fetchExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index { | ... | @@ -418,7 +418,7 @@ fn fetchExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index { |
| 418 | 418 | ||
| 419 | return switch (ref.decode()) { | 419 | return switch (ref.decode()) { |
| 420 | .value => |v| c.valueToExpression(v), | 420 | .value => |v| c.valueToExpression(v), |
| 421 | .inst => |index| fetchInstExpression(c, index), | 421 | .index => |index| fetchInstExpression(c, index), |
| 422 | }; | 422 | }; |
| 423 | } | 423 | } |
| 424 | 424 | ||
| ... | @@ -509,7 +509,7 @@ fn codeGenBranch(c: *JsNodeGen, inst: Air.Inst.Ref, temporary: ?Node.Index) !?Br | ... | @@ -509,7 +509,7 @@ fn codeGenBranch(c: *JsNodeGen, inst: Air.Inst.Ref, temporary: ?Node.Index) !?Br |
| 509 | } | 509 | } |
| 510 | break :items c.scratch.items[scratch_top..]; | 510 | break :items c.scratch.items[scratch_top..]; |
| 511 | }, | 511 | }, |
| 512 | .inst => |i| items: { | 512 | .index => |i| items: { |
| 513 | assert(c.air.instTag(i) == .block); | 513 | assert(c.air.instTag(i) == .block); |
| 514 | c.air_node_map[@intFromEnum(i)] = .{ | 514 | c.air_node_map[@intFromEnum(i)] = .{ |
| 515 | .block = .{ .index = @intCast(scratch_top) }, | 515 | .block = .{ .index = @intCast(scratch_top) }, |
| ... | @@ -600,7 +600,7 @@ fn canLowerToExpression(c: *const JsNodeGen, inst: Air.Inst.Ref) bool { | ... | @@ -600,7 +600,7 @@ fn canLowerToExpression(c: *const JsNodeGen, inst: Air.Inst.Ref) bool { |
| 600 | 600 | ||
| 601 | return switch (inst.decode()) { | 601 | return switch (inst.decode()) { |
| 602 | .value => true, | 602 | .value => true, |
| 603 | .inst => |index| switch (c.air.instTag(index)) { | 603 | .index => |index| switch (c.air.instTag(index)) { |
| 604 | .js_global_ref, | 604 | .js_global_ref, |
| 605 | .call, | 605 | .call, |
| 606 | .arg, | 606 | .arg, |
| ... | @@ -651,7 +651,7 @@ fn lowerToExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index { | ... | @@ -651,7 +651,7 @@ fn lowerToExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index { |
| 651 | assert(c.canLowerToExpression(ref)); | 651 | assert(c.canLowerToExpression(ref)); |
| 652 | return switch (ref.decode()) { | 652 | return switch (ref.decode()) { |
| 653 | .value => |v| try c.valueToExpression(v), | 653 | .value => |v| try c.valueToExpression(v), |
| 654 | .inst => |index| { | 654 | .index => |index| { |
| 655 | try c.codeGenInst(index); | 655 | try c.codeGenInst(index); |
| 656 | return c.fetchExpression(ref); | 656 | return c.fetchExpression(ref); |
| 657 | }, | 657 | }, |
src/compiler/Report.zig+62-2| ... | @@ -142,6 +142,16 @@ pub const Err = union(enum) { | ... | @@ -142,6 +142,16 @@ pub const Err = union(enum) { |
| 142 | try ctx.msgNode(node, "numeric literal \"{d}\" cannot be coerced to \"int\"", .{data.val}); | 142 | try ctx.msgNode(node, "numeric literal \"{d}\" cannot be coerced to \"int\"", .{data.val}); |
| 143 | } | 143 | } |
| 144 | }, | 144 | }, |
| 145 | coersion: struct { | ||
| 146 | from: Type, | ||
| 147 | to: Type, | ||
| 148 | src: LazyNode, | ||
| 149 | |||
| 150 | fn build(data: @This(), ctx: *MsgContext) !void { | ||
| 151 | const node = try data.src.get(ctx); | ||
| 152 | try ctx.msgNode(node, "stinky", .{}); | ||
| 153 | } | ||
| 154 | }, | ||
| 145 | }; | 155 | }; |
| 146 | 156 | ||
| 147 | pub const Warn = union(enum) { | 157 | pub const Warn = union(enum) { |
| ... | @@ -614,7 +624,8 @@ pub const MsgContext = struct { | ... | @@ -614,7 +624,8 @@ pub const MsgContext = struct { |
| 614 | 624 | ||
| 615 | pub const LazyNode = struct { | 625 | pub const LazyNode = struct { |
| 616 | decl: Comp.Decl.Index, | 626 | decl: Comp.Decl.Index, |
| 617 | node_offset: i32, | 627 | inst: Teg.Inst.Index, |
| 628 | operand: Operand, | ||
| 618 | 629 | ||
| 619 | pub fn get(lazy: LazyNode, ctx: *MsgContext) !NodeIndex { | 630 | pub fn get(lazy: LazyNode, ctx: *MsgContext) !NodeIndex { |
| 620 | const decl = ctx.comp.intern_pool.declPtrConst(lazy.decl); | 631 | const decl = ctx.comp.intern_pool.declPtrConst(lazy.decl); |
| ... | @@ -640,7 +651,50 @@ pub const LazyNode = struct { | ... | @@ -640,7 +651,50 @@ pub const LazyNode = struct { |
| 640 | 651 | ||
| 641 | const teg_decl = teg.instData(.declaration, decl_inst.resolve(&ctx.comp.intern_pool)); | 652 | const teg_decl = teg.instData(.declaration, decl_inst.resolve(&ctx.comp.intern_pool)); |
| 642 | 653 | ||
| 643 | return @intCast(teg_decl.src_node - lazy.node_offset); | 654 | const node_offset = teg.instNodeOffset(lazy.inst); |
| 655 | |||
| 656 | const base_node: NodeIndex = @intCast(node_offset - teg_decl.src_node); | ||
| 657 | if (lazy.operand == .main_node) | ||
| 658 | return base_node; | ||
| 659 | |||
| 660 | const data = ctx.ast.nodeData(base_node); | ||
| 661 | |||
| 662 | switch (teg.instTag(lazy.inst)) { | ||
| 663 | .as => switch (ctx.ast.nodeTag(base_node)) { | ||
| 664 | .var_decl => { | ||
| 665 | switch (lazy.operand) { | ||
| 666 | .rhs => return data.var_decl.init, | ||
| 667 | else => {}, | ||
| 668 | } | ||
| 669 | }, | ||
| 670 | else => {}, | ||
| 671 | }, | ||
| 672 | else => {}, | ||
| 673 | } | ||
| 674 | |||
| 675 | if (!std.debug.runtime_safety) unreachable; | ||
| 676 | |||
| 677 | std.debug.panic("TODO: operand lookup: .{s} + .{s} + {}", .{ | ||
| 678 | @tagName(teg.instTag(lazy.inst)), | ||
| 679 | @tagName(ctx.ast.nodeTag(base_node)), | ||
| 680 | lazy.operand, | ||
| 681 | }); | ||
| 682 | } | ||
| 683 | }; | ||
| 684 | |||
| 685 | pub const Operand = enum(u32) { | ||
| 686 | /// Point to the main node of an instruction | ||
| 687 | main_node = 0, | ||
| 688 | /// Base of a call, field, or operand to a unary instruction | ||
| 689 | operand = 1, | ||
| 690 | /// Left hand side of a binary instruction | ||
| 691 | lhs, | ||
| 692 | /// Right hand side of a binary instruction | ||
| 693 | rhs, | ||
| 694 | |||
| 695 | /// An argument of a call node | ||
| 696 | pub fn argument(id: u32) Operand { | ||
| 697 | return @enumFromInt(id + 2); | ||
| 644 | } | 698 | } |
| 645 | }; | 699 | }; |
| 646 | 700 | ||
| ... | @@ -660,7 +714,13 @@ const TokenIndex = Ast.TokenIndex; | ... | @@ -660,7 +714,13 @@ const TokenIndex = Ast.TokenIndex; |
| 660 | const NodeIndex = Ast.NodeIndex; | 714 | const NodeIndex = Ast.NodeIndex; |
| 661 | const Location = Ast.Location; | 715 | const Location = Ast.Location; |
| 662 | 716 | ||
| 717 | const Teg = @import("Teg.zig"); | ||
| 718 | |||
| 663 | const Comp = @import("Comp.zig"); | 719 | const Comp = @import("Comp.zig"); |
| 664 | const File = Comp.File; | 720 | const File = Comp.File; |
| 665 | 721 | ||
| 722 | const InternPool = @import("InternPool.zig"); | ||
| 723 | const Value = InternPool.Value; | ||
| 724 | const Type = InternPool.Type; | ||
| 725 | |||
| 666 | const util = @import("util.zig"); | 726 | const util = @import("util.zig"); |
src/compiler/Sema.zig+155-77| ... | @@ -64,7 +64,7 @@ const InstMap = struct { | ... | @@ -64,7 +64,7 @@ const InstMap = struct { |
| 64 | if (assertWithMessage(map.get(from) == null)) { | 64 | if (assertWithMessage(map.get(from) == null)) { |
| 65 | std.debug.panic("%{d} is already mapped (to #{d})", .{ | 65 | std.debug.panic("%{d} is already mapped (to #{d})", .{ |
| 66 | @intFromEnum(from), | 66 | @intFromEnum(from), |
| 67 | @intFromEnum(map.get(from).?.decode().inst), | 67 | @intFromEnum(map.get(from).?.decode().index), |
| 68 | }); | 68 | }); |
| 69 | } | 69 | } |
| 70 | const source_i = @intFromEnum(from); | 70 | const source_i = @intFromEnum(from); |
| ... | @@ -330,7 +330,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { | ... | @@ -330,7 +330,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { |
| 330 | .@"break" => { | 330 | .@"break" => { |
| 331 | const brk: Teg.Inst.Break = s.code.instPayload(.@"break", in); | 331 | const brk: Teg.Inst.Break = s.code.instPayload(.@"break", in); |
| 332 | const operand = try s.resolveRefRuntime(brk.operand); | 332 | const operand = try s.resolveRefRuntime(brk.operand); |
| 333 | const block_ref = s.inst_map.get(brk.block).?.decode().inst; // block ref is resolved by teg | 333 | const block_ref = s.inst_map.get(brk.block).?.decode().index; // block ref is resolved by teg |
| 334 | return s.addInstRef(.@"break", .{ | 334 | return s.addInstRef(.@"break", .{ |
| 335 | .block_ref = block_ref, | 335 | .block_ref = block_ref, |
| 336 | .value = operand, | 336 | .value = operand, |
| ... | @@ -439,7 +439,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { | ... | @@ -439,7 +439,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { |
| 439 | .block => { | 439 | .block => { |
| 440 | const block = try s.analyzeBlock(in); | 440 | const block = try s.analyzeBlock(in); |
| 441 | switch (block.decode()) { | 441 | switch (block.decode()) { |
| 442 | .inst => |t| if (s.tempAir().instTag(t) == .block) { | 442 | .index => |t| if (s.tempAir().instTag(t) == .block) { |
| 443 | try s.scratch.append(s.gpa, @intFromEnum(t)); | 443 | try s.scratch.append(s.gpa, @intFromEnum(t)); |
| 444 | }, | 444 | }, |
| 445 | else => {}, | 445 | else => {}, |
| ... | @@ -455,7 +455,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { | ... | @@ -455,7 +455,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { |
| 455 | .value => |v| switch (v.toKey(s.ip)) { | 455 | .value => |v| switch (v.toKey(s.ip)) { |
| 456 | .comptime_float => |val| { | 456 | .comptime_float => |val| { |
| 457 | try s.report.warn(.numeric_int_var_ambiguity, .{ | 457 | try s.report.warn(.numeric_int_var_ambiguity, .{ |
| 458 | .node = s.nodeLoc(in), | 458 | .node = s.nodeLoc(in, .operand), |
| 459 | }); | 459 | }); |
| 460 | initial_value = (try s.makeValue(.{ .float = val })).toAir(); | 460 | initial_value = (try s.makeValue(.{ .float = val })).toAir(); |
| 461 | }, | 461 | }, |
| ... | @@ -473,7 +473,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { | ... | @@ -473,7 +473,7 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { |
| 473 | const data: Teg.Inst.Store = s.code.instPayload(.store, in); | 473 | const data: Teg.Inst.Store = s.code.instPayload(.store, in); |
| 474 | assert(s.code.instTag(data.memory) == .memory); // corrupt store instruction | 474 | assert(s.code.instTag(data.memory) == .memory); // corrupt store instruction |
| 475 | 475 | ||
| 476 | const location = s.mapTeg(data.memory.toRef()).decode().inst; | 476 | const location = s.mapTeg(data.memory.toRef()).decode().index; |
| 477 | const operand = try s.resolveRefRuntime(data.operand); | 477 | const operand = try s.resolveRefRuntime(data.operand); |
| 478 | 478 | ||
| 479 | // try s.validateType( | 479 | // try s.validateType( |
| ... | @@ -488,9 +488,9 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { | ... | @@ -488,9 +488,9 @@ fn analyzeCodeInner(s: *Sema, in: Teg.Inst.Index) !Air.Inst.Ref { |
| 488 | }, | 488 | }, |
| 489 | .as => { | 489 | .as => { |
| 490 | const as: Teg.Inst.As = s.code.instPayload(.as, in); | 490 | const as: Teg.Inst.As = s.code.instPayload(.as, in); |
| 491 | const coerce_to = try s.resolveRefComptime(as.type); | 491 | const coerce_to = try s.resolveRefComptimeType(in.op(.lhs) ,as.type, .type); |
| 492 | const operand = try s.resolveRefRuntime(as.operand); | 492 | const operand = try s.resolveRefRuntime(as.operand); |
| 493 | return try s.coerceRef(in, operand, coerce_to.toType(s.ip).?); | 493 | return try s.coerceRef(in.op(.rhs), operand, coerce_to.toType(s.ip).?); |
| 494 | }, | 494 | }, |
| 495 | else => |tag| std.debug.panic("TODO: analyze of .{s}", .{@tagName(tag)}), | 495 | else => |tag| std.debug.panic("TODO: analyze of .{s}", .{@tagName(tag)}), |
| 496 | } | 496 | } |
| ... | @@ -516,8 +516,8 @@ fn analyzeRefToBlock(s: *Sema, in: Teg.Inst.Ref) anyerror!Air.Inst.Ref { | ... | @@ -516,8 +516,8 @@ fn analyzeRefToBlock(s: *Sema, in: Teg.Inst.Ref) anyerror!Air.Inst.Ref { |
| 516 | return visited; | 516 | return visited; |
| 517 | } | 517 | } |
| 518 | 518 | ||
| 519 | if (visited.kind == .inst and | 519 | if (visited.kind == .index and |
| 520 | s.air_instructions.items(.tag)[@intFromEnum(visited.decode().inst)] == .block) | 520 | s.air_instructions.items(.tag)[@intFromEnum(visited.decode().index)] == .block) |
| 521 | { | 521 | { |
| 522 | return visited; | 522 | return visited; |
| 523 | } | 523 | } |
| ... | @@ -538,7 +538,7 @@ fn resolveRefRuntimeExtra(s: *Sema, ref: Teg.Inst.Ref, mark: bool) anyerror!Air. | ... | @@ -538,7 +538,7 @@ fn resolveRefRuntimeExtra(s: *Sema, ref: Teg.Inst.Ref, mark: bool) anyerror!Air. |
| 538 | if (s.inst_map.get(index)) |air| { | 538 | if (s.inst_map.get(index)) |air| { |
| 539 | if (mark) { | 539 | if (mark) { |
| 540 | switch (air.decode()) { | 540 | switch (air.decode()) { |
| 541 | .inst => |i| s.markInst(i), | 541 | .index => |i| s.markInst(i), |
| 542 | else => {}, | 542 | else => {}, |
| 543 | } | 543 | } |
| 544 | } | 544 | } |
| ... | @@ -576,67 +576,130 @@ fn resolveRefComptime(s: *Sema, ref: Teg.Inst.Ref) !Value { | ... | @@ -576,67 +576,130 @@ fn resolveRefComptime(s: *Sema, ref: Teg.Inst.Ref) !Value { |
| 576 | } | 576 | } |
| 577 | 577 | ||
| 578 | /// Coerce `value` runtime ref to `coerce_type`, and emit an error at `teg_ref`'s location | 578 | /// Coerce `value` runtime ref to `coerce_type`, and emit an error at `teg_ref`'s location |
| 579 | fn coerceRef( | 579 | fn coerceRef(s: *Sema, src: InstOp, value: Air.Inst.Ref, to: Type) !Air.Inst.Ref { |
| 580 | s: *Sema, | 580 | const from = s.typeOfRef(value); |
| 581 | teg_ref: Teg.Inst.Index, | 581 | if (from == to) { |
| 582 | value: Air.Inst.Ref, | 582 | return value; |
| 583 | coerce_to: Type, | 583 | } |
| 584 | ) !Air.Inst.Ref { | 584 | const index = switch (value.decode()) { |
| 585 | _ = teg_ref; | 585 | .value => |v| return (try s.coerceValue(src, v, to)).toAir(), |
| 586 | _ = s; | 586 | .index => |index| index, |
| 587 | _ = value; | 587 | }; |
| 588 | _ = coerce_to; | 588 | switch (to) { |
| 589 | // const value_type = s.typeOfRef(value); | 589 | .@"opaque" => { |
| 590 | // switch (coerce_type.toKey(s.ip)) { | 590 | // |
| 591 | // .simple_type => |simple_type| switch (simple_type) { | 591 | }, |
| 592 | // // .@"opaque", | 592 | .bool => { |
| 593 | // .int32 => { | 593 | // |
| 594 | // switch (value_type.toKey(s.ip)) { | 594 | }, |
| 595 | // .simple_type => switch (simple_type) { | 595 | .int32 => switch (from) { |
| 596 | // // .int32 => return value, | 596 | .int32 => unreachable, // same type handled |
| 597 | // // .numeric_literal => { | 597 | .numeric_literal => unreachable, // must should comptime known |
| 598 | // // const val = value.decode().value.toKey(s.ip).comptime_float; | 598 | else => {}, |
| 599 | // // std.debug.print("buh {d}\n", .{val}); | 599 | }, |
| 600 | // // if (!math.isFinite(val) or | 600 | .float => switch (from) { |
| 601 | // // val < math.minInt(i32) or | 601 | .float => unreachable, // same type handled |
| 602 | // // val > math.maxInt(i32)) | 602 | .int32 => return index.toRef(), |
| 603 | // // { | 603 | else => {}, |
| 604 | // // try s.fail(.comptime_float_to_int, .{ | 604 | }, |
| 605 | // // .val = val, | 605 | .string => { |
| 606 | // // .src = s.nodeLoc(teg_ref), | 606 | // |
| 607 | // // }); | 607 | }, |
| 608 | // // } | 608 | .noreturn => { |
| 609 | // // return (try s.makeValue(.{ .int32 = @intFromFloat(val) })).toAir(); | 609 | // |
| 610 | // // }, | 610 | }, |
| 611 | // else => |tag| std.debug.panic("TODO: coerceTo value_type simple_type .{s}", .{@tagName(tag)}), | 611 | .type => { |
| 612 | // }, | 612 | // |
| 613 | // else => |tag| std.debug.panic("TODO: coerceTo value_type .{s}", .{@tagName(tag)}), | 613 | }, |
| 614 | // } | 614 | .numeric_literal => { |
| 615 | // }, | 615 | @panic("TODO: error message for not known at compile time"); |
| 616 | // // .float, | 616 | }, |
| 617 | // // .string, | 617 | .void => { |
| 618 | // // .bool, | 618 | // |
| 619 | // // .noreturn, | 619 | }, |
| 620 | // // .type, | 620 | else => {}, |
| 621 | // // .numeric_literal, | 621 | } |
| 622 | // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .simple_type = .{s}", .{@tagName(tag)}), | 622 | return s.coersionError(src, from, to); |
| 623 | // }, | 623 | } |
| 624 | // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .{s}", .{@tagName(tag)}), | 624 | |
| 625 | // } | 625 | fn coerceValue(s: *Sema, src: InstOp, value: Value, to: Type) !Value { |
| 626 | @panic("TODO"); | 626 | const from = value.typeOf(s.ip); |
| 627 | } | 627 | if (from == to) { |
| 628 | 628 | return value; | |
| 629 | fn coerceValue( | 629 | } |
| 630 | s: *Sema, | 630 | switch (to) { |
| 631 | teg_ref: Teg.Inst.Index, | 631 | // .simple_type => |simple_type| switch (simple_type) { |
| 632 | value: Value, | 632 | // // .@"opaque", |
| 633 | coerce_to: Type, | 633 | // .int32 => { |
| 634 | ) !Value { | 634 | // switch (value_type.toKey(s.ip)) { |
| 635 | _ = s; | 635 | // .simple_type => switch (simple_type) { |
| 636 | _ = teg_ref; | 636 | // // .int32 => return value, |
| 637 | _ = value; | 637 | // // .numeric_literal => { |
| 638 | _ = coerce_to; | 638 | // // const val = value.decode().value.toKey(s.ip).comptime_float; |
| 639 | @panic("TODO"); | 639 | // // }, |
| 640 | // else => |tag| std.debug.panic("TODO: coerceTo value_type simple_type .{s}", .{@tagName(tag)}), | ||
| 641 | // }, | ||
| 642 | // else => |tag| std.debug.panic("TODO: coerceTo value_type .{s}", .{@tagName(tag)}), | ||
| 643 | // } | ||
| 644 | // }, | ||
| 645 | // // .float, | ||
| 646 | // // .string, | ||
| 647 | // // .bool, | ||
| 648 | // // .noreturn, | ||
| 649 | // // .type, | ||
| 650 | // // .numeric_literal, | ||
| 651 | // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .simple_type = .{s}", .{@tagName(tag)}), | ||
| 652 | // }, | ||
| 653 | // else => |tag| std.debug.panic("TODO: coerceTo coerce_type .{s}", .{@tagName(tag)}), | ||
| 654 | // } | ||
| 655 | .@"opaque" => { | ||
| 656 | // | ||
| 657 | }, | ||
| 658 | .bool => { | ||
| 659 | // | ||
| 660 | }, | ||
| 661 | .int32 => switch (from) { | ||
| 662 | .int32 => unreachable, // same type handled | ||
| 663 | .numeric_literal, .float => switch (value.toKey(s.ip)) { | ||
| 664 | .comptime_float, .float => |val| { | ||
| 665 | if (!math.isFinite(val) or | ||
| 666 | val < math.minInt(i32) or | ||
| 667 | val > math.maxInt(i32) or | ||
| 668 | (@rem(val, 1) != 0)) | ||
| 669 | { | ||
| 670 | return s.fail(.comptime_float_to_int, .{ | ||
| 671 | .val = val, | ||
| 672 | .src = s.lazyNode(src), | ||
| 673 | }); | ||
| 674 | } | ||
| 675 | |||
| 676 | return try s.makeValue(.{ | ||
| 677 | .int32 = @intFromFloat(val), | ||
| 678 | }); | ||
| 679 | }, | ||
| 680 | else => unreachable, // not a numeric literal | ||
| 681 | }, | ||
| 682 | else => return s.coersionError(src, from, to), | ||
| 683 | }, | ||
| 684 | .float => { | ||
| 685 | // | ||
| 686 | }, | ||
| 687 | .string => { | ||
| 688 | // | ||
| 689 | }, | ||
| 690 | .noreturn => { | ||
| 691 | // | ||
| 692 | }, | ||
| 693 | .type => { | ||
| 694 | // | ||
| 695 | }, | ||
| 696 | .numeric_literal => {}, | ||
| 697 | .void => { | ||
| 698 | // | ||
| 699 | }, | ||
| 700 | else => {}, | ||
| 701 | } | ||
| 702 | return s.coersionError(src, from, to); | ||
| 640 | } | 703 | } |
| 641 | 704 | ||
| 642 | fn resolveDecl(s: *Sema, decl_index: Decl.Index) !Value { | 705 | fn resolveDecl(s: *Sema, decl_index: Decl.Index) !Value { |
| ... | @@ -856,23 +919,35 @@ fn lookupDecl(s: *Sema, name: NullTerminatedString) ?InternPool.DeclIndex { | ... | @@ -856,23 +919,35 @@ fn lookupDecl(s: *Sema, name: NullTerminatedString) ?InternPool.DeclIndex { |
| 856 | } | 919 | } |
| 857 | } | 920 | } |
| 858 | 921 | ||
| 859 | fn nodeLoc(s: *const Sema, in: Teg.Inst.Index) Report.LazyNode { | 922 | fn nodeLoc(s: *const Sema, in: Teg.Inst.Index, op: Report.Operand) Report.LazyNode { |
| 860 | return s.code.instSrcLoc(in, s.decl_index); | 923 | return s.lazyNode(in.op(op)); |
| 861 | } | 924 | } |
| 862 | 925 | ||
| 863 | pub fn addWarn(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void { | 926 | fn addWarn(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void { |
| 864 | try s.report.warn(kind, data); | 927 | try s.report.warn(kind, data); |
| 865 | } | 928 | } |
| 866 | 929 | ||
| 867 | pub fn addError(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void { | 930 | fn addError(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) !void { |
| 868 | try s.report.err(kind, data); | 931 | try s.report.err(kind, data); |
| 869 | } | 932 | } |
| 870 | 933 | ||
| 871 | pub fn fail(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) Error!void { | 934 | fn fail(s: *Sema, comptime kind: Report.Err.FieldEnum, data: std.meta.FieldType(Report.Err, kind)) Error { |
| 872 | try s.report.err(kind, data); | 935 | try s.report.err(kind, data); |
| 873 | return Error.AnalysisFail; | 936 | return Error.AnalysisFail; |
| 874 | } | 937 | } |
| 875 | 938 | ||
| 939 | fn coersionError(s: *Sema, src: InstOp, from: Type, to: Type) Error { | ||
| 940 | return s.fail(.coersion, .{ | ||
| 941 | .from = from, | ||
| 942 | .to = to, | ||
| 943 | .src = s.lazyNode(src), | ||
| 944 | }); | ||
| 945 | } | ||
| 946 | |||
| 947 | fn lazyNode(s: *const Sema, src: InstOp) Report.LazyNode { | ||
| 948 | return src.lazyNode( s.decl_index); | ||
| 949 | } | ||
| 950 | |||
| 876 | const Sema = @This(); | 951 | const Sema = @This(); |
| 877 | 952 | ||
| 878 | const std = @import("std"); | 953 | const std = @import("std"); |
| ... | @@ -895,9 +970,12 @@ const File = Comp.File; | ... | @@ -895,9 +970,12 @@ const File = Comp.File; |
| 895 | const Decl = Comp.Decl; | 970 | const Decl = Comp.Decl; |
| 896 | const Namespace = Comp.Namespace; | 971 | const Namespace = Comp.Namespace; |
| 897 | 972 | ||
| 898 | const Air = @import("Air.zig"); | ||
| 899 | const Teg = @import("Teg.zig"); | 973 | const Teg = @import("Teg.zig"); |
| 974 | const InstOp = Teg.InstOp; | ||
| 975 | |||
| 976 | const Air = @import("Air.zig"); | ||
| 900 | const Report = @import("Report.zig"); | 977 | const Report = @import("Report.zig"); |
| 978 | const Ast = @import("Ast.zig"); | ||
| 901 | const dod = @import("dod.zig"); | 979 | const dod = @import("dod.zig"); |
| 902 | const tracer = @import("tracer"); | 980 | const tracer = @import("tracer"); |
| 903 | 981 |
src/compiler/Teg.Dump.zig+1-1| ... | @@ -23,7 +23,7 @@ const State = struct { | ... | @@ -23,7 +23,7 @@ const State = struct { |
| 23 | const tag = s.teg.instTag(inst); | 23 | const tag = s.teg.instTag(inst); |
| 24 | 24 | ||
| 25 | try tty.setColor(writer, .bright_black); | 25 | try tty.setColor(writer, .bright_black); |
| 26 | const node_offset = teg.instSrcLoc(inst, @enumFromInt(0)).node_offset; | 26 | const node_offset = teg.instNodeOffset(inst); |
| 27 | try writer.print("{c}{d} ", .{ | 27 | try writer.print("{c}{d} ", .{ |
| 28 | @as(u8, if (node_offset >= 0) '+' else '-'), | 28 | @as(u8, if (node_offset >= 0) '+' else '-'), |
| 29 | @abs(node_offset), | 29 | @abs(node_offset), |
src/compiler/Teg.zig+25-12| ... | @@ -180,6 +180,10 @@ pub const Inst = struct { | ... | @@ -180,6 +180,10 @@ pub const Inst = struct { |
| 180 | pub fn toOptional(i: Index) OptionalIndex { | 180 | pub fn toOptional(i: Index) OptionalIndex { |
| 181 | return @enumFromInt(@intFromEnum(i)); | 181 | return @enumFromInt(@intFromEnum(i)); |
| 182 | } | 182 | } |
| 183 | |||
| 184 | pub fn op(i: Index, operand: Report.Operand) InstOp { | ||
| 185 | return .{ .index = i, .op = operand }; | ||
| 186 | } | ||
| 183 | }; | 187 | }; |
| 184 | 188 | ||
| 185 | pub const OptionalIndex = enum(u32) { | 189 | pub const OptionalIndex = enum(u32) { |
| ... | @@ -318,6 +322,19 @@ pub const Inst = struct { | ... | @@ -318,6 +322,19 @@ pub const Inst = struct { |
| 318 | }; | 322 | }; |
| 319 | }; | 323 | }; |
| 320 | 324 | ||
| 325 | pub const InstOp = struct { | ||
| 326 | index: Inst.Index, | ||
| 327 | op: Report.Operand, | ||
| 328 | |||
| 329 | pub fn lazyNode(inst: InstOp, decl: Comp.Decl.Index) LazyNode { | ||
| 330 | return .{ | ||
| 331 | .inst = inst.index, | ||
| 332 | .operand = inst.op, | ||
| 333 | .decl = decl, | ||
| 334 | }; | ||
| 335 | } | ||
| 336 | }; | ||
| 337 | |||
| 321 | pub const NullTerminatedString = enum(u32) { | 338 | pub const NullTerminatedString = enum(u32) { |
| 322 | empty = 0, | 339 | empty = 0, |
| 323 | _, | 340 | _, |
| ... | @@ -382,6 +399,14 @@ pub fn instPayload(teg: *const Teg, comptime tag: Inst.Tag, index: Inst.Index) t | ... | @@ -382,6 +399,14 @@ pub fn instPayload(teg: *const Teg, comptime tag: Inst.Tag, index: Inst.Index) t |
| 382 | return teg.instData(tag, index).extra_index.get(teg); | 399 | return teg.instData(tag, index).extra_index.get(teg); |
| 383 | } | 400 | } |
| 384 | 401 | ||
| 402 | pub fn instNodeOffset(teg: *const Teg, index: Inst.Index) i32 { | ||
| 403 | switch (teg.instTag(index)) { | ||
| 404 | inline else => |tag| { | ||
| 405 | return teg.instData(tag, index).src_node; | ||
| 406 | }, | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 385 | pub fn blockInstructions(teg: *const Teg, index: Inst.Index) []const Inst.Index { | 410 | pub fn blockInstructions(teg: *const Teg, index: Inst.Index) []const Inst.Index { |
| 386 | return teg.instData(.block, index).extra_index.get(teg).slice(teg); | 411 | return teg.instData(.block, index).extra_index.get(teg).slice(teg); |
| 387 | } | 412 | } |
| ... | @@ -396,18 +421,6 @@ pub fn declData(teg: *const Teg, index: Inst.Index) Inst.Decl { | ... | @@ -396,18 +421,6 @@ pub fn declData(teg: *const Teg, index: Inst.Index) Inst.Decl { |
| 396 | return teg.instData(.declaration, index).extra_index.get(teg); | 421 | return teg.instData(.declaration, index).extra_index.get(teg); |
| 397 | } | 422 | } |
| 398 | 423 | ||
| 399 | pub fn instSrcLoc(teg: *const Teg, inst: Inst.Index, decl: Comp.Decl.Index) LazyNode { | ||
| 400 | switch (teg.instTag(inst)) { | ||
| 401 | inline else => |tag| { | ||
| 402 | const data = teg.instData(tag, inst); | ||
| 403 | return .{ | ||
| 404 | .node_offset = data.src_node, | ||
| 405 | .decl = decl, | ||
| 406 | }; | ||
| 407 | }, | ||
| 408 | } | ||
| 409 | } | ||
| 410 | |||
| 411 | pub fn moduleDeclarations(teg: *const Teg, module_index: Inst.Index) []const Inst.Index { | 424 | pub fn moduleDeclarations(teg: *const Teg, module_index: Inst.Index) []const Inst.Index { |
| 412 | const module = teg.instData(.module, module_index); | 425 | const module = teg.instData(.module, module_index); |
| 413 | const module_data: IndexList = module.extra_index.get(teg); | 426 | const module_data: IndexList = module.extra_index.get(teg); |