예제 #1
0
파일: structs.go 프로젝트: kego/ke
func printStructDefinition(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) error {
	if typ.Description != "" {
		g.Println("// ", typ.Description)
	}
	g.Println("type ", system.GoName(typ.Id.Name), " struct {")
	{
		if !typ.Basic {
			g.Println("*", g.SprintRef("kego.io/system", system.GoName("object")))
		}

		embedsSortable := system.SortableReferences(typ.Embed)
		sort.Sort(embedsSortable)
		embeds := []*system.Reference(embedsSortable)
		for _, embed := range embeds {
			g.Println("*", builder.Reference(embed.Package, system.GoName(embed.Name), env.Path, g.Imports.Add))
		}

		for _, nf := range typ.SortedFields() {
			b := nf.Rule.(system.ObjectInterface).GetObject(nil)
			if b.Description != "" {
				g.Println("// ", b.Description)
			}
			descriptor, err := builder.FieldTypeDefinition(ctx, nf.Name, nf.Rule, env.Path, g.Imports.Add)
			if err != nil {
				return kerr.Wrap("GDSKJDEKQD", err)
			}
			g.Println(system.GoName(nf.Name), " ", descriptor)
		}
	}
	g.Println("}")
	return nil
}
예제 #2
0
파일: structs.go 프로젝트: kego/ke
func printExportFunction(ctx context.Context, env *envctx.Env, g *builder.Builder, export *sysctx.SysExportInfo) error {
	g.Println("func ", system.GoName(export.Name), "() *", g.SprintRef(export.TypePackage, system.GoName(export.TypeName)), " {")
	{
		g.Print("ctx := ")
		g.PrintFunctionCall("kego.io/system", "NewContext",
			g.SprintFunctionCall("context", "Background"),
			strconv.Quote(env.Path),
			fmt.Sprintf("%#v", env.Aliases),
		)
		g.Println()

		g.Println("o := new(", g.SprintRef(export.TypePackage, system.GoName(export.TypeName)), ")")

		g.Print("err := ")
		g.PrintMethodCall("o", "Unpack",
			"ctx",
			g.SprintFunctionCall("kego.io/system", "MustPackString", strconv.Quote(string(export.JsonContents))),
			"false",
		)
		g.Println()
		g.Println("if err != nil {")
		{
			g.Println("panic(err.Error())")
		}
		g.Println("}")
		g.Println("return o")
	}
	g.Println("}")
	return nil
}
예제 #3
0
파일: structs.go 프로젝트: kego/ke
func printInterfaceDefinition(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) {

	g.Println("type ", system.GoInterfaceName(typ.Id.Name), " interface {")
	{
		g.Println("Get",
			system.GoName(typ.Id.Name),
			"(ctx ",
			builder.Reference("context", "Context", env.Path, g.Imports.Add),
			") ",
			typ.PassedAsPointerString(ctx),
			system.GoName(typ.Id.Name))
	}
	g.Println("}")
}
예제 #4
0
파일: type.go 프로젝트: kego/ke
// TypeDefinition returns the Go source for the definition of the type
// [optional pointer][collection prefix][optional pointer][type name]
func TypeDefinition(ctx context.Context, field system.RuleInterface, path string, getAlias func(string) string) (string, error) {
	outer := system.WrapRule(ctx, field)

	outerPointer := outer.PassedAsPointerString(ctx)

	// if the rule is a complex collection, with possibly several maps and
	// arrays, this iterates over the rule and returns the go collection prefix
	// - e.g. []map[string] for an array of maps. It also returns the inner rule.
	prefix, inner, err := collectionPrefixInnerRule(ctx, "", outer)
	if err != nil {
		return "", kerr.Wrap("SOGEFOPJHB", err)
	}

	innerPointer := ""
	// if we have a prefix we should also work out the innerPointer
	if prefix != "" && inner.PassedAsPointer(ctx) {
		innerPointer = "*"
	}

	var n string
	if inner.Struct.Interface {
		n = system.GoInterfaceName(inner.Parent.Id.Name)
	} else {
		n = system.GoName(inner.Parent.Id.Name)
	}
	name := Reference(inner.Parent.Id.Package, n, path, getAlias)

	return fmt.Sprint(outerPointer, prefix, innerPointer, name), nil
}
예제 #5
0
파일: node.go 프로젝트: kego/ke
func (n *Node) AddToObject(ctx context.Context, parent *Node, rule *system.RuleWrapper, key string, updateParentVal bool) error {

	parent.Map[key] = n

	if updateParentVal {
		rt, err := rule.GetReflectType()
		if err != nil {
			return kerr.Wrap("QMGGBWEMPT", err)
		}
		val := n.Val
		if val == (reflect.Value{}) {
			val = reflect.Zero(rt)
		}
		p := parent.Val
		for p.Kind() == reflect.Interface || p.Kind() == reflect.Ptr {
			p = p.Elem()
		}
		f := p.FieldByName(system.GoName(key))
		f.Set(val)
	}

	n.initialiseValFromParent()

	return nil
}
예제 #6
0
파일: structs.go 프로젝트: kego/ke
func printInterfaceImplementation(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) {

	g.Println("func (o ",
		typ.PassedAsPointerString(ctx),
		system.GoName(typ.Id.Name),
		") Get",
		system.GoName(typ.Id.Name),
		"(ctx ",
		builder.Reference("context", "Context", env.Path, g.Imports.Add),
		") ",
		typ.PassedAsPointerString(ctx),
		system.GoName(typ.Id.Name),
		" {")
	{
		g.Println("return o")
	}
	g.Println("}")
}
예제 #7
0
파일: structs.go 프로젝트: kego/ke
func printAliasDefinition(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) error {
	if typ.Description != "" {
		g.Println("// ", typ.Description)
	}
	aliasType, err := builder.AliasTypeDefinition(ctx, typ.Alias, env.Path, g.Imports.Add)
	if err != nil {
		return kerr.Wrap("FWOLIESYUA", err)
	}
	g.Println("type ", system.GoName(typ.Id.Name), " ", aliasType)
	return nil
}
예제 #8
0
파일: structs.go 프로젝트: kego/ke
func printValueMethod(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) error {
	name := system.GoName(typ.Id.Name)
	gotype, err := typ.NativeValueGolangType()
	if err != nil {
		return kerr.Wrap("LUHQRVBQRT", err)
	}
	g.Println("func (o *", name, ") Value() ", gotype, "{")
	{
		g.Println("return ", gotype, "(*o)")
	}
	g.Println("}")
	return nil
}
예제 #9
0
파일: node.go 프로젝트: kego/ke
func (n *Node) initialiseValFromParent() {

	v := n.Parent.Val
	for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
		v = v.Elem()
	}

	switch v.Kind() {
	case reflect.Struct:
		n.Val = v.FieldByName(system.GoName(n.Key))
	case reflect.Map:
		n.Val = v.MapIndex(reflect.ValueOf(n.Key))
	case reflect.Slice:
		n.Val = v.Index(n.Index)
	}
	n.Value = n.Val.Interface()
}
예제 #10
0
파일: type.go 프로젝트: kego/ke
// AliasTypeDefinition returns the Go source for the definition of the type
// of this alias type [collection prefix][optional pointer][type name]
func AliasTypeDefinition(ctx context.Context, alias system.RuleInterface, path string, getAlias func(string) string) (string, error) {

	outer := system.WrapRule(ctx, alias)

	// if the rule is a complex collection, with possibly several maps and
	// arrays, this iterates over the rule and returns the go collection prefix
	// - e.g. []map[string] for an array of maps. It also returns the inner
	// rule.
	prefix, inner, err := collectionPrefixInnerRule(ctx, "", outer)
	if err != nil {
		return "", kerr.Wrap("BSWTXBHVTH", err)
	}

	pointer := ""
	// if we have a prefix we should also work out the innerPointer
	if prefix != "" && inner.PassedAsPointer(ctx) {
		pointer = "*"
	}

	name := Reference(inner.Parent.Id.Package, system.GoName(inner.Parent.Id.Name), path, getAlias)

	return fmt.Sprint(prefix, pointer, name), nil
}
예제 #11
0
파일: structs.go 프로젝트: kego/ke
func printInitFunction(ctx context.Context, env *envctx.Env, g *builder.Builder, types *sysctx.SysTypes) {
	g.Println("func init() {")
	{
		g.Print("pkg := ")
		g.PrintFunctionCall(
			"kego.io/context/jsonctx",
			"InitPackage",
			strconv.Quote(env.Path),
		)
		g.Println("")
		g.PrintMethodCall("pkg", "SetHash", env.Hash)
		g.Println("")
		for _, name := range types.Keys() {
			t, ok := types.Get(name)
			if !ok {
				// ke: {"block": {"notest": true}}
				continue
			}
			typ := t.Type.(*system.Type)
			isRule := typ.Id.IsRule()

			if isRule {
				continue
			}

			interfaceFunc := "nil"
			isNativeCollection := typ.IsNativeCollection() && typ.Alias == nil
			if !isNativeCollection {
				var ifaceName string
				if typ.Interface {
					ifaceName = system.GoName(typ.Id.Name)
				} else {
					ifaceName = system.GoInterfaceName(typ.Id.Name)
				}
				reflectTypeof := g.SprintFunctionCall(
					"reflect",
					"TypeOf",
					fmt.Sprintf("(*%s)(nil)", ifaceName),
				) + ".Elem()"
				reflectType := builder.Reference("reflect", "Type", env.Path, g.Imports.Add)
				interfaceFunc = "func() " + reflectType + " { return " + reflectTypeof + " }"
			}

			newFunc := "nil"
			derefFunc := "nil"
			if typ.Interface {
				newFunc = "func() interface{} { return (*" + system.GoName(typ.Id.Name) + ")(nil) }"
			} else if !typ.IsNativeCollection() || typ.Alias != nil {
				newFunc = "func() interface{} { return new(" + system.GoName(typ.Id.Name) + ")}"
				if !typ.PassedAsPointer(ctx) {
					derefFunc = "func(in interface{}) interface{} {return *in.(*" + system.GoName(typ.Id.Name) + ")}"
				}
			}
			g.Println("pkg.Init(")
			{
				g.Println(strconv.Quote(typ.Id.Name), ",")
				g.Println(newFunc, ",")
				g.Println(derefFunc, ",")
				g.Println("func() interface{} { return new("+system.GoName(typ.Id.ChangeToRule().Name)+")}", ",")
				g.Println(interfaceFunc, ",")
			}
			g.Println(")")

			g.Println("")
		}
	}
	g.Println("}")
}
예제 #12
0
파일: structs.go 프로젝트: kego/ke
func printInterfaceUnpacker(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) {
	// if type kind is native, also accept bare json native
	// if type kind is array, also accept bare json array
	typeName := system.GoName(typ.Id.Name)
	var interfaceName string
	if typ.Interface {
		interfaceName = system.GoName(typ.Id.Name)
	} else {
		interfaceName = system.GoInterfaceName(typ.Id.Name)
	}
	fmtPkg := g.Imports.Add("fmt")
	g.Println("func Unpack", interfaceName, "(ctx ", g.SprintRef("context", "Context"), ", in ", g.SprintRef("kego.io/system", "Packed"), ") (", interfaceName, ", error) {")
	{
		g.Println("switch in.Type() {")
		{
			g.Println("case ", g.SprintRef("kego.io/system", "J_MAP"), ":")
			{
				unknownTypeFunc := g.SprintFunctionCall("kego.io/system", "UnpackUnknownType", "ctx", "in", "true", strconv.Quote(typ.Id.Package), strconv.Quote(typ.Id.Name))
				g.Println("i, err := ", unknownTypeFunc)
				g.Println("if err != nil {")
				{
					g.Println("return nil, err")
				}
				g.Println("}")
				g.Println("ob, ok := i.(", interfaceName, ")")
				g.Println("if !ok {")
				{
					g.Println("return nil, ", fmtPkg, `.Errorf("%T does not implement `, interfaceName, `", i)`)
				}
				g.Println("}")
				g.Println("return ob, nil")
			}
			switch typ.NativeJsonType(ctx) {
			// We don't include J_MAP in here.
			case system.J_STRING, system.J_NUMBER, system.J_BOOL, system.J_ARRAY:
				switch typ.NativeJsonType(ctx) {
				case system.J_STRING:
					g.Println("case ", g.SprintRef("kego.io/system", "J_STRING"), ":")
				case system.J_NUMBER:
					g.Println("case ", g.SprintRef("kego.io/system", "J_NUMBER"), ":")
				case system.J_BOOL:
					g.Println("case ", g.SprintRef("kego.io/system", "J_BOOL"), ":")
				case system.J_ARRAY:
					g.Println("case ", g.SprintRef("kego.io/system", "J_ARRAY"), ":")
				}
				g.Println("ob := new(", typeName, ")")
				g.Println("if err := ob.Unpack(ctx, in, false); err != nil {")
				{
					g.Println("return nil, err")
				}
				g.Println("}")
				g.Println("return ob, nil")
			}
			g.Println("default:")
			{
				g.Println("return nil, ", fmtPkg, `.Errorf("Unsupported json type %s when unpacking into `, interfaceName, `.", in.Type())`)
			}
		}
		g.Println("}")
	}
	g.Println("}")
}
예제 #13
0
파일: structs.go 프로젝트: kego/ke
func printUnpackCode(ctx context.Context, env *envctx.Env, g *builder.Builder, in string, out string, depth int, f system.RuleInterface) error {
	field := system.WrapRule(ctx, f)
	fieldType := field.Parent
	fieldTypeName := builder.Reference(fieldType.Id.Package, system.GoName(fieldType.Id.Name), env.Path, g.Imports.Add)
	kind, alias := field.Kind(ctx)
	switch {
	case kind == system.KindStruct || alias:
		ptr := fieldType.PassedAsPointerInverseString(ctx)
		g.Println(out, " := ", ptr, "new(", fieldTypeName, ")")
		g.Println("if err := ", out, ".Unpack(ctx, ", in, ", false); err != nil {")
		{
			g.Println("return err")
		}
		g.Println("}")
		//if store {
		//	g.Println("v.", fieldName, " = ob")
		//}
	case kind == system.KindValue:
		var funcName string
		switch fieldType.NativeJsonType(ctx) {
		case system.J_STRING:
			funcName = "UnpackString"
		case system.J_NUMBER:
			funcName = "UnpackNumber"
		case system.J_BOOL:
			funcName = "UnpackBool"
		default:
			return kerr.New("LSGUACQGHB", "Kind == KindValue but native json type==%s", fieldType.NativeJsonType(ctx))
		}
		funcRef := g.SprintRef("kego.io/system", funcName)
		g.Println(out, ", err := ", funcRef, "(ctx, ", in, ")")
		g.Println("if err != nil {")
		{
			g.Println("return err")
		}
		g.Println("}")
		//if store {
		//	g.Println("v.", fieldName, " = ob")
		//}
	case kind == system.KindInterface:
		var interfaceName string
		if fieldType.Interface {
			interfaceName = system.GoName(fieldType.Id.Name)
		} else {
			interfaceName = system.GoInterfaceName(fieldType.Id.Name)
		}
		unpackFuncName := builder.Reference(fieldType.Id.Package, "Unpack"+interfaceName, env.Path, g.Imports.Add)
		g.Println(out, ", err := ", unpackFuncName, "(ctx, ", in, ")")
		g.Println("if err != nil {")
		{
			g.Println("return err")
		}
		g.Println("}")
		//if store {
		//	g.Println("v.", fieldName, " = ob")
		//}
	case kind == system.KindArray:
		fmtPkg := g.Imports.Add("fmt")
		g.Println("if ", in, ".Type() != ", g.SprintRef("kego.io/system", "J_ARRAY"), " {")
		{
			g.Println("return ", fmtPkg, ".Errorf(\"Unsupported json type %s found while unpacking into an array.\", ", in, ".Type())")
		}
		g.Println("}")
		fieldType, err := builder.TypeDefinition(ctx, f, env.Path, g.Imports.Add)
		if err != nil {
			return kerr.Wrap("UDPMSSFLTW", err)
		}
		g.Println(out, " := ", fieldType, "{}")
		iVar := fmt.Sprintf("i%d", depth)
		g.Println("for ", iVar, " := range ", in, ".Array() {")
		{
			childRule, err := field.ItemsRule()
			if err != nil {
				return kerr.Wrap("PJQBRUEHLD", err)
			}
			childDepth := depth + 1
			childIn := in + ".Array()[" + iVar + "]"
			childOut := fmt.Sprintf("ob%d", childDepth)
			if err := printUnpackCode(ctx, env, g, childIn, childOut, childDepth, childRule.Interface); err != nil {
				return kerr.Wrap("XCHEJPDJDS", err)
			}
			g.Println(out, " = append(", out, ", ", childOut, ")")
		}
		g.Println("}")
	case kind == system.KindMap:
		fmtPkg := g.Imports.Add("fmt")
		g.Println("if ", in, ".Type() != ", g.SprintRef("kego.io/system", "J_MAP"), " {")
		{
			g.Println("return ", fmtPkg, ".Errorf(\"Unsupported json type %s found while unpacking into a map.\", ", in, ".Type())")
		}
		g.Println("}")
		fieldType, err := builder.TypeDefinition(ctx, f, env.Path, g.Imports.Add)
		if err != nil {
			return kerr.Wrap("IHNYODUIKG", err)
		}
		g.Println(out, " := ", fieldType, "{}")
		kVar := fmt.Sprintf("k%d", depth)
		g.Println("for ", kVar, " := range ", in, ".Map() {")
		{
			items, err := field.ItemsRule()
			if err != nil {
				return kerr.Wrap("FPOBYGVOPP", err)
			}
			childDepth := depth + 1
			childIn := in + ".Map()[" + kVar + "]"
			childOut := fmt.Sprintf("ob%d", childDepth)
			if err := printUnpackCode(ctx, env, g, childIn, childOut, childDepth, items.Interface); err != nil {
				return kerr.Wrap("ONUJJGIKJE", err)
			}
			g.Println(out, "[", kVar, "] = ", childOut)
		}
		g.Println("}")
	}
	return nil
}
예제 #14
0
파일: structs.go 프로젝트: kego/ke
func printUnpacker(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) error {
	name := system.GoName(typ.Id.Name)
	fmtPkg := g.Imports.Add("fmt")
	g.Println("func (v *", name, ") Unpack(ctx ", g.SprintRef("context", "Context"), ", in ", g.SprintRef("kego.io/system", "Packed"), ", iface bool) error {")
	{

		g.Println("if in == nil || in.Type() == ", g.SprintRef("kego.io/system", "J_NULL"), " {")
		{
			g.Println("return nil")
		}
		g.Println("}")

		kind, _ := typ.Kind(ctx)
		switch kind {
		case system.KindStruct:
			structType := typ
			if typ.Alias != nil {
				structType = system.WrapRule(ctx, typ.Alias).Parent
			}
			for _, embedRef := range structType.AllEmbeds() {
				embedType, ok := system.GetTypeFromCache(ctx, embedRef.Package, embedRef.Name)
				if !ok {
					return kerr.New("IOEEVJCDPU", "Type %s not found", embedRef.String())
				}
				embedName := system.GoName(embedRef.Name)
				embedTypeName := builder.Reference(embedType.Id.Package, system.GoName(embedType.Id.Name), env.Path, g.Imports.Add)
				g.Println("if v.", embedName, " == nil {")
				{
					g.Println("v.", embedName, " = new(", embedTypeName, ")")
				}
				g.Println("}")
				g.Println("if err := v.", embedName, ".Unpack(ctx, in, false); err != nil {")
				{
					g.Println("return err")
				}
				g.Println("}")
				if embedRef.Package == "kego.io/system" && embedRef.Name == "object" {
					g.Println("if err := v.Object.InitializeType(", strconv.Quote(typ.Id.Package), ", ", strconv.Quote(typ.Id.Name), "); err != nil {")
					{
						g.Println("return err")
					}
					g.Println("}")
				}
			}
			for _, f := range structType.SortedFields() {
				g.Println("if field, ok := in.Map()[", strconv.Quote(f.Name), "]; ok && field.Type() != ", g.SprintRef("kego.io/system", "J_NULL"), " {")
				{
					in := "field"
					out := "ob0"
					depth := 0
					if err := printUnpackCode(ctx, env, g, in, out, depth, f.Rule); err != nil {
						return kerr.Wrap("QLARKEBDBJ", err)
					}
					g.Println("v.", system.GoName(f.Name), " = ", out)
				}
				if dr, ok := f.Rule.(system.DefaultRule); ok && dr.GetDefault() != nil {
					g.Println("} else {")
					{
						b, err := json.Marshal(dr.GetDefault())
						if err != nil {
							return kerr.Wrap("DLOUEHXVJF", err)
						}
						in := g.SprintFunctionCall("kego.io/system", "Pack", string(b))
						out := "ob0"
						depth := 0
						if err := printUnpackCode(ctx, env, g, in, out, depth, f.Rule); err != nil {
							return kerr.Wrap("UOWRFWSTNT", err)
						}
						g.Println("v.", system.GoName(f.Name), " = ", out)
					}
					g.Println("}")
				} else {
					g.Println("}")
				}
			}
		case system.KindValue:
			g.Println("if in.Type() == ", g.SprintRef("kego.io/system", "J_MAP"), " {")
			{
				g.Println("in = in.Map()[\"value\"]")
			}
			g.Println("}")
			switch typ.NativeJsonType(ctx) {
			case system.J_BOOL:
				g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_BOOL"), " {")
				{
					g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking a bool.", in.Type())`)
				}
				g.Println("}")
				g.Println("*v = ", name, "(in.Bool())")
			case system.J_STRING:
				g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_STRING"), " {")
				{
					g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking a string.", in.Type())`)
				}
				g.Println("}")
				g.Println("*v = ", name, "(in.String())")
			case system.J_NUMBER:
				g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_NUMBER"), " {")
				{
					g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking a number.", in.Type())`)
				}
				g.Println("}")
				g.Println("*v = ", name, "(in.Number())")
			default:
				panic(fmt.Sprintf("invalid type kind: %s, json native: %s", kind, typ.NativeJsonType(ctx)))
			}
		case system.KindArray:
			g.Println("if in.Type() == ", g.SprintRef("kego.io/system", "J_MAP"), " {")
			{
				g.Println("in = in.Map()[\"value\"]")
			}
			g.Println("}")

			g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_ARRAY"), " {")
			{
				g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking an array.", in.Type())`)
			}
			g.Println("}")

			in := "in"
			out := "ob0"
			depth := 0
			if err := printUnpackCode(ctx, env, g, in, out, depth, typ.Alias); err != nil {
				return kerr.Wrap("VELYRXXGMC", err)
			}
			g.Println("*v = ", out)
		case system.KindMap:
			g.Println("if iface {")
			{
				g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_MAP"), " {")
				{
					g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking a map.", in.Type())`)
				}
				g.Println("}")
				g.Println("in = in.Map()[\"value\"]")
			}
			g.Println("}")

			g.Println("if in.Type() != ", g.SprintRef("kego.io/system", "J_MAP"), " {")
			{
				g.Println("return ", fmtPkg, `.Errorf("Invalid type %s while unpacking an array.", in.Type())`)
			}
			g.Println("}")

			in := "in"
			out := "ob0"
			depth := 0
			if err := printUnpackCode(ctx, env, g, in, out, depth, typ.Alias); err != nil {
				return kerr.Wrap("TNEIUAFUNY", err)
			}
			g.Println("*v = ", out)
		}
	}
	g.Println("return nil")
	g.Println("}")
	return nil
}
예제 #15
0
파일: structs.go 프로젝트: kego/ke
func printRepacker(ctx context.Context, env *envctx.Env, g *builder.Builder, typ *system.Type) error {
	name := system.GoName(typ.Id.Name)
	context_Context := g.SprintRef("context", "Context")
	system_JsonType := g.SprintRef("kego.io/system", "JsonType")
	ptr := typ.PassedAsPointerString(ctx)
	v := "v"
	if typ.PassedAsPointer(ctx) {
		v = "(*v)"
	}
	g.Println("func (v ", ptr, name, ") Repack(ctx ", context_Context, ") (data interface{}, typePackage string, typeName string, jsonType ", system_JsonType, ", err error) {")
	{
		g.Println("if v == nil {")
		{
			system_J_NULL := g.SprintRef("kego.io/system", "J_NULL")
			g.Println("return nil, ", strconv.Quote(typ.Id.Package), ", ", strconv.Quote(typ.Id.Name), ", ", system_J_NULL, ", nil")
		}
		g.Println("}")

		jtype := typ.NativeJsonType(ctx)
		var jsonType string
		switch jtype {
		case system.J_NUMBER:
			jsonType = g.SprintRef("kego.io/system", "J_NUMBER")
		case system.J_STRING:
			jsonType = g.SprintRef("kego.io/system", "J_STRING")
		case system.J_BOOL:
			jsonType = g.SprintRef("kego.io/system", "J_BOOL")
		case system.J_MAP:
			jsonType = g.SprintRef("kego.io/system", "J_MAP")
		case system.J_OBJECT:
			jsonType = g.SprintRef("kego.io/system", "J_OBJECT")
		case system.J_ARRAY:
			jsonType = g.SprintRef("kego.io/system", "J_ARRAY")
		case system.J_NULL:
			jsonType = g.SprintRef("kego.io/system", "J_NULL")
		}

		kind, _ := typ.Kind(ctx)
		switch kind {
		case system.KindStruct:
			g.Println("m := map[string]interface{}{}")
			structType := typ
			if typ.Alias != nil {
				structType = system.WrapRule(ctx, typ.Alias).Parent
			}
			for _, embedRef := range structType.AllEmbeds() {
				embedName := system.GoName(embedRef.Name)
				g.Println("if v.", embedName, " != nil {")
				{
					g.Println("ob, _, _, _, err := v.", embedName, ".Repack(ctx)")
					g.Println("if err != nil {")
					{
						g.Println(`return nil, "", "", "", err`)
					}
					g.Println("}")
					g.Println("for key, val := range ob.(map[string]interface{}) {")
					{
						g.Println("m[key] = val")
					}
					g.Println("}")
				}
				g.Println("}")
			}
			for _, f := range structType.SortedFields() {
				fieldRule := system.WrapRule(ctx, f.Rule)
				fieldName := system.GoName(f.Name)
				fieldType := fieldRule.Parent
				kind, alias := fieldRule.Kind(ctx)
				switch {
				case kind == system.KindStruct || alias:
					g.Println("if v.", fieldName, " != nil {")
					{
						if err := printRepackCode(ctx, env, g, "v."+fieldName, "ob0", 0, f.Rule, true); err != nil {
							return kerr.Wrap("WSARHJIFHS", err)
						}
						g.Println("m[", strconv.Quote(f.Name), "] = ", "ob0")
					}
					g.Println("}")
				case kind == system.KindValue:
					switch fieldType.NativeJsonType(ctx) {
					case system.J_STRING:
						g.Println("if v.", fieldName, " != \"\" {")
					case system.J_NUMBER:
						g.Println("if v.", fieldName, " != 0.0 {")
					case system.J_BOOL:
						g.Println("if v.", fieldName, " != false {")
					}
					{
						if err := printRepackCode(ctx, env, g, "v."+fieldName, "ob0", 0, f.Rule, true); err != nil {
							return kerr.Wrap("YYDYVIMXPM", err)
						}
						g.Println("m[", strconv.Quote(f.Name), "] = ", "ob0")
					}
					g.Println("}")
				case kind == system.KindArray ||
					kind == system.KindMap ||
					kind == system.KindInterface:
					g.Println("if v.", fieldName, " != nil {")
					{
						if err := printRepackCode(ctx, env, g, "v."+fieldName, "ob0", 0, f.Rule, true); err != nil {
							return kerr.Wrap("YSFPHQTBNA", err)
						}
						g.Println("m[", strconv.Quote(f.Name), "] = ", "ob0")
					}
					g.Println("}")
				}
			}
			g.Println("return m, ", strconv.Quote(typ.Id.Package), ", ", strconv.Quote(typ.Id.Name), ", ", jsonType, ", nil")
		case system.KindValue:
			outer := typ
			inner := typ
			if typ.Alias != nil {
				inner = system.WrapRule(ctx, typ.Alias).Parent
			}
			switch inner.NativeJsonType(ctx) {
			case system.J_STRING:
				g.Println("if v != nil {")
				{
					g.Println("return string(", ptr, "v), ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil")
				}
				g.Println("}")
				g.Println("return nil, ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil")
			case system.J_NUMBER:
				g.Println("if v != nil {")
				{
					g.Println("return float64(", ptr, "v), ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil")
				}
				g.Println("}")
				g.Println("return nil, ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil")
			case system.J_BOOL:
				g.Println("if v != nil {")
				{
					g.Println("return bool(", ptr, "v), ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil")
				}
				g.Println("}")
				g.Println("return nil, ", strconv.Quote(outer.Id.Package), ", ", strconv.Quote(outer.Id.Name), ", ", jsonType, ", nil")
			}
		case system.KindArray:
			if err := printRepackCode(ctx, env, g, v, "ob0", 0, typ.Alias, false); err != nil {
				return kerr.Wrap("SYKLQKLCEO", err)
			}
			g.Println("return ob0, ", strconv.Quote(typ.Id.Package), ", ", strconv.Quote(typ.Id.Name), ", ", jsonType, ", nil")
		case system.KindMap:
			if err := printRepackCode(ctx, env, g, v, "ob0", 0, typ.Alias, false); err != nil {
				return kerr.Wrap("HBSGXLGKCD", err)
			}
			g.Println("return ob0, ", strconv.Quote(typ.Id.Package), ", ", strconv.Quote(typ.Id.Name), ", ", jsonType, ", nil")
		}
	}
	g.Println("}")
	return nil
}