Skip to content

Commit

Permalink
AST: Allow other type decls but struct
Browse files Browse the repository at this point in the history
E.g. classes or enums. Misnamed `TypeDefinition`,
`TypeDeclaration` would probably be the better
name, but whatever :-)
  • Loading branch information
helje5 committed Nov 4, 2024
1 parent cc4b9c2 commit 0e4b3c1
Show file tree
Hide file tree
Showing 16 changed files with 136 additions and 82 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Created by Helge Heß.
// Copyright © 2022 ZeeZide GmbH.
// Copyright © 2022-2024 ZeeZide GmbH.
//

public extension CodeGenerator {
Expand Down Expand Up @@ -42,9 +42,9 @@ public extension CodeGenerator {
}

indent {
for structure in value.structures {
for typeDefinition in value.typeDefinitions {
writeln()
generateStruct(structure, omitPublic: value.public)
generateTypeDefinition(typeDefinition, omitPublic: value.public)
}

for function in value.typeFunctions {
Expand Down
47 changes: 40 additions & 7 deletions Plugins/Libraries/LighterCodeGenAST/Generation/GenStructures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public extension CodeGenerator {

/// public static let schema = Schema()
/// public var personId : Int
func generateInstanceVariable(_ value : Struct.InstanceVariable,
func generateInstanceVariable(_ value : TypeDefinition.InstanceVariable,
`static` : Bool = false,
omitPublic : Bool = false)
{
Expand Down Expand Up @@ -77,7 +77,34 @@ public extension CodeGenerator {
writePlain()
}
}


/**
* ```swift
* public struct Person: SQLKeyedTableRecord, Identifiable {
*
* public static let schema = Schema()
*
* @inlinable
* public var id : Int { personId }
*
* public var personId : Int
* public var lastname : String
* public var firstname : String?
*
* @inlinable
* public init(personId: Int = 0, lastname: String, firstname: String? = nil) {
* self.personId = personId
* self.lastname = lastname
* self.firstname = firstname
* }
* }
* ```
*/
func generateStruct(_ value: TypeDefinition, omitPublic: Bool = false) {
assert(value.kind == .struct)
generateTypeDefinition(value, omitPublic: omitPublic)
}

/**
* ```swift
* public struct Person: SQLKeyedTableRecord, Identifiable {
Expand All @@ -100,7 +127,8 @@ public extension CodeGenerator {
* }
* ```
*/
func generateStruct(_ value: Struct, omitPublic: Bool = false) {
func generateTypeDefinition(_ value: TypeDefinition, omitPublic: Bool = false)
{
if !source.isEmpty { appendEOLIfMissing() }

if let comment = value.comment {
Expand All @@ -114,7 +142,11 @@ public extension CodeGenerator {
do { // header
appendIndent()
if value.public && !omitPublic { append("public ") }
append("struct ")
switch value.kind {
case .struct : append("struct ")
case .class : append("class ")
case .enum : append("enum ")
}
append(tickedWhenReserved(value.name))

if !value.conformances.isEmpty {
Expand All @@ -129,12 +161,13 @@ public extension CodeGenerator {

if !value.typeAliases.isEmpty { writeln() }
for ( name, ref ) in value.typeAliases {
writeln("\(pubPrefix)typealias \(tickedWhenReserved(name))\(configuration.propertyValueSeparator)\(string(for: ref))")
writeln("\(pubPrefix)typealias \(tickedWhenReserved(name))"
+ "\(configuration.propertyValueSeparator)\(string(for: ref))")
}

for structure in value.structures {
for nestedType in value.nestedTypes {
writeln()
generateStruct(structure)
generateStruct(nestedType)
}

// Later: I'd really like to vertically align the colors and equals.
Expand Down
6 changes: 3 additions & 3 deletions Plugins/Libraries/LighterCodeGenAST/Generation/GenUnit.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Created by Helge Heß.
// Copyright © 2022 ZeeZide GmbH.
// Copyright © 2022-2024 ZeeZide GmbH.
//

public extension CodeGenerator {
Expand All @@ -18,9 +18,9 @@ public extension CodeGenerator {
generateFunctionDefinition(function)
}

for structure in unit.structures {
for typeDefinition in unit.typeDefinitions {
writeln()
generateStruct(structure)
generateTypeDefinition(typeDefinition)
}

for ext in unit.extensions {
Expand Down
30 changes: 20 additions & 10 deletions Plugins/Libraries/LighterCodeGenAST/Nodes/CompilationUnit.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Created by Helge Heß.
// Copyright © 2022 ZeeZide GmbH.
// Copyright © 2022-2024 ZeeZide GmbH.
//

/**
Expand All @@ -20,25 +20,35 @@ public struct CompilationUnit {
public var reexports : [ String ] = []

/// The structures that are part of the unit.
public var structures : [ Struct ]
public var typeDefinitions : [ TypeDefinition ]
/// The functions that are part of the unit.
public var functions : [ FunctionDefinition ]
public var functions : [ FunctionDefinition ]
/// The extensions that are part of the unit.
public var extensions : [ Extension ]
public var extensions : [ Extension ]

/// Initialize a new CompilationUnit, only name and extensions are required.
public init(name : String,
imports : [ String ] = [],
structures : [ Struct ] = [],
functions : [ FunctionDefinition ] = [],
extensions : [ Extension ] = [])
public init(name : String,
imports : [ String ] = [],
typeDefinitions : [ TypeDefinition ] = [],
functions : [ FunctionDefinition ] = [],
extensions : [ Extension ] = [])
{
self.name = name
self.imports = imports
self.structures = structures
self.typeDefinitions = typeDefinitions
self.functions = functions
self.extensions = extensions
}
/// Initialize a new CompilationUnit, only name and extensions are required.
public init(name : String,
imports : [ String ] = [],
structures : [ TypeDefinition ], // legacy compat
functions : [ FunctionDefinition ] = [],
extensions : [ Extension ] = [])
{
self.init(name: name, imports: imports, typeDefinitions: structures,
functions: functions, extensions: extensions)
}
}


Expand Down
9 changes: 5 additions & 4 deletions Plugins/Libraries/LighterCodeGenAST/Nodes/Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public struct Extension {
// MARK: - Types

/// The structures added to the ``extendedType``.
public var structures : [ Struct ]
public var typeDefinitions : [ TypeDefinition ]

// MARK: - Functions

Expand All @@ -40,24 +40,25 @@ public struct Extension {
public init(extendedType : TypeReference,
`public` : Bool = true,
genericConstraints : [ GenericConstraint ] = [],
structures : [ Struct ] = [],
typeDefinitions : [ TypeDefinition ] = [],
typeFunctions : [ FunctionDefinition ] = [],
functions : [ FunctionDefinition ] = [],
minimumSwiftVersion : ( major: Int, minor: Int )? = nil,
requiredImports : [ String ] = [])
{
self.public = `public`
self.extendedType = extendedType
self.structures = structures
self.typeDefinitions = typeDefinitions
self.typeFunctions = typeFunctions
self.functions = functions
self.genericConstraints = genericConstraints
self.minimumSwiftVersion = minimumSwiftVersion
self.requiredImports = requiredImports
}

@inlinable
public var isEmpty : Bool {
functions.isEmpty && structures.isEmpty && typeFunctions.isEmpty
functions.isEmpty && typeDefinitions.isEmpty && typeFunctions.isEmpty
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
/**
* An AST node representing a Swift structure type.
*/
public struct Struct {
public struct TypeDefinition {

public enum Kind: Int, Sendable {
case `struct`, `class`, `enum`
}

/**
* An instance variable of a ``Struct``.
Expand Down Expand Up @@ -64,13 +68,15 @@ public struct Struct {
/// The types the structure conforms to, e.g. `SQLTableRecord`.
public var conformances : [ TypeReference ]

public var kind : Kind

// MARK: - Types

/// A set of type aliases that should be declare in the structure,
/// e.g. `typealias RecordType = Person`.
public var typeAliases : [ ( name: String, type: TypeReference ) ]
/// A set of structures nested in this structure.
public var structures : [ Struct ]
public var nestedTypes : [ TypeDefinition ]

// MARK: - Variables

Expand All @@ -94,11 +100,12 @@ public struct Struct {
/// Intialize a new struct AST node. Only the `name` is required.
public init(dynamicMemberLookup : Bool = false,
public : Bool = true,
kind : Kind,
name : String,
conformances : [ TypeReference ] = [],
typeAliases : [ ( name: String, type: TypeReference ) ]
= [],
structures : [ Struct ] = [],
nestedTypes : [ TypeDefinition ] = [],
typeVariables : [ InstanceVariable ] = [],
variables : [ InstanceVariable ] = [],
computedTypeProperties : [ ComputedPropertyDefinition ] = [],
Expand All @@ -109,10 +116,11 @@ public struct Struct {
{
self.dynamicMemberLookup = dynamicMemberLookup
self.public = `public`
self.kind = kind
self.name = name
self.conformances = conformances
self.typeAliases = typeAliases
self.structures = structures
self.nestedTypes = nestedTypes
self.typeVariables = typeVariables
self.variables = variables
self.computedTypeProperties = computedTypeProperties
Expand All @@ -130,7 +138,7 @@ public struct Struct {

// MARK: - Convenience

public extension Struct.InstanceVariable {
public extension TypeDefinition.InstanceVariable {

/// Initialize a new instance variable node for a `let`.
static func `let`(public: Bool = true, _ name: String,
Expand Down Expand Up @@ -176,5 +184,5 @@ public extension Struct.InstanceVariable {
}

#if swift(>=5.5)
extension Struct : Sendable {}
extension TypeDefinition : Sendable {}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ extension EnlighterASTGenerator {

// Database Structure

unit.structures.append(
unit.typeDefinitions.append(
generateDatabaseStructure(moduleFileName: moduleFileName))


// Entity Structures

if !options.nestRecordTypesInDatabase {
unit.structures += database.entities.map {
unit.typeDefinitions += database.entities.map {
generateRecordStructure(for: $0)
}
}
Expand All @@ -78,7 +78,7 @@ extension EnlighterASTGenerator {
unit.extensions += database.entities.map { entity in
Extension(
extendedType: globalTypeRef(of: entity),
structures: [ generateSchemaStructure(for: entity) ],
typeDefinitions: [ generateSchemaStructure(for: entity) ],
functions: [
generateRecordStatementInit(for: entity),
generateRecordStatementBind(for: entity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import LighterCodeGenAST
extension EnlighterASTGenerator {

public func generateDatabaseStructure(moduleFileName: String? = nil)
-> Struct
-> TypeDefinition
{
let typeAliases = calculateClassTypeAliases()
var structures = [ Struct ]()
var typeVariables = [ Struct.InstanceVariable ]()
var variables = [ Struct.InstanceVariable ]()
var computedTypeProperties = [ ComputedPropertyDefinition ]()
var typeFunctions = [ FunctionDefinition ]()
var functions = [ FunctionDefinition ]()
var structures = [ TypeDefinition ]()
var typeVariables = [ TypeDefinition.InstanceVariable ]()
var variables = [ TypeDefinition.InstanceVariable ]()
var computedTypeProperties = [ ComputedPropertyDefinition ]()
var typeFunctions = [ FunctionDefinition ]()
var functions = [ FunctionDefinition ]()

if options.useLighter, let filename = moduleFileName,
options.allowFoundation // needs `Bundle`
Expand Down Expand Up @@ -161,13 +161,14 @@ extension EnlighterASTGenerator {

// Assemble the structure

return Struct(
return TypeDefinition(
dynamicMemberLookup : options.useLighter,
public : options.public,
kind : .struct,
name : database.name,
conformances : dbTypeConformances,
typeAliases : typeAliases,
structures : structures,
nestedTypes : structures,
typeVariables : typeVariables,
variables : variables,
computedTypeProperties : computedTypeProperties,
Expand Down Expand Up @@ -554,11 +555,12 @@ extension EnlighterASTGenerator {
public let addresses = Address.self
}
*/
fileprivate func generateRecordTypesStruct(useAlias suffix: String?) -> Struct
fileprivate func generateRecordTypesStruct(useAlias suffix: String?)
-> TypeDefinition
{
let firstEntity = database.entities.first ?? .init(name: "NoTypes")
return Struct(
public: options.public,
return TypeDefinition(
public: options.public, kind: .struct,
name: api.recordTypeLookupTarget,
conformances: [ .name("Swift.Sendable") ],
variables: database.entities.map {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ extension EnlighterASTGenerator {
* ```
*/
func generateModuleSingleton(name propertyName: String = "module",
for filename: String) -> Struct.InstanceVariable
for filename: String)
-> TypeDefinition.InstanceVariable
{
let name : Expression
let ext : Expression
Expand Down Expand Up @@ -191,9 +192,9 @@ extension EnlighterASTGenerator {
/**
* Generate the SQLError struct, required when not used w/ Lighter.
*/
func generateSQLError(name: String = "SQLError") -> Struct {
return Struct(
public: options.public, name: name,
func generateSQLError(name: String = "SQLError") -> TypeDefinition {
return TypeDefinition(
public: options.public, kind: .struct, name: name,
conformances: [
.name("Swift.Error"), .name("Equatable"), .name("Sendable")
],
Expand Down
Loading

0 comments on commit 0e4b3c1

Please sign in to comment.