conlang: Add Quote expression as a hack for testing

Possibly removed later, or replaced with something that turns Conlang AST nodes into Conlang data structures.
This commit is contained in:
John 2025-01-29 03:56:19 -06:00
parent 518fbe74a1
commit d21683ad61
9 changed files with 53 additions and 1 deletions

View File

@ -347,6 +347,8 @@ pub enum ExprKind {
/// An empty expression: `(` `)`
#[default]
Empty,
/// A backtick-quoted expression
Quote(Quote),
/// A local bind instruction, `let` [`Sym`] `=` [`Expr`]
Let(Let),
/// An [Assign]ment expression: [`Expr`] (`=` [`Expr`])\+
@ -396,6 +398,12 @@ pub enum ExprKind {
Continue,
}
/// A backtick-quoted subexpression-literal
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Quote {
pub quote: Box<ExprKind>,
}
/// A local variable declaration [Stmt]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Let {

View File

@ -415,6 +415,7 @@ mod display {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ExprKind::Empty => "()".fmt(f),
ExprKind::Quote(v) => v.fmt(f),
ExprKind::Let(v) => v.fmt(f),
ExprKind::Assign(v) => v.fmt(f),
ExprKind::Modify(v) => v.fmt(f),
@ -442,6 +443,13 @@ mod display {
}
}
impl Display for Quote {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { quote } = self;
write!(f, "`{quote}`")
}
}
impl Display for Let {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { mutable, name, ty, init } = self;
@ -764,6 +772,7 @@ mod convert {
}
impl From for ExprKind {
Let => ExprKind::Let,
Quote => ExprKind::Quote,
Assign => ExprKind::Assign,
Modify => ExprKind::Modify,
Binary => ExprKind::Binary,

View File

@ -529,6 +529,7 @@ pub fn or_fold_stmt_kind<F: Fold + ?Sized>(folder: &mut F, kind: StmtKind) -> St
pub fn or_fold_expr_kind<F: Fold + ?Sized>(folder: &mut F, kind: ExprKind) -> ExprKind {
match kind {
ExprKind::Empty => ExprKind::Empty,
ExprKind::Quote(q) => ExprKind::Quote(q), // quoted expressions are left unmodified
ExprKind::Let(l) => ExprKind::Let(folder.fold_let(l)),
ExprKind::Assign(a) => ExprKind::Assign(folder.fold_assign(a)),
ExprKind::Modify(m) => ExprKind::Modify(folder.fold_modify(m)),

View File

@ -452,6 +452,7 @@ pub fn or_visit_stmt_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a StmtKind)
pub fn or_visit_expr_kind<'a, V: Visit<'a>>(visitor: &mut V, e: &'a ExprKind) {
match e {
ExprKind::Empty => {}
ExprKind::Quote(_q) => {} // Quoted expressions are left unvisited
ExprKind::Let(l) => visitor.visit_let(l),
ExprKind::Assign(a) => visitor.visit_assign(a),
ExprKind::Modify(m) => visitor.visit_modify(m),

View File

@ -1,7 +1,7 @@
//! Values in the dynamically typed AST interpreter.
//!
//! The most permanent fix is a temporary one.
use cl_ast::{format::FmtAdapter, Sym};
use cl_ast::{format::FmtAdapter, ExprKind, Sym};
use super::{
error::{Error, IResult},
@ -42,6 +42,8 @@ pub enum ConValue {
Struct(Box<(Sym, HashMap<Sym, ConValue>)>),
/// An entire namespace
Module(Box<HashMap<Sym, Option<ConValue>>>),
/// A quoted expression
Quote(Box<ExprKind>),
/// A callable thing
Function(Rc<Function>),
/// A built-in function
@ -165,6 +167,7 @@ from! {
&str => ConValue::String,
String => ConValue::String,
Rc<str> => ConValue::String,
ExprKind => ConValue::Quote,
Function => ConValue::Function,
Vec<ConValue> => ConValue::Tuple,
&'static dyn BuiltIn => ConValue::BuiltIn,
@ -319,6 +322,9 @@ impl std::fmt::Display for ConValue {
}
Ok(())
}
ConValue::Quote(q) => {
write!(f, "`{q}`")
}
ConValue::Function(func) => {
write!(f, "{}", func.decl())
}

View File

@ -147,6 +147,7 @@ impl Interpret for ExprKind {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
match self {
ExprKind::Empty => Ok(ConValue::Empty),
ExprKind::Quote(q) => q.interpret(env),
ExprKind::Let(v) => v.interpret(env),
ExprKind::Assign(v) => v.interpret(env),
ExprKind::Modify(v) => v.interpret(env),
@ -174,6 +175,13 @@ impl Interpret for ExprKind {
}
}
impl Interpret for Quote {
fn interpret(&self, _env: &mut Environment) -> IResult<ConValue> {
// TODO: squoosh down into a ConValue?
Ok(ConValue::Quote(self.quote.clone()))
}
}
mod assignment {
/// Pattern matching engine for assignment
use super::*;

View File

@ -900,6 +900,18 @@ impl Parse<'_> for ExprKind {
}
}
impl Parse<'_> for Quote {
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
let quote = delim(
ExprKind::parse,
(TokenKind::Grave, TokenKind::Grave),
Parsing::ExprKind,
)(p)?
.into();
Ok(Quote { quote })
}
}
impl Parse<'_> for Let {
fn parse(p: &mut Parser) -> PResult<Let> {
p.consume_peeked();

View File

@ -16,6 +16,7 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult<ExprKind> {
literal_like!() => Literal::parse(p)?.into(),
path_like!() => exprkind_pathlike(p)?,
TokenKind::Amp | TokenKind::AmpAmp => AddrOf::parse(p)?.into(),
TokenKind::Grave => Quote::parse(p)?.into(),
TokenKind::LCurly => Block::parse(p)?.into(),
TokenKind::LBrack => exprkind_arraylike(p)?,
TokenKind::LParen => exprkind_tuplelike(p)?,

View File

@ -388,6 +388,7 @@ pub mod yamlify {
impl Yamlify for ExprKind {
fn yaml(&self, y: &mut Yamler) {
match self {
ExprKind::Quote(k) => k.yaml(y),
ExprKind::Let(k) => k.yaml(y),
ExprKind::Assign(k) => k.yaml(y),
ExprKind::Modify(k) => k.yaml(y),
@ -417,6 +418,11 @@ pub mod yamlify {
}
}
}
impl Yamlify for Quote {
fn yaml(&self, y: &mut Yamler) {
y.key("Quote").value(self);
}
}
impl Yamlify for Assign {
fn yaml(&self, y: &mut Yamler) {
let Self { parts } = self;