From a99ba56ebacc4b60b96ecc4feb41a3bee0d26f74 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sat, 8 May 2021 23:17:41 +0200 Subject: [PATCH] implement list lowlevels --- compiler/mono/src/alias_analysis.rs | 103 +++++++++++++++++++++++----- 1 file changed, 87 insertions(+), 16 deletions(-) diff --git a/compiler/mono/src/alias_analysis.rs b/compiler/mono/src/alias_analysis.rs index 71e3b97aea..c4f69be41e 100644 --- a/compiler/mono/src/alias_analysis.rs +++ b/compiler/mono/src/alias_analysis.rs @@ -12,7 +12,7 @@ use crate::ir::{Call, CallType, Expr, Literal, Proc, Stmt}; use crate::layout::{Builtin, Layout, ListLayout, UnionLayout}; // just using one module for now -const MOD_NUM: ModName = ModName(b"UserApp"); +const MOD_LIST: ModName = ModName(b"UserApp"); const MOD_APP: ModName = ModName(b"UserApp"); pub fn proc_spec(proc: &Proc) -> Result { @@ -242,16 +242,73 @@ fn call_spec( fn lowlevel_spec( builder: &mut FuncDefBuilder, - _env: &Env, + env: &Env, block: BlockId, - _layout: &Layout, + layout: &Layout, op: &LowLevel, - _arguments: &[Symbol], + arguments: &[Symbol], ) -> Result { use LowLevel::*; + let type_id = layout_spec(builder, layout)?; + match op { - NumAdd => builder.add_make_tuple(block, &[]), + NumAdd | NumSub => { + // NOTE some numeric operations panic (e.g. on overflow) + + let pass_block = { + let block = builder.add_block(); + let value = new_num(builder, block)?; + BlockExpr(block, value) + }; + + let fail_block = { + let block = builder.add_block(); + let value = builder.add_terminate(block, type_id)?; + BlockExpr(block, value) + }; + + let sub_block = { + let block = builder.add_block(); + let choice = builder.add_choice(block, &[pass_block, fail_block])?; + + BlockExpr(block, choice) + }; + + builder.add_sub_block(block, sub_block) + } + NumLte | NumLt | NumGt | NumGte => new_order(builder, block), + ListLen => { + let list = env.symbols[&arguments[0]]; + + builder.add_get_tuple_field(block, list, LIST_LEN_INDEX) + } + ListGetUnsafe => { + // NOTE the ListGet lowlevel op is only evaluated if the index is in-bounds + let list = env.symbols[&arguments[0]]; + + let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?; + let cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?; + + let _unit = builder.add_touch(block, cell)?; + + builder.add_bag_get(block, bag) + } + ListSet => { + let list = env.symbols[&arguments[0]]; + let to_insert = env.symbols[&arguments[2]]; + + let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?; + let cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?; + + // even if this has been written to before, it's okay to write to it again + let update_mode_var = UpdateModeVar(&[]); + let _unit = builder.add_update_write_only(block, update_mode_var, cell); + + builder.add_bag_insert(block, bag, to_insert)?; + + Ok(list) + } _ => todo!(), } } @@ -405,7 +462,7 @@ fn layout_spec(builder: &mut FuncDefBuilder, layout: &Layout) -> Result use Layout::*; match layout { - Builtin(builtin) => Ok(builtin_spec(builder, builtin)), + Builtin(builtin) => builtin_spec(builder, builtin), PhantomEmptyStruct => todo!(), Struct(fields) => build_tuple_type(builder, fields), Union(union_layout) => { @@ -419,17 +476,11 @@ fn layout_spec(builder: &mut FuncDefBuilder, layout: &Layout) -> Result } } -fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> TypeId { +fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> Result { use Builtin::*; match builtin { - Int128 => todo!(), - Int64 => builder.add_named_type(MOD_NUM, TypeName(b"I64")), - Int32 => todo!(), - Int16 => todo!(), - Int8 => todo!(), - Int1 => todo!(), - Usize => todo!(), + Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Usize => builder.add_tuple_type(&[]), Float128 => todo!(), Float64 => todo!(), Float32 => todo!(), @@ -437,7 +488,10 @@ fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> TypeId { Str => todo!(), Dict(_, _) => todo!(), Set(_) => todo!(), - List(_, _) => todo!(), + List(_, _) => { + // TODO should incorporate the element type into the name + Ok(builder.add_named_type(MOD_LIST, TypeName(b"List"))) + } EmptyStr => todo!(), EmptyList => todo!(), EmptyDict => todo!(), @@ -445,6 +499,9 @@ fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> TypeId { } } +// const OK_TAG_ID: u8 = 1u8; +// const ERR_TAG_ID: u8 = 0u8; + const LIST_CELL_INDEX: u32 = 0; const LIST_BAG_INDEX: u32 = 1; const LIST_LEN_INDEX: u32 = 2; @@ -457,7 +514,7 @@ fn new_list(builder: &mut FuncDefBuilder, block: BlockId, element_type: TypeId) } fn new_usize(builder: &mut FuncDefBuilder, block: BlockId) -> Result { - builder.add_make_tuple(block, &[]) + new_num(builder, block) } fn new_static_string(builder: &mut FuncDefBuilder, block: BlockId) -> Result { @@ -470,3 +527,17 @@ fn new_static_string(builder: &mut FuncDefBuilder, block: BlockId) -> Result Result { + // always generats EQ + let tag_id = 0; + + let unit = builder.add_tuple_type(&[])?; + let unit_value = builder.add_make_tuple(block, &[])?; + builder.add_make_union(block, &[unit, unit, unit], tag_id, unit_value) +} + +fn new_num(builder: &mut FuncDefBuilder, block: BlockId) -> Result { + // we model all our numbers as unit values + builder.add_make_tuple(block, &[]) +}