Compare commits

..

No commits in common. "af3fa309868f28cd38c4597ea86351e04dfd90f6" and "728d013c6d6f8bca2e806b5225db76e48b6249cb" have entirely different histories.

2 changed files with 80 additions and 153 deletions

View file

@ -19,6 +19,7 @@ pub fn execute_(out: &mut String, ast: &Ast, value: &dyn Value) {
AstKind::For(f) => for_(out, f, value), AstKind::For(f) => for_(out, f, value),
AstKind::Has(h) => has(out, h, value), AstKind::Has(h) => has(out, h, value),
AstKind::If(h) => if_(out, h, value), AstKind::If(h) => if_(out, h, value),
e => todo!("{e:?}"),
} }
} }
} }

View file

@ -1,4 +1,4 @@
use core::fmt::Write; use core::fmt::{Display, Write};
pub mod internal; pub mod internal;
@ -7,7 +7,7 @@ use internal::{
parse::{parse, Ast}, parse::{parse, Ast},
}; };
pub trait Value { pub trait Value: core::fmt::Debug {
fn print(&self, out: &mut String); fn print(&self, out: &mut String);
fn lookup(&self, name: &str) -> Option<&dyn Value>; fn lookup(&self, name: &str) -> Option<&dyn Value>;
fn has(&self) -> Option<&dyn Value>; fn has(&self) -> Option<&dyn Value>;
@ -15,76 +15,9 @@ pub trait Value {
fn for_(&self, index: usize) -> Option<&dyn Value>; fn for_(&self, index: usize) -> Option<&dyn Value>;
} }
macro_rules! value_for_int {
($tp:ty) => {
impl Value for $tp {
fn print(&self, out: &mut String) {
let _ = write!(out, "{self}");
}
fn lookup(&self, _: &str) -> Option<&dyn Value> {
None
}
fn has(&self) -> Option<&dyn Value> {
if self.if_() {
Some(self)
} else {
None
}
}
fn if_(&self) -> bool {
*self != 0
}
fn for_(&self, _: usize) -> Option<&dyn Value> {
None
}
}
};
}
value_for_int!(u8);
value_for_int!(u16);
value_for_int!(u32);
value_for_int!(u64);
value_for_int!(u128);
value_for_int!(usize);
value_for_int!(i8);
value_for_int!(i16);
value_for_int!(i32);
value_for_int!(i64);
value_for_int!(i128);
value_for_int!(isize);
impl<'a, T> Value for &'a T impl<'a, T> Value for &'a T
where where
T: Value + ?Sized, T: Value,
{
fn print(&self, out: &mut String) {
(&**self).print(out)
}
fn lookup(&self, name: &str) -> Option<&dyn Value> {
(&**self).lookup(name)
}
fn has(&self) -> Option<&dyn Value> {
(&**self).has()
}
fn if_(&self) -> bool {
(&**self).if_()
}
fn for_(&self, index: usize) -> Option<&dyn Value> {
(&**self).for_(index)
}
}
impl<'a, T> Value for &'a mut T
where
T: Value + ?Sized,
{ {
fn print(&self, out: &mut String) { fn print(&self, out: &mut String) {
(&**self).print(out) (&**self).print(out)
@ -137,56 +70,24 @@ impl Value for &str {
} }
} }
impl Value for String { impl Value for (&str, &dyn Value) {
fn print(&self, out: &mut String) {
out.push_str(self);
}
fn lookup(&self, _: &str) -> Option<&dyn Value> {
None
}
fn has(&self) -> Option<&dyn Value> {
if self.if_() {
None
} else {
Some(self)
}
}
fn if_(&self) -> bool {
!self.is_empty()
}
fn for_(&self, index: usize) -> Option<&dyn Value> {
if index == 0 {
Some(self)
} else {
None
}
}
}
impl<A, B> Value for (A, B)
where
A: Value,
B: Value,
{
fn print(&self, out: &mut String) { fn print(&self, out: &mut String) {
out.push('(');
self.0.print(out); self.0.print(out);
out.push_str(", ");
self.1.print(out); self.1.print(out);
} }
fn lookup(&self, name: &str) -> Option<&dyn Value> { fn lookup(&self, name: &str) -> Option<&dyn Value> {
match name { match name {
"0" => Some(&self.0), "0" => Some(&self.0),
"1" => Some(&self.1), "1" => Some(self.1),
_ => None, _ => None,
} }
} }
fn has(&self) -> Option<&dyn Value> { fn has(&self) -> Option<&dyn Value> {
None Some(self)
} }
fn if_(&self) -> bool { fn if_(&self) -> bool {
@ -196,55 +97,53 @@ where
fn for_(&self, index: usize) -> Option<&dyn Value> { fn for_(&self, index: usize) -> Option<&dyn Value> {
match index { match index {
0 => Some(&self.0), 0 => Some(&self.0),
1 => Some(&self.1), 1 => Some(self.1),
_ => None, _ => None,
} }
} }
} }
pub struct ValuesListMap<'a>(pub &'a [(&'a str, &'a dyn Value)]); impl Value for (&dyn Value, &dyn Value) {
impl<'a> Value for ValuesListMap<'a> { fn print(&self, out: &mut String) {
self.0.print(out);
self.1.print(out);
}
fn lookup(&self, name: &str) -> Option<&dyn Value> {
match name {
"0" => Some(self.0),
"1" => Some(self.1),
_ => None,
}
}
fn has(&self) -> Option<&dyn Value> {
Some(self)
}
fn if_(&self) -> bool {
self.0.if_() && self.1.if_()
}
fn for_(&self, index: usize) -> Option<&dyn Value> {
match index {
0 => Some(self.0),
1 => Some(self.1),
_ => None,
}
}
}
impl<const N: usize> Value for [(&str, &dyn Value); N] {
fn print(&self, w: &mut String) { fn print(&self, w: &mut String) {
for (name, v) in self.0.iter() { for (name, v) in self.iter() {
let _ = write!(w, "{name}"); let _ = write!(w, "{name}");
v.print(w); v.print(w);
} }
} }
fn lookup(&self, name: &str) -> Option<&dyn Value> { fn lookup(&self, name: &str) -> Option<&dyn Value> {
self.0.iter().find(|(n, _)| *n == name).map(|(_, v)| *v) self.iter().find(|(n, _)| *n == name).map(|(_, v)| *v)
}
fn has(&self) -> Option<&dyn Value> {
if self.0.is_empty() {
None
} else {
Some(self)
}
}
fn if_(&self) -> bool {
!self.0.is_empty()
}
fn for_(&self, index: usize) -> Option<&dyn Value> {
self.0.get(index).map(|v| v as &dyn Value)
}
}
impl<const N: usize, T> Value for [T; N]
where
T: Value,
{
fn print(&self, w: &mut String) {
for v in self.iter() {
v.print(w)
}
}
fn lookup(&self, name: &str) -> Option<&dyn Value> {
let idx: usize = name.parse().ok()?;
self.get(idx).map(|v| v as &dyn Value)
} }
fn has(&self) -> Option<&dyn Value> { fn has(&self) -> Option<&dyn Value> {
@ -264,6 +163,35 @@ where
} }
} }
impl<const N: usize> Value for [&dyn Value; N] {
fn print(&self, w: &mut String) {
for v in self.iter() {
v.print(w)
}
}
fn lookup(&self, name: &str) -> Option<&dyn Value> {
let idx: usize = name.parse().ok()?;
self.get(idx).copied()
}
fn has(&self) -> Option<&dyn Value> {
if self.is_empty() {
None
} else {
Some(self)
}
}
fn if_(&self) -> bool {
self.is_empty()
}
fn for_(&self, index: usize) -> Option<&dyn Value> {
self.get(index).map(|v| *v)
}
}
impl<T> Value for Option<T> impl<T> Value for Option<T>
where where
T: Value, T: Value,
@ -314,13 +242,11 @@ impl Newt {
#[macro_export] #[macro_export]
macro_rules! values_list_map { macro_rules! values_list_map {
($($key:literal: $val:expr),* $(,)?) => {{ ($($key:literal: $val:expr),* $(,)?) => {{
&$crate::ValuesListMap( &[
&[ $(
$( ($key, $val as &dyn Value)
($key, $val as &dyn Value) )*,
)*, ]
]
)
}} }}
} }
@ -374,10 +300,10 @@ mod test {
"{for .items}{for .names}{.}, {/for}{/for}", "{for .items}{for .names}{.}, {/for}{/for}",
values_list_map! { values_list_map! {
"items": values![values_list_map! { "items": values![values_list_map! {
"names": values!["Bob", "Larry", 0], "names": values!["Bob", "Larry"],
}] }]
}, },
"Bob, Larry, 0, ", "Bob, Larry, ",
) )
} }