diff --git a/src/builtins/deprecated.rs b/src/builtins/deprecated.rs new file mode 100644 index 0000000..d5017b8 --- /dev/null +++ b/src/builtins/deprecated.rs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +use crate::ast::Expr; +use crate::builtins::utils::ensure_args_count; +use crate::builtins::BuiltinFcn; +use crate::lexer::Span; +use crate::value::Value; + +use std::collections::HashMap; + +use anyhow::{bail, Result}; +use lazy_static::lazy_static; + +#[rustfmt::skip] +lazy_static! { + pub static ref DEPRECATED: HashMap<&'static str, BuiltinFcn> = { + let mut m : HashMap<&'static str, BuiltinFcn> = HashMap::new(); + + m.insert("all", (all, 1)); + m.insert("any", (any, 1)); + + m + }; +} + +fn all(span: &Span, params: &[Expr], args: &[Value]) -> Result { + ensure_args_count(span, "all", params, args, 1)?; + + Ok(Value::Bool(match &args[0] { + Value::Array(a) => a.iter().all(|i| i == &Value::Bool(true)), + Value::Set(a) => a.iter().all(|i| i == &Value::Bool(true)), + a => { + let span = params[0].span(); + bail!(span.error(format!("`all` requires array/set argument. Got `{a}`.").as_str())) + } + })) +} + +fn any(span: &Span, params: &[Expr], args: &[Value]) -> Result { + ensure_args_count(span, "any", params, args, 1)?; + + Ok(Value::Bool(match &args[0] { + Value::Array(a) => a.iter().any(|i| i == &Value::Bool(true)), + Value::Set(a) => a.iter().any(|i| i == &Value::Bool(true)), + a => { + let span = params[0].span(); + bail!(span.error(format!("`any` requires array/set argument. Got `{a}`.").as_str())) + } + })) +} diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index cf50e6b..95a1ef6 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -7,6 +7,7 @@ mod bitwise; pub mod comparison; mod conversions; mod debugging; +pub mod deprecated; mod encoding; pub mod numbers; mod objects; @@ -27,6 +28,8 @@ use lazy_static::lazy_static; pub type BuiltinFcn = (fn(&Span, &[Expr], &[Value]) -> Result, u8); +pub use deprecated::DEPRECATED; + #[rustfmt::skip] lazy_static! { pub static ref BUILTINS: HashMap<&'static str, BuiltinFcn> = { diff --git a/src/interpreter.rs b/src/interpreter.rs index 60bbd90..a497e90 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -39,6 +39,7 @@ pub struct Interpreter<'source> { builtins_cache: BTreeMap<(&'static str, Vec), Value>, no_rules_lookup: bool, traces: Option>, + allow_deprecated: bool, } #[derive(Debug, Clone, Serialize)] @@ -106,6 +107,7 @@ impl<'source> Interpreter<'source> { builtins_cache: BTreeMap::new(), no_rules_lookup: false, traces: None, + allow_deprecated: true, }) } @@ -1502,6 +1504,13 @@ impl<'source> Interpreter<'source> { if let Some(builtin) = builtins::BUILTINS.get(path.as_str()) { return self.eval_builtin_call(span, path, *builtin, params); } + if let Some(builtin) = builtins::DEPRECATED.get(path.as_str()) { + if self.allow_deprecated { + return self.eval_builtin_call(span, path, *builtin, params); + } else { + bail!(span.error(format!("{path} is deprecated").as_str())) + } + } } return Err(span diff --git a/src/utils.rs b/src/utils.rs index a554d4e..072c483 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -46,6 +46,8 @@ pub fn get_extra_arg<'a>(expr: &'a Expr, arities: &HashMap) -> Optio *n_args } else if let Some((_, n_args)) = BUILTINS.get(path.as_str()) { *n_args + } else if let Some((_, n_args)) = DEPRECATED.get(path.as_str()) { + *n_args } else { return None; };