diff options
Diffstat (limited to 'crates/rebel-lang/examples/eval-string.rs')
-rw-r--r-- | crates/rebel-lang/examples/eval-string.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/crates/rebel-lang/examples/eval-string.rs b/crates/rebel-lang/examples/eval-string.rs new file mode 100644 index 0000000..a9c0b01 --- /dev/null +++ b/crates/rebel-lang/examples/eval-string.rs @@ -0,0 +1,101 @@ +use std::{fmt::Debug, process, time::Instant}; + +use clap::Parser; + +use rebel_lang::{ + func::{Func, FuncDef, FuncType}, + typing::{ArrayLen, Type, TypeFamily}, + value::{Context, EvalError, Result, Value}, +}; +use rebel_parse::{recipe, tokenize}; + +#[derive(Clone, Debug, Parser)] +struct Opts { + input: String, +} + +fn intrinsic_array_len(params: &[Value]) -> Result<Value> { + assert!(params.len() == 1); + let Value::Array(array) = ¶ms[0] else { + panic!(); + }; + Ok(Value::Integer(array.len().try_into().or(Err(EvalError))?)) +} +fn intrinsic_string_len(params: &[Value]) -> Result<Value> { + assert!(params.len() == 1); + let Value::Str(string) = ¶ms[0] else { + panic!(); + }; + Ok(Value::Integer( + string.chars().count().try_into().or(Err(EvalError))?, + )) +} + +fn main() { + let opts: Opts = Opts::parse(); + let input = opts.input.trim(); + + let start = Instant::now(); + let result = tokenize::token_stream(input); + let dur = Instant::now().duration_since(start); + println!("Tokenization took {} µs", dur.as_micros()); + + let tokens = match result { + Ok(value) => value, + Err(err) => { + println!("{err}"); + process::exit(1); + } + }; + + let start = Instant::now(); + let result = recipe::expr(&tokens); + let dur = Instant::now().duration_since(start); + println!("Parsing took {} µs", dur.as_micros()); + + let expr = match result { + Ok(value) => value, + Err(err) => { + println!("{err}"); + process::exit(1); + } + }; + + let mut ctx = Context::default(); + + ctx.methods.entry(TypeFamily::Array).or_default().insert( + "len", + Func { + typ: FuncType { + params: vec![Type::Array(Box::new(Type::Free), ArrayLen::Dynamic)], + ret: Type::Int, + }, + def: FuncDef::Intrinsic(intrinsic_array_len), + }, + ); + ctx.methods.entry(TypeFamily::Str).or_default().insert( + "len", + Func { + typ: FuncType { + params: vec![Type::Str], + ret: Type::Int, + }, + def: FuncDef::Intrinsic(intrinsic_string_len), + }, + ); + + let start = Instant::now(); + let result = ctx.eval(&expr); + let dur = Instant::now().duration_since(start); + println!("Eval took {} µs", dur.as_micros()); + + let value = match result { + Ok(value) => value, + Err(err) => { + println!("{err:?}"); + process::exit(1); + } + }; + + println!("{value}"); +} |