use crate::error::RuntimeError;
use crate::value::Value;
use relon_parser::TokenRange;
use std::collections::HashMap;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct EvaluatedArg {
pub name: Option<String>,
pub value: Value,
}
impl EvaluatedArg {
pub fn positional(value: Value) -> Self {
Self { name: None, value }
}
}
pub trait NativeFnCaps: Send + Sync {
fn call_relon(
&self,
func: &Value,
args: Vec<Value>,
range: TokenRange,
) -> Result<Value, RuntimeError>;
fn max_value_elements(&self) -> Option<usize> {
None
}
fn next_iter_id(&self) -> u64 {
0
}
fn iter_cursor_fetch_and_inc(&self, _iter_id: u64, _len: usize) -> Option<usize> {
None
}
fn tick(&self, _n: u64, _range: TokenRange) -> Result<(), RuntimeError> {
Ok(())
}
}
#[derive(Clone)]
pub struct NativeArgs {
pub positional: Vec<Value>,
pub named: HashMap<String, Value>,
caps: Arc<dyn NativeFnCaps>,
}
impl NativeArgs {
pub fn new(caps: Arc<dyn NativeFnCaps>) -> Self {
Self {
positional: Vec::new(),
named: HashMap::new(),
caps,
}
}
pub fn from_evaluated(args: Vec<EvaluatedArg>, caps: Arc<dyn NativeFnCaps>) -> Self {
let mut out = Self::new(caps);
for arg in args {
match arg.name {
Some(name) => {
out.named.insert(name, arg.value);
}
None => out.positional.push(arg.value),
}
}
out
}
pub fn from_positional(positional: Vec<Value>, caps: Arc<dyn NativeFnCaps>) -> Self {
Self {
positional,
named: HashMap::new(),
caps,
}
}
pub fn caps(&self) -> &dyn NativeFnCaps {
self.caps.as_ref()
}
pub fn into_positional(self) -> Vec<Value> {
self.positional
}
pub fn len(&self) -> usize {
self.positional.len() + self.named.len()
}
pub fn is_empty(&self) -> bool {
self.positional.is_empty() && self.named.is_empty()
}
pub fn get(&self, index: usize) -> Option<&Value> {
self.positional.get(index)
}
pub fn get_named(&self, name: &str) -> Option<&Value> {
self.named.get(name)
}
}
pub trait RelonFunction: Send + Sync {
fn call(&self, args: NativeArgs, range: TokenRange) -> Result<Value, RuntimeError>;
}
pub type NativeFn = dyn RelonFunction;