Implement default arguments in mixins

This commit is contained in:
ConnorSkees 2020-01-19 10:58:38 -05:00
parent 6da84575dc
commit 1636d775c5
2 changed files with 74 additions and 36 deletions

View File

@ -1,3 +1,4 @@
use std::collections::BTreeMap;
use std::iter::Peekable; use std::iter::Peekable;
use crate::common::Symbol; use crate::common::Symbol;
@ -19,8 +20,8 @@ impl FuncArgs {
} }
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, std::default::Default)]
pub struct CallArgs(pub Vec<CallArg>); pub struct CallArgs(pub BTreeMap<String, CallArg>);
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CallArg { pub struct CallArg {
@ -35,13 +36,17 @@ impl CallArg {
} }
impl CallArgs { impl CallArgs {
pub const fn new() -> Self { pub fn new() -> Self {
CallArgs(Vec::new()) CallArgs(BTreeMap::new())
} }
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.0.is_empty() self.0.is_empty()
} }
pub fn get(&self, val: &str) -> Option<&CallArg> {
self.0.get(val)
}
} }
pub fn eat_func_args<I: Iterator<Item = Token>>(toks: &mut Peekable<I>) -> FuncArgs { pub fn eat_func_args<I: Iterator<Item = Token>>(toks: &mut Peekable<I>) -> FuncArgs {
@ -54,27 +59,48 @@ pub fn eat_func_args<I: Iterator<Item = Token>>(toks: &mut Peekable<I>) -> FuncA
TokenKind::Symbol(Symbol::CloseParen) => break, TokenKind::Symbol(Symbol::CloseParen) => break,
_ => todo!(), _ => todo!(),
}; };
let mut default: Vec<Token> = Vec::new();
devour_whitespace(toks); devour_whitespace(toks);
let kind = if let Some(Token { kind, .. }) = toks.next() { let kind = match toks.next() {
kind Some(Token { kind, .. }) => kind,
} else { _ => todo!("unexpected eof"),
todo!()
}; };
match kind { match kind {
TokenKind::Symbol(Symbol::Colon) => { TokenKind::Symbol(Symbol::Colon) => {
todo!("handle default values") devour_whitespace(toks);
// let mut val: Vec<Token> = Vec::new(); while let Some(tok) = toks.peek() {
// while let Some(tok) = toks.next() { match &tok.kind {
// match &kind { TokenKind::Symbol(Symbol::Comma) => {
// _ => val.push(tok), toks.next();
// } args.push(FuncArg {
// } name,
default: Some(default),
});
break;
}
TokenKind::Symbol(Symbol::CloseParen) => {
args.push(FuncArg {
name,
default: Some(default),
});
break;
}
_ => {
let tok = toks.next().expect("we know this exists!");
default.push(tok)
}
}
}
} }
TokenKind::Symbol(Symbol::Period) => todo!("handle varargs"), TokenKind::Symbol(Symbol::Period) => todo!("handle varargs"),
TokenKind::Symbol(Symbol::CloseParen) => { TokenKind::Symbol(Symbol::CloseParen) => {
args.push(FuncArg { args.push(FuncArg {
name, name,
default: None, default: if default.is_empty() {
None
} else {
Some(default)
},
}); });
break; break;
} }
@ -99,7 +125,7 @@ pub fn eat_func_args<I: Iterator<Item = Token>>(toks: &mut Peekable<I>) -> FuncA
} }
pub fn eat_call_args<I: Iterator<Item = Token>>(toks: &mut Peekable<I>) -> CallArgs { pub fn eat_call_args<I: Iterator<Item = Token>>(toks: &mut Peekable<I>) -> CallArgs {
let mut args: Vec<CallArg> = Vec::new(); let mut args: BTreeMap<String, CallArg> = BTreeMap::new();
devour_whitespace(toks); devour_whitespace(toks);
let mut name: Option<String> = None; let mut name: Option<String> = None;
let mut val = Vec::new(); let mut val = Vec::new();
@ -116,14 +142,31 @@ pub fn eat_call_args<I: Iterator<Item = Token>>(toks: &mut Peekable<I>) -> CallA
// } // }
} }
TokenKind::Symbol(Symbol::CloseParen) => { TokenKind::Symbol(Symbol::CloseParen) => {
args.push(CallArg { name, val }); if name.is_some() {
args.insert(name.clone().unwrap(), CallArg { name, val });
} else {
args.insert(format!("{}", args.len()), CallArg { name, val });
}
break; break;
} }
TokenKind::Symbol(Symbol::Comma) => { TokenKind::Symbol(Symbol::Comma) => {
args.push(CallArg { if name.is_some() {
name: name.clone(), args.insert(
val: val.clone(), name.clone().unwrap(),
}); CallArg {
name: name.clone(),
val: val.clone(),
},
);
} else {
args.insert(
format!("{}", args.len()),
CallArg {
name: name.clone(),
val: val.clone(),
},
);
}
if let Some(ref mut s) = name { if let Some(ref mut s) = name {
s.clear(); s.clear();
} }

View File

@ -75,20 +75,15 @@ impl Mixin {
} }
pub fn args(mut self, args: &CallArgs) -> Mixin { pub fn args(mut self, args: &CallArgs) -> Mixin {
for (idx, arg) in args.0.iter().enumerate() { for (idx, arg) in self.args.0.iter().enumerate() {
if arg.is_named() { let val = match args.get(&format!("{}", idx)) {
todo!("keyword args") Some(v) => v.val.clone(),
} else { None => match args.get(&arg.name) {
self.scope.vars.insert( Some(v) => v.val.clone(),
self.args None => arg.default.clone().expect("missing variable!"),
.0 },
.get(idx) };
.expect("too many args passed to mixin") self.scope.vars.insert(arg.name.clone(), val);
.name
.clone(),
arg.val.clone(),
);
}
} }
self self
} }