Skip to content

Commit a4317a7

Browse files
committed
refactor cmds
1 parent 572daf2 commit a4317a7

File tree

2 files changed

+133
-100
lines changed

2 files changed

+133
-100
lines changed

src/main.zig

Lines changed: 133 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -93,25 +93,34 @@ pub fn main() !void {
9393
return;
9494
}
9595

96-
// Parse arguments with enhanced MLIR support
96+
// Parse arguments with compiler-style CLI
9797
var output_dir: ?[]const u8 = null;
98-
var no_cst: bool = false;
99-
var command: ?[]const u8 = null;
98+
var command: ?[]const u8 = null; // For legacy commands (lex, parse, etc.)
10099
var input_file: ?[]const u8 = null;
100+
101+
// Compilation stage control (--emit-X flags)
102+
var emit_tokens: bool = false;
103+
var emit_ast: bool = false;
101104
var emit_mlir: bool = false;
105+
var emit_yul: bool = false;
106+
var emit_bytecode: bool = false;
107+
108+
// MLIR options
102109
var mlir_verify: bool = false;
103110
var mlir_passes: ?[]const u8 = null;
104111
var mlir_opt_level: ?[]const u8 = null;
105112
var mlir_timing: bool = false;
106113
var mlir_print_ir: bool = false;
107114
var mlir_use_pipeline: bool = false;
108115

109-
// Artifact saving options
116+
// Artifact saving options (for --save-all)
110117
var save_tokens: bool = false;
111118
var save_ast: bool = false;
112119
var save_mlir: bool = false;
113120
var save_yul: bool = false;
114121
var save_bytecode: bool = false;
122+
123+
// var verbose: bool = false; // TODO: implement verbose mode
115124
var i: usize = 1;
116125

