Files
frankenphp/internal/extgen/phpfunc.go
Kévin Dunglas abfd893d88 feat: FrankenPHP extensions (#1651)
* feat: add helpers to create PHP extensions (#1644)

* feat: add helpers to create PHP extensions

* cs

* feat: GoString

* test

* add test for RegisterExtension

* cs

* optimize includes

* fix

* feat(extensions): add the PHP extension generator (#1649)

* feat(extensions): add the PHP extension generator

* unexport many types

* unexport more symbols

* cleanup some tests

* unexport more symbols

* fix

* revert types files

* revert

* add better validation and fix templates

* remove GoStringCopy

* small fixes

---------

Co-authored-by: Kévin Dunglas <kevin@dunglas.fr>

* try to fix tests

* fix CS

* try some workarounds

* try some workarounds

* ingore TestRegisterExtension

* exclude cgo tests in Docker images

* fix

* workaround...

* race detector

* simplify tests and code

* make linter happy

* feat(gofile): use templates to generate the Go file (#1666)

---------

Co-authored-by: Alexandre Daubois <2144837+alexandre-daubois@users.noreply.github.com>
2025-06-25 10:18:22 +02:00

83 lines
1.8 KiB
Go

package extgen
import (
"fmt"
"strings"
)
type PHPFuncGenerator struct {
paramParser *ParameterParser
}
func (pfg *PHPFuncGenerator) generate(fn phpFunction) string {
var builder strings.Builder
paramInfo := pfg.paramParser.analyzeParameters(fn.Params)
builder.WriteString(fmt.Sprintf("PHP_FUNCTION(%s)\n{\n", fn.Name))
if decl := pfg.paramParser.generateParamDeclarations(fn.Params); decl != "" {
builder.WriteString(decl + "\n")
}
builder.WriteString(pfg.paramParser.generateParamParsing(fn.Params, paramInfo.RequiredCount) + "\n")
builder.WriteString(pfg.generateGoCall(fn) + "\n")
if returnCode := pfg.generateReturnCode(fn.ReturnType); returnCode != "" {
builder.WriteString(returnCode + "\n")
}
builder.WriteString("}\n\n")
return builder.String()
}
func (pfg *PHPFuncGenerator) generateGoCall(fn phpFunction) string {
callParams := pfg.paramParser.generateGoCallParams(fn.Params)
if fn.ReturnType == "void" {
return fmt.Sprintf(" %s(%s);", fn.Name, callParams)
}
if fn.ReturnType == "string" {
return fmt.Sprintf(" zend_string *result = %s(%s);", fn.Name, callParams)
}
return fmt.Sprintf(" %s result = %s(%s);", pfg.getCReturnType(fn.ReturnType), fn.Name, callParams)
}
func (pfg *PHPFuncGenerator) getCReturnType(returnType string) string {
switch returnType {
case "string":
return "zend_string*"
case "int":
return "long"
case "float":
return "double"
case "bool":
return "int"
default:
return "void"
}
}
func (pfg *PHPFuncGenerator) generateReturnCode(returnType string) string {
switch returnType {
case "string":
return ` if (result) {
RETURN_STR(result);
} else {
RETURN_EMPTY_STRING();
}`
case "int":
return ` RETURN_LONG(result);`
case "float":
return ` RETURN_DOUBLE(result);`
case "bool":
return ` RETURN_BOOL(result);`
default:
return ""
}
}