diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index 5ed267fdd1..fd7f2356c3 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -79,6 +79,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option LIST_WALK => list_walk, LIST_WALK_BACKWARDS => list_walk_backwards, DICT_LEN => dict_len, + DICT_EMPTY => dict_empty, NUM_ADD => num_add, NUM_ADD_CHECKED => num_add_checked, NUM_ADD_WRAP => num_add_wrap, @@ -173,6 +174,8 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap { Symbol::LIST_KEEP_IF => list_keep_if, Symbol::LIST_WALK => list_walk, Symbol::LIST_WALK_BACKWARDS => list_walk_backwards, + Symbol::DICT_LEN => dict_len, + Symbol::DICT_EMPTY => dict_empty, Symbol::NUM_ADD => num_add, Symbol::NUM_ADD_CHECKED => num_add_checked, Symbol::NUM_ADD_WRAP => num_add_wrap, @@ -1848,6 +1851,24 @@ fn dict_len(symbol: Symbol, var_store: &mut VarStore) -> Def { ) } +/// Dict.empty : Dict * * +fn dict_empty(symbol: Symbol, var_store: &mut VarStore) -> Def { + let dict_var = var_store.fresh(); + let body = RunLowLevel { + op: LowLevel::DictEmpty, + args: vec![], + ret_var: dict_var, + }; + + Def { + annotation: None, + expr_var: dict_var, + loc_expr: Located::at_zero(body), + loc_pattern: Located::at_zero(Pattern::Identifier(symbol)), + pattern_vars: SendMap::default(), + } +} + /// Num.rem : Int, Int -> Result Int [ DivByZero ]* fn num_rem(symbol: Symbol, var_store: &mut VarStore) -> Def { let num_var = var_store.fresh(); diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index 1b1d874cd9..57d00b637d 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -1,4 +1,4 @@ -use crate::llvm::build_dict::dict_len; +use crate::llvm::build_dict::{dict_len, dict_empty}; use crate::llvm::build_hash::hash; use crate::llvm::build_list::{ allocate_list, empty_list, empty_polymorphic_list, list_append, list_concat, list_contains, @@ -3854,7 +3854,14 @@ fn run_low_level<'a, 'ctx, 'env>( hash(env, value, layout) } - DictSize => dict_len(env, scope, args[0]), + DictSize => { + debug_assert_eq!(args.len(), 1); + dict_len(env, scope, args[0]) + } + DictEmpty => { + debug_assert_eq!(args.len(), 0); + dict_empty(env, scope) + } } } diff --git a/compiler/gen/src/llvm/build_dict.rs b/compiler/gen/src/llvm/build_dict.rs index 548dd36a08..93f26290e6 100644 --- a/compiler/gen/src/llvm/build_dict.rs +++ b/compiler/gen/src/llvm/build_dict.rs @@ -25,6 +25,28 @@ pub fn dict_len<'a, 'ctx, 'env>( } } +pub fn dict_empty<'a, 'ctx, 'env>( + env: &Env<'a, 'ctx, 'env>, + scope: &Scope<'a, 'ctx>, +) -> BasicValueEnum<'ctx> { + let ctx = env.context; + + /* + let (_, dict_layout) = load_symbol_and_layout(env, scope, &dict_symbol); + + match dict_layout { + Layout::Builtin(Builtin::Dict(_, _)) => { + let dict_as_int = dict_symbol_to_i128(env, scope, dict_symbol); + + call_bitcode_fn(env, &[dict_as_int.into()], &bitcode::DICT_LEN) + } + Layout::Builtin(Builtin::EmptyDict) => ctx.i64_type().const_zero().into(), + _ => unreachable!("Invalid layout given to Dict.len : {:?}", dict_layout), + } + */ + todo!() +} + fn dict_symbol_to_i128<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, scope: &Scope<'a, 'ctx>, diff --git a/compiler/gen/src/llvm/convert.rs b/compiler/gen/src/llvm/convert.rs index c4229d97d2..75df4a38d8 100644 --- a/compiler/gen/src/llvm/convert.rs +++ b/compiler/gen/src/llvm/convert.rs @@ -181,7 +181,7 @@ pub fn basic_type_from_builtin<'ctx>( Float64 => context.f64_type().as_basic_type_enum(), Float32 => context.f32_type().as_basic_type_enum(), Float16 => context.f16_type().as_basic_type_enum(), - Dict(_, _) | EmptyDict => panic!("TODO layout_to_basic_type for Builtin::Dict"), + Dict(_, _) | EmptyDict => collection(context, ptr_bytes).into(), Set(_) | EmptySet => panic!("TODO layout_to_basic_type for Builtin::Set"), List(_, _) | Str | EmptyStr => collection(context, ptr_bytes).into(), EmptyList => BasicTypeEnum::StructType(collection(context, ptr_bytes)), diff --git a/compiler/module/src/low_level.rs b/compiler/module/src/low_level.rs index 7ba5b35b07..b833927387 100644 --- a/compiler/module/src/low_level.rs +++ b/compiler/module/src/low_level.rs @@ -28,6 +28,7 @@ pub enum LowLevel { ListWalkBackwards, ListSum, DictSize, + DictEmpty, NumAdd, NumAddWrap, NumAddChecked, diff --git a/compiler/mono/src/borrow.rs b/compiler/mono/src/borrow.rs index c8c483555d..86e5245b60 100644 --- a/compiler/mono/src/borrow.rs +++ b/compiler/mono/src/borrow.rs @@ -589,5 +589,6 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] { StrFromInt => arena.alloc_slice_copy(&[irrelevant]), Hash => arena.alloc_slice_copy(&[borrowed]), DictSize => arena.alloc_slice_copy(&[borrowed]), + DictEmpty => &[], } } diff --git a/compiler/mono/tests/test_mono.rs b/compiler/mono/tests/test_mono.rs index 29275c6876..6c01023120 100644 --- a/compiler/mono/tests/test_mono.rs +++ b/compiler/mono/tests/test_mono.rs @@ -642,21 +642,18 @@ mod test_mono { "#, indoc!( r#" - procedure List.5 (#Attr.2, #Attr.3): - let Test.7 = lowlevel ListAppend #Attr.2 #Attr.3; - ret Test.7; - - procedure Test.1 (Test.2): - let Test.6 = 42i64; - let Test.5 = CallByName List.5 Test.2 Test.6; - ret Test.5; - - procedure Test.0 (): - let Test.8 = 1i64; - let Test.9 = 2i64; - let Test.4 = Array [Test.8, Test.9]; - let Test.3 = CallByName Test.1 Test.4; + procedure Dict.2 (): + let Test.4 = lowlevel DictEmpty ; + ret Test.4; + + procedure Dict.6 (#Attr.2): + let Test.3 = lowlevel DictSize #Attr.2; ret Test.3; + + procedure Test.0 (): + let Test.2 = FunctionPointer Dict.2; + let Test.1 = CallByName Dict.6 Test.2; + ret Test.1; "# ), )