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

View File

@ -415,6 +415,7 @@ mod display {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
ExprKind::Empty => "()".fmt(f), ExprKind::Empty => "()".fmt(f),
ExprKind::Quote(v) => v.fmt(f),
ExprKind::Let(v) => v.fmt(f), ExprKind::Let(v) => v.fmt(f),
ExprKind::Assign(v) => v.fmt(f), ExprKind::Assign(v) => v.fmt(f),
ExprKind::Modify(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 { impl Display for Let {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { mutable, name, ty, init } = self; let Self { mutable, name, ty, init } = self;
@ -764,6 +772,7 @@ mod convert {
} }
impl From for ExprKind { impl From for ExprKind {
Let => ExprKind::Let, Let => ExprKind::Let,
Quote => ExprKind::Quote,
Assign => ExprKind::Assign, Assign => ExprKind::Assign,
Modify => ExprKind::Modify, Modify => ExprKind::Modify,
Binary => ExprKind::Binary, 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 { pub fn or_fold_expr_kind<F: Fold + ?Sized>(folder: &mut F, kind: ExprKind) -> ExprKind {
match kind { match kind {
ExprKind::Empty => ExprKind::Empty, 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::Let(l) => ExprKind::Let(folder.fold_let(l)),
ExprKind::Assign(a) => ExprKind::Assign(folder.fold_assign(a)), ExprKind::Assign(a) => ExprKind::Assign(folder.fold_assign(a)),
ExprKind::Modify(m) => ExprKind::Modify(folder.fold_modify(m)), 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) { pub fn or_visit_expr_kind<'a, V: Visit<'a>>(visitor: &mut V, e: &'a ExprKind) {
match e { match e {
ExprKind::Empty => {} ExprKind::Empty => {}
ExprKind::Quote(_q) => {} // Quoted expressions are left unvisited
ExprKind::Let(l) => visitor.visit_let(l), ExprKind::Let(l) => visitor.visit_let(l),
ExprKind::Assign(a) => visitor.visit_assign(a), ExprKind::Assign(a) => visitor.visit_assign(a),
ExprKind::Modify(m) => visitor.visit_modify(m), ExprKind::Modify(m) => visitor.visit_modify(m),

View File

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

View File

@ -147,6 +147,7 @@ impl Interpret for ExprKind {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> { fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
match self { match self {
ExprKind::Empty => Ok(ConValue::Empty), ExprKind::Empty => Ok(ConValue::Empty),
ExprKind::Quote(q) => q.interpret(env),
ExprKind::Let(v) => v.interpret(env), ExprKind::Let(v) => v.interpret(env),
ExprKind::Assign(v) => v.interpret(env), ExprKind::Assign(v) => v.interpret(env),
ExprKind::Modify(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 { mod assignment {
/// Pattern matching engine for assignment /// Pattern matching engine for assignment
use super::*; 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 { impl Parse<'_> for Let {
fn parse(p: &mut Parser) -> PResult<Let> { fn parse(p: &mut Parser) -> PResult<Let> {
p.consume_peeked(); 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(), literal_like!() => Literal::parse(p)?.into(),
path_like!() => exprkind_pathlike(p)?, path_like!() => exprkind_pathlike(p)?,
TokenKind::Amp | TokenKind::AmpAmp => AddrOf::parse(p)?.into(), TokenKind::Amp | TokenKind::AmpAmp => AddrOf::parse(p)?.into(),
TokenKind::Grave => Quote::parse(p)?.into(),
TokenKind::LCurly => Block::parse(p)?.into(), TokenKind::LCurly => Block::parse(p)?.into(),
TokenKind::LBrack => exprkind_arraylike(p)?, TokenKind::LBrack => exprkind_arraylike(p)?,
TokenKind::LParen => exprkind_tuplelike(p)?, TokenKind::LParen => exprkind_tuplelike(p)?,

View File

@ -388,6 +388,7 @@ pub mod yamlify {
impl Yamlify for ExprKind { impl Yamlify for ExprKind {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
match self { match self {
ExprKind::Quote(k) => k.yaml(y),
ExprKind::Let(k) => k.yaml(y), ExprKind::Let(k) => k.yaml(y),
ExprKind::Assign(k) => k.yaml(y), ExprKind::Assign(k) => k.yaml(y),
ExprKind::Modify(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 { impl Yamlify for Assign {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { parts } = self; let Self { parts } = self;