@@ -7,19 +7,24 @@ use acvm::{AcirField, FieldElement};
77use builtin_helpers:: {
88 check_argument_count, check_one_argument, check_three_arguments, check_two_arguments,
99 get_function_def, get_module, get_quoted, get_slice, get_trait_constraint, get_trait_def,
10- get_type, get_u32, hir_pattern_to_tokens,
10+ get_tuple , get_type, get_u32, hir_pattern_to_tokens,
1111} ;
1212use chumsky:: Parser ;
1313use iter_extended:: { try_vecmap, vecmap} ;
1414use noirc_errors:: Location ;
1515use rustc_hash:: FxHashMap as HashMap ;
1616
1717use crate :: {
18- ast:: IntegerBitSize ,
18+ ast:: {
19+ FunctionKind , FunctionReturnType , IntegerBitSize , UnresolvedType , UnresolvedTypeData ,
20+ Visibility ,
21+ } ,
1922 hir:: comptime:: { errors:: IResult , value:: add_token_spans, InterpreterError , Value } ,
23+ hir_def:: function:: FunctionBody ,
2024 macros_api:: { ModuleDefId , NodeInterner , Signedness } ,
25+ node_interner:: DefinitionKind ,
2126 parser,
22- token:: Token ,
27+ token:: { SpannedToken , Token } ,
2328 QuotedType , Shared , Type ,
2429} ;
2530
@@ -43,6 +48,11 @@ impl<'local, 'context> Interpreter<'local, 'context> {
4348 "function_def_name" => function_def_name ( interner, arguments, location) ,
4449 "function_def_parameters" => function_def_parameters ( interner, arguments, location) ,
4550 "function_def_return_type" => function_def_return_type ( interner, arguments, location) ,
51+ "function_def_set_body" => function_def_set_body ( self , arguments, location) ,
52+ "function_def_set_parameters" => function_def_set_parameters ( self , arguments, location) ,
53+ "function_def_set_return_type" => {
54+ function_def_set_return_type ( self , arguments, location)
55+ }
4656 "module_functions" => module_functions ( self , arguments, location) ,
4757 "module_is_contract" => module_is_contract ( self , arguments, location) ,
4858 "module_name" => module_name ( interner, arguments, location) ,
@@ -737,6 +747,176 @@ fn function_def_return_type(
737747 Ok ( Value :: Type ( func_meta. return_type ( ) . follow_bindings ( ) ) )
738748}
739749
750+ // fn set_body(self, body: Quoted)
751+ fn function_def_set_body (
752+ interpreter : & mut Interpreter ,
753+ arguments : Vec < ( Value , Location ) > ,
754+ location : Location ,
755+ ) -> IResult < Value > {
756+ let ( self_argument, body_argument) = check_two_arguments ( arguments, location) ?;
757+ let func_id = get_function_def ( self_argument, location) ?;
758+
759+ let func_meta = interpreter. elaborator . interner . function_meta ( & func_id) ;
760+ match func_meta. function_body {
761+ FunctionBody :: Unresolved ( _, _, _) => ( ) ,
762+ FunctionBody :: Resolving | FunctionBody :: Resolved => {
763+ return Err ( InterpreterError :: CannotMutateFunction { location } )
764+ }
765+ }
766+
767+ let body_tokens = get_quoted ( body_argument, location) ?;
768+ let mut body_quoted = add_token_spans ( body_tokens. clone ( ) , location. span ) ;
769+
770+ // Surround the body in `{ ... }` so we can parse it as a block
771+ body_quoted. 0 . insert ( 0 , SpannedToken :: new ( Token :: LeftBrace , location. span ) ) ;
772+ body_quoted. 0 . push ( SpannedToken :: new ( Token :: RightBrace , location. span ) ) ;
773+
774+ let body =
775+ parser:: block ( parser:: fresh_statement ( ) ) . parse ( body_quoted) . map_err ( |mut errors| {
776+ let error = errors. swap_remove ( 0 ) ;
777+ let rule = "a block" ;
778+ InterpreterError :: FailedToParseMacro {
779+ error,
780+ tokens : body_tokens,
781+ rule,
782+ file : location. file ,
783+ }
784+ } ) ?;
785+
786+ let func_meta = interpreter. elaborator . interner . function_meta_mut ( & func_id) ;
787+ func_meta. has_body = true ;
788+ func_meta. function_body = FunctionBody :: Unresolved ( FunctionKind :: Normal , body, location. span ) ;
789+
790+ Ok ( Value :: Unit )
791+ }
792+
793+ // fn set_parameters(self, parameters: [(Quoted, Type)])
794+ fn function_def_set_parameters (
795+ interpreter : & mut Interpreter ,
796+ arguments : Vec < ( Value , Location ) > ,
797+ location : Location ,
798+ ) -> IResult < Value > {
799+ let ( self_argument, parameters_argument) = check_two_arguments ( arguments, location) ?;
800+
801+ let func_id = get_function_def ( self_argument, location) ?;
802+ let func_meta = interpreter. elaborator . interner . function_meta ( & func_id) ;
803+ match func_meta. function_body {
804+ FunctionBody :: Unresolved ( _, _, _) => ( ) ,
805+ FunctionBody :: Resolving | FunctionBody :: Resolved => {
806+ return Err ( InterpreterError :: CannotMutateFunction { location } )
807+ }
808+ }
809+
810+ let ( input_parameters, _type) =
811+ get_slice ( interpreter. elaborator . interner , parameters_argument, location) ?;
812+
813+ // What follows is very similar to what happens in Elaborator::define_function_meta
814+ let mut parameters = Vec :: new ( ) ;
815+ let mut parameter_types = Vec :: new ( ) ;
816+ let mut parameter_idents = Vec :: new ( ) ;
817+
818+ for input_parameter in input_parameters {
819+ let mut tuple = get_tuple ( interpreter. elaborator . interner , input_parameter, location) ?;
820+ let parameter_type = get_type ( tuple. pop ( ) . unwrap ( ) , location) ?;
821+ let parameter_name_tokens = get_quoted ( tuple. pop ( ) . unwrap ( ) , location) ?;
822+ let parameter_name_quoted = add_token_spans ( parameter_name_tokens. clone ( ) , location. span ) ;
823+ let parameter_pattern =
824+ parser:: pattern ( ) . parse ( parameter_name_quoted) . map_err ( |mut errors| {
825+ let error = errors. swap_remove ( 0 ) ;
826+ let rule = "a pattern" ;
827+ InterpreterError :: FailedToParseMacro {
828+ error,
829+ tokens : parameter_name_tokens,
830+ rule,
831+ file : location. file ,
832+ }
833+ } ) ?;
834+
835+ let hir_pattern = interpreter. elaborate_item ( interpreter. current_function , |elaborator| {
836+ elaborator. elaborate_pattern_and_store_ids (
837+ parameter_pattern,
838+ parameter_type. clone ( ) ,
839+ DefinitionKind :: Local ( None ) ,
840+ & mut parameter_idents,
841+ None ,
842+ )
843+ } ) ;
844+
845+ parameters. push ( ( hir_pattern, parameter_type. clone ( ) , Visibility :: Private ) ) ;
846+ parameter_types. push ( parameter_type) ;
847+ }
848+
849+ let func_meta = interpreter. elaborator . interner . function_meta ( & func_id) ;
850+ let function_type = Type :: Function (
851+ parameter_types,
852+ Box :: new ( func_meta. return_type ( ) . clone ( ) ) ,
853+ Box :: new ( Type :: Unit ) ,
854+ ) ;
855+
856+ // TODO: generics. In Elaborator::define_function_meta there's this code:
857+ //
858+ // if !generics.is_empty() {
859+ // typ = Type::Forall(generics, Box::new(typ));
860+ // }
861+
862+ interpreter. elaborator . interner . push_definition_type ( func_meta. name . id , function_type. clone ( ) ) ;
863+
864+ {
865+ let func_meta = interpreter. elaborator . interner . function_meta_mut ( & func_id) ;
866+ func_meta. parameters = parameters. into ( ) ;
867+ func_meta. parameter_idents = parameter_idents;
868+ func_meta. typ = function_type;
869+ }
870+
871+ Ok ( Value :: Unit )
872+ }
873+
874+ // fn set_return_type(self, return_type: Type)
875+ fn function_def_set_return_type (
876+ interpreter : & mut Interpreter ,
877+ arguments : Vec < ( Value , Location ) > ,
878+ location : Location ,
879+ ) -> IResult < Value > {
880+ let ( self_argument, return_type_argument) = check_two_arguments ( arguments, location) ?;
881+ let return_type = get_type ( return_type_argument, location) ?;
882+
883+ let func_id = get_function_def ( self_argument, location) ?;
884+ let func_meta = interpreter. elaborator . interner . function_meta ( & func_id) ;
885+ match func_meta. function_body {
886+ FunctionBody :: Unresolved ( _, _, _) => ( ) ,
887+ FunctionBody :: Resolving | FunctionBody :: Resolved => {
888+ return Err ( InterpreterError :: CannotMutateFunction { location } )
889+ }
890+ }
891+
892+ let parameter_types = func_meta. parameters . iter ( ) . map ( |( _, typ, _) | typ. clone ( ) ) . collect ( ) ;
893+
894+ let func_meta = interpreter. elaborator . interner . function_meta ( & func_id) ;
895+ let function_type =
896+ Type :: Function ( parameter_types, Box :: new ( return_type. clone ( ) ) , Box :: new ( Type :: Unit ) ) ;
897+
898+ // TODO: generics. In Elaborator::define_function_meta there's this code:
899+ //
900+ // if !generics.is_empty() {
901+ // typ = Type::Forall(generics, Box::new(typ));
902+ // }
903+
904+ interpreter. elaborator . interner . push_definition_type ( func_meta. name . id , function_type. clone ( ) ) ;
905+
906+ let quoted_type_id = interpreter. elaborator . interner . push_quoted_type ( return_type) ;
907+
908+ {
909+ let func_meta = interpreter. elaborator . interner . function_meta_mut ( & func_id) ;
910+ func_meta. return_type = FunctionReturnType :: Ty ( UnresolvedType {
911+ typ : UnresolvedTypeData :: Resolved ( quoted_type_id) ,
912+ span : Some ( location. span ) ,
913+ } ) ;
914+ func_meta. typ = function_type;
915+ }
916+
917+ Ok ( Value :: Unit )
918+ }
919+
740920// fn functions(self) -> [FunctionDefinition]
741921fn module_functions (
742922 interpreter : & Interpreter ,
0 commit comments