UNPKG

4.24 kBPlain TextView Raw
1/**
2 * Copyright (c) 2016, John Hewson
3 * All rights reserved.
4 */
5
6// types
7
8export abstract class ElmType {}
9
10export class ElmTypeName extends ElmType {
11 constructor(public name: string) {
12 super();
13 }
14}
15
16export class ElmTypeApp extends ElmType {
17 constructor(public name: string, public args: Array<ElmType>) {
18 super();
19 }
20}
21
22export class ElmTypeRecord extends ElmType {
23 constructor(public fields: Array<ElmFieldDecl>, public typeParam?: string) {
24 super();
25 }
26}
27
28// decls
29
30export abstract class ElmDecl {}
31
32export class ElmTypeDecl extends ElmDecl {
33 constructor(public name: string,
34 public constructors: Array<string>) {
35 super();
36 }
37}
38
39export class ElmTypeAliasDecl extends ElmDecl {
40 constructor(public name: string,
41 public type: ElmType,
42 public typeParams: Array<string> = []) {
43 super();
44 }
45}
46
47export class ElmFunctionDecl extends ElmDecl {
48 constructor(public name: string,
49 public parameters: Array<ElmParameterDecl>,
50 public returnType: ElmType,
51 public body: ElmExpr) {
52 super();
53 }
54}
55
56export class ElmFieldDecl {
57 constructor(public name: string,
58 public type: ElmType) {}
59}
60
61export class ElmParameterDecl {
62 constructor(public name: string,
63 public type: ElmType) { }
64}
65
66// expressions
67
68export interface ElmExpr {
69 expr: string; // todo: expression trees
70}
71
72export function moduleToString(name: string, expose: Array<string>, imports: Array<string>,
73 decls: Array<ElmDecl>) {
74 let warn = '{-\n This file was automatically generated by elm-graphql.\n-}\n';
75 return warn + 'module ' + name + ' exposing (' + expose.join(', ') + ')\n' +
76 imports.map(str => '\nimport ' + str).join('') + '\n\n' +
77 decls.map(declToString).join('\n\n');
78}
79
80export function declToString(decl: ElmDecl): string {
81 if (decl instanceof ElmTypeDecl) {
82 return typeDeclToString(decl);
83 } else if (decl instanceof ElmFunctionDecl) {
84 return funtionToString(decl);
85 } else if (decl instanceof ElmTypeAliasDecl) {
86 return typeAliasDeclToString(decl);
87 } else {
88 throw new Error('unexpected decl: ' + decl.constructor.name + ' ' + JSON.stringify(decl));
89 }
90}
91
92export function typeDeclToString(type: ElmTypeDecl): string {
93 return 'type ' + type.name + '\n' +
94 ' = ' + type.constructors.join('\n | ') + '\n';
95}
96
97export function typeAliasDeclToString(type: ElmTypeAliasDecl): string {
98 return 'type alias ' + type.name + ' ' + type.typeParams.join(' ') + '\n' +
99 ' = ' + typeToString(type.type, 0) + '\n';
100}
101
102export function funtionToString(func: ElmFunctionDecl): string {
103 let paramTypes = func.parameters.map(p => typeToString(p.type, 1)).join(' -> ');
104 let paramNames = func.parameters.map(p => p.name).join(' ');
105 let arrow = paramTypes.length > 0 ? ' -> ' : '';
106 let space = paramTypes.length > 0 ? ' ' : '';
107 return func.name + ' : ' + paramTypes + arrow + typeToString(func.returnType, 0) + '\n' +
108 func.name + space + paramNames + ' =\n ' + exprToString(func.body, 0) + '\n';
109}
110
111function fieldToString(field: ElmFieldDecl, level: number): string {
112 return field.name + ' : ' + typeToString(field.type, level, true) + '\n';
113}
114
115export function typeToString(ty: ElmType, level: number, isField?: boolean): string {
116 if (ty instanceof ElmTypeName) {
117 return ty.name;
118 } else if (ty instanceof ElmTypeApp) {
119 let str = ty.name + ' ' + ty.args.map(arg => typeToString(arg, level)).join(' ');
120 if (isField) {
121 return str;
122 } else {
123 return '(' + str + ')';
124 }
125 } else if (ty instanceof ElmTypeRecord) {
126 let indent = makeIndent(level);
127 let pipe = ty.typeParam ? ty.typeParam + ' | ' : '';
128 return `${indent}{ ` + pipe +
129 ty.fields.map(f => fieldToString(f, level + 1)).join(`${indent} , `) +
130 `${indent}}`;
131 } else {
132 throw new Error('unexpected type: ' + ty.constructor.name + ' ' + JSON.stringify(ty));
133 }
134}
135
136function makeIndent(level: number) {
137 let str = '';
138 for (let i = 0; i < level; i++) {
139 str += ' ';
140 }
141 return str;
142}
143
144export function exprToString(expr: ElmExpr, level: number): string {
145 return expr.expr; // todo: expression trees
146}