Skip to content

Implements new spread instruction #1740

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

Merged
merged 9 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions src/cse-machine/instrCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,8 @@ export const breakMarkerInstr = (srcNode: Node): Instr => ({
instrType: InstrType.BREAK_MARKER,
srcNode
})

export const spreadInstr = (srcNode: Node): Instr => ({
instrType: InstrType.SPREAD,
srcNode
})
38 changes: 35 additions & 3 deletions src/cse-machine/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import * as rttc from '../utils/rttc'
import * as seq from '../utils/statementSeqTransform'
import { checkProgramForUndefinedVariables } from '../validator/validator'
import { isSchemeLanguage } from '../alt-langs/mapper'
import Closure from './closure'
import {
Continuation,
Expand All @@ -43,7 +44,8 @@
Instr,
InstrType,
UnOpInstr,
WhileInstr
WhileInstr,
SpreadInstr
} from './types'
import {
checkNumberOfArguments,
Expand Down Expand Up @@ -81,7 +83,6 @@
} from './utils'
import { isApply, isEval, schemeEval } from './scheme-macros'
import { Transformer } from './patterns'
import { isSchemeLanguage } from '../alt-langs/mapper'
import { flattenList, isList } from './macro-utils'

type CmdEvaluator = (
Expand Down Expand Up @@ -328,7 +329,7 @@
* @returns The corresponding promise.
*/
export function CSEResultPromise(context: Context, value: Value): Promise<Result> {
return new Promise((resolve, reject) => {

Check warning on line 332 in src/cse-machine/interpreter.ts

View workflow job for this annotation

GitHub Actions / build

'reject' is defined but never used. Allowed unused args must match /^_/u
if (value instanceof CSEBreak) {
resolve({ status: 'suspended-cse-eval', context })
} else if (value instanceof CseError) {
Expand Down Expand Up @@ -563,7 +564,7 @@
command: es.WhileStatement,
context: Context,
control: Control,
stash: Stash

Check warning on line 567 in src/cse-machine/interpreter.ts

View workflow job for this annotation

GitHub Actions / build

'stash' is defined but never used. Allowed unused args must match /^_/u
) {
if (hasBreakStatement(command.body as es.BlockStatement)) {
control.push(instr.breakMarkerInstr(command))
Expand Down Expand Up @@ -644,7 +645,7 @@
command: es.IfStatement,
context: Context,
control: Control,
stash: Stash

Check warning on line 648 in src/cse-machine/interpreter.ts

View workflow job for this annotation

GitHub Actions / build

'stash' is defined but never used. Allowed unused args must match /^_/u
) {
control.push(...reduceConditional(command))
},
Expand Down Expand Up @@ -717,7 +718,7 @@
command: es.ContinueStatement,
context: Context,
control: Control,
stash: Stash

Check warning on line 721 in src/cse-machine/interpreter.ts

View workflow job for this annotation

GitHub Actions / build

'stash' is defined but never used. Allowed unused args must match /^_/u
) {
control.push(instr.contInstr(command))
},
Expand All @@ -726,7 +727,7 @@
command: es.BreakStatement,
context: Context,
control: Control,
stash: Stash

Check warning on line 730 in src/cse-machine/interpreter.ts

View workflow job for this annotation

GitHub Actions / build

'stash' is defined but never used. Allowed unused args must match /^_/u
) {
control.push(instr.breakInstr(command))
},
Expand Down Expand Up @@ -758,6 +759,12 @@
}
},

SpreadElement: function (command: es.SpreadElement, context: Context, control: Control) {
const arr = command.argument as es.ArrayExpression
control.push(instr.spreadInstr(arr))
control.push(arr)
},

ArrayExpression: function (command: es.ArrayExpression, context: Context, control: Control) {
const elems = command.elements as ContiguousArrayElements
reverse(elems)
Expand All @@ -773,7 +780,7 @@
command: es.MemberExpression,
context: Context,
control: Control,
stash: Stash

Check warning on line 783 in src/cse-machine/interpreter.ts

View workflow job for this annotation

GitHub Actions / build

'stash' is defined but never used. Allowed unused args must match /^_/u
) {
control.push(instr.arrAccInstr(command))
control.push(command.property)
Expand All @@ -784,7 +791,7 @@
command: es.ConditionalExpression,
context: Context,
control: Control,
stash: Stash

Check warning on line 794 in src/cse-machine/interpreter.ts

View workflow job for this annotation

GitHub Actions / build

'stash' is defined but never used. Allowed unused args must match /^_/u
) {
control.push(...reduceConditional(command))
},
Expand Down Expand Up @@ -847,7 +854,7 @@
* Instructions
*/

[InstrType.RESET]: function (command: Instr, context: Context, control: Control, stash: Stash) {

Check warning on line 857 in src/cse-machine/interpreter.ts

View workflow job for this annotation

GitHub Actions / build

'stash' is defined but never used. Allowed unused args must match /^_/u
// Keep pushing reset instructions until marker is found.
const cmdNext: ControlItem | undefined = control.pop()
if (cmdNext && (!isInstr(cmdNext) || cmdNext.instrType !== InstrType.MARKER)) {
Expand Down Expand Up @@ -1310,5 +1317,30 @@
}
},

[InstrType.BREAK_MARKER]: function () {}
[InstrType.BREAK_MARKER]: function () {},

[InstrType.SPREAD]: function (
command: SpreadInstr,
context: Context,
control: Control,
stash: Stash
) {
const array = stash.pop()

// spread array
for (let i = 0; i < array.length; i++) {
stash.push(array[i])
}

// update call instr above
const cont = control.getStack()
const size = control.size()
for (let i = size - 1; i >= 0; i--) {
// guaranteed at least one call instr above, because spread is not allowed inside arrays
if ((cont[i] as AppInstr).instrType === InstrType.APPLICATION) {
;(cont[i] as AppInstr).numOfArgs += array.length - 1
break // only the nearest call instruction above
}
}
}
}
2 changes: 1 addition & 1 deletion src/cse-machine/patterns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// and a final template (for the list to be transformed into).
import { List, Pair } from '../stdlib/list'
import { _Symbol } from '../alt-langs/scheme/scm-slang/src/stdlib/base'
import { atomic_equals, is_number } from '../alt-langs/scheme/scm-slang/src/stdlib/core-math'
import {
arrayToImproperList,
arrayToList,
Expand All @@ -14,7 +15,6 @@ import {
isPair,
isList
} from './macro-utils'
import { atomic_equals, is_number } from '../alt-langs/scheme/scm-slang/src/stdlib/core-math'

// a single pattern stored within the patterns component
// may have several transformers attributed to it.
Expand Down
7 changes: 4 additions & 3 deletions src/cse-machine/scheme-macros.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ import { List } from '../stdlib/list'
import { _Symbol } from '../alt-langs/scheme/scm-slang/src/stdlib/base'
import { is_number, SchemeNumber } from '../alt-langs/scheme/scm-slang/src/stdlib/core-math'
import { Context } from '..'
import { encode } from '../alt-langs/scheme/scm-slang/src'
import { Control, Stash } from './interpreter'
import { currentTransformers, getVariable, handleRuntimeError } from './utils'
import { Transformer, macro_transform, match } from './patterns'
import {
arrayToImproperList,
arrayToList,
flattenImproperList,
isImproperList
isImproperList,
flattenList,
isList
} from './macro-utils'
import { ControlItem } from './types'
import { encode } from '../alt-langs/scheme/scm-slang/src'
import { popInstr } from './instrCreator'
import { flattenList, isList } from './macro-utils'

// this needs to be better but for now it's fine
export type SchemeControlItems = List | _Symbol | SchemeNumber | boolean | string
Expand Down
8 changes: 7 additions & 1 deletion src/cse-machine/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export enum InstrType {
CONTINUE = 'Continue',
CONTINUE_MARKER = 'ContinueMarker',
BREAK = 'Break',
BREAK_MARKER = 'BreakMarker'
BREAK_MARKER = 'BreakMarker',
SPREAD = 'Spread'
}

interface BaseInstr {
Expand Down Expand Up @@ -78,6 +79,10 @@ export interface ArrLitInstr extends BaseInstr {
arity: number
}

export interface SpreadInstr extends BaseInstr {
symbol: es.SpreadElement
}

export type Instr =
| BaseInstr
| WhileInstr
Expand All @@ -86,6 +91,7 @@ export type Instr =
| BranchInstr
| EnvInstr
| ArrLitInstr
| SpreadInstr

export type ControlItem = (Node | Instr | SchemeControlItems) & {
isEnvDependent?: boolean
Expand Down
5 changes: 3 additions & 2 deletions src/cse-machine/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import * as errors from '../errors/errors'
import { RuntimeSourceError } from '../errors/runtimeSourceError'
import { Chapter, type Environment, type Node, type StatementSequence, type Value } from '../types'
import * as ast from '../utils/ast/astCreator'
import { _Symbol } from '../alt-langs/scheme/scm-slang/src/stdlib/base'
import { is_number } from '../alt-langs/scheme/scm-slang/src/stdlib/core-math'
import Heap from './heap'
import * as instr from './instrCreator'
import { Control, Transformers } from './interpreter'
Expand All @@ -22,8 +24,6 @@ import {
import Closure from './closure'
import { Continuation, isCallWithCurrentContinuation } from './continuations'
import { isApply, isEval } from './scheme-macros'
import { _Symbol } from '../alt-langs/scheme/scm-slang/src/stdlib/base'
import { is_number } from '../alt-langs/scheme/scm-slang/src/stdlib/core-math'

/**
* Typeguard for commands to check if they are scheme values.
Expand Down Expand Up @@ -940,6 +940,7 @@ const propertySetter: PropertySetter = new Map<string, Transformer>([
[InstrType.APPLICATION, setToTrue],
[InstrType.ASSIGNMENT, setToTrue],
[InstrType.ARRAY_LITERAL, setToTrue],
[InstrType.SPREAD, setToFalse],
[
InstrType.WHILE,
(instr: WhileInstr) => {
Expand Down
Loading