diff --git a/src/alt-langs/scheme/scm-slang b/src/alt-langs/scheme/scm-slang index e012cebcd..ad3b2e39c 160000 --- a/src/alt-langs/scheme/scm-slang +++ b/src/alt-langs/scheme/scm-slang @@ -1 +1 @@ -Subproject commit e012cebcd73ea162b5436709b2821ee64aa7ff56 +Subproject commit ad3b2e39c6c9cd944494bc6abf0d8fbaa11ee59d diff --git a/src/py-slang b/src/py-slang index a412b2163..821987b3e 160000 --- a/src/py-slang +++ b/src/py-slang @@ -1 +1 @@ -Subproject commit a412b2163ed93a4956a770091206e362f26b376e +Subproject commit 821987b3e66ed6574981ce58f4d5d43a7ccb11c1 diff --git a/src/stepper/__tests__/__snapshots__/stepper.ts.snap b/src/stepper/__tests__/__snapshots__/stepper.ts.snap index 554c63464..fee15d2af 100644 --- a/src/stepper/__tests__/__snapshots__/stepper.ts.snap +++ b/src/stepper/__tests__/__snapshots__/stepper.ts.snap @@ -2109,166 +2109,725 @@ undefined; " `; -exports[`Infinite recursion 1`] = ` -"function f() { - return f(); +exports[`Expressions: Binary operators And-shortcut-false test case 1`] = ` +"if (false && 1 + 2 === 1 + 2) { + 1; +} else { + 2; } -f(); -function f() { - return f(); +if (false && 1 + 2 === 1 + 2) { + 1; +} else { + 2; } -f(); -f(); +if (false) { + 1; +} else { + 2; +} -f(); +if (false) { + 1; +} else { + 2; +} -f(); +{ + undefined; + 2; +} -f(); +{ + undefined; + 2; +} -f(); +{ + 2; +} -f(); +{ + 2; +} -f(); +2; -f(); +2; +" +`; -f(); +exports[`Expressions: Binary operators And-shortcut-true test case 1`] = ` +"if (true && 1 + 2 === 2 + 3) { + 1; +} else { + 2; +} -f(); +if (true && 1 + 2 === 2 + 3) { + 1; +} else { + 2; +} -f(); +if (1 + 2 === 2 + 3) { + 1; +} else { + 2; +} -f(); +if (1 + 2 === 2 + 3) { + 1; +} else { + 2; +} -f(); +if (3 === 2 + 3) { + 1; +} else { + 2; +} -f(); +if (3 === 2 + 3) { + 1; +} else { + 2; +} -f(); +if (3 === 5) { + 1; +} else { + 2; +} -f(); +if (3 === 5) { + 1; +} else { + 2; +} -f(); +if (false) { + 1; +} else { + 2; +} -f(); +if (false) { + 1; +} else { + 2; +} -f(); +{ + undefined; + 2; +} -f(); +{ + undefined; + 2; +} -f(); +{ + 2; +} -f(); +{ + 2; +} -f(); +2; -f(); +2; +" +`; -f(); +exports[`Expressions: Binary operators Left-binary-reduce test case 1`] = ` +"if (1 + 2 + 3 === 1 + 2 + 3) { + 1; +} else { + 2; +} -f(); +if (1 + 2 + 3 === 1 + 2 + 3) { + 1; +} else { + 2; +} -f(); +if (3 + 3 === 1 + 2 + 3) { + 1; +} else { + 2; +} -f(); +if (3 + 3 === 1 + 2 + 3) { + 1; +} else { + 2; +} -f(); +if (6 === 1 + 2 + 3) { + 1; +} else { + 2; +} -f(); +if (6 === 1 + 2 + 3) { + 1; +} else { + 2; +} -f(); +if (6 === 3 + 3) { + 1; +} else { + 2; +} -f(); +if (6 === 3 + 3) { + 1; +} else { + 2; +} -f(); +if (6 === 6) { + 1; +} else { + 2; +} -f(); +if (6 === 6) { + 1; +} else { + 2; +} -f(); +if (true) { + 1; +} else { + 2; +} -f(); +if (true) { + 1; +} else { + 2; +} -f(); +{ + undefined; + 1; +} -f(); +{ + undefined; + 1; +} -f(); +{ + 1; +} -f(); +{ + 1; +} -f(); +1; -f(); +1; +" +`; -f(); +exports[`Expressions: Binary operators Or-shortcut-false test case 1`] = ` +"if (false || 1 + 2 === 1 + 2) { + 1; +} else { + 2; +} -f(); +if (false || 1 + 2 === 1 + 2) { + 1; +} else { + 2; +} -f(); +if (1 + 2 === 1 + 2) { + 1; +} else { + 2; +} -f(); +if (1 + 2 === 1 + 2) { + 1; +} else { + 2; +} -f(); +if (3 === 1 + 2) { + 1; +} else { + 2; +} -f(); +if (3 === 1 + 2) { + 1; +} else { + 2; +} -f(); +if (3 === 3) { + 1; +} else { + 2; +} -f(); +if (3 === 3) { + 1; +} else { + 2; +} -f(); +if (true) { + 1; +} else { + 2; +} -f(); +if (true) { + 1; +} else { + 2; +} -f(); +{ + undefined; + 1; +} -f(); +{ + undefined; + 1; +} -f(); +{ + 1; +} -f(); +{ + 1; +} -f(); +1; -f(); +1; +" +`; -f(); +exports[`Expressions: Binary operators Or-shortcut-true test case 1`] = ` +"if (true || 1 + 2 === 2 + 3) { + 1; +} else { + 2; +} -f(); +if (true || 1 + 2 === 2 + 3) { + 1; +} else { + 2; +} -f(); +if (true) { + 1; +} else { + 2; +} -f(); +if (true) { + 1; +} else { + 2; +} -f(); +{ + undefined; + 1; +} -f(); +{ + undefined; + 1; +} -f(); +{ + 1; +} -f(); +{ + 1; +} -f(); +1; -f(); +1; +" +`; -f(); +exports[`Expressions: Binary operators Prim-binary-reduce test case 1`] = ` +"if (1 >= 2) { + 1; +} else { + 2; +} -f(); +if (1 >= 2) { + 1; +} else { + 2; +} -f(); +if (false) { + 1; +} else { + 2; +} -f(); +if (false) { + 1; +} else { + 2; +} -f(); +{ + undefined; + 2; +} -f(); +{ + undefined; + 2; +} -f(); +{ + 2; +} + +{ + 2; +} + +2; + +2; +" +`; + +exports[`Expressions: Binary operators Right-binary-reduce test case 1`] = ` +"if (1 >= 1 + 1) { + 1; +} else { + 2; +} + +if (1 >= 1 + 1) { + 1; +} else { + 2; +} + +if (1 >= 2) { + 1; +} else { + 2; +} + +if (1 >= 2) { + 1; +} else { + 2; +} + +if (false) { + 1; +} else { + 2; +} + +if (false) { + 1; +} else { + 2; +} + +{ + undefined; + 2; +} + +{ + undefined; + 2; +} + +{ + 2; +} + +{ + 2; +} + +2; + +2; +" +`; + +exports[`Expressions: conditionals Conditional-false-reduce test case 1`] = ` +"false ? 1 + 2 : 2 + 3; + +false ? 1 + 2 : 2 + 3; + +2 + 3; + +2 + 3; + +5; + +5; +" +`; + +exports[`Expressions: conditionals Conditional-predicate-reduce test case 1`] = ` +"1 + 1 === 2 ? 1 + 2 : 2 + 3; + +1 + 1 === 2 ? 1 + 2 : 2 + 3; + +2 === 2 ? 1 + 2 : 2 + 3; + +2 === 2 ? 1 + 2 : 2 + 3; + +true ? 1 + 2 : 2 + 3; + +true ? 1 + 2 : 2 + 3; + +1 + 2; + +1 + 2; + +3; + +3; +" +`; + +exports[`Expressions: conditionals Conditional-true-reduce test case 1`] = ` +"true ? 1 + 2 : 2 + 3; + +true ? 1 + 2 : 2 + 3; + +1 + 2; + +1 + 2; + +3; + +3; +" +`; + +exports[`Expresssions: Blocks Block-expression-empty-reduce test case 1`] = ` +"function foo(x) {} +foo(0); + +function foo(x) {} +foo(0); + +foo(0); + +foo(0); + +{}; + +{}; + +undefined; + +undefined; +" +`; + +exports[`Expresssions: Blocks Block-expression-intro test case 1`] = ` +"function foo(x) { + 1 + 1; +} +foo(0); + +function foo(x) { + 1 + 1; +} +foo(0); + +foo(0); + +foo(0); + +{ + 1 + 1; +}; + +{ + 1 + 1; +}; + +{ + 2; +}; + +{ + 2; +}; + +undefined; + +undefined; +" +`; + +exports[`Expresssions: Blocks Block-expression-single-reduce test case 1`] = ` +"function foo(x) { + 1; +} +foo(0); + +function foo(x) { + 1; +} +foo(0); + +foo(0); + +foo(0); + +{ + 1; +}; + +{ + 1; +}; + +undefined; + +undefined; +" +`; + +exports[`Infinite recursion 1`] = ` +"function f() { + return f(); +} +f(); + +function f() { + return f(); +} +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); f(); @@ -4114,6 +4673,739 @@ f(); f(); +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +f(); + +" +`; + +exports[`Programs Eliminate-constant-declaration test case 1 1`] = ` +"const x = 0; + +const x = 0; + + +undefined; +" +`; + +exports[`Programs Eliminate-constant-declaration test case 2 1`] = ` +"1; +const x = 0; + +1; +const x = 0; + +1; + +1; +" +`; + +exports[`Programs Eliminate-function-declaration test case 1 1`] = ` +"function foo(x) { + return 0; +} + +function foo(x) { + return 0; +} + + +undefined; +" +`; + +exports[`Programs Eliminate-function-declaration test case 2 1`] = ` +"1; +function foo(x) { + return 0; +} + +1; +function foo(x) { + return 0; +} + +1; + +1; +" +`; + +exports[`Programs Program-intro test case 1 1`] = ` +"1 + 1; + +1 + 1; + +2; + +2; +" +`; + +exports[`Programs Program-intro test case 2 1`] = ` +"1; +1 + 1; + +1; +1 + 1; + +1; +2; + +1; +2; + +2; + +2; +" +`; + +exports[`Programs Program-reduce test case 1`] = ` +"1; +2; + +1; +2; + +2; + +2; +" +`; + +exports[`Statements: Blocks Block-statement-empty-reduce test case 1 1`] = ` +"{} + +{} + + +undefined; +" +`; + +exports[`Statements: Blocks Block-statement-empty-reduce test case 2 1`] = ` +"{ + { + {} + {} + } + { + {} + {} + } +} + +{ + { + {} + {} + } + { + {} + {} + } +} + +{ + { + {} + } + { + {} + {} + } +} + +{ + { + {} + } + { + {} + {} + } +} + +{ + {} + { + {} + {} + } +} + +{ + {} + { + {} + {} + } +} + +{ + { + {} + {} + } +} + +{ + { + {} + {} + } +} + +{ + { + {} + } +} + +{ + { + {} + } +} + +{ + {} +} + +{ + {} +} + +{} + +{} + + +undefined; +" +`; + +exports[`Statements: Blocks Block-statement-intro test case 1`] = ` +"{ + 1 + 1; +} + +{ + 1 + 1; +} + +{ + 2; +} + +{ + 2; +} + +2; + +2; +" +`; + +exports[`Statements: Blocks Block-statement-single-reduce test case 1`] = ` +"{ + 1; +} + +{ + 1; +} + +1; + +1; +" +`; + +exports[`Statements: Conditionals Conditional-statement-alternative test case 1`] = ` +"if (false) { + 1; +} else { + 2; +} + +if (false) { + 1; +} else { + 2; +} + +{ + undefined; + 2; +} + +{ + undefined; + 2; +} + +{ + 2; +} + +{ + 2; +} + +2; + +2; +" +`; + +exports[`Statements: Conditionals Conditional-statement-blockexpr-alternative test case 1 1`] = ` +"function foo(x) { + if (false) { + 1; + } else { + 2; + } +} +foo(0); + +function foo(x) { + if (false) { + 1; + } else { + 2; + } +} +foo(0); + +foo(0); + +foo(0); + +{ + if (false) { + 1; + } else { + 2; + } +}; + +{ + if (false) { + 1; + } else { + 2; + } +}; + +{ + { + 2; + } +}; + +{ + { + 2; + } +}; + +{ + 2; +}; + +{ + 2; +}; + +undefined; + +undefined; +" +`; + +exports[`Statements: Conditionals Conditional-statement-blockexpr-alternative test case 2 1`] = ` +"function foo(x) { + 3; + if (false) { + 1; + } else { + 2; + } +} +foo(0); + +function foo(x) { + 3; + if (false) { + 1; + } else { + 2; + } +} +foo(0); + +foo(0); + +foo(0); + +{ + 3; + if (false) { + 1; + } else { + 2; + } +}; + +{ + 3; + if (false) { + 1; + } else { + 2; + } +}; + +{ + 3; + { + 2; + } +}; + +{ + 3; + { + 2; + } +}; + +{ + 3; + 2; +}; + +{ + 3; + 2; +}; + +{ + 2; +}; + +{ + 2; +}; + +undefined; + +undefined; +" +`; + +exports[`Statements: Conditionals Conditional-statement-blockexpr-consequent test case 1 1`] = ` +"function foo(x) { + if (true) { + 1; + } else { + 2; + } +} +foo(0); + +function foo(x) { + if (true) { + 1; + } else { + 2; + } +} +foo(0); + +foo(0); + +foo(0); + +{ + if (true) { + 1; + } else { + 2; + } +}; + +{ + if (true) { + 1; + } else { + 2; + } +}; + +{ + { + 1; + } +}; + +{ + { + 1; + } +}; + +{ + 1; +}; + +{ + 1; +}; + +undefined; + +undefined; +" +`; + +exports[`Statements: Conditionals Conditional-statement-blockexpr-consequent test case 2 1`] = ` +"function foo(x) { + 3; + if (true) { + 1; + } else { + 2; + } +} +foo(0); + +function foo(x) { + 3; + if (true) { + 1; + } else { + 2; + } +} +foo(0); + +foo(0); + +foo(0); + +{ + 3; + if (true) { + 1; + } else { + 2; + } +}; + +{ + 3; + if (true) { + 1; + } else { + 2; + } +}; + +{ + 3; + { + 1; + } +}; + +{ + 3; + { + 1; + } +}; + +{ + 3; + 1; +}; + +{ + 3; + 1; +}; + +{ + 1; +}; + +{ + 1; +}; + +undefined; + +undefined; +" +`; + +exports[`Statements: Conditionals Conditional-statement-consequent test case 1`] = ` +"if (true) { + 1; +} else { + 2; +} + +if (true) { + 1; +} else { + 2; +} + +{ + undefined; + 1; +} + +{ + undefined; + 1; +} + +{ + 1; +} + +{ + 1; +} + +1; + +1; +" +`; + +exports[`Statements: Conditionals Conditional-statement-predicate test case 1`] = ` +"if (1 + 2 + 3 === 1) {} else {} + +if (1 + 2 + 3 === 1) {} else {} + +if (3 + 3 === 1) {} else {} + +if (3 + 3 === 1) {} else {} + +if (6 === 1) {} else {} + +if (6 === 1) {} else {} + +if (false) {} else {} + +if (false) {} else {} + +{ + undefined; +} + +{ + undefined; +} + +undefined; + +undefined; +" +`; + +exports[`Statements: Constant declarations Evaluate-constant-declaration test case 1`] = ` +"const x = 1 + 2 + 3; + +const x = 1 + 2 + 3; + +const x = 3 + 3; + +const x = 3 + 3; + +const x = 6; + +const x = 6; + + +undefined; +" +`; + +exports[`Statements: Expression statements Expression-statement-reduce test case 1`] = ` +"1 + 2 + 3; + +1 + 2 + 3; + +3 + 3; + +3 + 3; + +6; + +6; " `; diff --git a/src/stepper/__tests__/stepper.ts b/src/stepper/__tests__/stepper.ts index 3f739ba23..e0d654131 100644 --- a/src/stepper/__tests__/stepper.ts +++ b/src/stepper/__tests__/stepper.ts @@ -1768,6 +1768,464 @@ describe(`Evaluation of empty code and imports`, () => { }) }) +/** + * start of stepper specification tests + */ +describe(`Programs`, () => { + //Program-intro: + test('Program-intro test case 1', async () => { + const code = `1 + 1;` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('2;') + }) + + test('Program-intro test case 2', async () => { + const code = ` + 1; + 1 + 1; + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('2;') + }) + //Program-reduce: + test('Program-reduce test case', async () => { + const code = ` + 1; + 2; + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('2;') + }) + //Eliminate-function-declaration: + test('Eliminate-function-declaration test case 1', async () => { + const code = ` + function foo(x) { + return 0; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) + + test('Eliminate-function-declaration test case 2', async () => { + const code = ` + 1; + function foo(x) { + return 0; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('1;') + }) + //Eliminate-constant-declaration: + test('Eliminate-constant-declaration test case 1', async () => { + const code = ` + const x = 0; + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) + + test('Eliminate-constant-declaration test case 2', async () => { + const code = ` + 1; + const x = 0; + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('1;') + }) +}) + +describe(`Statements: Expression statements`, () => { + //Expression-statement-reduce: + test('Expression-statement-reduce test case', async () => { + const code = ` + 1 + 2 + 3; + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('6;') + }) +}) + +describe(`Statements: Constant declarations`, () => { + //Evaluate-constant-declaration: + test('Evaluate-constant-declaration test case', async () => { + const code = ` + const x = 1 + 2 + 3; + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) +}) + +describe(`Statements: Conditionals`, () => { + //Conditional-statement-predicate: + test('Conditional-statement-predicate test case', async () => { + const code = ` + if (1 + 2 + 3 === 1) { + + } else { + + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) + //Conditional-statement-consequent: + test('Conditional-statement-consequent test case', async () => { + const code = ` + if (true) { + 1; + } else { + 2; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('1;') + }) + //Conditional-statement-alternative: + test('Conditional-statement-alternative test case', async () => { + const code = ` + if (false) { + 1; + } else { + 2; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('2;') + }) + //Conditional-statement-blockexpr-consequent: + test('Conditional-statement-blockexpr-consequent test case 1', async () => { + const code = ` + function foo(x) { + if (true) { + 1; + } else { + 2; + } + } + foo(0); + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) + + test('Conditional-statement-blockexpr-consequent test case 2', async () => { + const code = ` + function foo(x) { + 3; + if (true) { + 1; + } else { + 2; + } + } + foo(0); + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) + //Conditional-statement-blockexpr-alternative: + test('Conditional-statement-blockexpr-alternative test case 1', async () => { + const code = ` + function foo(x) { + if (false) { + 1; + } else { + 2; + } + } + foo(0); + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) + + test('Conditional-statement-blockexpr-alternative test case 2', async () => { + const code = ` + function foo(x) { + 3; + if (false) { + 1; + } else { + 2; + } + } + foo(0); + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) +}) + +describe(`Statements: Blocks`, () => { + //Block-statement-intro: + test('Block-statement-intro test case', async () => { + const code = ` + { + 1 + 1; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('2;') + }) + //Block-statement-single-reduce: + test('Block-statement-single-reduce test case', async () => { + const code = ` + { + 1; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('1;') + }) + //Block-statement-empty-reduce: + test('Block-statement-empty-reduce test case 1', async () => { + const code = ` + { + + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) + + test('Block-statement-empty-reduce test case 2', async () => { + const code = ` + { + { + { + + } + { + + } + } + + { + { + + } + { + + } + } + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) +}) + +describe(`Expresssions: Blocks`, () => { + //Block-expression-intro: + test('Block-expression-intro test case', async () => { + const code = ` + function foo(x) { + 1 + 1; + } + foo(0); + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) + //Block-expression-single-reduce: + test('Block-expression-single-reduce test case', async () => { + const code = ` + function foo(x) { + 1; + } + foo(0); + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) + //Block-expression-empty-reduce: + test('Block-expression-empty-reduce test case', async () => { + const code = ` + function foo(x) { + } + foo(0); + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('undefined;') + }) + /** + * Block-expression-return-reduce is not included as test cases + * This section needs further discussion + */ +}) + +describe(`Expressions: Binary operators`, () => { + //Left-binary-reduce: + test('Left-binary-reduce test case', async () => { + const code = ` + if (1 + 2 + 3 === 1 + 2 + 3) { + 1; + } else { + 2; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('1;') + }) + //And-shortcut-false: + test('And-shortcut-false test case', async () => { + const code = ` + if (false && 1 + 2 === 1 + 2) { + 1; + } else { + 2; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('2;') + }) + //And-shortcut-true: + test('And-shortcut-true test case', async () => { + const code = ` + if (true && 1 + 2 === 2 + 3) { + 1; + } else { + 2; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('2;') + }) + //Or-shortcut-true: + test('Or-shortcut-true test case', async () => { + const code = ` + if (true || 1 + 2 === 2 + 3) { + 1; + } else { + 2; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('1;') + }) + //Or-shortcut-false: + test('Or-shortcut-false test case', async () => { + const code = ` + if (false || 1 + 2 === 1 + 2) { + 1; + } else { + 2; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('1;') + }) + //Right-binary-reduce: + test('Right-binary-reduce test case', async () => { + const code = ` + if (1 >= 1 + 1) { + 1; + } else { + 2; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('2;') + }) + //Prim-binary-reduce: + test('Prim-binary-reduce test case', async () => { + const code = ` + if (1 >= 2) { + 1; + } else { + 2; + } + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('2;') + }) +}) + +describe(`Expressions: conditionals`, () => { + //Conditional-predicate-reduce: + test('Conditional-predicate-reduce test case', async () => { + const code = ` + 1 + 1 === 2 ? 1 + 2 : 2 + 3; + ` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('3;') + }) + //Conditional-true-reduce: + test('Conditional-true-reduce test case', async () => { + const code = `true ? 1 + 2 : 2 + 3;` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('3;') + }) + //Conditional-false-reduce: + test('Conditional-false-reduce test case', async () => { + const code = `false ? 1 + 2 : 2 + 3;` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('5;') + }) +}) +/* +test cases to be discussed +describe(`Expressions: function application`, () => { + +}) +*/ + +//template +/* +For a section of test cases +describe(``, () => { + +}) + +For specific test cases +test('', async () => { + const code = `` + const steps = await testEvalSteps(code, mockContext()) + expect(steps.map(x => codify(x[0])).join('\n')).toMatchSnapshot() + expect(getLastStepAsString(steps)).toEqual('') +}) +*/ + +/** + * end of stepper specification tests + */ + // describe(`#1223: Stepper: Import statements cause errors`, () => { // test('import a module and invoke its functions', async () => { // const code = `