Implement default arguments in mixins
This commit is contained in:
parent
6da84575dc
commit
1636d775c5
@ -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();
|
||||||
}
|
}
|
||||||
|
23
src/mixin.rs
23
src/mixin.rs
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user