mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
Compare commits
3 commits
c82c3701ba
...
4b5a61c060
Author | SHA1 | Date | |
---|---|---|---|
azur | 4b5a61c060 | ||
azur | 5aa7add0cc | ||
azur | e6bbbdd5bd |
7
b.hlm
7
b.hlm
|
@ -1,5 +1,4 @@
|
||||||
let foo : num = 1 in bar(foo) end
|
println((\x: num -> x + 35)(34));
|
||||||
|
16---1*3/-f(16)+8%-2;
|
||||||
|
|
||||||
lambda (foo : num) -> unknown = bar(foo)
|
a(b, c(d(e, f), g(h), i), j(k, l), m);
|
||||||
|
|
||||||
let x : t = e1 in e2 end
|
|
88
src/main.rs
88
src/main.rs
|
@ -1,55 +1,59 @@
|
||||||
#![feature(trait_alias)]
|
#![feature(trait_alias)]
|
||||||
pub mod parse;
|
pub mod read;
|
||||||
pub mod trans;
|
pub mod trans;
|
||||||
|
|
||||||
use parse::parse::lex;
|
use read::parse::{lex, parse};
|
||||||
|
use trans::low::{translate_expr, translate_js};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let input = r#"
|
let path = std::env::args().nth(1).expect("No file path provided");
|
||||||
println((\x: int -> x + 1)(1));
|
let src = std::fs::read_to_string(path).expect("Failed to read file");
|
||||||
"#;
|
|
||||||
|
|
||||||
let tokens = lex(input.to_owned());
|
let (tokens, lex_errs) = lex(src.to_owned());
|
||||||
println!("{:?}", tokens);
|
|
||||||
|
|
||||||
// use parse::past::*;
|
let parse_errs = if let Some(tokens) = tokens {
|
||||||
// use trans::ty::Type;
|
let (ast, parse_errs) = parse(tokens, src.len());
|
||||||
// use trans::low::*;
|
|
||||||
|
|
||||||
// let exprs = vec![
|
if let Some(ast) = ast {
|
||||||
// PExpr::Call(Box::new(PExpr::Sym("println".to_string())), vec![
|
println!();
|
||||||
// PExpr::Str("Hello, world!".to_string()),
|
println!("\x1b[90m───SOURCE─────────────────────────────────────────\x1b[0m");
|
||||||
// ]),
|
println!("{src}");
|
||||||
// PExpr::Let {
|
println!("\x1b[90m───PARSE TREE─────────────────────────────────────\x1b[0m");
|
||||||
// vars: vec![
|
for (e, _) in &ast {
|
||||||
// ("x".to_string(), Type::Num, PExpr::Num(1)),
|
println!("{}", {
|
||||||
// ],
|
let e = format!("{:?}", e);
|
||||||
// body: Box::new(PExpr::Sym("x".to_string())),
|
if e.len() > 50 {
|
||||||
// },
|
format!("{}...", &e[..47])
|
||||||
// PExpr::Let {
|
} else {
|
||||||
// vars: vec![
|
e
|
||||||
// ("x".to_string(), Type::Num, PExpr::Num(34)),
|
}
|
||||||
// ("y".to_string(), Type::Num, PExpr::Num(35)),
|
});
|
||||||
// ],
|
}
|
||||||
// body: Box::new(PExpr::BinaryOp(
|
println!("\x1b[90m───INTERNAL AST───────────────────────────────────\x1b[0m");
|
||||||
// PBinaryOp::Add,
|
let nexprs = ast.into_iter().map(|(e, _)| translate_expr(e)).collect::<Vec<_>>();
|
||||||
// Box::new(PExpr::Sym("x".to_string())),
|
|
||||||
// Box::new(PExpr::Sym("y".to_string())),
|
|
||||||
// )),
|
|
||||||
// },
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// let nexprs = exprs.into_iter().map(translate_expr).collect::<Vec<_>>();
|
for expr in &nexprs {
|
||||||
|
println!("{}", expr);
|
||||||
|
}
|
||||||
|
println!("\x1b[90m───JS OUTPUT──────────────────────────────────────\x1b[0m");
|
||||||
|
let jsexprs = nexprs.into_iter().map(translate_js).collect::<Vec<_>>();
|
||||||
|
|
||||||
// for expr in &nexprs {
|
for expr in &jsexprs {
|
||||||
// println!("{}", expr);
|
println!("{}", expr);
|
||||||
// }
|
}
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
|
||||||
// println!("──────────────────────────────────────────────────");
|
parse_errs
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
};
|
||||||
|
|
||||||
// let jsexprs = nexprs.into_iter().map(translate_js).collect::<Vec<_>>();
|
if !lex_errs.is_empty() || !parse_errs.is_empty() {
|
||||||
|
lex_errs
|
||||||
// for expr in &jsexprs {
|
.into_iter()
|
||||||
// println!("{}", expr);
|
.map(|e| e.map(|c| c.to_string()))
|
||||||
// }
|
.chain(parse_errs.into_iter().map(|e| e.map(|t| t.to_string())))
|
||||||
|
.for_each(|e| println!("{}", e));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
use chumsky::{error, prelude::*, Stream};
|
use chumsky::{prelude::*, Stream};
|
||||||
use std::fmt::{Display, Formatter, Result as FmtResult};
|
use std::fmt::{Display, Formatter, Result as FmtResult};
|
||||||
|
use crate::trans::ty::Type;
|
||||||
|
|
||||||
use super::past::*;
|
use super::past::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
|
@ -174,6 +176,32 @@ pub fn symbol_parser() -> impl P<String> {
|
||||||
.labelled("symbol")
|
.labelled("symbol")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn type_parser() -> impl P<Type> {
|
||||||
|
recursive(|ty| {
|
||||||
|
let litty = symbol_parser().map(|s| match s.as_str() {
|
||||||
|
"num" => Type::Num,
|
||||||
|
"str" => Type::Str,
|
||||||
|
"bool" => Type::Bool,
|
||||||
|
"?" => Type::Unknown,
|
||||||
|
_ => Type::Sym(s),
|
||||||
|
});
|
||||||
|
|
||||||
|
let fun = just(Token::Open(Delim::Paren))
|
||||||
|
.ignore_then(
|
||||||
|
ty.clone()
|
||||||
|
.separated_by(just(Token::Comma))
|
||||||
|
)
|
||||||
|
.then_ignore(just(Token::Close(Delim::Paren)))
|
||||||
|
.then_ignore(just(Token::Arrow))
|
||||||
|
.then(ty)
|
||||||
|
.map(|(args, ret)| Type::Fun(args, Box::new(ret)));
|
||||||
|
|
||||||
|
litty
|
||||||
|
.or(fun)
|
||||||
|
.labelled("type")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn nested_parser<'a, T: 'a>(
|
pub fn nested_parser<'a, T: 'a>(
|
||||||
parser: impl P<T> + 'a,
|
parser: impl P<T> + 'a,
|
||||||
delim: Delim,
|
delim: Delim,
|
||||||
|
@ -202,3 +230,181 @@ pub fn nested_parser<'a, T: 'a>(
|
||||||
))
|
))
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn expr_parser() -> impl P<Spanned<PExpr>> {
|
||||||
|
recursive(|expr: Recursive<Token, Spanned<PExpr>, Simple<Token>>| {
|
||||||
|
let lit = literal_parser().map(PExpr::Lit);
|
||||||
|
let sym = symbol_parser().map(PExpr::Sym);
|
||||||
|
|
||||||
|
let vec = nested_parser(
|
||||||
|
expr.clone()
|
||||||
|
.separated_by(just(Token::Comma))
|
||||||
|
.allow_trailing()
|
||||||
|
.map(Some),
|
||||||
|
Delim::Brack,
|
||||||
|
|_| None,
|
||||||
|
)
|
||||||
|
.map(|xs| match xs {
|
||||||
|
Some(xs) => PExpr::Vec(xs),
|
||||||
|
None => PExpr::Vec(Vec::new()),
|
||||||
|
})
|
||||||
|
.labelled("vector");
|
||||||
|
|
||||||
|
// (e)
|
||||||
|
let paren_expr = just(Token::Open(Delim::Paren))
|
||||||
|
.ignore_then(expr.clone())
|
||||||
|
.then_ignore(just(Token::Close(Delim::Paren)))
|
||||||
|
.map(|e| e.0)
|
||||||
|
.labelled("parenthesized expression");
|
||||||
|
|
||||||
|
// \[sym : type]* -> expr
|
||||||
|
let lam = just(Token::Lambda)
|
||||||
|
.ignore_then(
|
||||||
|
(
|
||||||
|
symbol_parser()
|
||||||
|
.then_ignore(just(Token::Colon))
|
||||||
|
.then(type_parser())
|
||||||
|
)
|
||||||
|
.repeated()
|
||||||
|
)
|
||||||
|
.then_ignore(just(Token::Arrow))
|
||||||
|
.then(expr.clone())
|
||||||
|
.map(|(args, body)| PExpr::Lambda {
|
||||||
|
args,
|
||||||
|
body: Box::new(body),
|
||||||
|
})
|
||||||
|
.labelled("lambda");
|
||||||
|
|
||||||
|
let atom = lit
|
||||||
|
.or(sym)
|
||||||
|
.or(vec)
|
||||||
|
.or(paren_expr)
|
||||||
|
.or(lam)
|
||||||
|
.map_with_span(|e, s| (e, s))
|
||||||
|
.boxed()
|
||||||
|
.labelled("atom");
|
||||||
|
|
||||||
|
// e(e*)
|
||||||
|
let call = atom
|
||||||
|
.then(
|
||||||
|
nested_parser(
|
||||||
|
expr.clone()
|
||||||
|
.separated_by(just(Token::Comma))
|
||||||
|
.allow_trailing()
|
||||||
|
.map(Some),
|
||||||
|
Delim::Paren,
|
||||||
|
|_| None,
|
||||||
|
)
|
||||||
|
.or_not(),
|
||||||
|
)
|
||||||
|
.map_with_span(|(f, args), s| match args {
|
||||||
|
Some(Some(args)) => (PExpr::Call(Box::new(f), args), s),
|
||||||
|
Some(None) => (PExpr::Error, s),
|
||||||
|
None => f,
|
||||||
|
});
|
||||||
|
|
||||||
|
// op e
|
||||||
|
let unary = choice((
|
||||||
|
just(Token::Sub).to(PUnaryOp::Neg),
|
||||||
|
just(Token::Not).to(PUnaryOp::Not),
|
||||||
|
))
|
||||||
|
.map_with_span(|op, s| (op, s))
|
||||||
|
.repeated()
|
||||||
|
.then(call)
|
||||||
|
.foldr(|op, expr| {
|
||||||
|
let s = op.1.start()..expr.1.end();
|
||||||
|
(PExpr::Unary(op, Box::new(expr)), s)
|
||||||
|
})
|
||||||
|
.boxed();
|
||||||
|
|
||||||
|
let product = unary
|
||||||
|
.clone()
|
||||||
|
.then(
|
||||||
|
choice((
|
||||||
|
just(Token::Mul).to(PBinaryOp::Mul),
|
||||||
|
just(Token::Div).to(PBinaryOp::Div),
|
||||||
|
just(Token::Mod).to(PBinaryOp::Mod),
|
||||||
|
))
|
||||||
|
.map_with_span(|op, s| (op, s))
|
||||||
|
.then(unary)
|
||||||
|
.repeated(),
|
||||||
|
)
|
||||||
|
.foldl(|lhs, (op, rhs)| {
|
||||||
|
let s = lhs.1.start()..rhs.1.end();
|
||||||
|
(PExpr::Binary(op, Box::new(lhs), Box::new(rhs)), s)
|
||||||
|
})
|
||||||
|
.boxed();
|
||||||
|
|
||||||
|
let sum = product
|
||||||
|
.clone()
|
||||||
|
.then(
|
||||||
|
choice((
|
||||||
|
just(Token::Add).to(PBinaryOp::Add),
|
||||||
|
just(Token::Sub).to(PBinaryOp::Sub),
|
||||||
|
))
|
||||||
|
.map_with_span(|op, s| (op, s))
|
||||||
|
.then(product)
|
||||||
|
.repeated(),
|
||||||
|
)
|
||||||
|
.foldl(|lhs, (op, rhs)| {
|
||||||
|
let s = lhs.1.start()..rhs.1.end();
|
||||||
|
(PExpr::Binary(op, Box::new(lhs), Box::new(rhs)), s)
|
||||||
|
})
|
||||||
|
.boxed();
|
||||||
|
|
||||||
|
let comparison = sum
|
||||||
|
.clone()
|
||||||
|
.then(
|
||||||
|
choice((
|
||||||
|
just(Token::Eq).to(PBinaryOp::Eq),
|
||||||
|
just(Token::Neq).to(PBinaryOp::Neq),
|
||||||
|
just(Token::Lt).to(PBinaryOp::Lt),
|
||||||
|
just(Token::Lte).to(PBinaryOp::Lte),
|
||||||
|
just(Token::Gt).to(PBinaryOp::Gt),
|
||||||
|
just(Token::Gte).to(PBinaryOp::Gte),
|
||||||
|
))
|
||||||
|
.map_with_span(|op, s| (op, s))
|
||||||
|
.then(sum)
|
||||||
|
.repeated(),
|
||||||
|
)
|
||||||
|
.foldl(|lhs, (op, rhs)| {
|
||||||
|
let s = lhs.1.start()..rhs.1.end();
|
||||||
|
(PExpr::Binary(op, Box::new(lhs), Box::new(rhs)), s)
|
||||||
|
})
|
||||||
|
.boxed();
|
||||||
|
|
||||||
|
comparison
|
||||||
|
.clone()
|
||||||
|
.then(
|
||||||
|
choice((
|
||||||
|
just(Token::And).to(PBinaryOp::And),
|
||||||
|
just(Token::Or).to(PBinaryOp::Or),
|
||||||
|
))
|
||||||
|
.map_with_span(|op, s| (op, s))
|
||||||
|
.then(comparison)
|
||||||
|
.repeated(),
|
||||||
|
)
|
||||||
|
.foldl(|lhs, (op, rhs)| {
|
||||||
|
let s = lhs.1.start()..rhs.1.end();
|
||||||
|
(PExpr::Binary(op, Box::new(lhs), Box::new(rhs)), s)
|
||||||
|
})
|
||||||
|
.boxed()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exprs_parser() -> impl P<Vec<Spanned<PExpr>>> {
|
||||||
|
expr_parser()
|
||||||
|
.then_ignore(just(Token::Semicolon))
|
||||||
|
.repeated()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse(
|
||||||
|
tokens: Vec<Spanned<Token>>,
|
||||||
|
len: usize,
|
||||||
|
) -> (Option<Vec<Spanned<PExpr>>>, Vec<Simple<Token>>) {
|
||||||
|
let (ast, parse_error) = exprs_parser()
|
||||||
|
.then_ignore(end())
|
||||||
|
.parse_recovery(Stream::from_iter(len..len + 1, tokens.into_iter()));
|
||||||
|
|
||||||
|
(ast, parse_error)
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
use std::fmt::{Display, Formatter, Result as FmtResult};
|
|
||||||
use crate::trans::ty::*;
|
use crate::trans::ty::*;
|
||||||
|
|
||||||
|
use super::parse::Spanned;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum PUnaryOp {
|
pub enum PUnaryOp {
|
||||||
Neg,
|
Neg,
|
||||||
|
@ -20,21 +21,22 @@ pub enum PLiteral { Num(i64), Str(String), Bool(bool) }
|
||||||
/// Enum to represent a parsed expression
|
/// Enum to represent a parsed expression
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum PExpr {
|
pub enum PExpr {
|
||||||
|
Error,
|
||||||
|
|
||||||
Lit(PLiteral),
|
Lit(PLiteral),
|
||||||
Sym(String),
|
Sym(String),
|
||||||
|
Vec(Vec<Spanned<Self>>),
|
||||||
|
|
||||||
Vec(Vec<Self>),
|
Unary(Spanned<PUnaryOp>, Box<Spanned<Self>>),
|
||||||
|
Binary(Spanned<PBinaryOp>, Box<Spanned<Self>>, Box<Spanned<Self>>),
|
||||||
|
|
||||||
UnaryOp(PUnaryOp, Box<Self>),
|
Call(Box<Spanned<Self>>, Vec<Spanned<Self>>),
|
||||||
BinaryOp(PBinaryOp, Box<Self>, Box<Self>),
|
|
||||||
|
|
||||||
Call(Box<Self>, Vec<Self>),
|
|
||||||
Lambda {
|
Lambda {
|
||||||
args: Vec<(String, Type)>,
|
args: Vec<(String, Type)>,
|
||||||
body: Box<Self>,
|
body: Box<Spanned<Self>>,
|
||||||
},
|
},
|
||||||
Let {
|
Let {
|
||||||
vars: Vec<(String, Type, Self)>,
|
vars: Vec<(String, Type, Self)>,
|
||||||
body: Box<Self>,
|
body: Box<Self>,
|
||||||
}
|
},
|
||||||
}
|
}
|
|
@ -24,6 +24,7 @@ pub enum Literal {
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Lit(Literal),
|
Lit(Literal),
|
||||||
Sym(String),
|
Sym(String),
|
||||||
|
Vec(Vec<Self>),
|
||||||
|
|
||||||
UnaryOp(UnaryOp, Box<Self>),
|
UnaryOp(UnaryOp, Box<Self>),
|
||||||
BinaryOp(BinaryOp, Box<Self>, Box<Self>),
|
BinaryOp(BinaryOp, Box<Self>, Box<Self>),
|
||||||
|
@ -44,9 +45,17 @@ impl Display for Expr {
|
||||||
Literal::Bool(b) => write!(f, "{}", b),
|
Literal::Bool(b) => write!(f, "{}", b),
|
||||||
},
|
},
|
||||||
Expr::Sym(s) => write!(f, "{}", s),
|
Expr::Sym(s) => write!(f, "{}", s),
|
||||||
|
Expr::Vec(v) => {
|
||||||
|
write!(f, "[")?;
|
||||||
|
for (i, e) in v.iter().enumerate() {
|
||||||
|
if i > 0 { write!(f, " ")?; }
|
||||||
|
write!(f, "{}", e)?;
|
||||||
|
}
|
||||||
|
write!(f, "]")
|
||||||
|
},
|
||||||
|
|
||||||
Expr::UnaryOp(op, e) => write!(f, "({:?} {})", op, e),
|
Expr::UnaryOp(op, e) => write!(f, "({} {})", format!("{:?}", op).to_lowercase(), e),
|
||||||
Expr::BinaryOp(op, e1, e2) => write!(f, "({:?} {} {})", op, e1, e2),
|
Expr::BinaryOp(op, e1, e2) => write!(f, "({} {} {})", format!("{:?}", op).to_lowercase(), e1, e2),
|
||||||
|
|
||||||
Expr::Call(c, args) => {
|
Expr::Call(c, args) => {
|
||||||
write!(f, "({}", c)?;
|
write!(f, "({}", c)?;
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub enum JSLiteral { Num(i64), Str(String), Bool(bool) }
|
||||||
pub enum JSExpr {
|
pub enum JSExpr {
|
||||||
Lit(JSLiteral),
|
Lit(JSLiteral),
|
||||||
Sym(String),
|
Sym(String),
|
||||||
|
Array(Vec<Self>),
|
||||||
|
|
||||||
Op(&'static str, Box<Self>, Option<Box<Self>>),
|
Op(&'static str, Box<Self>, Option<Box<Self>>),
|
||||||
|
|
||||||
|
@ -29,6 +30,14 @@ impl Display for JSExpr {
|
||||||
JSLiteral::Bool(b) => write!(f, "{}", b),
|
JSLiteral::Bool(b) => write!(f, "{}", b),
|
||||||
},
|
},
|
||||||
JSExpr::Sym(s) => write!(f, "{}", s),
|
JSExpr::Sym(s) => write!(f, "{}", s),
|
||||||
|
JSExpr::Array(v) => {
|
||||||
|
write!(f, "[")?;
|
||||||
|
for (i, e) in v.iter().enumerate() {
|
||||||
|
if i > 0 { write!(f, ", ")?; }
|
||||||
|
write!(f, "{}", e)?;
|
||||||
|
}
|
||||||
|
write!(f, "]")
|
||||||
|
},
|
||||||
|
|
||||||
JSExpr::Op(op, lhs, rhs) => {
|
JSExpr::Op(op, lhs, rhs) => {
|
||||||
match rhs {
|
match rhs {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::parse::past::{PExpr, PLiteral, PBinaryOp, PUnaryOp};
|
use crate::read::past::{PExpr, PLiteral, PBinaryOp, PUnaryOp};
|
||||||
use super::{
|
use super::{
|
||||||
ast::{Expr, Literal, BinaryOp, UnaryOp},
|
ast::{Expr, Literal, BinaryOp, UnaryOp},
|
||||||
js::{JSExpr, JSLiteral},
|
js::{JSExpr, JSLiteral},
|
||||||
|
@ -6,18 +6,21 @@ use super::{
|
||||||
|
|
||||||
pub fn translate_expr(expr: PExpr) -> Expr {
|
pub fn translate_expr(expr: PExpr) -> Expr {
|
||||||
match expr {
|
match expr {
|
||||||
|
PExpr::Error => panic!("Error in expression!"),
|
||||||
|
|
||||||
PExpr::Lit(l) => Expr::Lit(match l {
|
PExpr::Lit(l) => Expr::Lit(match l {
|
||||||
PLiteral::Num(n) => Literal::Num(n),
|
PLiteral::Num(n) => Literal::Num(n),
|
||||||
PLiteral::Str(s) => Literal::Str(s),
|
PLiteral::Str(s) => Literal::Str(s),
|
||||||
PLiteral::Bool(b) => Literal::Bool(b),
|
PLiteral::Bool(b) => Literal::Bool(b),
|
||||||
}),
|
}),
|
||||||
PExpr::Sym(s) => Expr::Sym(s),
|
PExpr::Sym(s) => Expr::Sym(s),
|
||||||
|
PExpr::Vec(v) => Expr::Vec(v.into_iter().map(|e| translate_expr(e.0)).collect()),
|
||||||
|
|
||||||
PExpr::UnaryOp(op, e) => Expr::UnaryOp(match op {
|
PExpr::Unary(op, e) => Expr::UnaryOp(match op.0 {
|
||||||
PUnaryOp::Neg => UnaryOp::Neg,
|
PUnaryOp::Neg => UnaryOp::Neg,
|
||||||
PUnaryOp::Not => UnaryOp::Not,
|
PUnaryOp::Not => UnaryOp::Not,
|
||||||
}, Box::new(translate_expr(*e))),
|
}, Box::new(translate_expr((*e).0))),
|
||||||
PExpr::BinaryOp(op, e1, e2) => Expr::BinaryOp(
|
PExpr::Binary((op, _), e1, e2) => Expr::BinaryOp(
|
||||||
match op {
|
match op {
|
||||||
PBinaryOp::Add => BinaryOp::Add,
|
PBinaryOp::Add => BinaryOp::Add,
|
||||||
PBinaryOp::Sub => BinaryOp::Sub,
|
PBinaryOp::Sub => BinaryOp::Sub,
|
||||||
|
@ -36,33 +39,34 @@ pub fn translate_expr(expr: PExpr) -> Expr {
|
||||||
PBinaryOp::And => BinaryOp::And,
|
PBinaryOp::And => BinaryOp::And,
|
||||||
PBinaryOp::Or => BinaryOp::Or,
|
PBinaryOp::Or => BinaryOp::Or,
|
||||||
},
|
},
|
||||||
Box::new(translate_expr(*e1)),
|
Box::new(translate_expr((*e1).0)),
|
||||||
Box::new(translate_expr(*e2)),
|
Box::new(translate_expr((*e2).0)),
|
||||||
),
|
),
|
||||||
|
|
||||||
PExpr::Call(f, args) => Expr::Call(
|
PExpr::Call(f, args) => Expr::Call(
|
||||||
Box::new(translate_expr(*f)),
|
Box::new(translate_expr((*f).0)),
|
||||||
args.into_iter().map(translate_expr).collect(),
|
args.into_iter().map(|a| translate_expr(a.0)).collect(),
|
||||||
),
|
),
|
||||||
PExpr::Lambda { args, body } => Expr::Lambda {
|
PExpr::Lambda { args, body } => Expr::Lambda {
|
||||||
args,
|
args,
|
||||||
body: Box::new(translate_expr(*body)),
|
body: Box::new(translate_expr((*body).0)),
|
||||||
},
|
},
|
||||||
PExpr::Let { vars, body } => {
|
PExpr::Let { vars, body } => {
|
||||||
let mut expr = *body; // The expression we're building up
|
let mut expr: Expr = translate_expr(*body); // The expression we're building up
|
||||||
for (name, ty, val) in vars.into_iter().rev() { // Reverse so we can build up the lambda
|
for (name, ty, val) in vars.into_iter().rev() { // Reverse so we can build up the lambda
|
||||||
// e.g.: let x : t = e1 in e2 end => (lambda (x : t) = e2)(e1)
|
// e.g.: let x : t = e1 in e2 end => (lambda (x : t) = e2)(e1)
|
||||||
|
|
||||||
// Build up the lambda
|
// Build up the lambda
|
||||||
expr = PExpr::Lambda {
|
expr = Expr::Lambda {
|
||||||
args: vec![(name, ty)],
|
args: vec![(name, ty)],
|
||||||
body: Box::new(expr),
|
body: Box::new(expr),
|
||||||
};
|
};
|
||||||
// Call the lambda with the value
|
// Call the lambda with the value
|
||||||
expr = PExpr::Call(Box::new(expr), vec![val]);
|
let val = translate_expr(val);
|
||||||
|
expr = Expr::Call(Box::new(expr), vec![val]);
|
||||||
}
|
}
|
||||||
|
|
||||||
translate_expr(expr)
|
expr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,6 +79,7 @@ pub fn translate_js(expr: Expr) -> JSExpr {
|
||||||
Literal::Bool(b) => JSExpr::Lit(JSLiteral::Bool(b)),
|
Literal::Bool(b) => JSExpr::Lit(JSLiteral::Bool(b)),
|
||||||
},
|
},
|
||||||
Expr::Sym(s) => JSExpr::Sym(s),
|
Expr::Sym(s) => JSExpr::Sym(s),
|
||||||
|
Expr::Vec(v) => JSExpr::Array(v.into_iter().map(translate_js).collect()),
|
||||||
|
|
||||||
Expr::UnaryOp(op, e) => JSExpr::Op(match op {
|
Expr::UnaryOp(op, e) => JSExpr::Op(match op {
|
||||||
UnaryOp::Neg => "-",
|
UnaryOp::Neg => "-",
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::fmt::{Display, Formatter, Result as FmtResult};
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
Num, Str, Bool,
|
Num, Str, Bool,
|
||||||
|
Sym(String),
|
||||||
Fun(Vec<Self>, Box<Self>),
|
Fun(Vec<Self>, Box<Self>),
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
@ -13,6 +14,7 @@ impl Display for Type {
|
||||||
Type::Num => write!(f, "num"),
|
Type::Num => write!(f, "num"),
|
||||||
Type::Str => write!(f, "str"),
|
Type::Str => write!(f, "str"),
|
||||||
Type::Bool => write!(f, "bool"),
|
Type::Bool => write!(f, "bool"),
|
||||||
|
Type::Sym(s) => write!(f, "{}", s),
|
||||||
Type::Fun(args, ret) => {
|
Type::Fun(args, ret) => {
|
||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
for (i, arg) in args.iter().enumerate() {
|
for (i, arg) in args.iter().enumerate() {
|
||||||
|
|
Loading…
Reference in a new issue