Skip to content

Commit df81b7d

Browse files
committed
add map properties and fix typecheck bug
1 parent 66a4c8a commit df81b7d

30 files changed

Lines changed: 803 additions & 271 deletions

bytecode/src/function.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ pub enum BuiltInFunction {
6868
FloatRound,
6969
FloatFloor,
7070
FloatCeil,
71+
MapLen,
72+
MapHasKey,
73+
MapReplace,
74+
MapKeys,
75+
MapValues,
76+
MapPairs,
7177
}
7278

7379
type BuiltInFunctionReturnBundle = (
@@ -942,6 +948,68 @@ impl BuiltInFunction {
942948

943949
Ok((Some(Primitive::Float(float.ceil())), None))
944950
}
951+
Self::MapLen => {
952+
let Some(Primitive::Map(map)) = arguments.first() else {
953+
unreachable!()
954+
};
955+
956+
Ok((
957+
Some(Primitive::Int(map.len().try_into().expect(
958+
"map length could not be stored in a 32 bit integer",
959+
))),
960+
None,
961+
))
962+
}
963+
Self::MapHasKey => {
964+
let (Some(Primitive::Map(map)), Some(key)) = (arguments.first(), arguments.get(1))
965+
else {
966+
unreachable!()
967+
};
968+
969+
Ok((Some(Primitive::Bool(map.contains_key(key))), None))
970+
}
971+
Self::MapReplace => {
972+
let (Some(Primitive::Map(map)), Some(key), Some(value)) =
973+
(arguments.first(), arguments.get(1), arguments.get(2))
974+
else {
975+
unreachable!()
976+
};
977+
978+
let maybe_existing_value = map.insert(key.clone(), value.clone())?;
979+
Ok((
980+
Some(Primitive::Optional(maybe_existing_value.map(Box::new))),
981+
None,
982+
))
983+
}
984+
Self::MapKeys => {
985+
let Some(Primitive::Map(map)) = arguments.first() else {
986+
unreachable!()
987+
};
988+
989+
Ok((Some(Primitive::Vector(GcVector::new(map.keys()))), None))
990+
}
991+
Self::MapValues => {
992+
let Some(Primitive::Map(map)) = arguments.first() else {
993+
unreachable!()
994+
};
995+
996+
Ok((Some(Primitive::Vector(GcVector::new(map.values()))), None))
997+
}
998+
Self::MapPairs => {
999+
let Some(Primitive::Map(map)) = arguments.first() else {
1000+
unreachable!()
1001+
};
1002+
1003+
Ok((
1004+
Some(Primitive::Vector(GcVector::new(
1005+
map.pairs()
1006+
.into_iter()
1007+
.map(|(key, value)| Primitive::Vector(GcVector::new(vec![key, value])))
1008+
.collect::<Vec<_>>(),
1009+
))),
1010+
None,
1011+
))
1012+
}
9451013
}
9461014
}
9471015
}

