Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update parser to new scm-slang parser #1584

Merged
merged 25 commits into from
Mar 21, 2024
Merged
Changes from 12 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
51144f9
Prepare scheme files for new parser
s-kybound Mar 6, 2024
c5429c0
update JS version for js-slang
s-kybound Mar 6, 2024
f778f67
Merge branch 'source-academy/master'
s-kybound Mar 6, 2024
d341b96
proper formatting of files
s-kybound Mar 6, 2024
0e43676
fix separate program environments across REPL eval calls
s-kybound Mar 7, 2024
18cb104
remove logger messages from interpreter
s-kybound Mar 7, 2024
28b2e8f
Enable variadic continuations for future
s-kybound Mar 11, 2024
af27846
Remove Infinity and NaN representation from Scheme
s-kybound Mar 11, 2024
fd62e06
Change scm-slang to follow forked version
s-kybound Mar 11, 2024
9f9d57a
Merge branch 'origin/master'
s-kybound Mar 12, 2024
cfa44bd
update scm-slang to newest parser
s-kybound Mar 18, 2024
d07e19b
Merge branch 'master' into master
martin-henz Mar 19, 2024
9347f34
resolve linting problems
s-kybound Mar 19, 2024
60fac47
Merge remote-tracking branch 'refs/remotes/origin/master'
s-kybound Mar 19, 2024
3f1d450
add test cases to verify proper chapter validation, decoded represent…
s-kybound Mar 19, 2024
d750e57
Merge branch 'master' into master
Mar 20, 2024
a6987ec
Merge branch 'master' into master
Mar 20, 2024
0d45e9d
update scm-slang
s-kybound Mar 20, 2024
42e184e
Move scheme-specific tests to scm-slang
s-kybound Mar 20, 2024
eae3212
Merge remote-tracking branch 'origin/master'
s-kybound Mar 20, 2024
9a912cf
make scheme test names more obvious
s-kybound Mar 20, 2024
467279d
Revert "Move scheme-specific tests to scm-slang"
s-kybound Mar 21, 2024
2959c97
move scm-slang to dedicated alt-lang folder
s-kybound Mar 21, 2024
a9fefb5
remove duplicate code between scm-slang and js-slang
s-kybound Mar 21, 2024
7089e07
ignore alt langs coverage
s-kybound Mar 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,535 changes: 0 additions & 1,535 deletions src/__tests__/__snapshots__/scmlib.ts.snap

This file was deleted.

1,186 changes: 0 additions & 1,186 deletions src/__tests__/scmlib.ts

This file was deleted.

191 changes: 135 additions & 56 deletions src/createContext.ts

Large diffs are not rendered by default.

44 changes: 8 additions & 36 deletions src/cse-machine/__tests__/__snapshots__/cse-machine-callcc.ts.snap
Original file line number Diff line number Diff line change
@@ -11,7 +11,10 @@ Object {
"displayResult": Array [],
"numErrors": 0,
"parsedErrors": "",
"result": 10,
"result": SchemeInteger {
"numberType": 1,
"value": 10n,
},
"resultStatus": "finished",
"visualiseListResult": Array [],
}
@@ -54,7 +57,10 @@ Object {
"displayResult": Array [],
"numErrors": 0,
"parsedErrors": "",
"result": 2,
"result": SchemeInteger {
"numberType": 1,
"value": 2n,
},
"resultStatus": "finished",
"visualiseListResult": Array [],
}
@@ -92,37 +98,3 @@ Object {
"visualiseListResult": Array [],
}
`;

exports[`cont throws error given >1 argument: expectParsedError 1`] = `
Object {
"alertResult": Array [],
"code": "
(+ 1 2 (call/cc
(lambda (k) (k 3 'wrongwrongwrong!)))
4)
",
"displayResult": Array [],
"numErrors": 1,
"parsedErrors": "Line 3: Expected 1 arguments, but got 2.",
"result": undefined,
"resultStatus": "error",
"visualiseListResult": Array [],
}
`;

exports[`cont throws error given no arguments: expectParsedError 1`] = `
Object {
"alertResult": Array [],
"code": "
(+ 1 2 (call/cc
(lambda (k) (k)))
4)
",
"displayResult": Array [],
"numErrors": 1,
"parsedErrors": "Line 3: Expected 1 arguments, but got 0.",
"result": undefined,
"resultStatus": "error",
"visualiseListResult": Array [],
}
`;
20 changes: 17 additions & 3 deletions src/cse-machine/__tests__/cse-machine-callcc.ts
Original file line number Diff line number Diff line change
@@ -13,7 +13,12 @@ test('basic call/cc works', () => {
4)
`,
optionECScm
).toMatchInlineSnapshot(`10`)
).toMatchInlineSnapshot(`
SchemeInteger {
"numberType": 1,
"value": 10n,
}
`)
})

