func (n *node) defineStructFields(w io.Writer, x *bam.Extractor) { assert(n.Which() == caps.NODE_STRUCT, "invalid struct node") for _, f := range n.codeOrderFields() { switch f.Which() { case caps.FIELD_SLOT: n.defineField(w, f, x) case caps.FIELD_GROUP: g := findNode(f.Group().TypeId()) fname := f.Name() if an := nameAnnotation(f.Annotations()); an != "" { fname = an } fname = strings.Title(fname) typeName := "" fld := &ast.Field{} x.GenerateStructField(fname, "", typeName, fld, false, fld.Tag, true, []string{typeName}) fmt.Fprintf(w, "%s struct {\n", fname) g.defineStructFields(w, x) fmt.Fprintf(w, "}\n") } } }
func (n *node) defineStructTypes(w io.Writer, baseNode *node, x *bam.Extractor) { assert(n.Which() == caps.NODE_STRUCT, "invalid struct node") for _, a := range n.Annotations().ToArray() { if a.Id() == C.Doc { fmt.Fprintf(w, "// %s\n", a.Value().Text()) } } if baseNode == nil { x.StartStruct(n.name) fmt.Fprintf(w, "type %s struct {\n", n.name) n.defineStructFields(w, x) fmt.Fprintf(w, "}\n\n") baseNode = n x.EndStruct() } for _, f := range n.codeOrderFields() { if f.Which() == caps.FIELD_GROUP { findNode(f.Group().TypeId()).defineStructTypes(w, baseNode, x) } } }
func (n *node) defineEnum(w io.Writer, x *bam.Extractor) { for _, a := range n.Annotations().ToArray() { if a.Id() == C.Doc { fmt.Fprintf(w, "// %s\n", a.Value().Text()) } } fmt.Fprintf(w, "type %s uint16\n", n.name) x.NewEnum(n.name) if es := n.Enum().Enumerants(); es.Len() > 0 { fmt.Fprintf(w, "const (\n") ev := make([]enumval, es.Len()) for i := 0; i < es.Len(); i++ { e := es.At(i) ename := e.Name() if an := nameAnnotation(e.Annotations()); an != "" { ename = an } t := ename for _, an := range e.Annotations().ToArray() { if an.Id() == C.Tag { t = an.Value().Text() } else if an.Id() == C.Notag { t = "" } } ev[e.CodeOrder()] = enumval{e, i, ename, t, n} } // not an iota, so type has to go on each line for _, e := range ev { fmt.Fprintf(w, "%s %s = %d\n", e.fullName(), n.name, e.val) } fmt.Fprintf(w, ")\n") fmt.Fprintf(w, "func (c %s) String() string {\n", n.name) fmt.Fprintf(w, "switch c {\n") for _, e := range ev { if e.tag != "" { fmt.Fprintf(w, "case %s: return \"%s\"\n", e.fullName(), e.tag) } } fmt.Fprintf(w, "default: return \"\"\n") fmt.Fprintf(w, "}\n}\n\n") fmt.Fprintf(w, "func %sFromString(c string) %s {\n", n.name, n.name) fmt.Fprintf(w, "switch c {\n") for _, e := range ev { if e.tag != "" { fmt.Fprintf(w, "case \"%s\": return %s\n", e.tag, e.fullName()) } } fmt.Fprintf(w, "default: return 0\n") fmt.Fprintf(w, "}\n}\n") } }
func (n *node) defineField(w io.Writer, f caps.Field, x *bam.Extractor) { t := f.Slot().Type() if t.Which() == caps.TYPE_INTERFACE { return } var fname string if an := nameAnnotation(f.Annotations()); an != "" { fname = an } else { fname = f.Name() } fname = strings.Title(fname) var g, s bytes.Buffer if f.DiscriminantValue() != 0xFFFF { if t.Which() == caps.TYPE_VOID { x.SetUnionStruct() w.Write(s.Bytes()) return } } else if t.Which() == caps.TYPE_VOID { return } customtype := "" for _, a := range f.Annotations().ToArray() { if a.Id() == C.Doc { fmt.Fprintf(&g, "// %s\n", a.Value().Text()) } if a.Id() == C.Customtype { customtype = a.Value().Text() if i := strings.LastIndex(customtype, "."); i != -1 { g_imported[customtype[:i]] = true } } } if len(customtype) != 0 { log.Println("CUSTOM TYPE:", customtype) } fmt.Fprintf(&s, "%s ", fname) typeName := GoTypeName(n, f.Slot(), customtype) fmt.Fprintf(&s, "%s", typeName) fld := &ast.Field{} goseq := strings.SplitAfter(typeName, "[]") typePrefix := "" if len(goseq) == 2 { typeName = goseq[1] typePrefix = goseq[0] } x.GenerateStructField(fname, typePrefix, typeName, fld, t.Which() == caps.TYPE_LIST, fld.Tag, false, goseq) ans := f.Annotations() n.processAnnotations(&s, f, t.Which(), ans) fmt.Fprintf(&s, "\n") w.Write(g.Bytes()) w.Write(s.Bytes()) }