Skip to main content

sway_core/language/ty/expression/
intrinsic_function.rs

1use crate::{
2    engine_threading::*, has_changes, language::ty::*, type_system::*, types::*, HasChanges,
3};
4use itertools::Itertools;
5use serde::{Deserialize, Serialize};
6use std::{
7    fmt,
8    hash::{Hash, Hasher},
9};
10use sway_ast::Intrinsic;
11use sway_error::handler::{ErrorEmitted, Handler};
12use sway_types::{Span, Spanned};
13
14/// The kind of memory representation selected by a [Intrinsic::MemReprEq] `str` argument.
15#[derive(Clone, Copy, PartialEq, Eq, Debug)]
16pub(crate) enum MemReprKind {
17    Runtime,
18    Encoding,
19    Hashing,
20}
21
22impl MemReprKind {
23    pub const KINDS: &[&str] = &["runtime", "encoding", "hashing"];
24
25    pub fn from_str(s: &str) -> Option<MemReprKind> {
26        match s {
27            "runtime" => Some(Self::Runtime),
28            "encoding" => Some(Self::Encoding),
29            "hashing" => Some(Self::Hashing),
30            _ => None,
31        }
32    }
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct TyIntrinsicFunctionKind {
37    pub kind: Intrinsic,
38    pub arguments: Vec<TyExpression>,
39    pub type_arguments: Vec<GenericArgument>,
40    pub span: Span,
41}
42
43impl EqWithEngines for TyIntrinsicFunctionKind {}
44impl PartialEqWithEngines for TyIntrinsicFunctionKind {
45    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
46        self.kind == other.kind
47            && self.arguments.eq(&other.arguments, ctx)
48            && self.type_arguments.eq(&other.type_arguments, ctx)
49    }
50}
51
52impl HashWithEngines for TyIntrinsicFunctionKind {
53    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
54        let TyIntrinsicFunctionKind {
55            kind,
56            arguments,
57            type_arguments,
58            // these fields are not hashed because they aren't relevant/a
59            // reliable source of obj v. obj distinction
60            span: _,
61        } = self;
62        kind.hash(state);
63        arguments.hash(state, engines);
64        type_arguments.hash(state, engines);
65    }
66}
67
68impl SubstTypes for TyIntrinsicFunctionKind {
69    fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges {
70        has_changes! {
71            self.arguments.subst(ctx);
72            self.type_arguments.subst(ctx);
73        }
74    }
75}
76
77impl DebugWithEngines for TyIntrinsicFunctionKind {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
79        let targs = self
80            .type_arguments
81            .iter()
82            .map(|targ| format!("{:?}", engines.help_out(targ.type_id())))
83            .join(", ");
84        let args = self
85            .arguments
86            .iter()
87            .map(|e| format!("{:?}", engines.help_out(e)))
88            .join(", ");
89
90        write!(f, "{}::<{}>::({})", self.kind, targs, args)
91    }
92}
93
94impl CollectTypesMetadata for TyIntrinsicFunctionKind {
95    fn collect_types_metadata(
96        &self,
97        handler: &Handler,
98        ctx: &mut CollectTypesMetadataContext,
99    ) -> Result<Vec<TypeMetadata>, ErrorEmitted> {
100        let mut types_metadata = vec![];
101
102        for type_arg in self.type_arguments.iter() {
103            ctx.call_site_insert(type_arg.type_id(), type_arg.span());
104            types_metadata.append(&mut type_arg.type_id().collect_types_metadata(handler, ctx)?);
105        }
106        for arg in self.arguments.iter() {
107            types_metadata.append(&mut arg.collect_types_metadata(handler, ctx)?);
108        }
109
110        match self.kind {
111            Intrinsic::Log => {
112                let logged_type_id = TypeMetadata::get_logged_type_id(
113                    &self.arguments[0],
114                    ctx.experimental.new_encoding,
115                )
116                .map_err(|err| handler.emit_err(err))?;
117                let logged_type = TypeMetadata::new_logged_type(
118                    handler,
119                    ctx.engines,
120                    logged_type_id,
121                    ctx.program_name.clone(),
122                )?;
123                types_metadata.push(logged_type);
124            }
125            Intrinsic::Smo => {
126                types_metadata.push(TypeMetadata::MessageType(
127                    MessageId::new(ctx.message_id_counter()),
128                    self.arguments[1].return_type,
129                ));
130                *ctx.message_id_counter_mut() += 1;
131            }
132            _ => {}
133        }
134
135        Ok(types_metadata)
136    }
137}