2018-07-12 12:08:40 -07:00
|
|
|
const std = @import("std");
|
2018-07-14 21:04:12 -07:00
|
|
|
const builtin = @import("builtin");
|
2018-07-12 12:08:40 -07:00
|
|
|
const Allocator = mem.Allocator;
|
|
|
|
const Decl = @import("decl.zig").Decl;
|
2018-07-14 13:12:41 -07:00
|
|
|
const Compilation = @import("compilation.zig").Compilation;
|
2018-07-12 12:08:40 -07:00
|
|
|
const mem = std.mem;
|
|
|
|
const ast = std.zig.ast;
|
|
|
|
const Value = @import("value.zig").Value;
|
2018-07-24 17:24:05 -07:00
|
|
|
const Type = @import("type.zig").Type;
|
2018-07-12 12:08:40 -07:00
|
|
|
const ir = @import("ir.zig");
|
2018-07-14 21:04:12 -07:00
|
|
|
const Span = @import("errmsg.zig").Span;
|
2018-07-19 12:11:39 -07:00
|
|
|
const assert = std.debug.assert;
|
2018-07-22 20:27:58 -07:00
|
|
|
const event = std.event;
|
2018-07-24 17:24:05 -07:00
|
|
|
const llvm = @import("llvm.zig");
|
2018-07-12 12:08:40 -07:00
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const Scope = struct {
|
2017-12-26 16:44:08 -08:00
|
|
|
id: Id,
|
2018-07-12 12:08:40 -07:00
|
|
|
parent: ?*Scope,
|
2018-07-24 17:24:05 -07:00
|
|
|
ref_count: std.atomic.Int(usize),
|
2018-07-12 12:08:40 -07:00
|
|
|
|
2018-07-24 17:24:05 -07:00
|
|
|
/// Thread-safe
|
2018-07-12 12:08:40 -07:00
|
|
|
pub fn ref(base: *Scope) void {
|
2018-07-24 17:24:05 -07:00
|
|
|
_ = base.ref_count.incr();
|
2018-07-12 12:08:40 -07:00
|
|
|
}
|
|
|
|
|
2018-07-24 17:24:05 -07:00
|
|
|
/// Thread-safe
|
2018-07-14 13:12:41 -07:00
|
|
|
pub fn deref(base: *Scope, comp: *Compilation) void {
|
2018-07-24 17:24:05 -07:00
|
|
|
if (base.ref_count.decr() == 1) {
|
2018-07-14 13:12:41 -07:00
|
|
|
if (base.parent) |parent| parent.deref(comp);
|
2018-07-12 12:08:40 -07:00
|
|
|
switch (base.id) {
|
2018-07-19 12:11:39 -07:00
|
|
|
Id.Root => @fieldParentPtr(Root, "base", base).destroy(comp),
|
|
|
|
Id.Decls => @fieldParentPtr(Decls, "base", base).destroy(comp),
|
2018-07-14 13:12:41 -07:00
|
|
|
Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
|
|
|
|
Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp),
|
|
|
|
Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp),
|
|
|
|
Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(comp),
|
|
|
|
Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp),
|
2018-07-24 17:24:05 -07:00
|
|
|
Id.Var => @fieldParentPtr(Var, "base", base).destroy(comp),
|
2018-08-02 14:04:17 -07:00
|
|
|
Id.AstTree => @fieldParentPtr(AstTree, "base", base).destroy(comp),
|
2018-07-12 12:08:40 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-19 12:11:39 -07:00
|
|
|
pub fn findRoot(base: *Scope) *Root {
|
|
|
|
var scope = base;
|
|
|
|
while (scope.parent) |parent| {
|
|
|
|
scope = parent;
|
|
|
|
}
|
|
|
|
assert(scope.id == Id.Root);
|
|
|
|
return @fieldParentPtr(Root, "base", scope);
|
|
|
|
}
|
|
|
|
|
2018-07-12 12:08:40 -07:00
|
|
|
pub fn findFnDef(base: *Scope) ?*FnDef {
|
|
|
|
var scope = base;
|
|
|
|
while (true) {
|
|
|
|
switch (scope.id) {
|
2018-07-24 17:24:05 -07:00
|
|
|
Id.FnDef => return @fieldParentPtr(FnDef, "base", scope),
|
|
|
|
Id.Root, Id.Decls => return null,
|
2018-07-12 12:08:40 -07:00
|
|
|
|
|
|
|
Id.Block,
|
|
|
|
Id.Defer,
|
|
|
|
Id.DeferExpr,
|
|
|
|
Id.CompTime,
|
2018-07-24 17:24:05 -07:00
|
|
|
Id.Var,
|
|
|
|
=> scope = scope.parent.?,
|
2018-08-03 14:22:17 -07:00
|
|
|
|
|
|
|
Id.AstTree => unreachable,
|
2018-07-12 12:08:40 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-12-26 16:44:08 -08:00
|
|
|
|
2018-07-18 14:40:59 -07:00
|
|
|
pub fn findDeferExpr(base: *Scope) ?*DeferExpr {
|
|
|
|
var scope = base;
|
|
|
|
while (true) {
|
|
|
|
switch (scope.id) {
|
2018-07-24 17:24:05 -07:00
|
|
|
Id.DeferExpr => return @fieldParentPtr(DeferExpr, "base", scope),
|
2018-07-18 14:40:59 -07:00
|
|
|
|
|
|
|
Id.FnDef,
|
|
|
|
Id.Decls,
|
|
|
|
=> return null,
|
|
|
|
|
|
|
|
Id.Block,
|
|
|
|
Id.Defer,
|
|
|
|
Id.CompTime,
|
2018-07-19 12:11:39 -07:00
|
|
|
Id.Root,
|
2018-07-24 17:24:05 -07:00
|
|
|
Id.Var,
|
2018-07-18 14:40:59 -07:00
|
|
|
=> scope = scope.parent orelse return null,
|
2018-08-03 14:22:17 -07:00
|
|
|
|
|
|
|
Id.AstTree => unreachable,
|
2018-07-18 14:40:59 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-24 17:24:05 -07:00
|
|
|
fn init(base: *Scope, id: Id, parent: *Scope) void {
|
2018-11-13 05:08:37 -08:00
|
|
|
base.* = Scope{
|
2018-07-24 17:24:05 -07:00
|
|
|
.id = id,
|
|
|
|
.parent = parent,
|
|
|
|
.ref_count = std.atomic.Int(usize).init(1),
|
|
|
|
};
|
|
|
|
parent.ref();
|
|
|
|
}
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const Id = enum {
|
2018-07-19 12:11:39 -07:00
|
|
|
Root,
|
2018-08-02 14:04:17 -07:00
|
|
|
AstTree,
|
2017-12-26 16:44:08 -08:00
|
|
|
Decls,
|
|
|
|
Block,
|
|
|
|
FnDef,
|
|
|
|
CompTime,
|
2018-07-12 12:08:40 -07:00
|
|
|
Defer,
|
|
|
|
DeferExpr,
|
2018-07-24 17:24:05 -07:00
|
|
|
Var,
|
2018-07-12 12:08:40 -07:00
|
|
|
};
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const Root = struct {
|
2018-07-19 12:11:39 -07:00
|
|
|
base: Scope,
|
|
|
|
realpath: []const u8,
|
2018-08-02 14:04:17 -07:00
|
|
|
decls: *Decls,
|
2018-07-19 12:11:39 -07:00
|
|
|
|
|
|
|
/// Creates a Root scope with 1 reference
|
|
|
|
/// Takes ownership of realpath
|
2018-08-02 14:04:17 -07:00
|
|
|
pub fn create(comp: *Compilation, realpath: []u8) !*Root {
|
2018-07-24 17:24:05 -07:00
|
|
|
const self = try comp.gpa().createOne(Root);
|
2018-11-13 05:08:37 -08:00
|
|
|
self.* = Root{
|
|
|
|
.base = Scope{
|
2018-07-19 12:11:39 -07:00
|
|
|
.id = Id.Root,
|
|
|
|
.parent = null,
|
2018-07-24 17:24:05 -07:00
|
|
|
.ref_count = std.atomic.Int(usize).init(1),
|
2018-07-19 12:11:39 -07:00
|
|
|
},
|
|
|
|
.realpath = realpath,
|
2018-08-02 14:04:17 -07:00
|
|
|
.decls = undefined,
|
2018-07-24 17:24:05 -07:00
|
|
|
};
|
2018-08-02 14:04:17 -07:00
|
|
|
errdefer comp.gpa().destroy(self);
|
|
|
|
self.decls = try Decls.create(comp, &self.base);
|
2018-07-19 12:11:39 -07:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn destroy(self: *Root, comp: *Compilation) void {
|
2018-08-03 14:22:17 -07:00
|
|
|
// TODO comp.fs_watch.removeFile(self.realpath);
|
2018-08-02 14:04:17 -07:00
|
|
|
self.decls.base.deref(comp);
|
|
|
|
comp.gpa().free(self.realpath);
|
|
|
|
comp.gpa().destroy(self);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const AstTree = struct {
|
2018-08-02 14:04:17 -07:00
|
|
|
base: Scope,
|
|
|
|
tree: *ast.Tree,
|
|
|
|
|
|
|
|
/// Creates a scope with 1 reference
|
|
|
|
/// Takes ownership of tree, will deinit and destroy when done.
|
2018-08-03 14:22:17 -07:00
|
|
|
pub fn create(comp: *Compilation, tree: *ast.Tree, root_scope: *Root) !*AstTree {
|
|
|
|
const self = try comp.gpa().createOne(AstTree);
|
2018-11-13 05:08:37 -08:00
|
|
|
self.* = AstTree{
|
2018-08-02 14:04:17 -07:00
|
|
|
.base = undefined,
|
|
|
|
.tree = tree,
|
|
|
|
};
|
2018-08-03 14:22:17 -07:00
|
|
|
self.base.init(Id.AstTree, &root_scope.base);
|
2018-08-02 14:04:17 -07:00
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn destroy(self: *AstTree, comp: *Compilation) void {
|
2018-07-19 12:11:39 -07:00
|
|
|
comp.gpa().free(self.tree.source);
|
|
|
|
self.tree.deinit();
|
2018-07-23 11:28:14 -07:00
|
|
|
comp.gpa().destroy(self.tree);
|
2018-07-19 12:11:39 -07:00
|
|
|
comp.gpa().destroy(self);
|
|
|
|
}
|
2018-08-02 14:04:17 -07:00
|
|
|
|
|
|
|
pub fn root(self: *AstTree) *Root {
|
|
|
|
return self.base.findRoot();
|
|
|
|
}
|
2018-07-19 12:11:39 -07:00
|
|
|
};
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const Decls = struct {
|
2018-07-12 12:08:40 -07:00
|
|
|
base: Scope,
|
2018-07-22 20:27:58 -07:00
|
|
|
|
2018-08-02 14:04:17 -07:00
|
|
|
/// This table remains Write Locked when the names are incomplete or possibly outdated.
|
|
|
|
/// So if a reader manages to grab a lock, it can be sure that the set of names is complete
|
|
|
|
/// and correct.
|
|
|
|
table: event.RwLocked(Decl.Table),
|
2018-07-12 12:08:40 -07:00
|
|
|
|
|
|
|
/// Creates a Decls scope with 1 reference
|
2018-07-19 12:11:39 -07:00
|
|
|
pub fn create(comp: *Compilation, parent: *Scope) !*Decls {
|
2018-07-24 17:24:05 -07:00
|
|
|
const self = try comp.gpa().createOne(Decls);
|
2018-11-13 05:08:37 -08:00
|
|
|
self.* = Decls{
|
2018-07-24 17:24:05 -07:00
|
|
|
.base = undefined,
|
2018-08-02 14:04:17 -07:00
|
|
|
.table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())),
|
2018-07-24 17:24:05 -07:00
|
|
|
};
|
|
|
|
self.base.init(Id.Decls, parent);
|
2018-07-12 12:08:40 -07:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2018-07-19 12:11:39 -07:00
|
|
|
pub fn destroy(self: *Decls, comp: *Compilation) void {
|
2018-07-12 12:08:40 -07:00
|
|
|
self.table.deinit();
|
2018-07-19 12:11:39 -07:00
|
|
|
comp.gpa().destroy(self);
|
2018-07-12 12:08:40 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const Block = struct {
|
2018-07-12 12:08:40 -07:00
|
|
|
base: Scope,
|
2018-07-18 14:40:59 -07:00
|
|
|
incoming_values: std.ArrayList(*ir.Inst),
|
2018-07-12 12:08:40 -07:00
|
|
|
incoming_blocks: std.ArrayList(*ir.BasicBlock),
|
|
|
|
end_block: *ir.BasicBlock,
|
2018-07-18 14:40:59 -07:00
|
|
|
is_comptime: *ir.Inst,
|
2018-07-12 12:08:40 -07:00
|
|
|
|
2018-07-14 21:04:12 -07:00
|
|
|
safety: Safety,
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
const Safety = union(enum) {
|
2018-07-14 21:04:12 -07:00
|
|
|
Auto,
|
|
|
|
Manual: Manual,
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
const Manual = struct {
|
2018-07-14 21:04:12 -07:00
|
|
|
/// the source span that disabled the safety value
|
|
|
|
span: Span,
|
|
|
|
|
|
|
|
/// whether safety is enabled
|
|
|
|
enabled: bool,
|
|
|
|
};
|
|
|
|
|
|
|
|
fn get(self: Safety, comp: *Compilation) bool {
|
|
|
|
return switch (self) {
|
|
|
|
Safety.Auto => switch (comp.build_mode) {
|
|
|
|
builtin.Mode.Debug,
|
|
|
|
builtin.Mode.ReleaseSafe,
|
|
|
|
=> true,
|
|
|
|
builtin.Mode.ReleaseFast,
|
|
|
|
builtin.Mode.ReleaseSmall,
|
|
|
|
=> false,
|
|
|
|
},
|
|
|
|
@TagType(Safety).Manual => |man| man.enabled,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-07-12 12:08:40 -07:00
|
|
|
/// Creates a Block scope with 1 reference
|
2018-07-19 12:11:39 -07:00
|
|
|
pub fn create(comp: *Compilation, parent: *Scope) !*Block {
|
2018-07-24 17:24:05 -07:00
|
|
|
const self = try comp.gpa().createOne(Block);
|
2018-11-13 05:08:37 -08:00
|
|
|
self.* = Block{
|
2018-07-24 17:24:05 -07:00
|
|
|
.base = undefined,
|
2018-07-12 12:08:40 -07:00
|
|
|
.incoming_values = undefined,
|
|
|
|
.incoming_blocks = undefined,
|
|
|
|
.end_block = undefined,
|
|
|
|
.is_comptime = undefined,
|
2018-07-14 21:04:12 -07:00
|
|
|
.safety = Safety.Auto,
|
2018-07-24 17:24:05 -07:00
|
|
|
};
|
|
|
|
self.base.init(Id.Block, parent);
|
2018-07-12 12:08:40 -07:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2018-07-14 13:12:41 -07:00
|
|
|
pub fn destroy(self: *Block, comp: *Compilation) void {
|
2018-07-16 17:52:50 -07:00
|
|
|
comp.gpa().destroy(self);
|
2018-07-12 12:08:40 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const FnDef = struct {
|
2018-07-12 12:08:40 -07:00
|
|
|
base: Scope,
|
|
|
|
|
|
|
|
/// This reference is not counted so that the scope can get destroyed with the function
|
2018-07-24 17:24:05 -07:00
|
|
|
fn_val: ?*Value.Fn,
|
2018-07-12 12:08:40 -07:00
|
|
|
|
|
|
|
/// Creates a FnDef scope with 1 reference
|
|
|
|
/// Must set the fn_val later
|
2018-07-19 12:11:39 -07:00
|
|
|
pub fn create(comp: *Compilation, parent: *Scope) !*FnDef {
|
2018-07-24 17:24:05 -07:00
|
|
|
const self = try comp.gpa().createOne(FnDef);
|
2018-11-13 05:08:37 -08:00
|
|
|
self.* = FnDef{
|
2018-07-24 17:24:05 -07:00
|
|
|
.base = undefined,
|
|
|
|
.fn_val = null,
|
|
|
|
};
|
|
|
|
self.base.init(Id.FnDef, parent);
|
2018-07-12 12:08:40 -07:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2018-07-14 13:12:41 -07:00
|
|
|
pub fn destroy(self: *FnDef, comp: *Compilation) void {
|
2018-07-16 17:52:50 -07:00
|
|
|
comp.gpa().destroy(self);
|
2018-07-12 12:08:40 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const CompTime = struct {
|
2018-07-12 12:08:40 -07:00
|
|
|
base: Scope,
|
|
|
|
|
|
|
|
/// Creates a CompTime scope with 1 reference
|
2018-07-19 12:11:39 -07:00
|
|
|
pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {
|
2018-07-24 17:24:05 -07:00
|
|
|
const self = try comp.gpa().createOne(CompTime);
|
2018-11-13 05:08:37 -08:00
|
|
|
self.* = CompTime{ .base = undefined };
|
2018-07-24 17:24:05 -07:00
|
|
|
self.base.init(Id.CompTime, parent);
|
2018-07-12 12:08:40 -07:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2018-07-14 13:12:41 -07:00
|
|
|
pub fn destroy(self: *CompTime, comp: *Compilation) void {
|
2018-07-16 17:52:50 -07:00
|
|
|
comp.gpa().destroy(self);
|
2018-07-12 12:08:40 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const Defer = struct {
|
2018-07-12 12:08:40 -07:00
|
|
|
base: Scope,
|
|
|
|
defer_expr_scope: *DeferExpr,
|
|
|
|
kind: Kind,
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const Kind = enum {
|
2018-07-12 12:08:40 -07:00
|
|
|
ScopeExit,
|
|
|
|
ErrorExit,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Creates a Defer scope with 1 reference
|
|
|
|
pub fn create(
|
2018-07-14 13:12:41 -07:00
|
|
|
comp: *Compilation,
|
2018-07-19 12:11:39 -07:00
|
|
|
parent: *Scope,
|
2018-07-12 12:08:40 -07:00
|
|
|
kind: Kind,
|
|
|
|
defer_expr_scope: *DeferExpr,
|
|
|
|
) !*Defer {
|
2018-07-24 17:24:05 -07:00
|
|
|
const self = try comp.gpa().createOne(Defer);
|
2018-11-13 05:08:37 -08:00
|
|
|
self.* = Defer{
|
2018-07-24 17:24:05 -07:00
|
|
|
.base = undefined,
|
2018-07-12 12:08:40 -07:00
|
|
|
.defer_expr_scope = defer_expr_scope,
|
|
|
|
.kind = kind,
|
2018-07-24 17:24:05 -07:00
|
|
|
};
|
|
|
|
self.base.init(Id.Defer, parent);
|
2018-07-12 12:08:40 -07:00
|
|
|
defer_expr_scope.base.ref();
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2018-07-14 13:12:41 -07:00
|
|
|
pub fn destroy(self: *Defer, comp: *Compilation) void {
|
|
|
|
self.defer_expr_scope.base.deref(comp);
|
2018-07-16 17:52:50 -07:00
|
|
|
comp.gpa().destroy(self);
|
2018-07-12 12:08:40 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const DeferExpr = struct {
|
2018-07-12 12:08:40 -07:00
|
|
|
base: Scope,
|
|
|
|
expr_node: *ast.Node,
|
2018-07-18 14:40:59 -07:00
|
|
|
reported_err: bool,
|
2018-07-12 12:08:40 -07:00
|
|
|
|
|
|
|
/// Creates a DeferExpr scope with 1 reference
|
2018-07-19 12:11:39 -07:00
|
|
|
pub fn create(comp: *Compilation, parent: *Scope, expr_node: *ast.Node) !*DeferExpr {
|
2018-07-24 17:24:05 -07:00
|
|
|
const self = try comp.gpa().createOne(DeferExpr);
|
2018-11-13 05:08:37 -08:00
|
|
|
self.* = DeferExpr{
|
2018-07-24 17:24:05 -07:00
|
|
|
.base = undefined,
|
2018-07-12 12:08:40 -07:00
|
|
|
.expr_node = expr_node,
|
2018-07-18 14:40:59 -07:00
|
|
|
.reported_err = false,
|
2018-07-24 17:24:05 -07:00
|
|
|
};
|
|
|
|
self.base.init(Id.DeferExpr, parent);
|
2018-07-12 12:08:40 -07:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2018-07-14 13:12:41 -07:00
|
|
|
pub fn destroy(self: *DeferExpr, comp: *Compilation) void {
|
2018-07-16 17:52:50 -07:00
|
|
|
comp.gpa().destroy(self);
|
2018-07-12 12:08:40 -07:00
|
|
|
}
|
2017-12-26 16:44:08 -08:00
|
|
|
};
|
2018-07-24 17:24:05 -07:00
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const Var = struct {
|
2018-07-24 17:24:05 -07:00
|
|
|
base: Scope,
|
|
|
|
name: []const u8,
|
|
|
|
src_node: *ast.Node,
|
|
|
|
data: Data,
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const Data = union(enum) {
|
2018-07-24 17:24:05 -07:00
|
|
|
Param: Param,
|
|
|
|
Const: *Value,
|
|
|
|
};
|
|
|
|
|
2018-11-13 05:08:37 -08:00
|
|
|
pub const Param = struct {
|
2018-07-24 17:24:05 -07:00
|
|
|
index: usize,
|
|
|
|
typ: *Type,
|
|
|
|
llvm_value: llvm.ValueRef,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub fn createParam(
|
|
|
|
comp: *Compilation,
|
|
|
|
parent: *Scope,
|
|
|
|
name: []const u8,
|
|
|
|
src_node: *ast.Node,
|
|
|
|
param_index: usize,
|
|
|
|
param_type: *Type,
|
|
|
|
) !*Var {
|
|
|
|
const self = try create(comp, parent, name, src_node);
|
2018-11-13 05:08:37 -08:00
|
|
|
self.data = Data{
|
|
|
|
.Param = Param{
|
2018-07-24 17:24:05 -07:00
|
|
|
.index = param_index,
|
|
|
|
.typ = param_type,
|
|
|
|
.llvm_value = undefined,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn createConst(
|
|
|
|
comp: *Compilation,
|
|
|
|
parent: *Scope,
|
|
|
|
name: []const u8,
|
|
|
|
src_node: *ast.Node,
|
|
|
|
value: *Value,
|
|
|
|
) !*Var {
|
|
|
|
const self = try create(comp, parent, name, src_node);
|
2018-11-13 05:08:37 -08:00
|
|
|
self.data = Data{ .Const = value };
|
2018-07-24 17:24:05 -07:00
|
|
|
value.ref();
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create(comp: *Compilation, parent: *Scope, name: []const u8, src_node: *ast.Node) !*Var {
|
|
|
|
const self = try comp.gpa().createOne(Var);
|
2018-11-13 05:08:37 -08:00
|
|
|
self.* = Var{
|
2018-07-24 17:24:05 -07:00
|
|
|
.base = undefined,
|
|
|
|
.name = name,
|
|
|
|
.src_node = src_node,
|
|
|
|
.data = undefined,
|
|
|
|
};
|
|
|
|
self.base.init(Id.Var, parent);
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn destroy(self: *Var, comp: *Compilation) void {
|
|
|
|
switch (self.data) {
|
|
|
|
Data.Param => {},
|
|
|
|
Data.Const => |value| value.deref(comp),
|
|
|
|
}
|
|
|
|
comp.gpa().destroy(self);
|
|
|
|
}
|
|
|
|
};
|
2017-12-26 16:44:08 -08:00
|
|
|
};
|