Skip to content

Commit 41a5023

Browse files
committed
Feature(compiler): Refactoring, extract code to FunctionDeclarationCodeGenerator
1 parent 679b122 commit 41a5023

2 files changed

Lines changed: 90 additions & 76 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
2+
import * as ts from "typescript";
3+
import * as llvm from 'llvm-node';
4+
import {NodeGenerateInterface} from "../node-generate.interface";
5+
import {Context} from "../context";
6+
import {FunctionReference, Primitive} from "../value";
7+
import {NativeTypeResolver} from "../native-type-resolver";
8+
import UnsupportedError from "../../error";
9+
import {passStatement} from "../index";
10+
11+
export class FunctionDeclarationCodeGenerator implements NodeGenerateInterface<ts.FunctionDeclaration, FunctionReference> {
12+
generate(node: ts.FunctionDeclaration, ctx: Context, builder: llvm.IRBuilder): FunctionReference {
13+
if (!node.name || !node.name.escapedText) {
14+
throw Error('Function must be declared with name');
15+
}
16+
17+
if (!node.type) {
18+
throw Error('Function must be declared with return type');
19+
}
20+
21+
let returnType = NativeTypeResolver.getType(ctx.typeChecker.getTypeFromTypeNode(node.type), ctx).getType();
22+
let fnType = llvm.FunctionType.get(
23+
returnType,
24+
node.parameters.map((parameter) => {
25+
if (parameter.type) {
26+
const nativeType = NativeTypeResolver.getType(ctx.typeChecker.getTypeFromTypeNode(parameter.type), ctx);
27+
if (nativeType) {
28+
return nativeType.getType();
29+
}
30+
}
31+
32+
throw new UnsupportedError(
33+
parameter,
34+
`Unsupported parameter`
35+
);
36+
}),
37+
false
38+
);
39+
let fn = llvm.Function.create(fnType, llvm.LinkageTypes.ExternalLinkage, <string>node.name.escapedText, ctx.llvmModule);
40+
41+
let block = llvm.BasicBlock.create(ctx.llvmContext, 'Entry', fn);
42+
let irBuilder = new llvm.IRBuilder(block);
43+
44+
for (const argument of fn.getArguments()) {
45+
const parameter = node.parameters[argument.argumentNumber];
46+
if (parameter) {
47+
argument.name = <string>(<ts.Identifier>parameter.name).escapedText;
48+
ctx.scope.variables.set(argument.name, new Primitive(argument));
49+
} else {
50+
throw new UnsupportedError(
51+
parameter,
52+
`Unsupported parameter`
53+
);
54+
}
55+
}
56+
57+
58+
// Store to return back
59+
const enclosureFnStore = ctx.scope.enclosureFunction;
60+
61+
ctx.scope.enclosureFunction = {
62+
llvmFunction: fn,
63+
declaration: node
64+
};
65+
66+
if (node.body) {
67+
for (const stmt of node.body.statements) {
68+
passStatement(stmt, ctx, irBuilder);
69+
}
70+
}
71+
72+
// store back
73+
ctx.scope.enclosureFunction = enclosureFnStore;
74+
75+
if (returnType.isVoidTy()) {
76+
if (!block.getTerminator()) {
77+
irBuilder.createRetVoid();
78+
}
79+
80+
const nextBlock = irBuilder.getInsertBlock();
81+
if (!nextBlock.getTerminator()) {
82+
irBuilder.createRetVoid();
83+
}
84+
}
85+
86+
return new FunctionReference(fn);
87+
}
88+
}

src/backend/llvm/index.ts

Lines changed: 2 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {CallExpressionCodeGenerator} from "./code-generation/call-expression";
3434
import {PropertyAccessExpressionCodeGenerator} from "./code-generation/property-access-expression";
3535
import {TryStatementGenerator} from "./code-generation/try-statement";
3636
import {PostfixUnaryExpressionCodeGenerator} from "./code-generation/postfix-unary-expression";
37+
import {FunctionDeclarationCodeGenerator} from "./code-generation/function-declaration";
3738

3839
export function emitCondition(
3940
condition: ts.Expression,
@@ -48,81 +49,6 @@ export function emitCondition(
4849
builder.createCondBr(conditionBoolValue.getValue(), positiveBlock, negativeBlock);
4950
}
5051

51-
export function passFunctionDeclaration(parent: ts.FunctionDeclaration, ctx: Context, builder: llvm.IRBuilder) {
52-
if (!parent.name || !parent.name.escapedText) {
53-
throw Error('Function must be declared with name');
54-
}
55-
56-
if (!parent.type) {
57-
throw Error('Function must be declared with return type');
58-
}
59-
60-
let returnType = NativeTypeResolver.getType(ctx.typeChecker.getTypeFromTypeNode(parent.type), ctx).getType();
61-
let fnType = llvm.FunctionType.get(
62-
returnType,
63-
parent.parameters.map((parameter) => {
64-
if (parameter.type) {
65-
const nativeType = NativeTypeResolver.getType(ctx.typeChecker.getTypeFromTypeNode(parameter.type), ctx);
66-
if (nativeType) {
67-
return nativeType.getType();
68-
}
69-
}
70-
71-
throw new UnsupportedError(
72-
parameter,
73-
`Unsupported parameter`
74-
);
75-
}),
76-
false
77-
);
78-
let fn = llvm.Function.create(fnType, llvm.LinkageTypes.ExternalLinkage, <string>parent.name.escapedText, ctx.llvmModule);
79-
80-
let block = llvm.BasicBlock.create(ctx.llvmContext, 'Entry', fn);
81-
let irBuilder = new llvm.IRBuilder(block);
82-
83-
for (const argument of fn.getArguments()) {
84-
const parameter = parent.parameters[argument.argumentNumber];
85-
if (parameter) {
86-
argument.name = <string>(<ts.Identifier>parameter.name).escapedText;
87-
ctx.scope.variables.set(argument.name, new Primitive(argument));
88-
} else {
89-
throw new UnsupportedError(
90-
parameter,
91-
`Unsupported parameter`
92-
);
93-
}
94-
}
95-
96-
97-
// Store to return back
98-
const enclosureFnStore = ctx.scope.enclosureFunction;
99-
100-
ctx.scope.enclosureFunction = {
101-
llvmFunction: fn,
102-
declaration: parent
103-
};
104-
105-
if (parent.body) {
106-
for (const stmt of parent.body.statements) {
107-
passStatement(stmt, ctx, irBuilder);
108-
}
109-
}
110-
111-
// store back
112-
ctx.scope.enclosureFunction = enclosureFnStore;
113-
114-
if (returnType.isVoidTy()) {
115-
if (!block.getTerminator()) {
116-
irBuilder.createRetVoid();
117-
}
118-
119-
const nextBlock = irBuilder.getInsertBlock();
120-
if (!nextBlock.getTerminator()) {
121-
irBuilder.createRetVoid();
122-
}
123-
}
124-
}
125-
12652
export function buildFromStringValue(node: ts.StringLiteral, ctx: Context, builder: llvm.IRBuilder): Value {
12753
return new Primitive(
12854
builder.createGlobalStringPtr(
@@ -457,7 +383,7 @@ export function passStatement(stmt: ts.Statement, ctx: Context, builder: llvm.IR
457383
buildFromExpression(<any>stmt, ctx, builder);
458384
break;
459385
case ts.SyntaxKind.FunctionDeclaration:
460-
passFunctionDeclaration(stmt as ts.FunctionDeclaration, ctx, builder);
386+
new FunctionDeclarationCodeGenerator().generate(stmt as ts.FunctionDeclaration, ctx, builder);
461387
break;
462388
case ts.SyntaxKind.ReturnStatement:
463389
new ReturnStatementCodeGenerator().generate(stmt as ts.ReturnStatement, ctx, builder);

0 commit comments

Comments
 (0)