Skip to content

Commit a8d7248

Browse files
Add native AXIOM runtime slice
1 parent 2a90e76 commit a8d7248

3 files changed

Lines changed: 69 additions & 0 deletions

File tree

‎native/README.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ from the Python bootstrap so both implementations can be compared before
66
migration. The current native pipeline covers lexing, parsing, and the first
77
semantic checks.
88

9+
The native runtime can execute the initial literal-printing slice:
10+
11+
```rust
12+
axiom_native::runtime::run("fn main() { print(\"Hello AXIOM\") }")?;
13+
```
14+
915
```bash
1016
cargo test --manifest-path native/Cargo.toml
1117
```

‎native/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod parser;
2+
pub mod runtime;
23
pub mod semantic;
34

45
#[derive(Debug, Clone, Copy, PartialEq, Eq)]

‎native/src/runtime.rs‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use crate::parser::{Expression, Program, Statement};
2+
use crate::{parser, semantic};
3+
4+
#[derive(Debug, Clone, PartialEq, Eq)]
5+
pub struct RuntimeError {
6+
pub message: String,
7+
}
8+
9+
pub fn run(source: &str) -> Result<String, RuntimeError> {
10+
let program = parser::parse(source).map_err(|error| RuntimeError {
11+
message: format!("{} at {}:{}", error.message, error.line, error.column),
12+
})?;
13+
semantic::analyze(&program).map_err(|error| RuntimeError {
14+
message: error.message,
15+
})?;
16+
execute(&program)
17+
}
18+
19+
pub fn execute(program: &Program) -> Result<String, RuntimeError> {
20+
let main = program
21+
.functions
22+
.iter()
23+
.find(|function| function.name == "main")
24+
.ok_or_else(|| RuntimeError {
25+
message: "program must define 'main'".into(),
26+
})?;
27+
let mut output = String::new();
28+
for statement in &main.body {
29+
let Statement::Call(call) = statement;
30+
if call.name == "print" {
31+
let value = match &call.arguments[0] {
32+
Expression::String(value) => value.clone(),
33+
Expression::Integer(value) => value.to_string(),
34+
Expression::Boolean(value) => value.to_string(),
35+
};
36+
output.push_str(&value);
37+
output.push('\n');
38+
}
39+
}
40+
Ok(output)
41+
}
42+
43+
#[cfg(test)]
44+
mod tests {
45+
use super::*;
46+
47+
#[test]
48+
fn runs_hello_program() {
49+
assert_eq!(
50+
run("fn main() { print(\"Hello AXIOM\") }").unwrap(),
51+
"Hello AXIOM\n"
52+
);
53+
}
54+
55+
#[test]
56+
fn runs_typed_literals() {
57+
assert_eq!(
58+
run("fn main() { print(42); print(true) }").unwrap(),
59+
"42\ntrue\n"
60+
);
61+
}
62+
}

0 commit comments

Comments
 (0)