Compare commits
No commits in common. "af3fa309868f28cd38c4597ea86351e04dfd90f6" and "728d013c6d6f8bca2e806b5225db76e48b6249cb" have entirely different histories.
af3fa30986
...
728d013c6d
|
|
@ -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:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
232
src/lib.rs
232
src/lib.rs
|
|
@ -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, ",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue