This commit is contained in:
soup 2024-05-31 15:41:22 -04:00
parent 8064118490
commit a3877817dd
No known key found for this signature in database
5 changed files with 61 additions and 69 deletions

View file

@ -75,7 +75,7 @@ pub fn for_(out: &mut String, f: &For, value: &dyn Value, arena: &AstArena) {
}; };
let mut idx = 0; let mut idx = 0;
while let Some(value) = value.for_(idx) { while let Some(value) = value.index(idx) {
let nodes = arena.deref_many(&f.body); let nodes = arena.deref_many(&f.body);
execute_(out, nodes, value, arena); execute_(out, nodes, value, arena);
idx += 1; idx += 1;
@ -100,7 +100,7 @@ pub fn if_(out: &mut String, f: &If, value: &dyn Value, arena: &AstArena) {
None => return, None => return,
}; };
if value.if_() { if value.is_truthy() {
let nodes = arena.deref_many(&f.then); let nodes = arena.deref_many(&f.then);
execute_(out, nodes, value, arena); execute_(out, nodes, value, arena);
} else if let Some(else_) = f.else_.as_ref() { } else if let Some(else_) = f.else_.as_ref() {

View file

@ -1,8 +1,2 @@
//! NOTE: Anything marked pub within this module or its children should not be
//! considered stable when it comes to semver. However, they are exposed for
//! advanced use cases.
pub mod execute;
pub mod parse; pub mod parse;
mod parse_backup; pub mod vm;
pub(crate) mod vm;

View file

@ -1,7 +1,3 @@
use std::ops::ControlFlow;
pub use super::parse_backup::*;
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
pub enum AstNodeKind { pub enum AstNodeKind {
If(If), If(If),
@ -56,10 +52,12 @@ struct ParseResult<'a, T>(
T, // output T, // output
); );
impl<'a, T> ParseResult<'a, T> { impl<'a, T> ParseResult<'a, T> {
#[allow(dead_code)]
fn remaining(&self) -> &'a str { fn remaining(&self) -> &'a str {
self.0 self.0
} }
#[allow(dead_code)]
fn output(&self) -> &T { fn output(&self) -> &T {
&self.1 &self.1
} }
@ -472,7 +470,7 @@ fn parse_many_until(
break; break;
} }
if remaining == "" { if remaining.is_empty() {
return ParseResult("", None); return ParseResult("", None);
} }

View file

@ -71,7 +71,7 @@ pub(crate) mod ops {
pub(crate) fn lower_ast(ast: &[AstNodeKind]) -> Ops { pub(crate) fn lower_ast(ast: &[AstNodeKind]) -> Ops {
let mut ops = Ops::new(); let mut ops = Ops::new();
lower_many(&mut ops, &ast); lower_many(&mut ops, ast);
ops.emit(Op::Exit); ops.emit(Op::Exit);
ops ops
@ -162,8 +162,8 @@ pub(crate) mod ops {
macro_rules! go { macro_rules! go {
($src:expr, $expected:expr) => { ($src:expr, $expected:expr) => {
assert_eq!( assert_eq!(
crate::internal::vm::ops::lower_ast( $crate::internal::vm::ops::lower_ast(
&crate::internal::parse::parse($src) &$crate::internal::parse::parse($src)
), ),
Ops($expected), Ops($expected),
) )
@ -342,7 +342,7 @@ impl<'a> VmState<'a> {
self.stack_values.pop().expect("stack_values is empty"); self.stack_values.pop().expect("stack_values is empty");
}, },
Op::ValueLookup(field) => { Op::ValueLookup(field) => {
let new_value = self.reg_value.lookup(&field); let new_value = self.reg_value.lookup(field);
match new_value { match new_value {
Some(v) => { Some(v) => {
self.reg_value = v; self.reg_value = v;
@ -356,7 +356,7 @@ impl<'a> VmState<'a> {
} }
}, },
Op::ValueIndex => { Op::ValueIndex => {
let value = self.reg_value.for_(self.reg_counter); let value = self.reg_value.index(self.reg_counter);
if let Some(value) = value { if let Some(value) = value {
self.reg_value = value; self.reg_value = value;
self.reg_cond = true; self.reg_cond = true;
@ -368,7 +368,7 @@ impl<'a> VmState<'a> {
self.reg_value.print(&mut self.output); self.reg_value.print(&mut self.output);
}, },
Op::ValueTruthy => { Op::ValueTruthy => {
self.reg_cond = self.reg_value.if_(); self.reg_cond = self.reg_value.is_truthy();
}, },
Op::ValueHas => { Op::ValueHas => {
if let Some(value) = self.reg_value.has() { if let Some(value) = self.reg_value.has() {

View file

@ -3,8 +3,7 @@ use core::fmt::Write;
pub mod internal; pub mod internal;
use internal::{ use internal::{
execute::execute, parse::parse,
parse::{parse, Ast},
vm::{ vm::{
ops::{lower_ast, Ops}, ops::{lower_ast, Ops},
VmState, VmState,
@ -15,8 +14,8 @@ 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>;
fn if_(&self) -> bool; fn is_truthy(&self) -> bool;
fn for_(&self, index: usize) -> Option<&dyn Value>; fn index(&self, index: usize) -> Option<&dyn Value>;
} }
macro_rules! value_for_int { macro_rules! value_for_int {
@ -31,18 +30,18 @@ macro_rules! value_for_int {
} }
fn has(&self) -> Option<&dyn Value> { fn has(&self) -> Option<&dyn Value> {
if self.if_() { if self.is_truthy() {
Some(self) Some(self)
} else { } else {
None None
} }
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
*self != 0 *self != 0
} }
fn for_(&self, _: usize) -> Option<&dyn Value> { fn index(&self, _: usize) -> Option<&dyn Value> {
None None
} }
} }
@ -66,23 +65,23 @@ where
T: Value + ?Sized, T: Value + ?Sized,
{ {
fn print(&self, out: &mut String) { fn print(&self, out: &mut String) {
(&**self).print(out) (**self).print(out);
} }
fn lookup(&self, name: &str) -> Option<&dyn Value> { fn lookup(&self, name: &str) -> Option<&dyn Value> {
(&**self).lookup(name) (**self).lookup(name)
} }
fn has(&self) -> Option<&dyn Value> { fn has(&self) -> Option<&dyn Value> {
(&**self).has() (**self).has()
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
(&**self).if_() (**self).is_truthy()
} }
fn for_(&self, index: usize) -> Option<&dyn Value> { fn index(&self, index: usize) -> Option<&dyn Value> {
(&**self).for_(index) (**self).index(index)
} }
} }
@ -91,23 +90,23 @@ where
T: Value + ?Sized, T: Value + ?Sized,
{ {
fn print(&self, out: &mut String) { fn print(&self, out: &mut String) {
(&**self).print(out) (**self).print(out);
} }
fn lookup(&self, name: &str) -> Option<&dyn Value> { fn lookup(&self, name: &str) -> Option<&dyn Value> {
(&**self).lookup(name) (**self).lookup(name)
} }
fn has(&self) -> Option<&dyn Value> { fn has(&self) -> Option<&dyn Value> {
(&**self).has() (**self).has()
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
(&**self).if_() (**self).is_truthy()
} }
fn for_(&self, index: usize) -> Option<&dyn Value> { fn index(&self, index: usize) -> Option<&dyn Value> {
(&**self).for_(index) (**self).index(index)
} }
} }
@ -121,18 +120,18 @@ impl Value for &str {
} }
fn has(&self) -> Option<&dyn Value> { fn has(&self) -> Option<&dyn Value> {
if self.if_() { if self.is_truthy() {
None None
} else { } else {
Some(self) Some(self)
} }
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
!self.is_empty() !self.is_empty()
} }
fn for_(&self, index: usize) -> Option<&dyn Value> { fn index(&self, index: usize) -> Option<&dyn Value> {
if index == 0 { if index == 0 {
Some(self) Some(self)
} else { } else {
@ -151,18 +150,18 @@ impl Value for String {
} }
fn has(&self) -> Option<&dyn Value> { fn has(&self) -> Option<&dyn Value> {
if self.if_() { if self.is_truthy() {
None None
} else { } else {
Some(self) Some(self)
} }
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
!self.is_empty() !self.is_empty()
} }
fn for_(&self, index: usize) -> Option<&dyn Value> { fn index(&self, index: usize) -> Option<&dyn Value> {
if index == 0 { if index == 0 {
Some(self) Some(self)
} else { } else {
@ -193,11 +192,11 @@ where
None None
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
self.0.if_() && self.1.if_() self.0.is_truthy() && self.1.is_truthy()
} }
fn for_(&self, index: usize) -> Option<&dyn Value> { fn index(&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),
@ -210,7 +209,7 @@ where
pub struct ValuesListMap<'a>(pub &'a [(&'a str, &'a dyn Value)]); pub struct ValuesListMap<'a>(pub &'a [(&'a str, &'a dyn Value)]);
impl<'a> Value for ValuesListMap<'a> { impl<'a> Value for ValuesListMap<'a> {
fn print(&self, w: &mut String) { fn print(&self, w: &mut String) {
for (name, v) in self.0.iter() { for (name, v) in self.0 {
let _ = write!(w, "{name}"); let _ = write!(w, "{name}");
v.print(w); v.print(w);
} }
@ -228,11 +227,11 @@ impl<'a> Value for ValuesListMap<'a> {
} }
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
!self.0.is_empty() !self.0.is_empty()
} }
fn for_(&self, index: usize) -> Option<&dyn Value> { fn index(&self, index: usize) -> Option<&dyn Value> {
self.0.get(index).map(|v| v as &dyn Value) self.0.get(index).map(|v| v as &dyn Value)
} }
} }
@ -242,8 +241,8 @@ where
T: Value, T: Value,
{ {
fn print(&self, w: &mut String) { fn print(&self, w: &mut String) {
for v in self.iter() { for v in self {
v.print(w) v.print(w);
} }
} }
@ -260,11 +259,11 @@ where
} }
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
self.is_empty() self.is_empty()
} }
fn for_(&self, index: usize) -> Option<&dyn Value> { fn index(&self, index: usize) -> Option<&dyn Value> {
self.get(index).map(|v| v as &dyn Value) self.get(index).map(|v| v as &dyn Value)
} }
} }
@ -275,7 +274,7 @@ where
{ {
fn print(&self, out: &mut String) { fn print(&self, out: &mut String) {
if let Some(v) = self { if let Some(v) = self {
v.print(out) v.print(out);
} }
} }
@ -287,11 +286,11 @@ where
self.as_ref().map(|v| v as &dyn Value) self.as_ref().map(|v| v as &dyn Value)
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
self.is_some() self.is_some()
} }
fn for_(&self, index: usize) -> Option<&dyn Value> { fn index(&self, index: usize) -> Option<&dyn Value> {
if index == 0 { if index == 0 {
self.has() self.has()
} else { } else {
@ -305,8 +304,8 @@ where
T: Value, T: Value,
{ {
fn print(&self, w: &mut String) { fn print(&self, w: &mut String) {
for v in self.iter() { for v in self {
v.print(w) v.print(w);
} }
} }
@ -323,11 +322,11 @@ where
} }
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
self.is_empty() self.is_empty()
} }
fn for_(&self, index: usize) -> Option<&dyn Value> { fn index(&self, index: usize) -> Option<&dyn Value> {
self.get(index).map(|v| v as &dyn Value) self.get(index).map(|v| v as &dyn Value)
} }
} }
@ -344,18 +343,18 @@ impl Value for () {
None None
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
true true
} }
fn for_(&self, _: usize) -> Option<&dyn Value> { fn index(&self, _: usize) -> Option<&dyn Value> {
None None
} }
} }
impl Value for bool { impl Value for bool {
fn print(&self, out: &mut String) { fn print(&self, out: &mut String) {
let _ = write!(out, "{}", self); let _ = write!(out, "{self}");
} }
fn lookup(&self, _name: &str) -> Option<&dyn Value> { fn lookup(&self, _name: &str) -> Option<&dyn Value> {
@ -366,11 +365,11 @@ impl Value for bool {
Some(self) Some(self)
} }
fn if_(&self) -> bool { fn is_truthy(&self) -> bool {
*self *self
} }
fn for_(&self, _index: usize) -> Option<&dyn Value> { fn index(&self, _index: usize) -> Option<&dyn Value> {
None None
} }
} }
@ -379,6 +378,7 @@ pub struct Newt {
ops: Ops, ops: Ops,
} }
impl Newt { impl Newt {
#[must_use]
pub fn build(tmpl: &str) -> Self { pub fn build(tmpl: &str) -> Self {
let ast = parse(tmpl); let ast = parse(tmpl);
let ops = lower_ast(&ast); let ops = lower_ast(&ast);