Skip to content

Commit

Permalink
Stepper: Catch and show "name not declared" error (#1608)
Browse files Browse the repository at this point in the history
* add: catch and show SourceRuntimeError

* refactor

* add: tests

* linting

* removed unused imports

* linting

* Revert "linting"

This reverts commit ff1c011.

* add comment for getExplanation

---------

Co-authored-by: Martin Henz <[email protected]>
  • Loading branch information
hanscau and martin-henz authored Mar 25, 2024
1 parent 7c831d8 commit 9c46cc1
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 4 deletions.
6 changes: 6 additions & 0 deletions src/stepper/__tests__/__snapshots__/stepper.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4117,6 +4117,12 @@ f();
"
`;

exports[`Test catching of undeclared variable error Variable not declared in block statement 1`] = `"Line 3: Name undeclared_variable not declared."`;

exports[`Test catching of undeclared variable error Variable not declared in function declaration 1`] = `"Line 3: Name undeclared_variable not declared."`;

exports[`Test catching of undeclared variable error Variable not declared in program 1`] = `"Line 2: Name undeclared_variable not declared."`;

exports[`Test correct evaluation sequence when first statement is a value Irreducible second statement in block 1`] = `
"{
'value';
Expand Down
35 changes: 35 additions & 0 deletions src/stepper/__tests__/stepper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ function getLastStepAsString(steps: [substituterNodes, string[][], string][]): s
return codify(steps[steps.length - 1][0]).trim()
}

function getExplanation(steps: [substituterNodes, string[][], string][]): string {
// Explanation of the step is kept in index 2 of steps
return steps.map(x => x[2]).join('\n')
}

describe('Test codify works on non-circular abstract syntax graphs', () => {
test('arithmetic', () => {
const code = `
Expand Down Expand Up @@ -80,6 +85,36 @@ const testEvalSteps = (programStr: string, context?: Context) => {
return getEvaluationSteps(program, context, options)
}

describe('Test catching of undeclared variable error', () => {
test('Variable not declared in program', async () => {
const code = `
undeclared_variable;
`
const steps = await testEvalSteps(code)
expect(getExplanation(steps)).toMatchSnapshot()
})

test('Variable not declared in block statement', async () => {
const code = `
{
undeclared_variable;
}
`
const steps = await testEvalSteps(code)
expect(getExplanation(steps)).toMatchSnapshot()
})

test('Variable not declared in function declaration', async () => {
const code = `
function foo() {
undeclared_variable;
}
`
const steps = await testEvalSteps(code)
expect(getExplanation(steps)).toMatchSnapshot()
})
})

describe('Test reducing of empty block into epsilon', () => {
test('Empty block in program', async () => {
const code = `
Expand Down
16 changes: 14 additions & 2 deletions src/stepper/stepper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type es from 'estree'

import { type IOptions } from '..'
import * as errors from '../errors/errors'
import { RuntimeSourceError } from '../errors/runtimeSourceError'
import { initModuleContextAsync, loadModuleBundleAsync } from '../modules/loader/moduleLoaderAsync'
import { parse } from '../parser/parser'
import {
Expand Down Expand Up @@ -37,7 +38,8 @@ import {
isAllowedLiterals,
isBuiltinFunction,
isImportedFunction,
isNegNumber
isNegNumber,
prettyPrintError
} from './util'

const irreducibleTypes = new Set<string>([
Expand Down Expand Up @@ -3414,7 +3416,17 @@ export async function getEvaluationSteps(
}
return steps
} catch (error) {
context.errors.push(error)
if (error instanceof RuntimeSourceError) {
// If steps not evaluated at all, add error message to the first step else add error to last step
if (steps.length === 0) {
steps.push([program, [], prettyPrintError(error)])
} else {
steps[steps.length - 1][2] = prettyPrintError(error)
}
} else {
context.errors.push(error)
}

return steps
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/stepper/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { RuntimeSourceError } from '../errors/runtimeSourceError'
import { BlockExpression, Environment, Node, substituterNodes, Value } from '../types'
import * as builtin from './lib'

export function prettyPrintError(error: RuntimeSourceError): string {
return `Line ${error.location.start.line}: ${error.explain()}`
}

export function isBuiltinFunction(node: substituterNodes): boolean {
return (
node.type === 'Identifier' &&
Expand Down
3 changes: 1 addition & 2 deletions src/validator/validator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as es from 'estree'

import { ConstAssignment } from '../errors/errors'
import { UndefinedVariable } from '../errors/errors'
import { ConstAssignment, UndefinedVariable } from '../errors/errors'
import { NoAssignmentToForVariable } from '../errors/validityErrors'
import { parse } from '../parser/parser'
import { Context, Node, NodeWithInferredType } from '../types'
Expand Down

0 comments on commit 9c46cc1

Please sign in to comment.