Skip to content

Commit 8a531f0

Browse files
committed
Enable Scoped Variables
1 parent b37bbb5 commit 8a531f0

File tree

6 files changed

+84
-7
lines changed

6 files changed

+84
-7
lines changed

Sources/FileCheck/FileCheck.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ public struct FileCheckOptions: OptionSet {
2727
public static let matchFullLines = FileCheckOptions(rawValue: 1 << 2)
2828
/// Disable colored diagnostics.
2929
public static let disableColors = FileCheckOptions(rawValue: 1 << 3)
30+
/// Enables scoping for variables defined in patterns. Variables with names
31+
/// that do not start with `$` will be reset at the beginning of each
32+
/// `CHECK-LABEL` block.
33+
public static let scopedVariables = FileCheckOptions(rawValue: 1 << 4)
3034
}
3135

3236
/// `FileCheckFD` represents the standard output streams `FileCheck` is capable
@@ -558,6 +562,20 @@ private func check(
558562
j += 1
559563
}
560564

565+
// Remove local variables from the variable table. Global variables
566+
// (start with `$`) are preserved.
567+
if options.contains(.scopedVariables) {
568+
var localVariables = [String]()
569+
localVariables.reserveCapacity(16)
570+
for (k, v) in variableTable where !k.hasPrefix("$") {
571+
localVariables.append(k)
572+
}
573+
574+
for k in localVariables {
575+
variableTable.removeValue(forKey: k)
576+
}
577+
}
578+
561579
while i != j {
562580
defer { i += 1 }
563581

Sources/FileCheck/Pattern.swift

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,20 @@ final class Pattern {
186186
var isExpression = false
187187
let diagLoc = CheckLocation.inBuffer(pattern.baseAddress!, buf)
188188
for (i, c) in name.enumerated() {
189-
if i == 0 && c == "@" {
190-
if nameEnd != nil {
191-
diagnose(.error, at: diagLoc, with: "invalid name in named regex definition", options: options)
192-
return nil
189+
if i == 0 {
190+
// Global vars start with '$'
191+
if c == "$" {
192+
continue
193+
}
194+
195+
if c == "@" {
196+
if nameEnd != nil {
197+
diagnose(.error, at: diagLoc, with: "invalid name in named regex definition", options: options)
198+
return nil
199+
}
200+
isExpression = true
201+
continue
193202
}
194-
isExpression = true
195-
continue
196203
}
197204
if c != "_" && isalnum(Int32(c.utf8CodePoint)) == 0 && (!isExpression || (c != "+" && c != "-")) {
198205
diagnose(.error, at: diagLoc, with: "invalid name in named regex", options: options)

Tests/FileCheckTests/DefinesSpec.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import XCTest
33
import Foundation
44

55
class DefinesSpec : XCTestCase {
6-
func testEnvironmentVariables() {
6+
func testGlobalDefines() {
77
XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["PASSDEF"], withGlobals: ["VALUE":"10"]) {
88
// PASSDEF: Value = [[VALUE]]
99
print("Value = 10")
@@ -19,5 +19,11 @@ class DefinesSpec : XCTestCase {
1919
})
2020
})
2121
}
22+
23+
#if !os(macOS)
24+
static var allTests = testCase([
25+
("testGlobalDefines", testGlobalDefines),
26+
])
27+
#endif
2228
}
2329

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import FileCheck
2+
import XCTest
3+
import Foundation
4+
5+
class RegexScopeSpec : XCTestCase {
6+
func testRegexScope() {
7+
let block = { () -> () in
8+
// CHECK: [[LOCAL:loc.*]]
9+
// CHECK: [[$GLOBAL:glo.*]]
10+
print("""
11+
local
12+
global
13+
""")
14+
// CHECK: [[LOCAL]]2
15+
// CHECK: [[$GLOBAL]]2
16+
print("""
17+
local2
18+
global2
19+
""")
20+
// CHECK-LABEL: barrier
21+
print("""
22+
barrier:
23+
""")
24+
// LOCAL: [[LOCAL]]3
25+
// GLOBAL: [[$GLOBAL]]3
26+
print("""
27+
local3
28+
global3
29+
""")
30+
}
31+
XCTAssert(fileCheckOutput(of: .stdout, block: block))
32+
XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["CHECK", "GLOBAL"], block: block))
33+
XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["CHECK", "LOCAL"], block: block))
34+
XCTAssert(fileCheckOutput(of: .stdout, withPrefixes: ["CHECK", "GLOBAL"], options: [.scopedVariables], block: block))
35+
XCTAssertFalse(fileCheckOutput(of: .stdout, withPrefixes: ["CHECK", "LOCAL"], options: [.scopedVariables], block: block))
36+
}
37+
#if !os(macOS)
38+
static var allTests = testCase([
39+
("testRegexScope", testRegexScope),
40+
])
41+
#endif
42+
}
43+

Tests/FileCheckTests/VariableRefSpec.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class VariableRefSpec : XCTestCase {
1414
print("op4 g1, g2, g1")
1515
})
1616
}
17+
1718
#if !os(macOS)
1819
static var allTests = testCase([
1920
("testSameLineVarRef", testSameLineVarRef),

Tests/LinuxMain.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import XCTest
55
#if !os(macOS)
66
XCTMain([
77
DAGSpec.allTests,
8+
DefinesSpec.allTests,
89
EmptySpec.allTests,
910
FileCheckSpec.allTests,
1011
LabelSpec.allTests,
1112
LineCountSpec.allTests,
1213
MultiPrefixSpec.allTests,
14+
RegexScopeSpec.allTests,
1315
VariableRefSpec.allTests,
1416
])
1517
#endif

0 commit comments

Comments
 (0)