1pub use self::{super::{Chunk, VirtualMachine}, Nillable::{Nil, NonNil}};
2use hashbrown::HashMap;
3use std::{borrow::Borrow, fmt::{Debug, Display, Formatter, Result as FMTResult}, hash::{BuildHasher, Hash, Hasher}, mem::take, ptr::{eq, hash}, sync::{Arc, Mutex}};
4
5macro_rules! value_conversions {
6 (
7 impl<$lf:tt $(; $($param:tt),*)?> for $convert:ident @ $for:ty $code:block
8 $($rest:tt)*
9 ) => {
10 impl<$lf $(, $($param),*)?> From<$for> for Value<$lf> {
11 fn from($convert: $for) -> Value<$lf> {
12 $code
13 }
14 }
15
16 value_conversions! {$($rest)*}
17 };
18 () => {}
19}
20
21macro_rules! nillable_conversions {
22 (
23 impl<$lf:tt $(; $($param:tt),*)?> all
24 for $convert:ident @ $for:ty $code:block $($rest:tt)*
25 ) => {
26 impl<$lf $(, $($param),*)?> IntoNillable<$lf> for $for {
27 #[inline]
28 fn nillable(self) -> Nillable<$lf> {
29 let $convert = self;
30 $code
31 }
32 }
33
34 impl<$lf $(, $($param),*)?> From<$for> for Nillable<$lf> {
35 #[inline]
36 fn from($convert: $for) -> Self {
37 $code
38 }
39 }
40
41 nillable_conversions! {$($rest)*}
42 };
43 (
44 impl<$lf:tt $(; $($param:tt),*)?>
45 for $convert:ident @ $for:ty $code:block $($rest:tt)*
46 ) => {
47 impl<$lf $(, $($param),*)?> IntoNillable<$lf> for $for {
48 #[inline]
49 fn nillable(self) -> Nillable<$lf> {
50 let $convert = self;
51 $code
52 }
53 }
54
55 nillable_conversions! {$($rest)*}
56 };
57 () => {}
58}
59
60#[macro_export]
61macro_rules! lua_value {
62 ($raw:literal) => {$crate::vm::value::Value::from($raw)};
63 ($($other:tt)*) => {Value::Table(lua_table! {$($other)*}.arc())}
64}
65
66#[macro_export]
67macro_rules! lua_table {
68 ($($arm:tt)*) => {{
69 #[allow(unused_assignments, unused_mut, unused_variables, unused_imports)]
70 {
71 use $crate::{vm::value::{Table, Value}, lua_table_inner, lua_value};
72 use hashbrown::HashMap;
73 use std::{default::Default, sync::Mutex};
74
75 let mut table = HashMap::<Value, Value>::new();
76 let mut counter = 1;
77
78 lua_table_inner!(table counter {$($arm)*});
79
80 Table {data: Mutex::new(table), ..Default::default()}
81 }
82 }}
83}
84
85#[macro_export]
86macro_rules! lua_table_inner {
87 ($table:ident $counter:ident {[$key:expr] = $value:expr $(, $($rest:tt)*)?}) => {
88 {
89 $table.insert(lua_table_inner!($key), lua_table_inner!($value));
90 }
91
92 lua_table_inner!($table $counter {$($($rest)*)?});
93 };
94 ($table:ident $counter:ident {$key:ident = $value:expr $(, $($rest:tt)*)?}) => {
95 {
96 $table.insert(Value::from(stringify!($key)), lua_table_inner!($value));
97 }
98
99 lua_table_inner!($table $counter {$($($rest)*)?});
100 };
101 ($table:ident $counter:ident {$value:expr $(, $($rest:tt)*)?}) => {
102 {
103 $table.insert(Value::from($counter), lua_table_inner!($value));
104 $counter += 1;
105 }
106
107 lua_table_inner!($table $counter {$($($rest)*)?});
108 };
109 ($table:ident $counter:ident {$($rest:tt)*}) => {};
110
111 ($value:literal) => {lua_value!($value)};
112 ($value:expr) => {$value}
113}
114
115#[macro_export]
116macro_rules! lua_tuple {
117 ($($arm:tt)*) => {{
118 #[allow(unused_assignments, unused_mut, unused_variables, unused_imports)]
119 {
120 use $crate::{
121 vm::value::{IntoNillable, Nillable::NonNil, Table, Value},
122 lua_tuple_inner, lua_value
123 };
124 use hashbrown::HashMap;
125 use std::{default::Default, sync::Mutex};
126
127 let mut table = HashMap::<Value, Value>::new();
128 let mut counter = 0;
129
130 lua_tuple_inner!(table counter {$($arm)*});
131 table.insert(Value::Integer(0), Value::Integer(counter));
132
133 Table {data: Mutex::new(table), ..Default::default()}
134 }
135 }}
136}
137
138#[macro_export]
139macro_rules! lua_tuple_inner {
140 ($table:ident $counter:ident {$value:expr $(, $($rest:tt)*)?}) => {
141 {
142 $counter += 1;
143 if let NonNil(value) = IntoNillable::nillable(lua_tuple_inner!($value).clone()) {
144 $table.insert(Value::Integer($counter), value);
145 }
146 }
147
148 lua_tuple_inner!($table $counter {$($($rest)*)?});
149 };
150 ($table:ident $counter:ident {}) => {};
151
152 ($value:literal) => {lua_value!($value)};
153 ($value:expr) => {$value}
154}
155
156pub trait UserData: Send + Sync {
157 fn type_name(&self) -> &'static str;
158}
159
160pub type NativeFunction<'n> = &'n (dyn Fn(Arc<Table<'n>>, &VirtualMachine<'n>)
161 -> Result<Arc<Table<'n>>, String> + Send + Sync);
162
163#[derive(Clone)]
166pub enum Value<'n> {
167 Integer(i64),
168 String(Box<str>),
169 Boolean(bool),
170 Table(Arc<Table<'n>>),
171 UserData {
172 data: &'n dyn UserData,
173 meta: Option<Arc<Table<'n>>>
174 },
175 Function(Arc<Function<'n>>),
176 NativeFunction(NativeFunction<'n>)
177}
178
179impl<'n> Value<'n> {
180 pub fn new_string(string: impl AsRef<str>) -> Self {
181 Self::String(string.as_ref().to_owned().into_boxed_str())
182 }
183
184 pub fn type_name(&self) -> &'static str {
185 match self {
186 Self::Integer(_) => "number",
187 Self::String(_) => "string",
188 Self::Boolean(_) => "boolean",
189 Self::Table(_) => "table",
190 Self::UserData {data, ..} => data.type_name(),
191 Self::Function(_) | Self::NativeFunction(_) => "function"
192 }
193 }
194
195 pub fn coerce_to_bool(&self) -> bool {
199 match self {
200 Self::Boolean(value) => *value,
201 _ => true
202 }
203 }
204
205 pub fn coerce_to_boolean<'nn>(&self) -> Value<'nn> {
207 Value::Boolean(self.coerce_to_bool())
208 }
209
210 pub fn integer(&self) -> Option<i64> {
211 match self {
212 Self::Integer(integer) => Some(*integer),
213 _ => None
214 }
215 }
216
217 pub fn string(&self) -> Option<&str> {
218 match self {
219 Self::String(string) => Some(string),
220 _ => None
221 }
222 }
223
224 pub fn boolean(&self) -> Option<bool> {
225 match self {
226 Self::Boolean(boolean) => Some(*boolean),
227 _ => None
228 }
229 }
230
231 pub fn table(&self) -> Option<&Arc<Table<'n>>> {
232 match self {
233 Self::Table(table) => Some(table),
234 _ => None
235 }
236 }
237
238 pub fn function(&self) -> Option<&Arc<Function<'n>>> {
239 match self {
240 Self::Function(function) => Some(function),
241 _ => None
242 }
243 }
244}
245
246impl Display for Value<'_> {
247 fn fmt(&self, f: &mut Formatter) -> FMTResult {
248 match self {
249 Self::Integer(integer) => write!(f, "{}", integer),
250 Self::String(string) => write!(f, "{}", string),
251 Self::Boolean(boolean) => write!(f, "{}", boolean),
252 Self::Table(table) => write!(f, "{}", table),
253 Self::UserData {..} => todo!(),
254 Self::Function(function) => write!(f, "{}", function),
255 Self::NativeFunction(function) => write!(f, "function: {:p}", *function)
256 }
257 }
258}
259
260impl Debug for Value<'_> {
261 fn fmt(&self, f: &mut Formatter) -> FMTResult {
262 match self {
263 Self::Integer(integer) => Debug::fmt(integer, f),
264 Self::String(string) => Debug::fmt(string, f),
265 Self::Boolean(boolean) => Debug::fmt(boolean, f),
266 Self::Table(table) => Debug::fmt(table, f),
267 Self::UserData {..} => todo!(),
268 Self::Function(function) => Debug::fmt(function, f),
269 Self::NativeFunction(function) => write!(f, "function: {:p}", function)
270 }
271 }
272}
273
274impl Eq for Value<'_> {}
275
276impl<'l, 'r> PartialEq<Value<'r>> for Value<'l> {
277 fn eq(&self, other: &Value<'r>) -> bool {
278 match (self, other) {
279 (Self::Integer(a), Value::Integer(b)) => *a == *b,
280 (Self::String(a), Value::String(b)) => *a == *b,
281 (Self::Boolean(a), Value::Boolean(b)) => *a == *b,
282 (Self::Function(a), Value::Function(b)) =>
283 eq(Arc::as_ptr(a) as *const u8, Arc::as_ptr(b) as *const u8),
284 (Self::Table(a), Value::Table(b)) =>
285 eq(Arc::as_ptr(a) as *const u8, Arc::as_ptr(b) as *const u8),
286 (Self::NativeFunction(a), Value::NativeFunction(b)) =>
287 eq(*a as *const _ as *const u8, *b as *const _ as *const u8),
288 _ => false
289 }
290 }
291}
292
293impl Hash for Value<'_> {
294 fn hash<H>(&self, state: &mut H)
295 where H: Hasher {
296 match self {
297 Self::Integer(integer) => integer.hash(state),
298 Self::String(string) => string.hash(state),
299 Self::Boolean(boolean) => boolean.hash(state),
300 Self::Table(arc) => Arc::as_ptr(arc).hash(state),
301 Self::UserData {data, ..} => hash(data, state),
302 Self::Function(arc) => Arc::as_ptr(arc).hash(state),
303 Self::NativeFunction(func) => hash(func, state)
304 }
305 }
306}
307
308value_conversions! {
309 impl<'n> for value @ i64 {Value::Integer(value)}
310 impl<'n; 'r> for value @ &'r str {Value::String(value.into())}
311 impl<'n> for value @ Box<str> {Value::String(value)}
312 impl<'n> for value @ String {Value::String(value.into_boxed_str())}
313 impl<'n> for value @ bool {Value::Boolean(value)}
314 impl<'n> for value @ Table<'n> {Value::Table(value.arc())}
315 impl<'n> for value @ Arc<Table<'n>> {Value::Table(value)}
316}
317
318#[derive(Clone, Eq, Hash, PartialEq)]
323pub enum Nillable<'n> {
324 NonNil(Value<'n>),
326 Nil
328}
329
330impl<'n> Nillable<'n> {
331 pub fn type_name(&self) -> &'static str {
333 match self {
334 NonNil(value) => value.borrow().type_name(),
335 Nil => "nil"
336 }
337 }
338
339 pub fn option(self) -> Option<Value<'n>> {
341 self.into()
342 }
343
344 pub fn coerce_to_bool(&self) -> bool {
348 match self {
349 NonNil(value) => value.borrow().coerce_to_bool(),
350 Nil => false
351 }
352 }
353
354 pub fn coerce_to_boolean<'nn>(&self) -> Value<'nn> {
356 Value::Boolean(self.coerce_to_bool())
357 }
358
359 pub fn is_nil(&self) -> bool {
360 matches!(self, Nil)
361 }
362
363 pub fn is_non_nil(&self) -> bool {
364 matches!(self, NonNil(_))
365 }
366}
367
368impl Display for Nillable<'_> {
369 fn fmt(&self, f: &mut Formatter) -> FMTResult {
370 match self {
371 Nillable::NonNil(value) => write!(f, "{}", value.borrow()),
372 Nil => write!(f, "nil")
373 }
374 }
375}
376
377impl Debug for Nillable<'_> {
378 fn fmt(&self, f: &mut Formatter) -> FMTResult {
379 match self {
380 Nillable::NonNil(value) => write!(f, "{:?}", value.borrow()),
381 Nil => write!(f, "nil")
382 }
383 }
384}
385
386impl Default for Nillable<'_> {
387 fn default() -> Self {
388 Nil
389 }
390}
391
392pub trait IntoNillable<'n>: Sized {
393 fn nillable(self) -> Nillable<'n>;
394}
395
396nillable_conversions! {
397 impl<'n> all for value @ Option<Value<'n>> {
400 match value {
401 Some(value) => NonNil(value),
402 None => Nil
403 }
404 }
405
406 impl<'n; 'r> for value @ Option<&'r Value<'n>> {
407 match value {
408 Some(value) => NonNil(value.clone()),
409 None => Nil
410 }
411 }
412
413 impl<'n> for value @ Nillable<'n> {value}
416 impl<'n> all for value @ Value<'n> {NonNil(value)}
417
418 impl<'n> all for value @ i64 {NonNil(value.into())}
421 impl<'n; 'r> all for value @ &'r str {NonNil(value.into())}
422 impl<'n> all for value @ Box<str> {NonNil(value.into())}
423 impl<'n> all for value @ String {NonNil(value.into())}
424 impl<'n> all for value @ bool {NonNil(value.into())}
425 impl<'n> all for value @ Table<'n> {NonNil(value.into())}
426 impl<'n> all for value @ Arc<Table<'n>> {NonNil(value.into())}
427 impl<'n> all for _value @ () {Nil}
428}
429
430impl<'n> From<Nillable<'n>> for Option<Value<'n>> {
431 fn from(nillable: Nillable<'n>) -> Self {
432 match nillable {
433 NonNil(value) => Some(value),
434 Nil => None
435 }
436 }
437}
438
439#[derive(Clone, Debug)]
440pub enum MaybeUpValue<'n> {
441 UpValue(Arc<Mutex<Nillable<'n>>>),
442 Normal(Nillable<'n>)
443}
444
445impl<'n> MaybeUpValue<'n> {
446 pub fn up_value(&mut self) -> &Arc<Mutex<Nillable<'n>>> {
447 match self {
448 Self::UpValue(up_value) => up_value,
449 Self::Normal(normal) => {
450 let normal = Arc::new(Mutex::new(std::mem::replace(normal, Nil)));
451 *self = Self::UpValue(normal);
452 match self {
453 Self::UpValue(up_value) => up_value,
454 _ => unreachable!()
455 }
456 }
457 }
458 }
459}
460
461impl Default for MaybeUpValue<'_> {
462 fn default() -> Self {
463 Self::Normal(Nil)
464 }
465}
466
467#[derive(Default)]
468pub struct Table<'n> {
469 pub data: Mutex<HashMap<Value<'n>, Value<'n>>>,
470 pub metatable: Mutex<Option<Arc<Table<'n>>>>
471}
472
473impl<'n> Table<'n> {
474 #[inline]
476 pub fn array_insert(&self, index: i64, mut value: Nillable<'n>) {
477 let len = self.array_len();
478 let mut data = self.data.lock().unwrap();
479
480 (index..=(len.max(1) + 1))
481 .for_each(|index| match take(&mut value) {
482 NonNil(new) =>
483 value = data.insert(Value::Integer(index), new).nillable(),
484 Nil =>
485 value = data.remove(&Value::Integer(index)).nillable()
486 });
487 }
488
489 #[inline]
490 pub fn array_remove(&self, index: i64) -> Nillable<'n> {
491 let len = self.array_len();
492 let mut data = self.data.lock().unwrap();
493
494 let mut value = Nil;
495 (index..=len).rev()
496 .for_each(|index| match take(&mut value) {
497 NonNil(new) =>
498 value = data.insert(Value::Integer(index as i64), new).nillable(),
499 Nil =>
500 value = data.remove(&Value::Integer(index as i64)).nillable()
501 });
502 value
503 }
504
505 #[inline]
506 pub fn array_push(&self, value: Nillable<'n>) {
507 self.array_insert(self.array_len(), value)
508 }
509
510 pub fn array_len(&self) -> i64 {
511 self.data.lock().unwrap().iter()
512 .filter_map(|(key, _)| key.integer())
513 .fold(0, |result, index| result.max(index))
514 }
515
516 pub fn array_is_empty(&self) -> bool {
517 self.data.lock().unwrap().iter()
518 .any(|(key, _)| key.integer().is_some())
519 }
520
521 #[inline]
523 pub fn tuple_insert(&self, index: i64, mut value: Nillable<'n>) {
524 let len = self.tuple_len();
525 let mut data = self.data.lock().unwrap();
526 data.insert(Value::Integer(0), Value::Integer(len + 1));
527
528 (index..=(len.max(1) + 1))
529 .for_each(|index| match take(&mut value) {
530 NonNil(new) =>
531 value = data.insert(Value::Integer(index), new).nillable(),
532 Nil =>
533 value = data.remove(&Value::Integer(index)).nillable()
534 });
535 }
536
537 pub fn tuple_len(&self) -> i64 {
538 self.data.lock().unwrap().get(&Value::Integer(0))
539 .unwrap().integer().unwrap()
540 }
541
542 pub fn index<'qn>(&self, index: &Value<'qn>) -> Nillable<'n> {
543 let data = self.data.lock().unwrap();
553 let mut hasher = data.hasher().build_hasher();
554 index.hash(&mut hasher);
555 data.raw_entry().from_hash(hasher.finish(), |check| index == check)
556 .map(|(_, value)| value).cloned().nillable()
557 }
559
560 pub fn arc(self) -> Arc<Self> {
561 Arc::new(self)
562 }
563}
564
565impl<'n> PartialEq for Table<'n> {
566 fn eq(&self, other: &Table<'n>) -> bool {
567 eq(self, other)
568 }
569}
570
571impl Display for Table<'_> {
572 fn fmt(&self, f: &mut Formatter) -> FMTResult {
573 write!(f, "table: {:p}", &*self)
574 }
575}
576
577impl Debug for Table<'_> {
578 fn fmt(&self, f: &mut Formatter) -> FMTResult {
579 match self.data.try_lock() {
580 Ok(data) => {
581 let mut first = true;
582 let mut comma = || {
583 if first {first = false; ""}
584 else {", "}
585 };
586
587 write!(f, "{{")?;
588 let mut array = data.iter()
589 .filter_map(|(key, value)| if let Value::Integer(key) = key
590 {Some((key, value))} else {None})
591 .collect::<Vec<_>>();
592 array.sort_unstable_by(|(a, _), (b, _)| a.cmp(b));
593 if let Some((highest, _)) = array.last() {
594 (1..=**highest)
595 .map(|index| array.iter().find(|value| *value.0 == index)
596 .map(|(_, value)| *value))
597 .try_for_each(|value| write!(f, "{}{:?}", comma(), value.nillable()))?;
598 }
599
600 data.iter()
601 .try_for_each(|(key, value)| match key {
602 Value::Integer(_) => Ok(()),
603 key => write!(f, "{}[{:?}] = {:?}", comma(), key, value)
604 })?;
605
606 write!(f, "}}")
607 },
608 Err(_) => write!(f, "{{<table is being accessed>}}")
609 }
610 }
611}
612
613#[derive(Debug)]
614pub struct Function<'n> {
615 pub up_values: Box<[Arc<Mutex<Nillable<'n>>>]>,
616 pub chunk: Arc<Chunk>
617}
618
619impl Function<'_> {
620 pub fn arc(self) -> Arc<Self> {
621 Arc::new(self)
622 }
623}
624
625impl<'n> PartialEq for Function<'n> {
626 fn eq(&self, other: &Function<'n>) -> bool {
627 eq(self, other)
628 }
629}
630
631impl Eq for Function<'_> {}
632
633impl Display for Function<'_> {
634 fn fmt(&self, f: &mut Formatter) -> FMTResult {
635 write!(f, "function: {:p}", &self)
636 }
637}
638
639impl From<Chunk> for Function<'_> {
640 fn from(chunk: Chunk) -> Self {
641 Self {chunk: chunk.arc(), up_values: vec![].into_boxed_slice()}
642 }
643}