rulox_types/
primitive_methods.rs1#![allow(clippy::redundant_pub_crate)]
2#![allow(clippy::unnecessary_wraps)]
3
4use crate::functions::LoxArgs;
5use crate::LoxError;
6use crate::LoxObject;
7use crate::LoxResult;
8use crate::LoxValue;
9use crate::MapKey;
10use crate::Shared;
11
12use std::collections::HashMap;
13
14pub(super) fn is_bool(args: LoxArgs) -> LoxResult {
15 Ok(LoxValue::Bool(matches!(
16 args.head.unwrap(),
17 LoxValue::Bool(_)
18 )))
19}
20
21pub(super) fn is_str(args: LoxArgs) -> LoxResult {
22 Ok(LoxValue::Bool(matches!(
23 args.head.unwrap(),
24 LoxValue::Str(_)
25 )))
26}
27
28pub(super) fn is_num(args: LoxArgs) -> LoxResult {
29 Ok(LoxValue::Bool(matches!(
30 args.head.unwrap(),
31 LoxValue::Num(_)
32 )))
33}
34
35pub(super) fn is_arr(args: LoxArgs) -> LoxResult {
36 Ok(LoxValue::Bool(matches!(
37 args.head.unwrap(),
38 LoxValue::Arr(_)
39 )))
40}
41
42pub(super) fn is_function(args: LoxArgs) -> LoxResult {
43 Ok(LoxValue::Bool(matches!(
44 args.head.unwrap(),
45 LoxValue::BoundMethod(_, _) | LoxValue::Coroutine(_) | LoxValue::PrimitiveMethod(_, _)
46 )))
47}
48
49pub(super) fn is_class(args: LoxArgs) -> LoxResult {
50 Ok(LoxValue::Bool(matches!(
51 args.head.unwrap(),
52 LoxValue::Class(_)
53 )))
54}
55
56pub(super) fn is_map(args: LoxArgs) -> LoxResult {
57 Ok(LoxValue::Bool(matches!(
58 args.head.unwrap(),
59 LoxValue::Map(_)
60 )))
61}
62
63pub(super) fn is_bytes(args: LoxArgs) -> LoxResult {
64 Ok(LoxValue::Bool(matches!(
65 args.head.unwrap(),
66 LoxValue::Bytes(_)
67 )))
68}
69
70pub(super) fn is_error(args: LoxArgs) -> LoxResult {
71 Ok(LoxValue::Bool(matches!(
72 args.head.unwrap(),
73 LoxValue::Error(_)
74 )))
75}
76
77pub(super) fn is_nil(args: LoxArgs) -> LoxResult {
78 Ok(LoxValue::Bool(matches!(args.head.unwrap(), LoxValue::Nil)))
79}
80
81macro_rules! default_collection {
82 ( $name:ident, $inner:ty, $loxvalue_variant:ident, $( $index:tt )+ ) => {
83 #[derive(Debug, Clone)]
84 struct $name($inner, LoxValue);
85
86 impl LoxObject for $name {
87 fn type_name() -> String
88 where
89 Self: Sized,
90 {
91 stringify!($name).to_string()
92 }
93
94 fn get(
95 &self,
96 _this: Shared<dyn LoxObject>,
97 key: &str,
98 ) -> Result<LoxValue, Option<LoxError>> {
99 Ok(LoxValue::$loxvalue_variant(self.0.clone()).get(key)?)
100 }
101
102 fn set(
103 &mut self,
104 _this: Shared<dyn LoxObject>,
105 key: &str,
106 value: LoxValue,
107 ) -> Result<(), Option<LoxError>> {
108 LoxValue::$loxvalue_variant(self.0.clone()).set(key, value)?;
109 Ok(())
110 }
111
112 $( $index )+
113
114 fn index_set(
115 &mut self,
116 key: LoxValue,
117 value: LoxValue,
118 ) -> Result<(), LoxError> {
119 LoxValue::$loxvalue_variant(self.0.clone()).index_set(key, value)
120 }
121 }
122 };
123}
124
125pub(super) fn set_default(mut args: LoxArgs) -> LoxResult {
126 match args.head.clone().unwrap() {
127 LoxValue::Arr(arr) => {
128 default_collection!(
129 DefaultArray,
130 Shared<Vec<LoxValue>>,
131 Arr,
132 fn index(&self, key: LoxValue) -> Result<LoxValue, LoxError> {
133 self.0
134 .read()
135 .get(usize::try_from(key)?)
136 .map_or_else(|| self.1.call([].into()), |value| Ok(value.clone()))
137 }
138 );
139
140 Ok(LoxValue::external(DefaultArray(
141 arr,
142 args.drain().next().unwrap(),
143 )))
144 }
145 LoxValue::Map(map) => {
146 default_collection!(
147 DefaultMap,
148 Shared<HashMap<MapKey, LoxValue>>,
149 Map,
150 fn index(&self, key: LoxValue) -> Result<LoxValue, LoxError> {
151 self.0
152 .read()
153 .get(&MapKey::verify_key(key)?)
154 .map_or_else(|| self.1.call([].into()), |value| Ok(value.clone()))
155 }
156 );
157
158 Ok(LoxValue::external(DefaultMap(
159 map,
160 args.drain().next().unwrap(),
161 )))
162 }
163 _ => Err(LoxError::type_error(
164 format!("'{}' has no attribute 'set_default'", args.head.unwrap()).into(),
165 )),
166 }
167}