Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP TL GEN: PART 2 #60

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/tlgen/main2.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ func parseFlags(opt *tlcodegen.Gen2Options) {
flag.StringVar(&opt.RootCPPNamespace, "cpp-namespace", "",
`c++ root namespace, separated by '::' if more than 1 element`)

// PHP
flag.BoolVar(&opt.AddFunctionBodies, "php-serialization-bodies", false,
`whether to generate body to write/read generated structs and functions`)

// .tlo
flag.StringVar(&opt.TLOPath, "tloPath", "",
"whether to serialize TL schema in binary form")
Expand Down
3 changes: 1 addition & 2 deletions internal/tlcodegen/helpers_php.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package tlcodegen
const BasicTlPathPhp = "basictl.php"
const BasicTLCodePHP = `
<?php
include "run.php";

class tl_constants {
const tinyStringLen = 253;
Expand Down Expand Up @@ -117,7 +116,7 @@ class tl_input_stream {
return ["", false];
}
$l64 = (ord($this->data[$this->offset + 7]) << 48) + (ord($this->data[$this->offset + 6]) << 40) + (ord($this->data[$this->offset + 5]) << 32) + (ord($this->data[$this->offset + 4]) << 24) + (ord($this->data[$this->offset + 3]) << 16) + (ord($this->data[$this->offset + 2]) << 8) + (ord($this->data[$this->offset + 1]) << 0);
// TODO: check l64 > maxint
// TODO: check l64 > max int
$l = $l64;
$this->offset += 8;
$p = $l;
Expand Down
3 changes: 3 additions & 0 deletions internal/tlcodegen/tlgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ type Gen2Options struct {
RootCPPNamespace string
SeparateFiles bool

// PHP
AddFunctionBodies bool

// .tlo
TLOPath string
CanonicalFormPath string // combinators in canonical form, with comment of source schema file path
Expand Down
4 changes: 4 additions & 0 deletions internal/tlcodegen/tlgen_kernel.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ func (gen *Gen2) getType(lrc LocalResolveContext, t tlast.TypeRef, unionParent *
func (gen *Gen2) generateType(myWrapper *TypeRWWrapper) error {
tlType := myWrapper.origTL

if tlType[0].Construct.Name.String() == "test.dataIgnoreFlags" {
print("debug")
}

lrc := LocalResolveContext{
localTypeArgs: map[string]LocalTypeArg{},
localNatArgs: map[string]LocalNatArg{},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ import (
"strings"
)

type TypeRWCPPData interface {
CPPFillRecursiveChildren(visitedNodes map[*TypeRWWrapper]bool)
cppTypeStringInNamespace(bytesVersion bool, hppInc *DirectIncludesCPP) string
cppTypeStringInNamespaceHalfResolved2(bytesVersion bool, typeReduction EvaluatedType) string
cppTypeStringInNamespaceHalfResolved(bytesVersion bool, hppInc *DirectIncludesCPP, halfResolved HalfResolvedArgument) string
cppDefaultInitializer(halfResolved HalfResolvedArgument, halfResolve bool) string
CPPHasBytesVersion() bool
CPPTypeResettingCode(bytesVersion bool, val string) string
CPPTypeWritingJsonCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string
CPPTypeWritingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string
CPPTypeReadingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string
CPPTypeJSONEmptyCondition(bytesVersion bool, val string, ref bool, deps []string) string
CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool)
}

func cppStartNamespace(s *strings.Builder, ns []string) {
for _, n := range ns {
s.WriteString(fmt.Sprintf("namespace %s { ", n))
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,31 @@
"strings"
)

type PhpClassMeta struct {
UsedOnlyInInternal bool
UsedInFunctions bool
}

const (
PHPFileStart = "<?php\n"
PHPRPCFunctionMock = "__RPC_FUNCTION_MOCK"
PHPRPCFunctionResultMock = "__RPC_FUNCTION_RESULT_MOCK"
PHPRPCResponseMock = "__RPC_RESPONSE_MOCK"
)

type TypeRWPHPData interface {
PhpClassName(withPath bool, bare bool) string
PhpClassNameReplaced() bool
PhpTypeName(withPath bool, bare bool) string
PhpGenerateCode(code *strings.Builder, bytes bool) error
// PhpDefaultInit return not null type initialization value
PhpDefaultInit() string
// PhpDefaultValue return default value for field of this type (can be null)
PhpDefaultValue() string
PhpIterateReachableTypes(reachableTypes *map[*TypeRWWrapper]bool)
PhpReadMethodCall(targetName string, bare bool, args []string) []string
}

type PhpClassMeta struct {
UsedOnlyInInternal bool
UsedInFunctions bool
}

func (gen *Gen2) generateCodePHP(generateByteVersions []string) error {
if err := gen.addCodeFile(BasicTlPathPhp, BasicTLCodePHP); err != nil {
return err
Expand All @@ -33,15 +46,20 @@
createdTypes := make(map[string]bool)

for _, wrapper := range gen.generatedTypesList {
if wrapper.trw.PhpClassName(false, true) == "logs2_dictionarySetInfo" {
print("debug")
}
if createdTypes[wrapper.trw.PhpClassName(true, true)] {
continue
}
if !wrapper.PHPNeedsCode() {
continue
}
fmt.Println(fmt.Sprintf(

Check failure on line 55 in internal/tlcodegen/tlgen_lang_php.go

View workflow job for this annotation

GitHub Actions / ci-go

should use fmt.Printf instead of fmt.Println(fmt.Sprintf(...)) (but don't forget the newline) (S1038)

Check failure on line 55 in internal/tlcodegen/tlgen_lang_php.go

View workflow job for this annotation

GitHub Actions / ci-go

should use fmt.Printf instead of fmt.Println(fmt.Sprintf(...)) (but don't forget the newline) (S1038)
"PHP{%[1]s} in GO{%[2]s}",
wrapper.trw.PhpClassName(false, true),
wrapper.goGlobalName,
wrapper.NatParams,
wrapper.origTL[0].TemplateArguments,
wrapper.arguments),
)
err := phpGenerateCodeForWrapper(gen, wrapper, createdTypes, true, wrapper.PHPGenerateCode)
if err != nil {
return err
Expand Down Expand Up @@ -159,3 +177,11 @@
}
return ""
}

func phpFormatArgs(args []string) string {
s := ""
for _, arg := range args {
s += ", " + arg
}
return s
}
102 changes: 80 additions & 22 deletions internal/tlcodegen/type_rw.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package tlcodegen

import (
"fmt"
"github.com/vkcom/tl/internal/utils"
"golang.org/x/exp/slices"
"regexp"
"strconv"
Expand Down Expand Up @@ -633,6 +634,84 @@ func (w *TypeRWWrapper) PHPNeedsCode() bool {
return !w.trw.PhpClassNameReplaced()
}

type TypeArgumentsTree struct {
value string
leaf bool
children []*TypeArgumentsTree
}

func (t *TypeArgumentsTree) IsEmpty() bool {
if t.leaf {
return false
}
for _, child := range t.children {
if child != nil && !child.IsEmpty() {
return false
}
}
return true
}

func (t *TypeArgumentsTree) EnumerateWithPrefixes() []string {
const natPrefix = ""
values := make([]string, 0)
t.enumerateWithPrefixes(&values, "")
values = utils.MapSlice(values, func(s string) string { return natPrefix + s })
return values
}

func (t *TypeArgumentsTree) EnumerateSubTreeWithPrefixes(childIndex int) []string {
if !(0 <= childIndex && childIndex < len(t.children)) {
panic("no such subtree")
}
ct := *t
ct.children = []*TypeArgumentsTree{t.children[childIndex]}
return ct.EnumerateWithPrefixes()
}

func (t *TypeArgumentsTree) enumerateWithPrefixes(values *[]string, curPrefix string) {
const delimiter = "_"
if t.leaf {
*values = append(*values, curPrefix)
} else {
for _, child := range t.children {
if child != nil {
prefix := curPrefix + child.value
if !child.leaf {
prefix += delimiter
}
child.enumerateWithPrefixes(values, prefix)
}
}
}
}

func (w *TypeRWWrapper) PHPGetNatTypeDependenciesDeclAsArray() []string {
t := TypeArgumentsTree{}
w.PHPGetNatTypeDependenciesDecl(&t)
return t.EnumerateWithPrefixes()
}

func (w *TypeRWWrapper) PHPGetNatTypeDependenciesDecl(tree *TypeArgumentsTree) {
for i, template := range w.origTL[0].TemplateArguments {
tree.children = append(tree.children, nil)
actualArg := w.arguments[i]
if template.IsNat {
tree.children[i] = &TypeArgumentsTree{}
tree.children[i].leaf = true
tree.children[i].value = template.FieldName
} else {
tree.children[i] = &TypeArgumentsTree{}
tree.children[i].leaf = false
tree.children[i].value = template.FieldName
actualArg.tip.PHPGetNatTypeDependenciesDecl(tree.children[i])
if tree.children[i].IsEmpty() {
tree.children[i] = nil
}
}
}
}

func (w *TypeRWWrapper) PhpIterateReachableTypes(reachableTypes *map[*TypeRWWrapper]bool) {
if (*reachableTypes)[w] {
return
Expand Down Expand Up @@ -877,15 +956,6 @@ outer:
return result
}

type TypeRWPHPData interface {
PhpClassName(withPath bool, bare bool) string
PhpClassNameReplaced() bool
PhpTypeName(withPath bool, bare bool) string
PhpGenerateCode(code *strings.Builder, bytes bool) error
PhpDefaultValue() string
PhpIterateReachableTypes(reachableTypes *map[*TypeRWWrapper]bool)
}

// TODO remove skipAlias after we start generating go code like we do for C++
type TypeRW interface {
// methods below are target language independent
Expand Down Expand Up @@ -918,19 +988,7 @@ type TypeRW interface {
typeJSON2ReadingCode(bytesVersion bool, directImports *DirectImports, ins *InternalNamespace, jvalue string, val string, natArgs []string, ref bool) string
GenerateCode(bytesVersion bool, directImports *DirectImports) string

CPPFillRecursiveChildren(visitedNodes map[*TypeRWWrapper]bool)
cppTypeStringInNamespace(bytesVersion bool, hppInc *DirectIncludesCPP) string
cppTypeStringInNamespaceHalfResolved2(bytesVersion bool, typeReduction EvaluatedType) string
cppTypeStringInNamespaceHalfResolved(bytesVersion bool, hppInc *DirectIncludesCPP, halfResolved HalfResolvedArgument) string
cppDefaultInitializer(halfResolved HalfResolvedArgument, halfResolve bool) string
CPPHasBytesVersion() bool
CPPTypeResettingCode(bytesVersion bool, val string) string
CPPTypeWritingJsonCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string
CPPTypeWritingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string
CPPTypeReadingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string
CPPTypeJSONEmptyCondition(bytesVersion bool, val string, ref bool, deps []string) string
CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool)

TypeRWCPPData
TypeRWPHPData
}

Expand Down
24 changes: 0 additions & 24 deletions internal/tlcodegen/type_rw_bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package tlcodegen

import (
"fmt"
"strings"
)

type TypeRWBool struct {
Expand Down Expand Up @@ -110,26 +109,3 @@ func (trw *TypeRWBool) typeJSONReadingCode(bytesVersion bool, directImports *Dir
func (trw *TypeRWBool) typeJSON2ReadingCode(bytesVersion bool, directImports *DirectImports, ins *InternalNamespace, jvalue string, val string, natArgs []string, ref bool) string {
return wrapLast(false, fmt.Sprintf("%sJson2ReadBool(%s, %s)", trw.wr.gen.InternalPrefix(), jvalue, addAmpersand(ref, val)))
}

func (trw *TypeRWBool) PhpClassName(withPath bool, bare bool) string {
return "boolean"
}

func (trw *TypeRWBool) PhpClassNameReplaced() bool {
return true
}

func (trw *TypeRWBool) PhpTypeName(withPath bool, bare bool) string {
return trw.PhpClassName(withPath, true)
}

func (trw *TypeRWBool) PhpGenerateCode(code *strings.Builder, bytes bool) error {
return fmt.Errorf("boolean doesn't have php code")
}

func (trw *TypeRWBool) PhpDefaultValue() string {
return "false"
}

func (trw *TypeRWBool) PhpIterateReachableTypes(reachableTypes *map[*TypeRWWrapper]bool) {
}
50 changes: 50 additions & 0 deletions internal/tlcodegen/type_rw_bool_php.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package tlcodegen

import (
"fmt"
"strings"
)

func (trw *TypeRWBool) PhpClassName(withPath bool, bare bool) string {
return "boolean"
}

func (trw *TypeRWBool) PhpClassNameReplaced() bool {
return true
}

func (trw *TypeRWBool) PhpTypeName(withPath bool, bare bool) string {
return trw.PhpClassName(withPath, true)
}

func (trw *TypeRWBool) PhpGenerateCode(code *strings.Builder, bytes bool) error {
return fmt.Errorf("boolean doesn't have php code")
}

func (trw *TypeRWBool) PhpDefaultValue() string {
return "false"
}

func (trw *TypeRWBool) PhpIterateReachableTypes(reachableTypes *map[*TypeRWWrapper]bool) {
}

func (trw *TypeRWBool) PhpReadMethodCall(targetName string, bare bool, args []string) []string {
if !bare {
return []string{
fmt.Sprintf(
"[%[1]s, $success] = $stream->read_bool(0x%08[2]x, 0x%08[3]x);",
targetName,
trw.falseTag,
trw.trueTag,
),
"if (!$success) {",
" return false;",
"}",
}
}
return nil
}

func (trw *TypeRWBool) PhpDefaultInit() string {
return "false"
}
Loading
Loading