From d21683ad611673847b66e7fb36c36d43afda3f7c Mon Sep 17 00:00:00 2001 From: John Date: Wed, 29 Jan 2025 03:56:19 -0600 Subject: [PATCH] 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. --- compiler/cl-ast/src/ast.rs | 8 ++++++++ compiler/cl-ast/src/ast_impl.rs | 9 +++++++++ compiler/cl-ast/src/ast_visitor/fold.rs | 1 + compiler/cl-ast/src/ast_visitor/visit.rs | 1 + compiler/cl-interpret/src/convalue.rs | 8 +++++++- compiler/cl-interpret/src/interpret.rs | 8 ++++++++ compiler/cl-parser/src/parser.rs | 12 ++++++++++++ compiler/cl-parser/src/parser/prec.rs | 1 + compiler/cl-repl/examples/yaml.rs | 6 ++++++ 9 files changed, 53 insertions(+), 1 deletion(-) diff --git a/compiler/cl-ast/src/ast.rs b/compiler/cl-ast/src/ast.rs index 36d97bf..251c039 100644 --- a/compiler/cl-ast/src/ast.rs +++ b/compiler/cl-ast/src/ast.rs @@ -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, +} + /// A local variable declaration [Stmt] #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Let { diff --git a/compiler/cl-ast/src/ast_impl.rs b/compiler/cl-ast/src/ast_impl.rs index 1220f13..f746ea8 100644 --- a/compiler/cl-ast/src/ast_impl.rs +++ b/compiler/cl-ast/src/ast_impl.rs @@ -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, diff --git a/compiler/cl-ast/src/ast_visitor/fold.rs b/compiler/cl-ast/src/ast_visitor/fold.rs index 082c461..402b693 100644 --- a/compiler/cl-ast/src/ast_visitor/fold.rs +++ b/compiler/cl-ast/src/ast_visitor/fold.rs @@ -529,6 +529,7 @@ pub fn or_fold_stmt_kind(folder: &mut F, kind: StmtKind) -> St pub fn or_fold_expr_kind(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)), diff --git a/compiler/cl-ast/src/ast_visitor/visit.rs b/compiler/cl-ast/src/ast_visitor/visit.rs index aa99d58..4411ad2 100644 --- a/compiler/cl-ast/src/ast_visitor/visit.rs +++ b/compiler/cl-ast/src/ast_visitor/visit.rs @@ -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), diff --git a/compiler/cl-interpret/src/convalue.rs b/compiler/cl-interpret/src/convalue.rs index bb8796f..9553a2b 100644 --- a/compiler/cl-interpret/src/convalue.rs +++ b/compiler/cl-interpret/src/convalue.rs @@ -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)>), /// An entire namespace Module(Box>>), + /// A quoted expression + Quote(Box), /// A callable thing Function(Rc), /// A built-in function @@ -165,6 +167,7 @@ from! { &str => ConValue::String, String => ConValue::String, Rc => ConValue::String, + ExprKind => ConValue::Quote, Function => ConValue::Function, Vec => 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()) } diff --git a/compiler/cl-interpret/src/interpret.rs b/compiler/cl-interpret/src/interpret.rs index 1163de9..a24146e 100644 --- a/compiler/cl-interpret/src/interpret.rs +++ b/compiler/cl-interpret/src/interpret.rs @@ -147,6 +147,7 @@ impl Interpret for ExprKind { fn interpret(&self, env: &mut Environment) -> IResult { 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 { + // TODO: squoosh down into a ConValue? + Ok(ConValue::Quote(self.quote.clone())) + } +} + mod assignment { /// Pattern matching engine for assignment use super::*; diff --git a/compiler/cl-parser/src/parser.rs b/compiler/cl-parser/src/parser.rs index dc29c5d..ee49f86 100644 --- a/compiler/cl-parser/src/parser.rs +++ b/compiler/cl-parser/src/parser.rs @@ -900,6 +900,18 @@ impl Parse<'_> for ExprKind { } } +impl Parse<'_> for Quote { + fn parse(p: &mut Parser<'_>) -> PResult { + 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 { p.consume_peeked(); diff --git a/compiler/cl-parser/src/parser/prec.rs b/compiler/cl-parser/src/parser/prec.rs index 3024912..8147364 100644 --- a/compiler/cl-parser/src/parser/prec.rs +++ b/compiler/cl-parser/src/parser/prec.rs @@ -16,6 +16,7 @@ pub fn exprkind(p: &mut Parser, power: u8) -> PResult { 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)?, diff --git a/compiler/cl-repl/examples/yaml.rs b/compiler/cl-repl/examples/yaml.rs index 80de6a6..ca174f0 100644 --- a/compiler/cl-repl/examples/yaml.rs +++ b/compiler/cl-repl/examples/yaml.rs @@ -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;