diff options
Diffstat (limited to 'nexgb/xgbgen/go.go')
-rw-r--r-- | nexgb/xgbgen/go.go | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/nexgb/xgbgen/go.go b/nexgb/xgbgen/go.go new file mode 100644 index 0000000..eb3f0fb --- /dev/null +++ b/nexgb/xgbgen/go.go @@ -0,0 +1,255 @@ +package main +/* + To the best of my ability, these are all of the Go specific formatting + functions. If I've designed xgbgen correctly, this should be only the + place that you change things to generate code for a new language. + + This file is organized as follows: + + * Imports and helper variables. + * Manual type and name override maps. + * Helper morphing functions. + * Morphing functions for each "unit". + * Morphing functions for collections of "units". +*/ + +import ( + "strings" +) + +/******************************************************************************/ +// Manual type and name overrides. +/******************************************************************************/ + +// BaseTypeMap is a map from X base types to Go types. +// X base types should correspond to the smallest set of X types +// that can be used to rewrite ALL X types in terms of Go types. +// That is, if you remove any of the following types, at least one +// XML protocol description will produce an invalid Go program. +// The types on the left *never* show themselves in the source. +var BaseTypeMap = map[string]string{ + "CARD8": "byte", + "CARD16": "uint16", + "CARD32": "uint32", + "INT8": "int8", + "INT16": "int16", + "INT32": "int32", + "BYTE": "byte", + "BOOL": "bool", + "float": "float64", + "double": "float64", +} + +// TypeMap is a map from types in the XML to type names that is used +// in the functions that follow. Basically, every occurrence of the key +// type is replaced with the value type. +var TypeMap = map[string]string{ + "VISUALTYPE": "VisualInfo", + "DEPTH": "DepthInfo", + "SCREEN": "ScreenInfo", + "Setup": "SetupInfo", +} + +// NameMap is the same as TypeMap, but for names. +var NameMap = map[string]string{ } + +/******************************************************************************/ +// Helper functions that aide in morphing repetive constructs. +// i.e., "structure contents", expressions, type and identifier names, etc. +/******************************************************************************/ + +// Morph changes every TYPE (not names) into something suitable +// for your language. +func (typ Type) Morph(c *Context) string { + t := string(typ) + + // If this is a base type, then write the raw Go type. + if newt, ok := BaseTypeMap[t]; ok { + return newt + } + + // If it's in the type map, use that translation. + if newt, ok := TypeMap[t]; ok { + return newt + } + + // If it's a resource type, just use 'Id'. + if c.xml.IsResource(typ) { + return "Id" + } + + // If there's a namespace to this type, just use it and be done. + if colon := strings.Index(t, ":"); colon > -1 { + namespace := t[:colon] + rest := t[colon+1:] + return splitAndTitle(namespace) + splitAndTitle(rest) + } + + // Since there is no namespace, we need to look for a namespace + // in the current context. + return c.TypePrefix(typ) + splitAndTitle(t) +} + +// Morph changes every identifier (NOT type) into something suitable +// for your language. +func (name Name) Morph(c *Context) string { + n := string(name) + + // If it's in the name map, use that translation. + if newn, ok := NameMap[n]; ok { + return newn + } + + return splitAndTitle(n) +} + +/******************************************************************************/ +// Per element morphing. +// Below are functions that morph a single unit. +/******************************************************************************/ + +// Import morphing. +func (imp *Import) Morph(c *Context) { + c.Putln("// import \"%s\"", imp.Name) +} + +// Enum morphing. +func (enum *Enum) Morph(c *Context) { + c.Putln("const (") + for _, item := range enum.Items { + c.Putln("%s%s = %d", enum.Name.Morph(c), item.Name.Morph(c), + item.Expr.Eval()) + } + c.Putln(")\n") +} + +// Xid morphing. +func (xid *Xid) Morph(c *Context) { + // Don't emit anything for xid types for now. + // We're going to force them all to simply be 'Id' + // to avoid excessive type converting. + // c.Putln("type %s Id", xid.Name.Morph(c)) +} + +// TypeDef morphing. +func (typedef *TypeDef) Morph(c *Context) { + c.Putln("type %s %s", typedef.Old.Morph(c), typedef.New.Morph(c)) +} + +// Struct morphing. +func (strct *Struct) Morph(c *Context) { +} + +// Union morphing. +func (union *Union) Morph(c *Context) { +} + +// Request morphing. +func (request *Request) Morph(c *Context) { +} + +// Event morphing. +func (ev *Event) Morph(c *Context) { +} + +// EventCopy morphing. +func (evcopy *EventCopy) Morph(c *Context) { +} + +// Error morphing. +func (err *Error) Morph(c *Context) { +} + +// ErrorCopy morphing. +func (errcopy *ErrorCopy) Morph(c *Context) { +} + +/******************************************************************************/ +// Collection morphing. +// Below are functions that morph a collections of units. +// Most of these can probably remain unchanged, but they are useful if you +// need to group all of some "unit" in a single block or something. +/******************************************************************************/ +func (imports Imports) Morph(c *Context) { + if len(imports) == 0 { + return + } + + c.Putln("// Imports are not required for XGB since everything is in") + c.Putln("// a single package. Still these may be useful for ") + c.Putln("// reference purposes.") + for _, imp := range imports { + imp.Morph(c) + } +} + +func (enums Enums) Morph(c *Context) { + c.Putln("// Enums\n") + for _, enum := range enums { + enum.Morph(c) + } +} + +func (xids Xids) Morph(c *Context) { + c.Putln("// Xids\n") + for _, xid := range xids { + xid.Morph(c) + } +} + +func (typedefs TypeDefs) Morph(c *Context) { + c.Putln("// TypeDefs\n") + for _, typedef := range typedefs { + typedef.Morph(c) + } +} + +func (strct Structs) Morph(c *Context) { + c.Putln("// Structs\n") + for _, typedef := range strct { + typedef.Morph(c) + } +} + +func (union Unions) Morph(c *Context) { + c.Putln("// Unions\n") + for _, typedef := range union { + typedef.Morph(c) + } +} + +func (request Requests) Morph(c *Context) { + c.Putln("// Requests\n") + for _, typedef := range request { + typedef.Morph(c) + } +} + +func (event Events) Morph(c *Context) { + c.Putln("// Events\n") + for _, typedef := range event { + typedef.Morph(c) + } +} + +func (evcopy EventCopies) Morph(c *Context) { + c.Putln("// Event Copies\n") + for _, typedef := range evcopy { + typedef.Morph(c) + } +} + +func (err Errors) Morph(c *Context) { + c.Putln("// Errors\n") + for _, typedef := range err { + typedef.Morph(c) + } +} + +func (errcopy ErrorCopies) Morph(c *Context) { + c.Putln("// Error copies\n") + for _, typedef := range errcopy { + typedef.Morph(c) + } +} + |