Skip to content

Commit ceddb1b

Browse files
Add compiled artifact execution
1 parent 7418136 commit ceddb1b

3 files changed

Lines changed: 101 additions & 24 deletions

File tree

‎examples/hello.axm‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
AXIOM_ARTIFACT_V1
2+
FUNCTION:main
3+
PARAMS:0
4+
INSTR:PushString:Hello AXIOM;Print

‎native/src/main.rs‎

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::env;
22
use std::fs;
3+
use std::path::Path;
34
use std::process::ExitCode;
45

56
fn main() -> ExitCode {
@@ -64,8 +65,16 @@ fn main() -> ExitCode {
6465
})
6566
}) {
6667
Ok(program) => {
68+
let output_path = match axiom_native::vm::write_artifact_file(Path::new(&path), &program) {
69+
Ok(path) => path,
70+
Err(error) => {
71+
eprintln!("error: {}", error.message);
72+
return ExitCode::from(1);
73+
}
74+
};
6775
let artifact = axiom_native::vm::build_artifact(&program);
6876
println!("build ok: {path}");
77+
println!("artifact file: {}", output_path.display());
6978
println!("artifact bytes: {}", artifact.len());
7079
ExitCode::SUCCESS
7180
}
@@ -77,33 +86,60 @@ fn main() -> ExitCode {
7786
ExitCode::from(1)
7887
}
7988
},
80-
"run" => match axiom_native::parser::parse(&source).and_then(|program| {
81-
axiom_native::semantic::analyze(&program)
82-
.map(|_| program)
83-
.map_err(|error| axiom_native::parser::ParseError {
84-
message: error.message,
85-
line: 0,
86-
column: 0,
87-
})
88-
}) {
89-
Ok(program) => match axiom_native::vm::execute_program(&program) {
90-
Ok(output) => {
91-
print!("{output}");
92-
ExitCode::SUCCESS
89+
"run" => {
90+
if Path::new(&path).extension().and_then(|ext| ext.to_str()) == Some("axm") {
91+
match fs::read_to_string(&path) {
92+
Ok(encoded) => match axiom_native::vm::Artifact::deserialize(&encoded) {
93+
Ok(artifact) => match axiom_native::vm::execute_artifact(&artifact) {
94+
Ok(output) => {
95+
print!("{output}");
96+
ExitCode::SUCCESS
97+
}
98+
Err(error) => {
99+
eprintln!("error: {}", error.message);
100+
ExitCode::from(1)
101+
}
102+
},
103+
Err(error) => {
104+
eprintln!("error: {}", error.message);
105+
ExitCode::from(1)
106+
}
107+
},
108+
Err(error) => {
109+
eprintln!("error: cannot read {path}: {error}");
110+
ExitCode::from(1)
111+
}
93112
}
94-
Err(error) => {
95-
eprintln!("error: {}", error.message);
96-
ExitCode::from(1)
113+
} else {
114+
match axiom_native::parser::parse(&source).and_then(|program| {
115+
axiom_native::semantic::analyze(&program)
116+
.map(|_| program)
117+
.map_err(|error| axiom_native::parser::ParseError {
118+
message: error.message,
119+
line: 0,
120+
column: 0,
121+
})
122+
}) {
123+
Ok(program) => match axiom_native::vm::execute_program(&program) {
124+
Ok(output) => {
125+
print!("{output}");
126+
ExitCode::SUCCESS
127+
}
128+
Err(error) => {
129+
eprintln!("error: {}", error.message);
130+
ExitCode::from(1)
131+
}
132+
},
133+
Err(error) => {
134+
eprintln!(
135+
"error: {} at {}:{}",
136+
error.message, error.line, error.column
137+
);
138+
ExitCode::from(1)
139+
}
97140
}
98-
},
99-
Err(error) => {
100-
eprintln!(
101-
"error: {} at {}:{}",
102-
error.message, error.line, error.column
103-
);
104-
ExitCode::from(1)
105141
}
106-
},
142+
}
107143
_ => {
108144
eprintln!("error: unknown command '{command}'");
109145
print_help();

‎native/src/vm.rs‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,37 @@ pub fn execute_program(program: &Program) -> Result<String, VmError> {
156156
Ok(machine.output)
157157
}
158158

159+
pub fn execute_artifact(artifact: &Artifact) -> Result<String, VmError> {
160+
let functions = artifact
161+
.functions
162+
.iter()
163+
.cloned()
164+
.map(|function| LoweredFunction {
165+
name: function.name,
166+
parameters: function.parameters,
167+
return_type: None,
168+
instructions: function.instructions,
169+
})
170+
.collect();
171+
let mut machine = Machine::new(functions);
172+
machine.call_function("main", Vec::new())?;
173+
Ok(machine.output)
174+
}
175+
159176
pub fn build_artifact(program: &Program) -> String {
160177
compile_program(program).serialize()
161178
}
162179

180+
pub fn write_artifact_file(path: &std::path::Path, program: &Program) -> Result<std::path::PathBuf, VmError> {
181+
let artifact = compile_program(program);
182+
let serialized = artifact.serialize();
183+
let out_path = path.with_extension("axm");
184+
std::fs::write(&out_path, &serialized).map_err(|error| VmError {
185+
message: format!("cannot write artifact '{}': {error}", out_path.display()),
186+
})?;
187+
Ok(out_path)
188+
}
189+
163190
struct Machine {
164191
functions: Vec<LoweredFunction>,
165192
output: String,
@@ -593,4 +620,14 @@ mod tests {
593620
assert_eq!(decoded.functions[0].name, "main");
594621
assert!(!decoded.functions[0].instructions.is_empty());
595622
}
623+
624+
#[test]
625+
fn executes_deserialized_artifact() {
626+
let program = parse("fn main() { print(42) }").unwrap();
627+
let artifact = compile_program(&program);
628+
let encoded = artifact.serialize();
629+
let decoded = Artifact::deserialize(&encoded).unwrap();
630+
let output = execute_artifact(&decoded).unwrap();
631+
assert_eq!(output, "42\n");
632+
}
596633
}

0 commit comments

Comments
 (0)