piccolo/
types.rs

1use std::fmt::{self, Debug};
2
3use gc_arena::Collect;
4
5/// An index that points to a register in the stack relative to the current frame.
6#[derive(Debug, Copy, Clone, Eq, PartialEq, Collect)]
7#[collect(require_static)]
8pub struct RegisterIndex(pub u8);
9
10/// An 8 bit index into the constant table
11#[derive(Debug, Copy, Clone, Eq, PartialEq, Collect)]
12#[collect(require_static)]
13pub struct ConstantIndex8(pub u8);
14
15/// A 16 bit index into the constant table
16#[derive(Debug, Copy, Clone, Eq, PartialEq, Collect)]
17#[collect(require_static)]
18pub struct ConstantIndex16(pub u16);
19
20/// An index into the upvalue table
21#[derive(Debug, Copy, Clone, Eq, PartialEq, Collect)]
22#[collect(require_static)]
23pub struct UpValueIndex(pub u8);
24
25/// An index into the prototype table
26#[derive(Debug, Copy, Clone, Eq, PartialEq, Collect)]
27#[collect(require_static)]
28pub struct PrototypeIndex(pub u8);
29
30/// A one byte Option value that can either be Some(0-254) or None
31#[derive(Copy, Clone, Eq, PartialEq, Collect)]
32#[collect(require_static)]
33pub struct Opt254(u8);
34
35#[derive(Debug, Collect, Clone, Copy, PartialEq, Eq)]
36#[collect(require_static)]
37pub enum UpValueDescriptor {
38    Environment,
39    ParentLocal(RegisterIndex),
40    Outer(UpValueIndex),
41}
42
43impl Opt254 {
44    pub fn try_new(v: Option<u8>) -> Option<Opt254> {
45        if let Some(v) = v {
46            if v == 255 {
47                None
48            } else {
49                Some(Opt254(v))
50            }
51        } else {
52            Some(Opt254(255))
53        }
54    }
55
56    pub fn new(v: Option<u8>) -> Opt254 {
57        Opt254::try_new(v).expect("Opt254 cannot hold Some(255)")
58    }
59
60    pub fn some(v: u8) -> Opt254 {
61        Opt254::new(Some(v))
62    }
63
64    pub fn try_some(v: u8) -> Option<Opt254> {
65        Opt254::try_new(Some(v))
66    }
67
68    pub fn none() -> Opt254 {
69        Opt254::new(None)
70    }
71
72    pub fn is_some(self) -> bool {
73        self.to_u8().is_some()
74    }
75
76    pub fn is_none(self) -> bool {
77        self.to_u8().is_none()
78    }
79
80    pub fn to_u8(self) -> Option<u8> {
81        if self.0 == 255 {
82            None
83        } else {
84            Some(self.0)
85        }
86    }
87}
88
89impl Debug for Opt254 {
90    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
91        if self.0 == 255 {
92            write!(fmt, "Opt254(None)")
93        } else {
94            write!(fmt, "Opt254(Some({}))", self.0)
95        }
96    }
97}
98
99/// Count of arguments or return values which can either be a constant between 0-254 or a special
100/// "variable" value.
101#[derive(Debug, Copy, Clone, Eq, PartialEq, Collect)]
102#[collect(require_static)]
103pub struct VarCount(Opt254);
104
105impl VarCount {
106    pub fn variable() -> VarCount {
107        VarCount(Opt254::none())
108    }
109
110    pub fn constant(constant: u8) -> VarCount {
111        VarCount(Opt254::some(constant))
112    }
113
114    pub fn try_constant(constant: u8) -> Option<VarCount> {
115        Opt254::try_some(constant).map(VarCount)
116    }
117
118    pub fn is_variable(self) -> bool {
119        self.0.is_none()
120    }
121
122    pub fn to_constant(self) -> Option<u8> {
123        self.0.to_u8()
124    }
125}