cl-ast: Cleanup

- Function bind is now one Pattern
- TyRef now allows &Ty (i.e. &[i32], &(char, bool)
- Range patterns (they cannot bind, only check whether a value is in range
- ArrayRep repeat has been reverted to usize, for now, until early consteval is implemented.
This commit is contained in:
John 2025-04-21 04:17:45 -04:00
parent ef92d8b798
commit 7ba808594c
15 changed files with 252 additions and 134 deletions

View File

@ -129,7 +129,7 @@ pub struct Static {
pub struct Function { pub struct Function {
pub name: Sym, pub name: Sym,
pub sign: TyFn, pub sign: TyFn,
pub bind: Vec<Pattern>, pub bind: Pattern,
pub body: Option<Expr>, pub body: Option<Expr>,
} }
@ -255,7 +255,7 @@ pub struct TyTuple {
pub struct TyRef { pub struct TyRef {
pub mutable: Mutability, pub mutable: Mutability,
pub count: u16, pub count: u16,
pub to: Path, pub to: Box<Ty>,
} }
/// The args and return value for a function pointer [Ty]pe /// The args and return value for a function pointer [Ty]pe
@ -360,7 +360,7 @@ pub enum ExprKind {
While(While), While(While),
/// An [If] expression: `if` [`Expr`] [`Block`] [`Else`]? /// An [If] expression: `if` [`Expr`] [`Block`] [`Else`]?
If(If), If(If),
/// A [For] expression: `for` Pattern `in` [`Expr`] [`Block`] [`Else`]? /// A [For] expression: `for` [`Pattern`] `in` [`Expr`] [`Block`] [`Else`]?
For(For), For(For),
/// A [Break] expression: `break` [`Expr`]? /// A [Break] expression: `break` [`Expr`]?
Break(Break), Break(Break),
@ -392,6 +392,8 @@ pub enum Pattern {
Literal(Literal), Literal(Literal),
Rest(Option<Box<Pattern>>), Rest(Option<Box<Pattern>>),
Ref(Mutability, Box<Pattern>), Ref(Mutability, Box<Pattern>),
RangeExc(Box<Pattern>, Box<Pattern>),
RangeInc(Box<Pattern>, Box<Pattern>),
Tuple(Vec<Pattern>), Tuple(Vec<Pattern>),
Array(Vec<Pattern>), Array(Vec<Pattern>),
Struct(Path, Vec<(Sym, Option<Pattern>)>), Struct(Path, Vec<(Sym, Option<Pattern>)>),
@ -557,7 +559,7 @@ pub struct Array {
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ArrayRep { pub struct ArrayRep {
pub value: Box<Expr>, pub value: Box<Expr>,
pub repeat: Box<Expr>, pub repeat: usize,
} }
/// An address-of expression: `&` `mut`? [`Expr`] /// An address-of expression: `&` `mut`? [`Expr`]

View File

@ -140,6 +140,14 @@ impl TryFrom<Expr> for Pattern {
}; };
Pattern::TupleStruct(path, args) Pattern::TupleStruct(path, args)
} }
ExprKind::Binary(Binary { kind: BinaryKind::RangeExc, parts }) => {
let (head, tail) = (Pattern::try_from(parts.0)?, Pattern::try_from(parts.1)?);
Pattern::RangeExc(head.into(), tail.into())
}
ExprKind::Binary(Binary { kind: BinaryKind::RangeInc, parts }) => {
let (head, tail) = (Pattern::try_from(parts.0)?, Pattern::try_from(parts.1)?);
Pattern::RangeInc(head.into(), tail.into())
}
ExprKind::Unary(Unary { kind: UnaryKind::RangeExc, tail }) => { ExprKind::Unary(Unary { kind: UnaryKind::RangeExc, tail }) => {
Pattern::Rest(Some(Pattern::try_from(*tail)?.into())) Pattern::Rest(Some(Pattern::try_from(*tail)?.into()))
} }

View File

@ -161,11 +161,19 @@ impl Display for Function {
Default::default() Default::default()
} }
}; };
let bind = match bind {
Pattern::Tuple(patterns) => patterns.as_slice(),
_ => {
write!(f, "Invalid argument binder: {bind}")?;
Default::default()
}
};
debug_assert_eq!(bind.len(), types.len()); debug_assert_eq!(bind.len(), types.len());
write!(f, "fn {name} ")?; write!(f, "fn {name} ")?;
{ {
let mut f = f.delimit(INLINE_PARENS); let mut f = f.delimit(INLINE_PARENS);
for (idx, (arg, ty)) in bind.iter().zip(types.iter()).enumerate() { for (idx, (arg, ty)) in bind.iter().zip(types.iter()).enumerate() {
if idx != 0 { if idx != 0 {
f.write_str(", ")?; f.write_str(", ")?;
@ -453,6 +461,8 @@ impl Display for Pattern {
Pattern::Rest(Some(name)) => write!(f, "..{name}"), Pattern::Rest(Some(name)) => write!(f, "..{name}"),
Pattern::Rest(None) => "..".fmt(f), Pattern::Rest(None) => "..".fmt(f),
Pattern::Ref(mutability, pattern) => write!(f, "&{mutability}{pattern}"), Pattern::Ref(mutability, pattern) => write!(f, "&{mutability}{pattern}"),
Pattern::RangeExc(head, tail) => write!(f, "{head}..{tail}"),
Pattern::RangeInc(head, tail) => write!(f, "{head}..={tail}"),
Pattern::Tuple(patterns) => separate(patterns, ", ")(f.delimit(INLINE_PARENS)), Pattern::Tuple(patterns) => separate(patterns, ", ")(f.delimit(INLINE_PARENS)),
Pattern::Array(patterns) => separate(patterns, ", ")(f.delimit(INLINE_SQUARE)), Pattern::Array(patterns) => separate(patterns, ", ")(f.delimit(INLINE_SQUARE)),
Pattern::Struct(path, items) => { Pattern::Struct(path, items) => {

View File

@ -342,6 +342,8 @@ impl WeightOf for Pattern {
Pattern::Rest(Some(pattern)) => pattern.weight_of(), Pattern::Rest(Some(pattern)) => pattern.weight_of(),
Pattern::Rest(None) => 0, Pattern::Rest(None) => 0,
Pattern::Ref(mutability, pattern) => mutability.weight_of() + pattern.weight_of(), Pattern::Ref(mutability, pattern) => mutability.weight_of() + pattern.weight_of(),
Pattern::RangeExc(head, tail) => head.weight_of() + tail.weight_of(),
Pattern::RangeInc(head, tail) => head.weight_of() + tail.weight_of(),
Pattern::Tuple(patterns) | Pattern::Array(patterns) => patterns.weight_of(), Pattern::Tuple(patterns) | Pattern::Array(patterns) => patterns.weight_of(),
Pattern::Struct(path, items) => { Pattern::Struct(path, items) => {
let sitems: usize = items let sitems: usize = items

View File

@ -100,7 +100,7 @@ pub trait Fold {
Function { Function {
name: self.fold_sym(name), name: self.fold_sym(name),
sign: self.fold_ty_fn(sign), sign: self.fold_ty_fn(sign),
bind: bind.into_iter().map(|p| self.fold_pattern(p)).collect(), bind: self.fold_pattern(bind),
body: body.map(|b| self.fold_expr(b)), body: body.map(|b| self.fold_expr(b)),
} }
} }
@ -184,7 +184,7 @@ pub trait Fold {
} }
fn fold_ty_ref(&mut self, t: TyRef) -> TyRef { fn fold_ty_ref(&mut self, t: TyRef) -> TyRef {
let TyRef { mutable, count, to } = t; let TyRef { mutable, count, to } = t;
TyRef { mutable: self.fold_mutability(mutable), count, to: self.fold_path(to) } TyRef { mutable: self.fold_mutability(mutable), count, to: Box::new(self.fold_ty(*to)) }
} }
fn fold_ty_fn(&mut self, t: TyFn) -> TyFn { fn fold_ty_fn(&mut self, t: TyFn) -> TyFn {
let TyFn { args, rety } = t; let TyFn { args, rety } = t;
@ -246,6 +246,14 @@ pub trait Fold {
self.fold_mutability(mutability), self.fold_mutability(mutability),
Box::new(self.fold_pattern(*pattern)), Box::new(self.fold_pattern(*pattern)),
), ),
Pattern::RangeExc(head, tail) => Pattern::RangeInc(
Box::new(self.fold_pattern(*head)),
Box::new(self.fold_pattern(*tail)),
),
Pattern::RangeInc(head, tail) => Pattern::RangeInc(
Box::new(self.fold_pattern(*head)),
Box::new(self.fold_pattern(*tail)),
),
Pattern::Tuple(patterns) => { Pattern::Tuple(patterns) => {
Pattern::Tuple(patterns.into_iter().map(|p| self.fold_pattern(p)).collect()) Pattern::Tuple(patterns.into_iter().map(|p| self.fold_pattern(p)).collect())
} }
@ -356,10 +364,7 @@ pub trait Fold {
} }
fn fold_array_rep(&mut self, a: ArrayRep) -> ArrayRep { fn fold_array_rep(&mut self, a: ArrayRep) -> ArrayRep {
let ArrayRep { value, repeat } = a; let ArrayRep { value, repeat } = a;
ArrayRep { ArrayRep { value: Box::new(self.fold_expr(*value)), repeat }
value: Box::new(self.fold_expr(*value)),
repeat: Box::new(self.fold_expr(*repeat)),
}
} }
fn fold_addrof(&mut self, a: AddrOf) -> AddrOf { fn fold_addrof(&mut self, a: AddrOf) -> AddrOf {
let AddrOf { mutable, expr } = a; let AddrOf { mutable, expr } = a;

View File

@ -82,7 +82,7 @@ pub trait Visit<'a>: Sized {
let Function { name, sign, bind, body } = f; let Function { name, sign, bind, body } = f;
self.visit_sym(name); self.visit_sym(name);
self.visit_ty_fn(sign); self.visit_ty_fn(sign);
bind.iter().for_each(|p| self.visit_pattern(p)); self.visit_pattern(bind);
if let Some(b) = body { if let Some(b) = body {
self.visit_expr(b) self.visit_expr(b)
} }
@ -154,7 +154,7 @@ pub trait Visit<'a>: Sized {
fn visit_ty_ref(&mut self, t: &'a TyRef) { fn visit_ty_ref(&mut self, t: &'a TyRef) {
let TyRef { mutable, count: _, to } = t; let TyRef { mutable, count: _, to } = t;
self.visit_mutability(mutable); self.visit_mutability(mutable);
self.visit_path(to); self.visit_ty(to);
} }
fn visit_ty_fn(&mut self, t: &'a TyFn) { fn visit_ty_fn(&mut self, t: &'a TyFn) {
let TyFn { args, rety } = t; let TyFn { args, rety } = t;
@ -215,6 +215,14 @@ pub trait Visit<'a>: Sized {
self.visit_mutability(mutability); self.visit_mutability(mutability);
self.visit_pattern(pattern); self.visit_pattern(pattern);
} }
Pattern::RangeExc(head, tail) => {
self.visit_pattern(head);
self.visit_pattern(tail);
}
Pattern::RangeInc(head, tail) => {
self.visit_pattern(head);
self.visit_pattern(tail);
}
Pattern::Tuple(patterns) => { Pattern::Tuple(patterns) => {
patterns.iter().for_each(|p| self.visit_pattern(p)); patterns.iter().for_each(|p| self.visit_pattern(p));
} }
@ -311,9 +319,8 @@ pub trait Visit<'a>: Sized {
values.iter().for_each(|e| self.visit_expr(e)) values.iter().for_each(|e| self.visit_expr(e))
} }
fn visit_array_rep(&mut self, a: &'a ArrayRep) { fn visit_array_rep(&mut self, a: &'a ArrayRep) {
let ArrayRep { value, repeat } = a; let ArrayRep { value, repeat: _ } = a;
self.visit_expr(value); self.visit_expr(value);
self.visit_expr(repeat);
} }
fn visit_addrof(&mut self, a: &'a AddrOf) { fn visit_addrof(&mut self, a: &'a AddrOf) {
let AddrOf { mutable, expr } = a; let AddrOf { mutable, expr } = a;

View File

@ -57,9 +57,6 @@ impl Callable for Function {
let FnDecl { name, bind, body, sign: _ } = &*self.decl; let FnDecl { name, bind, body, sign: _ } = &*self.decl;
// Check arg mapping // Check arg mapping
if args.len() != bind.len() {
return Err(Error::ArgNumber(bind.len(), args.len()));
}
if self.is_constructor { if self.is_constructor {
return Ok(ConValue::TupleStruct(Box::new(( return Ok(ConValue::TupleStruct(Box::new((
name.to_ref(), name.to_ref(),
@ -73,14 +70,10 @@ impl Callable for Function {
let upvars = self.upvars.take(); let upvars = self.upvars.take();
env.push_frame("upvars", upvars); env.push_frame("upvars", upvars);
eprintln!("{name}{args:?}");
// TODO: completely refactor data storage // TODO: completely refactor data storage
let mut frame = env.frame("fn args"); let mut frame = env.frame("fn args");
for (bind, value) in bind.iter().zip(args) { for (name, value) in pattern::substitution(bind, ConValue::Tuple(args.into()))? {
for (name, value) in pattern::substitution(bind, value.clone())? { frame.insert(*name, Some(value));
frame.insert(*name, Some(value));
}
} }
let res = body.interpret(&mut frame); let res = body.interpret(&mut frame);
drop(frame); drop(frame);

View File

@ -1,6 +1,6 @@
//! Collects the "Upvars" of a function at the point of its creation, allowing variable capture //! Collects the "Upvars" of a function at the point of its creation, allowing variable capture
use crate::{convalue::ConValue, env::Environment}; use crate::{convalue::ConValue, env::Environment};
use cl_ast::{ast_visitor::visit::*, Function, Let, Path, PathPart, Pattern, Sym}; use cl_ast::{Function, Let, Path, PathPart, Pattern, Sym, ast_visitor::visit::*};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
pub fn collect_upvars(f: &Function, env: &Environment) -> super::Upvars { pub fn collect_upvars(f: &Function, env: &Environment) -> super::Upvars {
@ -67,7 +67,7 @@ impl<'a> Visit<'a> for CollectUpvars<'_> {
fn visit_function(&mut self, f: &'a cl_ast::Function) { fn visit_function(&mut self, f: &'a cl_ast::Function) {
let Function { name: _, sign: _, bind, body } = f; let Function { name: _, sign: _, bind, body } = f;
// parameters can never be upvars // parameters can never be upvars
bind.iter().for_each(|pat| self.visit_pattern(pat)); self.visit_pattern(bind);
if let Some(body) = body { if let Some(body) = body {
self.visit_expr(body); self.visit_expr(body);
} }
@ -115,6 +115,8 @@ impl<'a> Visit<'a> for CollectUpvars<'_> {
self.visit_mutability(mutability); self.visit_mutability(mutability);
self.visit_pattern(pattern); self.visit_pattern(pattern);
} }
Pattern::RangeExc(_, _) => {}
Pattern::RangeInc(_, _) => {}
Pattern::Tuple(patterns) => { Pattern::Tuple(patterns) => {
patterns.iter().for_each(|p| self.visit_pattern(p)); patterns.iter().for_each(|p| self.visit_pattern(p));
} }

View File

@ -134,11 +134,12 @@ impl Interpret for Struct {
.into(), .into(),
), ),
}, },
bind: args bind: Pattern::Tuple(
.iter() args.iter()
.enumerate() .enumerate()
.map(|(idx, _)| Pattern::Name(idx.to_string().into())) .map(|(idx, _)| Pattern::Name(idx.to_string().into()))
.collect(), .collect(),
),
body: None, body: None,
}; };
let constructor = crate::function::Function::new_constructor(constructor); let constructor = crate::function::Function::new_constructor(constructor);
@ -814,12 +815,8 @@ impl Interpret for Array {
impl Interpret for ArrayRep { impl Interpret for ArrayRep {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> { fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
let Self { value, repeat } = self; let Self { value, repeat } = self;
let repeat = match repeat.interpret(env)? {
ConValue::Int(v) => v,
_ => Err(Error::TypeError())?,
};
let value = value.interpret(env)?; let value = value.interpret(env)?;
Ok(ConValue::Array(vec![value; repeat as usize].into())) Ok(ConValue::Array(vec![value; *repeat].into()))
} }
} }
impl Interpret for AddrOf { impl Interpret for AddrOf {

View File

@ -20,6 +20,8 @@ pub fn variables(pat: &Pattern) -> Vec<&Sym> {
Pattern::Rest(Some(pattern)) => patvars(set, pattern), Pattern::Rest(Some(pattern)) => patvars(set, pattern),
Pattern::Rest(None) => {} Pattern::Rest(None) => {}
Pattern::Ref(_, pattern) => patvars(set, pattern), Pattern::Ref(_, pattern) => patvars(set, pattern),
Pattern::RangeExc(_, _) => {}
Pattern::RangeInc(_, _) => {}
Pattern::Tuple(patterns) | Pattern::Array(patterns) => { Pattern::Tuple(patterns) | Pattern::Array(patterns) => {
patterns.iter().for_each(|pat| patvars(set, pat)) patterns.iter().for_each(|pat| patvars(set, pat))
} }
@ -127,6 +129,70 @@ pub fn append_sub<'pat>(
todo!("Dereference <{r}> in pattern matching {pat}") todo!("Dereference <{r}> in pattern matching {pat}")
} }
(Pattern::RangeExc(head, tail), value) => match (head.as_ref(), tail.as_ref(), value) {
(
Pattern::Literal(Literal::Int(a)),
Pattern::Literal(Literal::Int(c)),
ConValue::Int(b),
) => (*a as isize <= b as _ && b < *c as isize)
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::Char(a)),
Pattern::Literal(Literal::Char(c)),
ConValue::Char(b),
) => (*a <= b && b < *c)
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::Float(a)),
Pattern::Literal(Literal::Float(c)),
ConValue::Float(b),
) => (f64::from_bits(*a) <= b && b < f64::from_bits(*c))
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::String(a)),
Pattern::Literal(Literal::String(c)),
ConValue::String(b),
) => (a.as_str() <= b.to_ref() && b.to_ref() < c.as_str())
.then_some(())
.ok_or(Error::NotAssignable()),
_ => Err(Error::NotAssignable()),
},
(Pattern::RangeInc(head, tail), value) => match (head.as_ref(), tail.as_ref(), value) {
(
Pattern::Literal(Literal::Int(a)),
Pattern::Literal(Literal::Int(c)),
ConValue::Int(b),
) => (*a as isize <= b && b <= *c as isize)
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::Char(a)),
Pattern::Literal(Literal::Char(c)),
ConValue::Char(b),
) => (*a <= b && b <= *c)
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::Float(a)),
Pattern::Literal(Literal::Float(c)),
ConValue::Float(b),
) => (f64::from_bits(*a) <= b && b <= f64::from_bits(*c))
.then_some(())
.ok_or(Error::NotAssignable()),
(
Pattern::Literal(Literal::String(a)),
Pattern::Literal(Literal::String(c)),
ConValue::String(b),
) => (a.as_str() <= b.to_ref() && b.to_ref() <= c.as_str())
.then_some(())
.ok_or(Error::NotAssignable()),
_ => Err(Error::NotAssignable()),
},
(Pattern::Array(patterns), ConValue::Array(values)) => { (Pattern::Array(patterns), ConValue::Array(values)) => {
match rest_binding(sub, patterns, values.into_vec().into())? { match rest_binding(sub, patterns, values.into_vec().into())? {
Some((pattern, values)) => { Some((pattern, values)) => {

View File

@ -469,7 +469,7 @@ impl Parse<'_> for Function {
} }
} }
type FnSig = (Vec<Pattern>, Vec<TyKind>); type FnSig = (Pattern, Vec<TyKind>);
impl Parse<'_> for FnSig { impl Parse<'_> for FnSig {
/// Parses the [parameters](Param) associated with a Function /// Parses the [parameters](Param) associated with a Function
@ -484,7 +484,7 @@ impl Parse<'_> for FnSig {
break; break;
} }
} }
Ok((params, types)) Ok((Pattern::Tuple(params), types))
} }
} }
@ -783,7 +783,7 @@ impl Parse<'_> for TyRef {
} }
p.consume_peeked(); p.consume_peeked();
} }
Ok(TyRef { count, mutable: Mutability::parse(p)?, to: Path::parse(p)? }) Ok(TyRef { count, mutable: Mutability::parse(p)?, to: Box::new(Ty::parse(p)?) })
} }
} }

