first draft of partial application, is working in easy cases
This commit is contained in:
parent
dee9bcfc33
commit
f8adaa7971
|
@ -76,7 +76,9 @@ pub fn run(src: &'static str) {
|
|||
pub fn main() {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
let src = "
|
||||
fn add2 (x, y) -> add (x, y)
|
||||
|
||||
add2 (_, 2) (2)
|
||||
|
||||
";
|
||||
run(src);
|
||||
|
|
|
@ -203,7 +203,7 @@ impl fmt::Display for Ast {
|
|||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
),
|
||||
Placeholder => todo!(),
|
||||
Placeholder => write!(f, "Placeholder"),
|
||||
LBox(_name, _rhs) => todo!(),
|
||||
Match(value, clauses) => {
|
||||
write!(
|
||||
|
|
|
@ -52,6 +52,7 @@ impl LFn {
|
|||
}
|
||||
|
||||
pub fn chunk(&self, arity: u8) -> &Chunk {
|
||||
// println!("Getting chunk of {arity} from {:?}", self);
|
||||
match self {
|
||||
LFn::Declared { .. } => unreachable!(),
|
||||
LFn::Defined { chunks, .. } => &chunks.iter().find(|(a, _)| *a == arity).unwrap().1,
|
||||
|
@ -68,9 +69,9 @@ impl LFn {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Partial {
|
||||
args: Vec<Value>,
|
||||
name: &'static str,
|
||||
function: Value,
|
||||
pub args: Vec<Value>,
|
||||
pub name: &'static str,
|
||||
pub function: Value,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
44
src/vm.rs
44
src/vm.rs
|
@ -2,7 +2,7 @@ use crate::base::BaseFn;
|
|||
use crate::compiler::{Chunk, Op};
|
||||
use crate::parser::Ast;
|
||||
use crate::spans::Spanned;
|
||||
use crate::value::{LFn, Value};
|
||||
use crate::value::{LFn, Partial, Value};
|
||||
use chumsky::prelude::SimpleSpan;
|
||||
use imbl::{HashMap, Vector};
|
||||
use num_traits::FromPrimitive;
|
||||
|
@ -705,7 +705,19 @@ impl Vm {
|
|||
self.ip += 1;
|
||||
}
|
||||
Partial => {
|
||||
todo!();
|
||||
let arity = self.chunk().bytecode[self.ip + 1];
|
||||
self.ip += 2;
|
||||
let the_fn = self.pop();
|
||||
let Value::Fn(ref inner) = the_fn else {
|
||||
return self.panic("only functions may be partially applied");
|
||||
};
|
||||
let args = self.stack.split_off(self.stack.len() - arity as usize);
|
||||
let partial = crate::value::Partial {
|
||||
args,
|
||||
name: inner.name(),
|
||||
function: the_fn,
|
||||
};
|
||||
self.push(Value::Partial(Rc::new(partial)));
|
||||
}
|
||||
Call => {
|
||||
let arity = self.chunk().bytecode[self.ip + 1];
|
||||
|
@ -742,6 +754,34 @@ impl Vm {
|
|||
};
|
||||
self.push(value);
|
||||
}
|
||||
Value::Partial(partial) => {
|
||||
let last_arg = self.pop();
|
||||
let args = &partial.args;
|
||||
for arg in args {
|
||||
if *arg == Value::Nothing {
|
||||
self.push(last_arg.clone());
|
||||
} else {
|
||||
self.push(arg.clone());
|
||||
}
|
||||
}
|
||||
let the_fn = partial.function.clone();
|
||||
let mut frame = CallFrame {
|
||||
function: the_fn,
|
||||
arity: args.len() as u8,
|
||||
stack_base: self.stack.len() - arity as usize - 1,
|
||||
ip: 0,
|
||||
};
|
||||
|
||||
swap(&mut self.frame, &mut frame);
|
||||
frame.ip = self.ip;
|
||||
|
||||
self.call_stack.push(frame);
|
||||
self.ip = 0;
|
||||
|
||||
if crate::DEBUG_RUN {
|
||||
println!("== calling into {} ==", self.frame.function.show());
|
||||
}
|
||||
}
|
||||
_ => return self.panic_with(format!("{} is not a function", val.show())),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user