cairo_lang_sierra/extensions/modules/
function_call.rs1use itertools::chain;
2
3use super::coupon::coupon_ty;
4use crate::extensions::lib_func::{
5 LibfuncSignature, OutputVarInfo, SignatureBasedConcreteLibfunc, SignatureSpecializationContext,
6 SpecializationContext,
7};
8use crate::extensions::{
9 NamedLibfunc, OutputVarReferenceInfo, SpecializationError, args_as_single_user_func,
10};
11use crate::program::{Function, FunctionSignature, GenericArg};
12
13fn get_output_var_infos(
15 context: &dyn SignatureSpecializationContext,
16 signature: FunctionSignature,
17) -> Result<Vec<OutputVarInfo>, SpecializationError> {
18 let mut curr_stack_idx = 0;
19 let mut get_stack_idx = || {
20 let idx = curr_stack_idx;
21 curr_stack_idx += 1;
22 idx
23 };
24
25 signature
26 .ret_types
27 .iter()
28 .map(|ty| {
29 Ok(OutputVarInfo {
30 ty: ty.clone(),
31 ref_info: if context.get_type_info(ty.clone())?.zero_sized {
32 OutputVarReferenceInfo::ZeroSized
33 } else {
34 OutputVarReferenceInfo::NewTempVar { idx: get_stack_idx() }
35 },
36 })
37 })
38 .collect::<Result<Vec<_>, _>>()
39}
40
41#[derive(Default)]
43pub struct FunctionCallLibfunc {}
44impl NamedLibfunc for FunctionCallLibfunc {
45 type Concrete = SignatureAndFunctionConcreteLibfunc;
46 const STR_ID: &'static str = "function_call";
47
48 fn specialize_signature(
49 &self,
50 context: &dyn SignatureSpecializationContext,
51 args: &[GenericArg],
52 ) -> Result<LibfuncSignature, SpecializationError> {
53 let function_id = args_as_single_user_func(args)?;
54
55 let signature = context.get_function_signature(&function_id)?;
56 let ap_change = context.get_function_ap_change(&function_id)?;
57 Ok(LibfuncSignature::new_non_branch(
58 signature.param_types.clone(),
59 get_output_var_infos(context, signature)?,
60 ap_change,
61 ))
62 }
63
64 fn specialize(
65 &self,
66 context: &dyn SpecializationContext,
67 args: &[GenericArg],
68 ) -> Result<Self::Concrete, SpecializationError> {
69 let function_id = args_as_single_user_func(args)?;
70
71 Ok(Self::Concrete {
72 function: context.get_function(&function_id)?,
73 signature: self.specialize_signature(context.upcast(), args)?,
74 })
75 }
76}
77
78pub struct SignatureAndFunctionConcreteLibfunc {
79 pub function: Function,
80 pub signature: LibfuncSignature,
81}
82impl SignatureBasedConcreteLibfunc for SignatureAndFunctionConcreteLibfunc {
83 fn signature(&self) -> &LibfuncSignature {
84 &self.signature
85 }
86}
87
88#[derive(Default)]
90pub struct CouponCallLibfunc {}
91impl NamedLibfunc for CouponCallLibfunc {
92 type Concrete = SignatureAndFunctionConcreteLibfunc;
93 const STR_ID: &'static str = "coupon_call";
94
95 fn specialize_signature(
96 &self,
97 context: &dyn SignatureSpecializationContext,
98 args: &[GenericArg],
99 ) -> Result<LibfuncSignature, SpecializationError> {
100 let function_id = args_as_single_user_func(args)?;
101
102 let signature = context.get_function_signature(&function_id)?;
103 let ap_change = context.get_function_ap_change(&function_id)?;
104
105 let coupon_ty = coupon_ty(context, function_id.clone())?;
106 Ok(LibfuncSignature::new_non_branch(
107 chain!(signature.param_types.iter().cloned(), [coupon_ty]).collect(),
108 get_output_var_infos(context, signature)?,
109 ap_change,
110 ))
111 }
112
113 fn specialize(
114 &self,
115 context: &dyn SpecializationContext,
116 args: &[GenericArg],
117 ) -> Result<Self::Concrete, SpecializationError> {
118 let function_id = args_as_single_user_func(args)?;
119
120 Ok(Self::Concrete {
121 function: context.get_function(&function_id)?,
122 signature: self.specialize_signature(context.upcast(), args)?,
123 })
124 }
125}