Implement expression kind for Spanned<T> 👩‍💻

This commit is contained in:
Laurenz 2019-12-13 14:58:14 +01:00
parent f549914ff8
commit 971ff3a2dc
6 changed files with 44 additions and 44 deletions

View File

@ -13,8 +13,8 @@ function! {
parse(args, body, ctx) {
let mut map = ConsistentMap::new();
map.add_opt_span(Key::First, args.get_pos_opt::<AlignmentKey>()?)?;
map.add_opt_span(Key::Second, args.get_pos_opt::<AlignmentKey>()?)?;
map.add_opt(Key::First, args.get_pos_opt::<AlignmentKey>()?)?;
map.add_opt(Key::Second, args.get_pos_opt::<AlignmentKey>()?)?;
for arg in args.keys() {
let axis = AxisKey::from_ident(&arg.v.key)?;

View File

@ -14,9 +14,7 @@ function! {
Boxed {
body: parse!(optional: body, ctx).unwrap_or(SyntaxTree::new()),
map: ExtentMap::new(&mut args, false)?,
debug: args.get_key_opt::<bool>("debug")?
.map(Spanned::value)
.unwrap_or(true),
debug: args.get_key_opt::<bool>("debug")?.unwrap_or(true),
}
}

View File

@ -13,8 +13,8 @@ function! {
parse(args, body, ctx) {
let mut map = ConsistentMap::new();
map.add_opt_span(AxisKey::Primary, args.get_pos_opt::<Direction>()?)?;
map.add_opt_span(AxisKey::Secondary, args.get_pos_opt::<Direction>()?)?;
map.add_opt(AxisKey::Primary, args.get_pos_opt::<Direction>()?)?;
map.add_opt(AxisKey::Secondary, args.get_pos_opt::<Direction>()?)?;
for arg in args.keys() {
let axis = AxisKey::from_ident(&arg.v.key)?;

View File

@ -31,13 +31,6 @@ impl<K, V> ConsistentMap<K, V> where K: Hash + Eq {
})
}
/// Add a key-spanned-value pair the value is not `None`.
pub fn add_opt_span(&mut self, key: K, value: Option<Spanned<V>>) -> ParseResult<()> {
Ok(if let Some(spanned) = value {
self.add(key, spanned.v)?;
})
}
/// Call a function with the value if the key is present.
pub fn with<F>(&self, key: K, callback: F) where F: FnOnce(&V) {
if let Some(value) = self.map.get(&key) {
@ -143,7 +136,7 @@ impl PaddingMap {
pub fn new(args: &mut FuncArgs, enforce: bool) -> ParseResult<PaddingMap> {
let mut map = ConsistentMap::new();
map.add_opt_span(PaddingKey::All, args.get_pos_opt::<Size>()?)?;
map.add_opt(PaddingKey::All, args.get_pos_opt::<Size>()?)?;
for arg in args.keys() {
let key = match PaddingKey::from_ident(&arg.v.key) {

View File

@ -133,7 +133,7 @@ function! {
let spacing = if let Some(axis) = meta {
Spacing {
axis,
spacing: FSize::from_expr(args.get_pos::<Expression>()?)?,
spacing: FSize::from_expr(args.get_pos::<Spanned<Expression>>()?)?,
}
} else {
if let Some(arg) = args.get_key_next() {
@ -178,15 +178,7 @@ function! {
layout(self, ctx) {
let mut style = ctx.style.text.clone();
style.toggle_class(self.class.clone());
match &self.body {
Some(body) => vec![
SetTextStyle(style),
LayoutTree(body),
SetTextStyle(ctx.style.text.clone()),
],
None => vec![SetTextStyle(style)]
}
styled(&self.body, &ctx, style)
}
}
@ -201,21 +193,29 @@ function! {
parse(args, body, ctx) {
FontSize {
body: parse!(optional: body, ctx),
size: args.get_pos::<Size>()?.v,
size: args.get_pos::<Size>()?,
}
}
layout(self, ctx) {
let mut style = ctx.style.text.clone();
style.font_size = self.size;
match &self.body {
Some(body) => vec![
SetTextStyle(style),
LayoutTree(body),
SetTextStyle(ctx.style.text.clone()),
],
None => vec![SetTextStyle(style)]
}
styled(&self.body, &ctx, style)
}
}
/// Layout the body with the style or update the style if there is no body.
fn styled<'a>(
body: &'a Option<SyntaxTree>,
ctx: &LayoutContext,
style: TextStyle
) -> Commands<'a> {
match &body {
Some(body) => vec![
SetTextStyle(style),
LayoutTree(body),
SetTextStyle(ctx.style.text.clone()),
],
None => vec![SetTextStyle(style)]
}
}

View File

@ -121,16 +121,15 @@ impl FuncArgs {
}
/// Force-extract the first positional argument.
pub fn get_pos<E: ExpressionKind>(&mut self) -> ParseResult<Spanned<E>> {
pub fn get_pos<E: ExpressionKind>(&mut self) -> ParseResult<E> {
expect(self.get_pos_opt())
}
/// Extract the first positional argument.
pub fn get_pos_opt<E: ExpressionKind>(&mut self) -> ParseResult<Option<Spanned<E>>> {
pub fn get_pos_opt<E: ExpressionKind>(&mut self) -> ParseResult<Option<E>> {
Ok(if !self.pos.is_empty() {
let spanned = self.pos.remove(0);
let span = spanned.span;
Some(Spanned::new(E::from_expr(spanned)?, span))
Some(E::from_expr(spanned)?)
} else {
None
})
@ -143,15 +142,15 @@ impl FuncArgs {
}
/// Force-extract a keyword argument.
pub fn get_key<E: ExpressionKind>(&mut self, name: &str) -> ParseResult<Spanned<E>> {
pub fn get_key<E: ExpressionKind>(&mut self, name: &str) -> ParseResult<E> {
expect(self.get_key_opt(name))
}
/// Extract a keyword argument.
pub fn get_key_opt<E: ExpressionKind>(&mut self, name: &str) -> ParseResult<Option<Spanned<E>>> {
pub fn get_key_opt<E: ExpressionKind>(&mut self, name: &str) -> ParseResult<Option<E>> {
Ok(if let Some(index) = self.key.iter().position(|arg| arg.v.key.v.0 == name) {
let Spanned { v, span } = self.key.swap_remove(index);
Some(Spanned::new(E::from_expr(v.value)?, span))
let value = self.key.swap_remove(index).v.value;
Some(E::from_expr(value)?)
} else {
None
})
@ -181,7 +180,7 @@ impl FuncArgs {
}
/// Extract the option expression kind from the option or return an error.
fn expect<E: ExpressionKind>(opt: ParseResult<Option<Spanned<E>>>) -> ParseResult<Spanned<E>> {
fn expect<E: ExpressionKind>(opt: ParseResult<Option<E>>) -> ParseResult<E> {
match opt {
Ok(Some(spanned)) => Ok(spanned),
Ok(None) => error!("expected {}", E::NAME),
@ -308,3 +307,13 @@ kind!(ScaleSize, "number or size",
Expression::Size(size) => ScaleSize::Absolute(size),
Expression::Num(scale) => ScaleSize::Scaled(scale as f32)
);
impl<T> ExpressionKind for Spanned<T> where T: ExpressionKind {
const NAME: &'static str = T::NAME;
fn from_expr(expr: Spanned<Expression>) -> ParseResult<Spanned<T>> {
let span = expr.span;
T::from_expr(expr)
.map(|v| Spanned::new(v, span))
}
}