Skip to content

Commit ab0b2cc

Browse files
committed
feat: statement inside expression
1 parent f7c6dfe commit ab0b2cc

File tree

6 files changed

+123
-19
lines changed

6 files changed

+123
-19
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Code } from "../types";
2+
3+
class CodegenContext {
4+
needCaptureReturn = 0;
5+
returnType: (Code[] | null)[] = []
6+
}
7+
8+
// TODO: Make this not singleton
9+
export const context = new CodegenContext();

packages/language-server/src/codegen/function.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import type { SyntaxNode } from "tree-sitter";
22
import type { Code } from "../types";
33
import { generateBlock, generateExpression, generateIdentifier, generateSelf } from ".";
4+
import { codeFeatures } from "../utils/codeFeatures";
5+
import { context } from "./context";
46
import { generateType } from "./type";
5-
import { between, generateChildren } from "./utils";
7+
import { between, generateChildren, wrapWith } from "./utils";
68

79
export enum FunctionKind {
810
Declaration,
@@ -16,6 +18,7 @@ export function* generateFunction(
1618
kind: FunctionKind,
1719
selfType?: SyntaxNode,
1820
): Generator<Code> {
21+
1922
if (kind === FunctionKind.Declaration && node.namedChildren[0]?.type === "visibility_modifier") {
2023
yield `export `;
2124
}
@@ -31,8 +34,12 @@ export function* generateFunction(
3134

3235
const type = node.childForFieldName("return_type");
3336
if (type) {
37+
const typeCode = [...generateType(type)];
3438
yield `: `;
35-
yield type;
39+
yield* typeCode;
40+
context.returnType.push(typeCode);
41+
} else {
42+
context.returnType.push(null);
3643
}
3744

3845
if (kind === FunctionKind.Closure) {

packages/language-server/src/codegen/index.ts

Lines changed: 84 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import type { SyntaxNode } from "tree-sitter";
2-
import type { Code } from "../types";
2+
import { UserError, type Code } from "../types";
33
import { codeFeatures } from "../utils/codeFeatures";
4+
import { context } from "./context";
45
import { generateEnum } from "./enum";
56
import { FunctionKind, generateFunction } from "./function";
67
import { generateImpl } from "./impl";
8+
import { generateMatch } from "./match";
79
import { generatePrelude } from "./prelude";
810
import { generateStruct, generateStructExpression } from "./struct";
911
import { generateUse } from "./use";
@@ -17,15 +19,22 @@ export function* generateRoot(root: SyntaxNode): Generator<Code> {
1719
export function* generateBlock(node: SyntaxNode, implicitReturn: boolean): Generator<Code> {
1820
yield* generateChildren(node, implicitReturn
1921
? function* (node, index, array) {
20-
if (index === array.length - 1
21-
&& (node.type.endsWith("_expression")
22+
if (index === array.length - 1) {
23+
if (node.type.endsWith("_expression")
2224
|| node.type.endsWith("_literal")
25+
|| node.type.endsWith("identifier")
2326
|| (node.type === "expression_statement"
2427
&& (node.namedChildren[0].type === "match_expression"
25-
|| node.namedChildren[0].type === "if_expression")))) {
26-
yield "return ";
28+
|| node.namedChildren[0].type === "if_expression"))) {
29+
yield* wrapWith(node.startIndex, node.endIndex, codeFeatures.verification, "return");
30+
yield " ";
31+
yield* generateExpression(node);
32+
} else {
33+
yield* generateStatement(node);
34+
}
35+
} else {
36+
yield* generateStatement(node);
2737
}
28-
yield* generateStatement(node);
2938
}
3039
: generateStatement);
3140
}
@@ -48,11 +57,20 @@ export function* generateStatement(node: SyntaxNode): Generator<Code> {
4857
yield* generateLocal(node);
4958
break;
5059
case "expression_statement":
51-
yield* generateExpression(node.namedChildren[0]);
60+
yield* generateStatement(node.namedChildren[0]);
5261
break;
5362
case "use_declaration":
5463
yield* generateUse(node);
5564
break;
65+
case "match_expression":
66+
yield* generateMatch(node);
67+
break;
68+
case "block":
69+
yield* generateBlock(node, false);
70+
break;
71+
case "if_expression":
72+
yield* generateIf(node);
73+
break;
5674
default:
5775
yield* generateExpression(node);
5876
}
@@ -121,6 +139,9 @@ export function* generateExpression(node: SyntaxNode): Generator<Code> {
121139
case "parenthesized_expression":
122140
yield* generateParenthesizedExpression(node);
123141
break;
142+
case "expression_statement":
143+
yield* generateExpression(node.namedChildren[0]);
144+
break;
124145
case "range_expression":
125146
yield* generateRangeExpression(node);
126147
break;
@@ -136,6 +157,21 @@ export function* generateExpression(node: SyntaxNode): Generator<Code> {
136157
case "struct_expression":
137158
yield* generateStructExpression(node);
138159
break;
160+
161+
case "block":
162+
context.needCaptureReturn++;
163+
yield "(() => ";
164+
yield* generateBlock(node, true);
165+
yield ")()";
166+
context.needCaptureReturn--;
167+
break;
168+
case "match_expression":
169+
case "if_expression":
170+
// TODO:
171+
// yield "(() => ";
172+
// yield ")()";
173+
break;
174+
139175
case "ERROR":
140176
yield* generateBlock(node, false);
141177
break;
@@ -155,9 +191,14 @@ function* generateBinaryExpression(node: SyntaxNode): Generator<Code> {
155191
const left = node.children[0];
156192
const right = node.children[2];
157193

158-
yield* generateExpression(left);
159-
yield* between(node, left, right);
160-
yield* generateExpression(right);
194+
yield* wrapWith(
195+
node.startIndex,
196+
node.endIndex,
197+
codeFeatures.verification,
198+
...generateExpression(left),
199+
...between(node, left, right),
200+
...generateExpression(right),
201+
);
161202
}
162203

163204
export function* generateIdentifier(node: SyntaxNode): Generator<Code> {
@@ -293,15 +334,43 @@ function* generateReferenceExpression(_node: SyntaxNode): Generator<Code> {
293334
}
294335

295336
function* generateReturnExpression(node: SyntaxNode): Generator<Code> {
296-
const value = node.namedChildren[0];
337+
const [keyword, value] = node.children;
297338

298-
yield `return `;
299-
if (value) {
300-
yield* generateExpression(value);
339+
if (context.needCaptureReturn) {
340+
const typeCode = context.returnType[context.returnType.length - 1];
341+
if (typeCode) {
342+
yield `(`
343+
if (value) {
344+
yield* generateExpression(value);
345+
}
346+
yield ` `;
347+
yield* wrapWith(
348+
keyword.startIndex,
349+
keyword.endIndex,
350+
codeFeatures.verification,
351+
"satisfies",
352+
);
353+
yield ` `;
354+
yield* typeCode;
355+
yield `)`;
356+
} else {
357+
yield new UserError(node, "Return type must be specified explicitly");
358+
}
359+
}
360+
else {
361+
yield keyword;
362+
yield " ";
363+
if (value) {
364+
yield* generateExpression(value);
365+
}
366+
yield `;`;
301367
}
302-
yield `;`;
303368
}
304369

305370
export function* generateSelf(node: SyntaxNode): Generator<Code> {
306371
yield ["this", node.startIndex];
307372
}
373+
374+
function* generateIf(_node: SyntaxNode): Generator<Code> {
375+
// TODO:
376+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import type { SyntaxNode } from "tree-sitter";
2+
import type { Code } from "../types";
3+
4+
export function* generateMatch(_node: SyntaxNode): Generator<Code> {
5+
// TODO:
6+
}

packages/transpiler/src/nodes.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ export class Printer {
130130
if (
131131
child.type.endsWith("_expression")
132132
|| child.type.endsWith("_literal")
133+
|| child.type.endsWith("identifier")
133134
|| (child.type === "expression_statement"
134135
&& (child.namedChildren[0].type === "match_expression"
135136
|| child.namedChildren[0].type === "if_expression"))
@@ -289,8 +290,10 @@ export class Printer {
289290
yield* this.printExpr(expr.namedChildren[0]);
290291
yield ")";
291292
break;
292-
293293
case "expression_statement":
294+
yield* this.printExpr(expr.namedChildren[0]);
295+
break;
296+
294297
case "match_expression":
295298
case "block":
296299
case "if_expression":

playground/basic.jsrs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,14 @@
55

66
1 + 1;
77
let mut a = 1;
8-
a.toString;
8+
a.toString;
9+
10+
fn foo() -> number {
11+
let x = {
12+
return "1";
13+
1
14+
} + {
15+
2
16+
};
17+
x
18+
}

0 commit comments

Comments
 (0)