1mod constant;
2mod custom_type;
3mod expression;
4mod external_type;
5mod function;
6mod id;
7mod pattern;
8mod reference;
9mod step;
10mod type_scheme;
11
12use crate::plan::SourceContext;
13use ecow::EcoString;
14
15pub(crate) use constant::{
16 ConstantBitArrayFunctionInstantiation, ConstantBitArrayListInstantiation,
17 ConstantBitArrayReference, ConstantBitArraySegment, ConstantBitArrayValue,
18 ConstantBoolFunctionInstantiation, ConstantBoolListInstantiation, ConstantBoolReference,
19 ConstantCustomFunctionInstantiation, ConstantCustomListInstantiation, ConstantCustomReference,
20 ConstantExternalFunctionInstantiation, ConstantExternalListInstantiation,
21 ConstantFloatFunctionInstantiation, ConstantFloatListInstantiation, ConstantFloatReference,
22 ConstantFloatValue, ConstantFunctionFunctionInstantiation, ConstantFunctionInstantiation,
23 ConstantFunctionListInstantiation, ConstantGenericFunctionInstantiation,
24 ConstantGenericListInstantiation, ConstantInstantiation, ConstantIntFunctionInstantiation,
25 ConstantIntListInstantiation, ConstantIntReference, ConstantIntValue,
26 ConstantListConstructionError, ConstantListFunctionInstantiation, ConstantListInstantiation,
27 ConstantListListInstantiation, ConstantNilFunctionInstantiation, ConstantNilListInstantiation,
28 ConstantNilReference, ConstantParameterListListInstantiation,
29 ConstantStringFunctionInstantiation, ConstantStringListInstantiation, ConstantStringReference,
30 ConstantStringValue, ConstantTemplateSignature, ConstantTemplates,
31 ConstantTupleFunctionInstantiation, ConstantTupleListInstantiation, ConstantTupleReference,
32 ConstantUtfCodepointFunctionInstantiation, ConstantUtfCodepointListInstantiation,
33 ConstantValue,
34};
35pub use constant::{ConstantTemplate, ConstantTemplateId};
36pub(crate) use custom_type::{CustomConstructor, CustomConstructorField};
37pub use custom_type::{
38 CustomConstructorDefinition, CustomFieldDefinition, CustomTypeDefinition,
39 CustomTypeParameterId, CustomTypePublicity, CustomTypeTemplate,
40};
41pub(crate) use external_type::ExternalValueShape;
42pub use external_type::{ExternalType, ExternalTypeDefinition, ExternalTypeName};
43
44#[cfg(test)]
45pub(crate) use expression::TypedFunctionExpr;
46pub(crate) use expression::custom_constructor_expr;
47pub(crate) use expression::{
48 BitArrayBitsSize, BitArrayEvaluatedSize, BitArrayExprKind, BitArrayFunctionExprKind,
49 BitArraySegment, BoolCaseBranches, BoolExprKind, BoolFunctionExprKind, CallArgStorage,
50 CaptureArg, CustomBoolCaseBranches, CustomCaseBranches, CustomConstruction, CustomExprKind,
51 CustomFieldAccess, CustomFunctionExprKind, CustomLocalExpr, Endianness, ExprKind,
52 ExternalExprKind, ExternalFunctionExprKind, FloatBitSize, FloatCaseBranches, FloatExprKind,
53 FloatFunctionExprKind, FunctionExprKind, FunctionFunctionExprKind, GenericExpr,
54 GenericExprKind, GenericFunctionExpr, GenericFunctionExprKind, IntCaseBranches, IntExprKind,
55 IntFunctionExprKind, ListElements, ListFunctionExprKind, NilExprKind, NilFunctionExprKind,
56 PanicExpr, PanicExprKind, PotentiallyUninhabitedCallArg, StringCaseBranches, StringEncoding,
57 StringExprKind, StringFunctionExprKind, TupleExprKind, TupleFunctionExprKind,
58 TypedFunctionExprKind, UtfCodepointExprKind, UtfCodepointFunctionExprKind,
59};
60pub use expression::{
61 BitArrayExpr, BitArrayFunctionExpr, BoolExpr, BoolFunctionExpr, CallArg, CustomExpr,
62 CustomFunctionExpr, Expr, ExternalExpr, ExternalFunctionExpr, FloatExpr, FloatFunctionExpr,
63 FunctionExpr, FunctionFunctionExpr, IntExpr, IntFunctionExpr, ListFunctionExpr, NilExpr,
64 NilFunctionExpr, StringExpr, StringFunctionExpr, TupleExpr, TupleFunctionExpr,
65 UtfCodepointExpr, UtfCodepointFunctionExpr,
66};
67pub(crate) use expression::{
68 BitArrayListExpr, BitArrayListItem, BoolListCaseBranches, BoolListExpr, BoolListItem,
69 CustomListExpr, CustomListItem, ExternalListExpr, ExternalListItem, FloatListExpr,
70 FloatListItem, FunctionListExpr, FunctionListItem, GenericListExpr, GenericListItem,
71 IntListExpr, IntListItem, ListCaseBranches, ListExpr, ListItem, ListListExpr, ListListItem,
72 ListLocalExpr, ListSpreadConstructionError, ListSpreadElements, NilListExpr, NilListItem,
73 ParameterListListExpr, ParameterListListItem, StoredListExpr, StringListExpr, StringListItem,
74 TupleListExpr, TupleListItem, TypedListExpr, TypedListExprKind, TypedListReturnKind,
75 UtfCodepointListExpr, UtfCodepointListItem,
76};
77pub(crate) use function::{
78 BitArrayFunctionReturn, BitArrayReturn, BoolFunctionReturn, BoolReturn, CapturePosition,
79 CustomFunctionReturn, CustomReturn, ExternalFunctionReturn, ExternalReturn,
80 FloatFunctionReturn, FloatReturn, FunctionFunctionReturn, GenericFunctionReturn,
81 GenericListReturn, GenericReturn, IntFunctionReturn, IntReturn, ListFunctionReturn,
82 NilFunctionReturn, NilReturn, ParamLocal, ParamSlot, ParameterListListReturn, ReturnBody,
83 ReturnBodyKind, ReturnExprKind, StringFunctionReturn, StringReturn, TupleFunctionReturn,
84 TupleReturn, UtfCodepointFunctionReturn, UtfCodepointReturn,
85};
86#[cfg(test)]
87pub(crate) use function::{
88 BitArrayListReturn, BoolListReturn, CustomListReturn, FloatListReturn, FunctionListReturn,
89 IntListReturn, ListListReturn, ListReturn, NilListReturn, StringListReturn, TupleListReturn,
90 UtfCodepointListReturn,
91};
92pub use function::{FunctionTemplate, Param, ParamBinding, ReturnExpr};
93#[cfg(test)]
94pub(crate) use id::{
95 BitArrayFunctionFunctionId, BitArrayFunctionId, BoolFunctionFunctionId, BoolFunctionId,
96 CustomFunctionFunctionId, CustomFunctionId, FloatFunctionFunctionId, FloatFunctionId,
97 FunctionFunctionFunctionId, FunctionFunctionId, IntFunctionFunctionId, IntFunctionId,
98 ListFunctionFunctionId, ListFunctionId, NilFunctionFunctionId, NilFunctionId,
99 RuntimeFunctionId, StringFunctionFunctionId, StringFunctionId, TupleFunctionFunctionId,
100 TupleFunctionId, UtfCodepointFunctionFunctionId, UtfCodepointFunctionId,
101};
102pub use id::{
103 BitArrayFunctionLocalId, BitArrayListFunctionLocalId, BitArrayListLocalId, BitArrayLocalId,
104 BoolFunctionLocalId, BoolListFunctionLocalId, BoolListLocalId, BoolLocalId,
105 CustomFunctionLocalId, CustomListFunctionLocalId, CustomListLocalId, CustomLocalId,
106 ExternalFunctionLocalId, ExternalListFunctionLocalId, ExternalListLocalId, ExternalLocalId,
107 FloatFunctionLocalId, FloatListFunctionLocalId, FloatListLocalId, FloatLocalId,
108 FunctionFunctionLocalId, FunctionListFunctionLocalId, FunctionListLocalId,
109 FunctionReturnFamily, FunctionTemplateId, GenericFunctionLocalId, GenericListFunctionLocalId,
110 GenericListLocalId, GenericLocal, GenericLocalId, IntFunctionLocalId, IntListFunctionLocalId,
111 IntListLocalId, IntLocalId, ListFunctionLocal, ListListFunctionLocalId, ListListLocalId,
112 ListLocal, LocalId, ModuleId, NilFunctionLocalId, NilListFunctionLocalId, NilListLocalId,
113 NilLocalId, StringFunctionLocalId, StringListFunctionLocalId, StringListLocalId, StringLocalId,
114 TupleFunctionLocalId, TupleListFunctionLocalId, TupleListLocalId, TupleLocalId,
115 UtfCodepointFunctionLocalId, UtfCodepointListFunctionLocalId, UtfCodepointListLocalId,
116 UtfCodepointLocalId,
117};
118pub(crate) use id::{
119 CustomFunctionLocal, CustomLocal, ExternalFunctionLocal, ExternalLocal, FunctionFunctionLocal,
120 GenericFunctionLocal,
121};
122pub(crate) use pattern::{
123 BitArrayBindingPattern, BitArrayPattern, BitArrayPatternSegment, BitArrayPatternSize,
124 BitArrayPatternSizeExpr, BitArrayPatternValue, BitArrayStringPattern, CustomBindingPattern,
125 CustomPattern, PatternBinding, Signedness, TotalBindingPattern, TotalBindingPatternKind,
126};
127pub(crate) use reference::{
128 BitArrayFunctionReference, BoolFunctionReference, CustomFunctionReference,
129 ExternalFunctionReference, FloatFunctionReference, FunctionFunctionReference,
130 FunctionReference, GenericFunctionReference, IntFunctionReference, ListFunctionReference,
131 NilFunctionReference, StringFunctionReference, TupleFunctionReference, TypedFunctionReference,
132 UtfCodepointFunctionReference,
133};
134pub use step::Step;
135pub(crate) use step::{
136 AssertBinding, AssertPattern, AssertSubject, Echo, EchoSubject, ListAssertPattern,
137 ListAssertTail, StepKind, StringAssertBinding,
138};
139pub use type_scheme::TypeScheme;
140#[cfg(test)]
141pub(crate) use type_scheme::monomorphic_function_instantiation;
142pub(crate) use type_scheme::{FunctionInstantiation, FunctionTemplateSignature, TypeSubstitution};
143
144#[derive(Debug, PartialEq)]
145pub struct ModulePlan {
146 root: ModuleId,
147 entry: FunctionTemplateId,
148 modules: Vec<PlannedModule>,
149}
150
151#[derive(Debug, PartialEq)]
152pub struct PlannedModule {
153 id: ModuleId,
154 package: EcoString,
155 module: EcoString,
156 source_context: Option<SourceContext>,
157 custom_types: Vec<CustomTypeDefinition>,
158 constants: ConstantTemplates,
159 functions: Vec<FunctionTemplate>,
160 anonymous_functions: Vec<FunctionTemplate>,
161}
162
163pub(crate) struct ModulePlanParts {
164 pub(crate) root: ModuleId,
165 pub(crate) entry: FunctionTemplateId,
166 pub(crate) modules: Vec<PlannedModule>,
167}
168
169pub(crate) struct PlannedModuleParts {
170 pub(crate) module: EcoString,
171 pub(crate) source_context: Option<SourceContext>,
172 pub(crate) custom_types: Vec<CustomTypeDefinition>,
173 pub(crate) constants: ConstantTemplates,
174 pub(crate) functions: Vec<FunctionTemplate>,
175 pub(crate) anonymous_functions: Vec<FunctionTemplate>,
176}
177
178impl ModulePlan {
179 #[cfg(test)]
180 pub(crate) fn new(
181 module: EcoString,
182 main: FunctionTemplate,
183 functions: Vec<FunctionTemplate>,
184 ) -> Self {
185 let root = ModuleId::root();
186 let entry = main.id();
187 let mut named_functions = Vec::with_capacity(functions.len() + 1);
188 named_functions.push(main);
189 named_functions.extend(functions);
190 Self {
191 root,
192 entry,
193 modules: vec![PlannedModule {
194 id: root,
195 package: "geam".into(),
196 module,
197 source_context: None,
198 custom_types: Vec::new(),
199 constants: ConstantTemplates::empty(),
200 functions: named_functions,
201 anonymous_functions: Vec::new(),
202 }],
203 }
204 }
205
206 pub(crate) fn from_modules(
207 root: ModuleId,
208 entry: FunctionTemplateId,
209 modules: Vec<PlannedModule>,
210 ) -> Self {
211 Self {
212 root,
213 entry,
214 modules,
215 }
216 }
217
218 #[cfg(test)]
219 pub(crate) fn with_anonymous_functions(
220 mut self,
221 anonymous_functions: Vec<FunctionTemplate>,
222 ) -> Self {
223 self.root_module_mut().anonymous_functions = anonymous_functions;
224 self
225 }
226
227 #[cfg(test)]
228 pub(crate) fn with_custom_types(mut self, custom_types: Vec<CustomTypeDefinition>) -> Self {
229 self.root_module_mut().custom_types = custom_types;
230 self
231 }
232
233 #[cfg(test)]
234 pub(crate) fn with_constants(mut self, constants: ConstantTemplates) -> Self {
235 self.root_module_mut().constants = constants;
236 self
237 }
238
239 #[cfg(test)]
240 pub(crate) fn with_source_context(mut self, source_context: SourceContext) -> Self {
241 self.root_module_mut().source_context = Some(source_context);
242 self
243 }
244
245 pub fn root(&self) -> ModuleId {
246 self.root
247 }
248
249 pub fn entry(&self) -> FunctionTemplateId {
250 self.entry
251 }
252
253 pub fn modules(&self) -> &[PlannedModule] {
254 &self.modules
255 }
256
257 pub fn module(&self) -> &EcoString {
258 self.root_module().module()
259 }
260
261 pub fn source_context(&self) -> Option<&SourceContext> {
262 self.root_module().source_context()
263 }
264
265 pub fn custom_types(&self) -> &[CustomTypeDefinition] {
266 self.root_module().custom_types()
267 }
268
269 pub fn constants(&self) -> &[ConstantTemplate] {
270 self.root_module().constants()
271 }
272
273 pub fn main_function(&self) -> &FunctionTemplate {
274 &self.root_module().functions[self.entry.index()]
275 }
276
277 pub fn functions(&self) -> &[FunctionTemplate] {
278 &self.root_module().functions[1..]
279 }
280
281 #[cfg(test)]
282 pub(crate) fn anonymous_functions(&self) -> &[FunctionTemplate] {
283 &self.root_module().anonymous_functions
284 }
285
286 pub(crate) fn into_parts(self) -> ModulePlanParts {
287 ModulePlanParts {
288 root: self.root,
289 entry: self.entry,
290 modules: self.modules,
291 }
292 }
293
294 fn root_module(&self) -> &PlannedModule {
295 &self.modules[self.root.index()]
296 }
297
298 #[cfg(test)]
299 fn root_module_mut(&mut self) -> &mut PlannedModule {
300 &mut self.modules[self.root.index()]
301 }
302}
303
304impl PlannedModule {
305 pub(crate) fn new(id: ModuleId, package: EcoString, parts: PlannedModuleParts) -> Self {
306 let PlannedModuleParts {
307 module,
308 source_context,
309 custom_types,
310 constants,
311 functions,
312 anonymous_functions,
313 } = parts;
314 Self {
315 id,
316 package,
317 module,
318 source_context,
319 custom_types,
320 constants,
321 functions,
322 anonymous_functions,
323 }
324 }
325
326 pub fn id(&self) -> ModuleId {
327 self.id
328 }
329
330 pub fn package(&self) -> &EcoString {
331 &self.package
332 }
333
334 pub fn module(&self) -> &EcoString {
335 &self.module
336 }
337
338 pub fn source_context(&self) -> Option<&SourceContext> {
339 self.source_context.as_ref()
340 }
341
342 pub fn custom_types(&self) -> &[CustomTypeDefinition] {
343 &self.custom_types
344 }
345
346 pub fn constants(&self) -> &[ConstantTemplate] {
347 self.constants.headers()
348 }
349
350 pub fn functions(&self) -> &[FunctionTemplate] {
351 &self.functions
352 }
353
354 pub(crate) fn into_parts(self) -> PlannedModuleParts {
355 PlannedModuleParts {
356 module: self.module,
357 source_context: self.source_context,
358 custom_types: self.custom_types,
359 constants: self.constants,
360 functions: self.functions,
361 anonymous_functions: self.anonymous_functions,
362 }
363 }
364}
365
366#[cfg(test)]
367mod tests {
368 use super::ModulePlan;
369 use crate::plan::{
370 ConstantTemplate, ConstantTemplateId, ConstantTemplateSignature, ConstantTemplates,
371 ConstantValue, FunctionTemplate, FunctionTemplateId, IntExpr, IntFunctionId, ReturnExpr,
372 SourceContext, TypeScheme,
373 };
374 use num_bigint::BigInt;
375
376 #[test]
377 fn module_plan_accessors() {
378 let main = function(0, "main", 1);
379 let helper = function(1, "helper", 2);
380 let anonymous = function(2, "<anonymous:0>", 3);
381 let signature =
382 ConstantTemplateSignature::int(ConstantTemplateId::new(0), 0, TypeScheme::new(0));
383 let constant = ConstantTemplate::new(signature, "answer".into());
384 let plan = ModulePlan::new("main".into(), main, vec![helper])
385 .with_anonymous_functions(vec![anonymous])
386 .with_constants(ConstantTemplates::from_entries(vec![(
387 constant.clone(),
388 ConstantValue::int(BigInt::from(42)),
389 )]));
390
391 assert_eq!(plan.module(), "main");
392 assert_eq!(plan.modules()[0].package(), "geam");
393 assert_eq!(plan.main_function().name(), "main");
394 assert_eq!(plan.functions().len(), 1);
395 assert_eq!(plan.functions()[0].name(), "helper");
396 assert_eq!(plan.anonymous_functions().len(), 1);
397 assert_eq!(plan.anonymous_functions()[0].name(), "<anonymous:0>");
398 assert_eq!(plan.constants(), &[constant]);
399 assert_eq!(plan.constants()[0].scheme().parameters(), &[]);
400 assert_eq!(plan.source_context(), None);
401 }
402
403 #[test]
404 fn module_plan_debug_surface_contains_only_canonical_plan() {
405 let plan = ModulePlan::new("main".into(), function(0, "main", 1), Vec::new())
406 .with_source_context(SourceContext::new("main.gleam", "pub fn main() { panic }"));
407 let debug = format!("{plan:?}");
408
409 assert_eq!(
410 debug,
411 format!(
412 "ModulePlan {{ root: {:?}, entry: {:?}, modules: {:?} }}",
413 plan.root, plan.entry, plan.modules,
414 ),
415 );
416 }
417
418 #[test]
419 fn module_plan_equality_includes_source_context() {
420 let new_plan = || ModulePlan::new("main".into(), function(0, "main", 1), Vec::new());
421
422 assert_eq!(
423 new_plan().with_source_context(SourceContext::new("main.gleam", "pub fn main() { 1 }")),
424 new_plan().with_source_context(SourceContext::new("main.gleam", "pub fn main() { 1 }")),
425 );
426 assert_ne!(
427 new_plan(),
428 new_plan().with_source_context(SourceContext::new("main.gleam", "pub fn main() { 1 }")),
429 );
430 assert_ne!(
431 new_plan().with_source_context(SourceContext::new("main.gleam", "pub fn main() { 1 }")),
432 new_plan()
433 .with_source_context(SourceContext::new("other.gleam", "pub fn main() { 1 }")),
434 );
435 assert_ne!(
436 new_plan().with_source_context(SourceContext::new("main.gleam", "pub fn main() { 1 }")),
437 new_plan().with_source_context(SourceContext::new("main.gleam", "pub fn main() { 2 }")),
438 );
439 assert_ne!(
440 ModulePlan::new("left".into(), function(0, "main", 1), Vec::new()),
441 ModulePlan::new("right".into(), function(0, "main", 1), Vec::new()),
442 );
443 assert_ne!(
444 ModulePlan::new("main".into(), function(0, "main", 1), Vec::new()),
445 ModulePlan::new("main".into(), function(0, "main", 2), Vec::new()),
446 );
447 assert_ne!(
448 ModulePlan::new("main".into(), function(0, "main", 1), Vec::new()),
449 ModulePlan::new(
450 "main".into(),
451 function(0, "main", 1),
452 vec![function(1, "helper", 2)],
453 ),
454 );
455 assert_ne!(
456 ModulePlan::new("main".into(), function(0, "main", 1), Vec::new()),
457 ModulePlan::new("main".into(), function(0, "main", 1), Vec::new())
458 .with_anonymous_functions(vec![function(1, "<anonymous:0>", 2)]),
459 );
460 }
461
462 fn function(id: usize, name: &str, value: i64) -> FunctionTemplate {
463 FunctionTemplate::new(
464 FunctionTemplateId::new(id),
465 name.into(),
466 Vec::new(),
467 Vec::new(),
468 ReturnExpr::int(IntFunctionId(id), IntExpr::value(BigInt::from(value))),
469 )
470 }
471}