12 ClassBoolean TypeClass = iota
41 ktyp *Type // map key, chan elem, array elem, slice elem, pointee type
43 utyp *Type // underlying type
44 styp []*Type // function arguments
45 rtyp []*Type // function return values
46 elems []*Var // struct fileds and interface methods
48 complexLiteral func() string
54 func (smith *Smith) initTypes() {
55 smith.predefinedTypes = []*Type{
56 {id: "string", class: ClassString, literal: func() string { return "\"foo\"" }},
57 {id: "bool", class: ClassBoolean, literal: func() string { return "false" }},
58 {id: "int", class: ClassNumeric, literal: func() string { return "1" }},
59 {id: "byte", class: ClassNumeric, literal: func() string { return "byte(0)" }},
60 {id: "interface{}", class: ClassInterface, literal: func() string { return "interface{}(nil)" }},
61 {id: "rune", class: ClassNumeric, literal: func() string { return "rune(0)" }},
62 {id: "float32", class: ClassNumeric, literal: func() string { return "float32(1.0)" }},
63 {id: "float64", class: ClassNumeric, literal: func() string { return "1.0" }},
64 {id: "complex64", class: ClassComplex, literal: func() string { return "complex64(1i)" }},
65 {id: "complex128", class: ClassComplex, literal: func() string { return "1i" }},
67 {id: "uint", class: ClassNumeric, literal: func() string { return "uint(1)" }},
68 {id: "uintptr", class: ClassNumeric, literal: func() string { return "uintptr(0)" }},
69 {id: "int16", class: ClassNumeric, literal: func() string { return "int16(1)" }},
70 {id: "error", class: ClassInterface, literal: func() string { return "error(nil)" }},
72 for _, t := range smith.predefinedTypes {
76 smith.stringType = smith.predefinedTypes[0]
77 smith.boolType = smith.predefinedTypes[1]
78 smith.intType = smith.predefinedTypes[2]
79 smith.byteType = smith.predefinedTypes[3]
80 smith.efaceType = smith.predefinedTypes[4]
81 smith.runeType = smith.predefinedTypes[5]
82 smith.float32Type = smith.predefinedTypes[6]
83 smith.float64Type = smith.predefinedTypes[7]
84 smith.complex64Type = smith.predefinedTypes[8]
85 smith.complex128Type = smith.predefinedTypes[9]
87 smith.stringType.complexLiteral = func() string {
95 func fmtTypeList(list []*Type, parens bool) string {
97 if parens || len(list) > 1 {
98 buf.Write([]byte{'('})
100 for i, t := range list {
102 buf.Write([]byte{','})
104 fmt.Fprintf(&buf, "%v", t.id)
106 if parens || len(list) > 1 {
107 buf.Write([]byte{')'})
112 func (smith *Smith) atype(trait TypeClass) *Type {
118 if smith.typeDepth >= 3 || smith.rndBool() {
120 for _, t := range smith.types() {
121 if smith.satisfiesTrait(t, trait) {
122 cand = append(cand, t)
126 return cand[smith.rnd(len(cand))]
130 if t != nil && smith.satisfiesTrait(t, trait) {
136 func (smith *Smith) typeLit() *Type {
137 switch smith.choice("array", "chan", "struct", "pointer", "interface", "slice", "function", "map") {
139 return smith.arrayOf(smith.atype(TraitAny))
141 return smith.chanOf(smith.atype(TraitAny))
145 fmt.Fprintf(&buf, "struct { ")
146 for smith.rndBool() {
147 e := &Var{id: smith.newId("Field"), typ: smith.atype(TraitAny)}
148 elems = append(elems, e)
149 fmt.Fprintf(&buf, "%v %v\n", e.id, e.typ.id)
151 fmt.Fprintf(&buf, "}")
157 literal: func() string {
158 return F("(%v{})", id)
160 complexLiteral: func() string {
164 fmt.Fprintf(&buf, "(%v{", id)
165 for i := 0; i < len(elems); i++ {
166 fmt.Fprintf(&buf, "%v, ", smith.rvalue(elems[i].typ))
168 fmt.Fprintf(&buf, "})")
173 fmt.Fprintf(&buf, "(%v{", id)
174 for i := 0; i < len(elems); i++ {
176 fmt.Fprintf(&buf, "%v: %v, ", elems[i].id, smith.rvalue(elems[i].typ))
179 fmt.Fprintf(&buf, "})")
185 return pointerTo(smith.atype(TraitAny))
188 fmt.Fprintf(&buf, "interface { ")
189 for smith.rndBool() {
190 fmt.Fprintf(&buf, " %v %v %v\n", smith.newId("Method"),
191 fmtTypeList(smith.atypeList(TraitAny), true),
192 fmtTypeList(smith.atypeList(TraitAny), false))
194 fmt.Fprintf(&buf, "}")
197 class: ClassInterface,
198 literal: func() string {
199 return F("%v(nil)", buf.String())
203 return smith.sliceOf(smith.atype(TraitAny))
205 return smith.funcOf(smith.atypeList(TraitAny), smith.atypeList(TraitAny))
207 ktyp := smith.atype(TraitHashable)
208 vtyp := smith.atype(TraitAny)
210 id: F("map[%v]%v", ktyp.id, vtyp.id),
214 literal: func() string {
218 cap = "," + smith.rvalue(smith.intType)
220 return F("make(map[%v]%v %v)", ktyp.id, vtyp.id, cap)
222 return F("map[%v]%v{}", ktyp.id, vtyp.id)
231 func (smith *Smith) satisfiesTrait(t *Type, trait TypeClass) bool {
232 if trait < TraitAny {
233 return t.class == trait
240 return t.class == ClassNumeric || t.class == ClassString
241 case TraitComparable:
242 return t.class == ClassBoolean || t.class == ClassNumeric || t.class == ClassString ||
243 t.class == ClassPointer || t.class == ClassChan || t.class == ClassInterface
245 return t.class == ClassArray || t.class == ClassSlice || t.class == ClassString ||
247 case TraitReceivable:
248 return t.class == ClassChan
250 return t.class == ClassChan
252 if t.class == ClassFunction || t.class == ClassMap || t.class == ClassSlice {
255 if t.class == ClassArray && !smith.satisfiesTrait(t.ktyp, TraitHashable) {
258 if t.class == ClassStruct {
259 for _, e := range t.elems {
260 if !smith.satisfiesTrait(e.typ, TraitHashable) {
267 return t.class == ClassBoolean || t.class == ClassNumeric || t.class == ClassString ||
268 t.class == ClassPointer || t.class == ClassInterface
269 case TraitLenCapable:
270 return t.class == ClassString || t.class == ClassSlice || t.class == ClassArray ||
271 t.class == ClassMap || t.class == ClassChan
273 for _, t1 := range smith.predefinedTypes {
284 func (smith *Smith) atypeList(trait TypeClass) []*Type {
285 n := smith.rnd(4) + 1
286 list := make([]*Type, n)
287 for i := 0; i < n; i++ {
288 list[i] = smith.atype(trait)
293 func typeList(t *Type, n int) []*Type {
294 list := make([]*Type, n)
295 for i := 0; i < n; i++ {
301 func pointerTo(elem *Type) *Type {
303 id: F("*%v", elem.id),
306 literal: func() string {
307 return F("(*%v)(nil)", elem.id)
311 func (smith *Smith) chanOf(elem *Type) *Type {
313 id: F("chan %v", elem.id),
316 literal: func() string {
319 cap = "," + smith.rvalue(smith.intType)
321 return F("make(chan %v %v)", elem.id, cap)
326 func (smith *Smith) sliceOf(elem *Type) *Type {
328 id: F("[]%v", elem.id),
331 literal: func() string {
332 return F("[]%v{}", elem.id)
334 complexLiteral: func() string {
335 switch smith.choice("normal", "keyed") {
337 return F("[]%v{%v}", elem.id, smith.fmtRvalueList(typeList(elem, smith.rnd(3))))
342 for len(indexes) < n {
344 for _, i1 := range indexes {
349 indexes = append(indexes, i)
352 fmt.Fprintf(&buf, "[]%v{", elem.id)
353 for i, idx := range indexes {
355 fmt.Fprintf(&buf, ",")
357 fmt.Fprintf(&buf, "%v: %v", idx, smith.rvalue(elem))
359 fmt.Fprintf(&buf, "}")
368 func (smith *Smith) arrayOf(elem *Type) *Type {
371 id: F("[%v]%v", size, elem.id),
374 literal: func() string {
375 return F("[%v]%v{}", size, elem.id)
377 complexLiteral: func() string {
378 switch smith.choice("normal", "keyed") {
380 return F("[%v]%v{%v}", smith.choice(F("%v", size), "..."), elem.id, smith.fmtRvalueList(typeList(elem, size)))
383 fmt.Fprintf(&buf, "[%v]%v{", size, elem.id)
384 for i := 0; i < size; i++ {
386 fmt.Fprintf(&buf, ",")
388 fmt.Fprintf(&buf, "%v: %v", i, smith.rvalue(elem))
390 fmt.Fprintf(&buf, "}")
399 func (smith *Smith) funcOf(alist, rlist []*Type) *Type {
401 id: F("func%v %v", fmtTypeList(alist, true), fmtTypeList(rlist, false)),
402 class: ClassFunction,
406 t.literal = func() string {
407 return F("((func%v %v)(nil))", fmtTypeList(alist, true), fmtTypeList(rlist, false))
409 t.complexLiteral = func() string {
410 return smith.genFuncLit(t)
415 func (smith *Smith) genFuncLit(ft *Type) string {
416 //return F("((func%v %v)(nil))", fmtTypeList(ft.styp, true), fmtTypeList(ft.rtyp, false))
418 if smith.curBlockPos == -1 {
422 f := &Func{args: ft.styp, rets: ft.rtyp}
423 curFunc0 := smith.curFunc
425 curBlock0 := smith.curBlock
426 curBlockPos0 := smith.curBlockPos
427 curBlockLen0 := len(smith.curBlock.sub)
428 exprDepth0 := smith.exprDepth
429 exprCount0 := smith.exprCount
433 smith.curBlock = curBlock0
434 smith.curFunc = curFunc0
435 smith.exprDepth = exprDepth0
436 smith.exprCount = exprCount0
437 smith.curBlockPos = curBlockPos0 + (len(smith.curBlock.sub) - curBlockLen0)
440 fb := &Block{parent: smith.curBlock, subBlock: smith.curBlock.sub[smith.curBlockPos]}
442 smith.enterBlock(true)
443 smith.enterBlock(true)
444 argIds := make([]string, len(f.args))
446 for i, a := range f.args {
447 argIds[i] = smith.newId("Param")
451 argStr += argIds[i] + " " + a.id
453 smith.line("func(%v)%v {", argStr, fmtTypeList(f.rets, false))
454 for i, a := range f.args {
455 smith.defineVar(argIds[i], a)
457 smith.curBlock.funcBoundary = true
464 //b := curBlock.sub[curBlockPos]
465 //copy(curBlock.sub[curBlockPos:], curBlock.sub[curBlockPos+1:])
466 //curBlock.sub = curBlock.sub[:len(curBlock.sub)-1]
469 w := bufio.NewWriter(&buf)
470 serializeBlock(w, fb, 0)
473 //fmt.Printf("GEN FUNC:\n%v\n", s)
477 func dependsOn(t, t0 *Type) bool {
481 if t.class == ClassInterface {
482 // We don't know how to walk all types referenced by an interface yet.
485 if t0 == nil && t.namedUserType {
491 if dependsOn(t.ktyp, t0) {
494 if dependsOn(t.vtyp, t0) {
497 if dependsOn(t.ktyp, t0) {
500 for _, t1 := range t.styp {
501 if dependsOn(t1, t0) {
505 for _, t1 := range t.rtyp {
506 if dependsOn(t1, t0) {
510 for _, e := range t.elems {
511 if dependsOn(e.typ, t0) {