Skip to content

Commit d33b001

Browse files
CST: Add initial support for types (#231)
This PR adds initial support for serializing types as part of the CST. This includes serializing type references, singleton strings and booleans, types wrapped in parentheses (type group) and typeof. We also serialize type alias statements (for now, excluding generics. We will introduce generic declarations in a follow up commit)
1 parent e7f5fb6 commit d33b001

File tree

6 files changed

+333
-10
lines changed

6 files changed

+333
-10
lines changed

batteries/syntax/ast_types.luau

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,15 @@ export type AstStatLocalFunction = {
281281
body: AstFunctionBody,
282282
}
283283

284+
export type AstStatTypeAlias = {
285+
tag: "typealias",
286+
["export"]: Token<"export">?,
287+
typeToken: Token<"type">,
288+
name: Token,
289+
equals: Token<"=">,
290+
type: AstType,
291+
}
292+
284293
export type AstStat =
285294
| AstStatBlock
286295
| AstStatIf
@@ -297,5 +306,43 @@ export type AstStat =
297306
| AstStatCompoundAssign
298307
| AstStatFunction
299308
| AstStatLocalFunction
309+
| AstStatTypeAlias
310+
311+
export type AstTypeReference = {
312+
tag: "reference",
313+
prefix: Token<string>?,
314+
prefixPoint: Token<".">?,
315+
name: Token<string>,
316+
openParameters: Token<"<">?,
317+
parameters: Punctuated<AstType>?,
318+
closeParameters: Token<">">?,
319+
}
320+
321+
export type AstTypeSingletonBool = Token<"true" | "false"> & {
322+
tag: "boolean",
323+
value: boolean,
324+
}
325+
326+
export type AstTypeSingletonString = Token<string> & {
327+
tag: "string",
328+
quoteStyle: "single" | "double",
329+
}
330+
331+
export type AstTypeTypeof = {
332+
tag: "typeof",
333+
typeof: Token<"typeof">,
334+
openParens: Token<"(">,
335+
expr: AstExpr,
336+
closeParens: Token<")">,
337+
}
338+
339+
export type AstTypeGroup = {
340+
tag: "group",
341+
openParens: Token<"(">,
342+
type: AstType,
343+
closeParens: Token<">">,
344+
}
345+
346+
export type AstType = | AstTypeReference | AstTypeSingletonBool | AstTypeSingletonString | AstTypeTypeof | AstTypeGroup
300347

301348
return {}

batteries/syntax/printer.luau

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ local function printBlock(block: T.AstStatBlock): string
6161
return false
6262
end
6363

64+
printer.visitTypeString = function(node: T.AstTypeSingletonString)
65+
result ..= printString(node)
66+
return false
67+
end
68+
6469
visitor.visitBlock(block, printer)
6570

6671
return result

batteries/syntax/visitor.luau

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type Visitor = {
1515
visitCompoundAssign: (T.AstStatCompoundAssign) -> boolean,
1616
visitFunction: (T.AstStatFunction) -> boolean,
1717
visitLocalFunction: (T.AstStatLocalFunction) -> boolean,
18+
visitTypeAlias: (T.AstStatTypeAlias) -> boolean,
1819

1920
visitLocalReference: (T.AstExprLocal) -> boolean,
2021
visitGlobal: (T.AstExprGlobal) -> boolean,
@@ -28,6 +29,12 @@ type Visitor = {
2829
visitIndexExpr: (T.AstExprIndexExpr) -> boolean,
2930
visitGroup: (T.AstExprGroup) -> boolean,
3031

32+
visitTypeReference: (T.AstTypeReference) -> boolean,
33+
visitTypeBoolean: (T.AstTypeSingletonBool) -> boolean,
34+
visitTypeString: (T.AstTypeSingletonString) -> boolean,
35+
visitTypeTypeof: (T.AstTypeTypeof) -> boolean,
36+
visitTypeGroup: (T.AstTypeGroup) -> boolean,
37+
3138
visitToken: (T.Token) -> boolean,
3239
visitNil: (T.AstExprConstantNil) -> boolean,
3340
visitString: (T.AstExprConstantString) -> boolean,
@@ -54,6 +61,7 @@ local defaultVisitor: Visitor = {
5461
visitCompoundAssign = alwaysVisit :: any,
5562
visitFunction = alwaysVisit :: any,
5663
visitLocalFunction = alwaysVisit :: any,
64+
visitTypeAlias = alwaysVisit :: any,
5765

5866
visitLocalReference = alwaysVisit :: any,
5967
visitGlobal = alwaysVisit :: any,
@@ -67,6 +75,12 @@ local defaultVisitor: Visitor = {
6775
visitIndexExpr = alwaysVisit :: any,
6876
visitGroup = alwaysVisit :: any,
6977

78+
visitTypeReference = alwaysVisit :: any,
79+
visitTypeBoolean = alwaysVisit :: any,
80+
visitTypeString = alwaysVisit :: any,
81+
visitTypeTypeof = alwaysVisit :: any,
82+
visitTypeGroup = alwaysVisit :: any,
83+
7084
visitToken = alwaysVisit :: any,
7185
visitNil = alwaysVisit :: any,
7286
visitString = alwaysVisit :: any,
@@ -209,6 +223,18 @@ local function visitCompoundAssign(node: T.AstStatCompoundAssign, visitor: Visit
209223
end
210224
end
211225

226+
local function visitTypeAlias(node: T.AstStatTypeAlias, visitor: Visitor)
227+
if visitor.visitTypeAlias(node) then
228+
if node.export then
229+
visitToken(node.export, visitor)
230+
end
231+
visitToken(node.typeToken, visitor)
232+
visitToken(node.name, visitor)
233+
visitToken(node.equals, visitor)
234+
visitType(node.type, visitor)
235+
end
236+
end
237+
212238
local function visitString(node: T.AstExprConstantString, visitor: Visitor)
213239
if visitor.visitString(node) then
214240
visitor.visitToken(node)
@@ -370,6 +396,56 @@ local function visitGroup(node: T.AstExprGroup, visitor: Visitor)
370396
end
371397
end
372398

399+
local function visitTypeReference(node: T.AstTypeReference, visitor: Visitor)
400+
if visitor.visitTypeReference(node) then
401+
if node.prefix then
402+
visitToken(node.prefix, visitor)
403+
end
404+
if node.prefixPoint then
405+
visitToken(node.prefixPoint, visitor)
406+
end
407+
visitToken(node.name, visitor)
408+
if node.openParameters then
409+
visitToken(node.openParameters, visitor)
410+
end
411+
if node.parameters then
412+
visitPunctuated(node.parameters, visitor, visitType)
413+
end
414+
if node.closeParameters then
415+
visitToken(node.closeParameters, visitor)
416+
end
417+
end
418+
end
419+
420+
local function visitTypeBoolean(node: T.AstTypeSingletonBool, visitor: Visitor)
421+
if visitor.visitTypeBoolean(node) then
422+
visitToken(node, visitor)
423+
end
424+
end
425+
426+
local function visitTypeString(node: T.AstTypeSingletonString, visitor: Visitor)
427+
if visitor.visitTypeString(node) then
428+
visitToken(node, visitor)
429+
end
430+
end
431+
432+
local function visitTypeTypeof(node: T.AstTypeTypeof, visitor: Visitor)
433+
if visitor.visitTypeTypeof(node) then
434+
visitToken(node.typeof, visitor)
435+
visitToken(node.openParens, visitor)
436+
visitExpression(node.expr, visitor)
437+
visitToken(node.closeParens, visitor)
438+
end
439+
end
440+
441+
local function visitTypeGroup(node: T.AstTypeGroup, visitor: Visitor)
442+
if visitor.visitTypeGroup(node) then
443+
visitToken(node.openParens, visitor)
444+
visitType(node.type, visitor)
445+
visitToken(node.closeParens, visitor)
446+
end
447+
end
448+
373449
function visitExpression(expression: T.AstExpr, visitor: Visitor)
374450
if expression.tag == "nil" then
375451
visitNil(expression, visitor)
@@ -437,11 +513,29 @@ function visitStatement(statement: T.AstStat, visitor: Visitor)
437513
visitFunction(statement, visitor)
438514
elseif statement.tag == "localfunction" then
439515
visitLocalFunction(statement, visitor)
516+
elseif statement.tag == "typealias" then
517+
visitTypeAlias(statement, visitor)
440518
else
441519
exhaustiveMatch(statement.tag)
442520
end
443521
end
444522

523+
function visitType(type: T.AstType, visitor: Visitor)
524+
if type.tag == "reference" then
525+
visitTypeReference(type, visitor)
526+
elseif type.tag == "boolean" then
527+
visitTypeBoolean(type, visitor)
528+
elseif type.tag == "string" then
529+
visitTypeString(type, visitor)
530+
elseif type.tag == "typeof" then
531+
visitTypeTypeof(type, visitor)
532+
elseif type.tag == "group" then
533+
visitTypeGroup(type, visitor)
534+
else
535+
exhaustiveMatch(type.tag)
536+
end
537+
end
538+
445539
local function createVisitor()
446540
return table.clone(defaultVisitor)
447541
end

0 commit comments

Comments
 (0)