Skip to content

Commit

Permalink
CSE Machine: Overhaul environment handling at the start of programs (#…
Browse files Browse the repository at this point in the history
…1642)

* fix env push condition

* Overhaul environment handling at the start of programs

* code cleanup
  • Loading branch information
NhatMinh0208 authored Apr 4, 2024
1 parent 4b7aed1 commit 8747fd5
Showing 1 changed file with 23 additions and 41 deletions.
64 changes: 23 additions & 41 deletions src/cse-machine/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,48 +396,28 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
stash: Stash,
isPrelude: boolean
) {
// Create and push the environment only if it is non empty.
if (hasDeclarations(command) || hasImportDeclarations(command)) {
const environment = createProgramEnvironment(context, isPrelude)
pushEnvironment(context, environment)
evaluateImports(command as unknown as es.Program, context)
declareFunctionsAndVariables(context, command, environment)
// After execution of a program, the current environment might be a local one.
// This can cause issues (for example, during execution of consecutive REPL programs)
// This piece of code will reset the current environment to either a global one, a program one or a prelude one.
while (
currentEnvironment(context).name != 'global' &&
currentEnvironment(context).name != 'programEnvironment' &&
currentEnvironment(context).name != 'prelude'
) {
popEnvironment(context)
}

// 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]
// If the program has outer declarations:
// - Create the program environment (if none exists yet), and
// - Declare the functions and variables in the program environment.
if (hasDeclarations(command) || hasImportDeclarations(command)) {
if (currentEnvironment(context).name != 'programEnvironment') {
const programEnv = createProgramEnvironment(context, isPrelude)
pushEnvironment(context, programEnv)
}

// 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
const environment = currentEnvironment(context)
evaluateImports(command as unknown as es.Program, context)
declareFunctionsAndVariables(context, command, environment)
}

if (command.body.length == 1) {
Expand All @@ -457,8 +437,10 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
// we do not need to push another one
// The no declarations case is handled at the transform stage, so no blockStatement node without declarations should end up here.
const next = control.peek()
// Push ENVIRONMENT instruction if needed
if (!next || !(isInstr(next) && next.instrType === InstrType.ENVIRONMENT)) {

// Push ENVIRONMENT instruction if needed - if next control stack item
// exists and is not an environment instruction
if (next && !(isInstr(next) && next.instrType === InstrType.ENVIRONMENT)) {
control.push(instr.envInstr(currentEnvironment(context), command))
}

Expand Down

0 comments on commit 8747fd5

Please sign in to comment.