diff --git a/package.json b/package.json index 178fbeee..aae51826 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "test:game": "mocha --parallel -r ts-node/register/transpile-only test/**/game.test.ts", "test:dynamicDiagram": "mocha --parallel -r ts-node/register/transpile-only test/dynamicDiagram.test.ts", "test:helpers": "mocha --parallel -r ts-node/register/transpile-only test/helpers.test.ts", - "test:interpreter": "mocha --parallel -r ts-node/register/transpile-only test/interpreter.test.ts", + "test:interpreter": "mocha -r ts-node/register/transpile-only test/interpreter.test.ts", "test:linker": "mocha --parallel -r ts-node/register/transpile-only test/linker.test.ts", "test:messageReporter": "mocha --parallel -r ts-node/register/transpile-only test/messageReporter.test.ts", "test:model": "mocha --parallel -r ts-node/register/transpile-only test/model.test.ts", diff --git a/src/interpreter/interpreter.ts b/src/interpreter/interpreter.ts index 25a096de..a9bfc9b9 100644 --- a/src/interpreter/interpreter.ts +++ b/src/interpreter/interpreter.ts @@ -33,7 +33,7 @@ abstract class AbstractInterpreter { exec(node: Sentence): InterpreterResult exec(node: Node): InterpreterResult exec(node: Node): InterpreterResult { - return this.do(function*() { return yield* this.exec(node) }) + return this.do(function* () { return yield* this.exec(node) }) } run(programOrTestFQN: Name): InterpreterResult { @@ -41,39 +41,39 @@ abstract class AbstractInterpreter { } send(message: Name, receiver: RuntimeObject, ...args: RuntimeObject[]): InterpreterResult { - return this.do(function*() { return yield* this.send(message, receiver, ...args) }) + return this.do(function* () { return yield* this.send(message, receiver, ...args) }) } invoke(method: Method, receiver: RuntimeObject, ...args: RuntimeObject[]): InterpreterResult { - return this.do(function*() { return yield* this.invoke(method, receiver, ...args) }) + return this.do(function* () { return yield* this.invoke(method, receiver, ...args) }) } reify(value: boolean | number | string | null): InterpreterResult { - return this.do(function*() { return yield* this.reify(value) }) + return this.do(function* () { return yield* this.reify(value) }) } list(...value: RuntimeObject[]): InterpreterResult { - return this.do(function*() { return yield* this.list(...value) }) + return this.do(function* () { return yield* this.list(...value) }) } set(...value: RuntimeObject[]): InterpreterResult { - return this.do(function*() { return yield* this.set(...value) }) + return this.do(function* () { return yield* this.set(...value) }) } error(moduleOrFQN: Module | Name, locals?: Record, error?: Error): InterpreterResult { - return this.do(function*() { return yield* this.error(moduleOrFQN, locals, error) }) + return this.do(function* () { return yield* this.error(moduleOrFQN, locals, error) }) } instantiate(moduleOrFQN: Module | Name, locals: Record = {}): InterpreterResult { - return this.do(function*() { return yield* this.instantiate(moduleOrFQN, locals) }) + return this.do(function* () { return yield* this.instantiate(moduleOrFQN, locals) }) } } export type ExecutionResult = { - result: string; - error?: Error; - errored: boolean; + result: string + error?: Error + errored: boolean } const failureResult = (message: string, error?: Error): ExecutionResult => ({ @@ -92,6 +92,7 @@ export const getStackTraceSanitized = (e?: Error): string[] => { const fullStack = e?.stack?.slice(0, indexOfTsStack ?? -1) ?? '' return fullStack + .replaceAll('\r', '') .replaceAll('\t', ' ') .replaceAll(' ', ' ') .replaceAll(' ', ' ') @@ -109,7 +110,7 @@ export class Interpreter extends AbstractInterpreter { override do(executionDefinition: ExecutionDefinition): T { const execution = executionDefinition.call(this.evaluation) let next = execution.next() - while(!next.done) next = execution.next() + while (!next.done) next = execution.next() return next.value as InterpreterResult } @@ -204,17 +205,17 @@ export class ExecutionDirector { this.breakpoints.push(...nextBreakpoints) } - finish(): ExecutionState & {done: true} { + finish(): ExecutionState & { done: true } { let result = this.resume() - while(!result.done) result = this.resume() + while (!result.done) result = this.resume() return result } resume(shouldHalt: (next: Node, evaluation: Evaluation) => boolean = () => false): ExecutionState { try { let next = this.execution.next() - while(!next.done) { - if(this.breakpoints.includes(next.value) || shouldHalt(next.value, this.evaluation)) + while (!next.done) { + if (this.breakpoints.includes(next.value) || shouldHalt(next.value, this.evaluation)) return { done: false, next: next.value } next = this.execution.next() diff --git a/src/interpreter/runtimeModel.ts b/src/interpreter/runtimeModel.ts index 8bc5c827..af7116cd 100644 --- a/src/interpreter/runtimeModel.ts +++ b/src/interpreter/runtimeModel.ts @@ -138,18 +138,17 @@ export class Frame extends Context { [Entity, (node: Entity) => `${node.fullyQualifiedName}`], // TODO: Add fqn to method when(Method)(node => `${node.parent.fullyQualifiedName}.${node.name}(${node.parameters.map(parameter => parameter.name).join(', ')})`), + when(Send)(node => `${node.message}/${node.args.length}`), when(Catch)(node => `catch(${node.parameter.name}: ${node.parameterType.name})`), when(Environment)(() => 'root'), otherwise((node: Node) => `${node.kind}`), ) } - // TODO: On error report, this tells the node line, but not the actual error line. - // For example, an error on a test would say the test start line, not the line where the error occurred. get sourceInfo(): string { const target = this.node.is(Method) && this.node.name === CLOSURE_EVALUATE_METHOD - ? this.node.parent - : this.node + ? this.currentNode.parent + : this.currentNode return target.sourceInfo } diff --git a/test/game.test.ts b/test/game.test.ts index d9f21c57..6c71287f 100644 --- a/test/game.test.ts +++ b/test/game.test.ts @@ -51,7 +51,7 @@ describe('Wollok Game', () => { interpreter.run('actions.genericError') logs.should.be.deep.eq([ 'wollok.lang.Exception: ERROR', - '\tat actions.genericError [actions.wpgm:33]']) + '\tat actions.genericError [actions.wpgm:37]']) }) it('with file name game (devil test)', () => { diff --git a/test/interpreter.test.ts b/test/interpreter.test.ts index bbe0dd40..a8a0ab2f 100644 --- a/test/interpreter.test.ts +++ b/test/interpreter.test.ts @@ -47,7 +47,7 @@ describe('Wollok Interpreter', () => { it('should be able to execute unlinked sentences', () => { const environment = link([ new Package({ - name:'p', + name: 'p', members: [ new Singleton({ name: 'o', @@ -81,7 +81,7 @@ describe('Wollok Interpreter', () => { it('should fail if there is an uninitialized field in a singleton', () => { const environment = link([ new Package({ - name:'p', + name: 'p', members: [ new Singleton({ name: 'o', @@ -102,7 +102,7 @@ describe('Wollok Interpreter', () => { it('should not fail if there is an explicit null initialization for a field in a singleton', () => { const environment = link([ new Package({ - name:'p', + name: 'p', members: [ new Singleton({ name: 'o', @@ -140,12 +140,10 @@ describe('Wollok Interpreter', () => { describe('interpret API function', () => { let interpreter: Interpreter - const expectError = (command: string, errorMessage: string) => { + const expectError = (command: string, ...errorMessage: string[]) => { const { error } = interprete(interpreter, command) assertBasicError(error) - expect(getStackTraceSanitized(error)).to.deep.equal([ - errorMessage, - ]) + expect(getStackTraceSanitized(error)).to.deep.equal(errorMessage) } const checkSuccessfulResult = (expression: string, expectedResult: string) => { @@ -479,7 +477,7 @@ describe('Wollok Interpreter', () => { expect(getStackTraceSanitized(error)).to.deep.equal( [ 'wollok.lang.EvaluationError: RangeError: super call for message fly/1: parameter #1 produces no value, cannot use it', - ' at REPL.MockingBird.fly(minutes) [REPL:10]', + ' at REPL.MockingBird.fly(minutes) [REPL:11]', ] ) }) @@ -503,7 +501,7 @@ describe('Wollok Interpreter', () => { expect(getStackTraceSanitized(error)).to.deep.equal( [ 'wollok.lang.EvaluationError: RangeError: Message fly - if condition produces no value, cannot use it', - ' at REPL.Bird.fly(minutes) [REPL:4]', + ' at REPL.Bird.fly(minutes) [REPL:5]', ] ) }) @@ -579,9 +577,9 @@ describe('Wollok Interpreter', () => { assertBasicError(error) expect(getStackTraceSanitized(error)).to.deep.equal([ 'wollok.lang.EvaluationError: TypeError: Message plusDays: parameter "wollok.lang.Date" should be a number', - ' at REPL.comun.despegar() [REPL:7]', - ' at REPL.comun.volar() [REPL:3]', - ' at REPL.Ave.volar() [REPL:16]', + ' at REPL.comun.despegar() [REPL:8]', + ' at REPL.comun.volar() [REPL:4]', + ' at REPL.Ave.volar() [REPL:17]', ]) }) @@ -600,7 +598,7 @@ describe('Wollok Interpreter', () => { assertBasicError(error) expect(getStackTraceSanitized(error)).to.deep.equal([ 'wollok.lang.EvaluationError: RangeError: Cannot send message +, receiver is an expression that produces no value.', - ' at REPL.pepita.unMetodo() [REPL:3]', + ' at REPL.pepita.unMetodo() [REPL:4]', ]) })