allow let without body

pull/5/head
azur 2023-03-04 23:20:43 +07:00
parent b72121e256
commit c061c6d038
7 changed files with 407 additions and 66 deletions

313
Cargo.lock generated Normal file
View File

@ -0,0 +1,313 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom",
"once_cell",
"version_check",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chumsky"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23170228b96236b5a7299057ac284a321457700bc8c41a4476052f0f4ba5349d"
dependencies = [
"hashbrown",
"stacker",
]
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "getrandom"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash",
]
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
dependencies = [
"unicode-ident",
]
[[package]]
name = "psm"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
dependencies = [
"cc",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "renxi"
version = "0.1.0"
dependencies = [
"chumsky",
"structopt",
]
[[package]]
name = "stacker"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
dependencies = [
"cc",
"cfg-if",
"libc",
"psm",
"winapi",
]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "structopt"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
dependencies = [
"clap",
"lazy_static",
"structopt-derive",
]
[[package]]
name = "structopt-derive"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "unicode-ident"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "775c11906edafc97bc378816b94585fbd9a054eabaf86fdd0ced94af449efab7"
[[package]]
name = "unicode-segmentation"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
[[package]]
name = "unicode-width"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

14
a.hlm
View File

@ -1,9 +1,7 @@
func add (x: num) num = (\a: num -> a + 1)(x);
let x: num = 34,
y: num = 35
in
println(x + y);
println(
{
println("Hello");
return let x: num = 17 * 2 in
add(x);
} + 34
);
let foo: num = 69;
println(foo);

View File

@ -16,7 +16,7 @@ pub enum BinaryOp {
#[derive(Clone, Debug)]
pub enum Literal {
Num(i64), Str(String), Bool(bool),
Num(i64), Str(String), Bool(bool), Unit,
}
/// Enum to represent internal expression
@ -31,19 +31,19 @@ pub enum Expr {
Call(Box<Self>, Vec<Self>),
Lambda {
args: Vec<(String, Type)>,
args: Vec<String>,
body: Vec<Self>,
},
Defines(Vec<(String, Self)>),
Return(Box<Self>),
}
#[derive(Clone, Debug)]
pub enum Stmt {
Expr(Expr),
Let(Vec<(String, Type, Expr)>),
Func {
name: String,
args: Vec<(String, Type)>,
args: Vec<String>,
ret: Type,
body: Expr,
},
@ -56,6 +56,7 @@ impl Display for Expr {
Literal::Num(n) => write!(f, "{}", n),
Literal::Str(s) => write!(f, "\"{}\"", s),
Literal::Bool(b) => write!(f, "{}", b),
Literal::Unit => write!(f, "()"),
},
Expr::Sym(s) => write!(f, "{}", s),
Expr::Vec(v) => {
@ -79,8 +80,8 @@ impl Display for Expr {
},
Expr::Lambda { args, body } => {
write!(f, "(lambda ")?;
for (name, ty) in args {
write!(f, "[{} {}]", name, ty)?;
for arg in args {
write!(f, " {}", arg)?;
}
if body.len() == 1 {
write!(f, " {})", body[0])
@ -92,6 +93,13 @@ impl Display for Expr {
write!(f, "))")
}
},
Expr::Defines(defs) => {
write!(f, "(defs ")?;
for (name, expr) in defs {
write!(f, "({} {})", name, expr)?;
}
write!(f, ")")
},
Expr::Return(e) => write!(f, "(return {})", e),
}
}
@ -101,17 +109,10 @@ impl Display for Stmt {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
match self {
Stmt::Expr(e) => write!(f, "{}", e),
Stmt::Let(vars) => {
write!(f, "(let")?;
for (name, ty, e) in vars {
write!(f, " [{} {} {}]", name, ty, e)?;
}
write!(f, ")")
},
Stmt::Func { name, args, ret, body } => {
write!(f, "(defn {} [", name)?;
for (name, ty) in args {
write!(f, "[{} {}]", name, ty)?;
for name in args {
write!(f, " {}", name)?;
}
write!(f, "] {} {})", ret, body)
},

View File

@ -2,7 +2,7 @@ use std::fmt::{Display, Formatter, Result as FmtResult};
use crate::trans::ty::Type;
#[derive(Clone, Debug)]
pub enum JSLiteral { Num(i64), Str(String), Bool(bool) }
pub enum JSLiteral { Num(i64), Str(String), Bool(bool), Undefined }
/// Enum to represent javascript expression
#[derive(Clone, Debug)]
@ -16,19 +16,19 @@ pub enum JSExpr {
Call(Box<Self>, Vec<Self>),
Method(Box<Self>, String, Vec<Self>),
Lambda {
args: Vec<(String, Type)>,
args: Vec<String>,
body: Vec<Self>,
},
Defines(Vec<(String, Self)>),
Return(Box<Self>),
}
#[derive(Clone, Debug)]
pub enum JSStmt {
Expr(JSExpr),
Let(Vec<(String, Type, JSExpr)>),
Func {
name: String,
args: Vec<(String, Type)>,
args: Vec<String>,
ret: Type,
body: JSExpr,
},
@ -38,9 +38,10 @@ impl Display for JSExpr {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
match self {
JSExpr::Lit(l) => match l {
JSLiteral::Num(n) => write!(f, "{}", n),
JSLiteral::Str(s) => write!(f, "'{}'", s),
JSLiteral::Bool(b) => write!(f, "{}", b),
JSLiteral::Num(n) => write!(f, "{}", n),
JSLiteral::Str(s) => write!(f, "'{}'", s),
JSLiteral::Bool(b) => write!(f, "{}", b),
JSLiteral::Undefined => write!(f, "undefined"),
},
JSExpr::Sym(s) => write!(f, "{}", s),
JSExpr::Array(v) => {
@ -81,7 +82,7 @@ impl Display for JSExpr {
},
JSExpr::Lambda { args, body } => {
write!(f, "((")?;
for (i, (name, _ty)) in args.iter().enumerate() {
for (i, name) in args.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
@ -98,6 +99,23 @@ impl Display for JSExpr {
write!(f, "}})")
}
},
JSExpr::Defines(vs) => {
write!(f, "let [")?;
for (i, (name, _)) in vs.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", name)?;
}
write!(f, "] = [")?;
for (i, (_, expr)) in vs.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", expr)?;
}
write!(f, "]")
}
JSExpr::Return(e) => write!(f, "return {}", e),
}
}
@ -107,20 +125,10 @@ impl Display for JSStmt {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
match self {
JSStmt::Expr(e) => write!(f, "{}", e),
JSStmt::Let(vars) => {
write!(f, "let ")?;
for (i, (name, _ty, e)) in vars.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{} = {}", name, e)?;
}
write!(f, ";")
},
JSStmt::Func { name, args, ret: _, body } => {
// const name = (args) => body;
write!(f, "const {} = (", name)?;
for (i, (name, _ty)) in args.iter().enumerate() {
for (i, name) in args.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}

View File

@ -16,7 +16,7 @@ pub enum PBinaryOp {
}
#[derive(Clone, Debug)]
pub enum PLiteral { Num(i64), Str(String), Bool(bool) }
pub enum PLiteral { Num(i64), Str(String), Bool(bool), Unit }
#[derive(Clone, Debug)]
pub enum PExpr {
@ -36,7 +36,7 @@ pub enum PExpr {
},
Let {
vars: Vec<(String, Type, Spanned<Self>)>,
body: Box<Spanned<Self>>,
body: Option<Box<Spanned<Self>>>,
},
Block(Vec<Spanned<Self>>),
Return(Box<Spanned<Self>>),

View File

@ -295,10 +295,16 @@ pub fn expr_parser() -> impl P<Spanned<PExpr>> {
.then(expr.clone())
.map(|(vars, body)| PExpr::Let {
vars,
body: Box::new(body),
body: Some(Box::new(body)),
})
.boxed()
.labelled("let..in");
.labelled("let with expression");
let let_def = just(Token::Let)
.ignore_then(let_binds)
.map(|vars| PExpr::Let { vars, body: None })
.boxed()
.labelled("let definition");
let block = nested_parser(
expr.clone()
@ -322,6 +328,7 @@ pub fn expr_parser() -> impl P<Spanned<PExpr>> {
.or(paren_expr)
.or(lam)
.or(let_in)
.or(let_def)
.or(block)
.or(ret)
.map_with_span(|e, s| (e, s))

View File

@ -10,13 +10,21 @@ pub fn translate_stmt(stmt: PStmt) -> Stmt {
PStmt::Let(vars) => todo!(),
PStmt::Func { name, args, ret, body } => Stmt::Func {
name,
args,
args: args.into_iter().map(|(name, _ty)| name).collect(),
ret,
body: translate_expr(body.0),
},
}
}
pub fn exprs_to_lam(es: Vec<PExpr>) -> Expr {
let lam = Expr::Lambda {
args: vec![],
body: es.into_iter().map(|e| translate_expr(e)).collect(),
};
Expr::Call(Box::new(lam), vec![])
}
pub fn translate_expr(expr: PExpr) -> Expr {
match expr {
PExpr::Error => panic!("Error in expression!"),
@ -25,6 +33,7 @@ pub fn translate_expr(expr: PExpr) -> Expr {
PLiteral::Num(n) => Literal::Num(n),
PLiteral::Str(s) => Literal::Str(s),
PLiteral::Bool(b) => Literal::Bool(b),
PLiteral::Unit => Literal::Unit,
}),
PExpr::Sym(s) => Expr::Sym(s),
PExpr::Vec(v) => Expr::Vec(v.into_iter().map(|e| translate_expr(e.0)).collect()),
@ -61,30 +70,32 @@ pub fn translate_expr(expr: PExpr) -> Expr {
args.into_iter().map(|a| translate_expr(a.0)).collect(),
),
PExpr::Lambda { args, body } => Expr::Lambda {
args,
args: args.into_iter().map(|(name, _ty)| name).collect(),
body: vec![translate_expr((*body).0)],
},
PExpr::Let { vars, body } => {
let mut expr: Expr = translate_expr(body.0); // The expression we're building up
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; => (lambda (x : t) = e2)(e1)
// Build up the lambda
expr = Expr::Lambda {
args: vec![(name, ty)],
body: vec![expr],
};
// Call the lambda with the value
let val = translate_expr(val.0);
expr = Expr::Call(Box::new(expr), vec![val]);
if let Some(body) = body {
let mut expr: Expr = translate_expr(body.0); // The expression we're building up
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; => (lambda (x : t) = e2)(e1)
// Build up the lambda
expr = Expr::Lambda {
args: vec![name],
body: vec![expr],
};
// Call the lambda with the value
let val = translate_expr(val.0);
expr = Expr::Call(Box::new(expr), vec![val]);
}
expr
} else {
Expr::Defines(vars.into_iter().map(|(name, _ty, val)| {
(name, translate_expr(val.0))
}).collect())
}
expr
},
PExpr::Block(es) => {
let lam = Expr::Lambda {
args: vec![],
body: es.into_iter().map(|e| translate_expr(e.0)).collect(),
};
Expr::Call(Box::new(lam), vec![])
exprs_to_lam(es.into_iter().map(|e| e.0).collect())
},
PExpr::Return(e) => Expr::Return(Box::new(translate_expr((*e).0))),
}
@ -93,7 +104,6 @@ pub fn translate_expr(expr: PExpr) -> Expr {
pub fn translate_js_stmt(stmt: Stmt) -> JSStmt {
match stmt {
Stmt::Expr(e) => JSStmt::Expr(translate_js_expr(e)),
Stmt::Let(vars) => todo!(),
Stmt::Func { name, args, ret, body } => JSStmt::Func {
name,
args,
@ -109,6 +119,7 @@ pub fn translate_js_expr(expr: Expr) -> JSExpr {
Literal::Num(n) => JSExpr::Lit(JSLiteral::Num(n)),
Literal::Str(s) => JSExpr::Lit(JSLiteral::Str(s)),
Literal::Bool(b) => JSExpr::Lit(JSLiteral::Bool(b)),
Literal::Unit => JSExpr::Lit(JSLiteral::Undefined),
},
Expr::Sym(s) => JSExpr::Sym(s),
Expr::Vec(v) => JSExpr::Array(v.into_iter().map(translate_js_expr).collect()),
@ -162,6 +173,9 @@ pub fn translate_js_expr(expr: Expr) -> JSExpr {
args,
body: body.into_iter().map(translate_js_expr).collect(),
},
Expr::Defines(defs) => JSExpr::Defines(defs.into_iter().map(|(name, val)| {
(name, translate_js_expr(val))
}).collect()),
Expr::Return(e) => JSExpr::Return(Box::new(translate_js_expr(*e))),
}
}