summaryrefslogtreecommitdiffstats
path: root/third_party/rust/jsparagus-stencil/src/function.rs
blob: 212491e610a34606ed118f0b3776f0e4af90bc8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#[derive(Debug)]
pub struct FunctionFlags {
    flags: u16,
}

// WARNING
// The following section is generated by update_stencil.py.
// Do mot modify manually.
//
// @@@@ BEGIN TYPES @@@@
#[derive(Debug, Clone, Copy)]
pub enum FunctionKind {
    NormalFunction = 0,
    Arrow = 1,
    Method = 2,
    ClassConstructor = 3,
    Getter = 4,
    Setter = 5,
    AsmJS = 6,
    Wasm = 7,
    FunctionKindLimit = 8,
}

#[allow(dead_code)]
const FUNCTION_KIND_SHIFT: u16 = 0;
#[allow(dead_code)]
const FUNCTION_KIND_MASK: u16 = 0x0007;
#[allow(dead_code)]
const EXTENDED: u16 = 1 << 3;
#[allow(dead_code)]
const SELF_HOSTED: u16 = 1 << 4;
#[allow(dead_code)]
const BASESCRIPT: u16 = 1 << 5;
#[allow(dead_code)]
const SELFHOSTLAZY: u16 = 1 << 6;
#[allow(dead_code)]
const CONSTRUCTOR: u16 = 1 << 7;
#[allow(dead_code)]
const LAMBDA: u16 = 1 << 9;
#[allow(dead_code)]
const WASM_JIT_ENTRY: u16 = 1 << 10;
#[allow(dead_code)]
const HAS_INFERRED_NAME: u16 = 1 << 11;
#[allow(dead_code)]
const HAS_GUESSED_ATOM: u16 = 1 << 12;
#[allow(dead_code)]
const RESOLVED_NAME: u16 = 1 << 13;
#[allow(dead_code)]
const RESOLVED_LENGTH: u16 = 1 << 14;
#[allow(dead_code)]
const GHOST_FUNCTION: u16 = 1 << 15;
#[allow(dead_code)]
const NORMAL_KIND: u16 = (FunctionKind::NormalFunction as u16) << FUNCTION_KIND_SHIFT;
#[allow(dead_code)]
const ASMJS_KIND: u16 = (FunctionKind::AsmJS as u16) << FUNCTION_KIND_SHIFT;
#[allow(dead_code)]
const WASM_KIND: u16 = (FunctionKind::Wasm as u16) << FUNCTION_KIND_SHIFT;
#[allow(dead_code)]
const ARROW_KIND: u16 = (FunctionKind::Arrow as u16) << FUNCTION_KIND_SHIFT;
#[allow(dead_code)]
const METHOD_KIND: u16 = (FunctionKind::Method as u16) << FUNCTION_KIND_SHIFT;
#[allow(dead_code)]
const CLASSCONSTRUCTOR_KIND: u16 = (FunctionKind::ClassConstructor as u16) << FUNCTION_KIND_SHIFT;
#[allow(dead_code)]
const GETTER_KIND: u16 = (FunctionKind::Getter as u16) << FUNCTION_KIND_SHIFT;
#[allow(dead_code)]
const SETTER_KIND: u16 = (FunctionKind::Setter as u16) << FUNCTION_KIND_SHIFT;
#[allow(dead_code)]
const NATIVE_FUN: u16 = NORMAL_KIND;
#[allow(dead_code)]
const NATIVE_CTOR: u16 = CONSTRUCTOR | NORMAL_KIND;
#[allow(dead_code)]
const ASMJS_CTOR: u16 = CONSTRUCTOR | ASMJS_KIND;
#[allow(dead_code)]
const ASMJS_LAMBDA_CTOR: u16 = CONSTRUCTOR | LAMBDA | ASMJS_KIND;
#[allow(dead_code)]
const WASM: u16 = WASM_KIND;
#[allow(dead_code)]
const INTERPRETED_NORMAL: u16 = BASESCRIPT | CONSTRUCTOR | NORMAL_KIND;
#[allow(dead_code)]
const INTERPRETED_CLASS_CTOR: u16 = BASESCRIPT | CONSTRUCTOR | CLASSCONSTRUCTOR_KIND;
#[allow(dead_code)]
const INTERPRETED_GENERATOR_OR_ASYNC: u16 = BASESCRIPT | NORMAL_KIND;
#[allow(dead_code)]
const INTERPRETED_LAMBDA: u16 = BASESCRIPT | LAMBDA | CONSTRUCTOR | NORMAL_KIND;
#[allow(dead_code)]
const INTERPRETED_LAMBDA_ARROW: u16 = BASESCRIPT | LAMBDA | ARROW_KIND;
#[allow(dead_code)]
const INTERPRETED_LAMBDA_GENERATOR_OR_ASYNC: u16 = BASESCRIPT | LAMBDA | NORMAL_KIND;
#[allow(dead_code)]
const INTERPRETED_GETTER: u16 = BASESCRIPT | GETTER_KIND;
#[allow(dead_code)]
const INTERPRETED_SETTER: u16 = BASESCRIPT | SETTER_KIND;
#[allow(dead_code)]
const INTERPRETED_METHOD: u16 = BASESCRIPT | METHOD_KIND;
#[allow(dead_code)]
const MUTABLE_FLAGS: u16 = RESOLVED_NAME | RESOLVED_LENGTH;
#[allow(dead_code)]
const STABLE_ACROSS_CLONES: u16 =
    CONSTRUCTOR | LAMBDA | SELF_HOSTED | FUNCTION_KIND_MASK | GHOST_FUNCTION;
