250 lines
7.3 KiB
Rust
250 lines
7.3 KiB
Rust
use std::error::Error;
|
|
|
|
use doughlang::{
|
|
ast::{
|
|
types::{Literal, Path},
|
|
visit::{Visit, Walk},
|
|
*,
|
|
},
|
|
intern::interned::Interned,
|
|
lexer::Lexer,
|
|
parser::{Parser, expr::Prec},
|
|
};
|
|
|
|
use repline::prebaked::{Response, read_and};
|
|
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
|
read_and("\x1b[34m", "l>", " >", |line| {
|
|
let ast: Anno<Expr> = Parser::new(Lexer::new(line)).parse(Prec::MIN)?;
|
|
let mut to_lisp = ToLisp;
|
|
let _ = to_lisp.visit(&ast);
|
|
println!();
|
|
Ok(Response::Accept)
|
|
})?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
struct ToLisp;
|
|
|
|
impl ToLisp {
|
|
fn bind_op(&self, op: BindOp) -> &'static str {
|
|
match op {
|
|
BindOp::Let => "let",
|
|
BindOp::Type => "type",
|
|
BindOp::Fn => "fn",
|
|
BindOp::Mod => "mod",
|
|
BindOp::Impl => "impl",
|
|
BindOp::Struct => "struct",
|
|
BindOp::Enum => "enum",
|
|
BindOp::For => "for",
|
|
BindOp::Match => "match",
|
|
}
|
|
}
|
|
fn pat_op(&self, op: PatOp) -> &'static str {
|
|
match op {
|
|
PatOp::Pub => "pub",
|
|
PatOp::Mut => "mut",
|
|
PatOp::Ref => "ref",
|
|
PatOp::Ptr => "ptr",
|
|
PatOp::Rest => "rest",
|
|
PatOp::RangeEx => "range-ex",
|
|
PatOp::RangeIn => "range-in",
|
|
PatOp::Record => "record",
|
|
PatOp::Tuple => "tuple",
|
|
PatOp::Slice => "slice",
|
|
PatOp::ArRep => "ar-rep",
|
|
PatOp::Typed => "typed",
|
|
PatOp::TypePrefixed => "type-prefixed",
|
|
PatOp::Generic => "generic-in",
|
|
PatOp::Fn => "fn",
|
|
PatOp::Alt => "alt",
|
|
}
|
|
}
|
|
fn expr_op(&self, op: Op) -> &'static str {
|
|
match op {
|
|
Op::Do => "do",
|
|
Op::As => "cast",
|
|
Op::Macro => "macro",
|
|
Op::Block => "block",
|
|
Op::Array => "array",
|
|
Op::ArRep => "ar-rep",
|
|
Op::Group => "group",
|
|
Op::Tuple => "tuple",
|
|
Op::Meta => "meta",
|
|
Op::Try => "try",
|
|
Op::Index => "index",
|
|
Op::Call => "call",
|
|
Op::Pub => "pub",
|
|
Op::Loop => "loop",
|
|
Op::Const => "const",
|
|
Op::Static => "static",
|
|
Op::Match => "match",
|
|
Op::If => "if",
|
|
Op::While => "while",
|
|
Op::Break => "break",
|
|
Op::Return => "return",
|
|
Op::Continue => "continue",
|
|
Op::Dot => "dot",
|
|
Op::RangeEx => "range-ex",
|
|
Op::RangeIn => "range-in",
|
|
Op::Neg => "neg",
|
|
Op::Not => "not",
|
|
Op::Identity => "identity",
|
|
Op::Refer => "refer",
|
|
Op::Deref => "deref",
|
|
Op::Mul => "mul",
|
|
Op::Div => "div",
|
|
Op::Rem => "rem",
|
|
Op::Add => "add",
|
|
Op::Sub => "sub",
|
|
Op::Shl => "shl",
|
|
Op::Shr => "shr",
|
|
Op::And => "and",
|
|
Op::Xor => "xor",
|
|
Op::Or => "or",
|
|
Op::Lt => "lt",
|
|
Op::Leq => "leq",
|
|
Op::Eq => "eq",
|
|
Op::Neq => "neq",
|
|
Op::Geq => "geq",
|
|
Op::Gt => "gt",
|
|
Op::LogAnd => "log-and",
|
|
Op::LogXor => "log-xor",
|
|
Op::LogOr => "log-or",
|
|
Op::Set => "set",
|
|
Op::MulSet => "mul-set",
|
|
Op::DivSet => "div-set",
|
|
Op::RemSet => "rem-set",
|
|
Op::AddSet => "add-set",
|
|
Op::SubSet => "sub-set",
|
|
Op::ShlSet => "shl-set",
|
|
Op::ShrSet => "shr-set",
|
|
Op::AndSet => "and-set",
|
|
Op::XorSet => "xor-set",
|
|
Op::OrSet => "or-set",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a> Visit<'a, DefaultTypes> for ToLisp {
|
|
type Error = ();
|
|
|
|
fn visit_expr(&mut self, expr: &'a Expr) -> Result<(), Self::Error> {
|
|
match expr {
|
|
Expr::Omitted => print!("()"),
|
|
Expr::Id(path) => self.visit_path(path)?,
|
|
Expr::MetId(id) => print!("`{id}"),
|
|
Expr::Lit(literal) => self.visit_literal(literal)?,
|
|
Expr::Use(import) => import.visit_in(self)?,
|
|
Expr::Bind(bind) => bind.visit_in(self)?,
|
|
Expr::Make(make) => make.visit_in(self)?,
|
|
Expr::Op(op, annos) => {
|
|
print!("({}", self.expr_op(*op));
|
|
for anno in annos {
|
|
print!(" ");
|
|
anno.visit_in(self)?;
|
|
}
|
|
print!(")");
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn visit_macro_id(&mut self, name: &'a Interned<'static, str>) -> Result<(), Self::Error> {
|
|
print!("{name}");
|
|
Ok(())
|
|
}
|
|
|
|
fn visit_symbol(&mut self, name: &'a Interned<'static, str>) -> Result<(), Self::Error> {
|
|
print!("{name}");
|
|
Ok(())
|
|
}
|
|
|
|
fn visit_path(&mut self, path: &'a Path) -> Result<(), Self::Error> {
|
|
let Path { parts } = path;
|
|
print!("(at");
|
|
for part in parts {
|
|
print!(" ");
|
|
self.visit_symbol(part)?;
|
|
}
|
|
print!(")");
|
|
Ok(())
|
|
}
|
|
|
|
fn visit_literal(&mut self, lit: &'a Literal) -> Result<(), Self::Error> {
|
|
print!("{lit}");
|
|
Ok(())
|
|
}
|
|
|
|
fn visit_use(&mut self, item: &'a Use) -> Result<(), Self::Error> {
|
|
match item {
|
|
Use::Glob => print!("(use-glob)"),
|
|
Use::Name(name) => self.visit_symbol(name)?,
|
|
Use::Alias(name, alias) => print!("(use-alias {name} {alias})"),
|
|
Use::Path(name, tree) => {
|
|
print!("(use-path {name} ");
|
|
tree.visit_in(self)?;
|
|
print!(")");
|
|
}
|
|
Use::Tree(items) => {
|
|
print!("(use-tree");
|
|
for item in items {
|
|
print!(" ");
|
|
item.visit_in(self)?;
|
|
}
|
|
print!(")");
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn visit_pat(&mut self, item: &'a Pat) -> Result<(), Self::Error> {
|
|
match item {
|
|
Pat::Ignore => print!("(ignore)"),
|
|
Pat::Never => print!("(never)"),
|
|
Pat::MetId(id) => print!("(replace {id})"),
|
|
Pat::Name(name) => print!("{name}"),
|
|
Pat::Value(literal) => literal.visit_in(self)?,
|
|
Pat::Op(pat_op, pats) => {
|
|
print!("({}", self.pat_op(*pat_op));
|
|
for pat in pats {
|
|
print!(" ");
|
|
pat.visit_in(self)?;
|
|
}
|
|
print!(")");
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn visit_bind(&mut self, item: &'a Bind) -> Result<(), Self::Error> {
|
|
let Bind(op, generics, pattern, exprs) = item;
|
|
print!("({} ", self.bind_op(*op));
|
|
if !generics.is_empty() {
|
|
print!("(for-some");
|
|
for generic in generics {
|
|
print!(" {generic}");
|
|
}
|
|
print!(") ");
|
|
}
|
|
pattern.visit_in(self)?;
|
|
for expr in exprs {
|
|
print!(" ");
|
|
expr.visit_in(self)?;
|
|
}
|
|
print!(")");
|
|
Ok(())
|
|
}
|
|
|
|
fn visit_make(&mut self, item: &'a Make) -> Result<(), Self::Error> {
|
|
item.children(self)
|
|
}
|
|
|
|
fn visit_makearm(&mut self, item: &'a MakeArm) -> Result<(), Self::Error> {
|
|
item.children(self)
|
|
}
|
|
}
|