@@ -953,30 +953,81 @@ fn build_listlike_cost_analysis_tree(
953953 children. push ( child_tree) ;
954954 }
955955
956- let function_name = get_function_name ( & exprs[ 0 ] ) ?;
957- // Try to lookup the function as a native function first
958- let ( expr_node, cost) = if let Some ( native_function) =
959- NativeFunctions :: lookup_by_name_at_version ( function_name. as_str ( ) , clarity_version)
960- {
961- CostExprNode :: NativeFunction ( native_function) ;
962- let cost = calculate_function_cost_from_native_function (
963- native_function,
964- children. len ( ) as u64 ,
965- clarity_version,
966- ) ?;
967- ( CostExprNode :: NativeFunction ( native_function) , cost)
968- } else {
969- // If not a native function, treat as user-defined function and look it up
970- let expr_node = CostExprNode :: UserFunction ( function_name. clone ( ) ) ;
971- let cost = calculate_function_cost ( function_name. to_string ( ) , cost_map, clarity_version) ?;
972- ( expr_node, cost)
956+ // Try to get function name from first element
957+ let ( expr_node, cost, function_name_opt) = match get_function_name ( & exprs[ 0 ] ) {
958+ Ok ( function_name) => {
959+ // Try to lookup the function as a native function first
960+ if let Some ( native_function) =
961+ NativeFunctions :: lookup_by_name_at_version ( function_name. as_str ( ) , clarity_version)
962+ {
963+ let cost = calculate_function_cost_from_native_function (
964+ native_function,
965+ children. len ( ) as u64 ,
966+ clarity_version,
967+ ) ?;
968+ (
969+ CostExprNode :: NativeFunction ( native_function) ,
970+ cost,
971+ Some ( function_name) ,
972+ )
973+ } else {
974+ // If not a native function, treat as user-defined function and look it up
975+ let expr_node = CostExprNode :: UserFunction ( function_name. clone ( ) ) ;
976+ let cost =
977+ calculate_function_cost ( function_name. to_string ( ) , cost_map, clarity_version) ?;
978+ ( expr_node, cost, Some ( function_name) )
979+ }
980+ }
981+ Err ( _) => {
982+ // First element is not an atom - it might be a List that needs to be recursively analyzed
983+ match & exprs[ 0 ] . expr {
984+ SymbolicExpressionType :: List ( _) => {
985+ // Recursively analyze the nested list structure
986+ let ( _, nested_tree) =
987+ build_cost_analysis_tree ( & exprs[ 0 ] , user_args, cost_map, clarity_version) ?;
988+ // Add the nested tree as a child (its cost will be included when summing children)
989+ children. insert ( 0 , nested_tree) ;
990+ // The root cost is zero - the actual cost comes from the nested expression
991+ let expr_node = CostExprNode :: Atom ( ClarityName :: from ( "nested-expression" ) ) ;
992+ ( expr_node, StaticCost :: ZERO , None )
993+ }
994+ SymbolicExpressionType :: Atom ( name) => {
995+ // It's an atom but not a function name - treat as atom with zero cost
996+ ( CostExprNode :: Atom ( name. clone ( ) ) , StaticCost :: ZERO , None )
997+ }
998+ SymbolicExpressionType :: AtomValue ( value) => {
999+ // It's an atom value - calculate its cost
1000+ let cost = calculate_value_cost ( value) ?;
1001+ ( CostExprNode :: AtomValue ( value. clone ( ) ) , cost, None )
1002+ }
1003+ SymbolicExpressionType :: TraitReference ( trait_name, _trait_definition) => (
1004+ CostExprNode :: TraitReference ( trait_name. clone ( ) ) ,
1005+ StaticCost :: ZERO ,
1006+ None ,
1007+ ) ,
1008+ SymbolicExpressionType :: Field ( field_identifier) => (
1009+ CostExprNode :: FieldIdentifier ( field_identifier. clone ( ) ) ,
1010+ StaticCost :: ZERO ,
1011+ None ,
1012+ ) ,
1013+ SymbolicExpressionType :: LiteralValue ( value) => {
1014+ let cost = calculate_value_cost ( value) ?;
1015+ // TODO not sure if LiteralValue is needed in the CostExprNode types
1016+ ( CostExprNode :: AtomValue ( value. clone ( ) ) , cost, None )
1017+ }
1018+ }
1019+ }
9731020 } ;
9741021
9751022 // Handle special cases for string arguments to functions that include their processing cost
976- if FUNCTIONS_WITH_ZERO_STRING_ARG_COST . contains ( & function_name. as_str ( ) ) {
977- for child in & mut children {
978- if let CostExprNode :: AtomValue ( Value :: Sequence ( SequenceData :: String ( _) ) ) = & child. expr {
979- child. cost = StaticCost :: ZERO ;
1023+ if let Some ( function_name) = & function_name_opt {
1024+ if FUNCTIONS_WITH_ZERO_STRING_ARG_COST . contains ( & function_name. as_str ( ) ) {
1025+ for child in & mut children {
1026+ if let CostExprNode :: AtomValue ( Value :: Sequence ( SequenceData :: String ( _) ) ) =
1027+ & child. expr
1028+ {
1029+ child. cost = StaticCost :: ZERO ;
1030+ }
9801031 }
9811032 }
9821033 }
0 commit comments