(total int)
| 170 | } |
| 171 | |
| 172 | func (l *State) concat(total int) { |
| 173 | t := func(i int) value { return l.stack[l.top-i] } |
| 174 | put := func(i int, v value) { l.stack[l.top-i] = v } |
| 175 | concatTagMethod := func() { |
| 176 | if v, ok := l.callBinaryTagMethod(t(2), t(1), tmConcat); !ok { |
| 177 | l.concatError(t(2), t(1)) |
| 178 | } else { |
| 179 | put(2, v) |
| 180 | } |
| 181 | } |
| 182 | l.assert(total >= 2) |
| 183 | for total > 1 { |
| 184 | n := 2 // # of elements handled in this pass (at least 2) |
| 185 | s2, ok := t(2).(string) |
| 186 | if !ok { |
| 187 | _, ok = t(2).(float64) |
| 188 | } |
| 189 | if !ok { |
| 190 | concatTagMethod() |
| 191 | } else if s1, ok := l.toString(l.top - 1); !ok { |
| 192 | concatTagMethod() |
| 193 | } else if len(s1) == 0 { |
| 194 | v, _ := l.toString(l.top - 2) |
| 195 | put(2, v) |
| 196 | } else if s2, ok = t(2).(string); ok && len(s2) == 0 { |
| 197 | put(2, t(1)) |
| 198 | } else { |
| 199 | // at least 2 non-empty strings; scarf as many as possible |
| 200 | ss := []string{s1} |
| 201 | for ; n <= total; n++ { |
| 202 | if s, ok := l.toString(l.top - n); ok { |
| 203 | ss = append(ss, s) |
| 204 | } else { |
| 205 | break |
| 206 | } |
| 207 | } |
| 208 | n-- // last increment wasn't valid |
| 209 | for i, j := 0, len(ss)-1; i < j; i, j = i+1, j-1 { |
| 210 | ss[i], ss[j] = ss[j], ss[i] |
| 211 | } |
| 212 | put(len(ss), strings.Join(ss, "")) |
| 213 | } |
| 214 | total -= n - 1 // created 1 new string from `n` strings |
| 215 | l.top -= n - 1 // popped `n` strings and pushed 1 |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | func (l *State) traceExecution() { |
| 220 | callInfo := l.callInfo |
no test coverage detected