Skip to content

Commit 3497a7e

Browse files
authored
Merge pull request #653 from igrvlhlb/typealias-type
Add the `types.T.Alias` type
2 parents 5840882 + bc745f5 commit 3497a7e

File tree

6 files changed

+414
-123
lines changed

6 files changed

+414
-123
lines changed

spec/typechecker_spec.lua

Lines changed: 143 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,27 +92,27 @@ describe("Module", function()
9292
assert_error([[
9393
function m.f() end
9494
function m.f() end
95-
]], "multiple definitions for module field 'f'")
95+
]], "the module field 'f' is being shadowed")
9696
end)
9797

9898
it("forbids repeated exported names (function / variable)", function()
9999
assert_error([[
100100
function m.f() end
101101
m.f = 1
102-
]], "multiple definitions for module field 'f'")
102+
]], "the module field 'f' is being shadowed")
103103
end)
104104

105105
it("forbids repeated exported names (variable / variable)", function()
106106
assert_error([[
107107
m.x = 10
108108
m.x = 20
109-
]], "multiple definitions for module field 'x'")
109+
]], "the module field 'x' is being shadowed")
110110
end)
111111

112112
it("forbids repeated exported names (in multiple assignment)", function()
113113
assert_error([[
114114
m.x, m.x = 10, 20
115-
]], "multiple definitions for module field 'x'")
115+
]], "the module field 'x' is being shadowed")
116116
end)
117117

118118
it("ensures that exported variables are not in scope in their initializers", function()
@@ -142,6 +142,37 @@ describe("Typealias", function()
142142
]], "'t' is not a type")
143143
end)
144144

145+
it("must not be shadowed by other typealias names", function()
146+
assert_error([[
147+
typealias point = {x: integer, y: integer}
148+
typealias point = {x: float, y: float}
149+
]], "the type 'point' is being shadowed")
150+
end)
151+
152+
it("must not be shadowed by record names", function()
153+
assert_error([[
154+
typealias point = {x: float, y: float}
155+
record point
156+
x: integer
157+
y: integer
158+
end
159+
]], "the type 'point' is being shadowed")
160+
end)
161+
162+
it("must not be shadowed by module field names", function()
163+
assert_error([[
164+
typealias x = integer
165+
m.x = 10
166+
]], "the type 'x' is being shadowed")
167+
end)
168+
169+
it("must not be shadowed by function names", function()
170+
assert_error([[
171+
typealias f = integer
172+
function m.f() end
173+
]], "the type 'f' is being shadowed")
174+
end)
175+
145176
end)
146177

147178
describe("Record declaration", function()
@@ -155,6 +186,49 @@ describe("Record declaration", function()
155186
]], "duplicate field name 'x' in record type")
156187
end)
157188

189+
it("must not be shadowed by other record names", function()
190+
assert_error([[
191+
record Point
192+
x: integer
193+
y: integer
194+
end
195+
record Point
196+
x: float
197+
y: float
198+
end
199+
]], "the type 'Point' is being shadowed")
200+
end)
201+
202+
it("must not be shadowed by typealias names", function()
203+
assert_error([[
204+
record Point
205+
x: integer
206+
y: integer
207+
end
208+
typealias Point = {x: float, y: float}
209+
]], "the type 'Point' is being shadowed")
210+
end)
211+
212+
it("must not be shadowed by module field names", function()
213+
assert_error([[
214+
record P
215+
x: integer
216+
y: integer
217+
end
218+
m.P = 10
219+
]], "the type 'P' is being shadowed")
220+
end)
221+
222+
it("must not be shadowed by function names", function()
223+
assert_error([[
224+
record P
225+
x: integer
226+
y: integer
227+
end
228+
function m.P() end
229+
]], "the type 'P' is being shadowed")
230+
end)
231+
158232
end)
159233

160234
describe("Function declaration", function()
@@ -195,6 +269,71 @@ describe("Function declaration", function()
195269
]], "function 'f' was not forward declared")
196270
end)
197271

