fix: semantic restrictions for global variables, constant folding
This commit is contained in:
parent
cbcc796f1e
commit
9b5cd4038f
13 changed files with 569 additions and 375 deletions
|
|
@ -504,6 +504,7 @@ fn setDeclaration(
|
||||||
.extra_index = astgen.addExtraAssumeCapacity(Ir.Inst.Declaration{
|
.extra_index = astgen.addExtraAssumeCapacity(Ir.Inst.Declaration{
|
||||||
.name = args.name,
|
.name = args.name,
|
||||||
.value = args.value,
|
.value = args.value,
|
||||||
|
.flags = if (args.node.tag == .const_decl) 0x01 else 0x00,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,7 @@ pub const Inst = struct {
|
||||||
pub const Declaration = struct {
|
pub const Declaration = struct {
|
||||||
name: NullTerminatedString,
|
name: NullTerminatedString,
|
||||||
value: Index,
|
value: Index,
|
||||||
|
flags: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Var = struct {
|
pub const Var = struct {
|
||||||
|
|
|
||||||
760
src/Sema.zig
760
src/Sema.zig
File diff suppressed because it is too large
Load diff
|
|
@ -2,6 +2,22 @@ const std = @import("std");
|
||||||
const fatal = std.process.fatal;
|
const fatal = std.process.fatal;
|
||||||
const ink = @import("../root.zig");
|
const ink = @import("../root.zig");
|
||||||
|
|
||||||
|
test "fixture - hello world" {
|
||||||
|
try testRuntimeFixture("hello-world");
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixture - monsieur-fogg" {
|
||||||
|
try testRuntimeFixture("monsieur-fogg");
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixture - variable arithmetic" {
|
||||||
|
try testRuntimeFixture("variable-arithmetic");
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixture - constant folding" {
|
||||||
|
try testRuntimeFixture("constant-folding");
|
||||||
|
}
|
||||||
|
|
||||||
const Options = struct {
|
const Options = struct {
|
||||||
input_reader: *std.Io.Reader,
|
input_reader: *std.Io.Reader,
|
||||||
error_writer: *std.Io.Writer,
|
error_writer: *std.Io.Writer,
|
||||||
|
|
@ -63,11 +79,3 @@ fn testRuntimeFixture(comptime fixture: []const u8) !void {
|
||||||
});
|
});
|
||||||
return std.testing.expectEqualSlices(u8, transcript_bytes, io_w.written());
|
return std.testing.expectEqualSlices(u8, transcript_bytes, io_w.written());
|
||||||
}
|
}
|
||||||
|
|
||||||
test "fixture - hello world" {
|
|
||||||
try testRuntimeFixture("hello-world");
|
|
||||||
}
|
|
||||||
|
|
||||||
test "fixture - monsieur-fogg" {
|
|
||||||
try testRuntimeFixture("monsieur-fogg");
|
|
||||||
}
|
|
||||||
|
|
|
||||||
0
src/Story/testdata/constant-folding/input.txt
vendored
Normal file
0
src/Story/testdata/constant-folding/input.txt
vendored
Normal file
4
src/Story/testdata/constant-folding/story.ink
vendored
Normal file
4
src/Story/testdata/constant-folding/story.ink
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
VAR a = b + 1
|
||||||
|
CONST b = c
|
||||||
|
CONST c = 1
|
||||||
|
{a}
|
||||||
1
src/Story/testdata/constant-folding/transcript.txt
vendored
Normal file
1
src/Story/testdata/constant-folding/transcript.txt
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
2
|
||||||
0
src/Story/testdata/variable-arithmetic/input.txt
vendored
Normal file
0
src/Story/testdata/variable-arithmetic/input.txt
vendored
Normal file
3
src/Story/testdata/variable-arithmetic/story.ink
vendored
Normal file
3
src/Story/testdata/variable-arithmetic/story.ink
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
VAR a = 1
|
||||||
|
VAR b = 2
|
||||||
|
{a + b}
|
||||||
1
src/Story/testdata/variable-arithmetic/transcript.txt
vendored
Normal file
1
src/Story/testdata/variable-arithmetic/transcript.txt
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
3
|
||||||
123
src/compile.zig
123
src/compile.zig
|
|
@ -10,7 +10,6 @@ const assert = std.debug.assert;
|
||||||
pub fn IntrusiveQueue(comptime T: type) type {
|
pub fn IntrusiveQueue(comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
head: ?*T = null,
|
head: ?*T = null,
|
||||||
tail: ?*T = null,
|
tail: ?*T = null,
|
||||||
|
|
||||||
|
|
@ -80,32 +79,35 @@ test IntrusiveQueue {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const InternPool = struct {
|
pub const InternPool = struct {
|
||||||
constants: std.ArrayListUnmanaged(Constant.Key) = .empty,
|
values: std.ArrayListUnmanaged(Key) = .empty,
|
||||||
constants_map: std.AutoHashMapUnmanaged(Constant.Key, Constant.Index) = .empty,
|
values_map: std.AutoHashMapUnmanaged(Key, Index) = .empty,
|
||||||
code_chunks: std.ArrayListUnmanaged(*Module.CodeChunk) = .empty,
|
code_chunks: std.ArrayListUnmanaged(*Module.CodeChunk) = .empty,
|
||||||
|
|
||||||
pub const Constant = struct {
|
pub const Index = enum(u32) {
|
||||||
pub const Key = union(enum) {
|
none,
|
||||||
int: u64,
|
_,
|
||||||
str: Ir.NullTerminatedString,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Index = enum(u32) {
|
|
||||||
_,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn getOrPutConstant(
|
pub const Key = union(enum) {
|
||||||
|
int: u64,
|
||||||
|
str: Ir.NullTerminatedString,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn getOrPutValue(
|
||||||
ip: *InternPool,
|
ip: *InternPool,
|
||||||
gpa: std.mem.Allocator,
|
gpa: std.mem.Allocator,
|
||||||
key: Constant.Key,
|
key: Key,
|
||||||
) error{OutOfMemory}!Constant.Index {
|
) error{OutOfMemory}!Index {
|
||||||
if (ip.constants_map.get(key)) |index| {
|
if (ip.values_map.get(key)) |index| {
|
||||||
return index;
|
return index;
|
||||||
} else {
|
} else {
|
||||||
const new_index: Constant.Index = @enumFromInt(ip.constants.items.len);
|
const new_index: Index = @enumFromInt(ip.values.items.len);
|
||||||
try ip.constants.append(gpa, key);
|
const new_value: Key = switch (key) {
|
||||||
try ip.constants_map.put(gpa, key, new_index);
|
.int => |int| .{ .int = int },
|
||||||
|
.str => |str| .{ .str = str },
|
||||||
|
};
|
||||||
|
try ip.values.append(gpa, new_value);
|
||||||
|
try ip.values_map.put(gpa, key, new_index);
|
||||||
return new_index;
|
return new_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -114,8 +116,8 @@ pub const InternPool = struct {
|
||||||
ip: *InternPool,
|
ip: *InternPool,
|
||||||
gpa: std.mem.Allocator,
|
gpa: std.mem.Allocator,
|
||||||
value: u64,
|
value: u64,
|
||||||
) error{OutOfMemory}!Constant.Index {
|
) error{OutOfMemory}!Index {
|
||||||
return ip.getOrPutConstant(gpa, .{
|
return ip.getOrPutValue(gpa, .{
|
||||||
.int = value,
|
.int = value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -123,16 +125,16 @@ pub const InternPool = struct {
|
||||||
pub fn getOrPutStr(
|
pub fn getOrPutStr(
|
||||||
ip: *InternPool,
|
ip: *InternPool,
|
||||||
gpa: std.mem.Allocator,
|
gpa: std.mem.Allocator,
|
||||||
start: Ir.NullTerminatedString,
|
value: Ir.NullTerminatedString,
|
||||||
) error{OutOfMemory}!Constant.Index {
|
) error{OutOfMemory}!Index {
|
||||||
return ip.getOrPutConstant(gpa, .{
|
return ip.getOrPutValue(gpa, .{
|
||||||
.str = start,
|
.str = value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getStrBytes(ip: *InternPool, ir: Ir, index: Constant.Index) []const u8 {
|
pub fn getStrBytes(ip: *InternPool, ir: Ir, index: Index) []const u8 {
|
||||||
assert(ip.constants.items.len > @intFromEnum(index));
|
assert(ip.values.items.len > @intFromEnum(index));
|
||||||
const c = ip.constants.items[@intFromEnum(index)];
|
const c = ip.values.items[@intFromEnum(index)];
|
||||||
return ir.nullTerminatedString(c.str);
|
return ir.nullTerminatedString(c.str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,8 +144,8 @@ pub const InternPool = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(ip: *InternPool, gpa: std.mem.Allocator) void {
|
pub fn deinit(ip: *InternPool, gpa: std.mem.Allocator) void {
|
||||||
ip.constants.deinit(gpa);
|
ip.values.deinit(gpa);
|
||||||
ip.constants_map.deinit(gpa);
|
ip.values_map.deinit(gpa);
|
||||||
ip.code_chunks.deinit(gpa);
|
ip.code_chunks.deinit(gpa);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -151,7 +153,7 @@ pub const InternPool = struct {
|
||||||
pub const WorkItem = struct {
|
pub const WorkItem = struct {
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
next: ?*WorkItem = null,
|
next: ?*WorkItem = null,
|
||||||
decl_name: InternPool.Constant.Index,
|
decl_name: InternPool.Index,
|
||||||
inst_index: Ir.Inst.Index,
|
inst_index: Ir.Inst.Index,
|
||||||
namespace: *Module.Namespace,
|
namespace: *Module.Namespace,
|
||||||
|
|
||||||
|
|
@ -169,13 +171,19 @@ pub const Module = struct {
|
||||||
tree: Ast,
|
tree: Ast,
|
||||||
ir: Ir,
|
ir: Ir,
|
||||||
intern_pool: InternPool = .{},
|
intern_pool: InternPool = .{},
|
||||||
|
globals: std.ArrayListUnmanaged(Global) = .empty,
|
||||||
knots: std.ArrayListUnmanaged(Knot) = .empty,
|
knots: std.ArrayListUnmanaged(Knot) = .empty,
|
||||||
stitches: std.ArrayListUnmanaged(Stitch) = .empty,
|
stitches: std.ArrayListUnmanaged(Stitch) = .empty,
|
||||||
errors: std.ArrayListUnmanaged(Error) = .empty,
|
errors: std.ArrayListUnmanaged(Error) = .empty,
|
||||||
work_queue: WorkQueue = .{},
|
work_queue: WorkQueue = .{},
|
||||||
|
|
||||||
|
pub const Global = struct {
|
||||||
|
key: InternPool.Index,
|
||||||
|
value: InternPool.Index,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Knot = struct {
|
pub const Knot = struct {
|
||||||
name_index: InternPool.Constant.Index,
|
name_index: InternPool.Index,
|
||||||
code_index: CodeChunk.Index,
|
code_index: CodeChunk.Index,
|
||||||
|
|
||||||
pub const Index = enum(u32) {
|
pub const Index = enum(u32) {
|
||||||
|
|
@ -186,7 +194,7 @@ pub const Module = struct {
|
||||||
pub const Stitch = struct {
|
pub const Stitch = struct {
|
||||||
knot_index: ?Knot.Index,
|
knot_index: ?Knot.Index,
|
||||||
code_index: CodeChunk.Index,
|
code_index: CodeChunk.Index,
|
||||||
name_index: InternPool.Constant.Index,
|
name_index: InternPool.Index,
|
||||||
|
|
||||||
pub const Index = enum(u32) {
|
pub const Index = enum(u32) {
|
||||||
_,
|
_,
|
||||||
|
|
@ -195,18 +203,26 @@ pub const Module = struct {
|
||||||
|
|
||||||
pub const Namespace = struct {
|
pub const Namespace = struct {
|
||||||
parent: ?*Namespace,
|
parent: ?*Namespace,
|
||||||
decls: std.AutoHashMapUnmanaged(InternPool.Constant.Index, Decl),
|
decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl),
|
||||||
|
|
||||||
pub const Decl = struct {
|
pub const Decl = struct {
|
||||||
tag: Tag,
|
tag: Tag,
|
||||||
namespace: ?*Namespace,
|
namespace: ?*Namespace,
|
||||||
decl_inst: Ir.Inst.Index,
|
decl_inst: Ir.Inst.Index,
|
||||||
args_count: u32,
|
args_count: u32,
|
||||||
|
resolution: Resolution = .unresolved,
|
||||||
|
|
||||||
|
pub const Resolution = union(enum) {
|
||||||
|
unresolved,
|
||||||
|
in_progress,
|
||||||
|
resolved: Sema.ValueInfo,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Tag = enum {
|
pub const Tag = enum {
|
||||||
knot,
|
knot,
|
||||||
stitch,
|
stitch,
|
||||||
variable,
|
var_mut,
|
||||||
|
var_const,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -237,6 +253,7 @@ pub const Module = struct {
|
||||||
const extra = mod.ir.extraData(Ir.Inst.Block, data.extra_index);
|
const extra = mod.ir.extraData(Ir.Inst.Block, data.extra_index);
|
||||||
const top_level_decls = mod.ir.bodySlice(extra.end, extra.data.body_len);
|
const top_level_decls = mod.ir.bodySlice(extra.end, extra.data.body_len);
|
||||||
|
|
||||||
|
var knot_index: ?Knot.Index = null;
|
||||||
var sema: Sema = .{
|
var sema: Sema = .{
|
||||||
.module = mod,
|
.module = mod,
|
||||||
.gpa = gpa,
|
.gpa = gpa,
|
||||||
|
|
@ -247,39 +264,36 @@ pub const Module = struct {
|
||||||
defer sema.deinit();
|
defer sema.deinit();
|
||||||
|
|
||||||
const file_scope = try mod.createNamespace(null);
|
const file_scope = try mod.createNamespace(null);
|
||||||
for (top_level_decls) |decl_index| {
|
try sema.scanTopLevelDecls(file_scope, top_level_decls);
|
||||||
try sema.analyzeTopLevelDecl(file_scope, decl_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
var knot_index: ?Knot.Index = null;
|
|
||||||
while (mod.work_queue.pop()) |work_unit| {
|
while (mod.work_queue.pop()) |work_unit| {
|
||||||
const chunk_index = mod.intern_pool.code_chunks.items.len;
|
const chunk_index = mod.intern_pool.code_chunks.items.len;
|
||||||
var chunk: Sema.Chunk = .{
|
var builder: Sema.Builder = .{
|
||||||
.sema = &sema,
|
.sema = &sema,
|
||||||
.code = try mod.createCodeChunk(),
|
.code = try mod.createCodeChunk(),
|
||||||
.namespace = work_unit.namespace,
|
.namespace = work_unit.namespace,
|
||||||
};
|
};
|
||||||
defer chunk.deinit(gpa);
|
defer builder.deinit(gpa);
|
||||||
|
|
||||||
const debug_name_str = mod.intern_pool.getStrBytes(mod.ir, work_unit.decl_name);
|
const debug_name_str = mod.intern_pool.getStrBytes(mod.ir, work_unit.decl_name);
|
||||||
std.debug.print("Analyzing {s}\n", .{debug_name_str});
|
std.debug.print("Analyzing {s}\n", .{debug_name_str});
|
||||||
switch (work_unit.tag) {
|
switch (work_unit.tag) {
|
||||||
.knot => {
|
.knot => {
|
||||||
try sema.analyzeKnot(&chunk, work_unit.inst_index);
|
try sema.analyzeKnot(&builder, work_unit.inst_index);
|
||||||
try chunk.finalize();
|
try builder.finalize();
|
||||||
|
|
||||||
knot_index = @enumFromInt(mod.knots.items.len);
|
knot_index = @enumFromInt(mod.knots.items.len);
|
||||||
try mod.intern_pool.code_chunks.append(gpa, chunk.code);
|
try mod.intern_pool.code_chunks.append(gpa, builder.code);
|
||||||
try mod.knots.append(gpa, .{
|
try mod.knots.append(gpa, .{
|
||||||
.name_index = work_unit.decl_name,
|
.name_index = work_unit.decl_name,
|
||||||
.code_index = @enumFromInt(chunk_index),
|
.code_index = @enumFromInt(chunk_index),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.stitch => {
|
.stitch => {
|
||||||
try sema.analyzeStitch(&chunk, work_unit.inst_index);
|
try sema.analyzeStitch(&builder, work_unit.inst_index);
|
||||||
try chunk.finalize();
|
try builder.finalize();
|
||||||
|
|
||||||
try mod.intern_pool.code_chunks.append(gpa, chunk.code);
|
try mod.intern_pool.code_chunks.append(gpa, builder.code);
|
||||||
try mod.stitches.append(gpa, .{
|
try mod.stitches.append(gpa, .{
|
||||||
.knot_index = knot_index,
|
.knot_index = knot_index,
|
||||||
.name_index = work_unit.decl_name,
|
.name_index = work_unit.decl_name,
|
||||||
|
|
@ -360,10 +374,10 @@ pub const Module = struct {
|
||||||
|
|
||||||
pub fn setupStoryRuntime(mod: *Module, gpa: std.mem.Allocator, story: *Story) !void {
|
pub fn setupStoryRuntime(mod: *Module, gpa: std.mem.Allocator, story: *Story) !void {
|
||||||
assert(mod.errors.items.len == 0);
|
assert(mod.errors.items.len == 0);
|
||||||
const constants_len = mod.intern_pool.constants.items.len;
|
const constants_len = mod.intern_pool.values.items.len;
|
||||||
|
|
||||||
try story.constants_pool.ensureUnusedCapacity(gpa, constants_len);
|
try story.constants_pool.ensureUnusedCapacity(gpa, constants_len);
|
||||||
for (mod.intern_pool.constants.items) |constant| {
|
for (mod.intern_pool.values.items) |constant| {
|
||||||
switch (constant) {
|
switch (constant) {
|
||||||
.int => |value| {
|
.int => |value| {
|
||||||
const obj = try Object.Number.create(story, .{
|
const obj = try Object.Number.create(story, .{
|
||||||
|
|
@ -380,6 +394,14 @@ pub const Module = struct {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (mod.globals.items) |global| {
|
||||||
|
const key_bytes = mod.intern_pool.getStrBytes(mod.ir, global.key);
|
||||||
|
const constant_data = mod.intern_pool.values.items[@intFromEnum(global.value)];
|
||||||
|
const value_obj = try Object.Number.create(story, .{
|
||||||
|
.integer = @intCast(constant_data.int),
|
||||||
|
});
|
||||||
|
try story.globals.put(gpa, key_bytes, @ptrCast(value_obj));
|
||||||
|
}
|
||||||
for (mod.knots.items) |knot| {
|
for (mod.knots.items) |knot| {
|
||||||
const name_bytes = mod.intern_pool.getStrBytes(mod.ir, knot.name_index);
|
const name_bytes = mod.intern_pool.getStrBytes(mod.ir, knot.name_index);
|
||||||
const code_chunk = mod.intern_pool.getCodeChunk(knot.code_index);
|
const code_chunk = mod.intern_pool.getCodeChunk(knot.code_index);
|
||||||
|
|
@ -438,7 +460,7 @@ pub const Module = struct {
|
||||||
mod: *Module,
|
mod: *Module,
|
||||||
options: struct {
|
options: struct {
|
||||||
tag: WorkItem.Tag,
|
tag: WorkItem.Tag,
|
||||||
decl_name: InternPool.Constant.Index,
|
decl_name: InternPool.Index,
|
||||||
inst_index: Ir.Inst.Index,
|
inst_index: Ir.Inst.Index,
|
||||||
namespace: *Namespace,
|
namespace: *Namespace,
|
||||||
},
|
},
|
||||||
|
|
@ -476,6 +498,7 @@ pub const Module = struct {
|
||||||
const gpa = mod.gpa;
|
const gpa = mod.gpa;
|
||||||
mod.ir.deinit(gpa);
|
mod.ir.deinit(gpa);
|
||||||
mod.intern_pool.deinit(gpa);
|
mod.intern_pool.deinit(gpa);
|
||||||
|
mod.globals.deinit(gpa);
|
||||||
mod.knots.deinit(gpa);
|
mod.knots.deinit(gpa);
|
||||||
mod.stitches.deinit(gpa);
|
mod.stitches.deinit(gpa);
|
||||||
mod.errors.deinit(gpa);
|
mod.errors.deinit(gpa);
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,29 @@ test "compiler: invalid divert target" {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "compiler: global variable restrictions" {
|
||||||
|
try testEqual(
|
||||||
|
\\VAR a = b
|
||||||
|
\\VAR b = a
|
||||||
|
,
|
||||||
|
\\<STDIN>:1:9: error: global variable assignments cannot refer to other variables
|
||||||
|
\\1 | VAR a = b
|
||||||
|
\\ | ^
|
||||||
|
\\
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "compiler: constant cycle detection" {
|
||||||
|
try testEqual(
|
||||||
|
\\CONST a = a
|
||||||
|
,
|
||||||
|
\\<STDIN>:1:11: error: cycle detected in constant initializer
|
||||||
|
\\1 | CONST a = a
|
||||||
|
\\ | ^
|
||||||
|
\\
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn testEqual(source_bytes: [:0]const u8, expected_error: []const u8) !void {
|
fn testEqual(source_bytes: [:0]const u8, expected_error: []const u8) !void {
|
||||||
const gpa = std.testing.allocator;
|
const gpa = std.testing.allocator;
|
||||||
var arena_allocator = std.heap.ArenaAllocator.init(gpa);
|
var arena_allocator = std.heap.ArenaAllocator.init(gpa);
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,9 @@ pub const Writer = struct {
|
||||||
fn writeDeclarationInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
|
fn writeDeclarationInst(self: *Writer, w: *std.Io.Writer, inst: Ir.Inst.Index) Error!void {
|
||||||
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
|
const data = self.code.instructions[@intFromEnum(inst)].data.payload;
|
||||||
const extra = self.code.extraData(Ir.Inst.Declaration, data.extra_index);
|
const extra = self.code.extraData(Ir.Inst.Declaration, data.extra_index);
|
||||||
|
if (extra.data.flags == 0x01) {
|
||||||
|
try w.writeAll("const, ");
|
||||||
|
}
|
||||||
try w.writeAll("name=");
|
try w.writeAll("name=");
|
||||||
try self.writeStringRef(w, extra.data.name);
|
try self.writeStringRef(w, extra.data.name);
|
||||||
try w.writeAll(", ");
|
try w.writeAll(", ");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue