Skip to content

Commit

Permalink
Merge pull request #51 from mangolang/wasm-target
Browse files Browse the repository at this point in the history
Add representation of wasm as compile target (proof of concept)
  • Loading branch information
mverleg authored May 12, 2018
2 parents 0c93724 + 5923c13 commit 893cfec
Show file tree
Hide file tree
Showing 27 changed files with 1,095 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ pub mod mango {
pub mod reducing;
pub mod semanticating;
pub mod typing;

// Targets
pub mod towasm;
}
69 changes: 69 additions & 0 deletions src/mango/towasm/collect/datatype.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// The unsigned integers etc are not included.
// They're also not data types in wasm, the operation can choose signed/unsigned.
// The reason they're not included though, is that I don't expect to use them.
// If I do use them, I should probably add them here and break wasm 1-1.

use mango::towasm::Wasm;
use std::fs::File;
use std::io;

#[derive(PartialEq, Eq, Clone, Copy)]
pub enum Type {
Int32,
Int64,
Float32,
Float64,
Bool,
}

impl Wasm for Type {
fn as_wat(&self) -> String {
match self {
Type::Int32 => "i32",
Type::Int64 => "i64",
Type::Float32 => "f32",
Type::Float64 => "f64",
Type::Bool => "i32",
}.to_owned()
}

fn write_wasm(&self, file: &mut File) -> io::Result<()> {
unimplemented!()
}
}

pub enum Value {
Int(i64),
Float(f64),
}

impl Value {
pub fn is_type(&self, typ: &Type) -> bool {
match self {
Value::Int(_) => {
match typ {
Type::Bool => false,
_ => true, // int value can be stored in int or float
}
}
Value::Float(_) => match typ {
Type::Float32 => true,
Type::Float64 => true,
_ => false,
},
}
}
}

impl Wasm for Value {
fn as_wat(&self) -> String {
match self {
Value::Int(val) => format!("{}", val),
Value::Float(val) => format!("{}", val),
}.to_owned()
}

fn write_wasm(&self, file: &mut File) -> io::Result<()> {
unimplemented!()
}
}
8 changes: 8 additions & 0 deletions src/mango/towasm/collect/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pub mod typ;
pub use self::typ::Wasm;

pub mod datatype;
pub use self::datatype::Type;

pub mod statement;
pub use self::statement::Statement;
3 changes: 3 additions & 0 deletions src/mango/towasm/collect/statement.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use mango::towasm::Wasm;

pub trait Statement: Wasm {}
8 changes: 8 additions & 0 deletions src/mango/towasm/collect/typ.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use std::fs::File;
use std::io;

/// WASM type
pub trait Wasm {
fn as_wat(&self) -> String;
fn write_wasm(&self, file: &mut File) -> io::Result<()>;
}
80 changes: 80 additions & 0 deletions src/mango/towasm/control/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use mango::towasm::collect::Statement;
use mango::towasm::control::Label;
use mango::towasm::util::Name;
use mango::towasm::Wasm;
use std::fs::File;
use std::io;
use std::io::Write;
use std::rc::Rc;

pub struct Group {
statements: Vec<Box<Statement>>,
}

impl Group {
pub fn new<F>(label: Label, statements_gen: F) -> Self
where
F: FnOnce(Label) -> Vec<Box<Statement>>,
{
Group {
statements: statements_gen(label),
}
}
}

impl Wasm for Group {
fn as_wat(&self) -> String {
self.statements
.iter()
.map(|statement| statement.as_wat())
.collect::<Vec<_>>()
.join("\n")
}

fn write_wasm(&self, file: &mut File) -> io::Result<()> {
file.write(b" block ")?;
Ok(())
}
}

pub struct Block {
name: Rc<Name>,
group: Group,
}

impl Block {
pub fn new<F>(statements_gen: F) -> Box<Self>
where
F: FnOnce(Label) -> Vec<Box<Statement>>,
{
// todo: determine name automatically
Block::new_named(Name::new("b".to_owned()).unwrap(), statements_gen)
}

pub fn new_named<F>(name: Rc<Name>, statements_gen: F) -> Box<Self>
where
F: FnOnce(Label) -> Vec<Box<Statement>>,
{
Box::new(Block {
name: name.clone(),
group: Group::new(Label::internal(name), statements_gen),
})
}
}

impl Wasm for Block {
fn as_wat(&self) -> String {
format!(
"(block {0:}\n{1:}\n) ;; block {0:}",
self.name.as_wat(),
self.group.as_wat()
)
}

fn write_wasm(&self, file: &mut File) -> io::Result<()> {
file.write(b" block ")?;
Ok(())
}
}

impl Statement for Block {}
76 changes: 76 additions & 0 deletions src/mango/towasm/control/branch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use mango::towasm::collect::Statement;
use mango::towasm::collect::Type;
use mango::towasm::util::Name;
use mango::towasm::values::Expression;
use mango::towasm::Wasm;
use std::fs::File;
use std::io;
use std::io::Write;
use std::rc::Rc;