117126
while (i < args.len) {
@@ -122,12 +131,33 @@ pub fn main() !void {
122131
}
123132
output_dir = args[i + 1];
124133
i += 2;
125-
} else if (std.mem.eql(u8, args[i], "--no-cst")) {
126-
no_cst = true;
134+
// New --emit-X flags
135+
} else if (std.mem.eql(u8, args[i], "--emit-tokens")) {
136+
emit_tokens = true;
137+
i += 1;
138+
} else if (std.mem.eql(u8, args[i], "--emit-ast")) {
139+
emit_ast = true;
127140
i += 1;
128141
} else if (std.mem.eql(u8, args[i], "--emit-mlir")) {
129142
emit_mlir = true;
130143
i += 1;
144+
} else if (std.mem.eql(u8, args[i], "--emit-yul")) {
145+
emit_yul = true;
146+
i += 1;
147+
} else if (std.mem.eql(u8, args[i], "--emit-bytecode")) {
148+
emit_bytecode = true;
149+
i += 1;
150+
// Optimization level flags (-O0, -O1, -O2)
151+
} else if (std.mem.eql(u8, args[i], "-O0") or std.mem.eql(u8, args[i], "-Onone")) {
152+
mlir_opt_level = "none";
153+
i += 1;
154+
} else if (std.mem.eql(u8, args[i], "-O1") or std.mem.eql(u8, args[i], "-Obasic")) {
155+
mlir_opt_level = "basic";
156+
i += 1;
157+
} else if (std.mem.eql(u8, args[i], "-O2") or std.mem.eql(u8, args[i], "-Oaggressive")) {
158+
mlir_opt_level = "aggressive";
159+
i += 1;
160+
// MLIR options
131161
} else if (std.mem.eql(u8, args[i], "--mlir-verify")) {
132162
mlir_verify = true;
133163
i += 1;
@@ -154,6 +184,7 @@ pub fn main() !void {
154184
} else if (std.mem.eql(u8, args[i], "--mlir-pipeline")) {
155185
mlir_use_pipeline = true;
156186
i += 1;
187+
// Legacy --save-X flags
157188
} else if (std.mem.eql(u8, args[i], "--save-tokens")) {
158189
save_tokens = true;
159190
i += 1;
@@ -176,10 +207,21 @@ pub fn main() !void {
176207
save_yul = true;
177208
save_bytecode = true;
178209
i += 1;
179-
} else if (command == null) {
210+
// Debug/verbose
211+
} else if (std.mem.eql(u8, args[i], "--verbose") or std.mem.eql(u8, args[i], "-v")) {
212+
// verbose = true; // TODO: implement verbose mode
213+
i += 1;
214+
// Legacy commands (lex, parse, ast, compile, mlir)
215+
} else if (std.mem.eql(u8, args[i], "lex") or
216+
std.mem.eql(u8, args[i], "parse") or
217+
std.mem.eql(u8, args[i], "ast") or
218+
std.mem.eql(u8, args[i], "compile") or
219+
std.mem.eql(u8, args[i], "mlir"))
220+
{
180221
command = args[i];
181222
i += 1;
182-
} else if (input_file == null) {
223+
// Input file
224+
} else if (input_file == null and !std.mem.startsWith(u8, args[i], "-")) {
183225
input_file = args[i];
184226
i += 1;
185227
} else {
@@ -188,14 +230,20 @@ pub fn main() !void {
188230
}
189231
}
190232

191-
if (command == null or input_file == null) {
233+
// Require input file
234+
if (input_file == null) {
192235
try printUsage();
193236
return;
194237
}
195238

196-
const cmd = command.?;
197239
const file_path = input_file.?;
198240

241+
// Determine compilation mode
242+
// If no --emit-X flag is set and no legacy command, default to bytecode
243+
if (!emit_tokens and !emit_ast and !emit_mlir and !emit_yul and !emit_bytecode and command == null) {
244+
emit_bytecode = true; // Default: compile to bytecode
245+
}
246+
199247
// Create MLIR options structure
200248
const mlir_options = MlirOptions{
201249
.emit_mlir = emit_mlir,
@@ -218,24 +266,44 @@ pub fn main() !void {
218266
.output_dir = output_dir,
219267
};
220268

221-
if (std.mem.eql(u8, cmd, "lex")) {
222-
try runLexer(allocator, file_path, artifact_options);
223-
} else if (std.mem.eql(u8, cmd, "parse")) {
224-
try runParser(allocator, file_path, !no_cst, artifact_options);
225-
} else if (std.mem.eql(u8, cmd, "ast")) {
226-
try runASTGeneration(allocator, file_path, output_dir, !no_cst, artifact_options);
227-
} else if (std.mem.eql(u8, cmd, "compile")) {
228-
if (mlir_options.emit_mlir or artifact_options.save_mlir or artifact_options.save_yul or artifact_options.save_bytecode) {
229-
// If MLIR, Yul, or bytecode is requested, use the advanced MLIR pipeline with Yul conversion
230-
try runMlirEmitAdvanced(allocator, file_path, mlir_options, artifact_options);
269+
// Handle legacy commands first
270+
if (command) |cmd| {
271+
if (std.mem.eql(u8, cmd, "lex")) {
272+
try runLexer(allocator, file_path, artifact_options);
273+
} else if (std.mem.eql(u8, cmd, "parse")) {
274+
try runParser(allocator, file_path, artifact_options);
275+
} else if (std.mem.eql(u8, cmd, "ast")) {
276+
try runASTGeneration(allocator, file_path, output_dir, artifact_options);
277+
} else if (std.mem.eql(u8, cmd, "compile")) {
278+
if (mlir_options.emit_mlir or artifact_options.save_mlir or artifact_options.save_yul or artifact_options.save_bytecode) {
279+
try runMlirEmitAdvanced(allocator, file_path, mlir_options, artifact_options);
280+
} else {
281+
try runFullCompilation(allocator, file_path, mlir_options, artifact_options);
282+
}
283+
} else if (std.mem.eql(u8, cmd, "mlir")) {
284+
try runMlirEmitAdvancedWithYul(allocator, file_path, mlir_options, artifact_options, false);
231285
} else {
232-
// Otherwise, use the basic frontend compilation
233-
try runFullCompilation(allocator, file_path, !no_cst, mlir_options, artifact_options);
286+
try printUsage();
234287
}
235-
} else if (std.mem.eql(u8, cmd, "mlir")) {
288+
return;
289+
}
290+
291+
// New compiler-style behavior: process --emit-X flags
292+
// Stop at the earliest stage specified, but save later stages if --save-X is set
293+
// TODO: Use verbose flag for detailed output
294+
295+
if (emit_tokens) {
296+
// Stop after lexer
297+
try runLexer(allocator, file_path, artifact_options);
298+
} else if (emit_ast) {
299+
// Stop after parser
300+
try runParser(allocator, file_path, artifact_options);
301+
} else if (emit_mlir or emit_yul or emit_bytecode) {
302+
// Run full MLIR pipeline (includes Yul and bytecode if needed)
236303
try runMlirEmitAdvancedWithYul(allocator, file_path, mlir_options, artifact_options, false);
237304
} else {
238-
try printUsage();
305+
// Default: full compilation
306+
try runMlirEmitAdvancedWithYul(allocator, file_path, mlir_options, artifact_options, false);
239307
}
240308
}
241309

@@ -244,38 +312,45 @@ fn printUsage() !void {
244312
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
245313
const stdout = &stdout_writer.interface;
246314
try stdout.print("Ora Compiler v0.1 - Asuka\n", .{});
247-
try stdout.print("Usage: ora [options] <command> <file>\n", .{});
248-
try stdout.print("\nGeneral Options:\n", .{});
249-
try stdout.print(" -o, --output-dir <dir> - Specify output directory for generated files\n", .{});
250-
try stdout.print(" --no-cst - Disable CST building (enabled by default)\n", .{});
251-
try stdout.print("\nArtifact Saving Options:\n", .{});
252-
try stdout.print(" --save-tokens - Save tokens from lexical analysis\n", .{});
253-
try stdout.print(" --save-ast - Save AST from syntax analysis\n", .{});
254-
try stdout.print(" --save-mlir - Save MLIR from generation\n", .{});
255-
try stdout.print(" --save-yul - Save Yul from lowering\n", .{});
256-
try stdout.print(" --save-bytecode - Save EVM bytecode\n", .{});
257-
try stdout.print(" --save-all - Save all artifacts\n", .{});
315+
try stdout.print("Usage: ora [options] <file.ora>\n", .{});
316+
try stdout.print("\nCompilation Control:\n", .{});
317+
try stdout.print(" (default) - Compile to EVM bytecode\n", .{});
318+
try stdout.print(" --emit-tokens - Stop after lexical analysis (emit tokens)\n", .{});
319+
try stdout.print(" --emit-ast - Stop after parsing (emit AST)\n", .{});
320+
try stdout.print(" --emit-mlir - Stop after MLIR generation\n", .{});
321+
try stdout.print(" --emit-yul - Stop after Yul lowering\n", .{});
322+
try stdout.print(" --emit-bytecode - Generate EVM bytecode (default)\n", .{});
323+
try stdout.print("\nOutput Options:\n", .{});
324+
try stdout.print(" -o <file> - Write output to <file> (e.g., -o out.hex, -o out.mlir)\n", .{});
325+
try stdout.print(" -o <dir>/ - Write artifacts to <dir>/ (e.g., -o build/)\n", .{});
326+
try stdout.print(" Default: ./<basename>_artifacts/ or current dir\n", .{});
327+
try stdout.print("\nOptimization Options:\n", .{});
328+
try stdout.print(" -O0, -Onone - No optimization (default)\n", .{});
329+
try stdout.print(" -O1, -Obasic - Basic optimizations\n", .{});
330+
try stdout.print(" -O2, -Oaggressive - Aggressive optimizations\n", .{});
258331
try stdout.print("\nMLIR Options:\n", .{});
259-
try stdout.print(" --emit-mlir - Generate MLIR output in addition to normal compilation\n", .{});
260-
try stdout.print(" --mlir-verify - Run MLIR verification passes\n", .{});
261-
try stdout.print(" --mlir-passes <str> - Custom MLIR pass pipeline (e.g., 'canonicalize,cse')\n", .{});
262-
try stdout.print(" --mlir-opt <level> - Optimization level: none, basic, aggressive\n", .{});
263-
try stdout.print(" --mlir-timing - Enable pass timing statistics\n", .{});
264-
try stdout.print(" --mlir-print-ir - Print IR before and after passes\n", .{});
265-
try stdout.print(" --mlir-pipeline - Use comprehensive MLIR optimization pipeline\n", .{});
266-
try stdout.print("\nCommands:\n", .{});
267-
try stdout.print(" lex <file> - Tokenize a .ora file\n", .{});
268-
try stdout.print(" parse <file> - Parse a .ora file to AST\n", .{});
269-
try stdout.print(" ast <file> - Generate AST and save to JSON file\n", .{});
270-
try stdout.print(" compile <file> - Full frontend pipeline (lex -> parse -> [mlir])\n", .{});
271-
try stdout.print(" mlir <file> - Run front-end and emit MLIR with advanced options\n", .{});
332+
try stdout.print(" --mlir-verify - Run MLIR verification passes\n", .{});
333+
try stdout.print(" --mlir-passes <passes> - Custom MLIR pass pipeline (comma-separated)\n", .{});
334+
try stdout.print(" --mlir-timing - Enable pass timing statistics\n", .{});
335+
try stdout.print(" --mlir-print-ir - Print IR before and after passes\n", .{});
336+
try stdout.print(" --mlir-pipeline - Use comprehensive MLIR optimization pipeline\n", .{});
337+
try stdout.print("\nDevelopment/Debug Options:\n", .{});
338+
try stdout.print(" --save-all - Save all intermediate artifacts\n", .{});
339+
try stdout.print(" --verbose - Verbose output (show each compilation stage)\n", .{});
340+
try stdout.print("\nLegacy Commands (for step-by-step debugging):\n", .{});
341+
try stdout.print(" ora lex <file> - Only tokenize (legacy: use --emit-tokens)\n", .{});
342+
try stdout.print(" ora parse <file> - Only parse (legacy: use --emit-ast)\n", .{});
343+
try stdout.print(" ora ast <file> - Generate AST JSON (legacy)\n", .{});
344+
try stdout.print(" ora compile <file> - Full compilation (legacy: just use 'ora <file>')\n", .{});
272345
try stdout.print("\nExamples:\n", .{});
273-
try stdout.print(" ora -o build ast example.ora\n", .{});
274-
try stdout.print(" ora --emit-mlir compile example.ora\n", .{});
275-
try stdout.print(" ora --save-all compile example.ora\n", .{});
276-
try stdout.print(" ora --save-tokens --save-ast lex example.ora\n", .{});
277-
try stdout.print(" ora --mlir-opt aggressive --mlir-verify mlir example.ora\n", .{});
278-
try stdout.print(" ora --mlir-passes 'canonicalize,cse,sccp' --mlir-timing mlir example.ora\n", .{});
346+
try stdout.print(" ora contract.ora # Compile to bytecode → contract_artifacts/\n", .{});
347+
try stdout.print(" ora contract.ora -o build/ # Compile to bytecode → build/\n", .{});
348+
try stdout.print(" ora contract.ora -o contract.hex # Compile to specific file\n", .{});
349+
try stdout.print(" ora --emit-ast contract.ora # Stop at AST → contract_artifacts/ast.json\n", .{});
350+
try stdout.print(" ora --emit-mlir -O2 contract.ora # Generate optimized MLIR\n", .{});
351+
try stdout.print(" ora --emit-yul -o out.yul contract.ora # Compile to Yul\n", .{});
352+
try stdout.print(" ora --save-all contract.ora # Save all stages (tokens, AST, MLIR, Yul, bytecode)\n", .{});
353+
try stdout.print(" ora --mlir-verify --mlir-timing -O2 contract.ora # Compile with verification and timing\n", .{});
279354
try stdout.flush();
280355
}
281356

@@ -493,7 +568,7 @@ fn saveBytecode(allocator: std.mem.Allocator, file_path: []const u8, bytecode: [
493568
}
494569

495570
/// Run parser on file and display AST
496-
fn runParser(allocator: std.mem.Allocator, file_path: []const u8, enable_cst: bool, artifact_options: ArtifactOptions) !void {
571+
fn runParser(allocator: std.mem.Allocator, file_path: []const u8, artifact_options: ArtifactOptions) !void {
497572
var stdout_buffer: [1024]u8 = undefined;
498573
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
499574
const stdout = &stdout_writer.interface;
@@ -525,13 +600,6 @@ fn runParser(allocator: std.mem.Allocator, file_path: []const u8, enable_cst: bo
525600
defer arena.deinit();
526601
var parser = lib.Parser.init(tokens, &arena);
527602
parser.setFileId(1);
528-
var cst_builder_storage: lib.cst.CstBuilder = undefined;
529-
var cst_builder_ptr: ?*lib.cst.CstBuilder = null;
530-
if (enable_cst) {
531-
cst_builder_storage = lib.cst.CstBuilder.init(allocator);
532-
cst_builder_ptr = &cst_builder_storage;
533-
parser.withCst(cst_builder_ptr.?);
534-
}
535603
const ast_nodes = parser.parse() catch |err| {
536604
try stdout.print("Parser error: {s}\n", .{@errorName(err)});
537605
return;
@@ -551,17 +619,11 @@ fn runParser(allocator: std.mem.Allocator, file_path: []const u8, enable_cst: bo
551619
try saveAST(allocator, file_path, ast_nodes, artifact_options);
552620
}
553621

554-
if (enable_cst) {
555-
if (cst_builder_ptr) |builder| {
556-
const cst_root = try builder.buildRoot(tokens);
557-
_ = cst_root; // TODO: optional dump in future flag
558-
builder.deinit();
559-
}
560-
}
622+
try stdout.flush();
561623
}
562624

563625
/// Run full compilation pipeline with optional MLIR support
564-
fn runFullCompilation(allocator: std.mem.Allocator, file_path: []const u8, enable_cst: bool, mlir_options: MlirOptions, artifact_options: ArtifactOptions) !void {
626+
fn runFullCompilation(allocator: std.mem.Allocator, file_path: []const u8, mlir_options: MlirOptions, artifact_options: ArtifactOptions) !void {
565627
var stdout_buffer: [1024]u8 = undefined;
566628
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
567629
const stdout = &stdout_writer.interface;
@@ -603,13 +665,6 @@ fn runFullCompilation(allocator: std.mem.Allocator, file_path: []const u8, enabl
603665
defer arena.deinit();
604666
var parser = lib.Parser.init(tokens, &arena);
605667
parser.setFileId(1);
606-
var cst_builder_storage: lib.cst.CstBuilder = undefined;
607-
var cst_builder_ptr: ?*lib.cst.CstBuilder = null;
608-
if (enable_cst) {
609-
cst_builder_storage = lib.cst.CstBuilder.init(allocator);
610-
cst_builder_ptr = &cst_builder_storage;
611-
parser.withCst(cst_builder_ptr.?);
612-
}
613668
const ast_nodes = parser.parse() catch |err| {
614669
try stdout.print("Parser failed: {s}\n", .{@errorName(err)});
615670
return;
@@ -631,13 +686,6 @@ fn runFullCompilation(allocator: std.mem.Allocator, file_path: []const u8, enabl
631686
}
632687

633688
try stdout.print("============================================================\n", .{});
634-
if (enable_cst) {
635-
if (cst_builder_ptr) |builder| {
636-
const cst_root = try builder.buildRoot(tokens);
637-
_ = cst_root; // TODO: optional dump in future flag
638-
builder.deinit();
639-
}
640-
}
641689

642690
// Phase 3: MLIR Generation (if requested)
643691
if (mlir_options.emit_mlir) {
@@ -689,7 +737,7 @@ fn printAstSummary(writer: anytype, node: *lib.AstNode, indent: u32) !void {
689737
}
690738

691739
/// Generate AST and save to JSON file
692-
fn runASTGeneration(allocator: std.mem.Allocator, file_path: []const u8, output_dir: ?[]const u8, enable_cst: bool, artifact_options: ArtifactOptions) !void {
740+
fn runASTGeneration(allocator: std.mem.Allocator, file_path: []const u8, output_dir: ?[]const u8, artifact_options: ArtifactOptions) !void {
693741
var stdout_buffer: [1024]u8 = undefined;
694742
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
695743
const stdout = &stdout_writer.interface;
@@ -718,24 +766,10 @@ fn runASTGeneration(allocator: std.mem.Allocator, file_path: []const u8, output_
718766
defer arena.deinit();
719767
var parser = lib.Parser.init(tokens, &arena);
720768
parser.setFileId(1);
721-
var cst_builder_storage: lib.cst.CstBuilder = undefined;
722-
var cst_builder_ptr: ?*lib.cst.CstBuilder = null;
723-
if (enable_cst) {
724-
cst_builder_storage = lib.cst.CstBuilder.init(allocator);
725-
cst_builder_ptr = &cst_builder_storage;
726-
parser.withCst(cst_builder_ptr.?);
727-
}
728769
const ast_nodes = parser.parse() catch |err| {
729770
try stdout.print("Parser error: {s}\n", .{@errorName(err)});
730771
return;
731772
};
732-
if (enable_cst) {
733-
if (cst_builder_ptr) |builder| {
734-
const cst_root = try builder.buildRoot(tokens);
735-
_ = cst_root; // CST not emitted here yet
736-
builder.deinit();
737-
}
738-
}
739773
// Note: AST nodes are allocated in arena, so they're automatically freed when arena is deinited
740774

741775
try stdout.print("Generated {d} AST nodes\n", .{ast_nodes.len});

src/root.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ pub const yul_bindings = @import("yul_bindings.zig");
2828
pub const lossless_printer = @import("lossless_printer.zig");
2929
pub const doc_comments = @import("doc_comments.zig");
3030
pub const doc_attach = @import("doc_attach.zig");
31-
pub const cst = @import("cst.zig");
3231

3332
// Re-export key types for convenience
3433
/// Lexical analyzer for Ora source code

0 commit comments

Comments
 (0)