@@ -208,6 +208,19 @@ impl crate::query::CompilationBase for CompilerDatabase {
208208 . peek ( & ( key. into ( ) , None ) )
209209 . and_then ( |r| r. ok ( ) )
210210 }
211+
212+ fn peek_module_type ( & self , key : & str ) -> Option < ArcType > {
213+ self . query ( ModuleTypeQuery )
214+ . peek ( & ( key. into ( ) , None ) )
215+ . and_then ( |r| r. ok ( ) )
216+ }
217+
218+ fn peek_module_metadata ( & self , key : & str ) -> Option < Arc < Metadata > > {
219+ self . query ( ModuleMetadataQuery )
220+ . peek ( & ( key. into ( ) , None ) )
221+ . and_then ( |r| r. ok ( ) )
222+ }
223+
211224 fn peek_core_expr ( & self , key : & str ) -> Option < interpreter:: Global < CoreExpr > > {
212225 self . query ( CoreExprQuery )
213226 . peek ( & ( key. into ( ) , None ) )
@@ -326,6 +339,8 @@ pub trait CompilationBase: Send {
326339 fn add_module ( & mut self , module : String , contents : & str ) ;
327340
328341 fn peek_typechecked_module ( & self , key : & str ) -> Option < TypecheckValue < Arc < OwnedExpr < Symbol > > > > ;
342+ fn peek_module_type ( & self , key : & str ) -> Option < ArcType > ;
343+ fn peek_module_metadata ( & self , key : & str ) -> Option < Arc < Metadata > > ;
329344 fn peek_core_expr ( & self , key : & str ) -> Option < interpreter:: Global < CoreExpr > > ;
330345 fn peek_global ( & self , key : & str ) -> Option < DatabaseGlobal > ;
331346}
@@ -362,6 +377,18 @@ pub trait Compilation: CompilationBase {
362377 ( Option < TypecheckValue < Arc < OwnedExpr < Symbol > > > > , Error ) ,
363378 > ;
364379
380+ async fn module_type (
381+ & self ,
382+ module : String ,
383+ expected_type : Option < ArcType > ,
384+ ) -> StdResult < ArcType , Error > ;
385+
386+ async fn module_metadata (
387+ & self ,
388+ module : String ,
389+ expected_type : Option < ArcType > ,
390+ ) -> StdResult < Arc < Metadata > , Error > ;
391+
365392 #[ salsa:: cycle( recover_cycle_expected_type) ]
366393 async fn core_expr (
367394 & self ,
@@ -497,6 +524,36 @@ async fn typechecked_module(
497524 Ok ( value. map ( Arc :: new) )
498525}
499526
527+ async fn module_type (
528+ db : & mut ( impl Compilation + salsa:: Database ) ,
529+ name : String ,
530+ expected_type : Option < ArcType > ,
531+ ) -> StdResult < ArcType , Error > {
532+ if db. compiler ( ) . query ( ExternLoaderQuery ) . peek ( & name) . is_some ( ) {
533+ let ( _id, module) = & * db. extern_module ( name) . await ?;
534+ return Ok ( module. typ . clone ( ) ) ;
535+ }
536+ db. typechecked_module ( name, expected_type)
537+ . await
538+ . map ( |module| module. typ )
539+ . map_err ( |( _, err) | err)
540+ }
541+
542+ async fn module_metadata (
543+ db : & mut ( impl Compilation + salsa:: Database ) ,
544+ name : String ,
545+ expected_type : Option < ArcType > ,
546+ ) -> StdResult < Arc < Metadata > , Error > {
547+ if db. compiler ( ) . query ( ExternLoaderQuery ) . peek ( & name) . is_some ( ) {
548+ let ( _id, module) = & * db. extern_module ( name. clone ( ) ) . await ?;
549+ return Ok ( Arc :: new ( module. metadata . clone ( ) ) ) ;
550+ }
551+ db. typechecked_module ( name, expected_type)
552+ . await
553+ . map ( |module| module. metadata )
554+ . map_err ( |( _, err) | err)
555+ }
556+
500557async fn core_expr (
501558 db : & mut ( impl Compilation + salsa:: Database ) ,
502559 module : String ,
@@ -505,9 +562,15 @@ async fn core_expr(
505562 db. salsa_runtime_mut ( ) . report_untracked_read ( ) ;
506563
507564 let value = db
508- . typechecked_module ( module. clone ( ) , expected_type)
565+ . typechecked_module ( module. clone ( ) , expected_type. clone ( ) )
509566 . await
510567 . map_err ( |( _, err) | err) ?;
568+
569+ // Ensure the type is stored in the database so we can collect typechecked_module later
570+ db. module_type ( module. clone ( ) , expected_type. clone ( ) )
571+ . await ?;
572+ db. module_metadata ( module. clone ( ) , expected_type) . await ?;
573+
511574 let settings = db. compiler_settings ( ) ;
512575
513576 let env = env ( db. compiler ( ) ) ;
@@ -612,6 +675,11 @@ async fn global_inner(db: &mut dyn Compilation, name: String) -> Result<Unrooted
612675 . typechecked_module ( name. clone ( ) , None )
613676 . await
614677 . map_err ( |( _, err) | err) ?;
678+
679+ // Ensure the type is stored in the database so we can collect typechecked_module later
680+ db. module_type ( name. clone ( ) , None ) . await ?;
681+ db. module_metadata ( name. clone ( ) , None ) . await ?;
682+
615683 let closure = db. compiled_module ( name. clone ( ) , None ) . await ?;
616684
617685 let module_id = closure. function . name . clone ( ) ;
@@ -745,7 +813,15 @@ where
745813
746814 fn find_type ( & self , id : & SymbolRef ) -> Option < ArcType > {
747815 if id. is_global ( ) {
748- self . get_global ( id. definition_name ( ) ) . map ( |g| g. typ . clone ( ) )
816+ self . 0
817+ . borrow_mut ( )
818+ . get_binding_inner ( id. definition_name ( ) , |self_, module| {
819+ self_
820+ . get_extern_global ( module. as_str ( ) )
821+ . map ( |global| global. typ )
822+ . or_else ( || self_. peek_module_type ( module. as_str ( ) . into ( ) ) )
823+ } )
824+ . ok ( )
749825 } else {
750826 let name = id. definition_name ( ) ;
751827
@@ -831,10 +907,81 @@ where
831907 }
832908}
833909
910+ fn get_scoped_global < ' n , T > (
911+ name : & ' n str ,
912+ mut lookup : impl FnMut ( & Name ) -> Option < T > ,
913+ ) -> Option < ( & ' n Name , T ) > {
914+ let mut module = Name :: new ( name. trim_start_matches ( '@' ) ) ;
915+ // Try to find a global by successively reducing the module path
916+ // Input: "x.y.z.w"
917+ // Test: "x.y.z"
918+ // Test: "x.y"
919+ // Test: "x"
920+ // Test: -> Error
921+ let global = loop {
922+ if module. as_str ( ) == "" {
923+ return None ;
924+ }
925+ if let Some ( g) = lookup ( module) {
926+ break g;
927+ }
928+ module = module. module ( ) ;
929+ } ;
930+ let remaining_offset = :: std:: cmp:: min ( name. len ( ) , module. as_str ( ) . len ( ) + 1 ) ; //Add 1 byte for the '.'
931+ let remaining_fields = Name :: new ( & name[ remaining_offset..] ) ;
932+ Some ( ( remaining_fields, global) )
933+ }
934+
935+ use crate :: base:: resolve;
936+ trait Extract : Sized {
937+ // type Output;
938+ fn extract ( & self , db : & mut CompilerDatabase , field_name : & str ) -> Option < Self > ;
939+ fn typ ( & self ) -> & ArcType ;
940+ // fn output(&self) -> Self::Output;
941+ }
942+
943+ impl Extract for ArcType {
944+ fn extract ( & self , db : & mut CompilerDatabase , field_name : & str ) -> Option < Self > {
945+ let typ = resolve:: remove_aliases_cow ( & env ( db) , & mut NullInterner , self ) ;
946+ typ. row_iter ( )
947+ . find ( |field| field. name . as_ref ( ) == field_name)
948+ . map ( |field| field. typ . clone ( ) )
949+ }
950+ fn typ ( & self ) -> & ArcType {
951+ self
952+ }
953+ }
954+ impl Extract for ( RootedValue < RootedThread > , ArcType ) {
955+ fn extract ( & self , db : & mut CompilerDatabase , field_name : & str ) -> Option < Self > {
956+ let ( value, typ) = self ;
957+ let typ = resolve:: remove_aliases_cow ( & env ( db) , & mut NullInterner , typ) ;
958+ typ. row_iter ( )
959+ . enumerate ( )
960+ . find ( |& ( _, field) | field. name . as_ref ( ) == field_name)
961+ . map ( |( index, field) | match value. get_variants ( ) . as_ref ( ) {
962+ ValueRef :: Data ( data) => (
963+ db. thread ( ) . root_value ( data. get_variant ( index) . unwrap ( ) ) ,
964+ field. typ . clone ( ) ,
965+ ) ,
966+ _ => ice ! ( "Unexpected value {:?}" , value) ,
967+ } )
968+ }
969+ fn typ ( & self ) -> & ArcType {
970+ & self . 1
971+ }
972+ }
973+
834974impl CompilerDatabase {
835975 pub fn find_type_info ( & mut self , name : & str ) -> Result < Alias < Symbol , ArcType > > {
836976 let name = Name :: new ( name) ;
837- let ( _, typ) = self . get_binding ( name. module ( ) . as_str ( ) ) ?;
977+
978+ let typ = self . get_binding_inner ( name. module ( ) . as_str ( ) , |self_, module| {
979+ self_
980+ . get_extern_global ( module. as_str ( ) )
981+ . map ( |global| global. typ )
982+ . or_else ( || self_. peek_module_type ( module. as_str ( ) . into ( ) ) )
983+ } ) ?;
984+
838985 let maybe_type_info = {
839986 let field_name = name. name ( ) ;
840987 typ. type_field_iter ( )
@@ -846,49 +993,31 @@ impl CompilerDatabase {
846993 . ok_or_else ( move || vm:: Error :: UndefinedField ( typ, name. name ( ) . as_str ( ) . into ( ) ) . into ( ) )
847994 }
848995
849- fn get_scoped_global < ' s , ' n > (
850- & ' s mut self ,
851- name : & ' n str ,
852- ) -> Option < ( & ' n Name , DatabaseGlobal ) > {
853- let mut module = Name :: new ( name. trim_start_matches ( '@' ) ) ;
854- // Try to find a global by successively reducing the module path
855- // Input: "x.y.z.w"
856- // Test: "x.y.z"
857- // Test: "x.y"
858- // Test: "x"
859- // Test: -> Error
860- let global = loop {
861- if module. as_str ( ) == "" {
862- return None ;
863- }
864- if let Some ( g) = self
865- . get_extern_global ( name)
866- . or_else ( || self . peek_global ( module. as_str ( ) . into ( ) ) )
867- {
868- break g;
869- }
870- module = module. module ( ) ;
871- } ;
872- let remaining_offset = :: std:: cmp:: min ( name. len ( ) , module. as_str ( ) . len ( ) + 1 ) ; //Add 1 byte for the '.'
873- let remaining_fields = Name :: new ( & name[ remaining_offset..] ) ;
874- Some ( ( remaining_fields, global) )
875- }
876-
877996 pub fn get_binding ( & mut self , name : & str ) -> Result < ( RootedValue < RootedThread > , ArcType ) > {
878- use crate :: base:: resolve;
997+ self . get_binding_inner ( name, |self_, module| {
998+ self_
999+ . get_extern_global ( module. as_str ( ) )
1000+ . or_else ( || self_. peek_global ( module. as_str ( ) . into ( ) ) )
1001+ . map ( |global| ( global. value , global. typ ) )
1002+ } )
1003+ }
8791004
880- let ( remaining_fields, global) = self
881- . get_scoped_global ( name)
1005+ fn get_binding_inner < T > (
1006+ & mut self ,
1007+ name : & str ,
1008+ mut lookup : impl FnMut ( & mut Self , & Name ) -> Option < T > ,
1009+ ) -> Result < T >
1010+ where
1011+ T : Extract ,
1012+ {
1013+ let ( remaining_fields, mut value) = get_scoped_global ( name, |n| lookup ( self , n) )
8821014 . ok_or_else ( || vm:: Error :: UndefinedBinding ( name. into ( ) ) ) ?;
8831015
8841016 if remaining_fields. as_str ( ) . is_empty ( ) {
8851017 // No fields left
886- return Ok ( ( global . value , global . typ . clone ( ) ) ) ;
1018+ return Ok ( value) ;
8871019 }
8881020
889- let mut typ = global. typ ;
890- let mut value = global. value . get_variant ( ) ;
891-
8921021 for mut field_name in remaining_fields. components ( ) {
8931022 if field_name. starts_with ( '(' ) && field_name. ends_with ( ')' ) {
8941023 field_name = & field_name[ 1 ..field_name. len ( ) - 1 ] ;
@@ -902,24 +1031,13 @@ impl CompilerDatabase {
9021031 ) )
9031032 . into ( ) ) ;
9041033 }
905- typ = resolve:: remove_aliases ( & env ( self ) , & mut NullInterner , typ) ;
906- let next_type = {
907- typ. row_iter ( )
908- . enumerate ( )
909- . find ( |& ( _, field) | field. name . as_ref ( ) == field_name)
910- . map ( |( index, field) | match value. as_ref ( ) {
911- ValueRef :: Data ( data) => {
912- value = data. get_variant ( index) . unwrap ( ) ;
913- & field. typ
914- }
915- _ => ice ! ( "Unexpected value {:?}" , value) ,
916- } )
917- . cloned ( )
918- } ;
919- typ =
920- next_type. ok_or_else ( move || vm:: Error :: UndefinedField ( typ, field_name. into ( ) ) ) ?;
1034+
1035+ value = value. extract ( self , field_name) . ok_or_else ( move || {
1036+ vm:: Error :: UndefinedField ( value. typ ( ) . clone ( ) , field_name. into ( ) )
1037+ } ) ?;
9211038 }
922- Ok ( ( self . thread ( ) . root_value ( value) , typ) )
1039+
1040+ Ok ( value)
9231041 }
9241042
9251043 pub fn get_metadata ( & mut self , name_str : & str ) -> Result < Arc < Metadata > > {
@@ -928,9 +1046,14 @@ impl CompilerDatabase {
9281046 }
9291047
9301048 fn get_metadata_ ( & mut self , name_str : & str ) -> Option < Arc < Metadata > > {
931- let ( remaining, global) = self . get_scoped_global ( name_str) ?;
1049+ let ( remaining, metadata) = get_scoped_global ( name_str, |module| {
1050+ self . get_extern_global ( module. as_str ( ) )
1051+ . map ( |global| global. metadata )
1052+ . or_else ( || self . peek_module_metadata ( module. as_str ( ) . into ( ) ) )
1053+ } ) ?;
1054+
1055+ let mut metadata = & metadata;
9321056
933- let mut metadata = & global. metadata ;
9341057 for field_name in remaining. components ( ) {
9351058 metadata = metadata. module . get ( field_name) ?
9361059 }
0 commit comments