/// Label for a block, if or loop
pub struct Label {
name: Rc<Name>,
}

impl Label {
/// This constructor should not be called directly; blocks should create their own references.
pub fn internal(name: Rc<Name>) -> Self {
Label { name }
}
}

impl Wasm for Label {
fn as_wat(&self) -> String {
self.name.as_wat()
}

fn write_wasm(&self, file: &mut File) -> io::Result<()> {
unimplemented!()
}
}

pub struct Branch {}

impl Branch {
pub fn new() -> Box<Self> {
Box::new(Branch {})
}
}

impl Wasm for Branch {
fn as_wat(&self) -> String {
" br ".to_owned()
// format!(" add ")
}

fn write_wasm(&self, file: &mut File) -> io::Result<()> {
file.write(b" call ")?;
Ok(())
}
}

pub struct BranchIf {
condition: Box<Expression>,
label: Label,
}

impl BranchIf {
pub fn new(condition: Box<Expression>, label: Label) -> Box<Self> {
assert!(condition.typ() == &Type::Bool);
Box::new(BranchIf { condition, label })
}
}

impl Wasm for BranchIf {
fn as_wat(&self) -> String {
format!("{}\nbr_if {}", self.condition.as_wat(), self.label.as_wat())
}

fn write_wasm(&self, file: &mut File) -> io::Result<()> {
file.write(b" call ")?;
Ok(())
}
}

impl Statement for BranchIf {}
52 changes: 52 additions & 0 deletions src/mango/towasm/control/function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use mango::towasm::collect::Statement;
use mango::towasm::control::Label;
use mango::towasm::values::Expression;
use mango::towasm::Wasm;
use std::fs::File;
use std::io;
use std::io::Write;

// todo: call_indirect

pub struct Call {}

impl Call {
pub fn new() -> Box<Self> {
Box::new(Call {})
}
}

impl Wasm for Call {
fn as_wat(&self) -> String {
" call ".to_owned()
// format!(" add ")
}

fn write_wasm(&self, file: &mut File) -> io::Result<()> {
file.write(b" call ")?;
Ok(())
}
}

pub struct Return {
expression: Box<Expression>,
}

impl Return {
// Take label to make sure this inside a function, might be used in the future, or removed...
pub fn new(_label: Label, expression: Box<Expression>) -> Box<Self> {
Box::new(Return { expression })
}
}

impl Wasm for Return {
fn as_wat(&self) -> String {
self.expression.as_wat()
}

fn write_wasm(&self, file: &mut File) -> io::Result<()> {
unimplemented!();
}
}

impl Statement for Return {}
15 changes: 15 additions & 0 deletions src/mango/towasm/control/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
pub mod block;
pub use self::block::Block;
pub use self::block::Group;

pub mod branch;
pub use self::branch::Branch;
pub use self::branch::BranchIf;
pub use self::branch::Label;

pub mod repeat;
pub use self::repeat::Loop;

pub mod function;
pub use self::function::Call;
pub use self::function::Return;
49 changes: 49 additions & 0 deletions src/mango/towasm/control/repeat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use mango::towasm::collect::Statement;
use mango::towasm::control::Group;
use mango::towasm::control::Label;
use mango::towasm::util::Name;
use mango::towasm::Wasm;
use std::fs::File;
use std::io;
use std::rc::Rc;

pub struct Loop {
name: Rc<Name>,
group: Group,
}

impl Loop {
pub fn new<F>(statements_gen: F) -> Box<Self>
where
F: FnOnce(Label) -> Vec<Box<Statement>>,
{
// todo: determine name automatically
Loop::new_named(Name::new("l".to_owned()).unwrap(), statements_gen)
}

pub fn new_named<F>(name: Rc<Name>, statements_gen: F) -> Box<Self>
where
F: FnOnce(Label) -> Vec<Box<Statement>>,
{
Box::new(Loop {
name: name.clone(),
group: Group::new(Label::internal(name), statements_gen),
})
}
}

impl Wasm for Loop {
fn as_wat(&self) -> String {
format!(
"loop {0:}\n{1:}\nend ;; loop {0:}",
self.name.as_wat(),
self.group.as_wat()
)
}

fn write_wasm(&self, file: &mut File) -> io::Result<()> {
unimplemented!()
}
}

impl Statement for Loop {}
22 changes: 22 additions & 0 deletions src/mango/towasm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// TODO: possibly extract this to a separate crate

pub mod collect;
pub use self::collect::Wasm;

pub mod numeric;
pub use self::numeric::*;

pub mod control;
pub use self::control::*;

pub mod scope;
pub use self::scope::*;

pub mod util;
pub use self::util::*;

pub mod values;
pub use self::values::*;

#[cfg(test)]
mod tests;
Loading

0 comments on commit 893cfec

Please sign in to comment.