Example #1
0
File: type.go Project: 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
}
Example #2
0
File: structs.go Project: 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("}")
}
Example #3
0
File: structs.go Project: 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("}")
}
Example #4
0
File: structs.go Project: 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("}")
}
Example #5
0
File: structs.go Project: 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
}