@@ -526,25 +526,8 @@ private function MustacheStatement(MustacheStatement $mustache): string
526526 $ type = $ this ->classifySexpr ($ helperName , $ mustache ->params , $ mustache ->hash );
527527
528528 if ($ type === SexprType::Helper) {
529- if ($ helperName !== null ) {
530- $ call = $ this ->buildInlineHelperCall ($ helperName , $ mustache ->params , $ mustache ->hash );
531- return self ::getRuntimeFunc ($ fn , $ call );
532- }
533- // Complex PathExpression with params: route through resolveHelper+hbch so helperMissing fires,
534- // or dv() for data/depth/scoped paths where helper dispatch does not apply.
535- if ($ path instanceof PathExpression) {
536- $ varPath = $ this ->PathExpression ($ path );
537- $ stringParts = array_filter ($ path ->parts , 'is_string ' );
538- if (!$ path ->data && $ path ->depth === 0 && !self ::scopedId ($ path )
539- && count ($ stringParts ) === count ($ path ->parts )) {
540- $ logicalName = self ::quote (implode ('. ' , $ stringParts ));
541- $ compiledParams = $ this ->compileParams ($ mustache ->params , $ mustache ->hash );
542- return self ::getRuntimeFunc ($ fn , $ this ->buildResolvedHbchCall ($ logicalName , $ varPath , $ compiledParams ));
543- }
544- $ args = array_map (fn ($ p ) => $ this ->compileExpression ($ p ), $ mustache ->params );
545- $ call = self ::getRuntimeFunc ('dv ' , "$ varPath, " . implode (', ' , $ args ));
546- return self ::getRuntimeFunc ($ fn , $ call );
547- }
529+ $ call = $ this ->compileHelperCall ($ helperName , $ path , $ mustache ->params , $ mustache ->hash );
530+ return self ::getRuntimeFunc ($ fn , $ call );
548531 }
549532
550533 if ($ helperName !== null && $ type === SexprType::Ambiguous && !$ this ->context ->options ->strict ) {
@@ -584,17 +567,7 @@ private function SubExpression(SubExpression $expression): string
584567 ? $ this ->getSimpleHelperName ($ path )
585568 : null ;
586569
587- if ($ helperName === null ) {
588- // Dynamic callable: path rooted at a sub-expression, e.g. ((helper).prop args)
589- if ($ path instanceof PathExpression) {
590- $ varPath = $ this ->PathExpression ($ path );
591- $ args = array_map (fn ($ p ) => $ this ->compileExpression ($ p ), $ expression ->params );
592- return self ::getRuntimeFunc ('dv ' , implode (', ' , [$ varPath , ...$ args ]));
593- }
594- throw new \Exception ('Sub-expression must be a helper call ' );
595- }
596-
597- return $ this ->buildInlineHelperCall ($ helperName , $ expression ->params , $ expression ->hash );
570+ return $ this ->compileHelperCall ($ helperName , $ path , $ expression ->params , $ expression ->hash );
598571 }
599572
600573 private function PathExpression (PathExpression $ expression ): string
@@ -902,6 +875,37 @@ private function buildResolvedHbchCall(string $escapedName, string $varPath, str
902875 return self ::getRuntimeFunc ('hbch ' , "\$cx, $ resolved, $ escapedName, $ params, \$in " );
903876 }
904877
878+ /**
879+ * Compile a helper call for a MustacheStatement (Helper type) or SubExpression.
880+ * @param Expression[] $params
881+ */
882+ private function compileHelperCall (?string $ helperName , Expression $ path , array $ params , ?Hash $ hash ): string
883+ {
884+ if ($ helperName !== null ) {
885+ $ compiledParams = $ this ->compileParams ($ params , $ hash );
886+ $ escapedName = self ::quote ($ helperName );
887+ if ($ this ->isKnownHelper ($ helperName )) {
888+ return self ::getRuntimeFunc ('hbch ' , "\$cx, \$cx->helpers[ $ escapedName], $ escapedName, $ compiledParams, \$in " );
889+ }
890+ if ($ this ->context ->options ->knownHelpersOnly ) {
891+ $ this ->throwKnownHelpersOnly ($ helperName );
892+ }
893+ return $ this ->buildResolvedHbchCall ($ escapedName , "\$in[ $ escapedName] ?? null " , $ compiledParams );
894+ }
895+ if ($ path instanceof PathExpression) {
896+ $ varPath = $ this ->PathExpression ($ path );
897+ $ stringParts = array_filter ($ path ->parts , 'is_string ' );
898+ if (!$ path ->data && $ path ->depth === 0 && !self ::scopedId ($ path )
899+ && count ($ stringParts ) === count ($ path ->parts )) {
900+ $ logicalName = self ::quote (implode ('. ' , $ stringParts ));
901+ return $ this ->buildResolvedHbchCall ($ logicalName , $ varPath , $ this ->compileParams ($ params , $ hash ));
902+ }
903+ $ args = array_map (fn ($ p ) => $ this ->compileExpression ($ p ), $ params );
904+ return self ::getRuntimeFunc ('dv ' , implode (', ' , [$ varPath , ...$ args ]));
905+ }
906+ throw new \Exception ('Sub-expression must be a helper call ' );
907+ }
908+
905909 /**
906910 * Build runtime function call.
907911 */
@@ -964,21 +968,4 @@ private function throwKnownHelpersOnly(string $helperName): never
964968 {
965969 throw new \Exception ("You specified knownHelpersOnly, but used the unknown helper $ helperName " );
966970 }
967-
968- /**
969- * Build an hbch inline helper call string.
970- * @param Expression[] $params
971- */
972- private function buildInlineHelperCall (string $ name , array $ params , ?Hash $ hash ): string
973- {
974- $ compiledParams = $ this ->compileParams ($ params , $ hash );
975- $ helperName = self ::quote ($ name );
976- if ($ this ->isKnownHelper ($ name )) {
977- return self ::getRuntimeFunc ('hbch ' , "\$cx, \$cx->helpers[ $ helperName], $ helperName, $ compiledParams, \$in " );
978- }
979- if ($ this ->context ->options ->knownHelpersOnly ) {
980- $ this ->throwKnownHelpersOnly ($ name );
981- }
982- return $ this ->buildResolvedHbchCall ($ helperName , "\$in[ $ helperName] ?? null " , $ compiledParams );
983- }
984971}
0 commit comments