Skip to content

Commit

Permalink
1622 stepper does not evaluate arguments when it should (#1628)
Browse files Browse the repository at this point in the history
* refactor and rearrange function call reducer

* add tests

* add more tests

* change the order of operation

* removed redundant checks

* edit tests to new implementation
  • Loading branch information
hanscau authored Apr 1, 2024
1 parent 8486835 commit e1637fe
Show file tree
Hide file tree
Showing 3 changed files with 232 additions and 108 deletions.
136 changes: 111 additions & 25 deletions src/stepper/__tests__/__snapshots__/stepper.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4117,58 +4117,123 @@ f();
"
`;

exports[`Test catching errors from built in function Incorrect number of arguments 1`] = `
"Start of evaluation
Line 1: Expected 2 arguments, but got 1"
exports[`Test calling functions Argument reduction steps 1`] = `
"(1 * 3)(2 * 3 + 10);

(1 * 3)(2 * 3 + 10);

(3)(2 * 3 + 10);

(3)(2 * 3 + 10);

(3)(6 + 10);

(3)(6 + 10);

(3)(16);

(3)(16);
"
`;

exports[`Test catching errors from built in function Incorrect type of argument for math function 1`] = `
"Start of evaluation
Line 2: Math functions must be called with number arguments"
exports[`Test calling functions Built-in function 1`] = `
"is_boolean(false);

is_boolean(false);

true;

true;
"
`;

exports[`Test catching errors from built in function Incorrect type of arguments for module function 1`] = `
"Start of evaluation
Line 2: arity expects a function as argument"
exports[`Test calling functions Function that exists 1`] = `
"function foo(x) {
return x;
}
foo(1 + 2);

function foo(x) {
return x;
}
foo(1 + 2);

foo(1 + 2);

foo(1 + 2);

foo(3);

foo(3);

3;

3;
"
`;

exports[`Test catching of undeclared variable error Variable not declared in block statement 1`] = `"Line 3: Name undeclared_variable not declared."`;
exports[`Test calling functions Imported module function 1`] = `
"pair(1, 1);

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

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

exports[`Test catching runtime errors Calling non function value 1`] = `
"Start of evaluation
Binary expression 2 + 3 evaluated
Binary expression 2 + 3 evaluated
Line 2: Calling non-function value 5."
[1, 1];
"
`;

exports[`Test catching runtime errors Incorrect number of argument 1`] = `
exports[`Test calling functions Incorrect number of argument (less) 1`] = `
"Start of evaluation
Function foo declared, parameter(s) a required
Function foo declared, parameter(s) a required
Line 5: Expected 1 arguments, but got 0."
Line 5: Expected 0 arguments, but got 1."
`;

exports[`Test catching runtime errors Incorrect number of argument 2`] = `
exports[`Test calling functions Incorrect number of argument (more) 1`] = `
"Start of evaluation
Function foo declared, parameter(s) a required
Function foo declared, parameter(s) a required
Line 5: Expected 1 arguments, but got 3."
Line 5: Expected 3 arguments, but got 1."
`;

exports[`Test catching runtime errors Type error 1`] = `
exports[`Test calling functions Literal function should error 1`] = `
"Start of evaluation
Line 2: Expected number on right hand side of operation, got string."
Line 2: Calling non-function value 1."
`;

exports[`Test catching runtime errors Variable not assigned 1`] = `
exports[`Test calling functions Math function 1`] = `
"math_abs(-1);

math_abs(-1);

1;

1;
"
`;

exports[`Test catching errors from built in function Incorrect number of arguments 1`] = `
"Start of evaluation
Line 2: Name unassigned_variable declared later in current scope but not yet assigned"
"
`;

exports[`Test catching errors from built in function Incorrect type of argument for math function 1`] = `
"Start of evaluation
"
`;

exports[`Test catching errors from built in function Incorrect type of arguments for module function 1`] = `
"Start of evaluation
"
`;

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 Expand Up @@ -4655,6 +4720,27 @@ exports[`Test reducing of empty block into epsilon Empty blocks in block 1`] = `
"
`;

exports[`Test runtime errors Incompatible types operation 1`] = `
"Start of evaluation
Binary expression 2 * 3 evaluated
Binary expression 2 * 3 evaluated
Line 2: Expected string on right hand side of operation, got number."
`;

exports[`Test runtime errors Variable used before assigning in functions 1`] = `
"Start of evaluation
Function foo declared
Function foo declared
Function foo runs
Function foo runs
Line 3: Name unassigned_variable declared later in current scope but not yet assigned"
`;

exports[`Test runtime errors Variable used before assigning in program 1`] = `
"Start of evaluation
Line 2: Name unassigned_variable declared later in current scope but not yet assigned"
`;

exports[`const declarations in blocks subst into call expressions 1`] = `
"const z = 1;
function f(g) {
Expand Down
79 changes: 67 additions & 12 deletions src/stepper/__tests__/stepper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,33 +85,57 @@ const testEvalSteps = (programStr: string, context?: Context) => {
return getEvaluationSteps(program, context, options)
}

describe('Test catching runtime errors', () => {
test('Variable not assigned', async () => {
describe('Test calling functions', () => {
test('Function that exists', async () => {
const code = `
unassigned_variable;
const unassigned_variable = "value";
function foo(x) { return x;}
foo(1 + 2);
`
const steps = await testEvalSteps(code)
expect(getExplanation(steps)).toMatchSnapshot()
expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot()
})

test('Type error', async () => {
test('Math function', async () => {
const code = `
1 + "string";
math_abs(-1);
`
const steps = await testEvalSteps(code)
expect(getExplanation(steps)).toMatchSnapshot()
expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot()
})

test('Imported module function', async () => {
const code = `
pair(1, 1);
`
const steps = await testEvalSteps(code)
expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot()
})

test('Built-in function', async () => {
const code = `
is_boolean(false);
`
const steps = await testEvalSteps(code)
expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot()
})

test('Argument reduction steps', async () => {
const code = `
(1 * 3)(2 * 3 + 10);
`
const steps = await testEvalSteps(code)
expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot()
})

test('Calling non function value', async () => {
test('Literal function should error', async () => {
const code = `
(2 + 3)(1 - 4);
1(2);
`
const steps = await testEvalSteps(code)
expect(getExplanation(steps)).toMatchSnapshot()
})

test('Incorrect number of argument', async () => {
test('Incorrect number of argument (less)', async () => {
const code = `
function foo(a) {
return a;
Expand All @@ -122,7 +146,7 @@ describe('Test catching runtime errors', () => {
expect(getExplanation(steps)).toMatchSnapshot()
})

test('Incorrect number of argument', async () => {
test('Incorrect number of argument (more)', async () => {
const code = `
function foo(a) {
return a;
Expand All @@ -134,6 +158,37 @@ describe('Test catching runtime errors', () => {
})
})

describe('Test runtime errors', () => {
test('Variable used before assigning in program', async () => {
const code = `
unassigned_variable;
const unassigned_variable = "assigned";
`
const steps = await testEvalSteps(code)
expect(getExplanation(steps)).toMatchSnapshot()
})

test('Variable used before assigning in functions', async () => {
const code = `
function foo() {
unassigned_variable;
const unassigned_variable = "assigned";
}
foo();
`
const steps = await testEvalSteps(code)
expect(getExplanation(steps)).toMatchSnapshot()
})

test('Incompatible types operation', async () => {
const code = `
"1" + 2 * 3;
`
const steps = await testEvalSteps(code)
expect(getExplanation(steps)).toMatchSnapshot()
})
})

describe('Test catching errors from built in function', () => {
test('Incorrect type of argument for math function', async () => {
const code = `
Expand Down
Loading

0 comments on commit e1637fe

Please sign in to comment.