sizzle_parser/
tysys.rs

1//! Core type system expressions.
2
3use std::path::PathBuf;
4
5use crate::Identifier;
6
7/// A type expression is something that we resolve from an identifier and are
8/// valid as type parameters.  These aren't always necessarily types, but are
9/// type-related expressions.
10#[derive(Clone, Debug)]
11pub enum TyExpr {
12    /// None.
13    ///
14    /// This is a special type only for use in Union types.
15    None,
16
17    /// A type.
18    Ty(Ty),
19
20    /// A value, possibly resolved from a const.
21    ///
22    /// This isn't a normal type, but it's valid and we can resolve to it from
23    /// things that look like types and then would proceed to error from that.
24    Int(ConstValue),
25}
26
27impl TyExpr {
28    /// Create a new simple type expression.
29    pub fn new_simple(ident: Identifier) -> Self {
30        Self::Ty(Ty::Simple(ident))
31    }
32
33    /// Create a new integer type expression.
34    pub fn new_int(v: u64) -> Self {
35        Self::Int(ConstValue::Int(v))
36    }
37
38    /// Iterate over all the identifiers in the type expression.
39    pub fn iter_idents(&self) -> impl Iterator<Item = &Identifier> {
40        // FIXME I couldn't figure out how to make this no-alloc.
41        let idents = match self {
42            TyExpr::Ty(t) => t.iter_idents().collect::<Vec<_>>(),
43            TyExpr::Int(_) | TyExpr::None => Vec::new(),
44        };
45
46        idents.into_iter()
47    }
48}
49
50/// A type expression.
51///
52/// This can be used either to indicate the class's parent's type or a field's
53/// type.
54#[derive(Clone, Debug)]
55pub enum Ty {
56    /// An imported type.
57    Imported(PathBuf, Identifier, Identifier),
58
59    /// A simple type without arguments.
60    Simple(Identifier),
61
62    /// A complex type with arguments (possibly zero, like in an empty `Union`).
63    Complex(Identifier, Vec<TyExpr>),
64}
65
66impl Ty {
67    /// The base name of the type, without any arguments.
68    pub fn base_name(&self) -> &Identifier {
69        match self {
70            Ty::Imported(_, _, name) => name,
71            Ty::Simple(name) => name,
72            Ty::Complex(name, _) => name,
73        }
74    }
75
76    /// Iterate over all the identifiers in the type.
77    pub fn iter_idents(&self) -> impl Iterator<Item = &Identifier> {
78        let bn = self.base_name();
79
80        let ext = match self {
81            Ty::Imported(_, _, _) | Ty::Simple(_) => &[],
82            Ty::Complex(_, ch) => ch.as_slice(),
83        };
84
85        std::iter::once(bn).chain(ext.iter().flat_map(|e| e.iter_idents()))
86    }
87}
88
89/// A constant value.
90#[derive(Clone, Debug, Eq, PartialEq)]
91pub enum ConstValue {
92    /// Literal integer values.
93    Int(u64),
94
95    /// An integer value shifted to the left by another integer value.  This is
96    /// useful for very large numbers like 2**256 - 1.
97    Binop(Binop, u64, u64),
98}
99
100/// A binary operation.
101#[derive(Copy, Clone, Debug, Eq, PartialEq)]
102pub enum Binop {
103    /// Addition.
104    Add,
105
106    /// Multiplication.
107    Mul,
108
109    /// Shift left.
110    Shl,
111}
112
113impl ConstValue {
114    /// Evaluate the constant value.
115    pub fn eval(&self) -> u64 {
116        match self {
117            ConstValue::Int(v) => *v,
118            ConstValue::Binop(op, a, b) => match op {
119                Binop::Add => a + b,
120                Binop::Mul => a * b,
121                Binop::Shl => a << b,
122            },
123        }
124    }
125}