///|
fn print_usage() -> Unit {
println("MoonPack")
println("")
println("Usage:")
println(" moonpack check ")
println(" moonpack compat ")
println(" moonpack gen -o [--no-tests]")
println(" moonpack doc -o ")
}
///|
fn[T] fail(message : String) -> T {
println("error: " + message)
@sys.exit(1)
abort(message)
}
///|
fn parse_and_validate(path : String, text : String) -> @schema.Schema {
match @schema.parse_schema(text) {
Err(err) => fail(path + ":" + @schema.parse_error_to_string(err))
Ok(schema) =>
match @schema.validate_schema(schema) {
Err(err) => fail(path + ":" + @schema.parse_error_to_string(err))
Ok(_) => schema
}
}
}
///|
fn read_schema(path : String) -> @schema.Schema {
let text = @fs.read_file_to_string(path) catch {
_ => fail("cannot read schema file '\{path}'")
}
parse_and_validate(path, text)
}
///|
fn ensure_dir(path : String) -> Unit {
if !@fs.path_exists(path) {
@fs.create_dir(path) catch {
_ => fail("cannot create output directory '\{path}'")
}
}
}
///|
fn package_parts(package_name : String) -> Array[String] {
let parts : Array[String] = []
let mut start = 0
let mut i = 0
while i < package_name.length() {
if package_name[i].to_int() == 46 {
parts.push(package_name[start:i].to_owned())
start = i + 1
}
i = i + 1
}
parts.push(package_name[start:package_name.length()].to_owned())
parts
}
///|
fn package_output_dir(out_dir : String, package_name : String) -> String {
ensure_dir(out_dir)
let parts = package_parts(package_name)
let mut current = out_dir
for part in parts {
current = current + "/" + part
ensure_dir(current)
}
current
}
///|
fn package_doc_path(out_dir : String, package_name : String) -> String {
ensure_dir(out_dir)
let parts = package_parts(package_name)
let mut current = out_dir
let mut i = 0
while i + 1 < parts.length() {
current = current + "/" + parts[i]
ensure_dir(current)
i = i + 1
}
current + "/" + parts[parts.length() - 1] + ".md"
}
///|
fn command_check(path : String) -> Unit {
let schema = read_schema(path)
println("ok: " + schema.package_name)
}
///|
fn command_compat(old_path : String, new_path : String) -> Unit {
let old_schema = read_schema(old_path)
let new_schema = read_schema(new_path)
match @schema.check_compatible(old_schema, new_schema) {
Ok(_) => println("ok: compatible")
Err(err) => fail("compat failed: " + err)
}
}
///|
fn command_gen(path : String, out_dir : String, write_tests : Bool) -> Unit {
let schema = read_schema(path)
let package_dir = package_output_dir(out_dir, schema.package_name)
let mut count = 0
for decl in schema.declarations {
let stem = @codegen.decl_file_stem(decl)
let output = package_dir + "/" + stem + ".mbt"
@fs.write_string_to_file(output, @codegen.emit_decl(schema, decl)) catch {
_ => fail("cannot write generated file '\{output}'")
}
count = count + 1
let tests = @codegen.emit_decl_tests(schema, decl)
if write_tests && tests.length() > 0 {
let test_output = package_dir + "/" + stem + "_test.mbt"
@fs.write_string_to_file(test_output, tests) catch {
_ => fail("cannot write generated test file '\{test_output}'")
}
count = count + 1
}
}
let pkg = "import {\n \"001-Elsa/moonpack/src/core\" @core\n}\n"
@fs.write_string_to_file(package_dir + "/moon.pkg", pkg) catch {
_ => fail("cannot write generated package file")
}
count = count + 1
println("generated: " + package_dir + " (" + count.to_string() + " files)")
}
///|
fn command_doc(path : String, out_dir : String) -> Unit {
let schema = read_schema(path)
let output = package_doc_path(out_dir, schema.package_name)
@fs.write_string_to_file(output, @codegen.emit_schema_doc(schema)) catch {
_ => fail("cannot write schema documentation '\{output}'")
}
println("documented: " + output)
}
///|
fn main {
let args = @sys.get_cli_args()
if args.length() < 2 || args[1] == "--help" || args[1] == "-h" {
print_usage()
if args.length() < 2 {
@sys.exit(1)
}
@sys.exit(0)
}
match args[1] {
"check" => {
if args.length() == 3 && (args[2] == "--help" || args[2] == "-h") {
print_usage()
@sys.exit(0)
}
if args.length() != 3 {
print_usage()
@sys.exit(1)
}
command_check(args[2])
}
"compat" => {
if args.length() == 3 && (args[2] == "--help" || args[2] == "-h") {
print_usage()
@sys.exit(0)
}
if args.length() != 4 {
print_usage()
@sys.exit(1)
}
command_compat(args[2], args[3])
}
"gen" => {
if args.length() == 3 && (args[2] == "--help" || args[2] == "-h") {
print_usage()
@sys.exit(0)
}
if (args.length() != 5 && args.length() != 6) || args[3] != "-o" {
print_usage()
@sys.exit(1)
}
let write_tests = if args.length() == 6 {
if args[5] == "--no-tests" {
false
} else {
print_usage()
@sys.exit(1)
true
}
} else {
true
}
command_gen(args[2], args[4], write_tests)
}
"doc" => {
if args.length() == 3 && (args[2] == "--help" || args[2] == "-h") {
print_usage()
@sys.exit(0)
}
if args.length() != 5 || args[3] != "-o" {
print_usage()
@sys.exit(1)
}
command_doc(args[2], args[4])
}
_ => {
print_usage()
@sys.exit(1)
}
}
}