test('call/cc can be used to escape a computation', () => {
@@ -28,7 +33,12 @@ test('call/cc can be used to escape a computation', () => {
test
`,
optionECScm
).toMatchInlineSnapshot(`2`)
).toMatchInlineSnapshot(`
SchemeInteger {
"numberType": 1,
"value": 2n,
}
`)
})

test('call/cc throws error given no arguments', () => {
@@ -52,6 +62,10 @@ test('call/cc throws error given >1 argument', () => {
).toMatchInlineSnapshot(`"Line 2: Expected 1 arguments, but got 2."`)
})

/*
for now, continuations have variable arity but are unable to check for the "correct"
number of arguments. we will omit these tests for now

test('cont throws error given no arguments', () => {
return expectParsedError(
`
@@ -73,7 +87,7 @@ test('cont throws error given >1 argument', () => {
optionECScm
).toMatchInlineSnapshot(`"Line 3: Expected 1 arguments, but got 2."`)
})

*/
test('call/cc can be stored as a value', () => {
return expectResult(
`
3 changes: 2 additions & 1 deletion src/cse-machine/continuations.ts
Original file line number Diff line number Diff line change
@@ -50,7 +50,8 @@ export function getContinuationEnv(cn: Continuation): Environment[] {

export function makeContinuation(control: Control, stash: Stash, env: Environment[]): Function {
// Cast a function into a continuation
const fn: any = (x: any) => x
// a continuation may take any amount of arguments
const fn: Function = (...x: any[]) => x
const cn: Continuation = fn as Continuation

// Set the control, stash and environment
3 changes: 2 additions & 1 deletion src/cse-machine/instrCreator.ts
Original file line number Diff line number Diff line change
@@ -148,7 +148,8 @@ export const genContInstr = (srcNode: es.Node): GenContInstr => ({
srcNode
})

export const resumeContInstr = (srcNode: es.Node): ResumeContInstr => ({
export const resumeContInstr = (numOfArgs: number, srcNode: es.Node): ResumeContInstr => ({
numOfArgs: numOfArgs,
instrType: InstrType.RESUME_CONT,
srcNode
})
63 changes: 52 additions & 11 deletions src/cse-machine/interpreter.ts
Original file line number Diff line number Diff line change
@@ -47,8 +47,10 @@ import {
CseError,
EnvInstr,
ForInstr,
GenContInstr,
Instr,
InstrType,
ResumeContInstr,
UnOpInstr,
WhileInstr
} from './types'
@@ -395,6 +397,42 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
declareFunctionsAndVariables(context, command, environment)
}

// A strange bug occurs here when successive REPL commands are run, as they
// are each evaluated as separate programs. This causes the environment to be
// pushed multiple times.

// As such, we need to "append" the tail environment to the current environment
// if and only if the tail environment is a previous program environment.

const currEnv = currentEnvironment(context)
if (
currEnv &&
currEnv.name === 'programEnvironment' &&
currEnv.tail &&
currEnv.tail.name === 'programEnvironment'
) {
// we need to take that tail environment and append its items to the current environment
const oldEnv = currEnv.tail

// separate the tail environment from the environments list
currEnv.tail = oldEnv.tail

// we will recycle the old environment's item list
// add the items from the current environment to the tail environment
// this is fine, especially as the older program will never
// need to use the old environment's items again
for (const key in currEnv.head) {
oldEnv.head[key] = currEnv.head[key]
}

// set the current environment to the old one
// this will work across successive programs as well

// this will also allow continuations to read newer program
// values from their "outdated" program environment
currEnv.head = oldEnv.head
}

if (command.body.length == 1) {
// If program only consists of one statement, evaluate it immediately
const next = command.body[0]
@@ -914,17 +952,16 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
// Check for number of arguments mismatch error
checkNumberOfArguments(context, func, args, command.srcNode)

// A continuation is always given a single argument
const expression: Value = args[0]

const dummyContCallExpression = makeDummyContCallExpression('f', 'cont')

// Restore the state of the stash,
// but replace the function application instruction with
// a resume continuation instruction
stash.push(func)
stash.push(expression)
control.push(instr.resumeContInstr(dummyContCallExpression))
// we need to push the arguments back onto the stash
// as well
stash.push(...args)
control.push(instr.resumeContInstr(command.numOfArgs, dummyContCallExpression))
return
}

@@ -1107,7 +1144,7 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
[InstrType.BREAK_MARKER]: function () {},

[InstrType.GENERATE_CONT]: function (
_command: Instr,
_command: GenContInstr,
context: Context,
control: Control,
stash: Stash
@@ -1128,12 +1165,16 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
},

[InstrType.RESUME_CONT]: function (
_command: Instr,
command: ResumeContInstr,
context: Context,
control: Control,
stash: Stash
) {
const expression = stash.pop()
// pop the arguments
const args: Value[] = []
for (let i = 0; i < command.numOfArgs; i++) {
args.unshift(stash.pop())
}
const cn: Continuation = stash.pop() as Continuation

const contControl = getContinuationControl(cn)
@@ -1144,10 +1185,10 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
control.setTo(contControl)
stash.setTo(contStash)

// Push the expression given to the continuation onto the stash
stash.push(expression)
// Push the arguments given to the continuation back onto the stash
stash.push(...args)

// Restore the environment pointer to that of the continuation
// Restore the environment pointer to that of the continuation's environment
context.runtime.environments = contEnv
}
}
4 changes: 3 additions & 1 deletion src/cse-machine/types.ts
Original file line number Diff line number Diff line change
@@ -77,7 +77,9 @@ export interface ArrLitInstr extends BaseInstr {

export type GenContInstr = BaseInstr

export type ResumeContInstr = BaseInstr
export interface ResumeContInstr extends BaseInstr {
numOfArgs: number
}

export type Instr =
| BaseInstr
7 changes: 7 additions & 0 deletions src/cse-machine/utils.ts
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import { RuntimeSourceError } from '../errors/runtimeSourceError'
import Closure from '../interpreter/closure'
import { Environment, Frame, RawBlockStatement, Value } from '../types'
import * as ast from '../utils/astCreator'
import { isContinuation } from './continuations'
import * as instr from './instrCreator'
import { Control } from './interpreter'
import { AppInstr, AssmtInstr, ControlItem, Instr, InstrType } from './types'
@@ -490,6 +491,12 @@ export const checkNumberOfArguments = (
)
)
}
} else if (isContinuation(callee)) {
// Continuations have variadic arguments,
// and so we can let it pass
// in future, if we can somehow check the number of arguments
// expected by the continuation, we can add a check here.
return undefined
} else {
// Pre-built functions
const hasVarArgs = callee.minArgsNeeded != undefined
2 changes: 1 addition & 1 deletion src/editors/ace/modes/source.ts
Original file line number Diff line number Diff line change
@@ -861,7 +861,7 @@ export function ModeSelector(

// @ts-ignore
this.$id = 'ace/mode/source' + name
}).call(Mode.prototype)
}.call(Mode.prototype))

exports.Mode = Mode
}
Loading
Loading