forked from AbleScript/ablescript
Merge pull request 'Implemented built-in functios' (#3) from feature/builtins into master
Reviewed-on: https://git.ablecorp.us:443/AbleScript/able-script/pulls/3
This commit is contained in:
commit
7e2cba314b
|
@ -407,6 +407,7 @@ impl ExecEnv {
|
||||||
self.stack.pop();
|
self.stack.pop();
|
||||||
res?;
|
res?;
|
||||||
}
|
}
|
||||||
|
Functio::Builtin(b) => b.call(args).map_err(|e| Error::new(e, span.clone()))?,
|
||||||
Functio::Chain { functios, kind } => {
|
Functio::Chain { functios, kind } => {
|
||||||
let (left_functio, right_functio) = *functios;
|
let (left_functio, right_functio) = *functios;
|
||||||
match kind {
|
match kind {
|
||||||
|
|
|
@ -44,6 +44,7 @@ pub enum Functio {
|
||||||
params: Vec<String>,
|
params: Vec<String>,
|
||||||
body: Vec<Stmt>,
|
body: Vec<Stmt>,
|
||||||
},
|
},
|
||||||
|
Builtin(BuiltinFunctio),
|
||||||
Chain {
|
Chain {
|
||||||
functios: Box<(Functio, Functio)>,
|
functios: Box<(Functio, Functio)>,
|
||||||
kind: FunctioChainKind,
|
kind: FunctioChainKind,
|
||||||
|
@ -59,12 +60,61 @@ impl Functio {
|
||||||
tape_len: _,
|
tape_len: _,
|
||||||
} => 0,
|
} => 0,
|
||||||
Functio::Able { params, body: _ } => params.len(),
|
Functio::Able { params, body: _ } => params.len(),
|
||||||
|
Functio::Builtin(b) => b.arity,
|
||||||
Functio::Chain { functios, kind: _ } => functios.0.arity() + functios.1.arity(),
|
Functio::Chain { functios, kind: _ } => functios.0.arity() + functios.1.arity(),
|
||||||
Functio::Eval(_) => 0,
|
Functio::Eval(_) => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct BuiltinFunctio {
|
||||||
|
function: Rc<dyn Fn(&[Rc<RefCell<Value>>]) -> Result<(), crate::error::ErrorKind>>,
|
||||||
|
arity: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuiltinFunctio {
|
||||||
|
pub fn new<F>(f: F, arity: usize) -> Self
|
||||||
|
where
|
||||||
|
F: Fn(&[Rc<RefCell<Value>>]) -> Result<(), crate::error::ErrorKind> + 'static,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
function: Rc::new(f),
|
||||||
|
arity,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call(&self, args: &[Rc<RefCell<Value>>]) -> Result<(), crate::error::ErrorKind> {
|
||||||
|
(self.function)(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fn_addr(&self) -> usize {
|
||||||
|
Rc::as_ptr(&self.function) as *const () as _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for BuiltinFunctio {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("BuiltinFunctio")
|
||||||
|
.field("function", &"built-in")
|
||||||
|
.field("arity", &self.arity)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for BuiltinFunctio {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
Rc::ptr_eq(&self.function, &other.function) && self.arity == other.arity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for BuiltinFunctio {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.fn_addr().hash(state);
|
||||||
|
self.arity.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone, Hash)]
|
#[derive(Debug, PartialEq, Copy, Clone, Hash)]
|
||||||
pub enum FunctioChainKind {
|
pub enum FunctioChainKind {
|
||||||
Equal,
|
Equal,
|
||||||
|
@ -134,6 +184,7 @@ impl Value {
|
||||||
.sum::<i32>()
|
.sum::<i32>()
|
||||||
+ body.len() as i32
|
+ body.len() as i32
|
||||||
}
|
}
|
||||||
|
Functio::Builtin(b) => (b.fn_addr() + b.arity) as _,
|
||||||
Functio::Chain { functios, kind } => {
|
Functio::Chain { functios, kind } => {
|
||||||
let (lf, rf) = *functios;
|
let (lf, rf) = *functios;
|
||||||
Value::Functio(lf).into_i32()
|
Value::Functio(lf).into_i32()
|
||||||
|
@ -222,6 +273,7 @@ impl Value {
|
||||||
|
|
||||||
Value::Int((params + body) % 3 - 1).into_abool()
|
Value::Int((params + body) % 3 - 1).into_abool()
|
||||||
}
|
}
|
||||||
|
Functio::Builtin(b) => Value::Bool(b.fn_addr() % b.arity == 0).into_abool(),
|
||||||
Functio::Chain { functios, kind } => {
|
Functio::Chain { functios, kind } => {
|
||||||
let (lhs, rhs) = *functios;
|
let (lhs, rhs) = *functios;
|
||||||
match kind {
|
match kind {
|
||||||
|
@ -391,6 +443,22 @@ impl Value {
|
||||||
);
|
);
|
||||||
cart
|
cart
|
||||||
}
|
}
|
||||||
|
Functio::Builtin(b) => {
|
||||||
|
let mut cart = HashMap::new();
|
||||||
|
cart.insert(
|
||||||
|
Value::Str("addr".to_owned()),
|
||||||
|
Rc::new(RefCell::new(Value::Cart(
|
||||||
|
Value::Int(b.fn_addr() as _).into_cart(),
|
||||||
|
))),
|
||||||
|
);
|
||||||
|
|
||||||
|
cart.insert(
|
||||||
|
Value::Str("arity".to_owned()),
|
||||||
|
Rc::new(RefCell::new(Value::Int(b.arity as _))),
|
||||||
|
);
|
||||||
|
|
||||||
|
cart
|
||||||
|
}
|
||||||
Functio::Chain { functios, kind } => {
|
Functio::Chain { functios, kind } => {
|
||||||
let (lhs, rhs) = *functios;
|
let (lhs, rhs) = *functios;
|
||||||
match kind {
|
match kind {
|
||||||
|
@ -440,6 +508,9 @@ impl Value {
|
||||||
tape_len,
|
tape_len,
|
||||||
} => (instructions.len() + tape_len) as _,
|
} => (instructions.len() + tape_len) as _,
|
||||||
Functio::Able { params, body } => (params.len() + format!("{:?}", body).len()) as _,
|
Functio::Able { params, body } => (params.len() + format!("{:?}", body).len()) as _,
|
||||||
|
Functio::Builtin(b) => {
|
||||||
|
(std::mem::size_of_val(b.function.as_ref()) + b.arity) as i32
|
||||||
|
}
|
||||||
Functio::Chain { functios, kind } => {
|
Functio::Chain { functios, kind } => {
|
||||||
let (lhs, rhs) = *functios.clone();
|
let (lhs, rhs) = *functios.clone();
|
||||||
match kind {
|
match kind {
|
||||||
|
@ -564,6 +635,27 @@ impl ops::Sub for Value {
|
||||||
)
|
)
|
||||||
.into_functio(),
|
.into_functio(),
|
||||||
},
|
},
|
||||||
|
Functio::Builtin(b) => {
|
||||||
|
let arity = b.arity;
|
||||||
|
let resulting_arity = arity.saturating_sub(rhs.into_i32() as usize);
|
||||||
|
|
||||||
|
Functio::Builtin(BuiltinFunctio::new(
|
||||||
|
move |args| {
|
||||||
|
b.call(
|
||||||
|
&args
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.take(resulting_arity)
|
||||||
|
.chain(std::iter::repeat_with(|| {
|
||||||
|
Rc::new(RefCell::new(Value::Nul))
|
||||||
|
}))
|
||||||
|
.take(arity)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
resulting_arity,
|
||||||
|
))
|
||||||
|
}
|
||||||
Functio::Chain { functios, .. } => {
|
Functio::Chain { functios, .. } => {
|
||||||
let rhs = rhs.into_functio();
|
let rhs = rhs.into_functio();
|
||||||
let (a, b) = *functios;
|
let (a, b) = *functios;
|
||||||
|
@ -692,6 +784,10 @@ impl ops::Div for Value {
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Functio::Builtin(b) => Functio::Builtin(BuiltinFunctio {
|
||||||
|
arity: b.arity + rhs.into_i32() as usize,
|
||||||
|
..b
|
||||||
|
}),
|
||||||
Functio::Chain { functios, kind } => {
|
Functio::Chain { functios, kind } => {
|
||||||
let functios = *functios;
|
let functios = *functios;
|
||||||
Functio::Chain {
|
Functio::Chain {
|
||||||
|
@ -765,6 +861,13 @@ impl ops::Not for Value {
|
||||||
|
|
||||||
Functio::Able { params, body }
|
Functio::Able { params, body }
|
||||||
}
|
}
|
||||||
|
Functio::Builtin(b) => {
|
||||||
|
let arity = b.arity;
|
||||||
|
Functio::Builtin(BuiltinFunctio::new(
|
||||||
|
move |args| b.call(&args.iter().cloned().rev().collect::<Vec<_>>()),
|
||||||
|
arity,
|
||||||
|
))
|
||||||
|
}
|
||||||
Functio::Chain { functios, kind } => {
|
Functio::Chain { functios, kind } => {
|
||||||
let (a, b) = *functios;
|
let (a, b) = *functios;
|
||||||
Functio::Chain {
|
Functio::Chain {
|
||||||
|
@ -858,6 +961,7 @@ impl Display for Value {
|
||||||
body,
|
body,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Functio::Builtin(b) => write!(f, "builtin @ {}", b.fn_addr()),
|
||||||
Functio::Chain { functios, kind } => {
|
Functio::Chain { functios, kind } => {
|
||||||
let (a, b) = *functios.clone();
|
let (a, b) = *functios.clone();
|
||||||
write!(
|
write!(
|
||||||
|
|
Loading…
Reference in a new issue