mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
implement switch for the gen wasm backend
This commit is contained in:
parent
c888baccff
commit
1da32f18e5
3 changed files with 139 additions and 1 deletions
|
@ -1,6 +1,8 @@
|
||||||
use parity_wasm::builder;
|
use parity_wasm::builder;
|
||||||
use parity_wasm::builder::{CodeLocation, ModuleBuilder};
|
use parity_wasm::builder::{CodeLocation, ModuleBuilder};
|
||||||
use parity_wasm::elements::{Instruction, Instruction::*, Instructions, Local, ValueType};
|
use parity_wasm::elements::{
|
||||||
|
BlockType, Instruction, Instruction::*, Instructions, Local, ValueType,
|
||||||
|
};
|
||||||
|
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
|
@ -30,6 +32,12 @@ struct WasmLayout {
|
||||||
impl WasmLayout {
|
impl WasmLayout {
|
||||||
fn new(layout: &Layout) -> Result<Self, String> {
|
fn new(layout: &Layout) -> Result<Self, String> {
|
||||||
match layout {
|
match layout {
|
||||||
|
Layout::Builtin(Builtin::Int1 | Builtin::Int8 | Builtin::Int16 | Builtin::Int32) => {
|
||||||
|
Ok(Self {
|
||||||
|
value_type: ValueType::I32,
|
||||||
|
stack_memory: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
Layout::Builtin(Builtin::Int64) => Ok(Self {
|
Layout::Builtin(Builtin::Int64) => Ok(Self {
|
||||||
value_type: ValueType::I64,
|
value_type: ValueType::I64,
|
||||||
stack_memory: 0,
|
stack_memory: 0,
|
||||||
|
@ -207,6 +215,60 @@ impl<'a> WasmBackend<'a> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stmt::Switch {
|
||||||
|
cond_symbol,
|
||||||
|
cond_layout: _,
|
||||||
|
branches,
|
||||||
|
default_branch,
|
||||||
|
ret_layout: _,
|
||||||
|
} => {
|
||||||
|
// NOTE currently implemented as a series of conditional jumps
|
||||||
|
// We may be able to improve this in the future with `Select`
|
||||||
|
// or `BrTable`
|
||||||
|
|
||||||
|
// create (number_of_branches - 1) new blocks.
|
||||||
|
//
|
||||||
|
// Every branch ends in a `return`,
|
||||||
|
// so the block leaves no values on the stack
|
||||||
|
for _ in 0..branches.len() {
|
||||||
|
self.instructions.push(Block(BlockType::NoResult));
|
||||||
|
}
|
||||||
|
|
||||||
|
// the LocalId of the symbol that we match on
|
||||||
|
let matched_on = match self.symbol_storage_map.get(cond_symbol) {
|
||||||
|
Some(SymbolStorage(local_id, _)) => local_id.0,
|
||||||
|
None => unreachable!("symbol not defined: {:?}", cond_symbol),
|
||||||
|
};
|
||||||
|
|
||||||
|
// then, we jump whenever the value under scrutiny is equal to the value of a branch
|
||||||
|
for (i, (value, _, _)) in branches.iter().enumerate() {
|
||||||
|
// put the cond_symbol on the top of the stack
|
||||||
|
self.instructions.push(GetLocal(matched_on));
|
||||||
|
|
||||||
|
self.instructions.push(I32Const(*value as i32));
|
||||||
|
|
||||||
|
// compare the 2 topmost values
|
||||||
|
self.instructions.push(I32Eq);
|
||||||
|
|
||||||
|
// "break" out of `i` surrounding blocks
|
||||||
|
self.instructions.push(BrIf(i as u32));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we never jumped because a value matched, we're in the default case
|
||||||
|
self.build_stmt(default_branch.1, ret_layout)?;
|
||||||
|
|
||||||
|
// now put in the actual body of each branch in order
|
||||||
|
// (the first branch would have broken out of 1 block,
|
||||||
|
// hence we must generate its code first)
|
||||||
|
for (_, _, branch) in branches.iter() {
|
||||||
|
self.instructions.push(End);
|
||||||
|
|
||||||
|
self.build_stmt(branch, ret_layout)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
x => Err(format!("statement not yet implemented: {:?}", x)),
|
x => Err(format!("statement not yet implemented: {:?}", x)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,6 +310,14 @@ impl<'a> WasmBackend<'a> {
|
||||||
|
|
||||||
fn load_literal(&mut self, lit: &Literal<'a>) -> Result<(), String> {
|
fn load_literal(&mut self, lit: &Literal<'a>) -> Result<(), String> {
|
||||||
match lit {
|
match lit {
|
||||||
|
Literal::Bool(x) => {
|
||||||
|
self.instructions.push(I32Const(*x as i32));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Literal::Byte(x) => {
|
||||||
|
self.instructions.push(I32Const(*x as i32));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Literal::Int(x) => {
|
Literal::Int(x) => {
|
||||||
self.instructions.push(I64Const(*x as i64));
|
self.instructions.push(I64Const(*x as i64));
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -147,6 +147,7 @@ where
|
||||||
Err(e) => Err(format!("{:?}", e)),
|
Err(e) => Err(format!("{:?}", e)),
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
let integer = match result[0] {
|
let integer = match result[0] {
|
||||||
|
wasmer::Value::I32(a) => a as i64,
|
||||||
wasmer::Value::I64(a) => a,
|
wasmer::Value::I64(a) => a,
|
||||||
wasmer::Value::F64(a) => a.to_bits() as i64,
|
wasmer::Value::F64(a) => a.to_bits() as i64,
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
|
|
|
@ -49,6 +49,73 @@ mod dev_num {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn if_then_else() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
cond : Bool
|
||||||
|
cond = True
|
||||||
|
|
||||||
|
if cond then
|
||||||
|
0
|
||||||
|
else
|
||||||
|
1
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
0,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rgb_red() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
when Red is
|
||||||
|
Red -> 111
|
||||||
|
Green -> 222
|
||||||
|
Blue -> 333
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
111,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rgb_green() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
when Green is
|
||||||
|
Red -> 111
|
||||||
|
Green -> 222
|
||||||
|
Blue -> 333
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
222,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rgb_blue() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
when Blue is
|
||||||
|
Red -> 111
|
||||||
|
Green -> 222
|
||||||
|
Blue -> 333
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
333,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn gen_add_f64() {
|
// fn gen_add_f64() {
|
||||||
// assert_evals_to!(
|
// assert_evals_to!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue