[Swift] Remove Recognizer.tokenTypeMapCache and .ruleIndexMapCache.

Remove Recognizer.tokenTypeMapCache and .ruleIndexMapCache.  These
were easily replaced in Swift with lazy vars.  The input to these
two caches are fixed fields on the Recognizer (the Vocabulary and
rule names respectively) so a lazy var suffices.

Note that these differed compared with the Java runtime -- they are
declared as static in Java and therefore the caches are shared across
all recognizer instances, but the Swift runtime had them as Recognizer
instance variables, which meant that at most we had a cache with one
entry which got destroyed along with the parser.  Regardless, using
lazy vars is still simpler.

This removes the only usage of ArrayWrapper in the Swift runtime, so
delete that too.
This commit is contained in:
Ewan Mellor 2017-11-10 15:15:47 -08:00
parent b4c34da1f0
commit 167a3b8808
No known key found for this signature in database
GPG Key ID: 7CE1C6BC9EC8645D
2 changed files with 26 additions and 134 deletions

View File

@ -19,26 +19,11 @@ public protocol RecognizerProtocol {
open class Recognizer<ATNInterpreter: ATNSimulator>: RecognizerProtocol {
//TODO: WeakKeyDictionary NSMapTable Dictionary MapTable<Vocabulary,HashMap<String, Int>>
private let tokenTypeMapCache = HashMap<Vocabulary, [String : Int]>()
private let ruleIndexMapCache = HashMap<ArrayWrapper<String>, [String : Int]>()
private var _listeners: [ANTLRErrorListener] = [ConsoleErrorListener.INSTANCE]
public var _interp: ATNInterpreter!
private var _stateNumber = -1
///
/// mutex for tokenTypeMapCache updates
///
private let tokenTypeMapCacheMutex = Mutex()
///
/// mutex for ruleIndexMapCacheMutex updates
///
private let ruleIndexMapCacheMutex = Mutex()
open func getRuleNames() -> [String] {
fatalError(#function + " must be overridden")
@ -59,30 +44,30 @@ open class Recognizer<ATNInterpreter: ATNSimulator>: RecognizerProtocol {
///
/// Used for XPath and tree pattern compilation.
///
public func getTokenTypeMap() -> [String : Int] {
public func getTokenTypeMap() -> [String: Int] {
return tokenTypeMap
}
public lazy var tokenTypeMap: [String: Int] = {
let vocabulary = getVocabulary()
var result = tokenTypeMapCache[vocabulary]
tokenTypeMapCacheMutex.synchronized { [unowned self] in
if result == nil {
result = [String : Int]()
let length = self.getATN().maxTokenType
for i in 0...length {
if let literalName = vocabulary.getLiteralName(i) {
result![literalName] = i
}
if let symbolicName = vocabulary.getSymbolicName(i) {
result![symbolicName] = i
}
}
var result = [String: Int]()
let length = getATN().maxTokenType
for i in 0...length {
if let literalName = vocabulary.getLiteralName(i) {
result[literalName] = i
}
result!["EOF"] = CommonToken.EOF
self.tokenTypeMapCache[vocabulary] = result!
if let symbolicName = vocabulary.getSymbolicName(i) {
result[symbolicName] = i
}
}
return result!
}
result["EOF"] = CommonToken.EOF
return result
}()
///
/// Get a map from rule names to rule indexes.
@ -90,17 +75,15 @@ open class Recognizer<ATNInterpreter: ATNSimulator>: RecognizerProtocol {
/// Used for XPath and tree pattern compilation.
///
public func getRuleIndexMap() -> [String : Int] {
let ruleNames = getRuleNames()
let result = ruleIndexMapCache[ArrayWrapper<String>(ruleNames)]
ruleIndexMapCacheMutex.synchronized { [unowned self] in
if result == nil {
self.ruleIndexMapCache[ArrayWrapper<String>(ruleNames)] = Utils.toMap(ruleNames)
}
}
return result!
return ruleIndexMap
}
public lazy var ruleIndexMap: [String: Int] = {
let ruleNames = getRuleNames()
return Utils.toMap(ruleNames)
}()
public func getTokenType(_ tokenName: String) -> Int {
return getTokenTypeMap()[tokenName] ?? CommonToken.INVALID_TYPE
}

View File

@ -1,91 +0,0 @@
///
/// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
/// Use of this file is governed by the BSD 3-clause license that
/// can be found in the LICENSE.txt file in the project root.
///
//
// ArrayWrapper.swift
// Antlr4
//
// Created by janyou on 16/6/21.
//
import Foundation
public final class ArrayWrapper<T: Hashable>: ExpressibleByArrayLiteral, Hashable {
public var array: Array<T>
public init(slice: ArraySlice<T>) {
array = Array<T>()
for element in slice {
array.append(element)
}
}
public init(_ elements: T...) {
array = Array<T>()
for element in elements {
array.append(element)
}
}
public init(_ elements: [T]) {
array = elements
}
public init(count: Int, repeatedValue: T) {
array = Array<T>(repeating: repeatedValue, count: count)
}
public init(arrayLiteral elements: T...) {
array = Array<T>()
for element in elements {
array.append(element)
}
}
public subscript(index: Int) -> T {
get {
return array[index]
}
set {
array[index] = newValue
}
}
public subscript(subRange: Range<Int>) -> ArrayWrapper<T> {
return ArrayWrapper<T>(slice: array[subRange])
}
public var count: Int { return array.count }
public var hashValue: Int {
if count == 0 {
return 0
}
var result = 1
for element in array {
result = 31 &* result &+ element.hashValue
}
return result
}
}
public func == <Element>(lhs: ArrayWrapper<Element>, rhs: ArrayWrapper<Element>) -> Bool {
if lhs === rhs {
return true
}
if lhs.count != rhs.count {
return false
}
let length = lhs.count
for i in 0..<length {
if lhs[i] != rhs[i] {
return false
}
}
return true
}