From fa312ef9501147bff87a32a1fcd7f7d907a3647f Mon Sep 17 00:00:00 2001 From: Brat-vseznamus Date: Mon, 27 May 2024 15:39:59 +0300 Subject: [PATCH 01/10] change makefile tp cpp generation --- Makefile | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index c832572..5b94086 100644 --- a/Makefile +++ b/Makefile @@ -137,10 +137,11 @@ qtpl: fi # TODO: in progress... -#.PHONY: cpp -#cpp: build -# @./target/bin/tlgen -language=cpp -v \ -# --outdir=./test/cpp \ -# --basicPkgPath=gitlab.mvk.com/go/vkgo/pkg/basictl \ -# ./test/cpp.tl -# g++ -o test/test_cpp test/test_cpp.cpp test/cpp/all.cpp -std=c++17 -O3 -Wno-noexcept-type -g -Wall -Wextra -Werror=return-type -Wno-unused-parameter +.PHONY: cpp +cpp: build + @./target/bin/tlgen -language=cpp -v \ + --outdir=./$(GEN_PATH)/cpp \ + --generateRPCCode=false \ + --basicPkgPath=$(BASIC_TL_PATH) \ + ./$(TLS_PATH)/cpp.tl + g++ -o $(TEST_PATH)/test_cpp $(TEST_PATH)/test_cpp.cpp $(TEST_PATH)/gen/cpp/all.cpp -std=c++17 -O3 -Wno-noexcept-type -g -Wall -Wextra -Werror=return-type -Wno-unused-parameter From 6d07242ecc6c7307ab13d49c674548ef07cde498 Mon Sep 17 00:00:00 2001 From: Brat-vseznamus Date: Fri, 31 May 2024 11:51:59 +0300 Subject: [PATCH 02/10] my experiments with type reductions --- internal/tlcodegen/tlgen.go | 324 +++++++++++++++++++++++- internal/tlcodegen/tlgen_kernel.go | 2 + internal/tlcodegen/type_rw_tuple_cpp.go | 12 + 3 files changed, 335 insertions(+), 3 deletions(-) diff --git a/internal/tlcodegen/tlgen.go b/internal/tlcodegen/tlgen.go index 862f4ca..e005350 100644 --- a/internal/tlcodegen/tlgen.go +++ b/internal/tlcodegen/tlgen.go @@ -14,6 +14,7 @@ import ( "path/filepath" "runtime/debug" "sort" + "strconv" "strings" "sync/atomic" @@ -347,9 +348,10 @@ type Gen2 struct { // parsed TL supportedAnnotations map[string]int typeDescriptors map[string][]*tlast.Combinator - singleConstructors map[string]*tlast.Combinator // only types with 1 constructor, no functions - allConstructors map[string]*tlast.Combinator // for printing beautiful errors - allAnnotations []string // position is bit + + singleConstructors map[string]*tlast.Combinator // only types with 1 constructor, no functions + allConstructors map[string]*tlast.Combinator // for printing beautiful errors + allAnnotations []string // position is bit // generation builtinTypes map[string]*TypeRWWrapper @@ -1033,6 +1035,9 @@ func GenerateCode(tl tlast.TL, options Gen2Options) (*Gen2, error) { sort.Strings(gen.allAnnotations) } skippedDueToWhitelist := 0 + + processCombinators(gen.allConstructors) + for _, typ := range tl { if GenerateUnusedNatTemplates(typ.Construct.Name.String()) && len(typ.TemplateArguments) == 1 && typ.TemplateArguments[0].IsNat { t := tlast.TypeRef{Type: typ.TypeDecl.Name, PR: typ.TypeDecl.PR} @@ -1187,3 +1192,316 @@ func GenerateCode(tl tlast.TL, options Gen2Options) (*Gen2, error) { return gen, nil } + +type ConstructorName = tlast.Name +type Constructor struct { + Type *Type + Id uint + Name ConstructorName + Fields []tlast.Field +} + +type TypeName = tlast.Name + +type Type struct { + IsBasic bool + Name TypeName + TypeArguments []tlast.TemplateArgument + Constructors []*Constructor +} + +type EvaluatedTypeArgument struct { + Index int + + // union variants + Constant string // 0 + Variable string // 1 + TypeVariable string // 3 + Type *TypeReduction // 2 +} + +type TypeReduction struct { + IsType bool + + Type *Type + Constructor *Constructor + + Arguments []EvaluatedTypeArgument +} + +func (tr *TypeReduction) ReferenceName() (name tlast.Name) { + if tr.IsType { + name = tr.Type.Name + } else { + name = tr.Constructor.Name + } + return +} + +func (tr *TypeReduction) ReferenceType() *Type { + if tr.IsType { + return tr.Type + } + return tr.Constructor.Type +} + +func (tr *TypeReduction) String() string { + s := "" + if tr.Type != nil || tr.Constructor != nil { + s += tr.ReferenceName().String() + if len(tr.Arguments) != 0 { + s += "<" + for i, arg := range tr.Arguments { + switch arg.Index { + case 0: + s += "C" + arg.Constant + case 1: + s += "V" + case 2: + s += arg.Type.String() + case 3: + s += "TV" + } + if len(tr.Arguments) != i+1 { + s += "," + } + } + s += ">" + } + } + return s +} + +func processCombinators(types map[string]*tlast.Combinator) { + existingTypes := make(map[TypeName]*Type) + existingConstructors := make(map[ConstructorName]*Constructor) + + for _, comb := range types { + if comb.IsFunction { + continue + } + declaredType := comb.TypeDecl.Name + if comb.Builtin { + declaredType = comb.Construct.Name + } + currentConstructor := comb.Construct.Name + if _, presented := existingTypes[declaredType]; !presented { + existingTypes[declaredType] = &Type{ + IsBasic: comb.Builtin, + Name: declaredType, + Constructors: []*Constructor{}, + TypeArguments: comb.TemplateArguments, + } + } + targetType := existingTypes[declaredType] + constrId := len(targetType.Constructors) + constructor := Constructor{ + Name: currentConstructor, + Fields: comb.Fields, + Id: uint(constrId), + Type: targetType, + } + targetType.Constructors = append(targetType.Constructors, &constructor) + existingConstructors[currentConstructor] = &constructor + } + + typeReductions := make(map[*Type]*map[*TypeReduction]bool) + + for _, comb := range existingTypes { + if len(comb.TypeArguments) != 0 { + continue + } + reduce( + TypeReduction{ + IsType: true, + Type: existingTypes[comb.Name], + }, + &typeReductions, + &existingTypes, + &existingConstructors, + ) + } + + for tp, rds := range typeReductions { + fmt.Println(tp.Name.String()) + for rd, _ := range *rds { + fmt.Println("\t", rd.String()) + } + } +} + +func reduce( + targetTypeReduction TypeReduction, + visitedReductions *map[*Type]*map[*TypeReduction]bool, + types *map[TypeName]*Type, + constructors *map[ConstructorName]*Constructor, +) { + for _, arg := range targetTypeReduction.Arguments { + if arg.Index == 2 { + reduce(*arg.Type, visitedReductions, types, constructors) + } + } + + trs, ok := (*visitedReductions)[targetTypeReduction.ReferenceType()] + if !ok { + tmp := make(map[*TypeReduction]bool) + (*visitedReductions)[targetTypeReduction.ReferenceType()] = &tmp + trs = &tmp + } + + _, ok = (*trs)[&targetTypeReduction] + if !ok { + (*trs)[&targetTypeReduction] = true + } else { + return + } + + if targetTypeReduction.ReferenceType().IsBasic { + return + } + + var visitingConstructors []*Constructor + + if targetTypeReduction.IsType { + visitingConstructors = targetTypeReduction.Type.Constructors + } else { + visitingConstructors = append(visitingConstructors, targetTypeReduction.Constructor) + } + + for _, constr := range visitingConstructors { + reduceConstructor( + constr, + targetTypeReduction.Arguments, + visitedReductions, + types, + constructors, + ) + } +} + +func reduceConstructor( + constructor *Constructor, + args []EvaluatedTypeArgument, + visitedReductions *map[*Type]*map[*TypeReduction]bool, + types *map[TypeName]*Type, + constructors *map[ConstructorName]*Constructor, +) { + trs, ok := (*visitedReductions)[constructor.Type] + if !ok { + tmp := make(map[*TypeReduction]bool) + (*visitedReductions)[constructor.Type] = &tmp + trs = &tmp + } + + constructorReduction := TypeReduction{IsType: false, Constructor: constructor, Arguments: args} + + _, ok = (*trs)[&constructorReduction] + if !ok { + (*trs)[&constructorReduction] = true + } else { + return + } + + if constructor == nil { + return + } + for _, field := range constructor.Fields { + fieldType := toTypeReduction(field.FieldType, types, constructors) + if fieldType != nil { + fillTypeReduction(fieldType, constructor.Type, args) + reduce(*fieldType, visitedReductions, types, constructors) + } + } +} + +func findArgByName(targetArg string, args []tlast.TemplateArgument) int { + for i, arg := range args { + if arg.FieldName == targetArg { + return i + } + } + return -1 +} + +func fillTypeReduction( + typeReduction *TypeReduction, + originalType *Type, + args []EvaluatedTypeArgument, +) { + for argI, arg := range typeReduction.Arguments { + switch arg.Index { + // nat var + case 1: + j := findArgByName(arg.Variable, originalType.TypeArguments) + if j != -1 && args[j].Index == 0 { + typeReduction.Arguments[argI] = args[j] + } + // type + case 2: + fillTypeReduction(arg.Type, originalType, args) + // type var + case 3: + j := findArgByName(arg.TypeVariable, originalType.TypeArguments) + if j != -1 && args[j].Index == 2 { + typeReduction.Arguments[argI] = args[j] + } + } + } +} + +func toTypeReduction( + typeRef tlast.TypeRef, + types *map[TypeName]*Type, + constructors *map[ConstructorName]*Constructor, +) *TypeReduction { + var reduction TypeReduction + + typeName := typeRef.Type + var targetType *Type + + if constr, isConstructor := (*constructors)[typeName]; isConstructor { + reduction.IsType = false + reduction.Constructor = constr + targetType = constr.Type + } else if typ, isType := (*types)[typeName]; isType { + reduction.IsType = true + reduction.Type = typ + targetType = typ + } else { + return nil + } + + evalArguments := make([]EvaluatedTypeArgument, 0) + + for i, actualArg := range typeRef.Args { + typeArg := targetType.TypeArguments[i] + if actualArg.IsArith { + evalArguments = append(evalArguments, EvaluatedTypeArgument{ + Index: 0, + Constant: strconv.FormatInt(int64(actualArg.Arith.Res), 10), + }) + } else if typeArg.IsNat { + evalArguments = append(evalArguments, EvaluatedTypeArgument{ + Index: 1, + Variable: actualArg.T.Type.Name, + }) + } else { + typ := toTypeReduction(actualArg.T, types, constructors) + if typ != nil { + evalArguments = append(evalArguments, EvaluatedTypeArgument{ + Index: 2, + Type: typ, + }) + } else { + evalArguments = append(evalArguments, EvaluatedTypeArgument{ + Index: 3, + TypeVariable: actualArg.T.Type.Name, + }) + } + } + } + + reduction.Arguments = evalArguments + + return &reduction +} diff --git a/internal/tlcodegen/tlgen_kernel.go b/internal/tlcodegen/tlgen_kernel.go index c3c0ec1..2723faf 100644 --- a/internal/tlcodegen/tlgen_kernel.go +++ b/internal/tlcodegen/tlgen_kernel.go @@ -278,11 +278,13 @@ func (gen *Gen2) generateType(myWrapper *TypeRWWrapper) error { myWrapper.goGlobalName = gen.globalDec.deconflictName(head + tail) head, tail = myWrapper.resolvedT2GoName(myWrapper.tlName.Namespace) myWrapper.goLocalName = namespace.decGo.deconflictName(head + tail) + //actualName, _, _ := myWrapper.cppTypeStringInNamespace(false, &DirectIncludesCPP{ns: map[string]struct{}{}}, false, HalfResolvedArgument{}) actualName, canonicalName, _ := myWrapper.cppTypeStringInNamespace(false, &DirectIncludesCPP{ns: map[string]struct{}{}}, false, HalfResolvedArgument{}) otherRW, ok := namespace.cppTemplates[canonicalName] if ok { myWrapper.cppLocalName = otherRW.cppLocalName } else { + //myWrapper.cppLocalName = namespace.decCpp.deconflictName(ToUpperFirst(actualName) + tail) myWrapper.cppLocalName = namespace.decCpp.deconflictName(ToUpperFirst(actualName)) namespace.cppTemplates[canonicalName] = myWrapper } diff --git a/internal/tlcodegen/type_rw_tuple_cpp.go b/internal/tlcodegen/type_rw_tuple_cpp.go index f1cd94e..bee5a3d 100644 --- a/internal/tlcodegen/type_rw_tuple_cpp.go +++ b/internal/tlcodegen/type_rw_tuple_cpp.go @@ -46,6 +46,18 @@ func (trw *TypeRWBrackets) cppTypeStringInNamespaceHalfResolved(bytesVersion boo return fmt.Sprintf("std::array<%s, %s>", trw.element.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolved.Args[0]), halfResolved.Args[1].Name) } return fmt.Sprintf("std::array<%s, %d>", trw.element.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolved.Args[0]), trw.size) + + //if trw.vectorLike || trw.dynamicSize { + // index := 0 + // if len(halfResolved.Args) > 1 { + // index = 1 + // } + // return fmt.Sprintf("std::vector<%s>", trw.element.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolved.Args[index])) + //} + //if halfResolved.Args[1].Name != "" { + // return fmt.Sprintf("std::array<%s, %s>", trw.element.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolved.Args[1]), halfResolved.Args[0].Name) + //} + //return fmt.Sprintf("std::array<%s, %d>", trw.element.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolved.Args[1]), trw.size) } func (trw *TypeRWBrackets) cppDefaultInitializer(halfResolved HalfResolvedArgument, halfResolve bool) string { From 201abbe021f70b1aa16cae81405aa3c124efc81f Mon Sep 17 00:00:00 2001 From: Brat-vseznamus Date: Fri, 31 May 2024 14:41:49 +0300 Subject: [PATCH 03/10] add default values calculation --- internal/tlcodegen/tlgen.go | 91 +++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 39 deletions(-) diff --git a/internal/tlcodegen/tlgen.go b/internal/tlcodegen/tlgen.go index e005350..01b8d7a 100644 --- a/internal/tlcodegen/tlgen.go +++ b/internal/tlcodegen/tlgen.go @@ -1202,7 +1202,6 @@ type Constructor struct { } type TypeName = tlast.Name - type Type struct { IsBasic bool Name TypeName @@ -1214,7 +1213,7 @@ type EvaluatedTypeArgument struct { Index int // union variants - Constant string // 0 + Constant uint32 // 0 Variable string // 1 TypeVariable string // 3 Type *TypeReduction // 2 @@ -1254,13 +1253,13 @@ func (tr *TypeReduction) String() string { for i, arg := range tr.Arguments { switch arg.Index { case 0: - s += "C" + arg.Constant + s += "Con" + strconv.FormatInt(int64(arg.Constant), 10) case 1: - s += "V" + s += "Var" case 2: s += arg.Type.String() case 3: - s += "TV" + s += "TypeVar" } if len(tr.Arguments) != i+1 { s += "," @@ -1294,18 +1293,17 @@ func processCombinators(types map[string]*tlast.Combinator) { } } targetType := existingTypes[declaredType] - constrId := len(targetType.Constructors) constructor := Constructor{ Name: currentConstructor, Fields: comb.Fields, - Id: uint(constrId), + Id: uint(len(targetType.Constructors)), Type: targetType, } targetType.Constructors = append(targetType.Constructors, &constructor) existingConstructors[currentConstructor] = &constructor } - typeReductions := make(map[*Type]*map[*TypeReduction]bool) + typeReductions := make(map[*Type]*map[string]*TypeReduction) for _, comb := range existingTypes { if len(comb.TypeArguments) != 0 { @@ -1325,14 +1323,14 @@ func processCombinators(types map[string]*tlast.Combinator) { for tp, rds := range typeReductions { fmt.Println(tp.Name.String()) for rd, _ := range *rds { - fmt.Println("\t", rd.String()) + fmt.Println("\t", rd) } } } func reduce( targetTypeReduction TypeReduction, - visitedReductions *map[*Type]*map[*TypeReduction]bool, + visitedReductions *map[*Type]*map[string]*TypeReduction, types *map[TypeName]*Type, constructors *map[ConstructorName]*Constructor, ) { @@ -1342,24 +1340,6 @@ func reduce( } } - trs, ok := (*visitedReductions)[targetTypeReduction.ReferenceType()] - if !ok { - tmp := make(map[*TypeReduction]bool) - (*visitedReductions)[targetTypeReduction.ReferenceType()] = &tmp - trs = &tmp - } - - _, ok = (*trs)[&targetTypeReduction] - if !ok { - (*trs)[&targetTypeReduction] = true - } else { - return - } - - if targetTypeReduction.ReferenceType().IsBasic { - return - } - var visitingConstructors []*Constructor if targetTypeReduction.IsType { @@ -1382,38 +1362,68 @@ func reduce( func reduceConstructor( constructor *Constructor, args []EvaluatedTypeArgument, - visitedReductions *map[*Type]*map[*TypeReduction]bool, + visitedReductions *map[*Type]*map[string]*TypeReduction, types *map[TypeName]*Type, constructors *map[ConstructorName]*Constructor, ) { + if constructor == nil || constructor.Type.IsBasic { + return + } + trs, ok := (*visitedReductions)[constructor.Type] if !ok { - tmp := make(map[*TypeReduction]bool) + tmp := make(map[string]*TypeReduction) (*visitedReductions)[constructor.Type] = &tmp trs = &tmp } constructorReduction := TypeReduction{IsType: false, Constructor: constructor, Arguments: args} - _, ok = (*trs)[&constructorReduction] + _, ok = (*trs)[constructorReduction.String()] if !ok { - (*trs)[&constructorReduction] = true + (*trs)[constructorReduction.String()] = &constructorReduction } else { return } - if constructor == nil { - return - } + defaultFields := calculateDefaultFields(constructor, args) + for _, field := range constructor.Fields { fieldType := toTypeReduction(field.FieldType, types, constructors) if fieldType != nil { - fillTypeReduction(fieldType, constructor.Type, args) + fillTypeReduction(fieldType, args, constructor.Type, &defaultFields) reduce(*fieldType, visitedReductions, types, constructors) } } } +func calculateDefaultFields( + constructor *Constructor, + args []EvaluatedTypeArgument, +) map[string]bool { + defaults := make(map[string]bool) + + for _, field := range constructor.Fields { + if field.Mask != nil { + name := field.Mask.MaskName + bit := field.Mask.BitNumber + if _, ok := defaults[name]; ok { + defaults[field.FieldName] = true + continue + } + if argIndex := findArgByName(name, constructor.Type.TypeArguments); argIndex != -1 { + arg := args[argIndex] + if arg.Index == 0 && (arg.Constant&(1< Date: Tue, 4 Jun 2024 13:19:34 +0300 Subject: [PATCH 04/10] fix double implementation + true type set in union --- internal/tlcodegen/type_rw_struct_cpp.go | 6 +++--- internal/tlcodegen/type_rw_union_cpp.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/tlcodegen/type_rw_struct_cpp.go b/internal/tlcodegen/type_rw_struct_cpp.go index e74a52d..cf6c461 100644 --- a/internal/tlcodegen/type_rw_struct_cpp.go +++ b/internal/tlcodegen/type_rw_struct_cpp.go @@ -114,9 +114,9 @@ func (trw *TypeRWStruct) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectInc for _, field := range trw.Fields { fieldFullType := field.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, field.halfResolved) fieldsMaskComment := "" - if field.fieldMask != nil { - fieldsMaskComment = fmt.Sprintf(" // Conditional: %s.%d", formatNatArgCPP(trw.Fields, *field.fieldMask), field.BitNumber) - } + //if field.fieldMask != nil { + // fieldsMaskComment = fmt.Sprintf(" // Conditional: %s.%d", formatNatArgCPP(trw.Fields, *field.fieldMask), field.BitNumber) + //} if field.recursive { anyRecursive = true // requires destructor in cpp file hpp.WriteString(fmt.Sprintf("\tstd::shared_ptr<%s> %s{};%s\n", fieldFullType, field.cppName, fieldsMaskComment)) diff --git a/internal/tlcodegen/type_rw_union_cpp.go b/internal/tlcodegen/type_rw_union_cpp.go index 3796d94..e1fd3c6 100644 --- a/internal/tlcodegen/type_rw_union_cpp.go +++ b/internal/tlcodegen/type_rw_union_cpp.go @@ -416,7 +416,7 @@ func (trw *TypeRWUnion) CPPSetters(bytesVersion bool) string { var s strings.Builder for fieldIndex, field := range trw.Fields { if field.t.IsTrueType() { - s.WriteString(fmt.Sprintf("\tvoid set_%s() { value.emplace<%d>(); }\n", field.cppName, fieldIndex)) + s.WriteString(fmt.Sprintf("\tvoid set_%s() { value.emplace<%d>({}); }\n", field.cppName, fieldIndex)) } } return s.String() From 77fd6bd5900d006de1f4168039d5f9207792916f Mon Sep 17 00:00:00 2001 From: Brat-vseznamus Date: Wed, 12 Jun 2024 18:39:48 +0300 Subject: [PATCH 05/10] cpp gen start working --- Makefile | 14 +- internal/tlcodegen/tlgen.go | 335 +++++++++++++++++--- internal/tlcodegen/tlgen_cpp.go | 14 +- internal/tlcodegen/tlgen_kernel.go | 4 +- internal/tlcodegen/type_rw.go | 110 ++++++- internal/tlcodegen/type_rw_bool.go | 11 + internal/tlcodegen/type_rw_bool_cpp.go | 8 +- internal/tlcodegen/type_rw_maybe.go | 14 + internal/tlcodegen/type_rw_maybe_cpp.go | 12 +- internal/tlcodegen/type_rw_primitive.go | 11 + internal/tlcodegen/type_rw_primitive_cpp.go | 4 + internal/tlcodegen/type_rw_struct.go | 113 ++++++- internal/tlcodegen/type_rw_struct_cpp.go | 91 +++++- internal/tlcodegen/type_rw_tuple.go | 20 ++ internal/tlcodegen/type_rw_tuple_cpp.go | 19 +- internal/tlcodegen/type_rw_union.go | 44 ++- internal/tlcodegen/type_rw_union_cpp.go | 49 ++- 17 files changed, 757 insertions(+), 116 deletions(-) diff --git a/Makefile b/Makefile index 91df20a..9a58602 100644 --- a/Makefile +++ b/Makefile @@ -136,11 +136,19 @@ qtpl: qtc -dir=./internal -skipLineComments; \ fi -.PHONY: cpp -cpp: build +.PHONY: cpp_build +cpp_build: + g++ -o $(GEN_PATH)/test_cpp $(GEN_PATH)/test_cpp.cpp $(GEN_PATH)/cpp/all.cpp -std=c++17 -O3 -Wno-noexcept-type -g -Wall -Wextra -Werror=return-type -Wno-unused-parameter + +.PHONY: cpp_gen +cpp_gen: build @./target/bin/tlgen -language=cpp -v \ --outdir=./$(GEN_PATH)/cpp \ --generateRPCCode=false \ --basicPkgPath=$(BASIC_TL_PATH) \ ./$(TLS_PATH)/cpp.tl - g++ -o $(GEN_PATH)/test_cpp $(GEN_PATH)/test_cpp.cpp $(GEN_PATH)/cpp/all.cpp -std=c++17 -O3 -Wno-noexcept-type -g -Wall -Wextra -Werror=return-type -Wno-unused-parameter + +.PHONY: cpp +cpp: + $(MAKE) cpp_gen + $(MAKE) cpp_build diff --git a/internal/tlcodegen/tlgen.go b/internal/tlcodegen/tlgen.go index a49f203..de7b7b0 100644 --- a/internal/tlcodegen/tlgen.go +++ b/internal/tlcodegen/tlgen.go @@ -375,6 +375,10 @@ type Gen2 struct { TLO []byte // schema represented in tlo format, described using tls.* combinator Code map[string]string // fileName->Content, split by file names relative to output dir copyrightText string + + // new options + typesInfo *TypesInfo + componentsOrder []int } func (gen *Gen2) InternalPrefix() string { @@ -710,8 +714,11 @@ func (gen *Gen2) WriteToDir(outdir string) error { } } for filepathName := range relativeFiles { - deleted++ f := filepath.Join(outdir, filepathName) + //if strings.HasSuffix(f, ".o") { + // continue + //} + deleted++ if err := os.Remove(f); err != nil { return fmt.Errorf("error deleting previous file %q: %w", f, err) } @@ -1049,7 +1056,7 @@ func GenerateCode(tl tlast.TL, options Gen2Options) (*Gen2, error) { } skippedDueToWhitelist := 0 - processCombinators(gen.allConstructors) + gen.typesInfo = processCombinators(gen.allConstructors) for _, typ := range tl { if GenerateUnusedNatTemplates(typ.Construct.Name.String()) && len(typ.TemplateArguments) == 1 && typ.TemplateArguments[0].IsNat { @@ -1135,6 +1142,44 @@ func GenerateCode(tl tlast.TL, options Gen2Options) (*Gen2, error) { } } // in BeforeCodeGenerationStep we split recursion. Which links will be broken depends on order of nodes visited + for _, v := range sortedTypes { + if len(v.arguments) == 0 { + visitedNodes := make(map[*TypeRWWrapper]int) + currentPath := make([]*TypeRWWrapper, 0) + v.trw.FillRecursiveChildren(visitedNodes, ¤tPath) + } + } + + _, order := findAllTypesDependencyComponents(sortedTypes) + gen.componentsOrder = order + + //deps, order := findAllTypesDependencyComponents(sortedTypes) + //gen.componentsOrder = order + // + //compoments := make(map[int][]*TypeRWWrapper) + //cmpnts := make([]int, 0) + // + //for _, v := range sortedTypes { + // if _, ok := compoments[v.typeComponent]; !ok { + // cmpnts = append(cmpnts, v.typeComponent) + // } + // compoments[v.typeComponent] = append(compoments[v.typeComponent], v) + //} + // + //sort.Ints(cmpnts) + // + //for i, _ := range cmpnts { + // cId := order[i] + // curDeps := make([]int, 0) + // for dep, _ := range deps[cId] { + // curDeps = append(curDeps, dep) + // } + // fmt.Printf("C[%d]: %v\n", cId, curDeps) + // for _, tp := range compoments[cId] { + // fmt.Printf("\tGo: %s, TL: %s\n", tp.goGlobalName, tp.tlName.String()) + // } + //} + for _, v := range sortedTypes { v.trw.BeforeCodeGenerationStep1() } @@ -1206,39 +1251,154 @@ func GenerateCode(tl tlast.TL, options Gen2Options) (*Gen2, error) { return gen, nil } +func findAllTypesDependencyComponents(types []*TypeRWWrapper) (map[int]map[int]bool, []int) { + dependencyGraph := make(map[*TypeRWWrapper][]*TypeRWWrapper) + reverseDependencyGraph := make(map[*TypeRWWrapper][]*TypeRWWrapper) + + for _, tpU := range types { + dependencies := tpU.trw.AllTypeDependencies() + for _, tpV := range dependencies { + dependencyGraph[tpU] = append(dependencyGraph[tpU], tpV) + reverseDependencyGraph[tpV] = append(reverseDependencyGraph[tpV], tpU) + } + } + + visitedTypes := make(map[*TypeRWWrapper]bool) + order := make([]*TypeRWWrapper, 0) + for _, tp := range types { + if !visitedTypes[tp] { + findAllTypesDependencyComponentsStep1( + tp, + &visitedTypes, + &dependencyGraph, + &order, + ) + } + } + visitedTypes = make(map[*TypeRWWrapper]bool) + component := 1 + for i := len(order) - 1; i >= 0; i-- { + target := order[i] + if !visitedTypes[target] { + findAllTypesDependencyComponentsStep2( + target, + &visitedTypes, + &reverseDependencyGraph, + component, + ) + component += 1 + } + } + + componentsDeps := make(map[int]map[int]bool) + + for _, tpU := range types { + if _, ok := componentsDeps[tpU.typeComponent]; !ok { + componentsDeps[tpU.typeComponent] = make(map[int]bool) + } + for _, tpV := range tpU.trw.AllTypeDependencies() { + if tpU.typeComponent != tpV.typeComponent { + componentsDeps[tpU.typeComponent][tpV.typeComponent] = true + } + } + } + + compOrder := make([]int, 0) + compVisited := make(map[int]bool) + + for cmp := range componentsDeps { + if !compVisited[cmp] { + sortComponents(cmp, &compVisited, &componentsDeps, &compOrder) + } + } + + //slices.Reverse(compOrder) + + return componentsDeps, compOrder +} + +func findAllTypesDependencyComponentsStep1( + tp *TypeRWWrapper, + visited *map[*TypeRWWrapper]bool, + typeDeps *map[*TypeRWWrapper][]*TypeRWWrapper, + order *[]*TypeRWWrapper) { + (*visited)[tp] = true + for _, tpDep := range (*typeDeps)[tp] { + if !(*visited)[tpDep] { + findAllTypesDependencyComponentsStep1(tpDep, visited, typeDeps, order) + } + } + *order = append(*order, tp) +} + +func findAllTypesDependencyComponentsStep2( + tp *TypeRWWrapper, + visited *map[*TypeRWWrapper]bool, + typeDeps *map[*TypeRWWrapper][]*TypeRWWrapper, + component int) { + (*visited)[tp] = true + tp.typeComponent = component + for _, tpDep := range (*typeDeps)[tp] { + if !(*visited)[tpDep] { + findAllTypesDependencyComponentsStep2(tpDep, visited, typeDeps, component) + } + } +} + +func sortComponents(target int, visited *map[int]bool, deps *map[int]map[int]bool, order *[]int) { + (*visited)[target] = true + for next, _ := range (*deps)[target] { + if !(*visited)[next] { + sortComponents(next, visited, deps, order) + } + } + *order = append(*order, target) +} + type ConstructorName = tlast.Name type Constructor struct { - Type *Type + Type *TypeDefinition Id uint Name ConstructorName Fields []tlast.Field } type TypeName = tlast.Name -type Type struct { +type TypeDefinition struct { IsBasic bool Name TypeName TypeArguments []tlast.TemplateArgument Constructors []*Constructor } -type EvaluatedTypeArgument struct { - Index int +type EvaluatedTypeVariant = int + +const ( + NumberConstant EvaluatedTypeVariant = 0 + NumberVariable EvaluatedTypeVariant = 1 + TypeConstant EvaluatedTypeVariant = 2 + TypeVariable EvaluatedTypeVariant = 3 +) + +type EvaluatedType struct { + Index EvaluatedTypeVariant // union variants Constant uint32 // 0 Variable string // 1 - TypeVariable string // 3 Type *TypeReduction // 2 + TypeVariable string // 3 + + VariableActsAsConstant bool // only if Index == 1 and only for type declarations } type TypeReduction struct { IsType bool - Type *Type + Type *TypeDefinition Constructor *Constructor - Arguments []EvaluatedTypeArgument + Arguments []EvaluatedType } func (tr *TypeReduction) ReferenceName() (name tlast.Name) { @@ -1250,7 +1410,7 @@ func (tr *TypeReduction) ReferenceName() (name tlast.Name) { return } -func (tr *TypeReduction) ReferenceType() *Type { +func (tr *TypeReduction) ReferenceType() *TypeDefinition { if tr.IsType { return tr.Type } @@ -1284,21 +1444,21 @@ func (tr *TypeReduction) String() string { return s } -func processCombinators(types map[string]*tlast.Combinator) { - existingTypes := make(map[TypeName]*Type) +func processCombinators(types map[string]*tlast.Combinator) *TypesInfo { + existingTypes := make(map[TypeName]*TypeDefinition) existingConstructors := make(map[ConstructorName]*Constructor) for _, comb := range types { - if comb.IsFunction { - continue - } + //if comb.IsFunction { + // continue + //} declaredType := comb.TypeDecl.Name if comb.Builtin { declaredType = comb.Construct.Name } currentConstructor := comb.Construct.Name if _, presented := existingTypes[declaredType]; !presented { - existingTypes[declaredType] = &Type{ + existingTypes[declaredType] = &TypeDefinition{ IsBasic: comb.Builtin, Name: declaredType, Constructors: []*Constructor{}, @@ -1316,7 +1476,7 @@ func processCombinators(types map[string]*tlast.Combinator) { existingConstructors[currentConstructor] = &constructor } - typeReductions := make(map[*Type]*map[string]*TypeReduction) + typeReductions := make(map[*TypeDefinition]*map[string]*TypeReduction) for _, comb := range existingTypes { if len(comb.TypeArguments) != 0 { @@ -1333,22 +1493,58 @@ func processCombinators(types map[string]*tlast.Combinator) { ) } - for tp, rds := range typeReductions { - fmt.Println(tp.Name.String()) - for rd, _ := range *rds { - fmt.Println("\t", rd) + ti := TypesInfo{Types: existingTypes, Constructors: existingConstructors, TypeReductions: typeReductions} + + //printResults(ti) + + return &ti +} + +func printResults(ti TypesInfo) { + for tp, rds := range ti.TypeReductions { + suffix := "" + for i, tpArg := range tp.TypeArguments { + if i != 0 { + suffix += "," + } + if tpArg.IsNat { + suffix += "#" + } else { + suffix += "*" + } + } + if len(tp.TypeArguments) != 0 { + suffix = "<" + suffix + ">" + } + fmt.Println(tp.Name.String() + suffix) + for _, trd := range *rds { + fmt.Println("\t", trd) + if !trd.IsType { + for i, f := range trd.Constructor.Fields { + ftrd := ti.FieldTypeReduction(trd, i) + s := "" + if ftrd.Index == TypeVariable { + s = "[" + ftrd.TypeVariable + "]" + } else if ftrd.Index == TypeConstant { + if ftrd.Type != nil { + s = ftrd.Type.String() + } + } + fmt.Println("\t\t", "\""+f.FieldName+"\":", s) + } + } } } } func reduce( targetTypeReduction TypeReduction, - visitedReductions *map[*Type]*map[string]*TypeReduction, - types *map[TypeName]*Type, + visitedReductions *map[*TypeDefinition]*map[string]*TypeReduction, + types *map[TypeName]*TypeDefinition, constructors *map[ConstructorName]*Constructor, ) { for _, arg := range targetTypeReduction.Arguments { - if arg.Index == 2 { + if arg.Index == TypeConstant { reduce(*arg.Type, visitedReductions, types, constructors) } } @@ -1374,9 +1570,9 @@ func reduce( func reduceConstructor( constructor *Constructor, - args []EvaluatedTypeArgument, - visitedReductions *map[*Type]*map[string]*TypeReduction, - types *map[TypeName]*Type, + args []EvaluatedType, + visitedReductions *map[*TypeDefinition]*map[string]*TypeReduction, + types *map[TypeName]*TypeDefinition, constructors *map[ConstructorName]*Constructor, ) { if constructor == nil || constructor.Type.IsBasic { @@ -1412,7 +1608,7 @@ func reduceConstructor( func calculateDefaultFields( constructor *Constructor, - args []EvaluatedTypeArgument, + args []EvaluatedType, ) map[string]bool { defaults := make(map[string]bool) @@ -1448,8 +1644,8 @@ func findArgByName(targetArg string, args []tlast.TemplateArgument) int { func fillTypeReduction( typeReduction *TypeReduction, - args []EvaluatedTypeArgument, - originalType *Type, + args []EvaluatedType, + originalType *TypeDefinition, defaultFields *map[string]bool, ) { for argI, arg := range typeReduction.Arguments { @@ -1457,10 +1653,10 @@ func fillTypeReduction( // nat var case 1: j := findArgByName(arg.Variable, originalType.TypeArguments) - if j != -1 && args[j].Index == 0 { + if j != -1 && args[j].Index == NumberConstant { typeReduction.Arguments[argI] = args[j] } else if _, ok := (*defaultFields)[arg.Variable]; ok { - typeReduction.Arguments[argI] = EvaluatedTypeArgument{Index: 0, Constant: 0} + typeReduction.Arguments[argI] = EvaluatedType{Index: NumberConstant, Constant: 0} } // type case 2: @@ -1468,8 +1664,11 @@ func fillTypeReduction( // type var case 3: j := findArgByName(arg.TypeVariable, originalType.TypeArguments) - if j != -1 && args[j].Index == 2 { - typeReduction.Arguments[argI] = args[j] + if j != -1 { + index := args[j].Index + if index == TypeConstant || index == TypeVariable { + typeReduction.Arguments[argI] = args[j] + } } } } @@ -1477,13 +1676,13 @@ func fillTypeReduction( func toTypeReduction( typeRef tlast.TypeRef, - types *map[TypeName]*Type, + types *map[TypeName]*TypeDefinition, constructors *map[ConstructorName]*Constructor, ) *TypeReduction { var reduction TypeReduction typeName := typeRef.Type - var targetType *Type + var targetType *TypeDefinition if constr, isConstructor := (*constructors)[typeName]; isConstructor { reduction.IsType = false @@ -1497,30 +1696,30 @@ func toTypeReduction( return nil } - evalArguments := make([]EvaluatedTypeArgument, 0) + evalArguments := make([]EvaluatedType, 0) for i, actualArg := range typeRef.Args { typeArg := targetType.TypeArguments[i] if actualArg.IsArith { - evalArguments = append(evalArguments, EvaluatedTypeArgument{ - Index: 0, + evalArguments = append(evalArguments, EvaluatedType{ + Index: NumberConstant, Constant: actualArg.Arith.Res, }) } else if typeArg.IsNat { - evalArguments = append(evalArguments, EvaluatedTypeArgument{ - Index: 1, + evalArguments = append(evalArguments, EvaluatedType{ + Index: NumberVariable, Variable: actualArg.T.Type.Name, }) } else { typ := toTypeReduction(actualArg.T, types, constructors) if typ != nil { - evalArguments = append(evalArguments, EvaluatedTypeArgument{ - Index: 2, + evalArguments = append(evalArguments, EvaluatedType{ + Index: TypeConstant, Type: typ, }) } else { - evalArguments = append(evalArguments, EvaluatedTypeArgument{ - Index: 3, + evalArguments = append(evalArguments, EvaluatedType{ + Index: TypeVariable, TypeVariable: actualArg.T.Type.Name, }) } @@ -1531,3 +1730,49 @@ func toTypeReduction( return &reduction } + +type TypesInfo struct { + Types map[TypeName]*TypeDefinition + Constructors map[ConstructorName]*Constructor + TypeReductions map[*TypeDefinition]*map[string]*TypeReduction +} + +// works for given constructor or for 1-st +func (ti *TypesInfo) FieldTypeReduction(tr *TypeReduction, fieldId int) EvaluatedType { + constructor := tr.Constructor + if tr.IsType { + constructor = tr.ReferenceType().Constructors[0] + } + field := constructor.Fields[fieldId] + fieldType := toTypeReduction(field.FieldType, &ti.Types, &ti.Constructors) + if fieldType == nil { + genericName := field.FieldType.Type.Name + i := findArgByName(genericName, tr.ReferenceType().TypeArguments) + if i == -1 || tr.Arguments[i].Type == nil { + return EvaluatedType{Index: TypeVariable, TypeVariable: genericName} + } + return EvaluatedType{Index: TypeConstant, Type: tr.Arguments[i].Type} + } + defaultValues := calculateDefaultFields(constructor, tr.Arguments) + fillTypeReduction(fieldType, tr.Arguments, tr.ReferenceType(), &defaultValues) + return EvaluatedType{Index: TypeConstant, Type: fieldType} +} + +func (ti *TypesInfo) TypeNameToGenericTypeReduction(t TypeName) TypeReduction { + var rd TypeReduction + rd.Type, rd.IsType = ti.Types[t] + rd.Constructor = ti.Constructors[t] + + refType := rd.ReferenceType() + for i, arg := range refType.TypeArguments { + var evalType EvaluatedType + if arg.IsNat { + evalType = EvaluatedType{Index: NumberVariable, Variable: fmt.Sprintf("_Nat%d", i)} + } else { + evalType = EvaluatedType{Index: TypeVariable, TypeVariable: fmt.Sprintf("_Type%d", i)} + } + rd.Arguments = append(rd.Arguments, evalType) + } + + return rd +} diff --git a/internal/tlcodegen/tlgen_cpp.go b/internal/tlcodegen/tlgen_cpp.go index ad792a6..f681f92 100644 --- a/internal/tlcodegen/tlgen_cpp.go +++ b/internal/tlcodegen/tlgen_cpp.go @@ -26,7 +26,7 @@ func cppFinishNamespace(s *strings.Builder, ns []string) { func (gen *Gen2) generateCodeCPP(generateByteVersions []string) error { const basicTLFilepathName = "a_tlgen_helpers_code" + hppExt // TODO decollision - cppAllInc := &DirectIncludesCPP{ns: map[string]struct{}{}} + cppAllInc := &DirectIncludesCPP{ns: map[string]CppIncludeInfo{}} var hpp strings.Builder var hppDet strings.Builder var cppDet strings.Builder @@ -38,10 +38,10 @@ func (gen *Gen2) generateCodeCPP(generateByteVersions []string) error { internalFiles[ff] = append(internalFiles[ff], typeRw) } for ff, types := range internalFiles { - hppInc := &DirectIncludesCPP{ns: map[string]struct{}{}} - hppIncFwd := &DirectIncludesCPP{ns: map[string]struct{}{}} - hppDetInc := &DirectIncludesCPP{ns: map[string]struct{}{}} - cppDetInc := &DirectIncludesCPP{ns: map[string]struct{}{}} + hppInc := &DirectIncludesCPP{ns: map[string]CppIncludeInfo{}} + hppIncFwd := &DirectIncludesCPP{ns: map[string]CppIncludeInfo{}} + hppDetInc := &DirectIncludesCPP{ns: map[string]CppIncludeInfo{}} + cppDetInc := &DirectIncludesCPP{ns: map[string]CppIncludeInfo{}} multipleDefinitions := map[string]struct{}{} for _, typeRw := range types { // log.Printf("type: %s\n", typeRw.tlName.String()) @@ -68,7 +68,7 @@ func (gen *Gen2) generateCodeCPP(generateByteVersions []string) error { if hpp.Len() == 0 && hppDet.Len() == 0 && cppDet.Len() == 0 { continue } - cppAllInc.ns[ff.fileName] = struct{}{} + cppAllInc.ns[ff.fileName] = CppIncludeInfo{types[0].typeComponent} hppStr := hpp.String() hppDetStr := hppDet.String() cppDetStr := cppDet.String() @@ -115,7 +115,7 @@ func (gen *Gen2) generateCodeCPP(generateByteVersions []string) error { var cppMake strings.Builder var cppMakeO strings.Builder var cppMake1 strings.Builder - for _, n := range cppAllInc.sortedNames() { + for _, n := range cppAllInc.sortedIncludes(gen.componentsOrder) { cppAll.WriteString(fmt.Sprintf("#include \"details/%s%s\"\n", n+"_details", cppExt)) cppMake1.WriteString(fmt.Sprintf("%s.o: details/%s%s details/%s%s\n", n+"_details", n+"_details", cppExt, n+"_details", hppExt)) cppMake1.WriteString(fmt.Sprintf("\t$(CC) $(CFLAGS) -c details/%s%s\n", n+"_details", cppExt)) diff --git a/internal/tlcodegen/tlgen_kernel.go b/internal/tlcodegen/tlgen_kernel.go index 3e0f245..7a38b97 100644 --- a/internal/tlcodegen/tlgen_kernel.go +++ b/internal/tlcodegen/tlgen_kernel.go @@ -280,7 +280,7 @@ func (gen *Gen2) generateType(myWrapper *TypeRWWrapper) error { head, tail = myWrapper.resolvedT2GoName(myWrapper.tlName.Namespace) myWrapper.goLocalName = namespace.decGo.deconflictName(head + tail) //actualName, _, _ := myWrapper.cppTypeStringInNamespace(false, &DirectIncludesCPP{ns: map[string]struct{}{}}, false, HalfResolvedArgument{}) - actualName, canonicalName, _ := myWrapper.cppTypeStringInNamespace(false, &DirectIncludesCPP{ns: map[string]struct{}{}}, false, HalfResolvedArgument{}) + actualName, canonicalName, _ := myWrapper.cppTypeStringInNamespace(false, &DirectIncludesCPP{ns: map[string]CppIncludeInfo{}}, false, HalfResolvedArgument{}) otherRW, ok := namespace.cppTemplates[canonicalName] if ok { myWrapper.cppLocalName = otherRW.cppLocalName @@ -356,7 +356,7 @@ func (gen *Gen2) generateType(myWrapper *TypeRWWrapper) error { myWrapper.goGlobalName = gen.globalDec.deconflictName(head + tail) head, tail = myWrapper.resolvedT2GoName(myWrapper.tlName.Namespace) myWrapper.goLocalName = namespace.decGo.deconflictName(head + tail) - actualName, canonicalName, _ := myWrapper.cppTypeStringInNamespace(false, &DirectIncludesCPP{ns: map[string]struct{}{}}, false, HalfResolvedArgument{}) + actualName, canonicalName, _ := myWrapper.cppTypeStringInNamespace(false, &DirectIncludesCPP{ns: map[string]CppIncludeInfo{}}, false, HalfResolvedArgument{}) otherRW, ok := namespace.cppTemplates[canonicalName] if ok { myWrapper.cppLocalName = otherRW.cppLocalName diff --git a/internal/tlcodegen/type_rw.go b/internal/tlcodegen/type_rw.go index 2fb0811..c7520ec 100644 --- a/internal/tlcodegen/type_rw.go +++ b/internal/tlcodegen/type_rw.go @@ -12,8 +12,6 @@ import ( "strconv" "strings" - "golang.org/x/exp/slices" - "github.com/vkcom/tl/internal/tlast" ) @@ -43,6 +41,8 @@ func (d *Deconflicter) deconflictName(s string) string { return s } +var bannedCppFieldNames = []string{"and", "or", "friend", "xor", "operator", "errno", "class", "short", "default", "signed"} + func (d *Deconflicter) fillCPPIdentifiers() { // TODO - full list d.deconflictName("int") d.deconflictName("double") @@ -51,6 +51,10 @@ func (d *Deconflicter) fillCPPIdentifiers() { // TODO - full list d.deconflictName("else") d.deconflictName("inline") d.deconflictName("namespace") + + for _, word := range bannedCppFieldNames { + d.deconflictName(word) + } } type TypeRWWrapper struct { @@ -83,6 +87,9 @@ type TypeRWWrapper struct { WrLong *TypeRWWrapper // long transitioning code WrWithoutLong *TypeRWWrapper // long transitioning code + + typeComponent int + forwardDeclarations map[*TypeRWWrapper]bool } // Those have unique structure fully defined by the magic. @@ -171,6 +178,29 @@ func (w *TypeRWWrapper) NatArgs(result []ActualNatArg, prefix string) []ActualNa return result } +func (w *TypeRWWrapper) ActualTypeDependencies(evalType EvaluatedType) (res []*TypeRWWrapper) { + r := make(map[*TypeRWWrapper]bool) + w.actualTypeDependenciesRecur(evalType, &r) + for arg, _ := range r { + res = append(res, arg) + } + return +} + +func (w *TypeRWWrapper) actualTypeDependenciesRecur(evalType EvaluatedType, used *map[*TypeRWWrapper]bool) { + if evalType.Index != TypeConstant { + return + } + if !(*used)[w] { + (*used)[w] = true + } + for i, arg := range w.arguments { + if arg.tip != nil { + arg.tip.actualTypeDependenciesRecur(evalType.Type.Arguments[i], used) + } + } +} + func (w *TypeRWWrapper) resolvedT2GoName(insideNamespace string) (head, tail string) { b := strings.Builder{} for _, a := range w.arguments { @@ -202,9 +232,13 @@ type DirectImports struct { importSort bool } +type CppIncludeInfo struct { + componentId int +} + // for C++ includes type DirectIncludesCPP struct { - ns map[string]struct{} + ns map[string]CppIncludeInfo } func (d DirectIncludesCPP) sortedNames() []string { @@ -212,10 +246,31 @@ func (d DirectIncludesCPP) sortedNames() []string { for im := range d.ns { // Imports of this file. sortedNames = append(sortedNames, im) } - slices.Sort(sortedNames) return sortedNames } +func (d DirectIncludesCPP) sortedIncludes(componentOrder []int) (result []string) { + compIdToPosition := make(map[int]int) + + for i, cId := range componentOrder { + compIdToPosition[cId] = i + } + + filesByCID := make([][]string, len(componentOrder)) + + for im, cppInfo := range d.ns { // Imports of this file. + filesByCID[compIdToPosition[cppInfo.componentId]] = append(filesByCID[compIdToPosition[cppInfo.componentId]], im) + } + + for _, files := range filesByCID { + for _, f := range files { + result = append(result, f) + } + } + + return +} + func stringCompare(a string, b string) int { if a < b { return -1 @@ -362,6 +417,13 @@ func (w *TypeRWWrapper) CPPTypeStringInNamespaceHalfResolved(bytesVersion bool, return w.trw.cppTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolved) } +func (w *TypeRWWrapper) CPPTypeStringInNamespaceHalfResolved2(bytesVersion bool, typeReduction EvaluatedType) string { + if typeReduction.Type == nil { + return typeReduction.TypeVariable + } + return w.trw.cppTypeStringInNamespaceHalfResolved2(bytesVersion, typeReduction) +} + func (w *TypeRWWrapper) CPPDefaultInitializer(halfResolved HalfResolvedArgument, halfResolve bool) string { if halfResolve && halfResolved.Name != "" { return "{}" @@ -407,8 +469,39 @@ func (w *TypeRWWrapper) fullyResolvedClassCppNameArgs() (string, []string) { // return cppSuffix.String(), cppArgsDecl } +func (w *TypeRWWrapper) cppTypeArguments(bytesVersion bool, typeRedaction *TypeReduction) string { + arguments := make([]string, 0) + for i, a := range w.arguments { + evalArg := typeRedaction.Arguments[i] + if a.isNat { + if evalArg.Index == 0 { + arguments = append(arguments, strconv.FormatInt(int64(evalArg.Constant), 10)) + } else if evalArg.Index == 1 && evalArg.VariableActsAsConstant { + arguments = append(arguments, evalArg.Variable) + } + } else { + if evalArg.Index == 3 { + arguments = append(arguments, evalArg.TypeVariable) + } else if evalArg.Index == 2 { + arguments = append(arguments, a.tip.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, evalArg)) + } + } + } + s := "" + for i, arg := range arguments { + if i != 0 { + s += ", " + } + s += arg + } + if s != "" { + s = "<" + s + ">" + } + return s +} + func (w *TypeRWWrapper) cppTypeStringInNamespace(bytesVersion bool, hppInc *DirectIncludesCPP, halfResolve bool, halfResolved HalfResolvedArgument) (string, string, string) { - hppInc.ns[w.fileName] = struct{}{} + hppInc.ns[w.fileName] = CppIncludeInfo{w.typeComponent} bName := strings.Builder{} // bName.WriteString(w.cppNamespaceQualifier()) bName.WriteString(w.tlName.Name) @@ -545,7 +638,11 @@ outer: type TypeRW interface { // methods below are target language independent markWantsBytesVersion(visitedNodes map[*TypeRWWrapper]bool) - fillRecursiveUnwrap(visitedNodes map[*TypeRWWrapper]bool) + fillRecursiveUnwrap(vistrwitedNodes map[*TypeRWWrapper]bool) + + FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) + AllPossibleRecursionProducers() []*TypeRWWrapper + AllTypeDependencies() []*TypeRWWrapper BeforeCodeGenerationStep1() // during first phase, some wr.trw are nil due to recursive types. So we delay some BeforeCodeGenerationStep2() // during second phase, union fields recursive bit is set @@ -569,6 +666,7 @@ type TypeRW 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 diff --git a/internal/tlcodegen/type_rw_bool.go b/internal/tlcodegen/type_rw_bool.go index 7578a53..7739a5c 100644 --- a/internal/tlcodegen/type_rw_bool.go +++ b/internal/tlcodegen/type_rw_bool.go @@ -42,6 +42,17 @@ func (trw *TypeRWBool) fillRecursiveUnwrap(visitedNodes map[*TypeRWWrapper]bool) func (trw *TypeRWBool) markWantsBytesVersion(visitedNodes map[*TypeRWWrapper]bool) { } +func (trw *TypeRWBool) AllPossibleRecursionProducers() []*TypeRWWrapper { + return nil +} + +func (trw *TypeRWBool) AllTypeDependencies() []*TypeRWWrapper { + return nil +} + +func (trw *TypeRWBool) FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) { +} + func (trw *TypeRWBool) BeforeCodeGenerationStep1() { } diff --git a/internal/tlcodegen/type_rw_bool_cpp.go b/internal/tlcodegen/type_rw_bool_cpp.go index d6a8b29..e2b9ad4 100644 --- a/internal/tlcodegen/type_rw_bool_cpp.go +++ b/internal/tlcodegen/type_rw_bool_cpp.go @@ -15,12 +15,16 @@ func (trw *TypeRWBool) CPPFillRecursiveChildren(visitedNodes map[*TypeRWWrapper] } func (trw *TypeRWBool) cppTypeStringInNamespace(bytesVersion bool, hppInc *DirectIncludesCPP) string { - hppInc.ns[trw.wr.fileName] = struct{}{} + hppInc.ns[trw.wr.fileName] = CppIncludeInfo{componentId: trw.wr.typeComponent} return "bool" } func (trw *TypeRWBool) cppTypeStringInNamespaceHalfResolved(bytesVersion bool, hppInc *DirectIncludesCPP, halfResolved HalfResolvedArgument) string { - hppInc.ns[trw.wr.fileName] = struct{}{} + hppInc.ns[trw.wr.fileName] = CppIncludeInfo{componentId: trw.wr.typeComponent} + return "bool" +} + +func (trw *TypeRWBool) cppTypeStringInNamespaceHalfResolved2(bytesVersion bool, typeReduction EvaluatedType) string { return "bool" } diff --git a/internal/tlcodegen/type_rw_maybe.go b/internal/tlcodegen/type_rw_maybe.go index 263b7ed..cba95ef 100644 --- a/internal/tlcodegen/type_rw_maybe.go +++ b/internal/tlcodegen/type_rw_maybe.go @@ -40,6 +40,20 @@ func (trw *TypeRWMaybe) markWantsBytesVersion(visitedNodes map[*TypeRWWrapper]bo trw.element.t.MarkWantsBytesVersion(visitedNodes) } +func (trw *TypeRWMaybe) AllPossibleRecursionProducers() []*TypeRWWrapper { + return trw.element.t.trw.AllPossibleRecursionProducers() +} + +func (trw *TypeRWMaybe) AllTypeDependencies() []*TypeRWWrapper { + return nil +} + +func (trw *TypeRWMaybe) FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) { + visitedNodes[trw.wr] = 1 + trw.element.t.trw.FillRecursiveChildren(visitedNodes, currentPath) + visitedNodes[trw.wr] = 2 +} + func (trw *TypeRWMaybe) BeforeCodeGenerationStep1() { } diff --git a/internal/tlcodegen/type_rw_maybe_cpp.go b/internal/tlcodegen/type_rw_maybe_cpp.go index 945998d..aa87e3e 100644 --- a/internal/tlcodegen/type_rw_maybe_cpp.go +++ b/internal/tlcodegen/type_rw_maybe_cpp.go @@ -16,15 +16,19 @@ func (trw *TypeRWMaybe) CPPFillRecursiveChildren(visitedNodes map[*TypeRWWrapper } func (trw *TypeRWMaybe) cppTypeStringInNamespace(bytesVersion bool, hppInc *DirectIncludesCPP) string { - hppInc.ns[trw.wr.fileName] = struct{}{} + hppInc.ns[trw.wr.fileName] = CppIncludeInfo{componentId: trw.wr.typeComponent} return "::basictl::optional<" + trw.element.t.CPPTypeStringInNamespace(bytesVersion, hppInc) + ">" } func (trw *TypeRWMaybe) cppTypeStringInNamespaceHalfResolved(bytesVersion bool, hppInc *DirectIncludesCPP, halfResolved HalfResolvedArgument) string { - hppInc.ns[trw.wr.fileName] = struct{}{} + hppInc.ns[trw.wr.fileName] = CppIncludeInfo{componentId: trw.wr.typeComponent} return "::basictl::optional<" + trw.element.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolved.Args[0]) + ">" } +func (trw *TypeRWMaybe) cppTypeStringInNamespaceHalfResolved2(bytesVersion bool, typeReduction EvaluatedType) string { + return "::basictl::optional<" + trw.element.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeReduction.Type.Arguments[0]) + ">" +} + func (trw *TypeRWMaybe) cppDefaultInitializer(halfResolved HalfResolvedArgument, halfResolve bool) string { return "" } @@ -50,6 +54,10 @@ func (trw *TypeRWMaybe) CPPTypeReadingCode(bytesVersion bool, val string, bare b } func (trw *TypeRWMaybe) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool) { + if forwardDeclaration { + trw.element.t.trw.CPPGenerateCode(hpp, hppInc, hppIncFwd, hppDet, hppDetInc, cppDet, cppDetInc, bytesVersion, true) + return + } goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) myFullType := trw.cppTypeStringInNamespace(bytesVersion, hppDetInc) diff --git a/internal/tlcodegen/type_rw_primitive.go b/internal/tlcodegen/type_rw_primitive.go index ce4f50c..56eed8e 100644 --- a/internal/tlcodegen/type_rw_primitive.go +++ b/internal/tlcodegen/type_rw_primitive.go @@ -58,6 +58,17 @@ func (trw *TypeRWPrimitive) fillRecursiveUnwrap(visitedNodes map[*TypeRWWrapper] func (trw *TypeRWPrimitive) markWantsBytesVersion(visitedNodes map[*TypeRWWrapper]bool) { } +func (trw *TypeRWPrimitive) AllPossibleRecursionProducers() []*TypeRWWrapper { + return nil +} + +func (trw *TypeRWPrimitive) AllTypeDependencies() []*TypeRWWrapper { + return nil +} + +func (trw *TypeRWPrimitive) FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) { +} + func (trw *TypeRWPrimitive) BeforeCodeGenerationStep1() { } diff --git a/internal/tlcodegen/type_rw_primitive_cpp.go b/internal/tlcodegen/type_rw_primitive_cpp.go index a5b7ace..021f3e0 100644 --- a/internal/tlcodegen/type_rw_primitive_cpp.go +++ b/internal/tlcodegen/type_rw_primitive_cpp.go @@ -22,6 +22,10 @@ func (trw *TypeRWPrimitive) cppTypeStringInNamespaceHalfResolved(bytesVersion bo return trw.cppPrimitiveType } +func (trw *TypeRWPrimitive) cppTypeStringInNamespaceHalfResolved2(bytesVersion bool, typeReduction EvaluatedType) string { + return trw.cppPrimitiveType +} + func (trw *TypeRWPrimitive) cppDefaultInitializer(halfResolved HalfResolvedArgument, halfResolve bool) string { return trw.cppDefaultInit } diff --git a/internal/tlcodegen/type_rw_struct.go b/internal/tlcodegen/type_rw_struct.go index 0d5fe31..ba539c7 100644 --- a/internal/tlcodegen/type_rw_struct.go +++ b/internal/tlcodegen/type_rw_struct.go @@ -40,22 +40,22 @@ func (trw *TypeRWStruct) isUnwrapType() bool { if isPrimitive && primitive.tlType == trw.wr.tlName.String() { return true } - brackets, isBuiltinBrackets := trw.Fields[0].t.trw.(*TypeRWBrackets) - if isBuiltinBrackets && (brackets.dictLike || trw.wr.tlName.String() == "vector" || trw.wr.tlName.String() == "tuple") { - return true - } + //brackets, isBuiltinBrackets := trw.Fields[0].t.trw.(*TypeRWBrackets) + //if isBuiltinBrackets && (brackets.dictLike || trw.wr.tlName.String() == "vector" || trw.wr.tlName.String() == "tuple") { + // return true + //} // in combined TL Dictionary is defined via Vector. // dictionaryField {t:Type} key:string value:t = DictionaryField t; // dictionary#1f4c618f {t:Type} %(Vector %(DictionaryField t)) = Dictionary t; // TODO - change combined.tl to use # [] after we fully control generation of C++ & (k)PHP and remove code below - str, isStruct := trw.Fields[0].t.trw.(*TypeRWStruct) - if isStruct && str.wr.tlName.String() == "vector" { - // repeat check above 1 level deeper - brackets, isBuiltinBrackets = str.Fields[0].t.trw.(*TypeRWBrackets) - if isBuiltinBrackets && brackets.dictLike { - return true - } - } + //str, isStruct := trw.Fields[0].t.trw.(*TypeRWStruct) + //if isStruct && str.wr.tlName.String() == "vector" { + // // repeat check above 1 level deeper + // brackets, isBuiltinBrackets := str.Fields[0].t.trw.(*TypeRWBrackets) + // if isBuiltinBrackets && brackets.dictLike { + // return true + // } + //} return false } @@ -80,6 +80,34 @@ func (trw *TypeRWStruct) markHasBytesVersion(visitedNodes map[*TypeRWWrapper]boo return result } +func (trw *TypeRWWrapper) replaceUnwrapHalfResolvedName(topHalfResolved HalfResolvedArgument, name string) string { + if name == "" { + return "" + } + for i, arg := range trw.origTL[0].TemplateArguments { + if arg.FieldName == name { + return topHalfResolved.Args[i].Name + } + } + return "" +} + +// same code as in func (w *TypeRWWrapper) transformNatArgsToChild, replaceUnwrapArgs +func (trw *TypeRWWrapper) replaceUnwrapHalfResolved(topHalfResolved HalfResolvedArgument, halfResolved HalfResolvedArgument) HalfResolvedArgument { + // example + // tuple#9770768a {t:Type} {n:#} [t] = Tuple t n; + // innerMaybe {X:#} a:(Maybe (tuple int X)) = InnerMaybe X; + // when unwrapping we need to change tuple into __tuple + // halfResolved references in field of tuple are to "n", "t" local template args + // we must look up in tuple to replace "n" "t" into "X", "" + var result HalfResolvedArgument + result.Name = trw.replaceUnwrapHalfResolvedName(topHalfResolved, halfResolved.Name) + for _, arg := range halfResolved.Args { + result.Args = append(result.Args, trw.replaceUnwrapHalfResolved(topHalfResolved, arg)) + } + return result +} + func (trw *TypeRWStruct) markWriteHasError(visitedNodes map[*TypeRWWrapper]bool) bool { result := false for _, f := range trw.Fields { @@ -107,12 +135,65 @@ func (trw *TypeRWStruct) markWantsBytesVersion(visitedNodes map[*TypeRWWrapper]b } } -func (trw *TypeRWStruct) BeforeCodeGenerationStep1() { +func (trw *TypeRWStruct) AllPossibleRecursionProducers() []*TypeRWWrapper { + var result []*TypeRWWrapper + for _, typeDep := range trw.wr.arguments { + if typeDep.tip != nil { + result = append(result, typeDep.tip.trw.AllPossibleRecursionProducers()...) + } + } + if !trw.isTypeDef() { + result = append(result, trw.wr) + } + return result +} + +func (trw *TypeRWStruct) AllTypeDependencies() (res []*TypeRWWrapper) { + used := make(map[*TypeRWWrapper]bool) + red := trw.wr.gen.typesInfo.TypeNameToGenericTypeReduction(trw.wr.tlName) + for i, f := range trw.Fields { - visitedNodes := map[*TypeRWWrapper]bool{} - f.t.trw.fillRecursiveChildren(visitedNodes) - trw.Fields[i].recursive = visitedNodes[trw.wr] + fieldRed := trw.wr.gen.typesInfo.FieldTypeReduction(&red, i) + deps := f.t.ActualTypeDependencies(fieldRed) + for _, dep := range deps { + used[dep] = true + } + } + + for tp, _ := range used { + res = append(res, tp) + } + return +} + +func (trw *TypeRWStruct) FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) { + if visitedNodes[trw.wr] != 0 { + return } + *currentPath = append(*currentPath, trw.wr) + visitedNodes[trw.wr] = 1 + for i, f := range trw.Fields { + if f.recursive { + continue + } + for _, typeDep := range f.t.trw.AllPossibleRecursionProducers() { + if visitedNodes[typeDep] == 1 { + trw.Fields[i].recursive = true + } else { + typeDep.trw.FillRecursiveChildren(visitedNodes, currentPath) + } + } + } + *currentPath = (*currentPath)[:len(*currentPath)-1] + visitedNodes[trw.wr] = 2 +} + +func (trw *TypeRWStruct) BeforeCodeGenerationStep1() { + //for i, f := range trw.Fields { + // visitedNodes := map[*TypeRWWrapper]bool{} + // f.t.trw.fillRecursiveChildren(visitedNodes) + // trw.Fields[i].recursive = visitedNodes[trw.wr] + //} trw.setNames = make([]string, len(trw.Fields)) trw.clearNames = make([]string, len(trw.Fields)) trw.isSetNames = make([]string, len(trw.Fields)) diff --git a/internal/tlcodegen/type_rw_struct_cpp.go b/internal/tlcodegen/type_rw_struct_cpp.go index cf6c461..c8b47b8 100644 --- a/internal/tlcodegen/type_rw_struct_cpp.go +++ b/internal/tlcodegen/type_rw_struct_cpp.go @@ -28,13 +28,22 @@ func (trw *TypeRWStruct) cppTypeStringInNamespace(bytesVersion bool, hppInc *Dir } func (trw *TypeRWStruct) cppTypeStringInNamespaceHalfResolved(bytesVersion bool, hppInc *DirectIncludesCPP, halfResolved HalfResolvedArgument) string { - if trw.isUnwrapType() { // TODO - when replacing typedefs, we must make name resolution - return trw.Fields[0].t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolved) // trw.Fields[0].resolvedType + if trw.isUnwrapType() { + halfResolvedUnwrapped := trw.wr.replaceUnwrapHalfResolved(halfResolved, trw.Fields[0].halfResolved) + return trw.Fields[0].t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolvedUnwrapped) } _, _, args := trw.wr.cppTypeStringInNamespace(bytesVersion, hppInc, true, halfResolved) return trw.wr.cppNamespaceQualifier() + trw.wr.cppLocalName + args } +func (trw *TypeRWStruct) cppTypeStringInNamespaceHalfResolved2(bytesVersion bool, typeReduction EvaluatedType) string { + if trw.isUnwrapType() { + eval := trw.wr.gen.typesInfo.FieldTypeReduction(typeReduction.Type, 0) + return trw.Fields[0].t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, eval) + } + return trw.wr.cppNamespaceQualifier() + trw.wr.cppLocalName + trw.wr.cppTypeArguments(bytesVersion, typeReduction.Type) +} + func (trw *TypeRWStruct) cppDefaultInitializer(halfResolved HalfResolvedArgument, halfResolve bool) string { if trw.isUnwrapType() { return trw.Fields[0].t.CPPDefaultInitializer(trw.Fields[0].halfResolved, halfResolve) @@ -73,13 +82,14 @@ func (trw *TypeRWStruct) CPPTypeReadingCode(bytesVersion bool, val string, bare if !bare { prefix = fmt.Sprintf("\ts.nat_read_exact_tag(0x%x);\n", trw.wr.tlTag) } - return prefix + trw.Fields[0].t.trw.CPPTypeReadingCode(bytesVersion, val, trw.Fields[0].Bare(), trw.replaceUnwrapArgs(natArgs), last) + s := prefix + trw.Fields[0].t.trw.CPPTypeReadingCode(bytesVersion, val, trw.Fields[0].Bare(), trw.replaceUnwrapArgs(natArgs), last) + return s } - return fmt.Sprintf("\t::%s::%sRead%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + s := fmt.Sprintf("\t::%s::%sRead%s(s, %s%s);", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return s } func (trw *TypeRWStruct) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool) { - goLocalName := addBytes(trw.wr.goLocalName, bytesVersion) goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) //if trw.wr.unionParent != nil && trw.wr.unionParentIsEnum { // return @@ -95,6 +105,14 @@ func (trw *TypeRWStruct) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectInc if trw.wr.tlName.Namespace != "" { typeNamespace = append(typeNamespace, trw.wr.tlName.Namespace) } + + if !forwardDeclaration { + for _, typeDep := range trw.AllTypeDependencies() { + if typeDep.typeComponent == trw.wr.typeComponent { + typeDep.trw.CPPGenerateCode(hpp, nil, nil, nil, hppDetInc, nil, cppDetInc, bytesVersion, true) + } + } + } cppStartNamespace(hpp, typeNamespace) // hpp.WriteString("// " + goLocalName + "\n") - uncommenting will lead to multiple definition error if len(myArgsDecl) != 0 { @@ -107,26 +125,72 @@ func (trw *TypeRWStruct) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectInc } if trw.isTypeDef() { field := trw.Fields[0] - fieldFullType := field.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, field.halfResolved) - hpp.WriteString(fmt.Sprintf("using %s = %s;", trw.wr.cppLocalName, fieldFullType)) + + if !field.t.origTL[0].Builtin && len(trw.wr.arguments) != 0 { + // TODO TODO TODO temporary solution + ti := trw.wr.gen.typesInfo + tlName := trw.wr.tlName + + _, isType := ti.Types[tlName] + typeReduction := TypeReduction{IsType: isType} + if isType { + typeReduction.Type = ti.Types[tlName] + } else { + typeReduction.Constructor = ti.Constructors[tlName] + } + for i, arg := range typeReduction.ReferenceType().TypeArguments { + evalArg := EvaluatedType{} + if arg.IsNat { + evalArg.Index = 1 + evalArg.Variable = arg.FieldName + if trw.wr.arguments[i].isArith { + // set true only here + evalArg.VariableActsAsConstant = true + } + } else { + evalArg.Index = 3 + evalArg.TypeVariable = arg.FieldName + } + typeReduction.Arguments = append(typeReduction.Arguments, evalArg) + } + + typeRed := ti.FieldTypeReduction(&typeReduction, 0) + for _, typeRw := range trw.Fields[0].t.ActualTypeDependencies(typeRed) { + hppInc.ns[typeRw.fileName] = CppIncludeInfo{componentId: typeRw.typeComponent} + } + hpp.WriteString(fmt.Sprintf("using %s = %s;", trw.wr.cppLocalName, field.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeRed))) + } else { + fieldFullType := field.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, field.halfResolved) + hpp.WriteString(fmt.Sprintf("using %s = %s;", trw.wr.cppLocalName, fieldFullType)) + } } else { hpp.WriteString("struct " + trw.wr.cppLocalName + " {\n") for _, field := range trw.Fields { - fieldFullType := field.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, field.halfResolved) + hppIncByField := DirectIncludesCPP{ns: map[string]CppIncludeInfo{}} + fieldFullType := field.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, &hppIncByField, field.halfResolved) fieldsMaskComment := "" //if field.fieldMask != nil { // fieldsMaskComment = fmt.Sprintf(" // Conditional: %s.%d", formatNatArgCPP(trw.Fields, *field.fieldMask), field.BitNumber) //} if field.recursive { + // TODO make better + for includeType, includeInfo := range hppIncByField.ns { + if includeInfo.componentId == trw.wr.typeComponent { + delete(hppIncByField.ns, includeType) + } + } anyRecursive = true // requires destructor in cpp file hpp.WriteString(fmt.Sprintf("\tstd::shared_ptr<%s> %s{};%s\n", fieldFullType, field.cppName, fieldsMaskComment)) } else { hpp.WriteString(fmt.Sprintf("\t%s %s%s;%s\n", fieldFullType, field.cppName, field.t.CPPDefaultInitializer(field.halfResolved, true), fieldsMaskComment)) } + for includeType, includeInfo := range hppIncByField.ns { + hppInc.ns[includeType] = includeInfo + } //hpp.WriteString(fmt.Sprintf("\t// DebugString: %s\n", field.resolvedType.DebugString())) } if anyRecursive { // && len(trw.cppArgs) != 0 - hpp.WriteString(fmt.Sprintf("\n\t~%s() {}\n", goLocalName)) // TODO - move destructor to cpp + hpp.WriteString(fmt.Sprintf("\n\t~%s() {}\n", trw.wr.cppLocalName)) // TODO - move destructor to cpp // cppDet.WriteString(fmt.Sprintf("%s%s::~%s() {}\n", trw.wr.cppNamespaceQualifier, goLocalName, goLocalName)) } if trw.wr.tlTag != 0 { // anonymous square brackets citizens or other exotic type @@ -223,15 +287,15 @@ void %[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s); myFullType, formatNatArgsDeclCPP(trw.wr.NatParams))) - cppDet.WriteString(fmt.Sprintf(` + s := fmt.Sprintf(` void %[7]s::%[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s) { s.nat_read_exact_tag(0x%08[9]x); - %[1]sRead(s, item%[8]s); + %[7]s::%[1]sRead(s, item%[8]s); } void %[7]s::%[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { s.nat_write(0x%08[9]x); - %[1]sWrite(s, item%[8]s); + %[7]s::%[1]sWrite(s, item%[8]s); } `, goGlobalName, @@ -243,7 +307,8 @@ void %[7]s::%[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { trw.wr.gen.DetailsCPPNamespace, formatNatArgsCallCPP(trw.wr.NatParams), trw.wr.tlTag, - )) + ) + cppDet.WriteString(s) } cppFinishNamespace(hppDet, trw.wr.gen.DetailsCPPNamespaceElements) diff --git a/internal/tlcodegen/type_rw_tuple.go b/internal/tlcodegen/type_rw_tuple.go index ae0f73e..96e6f3f 100644 --- a/internal/tlcodegen/type_rw_tuple.go +++ b/internal/tlcodegen/type_rw_tuple.go @@ -74,6 +74,26 @@ func isDictionaryElement(wr *TypeRWWrapper) (bool, bool, Field, Field) { return ok, isString, structElement.Fields[0], structElement.Fields[1] } +func (trw *TypeRWBrackets) FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) { + for _, typeDep := range trw.AllPossibleRecursionProducers() { + typeDep.trw.FillRecursiveChildren(visitedNodes, currentPath) + } +} + +func (trw *TypeRWBrackets) AllPossibleRecursionProducers() []*TypeRWWrapper { + var result []*TypeRWWrapper + for _, typeDep := range trw.wr.arguments { + if typeDep.tip != nil { + result = append(result, typeDep.tip.trw.AllPossibleRecursionProducers()...) + } + } + return result +} + +func (trw *TypeRWBrackets) AllTypeDependencies() (res []*TypeRWWrapper) { + return nil +} + func (trw *TypeRWBrackets) BeforeCodeGenerationStep1() { if trw.vectorLike { if ok, isString, kf, vf := isDictionaryElement(trw.element.t); ok { diff --git a/internal/tlcodegen/type_rw_tuple_cpp.go b/internal/tlcodegen/type_rw_tuple_cpp.go index be3c008..356a8eb 100644 --- a/internal/tlcodegen/type_rw_tuple_cpp.go +++ b/internal/tlcodegen/type_rw_tuple_cpp.go @@ -19,7 +19,7 @@ func (trw *TypeRWBrackets) CPPFillRecursiveChildren(visitedNodes map[*TypeRWWrap } func (trw *TypeRWBrackets) cppTypeStringInNamespace(bytesVersion bool, hppInc *DirectIncludesCPP) string { - hppInc.ns[trw.wr.fileName] = struct{}{} + hppInc.ns[trw.wr.fileName] = CppIncludeInfo{componentId: trw.wr.typeComponent} //if trw.dictLike && !bytesVersion { // TODO - which arguments must map have is very complicated //return fmt.Sprintf("std::map<%s, %s>", @@ -51,6 +51,19 @@ func (trw *TypeRWBrackets) cppTypeStringInNamespaceHalfResolved(bytesVersion boo return fmt.Sprintf("std::array<%s, %d>", trw.element.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, halfResolved.Args[1]), trw.size) } +func (trw *TypeRWBrackets) cppTypeStringInNamespaceHalfResolved2(bytesVersion bool, typeReduction EvaluatedType) string { + switch len(typeReduction.Type.Arguments) { + case 1: + return fmt.Sprintf("std::vector<%s>", trw.element.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeReduction.Type.Arguments[0])) + case 2: + if typeReduction.Type.Arguments[1].VariableActsAsConstant { + return fmt.Sprintf("std::array<%s, %s>", trw.element.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeReduction.Type.Arguments[0]), typeReduction.Type.Arguments[1].Variable) + } + return fmt.Sprintf("std::vector<%s>", trw.element.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeReduction.Type.Arguments[0])) + } + return "" +} + func (trw *TypeRWBrackets) cppDefaultInitializer(halfResolved HalfResolvedArgument, halfResolve bool) string { if trw.vectorLike || trw.dynamicSize { return "" @@ -84,6 +97,10 @@ func (trw *TypeRWBrackets) CPPTypeReadingCode(bytesVersion bool, val string, bar } func (trw *TypeRWBrackets) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool) { + if forwardDeclaration { + trw.element.t.trw.CPPGenerateCode(hpp, hppInc, hppIncFwd, hppDet, hppDetInc, cppDet, cppDetInc, bytesVersion, true) + return + } cppStartNamespace(hppDet, trw.wr.gen.DetailsCPPNamespaceElements) hppDetCode := ` diff --git a/internal/tlcodegen/type_rw_union.go b/internal/tlcodegen/type_rw_union.go index ba7dd08..062c2c9 100644 --- a/internal/tlcodegen/type_rw_union.go +++ b/internal/tlcodegen/type_rw_union.go @@ -51,15 +51,49 @@ func (trw *TypeRWUnion) markWantsBytesVersion(visitedNodes map[*TypeRWWrapper]bo } } +func (trw *TypeRWUnion) FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) { + if visitedNodes[trw.wr] != 0 { + return + } + *currentPath = append(*currentPath, trw.wr) + visitedNodes[trw.wr] = 1 + for _, f := range trw.Fields { + if f.recursive { + continue + } + f.t.trw.FillRecursiveChildren(visitedNodes, currentPath) + } + *currentPath = (*currentPath)[:len(*currentPath)-1] + visitedNodes[trw.wr] = 2 +} + +func (trw *TypeRWUnion) AllPossibleRecursionProducers() []*TypeRWWrapper { + var result []*TypeRWWrapper + for _, typeDep := range trw.wr.arguments { + if typeDep.tip != nil { + result = append(result, typeDep.tip.trw.AllPossibleRecursionProducers()...) + } + } + result = append(result, trw.wr) + return result +} + +func (trw *TypeRWUnion) AllTypeDependencies() (res []*TypeRWWrapper) { + for _, f := range trw.Fields { + res = append(res, f.t) + } + return +} + func (trw *TypeRWUnion) BeforeCodeGenerationStep1() { } func (trw *TypeRWUnion) BeforeCodeGenerationStep2() { - for i, f := range trw.Fields { - visitedNodes := map[*TypeRWWrapper]bool{} - f.t.trw.fillRecursiveChildren(visitedNodes) - trw.Fields[i].recursive = visitedNodes[trw.wr] - } + //for i, f := range trw.Fields { + // visitedNodes := map[*TypeRWWrapper]bool{} + // f.t.trw.fillRecursiveChildren(visitedNodes) + // trw.Fields[i].recursive = visitedNodes[trw.wr] + //} //if trw.wr.gen.options.Language == "cpp" { // Temporary solution to benchmark combined tl // var nf []Field // for _, f := range trw.Fields { diff --git a/internal/tlcodegen/type_rw_union_cpp.go b/internal/tlcodegen/type_rw_union_cpp.go index e1fd3c6..1dae153 100644 --- a/internal/tlcodegen/type_rw_union_cpp.go +++ b/internal/tlcodegen/type_rw_union_cpp.go @@ -29,6 +29,10 @@ func (trw *TypeRWUnion) cppTypeStringInNamespaceHalfResolved(bytesVersion bool, return trw.wr.cppNamespaceQualifier() + trw.wr.cppLocalName + args } +func (trw *TypeRWUnion) cppTypeStringInNamespaceHalfResolved2(bytesVersion bool, typeReduction EvaluatedType) string { + return "" +} + func (trw *TypeRWUnion) cppDefaultInitializer(halfResolved HalfResolvedArgument, halfResolve bool) string { return "" } @@ -58,10 +62,25 @@ func (trw *TypeRWUnion) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncl _, myArgsDecl := trw.wr.fullyResolvedClassCppNameArgs() myFullType := trw.cppTypeStringInNamespace(bytesVersion, hppDetInc) - fmt.Printf("Ts: %s %s\n", myFullType, strings.Join(myArgsDecl, ", ")) - fmt.Printf(" %s\n", trw.wr.cppLocalName) + //fmt.Printf("Ts: %s %s\n", myFullType, strings.Join(myArgsDecl, ", ")) + //fmt.Printf(" %s\n", trw.wr.cppLocalName) myFullTypeNoPrefix := strings.TrimPrefix(myFullType, "::") // Stupid C++ has sometimes problems with name resolution of definitions + typeNamespace := trw.wr.gen.RootCPPNamespaceElements + if trw.wr.tlName.Namespace != "" { + typeNamespace = append(typeNamespace, trw.wr.tlName.Namespace) + } + + if forwardDeclaration { + cppStartNamespace(hpp, typeNamespace) + if len(myArgsDecl) != 0 { + hpp.WriteString("template<" + strings.Join(myArgsDecl, ", ") + ">\n") + } + hpp.WriteString("struct " + trw.wr.cppLocalName + ";") + cppFinishNamespace(hpp, typeNamespace) + return + } + cppStartNamespace(hppDet, trw.wr.gen.DetailsCPPNamespaceElements) hppDet.WriteString(fmt.Sprintf(` void %[1]sReset(%[2]s& item); @@ -71,15 +90,12 @@ void %[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s); cppFinishNamespace(hppDet, trw.wr.gen.DetailsCPPNamespaceElements) - for _, field := range trw.Fields { - if field.recursive { - field.t.trw.CPPGenerateCode(hpp, nil, nil, nil, hppDetInc, nil, cppDetInc, bytesVersion, true) + for _, typeDep := range trw.AllTypeDependencies() { + if typeDep.typeComponent == trw.wr.typeComponent { + typeDep.trw.CPPGenerateCode(hpp, nil, nil, nil, hppDetInc, nil, cppDetInc, bytesVersion, true) } } - typeNamespace := trw.wr.gen.RootCPPNamespaceElements - if trw.wr.tlName.Namespace != "" { - typeNamespace = append(typeNamespace, trw.wr.tlName.Namespace) - } + cppStartNamespace(hpp, typeNamespace) if len(myArgsDecl) != 0 { hpp.WriteString("template<" + strings.Join(myArgsDecl, ", ") + ">\n") @@ -125,8 +141,8 @@ static const uint32_t %[1]s_tbl_tl_tag[]{%[3]s}; `, formatNatArgsDeclCPP(trw.wr.NatParams), trw.CPPTypeResettingCode(bytesVersion, "*this"), - trw.CPPTypeReadingCode(bytesVersion, "*this", false, trw.wr.NatParams, true), - trw.CPPTypeWritingCode(bytesVersion, "*this", false, trw.wr.NatParams, true))) + trw.CPPTypeReadingCode(bytesVersion, "*this", false, formatNatArgsAddNat(trw.wr.NatParams), true), + trw.CPPTypeWritingCode(bytesVersion, "*this", false, formatNatArgsAddNat(trw.wr.NatParams), true))) cppDet.WriteString(fmt.Sprintf(` void %[5]s::read_boxed(::basictl::tl_istream & s%[1]s) { %[3]s @@ -144,8 +160,8 @@ uint32_t %[5]s::tl_tag() const { `, formatNatArgsDeclCPP(trw.wr.NatParams), trw.CPPTypeResettingCode(bytesVersion, "*this"), - trw.CPPTypeReadingCode(bytesVersion, "*this", false, trw.wr.NatParams, true), - trw.CPPTypeWritingCode(bytesVersion, "*this", false, trw.wr.NatParams, true), + trw.CPPTypeReadingCode(bytesVersion, "*this", false, formatNatArgsAddNat(trw.wr.NatParams), true), + trw.CPPTypeWritingCode(bytesVersion, "*this", false, formatNatArgsAddNat(trw.wr.NatParams), true), myFullTypeNoPrefix, goGlobalName)) } @@ -414,9 +430,14 @@ func (trw *TypeRWUnion) CPPWriteFields(bytesVersion bool) string { func (trw *TypeRWUnion) CPPSetters(bytesVersion bool) string { var s strings.Builder + _, myArgsDecl := trw.wr.fullyResolvedClassCppNameArgs() for fieldIndex, field := range trw.Fields { if field.t.IsTrueType() { - s.WriteString(fmt.Sprintf("\tvoid set_%s() { value.emplace<%d>({}); }\n", field.cppName, fieldIndex)) + initValue := "" + if len(myArgsDecl) != 0 { + initValue = "{}" + } + s.WriteString(fmt.Sprintf("\tvoid set_%s() { value.emplace<%d>(%s); }\n", field.cppName, fieldIndex, initValue)) } } return s.String() From 2a8772a98360e8e48ba4a08a2e01d9ed11b47628 Mon Sep 17 00:00:00 2001 From: Brat-vseznamus Date: Wed, 12 Jun 2024 18:40:06 +0300 Subject: [PATCH 06/10] test cpp file for example --- internal/tlcodegen/test/gen/test_cpp.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/internal/tlcodegen/test/gen/test_cpp.cpp b/internal/tlcodegen/test/gen/test_cpp.cpp index 855fe48..7e8d9f0 100644 --- a/internal/tlcodegen/test/gen/test_cpp.cpp +++ b/internal/tlcodegen/test/gen/test_cpp.cpp @@ -1,6 +1,5 @@ #include #include "cpp/a.top2.hpp" -#include "cpp/a.top3.hpp" std::string to_hex(const uint8_t *data, size_t count) { static const char hexdigits[] = "0123456789abcdef"; @@ -16,6 +15,8 @@ std::string to_hex(const uint8_t *data, size_t count) { int main() { basictl::tl_ostream_string str; + basictl::tl_ostream_string str2; + tl2::a::Top2 top2; @@ -23,18 +24,8 @@ int main() { auto & buf = str.get_buffer(); std::cout << top2.tl_name() << ": " << to_hex(reinterpret_cast(buf.data()), buf.size()) << std::endl; - tl2::a::Top3 top3; - top3.n = 2; - // top3.a.a = "Hi!"; - top3.c.b.a.a.push_back(5); - top3.c.b.a.a.push_back(7); - - basictl::tl_ostream_string str2; - - top3.write(str2); - - auto & buf2 = str2.get_buffer(); - std::cout << top3.tl_name() << ": " << to_hex(reinterpret_cast(buf2.data()), buf2.size()) << std::endl; +// top3.write(str2); +// std::cout << top3.tl_name() << ": " << to_hex(reinterpret_cast(buf2.data()), buf2.size()) << std::endl; return 0; } From 294bcd498cd6580e24b54980261a81997651b2b6 Mon Sep 17 00:00:00 2001 From: Brat-vseznamus Date: Mon, 17 Jun 2024 14:05:36 +0300 Subject: [PATCH 07/10] stabilize orders --- internal/tlcodegen/tlgen.go | 88 +++++++++++++----------- internal/tlcodegen/type_rw.go | 3 + internal/tlcodegen/type_rw_struct_cpp.go | 6 +- 3 files changed, 55 insertions(+), 42 deletions(-) diff --git a/internal/tlcodegen/tlgen.go b/internal/tlcodegen/tlgen.go index de7b7b0..4f092b2 100644 --- a/internal/tlcodegen/tlgen.go +++ b/internal/tlcodegen/tlgen.go @@ -8,6 +8,7 @@ package tlcodegen import ( "fmt" + "github.com/google/go-cmp/cmp" "io" "log" "os" @@ -694,6 +695,9 @@ func (gen *Gen2) WriteToDir(outdir string) error { if string(was) == code { notTouched++ continue + } else { + fmt.Printf("File \"%s\":\n", f) + fmt.Println(cmp.Diff(string(was), code)) } } if filepathName != TlJSONHTML { // not deterministic, do not write marker if json help changed @@ -715,9 +719,9 @@ func (gen *Gen2) WriteToDir(outdir string) error { } for filepathName := range relativeFiles { f := filepath.Join(outdir, filepathName) - //if strings.HasSuffix(f, ".o") { - // continue - //} + if strings.HasSuffix(f, ".o") { + continue + } deleted++ if err := os.Remove(f); err != nil { return fmt.Errorf("error deleting previous file %q: %w", f, err) @@ -1141,6 +1145,10 @@ func GenerateCode(tl tlast.TL, options Gen2Options) (*Gen2, error) { fmt.Printf("prevented unwrap of %v\n", v.tlName) } } + + _, order := findAllTypesDependencyComponents(sortedTypes) + gen.componentsOrder = order + // in BeforeCodeGenerationStep we split recursion. Which links will be broken depends on order of nodes visited for _, v := range sortedTypes { if len(v.arguments) == 0 { @@ -1150,36 +1158,6 @@ func GenerateCode(tl tlast.TL, options Gen2Options) (*Gen2, error) { } } - _, order := findAllTypesDependencyComponents(sortedTypes) - gen.componentsOrder = order - - //deps, order := findAllTypesDependencyComponents(sortedTypes) - //gen.componentsOrder = order - // - //compoments := make(map[int][]*TypeRWWrapper) - //cmpnts := make([]int, 0) - // - //for _, v := range sortedTypes { - // if _, ok := compoments[v.typeComponent]; !ok { - // cmpnts = append(cmpnts, v.typeComponent) - // } - // compoments[v.typeComponent] = append(compoments[v.typeComponent], v) - //} - // - //sort.Ints(cmpnts) - // - //for i, _ := range cmpnts { - // cId := order[i] - // curDeps := make([]int, 0) - // for dep, _ := range deps[cId] { - // curDeps = append(curDeps, dep) - // } - // fmt.Printf("C[%d]: %v\n", cId, curDeps) - // for _, tp := range compoments[cId] { - // fmt.Printf("\tGo: %s, TL: %s\n", tp.goGlobalName, tp.tlName.String()) - // } - //} - for _, v := range sortedTypes { v.trw.BeforeCodeGenerationStep1() } @@ -1251,6 +1229,19 @@ func GenerateCode(tl tlast.TL, options Gen2Options) (*Gen2, error) { return gen, nil } +var TypeComparator = func(a, b *TypeRWWrapper) int { + return strings.Compare(a.goGlobalName, b.goGlobalName) +} + +func stabilizeOrder(mp *map[*TypeRWWrapper][]*TypeRWWrapper) (keyOrder []*TypeRWWrapper) { + for k, v := range *mp { + slices.SortFunc(v, TypeComparator) + keyOrder = append(keyOrder, k) + } + slices.SortFunc(keyOrder, TypeComparator) + return +} + func findAllTypesDependencyComponents(types []*TypeRWWrapper) (map[int]map[int]bool, []int) { dependencyGraph := make(map[*TypeRWWrapper][]*TypeRWWrapper) reverseDependencyGraph := make(map[*TypeRWWrapper][]*TypeRWWrapper) @@ -1263,6 +1254,9 @@ func findAllTypesDependencyComponents(types []*TypeRWWrapper) (map[int]map[int]b } } + _ = stabilizeOrder(&dependencyGraph) + _ = stabilizeOrder(&reverseDependencyGraph) + visitedTypes := make(map[*TypeRWWrapper]bool) order := make([]*TypeRWWrapper, 0) for _, tp := range types { @@ -1303,12 +1297,27 @@ func findAllTypesDependencyComponents(types []*TypeRWWrapper) (map[int]map[int]b } } + componentsOrdered := make([]int, 0) + componentsDepsOrdered := make(map[int][]int) + + for componentId, itsDeps := range componentsDeps { + componentsOrdered = append(componentsOrdered, componentId) + list := make([]int, len(itsDeps)) + for dep, _ := range itsDeps { + list = append(list, dep) + } + sort.Ints(list) + componentsDepsOrdered[componentId] = list + } + + sort.Ints(componentsOrdered) + compOrder := make([]int, 0) compVisited := make(map[int]bool) - for cmp := range componentsDeps { - if !compVisited[cmp] { - sortComponents(cmp, &compVisited, &componentsDeps, &compOrder) + for comp := range componentsOrdered { + if !compVisited[comp] { + sortComponents(comp, &compVisited, &componentsDepsOrdered, &compOrder) } } @@ -1345,9 +1354,9 @@ func findAllTypesDependencyComponentsStep2( } } -func sortComponents(target int, visited *map[int]bool, deps *map[int]map[int]bool, order *[]int) { +func sortComponents(target int, visited *map[int]bool, deps *map[int][]int, order *[]int) { (*visited)[target] = true - for next, _ := range (*deps)[target] { + for _, next := range (*deps)[target] { if !(*visited)[next] { sortComponents(next, visited, deps, order) } @@ -1449,9 +1458,6 @@ func processCombinators(types map[string]*tlast.Combinator) *TypesInfo { existingConstructors := make(map[ConstructorName]*Constructor) for _, comb := range types { - //if comb.IsFunction { - // continue - //} declaredType := comb.TypeDecl.Name if comb.Builtin { declaredType = comb.Construct.Name diff --git a/internal/tlcodegen/type_rw.go b/internal/tlcodegen/type_rw.go index c7520ec..2d20834 100644 --- a/internal/tlcodegen/type_rw.go +++ b/internal/tlcodegen/type_rw.go @@ -9,6 +9,7 @@ package tlcodegen import ( "fmt" "regexp" + "sort" "strconv" "strings" @@ -246,6 +247,7 @@ func (d DirectIncludesCPP) sortedNames() []string { for im := range d.ns { // Imports of this file. sortedNames = append(sortedNames, im) } + sort.Strings(sortedNames) return sortedNames } @@ -263,6 +265,7 @@ func (d DirectIncludesCPP) sortedIncludes(componentOrder []int) (result []string } for _, files := range filesByCID { + sort.Strings(files) for _, f := range files { result = append(result, f) } diff --git a/internal/tlcodegen/type_rw_struct_cpp.go b/internal/tlcodegen/type_rw_struct_cpp.go index c8b47b8..eaeb512 100644 --- a/internal/tlcodegen/type_rw_struct_cpp.go +++ b/internal/tlcodegen/type_rw_struct_cpp.go @@ -8,6 +8,7 @@ package tlcodegen import ( "fmt" + "golang.org/x/exp/slices" "strings" ) @@ -107,7 +108,10 @@ func (trw *TypeRWStruct) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectInc } if !forwardDeclaration { - for _, typeDep := range trw.AllTypeDependencies() { + deps := trw.AllTypeDependencies() + slices.SortFunc(deps, TypeComparator) + + for _, typeDep := range deps { if typeDep.typeComponent == trw.wr.typeComponent { typeDep.trw.CPPGenerateCode(hpp, nil, nil, nil, hppDetInc, nil, cppDetInc, bytesVersion, true) } From 7303e40e5035a187f332b1f1da0ef72696091bc1 Mon Sep 17 00:00:00 2001 From: Brat-vseznamus Date: Tue, 18 Jun 2024 16:38:07 +0300 Subject: [PATCH 08/10] field type fix --- internal/tlcodegen/tlgen.go | 8 ++- internal/tlcodegen/tlgen_cpp.go | 9 ++- internal/tlcodegen/type_rw.go | 18 ++++-- internal/tlcodegen/type_rw_bool.go | 4 ++ internal/tlcodegen/type_rw_maybe.go | 4 ++ internal/tlcodegen/type_rw_primitive.go | 4 ++ internal/tlcodegen/type_rw_struct.go | 4 ++ internal/tlcodegen/type_rw_struct_cpp.go | 82 ++++++++++++++---------- internal/tlcodegen/type_rw_tuple.go | 4 ++ internal/tlcodegen/type_rw_tuple_cpp.go | 6 +- internal/tlcodegen/type_rw_union.go | 4 ++ internal/tlcodegen/type_rw_union_cpp.go | 2 +- 12 files changed, 97 insertions(+), 52 deletions(-) diff --git a/internal/tlcodegen/tlgen.go b/internal/tlcodegen/tlgen.go index 4f092b2..01526f9 100644 --- a/internal/tlcodegen/tlgen.go +++ b/internal/tlcodegen/tlgen.go @@ -1657,18 +1657,20 @@ func fillTypeReduction( for argI, arg := range typeReduction.Arguments { switch arg.Index { // nat var - case 1: + case NumberVariable: j := findArgByName(arg.Variable, originalType.TypeArguments) if j != -1 && args[j].Index == NumberConstant { typeReduction.Arguments[argI] = args[j] + } else if j != -1 && args[j].Index == NumberVariable && args[j].VariableActsAsConstant { + typeReduction.Arguments[argI].VariableActsAsConstant = true } else if _, ok := (*defaultFields)[arg.Variable]; ok { typeReduction.Arguments[argI] = EvaluatedType{Index: NumberConstant, Constant: 0} } // type - case 2: + case TypeConstant: fillTypeReduction(arg.Type, args, originalType, defaultFields) // type var - case 3: + case TypeVariable: j := findArgByName(arg.TypeVariable, originalType.TypeArguments) if j != -1 { index := args[j].Index diff --git a/internal/tlcodegen/tlgen_cpp.go b/internal/tlcodegen/tlgen_cpp.go index f681f92..b429817 100644 --- a/internal/tlcodegen/tlgen_cpp.go +++ b/internal/tlcodegen/tlgen_cpp.go @@ -78,7 +78,7 @@ func (gen *Gen2) generateCodeCPP(generateByteVersions []string) error { hpp.WriteString("#pragma once\n\n") hppDet.WriteString("#pragma once\n\n") hpp.WriteString(fmt.Sprintf("#include \"%s\"\n", basicTLFilepathName)) - for _, n := range hppInc.sortedNames() { + for _, n := range hppInc.sortedIncludes(gen.componentsOrder) { hpp.WriteString(fmt.Sprintf("#include \"%s%s\"\n", n, hppExt)) } hpp.WriteString("\n\n") @@ -88,11 +88,14 @@ func (gen *Gen2) generateCodeCPP(generateByteVersions []string) error { // for _, n := range hppIncFwd.sortedNames() { // hpp.WriteString(fmt.Sprintf("#include \"%s%s\"\n", n, hppExt)) // } - for _, n := range hppDetInc.sortedNames() { + for _, n := range hppDetInc.sortedIncludes(gen.componentsOrder) { hppDet.WriteString(fmt.Sprintf("#include \"../%s%s\"\n", n, hppExt)) } cppDet.WriteString(fmt.Sprintf("#include \"%s_details%s\"\n", ff.fileName, hppExt)) - for _, n := range cppDetInc.sortedNames() { + for _, n := range cppDetInc.sortedIncludes(gen.componentsOrder) { + if n == ff.fileName { + continue + } cppDet.WriteString(fmt.Sprintf("#include \"%s_details%s\"\n", n, hppExt)) } filepathName := ff.fileName + hppExt diff --git a/internal/tlcodegen/type_rw.go b/internal/tlcodegen/type_rw.go index 2d20834..ab198a7 100644 --- a/internal/tlcodegen/type_rw.go +++ b/internal/tlcodegen/type_rw.go @@ -89,8 +89,7 @@ type TypeRWWrapper struct { WrLong *TypeRWWrapper // long transitioning code WrWithoutLong *TypeRWWrapper // long transitioning code - typeComponent int - forwardDeclarations map[*TypeRWWrapper]bool + typeComponent int } // Those have unique structure fully defined by the magic. @@ -259,9 +258,13 @@ func (d DirectIncludesCPP) sortedIncludes(componentOrder []int) (result []string } filesByCID := make([][]string, len(componentOrder)) + used := make(map[string]bool) for im, cppInfo := range d.ns { // Imports of this file. - filesByCID[compIdToPosition[cppInfo.componentId]] = append(filesByCID[compIdToPosition[cppInfo.componentId]], im) + if !used[im] { + used[im] = true + filesByCID[compIdToPosition[cppInfo.componentId]] = append(filesByCID[compIdToPosition[cppInfo.componentId]], im) + } } for _, files := range filesByCID { @@ -477,15 +480,15 @@ func (w *TypeRWWrapper) cppTypeArguments(bytesVersion bool, typeRedaction *TypeR for i, a := range w.arguments { evalArg := typeRedaction.Arguments[i] if a.isNat { - if evalArg.Index == 0 { + if evalArg.Index == NumberConstant { arguments = append(arguments, strconv.FormatInt(int64(evalArg.Constant), 10)) - } else if evalArg.Index == 1 && evalArg.VariableActsAsConstant { + } else if evalArg.Index == NumberVariable && evalArg.VariableActsAsConstant { arguments = append(arguments, evalArg.Variable) } } else { - if evalArg.Index == 3 { + if evalArg.Index == TypeVariable { arguments = append(arguments, evalArg.TypeVariable) - } else if evalArg.Index == 2 { + } else if evalArg.Index == TypeConstant { arguments = append(arguments, a.tip.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, evalArg)) } } @@ -646,6 +649,7 @@ type TypeRW interface { FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) AllPossibleRecursionProducers() []*TypeRWWrapper AllTypeDependencies() []*TypeRWWrapper + IsWrappingType() bool BeforeCodeGenerationStep1() // during first phase, some wr.trw are nil due to recursive types. So we delay some BeforeCodeGenerationStep2() // during second phase, union fields recursive bit is set diff --git a/internal/tlcodegen/type_rw_bool.go b/internal/tlcodegen/type_rw_bool.go index 7739a5c..d112ce4 100644 --- a/internal/tlcodegen/type_rw_bool.go +++ b/internal/tlcodegen/type_rw_bool.go @@ -50,6 +50,10 @@ func (trw *TypeRWBool) AllTypeDependencies() []*TypeRWWrapper { return nil } +func (trw *TypeRWBool) IsWrappingType() bool { + return true +} + func (trw *TypeRWBool) FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) { } diff --git a/internal/tlcodegen/type_rw_maybe.go b/internal/tlcodegen/type_rw_maybe.go index cba95ef..6b863da 100644 --- a/internal/tlcodegen/type_rw_maybe.go +++ b/internal/tlcodegen/type_rw_maybe.go @@ -48,6 +48,10 @@ func (trw *TypeRWMaybe) AllTypeDependencies() []*TypeRWWrapper { return nil } +func (trw *TypeRWMaybe) IsWrappingType() bool { + return true +} + func (trw *TypeRWMaybe) FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) { visitedNodes[trw.wr] = 1 trw.element.t.trw.FillRecursiveChildren(visitedNodes, currentPath) diff --git a/internal/tlcodegen/type_rw_primitive.go b/internal/tlcodegen/type_rw_primitive.go index 56eed8e..5ce4e0b 100644 --- a/internal/tlcodegen/type_rw_primitive.go +++ b/internal/tlcodegen/type_rw_primitive.go @@ -66,6 +66,10 @@ func (trw *TypeRWPrimitive) AllTypeDependencies() []*TypeRWWrapper { return nil } +func (trw *TypeRWPrimitive) IsWrappingType() bool { + return true +} + func (trw *TypeRWPrimitive) FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) { } diff --git a/internal/tlcodegen/type_rw_struct.go b/internal/tlcodegen/type_rw_struct.go index ba539c7..4b801c9 100644 --- a/internal/tlcodegen/type_rw_struct.go +++ b/internal/tlcodegen/type_rw_struct.go @@ -166,6 +166,10 @@ func (trw *TypeRWStruct) AllTypeDependencies() (res []*TypeRWWrapper) { return } +func (trw *TypeRWStruct) IsWrappingType() bool { + return trw.isUnwrapType() +} + func (trw *TypeRWStruct) FillRecursiveChildren(visitedNodes map[*TypeRWWrapper]int, currentPath *[]*TypeRWWrapper) { if visitedNodes[trw.wr] != 0 { return diff --git a/internal/tlcodegen/type_rw_struct_cpp.go b/internal/tlcodegen/type_rw_struct_cpp.go index eaeb512..120ad63 100644 --- a/internal/tlcodegen/type_rw_struct_cpp.go +++ b/internal/tlcodegen/type_rw_struct_cpp.go @@ -127,51 +127,63 @@ func (trw *TypeRWStruct) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectInc cppFinishNamespace(hpp, typeNamespace) return } - if trw.isTypeDef() { - field := trw.Fields[0] - if !field.t.origTL[0].Builtin && len(trw.wr.arguments) != 0 { - // TODO TODO TODO temporary solution - ti := trw.wr.gen.typesInfo - tlName := trw.wr.tlName + ti := trw.wr.gen.typesInfo + tlName := trw.wr.tlName - _, isType := ti.Types[tlName] - typeReduction := TypeReduction{IsType: isType} - if isType { - typeReduction.Type = ti.Types[tlName] - } else { - typeReduction.Constructor = ti.Constructors[tlName] - } - for i, arg := range typeReduction.ReferenceType().TypeArguments { - evalArg := EvaluatedType{} - if arg.IsNat { - evalArg.Index = 1 - evalArg.Variable = arg.FieldName - if trw.wr.arguments[i].isArith { - // set true only here - evalArg.VariableActsAsConstant = true - } - } else { - evalArg.Index = 3 - evalArg.TypeVariable = arg.FieldName - } - typeReduction.Arguments = append(typeReduction.Arguments, evalArg) + _, isType := ti.Types[tlName] + typeReduction := TypeReduction{IsType: isType} + if isType { + typeReduction.Type = ti.Types[tlName] + } else { + typeReduction.Constructor = ti.Constructors[tlName] + } + for i, arg := range typeReduction.ReferenceType().TypeArguments { + evalArg := EvaluatedType{} + if arg.IsNat { + evalArg.Index = 1 + evalArg.Variable = arg.FieldName + if trw.wr.arguments[i].isArith { + // set true only here + evalArg.VariableActsAsConstant = true } + } else { + evalArg.Index = 3 + evalArg.TypeVariable = arg.FieldName + } + typeReduction.Arguments = append(typeReduction.Arguments, evalArg) + } - typeRed := ti.FieldTypeReduction(&typeReduction, 0) - for _, typeRw := range trw.Fields[0].t.ActualTypeDependencies(typeRed) { + if trw.isTypeDef() { + field := trw.Fields[0] + + //if !field.t.origTL[0].Builtin && len(trw.wr.arguments) != 0 { + typeRed := ti.FieldTypeReduction(&typeReduction, 0) + typeDependencies := field.t.ActualTypeDependencies(typeRed) + for _, typeRw := range typeDependencies { + if typeRw.cppLocalName != "" { hppInc.ns[typeRw.fileName] = CppIncludeInfo{componentId: typeRw.typeComponent} } - hpp.WriteString(fmt.Sprintf("using %s = %s;", trw.wr.cppLocalName, field.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeRed))) - } else { - fieldFullType := field.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, field.halfResolved) - hpp.WriteString(fmt.Sprintf("using %s = %s;", trw.wr.cppLocalName, fieldFullType)) } + hpp.WriteString(fmt.Sprintf("using %s = %s;", trw.wr.cppLocalName, field.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeRed))) + //} else { + // fieldFullType := field.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, hppInc, field.halfResolved) + // hpp.WriteString(fmt.Sprintf("using %s = %s;", trw.wr.cppLocalName, fieldFullType)) + //} } else { hpp.WriteString("struct " + trw.wr.cppLocalName + " {\n") - for _, field := range trw.Fields { + for i, field := range trw.Fields { hppIncByField := DirectIncludesCPP{ns: map[string]CppIncludeInfo{}} - fieldFullType := field.t.CPPTypeStringInNamespaceHalfResolved(bytesVersion, &hppIncByField, field.halfResolved) + + typeRed := ti.FieldTypeReduction(&typeReduction, i) + for _, typeRw := range trw.Fields[i].t.ActualTypeDependencies(typeRed) { + if typeRw.trw.IsWrappingType() { + continue + } + hppIncByField.ns[typeRw.fileName] = CppIncludeInfo{componentId: typeRw.typeComponent} + } + + fieldFullType := field.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeRed) fieldsMaskComment := "" //if field.fieldMask != nil { // fieldsMaskComment = fmt.Sprintf(" // Conditional: %s.%d", formatNatArgCPP(trw.Fields, *field.fieldMask), field.BitNumber) diff --git a/internal/tlcodegen/type_rw_tuple.go b/internal/tlcodegen/type_rw_tuple.go index 96e6f3f..ace31ae 100644 --- a/internal/tlcodegen/type_rw_tuple.go +++ b/internal/tlcodegen/type_rw_tuple.go @@ -94,6 +94,10 @@ func (trw *TypeRWBrackets) AllTypeDependencies() (res []*TypeRWWrapper) { return nil } +func (trw *TypeRWBrackets) IsWrappingType() bool { + return false +} + func (trw *TypeRWBrackets) BeforeCodeGenerationStep1() { if trw.vectorLike { if ok, isString, kf, vf := isDictionaryElement(trw.element.t); ok { diff --git a/internal/tlcodegen/type_rw_tuple_cpp.go b/internal/tlcodegen/type_rw_tuple_cpp.go index 356a8eb..832348c 100644 --- a/internal/tlcodegen/type_rw_tuple_cpp.go +++ b/internal/tlcodegen/type_rw_tuple_cpp.go @@ -56,10 +56,10 @@ func (trw *TypeRWBrackets) cppTypeStringInNamespaceHalfResolved2(bytesVersion bo case 1: return fmt.Sprintf("std::vector<%s>", trw.element.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeReduction.Type.Arguments[0])) case 2: - if typeReduction.Type.Arguments[1].VariableActsAsConstant { - return fmt.Sprintf("std::array<%s, %s>", trw.element.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeReduction.Type.Arguments[0]), typeReduction.Type.Arguments[1].Variable) + if typeReduction.Type.Arguments[0].VariableActsAsConstant { + return fmt.Sprintf("std::array<%s, %s>", trw.element.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeReduction.Type.Arguments[1]), typeReduction.Type.Arguments[0].Variable) } - return fmt.Sprintf("std::vector<%s>", trw.element.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeReduction.Type.Arguments[0])) + return fmt.Sprintf("std::vector<%s>", trw.element.t.CPPTypeStringInNamespaceHalfResolved2(bytesVersion, typeReduction.Type.Arguments[1])) } return "" } diff --git a/internal/tlcodegen/type_rw_union.go b/internal/tlcodegen/type_rw_union.go index 062c2c9..2dcefc5 100644 --- a/internal/tlcodegen/type_rw_union.go +++ b/internal/tlcodegen/type_rw_union.go @@ -85,6 +85,10 @@ func (trw *TypeRWUnion) AllTypeDependencies() (res []*TypeRWWrapper) { return } +func (trw *TypeRWUnion) IsWrappingType() bool { + return false +} + func (trw *TypeRWUnion) BeforeCodeGenerationStep1() { } diff --git a/internal/tlcodegen/type_rw_union_cpp.go b/internal/tlcodegen/type_rw_union_cpp.go index 1dae153..3d595e4 100644 --- a/internal/tlcodegen/type_rw_union_cpp.go +++ b/internal/tlcodegen/type_rw_union_cpp.go @@ -30,7 +30,7 @@ func (trw *TypeRWUnion) cppTypeStringInNamespaceHalfResolved(bytesVersion bool, } func (trw *TypeRWUnion) cppTypeStringInNamespaceHalfResolved2(bytesVersion bool, typeReduction EvaluatedType) string { - return "" + return trw.wr.cppNamespaceQualifier() + trw.wr.cppLocalName + trw.wr.cppTypeArguments(bytesVersion, typeReduction.Type) } func (trw *TypeRWUnion) cppDefaultInitializer(halfResolved HalfResolvedArgument, halfResolve bool) string { From 2445189e0e5a2c3790cbd12d5969870e543a8461 Mon Sep 17 00:00:00 2001 From: Brat-vseznamus Date: Tue, 18 Jun 2024 17:17:11 +0300 Subject: [PATCH 09/10] fix after merge --- internal/tlcodegen/type_rw_bool_cpp.go | 2 +- internal/tlcodegen/type_rw_struct.go | 28 ------------------------ internal/tlcodegen/type_rw_struct_cpp.go | 4 +--- internal/tlcodegen/type_rw_union_cpp.go | 6 +++-- 4 files changed, 6 insertions(+), 34 deletions(-) diff --git a/internal/tlcodegen/type_rw_bool_cpp.go b/internal/tlcodegen/type_rw_bool_cpp.go index 3adc588..e9352ce 100644 --- a/internal/tlcodegen/type_rw_bool_cpp.go +++ b/internal/tlcodegen/type_rw_bool_cpp.go @@ -47,7 +47,7 @@ func (trw *TypeRWBool) CPPTypeWritingCode(bytesVersion bool, val string, bare bo func (trw *TypeRWBool) CPPTypeReadingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) - return fmt.Sprintf("\tif (!::%s::%sRead%s(s, %s%s) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sRead%s(s, %s%s)) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) } func (trw *TypeRWBool) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool) { diff --git a/internal/tlcodegen/type_rw_struct.go b/internal/tlcodegen/type_rw_struct.go index 36ed107..4b801c9 100644 --- a/internal/tlcodegen/type_rw_struct.go +++ b/internal/tlcodegen/type_rw_struct.go @@ -457,34 +457,6 @@ outer: return result } -func (trw *TypeRWWrapper) replaceUnwrapHalfResolvedName(topHalfResolved HalfResolvedArgument, name string) string { - if name == "" { - return "" - } - for i, arg := range trw.origTL[0].TemplateArguments { - if arg.FieldName == name { - return topHalfResolved.Args[i].Name - } - } - return "" -} - -// same code as in func (w *TypeRWWrapper) transformNatArgsToChild, replaceUnwrapArgs -func (trw *TypeRWWrapper) replaceUnwrapHalfResolved(topHalfResolved HalfResolvedArgument, halfResolved HalfResolvedArgument) HalfResolvedArgument { - // example - // tuple#9770768a {t:Type} {n:#} [t] = Tuple t n; - // innerMaybe {X:#} a:(Maybe (tuple int X)) = InnerMaybe X; - // when unwrapping we need to change tuple into __tuple - // halfResolved references in field of tuple are to "n", "t" local template args - // we must look up in tuple to replace "n" "t" into "X", "" - var result HalfResolvedArgument - result.Name = trw.replaceUnwrapHalfResolvedName(topHalfResolved, halfResolved.Name) - for _, arg := range halfResolved.Args { - result.Args = append(result.Args, trw.replaceUnwrapHalfResolved(topHalfResolved, arg)) - } - return result -} - func (trw *TypeRWStruct) typeResettingCode(bytesVersion bool, directImports *DirectImports, ins *InternalNamespace, val string, ref bool) string { if trw.isUnwrapType() { return trw.Fields[0].t.TypeResettingCode(bytesVersion, directImports, ins, val, ref) diff --git a/internal/tlcodegen/type_rw_struct_cpp.go b/internal/tlcodegen/type_rw_struct_cpp.go index 60320d3..84cd974 100644 --- a/internal/tlcodegen/type_rw_struct_cpp.go +++ b/internal/tlcodegen/type_rw_struct_cpp.go @@ -327,9 +327,7 @@ bool %[7]s::%[1]sWriteBoxed(::basictl::tl_ostream & s, const %[2]s& item%[3]s) { trw.wr.gen.DetailsCPPNamespace, formatNatArgsCallCPP(trw.wr.NatParams), trw.wr.tlTag, - ) - cppDet.WriteString(s) - + )) } cppFinishNamespace(hppDet, trw.wr.gen.DetailsCPPNamespaceElements) } diff --git a/internal/tlcodegen/type_rw_union_cpp.go b/internal/tlcodegen/type_rw_union_cpp.go index bd41340..7aa71de 100644 --- a/internal/tlcodegen/type_rw_union_cpp.go +++ b/internal/tlcodegen/type_rw_union_cpp.go @@ -53,7 +53,7 @@ func (trw *TypeRWUnion) CPPTypeWritingCode(bytesVersion bool, val string, bare b func (trw *TypeRWUnion) CPPTypeReadingCode(bytesVersion bool, val string, bare bool, natArgs []string, last bool) string { goGlobalName := addBytes(trw.wr.goGlobalName, bytesVersion) - return fmt.Sprintf("\tif (!::%s::%sRead%s(s, %s%s) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) + return fmt.Sprintf("\tif (!::%s::%sRead%s(s, %s%s)) { return false; }", trw.wr.gen.DetailsCPPNamespace, goGlobalName, addBare(bare), val, joinWithCommas(natArgs)) } func (trw *TypeRWUnion) CPPGenerateCode(hpp *strings.Builder, hppInc *DirectIncludesCPP, hppIncFwd *DirectIncludesCPP, hppDet *strings.Builder, hppDetInc *DirectIncludesCPP, cppDet *strings.Builder, cppDetInc *DirectIncludesCPP, bytesVersion bool, forwardDeclaration bool) { @@ -176,7 +176,9 @@ void %[7]s::%[1]sReset(%[2]s& item) { } bool %[7]s::%[1]sReadBoxed(::basictl::tl_istream & s, %[2]s& item%[3]s) { - switch (s.nat_read()) { + uint32_t nat; + s.nat_read(nat); + switch (nat) { %[5]s default: return s.set_error_union_tag(); } From b549dd8d70a5dfdbbaa923d17a2d17b364b0074b Mon Sep 17 00:00:00 2001 From: Brat-vseznamus Date: Tue, 18 Jun 2024 17:36:22 +0300 Subject: [PATCH 10/10] static check fix --- internal/tlcodegen/tlgen.go | 39 +--------------------------- internal/tlcodegen/type_rw.go | 24 ++++++++--------- internal/tlcodegen/type_rw_struct.go | 2 +- 3 files changed, 14 insertions(+), 51 deletions(-) diff --git a/internal/tlcodegen/tlgen.go b/internal/tlcodegen/tlgen.go index 01526f9..f1acf97 100644 --- a/internal/tlcodegen/tlgen.go +++ b/internal/tlcodegen/tlgen.go @@ -1303,7 +1303,7 @@ func findAllTypesDependencyComponents(types []*TypeRWWrapper) (map[int]map[int]b for componentId, itsDeps := range componentsDeps { componentsOrdered = append(componentsOrdered, componentId) list := make([]int, len(itsDeps)) - for dep, _ := range itsDeps { + for dep := range itsDeps { list = append(list, dep) } sort.Ints(list) @@ -1506,43 +1506,6 @@ func processCombinators(types map[string]*tlast.Combinator) *TypesInfo { return &ti } -func printResults(ti TypesInfo) { - for tp, rds := range ti.TypeReductions { - suffix := "" - for i, tpArg := range tp.TypeArguments { - if i != 0 { - suffix += "," - } - if tpArg.IsNat { - suffix += "#" - } else { - suffix += "*" - } - } - if len(tp.TypeArguments) != 0 { - suffix = "<" + suffix + ">" - } - fmt.Println(tp.Name.String() + suffix) - for _, trd := range *rds { - fmt.Println("\t", trd) - if !trd.IsType { - for i, f := range trd.Constructor.Fields { - ftrd := ti.FieldTypeReduction(trd, i) - s := "" - if ftrd.Index == TypeVariable { - s = "[" + ftrd.TypeVariable + "]" - } else if ftrd.Index == TypeConstant { - if ftrd.Type != nil { - s = ftrd.Type.String() - } - } - fmt.Println("\t\t", "\""+f.FieldName+"\":", s) - } - } - } - } -} - func reduce( targetTypeReduction TypeReduction, visitedReductions *map[*TypeDefinition]*map[string]*TypeReduction, diff --git a/internal/tlcodegen/type_rw.go b/internal/tlcodegen/type_rw.go index 1400e4b..a3c0ee7 100644 --- a/internal/tlcodegen/type_rw.go +++ b/internal/tlcodegen/type_rw.go @@ -8,6 +8,7 @@ package tlcodegen import ( "fmt" + "golang.org/x/exp/slices" "regexp" "sort" "strconv" @@ -181,9 +182,10 @@ func (w *TypeRWWrapper) NatArgs(result []ActualNatArg, prefix string) []ActualNa func (w *TypeRWWrapper) ActualTypeDependencies(evalType EvaluatedType) (res []*TypeRWWrapper) { r := make(map[*TypeRWWrapper]bool) w.actualTypeDependenciesRecur(evalType, &r) - for arg, _ := range r { + for arg := range r { res = append(res, arg) } + slices.SortFunc(res, TypeComparator) return } @@ -241,14 +243,14 @@ type DirectIncludesCPP struct { ns map[string]CppIncludeInfo } -func (d DirectIncludesCPP) sortedNames() []string { - var sortedNames []string - for im := range d.ns { // Imports of this file. - sortedNames = append(sortedNames, im) - } - sort.Strings(sortedNames) - return sortedNames -} +//func (d DirectIncludesCPP) sortedNames() []string { +// var sortedNames []string +// for im := range d.ns { // Imports of this file. +// sortedNames = append(sortedNames, im) +// } +// sort.Strings(sortedNames) +// return sortedNames +//} func (d DirectIncludesCPP) sortedIncludes(componentOrder []int) (result []string) { compIdToPosition := make(map[int]int) @@ -269,9 +271,7 @@ func (d DirectIncludesCPP) sortedIncludes(componentOrder []int) (result []string for _, files := range filesByCID { sort.Strings(files) - for _, f := range files { - result = append(result, f) - } + result = append(result, files...) } return diff --git a/internal/tlcodegen/type_rw_struct.go b/internal/tlcodegen/type_rw_struct.go index 4b801c9..ae9730e 100644 --- a/internal/tlcodegen/type_rw_struct.go +++ b/internal/tlcodegen/type_rw_struct.go @@ -160,7 +160,7 @@ func (trw *TypeRWStruct) AllTypeDependencies() (res []*TypeRWWrapper) { } } - for tp, _ := range used { + for tp := range used { res = append(res, tp) } return