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

Migrate to TypeScript v5 #1666

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
"jsdom": "^19.0.0",
"prettier": "^2.1.2",
"ts-jest": "^29.0.0",
"typescript": "^4.0.3"
"typescript": "^5.4.5"
},
"jest": {
"snapshotFormat": {
Expand Down
2 changes: 1 addition & 1 deletion src/infiniteLoops/__tests__/instrument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {

function mockFunctionsAndState() {
const theState = undefined
const functions = {}
const functions: Partial<Record<functionNames, any>> = {}
const returnFirst = (...args: any[]) => args[0]
const nothing = (..._args: any[]) => {}
functions[functionNames.nothingFunction] = nothing
Expand Down
13 changes: 7 additions & 6 deletions src/infiniteLoops/instrument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import type es from 'estree'
import { transformImportDeclarations } from '../transpiler/transpiler'
import type { Node } from '../types'
import * as create from '../utils/ast/astCreator'
import { recursive, simple, WalkerCallback } from '../utils/walkers'
import { getIdsFromDeclaration } from '../utils/ast/helpers'
import { objectValues } from '../utils/misc'
import { recursive, simple, WalkerCallback } from '../utils/walkers'
// transforms AST of program

const globalIds = {
Expand Down Expand Up @@ -40,8 +41,8 @@ enum FunctionNames {
* E.g. "function f(f)..." -> "function f_0(f_1)..."
* @param predefined A table of [key: string, value:string], where variables named 'key' will be renamed to 'value'
*/
function unshadowVariables(program: Node, predefined = {}) {
for (const name of Object.values(globalIds)) {
function unshadowVariables(program: Node, predefined: Record<string, string> = {}) {
for (const name of objectValues(globalIds)) {
predefined[name] = name
}
const seenIds = new Set()
Expand Down Expand Up @@ -607,7 +608,7 @@ function instrument(
builtins: Iterable<string>
): string {
const { builtinsId, functionsId, stateId } = globalIds
const predefined = {}
const predefined: Record<string, string> = {}
predefined[builtinsId] = builtinsId
predefined[functionsId] = functionsId
predefined[stateId] = stateId
Expand Down Expand Up @@ -640,7 +641,7 @@ function instrument(
}

export {
instrument,
FunctionNames as InfiniteLoopRuntimeFunctions,
globalIds as InfiniteLoopRuntimeObjectNames
globalIds as InfiniteLoopRuntimeObjectNames,
instrument
}
6 changes: 3 additions & 3 deletions src/interpreter/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import * as errors from '../errors/errors'
import { RuntimeSourceError } from '../errors/runtimeSourceError'
import { checkEditorBreakpoints } from '../stdlib/inspector'
import {
Variant,
type Context,
type ContiguousArrayElements,
type Environment,
type Node,
type Value,
Variant
type Value
} from '../types'
import * as create from '../utils/ast/astCreator'
import { conditionalExpression, literal, primitive } from '../utils/ast/astCreator'
Expand Down Expand Up @@ -637,7 +637,7 @@ export const evaluators: { [nodeType: string]: Evaluator<Node> } = {
},

ObjectExpression: function*(node: es.ObjectExpression, context: Context) {
const obj = {}
const obj: Record<any, any> = {}
for (const propUntyped of node.properties) {
// node.properties: es.Property | es.SpreadExpression, but
// our Acorn is set to ES6 which cannot have a es.SpreadExpression
Expand Down
16 changes: 8 additions & 8 deletions src/parser/__tests__/disallowed-syntax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ test('Cannot use function expressions', () => {
stripIndent`
(function fib(x) { return x <= 1 ? x : fib(x-1) + fib(x-2); })(4);
`,
{ chapter: 5 }
{ chapter: 5 as Chapter }
).toMatchInlineSnapshot(`"Line 1: Function expressions are not allowed"`)
})

Expand All @@ -422,7 +422,7 @@ test('Cannot use function expressions - verbose', () => {
"enable verbose";
(function fib(x) { return x <= 1 ? x : fib(x-1) + fib(x-2); })(4);
`,
{ chapter: 5 }
{ chapter: 5 as Chapter }
).toMatchInlineSnapshot(`
"Line 2, Column 1: Function expressions are not allowed
You are trying to use Function expressions, which is not allowed (yet).
Expand All @@ -435,7 +435,7 @@ test('Cannot use function expressions', () => {
stripIndent`
(function(x) { return x + 1; })(4);
`,
{ chapter: 5 }
{ chapter: 5 as Chapter }
).toMatchInlineSnapshot(`"Line 1: Function expressions are not allowed"`)
})

Expand All @@ -445,7 +445,7 @@ test('Cannot use function expressions - verbose', () => {
"enable verbose";
(function(x) { return x + 1; })(4);
`,
{ chapter: 5 }
{ chapter: 5 as Chapter }
).toMatchInlineSnapshot(`
"Line 2, Column 1: Function expressions are not allowed
You are trying to use Function expressions, which is not allowed (yet).
Expand Down Expand Up @@ -840,7 +840,7 @@ test('no classes', () => {
class Box {
}
`,
{ chapter: 5 }
{ chapter: 5 as Chapter }
).toMatchInlineSnapshot(`
"Line 1: Class bodys are not allowed
Line 1: Class declarations are not allowed"
Expand All @@ -854,7 +854,7 @@ test('no classes - verbose', () => {
class Box {
}
`,
{ chapter: 5 }
{ chapter: 5 as Chapter }
).toMatchInlineSnapshot(`
"Line 2, Column 10: Class bodys are not allowed
You are trying to use Class bodys, which is not allowed (yet).
Expand All @@ -874,7 +874,7 @@ test('no super', () => {
}
}
`,
{ chapter: 5 }
{ chapter: 5 as Chapter }
).toMatchInlineSnapshot(`
"Line 3: Supers are not allowed
Line 2: Function expressions are not allowed
Expand All @@ -894,7 +894,7 @@ test('no super - verbose', () => {
}
}
`,
{ chapter: 5 }
{ chapter: 5 as Chapter }
).toMatchInlineSnapshot(`
"Line 4, Column 4: Supers are not allowed
You are trying to use Supers, which is not allowed (yet).
Expand Down
10 changes: 6 additions & 4 deletions src/stepper/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function nodeToValue(node: substituterNodes): any {
return node.type === 'Literal'
? node.value
: util.isBuiltinFunction(node)
? builtin[(node as es.Identifier).name]
? builtin[(node as es.Identifier).name as keyof typeof builtin]
: // tslint:disable-next-line
eval(javascriptify(node))
}
Expand All @@ -62,7 +62,7 @@ export function nodeToValueWithContext(node: substituterNodes, context: Context)
return node.type === 'Literal'
? node.value
: util.isBuiltinFunction(node)
? builtin[(node as es.Identifier).name]
? builtin[(node as es.Identifier).name as keyof typeof builtin]
: node.type === 'Identifier' && util.isImportedFunction(node, context)
? context.runtime.environments[0].head[node.name]
: // tslint:disable-next-line
Expand All @@ -77,11 +77,13 @@ function evaluateFunctionObject(node: substituterNodes, context: Context) {
}
visited.add(node)
if (node.type === 'Identifier' && builtinFunctions[node.name]) {
// @ts-expect-error implicitAnyIndexError
global[node.name] = builtinFunctions[node.name]
}
for (const key in node) {
for (const k in node) {
const key = k as keyof typeof node
if (node[key] && typeof node[key] === 'object') {
lookUpIdentifiers(node[key], visited)
lookUpIdentifiers(node[key] as any, visited)
}
}
}
Expand Down
41 changes: 25 additions & 16 deletions src/stepper/stepper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
dummyVariableDeclarator
} from '../utils/ast/dummyAstCreator'
import { filterImportDeclarations } from '../utils/ast/helpers'
import { objectGetOwnPropertyNames } from '../utils/misc'
import { evaluateBinaryExpression, evaluateUnaryExpression } from '../utils/operators'
import * as rttc from '../utils/rttc'
import { checkProgramForUndefinedVariables } from '../validator/validator'
Expand Down Expand Up @@ -210,7 +211,7 @@ function findMain(

const freeNames: any[] = []

const finders = {
const finders: Partial<Record<any, (target: any) => void>> = {
Identifier(target: es.Identifier): void {
seenBefore.set(target, target)
let bound = false
Expand Down Expand Up @@ -418,7 +419,7 @@ function substituteMain(
* and push the appropriate access string into the path
* 3. Return the dummyReplacement
*/
const substituters = {
const substituters: Partial<Record<substituterNodes['type'], any>> = {
// if name to be replaced is found,
// push endMarker into path
Identifier(
Expand Down Expand Up @@ -1325,7 +1326,7 @@ function reduceMain(

// converts body of code to string
function bodify(target: substituterNodes): string {
const bodifiers = {
const bodifiers: Partial<Record<substituterNodes['type'], (target: any) => string>> = {
Literal: (target: es.Literal): string =>
target.raw !== undefined ? target.raw : String(target.value),

Expand Down Expand Up @@ -1409,7 +1410,7 @@ function reduceMain(

// generates string to explain current step
function explain(target: substituterNodes): string {
const explainers = {
const explainers: Partial<Record<substituterNodes['type'], (target: any) => string>> = {
BinaryExpression: (target: es.BinaryExpression): string =>
'Binary expression ' + bodify(target) + ' evaluated',

Expand Down Expand Up @@ -1496,7 +1497,7 @@ function reduceMain(
return explainer === undefined ? '...' : explainer(target)
}

const reducers = {
const reducers: Partial<Record<substituterNodes['type'], any>> = {
// source 0
Identifier(
node: es.Identifier,
Expand Down Expand Up @@ -1738,8 +1739,10 @@ function reduceMain(
paths,
explain(node)
]
// @ts-expect-error implicitAnyIndexError
} else if (typeof builtin[(callee as es.Identifier).name] === 'function') {
// Source specific built-in function
// @ts-expect-error implicitAnyIndexError
return [builtin[(callee as es.Identifier).name](...args), context, paths, explain(node)]
} else {
// Common built-in function
Expand Down Expand Up @@ -1825,10 +1828,12 @@ function reduceMain(
)

// Fix path highlighting after preserving first statement
path.forEach(pathStep => {
path.forEach((pathStep: any[]) => {
pathStep.forEach((_, i) => {
if (i == 0) {
pathStep[i] = pathStep[i].replace(/\d+/g, match => String(Number(match) + 1))
pathStep[i] = pathStep[i].replace(/\d+/g, (match: any) =>
String(Number(match) + 1)
)
}
})
})
Expand Down Expand Up @@ -2050,10 +2055,12 @@ function reduceMain(
)

// Fix path highlighting after preserving first statement
path.forEach(pathStep => {
path.forEach((pathStep: any[]) => {
pathStep.forEach((_, i) => {
if (i == 0) {
pathStep[i] = pathStep[i].replace(/\d+/g, match => String(Number(match) + 1))
pathStep[i] = pathStep[i].replace(/\d+/g, (match: any) =>
String(Number(match) + 1)
)
}
})
})
Expand Down Expand Up @@ -2269,10 +2276,12 @@ function reduceMain(
)

// Fix path highlighting after preserving first statement
path.forEach(pathStep => {
path.forEach((pathStep: any[]) => {
pathStep.forEach((_, i) => {
if (i == 0) {
pathStep[i] = pathStep[i].replace(/\d+/g, match => String(Number(match) + 1))
pathStep[i] = pathStep[i].replace(/\d+/g, (match: any) =>
String(Number(match) + 1)
)
}
})
})
Expand Down Expand Up @@ -2483,7 +2492,7 @@ function treeifyMain(target: substituterNodes): substituterNodes {
// has an identifier: replace with the name
// else: replace with an identifer "=>"
let verboseCount = 0
const treeifiers = {
const treeifiers: Partial<Record<substituterNodes['type'], (target: any) => any>> = {
// Identifier: return
ExpressionStatement: (target: es.ExpressionStatement): es.ExpressionStatement => {
return ast.expressionStatement(treeify(target.expression) as es.Expression)
Expand Down Expand Up @@ -2635,7 +2644,7 @@ function jsTreeifyMain(
// visited before recursing to this target: replace with the name
// else: replace with a FunctionExpression
let verboseCount = 0
const treeifiers = {
const treeifiers: Partial<Record<substituterNodes['type'], (target: any) => substituterNodes>> = {
Identifier: (target: es.Identifier): es.Identifier => {
if (readOnly && target.name.startsWith('anonymous_')) {
return ast.identifier('[Function]')
Expand Down Expand Up @@ -2817,7 +2826,7 @@ function pathifyMain(
let endIndex = path === undefined ? 0 : path.length - 1
const redexMarker = ast.identifier('@redex') as substituterNodes
const withBrackets = ast.identifier('(@redex)') as substituterNodes
const pathifiers = {
const pathifiers: Partial<Record<substituterNodes['type'], any>> = {
ExpressionStatement: (target: es.ExpressionStatement): es.ExpressionStatement => {
let exp = jsTreeifyMain(target.expression, visited, true) as es.Expression
if (path[pathIndex] === 'expression') {
Expand Down Expand Up @@ -3262,9 +3271,9 @@ function substPredefinedFns(program: es.Program, context: Context): [es.Program,

function substPredefinedConstants(program: es.Program): es.Program {
const constants = [['undefined', undefined]]
const mathConstants = Object.getOwnPropertyNames(Math)
const mathConstants = objectGetOwnPropertyNames(Math)
.filter(name => typeof Math[name] !== 'function')
.map(name => ['math_' + name, Math[name]])
.map(name => ['math_' + (name as string), Math[name]]) as (string | undefined)[][]
let substed = program
for (const nameValuePair of constants.concat(mathConstants)) {
substed = substituteMain(
Expand Down
9 changes: 9 additions & 0 deletions src/utils/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,12 @@ export function objectKeys<T extends string | number | symbol>(obj: Record<T, an
export function objectValues<T>(obj: Record<any, T>) {
return Object.values(obj) as T[]
}

/**
* Type safe `Object.getOwnPropertyNames`
*/
export function objectGetOwnPropertyNames<T extends string | number | symbol>(
obj: Record<T, any>
): T[] {
return Object.getOwnPropertyNames(obj) as T[]
}
2 changes: 1 addition & 1 deletion src/utils/uniqueIds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const globalIdNames = [
export type NativeIds = Record<(typeof globalIdNames)[number], es.Identifier>

export function getNativeIds(program: es.Program, usedIdentifiers: Set<string>): NativeIds {
const globalIds = {}
const globalIds: Partial<NativeIds> = {}
for (const identifier of globalIdNames) {
globalIds[identifier] = create.identifier(getUniqueId(usedIdentifiers, identifier))
}
Expand Down
14 changes: 12 additions & 2 deletions src/vm/svml-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { ConstAssignment, UndefinedVariable } from '../errors/errors'
import { parse } from '../parser/parser'
import {
CONSTANT_PRIMITIVES,
generatePrimitiveFunctionCode,
INTERNAL_FUNCTIONS,
PRIMITIVE_FUNCTION_NAMES,
generatePrimitiveFunctionCode,
vmPrelude
} from '../stdlib/vm.prelude'
import type { Context, ContiguousArrayElements, Node } from '../types'
Expand Down Expand Up @@ -485,7 +485,17 @@ function compileStatements(
}

// each compiler should return a maxStackSize
const compilers = {
const compilers: Partial<
Record<
Node['type'],
(
node: Node,
indexTable: Map<string, EnvEntry>[],
insertFlag: boolean,
isTailCallPosition?: boolean
) => ReturnType<typeof compileStatements>
>
> = {
// wrapper
Program(node: Node, indexTable: Map<string, EnvEntry>[], insertFlag: boolean) {
node = node as es.Program
Expand Down
Loading
Loading