Skip to content

Commit 858c0ae

Browse files
committed
Contribution of a generator implementation using expandToNode and joinToNode
1 parent e7ed0cb commit 858c0ae

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

src/arithmeticsEditor/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { expandToString } from 'langium';
88
import { buildWorkerDefinition } from 'monaco-editor-workers';
99
import { CodeEditorConfig, MonacoEditorLanguageClientWrapper, WorkerConfigOptions } from 'monaco-editor-wrapper';
1010
import { Diagnostic, DiagnosticSeverity, NotificationType } from 'vscode-languageserver/browser.js';
11-
import { generate } from '../generator/generator.js';
11+
import { generate } from '../generator/generator-with-nodes.js';
1212

1313
type DocumentChange = { uri: string, content: string, diagnostics: Diagnostic[] };
1414

src/generator/generator-with-nodes.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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

Comments
 (0)