Use pass-by-reference for variables, pass-by-value for expressions

This commit is contained in:
Alex Bethel 2021-06-14 16:19:56 -05:00
parent 5ac9117651
commit 0e6bf2b27e
3 changed files with 17 additions and 18 deletions

View file

@ -70,11 +70,7 @@ pub enum StmtKind {
},
Call {
iden: Iden,
// NOTE(Alex): Function arguments are Iden's, not Expr's,
// because they're passed by reference rather than by value
// and therefore need to be assignable.
args: Vec<Iden>,
args: Vec<Expr>,
},
Print(Expr),
Melo(Iden),

View file

@ -20,7 +20,7 @@ use std::{
use rand::random;
use crate::{
ast::{Expr, Iden, Stmt, StmtKind},
ast::{Expr, ExprKind, Iden, Stmt, StmtKind},
base_55,
error::{Error, ErrorKind},
variables::{Functio, Value, Variable},
@ -286,16 +286,22 @@ impl ExecEnv {
/// Call a function with the given arguments (i.e., actual
/// parameters). If the function invocation fails for some reason,
/// report the error at `span`.
fn fn_call(
&mut self,
func: Functio,
args: &[Iden],
span: &Range<usize>,
) -> Result<(), Error> {
fn fn_call(&mut self, func: Functio, args: &[Expr], span: &Range<usize>) -> Result<(), Error> {
// Arguments that are ExprKind::Variable are pass by
// reference; all other expressions are pass by value.
let args = args
.iter()
.map(|arg| self.get_var_rc(arg))
.collect::<Result<Vec<Rc<RefCell<Value>>>, Error>>()?;
.map(|arg| {
if let ExprKind::Variable(name) = &arg.kind {
self.get_var_rc(&Iden {
iden: name.to_owned(),
span: arg.span.clone(),
})
} else {
self.eval_expr(arg).map(|v| Rc::new(RefCell::new(v)))
}
})
.collect::<Result<Vec<_>, Error>>()?;
match func {
Functio::BfFunctio {

View file

@ -469,10 +469,7 @@ impl<'source> Parser<'source> {
}
self.require(Token::Semicolon)?;
// Ok(StmtKind::Call { iden, args })
// `args` needs to be a vector of Idens now. ~~Alex
todo!()
Ok(StmtKind::Call { iden, args })
}
/// Parse variable declaration