-
Notifications
You must be signed in to change notification settings - Fork 53
/
tlc
executable file
·154 lines (134 loc) · 3.74 KB
/
tlc
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env lua
local tlast = require "typedlua.tlast"
local tlparser = require "typedlua.tlparser"
local tlchecker = require "typedlua.tlchecker"
local tlcode = require "typedlua.tlcode"
local VERSION = "scm"
local PROGNAME = "tlc"
local OUTPUT
local DUMPAST = false
local PRINTAST = false
local COLOR = false
local STRICT = false
local WARNINGS = false
local INTEGER = false
if _VERSION == "Lua 5.3" then INTEGER = true end
local progname = PROGNAME
local USAGE = [[
usage: %s [options] [filename]
Available options are:
-h print this help
-d name dump the AST (after typechecking) to file 'name'
-o name output to file 'name' (default is '%s')
-c ansi colors on
-p print the AST in Metalua format (before typechecking)
-s strict mode on
-v print current version
-w warnings on (consistent-subtyping, unused locals)
]]
local function usage (msg)
if msg then
io.stderr:write(string.format("%s: %s\n", progname, msg))
end
io.stderr:write(string.format(USAGE, progname, "tlc.lua"))
os.exit(1)
end
local function doargs ()
local i = 1
while i <= #arg do
if string.find(arg[i], "^-") == nil then
return i
else
for j = 2, #arg[i] do
local option_char = arg[i]:sub(j, j)
if option_char == "d" then
if j ~= #arg[i] then
usage("'-d' appears last in option block")
end
i = i + 1
if arg[i] == nil or string.find(arg[i], "^-") then
usage("'-d' needs argument")
else
DUMPAST = arg[i]
break
end
elseif option_char == "h" then
usage()
elseif option_char == "o" then
if j ~= #arg[i] then
usage("'-o' appears last in option block")
end
i = i + 1
if arg[i] == nil or string.find(arg[i], "^-") then
usage("'-o' needs argument")
else
OUTPUT = arg[i]
break
end
elseif option_char == "c" then
COLOR = true
elseif option_char == "p" then
PRINTAST = true
elseif option_char == "s" then
STRICT = true
elseif option_char == "v" then
io.write(string.format("Typed Lua %s\n", VERSION))
os.exit(0)
elseif option_char == "w" then
WARNINGS = true
else
usage(string.format("'%s' unknown option", arg[i]))
end
end
end
i = i + 1
end
return i
end
local function getcontents (filename)
local file = assert(io.open(filename, "r"))
local contents = file:read("*a")
file:close()
return contents
end
local function setcontents (contents, filename)
local file = assert(io.open(filename, "w"))
file:write(contents)
file:write("\n")
file:close()
end
local i = doargs()
local filename = arg[i]
if not filename then
usage("no input file given")
end
if i < #arg then
io.stderr:write(string.format("%s: Ignored extra arguments (%s)\n", progname, table.concat(arg, ", ", i+1, #arg)))
end
if not OUTPUT then
local name_part = filename:match("(.*)[.]tl$") or "tlc"
OUTPUT = name_part .. ".lua"
end
local subject = getcontents(filename)
local ast, error_msg = tlparser.parse(subject, filename, STRICT, INTEGER)
if not ast then
print(error_msg)
os.exit(1)
end
if PRINTAST then
print(tlast.tostring(ast))
end
error_msg = tlchecker.typecheck(ast, subject, filename, STRICT, INTEGER, COLOR)
local status
error_msg, status = tlchecker.error_msgs(error_msg, WARNINGS, COLOR, true)
if error_msg then print(error_msg) end
if status == 0 then
local generated_code = tlcode.generate(ast)
setcontents(generated_code, OUTPUT)
end
if DUMPAST then
local out = assert(io.open(DUMPAST, "w+"))
out:write("return ")
tlast.dump(out, ast)
end
os.exit(status)