sway_core/language/ty/expression/
intrinsic_function.rs1use crate::{
2 abi_generation::abi_str::AbiStrContext, engine_threading::*, has_changes, language::ty::*,
3 type_system::*, types::*,
4};
5use itertools::Itertools;
6use serde::{Deserialize, Serialize};
7use std::{
8 fmt,
9 hash::{Hash, Hasher},
10};
11use sway_ast::Intrinsic;
12use sway_error::handler::{ErrorEmitted, Handler};
13use sway_types::Span;
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct TyIntrinsicFunctionKind {
17 pub kind: Intrinsic,
18 pub arguments: Vec<TyExpression>,
19 pub type_arguments: Vec<GenericArgument>,
20 pub span: Span,
21}
22
23impl TyIntrinsicFunctionKind {
24 pub fn get_logged_type(&self, new_encoding: bool) -> Option<TypeId> {
28 if new_encoding {
29 if matches!(self.kind, Intrinsic::Log) {
30 match &self.arguments[0].expression {
31 TyExpressionVariant::FunctionApplication {
32 call_path,
33 arguments,
34 ..
35 } => {
36 assert!(call_path.suffix.as_str() == "encode");
37 Some(arguments[0].1.return_type)
38 }
39 _ => None,
40 }
41 } else {
42 None
43 }
44 } else {
45 Some(self.arguments[0].return_type)
46 }
47 }
48}
49
50impl EqWithEngines for TyIntrinsicFunctionKind {}
51impl PartialEqWithEngines for TyIntrinsicFunctionKind {
52 fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
53 self.kind == other.kind
54 && self.arguments.eq(&other.arguments, ctx)
55 && self.type_arguments.eq(&other.type_arguments, ctx)
56 }
57}
58
59impl HashWithEngines for TyIntrinsicFunctionKind {
60 fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
61 let TyIntrinsicFunctionKind {
62 kind,
63 arguments,
64 type_arguments,
65 span: _,
68 } = self;
69 kind.hash(state);
70 arguments.hash(state, engines);
71 type_arguments.hash(state, engines);
72 }
73}
74
75impl SubstTypes for TyIntrinsicFunctionKind {
76 fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
77 has_changes! {
78 self.arguments.subst(ctx);
79 self.type_arguments.subst(ctx);
80 }
81 }
82}
83
84impl DebugWithEngines for TyIntrinsicFunctionKind {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
86 let targs = self
87 .type_arguments
88 .iter()
89 .map(|targ| format!("{:?}", engines.help_out(targ.type_id())))
90 .join(", ");
91 let args = self
92 .arguments
93 .iter()
94 .map(|e| format!("{:?}", engines.help_out(e)))
95 .join(", ");
96
97 write!(f, "{}::<{}>::({})", self.kind, targs, args)
98 }
99}
100
101impl CollectTypesMetadata for TyIntrinsicFunctionKind {
102 fn collect_types_metadata(
103 &self,
104 handler: &Handler,
105 ctx: &mut CollectTypesMetadataContext,
106 ) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
107 let mut types_metadata = vec![];
108 for type_arg in self.type_arguments.iter() {
109 types_metadata.append(&mut type_arg.type_id().collect_types_metadata(handler, ctx)?);
110 }
111 for arg in self.arguments.iter() {
112 types_metadata.append(&mut arg.collect_types_metadata(handler, ctx)?);
113 }
114
115 match self.kind {
116 Intrinsic::Log => {
117 let logged_type = self.get_logged_type(ctx.experimental.new_encoding).unwrap();
118 types_metadata.push(TypeMetadata::LoggedType(
119 LogId::new(logged_type.get_abi_type_str(
120 &AbiStrContext {
121 program_name: ctx.program_name.clone(),
122 abi_with_callpaths: true,
123 abi_with_fully_specified_types: true,
124 abi_root_type_without_generic_type_parameters: false,
125 },
126 ctx.engines,
127 logged_type,
128 )),
129 logged_type,
130 ));
131 }
132 Intrinsic::Smo => {
133 types_metadata.push(TypeMetadata::MessageType(
134 MessageId::new(ctx.message_id_counter()),
135 self.arguments[1].return_type,
136 ));
137 *ctx.message_id_counter_mut() += 1;
138 }
139 _ => {}
140 }
141
142 Ok(types_metadata)
143 }
144}