1- use crate :: builtins:: GlobalMethod ;
1+ use crate :: builtins:: { ContractTypeMethod , GlobalFunction , ValueMethod } ;
22use crate :: errors:: { self , CannotMove , TypeError } ;
3- use crate :: namespace:: items:: { DiagnosticSink , EventId , FunctionId , Item } ;
4- use crate :: namespace:: types:: { FixedSize , Type } ;
3+ use crate :: namespace:: items:: { Class , ContractId , DiagnosticSink , EventId , FunctionId , Item } ;
4+ use crate :: namespace:: types:: { FixedSize , SelfDecl , Type } ;
55use crate :: AnalyzerDb ;
66use fe_common:: diagnostics:: Diagnostic ;
77pub use fe_common:: diagnostics:: Label ;
@@ -96,6 +96,16 @@ pub trait AnalyzerContext {
9696#[ derive( Clone , Debug , PartialEq , Eq ) ]
9797pub enum NamedThing {
9898 Item ( Item ) ,
99+ SelfValue {
100+ /// Function `self` parameter.
101+ decl : Option < SelfDecl > ,
102+
103+ /// The function's parent, if any. If `None`, `self` has been
104+ /// used in a module-level function.
105+ class : Option < Class > ,
106+ span : Option < Span > ,
107+ } ,
108+ // SelfType // when/if we add a `Self` type keyword
99109 Variable {
100110 name : String ,
101111 typ : Result < FixedSize , TypeError > ,
@@ -107,6 +117,7 @@ impl NamedThing {
107117 pub fn name_span ( & self , db : & dyn AnalyzerDb ) -> Option < Span > {
108118 match self {
109119 NamedThing :: Item ( item) => item. name_span ( db) ,
120+ NamedThing :: SelfValue { span, .. } => * span,
110121 NamedThing :: Variable { span, .. } => Some ( * span) ,
111122 }
112123 }
@@ -115,13 +126,15 @@ impl NamedThing {
115126 match self {
116127 NamedThing :: Item ( item) => item. is_builtin ( ) ,
117128 NamedThing :: Variable { .. } => false ,
129+ NamedThing :: SelfValue { .. } => false ,
118130 }
119131 }
120132
121133 pub fn item_kind_display_name ( & self ) -> & str {
122134 match self {
123135 NamedThing :: Item ( item) => item. item_kind_display_name ( ) ,
124136 NamedThing :: Variable { .. } => "variable" ,
137+ NamedThing :: SelfValue { .. } => "value" ,
125138 }
126139 }
127140}
@@ -210,16 +223,15 @@ impl ExpressionAttributes {
210223 /// Adds a move to value, if it is in storage or memory.
211224 pub fn into_loaded ( mut self ) -> Result < Self , CannotMove > {
212225 match self . typ {
213- Type :: Base ( _) => { }
214- Type :: Contract ( _ ) => { }
215- _ => return Err ( CannotMove ) ,
216- }
226+ Type :: Base ( _) | Type :: Contract ( _ ) => {
227+ if self . location != Location :: Value {
228+ self . move_location = Some ( Location :: Value ) ;
229+ }
217230
218- if self . location != Location :: Value {
219- self . move_location = Some ( Location :: Value ) ;
231+ Ok ( self )
232+ }
233+ _ => Err ( CannotMove ) ,
220234 }
221-
222- Ok ( self )
223235 }
224236
225237 /// The final location of an expression after a possible move.
@@ -233,21 +245,77 @@ impl ExpressionAttributes {
233245
234246impl fmt:: Display for ExpressionAttributes {
235247 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> Result < ( ) , fmt:: Error > {
236- write ! (
237- f ,
238- "{}: {:?} => {:?}" ,
239- self . typ , self . location , self . move_location
240- )
248+ if let Some ( move_to ) = self . move_location {
249+ write ! ( f , "{}: {:?} => {:?}" , self . typ , self . location , move_to )
250+ } else {
251+ write ! ( f , "{}: {:?}" , self . typ , self . location )
252+ }
241253 }
242254}
243255
244256/// The type of a function call.
245257#[ derive( Clone , Debug , PartialEq , Eq ) ]
246258pub enum CallType {
247- BuiltinFunction ( GlobalMethod ) ,
248- TypeConstructor { typ : Type } ,
249- SelfAttribute { func_name : String , self_span : Span } ,
259+ BuiltinFunction ( GlobalFunction ) ,
260+ BuiltinValueMethod ( ValueMethod ) ,
261+
262+ // create, create2 (will be methods of the context struct soon)
263+ BuiltinAssociatedFunction {
264+ contract : ContractId ,
265+ function : ContractTypeMethod ,
266+ } ,
267+
268+ // MyStruct.foo() (soon MyStruct::foo())
269+ AssociatedFunction {
270+ class : Class ,
271+ function : FunctionId ,
272+ } ,
273+ ValueMethod {
274+ is_self : bool ,
275+ class : Class ,
276+ method : FunctionId ,
277+ } ,
250278 Pure ( FunctionId ) ,
251- ValueAttribute ,
252- TypeAttribute { typ : Type , func_name : String } ,
279+ TypeConstructor ( Type ) ,
280+ }
281+
282+ impl CallType {
283+ pub fn function ( & self ) -> Option < FunctionId > {
284+ use CallType :: * ;
285+ match self {
286+ BuiltinFunction ( _)
287+ | BuiltinValueMethod ( _)
288+ | TypeConstructor ( _)
289+ | BuiltinAssociatedFunction { .. } => None ,
290+ AssociatedFunction { function : id, .. } | ValueMethod { method : id, .. } | Pure ( id) => {
291+ Some ( * id)
292+ }
293+ }
294+ }
295+
296+ pub fn function_name ( & self , db : & dyn AnalyzerDb ) -> String {
297+ match self {
298+ CallType :: BuiltinFunction ( f) => f. as_ref ( ) . to_string ( ) ,
299+ CallType :: BuiltinValueMethod ( f) => f. as_ref ( ) . to_string ( ) ,
300+ CallType :: BuiltinAssociatedFunction { function, .. } => function. as_ref ( ) . to_string ( ) ,
301+
302+ CallType :: AssociatedFunction { function : id, .. }
303+ | CallType :: ValueMethod { method : id, .. }
304+ | CallType :: Pure ( id) => id. name ( db) ,
305+ CallType :: TypeConstructor ( typ) => typ. to_string ( ) ,
306+ }
307+ }
308+
309+ pub fn is_unsafe ( & self , db : & dyn AnalyzerDb ) -> bool {
310+ // There are no built-in unsafe fns yet
311+ self . function ( )
312+ . map ( |id| id. unsafe_span ( db) . is_some ( ) )
313+ . unwrap_or ( false )
314+ }
315+ }
316+
317+ impl fmt:: Display for CallType {
318+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> Result < ( ) , fmt:: Error > {
319+ write ! ( f, "{:?}" , self )
320+ }
253321}
0 commit comments