Skip to content

Commit f85225d

Browse files
openorclosemartin-henz
andauthoredJun 15, 2021
greatly simplify variable access/storage in transpiler (#968)
* greatly simplify variable access/storage in transpiler * fix repl * fix eslint * Fix console.log warnings Co-authored-by: Martin Henz <[email protected]>
1 parent 8b750f1 commit f85225d

File tree

10 files changed

+299
-532
lines changed

10 files changed

+299
-532
lines changed
 

‎src/createContext.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as misc from './stdlib/misc'
1010
import * as parser from './stdlib/parser'
1111
import * as stream from './stdlib/stream'
1212
import { streamPrelude } from './stdlib/stream.prelude'
13-
import { Context, CustomBuiltIns, Environment, Value, Variant } from './types'
13+
import { Context, CustomBuiltIns, Environment, NativeStorage, Value, Variant } from './types'
1414
import * as operators from './utils/operators'
1515
import * as gpu_lib from './gpu/lib'
1616
import { stringify } from './utils/stringify'
@@ -112,11 +112,13 @@ export const createGlobalEnvironment = (): Environment => ({
112112
head: {}
113113
})
114114

115-
const createNativeStorage = () => ({
116-
globals: { variables: new Map(), previousScope: null },
115+
const createNativeStorage = (): NativeStorage => ({
116+
builtins: new Map(),
117+
previousProgramsIdentifiers: new Set(),
117118
operators: new Map(Object.entries(operators)),
118119
gpu: new Map(Object.entries(gpu_lib)),
119-
maxExecTime: JSSLANG_PROPERTIES.maxExecTime
120+
maxExecTime: JSSLANG_PROPERTIES.maxExecTime,
121+
evaller: null
120122
})
121123

122124
export const createEmptyContext = <T>(
@@ -171,10 +173,7 @@ export const defineSymbol = (context: Context, name: string, value: Value) => {
171173
writable: false,
172174
enumerable: true
173175
})
174-
context.nativeStorage.globals!.variables.set(name, {
175-
kind: 'const',
176-
getValue: () => value
177-
})
176+
context.nativeStorage.builtins.set(name, value)
178177
const typeEnv = context.typeEnvironment[0]
179178
// if the global type env doesn't already have the imported symbol,
180179
// we set it to a type var T that can typecheck with anything.

‎src/index.ts

+15-24
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,6 @@ export async function runInContext(
489489
}
490490
let transpiled
491491
let sourceMapJson: RawSourceMap | undefined
492-
let lastStatementSourceMapJson: RawSourceMap | undefined
493492
try {
494493
appendModulesToContext(program, context)
495494
// Mutates program
@@ -502,11 +501,7 @@ export async function runInContext(
502501
break
503502
}
504503

505-
const temp = transpile(program, context, false)
506-
// some issues with formatting and semicolons and tslint so no destructure
507-
transpiled = temp.transpiled
508-
sourceMapJson = temp.codeMap
509-
lastStatementSourceMapJson = temp.evalMap
504+
;({ transpiled, codeMap: sourceMapJson } = transpile(program, context))
510505
let value = await sandboxedEval(transpiled, context.nativeStorage, context.moduleParams)
511506
if (context.variant === 'lazy') {
512507
value = forceIt(value)
@@ -544,24 +539,20 @@ export async function runInContext(
544539
}
545540
const line = Number(match![1])
546541
const column = Number(match![2])
547-
return SourceMapConsumer.with(
548-
line === 1 ? lastStatementSourceMapJson! : sourceMapJson!,
549-
null,
550-
consumer => {
551-
const {
552-
line: originalLine,
553-
column: originalColumn,
554-
name
555-
} = consumer.originalPositionFor({
556-
line,
557-
column
558-
})
559-
context.errors.push(
560-
convertNativeErrorToSourceError(error, originalLine, originalColumn, name)
561-
)
562-
return resolvedErrorPromise
563-
}
564-
)
542+
return SourceMapConsumer.with(sourceMapJson!, null, consumer => {
543+
const {
544+
line: originalLine,
545+
column: originalColumn,
546+
name
547+
} = consumer.originalPositionFor({
548+
line,
549+
column
550+
})
551+
context.errors.push(
552+
convertNativeErrorToSourceError(error, originalLine, originalColumn, name)
553+
)
554+
return resolvedErrorPromise
555+
})
565556
}
566557
} else {
567558
let it = evaluate(program, context)

‎src/repl/transpiler.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function transpileCode(chapter = 1, variant: Variant = 'default', code = '', pre
2929
if (pretranspile) {
3030
return generate(program)
3131
} else {
32-
return transpile(program as Program, context, false).transpiled
32+
return transpile(program as Program, context).transpiled
3333
}
3434
}
3535

‎src/transpiler/__tests__/__snapshots__/transpiled-code.ts.snap

+179-197
Large diffs are not rendered by default.

‎src/transpiler/evalContainer.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ export const sandboxedEval: Evaler = new Function(
1313
NATIVE_STORAGE_ID,
1414
MODULE_PARAMS_ID,
1515
`
16-
return eval(code)
16+
if (${NATIVE_STORAGE_ID}.evaller === null) {
17+
return eval(code);
18+
} else {
19+
return ${NATIVE_STORAGE_ID}.evaller(code);
20+
}
1721
`
1822
) as Evaler

‎src/transpiler/transpiler.ts

+73-275
Large diffs are not rendered by default.

‎src/types.ts

+8-6
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,18 @@ export interface ConstWrapper {
7878
getValue: () => Value
7979
}
8080

81-
export interface Globals {
82-
variables: Map<string, ValueWrapper>
83-
previousScope: Globals | null
84-
}
85-
8681
export interface NativeStorage {
87-
globals: Globals | null
82+
builtins: Map<string, Value>
83+
previousProgramsIdentifiers: Set<string>
8884
operators: Map<string, (...operands: Value[]) => Value>
8985
gpu: Map<string, (...operands: Value[]) => Value>
9086
maxExecTime: number
87+
evaller: null | ((program: string) => Value)
88+
/*
89+
the first time evaller is used, it must be used directly like `eval(code)` to inherit
90+
surrounding scope, so we cannot set evaller to `eval` directly. subsequent assignments to evaller will
91+
close in the surrounding values, so no problem
92+
*/
9193
}
9294

9395
export interface Context<T = any> {

‎src/utils/testing.ts

+6-9
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,10 @@ async function testInContext(code: string, options: TestOptions): Promise<TestRe
115115
const nativeTestContext = createTestContext(options)
116116
let pretranspiled: string = ''
117117
let transpiled: string = ''
118-
let parsed
119-
try {
120-
parsed = parse(code, nativeTestContext)!
118+
const parsed = parse(code, nativeTestContext)!
119+
if (parsed === undefined) {
120+
pretranspiled = 'parseError'
121+
} else {
121122
// Mutates program
122123
switch (options.variant) {
123124
case 'gpu':
@@ -132,15 +133,11 @@ async function testInContext(code: string, options: TestOptions): Promise<TestRe
132133
try {
133134
transpiled = transpile(parsed, nativeTestContext, true).transpiled
134135
// replace declaration of builtins since they're repetitive
135-
transpiled = transpiled.replace(
136-
/\n const \w+ = globals\.(previousScope.)+variables.get\("\w+"\)\.getValue\(\);/g,
137-
''
138-
)
136+
transpiled = transpiled.replace(/\n const \w+ = nativeStorage\..*;/g, '')
137+
transpiled = transpiled.replace(/\n\s*const \w+ = .*\.operators\..*;/g, '')
139138
} catch {
140139
transpiled = 'parseError'
141140
}
142-
} catch {
143-
pretranspiled = 'parseError'
144141
}
145142
const nativeResult = getTestResult(
146143
nativeTestContext,

‎src/utils/uniqueIds.ts

+3-9
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,9 @@ export function getUniqueId(usedIdentifiers: Set<string>, uniqueId = 'unique') {
1818
}
1919

2020
export function getIdentifiersInNativeStorage(nativeStorage: NativeStorage) {
21-
const identifiers = new Set<string>()
22-
let variableScope = nativeStorage.globals
23-
while (variableScope !== null) {
24-
for (const name of variableScope.variables.keys()) {
25-
identifiers.add(name)
26-
}
27-
variableScope = variableScope.previousScope
28-
}
29-
return identifiers
21+
const used = new Set(...nativeStorage.builtins.keys())
22+
nativeStorage.previousProgramsIdentifiers.forEach(id => used.add(id))
23+
return used
3024
}
3125

3226
export function getIdentifiersInProgram(program: es.Program) {

‎src/vm/svml-machine.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1770,7 +1770,7 @@ export function runWithProgram(p: Program, context: Context): any {
17701770
// setup externalBuiltins
17711771
// certain functions are imported from cadet-frontend
17721772
// so import them first every time
1773-
const externals = context.nativeStorage.globals!.variables
1773+
const externals = context.nativeStorage.builtins
17741774
if (externals.size > 0) {
17751775
EXTERNAL_PRIMITIVES.forEach(func => extractExternalBuiltin(func, externals))
17761776
}
@@ -1834,5 +1834,5 @@ const externalFunctions = new Map<number, any>()
18341834
function extractExternalBuiltin(func: [string, number], externals: Map<string, any>) {
18351835
const name = func[0]
18361836
const opcode = func[1]
1837-
externalFunctions.set(opcode, externals.get(name).getValue())
1837+
externalFunctions.set(opcode, externals.get(name))
18381838
}

0 commit comments

Comments
 (0)
Please sign in to comment.