mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
build skeleton
This commit is contained in:
parent
f7fe811f0c
commit
352dacc5a3
2 changed files with 168 additions and 44 deletions
|
@ -1,20 +1,52 @@
|
|||
use morphic_lib::TypeContext;
|
||||
use morphic_lib::{
|
||||
BlockExpr, BlockId, FuncDef, FuncDefBuilder, ModName, Result, TypeId, TypeName, ValueId,
|
||||
BlockExpr, BlockId, CalleeSpecVar, FuncDef, FuncDefBuilder, FuncName, ModName, Result, TypeId,
|
||||
TypeName, ValueId,
|
||||
};
|
||||
use roc_collections::all::MutMap;
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::Symbol;
|
||||
|
||||
use crate::ir::{Call, CallType, Expr, Literal, Proc, Stmt};
|
||||
use crate::layout::{Builtin, Layout};
|
||||
|
||||
fn proc_spec(proc: &Proc) -> Result<FuncDef> {
|
||||
todo!()
|
||||
// just using one module for now
|
||||
const MOD_NUM: ModName = ModName(b"UserApp");
|
||||
const MOD_APP: ModName = ModName(b"UserApp");
|
||||
|
||||
pub fn proc_spec(proc: &Proc) -> Result<FuncDef> {
|
||||
let mut builder = FuncDefBuilder::new();
|
||||
let mut env = Env::default();
|
||||
|
||||
let block = builder.add_block();
|
||||
|
||||
let mut argument_layouts = Vec::new();
|
||||
|
||||
for (layout, _symbol) in proc.args.iter() {
|
||||
// NOTE how do I access the passed-in argument?
|
||||
// let value_id = builder.add_get_tuple_field(block, proc_argument_value_id, i as u32)?;
|
||||
// env.symbols.insert(symbol, value_id);
|
||||
|
||||
argument_layouts.push(*layout);
|
||||
}
|
||||
|
||||
let value_id = stmt_spec(&mut builder, &mut env, block, &proc.ret_layout, &proc.body)?;
|
||||
|
||||
let root = BlockExpr(block, value_id);
|
||||
let arg_type_id = layout_spec(&mut builder, &Layout::Struct(&argument_layouts))?;
|
||||
let ret_type_id = layout_spec(&mut builder, &proc.ret_layout)?;
|
||||
builder.build(arg_type_id, ret_type_id, root)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Env {
|
||||
symbols: MutMap<Symbol, ValueId>,
|
||||
join_points: MutMap<crate::ir::JoinPointId, morphic_lib::JoinPointId>,
|
||||
}
|
||||
|
||||
fn stmt_spec(
|
||||
builder: &mut FuncDefBuilder,
|
||||
env: &mut MutMap<Symbol, ValueId>,
|
||||
env: &mut Env,
|
||||
block: BlockId,
|
||||
layout: &Layout,
|
||||
stmt: &Stmt,
|
||||
|
@ -24,9 +56,9 @@ fn stmt_spec(
|
|||
match stmt {
|
||||
Let(symbol, expr, layout, continuation) => {
|
||||
let value_id = expr_spec(builder, env, block, layout, expr)?;
|
||||
env.insert(*symbol, value_id);
|
||||
env.symbols.insert(*symbol, value_id);
|
||||
let result = stmt_spec(builder, env, block, layout, continuation)?;
|
||||
env.remove(symbol);
|
||||
env.symbols.remove(symbol);
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
@ -42,34 +74,96 @@ fn stmt_spec(
|
|||
let value_id = call_spec(builder, env, block, call_layout, call)?;
|
||||
|
||||
let pass_block = builder.add_block();
|
||||
env.insert(*symbol, value_id);
|
||||
env.symbols.insert(*symbol, value_id);
|
||||
let pass_value_id = stmt_spec(builder, env, pass_block, layout, pass)?;
|
||||
env.remove(symbol);
|
||||
env.symbols.remove(symbol);
|
||||
let pass_block_expr = BlockExpr(pass_block, pass_value_id);
|
||||
|
||||
let fail_block = builder.add_block();
|
||||
let fail_value_id = stmt_spec(builder, env, fail_block, layout, fail)?;
|
||||
let fail_block_expr = BlockExpr(fail_block, fail_value_id);
|
||||
|
||||
let cases = &[pass_block, fail_block];
|
||||
builder.add_choice(block, &[pass_block_expr, fail_block_expr])
|
||||
}
|
||||
Switch {
|
||||
cond_symbol,
|
||||
cond_layout,
|
||||
cond_symbol: _,
|
||||
cond_layout: _,
|
||||
branches,
|
||||
default_branch,
|
||||
ret_layout,
|
||||
} => todo!(),
|
||||
Ret(symbol) => Ok(env[symbol]),
|
||||
} => {
|
||||
// NOTE should we touch the cond_symbol here? it is always an integer, but the
|
||||
// cond_symbol might be unused if we don't somehow "use" it here
|
||||
|
||||
let mut cases = Vec::with_capacity(branches.len() + 1);
|
||||
|
||||
let it = branches
|
||||
.iter()
|
||||
.map(|(_, _, body)| body)
|
||||
.chain(std::iter::once(default_branch.1));
|
||||
|
||||
for branch in it {
|
||||
let block = builder.add_block();
|
||||
let value_id = stmt_spec(builder, env, block, ret_layout, branch)?;
|
||||
cases.push(BlockExpr(block, value_id));
|
||||
}
|
||||
|
||||
builder.add_choice(block, &cases)
|
||||
}
|
||||
Ret(symbol) => Ok(env.symbols[symbol]),
|
||||
Refcounting(_, _) => unreachable!("not yet introduced"),
|
||||
Join {
|
||||
id,
|
||||
parameters,
|
||||
continuation,
|
||||
remainder,
|
||||
} => todo!(),
|
||||
Jump(_, _) => todo!(),
|
||||
} => {
|
||||
let mut type_ids = Vec::new();
|
||||
|
||||
for p in parameters.iter() {
|
||||
type_ids.push(layout_spec(builder, &p.layout)?);
|
||||
}
|
||||
|
||||
let ret_type_id = layout_spec(builder, layout)?;
|
||||
|
||||
let jp_arg_type_id = builder.add_tuple_type(&type_ids)?;
|
||||
// NOTE just one value_id is returned, but we need the ids of the individual arguments!
|
||||
// symbols bound by the join point won't be defined right now!
|
||||
let (jpid, jp_argument) =
|
||||
builder.declare_join_point(block, jp_arg_type_id, ret_type_id)?;
|
||||
|
||||
env.join_points.insert(*id, jpid);
|
||||
let jp_body_block = builder.add_block();
|
||||
|
||||
// unpack the argument
|
||||
for (i, p) in parameters.iter().enumerate() {
|
||||
let value_id = builder.add_get_tuple_field(jp_body_block, jp_argument, i as u32)?;
|
||||
env.symbols.insert(p.symbol, value_id);
|
||||
}
|
||||
|
||||
let jp_body_value_id = stmt_spec(builder, env, jp_body_block, layout, remainder)?;
|
||||
|
||||
for p in parameters.iter() {
|
||||
env.symbols.remove(&p.symbol);
|
||||
}
|
||||
|
||||
// NOTE I think we need to use add_sub_block here, but not sure how
|
||||
|
||||
let cont_block = builder.add_block();
|
||||
let cont_value_id = stmt_spec(builder, env, cont_block, layout, continuation)?;
|
||||
|
||||
env.join_points.remove(id);
|
||||
builder.define_join_point(jpid, BlockExpr(jp_body_block, jp_body_value_id))?;
|
||||
|
||||
Ok(cont_value_id)
|
||||
}
|
||||
Jump(id, symbols) => {
|
||||
let ret_type_id = layout_spec(builder, layout)?;
|
||||
let argument = build_tuple_value(builder, env, block, symbols)?;
|
||||
|
||||
let jpid = env.join_points[id];
|
||||
builder.add_jump(block, jpid, argument, ret_type_id)
|
||||
}
|
||||
Rethrow | RuntimeError(_) => {
|
||||
let type_id = layout_spec(builder, layout)?;
|
||||
|
||||
|
@ -78,40 +172,77 @@ fn stmt_spec(
|
|||
}
|
||||
}
|
||||
|
||||
fn build_tuple_value(
|
||||
builder: &mut FuncDefBuilder,
|
||||
env: &Env,
|
||||
block: BlockId,
|
||||
symbols: &[Symbol],
|
||||
) -> Result<ValueId> {
|
||||
let mut value_ids = Vec::new();
|
||||
|
||||
for field in symbols.iter() {
|
||||
let value_id = env.symbols[field];
|
||||
value_ids.push(value_id);
|
||||
}
|
||||
|
||||
builder.add_make_tuple(block, &value_ids)
|
||||
}
|
||||
|
||||
fn call_spec(
|
||||
builder: &mut FuncDefBuilder,
|
||||
env: &MutMap<Symbol, ValueId>,
|
||||
env: &Env,
|
||||
block: BlockId,
|
||||
layout: &Layout,
|
||||
call: &Call,
|
||||
) -> Result<ValueId> {
|
||||
use CallType::*;
|
||||
//pub call_type: CallType<'a>,
|
||||
// pub arguments: &'a [Symbol],
|
||||
|
||||
match &call.call_type {
|
||||
ByName {
|
||||
name,
|
||||
name: symbol,
|
||||
full_layout,
|
||||
ret_layout,
|
||||
arg_layouts,
|
||||
} => todo!(),
|
||||
} => {
|
||||
// TODO annotate each call with a unique identifier
|
||||
let spec_var = CalleeSpecVar(&[]);
|
||||
|
||||
let arg_value_id = build_tuple_value(builder, env, block, call.arguments)?;
|
||||
let name = FuncName(&symbol.to_be_bytes());
|
||||
let module = FuncName(&symbol.to_be_bytes());
|
||||
builder.add_call(block, spec_var, module, name, arg_value_id)
|
||||
}
|
||||
ByPointer {
|
||||
name,
|
||||
full_layout,
|
||||
ret_layout,
|
||||
arg_layouts,
|
||||
name: _,
|
||||
full_layout: _,
|
||||
ret_layout: _,
|
||||
arg_layouts: _,
|
||||
} => todo!(),
|
||||
Foreign {
|
||||
foreign_symbol,
|
||||
ret_layout,
|
||||
} => todo!(),
|
||||
LowLevel { op } => todo!(),
|
||||
foreign_symbol: _,
|
||||
ret_layout: _,
|
||||
} => {
|
||||
// NOTE foreign functions are those exposed by the platform
|
||||
todo!()
|
||||
}
|
||||
LowLevel { op } => lowlevel_spec(builder, env, block, layout, op, call.arguments),
|
||||
}
|
||||
}
|
||||
|
||||
fn lowlevel_spec(
|
||||
_builder: &mut FuncDefBuilder,
|
||||
_env: &Env,
|
||||
_block: BlockId,
|
||||
_layout: &Layout,
|
||||
_op: &LowLevel,
|
||||
_arguments: &[Symbol],
|
||||
) -> Result<ValueId> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn expr_spec(
|
||||
builder: &mut FuncDefBuilder,
|
||||
env: &MutMap<Symbol, ValueId>,
|
||||
env: &Env,
|
||||
block: BlockId,
|
||||
layout: &Layout,
|
||||
expr: &Expr,
|
||||
|
@ -121,7 +252,7 @@ fn expr_spec(
|
|||
match expr {
|
||||
Literal(literal) => literal_spec(builder, block, literal),
|
||||
FunctionPointer(_, _) => todo!(),
|
||||
Call(_) => todo!(),
|
||||
Call(call) => call_spec(builder, env, block, layout, call),
|
||||
Tag {
|
||||
tag_layout,
|
||||
tag_name,
|
||||
|
@ -129,16 +260,7 @@ fn expr_spec(
|
|||
union_size,
|
||||
arguments,
|
||||
} => todo!(),
|
||||
Struct(fields) => {
|
||||
let mut value_ids = Vec::new();
|
||||
|
||||
for field in fields.iter() {
|
||||
let value_id = env[field];
|
||||
value_ids.push(value_id);
|
||||
}
|
||||
|
||||
builder.add_make_tuple(block, &value_ids)
|
||||
}
|
||||
Struct(fields) => build_tuple_value(builder, env, block, fields),
|
||||
AccessAtIndex {
|
||||
index,
|
||||
field_layouts: _,
|
||||
|
@ -147,7 +269,7 @@ fn expr_spec(
|
|||
} => {
|
||||
use crate::ir::Wrapped;
|
||||
|
||||
let value_id = env[structure];
|
||||
let value_id = env.symbols[structure];
|
||||
|
||||
match wrapped {
|
||||
Wrapped::EmptyRecord => {
|
||||
|
@ -171,7 +293,7 @@ fn expr_spec(
|
|||
let mut bag = builder.add_empty_bag(block, type_id)?;
|
||||
|
||||
for symbol in elems.iter() {
|
||||
let value_id = env[symbol];
|
||||
let value_id = env.symbols[symbol];
|
||||
|
||||
bag = builder.add_bag_insert(block, bag, value_id)?;
|
||||
}
|
||||
|
@ -222,8 +344,6 @@ fn layout_spec(builder: &mut FuncDefBuilder, layout: &Layout) -> Result<TypeId>
|
|||
}
|
||||
}
|
||||
|
||||
const MOD_NUM: ModName = ModName(b"Num");
|
||||
|
||||
fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> TypeId {
|
||||
use Builtin::*;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue