-
Notifications
You must be signed in to change notification settings - Fork 46
/
main.bal
126 lines (118 loc) · 4.05 KB
/
main.bal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import wso2/nballerina.bir;
import wso2/nballerina.nback;
import wso2/nballerina.comm.err;
import wso2/nballerina.comm.diagnostic as d;
import ballerina/io;
import ballerina/file;
type CompileError err:Diagnostic|io:Error|file:Error;
public type Options record {
boolean testJsonTypes = false;
boolean showTypes = false;
int? debugLevel;
// outDir also implies treating each file as a separate module
string? outDir = ();
string? expectOutDir = ();
string? gc = ();
string? htmlError = ();
boolean bir = false;
*OutputOptions;
};
const DEFAULT_ROOT_MODULE_NAME = "root";
final bir:ModuleId DEFAULT_ROOT_MODULE_ID = { org: "", names: [DEFAULT_ROOT_MODULE_NAME] };
const SOURCE_EXTENSION = ".bal";
const TEST_EXTENSION = ".balt";
public function main(string[] filenames, *Options opts) returns error? {
if filenames.length() == 0 {
return error("no input files");
}
if opts.testJsonTypes {
if filenames.length() > 1 {
return error("multiple input files not supported with --testJsonTypes");
}
check testJsonTypes(filenames[0]);
return;
}
if opts.showTypes {
if filenames.length() > 1 {
return error("multiple input files not supported with --showTypes");
}
check printDiagnostic(showTypes([{ filename: filenames[0] }]));
return;
}
nback:Options nbackOptions = {
gcName: check nback:validGcName(opts.gc),
debugLevel: check nback:validDebugLevel(opts.debugLevel)
};
int errorFileCount = 0;
d:Printer dPrinter;
string? errorFilename = opts.htmlError;
if errorFilename != () {
dPrinter = new d:HtmlPrinter(errorFilename);
}
else {
dPrinter = new d:ConsolePrinter(io:stderr);
}
foreach string filename in filenames {
var [basename, ext] = basenameExtension(filename);
if ext == SOURCE_EXTENSION {
string outputBasename = check chooseOutputBasename(basename, opts.outDir);
Emitter emitter;
if opts.bir {
emitter = new BirEmitter(outputBasename);
}
else {
emitter = new LlvmEmitter(outputBasename, nbackOptions, opts);
}
CompileError? err = compileBalFile({ filename }, basename, emitter);
if err is err:Internal {
panic error(d:toString(err.detail()), err);
}
else if err is err:Diagnostic {
errorFileCount += 1;
dPrinter.print(err.detail());
}
else {
_ = check err;
}
}
else if ext == TEST_EXTENSION {
check compileBaltFile(filename, basename, opts.outDir ?: check file:parentPath(filename), nbackOptions, opts);
}
else if ext == () {
return error("input filename must have a .bal or .balt extension");
}
else {
return error(d:messageFormat(`unsupported extension ${ext}`));
}
}
check dPrinter.close();
if errorFileCount != 0 {
string files = errorFileCount == 1 ? "file" : "files";
return error(string `compilation of ${errorFileCount} ${files} failed`);
}
}
function printDiagnostic(CompileError? err) returns CompileError? {
if err is err:Diagnostic {
foreach string line in d:format(err.detail()) {
io:fprintln(io:stderr, line);
}
}
return err;
}
// Basename here means filename without extension
function chooseOutputBasename(string sourceBasename, string? outDir = ()) returns string|error {
if outDir == () {
return sourceBasename;
}
else {
return check file:joinPath(outDir, check file:basename(sourceBasename));
}
}
// Note that this converts extension to lower case
function basenameExtension(string filename) returns [string, string?] {
int? extIndex = filename.lastIndexOf(".");
if extIndex is int {
return [filename.substring(0, extIndex), filename.substring(extIndex).toLowerAscii()];
}
return [filename, ()];
}