File: inline.go

package info (click to toggle)
golang-github-tinylib-msgp 1.0~beta-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 456 kB
  • ctags: 973
  • sloc: makefile: 41
file content (100 lines) | stat: -rw-r--r-- 2,468 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package parse

import (
	"github.com/tinylib/msgp/gen"
)

// This file defines when and how we
// propagate type information from
// one type declaration to another.
// After the processing pass, every
// non-primitive type is marshalled/unmarshalled/etc.
// through a function call. Here, we propagate
// the type information into the caller's type
// tree *if* the child type is simple enough.
//
// For example, types like
//
//    type A [4]int
//
// will get pushed into parent methods,
// whereas types like
//
//    type B [3]map[string]struct{A, B [4]string}
//
// will not.

// this is an approximate measure
// of the number of children in a node
const maxComplex = 5

// propInline identifies and inlines candidates
func (f *FileSet) propInline() {
	for name, el := range f.Identities {
		pushstate(name)
		switch el := el.(type) {
		case *gen.Struct:
			for i := range el.Fields {
				f.nextInline(&el.Fields[i].FieldElem, name)
			}
		case *gen.Array:
			f.nextInline(&el.Els, name)
		case *gen.Slice:
			f.nextInline(&el.Els, name)
		case *gen.Map:
			f.nextInline(&el.Value, name)
		case *gen.Ptr:
			f.nextInline(&el.Value, name)
		}
		popstate()
	}
}

const fatalloop = `detected infinite recursion in inlining loop!
Please file a bug at github.com/tinylib/msgp/issues!
Thanks!
`

func (f *FileSet) nextInline(ref *gen.Elem, root string) {
	switch el := (*ref).(type) {
	case *gen.BaseElem:
		// ensure that we're not inlining
		// a type into itself
		typ := el.TypeName()
		if el.Value == gen.IDENT && typ != root {
			if node, ok := f.Identities[typ]; ok && node.Complexity() < maxComplex {
				infof("inlining %s\n", typ)

				// This should never happen; it will cause
				// infinite recursion.
				if node == *ref {
					panic(fatalloop)
				}

				// inline bottom-up so as not to miss
				// other inlining opportunities.
				f.nextInline(&node, root)
				*ref = node.Copy()
			} else if !ok && !el.Resolved() {
				// this is the point at which we're sure that
				// we've got a type that isn't a primitive,
				// a library builtin, or a processed type
				warnf("unresolved identifier: %s\n", typ)
			}
		}
	case *gen.Struct:
		for i := range el.Fields {
			f.nextInline(&el.Fields[i].FieldElem, root)
		}
	case *gen.Array:
		f.nextInline(&el.Els, root)
	case *gen.Slice:
		f.nextInline(&el.Els, root)
	case *gen.Map:
		f.nextInline(&el.Value, root)
	case *gen.Ptr:
		f.nextInline(&el.Value, root)
	default:
		panic("bad elem type")
	}
}