4
4
CommonFlags ,
5
5
FloatLiteralExpression ,
6
6
FunctionDeclaration ,
7
- IdentifierExpression ,
8
7
IntegerLiteralExpression ,
9
8
LiteralExpression ,
10
9
LiteralKind ,
@@ -22,14 +21,29 @@ import {
22
21
Token ,
23
22
Tokenizer ,
24
23
ExportStatement ,
24
+ ImportStatement ,
25
25
} from "assemblyscript/dist/assemblyscript.js" ;
26
26
import { Parameter } from "./types.js" ;
27
-
28
27
class OptionalParam {
29
28
param : Parameter ;
30
29
defaultValue : string | null = null ;
31
30
}
32
31
32
+ class NameMeta {
33
+ localName : string | null ;
34
+ foreignName : string | null ;
35
+ exportedName : string | null ;
36
+ constructor (
37
+ localName : string | null = null ,
38
+ foreignName : string | null = null ,
39
+ exportedName : string | null = null ,
40
+ ) {
41
+ this . localName = localName ;
42
+ this . foreignName = foreignName ;
43
+ this . exportedName = exportedName ;
44
+ }
45
+ }
46
+
33
47
/**
34
48
* Overrides the default multi-param generated by ASC
35
49
* By default, you must have optional params declared in sequential order
@@ -63,41 +77,28 @@ class OptionalParam {
63
77
*/
64
78
export class MultiParamGen {
65
79
static SN : MultiParamGen = new MultiParamGen ( ) ;
66
- public required_fns : string [ ] = [ ] ;
80
+ public sources : Source [ ] = [ ] ;
81
+ public foreign_fns = new Map < string , NameMeta [ ] > ( ) ;
82
+ public foreign_files = new Set < string > ( ) ;
83
+
84
+ public exported_fns : NameMeta [ ] = [ ] ;
67
85
public optional_fns = new Map < string , OptionalParam [ ] > ( ) ;
68
86
static init ( ) : MultiParamGen {
69
87
if ( ! MultiParamGen . SN ) MultiParamGen . SN = new MultiParamGen ( ) ;
70
88
return MultiParamGen . SN ;
71
89
}
72
- visitExportStatement ( node : ExportStatement ) : void {
73
- const source = node . range . source ;
74
- if ( source . sourceKind != SourceKind . UserEntry ) return ;
75
- for ( const member of node . members ) {
76
- const name = member . localName . text ;
77
- this . required_fns . push ( name ) ;
78
- }
79
- }
80
90
visitFunctionDeclaration ( node : FunctionDeclaration ) {
81
91
const source = node . range . source ;
82
- let name = node . name . text ;
83
- if ( ! node . body && node . decorators ?. length ) {
84
- const decorator = node . decorators . find (
85
- ( e ) => ( e . name as IdentifierExpression ) . text === "external" ,
86
- ) ;
87
- if (
88
- decorator . args . length > 1 &&
89
- decorator . args [ 1 ] . kind === NodeKind . Literal
90
- ) {
91
- name = ( decorator . args [ 1 ] as StringLiteralExpression ) . value . toString ( ) ;
92
- }
93
- }
92
+ const name = node . name . text ;
93
+ const exported = isExported ( name , source ) ;
94
+ if ( ! exported ) return ;
94
95
if (
95
96
source . sourceKind != SourceKind . UserEntry &&
96
- ! this . required_fns . includes ( name )
97
+ ! this . foreign_fns
98
+ . get ( source . internalPath )
99
+ ?. find ( ( v ) => v . foreignName == name )
97
100
)
98
101
return ;
99
- if ( node . flags != CommonFlags . Export && ! this . required_fns . includes ( name ) )
100
- return ;
101
102
if ( node . signature . parameters . length > 63 ) {
102
103
throw new Error ( "Functions exceeding 64 parameters not allowed!" ) ;
103
104
}
@@ -117,52 +118,117 @@ export class MultiParamGen {
117
118
} ) ;
118
119
}
119
120
120
- this . optional_fns . set ( name , params ) ;
121
+ const exportedName = getExportedName ( name , source ) ;
122
+ this . optional_fns . set ( exportedName , params ) ;
121
123
122
- initDefaultValues ( node ) ;
124
+ if (
125
+ node . flags == CommonFlags . Export ||
126
+ node . flags == CommonFlags . ModuleExport
127
+ ) {
128
+ if ( name != exportedName ) {
129
+ this . optional_fns . set ( name , params ) ;
130
+ }
131
+ }
123
132
124
- if ( node . body == null ) {
125
- let name = node . name . text ;
126
- if ( ! node . body && node . decorators ?. length ) {
127
- const decorator = node . decorators . find (
128
- ( e ) => ( e . name as IdentifierExpression ) . text === "external" ,
129
- ) ;
130
- if (
131
- decorator . args . length > 1 &&
132
- decorator . args [ 1 ] . kind === NodeKind . Literal
133
- ) {
134
- name = (
135
- decorator . args [ 1 ] as StringLiteralExpression
136
- ) . value . toString ( ) ;
133
+ initDefaultValues ( node ) ;
134
+ }
135
+ visitSource ( source : Source ) {
136
+ if ( this . foreign_files . has ( source . internalPath ) ) {
137
+ for ( const stmt of source . statements ) {
138
+ if ( stmt . kind === NodeKind . FunctionDeclaration ) {
139
+ const node = stmt as FunctionDeclaration ;
140
+ const foreignName = node . name . text ;
141
+ const internalPath = source . internalPath ;
142
+ const exported = isExported ( foreignName , source ) ;
143
+ const exportedName = getExportedName ( foreignName , source ) ;
144
+ if ( exported ) {
145
+ if ( this . foreign_fns . has ( internalPath ) ) {
146
+ this . foreign_fns
147
+ . get ( foreignName )
148
+ ?. push ( new NameMeta ( foreignName , foreignName , exportedName ) ) ;
149
+ } else {
150
+ this . foreign_fns . set ( internalPath , [
151
+ new NameMeta ( foreignName , foreignName , exportedName ) ,
152
+ ] ) ;
153
+ }
154
+ }
155
+ this . exported_fns . push (
156
+ new NameMeta ( foreignName , foreignName , exportedName ) ,
157
+ ) ;
158
+ console . log ( this . exported_fns ) ;
137
159
}
138
160
}
139
- const params : OptionalParam [ ] = [ ] ;
140
- for ( const param of node . signature . parameters ) {
141
- const defaultValue = getDefaultValue ( param ) ;
142
- params . push ( {
143
- param : {
144
- name : param . name . text ,
145
- type : {
146
- name : "UNINITIALIZED_VALUE" ,
147
- path : "UNINITIALIZED_VALUE" ,
148
- } ,
149
- optional : ! ! param . initializer ,
150
- } ,
151
- defaultValue,
152
- } ) ;
153
- if ( param . initializer ) param . initializer = null ;
154
- }
155
- this . optional_fns . set ( name , params ) ;
156
161
}
157
- }
158
- visitSource ( node : Source ) {
159
- if ( node . isLibrary ) return ;
160
- for ( const stmt of node . statements ) {
161
- if ( stmt . kind === NodeKind . Export ) {
162
- this . visitExportStatement ( stmt as ExportStatement ) ;
162
+ if ( source . sourceKind === SourceKind . UserEntry ) {
163
+ for ( const stmt of source . statements ) {
164
+ if ( stmt . kind === NodeKind . Import ) {
165
+ const internalPath = ( stmt as ImportStatement ) . internalPath ;
166
+ for ( const node of ( stmt as ImportStatement ) . declarations ) {
167
+ const source = node . range . source ;
168
+ if ( source . sourceKind != SourceKind . UserEntry ) return ;
169
+ const foreignName = getRealName (
170
+ node . foreignName . text ,
171
+ this . sources . find ( ( src ) => src . internalPath == internalPath ) ,
172
+ ) ;
173
+ const localName = node . name . text ;
174
+ const exported = isExported ( localName , source ) ;
175
+ if ( ! exported ) return ;
176
+ if ( this . foreign_fns . has ( internalPath ) ) {
177
+ this . foreign_fns
178
+ . get ( internalPath )
179
+ . push ( new NameMeta ( localName , foreignName ) ) ;
180
+ } else {
181
+ this . foreign_fns . set ( internalPath , [
182
+ new NameMeta ( localName , foreignName ) ,
183
+ ] ) ;
184
+ }
185
+ }
186
+ } else if ( stmt . kind === NodeKind . Export ) {
187
+ const node = stmt as ExportStatement ;
188
+ const internalPath = node . internalPath ;
189
+ if ( internalPath ) {
190
+ if ( node . members ?. length ) {
191
+ if ( ! this . foreign_fns . has ( internalPath ) ) {
192
+ this . foreign_fns . set ( internalPath , [ ] ) ;
193
+ }
194
+ const foreign_fns = this . foreign_fns . get ( internalPath ) ;
195
+ for ( const member of node . members ) {
196
+ const localName = member . localName . text ;
197
+ const exportedName = member . exportedName . text ;
198
+ const exists = foreign_fns . find (
199
+ ( v ) => v . localName == localName ,
200
+ ) ;
201
+ if ( exists ) {
202
+ exists . exportedName = exportedName ;
203
+ } else {
204
+ foreign_fns . push (
205
+ new NameMeta ( localName , localName , exportedName ) ,
206
+ ) ;
207
+ }
208
+ }
209
+ } else {
210
+ this . foreign_files . add ( internalPath ) ;
211
+ }
212
+ } else {
213
+ if ( ! node . members ?. length ) continue ;
214
+ for ( const member of node . members ) {
215
+ const localName = member . localName . text ;
216
+ let foreignName : string = localName ;
217
+ for ( const v of this . foreign_fns . values ( ) ) {
218
+ for ( const value of v ) {
219
+ if ( value . localName === localName )
220
+ foreignName = value . foreignName ;
221
+ }
222
+ }
223
+ const exportedName = member . exportedName . text ;
224
+ const meta = new NameMeta ( localName , foreignName , exportedName ) ;
225
+ this . exported_fns . push ( meta ) ;
226
+ }
227
+ }
228
+ }
163
229
}
164
230
}
165
- for ( const stmt of node . statements ) {
231
+ for ( const stmt of source . statements ) {
166
232
if ( stmt . kind === NodeKind . FunctionDeclaration ) {
167
233
this . visitFunctionDeclaration ( stmt as FunctionDeclaration ) ;
168
234
}
@@ -315,3 +381,69 @@ function initDefaultValues(node: FunctionDeclaration) {
315
381
}
316
382
}
317
383
}
384
+
385
+ function isExported ( name : string , source : Source ) : boolean {
386
+ let i = source . statements . length - 1 ;
387
+ while ( i >= 0 ) {
388
+ const stmt = source . statements [ i ] ;
389
+ if ( stmt . kind === NodeKind . FunctionDeclaration ) {
390
+ const node = stmt as FunctionDeclaration ;
391
+ return (
392
+ node . flags === CommonFlags . Export ||
393
+ node . flags === CommonFlags . ModuleExport
394
+ ) ;
395
+ } else if ( stmt . kind === NodeKind . Export ) {
396
+ const node = stmt as ExportStatement ;
397
+ // export { ... } from "..."
398
+ if ( node . members ) {
399
+ for ( const member of node . members ) {
400
+ const localName = member . localName . text ;
401
+ if ( name === localName ) return true ;
402
+ }
403
+ }
404
+ }
405
+ i -- ;
406
+ }
407
+ return false ;
408
+ }
409
+
410
+ function getExportedName ( name : string , source : Source ) : string {
411
+ const exists = MultiParamGen . SN . exported_fns . find (
412
+ ( v ) => v . foreignName == name ,
413
+ ) ;
414
+ if ( exists ) return exists . exportedName ;
415
+ let i = source . statements . length - 1 ;
416
+ while ( i >= 0 ) {
417
+ const stmt = source . statements [ i ] ;
418
+ if ( stmt . kind === NodeKind . Export ) {
419
+ const node = stmt as ExportStatement ;
420
+ // export { ... } from "..."
421
+ if ( node . members ) {
422
+ for ( const member of node . members ) {
423
+ const localName = member . localName . text ;
424
+ const exportedName = member . exportedName . text ;
425
+ if ( name === localName ) return exportedName || localName ;
426
+ }
427
+ }
428
+ }
429
+ i -- ;
430
+ }
431
+ return name ;
432
+ }
433
+
434
+ function getRealName ( name : string , source : Source ) : string {
435
+ if ( ! source || ! source ?. statements ) return name ;
436
+ for ( const stmt of source . statements ) {
437
+ if ( stmt . kind === NodeKind . Export ) {
438
+ const node = stmt as ExportStatement ;
439
+ if ( node . members ) {
440
+ for ( const member of node . members ) {
441
+ const localName = member . localName . text ;
442
+ const exportedName = member . exportedName . text ;
443
+ if ( name === exportedName ) return localName ;
444
+ }
445
+ }
446
+ }
447
+ }
448
+ return name ;
449
+ }
0 commit comments