View File

@ -203,7 +203,13 @@ fn exprkind_array_rep(p: &mut Parser) -> PResult<ExprKind> {
value: first.into(), value: first.into(),
repeat: { repeat: {
p.consume_peeked(); p.consume_peeked();
Box::new(expr(p, 0)?) let value = p.match_type(TokenKind::Literal, Parsing::ArrayRep)?;
match value.data() {
TokenData::Integer(size) => *size as usize,
_ => {
Err(p.error(ErrorKind::Unexpected(TokenKind::Literal), Parsing::ArrayRep))?
}
}
}, },
} }
.into(), .into(),

View File

@ -54,13 +54,13 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(()) Ok(())
} }
pub use yamler::CLangifier; pub use clangifier::CLangifier;
pub mod yamler { pub mod clangifier {
use crate::yamlify::CLangify; use crate::clangify::CLangify;
use std::{ use std::{
fmt::Display, fmt::Display,
io::Write, io::Write,
ops::{Deref, DerefMut}, ops::{Add, Deref, DerefMut},
}; };
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct CLangifier { pub struct CLangifier {
@ -104,12 +104,20 @@ pub mod yamler {
} }
/// Prints a section header and increases indentation /// Prints a section header and increases indentation
pub fn key(&mut self, name: impl Display) -> Section { pub fn nest(&mut self, name: impl Display) -> Section {
print!("{name}"); print!("{name}");
self.indent() self.indent()
} }
} }
impl<C: CLangify + ?Sized> Add<&C> for &mut CLangifier {
type Output = Self;
fn add(self, rhs: &C) -> Self::Output {
self.p(rhs)
}
}
/// Tracks the start and end of an indented block (a "section") /// Tracks the start and end of an indented block (a "section")
pub struct Section<'y> { pub struct Section<'y> {
yamler: &'y mut CLangifier, yamler: &'y mut CLangifier,
@ -142,10 +150,11 @@ pub mod yamler {
} }
} }
pub mod yamlify { pub mod clangify {
use core::panic;
use std::iter; use std::iter;
use super::yamler::CLangifier; use super::clangifier::CLangifier;
use cl_ast::*; use cl_ast::*;
pub trait CLangify { pub trait CLangify {
@ -153,11 +162,17 @@ pub mod yamlify {
} }
impl CLangify for File { impl CLangify for File {
fn print(&self, y: &mut CLangifier) { fn print(&self, mut y: &mut CLangifier) {
let File { name, items } = self; let File { name, items } = self;
// TODO: turn name into include guard // TODO: turn name into include guard
y.p("// Generated from ").p(name).endl(); y = (y + "// Generated from " + name).endl();
y.p(items); for (idx, item) in items.iter().enumerate() {
if idx > 0 {
y.endl().endl();
}
y.p(item);
}
y.endl();
} }
} }
impl CLangify for Visibility { impl CLangify for Visibility {
@ -174,14 +189,14 @@ pub mod yamlify {
impl CLangify for Attrs { impl CLangify for Attrs {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { meta } = self; let Self { meta } = self;
y.key("Attrs").p(meta); y.nest("Attrs").p(meta);
todo!("Attributes"); todo!("Attributes");
} }
} }
impl CLangify for Meta { impl CLangify for Meta {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { name, kind } = self; let Self { name, kind } = self;
y.key("Meta").p(name).p(kind); y.nest("Meta").p(name).p(kind);
todo!("Attributes"); todo!("Attributes");
} }
} }
@ -199,7 +214,7 @@ pub mod yamlify {
impl CLangify for Item { impl CLangify for Item {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { span: _, attrs: _, vis, kind } = self; let Self { span: _, attrs: _, vis, kind } = self;
y.p(vis).p(kind).endl().endl(); y.p(vis).p(kind);
} }
} }
impl CLangify for ItemKind { impl CLangify for ItemKind {
@ -241,7 +256,7 @@ pub mod yamlify {
impl CLangify for Module { impl CLangify for Module {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { name, file } = self; let Self { name, file } = self;
y.key("// mod ").p(name).p(" {").endl(); y.nest("// mod ").p(name).p(" {").endl();
y.p(file); y.p(file);
y.endl().p("// } mod ").p(name); y.endl().p("// } mod ").p(name);
} }
@ -255,13 +270,17 @@ pub mod yamlify {
TyKind::Empty => &[], TyKind::Empty => &[],
_ => panic!("Unsupported function args: {args}"), _ => panic!("Unsupported function args: {args}"),
}; };
let bind = match bind {
Pattern::Tuple(tup) => tup.as_slice(),
_ => panic!("Unsupported function binders: {args}"),
};
match rety { match rety {
Some(ty) => y.p(ty), Some(ty) => y.p(ty),
None => y.p("void"), None => y.p("void"),
} }
.p(" ") .p(" ")
.p(name) .p(name)
.p("("); .p(" (");
for (idx, (bind, ty)) in bind.iter().zip(types).enumerate() { for (idx, (bind, ty)) in bind.iter().zip(types).enumerate() {
if idx > 0 { if idx > 0 {
y.p(", "); y.p(", ");
@ -269,13 +288,13 @@ pub mod yamlify {
// y.print("/* TODO: desugar pat match args */"); // y.print("/* TODO: desugar pat match args */");
y.p(ty).p(" ").p(bind); y.p(ty).p(" ").p(bind);
} }
y.p(")").p(body); y.p(") ").p(body);
} }
} }
impl CLangify for Struct { impl CLangify for Struct {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { name, kind } = self; let Self { name, kind } = self;
y.p("struct ").p(name).key(" {").p(kind); y.p("struct ").p(name).nest(" {").p(kind);
y.endl().p("}"); y.endl().p("}");
} }
} }
@ -302,7 +321,7 @@ pub mod yamlify {
impl CLangify for Enum { impl CLangify for Enum {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { name, variants } = self; let Self { name, variants } = self;
y.key("enum ").p(name).p(" {").endl(); y.nest("enum ").p(name).p(" {").endl();
match variants { match variants {
Some(v) => { Some(v) => {
for (idx, variant) in v.iter().enumerate() { for (idx, variant) in v.iter().enumerate() {
@ -336,7 +355,7 @@ pub mod yamlify {
impl CLangify for Impl { impl CLangify for Impl {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { target, body } = self; let Self { target, body } = self;
y.key("/* TODO: impl ").p(target).p(" { */ "); y.nest("/* TODO: impl ").p(target).p(" { */ ");
y.p(body); y.p(body);
y.p("/* } // impl ").p(target).p(" */ "); y.p("/* } // impl ").p(target).p(" */ ");
} }
@ -372,7 +391,7 @@ pub mod yamlify {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { stmts } = self; let Self { stmts } = self;
{ {
let mut y = y.key("{"); let mut y = y.nest("{");
y.endl(); y.endl();
if let [ if let [
stmts @ .., stmts @ ..,
@ -442,14 +461,14 @@ pub mod yamlify {
ExprKind::Break(k) => k.print(y), ExprKind::Break(k) => k.print(y),
ExprKind::Return(k) => k.print(y), ExprKind::Return(k) => k.print(y),
ExprKind::Continue => { ExprKind::Continue => {
y.key("continue"); y.nest("continue");
} }
} }
} }
} }
impl CLangify for Quote { impl CLangify for Quote {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
y.key("\""); y.nest("\"");
print!("{self}"); print!("{self}");
y.p("\""); y.p("\"");
} }
@ -463,7 +482,7 @@ pub mod yamlify {
y.p(ty).p(" ").p(mutable).p(name).p("[").p(count).p("]"); y.p(ty).p(" ").p(mutable).p(name).p("[").p(count).p("]");
} }
TyKind::Fn(TyFn { args, rety }) => { TyKind::Fn(TyFn { args, rety }) => {
y.key("(").p(rety).p(" *").p(mutable).p(name).p(")("); y.nest("(").p(rety).p(" *").p(mutable).p(name).p(")(");
match args.as_ref() { match args.as_ref() {
TyKind::Empty => {} TyKind::Empty => {}
TyKind::Tuple(TyTuple { types }) => { TyKind::Tuple(TyTuple { types }) => {
@ -498,11 +517,13 @@ pub mod yamlify {
Pattern::Literal(literal) => y.p(literal), Pattern::Literal(literal) => y.p(literal),
Pattern::Rest(name) => y.p("..").p(name), Pattern::Rest(name) => y.p("..").p(name),
Pattern::Ref(mutability, pattern) => y.p("&").p(mutability).p(pattern), Pattern::Ref(mutability, pattern) => y.p("&").p(mutability).p(pattern),
Pattern::Tuple(patterns) => y.key("Tuple").p(patterns), Pattern::RangeExc(head, tail) => y.p("RangeExc").p(head).p(tail),
Pattern::Array(patterns) => y.key("Array").p(patterns), Pattern::RangeInc(head, tail) => y.p("RangeExc").p(head).p(tail),
Pattern::Tuple(patterns) => y.nest("Tuple").p(patterns),
Pattern::Array(patterns) => y.nest("Array").p(patterns),
Pattern::Struct(path, items) => { Pattern::Struct(path, items) => {
{ {
let mut y = y.key("Struct"); let mut y = y.nest("Struct");
y.p(path); y.p(path);
for (name, item) in items { for (name, item) in items {
y.p(name).p(item); y.p(name).p(item);
@ -512,7 +533,7 @@ pub mod yamlify {
} }
Pattern::TupleStruct(path, items) => { Pattern::TupleStruct(path, items) => {
{ {
let mut y = y.key("TupleStruct"); let mut y = y.nest("TupleStruct");
y.p(path).p(items); y.p(path).p(items);
} }
y y
@ -524,7 +545,7 @@ pub mod yamlify {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { scrutinee, arms } = self; let Self { scrutinee, arms } = self;
y.p("/* match ").p(scrutinee); y.p("/* match ").p(scrutinee);
y.key(" { ").p(arms); y.nest(" { ").p(arms);
y.p(" } */"); y.p(" } */");
} }
} }
@ -575,7 +596,7 @@ pub mod yamlify {
UnaryKind::Not => y.p("!").p(tail), UnaryKind::Not => y.p("!").p(tail),
UnaryKind::RangeInc => todo!("Unary RangeInc in C"), UnaryKind::RangeInc => todo!("Unary RangeInc in C"),
UnaryKind::RangeExc => todo!("Unary RangeExc in C"), UnaryKind::RangeExc => todo!("Unary RangeExc in C"),
UnaryKind::Loop => y.key("while (1) { ").p(tail).p(" }"), UnaryKind::Loop => y.nest("while (1) { ").p(tail).p(" }"),
UnaryKind::At => todo!(), UnaryKind::At => todo!(),
UnaryKind::Tilde => todo!(), UnaryKind::Tilde => todo!(),
}; };
@ -584,7 +605,7 @@ pub mod yamlify {
impl CLangify for Cast { impl CLangify for Cast {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { head, ty } = self; let Self { head, ty } = self;
y.key("(").p(ty).p(")"); y.nest("(").p(ty).p(")");
y.p(head); y.p(head);
} }
} }
@ -611,7 +632,7 @@ pub mod yamlify {
impl CLangify for Tuple { impl CLangify for Tuple {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { exprs } = self; let Self { exprs } = self;
let mut y = y.key("( "); let mut y = y.nest("( ");
for (idx, expr) in exprs.iter().enumerate() { for (idx, expr) in exprs.iter().enumerate() {
if idx > 0 { if idx > 0 {
y.p(", "); y.p(", ");
@ -633,9 +654,9 @@ pub mod yamlify {
impl CLangify for Structor { impl CLangify for Structor {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { to, init } = self; let Self { to, init } = self;
y.key("(").p(to).p(")"); y.nest("(").p(to).p(")");
{ {
let mut y = y.key("{ "); let mut y = y.nest("{ ");
for (idx, field) in init.iter().enumerate() { for (idx, field) in init.iter().enumerate() {
if idx > 0 { if idx > 0 {
y.p(", "); y.p(", ");
@ -657,7 +678,7 @@ pub mod yamlify {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { values } = self; let Self { values } = self;
{ {
let mut y = y.key("{"); let mut y = y.nest("{");
y.endl(); y.endl();
for (idx, value) in values.iter().enumerate() { for (idx, value) in values.iter().enumerate() {
if idx > 0 { if idx > 0 {
@ -672,14 +693,10 @@ pub mod yamlify {
impl CLangify for ArrayRep { impl CLangify for ArrayRep {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { value, repeat } = self; let Self { value, repeat } = self;
// TODO: compile time evaluation
let ExprKind::Literal(Literal::Int(count)) = &repeat.kind else {
panic!("Unsupported repeat count: {repeat}");
};
{ {
let mut y = y.key("{"); let mut y = y.nest("{");
y.endl(); y.endl();
for idx in 0..*count { for idx in 0..*repeat {
if idx > 0 { if idx > 0 {
y.p(", "); y.p(", ");
} }
@ -707,24 +724,35 @@ pub mod yamlify {
// declared on every line lmao. This will require type info. // declared on every line lmao. This will require type info.
let Self { cond, pass, fail } = self; let Self { cond, pass, fail } = self;
let Else { body: fail } = fail; let Else { body: fail } = fail;
y.key("while(1) { if (").p(cond).p(")").p(pass); y.nest("while(1) {")
if let Some(fail) = fail { .endl()
y.p("else { ").p(fail).p("; break; }"); .p("if (")
.p(cond)
.p(") ")
.p(pass);
{
let mut y = y.nest(" else {");
y.endl();
if let Some(fail) = fail {
y.p(fail).p(";").endl();
}
y.p("break;");
} }
y.endl().p("}");
} }
} }
impl CLangify for Else { impl CLangify for Else {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { body } = self; let Self { body } = self;
if let Some(body) = body { if let Some(body) = body {
y.key("else ").p(body); y.p(" else ").p(body);
} }
} }
} }
impl CLangify for If { impl CLangify for If {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { cond, pass, fail } = self; let Self { cond, pass, fail } = self;
y.p("(").p(cond).p(")"); y.p("if (").p(cond).p(")");
y.p(pass).p(fail); y.p(pass).p(fail);
} }
} }
@ -747,13 +775,13 @@ pub mod yamlify {
impl CLangify for Break { impl CLangify for Break {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { body } = self; let Self { body } = self;
y.key("break ").p(body); y.nest("break ").p(body);
} }
} }
impl CLangify for Return { impl CLangify for Return {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { body } = self; let Self { body } = self;
y.key("return ").p(body); y.nest("return ").p(body);
} }
} }
impl CLangify for Literal { impl CLangify for Literal {
@ -830,7 +858,7 @@ pub mod yamlify {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { types } = self; let Self { types } = self;
{ {
let mut y = y.key("struct {"); let mut y = y.nest("struct {");
y.endl(); y.endl();
for (idx, ty) in types.iter().enumerate() { for (idx, ty) in types.iter().enumerate() {
if idx > 0 { if idx > 0 {
@ -855,7 +883,7 @@ pub mod yamlify {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { args, rety } = self; let Self { args, rety } = self;
// TODO: function pointer syntax // TODO: function pointer syntax
y.key("*(").p(rety).p(")("); y.nest("(").p(rety).p(" *)(");
match args.as_ref() { match args.as_ref() {
TyKind::Empty => y, TyKind::Empty => y,
TyKind::Tuple(TyTuple { types }) => { TyKind::Tuple(TyTuple { types }) => {

View File

@ -41,7 +41,6 @@ pub use yamler::Yamler;
pub mod yamler { pub mod yamler {
use crate::yamlify::Yamlify; use crate::yamlify::Yamlify;
use std::{ use std::{
fmt::Display,
io::Write, io::Write,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
}; };
@ -81,22 +80,25 @@ pub mod yamler {
} }
/// Prints a section header and increases indentation /// Prints a section header and increases indentation
pub fn key(&mut self, name: impl Display) -> Section { pub fn key(&mut self, name: impl Yamlify) -> Section {
println!(); println!();
self.print_indentation(&mut std::io::stdout().lock()); self.print_indentation(&mut std::io::stdout().lock());
print!("- {name}:"); print!("- ");
name.yaml(self);
print!(":");
self.indent() self.indent()
} }
/// Prints a yaml key value pair: `- name: "value"` /// Prints a yaml key value pair: `- name: "value"`
pub fn pair<D: Display, T: Yamlify>(&mut self, name: D, value: T) -> &mut Self { pub fn pair<D: Yamlify, T: Yamlify>(&mut self, name: D, value: T) -> &mut Self {
self.key(name).yaml(&value); self.key(name).value(value);
self self
} }
/// Prints a yaml scalar value: `"name"`` /// Prints a yaml scalar value: `"name"``
pub fn value<D: Display>(&mut self, value: D) -> &mut Self { pub fn value<D: Yamlify>(&mut self, value: D) -> &mut Self {
print!(" {value}"); print!(" ");
value.yaml(self);
self self
} }
@ -334,7 +336,7 @@ pub mod yamlify {
impl Yamlify for Stmt { impl Yamlify for Stmt {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { span: _, kind, semi } = self; let Self { span: _, kind, semi } = self;
y.key("Stmt").yaml(kind).yaml(semi); y.key("Stmt").value(kind).yaml(semi);
} }
} }
impl Yamlify for Semi { impl Yamlify for Semi {
@ -415,11 +417,17 @@ pub mod yamlify {
Pattern::Name(name) => y.value(name), Pattern::Name(name) => y.value(name),
Pattern::Literal(literal) => y.value(literal), Pattern::Literal(literal) => y.value(literal),
Pattern::Rest(name) => y.pair("Rest", name), Pattern::Rest(name) => y.pair("Rest", name),
Pattern::Ref(mutability, pattern) => { Pattern::Ref(mutability, pattern) => y.yaml(mutability).pair("Pat", pattern),
y.pair("mutability", mutability).pair("subpattern", pattern) Pattern::RangeInc(head, tail) => {
y.key("RangeInc").pair("head", head).pair("tail", tail);
y
} }
Pattern::Tuple(patterns) => y.key("Tuple").yaml(patterns), Pattern::RangeExc(head, tail) => {
Pattern::Array(patterns) => y.key("Array").yaml(patterns), y.key("RangeExc").pair("head", head).pair("tail", tail);
y
}
Pattern::Tuple(patterns) => y.key("Tuple").list(patterns),
Pattern::Array(patterns) => y.key("Array").list(patterns),
Pattern::Struct(path, items) => { Pattern::Struct(path, items) => {
{ {
let mut y = y.key("Struct"); let mut y = y.key("Struct");
@ -431,10 +439,7 @@ pub mod yamlify {
y y
} }
Pattern::TupleStruct(path, items) => { Pattern::TupleStruct(path, items) => {
{ y.key("TupleStruct").yaml(path).list(items);
let mut y = y.key("TupleStruct");
y.yaml(path).list(items);
}
y y
} }
}; };
@ -472,11 +477,6 @@ pub mod yamlify {
.pair("tail", &parts.1); .pair("tail", &parts.1);
} }
} }
impl Yamlify for ModifyKind {
fn yaml(&self, y: &mut Yamler) {
y.value(self);
}
}
impl Yamlify for Binary { impl Yamlify for Binary {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { kind, parts } = self; let Self { kind, parts } = self;
@ -486,22 +486,12 @@ pub mod yamlify {
.pair("tail", &parts.1); .pair("tail", &parts.1);
} }
} }
impl Yamlify for BinaryKind {
fn yaml(&self, y: &mut Yamler) {
y.value(self);
}
}
impl Yamlify for Unary { impl Yamlify for Unary {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { kind, tail } = self; let Self { kind, tail } = self;
y.key("Unary").pair("kind", kind).pair("tail", tail); y.key("Unary").pair("kind", kind).pair("tail", tail);
} }
} }
impl Yamlify for UnaryKind {
fn yaml(&self, y: &mut Yamler) {
y.value(self);
}
}
impl Yamlify for Cast { impl Yamlify for Cast {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { head, ty } = self; let Self { head, ty } = self;
@ -617,13 +607,14 @@ pub mod yamlify {
} }
} }
impl Yamlify for Literal { impl Yamlify for Literal {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, _y: &mut Yamler) {
y.value(format_args!("\"{self}\"")); match self {
} Literal::Bool(v) => print!("{v}"),
} Literal::Char(v) => print!("'{}'", v.escape_debug()),
impl Yamlify for Sym { Literal::Int(v) => print!("{v}"),
fn yaml(&self, y: &mut Yamler) { Literal::Float(v) => print!("{v}"),
y.value(self); Literal::String(v) => print!("{}", v.escape_debug()),
}
} }
} }
impl Yamlify for Ty { impl Yamlify for Ty {
@ -740,14 +731,15 @@ pub mod yamlify {
macro_rules! scalar { macro_rules! scalar {
($($t:ty),*$(,)?) => { ($($t:ty),*$(,)?) => {
$(impl Yamlify for $t { $(impl Yamlify for $t {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, _y: &mut Yamler) {
y.value(self); print!("{self}");
} }
})* })*
}; };
} }
scalar! { scalar! {
bool, char, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, &str, String bool, char, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, &str, String,
BinaryKind, UnaryKind, ModifyKind, Sym,
} }
} }

View File

@ -5,14 +5,14 @@ struct Student {
age: i32, age: i32,
} }
fn Student (name: str, age: i32) -> Student { fn Student(name: str, age: i32) -> Student {
Student: { name, age } Student { name, age }
} }
fn match_test(student: Student) { fn match_test(student: Student) {
match student { match student {
Student: { name: "shark", age } => println("Found a shark of ", age, " year(s)"), Student { name: "shark", age } => println("Found a shark of ", age, " year(s)"),
Student: { name, age: 22 } => println("Found a 22-year-old named ", name), Student { name, age: 22 } => println("Found a 22-year-old named ", name),
Student: { name, age } => println("Found someone named ", name, " of ", age, " year(s)"), Student { name, age } => println("Found someone named ", name, " of ", age, " year(s)"),
} }
} }