i32s, variables, and addition
This commit is contained in:
commit
ef6b222db2
|
@ -0,0 +1 @@
|
|||
/target
|
|
@ -0,0 +1,366 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc948ebb96241bb40ab73effeb80d9f93afaad49359d159a5e61be51619fe813"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "downcast-rs"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||
|
||||
[[package]]
|
||||
name = "dust-bunny"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"wasm-encoder",
|
||||
"wasmi",
|
||||
"wasmprinter",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leb128"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565"
|
||||
|
||||
[[package]]
|
||||
name = "memory_units"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "905708f7f674518498c1f8d644481440f476d39ca6ecae83319bba7c6c12da91"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5803d8284a629cc999094ecd630f55e91b561a1d1ba75e233b00ae13b91a69ad"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
"sha-1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-encoder"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d443c5a7daae71697d97ec12ad70b4fe8766d3a0f4db16158ac8b781365892f7"
|
||||
dependencies = [
|
||||
"leb128",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmi"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81a9c47f1785842298b082431a60d6c27bbceda84ff14558598ba44f5c609ccd"
|
||||
dependencies = [
|
||||
"spin",
|
||||
"wasmi_core",
|
||||
"wasmparser-nostd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmi_core"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a53379aecfee3604c2423dddbbecf1d65e0327b0249812dcc2737e5a1db43b5"
|
||||
dependencies = [
|
||||
"downcast-rs",
|
||||
"libm",
|
||||
"memory_units",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.89.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5d3e08b13876f96dd55608d03cd4883a0545884932d5adf11925876c96daef"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser-nostd"
|
||||
version = "0.83.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58a45f1058fed5ce7ff3da64153d0537a1ae664d09855fbb1402c6472f09571b"
|
||||
|
||||
[[package]]
|
||||
name = "wasmprinter"
|
||||
version = "0.2.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa9e5ee2f56cc8a5da489558114e8c118e5a8416d96aefe63dcf1b5b05b858c6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"wasmparser",
|
||||
]
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "dust-bunny"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
pest = "2.3"
|
||||
pest_derive = "2"
|
||||
wasm-encoder = "0.16"
|
||||
wasmi = "0.15"
|
||||
wasmprinter = "0.2"
|
|
@ -0,0 +1,84 @@
|
|||
use crate::parse::{PestPair, Rule as PestRule};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct Span<'a> {
|
||||
pub slice: &'a str,
|
||||
pub line: usize,
|
||||
pub column: usize,
|
||||
}
|
||||
|
||||
impl<'a> From<pest::Span<'a>> for Span<'a> {
|
||||
fn from(other: pest::Span<'a>) -> Self {
|
||||
let slice = other.as_str();
|
||||
let (line, column) = other.start_pos().line_col();
|
||||
Self {
|
||||
slice,
|
||||
line,
|
||||
column,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct BranchBody<'a> {
|
||||
pub statements: Vec<Statement<'a>>,
|
||||
pub tail_expr: Option<Box<Expr<'a>>>,
|
||||
}
|
||||
|
||||
pub type ExprPair<'a> = Box<(Expr<'a>, Expr<'a>)>;
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum Expr<'a> {
|
||||
BinaryOp(BinaryOp, ExprPair<'a>),
|
||||
Literal(Literal<'a>),
|
||||
Local(Span<'a>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum BinaryOp {
|
||||
Add,
|
||||
}
|
||||
|
||||
impl FromStr for BinaryOp {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
use BinaryOp::*;
|
||||
match s {
|
||||
"+" => Ok(Add),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<PestPair<'a>> for BinaryOp {
|
||||
fn from(other: PestPair<'a>) -> Self {
|
||||
assert_eq!(other.as_rule(), PestRule::binary_op);
|
||||
let span = other.as_span().as_str();
|
||||
Self::from_str(span).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum Literal<'a> {
|
||||
DecimalInteger(Span<'a>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum Statement<'a> {
|
||||
Let { ident: Ident<'a>, expr: Expr<'a> },
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct Ident<'a> {
|
||||
pub span: Span<'a>,
|
||||
}
|
||||
|
||||
impl<'a> From<PestPair<'a>> for Ident<'a> {
|
||||
fn from(other: PestPair<'a>) -> Self {
|
||||
assert_eq!(other.as_rule(), PestRule::identifier);
|
||||
let span = other.as_span().into();
|
||||
Self { span }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
use crate::ast::*;
|
||||
use std::collections::HashMap;
|
||||
use wasm_encoder::{Function, Instruction, ValType};
|
||||
|
||||
pub struct FunctionBuilder {
|
||||
locals: Vec<ValType>,
|
||||
local_names: HashMap<String, u32>,
|
||||
instructions: Vec<Instruction<'static>>,
|
||||
}
|
||||
|
||||
impl FunctionBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
locals: Vec::new(),
|
||||
local_names: HashMap::new(),
|
||||
instructions: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_instr(&mut self, instr: Instruction<'static>) {
|
||||
self.instructions.push(instr);
|
||||
}
|
||||
|
||||
pub fn add_local(&mut self, name: &str, ty: ValType) -> u32 {
|
||||
let index = self.locals.len() as u32;
|
||||
self.locals.push(ty);
|
||||
self.local_names.insert(name.to_string(), index);
|
||||
index
|
||||
}
|
||||
|
||||
pub fn get_local(&self, name: &str) -> u32 {
|
||||
*self.local_names.get(name).unwrap()
|
||||
}
|
||||
|
||||
pub fn finish(self) -> Function {
|
||||
let mut func = Function::new_with_locals_types(self.locals.into_iter());
|
||||
|
||||
for instr in self.instructions.into_iter() {
|
||||
func.instruction(&instr);
|
||||
}
|
||||
|
||||
func.instruction(&Instruction::End);
|
||||
|
||||
func
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_branch(ctx: &mut FunctionBuilder, ast: &BranchBody) {
|
||||
for stmt in ast.statements.iter() {
|
||||
match stmt {
|
||||
Statement::Let { ident, expr } => {
|
||||
codegen_expr(ctx, expr);
|
||||
let idx = ctx.add_local(ident.span.slice, ValType::I32);
|
||||
ctx.push_instr(Instruction::LocalSet(idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(expr) = ast.tail_expr.as_ref() {
|
||||
codegen_expr(ctx, expr);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_expr(ctx: &mut FunctionBuilder, ast: &Expr) {
|
||||
match ast {
|
||||
Expr::BinaryOp(op, sides) => {
|
||||
codegen_expr(ctx, &sides.0);
|
||||
codegen_expr(ctx, &sides.1);
|
||||
|
||||
let instr = match op {
|
||||
BinaryOp::Add => Instruction::I32Add,
|
||||
};
|
||||
|
||||
ctx.push_instr(instr);
|
||||
}
|
||||
Expr::Literal(lit) => match lit {
|
||||
Literal::DecimalInteger(span) => {
|
||||
let int: i32 = span.slice.parse().unwrap();
|
||||
let instr = Instruction::I32Const(int);
|
||||
ctx.push_instr(instr);
|
||||
}
|
||||
},
|
||||
Expr::Local(span) => {
|
||||
let idx = ctx.get_local(span.slice);
|
||||
let instr = Instruction::LocalGet(idx);
|
||||
ctx.push_instr(instr);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
branch = _{ "{" ~ stmt* ~ expr? ~ "}" }
|
||||
stmt = _{ let_stmt }
|
||||
let_stmt = { "let" ~ identifier ~ "=" ~ expr ~ ";" }
|
||||
expr = { term ~ (binary_op ~ term)* }
|
||||
term = { val }
|
||||
val = _{ identifier | literal | "(" ~ expr ~ ")" }
|
||||
literal = _{ int }
|
||||
binary_op = { "+" }
|
||||
int = @{ "-"? ~ ASCII_DIGIT+ }
|
||||
identifier = @{ ("_" | ASCII_ALPHA) ~ ("_" | ASCII_ALPHANUMERIC)* }
|
||||
WHITESPACE = _{ " " | "\t" | NEWLINE }
|
||||
COMMENT = _{ "//" ~ (!NEWLINE ~ ANY)* }
|
|
@ -0,0 +1,92 @@
|
|||
mod ast;
|
||||
mod cg;
|
||||
mod parse;
|
||||
|
||||
fn main() {
|
||||
println!("Hello world! Please run cargo test.");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn branch_test_inner(expected: i32, body: &str) {
|
||||
let ast = parse::parse_branch(body);
|
||||
println!("{:#?}", ast);
|
||||
|
||||
use wasm_encoder::{
|
||||
CodeSection, ExportKind, ExportSection, FunctionSection, TypeSection, ValType,
|
||||
};
|
||||
|
||||
let mut builder = cg::FunctionBuilder::new();
|
||||
cg::codegen_branch(&mut builder, &ast);
|
||||
let f = builder.finish();
|
||||
|
||||
let mut module = wasm_encoder::Module::new();
|
||||
|
||||
let mut types = TypeSection::new();
|
||||
let params = vec![];
|
||||
let results = vec![ValType::I32];
|
||||
types.function(params, results);
|
||||
module.section(&types);
|
||||
|
||||
let mut functions = FunctionSection::new();
|
||||
functions.function(0);
|
||||
module.section(&functions);
|
||||
|
||||
let mut exports = ExportSection::new();
|
||||
exports.export("f", ExportKind::Func, 0);
|
||||
module.section(&exports);
|
||||
|
||||
let mut codes = CodeSection::new();
|
||||
codes.function(&f);
|
||||
module.section(&codes);
|
||||
|
||||
let wasm_bytes = module.finish();
|
||||
|
||||
let wasm_text = wasmprinter::print_bytes(&wasm_bytes).unwrap();
|
||||
println!("{}", wasm_text);
|
||||
|
||||
use wasmi::{Engine, Extern, Linker, Module, Store};
|
||||
let engine = Engine::default();
|
||||
let module = Module::new(&engine, &wasm_bytes[..]).unwrap();
|
||||
let mut store = Store::new(&engine, ());
|
||||
let mut linker = <Linker<()>>::new();
|
||||
let instance_pre = linker.instantiate(&mut store, &module).unwrap();
|
||||
let instance = instance_pre.start(&mut store).unwrap();
|
||||
let f = instance
|
||||
.get_export(&store, "f")
|
||||
.and_then(Extern::into_func)
|
||||
.unwrap()
|
||||
.typed::<(), i32, _>(&mut store)
|
||||
.unwrap();
|
||||
|
||||
let result = f.call(&mut store, ()).unwrap();
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
macro_rules! branch_test {
|
||||
($name: ident, $expected:expr, $body:expr) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
let body = concat!("{", $body, "}");
|
||||
branch_test_inner($expected, body);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
branch_test!(add, 3, "1 + 2");
|
||||
|
||||
branch_test!(chained_add, 5, "1 + 1 + 1 + 1 + 1");
|
||||
|
||||
branch_test!(
|
||||
vars,
|
||||
5,
|
||||
r#"
|
||||
let a = 2;
|
||||
let b = 3;
|
||||
let c = a + b;
|
||||
c
|
||||
"#
|
||||
);
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
use crate::ast::*;
|
||||
use pest::iterators::*;
|
||||
use pest::Parser;
|
||||
use pest_derive::Parser as DeriveParser;
|
||||
|
||||
#[derive(DeriveParser)]
|
||||
#[grammar = "dust_bunny.pest"]
|
||||
pub struct PestParser;
|
||||
|
||||
pub type PestPairs<'a> = Pairs<'a, Rule>;
|
||||
pub type PestPair<'a> = Pair<'a, Rule>;
|
||||
|
||||
pub fn parse_branch(body: &str) -> BranchBody<'_> {
|
||||
let rule = Rule::branch;
|
||||
let pairs = PestParser::parse(rule, body).unwrap();
|
||||
|
||||
println!("{:#?}", pairs);
|
||||
|
||||
let mut statements = Vec::new();
|
||||
let mut tail_expr = None;
|
||||
|
||||
for pair in pairs {
|
||||
match pair.as_rule() {
|
||||
Rule::let_stmt => {
|
||||
let mut tok = pair.into_inner();
|
||||
let ident = tok.next().unwrap().into();
|
||||
let expr = parse_expr(tok.next().unwrap());
|
||||
statements.push(Statement::Let { ident, expr });
|
||||
}
|
||||
Rule::expr => {
|
||||
tail_expr = Some(Box::new(parse_expr(pair)));
|
||||
break;
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
}
|
||||
|
||||
BranchBody {
|
||||
statements,
|
||||
tail_expr,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_expr<'a>(mut pair: PestPair<'a>) -> Expr<'a> {
|
||||
assert_eq!(pair.as_rule(), Rule::expr);
|
||||
|
||||
let mut pairs = pair.into_inner();
|
||||
let first_term = pairs.next().unwrap();
|
||||
let mut expr = parse_term(first_term);
|
||||
|
||||
while pairs.peek().is_some() {
|
||||
let op = pairs.next().unwrap().into();
|
||||
let lhs = expr.clone();
|
||||
let rhs = parse_term(pairs.next().unwrap());
|
||||
let sides = Box::new((lhs, rhs));
|
||||
expr = Expr::BinaryOp(op, sides);
|
||||
}
|
||||
|
||||
expr
|
||||
}
|
||||
|
||||
pub fn parse_term<'a>(mut pair: PestPair<'a>) -> Expr<'a> {
|
||||
assert_eq!(pair.as_rule(), Rule::term);
|
||||
|
||||
let term = pair.into_inner().next().unwrap();
|
||||
|
||||
match term.as_rule() {
|
||||
Rule::identifier => Expr::Local(term.as_span().into()),
|
||||
Rule::int => Expr::Literal(Literal::DecimalInteger(term.as_span().into())),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue