1pub mod well_known;
2
3use crate::{
4 ast::well_known::VALIDATOR_ELSE,
5 expr::{TypedExpr, UntypedExpr},
6 line_numbers::LineNumbers,
7 parser::token::{Base, Token},
8 tipo::{PatternConstructor, Type, TypeInfo},
9};
10use indexmap::IndexMap;
11use miette::Diagnostic;
12use ordinal::Ordinal;
13use owo_colors::{OwoColorize, Stream::Stdout};
14use std::{
15 fmt::{self, Display},
16 ops::Range,
17 rc::Rc,
18};
19use uplc::machine::runtime::Compressable;
20use vec1::{Vec1, vec1};
21
22pub const BACKPASS_VARIABLE: &str = "_backpass";
23pub const CAPTURE_VARIABLE: &str = "_capture";
24pub const PIPE_VARIABLE: &str = "_pipe";
25
26pub const ENV_MODULE: &str = "env";
27pub const CONFIG_MODULE: &str = "config";
28pub const DEFAULT_ENV_MODULE: &str = "default";
29
30pub const HANDLER_SPEND: &str = "spend";
31pub const HANDLER_MINT: &str = "mint";
32pub const HANDLER_WITHDRAW: &str = "withdraw";
33pub const HANDLER_PUBLISH: &str = "publish";
34pub const HANDLER_VOTE: &str = "vote";
35pub const HANDLER_PROPOSE: &str = "propose";
36
37pub type TypedModule = Module<TypeInfo, TypedDefinition>;
38pub type UntypedModule = Module<(), UntypedDefinition>;
39
40#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
41pub enum ModuleKind {
42 Lib,
43 Validator,
44 Env,
45 Config,
46}
47
48impl ModuleKind {
49 pub fn is_validator(&self) -> bool {
50 matches!(self, ModuleKind::Validator)
51 }
52
53 pub fn is_lib(&self) -> bool {
54 matches!(self, ModuleKind::Lib)
55 }
56
57 pub fn is_env(&self) -> bool {
58 matches!(self, ModuleKind::Env)
59 }
60
61 pub fn is_config(&self) -> bool {
62 matches!(self, ModuleKind::Config)
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
67pub struct Module<Info, Definitions> {
68 pub name: String,
69 pub docs: Vec<String>,
70 pub type_info: Info,
71 pub definitions: Vec<Definitions>,
72 pub lines: LineNumbers,
73 pub kind: ModuleKind,
74}
75
76impl<Info, Definitions> Module<Info, Definitions> {
77 pub fn definitions(&self) -> impl Iterator<Item = &Definitions> {
78 self.definitions.iter()
79 }
80
81 pub fn into_definitions(self) -> impl Iterator<Item = Definitions> {
82 self.definitions.into_iter()
83 }
84}
85
86impl UntypedModule {
87 pub fn dependencies(&self, env_modules: &[String]) -> Vec<String> {
88 self.definitions()
89 .flat_map(|def| {
90 if let Definition::Use(Use { module, .. }) = def {
91 let name = module.join("/");
92 if name == ENV_MODULE {
93 env_modules.to_vec()
94 } else {
95 vec![name]
96 }
97 } else {
98 Vec::new()
99 }
100 })
101 .collect()
102 }
103}
104
105impl TypedModule {
106 pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
107 self.definitions
108 .iter()
109 .find_map(|definition| definition.find_node(byte_index))
110 }
111
112 pub fn has_definition(&self, name: &str) -> bool {
113 self.definitions.iter().any(|def| match def {
114 Definition::Fn(f) => f.public && f.name == name,
115 Definition::TypeAlias(alias) => alias.public && alias.alias == name,
116 Definition::ModuleConstant(cst) => cst.public && cst.name == name,
117 Definition::DataType(t) => t.public && t.name == name,
118 Definition::Use(_) => false,
119 Definition::Test(_) => false,
120 Definition::Validator(_) => false,
121 Definition::Benchmark(_) => false,
122 })
123 }
124
125 pub fn has_constructor(&self, name: &str) -> bool {
126 self.definitions.iter().any(|def| match def {
127 Definition::DataType(t) if t.public && !t.opaque => t
128 .constructors
129 .iter()
130 .any(|constructor| constructor.name == name),
131 Definition::DataType(_) => false,
132 Definition::Fn(_) => false,
133 Definition::TypeAlias(_) => false,
134 Definition::ModuleConstant(_) => false,
135 Definition::Use(_) => false,
136 Definition::Test(_) => false,
137 Definition::Validator(_) => false,
138 Definition::Benchmark(_) => false,
139 })
140 }
141
142 pub fn validate_module_name(&self) -> Result<(), Error> {
143 if self.name == "aiken" || self.name == "aiken/builtin" {
144 return Err(Error::ReservedModuleName {
145 name: self.name.to_string(),
146 });
147 };
148
149 for segment in self.name.split('/') {
150 if str_to_keyword(segment).is_some() {
151 return Err(Error::KeywordInModuleName {
152 name: self.name.to_string(),
153 keyword: segment.to_string(),
154 });
155 }
156 }
157
158 Ok(())
159 }
160
161 pub fn register_definitions(
164 &self,
165 functions: &mut IndexMap<FunctionAccessKey, TypedFunction>,
166 constants: &mut IndexMap<FunctionAccessKey, TypedExpr>,
167 data_types: &mut IndexMap<DataTypeKey, TypedDataType>,
168 ) {
169 for def in self.definitions() {
170 match def {
171 Definition::Fn(func) => {
172 functions.insert(
173 FunctionAccessKey {
174 module_name: self.name.clone(),
175 function_name: func.name.clone(),
176 },
177 func.clone(),
178 );
179 }
180
181 Definition::Test(test) => {
182 functions.insert(
183 FunctionAccessKey {
184 module_name: self.name.clone(),
185 function_name: test.name.clone(),
186 },
187 test.clone().into(),
188 );
189 }
190
191 Definition::Benchmark(benchmark) => {
192 functions.insert(
193 FunctionAccessKey {
194 module_name: self.name.clone(),
195 function_name: benchmark.name.clone(),
196 },
197 benchmark.clone().into(),
198 );
199 }
200
201 Definition::DataType(dt) => {
202 data_types.insert(
203 DataTypeKey {
204 module_name: self.name.clone(),
205 defined_type: dt.name.clone(),
206 },
207 dt.clone(),
208 );
209 }
210
211 Definition::Validator(v) => {
212 let module_name = self.name.as_str();
213
214 for (k, v) in v.into_function_definitions(module_name) {
215 functions.insert(k, v);
216 }
217 }
218
219 Definition::ModuleConstant(ModuleConstant { name, value, .. }) => {
220 constants.insert(
221 FunctionAccessKey {
222 module_name: self.name.clone(),
223 function_name: name.clone(),
224 },
225 value.clone(),
226 );
227 }
228
229 Definition::TypeAlias(_) | Definition::Use(_) => {}
230 }
231 }
232 }
233}
234
235fn str_to_keyword(word: &str) -> Option<Token> {
236 match word {
238 "expect" => Some(Token::Expect),
239 "else" => Some(Token::Else),
240 "is" => Some(Token::Is),
241 "as" => Some(Token::As),
242 "when" => Some(Token::When),
243 "const" => Some(Token::Const),
244 "fn" => Some(Token::Fn),
245 "if" => Some(Token::If),
246 "use" => Some(Token::Use),
247 "let" => Some(Token::Let),
248 "opaque" => Some(Token::Opaque),
249 "pub" => Some(Token::Pub),
250 "todo" => Some(Token::Todo),
251 "type" => Some(Token::Type),
252 "trace" => Some(Token::Trace),
253 "test" => Some(Token::Test),
254 "error" => Some(Token::Fail),
256 "fail" => Some(Token::Fail),
257 "and" => Some(Token::And),
258 "or" => Some(Token::Or),
259 "validator" => Some(Token::Validator),
260 "via" => Some(Token::Via),
261 "bench" => Some(Token::Benchmark),
262 _ => None,
263 }
264}
265
266pub type TypedFunction = Function<Rc<Type>, TypedExpr, TypedArg>;
267pub type UntypedFunction = Function<(), UntypedExpr, UntypedArg>;
268
269impl UntypedFunction {
270 pub fn is_default_fallback(&self) -> bool {
271 matches!(
272 &self.arguments[..],
273 [UntypedArg {
274 by: ArgBy::ByName(ArgName::Discarded { .. }),
275 ..
276 }]
277 ) && matches!(&self.body, UntypedExpr::ErrorTerm { .. })
278 && self.name.as_str() == well_known::VALIDATOR_ELSE
279 }
280}
281
282pub type TypedTest = Function<Rc<Type>, TypedExpr, TypedArgVia>;
283pub type UntypedTest = Function<(), UntypedExpr, UntypedArgVia>;
284
285#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
286pub enum OnTestFailure {
287 FailImmediately,
288 SucceedImmediately,
289 SucceedEventually,
290}
291
292#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
293pub struct Function<T, Expr, Arg> {
294 pub arguments: Vec<Arg>,
295 pub body: Expr,
296 pub doc: Option<String>,
297 pub location: Span,
298 pub name: String,
299 pub public: bool,
300 pub return_annotation: Option<Annotation>,
301 pub return_type: T,
302 pub end_position: usize,
303 pub on_test_failure: OnTestFailure,
304}
305
306impl<T, Expr, Arg> Function<T, Expr, Arg> {
307 pub fn is_spend(&self) -> bool {
308 self.name == HANDLER_SPEND
309 }
310
311 pub fn is_mint(&self) -> bool {
312 self.name == HANDLER_MINT
313 }
314}
315
316impl TypedFunction {
317 pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
318 self.arguments
319 .iter()
320 .find_map(|arg| arg.find_node(byte_index))
321 .or_else(|| self.body.find_node(byte_index))
322 .or_else(|| {
323 self.return_annotation
324 .as_ref()
325 .and_then(|a| a.find_node(byte_index))
326 })
327 }
328
329 pub fn has_valid_purpose_name(&self) -> bool {
330 self.name == HANDLER_SPEND
331 || self.name == HANDLER_PUBLISH
332 || self.name == HANDLER_PROPOSE
333 || self.name == HANDLER_MINT
334 || self.name == HANDLER_WITHDRAW
335 || self.name == HANDLER_VOTE
336 }
337
338 pub fn validator_arity(&self) -> usize {
339 if self.name == HANDLER_SPEND {
340 4
341 } else if self.name == HANDLER_MINT
342 || self.name == HANDLER_WITHDRAW
343 || self.name == HANDLER_VOTE
344 || self.name == HANDLER_PUBLISH
345 || self.name == HANDLER_PROPOSE
346 {
347 3
348 } else {
349 panic!(
350 "tried to get validator arity of a non-validator function {}",
351 &self.name
352 );
353 }
354 }
355}
356
357impl TypedTest {
358 pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
359 self.arguments
360 .iter()
361 .find_map(|arg| arg.find_node(byte_index))
362 .or_else(|| self.body.find_node(byte_index))
363 .or_else(|| {
364 self.return_annotation
365 .as_ref()
366 .and_then(|a| a.find_node(byte_index))
367 })
368 }
369}
370
371pub type TypedTypeAlias = TypeAlias<Rc<Type>>;
372pub type UntypedTypeAlias = TypeAlias<()>;
373
374impl From<UntypedTest> for UntypedFunction {
375 fn from(f: UntypedTest) -> Self {
376 Function {
377 doc: f.doc,
378 location: f.location,
379 name: f.name,
380 public: f.public,
381 arguments: f.arguments.into_iter().map(|arg| arg.into()).collect(),
382 return_annotation: f.return_annotation,
383 return_type: f.return_type,
384 body: f.body,
385 on_test_failure: f.on_test_failure,
386 end_position: f.end_position,
387 }
388 }
389}
390
391impl From<TypedTest> for TypedFunction {
392 fn from(f: TypedTest) -> Self {
393 Function {
394 doc: f.doc,
395 location: f.location,
396 name: f.name,
397 public: f.public,
398 arguments: f.arguments.into_iter().map(|arg| arg.into()).collect(),
399 return_annotation: f.return_annotation,
400 return_type: f.return_type,
401 body: f.body,
402 on_test_failure: f.on_test_failure,
403 end_position: f.end_position,
404 }
405 }
406}
407
408#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
409pub struct TypeAlias<T> {
410 pub alias: String,
411 pub annotation: Annotation,
412 pub doc: Option<String>,
413 pub location: Span,
414 pub parameters: Vec<String>,
415 pub public: bool,
416 pub tipo: T,
417}
418
419#[derive(Clone, Debug, Eq, PartialEq, Hash)]
420pub struct DataTypeKey {
421 pub module_name: String,
422 pub defined_type: String,
423}
424
425#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
426pub struct FunctionAccessKey {
427 pub module_name: String,
428 pub function_name: String,
429}
430
431pub type UntypedDataType = DataType<()>;
432pub type TypedDataType = DataType<Rc<Type>>;
433
434impl TypedDataType {
435 pub fn known_enum(name: &str, constructors: &[&str]) -> Self {
436 Self::known_data_type(name, &RecordConstructor::known_enum(constructors))
437 }
438
439 pub fn known_data_type(name: &str, constructors: &[RecordConstructor<Rc<Type>>]) -> Self {
440 Self {
441 decorators: vec![],
442 name: name.to_string(),
443 constructors: constructors.to_vec(),
444 location: Span::empty(),
445 opaque: false,
446 public: true,
447 parameters: vec![],
448 typed_parameters: vec![],
449 doc: None,
450 }
451 }
452
453 pub fn is_never(&self) -> bool {
454 self.name == well_known::NEVER
455 && self.constructors.len() == well_known::NEVER_CONSTRUCTORS.len()
456 && self.location == Span::empty()
457 && self
458 .constructors
459 .iter()
460 .zip(well_known::NEVER_CONSTRUCTORS)
461 .all(|(constructor, name)| {
462 name == &constructor.name && constructor.arguments.is_empty()
463 })
464 }
465}
466
467#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
468pub struct Decorator {
469 pub kind: DecoratorKind,
470 pub location: Span,
471}
472
473#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
474pub enum DecoratorKind {
475 Tag { value: String, base: Base },
476 List,
477}
478
479#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
480pub struct DataType<T> {
481 pub decorators: Vec<Decorator>,
482 pub constructors: Vec<RecordConstructor<T>>,
483 pub doc: Option<String>,
484 pub location: Span,
485 pub name: String,
486 pub opaque: bool,
487 pub parameters: Vec<String>,
488 pub public: bool,
489 pub typed_parameters: Vec<T>,
490}
491
492pub type TypedUse = Use<String>;
493pub type UntypedUse = Use<()>;
494
495#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
496pub struct Use<PackageName> {
497 pub as_name: Option<String>,
498 pub location: Span,
499 pub module: Vec<String>,
500 pub package: PackageName,
501 pub unqualified: (usize, Vec<UnqualifiedImport>),
502}
503
504pub type TypedModuleConstant = ModuleConstant<TypedExpr>;
505pub type UntypedModuleConstant = ModuleConstant<UntypedExpr>;
506
507#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
508pub struct ModuleConstant<Expr> {
509 pub doc: Option<String>,
510 pub location: Span,
511 pub public: bool,
512 pub name: String,
513 pub annotation: Option<Annotation>,
514 pub value: Expr,
515}
516
517pub type TypedValidator = Validator<Rc<Type>, TypedArg, TypedExpr>;
518pub type UntypedValidator = Validator<(), UntypedArg, UntypedExpr>;
519
520#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
521pub enum Purpose {
522 Spend,
523 Mint,
524 Withdraw,
525 Publish,
526 Propose,
527 Vote,
528}
529
530#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
531pub struct Validator<T, Arg, Expr> {
532 pub doc: Option<String>,
533 pub end_position: usize,
534 pub handlers: Vec<Function<T, Expr, Arg>>,
535 pub location: Span,
536 pub name: String,
537 pub params: Vec<Arg>,
538 pub fallback: Function<T, Expr, Arg>,
539}
540
541impl<T, Arg, Expr> Validator<T, Arg, Expr> {
542 pub fn handler_name(validator: &str, handler: &str) -> String {
543 format!("{validator}.{handler}")
544 }
545}
546
547impl UntypedValidator {
548 pub fn default_fallback(location: Span) -> UntypedFunction {
549 Function {
550 arguments: vec![UntypedArg {
551 by: ArgBy::ByName(ArgName::Discarded {
552 name: "_".to_string(),
553 label: "_".to_string(),
554 location,
555 }),
556 location,
557 annotation: None,
558 doc: None,
559 is_validator_param: false,
560 }],
561 body: UntypedExpr::fail(None, location),
562 doc: None,
563 location,
564 end_position: location.end - 1,
565 name: well_known::VALIDATOR_ELSE.to_string(),
566 public: true,
567 return_annotation: Some(Annotation::boolean(location)),
568 return_type: (),
569 on_test_failure: OnTestFailure::FailImmediately,
570 }
571 }
572}
573
574impl TypedValidator {
575 pub fn available_handler_names() -> Vec<String> {
576 vec![
577 HANDLER_SPEND.to_string(),
578 HANDLER_MINT.to_string(),
579 HANDLER_WITHDRAW.to_string(),
580 HANDLER_PUBLISH.to_string(),
581 HANDLER_VOTE.to_string(),
582 HANDLER_PROPOSE.to_string(),
583 VALIDATOR_ELSE.to_string(),
584 ]
585 }
586
587 pub fn into_script_context_handler(&self) -> TypedExpr {
590 let var_context = "__context__";
591 let var_transaction = "__transaction__";
592 let var_redeemer = "__redeemer__";
593 let var_purpose = "__purpose__";
594 let var_purpose_arg = "__purpose_arg__";
595 let var_datum = "__datum__";
596
597 let context_handler = TypedExpr::sequence(&[
598 TypedExpr::let_(
599 TypedExpr::local_var(var_context, Type::script_context(), self.location),
600 TypedPattern::Constructor {
601 is_record: false,
602 location: Span::empty(),
603 name: well_known::SCRIPT_CONTEXT_CONSTRUCTORS[0].to_string(),
604 arguments: vec![
605 CallArg::var(var_transaction, Span::empty()),
606 CallArg::var(var_redeemer, Span::empty()),
607 CallArg::var(var_purpose, Span::empty()),
608 ],
609 module: None,
610 constructor: PatternConstructor::Record {
611 name: well_known::SCRIPT_CONTEXT_CONSTRUCTORS[0].to_string(),
612 field_map: None,
613 },
614 spread_location: None,
615 tipo: Type::function(
616 vec![Type::data(), Type::data(), Type::script_purpose()],
617 Type::data(),
618 ),
619 },
620 Type::script_context(),
621 Span::empty(),
622 ),
623 TypedExpr::When {
624 location: Span::empty(),
625 tipo: Type::bool(),
626 subject: TypedExpr::local_var(var_purpose, Type::script_purpose(), Span::empty())
627 .into(),
628 clauses: self
629 .handlers
630 .iter()
631 .map(|handler| {
632 let datum = if handler.name.as_str() == "spend" {
633 handler.arguments.first()
634 } else {
635 None
636 };
637
638 let redeemer = handler
639 .arguments
640 .get(if datum.is_some() { 1 } else { 0 })
641 .unwrap();
642
643 let purpose_arg = handler.arguments.iter().nth_back(1).unwrap();
644
645 let transaction = handler.arguments.last().unwrap();
646
647 let pattern = match handler.name.as_str() {
648 "spend" => TypedPattern::spend_purpose(
649 (var_purpose_arg, purpose_arg.location),
650 (
651 var_datum,
652 datum.map(|x| x.location).unwrap_or(Span::empty()),
653 ),
654 redeemer.location,
655 ),
656 "mint" => TypedPattern::mint_purpose(
657 (var_purpose_arg, purpose_arg.location),
658 redeemer.location,
659 ),
660 "withdraw" => TypedPattern::withdraw_purpose(
661 (var_purpose_arg, purpose_arg.location),
662 redeemer.location,
663 ),
664 "publish" => TypedPattern::publish_purpose(
665 (var_purpose_arg, purpose_arg.location),
666 redeemer.location,
667 ),
668 "propose" => TypedPattern::propose_purpose(
669 (var_purpose_arg, purpose_arg.location),
670 redeemer.location,
671 ),
672 "vote" => TypedPattern::vote_purpose(
673 (var_purpose_arg, purpose_arg.location),
674 redeemer.location,
675 ),
676 purpose => {
677 unreachable!("unexpected/unknown purpose: {:?}", purpose)
678 }
679 };
680
681 let mut then = vec![];
682
683 then.push(TypedExpr::flexible_expect(
685 TypedExpr::local_var(var_redeemer, Type::data(), redeemer.location),
686 TypedPattern::var(redeemer.get_variable_name().unwrap_or("_")),
687 redeemer.tipo.clone(),
688 redeemer.location,
689 ));
690
691 if let Some(datum) = datum {
693 then.push(TypedExpr::flexible_expect(
695 TypedExpr::local_var(
696 var_datum,
697 Type::option(Type::data()),
698 datum.location,
699 ),
700 TypedPattern::var(datum.get_variable_name().unwrap_or("_")),
701 datum.tipo.clone(),
702 datum.location,
703 ))
704 }
705
706 if let Some(arg_name) = purpose_arg.get_variable_name() {
708 then.push(TypedExpr::let_(
709 TypedExpr::local_var(
710 var_purpose_arg,
711 Type::data(),
712 purpose_arg.location,
713 ),
714 TypedPattern::var(arg_name),
715 purpose_arg.tipo.clone(),
716 purpose_arg.location,
717 ));
718 }
719
720 if let Some(arg_name) = transaction.get_variable_name() {
722 then.push(TypedExpr::let_(
723 TypedExpr::local_var(
724 var_transaction,
725 Type::data(),
726 transaction.location,
727 ),
728 TypedPattern::var(arg_name),
729 Type::data(),
730 transaction.location,
731 ));
732 }
733
734 then.push(handler.body.clone());
735
736 TypedClause {
737 location: Span::empty(),
738 pattern,
739 then: TypedExpr::Sequence {
740 location: Span::empty(),
741 expressions: then,
742 },
743 }
744 })
745 .chain(std::iter::once(&self.fallback).map(|fallback| {
746 let arg = fallback.arguments.first().unwrap();
747
748 let then = match arg.get_variable_name() {
749 Some(arg_name) => TypedExpr::sequence(&[
750 TypedExpr::let_(
751 TypedExpr::local_var(
752 var_context,
753 arg.tipo.clone(),
754 arg.location,
755 ),
756 TypedPattern::var(arg_name),
757 arg.tipo.clone(),
758 arg.location,
759 ),
760 fallback.body.clone(),
761 ]),
762 None => fallback.body.clone(),
763 };
764
765 TypedClause {
766 location: Span::empty(),
767 pattern: TypedPattern::Discard {
768 name: "_".to_string(),
769 location: arg.location,
770 },
771 then,
772 }
773 }))
774 .collect(),
775 },
776 ]);
777
778 if self.handlers.is_empty() {
779 let fallback = &self.fallback;
780 let arg = fallback.arguments.first().unwrap();
781
782 match arg.get_variable_name() {
783 Some(arg_name) => TypedExpr::sequence(&[
784 TypedExpr::let_(
785 TypedExpr::local_var(var_context, arg.tipo.clone(), arg.location),
786 TypedPattern::var(arg_name),
787 arg.tipo.clone(),
788 arg.location,
789 ),
790 fallback.body.clone(),
791 ]),
792 None => fallback.body.clone(),
793 }
794 } else {
795 context_handler
796 }
797 }
798
799 pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
800 self.params
801 .iter()
802 .find_map(|arg| arg.find_node(byte_index))
803 .or_else(|| {
804 self.handlers
805 .iter()
806 .find_map(|func| func.find_node(byte_index))
807 })
808 .or_else(|| self.fallback.find_node(byte_index))
809 }
810
811 pub fn into_function_definitions(
812 &self,
813 module_name: &str,
814 ) -> Vec<(FunctionAccessKey, TypedFunction)> {
815 self.handlers
816 .iter()
817 .chain(std::iter::once(&self.fallback))
818 .map(|handler| {
819 let mut handler = handler.clone();
820
821 handler.arguments = self
822 .params
823 .clone()
824 .into_iter()
825 .chain(handler.arguments)
826 .collect();
827
828 (
829 FunctionAccessKey {
830 module_name: module_name.to_string(),
831 function_name: TypedValidator::handler_name(
832 self.name.as_str(),
833 handler.name.as_str(),
834 ),
835 },
836 handler,
837 )
838 })
839 .collect()
840 }
841}
842
843pub type TypedDefinition = Definition<Rc<Type>, TypedArg, TypedExpr, String>;
844pub type UntypedDefinition = Definition<(), UntypedArg, UntypedExpr, ()>;
845
846#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
847pub enum Definition<T, Arg, Expr, PackageName> {
848 Fn(Function<T, Expr, Arg>),
849
850 TypeAlias(TypeAlias<T>),
851
852 DataType(DataType<T>),
853
854 Use(Use<PackageName>),
855
856 ModuleConstant(ModuleConstant<Expr>),
857
858 Test(Function<T, Expr, ArgVia<Arg, Expr>>),
859
860 Benchmark(Function<T, Expr, ArgVia<Arg, Expr>>),
861
862 Validator(Validator<T, Arg, Expr>),
863}
864
865impl<A, B, C, D> Definition<A, B, C, D> {
866 pub fn location(&self) -> Span {
867 match self {
868 Definition::Fn(Function { location, .. })
869 | Definition::Use(Use { location, .. })
870 | Definition::TypeAlias(TypeAlias { location, .. })
871 | Definition::DataType(DataType { location, .. })
872 | Definition::ModuleConstant(ModuleConstant { location, .. })
873 | Definition::Validator(Validator { location, .. })
874 | Definition::Benchmark(Function { location, .. })
875 | Definition::Test(Function { location, .. }) => *location,
876 }
877 }
878
879 pub fn put_doc(&mut self, new_doc: String) {
880 match self {
881 Definition::Use { .. } => (),
882 Definition::Fn(Function { doc, .. })
883 | Definition::TypeAlias(TypeAlias { doc, .. })
884 | Definition::DataType(DataType { doc, .. })
885 | Definition::ModuleConstant(ModuleConstant { doc, .. })
886 | Definition::Validator(Validator { doc, .. })
887 | Definition::Benchmark(Function { doc, .. })
888 | Definition::Test(Function { doc, .. }) => {
889 let _ = doc.replace(new_doc);
890 }
891 }
892 }
893
894 pub fn doc(&self) -> Option<String> {
895 match self {
896 Definition::Use { .. } => None,
897 Definition::Fn(Function { doc, .. })
898 | Definition::TypeAlias(TypeAlias { doc, .. })
899 | Definition::DataType(DataType { doc, .. })
900 | Definition::ModuleConstant(ModuleConstant { doc, .. })
901 | Definition::Validator(Validator { doc, .. })
902 | Definition::Benchmark(Function { doc, .. })
903 | Definition::Test(Function { doc, .. }) => doc.clone(),
904 }
905 }
906}
907
908impl TypedDefinition {
909 pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
910 let located = match self {
913 Definition::Validator(validator) => validator.find_node(byte_index),
914 Definition::Fn(func) => func.find_node(byte_index),
915 Definition::Test(func) => func.find_node(byte_index),
916 _ => None,
917 };
918
919 if located.is_none() && self.location().contains(byte_index) {
920 return Some(Located::Definition(self));
921 }
922
923 located
924 }
925}
926
927#[derive(Debug, Clone, PartialEq)]
928pub enum Located<'a> {
929 Expression(&'a TypedExpr),
930 Pattern(&'a TypedPattern, Rc<Type>),
931 Definition(&'a TypedDefinition),
932 Argument(&'a ArgName, Rc<Type>),
933 Annotation(&'a Annotation),
934}
935
936impl Located<'_> {
937 pub fn definition_location(&self) -> Option<DefinitionLocation<'_>> {
938 match self {
939 Self::Expression(expression) => expression.definition_location(),
940 Self::Definition(definition) => Some(DefinitionLocation {
941 module: None,
942 span: definition.location(),
943 }),
944 Self::Pattern(_, _) | Located::Argument(_, _) | Located::Annotation(_) => None,
948 }
949 }
950}
951
952#[derive(Debug, PartialEq, Eq, Clone)]
953pub struct DefinitionLocation<'module> {
954 pub module: Option<&'module str>,
955 pub span: Span,
956}
957
958pub type TypedCallArg = CallArg<TypedExpr>;
959pub type ParsedCallArg = CallArg<Option<UntypedExpr>>;
960
961#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
962pub struct CallArg<A> {
963 pub label: Option<String>,
964 pub location: Span,
965 pub value: A,
966}
967
968impl CallArg<UntypedExpr> {
969 pub fn is_capture_hole(&self) -> bool {
970 match &self.value {
971 UntypedExpr::Var { name, .. } => name.contains(CAPTURE_VARIABLE),
972 _ => false,
973 }
974 }
975}
976
977impl TypedCallArg {
978 pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
979 self.value.find_node(byte_index)
980 }
981}
982
983impl CallArg<TypedPattern> {
984 pub fn var(name: &str, location: Span) -> Self {
985 CallArg {
986 label: None,
987 location: Span::empty(),
988 value: TypedPattern::Var {
989 location,
990 name: name.to_string(),
991 },
992 }
993 }
994}
995
996#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
997pub struct RecordConstructor<T> {
998 pub decorators: Vec<Decorator>,
999 pub location: Span,
1000 pub name: String,
1001 pub arguments: Vec<RecordConstructorArg<T>>,
1002 pub doc: Option<String>,
1003 pub sugar: bool,
1004}
1005
1006impl<A> RecordConstructor<A>
1007where
1008 A: Clone,
1009{
1010 pub fn put_doc(&mut self, new_doc: String) {
1011 self.doc = Some(new_doc);
1012 }
1013
1014 pub fn known_enum(names: &[&str]) -> Vec<RecordConstructor<A>> {
1015 names
1016 .iter()
1017 .map(|name| RecordConstructor {
1018 decorators: vec![],
1019 location: Span::empty(),
1020 name: name.to_string(),
1021 arguments: vec![],
1022 doc: None,
1023 sugar: false,
1024 })
1025 .collect()
1026 }
1027
1028 pub fn known_record(name: &str, args: &[RecordConstructorArg<A>]) -> Self {
1029 RecordConstructor {
1030 decorators: vec![],
1031 location: Span::empty(),
1032 name: name.to_string(),
1033 arguments: args.to_vec(),
1034 doc: None,
1035 sugar: false,
1036 }
1037 }
1038}
1039
1040#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
1041pub struct RecordConstructorArg<T> {
1042 pub label: Option<String>,
1043 pub annotation: Annotation,
1045 pub location: Span,
1046 pub tipo: T,
1047 pub doc: Option<String>,
1048}
1049
1050impl<T: PartialEq> RecordConstructorArg<T> {
1051 pub fn put_doc(&mut self, new_doc: String) {
1052 self.doc = Some(new_doc);
1053 }
1054}
1055
1056#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
1057pub enum ArgBy {
1058 ByName(ArgName),
1059 ByPattern(UntypedPattern),
1060}
1061
1062impl ArgBy {
1063 pub fn into_extra_assignment(
1064 self,
1065 name: &ArgName,
1066 annotation: Option<&Annotation>,
1067 location: Span,
1068 ) -> Option<UntypedExpr> {
1069 match self {
1070 ArgBy::ByName(..) => None,
1071 ArgBy::ByPattern(pattern) => Some(UntypedExpr::Assignment {
1072 location,
1073 value: Box::new(UntypedExpr::Var {
1074 location,
1075 name: name.get_name(),
1076 }),
1077 patterns: vec1![AssignmentPattern {
1078 pattern,
1079 location,
1080 annotation: annotation.cloned(),
1081 }],
1082 kind: AssignmentKind::Let { backpassing: false },
1083 comment: None,
1084 }),
1085 }
1086 }
1087}
1088
1089#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
1090pub struct UntypedArg {
1091 pub by: ArgBy,
1092 pub location: Span,
1093 pub annotation: Option<Annotation>,
1094 pub doc: Option<String>,
1095 pub is_validator_param: bool,
1096}
1097
1098impl UntypedArg {
1099 pub fn arg_name(&self, ix: usize) -> ArgName {
1100 match self.by {
1101 ArgBy::ByName(ref name) => name.clone(),
1102 ArgBy::ByPattern(..) => {
1103 let name = format!("{}{}_arg", ix + 1, Ordinal::<usize>(ix + 1).suffix());
1107 ArgName::Named {
1108 label: name.clone(),
1109 name,
1110 location: self.location,
1111 }
1112 }
1113 }
1114 }
1115
1116 pub fn set_type(self, tipo: Rc<Type>, ix: usize) -> TypedArg {
1117 TypedArg {
1118 tipo,
1119 arg_name: self.arg_name(ix),
1120 location: self.location,
1121 annotation: self.annotation,
1122 is_validator_param: self.is_validator_param,
1123 doc: self.doc,
1124 }
1125 }
1126}
1127
1128#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
1129pub struct TypedArg {
1130 pub arg_name: ArgName,
1131 pub location: Span,
1132 pub annotation: Option<Annotation>,
1133 pub doc: Option<String>,
1134 pub is_validator_param: bool,
1135 pub tipo: Rc<Type>,
1136}
1137
1138impl TypedArg {
1139 pub fn new(name: &str, tipo: Rc<Type>) -> Self {
1140 TypedArg {
1141 arg_name: ArgName::Named {
1142 name: name.to_string(),
1143 label: name.to_string(),
1144 location: Span::empty(),
1145 },
1146 location: Span::empty(),
1147 annotation: None,
1148 doc: None,
1149 is_validator_param: false,
1150 tipo: tipo.clone(),
1151 }
1152 }
1153
1154 pub fn put_doc(&mut self, new_doc: String) {
1155 self.doc = Some(new_doc);
1156 }
1157
1158 pub fn get_variable_name(&self) -> Option<&str> {
1159 self.arg_name.get_variable_name()
1160 }
1161
1162 pub fn get_name(&self) -> String {
1163 self.arg_name.get_name()
1164 }
1165
1166 pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
1167 if self.arg_name.location().contains(byte_index) {
1168 Some(Located::Argument(&self.arg_name, self.tipo.clone()))
1169 } else {
1170 self.annotation
1171 .as_ref()
1172 .and_then(|annotation| annotation.find_node(byte_index))
1173 }
1174 }
1175}
1176
1177pub type TypedArgVia = ArgVia<TypedArg, TypedExpr>;
1178pub type UntypedArgVia = ArgVia<UntypedArg, UntypedExpr>;
1179
1180#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
1181pub struct ArgVia<Arg, Expr> {
1182 pub arg: Arg,
1183 pub via: Expr,
1184}
1185
1186impl<Expr> From<ArgVia<TypedArg, Expr>> for TypedArg {
1187 fn from(this: ArgVia<TypedArg, Expr>) -> TypedArg {
1188 this.arg
1189 }
1190}
1191
1192impl<Expr> From<ArgVia<UntypedArg, Expr>> for UntypedArg {
1193 fn from(this: ArgVia<UntypedArg, Expr>) -> UntypedArg {
1194 this.arg
1195 }
1196}
1197
1198impl TypedArgVia {
1199 pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
1200 if self.arg.arg_name.location().contains(byte_index) {
1201 Some(Located::Argument(&self.arg.arg_name, self.arg.tipo.clone()))
1202 } else {
1203 self.via.find_node(byte_index).or_else(|| {
1207 self.arg
1208 .annotation
1209 .as_ref()
1210 .and_then(|annotation| annotation.find_node(byte_index))
1211 })
1212 }
1213 }
1214}
1215
1216#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
1217pub enum ArgName {
1218 Discarded {
1219 name: String,
1220 label: String,
1221 location: Span,
1222 },
1223 Named {
1224 name: String,
1225 label: String,
1226 location: Span,
1227 },
1228}
1229
1230impl ArgName {
1231 pub fn location(&self) -> Span {
1232 match self {
1233 ArgName::Discarded { location, .. } => *location,
1234 ArgName::Named { location, .. } => *location,
1235 }
1236 }
1237
1238 pub fn get_variable_name(&self) -> Option<&str> {
1241 match self {
1242 ArgName::Discarded { .. } => None,
1243 ArgName::Named { name, .. } => Some(name),
1244 }
1245 }
1246
1247 pub fn get_name(&self) -> String {
1248 match self {
1249 ArgName::Discarded { name, .. } | ArgName::Named { name, .. } => name.clone(),
1250 }
1251 }
1252
1253 pub fn get_label(&self) -> String {
1254 match self {
1255 ArgName::Discarded { label, .. } | ArgName::Named { label, .. } => label.to_string(),
1256 }
1257 }
1258}
1259
1260#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
1261pub struct UnqualifiedImport {
1262 pub location: Span,
1263 pub name: String,
1264 pub as_name: Option<String>,
1265}
1266
1267impl UnqualifiedImport {
1268 pub fn variable_name(&self) -> &str {
1269 self.as_name.as_deref().unwrap_or(&self.name)
1270 }
1271}
1272
1273#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
1275pub enum Annotation {
1276 Constructor {
1277 location: Span,
1278 module: Option<String>,
1279 name: String,
1280 arguments: Vec<Self>,
1281 },
1282
1283 Fn {
1284 location: Span,
1285 arguments: Vec<Self>,
1286 ret: Box<Self>,
1287 },
1288
1289 Var {
1290 location: Span,
1291 name: String,
1292 },
1293
1294 Hole {
1295 location: Span,
1296 name: String,
1297 },
1298
1299 Tuple {
1300 location: Span,
1301 elems: Vec<Self>,
1302 },
1303
1304 Pair {
1305 location: Span,
1306 fst: Box<Self>,
1307 snd: Box<Self>,
1308 },
1309}
1310
1311impl Annotation {
1312 pub fn location(&self) -> Span {
1313 match self {
1314 Annotation::Fn { location, .. }
1315 | Annotation::Tuple { location, .. }
1316 | Annotation::Var { location, .. }
1317 | Annotation::Hole { location, .. }
1318 | Annotation::Constructor { location, .. }
1319 | Annotation::Pair { location, .. } => *location,
1320 }
1321 }
1322
1323 pub fn boolean(location: Span) -> Self {
1324 Annotation::Constructor {
1325 name: "Bool".to_string(),
1326 module: None,
1327 arguments: vec![],
1328 location,
1329 }
1330 }
1331
1332 pub fn int(location: Span) -> Self {
1333 Annotation::Constructor {
1334 name: "Int".to_string(),
1335 module: None,
1336 arguments: vec![],
1337 location,
1338 }
1339 }
1340
1341 pub fn bytearray(location: Span) -> Self {
1342 Annotation::Constructor {
1343 name: "ByteArray".to_string(),
1344 module: None,
1345 arguments: vec![],
1346 location,
1347 }
1348 }
1349
1350 pub fn data(location: Span) -> Self {
1351 Annotation::Constructor {
1352 name: "Data".to_string(),
1353 module: None,
1354 arguments: vec![],
1355 location,
1356 }
1357 }
1358
1359 pub fn option(inner: Annotation) -> Self {
1360 Annotation::Constructor {
1361 name: "Option".to_string(),
1362 module: None,
1363 location: inner.location(),
1364 arguments: vec![inner],
1365 }
1366 }
1367
1368 pub fn list(inner: Annotation, location: Span) -> Self {
1369 Annotation::Constructor {
1370 name: "List".to_string(),
1371 module: None,
1372 arguments: vec![inner],
1373 location,
1374 }
1375 }
1376
1377 pub fn tuple(elems: Vec<Annotation>, location: Span) -> Self {
1378 Annotation::Tuple { elems, location }
1379 }
1380
1381 pub fn is_logically_equal(&self, other: &Annotation) -> bool {
1382 match self {
1383 Annotation::Constructor {
1384 module,
1385 name,
1386 arguments,
1387 location: _,
1388 } => match other {
1389 Annotation::Constructor {
1390 module: o_module,
1391 name: o_name,
1392 arguments: o_arguments,
1393 location: _,
1394 } => {
1395 module == o_module
1396 && name == o_name
1397 && arguments.len() == o_arguments.len()
1398 && arguments
1399 .iter()
1400 .zip(o_arguments)
1401 .all(|a| a.0.is_logically_equal(a.1))
1402 }
1403 _ => false,
1404 },
1405 Annotation::Tuple { elems, location: _ } => match other {
1406 Annotation::Tuple {
1407 elems: o_elems,
1408 location: _,
1409 } => {
1410 elems.len() == o_elems.len()
1411 && elems
1412 .iter()
1413 .zip(o_elems)
1414 .all(|a| a.0.is_logically_equal(a.1))
1415 }
1416 _ => false,
1417 },
1418 Annotation::Fn {
1419 arguments,
1420 ret,
1421 location: _,
1422 } => match other {
1423 Annotation::Fn {
1424 arguments: o_arguments,
1425 ret: o_return,
1426 location: _,
1427 } => {
1428 arguments.len() == o_arguments.len()
1429 && arguments
1430 .iter()
1431 .zip(o_arguments)
1432 .all(|a| a.0.is_logically_equal(a.1))
1433 && ret.is_logically_equal(o_return)
1434 }
1435 _ => false,
1436 },
1437 Annotation::Var { name, location: _ } => match other {
1438 Annotation::Var {
1439 name: o_name,
1440 location: _,
1441 } => name == o_name,
1442 _ => false,
1443 },
1444
1445 Annotation::Hole { name, location: _ } => match other {
1446 Annotation::Hole {
1447 name: o_name,
1448 location: _,
1449 } => name == o_name,
1450 _ => false,
1451 },
1452 Annotation::Pair { fst, snd, .. } => {
1453 if let Annotation::Pair {
1454 fst: o_fst,
1455 snd: o_snd,
1456 ..
1457 } = other
1458 {
1459 fst.is_logically_equal(o_fst) && snd.is_logically_equal(o_snd)
1460 } else {
1461 false
1462 }
1463 }
1464 }
1465 }
1466
1467 pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
1468 if !self.location().contains(byte_index) {
1469 return None;
1470 }
1471
1472 let located = match self {
1473 Annotation::Constructor { arguments, .. } => {
1474 arguments.iter().find_map(|arg| arg.find_node(byte_index))
1475 }
1476 Annotation::Fn { arguments, ret, .. } => arguments
1477 .iter()
1478 .find_map(|arg| arg.find_node(byte_index))
1479 .or_else(|| ret.find_node(byte_index)),
1480 Annotation::Tuple { elems, .. } => {
1481 elems.iter().find_map(|arg| arg.find_node(byte_index))
1482 }
1483 Annotation::Var { .. } | Annotation::Hole { .. } => None,
1484 Annotation::Pair { fst, snd, .. } => fst
1485 .find_node(byte_index)
1486 .or_else(|| snd.find_node(byte_index)),
1487 };
1488
1489 located.or(Some(Located::Annotation(self)))
1490 }
1491}
1492
1493#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
1494pub enum BinOp {
1495 And,
1497 Or,
1498
1499 Eq,
1501 NotEq,
1502
1503 LtInt,
1505 LtEqInt,
1506 GtEqInt,
1507 GtInt,
1508
1509 AddInt,
1511 SubInt,
1512 MultInt,
1513 DivInt,
1514 ModInt,
1515}
1516
1517impl From<LogicalOpChainKind> for BinOp {
1518 fn from(value: LogicalOpChainKind) -> Self {
1519 match value {
1520 LogicalOpChainKind::And => BinOp::And,
1521 LogicalOpChainKind::Or => BinOp::Or,
1522 }
1523 }
1524}
1525
1526#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
1527pub enum UnOp {
1528 Not,
1530 Negate,
1532}
1533
1534impl BinOp {
1535 pub fn precedence(&self) -> u8 {
1536 match self {
1538 Self::Or => 2,
1541
1542 Self::And => 3,
1543
1544 Self::Eq | Self::NotEq | Self::LtInt | Self::LtEqInt | Self::GtEqInt | Self::GtInt => 4,
1545
1546 Self::AddInt | Self::SubInt => 6,
1548
1549 Self::MultInt | Self::DivInt | Self::ModInt => 7,
1550 }
1551 }
1552}
1553
1554pub type UntypedPattern = Pattern<(), (), Namespace, (u8, Span)>;
1555pub type TypedPattern = Pattern<PatternConstructor, Rc<Type>, String, u8>;
1556
1557impl TypedPattern {
1558 pub fn var(name: &str) -> Self {
1559 TypedPattern::Var {
1560 name: name.to_string(),
1561 location: Span::empty(),
1562 }
1563 }
1564
1565 pub fn constructor(
1566 name: &str,
1567 arguments: &[CallArg<TypedPattern>],
1568 tipo: Rc<Type>,
1569 location: Span,
1570 ) -> Self {
1571 TypedPattern::Constructor {
1572 is_record: false,
1573 location,
1574 name: name.to_string(),
1575 arguments: arguments.to_vec(),
1576 module: None,
1577 constructor: PatternConstructor::Record {
1578 name: name.to_string(),
1579 field_map: None,
1580 },
1581 spread_location: None,
1582 tipo: tipo.clone(),
1583 }
1584 }
1585
1586 pub fn mint_purpose(
1587 (var_purpose_arg, purpose_span): (&str, Span),
1588 redeemer_span: Span,
1589 ) -> Self {
1590 TypedPattern::constructor(
1591 well_known::SCRIPT_PURPOSE_MINT,
1592 &[CallArg::var(var_purpose_arg, purpose_span)],
1593 Type::function(vec![Type::byte_array()], Type::script_purpose()),
1594 redeemer_span,
1595 )
1596 }
1597
1598 pub fn spend_purpose(
1599 (var_purpose_arg, purpose_span): (&str, Span),
1600 (var_datum, datum_span): (&str, Span),
1601 redeemer_span: Span,
1602 ) -> Self {
1603 TypedPattern::constructor(
1604 well_known::SCRIPT_PURPOSE_SPEND,
1605 &[
1606 CallArg::var(var_purpose_arg, purpose_span),
1607 CallArg::var(var_datum, datum_span),
1608 ],
1609 Type::function(
1610 vec![Type::data(), Type::option(Type::data())],
1611 Type::script_purpose(),
1612 ),
1613 redeemer_span,
1614 )
1615 }
1616
1617 pub fn withdraw_purpose(
1618 (var_purpose_arg, purpose_span): (&str, Span),
1619 redeemer_span: Span,
1620 ) -> Self {
1621 TypedPattern::constructor(
1622 well_known::SCRIPT_PURPOSE_WITHDRAW,
1623 &[CallArg::var(var_purpose_arg, purpose_span)],
1624 Type::function(vec![Type::data()], Type::script_purpose()),
1625 redeemer_span,
1626 )
1627 }
1628
1629 pub fn publish_purpose(
1630 (var_purpose_arg, purpose_span): (&str, Span),
1631 redeemer_span: Span,
1632 ) -> Self {
1633 TypedPattern::constructor(
1634 well_known::SCRIPT_PURPOSE_PUBLISH,
1635 &[
1636 CallArg::var("__discarded_purpose_ix__", purpose_span),
1637 CallArg::var(var_purpose_arg, purpose_span),
1638 ],
1639 Type::function(vec![Type::int(), Type::data()], Type::script_purpose()),
1640 redeemer_span,
1641 )
1642 }
1643
1644 pub fn vote_purpose(
1645 (var_purpose_arg, purpose_span): (&str, Span),
1646 redeemer_span: Span,
1647 ) -> Self {
1648 TypedPattern::constructor(
1649 well_known::SCRIPT_PURPOSE_VOTE,
1650 &[CallArg::var(var_purpose_arg, purpose_span)],
1651 Type::function(vec![Type::data()], Type::script_purpose()),
1652 redeemer_span,
1653 )
1654 }
1655
1656 pub fn propose_purpose(
1657 (var_purpose_arg, purpose_span): (&str, Span),
1658 redeemer_span: Span,
1659 ) -> Self {
1660 TypedPattern::constructor(
1661 well_known::SCRIPT_PURPOSE_PROPOSE,
1662 &[
1663 CallArg::var("__discarded_purpose_ix__", purpose_span),
1664 CallArg::var(var_purpose_arg, purpose_span),
1665 ],
1666 Type::function(vec![Type::int(), Type::data()], Type::script_purpose()),
1667 redeemer_span,
1668 )
1669 }
1670}
1671
1672#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
1673pub enum Namespace {
1674 Module(String),
1675 Type(Option<String>, String),
1676}
1677
1678#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
1679pub enum Pattern<Constructor, Type, NamespaceKind, ByteValue> {
1680 Int {
1681 location: Span,
1682 value: String,
1683 base: Base,
1684 },
1685
1686 ByteArray {
1687 location: Span,
1688 value: Vec<ByteValue>,
1689 preferred_format: ByteArrayFormatPreference,
1690 },
1691
1692 Var {
1696 location: Span,
1697 name: String,
1698 },
1699
1700 Assign {
1708 name: String,
1709 location: Span,
1710 pattern: Box<Self>,
1711 },
1712
1713 Discard {
1716 name: String,
1717 location: Span,
1718 },
1719
1720 List {
1721 location: Span,
1722 elements: Vec<Self>,
1723 tail: Option<Box<Self>>,
1724 },
1725
1726 Constructor {
1728 is_record: bool,
1729 location: Span,
1730 name: String,
1731 arguments: Vec<CallArg<Self>>,
1732 module: Option<NamespaceKind>,
1733 constructor: Constructor,
1734 spread_location: Option<Span>,
1735 tipo: Type,
1736 },
1737
1738 Pair {
1739 location: Span,
1740 fst: Box<Self>,
1741 snd: Box<Self>,
1742 },
1743
1744 Tuple {
1745 location: Span,
1746 elems: Vec<Self>,
1747 },
1748}
1749
1750impl<A, B, C, BV> Pattern<A, B, C, BV> {
1751 pub fn location(&self) -> Span {
1752 match self {
1753 Pattern::Assign { pattern, .. } => pattern.location(),
1754 Pattern::Int { location, .. }
1755 | Pattern::Var { location, .. }
1756 | Pattern::List { location, .. }
1757 | Pattern::Discard { location, .. }
1758 | Pattern::Tuple { location, .. }
1759 | Pattern::Pair { location, .. }
1760 | Pattern::ByteArray { location, .. }
1761 | Pattern::Constructor { location, .. } => *location,
1762 }
1763 }
1764
1765 pub fn is_simple_pattern_to_format(&self) -> bool {
1769 match self {
1770 Self::ByteArray { .. } | Self::Int { .. } | Self::Var { .. } | Self::Discard { .. } => {
1771 true
1772 }
1773 Self::Pair { fst, snd, .. } => {
1774 fst.is_simple_pattern_to_format() && snd.is_simple_pattern_to_format()
1775 }
1776 Self::Tuple { elems, .. } => elems.iter().all(|e| e.is_simple_pattern_to_format()),
1777 Self::List { elements, .. } if elements.len() <= 3 => {
1778 elements.iter().all(|e| e.is_simple_pattern_to_format())
1779 }
1780 Self::Constructor { arguments, .. } => arguments.is_empty(),
1781 _ => false,
1782 }
1783 }
1784
1785 pub fn with_spread(&self) -> bool {
1786 match self {
1787 Pattern::Constructor {
1788 spread_location, ..
1789 } => spread_location.is_some(),
1790 _ => false,
1791 }
1792 }
1793
1794 pub fn is_discard(&self) -> bool {
1798 matches!(self, Self::Discard { .. })
1799 }
1800
1801 pub fn is_var(&self) -> bool {
1805 matches!(self, Self::Var { .. })
1806 }
1807}
1808
1809impl UntypedPattern {
1810 pub fn true_(location: Span) -> UntypedPattern {
1811 UntypedPattern::Constructor {
1812 location,
1813 name: "True".to_string(),
1814 arguments: vec![],
1815 constructor: (),
1816 spread_location: None,
1817 tipo: (),
1818 module: None,
1819 is_record: false,
1820 }
1821 }
1822
1823 pub fn collect_identifiers<F>(&self, collect: &mut F)
1824 where
1825 F: FnMut((String, Span)),
1826 {
1827 match self {
1828 Pattern::Var { name, location } => {
1829 collect((name.to_string(), *location));
1830 }
1831 Pattern::List { elements, .. } => {
1832 elements.iter().for_each(|e| e.collect_identifiers(collect));
1833 }
1834 Pattern::Pair { fst, snd, .. } => {
1835 fst.collect_identifiers(collect);
1836 snd.collect_identifiers(collect);
1837 }
1838 Pattern::Tuple { elems, .. } => {
1839 elems.iter().for_each(|e| e.collect_identifiers(collect));
1840 }
1841 Pattern::Constructor { arguments, .. } => {
1842 arguments
1843 .iter()
1844 .for_each(|arg| arg.value.collect_identifiers(collect));
1845 }
1846 Pattern::Int { .. }
1847 | Pattern::ByteArray { .. }
1848 | Pattern::Discard { .. }
1849 | Pattern::Assign { .. } => {}
1850 }
1851 }
1852}
1853
1854impl TypedPattern {
1855 pub fn find_node<'a>(&'a self, byte_index: usize, value: &Rc<Type>) -> Option<Located<'a>> {
1856 if !self.location().contains(byte_index) {
1857 return None;
1858 }
1859
1860 match self {
1861 Pattern::Int { .. }
1862 | Pattern::Var { .. }
1863 | Pattern::Assign { .. }
1864 | Pattern::ByteArray { .. }
1865 | Pattern::Discard { .. } => Some(Located::Pattern(self, value.clone())),
1866
1867 Pattern::List { elements, .. }
1868 | Pattern::Tuple {
1869 elems: elements, ..
1870 } => match &**value {
1871 Type::Tuple { elems, .. } => elements
1872 .iter()
1873 .zip(elems.iter())
1874 .find_map(|(e, t)| e.find_node(byte_index, t))
1875 .or(Some(Located::Pattern(self, value.clone()))),
1876 Type::App {
1877 module, name, args, ..
1878 } if module.is_empty() && name == "List" => elements
1879 .iter()
1880 .zip(args.iter().cycle())
1885 .find_map(|(e, t)| e.find_node(byte_index, t))
1886 .or(Some(Located::Pattern(self, value.clone()))),
1887 _ => None,
1888 },
1889
1890 Pattern::Pair { fst, snd, .. } => match &**value {
1891 Type::Pair {
1892 fst: fst_v,
1893 snd: snd_v,
1894 ..
1895 } => [fst, snd]
1896 .into_iter()
1897 .zip([fst_v, snd_v].iter())
1898 .find_map(|(e, t)| e.find_node(byte_index, t))
1899 .or(Some(Located::Pattern(self, value.clone()))),
1900 _ => None,
1901 },
1902
1903 Pattern::Constructor {
1904 arguments, tipo, ..
1905 } => match &**tipo {
1906 Type::Fn { args, .. } => arguments
1907 .iter()
1908 .zip(args.iter())
1909 .find_map(|(e, t)| e.value.find_node(byte_index, t))
1910 .or(Some(Located::Pattern(self, value.clone()))),
1911 _ => None,
1912 },
1913 }
1914 }
1915
1916 pub fn tipo(&self, value: &TypedExpr) -> Option<Rc<Type>> {
1918 match self {
1919 Pattern::Int { .. } => Some(Type::int()),
1920 Pattern::ByteArray { .. } => Some(Type::byte_array()),
1921 Pattern::Constructor { tipo, .. } => Some(tipo.clone()),
1922 Pattern::Var { .. } | Pattern::Assign { .. } | Pattern::Discard { .. } => {
1923 Some(value.tipo())
1924 }
1925 Pattern::List { .. } | Pattern::Tuple { .. } | Pattern::Pair { .. } => None,
1926 }
1927 }
1928}
1929
1930#[derive(Debug, Clone, PartialEq, Eq, Copy, serde::Serialize, serde::Deserialize)]
1931pub enum ByteArrayFormatPreference {
1932 HexadecimalString,
1933 ArrayOfBytes(Base),
1934 Utf8String,
1935}
1936
1937#[derive(Debug, Clone, PartialEq, Eq, Copy)]
1938pub enum CurveType {
1939 Bls12_381(Bls12_381PointType),
1940}
1941
1942impl Display for CurveType {
1943 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1944 match self {
1945 CurveType::Bls12_381(point) => write!(f, "<Bls12_381, {point}>"),
1946 }
1947 }
1948}
1949impl From<&Curve> for CurveType {
1950 fn from(value: &Curve) -> Self {
1951 match value {
1952 Curve::Bls12_381(point) => CurveType::Bls12_381(point.into()),
1953 }
1954 }
1955}
1956
1957#[derive(Debug, Clone, PartialEq, Eq, Copy)]
1958pub enum Bls12_381PointType {
1959 G1,
1960 G2,
1961}
1962
1963impl From<&Bls12_381Point> for Bls12_381PointType {
1964 fn from(value: &Bls12_381Point) -> Self {
1965 match value {
1966 Bls12_381Point::G1(_) => Bls12_381PointType::G1,
1967 Bls12_381Point::G2(_) => Bls12_381PointType::G2,
1968 }
1969 }
1970}
1971
1972impl Display for Bls12_381PointType {
1973 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1974 match self {
1975 Bls12_381PointType::G1 => write!(f, "G1"),
1976 Bls12_381PointType::G2 => write!(f, "G2"),
1977 }
1978 }
1979}
1980
1981#[derive(Debug, Clone, PartialEq, Eq, Copy, serde::Serialize, serde::Deserialize)]
1982pub enum Curve {
1983 Bls12_381(Bls12_381Point),
1984}
1985
1986impl Curve {
1987 pub fn compress(&self) -> Vec<u8> {
1988 match self {
1989 Curve::Bls12_381(point) => match point {
1990 Bls12_381Point::G1(g1) => g1.compress(),
1991 Bls12_381Point::G2(g2) => g2.compress(),
1992 },
1993 }
1994 }
1995
1996 pub fn tipo(&self) -> Rc<Type> {
1997 match self {
1998 Curve::Bls12_381(point) => point.tipo(),
1999 }
2000 }
2001}
2002
2003#[derive(Debug, Clone, PartialEq, Eq, Copy)]
2004pub enum Bls12_381Point {
2005 G1(blst::blst_p1),
2006 G2(blst::blst_p2),
2007}
2008
2009impl serde::Serialize for Bls12_381Point {
2010 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2011 where
2012 S: serde::Serializer,
2013 {
2014 match *self {
2015 Bls12_381Point::G1(ref p1) => {
2016 let bytes = p1.compress();
2018
2019 serializer.serialize_newtype_variant("Bls12_381Point", 0, "G1", &bytes)
2021 }
2022 Bls12_381Point::G2(ref p2) => {
2023 let bytes = p2.compress();
2024
2025 serializer.serialize_newtype_variant("Bls12_381Point", 1, "G2", &bytes)
2026 }
2027 }
2028 }
2029}
2030
2031impl<'de> serde::Deserialize<'de> for Bls12_381Point {
2032 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2033 where
2034 D: serde::Deserializer<'de>,
2035 {
2036 enum Field {
2037 G1,
2038 G2,
2039 }
2040
2041 impl<'de> serde::Deserialize<'de> for Field {
2042 fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
2043 where
2044 D: serde::Deserializer<'de>,
2045 {
2046 struct FieldVisitor;
2047
2048 impl serde::de::Visitor<'_> for FieldVisitor {
2049 type Value = Field;
2050
2051 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2052 formatter.write_str("`G1` or `G2`")
2053 }
2054
2055 fn visit_str<E>(self, value: &str) -> Result<Field, E>
2056 where
2057 E: serde::de::Error,
2058 {
2059 match value {
2060 "G1" => Ok(Field::G1),
2061 "G2" => Ok(Field::G2),
2062 _ => Err(serde::de::Error::unknown_field(value, FIELDS)),
2063 }
2064 }
2065 }
2066
2067 deserializer.deserialize_identifier(FieldVisitor)
2068 }
2069 }
2070
2071 struct Bls12_381PointVisitor;
2072
2073 impl<'de> serde::de::Visitor<'de> for Bls12_381PointVisitor {
2074 type Value = Bls12_381Point;
2075
2076 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2077 formatter.write_str("struct Bls12_381Point")
2078 }
2079
2080 fn visit_seq<V>(self, mut seq: V) -> Result<Bls12_381Point, V::Error>
2081 where
2082 V: serde::de::SeqAccess<'de>,
2083 {
2084 let tag = seq
2085 .next_element::<Field>()?
2086 .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
2087
2088 let bytes = seq
2089 .next_element::<Vec<u8>>()?
2090 .ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
2091
2092 match tag {
2093 Field::G1 => {
2094 let p1 =
2095 blst::blst_p1::uncompress(&bytes).map_err(serde::de::Error::custom)?;
2096
2097 Ok(Bls12_381Point::G1(p1))
2098 }
2099 Field::G2 => {
2100 let p2 =
2101 blst::blst_p2::uncompress(&bytes).map_err(serde::de::Error::custom)?;
2102
2103 Ok(Bls12_381Point::G2(p2))
2104 }
2105 }
2106 }
2107 }
2108
2109 const FIELDS: &[&str] = &["G1", "G2"];
2110
2111 deserializer.deserialize_enum("Bls12_381Point", FIELDS, Bls12_381PointVisitor)
2112 }
2113}
2114
2115impl Bls12_381Point {
2116 pub fn tipo(&self) -> Rc<Type> {
2117 match self {
2118 Bls12_381Point::G1(_) => Type::g1_element(),
2119 Bls12_381Point::G2(_) => Type::g2_element(),
2120 }
2121 }
2122}
2123
2124impl Default for Bls12_381Point {
2125 fn default() -> Self {
2126 Bls12_381Point::G1(Default::default())
2127 }
2128}
2129
2130#[derive(Debug, Clone, PartialEq)]
2131pub struct AssignmentPattern {
2132 pub pattern: UntypedPattern,
2133 pub annotation: Option<Annotation>,
2134 pub location: Span,
2135}
2136
2137impl AssignmentPattern {
2138 pub fn new(
2139 pattern: UntypedPattern,
2140 annotation: Option<Annotation>,
2141 location: Span,
2142 ) -> AssignmentPattern {
2143 Self {
2144 pattern,
2145 annotation,
2146 location,
2147 }
2148 }
2149}
2150
2151impl From<AssignmentPattern> for Vec1<AssignmentPattern> {
2152 fn from(value: AssignmentPattern) -> Self {
2153 Vec1::new(value)
2154 }
2155}
2156
2157pub type UntypedAssignmentKind = AssignmentKind<bool>;
2158pub type TypedAssignmentKind = AssignmentKind<()>;
2159
2160#[derive(Debug, Clone, PartialEq, Eq, Copy, serde::Serialize, serde::Deserialize)]
2161pub enum AssignmentKind<T> {
2162 Is,
2163 Let { backpassing: T },
2164 Expect { backpassing: T },
2165}
2166
2167impl From<UntypedAssignmentKind> for TypedAssignmentKind {
2168 fn from(kind: UntypedAssignmentKind) -> TypedAssignmentKind {
2169 match kind {
2170 AssignmentKind::Is => AssignmentKind::Is,
2171 AssignmentKind::Let { .. } => AssignmentKind::Let { backpassing: () },
2172 AssignmentKind::Expect { .. } => AssignmentKind::Expect { backpassing: () },
2173 }
2174 }
2175}
2176
2177impl<T> AssignmentKind<T> {
2178 pub fn is_let(&self) -> bool {
2179 matches!(self, AssignmentKind::Let { .. })
2180 }
2181
2182 pub fn is_expect(&self) -> bool {
2183 matches!(self, AssignmentKind::Expect { .. })
2184 }
2185
2186 pub fn if_is(&self) -> bool {
2187 matches!(self, AssignmentKind::Is)
2188 }
2189
2190 pub fn location_offset(&self) -> usize {
2191 match self {
2192 AssignmentKind::Is => 2,
2193 AssignmentKind::Let { .. } => 3,
2194 AssignmentKind::Expect { .. } => 6,
2195 }
2196 }
2197}
2198
2199impl AssignmentKind<bool> {
2200 pub fn is_backpassing(&self) -> bool {
2201 match self {
2202 Self::Is => unreachable!(),
2203 Self::Let { backpassing } | Self::Expect { backpassing } => *backpassing,
2204 }
2205 }
2206}
2207
2208impl<T: Default> AssignmentKind<T> {
2209 pub fn let_() -> Self {
2210 AssignmentKind::Let {
2211 backpassing: Default::default(),
2212 }
2213 }
2214
2215 pub fn is() -> Self {
2216 AssignmentKind::Is
2217 }
2218
2219 pub fn expect() -> Self {
2220 AssignmentKind::Expect {
2221 backpassing: Default::default(),
2222 }
2223 }
2224}
2225
2226pub type MultiPattern<PatternConstructor, Type, NamespaceKind, ByteValue> =
2227 Vec<Pattern<PatternConstructor, Type, NamespaceKind, ByteValue>>;
2228
2229pub type UntypedMultiPattern = MultiPattern<(), (), Namespace, (u8, Span)>;
2230pub type TypedMultiPattern = MultiPattern<PatternConstructor, Rc<Type>, String, u8>;
2231
2232#[derive(Debug, Clone, PartialEq)]
2233pub struct UntypedClause {
2234 pub location: Span,
2235 pub patterns: Vec1<UntypedPattern>,
2236 pub then: UntypedExpr,
2237}
2238
2239#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
2240pub struct TypedClause {
2241 pub location: Span,
2242 pub pattern: TypedPattern,
2243 pub then: TypedExpr,
2244}
2245
2246impl TypedClause {
2247 pub fn location(&self) -> Span {
2248 Span {
2249 start: self.pattern.location().start,
2250 end: self.then.location().end,
2251 }
2252 }
2253
2254 pub fn find_node(&self, byte_index: usize, subject_type: &Rc<Type>) -> Option<Located<'_>> {
2255 self.pattern
2256 .find_node(byte_index, subject_type)
2257 .or_else(|| self.then.find_node(byte_index))
2258 }
2259}
2260
2261pub struct UntypedClauseGuard {}
2262
2263pub type TypedIfBranch = IfBranch<TypedExpr, (TypedPattern, Rc<Type>)>;
2264pub type UntypedIfBranch = IfBranch<UntypedExpr, AssignmentPattern>;
2265
2266#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
2267pub struct IfBranch<Expr, Is> {
2268 pub condition: Expr,
2269 pub body: Expr,
2270 pub is: Option<Is>,
2271 pub location: Span,
2272}
2273
2274#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
2275pub struct TypedRecordUpdateArg {
2276 pub label: String,
2277 pub location: Span,
2278 pub value: TypedExpr,
2279 pub index: usize,
2280}
2281
2282impl TypedRecordUpdateArg {
2283 pub fn find_node(&self, byte_index: usize) -> Option<Located<'_>> {
2284 self.value.find_node(byte_index)
2285 }
2286}
2287
2288#[derive(Debug, Clone, PartialEq)]
2289pub struct UntypedRecordUpdateArg {
2290 pub label: String,
2291 pub location: Span,
2292 pub value: UntypedExpr,
2293}
2294
2295#[derive(Debug, Clone, PartialEq)]
2296pub struct RecordUpdateSpread {
2297 pub base: Box<UntypedExpr>,
2298 pub location: Span,
2299}
2300
2301#[derive(Debug, Clone, PartialEq, Eq)]
2302pub enum TraceKind {
2303 Trace,
2304 Todo,
2305 Error,
2306}
2307
2308#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2309pub enum Tracing {
2310 UserDefined(TraceLevel),
2311 CompilerGenerated(TraceLevel),
2312 All(TraceLevel),
2313}
2314
2315#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2316pub enum TraceLevel {
2317 Silent, Compact, Verbose, }
2321
2322impl Tracing {
2323 pub fn verbose() -> Self {
2324 Tracing::All(TraceLevel::Verbose)
2325 }
2326
2327 pub fn silent() -> Self {
2328 Tracing::All(TraceLevel::Silent)
2329 }
2330
2331 pub fn trace_level(&self, is_code_gen: bool) -> TraceLevel {
2333 match self {
2334 Tracing::UserDefined(lvl) => {
2335 if is_code_gen {
2336 TraceLevel::Silent
2337 } else {
2338 *lvl
2339 }
2340 }
2341 Tracing::CompilerGenerated(lvl) => {
2342 if is_code_gen {
2343 *lvl
2344 } else {
2345 TraceLevel::Silent
2346 }
2347 }
2348 Tracing::All(lvl) => *lvl,
2349 }
2350 }
2351}
2352
2353impl Display for TraceLevel {
2354 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
2355 match self {
2356 TraceLevel::Silent => f.write_str("silent"),
2357 TraceLevel::Compact => f.write_str("compact"),
2358 TraceLevel::Verbose => f.write_str("verbose"),
2359 }
2360 }
2361}
2362
2363#[derive(Copy, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
2364pub struct Span {
2365 pub start: usize,
2366 pub end: usize,
2367}
2368
2369impl From<Span> for miette::SourceSpan {
2370 fn from(span: Span) -> Self {
2371 Self::new(span.start.into(), span.end - span.start)
2372 }
2373}
2374
2375impl Span {
2376 pub fn empty() -> Self {
2377 use chumsky::Span;
2378
2379 Self::new((), 0..0)
2380 }
2381
2382 pub fn create(i: usize, n: usize) -> Self {
2383 use chumsky::Span;
2384
2385 Self::new((), i..i + n)
2386 }
2387
2388 pub fn range(&self) -> Range<usize> {
2389 use chumsky::Span;
2390
2391 self.start()..self.end()
2392 }
2393
2394 pub fn union(self, other: Self) -> Self {
2395 use chumsky::Span;
2396
2397 Self {
2398 start: self.start().min(other.start()),
2399 end: self.end().max(other.end()),
2400 }
2401 }
2402
2403 pub fn map<F: FnOnce(usize, usize) -> (usize, usize)>(&self, f: F) -> Self {
2418 let (start, end) = f(self.start, self.end);
2419
2420 Self { start, end }
2421 }
2422
2423 pub fn map_end<F: FnOnce(usize) -> usize>(&self, f: F) -> Self {
2438 Self {
2439 start: self.start,
2440 end: f(self.end),
2441 }
2442 }
2443
2444 pub fn contains(&self, byte_index: usize) -> bool {
2445 byte_index >= self.start && byte_index < self.end
2446 }
2447}
2448
2449impl fmt::Debug for Span {
2450 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2451 write!(f, "{:?}", self.range())
2452 }
2453}
2454
2455impl chumsky::Span for Span {
2456 type Context = ();
2457
2458 type Offset = usize;
2459
2460 fn new(_context: Self::Context, range: Range<Self::Offset>) -> Self {
2461 assert!(range.start <= range.end);
2462
2463 Self {
2464 start: range.start,
2465 end: range.end,
2466 }
2467 }
2468
2469 fn context(&self) -> Self::Context {}
2470
2471 fn start(&self) -> Self::Offset {
2472 self.start
2473 }
2474
2475 fn end(&self) -> Self::Offset {
2476 self.end
2477 }
2478}
2479
2480#[derive(Debug, Clone, PartialEq, Eq)]
2481pub enum LogicalOpChainKind {
2482 And,
2483 Or,
2484}
2485
2486impl Display for LogicalOpChainKind {
2487 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2488 match self {
2489 LogicalOpChainKind::And => write!(f, "and"),
2490 LogicalOpChainKind::Or => write!(f, "or"),
2491 }
2492 }
2493}
2494
2495#[derive(Debug, thiserror::Error, Diagnostic)]
2496pub enum Error {
2497 #[error(
2498 "I realized the module '{}' contains the keyword '{}', which is forbidden.\n",
2499 name.if_supports_color(Stdout, |s| s.purple()),
2500 keyword.if_supports_color(Stdout, |s| s.purple())
2501 )]
2502 #[diagnostic(url("https://aiken-lang.org/language-tour/modules"))]
2503 #[diagnostic(code("illegal::module_name"))]
2504 #[diagnostic(help(r#"You cannot use keywords as part of a module path name. As a quick reminder, here's a list of all the keywords (and thus, of invalid module path names):
2505
2506 as, expect, check, const, else, fn, if, is, let, opaque, pub, test, todo, trace, type, use, when"#))]
2507 KeywordInModuleName { name: String, keyword: String },
2508
2509 #[error("I realized you used '{}' as a module name, which is reserved (and not available).\n",
2510 name.if_supports_color(Stdout, |s| s.purple())
2511 )]
2512 #[diagnostic(code("illegal::module_name"))]
2513 #[diagnostic(help(r#"Some module names are reserved for internal use. This the case of:
2514
2515- aiken: where the prelude is located;
2516- aiken/builtin: where I store low-level Plutus builtins.
2517
2518Note that 'aiken' is also imported by default; but you can refer to it explicitly to disambiguate with a local value that would clash with one from that module."#
2519 ))]
2520 ReservedModuleName { name: String },
2521}