Skip to content

Commit

Permalink
Implements new spread instruction (#1740)
Browse files Browse the repository at this point in the history
* Fixed bug in for loops

* comment removed

* Fix bugs in for loops and block exec

* Fix bugs in for loops and block exec

* Fix bugs in for loops and block exec

* Implemented spread operator

* spreadinstr

* Fix formatting issues

---------

Co-authored-by: chuckyang123 <xiangwall0926@gmail.com>
  • Loading branch information
alsonleej and chuckyang123 authored Feb 26, 2025
1 parent 07f1f87 commit 1ec7669
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 10 deletions.
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 { evaluateBinaryExpression, evaluateUnaryExpression } from '../utils/oper
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 @@ import {
Instr,
InstrType,
UnOpInstr,
WhileInstr
WhileInstr,
SpreadInstr
} from './types'
import {
checkNumberOfArguments,
Expand Down Expand Up @@ -81,7 +83,6 @@ import {
} 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 @@ -758,6 +759,12 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
}
},

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 Down Expand Up @@ -1310,5 +1317,30 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
}
},

[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

0 comments on commit 1ec7669

Please sign in to comment.