Skip to main content

lutra_bin/value/
mod.rs

1//! Generic value object
2//!
3//! [Value] can represent any value in the Lutra type system.
4//! It is essentially moving type information from compile time into runtime,
5//! which is why it not recommended to use in general.
6//!
7//! Use this only when you need dynamic types, i.e. data whose type cannot be
8//! determined at compile time.
9
10mod decode;
11mod encode;
12mod fold;
13mod print_source;
14
15pub use fold::ValueVisitor;
16
17use crate::{boxed, string, vec};
18
19use crate::ir;
20use crate::{Error, Result};
21
22/// Generic Lutra value object
23#[derive(Clone, Debug, PartialEq)]
24pub enum Value {
25    Prim8(u8),
26    Prim16(u16),
27    Prim32(u32),
28    Prim64(u64),
29
30    // TODO: replace with Array<Prim8>
31    Text(string::String),
32
33    Tuple(vec::Vec<Value>),
34    Array(vec::Vec<Value>),
35    Enum(usize, boxed::Box<Value>),
36}
37
38impl Value {
39    pub fn unit() -> Value {
40        Value::Tuple(vec![])
41    }
42
43    pub fn expect_prim8(&self) -> Result<u8> {
44        match self {
45            Value::Prim8(value) => Ok(*value),
46            _ => Err(Error::BadValueType {
47                expected: "Prim8",
48                found: self.name(),
49            }),
50        }
51    }
52
53    pub fn expect_prim16(&self) -> Result<u16> {
54        match self {
55            Value::Prim16(value) => Ok(*value),
56            _ => Err(Error::BadValueType {
57                expected: "Prim16",
58                found: self.name(),
59            }),
60        }
61    }
62
63    pub fn expect_prim32(&self) -> Result<u32> {
64        match self {
65            Value::Prim32(value) => Ok(*value),
66            _ => Err(Error::BadValueType {
67                expected: "Prim32",
68                found: self.name(),
69            }),
70        }
71    }
72
73    pub fn expect_prim64(&self) -> Result<u64> {
74        match self {
75            Value::Prim64(value) => Ok(*value),
76            _ => Err(Error::BadValueType {
77                expected: "Prim64",
78                found: self.name(),
79            }),
80        }
81    }
82
83    pub fn expect_text(&self) -> Result<&str> {
84        match self {
85            Value::Text(value) => Ok(value),
86            _ => Err(Error::BadValueType {
87                expected: "Text",
88                found: self.name(),
89            }),
90        }
91    }
92
93    pub fn expect_tuple(&self) -> Result<&[Value]> {
94        match self {
95            Value::Tuple(value) => Ok(value),
96            _ => Err(Error::BadValueType {
97                expected: "Tuple",
98                found: self.name(),
99            }),
100        }
101    }
102
103    pub fn expect_array(&self) -> Result<&[Value]> {
104        match self {
105            Value::Array(value) => Ok(value),
106            _ => Err(Error::BadValueType {
107                expected: "Array",
108                found: self.name(),
109            }),
110        }
111    }
112
113    pub fn expect_enum(&self) -> Result<(usize, &Value)> {
114        match self {
115            Value::Enum(tag, inner) => Ok((*tag, inner)),
116            _ => Err(Error::BadValueType {
117                expected: "Enum",
118                found: self.name(),
119            }),
120        }
121    }
122
123    fn name(&self) -> &'static str {
124        match self {
125            Value::Prim8(..) => "Prim8",
126            Value::Prim16(..) => "Prim16",
127            Value::Prim32(..) => "Prim32",
128            Value::Prim64(..) => "Prim64",
129            Value::Text(..) => "Text",
130            Value::Tuple(..) => "Tuple",
131            Value::Array(..) => "Array",
132            Value::Enum(..) => "Enum",
133        }
134    }
135}
136
137#[derive(Clone, Copy, Debug, PartialEq)]
138enum TyClass<'t> {
139    Prim8,
140    Prim16,
141    Prim32,
142    Prim64,
143    PrimText,
144    Tuple(&'t [ir::TyTupleField]),
145    Array(&'t ir::Ty),
146    Enum(&'t [ir::TyEnumVariant]),
147}
148
149impl<'t> TyClass<'t> {
150    fn of_ty(ty_mat: &'t ir::Ty) -> Result<Self> {
151        Ok(match &ty_mat.kind {
152            ir::TyKind::Primitive(ir::TyPrimitive::bool)
153            | ir::TyKind::Primitive(ir::TyPrimitive::int8)
154            | ir::TyKind::Primitive(ir::TyPrimitive::uint8) => TyClass::Prim8,
155            ir::TyKind::Primitive(ir::TyPrimitive::int16)
156            | ir::TyKind::Primitive(ir::TyPrimitive::uint16) => TyClass::Prim16,
157            ir::TyKind::Primitive(ir::TyPrimitive::int32)
158            | ir::TyKind::Primitive(ir::TyPrimitive::uint32)
159            | ir::TyKind::Primitive(ir::TyPrimitive::float32) => TyClass::Prim32,
160            ir::TyKind::Primitive(ir::TyPrimitive::int64)
161            | ir::TyKind::Primitive(ir::TyPrimitive::uint64)
162            | ir::TyKind::Primitive(ir::TyPrimitive::float64) => TyClass::Prim64,
163
164            ir::TyKind::Primitive(ir::TyPrimitive::text) => TyClass::PrimText,
165
166            ir::TyKind::Tuple(t) => TyClass::Tuple(t),
167            ir::TyKind::Array(t) => TyClass::Array(t),
168            ir::TyKind::Enum(t) => TyClass::Enum(t),
169
170            ir::TyKind::Function(..) => return Err(Error::InvalidType),
171            ir::TyKind::Ident(..) => return Err(Error::Bug),
172        })
173    }
174}