7 func (smith *Smith) initStatements() {
8 smith.statements = []func(){
30 func (smith *Smith) genStatement() {
31 if smith.stmtCount >= NStatements {
36 smith.statements[smith.rnd(len(smith.statements))]()
39 func (smith *Smith) stmtOas() {
40 list := smith.atypeList(TraitAny)
41 str, vars := smith.fmtOasVarList(list)
42 smith.line("%v := %v", str, smith.fmtRvalueList(list))
43 for _, v := range vars {
44 smith.defineVar(v.id, v.typ)
48 func (smith *Smith) stmtReturn() {
49 smith.line("return %v", smith.fmtRvalueList(smith.curFunc.rets))
52 func (smith *Smith) stmtAs() {
53 types := smith.atypeList(TraitAny)
54 smith.line("%v = %v", smith.fmtLvalueList(types), smith.fmtRvalueList(types))
57 func (smith *Smith) stmtInc() {
58 smith.line("%v %v", smith.lvalueOrMapIndex(smith.atype(ClassNumeric)), smith.choice("--", "++"))
61 func (smith *Smith) stmtIf() {
62 smith.enterBlock(true)
63 smith.enterBlock(true)
65 smith.line("if %v {", smith.rvalue(smith.atype(ClassBoolean)))
67 smith.line("if %v; %v {", smith.stmtSimple(true, nil), smith.rvalue(smith.atype(ClassBoolean)))
71 smith.line("} else {")
79 func (smith *Smith) stmtFor() {
80 smith.enterBlock(true)
81 smith.enterBlock(true)
82 smith.curBlock.isBreakable = true
83 smith.curBlock.isContinuable = true
85 switch smith.choice("simple", "complex", "range") {
87 smith.line("for %v {", smith.rvalue(smith.atype(ClassBoolean)))
89 smith.line("for %v; %v; %v {", smith.stmtSimple(true, nil), smith.rvalue(smith.atype(ClassBoolean)), smith.stmtSimple(false, nil))
91 switch smith.choice("slice", "string", "channel", "map") {
93 t := smith.atype(TraitAny)
94 s := smith.rvalue(smith.sliceOf(t))
95 switch smith.choice("one", "two", "oneDecl", "twoDecl") {
97 smith.line("for %v = range %v {", smith.lvalueOrBlank(smith.intType), s)
99 smith.line("for %v, %v = range %v {", smith.lvalueOrBlank(smith.intType), smith.lvalueOrBlank(t), s)
101 id := smith.newId("Var")
102 smith.line("for %v := range %v {", id, s)
103 vars = append(vars, &Var{id: id, typ: smith.intType})
105 types := []*Type{smith.intType, t}
107 str, vars = smith.fmtOasVarList(types)
108 smith.line("for %v := range %v {", str, s)
113 s := smith.rvalue(smith.stringType)
114 switch smith.choice("one", "two", "oneDecl", "twoDecl") {
116 smith.line("for %v = range %v {", smith.lvalueOrBlank(smith.intType), s)
118 smith.line("for %v, %v = range %v {", smith.lvalueOrBlank(smith.intType), smith.lvalueOrBlank(smith.runeType), s)
120 id := smith.newId("Var")
121 smith.line("for %v := range %v {", id, s)
122 vars = append(vars, &Var{id: id, typ: smith.intType})
124 types := []*Type{smith.intType, smith.runeType}
126 str, vars = smith.fmtOasVarList(types)
127 smith.line("for %v := range %v {", str, s)
132 cht := smith.atype(ClassChan)
133 ch := smith.rvalue(cht)
134 switch smith.choice("one", "oneDecl") {
136 smith.line("for %v = range %v {", smith.lvalueOrBlank(cht.ktyp), ch)
138 id := smith.newId("Var")
139 smith.line("for %v := range %v {", id, ch)
140 vars = append(vars, &Var{id: id, typ: cht.ktyp})
145 t := smith.atype(ClassMap)
147 switch smith.choice("one", "two", "oneDecl", "twoDecl") {
149 smith.line("for %v = range %v {", smith.lvalueOrBlank(t.ktyp), m)
151 smith.line("for %v, %v = range %v {", smith.lvalueOrBlank(t.ktyp), smith.lvalueOrBlank(t.vtyp), m)
153 id := smith.newId("Var")
154 smith.line("for %v := range %v {", id, m)
155 vars = append(vars, &Var{id: id, typ: t.ktyp})
157 types := []*Type{t.ktyp, t.vtyp}
159 str, vars = smith.fmtOasVarList(types)
160 smith.line("for %v := range %v {", str, m)
170 smith.enterBlock(true)
173 for _, v := range vars {
174 smith.defineVar(v.id, v.typ)
184 func (smith *Smith) stmtSimple(oas bool, newVars *[]*Var) string {
185 // We emit a fake statement in "oas", so make sure that nothing can be inserted in between.
186 if smith.curBlock.extendable {
189 // "send" crashes gccgo with random errors too frequently.
190 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61273
191 switch smith.choice("empty", "inc", "assign", "oas", "send", "expr") {
195 return F("%v %v", smith.lvalueOrMapIndex(smith.atype(ClassNumeric)), smith.choice("--", "++"))
197 list := smith.atypeList(TraitAny)
198 return F("%v = %v", smith.fmtLvalueList(list), smith.fmtRvalueList(list))
203 list := smith.atypeList(TraitAny)
204 str, vars := smith.fmtOasVarList(list)
208 res := F("%v := %v", str, smith.fmtRvalueList(list))
210 for _, v := range vars {
211 smith.defineVar(v.id, v.typ)
215 t := smith.atype(TraitSendable)
216 return F("%v <- %v", smith.rvalue(t), smith.rvalue(t.ktyp))
224 func (smith *Smith) stmtSend() {
225 t := smith.atype(TraitSendable)
226 smith.line("%v <- %v", smith.rvalue(t), smith.rvalue(t.ktyp))
229 func (smith *Smith) stmtRecv() {
230 t := smith.atype(TraitReceivable)
231 ch := smith.rvalue(t)
232 switch smith.choice("normal", "decl") {
234 smith.line("%v, %v = <-%v", smith.lvalueOrBlank(t.ktyp), smith.lvalueOrBlank(smith.boolType), ch)
236 vv := smith.newId("Var")
237 ok := smith.newId("Var")
238 smith.line("%v, %v := <-%v", vv, ok, ch)
239 smith.defineVar(vv, t.ktyp)
240 smith.defineVar(ok, smith.boolType)
246 func (smith *Smith) stmtTypeDecl() {
247 id := smith.newId("Type")
248 t := smith.atype(TraitAny)
249 smith.line("type %v %v", id, t.id)
254 newTyp.namedUserType = true
255 if t.class == ClassStruct {
256 newTyp.literal = func() string {
257 // replace struct name with new type id
262 newTyp.complexLiteral = func() string {
263 // replace struct name with new type id
264 l := t.complexLiteral()
269 newTyp.literal = func() string {
270 return F("%v(%v)", id, t.literal())
272 if t.complexLiteral != nil {
273 newTyp.complexLiteral = func() string {
274 return F("%v(%v)", id, t.complexLiteral())
278 smith.defineType(newTyp)
281 func (smith *Smith) stmtVarDecl() {
282 id := smith.newId("Var")
283 t := smith.atype(TraitAny)
284 smith.line("var %v %v = %v", id, t.id, smith.rvalue(t))
285 smith.defineVar(id, t)
288 func (smith *Smith) stmtSelect() {
289 smith.enterBlock(true)
290 smith.line("select {")
291 for smith.rnd(5) != 0 {
292 smith.enterBlock(true)
293 elem := smith.atype(TraitAny)
294 cht := smith.chanOf(elem)
295 ch := smith.rvalue(cht)
297 smith.line("case %v <- %v:", ch, smith.rvalue(elem))
299 switch smith.choice("one", "two", "oneDecl", "twoDecl") {
301 smith.line("case %v = <-%v:", smith.lvalueOrBlank(elem), ch)
303 smith.line("case %v, %v = <-%v:", smith.lvalueOrBlank(elem), smith.lvalueOrBlank(smith.boolType), ch)
305 vv := smith.newId("Var")
306 smith.line("case %v := <-%v:", vv, ch)
307 smith.defineVar(vv, elem)
309 vv := smith.newId("Var")
310 ok := smith.newId("Var")
311 smith.line("case %v, %v := <-%v:", vv, ok, ch)
312 smith.defineVar(vv, elem)
313 smith.defineVar(ok, smith.boolType)
322 smith.enterBlock(true)
323 smith.line("default:")
331 func (smith *Smith) stmtSwitchExpr() {
335 t = smith.atype(TraitComparable)
336 cond = smith.rvalue(t)
340 smith.enterBlock(true)
341 smith.enterBlock(true)
342 smith.curBlock.isBreakable = true
345 smith.line("switch %v {", cond)
347 smith.line("switch %v; %v {", smith.stmtSimple(true, &vars), cond)
349 // TODO: we generate at most one case, because if we generate more,
350 // we can generate two cases with equal constants.
353 smith.enterBlock(true)
354 smith.line("case %v:", smith.rvalue(t))
359 smith.line("fallthrough")
362 if fallth || len(vars) > 0 || smith.rndBool() {
363 smith.enterBlock(true)
364 smith.line("default:")
366 for _, v := range vars {
367 smith.line("_ = %v", v.id)
377 func (smith *Smith) stmtSwitchType() {
378 cond := smith.lvalue(smith.atype(TraitAny))
379 smith.enterBlock(true)
380 smith.curBlock.isBreakable = true
381 smith.line("switch COND := (interface{})(%v); COND.(type) {", cond)
383 smith.enterBlock(true)
384 smith.line("case %v:", smith.atype(TraitAny).id)
389 smith.enterBlock(true)
390 smith.line("default:")
398 func (smith *Smith) stmtCall() {
400 smith.stmtCallBuiltin()
402 t := smith.atype(ClassFunction)
403 prefix := smith.choice("", "go", "defer")
404 smith.line("%v %v(%v)", prefix, smith.rvalue(t), smith.fmtRvalueList(t.styp))
407 func (smith *Smith) stmtCallBuiltin() {
408 prefix := smith.choice("", "go", "defer")
409 switch fn := smith.choice("close", "copy", "delete", "panic", "print", "println", "recover"); fn {
411 smith.line("%v %v(%v)", prefix, fn, smith.rvalue(smith.atype(ClassChan)))
413 smith.line("%v %v", prefix, smith.exprCopySlice())
415 t := smith.atype(ClassMap)
416 smith.line("%v %v(%v, %v)", prefix, fn, smith.rvalue(t), smith.rvalue(t.ktyp))
418 smith.line("%v %v(%v)", prefix, fn, smith.rvalue(smith.atype(TraitAny)))
422 list := smith.atypeList(TraitPrintable)
423 smith.line("%v %v(%v)", prefix, fn, smith.fmtRvalueList(list))
425 smith.line("%v %v()", prefix, fn)
431 func (smith *Smith) stmtBreak() {
432 if !smith.curBlock.isBreakable {
438 func (smith *Smith) stmtContinue() {
439 if !smith.curBlock.isContinuable {
442 smith.line("continue")
445 func (smith *Smith) stmtGoto() {
446 // TODO: suppport goto down
447 id := smith.materializeGotoLabel()
448 smith.line("goto %v", id)
451 func (smith *Smith) stmtSink() {
453 smith.line("SINK = %v", smith.exprVar(smith.atype(TraitAny)))