1
+ /******************************************************************************
2
+ * Copyright 2023 TypeFox GmbH
3
+ * This program and the accompanying materials are made available under the
4
+ * terms of the MIT License, which is available in the project root.
5
+ ******************************************************************************/
6
+
7
+ import { DefaultAstNodeLocator , DefaultJsonSerializer , DefaultNameProvider , expandToNode , Generated , joinToNode , toString } from 'langium' ;
8
+ import { Definition , Evaluation , Expression , isBinaryExpression , isDefinition , isFunctionCall , isNumberLiteral , Module , Statement } from 'langium-arithmetics-dsl/api' ;
9
+
10
+ export function generate ( { uri, content} : { uri : string , content : string | Module } ) : string {
11
+ if ( typeof content === 'string' ) {
12
+ content = deserializeModule ( content ) ;
13
+ }
14
+
15
+ return toString (
16
+ generateModule ( content )
17
+ ) ;
18
+ }
19
+
20
+ function generateModule ( root : Module ) : Generated {
21
+ return expandToNode `
22
+ "use strict";
23
+ (() => {
24
+ ${ generateModuleContent ( root ) }
25
+ })
26
+ ` ;
27
+ }
28
+
29
+ const lastComputableExpressionValueVarName = 'lastComputableExpressionValue' ;
30
+
31
+ function generateModuleContent ( module : Module ) : Generated {
32
+ return expandToNode `
33
+ let ${ lastComputableExpressionValueVarName } ;
34
+ ${ joinToNode ( module . statements , generateStatement , { appendNewLineIfNotEmpty : true } ) }
35
+
36
+ return ${ lastComputableExpressionValueVarName } ;
37
+ ` ;
38
+ }
39
+
40
+ function generateStatement ( stmt : Statement ) : Generated {
41
+ if ( isDefinition ( stmt ) )
42
+ return generateDefinition ( stmt ) ;
43
+ else
44
+ return generateEvaluation ( stmt ) ;
45
+ }
46
+
47
+ function generateDefinition ( def : Definition ) : Generated {
48
+ return def . args && def . args . length ?
49
+ expandToNode `
50
+ const ${ def . name } = (${ joinToNode ( def . args , arg => arg . name , { separator : ', ' } ) } ) => ${ generateExpression ( def . expr ) } ;
51
+ ` : expandToNode `
52
+ const ${ def . name } = ${ lastComputableExpressionValueVarName } = ${ generateExpression ( def . expr ) } ;
53
+ ` ;
54
+ }
55
+
56
+ function generateEvaluation ( evaln : Evaluation ) : Generated {
57
+ return expandToNode `
58
+ ${ lastComputableExpressionValueVarName } = ${ generateExpression ( evaln . expression ) } ;
59
+ ` ;
60
+ }
61
+
62
+ function generateExpression ( expr : Expression ) : Generated {
63
+ if ( isNumberLiteral ( expr ) ) {
64
+ return expr . value . toString ( ) ;
65
+
66
+ } else if ( isBinaryExpression ( expr ) ) {
67
+ const leftAsIs = isNumberLiteral ( expr . left ) || isFunctionCall ( expr . left ) ;
68
+ const rightAsIs = isNumberLiteral ( expr . right ) || isFunctionCall ( expr . right ) ;
69
+ const left = leftAsIs ? generateExpression ( expr . left ) : expandToNode `(${ generateExpression ( expr . left ) } )` ;
70
+ const right = rightAsIs ? generateExpression ( expr . right ) : expandToNode `(${ generateExpression ( expr . right ) } )` ;
71
+ return expandToNode `
72
+ ${ left } ${ expr . operator } ${ right }
73
+ ` ;
74
+
75
+ } else {
76
+ return expandToNode `${ expr . func . ref ?. name } ` . appendTemplateIf ( ! ! expr . args . length ) `
77
+ (
78
+ ${ joinToNode ( expr . args , generateExpression , { separator : ', ' } ) }
79
+ )
80
+ ` ;
81
+ } ;
82
+ }
83
+
84
+ function deserializeModule ( input : string ) : Module {
85
+ return new DefaultJsonSerializer ( {
86
+ workspace : {
87
+ AstNodeLocator : new DefaultAstNodeLocator ( )
88
+ } ,
89
+ references : {
90
+ NameProvider : new DefaultNameProvider ( )
91
+ }
92
+ } as any ) . deserialize ( input ) as Module ;
93
+ }
0 commit comments