Skip to content

Commit 165318f

Browse files
committed
Support weaving functions to and from Rust
1 parent 663ce33 commit 165318f

File tree

4 files changed

+119
-37
lines changed

4 files changed

+119
-37
lines changed

src/context.rs

+67-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::error::Error;
2-
use crate::parser::{Block, Expr, ExprKind as EK, Parser};
2+
use crate::parser::{Block, Expr, ExprKind as EK, FunctionBean, Parser};
33
use crate::position::Position;
4-
use crate::value::{ImmutableString, Function, Object, Value};
4+
use crate::value::{ImmutableString, Function, FunctionRust, FunctionKind, Object, Value};
55
use std::collections::BTreeMap;
66
use std::mem;
77

@@ -126,6 +126,10 @@ impl Context {
126126
Ok(self.eval_block(&Parser::parse_script(source)?)?)
127127
}
128128

129+
pub fn call_function(&mut self, func: &Function, vals: Vec<Value>) -> Result<Value, Value> {
130+
Ok(self.eval_call_inner_vals(func, vals)?)
131+
}
132+
129133
fn eval_block(&mut self, block: &Block) -> Result<Value, Interrupt> {
130134
self.scopes.push(Object::new());
131135
let result = self.eval_block_no_scope(block);
@@ -418,10 +422,9 @@ impl Context {
418422
_ => return Err(Interrupt::Error(Error::bad_iter(position))),
419423
};
420424

421-
let args = Vec::new();
422-
425+
let empty_args = Vec::new();
423426
loop {
424-
let object_val = self.eval_call_inner(next, &args)?;
427+
let object_val = self.eval_call_inner_exprs(next, &empty_args)?;
425428
let object = match object_val {
426429
Value::Object(ref object) => object,
427430
_ => return Err(Interrupt::Error(Error::bad_iter_next(position))),
@@ -503,27 +506,58 @@ impl Context {
503506
// the error is "localized" to the caller's location (i.e. the line/column point to `pos`).
504507
let func = self.eval_expr(func)?;
505508
if let Value::Function(ref func) = func {
506-
self.eval_call_inner(func, args)
509+
self.eval_call_inner_exprs(func, args)
507510
} else {
508511
Err(Interrupt::Error(Error::not_a_function(pos)))
509512
}
510513
}
511514

512-
fn eval_call_inner(&mut self, func: &Function, args: &Vec<Expr>) -> Result<Value, Interrupt> {
515+
fn eval_call_inner_exprs(
516+
&mut self,
517+
func: &Function,
518+
args: &Vec<Expr>,
519+
) -> Result<Value, Interrupt> {
520+
let mut vals = Vec::with_capacity(args.len());
521+
for arg in args {
522+
vals.push(self.eval_expr(arg)?);
523+
}
524+
525+
self.eval_call_inner_vals(func, vals)
526+
}
527+
528+
fn eval_call_inner_vals(
529+
&mut self,
530+
func: &Function,
531+
vals: Vec<Value>,
532+
) -> Result<Value, Interrupt> {
533+
match func.kind() {
534+
FunctionKind::Bean(bean_func) => self.eval_call_bean(bean_func, func.scopes(), vals),
535+
FunctionKind::Rust(rust_func) => self.eval_call_rust(rust_func, vals),
536+
}
537+
}
538+
539+
fn eval_call_bean(
540+
&mut self,
541+
func: &FunctionBean,
542+
scopes: &[Object],
543+
mut vals: Vec<Value>,
544+
) -> Result<Value, Interrupt> {
513545
let scope = Object::new();
514-
for (index, param) in func.def().params.iter().enumerate() {
515-
let arg = match args.get(index) {
516-
Some(expr) => self.eval_expr(expr)?,
517-
None => Value::Null,
546+
for param in func.params.iter() {
547+
let val = if vals.len() > 0 {
548+
vals.remove(0)
549+
} else {
550+
Value::Null
518551
};
519-
scope.set(param.clone(), arg);
552+
553+
scope.set(param.clone(), val);
520554
}
521555

522556
// Restore the original scope stack at the declaration site of the function:
523-
let ctx_scopes = mem::replace(&mut self.scopes, func.scopes().to_vec());
557+
let ctx_scopes = mem::replace(&mut self.scopes, scopes.to_vec());
524558
self.scopes.push(scope);
525559

526-
let result = match self.eval_expr(&func.def().body) {
560+
let result = match self.eval_expr(&func.body) {
527561
Ok(value) => Ok(value),
528562
Err(Interrupt::Return { value, .. }) => Ok(match value {
529563
Some(value) => value,
@@ -543,6 +577,14 @@ impl Context {
543577
result
544578
}
545579

580+
fn eval_call_rust(
581+
&mut self,
582+
func: &FunctionRust,
583+
vals: Vec<Value>,
584+
) -> Result<Value, Interrupt> {
585+
func(self, vals).map_err(|val| Interrupt::Error(val))
586+
}
587+
546588
fn eval_bool_or(&mut self, a: &Expr, b: &Expr) -> Result<Value, Interrupt> {
547589
let a = self.eval_expr(a)?.coerce_bool();
548590
if a {
@@ -616,11 +658,18 @@ pub enum Interrupt {
616658

617659
impl From<Interrupt> for Error {
618660
fn from(interrupt: Interrupt) -> Error {
661+
let value: Value = interrupt.into();
662+
Error::Runtime(value)
663+
}
664+
}
665+
666+
impl From<Interrupt> for Value {
667+
fn from(interrupt: Interrupt) -> Value {
619668
match interrupt {
620-
Interrupt::Break { position, .. } => Error::Runtime(Error::bad_break(position)),
621-
Interrupt::Continue { position, .. } => Error::Runtime(Error::bad_continue(position)),
622-
Interrupt::Return { position, .. } => Error::Runtime(Error::bad_return(position)),
623-
Interrupt::Error(value) => Error::Runtime(value),
669+
Interrupt::Break { position, .. } => Error::bad_break(position),
670+
Interrupt::Continue { position, .. } => Error::bad_continue(position),
671+
Interrupt::Return { position, .. } => Error::bad_return(position),
672+
Interrupt::Error(value) => value,
624673
}
625674
}
626675
}

src/error.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ impl Error {
7575

7676
pub fn runtime(pos: Position, message: String) -> Value {
7777
let object = Object::new();
78-
object.set("message".into(), Value::string(message));
79-
object.set("line".into(), Value::Number(pos.line as f64));
80-
object.set("column".into(), Value::Number(pos.column as f64));
78+
object.set("message", Value::string(message));
79+
object.set("line", Value::Number(pos.line as f64));
80+
object.set("column", Value::Number(pos.column as f64));
8181
Value::Object(object)
8282
}
8383
}

src/parser.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ use crate::error::{Error, ParserError, ParserErrorKind as PEK};
22
use crate::iter::MultiPeek;
33
use crate::lexer::{TokenIterator, Token, TokenKind as TK};
44
use crate::position::Position;
5+
use crate::value::FunctionKind;
56
use std::collections::BTreeMap;
67
use std::rc::Rc;
78

89
use ExprKind as EK;
910

1011
#[derive(Clone, Debug)]
11-
pub struct FunctionDef {
12+
pub struct FunctionBean {
1213
pub params: Vec<String>,
1314
pub body: Box<Expr>,
1415
}
@@ -33,7 +34,7 @@ pub enum ExprKind {
3334

3435
// Primary:
3536
Identifier(String),
36-
Function(Rc<FunctionDef>),
37+
Function(Rc<FunctionKind>),
3738
Boolean(bool),
3839
Number(f64),
3940
String(String),
@@ -447,7 +448,7 @@ fn parse_function<'a>(parser: &mut Parser<'a>, skip_params: bool) -> Result<EK,
447448
parse_expr(parser)?
448449
};
449450

450-
Ok(EK::Function(Rc::new(FunctionDef { params, body: Box::new(body) })))
451+
Ok(EK::Function(Rc::new(FunctionKind::Bean(FunctionBean { params, body: Box::new(body) }))))
451452
}
452453

453454
fn is_next_curly_pair<'a>(parser: &mut Parser<'a>) -> Result<bool, Error> {

src/value.rs

+45-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
use crate::parser::FunctionDef;
1+
use crate::context::Context;
2+
use crate::parser::FunctionBean;
3+
use gc::{Gc, GcCell};
24
use std::collections::BTreeMap;
5+
use std::fmt;
36
use std::rc::Rc;
4-
use gc::{Gc, GcCell};
57

68
#[derive(Clone, Debug, Trace, Finalize)]
79
pub enum Value {
@@ -49,7 +51,7 @@ impl PartialEq<Value> for Value {
4951
},
5052
Value::Function(a) => {
5153
match other {
52-
Value::Function(b) => Rc::ptr_eq(&a.def, &b.def),
54+
Value::Function(b) => Rc::ptr_eq(&a.kind, &b.kind),
5355
_ => false,
5456
}
5557
},
@@ -64,12 +66,22 @@ impl PartialEq<Value> for Value {
6466
}
6567

6668
impl Value {
67-
pub fn string(string: String) -> Value {
68-
Value::String(ImmutableString::new(string))
69+
pub fn string<S: Into<String>>(string: S) -> Value {
70+
Value::String(ImmutableString::new(string.into()))
71+
}
72+
73+
pub fn function(scopes: Vec<Object>, kind: Rc<FunctionKind>) -> Value {
74+
Value::Function(Function { scopes, kind })
6975
}
7076

71-
pub fn function(scopes: Vec<Object>, def: Rc<FunctionDef>) -> Value {
72-
Value::Function(Function { scopes, def })
77+
pub fn rust_function<F>(func: F) -> Value
78+
where
79+
F: Fn(&mut Context, Vec<Value>) -> Result<Value, Value> + 'static,
80+
{
81+
Value::Function(Function {
82+
scopes: Vec::new(),
83+
kind: Rc::new(FunctionKind::Rust(Box::new(func))),
84+
})
7385
}
7486

7587
pub fn array(values: Vec<Value>) -> Value {
@@ -106,20 +118,40 @@ impl ImmutableString {
106118
}
107119
}
108120

109-
#[derive(Clone, Debug, Trace, Finalize)]
121+
#[derive(Clone, Trace, Finalize)]
110122
pub struct Function {
123+
// Unused for `FunctionKind::Rust` functions:
111124
scopes: Vec<Object>,
112125
#[unsafe_ignore_trace]
113-
def: Rc<FunctionDef>,
126+
kind: Rc<FunctionKind>,
127+
}
128+
129+
impl fmt::Debug for Function {
130+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131+
write!(f, "function")
132+
}
133+
}
134+
135+
pub enum FunctionKind {
136+
Rust(FunctionRust),
137+
Bean(FunctionBean),
138+
}
139+
140+
pub type FunctionRust = Box<Fn(&mut Context, Vec<Value>) -> Result<Value, Value>>;
141+
142+
impl fmt::Debug for FunctionKind {
143+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144+
write!(f, "function")
145+
}
114146
}
115147

116148
impl Function {
117149
pub fn scopes(&self) -> &[Object] {
118150
self.scopes.as_slice()
119151
}
120152

121-
pub fn def(&self) -> &FunctionDef {
122-
&*self.def
153+
pub fn kind(&self) -> &FunctionKind {
154+
&*self.kind
123155
}
124156
}
125157

@@ -158,8 +190,8 @@ impl Object {
158190
Object(Gc::new(GcCell::new(BTreeMap::new())))
159191
}
160192

161-
pub fn set(&self, key: String, value: Value) {
162-
self.0.borrow_mut().insert(key, value);
193+
pub fn set<S: Into<String>>(&self, key: S, value: Value) {
194+
self.0.borrow_mut().insert(key.into(), value);
163195
}
164196

165197
pub fn get(&self, key: &str) -> Option<Value> {

0 commit comments

Comments
 (0)