Skip to content

Commit f84a9e7

Browse files
committed
Better pragma value
1 parent 13dc950 commit f84a9e7

8 files changed

Lines changed: 103 additions & 30 deletions

File tree

‎Sources/Compiler/Compiler.swift‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ fileprivate struct CompilerWithSource {
8080
var pragmas: PragmaAnalyzer
8181

8282
/// Just performs type checking.
83-
private mutating func typeCheck<S: StmtSyntax>(_ stmt: S, isReadOnly: Bool) -> (Statement, Diagnostics) {
83+
private mutating func typeCheck<S: StmtSyntax>(
84+
_ stmt: S,
85+
isReadOnly: Bool
86+
) -> (Statement, Diagnostics) {
8487
// Calculating the statement signature will type check it.
8588
// We can just ignore the output
8689
var typeChecker = StmtTypeChecker(schema: schema, pragmas: pragmas.featherPragmas)
@@ -178,7 +181,7 @@ extension CompilerWithSource: StmtSyntaxVisitor {
178181
mutating func visit(_ stmt: PragmaStmt) -> (Statement, Diagnostics)? {
179182
pragmas.handle(pragma: stmt)
180183
// TODO: Figure out what to do with these
181-
return (Statement(name: nil, parameters: [:], output: nil, outputCardinality: .single, isReadOnly: true, sanitizedSource: "", syntax: stmt), Diagnostics())
184+
return nil
182185
}
183186

184187
mutating func visit(_ stmt: EmptyStmtSyntax) -> (Statement, Diagnostics)? {

‎Sources/Compiler/Parse/Parsers.swift‎

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,27 +205,27 @@ enum Parsers {
205205
let name = identifier(state: &state)
206206

207207
let isFunctionCall: Bool
208-
let value: ExprSyntax
208+
let value: PragmaStmt.Value?
209209
switch state.current.kind {
210210
case .openParen:
211211
isFunctionCall = true
212212
// The parens could technically get parsed by the `expr` but
213213
// then the expr type would technically be different.
214214
value = parens(state: &state) { state in
215-
expr(state: &state)
215+
pragmaValue(state: &state)
216216
}
217217
case .equal:
218218
isFunctionCall = false
219219
state.skip()
220-
value = expr(state: &state)
220+
value = pragmaValue(state: &state)
221221
default:
222222
state.diagnostics.add(.unexpectedToken(
223223
of: state.current.kind,
224224
expectedAnyOf: .equal, .openParen,
225225
at: state.current.range
226226
))
227227
// Still try to parse the value
228-
value = expr(state: &state)
228+
value = pragmaValue(state: &state)
229229
isFunctionCall = false
230230
}
231231

@@ -239,6 +239,42 @@ enum Parsers {
239239
)
240240
}
241241

242+
/// https://www.sqlite.org/pragma.html
243+
static func pragmaValue(state: inout ParserState) -> PragmaStmt.Value? {
244+
switch state.current.kind {
245+
case .yes:
246+
state.skip()
247+
return .yes
248+
case .no:
249+
state.skip()
250+
return .no
251+
case .true:
252+
state.skip()
253+
return .true
254+
case .false:
255+
state.skip()
256+
return .false
257+
case .int(let value):
258+
let token = state.take()
259+
if value == 0 {
260+
return .zero
261+
} else if value == 1 {
262+
return .one
263+
} else {
264+
state.diagnostics.add(.init("Expected 1 or 0", at: token.range))
265+
return nil
266+
}
267+
case .on:
268+
state.skip()
269+
return .on
270+
case .off:
271+
state.skip()
272+
return .off
273+
default:
274+
return nil
275+
}
276+
}
277+
242278
/// https://www.sqlite.org/syntax/upsert-clause.html
243279
static func upsertClause(
244280
state: inout ParserState
@@ -391,7 +427,7 @@ enum Parsers {
391427
state.consume(.from)
392428
let table = qualifiedTableName(state: &state)
393429
let whereExpr = state.take(if: .where) ? expr(state: &state) : nil
394-
let returningClause = state.take(if: .returning) ? returningClause(state: &state) : nil
430+
let returningClause = state.current.kind == .returning ? returningClause(state: &state) : nil
395431
return DeleteStmtSyntax(
396432
id: state.nextId(),
397433
cte: cte,

‎Sources/Compiler/Parse/Token.swift‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ struct Token {
169169
enum Kind: Hashable {
170170
static let `true`: Kind = .symbol("TRUE")
171171
static let `false`: Kind = .symbol("FALSE")
172+
static let off: Kind = .symbol("OFF")
173+
static let yes: Kind = .symbol("YES")
172174

173175
case symbol(Substring)
174176
case string(Substring)

‎Sources/Compiler/Sema/PragmaAnalyzer.swift‎

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ public struct FeatherPragmas: OptionSet, Sendable {
2222
struct PragmaAnalyzer {
2323
private(set) var featherPragmas: FeatherPragmas
2424
private(set) var diagnostics = Diagnostics()
25-
private var isStaticallyTrue = IsStaticallyTrue(allowOnOff: true)
2625

2726
init(featherPragmas: FeatherPragmas = FeatherPragmas()) {
2827
self.featherPragmas = featherPragmas
@@ -41,9 +40,9 @@ struct PragmaAnalyzer {
4140
}
4241

4342
if isTrue(expr) {
44-
featherPragmas.remove(.requireStrictTables)
45-
} else {
4643
featherPragmas.insert(.requireStrictTables)
44+
} else {
45+
featherPragmas.remove(.requireStrictTables)
4746
}
4847
case "journal_mode":
4948
diagnostics.add(.init(
@@ -56,15 +55,10 @@ struct PragmaAnalyzer {
5655
}
5756
}
5857

59-
private mutating func isTrue(_ expr: ExprSyntax) -> Bool {
60-
guard expr.accept(visitor: &isStaticallyTrue) else {
61-
diagnostics.add(.init(
62-
"Value is not a static boolean, expected TRUE, FALSE, 1 or 0",
63-
at: expr.range
64-
))
65-
return false
58+
private mutating func isTrue(_ value: PragmaStmt.Value) -> Bool {
59+
return switch value {
60+
case .on, .true, .one, .yes: true
61+
case .off, .false, .zero, .no: false
6662
}
67-
68-
return true
6963
}
7064
}

‎Sources/Compiler/Syntax/StmtSyntax.swift‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,10 +531,21 @@ struct PragmaStmt: StmtSyntax {
531531
let id: SyntaxId
532532
let schema: IdentifierSyntax?
533533
let name: IdentifierSyntax
534-
let value: ExprSyntax?
534+
let value: Value?
535535
let isFunctionCall: Bool
536536
let range: Range<Substring.Index>
537537

538+
enum Value {
539+
case on
540+
case off
541+
case `true`
542+
case `false`
543+
case one
544+
case zero
545+
case yes
546+
case no
547+
}
548+
538549
func accept<V>(visitor: inout V) -> V.StmtOutput where V : StmtSyntaxVisitor {
539550
return visitor.visit(self)
540551
}

‎Tests/CompilerTests/CompilerTests.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class CompilerTests: XCTestCase {
2727
}
2828

2929
func testDelete() throws {
30-
try checkQueries(compile: "CompileDelete", dump: true)
30+
try checkQueries(compile: "CompileDelete")
3131
}
3232

3333
func testCreateTable() throws {
Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,48 @@
11
-- CHECK: PRAGMA_STMT
22
-- CHECK: NAME name
3-
-- CHECK: VALUE
4-
-- CHECK: LITERAL 1.0
3+
-- CHECK: VALUE one
54
-- CHECK: IS_FUNCTION_CALL false
65
PRAGMA name = 1;
76

87
-- CHECK: PRAGMA_STMT
98
-- CHECK: NAME name
10-
-- CHECK: VALUE
11-
-- CHECK: LITERAL 1.0
9+
-- CHECK: VALUE zero
1210
-- CHECK: IS_FUNCTION_CALL true
13-
PRAGMA name(1);
11+
PRAGMA name(0);
1412

1513
-- CHECK: PRAGMA_STMT
1614
-- CHECK: SCHEMA schema
1715
-- CHECK: NAME name
18-
-- CHECK: VALUE
19-
-- CHECK: LITERAL 1.0
16+
-- CHECK: VALUE yes
2017
-- CHECK: IS_FUNCTION_CALL true
21-
PRAGMA schema.name(1);
18+
PRAGMA schema.name(YES);
19+
20+
-- CHECK: PRAGMA_STMT
21+
-- CHECK: NAME name
22+
-- CHECK: VALUE no
23+
-- CHECK: IS_FUNCTION_CALL false
24+
PRAGMA name = NO;
25+
26+
-- CHECK: PRAGMA_STMT
27+
-- CHECK: NAME name
28+
-- CHECK: VALUE true
29+
-- CHECK: IS_FUNCTION_CALL false
30+
PRAGMA name = TRUE;
31+
32+
-- CHECK: PRAGMA_STMT
33+
-- CHECK: NAME name
34+
-- CHECK: VALUE false
35+
-- CHECK: IS_FUNCTION_CALL false
36+
PRAGMA name = FALSE;
37+
38+
-- CHECK: PRAGMA_STMT
39+
-- CHECK: NAME name
40+
-- CHECK: VALUE on
41+
-- CHECK: IS_FUNCTION_CALL false
42+
PRAGMA name = ON;
43+
44+
-- CHECK: PRAGMA_STMT
45+
-- CHECK: NAME name
46+
-- CHECK: VALUE off
47+
-- CHECK: IS_FUNCTION_CALL false
48+
PRAGMA name = OFF;

‎Tests/CompilerTests/SQL/CompileCreateTable.sql‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ CREATE TABLE bar (
2828
PRIMARY KEY (foo, baz)
2929
);
3030

31-
PRAGMA feather_require_strict_tables = ON;
31+
PRAGMA feather_require_strict_tables = TRUE;
3232

3333
-- CHECK: TABLE
3434
-- CHECK: NAME baz

0 commit comments

Comments
 (0)