diff --git a/app/javascript/interpreter/error.ts b/app/javascript/interpreter/error.ts index 6c53cf0f95..e7a5aa5ae9 100644 --- a/app/javascript/interpreter/error.ts +++ b/app/javascript/interpreter/error.ts @@ -20,6 +20,7 @@ export type RuntimeErrorType = | 'InvalidExpression' | 'RepeatCountMustBeNumber' | 'RepeatCountMustBeGreaterThanZero' + | 'RepeatCountMustBeLessThanOneThousand' | 'NonCallableTarget' | 'InfiniteLoop' | 'TooFewArguments' diff --git a/app/javascript/interpreter/executor.ts b/app/javascript/interpreter/executor.ts index ea7284c4c5..95d3a7746f 100644 --- a/app/javascript/interpreter/executor.ts +++ b/app/javascript/interpreter/executor.ts @@ -260,15 +260,28 @@ export class Executor this.evaluate(statement.count) ) - if (!isNumber(count)) + if (!isNumber(count)) { this.error('RepeatCountMustBeNumber', statement.count.location, { count, }) + } - if (count < 1) + if (count < 1) { this.error('RepeatCountMustBeGreaterThanZero', statement.count.location, { count, }) + } + + if (count > 1000) { + console.log('HERE') + this.error( + 'RepeatCountMustBeLessThanOneThousand', + statement.count.location, + { + count, + } + ) + } while (count > 0) { this.executeBlock(statement.body, this.environment) diff --git a/app/javascript/interpreter/locales/en/translation.json b/app/javascript/interpreter/locales/en/translation.json index 22329d2c34..5847d2278c 100644 --- a/app/javascript/interpreter/locales/en/translation.json +++ b/app/javascript/interpreter/locales/en/translation.json @@ -86,7 +86,8 @@ "OperandMustBeNumber": "Operand must be a number.", "OperandsMustBeNumber": "Operands must be numbers.", "OperandsMustBeTwoNumbersOrTwoStrings": "Operands must be two numbers or two strings.", - "RepeatCountMustBeGreaterThanZero": "The repeat argument must be greater than zero.", + "RepeatCountMustBeGreaterThanZero": "You must repeat things at least once.", + "RepeatCountMustBeLessThanOneThousand": "The most times you can repeat things is 1000.", "RepeatCountMustBeNumber": "repeat can only take a number as its argument.", "VariableAlreadyDeclared": "A variable with this name has already been created. Did you mean to use the <code>change</code> keyword?" }, diff --git a/test/javascript/interpreter/languages/jikiscript/interpreter.test.ts b/test/javascript/interpreter/languages/jikiscript/interpreter.test.ts index 5d7df64f76..5dabac31e6 100644 --- a/test/javascript/interpreter/languages/jikiscript/interpreter.test.ts +++ b/test/javascript/interpreter/languages/jikiscript/interpreter.test.ts @@ -633,6 +633,20 @@ describe('statements', () => { expect(frames[4].status).toBe('SUCCESS') expect(frames[4].variables).toMatchObject({ x: 3 }) }) + test('must be 1000 times or fewer', () => { + const { error, frames } = interpret(` + repeat 1001 times do + end + `) + expect(frames).toBeArrayOfSize(2) + + expect(frames[1].line).toBe(2) + expect(frames[1].status).toBe('ERROR') + expect(frames[1].code).toBe('1001') + expect(frames[1].error).not.toBeNull() + expect(frames[1].error!.category).toBe('RuntimeError') + expect(frames[1].error!.type).toBe('RepeatCountMustBeLessThanOneThousand') + }) }) describe('while', () => {