Skip to content

Commit 6f734a1

Browse files
committed
...
1 parent 38604d8 commit 6f734a1

File tree

6 files changed

+41
-8
lines changed

6 files changed

+41
-8
lines changed

src/callable/core.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ pub trait CallableFormals {
3838
pub trait Callable: CallableFormals {
3939
fn match_args(&self, args: List, stack: &mut CallStack) -> Result<(List, List), Signal> {
4040
let mut formals = self.formals();
41+
// instead of using a List for ellipsis I want an ExprList
42+
43+
let mut expr_ellipsis: ExprList = ExprList::new();
44+
4145
let mut ellipsis: List = List::new();
4246
let mut matched_args: List = List::new();
4347

@@ -67,19 +71,27 @@ pub trait Callable: CallableFormals {
6771

6872
// backfill unnamed args, populating ellipsis with overflow
6973
for (key, value) in args.iter_pairs() {
70-
match key {
74+
match (key, value.clone()) {
7175
// named args go directly to ellipsis, they did not match a formal
72-
Character::Some(arg) => ellipsis.push_named(Character::Some(arg), value),
76+
(Character::Some(arg), Obj::Promise(_, e, _)) => {
77+
expr_ellipsis.push_named(Character::Some(arg.clone()).as_option(), e);
78+
ellipsis.push_named(Character::Some(arg), value);
79+
}
7380

7481
// unnamed args populate next formal, or ellipsis if formals exhausted
75-
Character::NA => {
82+
(Character::NA, value) => {
7683
let next_unassigned_formal = formals.remove(0);
7784
if let Some((Some(param), _)) = next_unassigned_formal {
7885
matched_args.push_named(Character::Some(param), value);
7986
} else {
87+
let Obj::Promise(_, e, _) = value.clone() else {
88+
unreachable!()
89+
};
90+
expr_ellipsis.push_named(Character::NA.as_option(), e);
8091
ellipsis.push_named(Character::NA, value);
8192
}
8293
}
94+
_ => unreachable!(),
8395
}
8496
}
8597

@@ -91,8 +103,20 @@ pub trait Callable: CallableFormals {
91103
)
92104
}
93105

106+
use crate::callable::builtins::BUILTIN;
107+
108+
let list = BUILTIN.get("list").cloned().unwrap();
109+
110+
// convert the expr_ellipsis to an Obj::Promise where the expression is a call into List
111+
112+
let a = Obj::Promise(
113+
None,
114+
Expr::Call(Box::new(Expr::Primitive(list)), expr_ellipsis),
115+
stack.last_frame().env().clone(),
116+
);
117+
94118
if let Some(Expr::Ellipsis(Some(name))) = remainder.get(0) {
95-
matched_args.push_named(Character::Some(name), Obj::List(ellipsis.clone()));
119+
matched_args.push_named(Character::Some(name), a);
96120
} else if !remainder.is_empty() {
97121
matched_args.push_named(
98122
Character::Some("...".to_string()),

src/callable/primitive/c.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use r_derive::*;
22

33
use crate::callable::core::*;
4-
use crate::context::Context;
54
use crate::object::types::*;
65
use crate::object::*;
76
use crate::{formals, lang::*};

src/callable/primitive/list.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use r_derive::*;
22

33
use crate::callable::core::*;
4-
use crate::context::Context;
54
use crate::formals;
65
use crate::lang::*;
76
use crate::object::*;

src/callable/primitive/quote.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ use crate::object::*;
2525
///
2626
/// ```custom,{class=r-repl}
2727
/// quote(x + y)
28+
/// quote(1)
2829
/// ```
29-
///
30+
/// ## Differentes to the R implementation
31+
/// While R treats literals as expressions this implementation of `quote` differentiates between
32+
/// the literal `1` and the length-1 vector "`c(1)`".
33+
/// Thereby the return type of `quote()` can be expected to be an object of type `Expression`.
3034
#[doc(alias = "quote")]
3135
#[builtin(sym = "quote")]
3236
#[derive(Debug, Clone, PartialEq)]

src/context/core.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::rc::Rc;
22

33
use crate::lang::{EvalResult, Signal};
4-
use crate::object::types::Character;
54
use crate::object::*;
65
use crate::{error::*, internal_err};
76

src/object/ast.rs

+8
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ pub struct ExprList {
100100
pub values: Vec<Expr>,
101101
}
102102

103+
impl ExprList {
104+
pub fn push_named(&mut self, key: Option<String>, value: Expr) {
105+
self.keys.push(key);
106+
self.values.push(value);
107+
}
108+
}
109+
110+
103111
impl fmt::Display for ExprList {
104112
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105113
let pairs: Vec<String> = self

0 commit comments

Comments
 (0)