@@ -9,11 +9,14 @@ export interface Options {
99 tagName : string
1010 /** the name prefix used for pattern matching functions */
1111 foldName : string
12+ /** the name used for the input of pattern matching functions */
13+ matcheeName : string
1214}
1315
1416export const defaultOptions : Options = {
1517 tagName : 'type' ,
16- foldName : 'fold'
18+ foldName : 'fold' ,
19+ matcheeName : 'fa'
1720}
1821
1922export interface AST < A > extends Reader < Options , A > { }
@@ -28,7 +31,7 @@ const getType = (t: M.Type): ts.TypeReferenceNode => {
2831
2932export const data = ( d : M . Data ) : AST < ts . TypeAliasDeclaration > => {
3033 return new Reader ( e => {
31- const type = ts . createUnionTypeNode (
34+ const unionType = ts . createUnionTypeNode (
3235 d . constructors . toArray ( ) . map ( c => {
3336 const tag : ts . TypeElement = ts . createPropertySignature (
3437 [ ts . createModifier ( ts . SyntaxKind . ReadonlyKeyword ) ] ,
@@ -56,7 +59,7 @@ export const data = (d: M.Data): AST<ts.TypeAliasDeclaration> => {
5659 d . introduction . parameters . map ( p =>
5760 ts . createTypeParameterDeclaration ( p . name , p . constraint . map ( getType ) . toUndefined ( ) )
5861 ) ,
59- type
62+ unionType
6063 )
6164 } )
6265}
@@ -65,67 +68,96 @@ const getConstructorName = (name: string): string => {
6568 return name . substring ( 0 , 1 ) . toLocaleLowerCase ( ) + name . substring ( 1 )
6669}
6770
71+ const getNullaryConstructorVariableStatement = (
72+ tagName : string ,
73+ c : M . Constructor ,
74+ introduction : M . Introduction
75+ ) : ts . VariableStatement => {
76+ const name = getConstructorName ( c . name )
77+ return ts . createVariableStatement (
78+ [ ts . createModifier ( ts . SyntaxKind . ExportKeyword ) ] ,
79+ ts . createVariableDeclarationList (
80+ [
81+ ts . createVariableDeclaration (
82+ name ,
83+ ts . createTypeReferenceNode (
84+ introduction . name ,
85+ introduction . parameters . map ( p =>
86+ p . constraint
87+ . map < ts . TypeNode > ( c => getType ( c ) )
88+ . getOrElse ( ts . createKeywordTypeNode ( ts . SyntaxKind . NeverKeyword ) )
89+ )
90+ ) ,
91+ ts . createObjectLiteral ( [ ts . createPropertyAssignment ( tagName , ts . createStringLiteral ( c . name ) ) ] )
92+ )
93+ ] ,
94+ ts . NodeFlags . Const
95+ )
96+ )
97+ }
98+
99+ const getFunctionDeclaration = (
100+ name : string ,
101+ typeParameters : Array < ts . TypeParameterDeclaration > ,
102+ parameters : Array < ts . ParameterDeclaration > ,
103+ type : ts . TypeNode ,
104+ body : ts . Block
105+ ) => {
106+ return ts . createFunctionDeclaration (
107+ undefined ,
108+ [ ts . createModifier ( ts . SyntaxKind . ExportKeyword ) ] ,
109+ undefined ,
110+ name ,
111+ typeParameters ,
112+ parameters ,
113+ type ,
114+ body
115+ )
116+ }
117+
118+ const getParameterDeclaration = ( name : string , type : ts . TypeNode ) : ts . ParameterDeclaration => {
119+ return ts . createParameter ( undefined , undefined , undefined , name , undefined , type , undefined )
120+ }
121+
122+ const getConstructorFunctionDeclaration = (
123+ tagName : string ,
124+ c : M . Constructor ,
125+ introduction : M . Introduction
126+ ) : ts . FunctionDeclaration => {
127+ const name = getConstructorName ( c . name )
128+ const typeParameters = introduction . parameters . map ( p => {
129+ return ts . createTypeParameterDeclaration ( p . name , p . constraint . map ( getType ) . toUndefined ( ) )
130+ } )
131+ const parameters = c . members . map ( ( m , position ) => {
132+ const name = getMemberName ( m , position )
133+ const type = getType ( m . type )
134+ return getParameterDeclaration ( name , type )
135+ } )
136+ const type = ts . createTypeReferenceNode (
137+ introduction . name ,
138+ introduction . parameters . map ( p => ts . createTypeReferenceNode ( p . name , [ ] ) )
139+ )
140+ const body = ts . createBlock ( [
141+ ts . createReturn (
142+ ts . createObjectLiteral ( [
143+ ts . createPropertyAssignment ( tagName , ts . createStringLiteral ( c . name ) ) ,
144+ ...c . members . map ( ( m , position ) => {
145+ const name = getMemberName ( m , position )
146+ return ts . createShorthandPropertyAssignment ( name )
147+ } )
148+ ] )
149+ )
150+ ] )
151+ return getFunctionDeclaration ( name , typeParameters , parameters , type , body )
152+ }
153+
68154export const constructors = ( d : M . Data ) : AST < Array < ts . Node > > => {
69155 return new Reader ( e => {
70156 return d . constructors . toArray ( ) . map ( c => {
71- const name = getConstructorName ( c . name )
72157 if ( c . members . length === 0 ) {
73- return ts . createVariableStatement (
74- [ ts . createModifier ( ts . SyntaxKind . ExportKeyword ) ] ,
75- ts . createVariableDeclarationList (
76- [
77- ts . createVariableDeclaration (
78- name ,
79- ts . createTypeReferenceNode (
80- d . introduction . name ,
81- d . introduction . parameters . map ( p =>
82- p . constraint
83- . map < ts . TypeNode > ( c => getType ( c ) )
84- . getOrElse ( ts . createKeywordTypeNode ( ts . SyntaxKind . NeverKeyword ) )
85- )
86- ) ,
87- ts . createObjectLiteral ( [ ts . createPropertyAssignment ( e . tagName , ts . createStringLiteral ( c . name ) ) ] )
88- )
89- ] ,
90- ts . NodeFlags . Const
91- )
92- )
158+ return getNullaryConstructorVariableStatement ( e . tagName , c , d . introduction )
93159 } else {
94- return ts . createFunctionDeclaration (
95- undefined ,
96- [ ts . createModifier ( ts . SyntaxKind . ExportKeyword ) ] ,
97- undefined ,
98- name ,
99- d . introduction . parameters . map ( p => {
100- return ts . createTypeParameterDeclaration ( p . name , p . constraint . map ( getType ) . toUndefined ( ) )
101- } ) ,
102- c . members . map ( ( m , position ) => {
103- return ts . createParameter (
104- undefined ,
105- undefined ,
106- undefined ,
107- getMemberName ( m , position ) ,
108- undefined ,
109- getType ( m . type ) ,
110- undefined
111- )
112- } ) ,
113- ts . createTypeReferenceNode (
114- d . introduction . name ,
115- d . introduction . parameters . map ( p => ts . createTypeReferenceNode ( p . name , [ ] ) )
116- ) ,
117- ts . createBlock ( [
118- ts . createReturn (
119- ts . createObjectLiteral ( [
120- ts . createPropertyAssignment ( e . tagName , ts . createStringLiteral ( c . name ) ) ,
121- ...c . members . map ( ( m , position ) => {
122- const name = getMemberName ( m , position )
123- return ts . createShorthandPropertyAssignment ( name )
124- } )
125- ] )
126- )
127- ] )
128- )
160+ return getConstructorFunctionDeclaration ( e . tagName , c , d . introduction )
129161 }
130162 } )
131163 } )
@@ -159,79 +191,54 @@ const getHandlerName = (c: M.Constructor): string => {
159191
160192const getFold = ( d : M . Data , name : string , isEager : boolean ) : AST < ts . FunctionDeclaration > => {
161193 return new Reader ( e => {
194+ const matcheeName = e . matcheeName
162195 const returnTypeParameterName = getFoldReturnTypeParameterName ( d . introduction )
163- return ts . createFunctionDeclaration (
164- undefined ,
165- [ ts . createModifier ( ts . SyntaxKind . ExportKeyword ) ] ,
166- undefined ,
167- name ,
168- d . introduction . parameters
169- . concat ( M . parameter ( returnTypeParameterName , none ) )
170- . map ( p => ts . createTypeParameterDeclaration ( p . name , p . constraint . map ( getType ) . toUndefined ( ) ) ) ,
171- [
172- ts . createParameter (
173- undefined ,
174- undefined ,
175- undefined ,
176- 'fa' ,
177- undefined ,
178- ts . createTypeReferenceNode (
179- d . introduction . name ,
180- d . introduction . parameters . map ( p => ts . createTypeReferenceNode ( p . name , [ ] ) )
181- ) ,
182- undefined
183- ) ,
184- ...d . constructors . toArray ( ) . map ( c => {
185- return ts . createParameter (
186- undefined ,
187- undefined ,
188- undefined ,
189- getHandlerName ( c ) ,
190- undefined ,
191- isEager && isNullaryConstructor ( c )
192- ? ts . createTypeReferenceNode ( returnTypeParameterName , [ ] )
193- : ts . createFunctionTypeNode (
194- undefined ,
195- c . members . map ( ( m , position ) => {
196- return ts . createParameter (
197- undefined ,
198- undefined ,
199- undefined ,
200- getMemberName ( m , position ) ,
201- undefined ,
202- getType ( m . type )
196+ const typeParameters = d . introduction . parameters
197+ . concat ( M . parameter ( returnTypeParameterName , none ) )
198+ . map ( p => ts . createTypeParameterDeclaration ( p . name , p . constraint . map ( getType ) . toUndefined ( ) ) )
199+ const matchee = getParameterDeclaration (
200+ matcheeName ,
201+ ts . createTypeReferenceNode (
202+ d . introduction . name ,
203+ d . introduction . parameters . map ( p => ts . createTypeReferenceNode ( p . name , [ ] ) )
204+ )
205+ )
206+ const handlers = d . constructors . toArray ( ) . map ( c => {
207+ const type =
208+ isEager && isNullaryConstructor ( c )
209+ ? ts . createTypeReferenceNode ( returnTypeParameterName , [ ] )
210+ : ts . createFunctionTypeNode (
211+ undefined ,
212+ c . members . map ( ( m , position ) => getParameterDeclaration ( getMemberName ( m , position ) , getType ( m . type ) ) ) ,
213+ ts . createTypeReferenceNode ( returnTypeParameterName , [ ] )
214+ )
215+ return getParameterDeclaration ( getHandlerName ( c ) , type )
216+ } )
217+ const parameters = [ matchee , ...handlers ]
218+ const type = ts . createTypeReferenceNode ( returnTypeParameterName , [ ] )
219+ const body = ts . createBlock ( [
220+ ts . createSwitch (
221+ ts . createPropertyAccess ( ts . createIdentifier ( matcheeName ) , e . tagName ) ,
222+ ts . createCaseBlock (
223+ d . constructors . toArray ( ) . map ( c => {
224+ return ts . createCaseClause ( ts . createStringLiteral ( c . name ) , [
225+ ts . createReturn (
226+ isEager && isNullaryConstructor ( c )
227+ ? ts . createIdentifier ( getHandlerName ( c ) )
228+ : ts . createCall (
229+ ts . createIdentifier ( getHandlerName ( c ) ) ,
230+ [ ] ,
231+ c . members . map ( ( m , position ) => {
232+ return ts . createPropertyAccess ( ts . createIdentifier ( matcheeName ) , getMemberName ( m , position ) )
233+ } )
203234 )
204- } ) ,
205- ts . createTypeReferenceNode ( returnTypeParameterName , [ ] )
206- ) ,
207- undefined
208- )
209- } )
210- ] ,
211- ts . createTypeReferenceNode ( returnTypeParameterName , [ ] ) ,
212- ts . createBlock ( [
213- ts . createSwitch (
214- ts . createPropertyAccess ( ts . createIdentifier ( 'fa' ) , e . tagName ) ,
215- ts . createCaseBlock (
216- d . constructors . toArray ( ) . map ( c => {
217- return ts . createCaseClause ( ts . createStringLiteral ( c . name ) , [
218- ts . createReturn (
219- isEager && isNullaryConstructor ( c )
220- ? ts . createIdentifier ( getHandlerName ( c ) )
221- : ts . createCall (
222- ts . createIdentifier ( getHandlerName ( c ) ) ,
223- [ ] ,
224- c . members . map ( ( m , position ) => {
225- return ts . createPropertyAccess ( ts . createIdentifier ( 'fa' ) , getMemberName ( m , position ) )
226- } )
227- )
228- )
229- ] )
230- } )
231- )
235+ )
236+ ] )
237+ } )
232238 )
233- ] )
234- )
239+ )
240+ ] )
241+ return getFunctionDeclaration ( name , typeParameters , parameters , type , body )
235242 } )
236243}
237244
0 commit comments