More project cleanup

This commit is contained in:
Garen Tyler 2020-12-10 20:51:49 -07:00
parent e6a0e06384
commit fb1d42d910
5 changed files with 177 additions and 180 deletions

View File

@ -2,5 +2,8 @@ fn main() {
println!("cargo:rerun-if-changed=test.js");
println!("cargo:rerun-if-changed=package.json");
println!("cargo:rerun-if-changed=package-lock.json");
std::process::Command::new("npm").arg("install").output().expect("could not install npm dependencies");
std::process::Command::new("npm")
.arg("install")
.output()
.expect("could not install npm dependencies");
}

View File

@ -1,14 +1,12 @@
use ron::from_str;
use crate::ast::{AstNode, AstNodeKind};
use ron::from_str;
pub struct SymbolGenerator {
counter: usize,
}
impl SymbolGenerator {
pub fn new() -> SymbolGenerator {
SymbolGenerator {
counter: 0,
}
SymbolGenerator { counter: 0 }
}
pub fn next(&mut self) -> usize {
self.counter += 1;
@ -29,12 +27,36 @@ impl Wasm for AstNode {
// Unary operators
Not => format!("(i32.eq (i32.const 0) {})", self.subnodes[1].emit(s)),
// Infix operators
NotEqual => format!("(i32.ne {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)),
Equal => format!("(i32.eq {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)),
Add => format!("(i32.add {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)),
Subtract => format!("(i32.sub {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)),
Multiply => format!("(i32.mul {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)),
Divide => format!("(i32.div_s {} {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)),
NotEqual => format!(
"(i32.ne {} {})",
self.subnodes[0].emit(s),
self.subnodes[1].emit(s)
),
Equal => format!(
"(i32.eq {} {})",
self.subnodes[0].emit(s),
self.subnodes[1].emit(s)
),
Add => format!(
"(i32.add {} {})",
self.subnodes[0].emit(s),
self.subnodes[1].emit(s)
),
Subtract => format!(
"(i32.sub {} {})",
self.subnodes[0].emit(s),
self.subnodes[1].emit(s)
),
Multiply => format!(
"(i32.mul {} {})",
self.subnodes[0].emit(s),
self.subnodes[1].emit(s)
),
Divide => format!(
"(i32.div_s {} {})",
self.subnodes[0].emit(s),
self.subnodes[1].emit(s)
),
// Control flow
Block => {
let mut out = String::new();
@ -46,7 +68,11 @@ impl Wasm for AstNode {
}
IfStatement => {
let mut out = String::new();
out += &format!("(if {} (then {})", self.subnodes[0].emit(s), self.subnodes[1].emit(s)); // Emit the conditional and consequence.
out += &format!(
"(if {} (then {})",
self.subnodes[0].emit(s),
self.subnodes[1].emit(s)
); // Emit the conditional and consequence.
if let Some(alternative) = self.subnodes.get(2) {
out += &format!(" (else {})", alternative.emit(s)); // Emit the alternative.
}
@ -59,7 +85,11 @@ impl Wasm for AstNode {
out += &format!("(block ${}_wrapper", loop_symbol);
out += &format!(" (loop ${}_loop", loop_symbol);
out += &format!(" {}", self.subnodes[1].emit(s));
out += &format!(" (br_if ${}_wrapper (i32.eq (i32.const 0) {}))", loop_symbol, self.subnodes[0].emit(s));
out += &format!(
" (br_if ${}_wrapper (i32.eq (i32.const 0) {}))",
loop_symbol,
self.subnodes[0].emit(s)
);
out += &format!(" (br ${}_loop)", loop_symbol);
out += "))";
out
@ -91,7 +121,7 @@ impl Wasm for AstNode {
}
out += ")";
out
},
}
FunctionReturn => format!("{} (return)", self.subnodes[0].emit(s)),
FunctionDefinition => {
let mut out = String::new();

View File

@ -1,14 +1,10 @@
#![allow(unused_variables)]
#![allow(non_snake_case)]
#![allow(dead_code)]
extern crate regex;
extern crate wat;
pub mod ast;
pub mod parse;
pub mod codegen;
use codegen::{Wasm, SymbolGenerator};
pub mod parse;
use codegen::{SymbolGenerator, Wasm};
pub fn compile<T: Into<String>>(src: T) -> Vec<u8> {
wat::parse_str(compile_wat(src)).unwrap()

View File

@ -4,15 +4,11 @@ use std::ops::Range;
use std::rc::Rc;
pub enum ParserKind {
Literal(String),
Regex(Regex),
Constant(String),
And,
Ignore,
Or,
Repeat(usize),
RepeatRange(Range<usize>),
Error(String),
Map(Rc<Box<dyn Fn(String) -> Result<String, ron::Error>>>),
Custom(Rc<Box<dyn Fn(String) -> Result<(String, String), String>>>),
}
@ -25,15 +21,11 @@ impl std::fmt::Display for ParserKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use ParserKind::*;
match self {
Literal(s) => write!(f, "Literal \"{}\"", s),
Regex(r) => write!(f, "Regex /{}/", r.as_str()),
Constant(c) => write!(f, "Constant \"{}\"", c),
And => write!(f, "And"),
Ignore => write!(f, "Ignore"),
Or => write!(f, "Or"),
Repeat(num) => write!(f, "Repeat {}", num),
RepeatRange(range) => write!(f, "RepeatRange {:?}", range),
Error(msg) => write!(f, "Error \"{}\"", msg),
Map(_) => write!(f, "Map"),
Custom(_) => write!(f, "Custom"),
}
@ -43,15 +35,11 @@ impl Clone for ParserKind {
fn clone(&self) -> Self {
use ParserKind::*;
match self {
Literal(s) => Literal(s.clone()),
Regex(r) => Regex(r.clone()),
Constant(c) => Constant(c.clone()),
And => And,
Ignore => Ignore,
Or => Or,
Repeat(num) => Repeat(num.clone()),
RepeatRange(range) => RepeatRange(range.clone()),
Error(msg) => Error(msg.clone()),
Map(cfn) => Map(Rc::clone(cfn)),
Custom(cfn) => Custom(Rc::clone(cfn)),
}
@ -78,13 +66,6 @@ impl Parser {
use ParserKind::*;
let s: String = src.into();
match &self.kind {
Literal(literal) => {
if s.len() >= literal.len() && s[..literal.len()] == literal[..] {
Ok((s[..literal.len()].to_owned(), s[literal.len()..].to_owned()))
} else {
Err(s)
}
}
Regex(re) => {
if let Some(mat) = re.find(&s) {
if mat.start() == 0 {
@ -99,10 +80,8 @@ impl Parser {
Err(s)
}
}
Constant(constant) => Ok((constant.clone(), s)),
And => {
if self.subparsers[0].kind == Ignore
&& self.subparsers[1].kind == Ignore {
if self.subparsers[0].kind == Ignore && self.subparsers[1].kind == Ignore {
Ok(("".into(), s))
} else if self.subparsers[0].kind == Ignore {
let (_, rest) = self.subparsers[0].parse(s)?;
@ -123,9 +102,7 @@ impl Parser {
))
}
}
Ignore => {
Ok(("".into(), self.subparsers[0].parse(s)?.1))
}
Ignore => Ok(("".into(), self.subparsers[0].parse(s)?.1)),
Or => {
if let Ok(lresult) = self.subparsers[0].parse(s.clone()) {
Ok(lresult)
@ -133,16 +110,6 @@ impl Parser {
self.subparsers[1].parse(s.clone())
}
}
Repeat(num_repeats) => {
let mut matched = vec![];
let mut rest = s.clone();
for _ in 0..*num_repeats {
let (m, r) = self.subparsers[0].parse(rest)?;
matched.push(m);
rest = r;
}
Ok((to_string(&matched).unwrap(), rest))
}
RepeatRange(range) => {
let mut matched = vec![];
let mut rest = s.clone();
@ -169,7 +136,6 @@ impl Parser {
Ok((to_string(&matched).unwrap(), rest))
}
Error(msg) => panic!(msg.clone()),
Map(cfn) => {
let (matched, rest) = self.subparsers[0].parse(s)?;
if let Ok(m) = cfn(matched) {
@ -178,37 +144,17 @@ impl Parser {
Err(rest)
}
}
Custom(cfn) => {
cfn(s)
}
Custom(cfn) => cfn(s),
}
}
// Static
pub fn literal<T: Into<String>>(s: T) -> Parser {
Parser {
kind: ParserKind::Literal(s.into()),
subparsers: vec![],
}
}
pub fn regex<T: Into<String>>(s: T) -> Parser {
Parser {
kind: ParserKind::Regex(Regex::new(&s.into()).expect("could not compile regex")),
subparsers: vec![],
}
}
pub fn constant<T: Into<String>>(s: T) -> Parser {
Parser {
kind: ParserKind::Constant(s.into()),
subparsers: vec![],
}
}
pub fn error<T: Into<String>>(s: T) -> Parser {
Parser {
kind: ParserKind::Error(s.into()),
subparsers: vec![],
}
}
pub fn custom<F: 'static>(cfn: F) -> Parser
where
F: Fn(String) -> Result<(String, String), String>,
@ -238,12 +184,6 @@ impl Parser {
subparsers: vec![self, r],
}
}
pub fn repeat(self, num_repeats: usize) -> Parser {
Parser {
kind: ParserKind::Repeat(num_repeats),
subparsers: vec![self],
}
}
pub fn repeat_range(self, num_repeats: Range<usize>) -> Parser {
Parser {
kind: ParserKind::RepeatRange(num_repeats),

View File

@ -9,8 +9,12 @@ pub fn parse<T: Into<String>>(src: T) -> AstNode {
let whitespace = Parser::regex(r"[ \n\r\t]+");
let comments = Parser::regex(r"[/][/].*").or(Parser::regex(r"[/][*].*[*][/]"));
let ignored = whitespace.or(comments).repeat_range(0..usize::MAX);
let statement = ignored.optional().ignore().and(Parser::custom(parse_statement));
let parse_program = statement.clone()
let statement = ignored
.optional()
.ignore()
.and(Parser::custom(parse_statement));
let parse_program = statement
.clone()
.repeat_range(0..usize::MAX)
.map(|matched| {
let data = from_str::<Vec<String>>(&matched)?;
@ -30,44 +34,51 @@ fn parse_statement(src: String) -> Result<(String, String), String> {
let i = ignored.clone();
let token = move |pattern: &str| i.clone().ignore().and(Parser::regex(pattern));
// Token helper parsers.
let FUNCTION = Parser::regex(r"function\b").or(ignored.clone());
let RETURN = token(r"return\b");
let SEMICOLON = token(r"[;]");
let IF = token(r"if\b");
let ELSE = token(r"else\b");
let LEFT_PAREN = token(r"[(]");
let RIGHT_PAREN = token(r"[)]");
let LEFT_BRACE = token(r"[{]");
let RIGHT_BRACE = token(r"[}]");
let WHILE = token(r"while\b");
let VAR = token(r"var\b");
let IDENTIFIER = token(r"[a-zA-Z_][a-zA-Z0-9_]*")
let function = Parser::regex(r"function\b").or(ignored.clone());
let return_token = token(r"return\b");
let semicolon = token(r"[;]");
let if_token = token(r"if\b");
let else_token = token(r"else\b");
let left_paren = token(r"[(]");
let right_paren = token(r"[)]");
let left_brace = token(r"[{]");
let right_brace = token(r"[}]");
let while_token = token(r"while\b");
let var = token(r"var\b");
let identifier = token(r"[a-zA-Z_][a-zA-Z0-9_]*")
.map(|matched| Ok(to_string(&AstNode::identifier(matched))?));
let ASSIGN =
token(r"=").map(|matched| Ok(to_string(&AstNode::assign("".into(), AstNode::null()))?));
let COMMA = token(r"[,]");
let assign =
token(r"=").map(|_matched| Ok(to_string(&AstNode::assign("".into(), AstNode::null()))?));
let comma = token(r"[,]");
let expression = Parser::custom(parse_expression);
let statement = Parser::custom(parse_statement);
let return_statement = RETURN.clone().ignore()
let return_statement = return_token
.clone()
.ignore()
.and(expression.clone())
.and(SEMICOLON.clone().ignore())
.and(semicolon.clone().ignore())
.map(|matched| {
let data = from_str::<AstNode>(&matched)?;
Ok(to_string(&AstNode::function_return(data))?)
});
let expression_statement = expression.clone()
.and(SEMICOLON.clone().ignore());
let if_statement = IF.clone().ignore()
let expression_statement = expression.clone().and(semicolon.clone().ignore());
let if_statement = if_token
.clone()
.ignore()
.and(
LEFT_PAREN.clone().ignore()
.and(expression.clone())
.and(RIGHT_PAREN.clone().ignore())
left_paren
.clone()
.ignore()
.and(expression.clone())
.and(right_paren.clone().ignore()),
)
.and(statement.clone())
.and(
ELSE.clone().ignore()
.and(statement.clone())
.optional()
else_token
.clone()
.ignore()
.and(statement.clone())
.optional(),
)
.map(|matched| {
let data = from_str::<Vec<String>>(&matched)?;
@ -79,13 +90,21 @@ fn parse_statement(src: String) -> Result<(String, String), String> {
let others = from_str::<Vec<String>>(&data[0])?;
let conditional = from_str::<AstNode>(&others[0])?;
let consequence = from_str::<AstNode>(&others[1])?;
Ok(to_string(&AstNode::if_statement(conditional, consequence, alternative))?)
Ok(to_string(&AstNode::if_statement(
conditional,
consequence,
alternative,
))?)
});
let while_statement = WHILE.clone().ignore()
let while_statement = while_token
.clone()
.ignore()
.and(
LEFT_PAREN.clone().ignore()
.and(expression.clone())
.and(RIGHT_PAREN.clone().ignore())
left_paren
.clone()
.ignore()
.and(expression.clone())
.and(right_paren.clone().ignore()),
)
.and(statement.clone())
.map(|matched| {
@ -94,30 +113,35 @@ fn parse_statement(src: String) -> Result<(String, String), String> {
let body = from_str::<AstNode>(&data[1])?;
Ok(to_string(&AstNode::while_loop(conditional, body))?)
});
let var_statement = VAR.clone().ignore()
.and(IDENTIFIER.clone())
.and(ASSIGN.clone().ignore())
let var_statement = var
.clone()
.ignore()
.and(identifier.clone())
.and(assign.clone().ignore())
.and(expression.clone())
.and(SEMICOLON.clone().ignore())
.and(semicolon.clone().ignore())
.map(|matched| {
let data = from_str::<Vec<String>>(&matched)?;
let name = from_str::<AstNode>(&data[0])?.value;
let value = from_str::<AstNode>(&data[1])?;
Ok(to_string(&AstNode::variable_definition(name, value))?)
});
let assignment_statement = IDENTIFIER.clone()
.and(ASSIGN.clone().ignore())
let assignment_statement = identifier
.clone()
.and(assign.clone().ignore())
.and(expression.clone())
.and(SEMICOLON.clone().ignore())
.and(semicolon.clone().ignore())
.map(|matched| {
let data = from_str::<Vec<String>>(&matched)?;
let name = from_str::<AstNode>(&data[0])?.value;
let value = from_str::<AstNode>(&data[1])?;
Ok(to_string(&AstNode::assign(name, value))?)
});
let block_statement = LEFT_BRACE.clone().ignore()
let block_statement = left_brace
.clone()
.ignore()
.and(statement.clone().repeat_range(0..usize::MAX))
.and(RIGHT_BRACE.clone().ignore())
.and(right_brace.clone().ignore())
.map(|matched| {
let data = from_str::<Vec<String>>(&matched)?;
let mut statements = vec![];
@ -126,10 +150,13 @@ fn parse_statement(src: String) -> Result<(String, String), String> {
}
Ok(to_string(&AstNode::block(statements))?)
});
let args = IDENTIFIER.clone()
let args = identifier
.clone()
.and(
COMMA.clone().ignore()
.and(IDENTIFIER.clone())
comma
.clone()
.ignore()
.and(identifier.clone())
.repeat_range(0..usize::MAX),
)
.map(|matched| {
@ -142,12 +169,16 @@ fn parse_statement(src: String) -> Result<(String, String), String> {
}
Ok(to_string(&args)?)
});
let function_statement = FUNCTION.clone().ignore()
.and(IDENTIFIER.clone())
let function_statement = function
.clone()
.ignore()
.and(identifier.clone())
.and(
LEFT_PAREN.clone().ignore()
.and(args.clone().optional())
.and(RIGHT_PAREN.clone().ignore())
left_paren
.clone()
.ignore()
.and(args.clone().optional())
.and(right_paren.clone().ignore()),
)
.and(block_statement.clone())
.map(|matched| {
@ -169,16 +200,22 @@ fn parse_statement(src: String) -> Result<(String, String), String> {
match node.kind {
AstNodeKind::VariableDefinition => {
vars.push(AstNode::variable_declaration(node.value.clone()));
others.push(AstNode::assign(node.value.clone(), node.subnodes[0].clone()))
},
others.push(AstNode::assign(
node.value.clone(),
node.subnodes[0].clone(),
))
}
_ => others.push(node.clone()),
}
}
vars.append(&mut others);
body.subnodes = vars;
Ok(to_string(&AstNode::function_definition(name, parameters, body))?)
Ok(to_string(&AstNode::function_definition(
name, parameters, body,
))?)
});
return_statement.clone()
return_statement
.clone()
.or(if_statement.clone())
.or(while_statement.clone())
.or(var_statement.clone())
@ -196,55 +233,44 @@ fn parse_expression(src: String) -> Result<(String, String), String> {
let i = ignored.clone();
let token = move |pattern: &str| i.clone().ignore().and(Parser::regex(pattern));
// Token helper parsers.
let FUNCTION = Parser::regex(r"function\b").or(ignored.clone());
let IF = token(r"if\b");
let ELSE = token(r"else\b");
let RETURN = token(r"return\b");
let VAR = token(r"var\b");
let WHILE = token(r"while\b");
let COMMA = token(r"[,]");
let SEMICOLON = token(r"[;]");
let LEFT_PAREN = token(r"[(]");
let RIGHT_PAREN = token(r"[)]");
let LEFT_BRACE = token(r"[{]");
let RIGHT_BRACE = token(r"[}]");
let NUMBER = token(r"[0-9]+").map(|matched| {
let comma = token(r"[,]");
let left_paren = token(r"[(]");
let right_paren = token(r"[)]");
let number = token(r"[0-9]+").map(|matched| {
Ok(to_string(&AstNode::integer(
matched.parse::<i64>().unwrap(),
))?)
});
let IDENTIFIER = token(r"[a-zA-Z_][a-zA-Z0-9_]*")
let identifier = token(r"[a-zA-Z_][a-zA-Z0-9_]*")
.map(|matched| Ok(to_string(&AstNode::identifier(matched))?));
let NOT = token(r"!").map(|matched| Ok(to_string(&AstNode::not(AstNode::null()))?));
let ASSIGN =
token(r"=").map(|matched| Ok(to_string(&AstNode::assign("".into(), AstNode::null()))?));
let EQUAL = token(r"==").map(|matched| {
let not = token(r"!").map(|_matched| Ok(to_string(&AstNode::not(AstNode::null()))?));
let equal = token(r"==").map(|_matched| {
Ok(to_string(&AstNode::equal(
AstNode::null(),
AstNode::null(),
))?)
});
let NOT_EQUAL = token(r"!=").map(|matched| {
let not_equal = token(r"!=").map(|_matched| {
Ok(to_string(&AstNode::not_equal(
AstNode::null(),
AstNode::null(),
))?)
});
let PLUS = token(r"[+]")
.map(|matched| Ok(to_string(&AstNode::add(AstNode::null(), AstNode::null()))?));
let MINUS = token(r"[-]").map(|matched| {
let plus = token(r"[+]")
.map(|_matched| Ok(to_string(&AstNode::add(AstNode::null(), AstNode::null()))?));
let minus = token(r"[-]").map(|_matched| {
Ok(to_string(&AstNode::subtract(
AstNode::null(),
AstNode::null(),
))?)
});
let STAR = token(r"[*]").map(|matched| {
let star = token(r"[*]").map(|_matched| {
Ok(to_string(&AstNode::multiply(
AstNode::null(),
AstNode::null(),
))?)
});
let SLASH = token(r"[/]").map(|matched| {
let slash = token(r"[/]").map(|_matched| {
Ok(to_string(&AstNode::divide(
AstNode::null(),
AstNode::null(),
@ -253,9 +279,12 @@ fn parse_expression(src: String) -> Result<(String, String), String> {
// Expression parser.
let expression = Parser::custom(parse_expression);
// Call parser.
let args = expression.clone()
let args = expression
.clone()
.and(
COMMA.clone().ignore()
comma
.clone()
.ignore()
.and(expression.clone())
.repeat_range(0..usize::MAX),
)
@ -269,10 +298,11 @@ fn parse_expression(src: String) -> Result<(String, String), String> {
}
Ok(to_string(&args)?)
});
let call = IDENTIFIER.clone()
.and(LEFT_PAREN.clone().ignore())
let call = identifier
.clone()
.and(left_paren.clone().ignore())
.and(args.clone().optional())
.and(RIGHT_PAREN.clone().ignore())
.and(right_paren.clone().ignore())
.map(|matched| {
let data = from_str::<Vec<String>>(&matched)?;
let callee = data[0].clone();
@ -284,22 +314,20 @@ fn parse_expression(src: String) -> Result<(String, String), String> {
ast_args.push(from_str::<AstNode>(arg)?);
}
}
Ok(to_string(
&AstNode::function_call(callee, ast_args),
)?)
Ok(to_string(&AstNode::function_call(callee, ast_args))?)
});
// Atom parser.
let atom = call
.clone()
.or(IDENTIFIER.clone())
.or(NUMBER.clone())
.or(
LEFT_PAREN.clone().ignore()
.and(expression.clone())
.and(RIGHT_PAREN.clone().ignore())
);
.or(identifier.clone())
.or(number.clone())
.or(left_paren
.clone()
.ignore()
.and(expression.clone())
.and(right_paren.clone().ignore()));
// Unary operator parsers.
let unary = NOT.clone().optional().and(atom.clone()).map(|matched| {
let unary = not.clone().optional().and(atom.clone()).map(|matched| {
let data = from_str::<Vec<String>>(&matched)?;
let atom_data = from_str::<AstNode>(&data[1])?;
Ok(to_string(&match &data[0][..] {
@ -331,8 +359,8 @@ fn parse_expression(src: String) -> Result<(String, String), String> {
Ok(to_string(&current)?)
})
};
let product = infix(STAR.clone().or(SLASH.clone()), unary.clone());
let sum = infix(PLUS.clone().or(MINUS.clone()), product.clone());
let comparison = infix(EQUAL.clone().or(NOT_EQUAL.clone()), sum.clone());
let product = infix(star.clone().or(slash.clone()), unary.clone());
let sum = infix(plus.clone().or(minus.clone()), product.clone());
let comparison = infix(equal.clone().or(not_equal.clone()), sum.clone());
comparison.parse(src)
}