| 215 | } |
| 216 | |
| 217 | static ConvertForOfStatement (n, ctx) { |
| 218 | ctx.scope[n.left.name] = { type: 'var' } |
| 219 | const body = convert(n.body, { ...ctx, nospace: true, context: 'statement' }) |
| 220 | let o |
| 221 | if (n.right?.type === 'CallExpression' && n.right.callee?.name === 'range' && n.right.arguments?.length && (!n.right.arguments[2] || n.right.arguments[2].value === 1)) { |
| 222 | try { |
| 223 | // Use controls_repeat_ext block instead of a controls_forEach block for Python ranges that are just repeating N times |
| 224 | let start, end, endNode |
| 225 | if (n.right.arguments.length > 1) { |
| 226 | start = n.right.arguments[0].value |
| 227 | end = n.right.arguments[1].value |
| 228 | endNode = n.right.arguments[1] |
| 229 | } else { |
| 230 | start = 0 |
| 231 | end = n.right.arguments[0].value |
| 232 | endNode = n.right.arguments[0] |
| 233 | } |
| 234 | const times = end - start |
| 235 | // For Junior, we have simplified dropdown block if the range is in 1-7 |
| 236 | const type = times >= 1 && times <= 7 && _.find(ctx.plan, p => p[0].type === 'controls_repeat_dropdown') ? 'controls_repeat_dropdown' : 'controls_repeat_ext' |
| 237 | if (type === 'controls_repeat_ext' && !_.find(ctx.plan, p => p[0].type === 'controls_repeat_ext')) { |
| 238 | // TODO: figure out how to include both block definitions without breaking code-to-blocks finding right one in its planning |
| 239 | throw new Error('controls_repeat_ext block not available for loop with range', start, 'to', end) |
| 240 | } |
| 241 | if (type === 'controls_repeat_dropdown') { |
| 242 | // Change input to field |
| 243 | o = { type, inputs: {}, fields: { TIMES: '' + times } } |
| 244 | } else { |
| 245 | const fakeTimesNode = _.cloneDeep(endNode) |
| 246 | fakeTimesNode.raw = '' + times |
| 247 | fakeTimesNode.value = times |
| 248 | const fakeBlock = convert(fakeTimesNode, ctx) |
| 249 | o = { type, inputs: { TIMES: { block: fakeBlock } } } |
| 250 | } |
| 251 | } catch (err) { |
| 252 | console.error("Couldn't convert for-in range to simple repeat block:", n, err) |
| 253 | } |
| 254 | } |
| 255 | if (!o) { |
| 256 | o = { |
| 257 | // type: 'controls_untyped_for_each', |
| 258 | type: 'controls_forEach', |
| 259 | fields: { |
| 260 | VAR: { id: n.left.name }, |
| 261 | }, |
| 262 | inputs: { |
| 263 | LIST: { block: convert(n.right, { ...ctx, context: 'value' }) }, |
| 264 | }, |
| 265 | } |
| 266 | } |
| 267 | |
| 268 | if (body) o.inputs.DO = { block: body[0] } |
| 269 | return o |
| 270 | } |
| 271 | |
| 272 | static ConvertIfStatement (n, ctx) { |
| 273 | // TODO: ELSE, ELSEIF |