77
88import OrderedCollections
99
10+ /// A type, these are not just the types define in the tables
11+ /// but rather any value or function that can exist within
12+ /// an expression/statement.
1013public enum Type : Equatable , CustomStringConvertible , Sendable {
14+ /// A named type, these are the values defined in the columns.
1115 case nominal( Substring )
16+ /// A placeholder for a type that needs to be solved for
1217 case `var`( TypeVariable )
18+ /// A function
1319 indirect case fn( params: [ Type ] , ret: Type )
20+ /// A row is a value from a `SELECT` statement or a group `(?, ?, ?)`
1421 case row( Row )
22+ /// A type that might be null.
1523 indirect case optional( Type )
24+ /// A type that has been aliased. These are not in SQL by default
25+ /// but are from the layer on top that we are adding so a user
26+ /// can replace a `INTEGER` with a `Bool`
1627 indirect case alias( Type , Substring )
1728 /// There was an error somewhere in the analysis. We can just return
1829 /// an `error` type and continue the analysis. So if the user makes up
@@ -31,7 +42,10 @@ public enum Type: Equatable, CustomStringConvertible, Sendable {
3142 /// a FROM or JOIN. Unnamed would be from a subquery or
3243 /// a row expression `(?, ?, ?)`.
3344 public enum Row : Equatable , Sendable , ExpressibleByArrayLiteral {
45+ /// A row that has names for each value
3446 case named( OrderedDictionary < Substring , Type > )
47+ /// A row that does not have names. These can come from
48+ /// using `VALUES (1, 2, 3)`.
3549 case unnamed( [ Type ] )
3650 /// This is a special row that we don't know the inner types of.
3751 /// It assumes that all types in it are the same type and of an
@@ -157,6 +171,30 @@ public enum Type: Equatable, CustomStringConvertible, Sendable {
157171 case ( . error, _) , ( _, . error) :
158172 // Already had an upstream error so no need to emit any more diagnostics
159173 return [ : ]
174+ case let ( . var( tv1) , . var( tv2) ) :
175+ // Unify to type variables.
176+ // We need to prioritize what gets substituded for what
177+ // by its kind.
178+ // So if we get an `integer` and `float`, we want to promote
179+ // the `integer` to a `float`, so we sub the int for the float
180+ switch ( tv1. kind, tv2. kind) {
181+ case ( . general, _) :
182+ // General can always be substitued out
183+ return [ tv1: other]
184+ case ( _, . general) :
185+ // General can always be substitued out
186+ return [ tv2: self ]
187+ case ( . float, . integer) :
188+ // self: float, other: int
189+ // substitute other for self
190+ return [ tv2: self ]
191+ case ( . integer, . float) :
192+ // self: int, other: float
193+ // substitute self for other
194+ return [ tv1: other]
195+ default :
196+ return [ tv1: other]
197+ }
160198 case let ( . var( tv) , ty) :
161199 return [ tv: ty]
162200 case let ( ty, . var( tv) ) :
@@ -167,7 +205,7 @@ public enum Type: Equatable, CustomStringConvertible, Sendable {
167205 return [ : ]
168206 case ( . nominal, . nominal) :
169207 guard self != other else { return [ : ] }
170- diagnostics. add ( . init ( " Unable to unify types ' \( self ) ' and ' \( other) ' " , at: range) )
208+ diagnostics. add ( . unableToUnify ( self , with : other, at: range) )
171209 return [ : ]
172210 case let ( . optional( t1) , t2) :
173211 return t1. unify ( with: t2, at: range, diagnostics: & diagnostics)
@@ -187,22 +225,22 @@ public enum Type: Equatable, CustomStringConvertible, Sendable {
187225 if row. count == 1 , let first = row. first {
188226 return first. unify ( with: t, at: range, diagnostics: & diagnostics)
189227 } else {
190- diagnostics. add ( . init ( " Unable to unify types ' \( self ) ' and ' \( other) ' " , at: range) )
228+ diagnostics. add ( . unableToUnify ( self , with : other, at: range) )
191229 return [ : ]
192230 }
193231 case let ( t, . row( row) ) :
194232 if row. count == 1 , let first = row. first {
195233 return first. unify ( with: t, at: range, diagnostics: & diagnostics)
196234 } else {
197- diagnostics. add ( . init ( " Unable to unify types ' \( self ) ' and ' \( other) ' " , at: range) )
235+ diagnostics. add ( . unableToUnify ( self , with : other, at: range) )
198236 return [ : ]
199237 }
200- case let ( . alias( t1, a ) , t2) :
238+ case let ( . alias( t1, _ ) , t2) :
201239 return t1. unify ( with: t2, at: range, diagnostics: & diagnostics)
202- case let ( t1, . alias( t2, a ) ) :
240+ case let ( t1, . alias( t2, _ ) ) :
203241 return t2. unify ( with: t1, at: range, diagnostics: & diagnostics)
204242 default :
205- diagnostics. add ( . init ( " Unable to unify types ' \( self ) ' and ' \( other) ' " , at: range) )
243+ diagnostics. add ( . unableToUnify ( self , with : other, at: range) )
206244 return [ : ]
207245 }
208246 }
@@ -247,39 +285,73 @@ public enum Type: Equatable, CustomStringConvertible, Sendable {
247285
248286 return sub
249287 }
288+
289+ private func validateCanUnify(
290+ with tvKind: TypeVariable . Kind ,
291+ diagnostics: inout Diagnostics ,
292+ at range: Range < Substring . Index >
293+ ) {
294+ switch tvKind {
295+ case . general:
296+ return
297+ case . integer:
298+ switch self {
299+ case . int, . integer, . real: return
300+ default : diagnostics. add ( . unableToUnify( self , with: . integer, at: range) )
301+ }
302+ case . float:
303+ switch self {
304+ case . int, . integer, . real: return
305+ default : diagnostics. add ( . unableToUnify( self , with: . real, at: range) )
306+ }
307+ }
308+ }
250309}
251310
311+ /// A type variable is a type placeholder for an expression who's type we need to solve.
252312public struct TypeVariable : Hashable , CustomStringConvertible , ExpressibleByIntegerLiteral , Sendable {
313+ /// The unique integer associated with the variable.
314+ /// These are just incremented as they are created.
253315 let n : Int
316+ /// What kind or group this type variable belongs too.
317+ let kind : Kind
254318
255- init ( _ n: Int ) {
319+ /// There are different type of type variables.
320+ /// Each are spawned from different usages.
321+ enum Kind {
322+ /// `integer` is any type variable from an integer literal e.g. `0`
323+ case integer
324+ /// `float` is any type variable from an float literal e.g. `0.0`
325+ case float
326+ /// `general` is any type variable that does not fall into the above
327+ case general
328+ }
329+
330+ init ( _ n: Int , kind: Kind ) {
256331 self . n = n
332+ self . kind = kind
257333 }
258334
259335 public init ( integerLiteral value: Int ) {
260336 self . n = value
337+ self . kind = . general
261338 }
262339
263- public var description : String {
264- return " τ \( n) "
340+ /// The type to use for an expression if no concrete type was
341+ /// found in the solution.
342+ ///
343+ /// e.g. `1 + 1`, each literal is not bound to a concrete type
344+ /// like a column. So each would still be a variable after the
345+ /// substitution is applied. In which a default is needed.
346+ var defaultType : Type {
347+ return switch kind {
348+ case . general: . any
349+ case . integer: . integer
350+ case . float: . real
351+ }
265352 }
266- }
267-
268- // TODO: Need a better name for this. TypeConstraints vs Constraints is confusing
269- typealias Constraints = [ TypeVariable : TypeConstraints ]
270-
271- /// Any type constraints that may exist on the type variable.
272- /// SQL is not a full language and users cannot create their
273- /// own interfaces so a simple option set will do since it is
274- /// a finite number.
275- struct TypeConstraints : OptionSet , Hashable {
276- let rawValue : UInt8
277353
278- static let numeric = TypeConstraints ( rawValue: 1 << 0 )
279- }
280-
281- extension Constraints {
282- func merging( _ other: Constraints ) -> Constraints {
283- return merging ( other, uniquingKeysWith: { $0. union ( $1) } )
354+ public var description : String {
355+ return " τ \( n) "
284356 }
285357}
0 commit comments