@@ -9,17 +9,18 @@ use miniscript::iter::{Tree, TreeLike};
99use simplicity:: jet:: Elements ;
1010
1111use crate :: debug:: { CallTracker , DebugSymbols , TrackedCallName } ;
12+ use crate :: driver:: ProgramResolutions ;
1213use crate :: error:: { Error , RichError , Span , WithSpan } ;
1314use crate :: num:: { NonZeroPow2Usize , Pow2Usize } ;
14- use crate :: parse:: { MatchPattern , UseDecl , Visibility } ;
15+ use crate :: parse:: MatchPattern ;
1516use crate :: pattern:: Pattern ;
1617use crate :: str:: { AliasName , FunctionName , Identifier , ModuleName , WitnessName } ;
1718use crate :: types:: {
1819 AliasedType , ResolvedType , StructuralType , TypeConstructible , TypeDeconstructible , UIntType ,
1920} ;
2021use crate :: value:: { UIntValue , Value } ;
2122use crate :: witness:: { Parameters , WitnessTypes , WitnessValues } ;
22- use crate :: { impl_eq_hash, parse} ;
23+ use crate :: { SourceName , driver , impl_eq_hash, parse} ;
2324
2425/// A program consists of the main function.
2526///
@@ -73,8 +74,6 @@ pub enum Item {
7374 TypeAlias ,
7475 /// A function.
7576 Function ( Function ) ,
76- /// A use declaration
77- Use ( UseDecl ) ,
7877 /// A module, which is ignored.
7978 Module ,
8079}
@@ -307,7 +306,6 @@ pub enum CallName {
307306/// Definition of a custom function.
308307#[ derive( Clone , Debug , Eq , PartialEq , Hash ) ]
309308pub struct CustomFunction {
310- visibility : Visibility ,
311309 params : Arc < [ FunctionParam ] > ,
312310 body : Arc < Expression > ,
313311}
@@ -525,6 +523,10 @@ impl TreeLike for ExprTree<'_> {
525523/// 4. Resolving calls to custom functions
526524#[ derive( Clone , Debug , Eq , PartialEq , Default ) ]
527525struct Scope {
526+ resolutions : ProgramResolutions ,
527+ paths : Arc < [ SourceName ] > ,
528+ file_id : usize , // ID of the file from which the function is called.
529+
528530 variables : Vec < HashMap < Identifier , ResolvedType > > ,
529531 aliases : HashMap < AliasName , ResolvedType > ,
530532 parameters : HashMap < WitnessName , ResolvedType > ,
@@ -535,6 +537,26 @@ struct Scope {
535537}
536538
537539impl Scope {
540+ pub fn new ( resolutions : ProgramResolutions , paths : Arc < [ SourceName ] > ) -> Self {
541+ Self {
542+ resolutions,
543+ paths,
544+ file_id : 0 ,
545+ variables : Vec :: new ( ) ,
546+ aliases : HashMap :: new ( ) ,
547+ parameters : HashMap :: new ( ) ,
548+ witnesses : HashMap :: new ( ) ,
549+ functions : HashMap :: new ( ) ,
550+ is_main : false ,
551+ call_tracker : CallTracker :: default ( ) ,
552+ }
553+ }
554+
555+ /// Access to current function file id.
556+ pub fn file_id ( & self ) -> usize {
557+ self . file_id
558+ }
559+
538560 /// Check if the current scope is topmost.
539561 pub fn is_topmost ( & self ) -> bool {
540562 self . variables . is_empty ( )
@@ -545,6 +567,11 @@ impl Scope {
545567 self . variables . push ( HashMap :: new ( ) ) ;
546568 }
547569
570+ pub fn push_function_scope ( & mut self , file_id : usize ) {
571+ self . push_scope ( ) ;
572+ self . file_id = file_id;
573+ }
574+
548575 /// Push the scope of the main function onto the stack.
549576 ///
550577 /// ## Panics
@@ -567,6 +594,11 @@ impl Scope {
567594 self . variables . pop ( ) . expect ( "Stack is empty" ) ;
568595 }
569596
597+ pub fn pop_function_scope ( & mut self , previous_file_id : usize ) {
598+ self . pop_scope ( ) ;
599+ self . file_id = previous_file_id;
600+ }
601+
570602 /// Pop the scope of the main function from the stack.
571603 ///
572604 /// ## Panics
@@ -693,11 +725,51 @@ impl Scope {
693725 }
694726 }
695727
696- /// Get the definition of a custom function.
697- pub fn get_function ( & self , name : & FunctionName ) -> Option < & CustomFunction > {
698- self . functions . get ( name)
728+ /// Get the definition of a custom function with visibility and existence checks.
729+ ///
730+ /// # Errors
731+ ///
732+ /// - `Error::FileNotFound`: The specified file_id does not exist in the resolutions.
733+ /// - `Error::FunctionUndefined`: The function is not found in the file's scope OR not defined globally.
734+ /// - `Error::FunctionIsPrivate`: The function exists but is private (and thus not accessible).
735+
736+ // TODO: Add errors later
737+ pub fn get_function (
738+ & self ,
739+ name : & FunctionName ,
740+ ) -> Result < & CustomFunction , Error > {
741+ // The order of the errors is important!
742+ let function = self . functions
743+ . get ( name)
744+ . ok_or_else ( || Error :: FunctionUndefined ( name. clone ( ) ) ) ?;
745+
746+ let source_name = self . paths [ self . file_id ] . clone ( ) ;
747+
748+ let file_scope = match source_name {
749+ SourceName :: Real ( path) => {
750+ self . resolutions
751+ . get ( self . file_id )
752+ . ok_or ( Error :: FileNotFound ( path) ) ?
753+ } ,
754+ SourceName :: Virtual ( _) => {
755+ return Ok ( function) ;
756+ }
757+ } ;
758+
759+ let identifier: Identifier = name. clone ( ) . into ( ) ;
760+
761+ if file_scope. contains_key ( & identifier) {
762+ Ok ( function)
763+ } else {
764+ Err ( Error :: FunctionIsPrivate ( name. clone ( ) ) )
765+ }
699766 }
700767
768+ /// Get the definition of a custom function.
769+ // pub fn get_function(&self, name: &FunctionName) -> Option<&CustomFunction> {
770+ // self.functions.get(name)
771+ // }
772+
701773 /// Track a call expression with its span.
702774 pub fn track_call < S : AsRef < Span > > ( & mut self , span : & S , name : TrackedCallName ) {
703775 self . call_tracker . track_call ( * span. as_ref ( ) , name) ;
@@ -718,9 +790,10 @@ trait AbstractSyntaxTree: Sized {
718790}
719791
720792impl Program {
721- pub fn analyze ( from : & parse:: Program ) -> Result < Self , RichError > {
793+ // TODO: Add visibility check inside program
794+ pub fn analyze ( from : & driver:: Program ) -> Result < Self , RichError > {
722795 let unit = ResolvedType :: unit ( ) ;
723- let mut scope = Scope :: default ( ) ;
796+ let mut scope = Scope :: new ( Arc :: from ( from . resolutions ( ) ) , Arc :: from ( from . paths ( ) ) ) ;
724797 let items = from
725798 . items ( )
726799 . iter ( )
@@ -746,103 +819,37 @@ impl Program {
746819}
747820
748821impl AbstractSyntaxTree for Item {
749- type From = parse :: Item ;
822+ type From = driver :: Item ;
750823
751824 fn analyze ( from : & Self :: From , ty : & ResolvedType , scope : & mut Scope ) -> Result < Self , RichError > {
752825 assert ! ( ty. is_unit( ) , "Items cannot return anything" ) ;
753826 assert ! ( scope. is_topmost( ) , "Items live in the topmost scope only" ) ;
754827
755828 match from {
756- parse :: Item :: TypeAlias ( alias) => {
829+ driver :: Item :: TypeAlias ( alias) => {
757830 scope
758831 . insert_alias ( alias. name ( ) . clone ( ) , alias. ty ( ) . clone ( ) )
759832 . with_span ( alias) ?;
760833 Ok ( Self :: TypeAlias )
761834 }
762- parse :: Item :: Function ( function) => {
835+ driver :: Item :: Function ( function) => {
763836 Function :: analyze ( function, ty, scope) . map ( Self :: Function )
764837 }
765- parse:: Item :: Use ( _) => {
766- println ! ( "WARN: Skipping use declaration (not implemented yet)" ) ;
767- Ok ( Self :: Module )
768- //todo!()
769- //Use::analyze(use_declaration).map(Self::Use)
770- }
771- parse:: Item :: Module => Ok ( Self :: Module ) ,
838+ driver:: Item :: Module => Ok ( Self :: Module ) ,
772839 }
773840 }
774841}
775842
776843impl AbstractSyntaxTree for Function {
777- type From = parse:: Function ;
778-
779- fn analyze ( from : & Self :: From , ty : & ResolvedType , scope : & mut Scope ) -> Result < Self , RichError > {
780- assert ! ( ty. is_unit( ) , "Function definitions cannot return anything" ) ;
781- assert ! ( scope. is_topmost( ) , "Items live in the topmost scope only" ) ;
782-
783- if from. name ( ) . as_inner ( ) != "main" {
784- let visibility = from. visibility ( ) . clone ( ) ;
785- let params = from
786- . params ( )
787- . iter ( )
788- . map ( |param| {
789- let identifier = param. identifier ( ) . clone ( ) ;
790- let ty = scope. resolve ( param. ty ( ) ) ?;
791- Ok ( FunctionParam { identifier, ty } )
792- } )
793- . collect :: < Result < Arc < [ FunctionParam ] > , Error > > ( )
794- . with_span ( from) ?;
795- let ret = from
796- . ret ( )
797- . as_ref ( )
798- . map ( |aliased| scope. resolve ( aliased) . with_span ( from) )
799- . transpose ( ) ?
800- . unwrap_or_else ( ResolvedType :: unit) ;
801- scope. push_scope ( ) ;
802- for param in params. iter ( ) {
803- scope. insert_variable ( param. identifier ( ) . clone ( ) , param. ty ( ) . clone ( ) ) ;
804- }
805- let body = Expression :: analyze ( from. body ( ) , & ret, scope) . map ( Arc :: new) ?;
806- scope. pop_scope ( ) ;
807- debug_assert ! ( scope. is_topmost( ) ) ;
808- let function = CustomFunction {
809- visibility,
810- params,
811- body,
812- } ;
813- scope
814- . insert_function ( from. name ( ) . clone ( ) , function)
815- . with_span ( from) ?;
816-
817- return Ok ( Self :: Custom ) ;
818- }
819-
820- if !from. params ( ) . is_empty ( ) {
821- return Err ( Error :: MainNoInputs ) . with_span ( from) ;
822- }
823- if let Some ( aliased) = from. ret ( ) {
824- let resolved = scope. resolve ( aliased) . with_span ( from) ?;
825- if !resolved. is_unit ( ) {
826- return Err ( Error :: MainNoOutput ) . with_span ( from) ;
827- }
828- }
829-
830- scope. push_main_scope ( ) ;
831- let body = Expression :: analyze ( from. body ( ) , ty, scope) ?;
832- scope. pop_main_scope ( ) ;
833- Ok ( Self :: Main ( body) )
834- }
835- }
836-
837- /*
838- impl AbstractSyntaxTree for UseDecl {
839- type From = parse::UseDecl;
844+ type From = driver:: Function ;
840845
841846 fn analyze ( from : & Self :: From , ty : & ResolvedType , scope : & mut Scope ) -> Result < Self , RichError > {
842847 assert ! ( ty. is_unit( ) , "Function definitions cannot return anything" ) ;
843848 assert ! ( scope. is_topmost( ) , "Items live in the topmost scope only" ) ;
849+ let previous_file_id = scope. file_id ( ) ;
844850
845851 if from. name ( ) . as_inner ( ) != "main" {
852+ let file_id = from. file_id ( ) ;
846853 let params = from
847854 . params ( )
848855 . iter ( )
@@ -859,12 +866,12 @@ impl AbstractSyntaxTree for UseDecl {
859866 . map ( |aliased| scope. resolve ( aliased) . with_span ( from) )
860867 . transpose ( ) ?
861868 . unwrap_or_else ( ResolvedType :: unit) ;
862- scope.push_scope( );
869+ scope. push_function_scope ( file_id ) ;
863870 for param in params. iter ( ) {
864871 scope. insert_variable ( param. identifier ( ) . clone ( ) , param. ty ( ) . clone ( ) ) ;
865872 }
866873 let body = Expression :: analyze ( from. body ( ) , & ret, scope) . map ( Arc :: new) ?;
867- scope.pop_scope( );
874+ scope. pop_function_scope ( previous_file_id ) ;
868875 debug_assert ! ( scope. is_topmost( ) ) ;
869876 let function = CustomFunction { params, body } ;
870877 scope
@@ -890,7 +897,6 @@ impl AbstractSyntaxTree for UseDecl {
890897 Ok ( Self :: Main ( body) )
891898 }
892899}
893- */
894900
895901impl AbstractSyntaxTree for Statement {
896902 type From = parse:: Statement ;
@@ -1361,6 +1367,8 @@ impl AbstractSyntaxTree for CallName {
13611367 _ty : & ResolvedType ,
13621368 scope : & mut Scope ,
13631369 ) -> Result < Self , RichError > {
1370+ println ! ( "_ty: {:#?}" , _ty) ;
1371+ println ! ( "Scope: {:#?}" , scope) ;
13641372 match from. name ( ) {
13651373 parse:: CallName :: Jet ( name) => match Elements :: from_str ( name. as_inner ( ) ) {
13661374 Ok ( Elements :: CheckSigVerify | Elements :: Verify ) | Err ( _) => {
@@ -1390,13 +1398,11 @@ impl AbstractSyntaxTree for CallName {
13901398 . get_function ( name)
13911399 . cloned ( )
13921400 . map ( Self :: Custom )
1393- . ok_or ( Error :: FunctionUndefined ( name. clone ( ) ) )
13941401 . with_span ( from) ,
13951402 parse:: CallName :: ArrayFold ( name, size) => {
13961403 let function = scope
13971404 . get_function ( name)
13981405 . cloned ( )
1399- . ok_or ( Error :: FunctionUndefined ( name. clone ( ) ) )
14001406 . with_span ( from) ?;
14011407 // A function that is used in a array fold has the signature:
14021408 // fn f(element: E, accumulator: A) -> A
@@ -1411,7 +1417,6 @@ impl AbstractSyntaxTree for CallName {
14111417 let function = scope
14121418 . get_function ( name)
14131419 . cloned ( )
1414- . ok_or ( Error :: FunctionUndefined ( name. clone ( ) ) )
14151420 . with_span ( from) ?;
14161421 // A function that is used in a list fold has the signature:
14171422 // fn f(element: E, accumulator: A) -> A
@@ -1426,7 +1431,6 @@ impl AbstractSyntaxTree for CallName {
14261431 let function = scope
14271432 . get_function ( name)
14281433 . cloned ( )
1429- . ok_or ( Error :: FunctionUndefined ( name. clone ( ) ) )
14301434 . with_span ( from) ?;
14311435 // A function that is used in a for-while loop has the signature:
14321436 // fn f(accumulator: A, readonly_context: C, counter: u{N}) -> Either<B, A>
@@ -1503,6 +1507,9 @@ fn analyze_named_module(
15031507 from : & parse:: ModuleProgram ,
15041508) -> Result < HashMap < WitnessName , Value > , RichError > {
15051509 let unit = ResolvedType :: unit ( ) ;
1510+
1511+ // IMPORTANT! If modules allow imports, then we need to consider
1512+ // passing the resolution conetxt by calling `Scope::new(resolutions)`
15061513 let mut scope = Scope :: default ( ) ;
15071514 let items = from
15081515 . items ( )
0 commit comments