mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
implement factorial example
This commit is contained in:
parent
f40949c64e
commit
e802da5f54
3 changed files with 51 additions and 14 deletions
|
@ -23,7 +23,7 @@ struct LabelId(u32);
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SymbolStorage(LocalId, WasmLayout);
|
struct SymbolStorage(LocalId, WasmLayout);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
struct WasmLayout {
|
struct WasmLayout {
|
||||||
value_type: ValueType,
|
value_type: ValueType,
|
||||||
stack_memory: u32,
|
stack_memory: u32,
|
||||||
|
@ -185,12 +185,12 @@ impl<'a> WasmBackend<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_loop(&mut self) {
|
/// start a loop that leaves a value on the stack
|
||||||
|
fn start_loop_with_return(&mut self, value_type: ValueType) {
|
||||||
self.block_depth += 1;
|
self.block_depth += 1;
|
||||||
|
|
||||||
// self.instructions.push(Loop(BlockType::NoResult));
|
// self.instructions.push(Loop(BlockType::NoResult));
|
||||||
self.instructions
|
self.instructions.push(Loop(BlockType::Value(value_type)));
|
||||||
.push(Loop(BlockType::Value(ValueType::I64)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end_loop(&mut self) {
|
fn end_loop(&mut self) {
|
||||||
|
@ -307,19 +307,21 @@ impl<'a> WasmBackend<'a> {
|
||||||
for parameter in parameters.iter() {
|
for parameter in parameters.iter() {
|
||||||
let wasm_layout = WasmLayout::new(¶meter.layout)?;
|
let wasm_layout = WasmLayout::new(¶meter.layout)?;
|
||||||
let local_id = self.insert_local(wasm_layout, parameter.symbol);
|
let local_id = self.insert_local(wasm_layout, parameter.symbol);
|
||||||
|
|
||||||
local_ids.push(local_id);
|
local_ids.push(local_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.start_block();
|
self.start_block();
|
||||||
|
|
||||||
self.joinpoint_label_map
|
self.joinpoint_label_map
|
||||||
.insert(*id, (self.block_depth, local_ids.clone()));
|
.insert(*id, (self.block_depth, local_ids));
|
||||||
|
|
||||||
self.build_stmt(remainder, ret_layout)?;
|
self.build_stmt(remainder, ret_layout)?;
|
||||||
|
|
||||||
self.end_block();
|
self.end_block();
|
||||||
|
|
||||||
self.start_loop();
|
let return_wasm_layout = WasmLayout::new(ret_layout)?;
|
||||||
|
self.start_loop_with_return(return_wasm_layout.value_type);
|
||||||
|
|
||||||
self.build_stmt(body, ret_layout)?;
|
self.build_stmt(body, ret_layout)?;
|
||||||
|
|
||||||
|
@ -358,7 +360,7 @@ impl<'a> WasmBackend<'a> {
|
||||||
layout: &Layout<'a>,
|
layout: &Layout<'a>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Literal(lit) => self.load_literal(lit),
|
Expr::Literal(lit) => self.load_literal(lit, layout),
|
||||||
|
|
||||||
Expr::Call(roc_mono::ir::Call {
|
Expr::Call(roc_mono::ir::Call {
|
||||||
call_type,
|
call_type,
|
||||||
|
@ -386,7 +388,7 @@ impl<'a> WasmBackend<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_literal(&mut self, lit: &Literal<'a>) -> Result<(), String> {
|
fn load_literal(&mut self, lit: &Literal<'a>, layout: &Layout<'a>) -> Result<(), String> {
|
||||||
match lit {
|
match lit {
|
||||||
Literal::Bool(x) => {
|
Literal::Bool(x) => {
|
||||||
self.instructions.push(I32Const(*x as i32));
|
self.instructions.push(I32Const(*x as i32));
|
||||||
|
@ -397,7 +399,15 @@ impl<'a> WasmBackend<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Literal::Int(x) => {
|
Literal::Int(x) => {
|
||||||
self.instructions.push(I64Const(*x as i64));
|
match layout {
|
||||||
|
Layout::Builtin(Builtin::Int32) => {
|
||||||
|
self.instructions.push(I32Const(*x as i32));
|
||||||
|
}
|
||||||
|
Layout::Builtin(Builtin::Int64) => {
|
||||||
|
self.instructions.push(I64Const(*x as i64));
|
||||||
|
}
|
||||||
|
x => panic!("loading literal, {:?}, is not yet implemented", x),
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Literal::Float(x) => {
|
Literal::Float(x) => {
|
||||||
|
@ -441,6 +451,22 @@ impl<'a> WasmBackend<'a> {
|
||||||
ValueType::F32 => &[F32Add],
|
ValueType::F32 => &[F32Add],
|
||||||
ValueType::F64 => &[F64Add],
|
ValueType::F64 => &[F64Add],
|
||||||
},
|
},
|
||||||
|
LowLevel::NumSub => match return_value_type {
|
||||||
|
ValueType::I32 => &[I32Sub],
|
||||||
|
ValueType::I64 => &[I64Sub],
|
||||||
|
ValueType::F32 => &[F32Sub],
|
||||||
|
ValueType::F64 => &[F64Sub],
|
||||||
|
},
|
||||||
|
LowLevel::NumMul => match return_value_type {
|
||||||
|
ValueType::I32 => &[I32Mul],
|
||||||
|
ValueType::I64 => &[I64Mul],
|
||||||
|
ValueType::F32 => &[F32Mul],
|
||||||
|
ValueType::F64 => &[F64Mul],
|
||||||
|
},
|
||||||
|
LowLevel::NumGt => {
|
||||||
|
// needs layout of the argument to be implemented fully
|
||||||
|
&[I32GtS]
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(format!("unsupported low-level op {:?}", lowlevel));
|
return Err(format!("unsupported low-level op {:?}", lowlevel));
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@ pub fn build_module<'a>(
|
||||||
let mut backend = WasmBackend::new();
|
let mut backend = WasmBackend::new();
|
||||||
let mut layout_ids = LayoutIds::default();
|
let mut layout_ids = LayoutIds::default();
|
||||||
|
|
||||||
|
let mut procedures: std::vec::Vec<_> = procedures.into_iter().collect();
|
||||||
|
procedures.sort_by(|a, b| b.0 .0.cmp(&a.0 .0));
|
||||||
|
|
||||||
for ((sym, layout), proc) in procedures {
|
for ((sym, layout), proc) in procedures {
|
||||||
let function_index = backend.build_proc(proc, sym)?;
|
let function_index = backend.build_proc(proc, sym)?;
|
||||||
if env.exposed_to_host.contains(&sym) {
|
if env.exposed_to_host.contains(&sym) {
|
||||||
|
|
|
@ -132,17 +132,25 @@ mod dev_num {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn factorial() {
|
fn factorial() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
fac = \n ->
|
app "test" provides [ main ] to "./platform"
|
||||||
if n
|
|
||||||
|
fac : I32, I32 -> I32
|
||||||
|
fac = \n, accum ->
|
||||||
|
if n > 1 then
|
||||||
|
fac (n - 1) (n * accum)
|
||||||
|
else
|
||||||
|
accum
|
||||||
|
|
||||||
|
main : I32
|
||||||
|
main = fac 8 1
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
234,
|
40_320,
|
||||||
i64
|
i32
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue