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) { parse(args, body, ctx) {
let mut map = ConsistentMap::new(); let mut map = ConsistentMap::new();
map.add_opt_span(Key::First, args.get_pos_opt::<AlignmentKey>()?)?; map.add_opt(Key::First, args.get_pos_opt::<AlignmentKey>()?)?;
map.add_opt_span(Key::Second, args.get_pos_opt::<AlignmentKey>()?)?; map.add_opt(Key::Second, args.get_pos_opt::<AlignmentKey>()?)?;
for arg in args.keys() { for arg in args.keys() {
let axis = AxisKey::from_ident(&arg.v.key)?; let axis = AxisKey::from_ident(&arg.v.key)?;

View File

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

View File

@ -13,8 +13,8 @@ function! {
parse(args, body, ctx) { parse(args, body, ctx) {
let mut map = ConsistentMap::new(); let mut map = ConsistentMap::new();
map.add_opt_span(AxisKey::Primary, args.get_pos_opt::<Direction>()?)?; map.add_opt(AxisKey::Primary, args.get_pos_opt::<Direction>()?)?;
map.add_opt_span(AxisKey::Secondary, args.get_pos_opt::<Direction>()?)?; map.add_opt(AxisKey::Secondary, args.get_pos_opt::<Direction>()?)?;
for arg in args.keys() { for arg in args.keys() {
let axis = AxisKey::from_ident(&arg.v.key)?; 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. /// Call a function with the value if the key is present.
pub fn with<F>(&self, key: K, callback: F) where F: FnOnce(&V) { pub fn with<F>(&self, key: K, callback: F) where F: FnOnce(&V) {
if let Some(value) = self.map.get(&key) { if let Some(value) = self.map.get(&key) {
@ -143,7 +136,7 @@ impl PaddingMap {
pub fn new(args: &mut FuncArgs, enforce: bool) -> ParseResult<PaddingMap> { pub fn new(args: &mut FuncArgs, enforce: bool) -> ParseResult<PaddingMap> {
let mut map = ConsistentMap::new(); 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() { for arg in args.keys() {
let key = match PaddingKey::from_ident(&arg.v.key) { let key = match PaddingKey::from_ident(&arg.v.key) {

View File

@ -133,7 +133,7 @@ function! {
let spacing = if let Some(axis) = meta { let spacing = if let Some(axis) = meta {
Spacing { Spacing {
axis, axis,
spacing: FSize::from_expr(args.get_pos::<Expression>()?)?, spacing: FSize::from_expr(args.get_pos::<Spanned<Expression>>()?)?,
} }
} else { } else {
if let Some(arg) = args.get_key_next() { if let Some(arg) = args.get_key_next() {
@ -178,15 +178,7 @@ function! {
layout(self, ctx) { layout(self, ctx) {
let mut style = ctx.style.text.clone(); let mut style = ctx.style.text.clone();
style.toggle_class(self.class.clone()); style.toggle_class(self.class.clone());
styled(&self.body, &ctx, style)
match &self.body {
Some(body) => vec![
SetTextStyle(style),
LayoutTree(body),
SetTextStyle(ctx.style.text.clone()),
],
None => vec![SetTextStyle(style)]
}
} }
} }
@ -201,21 +193,29 @@ function! {
parse(args, body, ctx) { parse(args, body, ctx) {
FontSize { FontSize {
body: parse!(optional: body, ctx), body: parse!(optional: body, ctx),
size: args.get_pos::<Size>()?.v, size: args.get_pos::<Size>()?,
} }
} }
layout(self, ctx) { layout(self, ctx) {
let mut style = ctx.style.text.clone(); let mut style = ctx.style.text.clone();
style.font_size = self.size; style.font_size = self.size;
styled(&self.body, &ctx, style)
match &self.body { }
Some(body) => vec![ }
SetTextStyle(style),
LayoutTree(body), /// Layout the body with the style or update the style if there is no body.
SetTextStyle(ctx.style.text.clone()), fn styled<'a>(
], body: &'a Option<SyntaxTree>,
None => vec![SetTextStyle(style)] 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. /// 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()) expect(self.get_pos_opt())
} }
/// Extract the first positional argument. /// 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() { Ok(if !self.pos.is_empty() {
let spanned = self.pos.remove(0); let spanned = self.pos.remove(0);
let span = spanned.span; Some(E::from_expr(spanned)?)
Some(Spanned::new(E::from_expr(spanned)?, span))
} else { } else {
None None
}) })
@ -143,15 +142,15 @@ impl FuncArgs {
} }
/// Force-extract a keyword argument. /// 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)) expect(self.get_key_opt(name))
} }
/// Extract a keyword argument. /// 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) { 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); let value = self.key.swap_remove(index).v.value;
Some(Spanned::new(E::from_expr(v.value)?, span)) Some(E::from_expr(value)?)
} else { } else {
None None
}) })
@ -181,7 +180,7 @@ impl FuncArgs {
} }
/// Extract the option expression kind from the option or return an error. /// 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 { match opt {
Ok(Some(spanned)) => Ok(spanned), Ok(Some(spanned)) => Ok(spanned),
Ok(None) => error!("expected {}", E::NAME), Ok(None) => error!("expected {}", E::NAME),
@ -308,3 +307,13 @@ kind!(ScaleSize, "number or size",
Expression::Size(size) => ScaleSize::Absolute(size), Expression::Size(size) => ScaleSize::Absolute(size),
Expression::Num(scale) => ScaleSize::Scaled(scale as f32) 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))
}
}