compileLoop compiles an endless loop.
(node *ast.Loop)
| 10 | |
| 11 | // compileLoop compiles an endless loop. |
| 12 | func (f *Function) compileLoop(node *ast.Loop) error { |
| 13 | f.Count.Loop++ |
| 14 | headLabel := f.CreateLabel("loop.head", f.Count.Loop) |
| 15 | exitLabel := f.CreateLabel("loop.exit", f.Count.Loop) |
| 16 | beforeLoop := f.Block() |
| 17 | loopHead := ssa.NewBlock(headLabel) |
| 18 | loopExit := ssa.NewBlock(exitLabel) |
| 19 | loopBlockIndex := len(f.Blocks) |
| 20 | |
| 21 | loop := &Loop{ |
| 22 | Head: loopHead, |
| 23 | Exit: loopExit, |
| 24 | } |
| 25 | |
| 26 | if node.Head != nil { |
| 27 | // Before the loop starts, we evaluate the lower limit |
| 28 | // and identify it as the loop counter. |
| 29 | name, from, to := f.parseLoopHeader(node.Head) |
| 30 | |
| 31 | if from == nil { |
| 32 | return errors.New(InvalidLoopHeader, f.File, node.Head.Source()) |
| 33 | } |
| 34 | |
| 35 | loop.IteratorName = name |
| 36 | fromValue, err := f.evaluateRight(from) |
| 37 | |
| 38 | if err != nil { |
| 39 | return err |
| 40 | } |
| 41 | |
| 42 | if !types.Is(fromValue.Type(), types.AnyInt) { |
| 43 | return errors.New(&TypeMismatch{Encountered: fromValue.Type().Name(), Expected: types.AnyInt.Name()}, f.File, from.Source()) |
| 44 | } |
| 45 | |
| 46 | if f.Block().IsIdentified(fromValue) { |
| 47 | fromValue = f.copy(fromValue, from.Source()) |
| 48 | } |
| 49 | |
| 50 | beforeLoop.Identify(name, fromValue) |
| 51 | f.jump(loopHead) |
| 52 | |
| 53 | // Loop starts, this is the jump target for new iterations. |
| 54 | // The upper limit is recalculated on every iteration. |
| 55 | // We check that the condition to jump to the loop body is true, |
| 56 | // otherwise we jump to the loop exit. |
| 57 | f.AddBlock(loopHead) |
| 58 | toValue, err := f.evaluateRight(to) |
| 59 | |
| 60 | if err != nil { |
| 61 | return err |
| 62 | } |
| 63 | |
| 64 | if !types.Is(toValue.Type(), fromValue.Type()) { |
| 65 | return errors.New(&TypeMismatch{Encountered: toValue.Type().Name(), Expected: fromValue.Type().Name()}, f.File, to.Source()) |
| 66 | } |
| 67 | |
| 68 | condition := f.Append(&ssa.BinaryOp{ |
| 69 | Op: token.Less, |
no test coverage detected