272+
it("must not be shadowed by typealias names", function()
273+
assert_error([[
274+
function m.f() end
275+
typealias f = integer
276+
]], "the module field 'f' is being shadowed")
277+
end)
278+
279+
it("must not be shadowed by record names", function()
280+
assert_error([[
281+
function m.f() end
282+
record f
283+
x: integer
284+
y: integer
285+
end
286+
]], "the module field 'f' is being shadowed")
287+
end)
288+
289+
it("must not be shadowed by module field names", function()
290+
assert_error([[
291+
function m.f() end
292+
m.f = 10
293+
]], "the module field 'f' is being shadowed")
294+
end)
295+
296+
it("must not be shadowed by function names", function()
297+
assert_error([[
298+
function m.f() end
299+
function m.f() end
300+
]], "the module field 'f' is being shadowed")
301+
end)
302+
303+
end)
304+
305+
describe("Module fields", function()
306+
307+
it("must not be shadowed by typealias names", function()
308+
assert_error([[
309+
m.x = 10
310+
typealias x = integer
311+
]], "the module field 'x' is being shadowed")
312+
end)
313+
314+
it("must not be shadowed by record names", function()
315+
assert_error([[
316+
m.x = 10
317+
record x
318+
y: integer
319+
end
320+
]], "the module field 'x' is being shadowed")
321+
end)
322+
323+
it("must not be shadowed by function names", function()
324+
assert_error([[
325+
m.f = 10
326+
function m.f() end
327+
]], "the module field 'f' is being shadowed")
328+
end)
329+
330+
it("must not be shadowed by module field names", function()
331+
assert_error([[
332+
m.x = 10
333+
m.x = 20
334+
]], "the module field 'x' is being shadowed")
335+
end)
336+
198337
end)
199338

200339
--

spec/types_spec.lua

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,21 @@ describe("Pallene types", function()
119119
local t2 = types.T.Record("P", {}, {}, false)
120120
assert.falsy(types.equals(t1, t2))
121121
end)
122+
123+
it("is true for similar type aliases", function()
124+
local ta1 = types.T.Alias("A", types.T.Integer)
125+
local ta2 = types.T.Alias("B", types.T.Integer)
126+
assert.truthy(types.equals(ta1, ta2))
127+
end)
128+
129+
it("should expand type aliases", function()
130+
local ta = types.T.Alias("A", types.T.Integer)
131+
132+
assert.truthy(types.equals(
133+
ta,
134+
types.T.Integer
135+
))
136+
end)
122137
end)
123138

124139
describe("consistency", function()
@@ -161,5 +176,50 @@ describe("Pallene types", function()
161176
types.T.Function({types.T.Integer},{types.T.Integer})
162177
))
163178
end)
179+
180+
it("should be true for type aliases whose types are consistent", function()
181+
local ta1 = types.T.Alias("A", types.T.Any)
182+
local ta2 = types.T.Alias("B", types.T.Integer)
183+
local ta3 = types.T.Alias("C", types.T.String)
184+
185+
assert.truthy(types.consistent(ta1, ta2))
186+
assert.truthy(types.consistent(ta1, ta3))
187+
assert.falsy(types.consistent(ta2, ta3))
188+
end)
189+
190+
it("should expand type aliases", function()
191+
local ta = types.T.Alias("A", types.T.Integer)
192+
193+
assert.truthy(types.consistent(
194+
ta,
195+
types.T.Integer
196+
))
197+
198+
assert.falsy(types.consistent(
199+
ta,
200+
types.T.String
201+
))
202+
end)
164203
end)
204+
205+
describe("type aliases", function()
206+
207+
it("should recursively expand type aliases", function()
208+
local ta1 = types.T.Alias("A", types.T.Integer)
209+
local ta2 = types.T.Alias("B", ta1)
210+
local ta3 = types.T.Alias("C", ta2)
211+
212+
assert.truthy(types.expand_typealias(ta3) == types.T.Integer)
213+
end)
214+
215+
it("should be considered equal to the expanded type", function()
216+
local ta1 = types.T.Alias("A", types.T.Integer)
217+
218+
assert.truthy(types.equals(
219+
ta1,
220+
types.T.Integer
221+
))
222+
end)
223+
end)
224+
165225
end)

src/pallene/to_ir.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ end
4747

4848
function to_ir.convert(prog_ast)
4949
assert(prog_ast._tag == "ast.Program.Program")
50+
local alias_free_prog_ast = util.expand_type_aliases(prog_ast)
5051
local ok, ret = trycatch.pcall(function()
51-
return ToIR.new():convert_toplevel(prog_ast.tls)
52+
return ToIR.new():convert_toplevel(alias_free_prog_ast.tls)
5253
end)
5354

5455
if not ok then

0 commit comments

Comments
 (0)