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

View File

@ -140,6 +140,14 @@ impl TryFrom<Expr> for Pattern {
};
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 }) => {
Pattern::Rest(Some(Pattern::try_from(*tail)?.into()))
}

View File

@ -161,11 +161,19 @@ impl Display for Function {
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());
write!(f, "fn {name} ")?;
{
let mut f = f.delimit(INLINE_PARENS);
for (idx, (arg, ty)) in bind.iter().zip(types.iter()).enumerate() {
if idx != 0 {
f.write_str(", ")?;
@ -453,6 +461,8 @@ impl Display for Pattern {
Pattern::Rest(Some(name)) => write!(f, "..{name}"),
Pattern::Rest(None) => "..".fmt(f),
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::Array(patterns) => separate(patterns, ", ")(f.delimit(INLINE_SQUARE)),
Pattern::Struct(path, items) => {

View File

@ -342,6 +342,8 @@ impl WeightOf for Pattern {
Pattern::Rest(Some(pattern)) => pattern.weight_of(),
Pattern::Rest(None) => 0,
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::Struct(path, items) => {
let sitems: usize = items

View File

@ -100,7 +100,7 @@ pub trait Fold {
Function {
name: self.fold_sym(name),
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)),
}
}
@ -184,7 +184,7 @@ pub trait Fold {
}
fn fold_ty_ref(&mut self, t: TyRef) -> TyRef {
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 {
let TyFn { args, rety } = t;
@ -246,6 +246,14 @@ pub trait Fold {
self.fold_mutability(mutability),
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.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 {
let ArrayRep { value, repeat } = a;
ArrayRep {
value: Box::new(self.fold_expr(*value)),
repeat: Box::new(self.fold_expr(*repeat)),
}
ArrayRep { value: Box::new(self.fold_expr(*value)), repeat }
}
fn fold_addrof(&mut self, a: AddrOf) -> AddrOf {
let AddrOf { mutable, expr } = a;

View File

@ -82,7 +82,7 @@ pub trait Visit<'a>: Sized {
let Function { name, sign, bind, body } = f;
self.visit_sym(name);
self.visit_ty_fn(sign);
bind.iter().for_each(|p| self.visit_pattern(p));
self.visit_pattern(bind);
if let Some(b) = body {
self.visit_expr(b)
}
@ -154,7 +154,7 @@ pub trait Visit<'a>: Sized {
fn visit_ty_ref(&mut self, t: &'a TyRef) {
let TyRef { mutable, count: _, to } = t;
self.visit_mutability(mutable);
self.visit_path(to);
self.visit_ty(to);
}
fn visit_ty_fn(&mut self, t: &'a TyFn) {
let TyFn { args, rety } = t;
@ -215,6 +215,14 @@ pub trait Visit<'a>: Sized {
self.visit_mutability(mutability);
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) => {
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))
}
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(repeat);
}
fn visit_addrof(&mut self, a: &'a AddrOf) {
let AddrOf { mutable, expr } = a;

View File

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

View File

@ -1,6 +1,6 @@
//! Collects the "Upvars" of a function at the point of its creation, allowing variable capture
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};
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) {
let Function { name: _, sign: _, bind, body } = f;
// parameters can never be upvars
bind.iter().for_each(|pat| self.visit_pattern(pat));
self.visit_pattern(bind);
if let Some(body) = body {
self.visit_expr(body);
}
@ -115,6 +115,8 @@ impl<'a> Visit<'a> for CollectUpvars<'_> {
self.visit_mutability(mutability);
self.visit_pattern(pattern);
}
Pattern::RangeExc(_, _) => {}
Pattern::RangeInc(_, _) => {}
Pattern::Tuple(patterns) => {
patterns.iter().for_each(|p| self.visit_pattern(p));
}

View File

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

View File

@ -20,6 +20,8 @@ pub fn variables(pat: &Pattern) -> Vec<&Sym> {
Pattern::Rest(Some(pattern)) => patvars(set, pattern),
Pattern::Rest(None) => {}
Pattern::Ref(_, pattern) => patvars(set, pattern),
Pattern::RangeExc(_, _) => {}
Pattern::RangeInc(_, _) => {}
Pattern::Tuple(patterns) | Pattern::Array(patterns) => {
patterns.iter().for_each(|pat| patvars(set, pat))
}
@ -127,6 +129,70 @@ pub fn append_sub<'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)) => {
match rest_binding(sub, patterns, values.into_vec().into())? {
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 {
/// Parses the [parameters](Param) associated with a Function
@ -484,7 +484,7 @@ impl Parse<'_> for FnSig {
break;
}
}
Ok((params, types))
Ok((Pattern::Tuple(params), types))
}
}
@ -783,7 +783,7 @@ impl Parse<'_> for TyRef {
}
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(),
repeat: {
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(),

View File

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

View File

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