// @@@@ END TYPES @@@@

#[derive(Debug)]
pub struct FunctionSyntaxKind {
    kind: FunctionKind,
    is_lambda: bool,
    is_generator: bool,
    is_async: bool,
}

impl FunctionSyntaxKind {
    pub fn function_declaration(is_generator: bool, is_async: bool) -> Self {
        Self {
            kind: FunctionKind::NormalFunction,
            is_lambda: false,
            is_generator,
            is_async,
        }
    }

    pub fn function_expression(is_generator: bool, is_async: bool) -> Self {
        Self {
            kind: FunctionKind::NormalFunction,
            is_lambda: true,
            is_generator,
            is_async,
        }
    }

    pub fn method(is_generator: bool, is_async: bool) -> Self {
        Self {
            kind: FunctionKind::Method,
            is_lambda: false,
            is_generator,
            is_async,
        }
    }

    pub fn getter() -> Self {
        FunctionSyntaxKind {
            kind: FunctionKind::Getter,
            is_lambda: false,
            is_generator: false,
            is_async: false,
        }
    }

    pub fn setter() -> Self {
        FunctionSyntaxKind {
            kind: FunctionKind::Setter,
            is_lambda: false,
            is_generator: false,
            is_async: false,
        }
    }

    pub fn arrow(is_async: bool) -> Self {
        Self {
            kind: FunctionKind::Arrow,
            is_lambda: true,
            is_generator: false,
            is_async,
        }
    }

    pub fn is_generator(&self) -> bool {
        self.is_generator
    }

    pub fn is_async(&self) -> bool {
        self.is_async
    }
}

impl FunctionFlags {
    fn new(flags: u16) -> Self {
        debug_assert!(
            (((FunctionKind::FunctionKindLimit as u16) - 1) << FUNCTION_KIND_SHIFT)
                <= FUNCTION_KIND_MASK
        );

        Self { flags }
    }

    /// Returns empty flag that is used for top level script
    pub fn empty() -> Self {
        Self { flags: 0 }
    }

    pub fn interpreted(syntax_kind: FunctionSyntaxKind) -> Self {
        let kind_flag = (syntax_kind.kind as u16) << FUNCTION_KIND_SHIFT;
        let mut flags = BASESCRIPT | kind_flag;
        match syntax_kind.kind {
            FunctionKind::NormalFunction => {
                if !syntax_kind.is_generator && !syntax_kind.is_async {
                    flags |= CONSTRUCTOR;
                }
                if syntax_kind.is_lambda {
                    flags |= LAMBDA;
                }
            }
            FunctionKind::ClassConstructor => {
                debug_assert!(!syntax_kind.is_generator);
                debug_assert!(!syntax_kind.is_async);
                flags |= CONSTRUCTOR;
            }
            _ => {}
        }
        Self::new(flags)
    }

    pub fn is_arrow(&self) -> bool {
        let kind_num = (self.flags >> FUNCTION_KIND_SHIFT) & FUNCTION_KIND_MASK;
        kind_num == FunctionKind::Arrow as u16
    }
}

impl From<FunctionFlags> for u16 {
    fn from(flags: FunctionFlags) -> u16 {
        flags.flags
    }
}