bytecode/src/instruction.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ pub mod implementations {
170170
.context("there must be a value at the top of the stack for a `bin_op_assign`")?;
171171

172172
let result = {
173-
let no_mut: &Primitive = value;
173+
let no_hp = value.move_out_of_heap_primitive_borrow()?;
174+
let no_mut: &Primitive = &no_hp;
174175

175176
match op.as_str() {
176177
"+=" => (&*bundle.primitive() + no_mut)?,
@@ -187,7 +188,8 @@ pub mod implementations {
187188
} else {
188189
let value = ctx
189190
.pop()
190-
.context("there must be a value at the top of the stack for a `bin_op_assign`")?;
191+
.context("there must be a value at the top of the stack for a `bin_op_assign`")?
192+
.move_out_of_heap_primitive()?;
191193

192194
let Some(maybe_ptr) = ctx.get_last_op_item_mut() else {
193195
bail!("`bin_op_assign` without a name argument will attempt to modify a pointer that is second to last on the stack, but no primitive was there");
@@ -1461,7 +1463,8 @@ pub mod implementations {
14611463
*/
14621464
#[allow(clippy::mutable_key_type)]
14631465
let raw_map = if let Some(first) = args.first() {
1464-
let capacity = str::parse::<usize>(first).context("could not parse usize for map capacity")?;
1466+
let capacity =
1467+
str::parse::<usize>(first).context("could not parse usize for map capacity")?;
14651468
HashMap::with_capacity(capacity)
14661469
} else {
14671470
HashMap::new()
@@ -1486,25 +1489,32 @@ pub mod implementations {
14861489

14871490
let key = ctx.load_local(key_register)?;
14881491

1489-
map.insert(key.primitive().clone(), ctx.pop().expect("no value in the op stack"))?;
1492+
map.insert(
1493+
key.primitive().clone(),
1494+
ctx.pop().expect("no value in the op stack"),
1495+
)?;
14901496

14911497
Ok(())
14921498
}
14931499

1494-
14951500
#[inline(always)]
14961501
pub(crate) fn map_op(ctx: &mut Ctx, args: &[String]) -> Result<()> {
14971502
let map_register = args.first().context("no map register arg")?;
14981503

14991504
let index_key = ctx.pop().context("no index in the stack")?;
15001505

1501-
let map = ctx.load_local(map_register).with_context(|| format!("no map at register {map_register}"))?;
1506+
let map = ctx
1507+
.load_local(map_register)
1508+
.with_context(|| format!("no map at register {map_register}"))?;
15021509

15031510
let Primitive::Map(map) = &*map.primitive() else {
1504-
bail!("not a map")
1511+
bail!("{} is not a map", map.primitive())
15051512
};
15061513

1507-
ctx.push(Primitive::HeapPrimitive(HeapPrimitive::MapPtr(map.clone(), Box::new(index_key))));
1514+
ctx.push(Primitive::HeapPrimitive(HeapPrimitive::MapPtr(
1515+
map.clone(),
1516+
Box::new(index_key),
1517+
)));
15081518

15091519
Ok(())
15101520
}

bytecode/src/stack.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,12 @@ static_module_generator! {
125125
float_round(BuiltInFunction::FloatRound),
126126
float_floor(BuiltInFunction::FloatFloor),
127127
float_ceil(BuiltInFunction::FloatCeil),
128-
128+
map_len(BuiltInFunction::MapLen),
129+
map_contains_key(BuiltInFunction::MapHasKey),
130+
map_replace(BuiltInFunction::MapReplace),
131+
map_keys(BuiltInFunction::MapKeys),
132+
map_values(BuiltInFunction::MapValues),
133+
map_pairs(BuiltInFunction::MapPairs),
129134
}
130135

131136
impl PrimitiveFlagsPair {

bytecode/src/variables/ops/add.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::variables::Primitive::{self, *};
1+
use crate::variables::Primitive::*;
22
use crate::*;
33
use anyhow::{bail, Result};
44

bytecode/src/variables/ops/bitops.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::variables::Primitive::{self, *};
1+
use crate::variables::Primitive::*;
22
use crate::*;
33
use anyhow::{bail, Context, Result};
44

bytecode/src/variables/ops/div.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::variables::Primitive::{self, *};
1+
use crate::variables::Primitive::*;
22
use crate::*;
33
use anyhow::{bail, Result};
44

bytecode/src/variables/ops/mul.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::variables::Primitive::{self, *};
1+
use crate::variables::Primitive::*;
22
use crate::*;
33
use anyhow::{bail, Result};
44

bytecode/src/variables/ops/ord.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::variables::Primitive;
21
use crate::*;
32
use std::cmp::Ordering;
43

bytecode/src/variables/ops/rem.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::variables::Primitive::{self, *};
1+
use crate::variables::Primitive::*;
22
use crate::*;
33
use anyhow::{bail, Result};
44

bytecode/src/variables/ops/sub.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::variables::Primitive;
21
use crate::*;
32
use anyhow::{bail, Result};
43

0 commit comments

Comments
 (0)