Skip to main content

string_ops/
string_ops.rs

1//! End-to-end demonstration of string concatenation, slicing, and
2//! f-string interpolation.
3//!
4//! `concat(a, b)` and `slice(s, start, end)` are utility natives.
5//! f-strings `f"hello {name}"` desugar at lex time to a chain of
6//! `concat` and `to_string` calls. The desugaring is performed by
7//! the lexer, which queues the synthesized tokens; the parser sees
8//! a regular function-call AST and emits the corresponding bytecode.
9//!
10//! WCET note. String concatenation and slicing produce dynamic
11//! strings whose worst-case output length is the sum of operand
12//! lengths (concat) or `end - start` (slice). The current verifier
13//! treats native function allocations as the per-native attestation
14//! supplied through `Vm::set_native_bounds`. Hosts that rely on
15//! `verify_resource_bounds` for real-time embedding must declare
16//! heap bounds for `concat` and `slice` before constructing the VM
17//! through the safe constructor.
18//!
19//! Run with: `cargo run --example string_ops`
20
21use keleusma::compiler::compile;
22use keleusma::lexer::tokenize;
23use keleusma::parser::parse;
24use keleusma::utility_natives::register_utility_natives;
25use keleusma::vm::{DEFAULT_ARENA_CAPACITY, Vm, VmState};
26use keleusma::{Arena, Value};
27
28fn main() {
29    let src = r#"
30        use to_string
31        use concat
32        use slice
33        fn main() -> String {
34            let name = "Keleusma";
35            let n: i64 = 42;
36            let greeting = f"hello, {name}! n = {n}";
37            let head = slice(greeting, 0, 5);
38            concat(head, "...")
39        }
40    "#;
41    let tokens = tokenize(src).expect("lex");
42    let program = parse(&tokens).expect("parse");
43    let module = compile(&program).expect("compile");
44    let arena = Arena::with_capacity(DEFAULT_ARENA_CAPACITY);
45    let mut vm = Vm::new(module, &arena).expect("verify");
46    register_utility_natives(&mut vm);
47    match vm.call(&[]) {
48        Ok(VmState::Finished(Value::DynStr(s))) => {
49            println!("result: {}", s);
50            assert_eq!(s, "hello...");
51            println!("string ops executed end to end");
52        }
53        other => panic!("unexpected: {:?}", other),
54    }
55}