runar_compiler_rust/
lib.rs1pub mod artifact;
8pub mod codegen;
9pub mod frontend;
10pub mod ir;
11
12use artifact::{assemble_artifact, RunarArtifact};
13use codegen::emit::emit;
14use codegen::optimizer::optimize_stack_ops;
15use codegen::stack::lower_to_stack;
16use ir::loader::{load_ir, load_ir_from_str};
17
18use std::path::Path;
19
20pub fn compile_from_ir(path: &Path) -> Result<RunarArtifact, String> {
22 let program = load_ir(path)?;
23 compile_from_program(&program)
24}
25
26pub fn compile_from_ir_str(json_str: &str) -> Result<RunarArtifact, String> {
28 let program = load_ir_from_str(json_str)?;
29 compile_from_program(&program)
30}
31
32pub fn compile_from_source(path: &Path) -> Result<RunarArtifact, String> {
34 let source = std::fs::read_to_string(path)
35 .map_err(|e| format!("reading source file: {}", e))?;
36 let file_name = path
37 .file_name()
38 .map(|n| n.to_string_lossy().to_string())
39 .unwrap_or_else(|| "contract.ts".to_string());
40 compile_from_source_str(&source, Some(&file_name))
41}
42
43pub fn compile_from_source_str(
45 source: &str,
46 file_name: Option<&str>,
47) -> Result<RunarArtifact, String> {
48 let parse_result = frontend::parser::parse_source(source, file_name);
50 if !parse_result.errors.is_empty() {
51 let error_msgs: Vec<String> = parse_result.errors.iter().map(|e| e.to_string()).collect();
52 return Err(format!("Parse errors:\n {}", error_msgs.join("\n ")));
53 }
54
55 let contract = parse_result
56 .contract
57 .ok_or_else(|| "No contract found in source file".to_string())?;
58
59 let validation = frontend::validator::validate(&contract);
61 if !validation.errors.is_empty() {
62 return Err(format!(
63 "Validation errors:\n {}",
64 validation.errors.join("\n ")
65 ));
66 }
67 for w in &validation.warnings {
68 eprintln!("Validation warning: {}", w);
69 }
70
71 let tc_result = frontend::typecheck::typecheck(&contract);
73 if !tc_result.errors.is_empty() {
74 return Err(format!(
75 "Type-check errors:\n {}",
76 tc_result.errors.join("\n ")
77 ));
78 }
79
80 let anf_program = frontend::anf_lower::lower_to_anf(&contract);
82
83 let anf_program = frontend::anf_optimize::optimize_ec(anf_program);
85
86 compile_from_program(&anf_program)
88}
89
90pub fn compile_source_to_ir(path: &Path) -> Result<ir::ANFProgram, String> {
92 let source = std::fs::read_to_string(path)
93 .map_err(|e| format!("reading source file: {}", e))?;
94 let file_name = path
95 .file_name()
96 .map(|n| n.to_string_lossy().to_string())
97 .unwrap_or_else(|| "contract.ts".to_string());
98 compile_source_str_to_ir(&source, Some(&file_name))
99}
100
101pub fn compile_source_str_to_ir(
103 source: &str,
104 file_name: Option<&str>,
105) -> Result<ir::ANFProgram, String> {
106 let parse_result = frontend::parser::parse_source(source, file_name);
107 if !parse_result.errors.is_empty() {
108 let error_msgs: Vec<String> = parse_result.errors.iter().map(|e| e.to_string()).collect();
109 return Err(format!("Parse errors:\n {}", error_msgs.join("\n ")));
110 }
111
112 let contract = parse_result
113 .contract
114 .ok_or_else(|| "No contract found in source file".to_string())?;
115
116 let validation = frontend::validator::validate(&contract);
117 if !validation.errors.is_empty() {
118 return Err(format!(
119 "Validation errors:\n {}",
120 validation.errors.join("\n ")
121 ));
122 }
123
124 let tc_result = frontend::typecheck::typecheck(&contract);
125 if !tc_result.errors.is_empty() {
126 return Err(format!(
127 "Type-check errors:\n {}",
128 tc_result.errors.join("\n ")
129 ));
130 }
131
132 let anf_program = frontend::anf_lower::lower_to_anf(&contract);
133 Ok(frontend::anf_optimize::optimize_ec(anf_program))
134}
135
136pub fn compile_from_program(program: &ir::ANFProgram) -> Result<RunarArtifact, String> {
138 let optimized = frontend::anf_optimize::optimize_ec(program.clone());
140
141 let mut stack_methods = lower_to_stack(&optimized)?;
143
144 for method in &mut stack_methods {
146 method.ops = optimize_stack_ops(&method.ops);
147 }
148
149 let emit_result = emit(&stack_methods)?;
151
152 let artifact = assemble_artifact(
153 &optimized,
154 &emit_result.script_hex,
155 &emit_result.script_asm,
156 emit_result.constructor_slots,
157 );
158 Ok(artifact)
159}