aboutsummaryrefslogtreecommitdiff
path: root/src/Package.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-04-08 19:05:05 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-04-08 19:05:05 -0700
commit482b995a4963e045860c7fb1a4e11c48cf4de880 (patch)
treee00079980426580bbefd547e879d890dab842511 /src/Package.zig
parentb9e508c410cd077d704a73418281f6d7839df241 (diff)
downloadzig-482b995a4963e045860c7fb1a4e11c48cf4de880.tar.gz
zig-482b995a4963e045860c7fb1a4e11c48cf4de880.zip
stage2: blaze the trail for std lib integration
This branch adds "builtin" and "std" to the import table when using the self-hosted backend. "builtin" gains one additional item: ``` pub const zig_is_stage2 = true; // false when using stage1 backend ``` This allows the std lib to do conditional compilation based on detecting which backend is being used. This will be removed from builtin as soon as self-hosted catches up to feature parity with stage1. Keep a sharp eye out - people are going to be tempted to abuse this. The general rule of thumb is do not use `builtin.zig_is_stage2`. However this commit breaks the rule so that we can gain limited start.zig support as we incrementally improve the self-hosted compiler. This commit also implements `fullyQualifiedNameHash` and related functionality, which effectively puts all Decls in their proper namespaces. `fullyQualifiedName` is not yet implemented. Stop printing "todo" log messages for test decls unless we are in test mode. Add "previous definition here" error notes for Decl name collisions. This commit does not bring us yet to a newly passing test case. Here's what I'm working towards: ```zig const std = @import("std"); export fn main() c_int { const a = std.fs.base64_alphabet[0]; return a - 'A'; } ``` Current output: ``` $ ./zig-cache/bin/zig build-exe test.zig test.zig:3:1: error: TODO implement more analyze elemptr zig-cache/lib/zig/std/start.zig:38:46: error: TODO implement structInitExpr ty ``` So the next steps are clear: * Sema: improve elemptr * AstGen: implement structInitExpr
Diffstat (limited to 'src/Package.zig')
-rw-r--r--src/Package.zig76
1 files changed, 68 insertions, 8 deletions
diff --git a/src/Package.zig b/src/Package.zig
index 33ff4766ca..25a9f55d63 100644
--- a/src/Package.zig
+++ b/src/Package.zig
@@ -4,18 +4,29 @@ const std = @import("std");
const fs = std.fs;
const mem = std.mem;
const Allocator = mem.Allocator;
+const assert = std.debug.assert;
const Compilation = @import("Compilation.zig");
+const Module = @import("Module.zig");
pub const Table = std.StringHashMapUnmanaged(*Package);
+pub const root_namespace_hash: Module.Scope.NameHash = .{
+ 0, 0, 6, 6, 6, 0, 0, 0,
+ 6, 9, 0, 0, 0, 4, 2, 0,
+};
+
root_src_directory: Compilation.Directory,
/// Relative to `root_src_directory`. May contain path separators.
root_src_path: []const u8,
table: Table = .{},
parent: ?*Package = null,
+namespace_hash: Module.Scope.NameHash,
+/// Whether to free `root_src_directory` on `destroy`.
+root_src_directory_owned: bool = false,
/// Allocate a Package. No references to the slices passed are kept.
+/// Don't forget to set `namespace_hash` later.
pub fn create(
gpa: *Allocator,
/// Null indicates the current working directory
@@ -38,27 +49,69 @@ pub fn create(
.handle = if (owned_dir_path) |p| try fs.cwd().openDir(p, .{}) else fs.cwd(),
},
.root_src_path = owned_src_path,
+ .root_src_directory_owned = true,
+ .namespace_hash = undefined,
};
return ptr;
}
-/// Free all memory associated with this package and recursively call destroy
-/// on all packages in its table
+pub fn createWithDir(
+ gpa: *Allocator,
+ directory: Compilation.Directory,
+ /// Relative to `directory`. If null, means `directory` is the root src dir
+ /// and is owned externally.
+ root_src_dir_path: ?[]const u8,
+ /// Relative to root_src_dir_path
+ root_src_path: []const u8,
+) !*Package {
+ const ptr = try gpa.create(Package);
+ errdefer gpa.destroy(ptr);
+
+ const owned_src_path = try gpa.dupe(u8, root_src_path);
+ errdefer gpa.free(owned_src_path);
+
+ if (root_src_dir_path) |p| {
+ const owned_dir_path = try directory.join(gpa, &[1][]const u8{p});
+ errdefer gpa.free(owned_dir_path);
+
+ ptr.* = .{
+ .root_src_directory = .{
+ .path = owned_dir_path,
+ .handle = try directory.handle.openDir(p, .{}),
+ },
+ .root_src_directory_owned = true,
+ .root_src_path = owned_src_path,
+ .namespace_hash = undefined,
+ };
+ } else {
+ ptr.* = .{
+ .root_src_directory = directory,
+ .root_src_directory_owned = false,
+ .root_src_path = owned_src_path,
+ .namespace_hash = undefined,
+ };
+ }
+ return ptr;
+}
+
+/// Free all memory associated with this package. It does not destroy any packages
+/// inside its table; the caller is responsible for calling destroy() on them.
pub fn destroy(pkg: *Package, gpa: *Allocator) void {
gpa.free(pkg.root_src_path);
- // If root_src_directory.path is null then the handle is the cwd()
- // which shouldn't be closed.
- if (pkg.root_src_directory.path) |p| {
- gpa.free(p);
- pkg.root_src_directory.handle.close();
+ if (pkg.root_src_directory_owned) {
+ // If root_src_directory.path is null then the handle is the cwd()
+ // which shouldn't be closed.
+ if (pkg.root_src_directory.path) |p| {
+ gpa.free(p);
+ pkg.root_src_directory.handle.close();
+ }
}
{
var it = pkg.table.iterator();
while (it.next()) |kv| {
- kv.value.destroy(gpa);
gpa.free(kv.key);
}
}
@@ -72,3 +125,10 @@ pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package)
const name_dupe = try mem.dupe(gpa, u8, name);
pkg.table.putAssumeCapacityNoClobber(name_dupe, package);
}
+
+pub fn addAndAdopt(parent: *Package, gpa: *Allocator, name: []const u8, child: *Package) !void {
+ assert(child.parent == null); // make up your mind, who is the parent??
+ child.parent = parent;
+ child.namespace_hash = std.zig.hashName(parent.namespace_hash, ":", name);
+ return parent.add(gpa, name, child);
+}