conlang: Move all cl-libs into the compiler directory
This commit is contained in:
69
compiler/cl-repl/examples/identify_tokens.rs
Normal file
69
compiler/cl-repl/examples/identify_tokens.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
//! This example grabs input from stdin, lexes it, and prints which lexer rules matched
|
||||
#![allow(unused_imports)]
|
||||
use cl_lexer::Lexer;
|
||||
use cl_token::Token;
|
||||
use std::{
|
||||
error::Error,
|
||||
io::{stdin, IsTerminal, Read},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let conf = Config::new();
|
||||
if conf.paths.is_empty() {
|
||||
take_stdin()?;
|
||||
} else {
|
||||
for path in conf.paths.iter().map(PathBuf::as_path) {
|
||||
lex_tokens(&std::fs::read_to_string(path)?, Some(path))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct Config {
|
||||
paths: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
fn new() -> Self {
|
||||
Config { paths: std::env::args().skip(1).map(PathBuf::from).collect() }
|
||||
}
|
||||
}
|
||||
|
||||
fn take_stdin() -> Result<(), Box<dyn Error>> {
|
||||
if stdin().is_terminal() {
|
||||
for line in stdin().lines() {
|
||||
lex_tokens(&line?, None)?
|
||||
}
|
||||
} else {
|
||||
lex_tokens(&std::io::read_to_string(stdin())?, None)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn lex_tokens(file: &str, path: Option<&Path>) -> Result<(), Box<dyn Error>> {
|
||||
for token in Lexer::new(file) {
|
||||
let token = match token {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
println!("{e:?}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if let Some(path) = path {
|
||||
print!("{path:?}:")
|
||||
}
|
||||
print_token(token);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_token(t: Token) {
|
||||
println!(
|
||||
"{:02}:{:02}: {:#19} │{}│",
|
||||
t.line(),
|
||||
t.col(),
|
||||
t.ty(),
|
||||
t.data(),
|
||||
)
|
||||
}
|
||||
179
compiler/cl-repl/examples/typeck.rs
Normal file
179
compiler/cl-repl/examples/typeck.rs
Normal file
@@ -0,0 +1,179 @@
|
||||
use cl_ast::{
|
||||
ast_visitor::fold::Fold,
|
||||
desugar::{squash_groups::SquashGroups, while_else::WhileElseDesugar},
|
||||
};
|
||||
use cl_lexer::Lexer;
|
||||
use cl_parser::Parser;
|
||||
use cl_typeck::{
|
||||
definition::Def, name_collector::NameCollectable, project::Project, type_resolver::resolve,
|
||||
};
|
||||
use repline::{error::Error as RlError, prebaked::*};
|
||||
use std::error::Error;
|
||||
|
||||
// Path to display in standard library errors
|
||||
const STDLIB_DISPLAY_PATH: &str = "stdlib/lib.cl";
|
||||
// Statically included standard library
|
||||
const STDLIB: &str = include_str!("../../../stdlib/lib.cl");
|
||||
|
||||
// Colors
|
||||
const C_MAIN: &str = "";
|
||||
const C_RESV: &str = "\x1b[35m";
|
||||
const C_CODE: &str = "\x1b[36m";
|
||||
const C_LISTING: &str = "\x1b[38;5;117m";
|
||||
|
||||
/// A home for immutable intermediate ASTs
|
||||
///
|
||||
/// TODO: remove this.
|
||||
static mut TREES: TreeManager = TreeManager::new();
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut prj = Project::default();
|
||||
|
||||
let mut parser = Parser::new(Lexer::new(STDLIB));
|
||||
let code = match parser.file() {
|
||||
Ok(code) => code,
|
||||
Err(e) => {
|
||||
eprintln!("{STDLIB_DISPLAY_PATH}:{e}");
|
||||
Err(e)?
|
||||
}
|
||||
};
|
||||
|
||||
unsafe { TREES.push(code) }.collect_in_root(&mut prj)?;
|
||||
|
||||
main_menu(&mut prj)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main_menu(prj: &mut Project) -> Result<(), RlError> {
|
||||
banner();
|
||||
read_and(C_MAIN, "mu>", "? >", |line| {
|
||||
match line.trim() {
|
||||
"c" | "code" => enter_code(prj)?,
|
||||
"clear" => clear()?,
|
||||
"e" | "exit" => return Ok(Response::Break),
|
||||
"l" | "list" => list_types(prj),
|
||||
"q" | "query" => query_type_expression(prj)?,
|
||||
"r" | "resolve" => resolve_all(prj)?,
|
||||
"d" | "desugar" => live_desugar()?,
|
||||
"h" | "help" => {
|
||||
println!(
|
||||
"Valid commands are:
|
||||
code (c): Enter code to type-check
|
||||
list (l): List all known types
|
||||
query (q): Query the type system
|
||||
resolve (r): Perform type resolution
|
||||
desugar (d): WIP: Test the experimental desugaring passes
|
||||
help (h): Print this list
|
||||
exit (e): Exit the program"
|
||||
);
|
||||
return Ok(Response::Deny);
|
||||
}
|
||||
_ => Err(r#"Invalid command. Type "help" to see the list of valid commands."#)?,
|
||||
}
|
||||
Ok(Response::Accept)
|
||||
})
|
||||
}
|
||||
|
||||
fn enter_code(prj: &mut Project) -> Result<(), RlError> {
|
||||
read_and(C_CODE, "cl>", "? >", |line| {
|
||||
if line.trim().is_empty() {
|
||||
return Ok(Response::Break);
|
||||
}
|
||||
let code = Parser::new(Lexer::new(line)).file()?;
|
||||
let code = WhileElseDesugar.fold_file(code);
|
||||
// Safety: this is totally unsafe
|
||||
unsafe { TREES.push(code) }.collect_in_root(prj)?;
|
||||
|
||||
Ok(Response::Accept)
|
||||
})
|
||||
}
|
||||
|
||||
fn live_desugar() -> Result<(), RlError> {
|
||||
read_and(C_RESV, "se>", "? >", |line| {
|
||||
let code = Parser::new(Lexer::new(line)).stmt()?;
|
||||
println!("Raw, as parsed:\n{C_LISTING}{code}\x1b[0m");
|
||||
|
||||
let code = SquashGroups.fold_stmt(code);
|
||||
println!("SquashGroups\n{C_LISTING}{code}\x1b[0m");
|
||||
|
||||
let code = WhileElseDesugar.fold_stmt(code);
|
||||
println!("WhileElseDesugar\n{C_LISTING}{code}\x1b[0m");
|
||||
|
||||
Ok(Response::Accept)
|
||||
})
|
||||
}
|
||||
|
||||
fn query_type_expression(prj: &mut Project) -> Result<(), RlError> {
|
||||
read_and(C_RESV, "ty>", "? >", |line| {
|
||||
if line.trim().is_empty() {
|
||||
return Ok(Response::Break);
|
||||
}
|
||||
// parse it as a path, and convert the path into a borrowed path
|
||||
let ty = Parser::new(Lexer::new(line)).ty()?.kind;
|
||||
let id = prj.evaluate(&ty, prj.root)?;
|
||||
pretty_def(&prj[id], id);
|
||||
Ok(Response::Accept)
|
||||
})
|
||||
}
|
||||
|
||||
fn resolve_all(prj: &mut Project) -> Result<(), Box<dyn Error>> {
|
||||
for id in prj.pool.key_iter() {
|
||||
resolve(prj, id)?;
|
||||
}
|
||||
println!("Types resolved successfully!");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn list_types(prj: &mut Project) {
|
||||
println!(" name\x1b[30G type");
|
||||
for (idx, Def { name, vis, kind, .. }) in prj.pool.iter().enumerate() {
|
||||
print!("{idx:3}: {vis}");
|
||||
if name.is_empty() {
|
||||
print!("\x1b[30m_\x1b[0m")
|
||||
}
|
||||
println!("{name}\x1b[30G| {kind}");
|
||||
}
|
||||
}
|
||||
|
||||
fn pretty_def(def: &Def, id: impl Into<usize>) {
|
||||
let id = id.into();
|
||||
let Def { vis, name, kind, module, meta, source } = def;
|
||||
for meta in *meta {
|
||||
println!("#[{meta}]")
|
||||
}
|
||||
println!("{vis}{name} [id: {id}] = {kind}");
|
||||
if let Some(source) = source {
|
||||
println!("Source:\n{C_LISTING}{source}\x1b[0m");
|
||||
}
|
||||
println!("\x1b[90m{module}\x1b[0m");
|
||||
}
|
||||
|
||||
fn clear() -> Result<(), Box<dyn Error>> {
|
||||
println!("\x1b[H\x1b[2J");
|
||||
banner();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn banner() {
|
||||
println!(
|
||||
"--- {} v{} 💪🦈 ---",
|
||||
env!("CARGO_BIN_NAME"),
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
);
|
||||
}
|
||||
|
||||
/// Keeps leaked references to past ASTs, for posterity:tm:
|
||||
struct TreeManager {
|
||||
trees: Vec<&'static cl_ast::File>,
|
||||
}
|
||||
|
||||
impl TreeManager {
|
||||
const fn new() -> Self {
|
||||
Self { trees: vec![] }
|
||||
}
|
||||
fn push(&mut self, tree: cl_ast::File) -> &'static cl_ast::File {
|
||||
let ptr = Box::leak(Box::new(tree));
|
||||
self.trees.push(ptr);
|
||||
ptr
|
||||
}
|
||||
}
|
||||
656
compiler/cl-repl/examples/yaml.rs
Normal file
656
compiler/cl-repl/examples/yaml.rs
Normal file
@@ -0,0 +1,656 @@
|
||||
//! Pretty prints a conlang AST in yaml
|
||||
|
||||
use cl_lexer::Lexer;
|
||||
use cl_parser::Parser;
|
||||
use repline::{error::Error as RlError, Repline};
|
||||
use std::error::Error;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let mut rl = Repline::new("\x1b[33m", "cl>", "? >");
|
||||
loop {
|
||||
let line = match rl.read() {
|
||||
Err(RlError::CtrlC(_)) => break,
|
||||
Err(RlError::CtrlD(line)) => {
|
||||
rl.deny();
|
||||
line
|
||||
}
|
||||
Ok(line) => line,
|
||||
Err(e) => Err(e)?,
|
||||
};
|
||||
|
||||
let mut parser = Parser::new(Lexer::new(&line));
|
||||
let code = match parser.stmt() {
|
||||
Ok(code) => {
|
||||
rl.accept();
|
||||
code
|
||||
}
|
||||
Err(e) => {
|
||||
print!("\x1b[40G\x1bJ\x1b[91m{e}\x1b[0m");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
print!("\x1b[G\x1b[J\x1b[A");
|
||||
Yamler::new().yaml(&code);
|
||||
println!();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub use yamler::Yamler;
|
||||
pub mod yamler {
|
||||
use crate::yamlify::Yamlify;
|
||||
use std::{
|
||||
fmt::Display,
|
||||
io::Write,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Yamler {
|
||||
depth: usize,
|
||||
}
|
||||
|
||||
impl Yamler {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn indent(&mut self) -> Section {
|
||||
Section::new(self)
|
||||
}
|
||||
|
||||
/// Prints a [Yamlify] value
|
||||
#[inline]
|
||||
pub fn yaml<T: Yamlify>(&mut self, yaml: &T) -> &mut Self {
|
||||
yaml.yaml(self);
|
||||
self
|
||||
}
|
||||
|
||||
fn increase(&mut self) {
|
||||
self.depth += 1;
|
||||
}
|
||||
|
||||
fn decrease(&mut self) {
|
||||
self.depth -= 1;
|
||||
}
|
||||
|
||||
fn print_indentation(&self, writer: &mut impl Write) {
|
||||
for _ in 0..self.depth {
|
||||
let _ = write!(writer, " ");
|
||||
}
|
||||
}
|
||||
|
||||
/// Prints a section header and increases indentation
|
||||
pub fn key(&mut self, name: impl Display) -> Section {
|
||||
println!();
|
||||
self.print_indentation(&mut std::io::stdout().lock());
|
||||
print!("- {name}:");
|
||||
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);
|
||||
self
|
||||
}
|
||||
|
||||
/// Prints a yaml scalar value: `"name"``
|
||||
pub fn value<D: Display>(&mut self, value: D) -> &mut Self {
|
||||
print!(" {value}");
|
||||
self
|
||||
}
|
||||
|
||||
pub fn list<D: Yamlify>(&mut self, list: &[D]) -> &mut Self {
|
||||
for (idx, value) in list.iter().enumerate() {
|
||||
self.pair(idx, value);
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Tracks the start and end of an indented block (a "section")
|
||||
pub struct Section<'y> {
|
||||
yamler: &'y mut Yamler,
|
||||
}
|
||||
|
||||
impl<'y> Section<'y> {
|
||||
pub fn new(yamler: &'y mut Yamler) -> Self {
|
||||
yamler.increase();
|
||||
Self { yamler }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'y> Deref for Section<'y> {
|
||||
type Target = Yamler;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.yamler
|
||||
}
|
||||
}
|
||||
impl<'y> DerefMut for Section<'y> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.yamler
|
||||
}
|
||||
}
|
||||
|
||||
impl<'y> Drop for Section<'y> {
|
||||
fn drop(&mut self) {
|
||||
let Self { yamler } = self;
|
||||
yamler.decrease();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod yamlify {
|
||||
use super::yamler::Yamler;
|
||||
use cl_ast::*;
|
||||
|
||||
pub trait Yamlify {
|
||||
fn yaml(&self, y: &mut Yamler);
|
||||
}
|
||||
|
||||
impl Yamlify for File {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let File { items } = self;
|
||||
y.key("File").yaml(items);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Visibility {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
if let Visibility::Public = self {
|
||||
y.pair("vis", "pub");
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Yamlify for Mutability {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
if let Mutability::Mut = self {
|
||||
y.pair("mut", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Yamlify for Attrs {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { meta } = self;
|
||||
y.key("Attrs").yaml(meta);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Meta {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { name, kind } = self;
|
||||
y.key("Meta").pair("name", name).yaml(kind);
|
||||
}
|
||||
}
|
||||
impl Yamlify for MetaKind {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
match self {
|
||||
MetaKind::Plain => y,
|
||||
MetaKind::Equals(value) => y.pair("equals", value),
|
||||
MetaKind::Func(args) => y.pair("args", args),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl Yamlify for Item {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { extents: _, attrs, vis, kind } = self;
|
||||
y.key("Item").yaml(attrs).yaml(vis).yaml(kind);
|
||||
}
|
||||
}
|
||||
impl Yamlify for ItemKind {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
match self {
|
||||
ItemKind::Alias(f) => y.yaml(f),
|
||||
ItemKind::Const(f) => y.yaml(f),
|
||||
ItemKind::Static(f) => y.yaml(f),
|
||||
ItemKind::Module(f) => y.yaml(f),
|
||||
ItemKind::Function(f) => y.yaml(f),
|
||||
ItemKind::Struct(f) => y.yaml(f),
|
||||
ItemKind::Enum(f) => y.yaml(f),
|
||||
ItemKind::Impl(f) => y.yaml(f),
|
||||
};
|
||||
}
|
||||
}
|
||||
impl Yamlify for Alias {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { to, from } = self;
|
||||
y.key("Alias").pair("to", to).pair("from", from);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Const {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { name, ty, init } = self;
|
||||
y.key("Const")
|
||||
.pair("name", name)
|
||||
.pair("ty", ty)
|
||||
.pair("init", init);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Static {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { mutable, name, ty, init } = self;
|
||||
y.key(name).yaml(mutable).pair("ty", ty).pair("init", init);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Module {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { name, kind } = self;
|
||||
y.key("Module").pair("name", name).yaml(kind);
|
||||
}
|
||||
}
|
||||
impl Yamlify for ModuleKind {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
match self {
|
||||
ModuleKind::Inline(f) => y.yaml(f),
|
||||
ModuleKind::Outline => y,
|
||||
};
|
||||
}
|
||||
}
|
||||
impl Yamlify for Function {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { name, sign, bind, body } = self;
|
||||
y.key("Function")
|
||||
.pair("name", name)
|
||||
.pair("sign", sign)
|
||||
.pair("bind", bind)
|
||||
.pair("body", body);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Struct {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { name, kind } = self;
|
||||
y.key("Struct").pair("name", name).yaml(kind);
|
||||
}
|
||||
}
|
||||
impl Yamlify for StructKind {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
match self {
|
||||
StructKind::Empty => y,
|
||||
StructKind::Tuple(k) => y.yaml(k),
|
||||
StructKind::Struct(k) => y.yaml(k),
|
||||
};
|
||||
}
|
||||
}
|
||||
impl Yamlify for StructMember {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { vis, name, ty } = self;
|
||||
y.key("StructMember").yaml(vis).pair("name", name).yaml(ty);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Enum {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { name, kind } = self;
|
||||
y.key("Enum").pair("name", name).yaml(kind);
|
||||
}
|
||||
}
|
||||
impl Yamlify for EnumKind {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
match self {
|
||||
EnumKind::NoVariants => y,
|
||||
EnumKind::Variants(v) => y.yaml(v),
|
||||
};
|
||||
}
|
||||
}
|
||||
impl Yamlify for Variant {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { name, kind } = self;
|
||||
y.key("Variant").pair("name", name).yaml(kind);
|
||||
}
|
||||
}
|
||||
impl Yamlify for VariantKind {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
match self {
|
||||
VariantKind::Plain => y,
|
||||
VariantKind::CLike(v) => y.yaml(v),
|
||||
VariantKind::Tuple(v) => y.yaml(v),
|
||||
VariantKind::Struct(v) => y.yaml(v),
|
||||
};
|
||||
}
|
||||
}
|
||||
impl Yamlify for Impl {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { target, body } = self;
|
||||
y.key("Impl").pair("target", target).pair("body", body);
|
||||
}
|
||||
}
|
||||
impl Yamlify for ImplKind {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
match self {
|
||||
ImplKind::Type(t) => y.value(t),
|
||||
ImplKind::Trait { impl_trait, for_type } => {
|
||||
y.pair("trait", impl_trait).pair("for_type", for_type)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
impl Yamlify for Block {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { stmts } = self;
|
||||
y.key("Block").yaml(stmts);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Stmt {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { extents: _, kind, semi } = self;
|
||||
y.key("Stmt").yaml(kind).yaml(semi);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Semi {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
if let Semi::Terminated = self {
|
||||
y.pair("terminated", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Yamlify for StmtKind {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
match self {
|
||||
StmtKind::Empty => y,
|
||||
StmtKind::Local(s) => y.yaml(s),
|
||||
StmtKind::Item(s) => y.yaml(s),
|
||||
StmtKind::Expr(s) => y.yaml(s),
|
||||
};
|
||||
}
|
||||
}
|
||||
impl Yamlify for Let {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { mutable, name, ty, init } = self;
|
||||
y.key("Let")
|
||||
.pair("name", name)
|
||||
.yaml(mutable)
|
||||
.pair("ty", ty)
|
||||
.pair("init", init);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Expr {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { extents: _, kind } = self;
|
||||
y.yaml(kind);
|
||||
}
|
||||
}
|
||||
impl Yamlify for ExprKind {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
match self {
|
||||
ExprKind::Assign(k) => k.yaml(y),
|
||||
ExprKind::Binary(k) => k.yaml(y),
|
||||
ExprKind::Unary(k) => k.yaml(y),
|
||||
ExprKind::Index(k) => k.yaml(y),
|
||||
ExprKind::Path(k) => k.yaml(y),
|
||||
ExprKind::Literal(k) => k.yaml(y),
|
||||
ExprKind::Array(k) => k.yaml(y),
|
||||
ExprKind::ArrayRep(k) => k.yaml(y),
|
||||
ExprKind::AddrOf(k) => k.yaml(y),
|
||||
ExprKind::Block(k) => k.yaml(y),
|
||||
ExprKind::Empty => {}
|
||||
ExprKind::Group(k) => k.yaml(y),
|
||||
ExprKind::Tuple(k) => k.yaml(y),
|
||||
ExprKind::Loop(k) => k.yaml(y),
|
||||
ExprKind::While(k) => k.yaml(y),
|
||||
ExprKind::If(k) => k.yaml(y),
|
||||
ExprKind::For(k) => k.yaml(y),
|
||||
ExprKind::Break(k) => k.yaml(y),
|
||||
ExprKind::Return(k) => k.yaml(y),
|
||||
ExprKind::Continue(k) => k.yaml(y),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Yamlify for Assign {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { kind, parts } = self;
|
||||
y.key("Assign")
|
||||
.pair("kind", kind)
|
||||
.pair("head", &parts.0)
|
||||
.pair("tail", &parts.1);
|
||||
}
|
||||
}
|
||||
impl Yamlify for AssignKind {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
y.value(self);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Binary {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { kind, parts } = self;
|
||||
y.key("Binary")
|
||||
.pair("kind", kind)
|
||||
.pair("head", &parts.0)
|
||||
.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 Tuple {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { exprs } = self;
|
||||
y.key("Tuple").list(exprs);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Index {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { head, indices } = self;
|
||||
y.key("Index").pair("head", head).list(indices);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Array {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { values } = self;
|
||||
y.key("Array").list(values);
|
||||
}
|
||||
}
|
||||
impl Yamlify for ArrayRep {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { value, repeat } = self;
|
||||
y.key("ArrayRep")
|
||||
.pair("value", value)
|
||||
.pair("repeat", repeat);
|
||||
}
|
||||
}
|
||||
impl Yamlify for AddrOf {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { count, mutable, expr } = self;
|
||||
y.key("AddrOf")
|
||||
.pair("count", count)
|
||||
.yaml(mutable)
|
||||
.pair("expr", expr);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Group {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { expr } = self;
|
||||
y.key("Group").yaml(expr);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Loop {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { body } = self;
|
||||
y.key("Loop").yaml(body);
|
||||
}
|
||||
}
|
||||
impl Yamlify for While {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { cond, pass, fail } = self;
|
||||
y.key("While")
|
||||
.pair("cond", cond)
|
||||
.pair("pass", pass)
|
||||
.yaml(fail);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Else {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { body } = self;
|
||||
y.key("Else").yaml(body);
|
||||
}
|
||||
}
|
||||
impl Yamlify for If {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { cond, pass, fail } = self;
|
||||
y.key("If").pair("cond", cond).pair("pass", pass).yaml(fail);
|
||||
}
|
||||
}
|
||||
impl Yamlify for For {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { bind, cond, pass, fail } = self;
|
||||
y.key("For")
|
||||
.pair("bind", bind)
|
||||
.pair("cond", cond)
|
||||
.pair("pass", pass)
|
||||
.yaml(fail);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Break {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { body } = self;
|
||||
y.key("Break").yaml(body);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Return {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { body } = self;
|
||||
y.key("Return").yaml(body);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Continue {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
y.key("Continue");
|
||||
}
|
||||
}
|
||||
impl Yamlify for Literal {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
y.value(format_args!("\"{self}\""));
|
||||
}
|
||||
}
|
||||
impl Yamlify for Identifier {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self(name) = self;
|
||||
y.value(name);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Param {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { mutability, name } = self;
|
||||
y.key("Param").yaml(mutability).pair("name", name);
|
||||
}
|
||||
}
|
||||
impl Yamlify for Ty {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { extents: _, kind } = self;
|
||||
y.key("Ty").yaml(kind);
|
||||
}
|
||||
}
|
||||
impl Yamlify for TyKind {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
match self {
|
||||
TyKind::Never => y.value("Never"),
|
||||
TyKind::Empty => y.value("Empty"),
|
||||
TyKind::SelfTy => y.value("Self"),
|
||||
TyKind::Path(t) => y.yaml(t),
|
||||
TyKind::Tuple(t) => y.yaml(t),
|
||||
TyKind::Ref(t) => y.yaml(t),
|
||||
TyKind::Fn(t) => y.yaml(t),
|
||||
};
|
||||
}
|
||||
}
|
||||
impl Yamlify for Path {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { absolute, parts } = self;
|
||||
let mut y = y.key("Path");
|
||||
if *absolute {
|
||||
y.pair("absolute", absolute);
|
||||
}
|
||||
for part in parts {
|
||||
y.pair("part", part);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Yamlify for PathPart {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
match self {
|
||||
PathPart::SuperKw => y.value("super"),
|
||||
PathPart::SelfKw => y.value("self"),
|
||||
PathPart::Ident(i) => y.yaml(i),
|
||||
};
|
||||
}
|
||||
}
|
||||
impl Yamlify for TyTuple {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { types } = self;
|
||||
let mut y = y.key("TyTuple");
|
||||
for ty in types {
|
||||
y.yaml(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Yamlify for TyRef {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { count, mutable, to } = self;
|
||||
y.key("TyRef")
|
||||
.pair("count", count)
|
||||
.yaml(mutable)
|
||||
.pair("to", to);
|
||||
}
|
||||
}
|
||||
impl Yamlify for TyFn {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
let Self { args, rety } = self;
|
||||
y.key("TyFn").pair("args", args).pair("rety", rety);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Yamlify> Yamlify for Option<T> {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
if let Some(v) = self {
|
||||
y.yaml(v);
|
||||
} else {
|
||||
y.value("");
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T: Yamlify> Yamlify for Box<T> {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
y.yaml(&**self);
|
||||
}
|
||||
}
|
||||
impl<T: Yamlify> Yamlify for Vec<T> {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
for thing in self {
|
||||
y.yaml(thing);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Yamlify for () {
|
||||
fn yaml(&self, _y: &mut Yamler) {}
|
||||
}
|
||||
|
||||
impl<T: Yamlify> Yamlify for &T {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
(*self).yaml(y)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! scalar {
|
||||
($($t:ty),*$(,)?) => {
|
||||
$(impl Yamlify for $t {
|
||||
fn yaml(&self, y: &mut Yamler) {
|
||||
y.value(self);
|
||||
}
|
||||
})*
|
||||
};
|
||||
}
|
||||
|
||||
scalar! {
|
||||
bool, char, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, &str, String
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user