Skip to main content

luaur_ast_cli/functions/
main.rs

1//! Source: `CLI/src/Ast.cpp:24-90` (hand-ported)
2use crate::functions::assertion_handler::assertion_handler;
3use crate::functions::display_help::display_help;
4use luaur_analysis::functions::to_json_ast_json_encoder_alt_b::to_json;
5use luaur_analysis::functions::to_string_to_string_alt_t::to_string_location_i32_bool;
6use luaur_ast::records::allocator::Allocator;
7use luaur_ast::records::ast_name_table::AstNameTable;
8use luaur_ast::records::ast_node::AstNode;
9use luaur_ast::records::parse_options::ParseOptions;
10use luaur_ast::records::parser::Parser;
11use luaur_cli_lib::functions::read_file::read_file;
12use luaur_cli_lib::functions::read_stdin::read_stdin;
13use luaur_cli_lib::functions::set_luau_flags_default::set_luau_flags_default;
14
15/// C++ `int main(int argc, char** argv)` (`CLI/src/Ast.cpp:24-90`).
16pub fn main() {
17    std::process::exit(run());
18}
19
20fn run() -> i32 {
21    let args: alloc::vec::Vec<alloc::string::String> = std::env::args().collect();
22    let argc = args.len();
23
24    // Luau::assertHandler() = assertionHandler;
25    *luaur_common::functions::assert_handler::assert_handler() = Some(assertion_handler);
26
27    // for (FValue<bool>* flag = ...; flag; flag = flag->next)
28    //     if (strncmp(flag->name, "Luau", 4) == 0) flag->value = true;
29    // The shared port enables every `Luau`-prefixed flag (matching the C++ loop;
30    // it additionally skips experimental flags, the project's CLI convention).
31    set_luau_flags_default();
32
33    // if (argc >= 2 && strcmp(argv[1], "--help") == 0) { displayHelp(argv[0]); return 0; }
34    if argc >= 2 && args[1] == "--help" {
35        display_help(&args[0]);
36        return 0;
37    }
38    // else if (argc < 2) { displayHelp(argv[0]); return 1; }
39    else if argc < 2 {
40        display_help(&args[0]);
41        return 1;
42    }
43
44    // const char* name = argv[1];
45    let name = &args[1];
46
47    // std::optional<std::string> maybeSource;
48    // if (strcmp(name, "-") == 0) maybeSource = readStdin(); else maybeSource = readFile(name);
49    let maybe_source = if name == "-" {
50        read_stdin()
51    } else {
52        read_file(name)
53    };
54
55    // if (!maybeSource) { fprintf(stderr, "Couldn't read source %s\n", name); return 1; }
56    let source = match maybe_source {
57        Some(s) => s,
58        None => {
59            eprintln!("Couldn't read source {}", name);
60            return 1;
61        }
62    };
63
64    // Luau::Allocator allocator; Luau::AstNameTable names(allocator);
65    // The `AstNameTable` keeps a `*mut Allocator`, so both are boxed for a stable
66    // address (mirrors the parser test `Fixture`).
67    let mut allocator = alloc::boxed::Box::new(Allocator::allocator());
68    let mut names = alloc::boxed::Box::new(AstNameTable::new(&mut allocator));
69
70    // ParseOptions options; options.captureComments = true; options.allowDeclarationSyntax = true;
71    let mut options = ParseOptions::default();
72    options.capture_comments = true;
73    options.allow_declaration_syntax = true;
74
75    // ParseResult parseResult = Parser::parse(source.data(), source.size(), names, allocator, std::move(options));
76    let parse_result = Parser::parse(&source, source.len(), &mut names, &mut allocator, options);
77
78    // if (parseResult.errors.size() > 0) { ... print each error ... }
79    if !parse_result.errors.is_empty() {
80        eprintln!("Parse errors were encountered:");
81        for error in &parse_result.errors {
82            eprintln!(
83                "  {} - {}",
84                to_string_location_i32_bool(error.get_location(), 0, true),
85                error.get_message()
86            );
87        }
88        eprintln!();
89    }
90
91    // printf("%s", Luau::toJson(parseResult.root, parseResult.commentLocations).c_str());
92    let json = to_json(
93        parse_result.root as *mut AstNode,
94        parse_result.comment_locations.clone(),
95    );
96    print!("{}", json);
97
98    // return parseResult.errors.size() > 0 ? 1 : 0;
99    if parse_result.errors.is_empty() {
100        0
101    } else {
102        1
103    }
104}