forked from pallene-lang/pallene
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pallenec
executable file
·131 lines (109 loc) · 4.01 KB
/
pallenec
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
127
128
129
130
131
#!/usr/bin/env lua
local argparse = require "argparse"
local inspect = require "inspect"
local driver = require "pallene.driver"
local print_ir = require "pallene.print_ir"
local util = require "pallene.util"
local C = require "pallene.C"
--
-- Command-line options
--
local p = argparse("pallenec", "Pallene compiler")
p:argument("source_file", "File to compile")
-- What the compiler should output.
p:mutex(
p:flag("--emit-c", "Generate a .c file instead of an .so file"),
p:flag("--emit-asm", "Generate a .s file instead of an .so file"),
p:flag("--emit-lua", "Generate a .lua file instead of an .so file"),
p:flag("--compile-c", "Compile a .c file generated by --emit-c"),
p:flag("--print-ir", "Print a human-readable version of the program's IR"),
p:option("--dump", "Print the result of an internal compiler pass")
:choices(driver.list_of_compiler_passes)
)
-- Optimization levels for the Pallene and C compiler. (-O0 disables optimizations for both)
-- NOTE: *For C compiler only* this option may be overridden using the CFLAGS environment variable.
p:option("-O", "Optimization level")
:args(1):convert(tonumber)
:choices({"0", "1", "2", "3"})
:default(2)
p:option("-o --output", "Output file path")
local args = p:parse()
local opt_level = args.O
-- For compilation errors that don't happen inside a source file.
-- Inspired by gcc, eg. "gcc: fatal error: no input files".
local compiler_name = arg[0]
local function compile(in_ext, out_ext)
local ok, errs = driver.compile(compiler_name, opt_level, in_ext, out_ext, args.source_file,
args.output)
if not ok then util.abort(table.concat(errs, "\n")) end
end
local inspect_opts = {
process = function(item, path)
local key = path[#path]
if key == inspect.METATABLE then
return nil
elseif type(key) == "string" and (key == "loc" or string.match(key, "_loc$")) then
if args.show_locations then
return item and string.format("%d:%d", item.line, item.col)
else
return nil
end
else
return item
end
end
}
local function print_tokens(lexer)
while true do
local token, err = lexer:next()
if not token then
local loc = lexer:loc()
print(string.format("%02d:%02d ERROR %s", loc.line, loc.col, err))
break
end
if token.name == "EOF" then
break
end
local value
if token.value then
if type(token.value) == "string" then
value = " " .. C.string(token.value)
else
value = " " .. tostring(token.value)
end
else
value = ""
end
print(string.format("%02d:%02d %d-%d %s%s",
token.loc.line, token.loc.col, token.loc.pos, token.end_pos, token.name, value))
end
end
local function dump(filename, stop_after)
local input, err = driver.load_input(filename)
if err then util.abort(err) end
local out, errs = driver.compile_internal(filename, input, stop_after, opt_level)
if not out then
util.abort(table.concat(errs, "\n"))
end
if stop_after == "lexer" then
print_tokens(out)
else
print(inspect(out, inspect_opts))
print(string.format("Exit after %s step", stop_after))
end
end
local function pretty_print_ir(filename)
local input, err = driver.load_input(filename)
if not input then util.abort(err) end
local module, errs = driver.compile_internal(filename, input, "ir")
if not module then util.abort(table.concat(errs, "\n")) end
io.stdout:write(print_ir(module))
end
if args.emit_c then compile("pln", "c")
elseif args.emit_asm then compile("c", "s")
elseif args.compile_c then compile("c" , "so")
elseif args.dump then dump(args.source_file, args.dump)
elseif args.print_ir then pretty_print_ir(args.source_file)
elseif args.emit_lua then compile("pln", "lua")
else compile("pln", "so")
end