@@ -9,6 +9,7 @@ import { conditionalExpression, literal, primitive } from '../utils/astCreator'
9
9
import { evaluateBinaryExpression , evaluateUnaryExpression } from '../utils/operators'
10
10
import * as rttc from '../utils/rttc'
11
11
import Closure from './closure'
12
+ import { loadIIFEModule } from '../modules/moduleLoader'
12
13
13
14
class BreakValue { }
14
15
@@ -96,9 +97,9 @@ const handleRuntimeError = (context: Context, error: RuntimeSourceError): never
96
97
throw error
97
98
}
98
99
99
- const HOISTED_BUT_NOT_YET_ASSIGNED = Symbol ( 'Used to implement hoisting' )
100
+ const DECLARED_BUT_NOT_YET_ASSIGNED = Symbol ( 'Used to implement hoisting' )
100
101
101
- function hoistIdentifier ( context : Context , name : string , node : es . Node ) {
102
+ function declareIdentifier ( context : Context , name : string , node : es . Node ) {
102
103
const environment = currentEnvironment ( context )
103
104
if ( environment . head . hasOwnProperty ( name ) ) {
104
105
const descriptors = Object . getOwnPropertyDescriptors ( environment . head )
@@ -108,27 +109,30 @@ function hoistIdentifier(context: Context, name: string, node: es.Node) {
108
109
new errors . VariableRedeclaration ( node , name , descriptors [ name ] . writable )
109
110
)
110
111
}
111
- environment . head [ name ] = HOISTED_BUT_NOT_YET_ASSIGNED
112
+ environment . head [ name ] = DECLARED_BUT_NOT_YET_ASSIGNED
112
113
return environment
113
114
}
114
115
115
- function hoistVariableDeclarations ( context : Context , node : es . VariableDeclaration ) {
116
+ function declareVariables ( context : Context , node : es . VariableDeclaration ) {
116
117
for ( const declaration of node . declarations ) {
117
- hoistIdentifier ( context , ( declaration . id as es . Identifier ) . name , node )
118
+ declareIdentifier ( context , ( declaration . id as es . Identifier ) . name , node )
118
119
}
119
120
}
120
121
121
- function hoistFunctionsAndVariableDeclarationsIdentifiers (
122
- context : Context ,
123
- node : es . BlockStatement
124
- ) {
122
+ function declareImports ( context : Context , node : es . ImportDeclaration ) {
123
+ for ( const declaration of node . specifiers ) {
124
+ declareIdentifier ( context , declaration . local . name , node )
125
+ }
126
+ }
127
+
128
+ function declareFunctionsAndVariables ( context : Context , node : es . BlockStatement ) {
125
129
for ( const statement of node . body ) {
126
130
switch ( statement . type ) {
127
131
case 'VariableDeclaration' :
128
- hoistVariableDeclarations ( context , statement )
132
+ declareVariables ( context , statement )
129
133
break
130
134
case 'FunctionDeclaration' :
131
- hoistIdentifier ( context , ( statement . id as es . Identifier ) . name , statement )
135
+ declareIdentifier ( context , ( statement . id as es . Identifier ) . name , statement )
132
136
break
133
137
}
134
138
}
@@ -137,7 +141,7 @@ function hoistFunctionsAndVariableDeclarationsIdentifiers(
137
141
function defineVariable ( context : Context , name : string , value : Value , constant = false ) {
138
142
const environment = context . runtime . environments [ 0 ]
139
143
140
- if ( environment . head [ name ] !== HOISTED_BUT_NOT_YET_ASSIGNED ) {
144
+ if ( environment . head [ name ] !== DECLARED_BUT_NOT_YET_ASSIGNED ) {
141
145
return handleRuntimeError (
142
146
context ,
143
147
new errors . VariableRedeclaration ( context . runtime . nodes [ 0 ] ! , name , ! constant )
@@ -176,7 +180,7 @@ const getVariable = (context: Context, name: string) => {
176
180
let environment : Environment | null = context . runtime . environments [ 0 ]
177
181
while ( environment ) {
178
182
if ( environment . head . hasOwnProperty ( name ) ) {
179
- if ( environment . head [ name ] === HOISTED_BUT_NOT_YET_ASSIGNED ) {
183
+ if ( environment . head [ name ] === DECLARED_BUT_NOT_YET_ASSIGNED ) {
180
184
return handleRuntimeError (
181
185
context ,
182
186
new errors . UnassignedVariable ( name , context . runtime . nodes [ 0 ] )
@@ -195,7 +199,7 @@ const setVariable = (context: Context, name: string, value: any) => {
195
199
let environment : Environment | null = context . runtime . environments [ 0 ]
196
200
while ( environment ) {
197
201
if ( environment . head . hasOwnProperty ( name ) ) {
198
- if ( environment . head [ name ] === HOISTED_BUT_NOT_YET_ASSIGNED ) {
202
+ if ( environment . head [ name ] === DECLARED_BUT_NOT_YET_ASSIGNED ) {
199
203
break
200
204
}
201
205
const descriptors = Object . getOwnPropertyDescriptors ( environment . head )
@@ -266,7 +270,7 @@ function* reduceIf(
266
270
export type Evaluator < T extends es . Node > = ( node : T , context : Context ) => IterableIterator < Value >
267
271
268
272
function * evaluateBlockSatement ( context : Context , node : es . BlockStatement ) {
269
- hoistFunctionsAndVariableDeclarationsIdentifiers ( context , node )
273
+ declareFunctionsAndVariables ( context , node )
270
274
let result
271
275
for ( const statement of node . body ) {
272
276
result = yield * evaluate ( statement , context )
@@ -412,7 +416,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
412
416
const testNode = node . test !
413
417
const updateNode = node . update !
414
418
if ( initNode . type === 'VariableDeclaration' ) {
415
- hoistVariableDeclarations ( context , initNode )
419
+ declareVariables ( context , initNode )
416
420
}
417
421
yield * actualValue ( initNode , context )
418
422
@@ -427,7 +431,7 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
427
431
pushEnvironment ( context , environment )
428
432
for ( const name in loopEnvironment . head ) {
429
433
if ( loopEnvironment . head . hasOwnProperty ( name ) ) {
430
- hoistIdentifier ( context , name , node )
434
+ declareIdentifier ( context , name , node )
431
435
defineVariable ( context , name , loopEnvironment . head [ name ] , true )
432
436
}
433
437
}
@@ -600,6 +604,17 @@ export const evaluators: { [nodeType: string]: Evaluator<es.Node> } = {
600
604
return result
601
605
} ,
602
606
607
+ ImportDeclaration : function * ( node : es . ImportDeclaration , context : Context ) {
608
+ const moduleName = node . source . value as string
609
+ const neededSymbols = node . specifiers . map ( spec => spec . local . name )
610
+ const module = loadIIFEModule ( moduleName )
611
+ declareImports ( context , node )
612
+ for ( const name of neededSymbols ) {
613
+ defineVariable ( context , name , module [ name ] , true ) ;
614
+ }
615
+ return undefined
616
+ } ,
617
+
603
618
Program : function * ( node : es . BlockStatement , context : Context ) {
604
619
context . numberOfOuterEnvironments += 1
605
620
const environment = createBlockEnvironment ( context , 'programEnvironment' )
0 commit comments