44 CommonFlags ,
55 FloatLiteralExpression ,
66 FunctionDeclaration ,
7- IdentifierExpression ,
87 IntegerLiteralExpression ,
98 LiteralExpression ,
109 LiteralKind ,
@@ -22,14 +21,29 @@ import {
2221 Token ,
2322 Tokenizer ,
2423 ExportStatement ,
24+ ImportStatement ,
2525} from "assemblyscript/dist/assemblyscript.js" ;
2626import { Parameter } from "./types.js" ;
27-
2827class OptionalParam {
2928 param : Parameter ;
3029 defaultValue : string | null = null ;
3130}
3231
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+
3347/**
3448 * Overrides the default multi-param generated by ASC
3549 * By default, you must have optional params declared in sequential order
@@ -63,41 +77,28 @@ class OptionalParam {
6377 */
6478export class MultiParamGen {
6579 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 [ ] = [ ] ;
6785 public optional_fns = new Map < string , OptionalParam [ ] > ( ) ;
6886 static init ( ) : MultiParamGen {
6987 if ( ! MultiParamGen . SN ) MultiParamGen . SN = new MultiParamGen ( ) ;
7088 return MultiParamGen . SN ;
7189 }
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- }
8090 visitFunctionDeclaration ( node : FunctionDeclaration ) {
8191 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 ;
9495 if (
9596 source . sourceKind != SourceKind . UserEntry &&
96- ! this . required_fns . includes ( name )
97+ ! this . foreign_fns
98+ . get ( source . internalPath )
99+ ?. find ( ( v ) => v . foreignName == name )
97100 )
98101 return ;
99- if ( node . flags != CommonFlags . Export && ! this . required_fns . includes ( name ) )
100- return ;
101102 if ( node . signature . parameters . length > 63 ) {
102103 throw new Error ( "Functions exceeding 64 parameters not allowed!" ) ;
103104 }
@@ -117,52 +118,117 @@ export class MultiParamGen {
117118 } ) ;
118119 }
119120
120- this . optional_fns . set ( name , params ) ;
121+ const exportedName = getExportedName ( name , source ) ;
122+ this . optional_fns . set ( exportedName , params ) ;
121123
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+ }
123132
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 ) ;
137159 }
138160 }
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 ) ;
156161 }
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+ }
163229 }
164230 }
165- for ( const stmt of node . statements ) {
231+ for ( const stmt of source . statements ) {
166232 if ( stmt . kind === NodeKind . FunctionDeclaration ) {
167233 this . visitFunctionDeclaration ( stmt as FunctionDeclaration ) ;
168234 }
@@ -315,3 +381,69 @@ function initDefaultValues(node: FunctionDeclaration) {
315381 }
316382 }
317383}
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