clean up self hosted main. delete unsupported commands

This commit is contained in:
Andrew Kelley 2018-06-22 01:49:32 -04:00
parent be2a4c42bd
commit 8866bef92c
4 changed files with 122 additions and 460 deletions

View File

@ -168,7 +168,7 @@ pub const Args = struct {
}
// e.g. --names value1 value2 value3
pub fn many(self: *Args, name: []const u8) ?[]const []const u8 {
pub fn many(self: *Args, name: []const u8) []const []const u8 {
if (self.flags.get(name)) |entry| {
switch (entry.value) {
FlagArg.Many => |inner| {
@ -177,7 +177,7 @@ pub const Args = struct {
else => @panic("attempted to retrieve flag with wrong type"),
}
} else {
return null;
return []const []const u8{};
}
}
};

View File

@ -26,15 +26,11 @@ const usage =
\\
\\Commands:
\\
\\ build Build project from build.zig
\\ build-exe [source] Create executable from source or object files
\\ build-lib [source] Create library from source or object files
\\ build-obj [source] Create object from source or assembly
\\ fmt [source] Parse file and render in canonical zig format
\\ run [source] Create executable and run immediately
\\ targets List available compilation targets
\\ test [source] Create and run a test build
\\ translate-c [source] Convert c code to zig code
\\ version Print version number and exit
\\ zen Print zen of zig and exit
\\
@ -47,7 +43,7 @@ const Command = struct {
};
pub fn main() !void {
var allocator = std.heap.c_allocator;
const allocator = std.heap.c_allocator;
var stdout_file = try std.io.getStdOut();
var stdout_out_stream = std.io.FileOutStream.init(&stdout_file);
@ -58,18 +54,16 @@ pub fn main() !void {
stderr = &stderr_out_stream.stream;
const args = try os.argsAlloc(allocator);
defer os.argsFree(allocator, args);
// TODO I'm getting unreachable code here, which shouldn't happen
//defer os.argsFree(allocator, args);
if (args.len <= 1) {
try stderr.write("expected command argument\n\n");
try stderr.write(usage);
os.exit(1);
}
const commands = []Command{
Command{
.name = "build",
.exec = cmdBuild,
},
Command{
.name = "build-exe",
.exec = cmdBuildExe,
@ -86,22 +80,10 @@ pub fn main() !void {
.name = "fmt",
.exec = cmdFmt,
},
Command{
.name = "run",
.exec = cmdRun,
},
Command{
.name = "targets",
.exec = cmdTargets,
},
Command{
.name = "test",
.exec = cmdTest,
},
Command{
.name = "translate-c",
.exec = cmdTranslateC,
},
Command{
.name = "version",
.exec = cmdVersion,
@ -124,177 +106,15 @@ pub fn main() !void {
for (commands) |command| {
if (mem.eql(u8, command.name, args[1])) {
try command.exec(allocator, args[2..]);
return;
return command.exec(allocator, args[2..]);
}
}
try stderr.print("unknown command: {}\n\n", args[1]);
try stderr.write(usage);
os.exit(1);
}
// cmd:build ///////////////////////////////////////////////////////////////////////////////////////
const usage_build =
\\usage: zig build <options>
\\
\\General Options:
\\ --help Print this help and exit
\\ --init Generate a build.zig template
\\ --build-file [file] Override path to build.zig
\\ --cache-dir [path] Override path to cache directory
\\ --verbose Print commands before executing them
\\ --prefix [path] Override default install prefix
\\
\\Project-Specific Options:
\\
\\ Project-specific options become available when the build file is found.
\\
\\Advanced Options:
\\ --build-file [file] Override path to build.zig
\\ --cache-dir [path] Override path to cache directory
\\ --verbose-tokenize Enable compiler debug output for tokenization
\\ --verbose-ast Enable compiler debug output for parsing into an AST
\\ --verbose-link Enable compiler debug output for linking
\\ --verbose-ir Enable compiler debug output for Zig IR
\\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
\\ --verbose-cimport Enable compiler debug output for C imports
\\
\\
;
const args_build_spec = []Flag{
Flag.Bool("--help"),
Flag.Bool("--init"),
Flag.Arg1("--build-file"),
Flag.Arg1("--cache-dir"),
Flag.Bool("--verbose"),
Flag.Arg1("--prefix"),
Flag.Arg1("--build-file"),
Flag.Arg1("--cache-dir"),
Flag.Bool("--verbose-tokenize"),
Flag.Bool("--verbose-ast"),
Flag.Bool("--verbose-link"),
Flag.Bool("--verbose-ir"),
Flag.Bool("--verbose-llvm-ir"),
Flag.Bool("--verbose-cimport"),
};
const missing_build_file =
\\No 'build.zig' file found.
\\
\\Initialize a 'build.zig' template file with `zig build --init`,
\\or build an executable directly with `zig build-exe $FILENAME.zig`.
\\
\\See: `zig build --help` or `zig help` for more options.
\\
;
fn cmdBuild(allocator: *Allocator, args: []const []const u8) !void {
var flags = try Args.parse(allocator, args_build_spec, args);
defer flags.deinit();
if (flags.present("help")) {
try stderr.write(usage_build);
os.exit(0);
}
const zig_lib_dir = try introspect.resolveZigLibDir(allocator);
defer allocator.free(zig_lib_dir);
const zig_std_dir = try os.path.join(allocator, zig_lib_dir, "std");
defer allocator.free(zig_std_dir);
const special_dir = try os.path.join(allocator, zig_std_dir, "special");
defer allocator.free(special_dir);
const build_runner_path = try os.path.join(allocator, special_dir, "build_runner.zig");
defer allocator.free(build_runner_path);
const build_file = flags.single("build-file") orelse "build.zig";
const build_file_abs = try os.path.resolve(allocator, ".", build_file);
defer allocator.free(build_file_abs);
const build_file_exists = os.File.access(allocator, build_file_abs, os.default_file_mode) catch false;
if (flags.present("init")) {
if (build_file_exists) {
try stderr.print("build.zig already exists\n");
os.exit(1);
}
// need a new scope for proper defer scope finalization on exit
{
const build_template_path = try os.path.join(allocator, special_dir, "build_file_template.zig");
defer allocator.free(build_template_path);
try os.copyFile(allocator, build_template_path, build_file_abs);
try stderr.print("wrote build.zig template\n");
}
os.exit(0);
}
if (!build_file_exists) {
try stderr.write(missing_build_file);
os.exit(1);
}
// TODO: Invoke build.zig entrypoint directly?
var zig_exe_path = try os.selfExePath(allocator);
defer allocator.free(zig_exe_path);
var build_args = ArrayList([]const u8).init(allocator);
defer build_args.deinit();
const build_file_basename = os.path.basename(build_file_abs);
const build_file_dirname = os.path.dirname(build_file_abs) orelse ".";
var full_cache_dir: []u8 = undefined;
if (flags.single("cache-dir")) |cache_dir| {
full_cache_dir = try os.path.resolve(allocator, ".", cache_dir, full_cache_dir);
} else {
full_cache_dir = try os.path.join(allocator, build_file_dirname, "zig-cache");
}
defer allocator.free(full_cache_dir);
const path_to_build_exe = try os.path.join(allocator, full_cache_dir, "build");
defer allocator.free(path_to_build_exe);
try build_args.append(path_to_build_exe);
try build_args.append(zig_exe_path);
try build_args.append(build_file_dirname);
try build_args.append(full_cache_dir);
var proc = try os.ChildProcess.init(build_args.toSliceConst(), allocator);
defer proc.deinit();
var term = try proc.spawnAndWait();
switch (term) {
os.ChildProcess.Term.Exited => |status| {
if (status != 0) {
try stderr.print("{} exited with status {}\n", build_args.at(0), status);
os.exit(1);
}
},
os.ChildProcess.Term.Signal => |signal| {
try stderr.print("{} killed by signal {}\n", build_args.at(0), signal);
os.exit(1);
},
os.ChildProcess.Term.Stopped => |signal| {
try stderr.print("{} stopped by signal {}\n", build_args.at(0), signal);
os.exit(1);
},
os.ChildProcess.Term.Unknown => |status| {
try stderr.print("{} encountered unknown failure {}\n", build_args.at(0), status);
os.exit(1);
},
}
}
// cmd:build-exe ///////////////////////////////////////////////////////////////////////////////////
const usage_build_generic =
\\usage: zig build-exe <options> [file]
\\ zig build-lib <options> [file]
@ -315,8 +135,11 @@ const usage_build_generic =
\\ --output-h [file] Override generated header file path
\\ --pkg-begin [name] [path] Make package available to import and push current pkg
\\ --pkg-end Pop current pkg
\\ --release-fast Build with optimizations on and safety off
\\ --release-safe Build with optimizations on and safety on
\\ --mode [mode] Set the build mode
\\ debug (default) optimizations off, safety on
\\ release-fast optimizations on, safety off
\\ release-safe optimizations on, safety on
\\ release-small optimize for small binary, safety off
\\ --static Output will be statically linked
\\ --strip Exclude debug symbols
\\ --target-arch [name] Specify target architecture
@ -367,6 +190,12 @@ const args_build_generic = []Flag{
"off",
"on",
}),
Flag.Option("--mode", []const []const u8{
"debug",
"release-fast",
"release-safe",
"release-small",
}),
Flag.ArgMergeN("--assembly", 1),
Flag.Arg1("--cache-dir"),
@ -383,8 +212,6 @@ const args_build_generic = []Flag{
// NOTE: Parsed manually after initial check
Flag.ArgN("--pkg-begin", 2),
Flag.Bool("--pkg-end"),
Flag.Bool("--release-fast"),
Flag.Bool("--release-safe"),
Flag.Bool("--static"),
Flag.Bool("--strip"),
Flag.Arg1("--target-arch"),
@ -431,16 +258,25 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
defer flags.deinit();
if (flags.present("help")) {
try stderr.write(usage_build_generic);
try stdout.write(usage_build_generic);
os.exit(0);
}
var build_mode = builtin.Mode.Debug;
if (flags.present("release-fast")) {
build_mode = builtin.Mode.ReleaseFast;
} else if (flags.present("release-safe")) {
build_mode = builtin.Mode.ReleaseSafe;
}
const build_mode = blk: {
if (flags.single("mode")) |mode_flag| {
if (mem.eql(u8, mode_flag, "debug")) {
break :blk builtin.Mode.Debug;
} else if (mem.eql(u8, mode_flag, "release-fast")) {
break :blk builtin.Mode.ReleaseFast;
} else if (mem.eql(u8, mode_flag, "release-safe")) {
break :blk builtin.Mode.ReleaseSafe;
} else if (mem.eql(u8, mode_flag, "release-small")) {
break :blk builtin.Mode.ReleaseSmall;
} else unreachable;
} else {
break :blk builtin.Mode.Debug;
}
};
const color = blk: {
if (flags.single("color")) |color_flag| {
@ -456,20 +292,21 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
}
};
var emit_type = Module.Emit.Binary;
if (flags.single("emit")) |emit_flag| {
if (mem.eql(u8, emit_flag, "asm")) {
emit_type = Module.Emit.Assembly;
} else if (mem.eql(u8, emit_flag, "bin")) {
emit_type = Module.Emit.Binary;
} else if (mem.eql(u8, emit_flag, "llvm-ir")) {
emit_type = Module.Emit.LlvmIr;
const emit_type = blk: {
if (flags.single("emit")) |emit_flag| {
if (mem.eql(u8, emit_flag, "asm")) {
break :blk Module.Emit.Assembly;
} else if (mem.eql(u8, emit_flag, "bin")) {
break :blk Module.Emit.Binary;
} else if (mem.eql(u8, emit_flag, "llvm-ir")) {
break :blk Module.Emit.LlvmIr;
} else unreachable;
} else {
unreachable;
break :blk Module.Emit.Binary;
}
}
};
var cur_pkg = try Module.CliPkg.init(allocator, "", "", null); // TODO: Need a path, name?
var cur_pkg = try CliPkg.init(allocator, "", "", null);
defer cur_pkg.deinit();
var i: usize = 0;
@ -482,15 +319,16 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
i += 1;
const new_pkg_path = args[i];
var new_cur_pkg = try Module.CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg);
var new_cur_pkg = try CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg);
try cur_pkg.children.append(new_cur_pkg);
cur_pkg = new_cur_pkg;
} else if (mem.eql(u8, "--pkg-end", arg_name)) {
if (cur_pkg.parent == null) {
if (cur_pkg.parent) |parent| {
cur_pkg = parent;
} else {
try stderr.print("encountered --pkg-end with no matching --pkg-begin\n");
os.exit(1);
}
cur_pkg = cur_pkg.parent.?;
}
}
@ -499,43 +337,42 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
os.exit(1);
}
var in_file: ?[]const u8 = undefined;
switch (flags.positionals.len) {
0 => {
try stderr.write("--name [name] not provided and unable to infer\n");
os.exit(1);
},
1 => {
in_file = flags.positionals.at(0);
},
const provided_name = flags.single("name");
const root_source_file = switch (flags.positionals.len) {
0 => null,
1 => flags.positionals.at(0),
else => {
try stderr.write("only one zig input file is accepted during build\n");
try stderr.print("unexpected extra parameter: {}\n", flags.positionals.at(1));
os.exit(1);
},
}
const basename = os.path.basename(in_file.?);
var it = mem.split(basename, ".");
const root_name = it.next() orelse {
try stderr.write("file name cannot be empty\n");
os.exit(1);
};
const asm_a = flags.many("assembly");
const obj_a = flags.many("object");
if (in_file == null and (obj_a == null or obj_a.?.len == 0) and (asm_a == null or asm_a.?.len == 0)) {
const root_name = if (provided_name) |n| n else blk: {
if (root_source_file) |file| {
const basename = os.path.basename(file);
var it = mem.split(basename, ".");
break :blk it.next() orelse basename;
} else {
try stderr.write("--name [name] not provided and unable to infer\n");
os.exit(1);
}
};
const assembly_files = flags.many("assembly");
const link_objects = flags.many("object");
if (root_source_file == null and link_objects.len == 0 and assembly_files.len == 0) {
try stderr.write("Expected source file argument or at least one --object or --assembly argument\n");
os.exit(1);
}
if (out_type == Module.Kind.Obj and (obj_a != null and obj_a.?.len != 0)) {
if (out_type == Module.Kind.Obj and link_objects.len != 0) {
try stderr.write("When building an object file, --object arguments are invalid\n");
os.exit(1);
}
const zig_root_source_file = in_file;
const full_cache_dir = os.path.resolve(allocator, ".", flags.single("cache-dir") orelse "zig-cache"[0..]) catch {
const rel_cache_dir = flags.single("cache-dir") orelse "zig-cache"[0..];
const full_cache_dir = os.path.resolve(allocator, ".", rel_cache_dir) catch {
try stderr.print("invalid cache dir: {}\n", rel_cache_dir);
os.exit(1);
};
defer allocator.free(full_cache_dir);
@ -546,7 +383,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
var module = try Module.create(
allocator,
root_name,
zig_root_source_file,
root_source_file,
Target.Native,
out_type,
build_mode,
@ -561,24 +398,21 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
module.is_test = false;
if (flags.single("linker-script")) |linker_script| {
module.linker_script = linker_script;
}
module.linker_script = flags.single("linker-script");
module.each_lib_rpath = flags.present("each-lib-rpath");
var clang_argv_buf = ArrayList([]const u8).init(allocator);
defer clang_argv_buf.deinit();
if (flags.many("mllvm")) |mllvm_flags| {
for (mllvm_flags) |mllvm| {
try clang_argv_buf.append("-mllvm");
try clang_argv_buf.append(mllvm);
}
module.llvm_argv = mllvm_flags;
module.clang_argv = clang_argv_buf.toSliceConst();
const mllvm_flags = flags.many("mllvm");
for (mllvm_flags) |mllvm| {
try clang_argv_buf.append("-mllvm");
try clang_argv_buf.append(mllvm);
}
module.llvm_argv = mllvm_flags;
module.clang_argv = clang_argv_buf.toSliceConst();
module.strip = flags.present("strip");
module.is_static = flags.present("static");
@ -610,18 +444,9 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
module.verbose_cimport = flags.present("verbose-cimport");
module.err_color = color;
if (flags.many("library-path")) |lib_dirs| {
module.lib_dirs = lib_dirs;
}
if (flags.many("framework")) |frameworks| {
module.darwin_frameworks = frameworks;
}
if (flags.many("rpath")) |rpath_list| {
module.rpath_list = rpath_list;
}
module.lib_dirs = flags.many("library-path");
module.darwin_frameworks = flags.many("framework");
module.rpath_list = flags.many("rpath");
if (flags.single("output-h")) |output_h| {
module.out_h_path = output_h;
@ -644,41 +469,25 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
}
module.emit_file_type = emit_type;
if (flags.many("object")) |objects| {
module.link_objects = objects;
}
if (flags.many("assembly")) |assembly_files| {
module.assembly_files = assembly_files;
}
module.link_objects = link_objects;
module.assembly_files = assembly_files;
try module.build();
try module.link(flags.single("out-file") orelse null);
if (flags.present("print-timing-info")) {
// codegen_print_timing_info(g, stderr);
}
try stderr.print("building {}: {}\n", @tagName(out_type), in_file);
try module.link(flags.single("out-file"));
}
fn cmdBuildExe(allocator: *Allocator, args: []const []const u8) !void {
try buildOutputType(allocator, args, Module.Kind.Exe);
return buildOutputType(allocator, args, Module.Kind.Exe);
}
// cmd:build-lib ///////////////////////////////////////////////////////////////////////////////////
fn cmdBuildLib(allocator: *Allocator, args: []const []const u8) !void {
try buildOutputType(allocator, args, Module.Kind.Lib);
return buildOutputType(allocator, args, Module.Kind.Lib);
}
// cmd:build-obj ///////////////////////////////////////////////////////////////////////////////////
fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {
try buildOutputType(allocator, args, Module.Kind.Obj);
return buildOutputType(allocator, args, Module.Kind.Obj);
}
// cmd:fmt /////////////////////////////////////////////////////////////////////////////////////////
const usage_fmt =
\\usage: zig fmt [file]...
\\
@ -735,7 +544,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
defer flags.deinit();
if (flags.present("help")) {
try stderr.write(usage_fmt);
try stdout.write(usage_fmt);
os.exit(0);
}
@ -863,162 +672,16 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
}
}
// cmd:version /////////////////////////////////////////////////////////////////////////////////////
fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
try stdout.print("{}\n", std.cstr.toSliceConst(c.ZIG_VERSION_STRING));
}
// cmd:test ////////////////////////////////////////////////////////////////////////////////////////
const usage_test =
\\usage: zig test [file]...
\\
\\Options:
\\ --help Print this help and exit
\\
\\
;
const args_test_spec = []Flag{Flag.Bool("--help")};
fn cmdTest(allocator: *Allocator, args: []const []const u8) !void {
var flags = try Args.parse(allocator, args_build_spec, args);
defer flags.deinit();
if (flags.present("help")) {
try stderr.write(usage_test);
os.exit(0);
}
if (flags.positionals.len != 1) {
try stderr.write("expected exactly one zig source file\n");
os.exit(1);
}
// compile the test program into the cache and run
// NOTE: May be overlap with buildOutput, take the shared part out.
try stderr.print("testing file {}\n", flags.positionals.at(0));
}
// cmd:run /////////////////////////////////////////////////////////////////////////////////////////
// Run should be simple and not expose the full set of arguments provided by build-exe. If specific
// build requirements are need, the user should `build-exe` then `run` manually.
const usage_run =
\\usage: zig run [file] -- <runtime args>
\\
\\Options:
\\ --help Print this help and exit
\\
\\
;
const args_run_spec = []Flag{Flag.Bool("--help")};
fn cmdRun(allocator: *Allocator, args: []const []const u8) !void {
var compile_args = args;
var runtime_args: []const []const u8 = []const []const u8{};
for (args) |argv, i| {
if (mem.eql(u8, argv, "--")) {
compile_args = args[0..i];
runtime_args = args[i + 1 ..];
break;
}
}
var flags = try Args.parse(allocator, args_run_spec, compile_args);
defer flags.deinit();
if (flags.present("help")) {
try stderr.write(usage_run);
os.exit(0);
}
if (flags.positionals.len != 1) {
try stderr.write("expected exactly one zig source file\n");
os.exit(1);
}
try stderr.print("runtime args:\n");
for (runtime_args) |cargs| {
try stderr.print("{}\n", cargs);
}
}
// cmd:translate-c /////////////////////////////////////////////////////////////////////////////////
const usage_translate_c =
\\usage: zig translate-c [file]
\\
\\Options:
\\ --help Print this help and exit
\\ --enable-timing-info Print timing diagnostics
\\ --output [path] Output file to write generated zig file (default: stdout)
\\
\\
;
const args_translate_c_spec = []Flag{
Flag.Bool("--help"),
Flag.Bool("--enable-timing-info"),
Flag.Arg1("--libc-include-dir"),
Flag.Arg1("--output"),
};
fn cmdTranslateC(allocator: *Allocator, args: []const []const u8) !void {
var flags = try Args.parse(allocator, args_translate_c_spec, args);
defer flags.deinit();
if (flags.present("help")) {
try stderr.write(usage_translate_c);
os.exit(0);
}
if (flags.positionals.len != 1) {
try stderr.write("expected exactly one c source file\n");
os.exit(1);
}
// set up codegen
const zig_root_source_file = null;
// NOTE: translate-c shouldn't require setting up the full codegen instance as it does in
// the C++ compiler.
// codegen_create(g);
// codegen_set_out_name(g, null);
// codegen_translate_c(g, flags.positional.at(0))
var output_stream = stdout;
if (flags.single("output")) |output_file| {
var file = try os.File.openWrite(allocator, output_file);
defer file.close();
var file_stream = io.FileOutStream.init(&file);
// TODO: Not being set correctly, still stdout
output_stream = &file_stream.stream;
}
// ast_render(g, output_stream, g->root_import->root, 4);
try output_stream.write("pub const example = 10;\n");
if (flags.present("enable-timing-info")) {
// codegen_print_timing_info(g, stdout);
try stderr.write("printing timing info for translate-c\n");
}
}
// cmd:help ////////////////////////////////////////////////////////////////////////////////////////
fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
try stderr.write(usage);
try stdout.write(usage);
}
// cmd:zen /////////////////////////////////////////////////////////////////////////////////////////
const info_zen =
\\
\\ * Communicate intent precisely.
@ -1040,8 +703,6 @@ fn cmdZen(allocator: *Allocator, args: []const []const u8) !void {
try stdout.write(info_zen);
}
// cmd:internal ////////////////////////////////////////////////////////////////////////////////////
const usage_internal =
\\usage: zig internal [subcommand]
\\
@ -1095,3 +756,28 @@ fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void {
std.cstr.toSliceConst(c.ZIG_DIA_GUIDS_LIB),
);
}
const CliPkg = struct {
name: []const u8,
path: []const u8,
children: ArrayList(*CliPkg),
parent: ?*CliPkg,
pub fn init(allocator: *mem.Allocator, name: []const u8, path: []const u8, parent: ?*CliPkg) !*CliPkg {
var pkg = try allocator.create(CliPkg{
.name = name,
.path = path,
.children = ArrayList(*CliPkg).init(allocator),
.parent = parent,
});
return pkg;
}
pub fn deinit(self: *CliPkg) void {
for (self.children.toSliceConst()) |child| {
child.deinit();
}
self.children.deinit();
}
};

View File

@ -103,30 +103,6 @@ pub const Module = struct {
LlvmIr,
};
pub const CliPkg = struct {
name: []const u8,
path: []const u8,
children: ArrayList(*CliPkg),
parent: ?*CliPkg,
pub fn init(allocator: *mem.Allocator, name: []const u8, path: []const u8, parent: ?*CliPkg) !*CliPkg {
var pkg = try allocator.create(CliPkg{
.name = name,
.path = path,
.children = ArrayList(*CliPkg).init(allocator),
.parent = parent,
});
return pkg;
}
pub fn deinit(self: *CliPkg) void {
for (self.children.toSliceConst()) |child| {
child.deinit();
}
self.children.deinit();
}
};
pub fn create(
allocator: *mem.Allocator,
name: []const u8,

View File

@ -5,8 +5,8 @@ const Foo = extern enum {
test "issue 1111 fixed" {
const v = Foo.Bar;
switch(v) {
Foo.Bar => return,
else => return,
switch (v) {
Foo.Bar => return,
else => return,
}
}