diff --git a/Spreadsheet/Spreadsheet.xcodeproj/project.pbxproj b/Spreadsheet/Spreadsheet.xcodeproj/project.pbxproj index ef79e83..64ad0cb 100644 --- a/Spreadsheet/Spreadsheet.xcodeproj/project.pbxproj +++ b/Spreadsheet/Spreadsheet.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 63; objects = { /* Begin PBXBuildFile section */ @@ -118,9 +118,10 @@ 83E6F36D1962FCDD0030D82A /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 1530; ORGANIZATIONNAME = "Unsigned Integer"; TargetAttributes = { 83E6F3741962FCDD0030D82A = { @@ -130,8 +131,8 @@ }; }; buildConfigurationList = 83E6F3701962FCDD0030D82A /* Build configuration list for PBXProject "Spreadsheet" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + compatibilityVersion = "Xcode 15.3"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -196,21 +197,32 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -226,7 +238,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 14.4; METAL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -242,22 +254,33 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = YES; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -266,9 +289,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; + MACOSX_DEPLOYMENT_TARGET = 14.4; METAL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; }; name = Release; }; @@ -277,17 +301,22 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; INFOPLIST_FILE = Spreadsheet/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", "$(PROJECT_DIR)/Spreadsheet", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.unsignedinteger.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_INCLUDE_PATHS = "/Users/chris/Desktop/fpinswift/test-projects/Parsing/Parsing"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -296,17 +325,22 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; INFOPLIST_FILE = Spreadsheet/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", "$(PROJECT_DIR)/Spreadsheet", ); + MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; PRODUCT_BUNDLE_IDENTIFIER = "com.unsignedinteger.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_INCLUDE_PATHS = "/Users/chris/Desktop/fpinswift/test-projects/Parsing/Parsing"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Spreadsheet/Spreadsheet.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Spreadsheet/Spreadsheet.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Spreadsheet/Spreadsheet.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Spreadsheet/Spreadsheet.xcodeproj/project.xcworkspace/xcuserdata/macintosh.xcuserdatad/UserInterfaceState.xcuserstate b/Spreadsheet/Spreadsheet.xcodeproj/project.xcworkspace/xcuserdata/macintosh.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..b06d890 Binary files /dev/null and b/Spreadsheet/Spreadsheet.xcodeproj/project.xcworkspace/xcuserdata/macintosh.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Spreadsheet/Spreadsheet.xcodeproj/xcuserdata/macintosh.xcuserdatad/xcschemes/xcschememanagement.plist b/Spreadsheet/Spreadsheet.xcodeproj/xcuserdata/macintosh.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..ad83256 --- /dev/null +++ b/Spreadsheet/Spreadsheet.xcodeproj/xcuserdata/macintosh.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + Spreadsheet.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Spreadsheet/Spreadsheet/AppDelegate.swift b/Spreadsheet/Spreadsheet/AppDelegate.swift index 409d829..13a5cf2 100644 --- a/Spreadsheet/Spreadsheet/AppDelegate.swift +++ b/Spreadsheet/Spreadsheet/AppDelegate.swift @@ -1,7 +1,7 @@ import Cocoa class AppDelegate: NSObject, NSApplicationDelegate { - var controller : SheetWindowController? + var controller: SheetWindowController? func applicationDidFinishLaunching(_ aNotification: Notification) { controller = SheetWindowController(windowNibName: "Sheet") diff --git a/Spreadsheet/Spreadsheet/Expression.swift b/Spreadsheet/Spreadsheet/Expression.swift index 5e5a613..5bf1431 100644 --- a/Spreadsheet/Spreadsheet/Expression.swift +++ b/Spreadsheet/Spreadsheet/Expression.swift @@ -45,7 +45,6 @@ extension Expression { } - enum Result { case int(Int) case list([Result]) @@ -67,7 +66,7 @@ extension Expression { case let .infix(l, op, r): return self.evaluateArithmetic(context: context) ?? self.evaluateList(context: context) - ?? .error("Invalid operator \(op) for operands \(l, r)") + ?? .error("Invalid operator \(op) for operands \(l) and \(r)") default: return .error("Couldn't evaluate expression \(self)") } @@ -117,7 +116,7 @@ extension Expression { func lift(_ op: @escaping (Int, Int) -> Int) -> ((Result, Result) -> Result) { return { lhs, rhs in guard case let (.int(x), .int(y)) = (lhs, rhs) else { - return .error("Invalid operands \(lhs, rhs) for integer operator") + return .error("Invalid operands \(lhs) and \(rhs) for integer operator") } return .int(op(x, y)) } @@ -125,9 +124,5 @@ func lift(_ op: @escaping (Int, Int) -> Int) -> ((Result, Result) -> Result) { func evaluate(expressions: [Expression?]) -> [Result] { - return expressions.map { $0?.evaluate(context: expressions) ?? .error("Invalid expression \($0)") } + return expressions.map { $0?.evaluate(context: expressions) ?? .error("Invalid expression \(String(describing: $0))") } } - - - - diff --git a/Spreadsheet/Spreadsheet/Helpers.swift b/Spreadsheet/Spreadsheet/Helpers.swift index db47233..2f20711 100644 --- a/Spreadsheet/Spreadsheet/Helpers.swift +++ b/Spreadsheet/Spreadsheet/Helpers.swift @@ -15,6 +15,3 @@ func curry(_ f: @escaping (A, B) -> C) -> (A) -> (B) -> C { func curry(_ f: @escaping (A, B, C) -> D) -> (A) -> (B) -> (C) -> D { return { a in { b in { c in f(a, b, c) } } } } - - - diff --git a/Spreadsheet/Spreadsheet/Sheet.xib b/Spreadsheet/Spreadsheet/Sheet.xib index 89969a8..3e286db 100644 --- a/Spreadsheet/Spreadsheet/Sheet.xib +++ b/Spreadsheet/Spreadsheet/Sheet.xib @@ -1,8 +1,8 @@ - + - - + + @@ -15,11 +15,11 @@ - + - + @@ -27,19 +27,18 @@ - + - - + + - @@ -58,15 +57,15 @@ - + diff --git a/Spreadsheet/Spreadsheet/SheetWindowController.swift b/Spreadsheet/Spreadsheet/SheetWindowController.swift index 4905983..ceb9d90 100644 --- a/Spreadsheet/Spreadsheet/SheetWindowController.swift +++ b/Spreadsheet/Spreadsheet/SheetWindowController.swift @@ -7,7 +7,7 @@ class SheetWindowController: NSWindowController { override func windowDidLoad() { delegate?.editedRowDelegate = dataSource - NotificationCenter.default.addObserver(self, selector: NSSelectorFromString("endEditing:"), name: NSNotification.Name.NSControlTextDidEndEditing, object: nil) + NotificationCenter.default.addObserver(self, selector: NSSelectorFromString("endEditing:"), name: NSControl.textDidEndEditingNotification, object: nil) } func endEditing(_ note: Notification) { @@ -17,7 +17,7 @@ class SheetWindowController: NSWindowController { } -protocol EditedRow: class { +protocol EditedRow: AnyObject { var editedRow: Int? { get set } } @@ -44,7 +44,7 @@ class SpreadsheetDatasource: NSObject, NSTableViewDataSource, EditedRow { } func parseAndEvaluate() { - let expressions = formulas.map { Expression.parser.parse($0.characters)?.0 } + let expressions = formulas.map { formula in Expression.parser.parse(formula[...])?.0 } results = evaluate(expressions: expressions) } diff --git a/Spreadsheet/Spreadsheet/main.swift b/Spreadsheet/Spreadsheet/main.swift index 2408dd7..a511b5c 100644 --- a/Spreadsheet/Spreadsheet/main.swift +++ b/Spreadsheet/Spreadsheet/main.swift @@ -8,4 +8,4 @@ import Cocoa -NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv) +_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv) diff --git a/Spreadsheet/Spreadsheet/parsing.swift b/Spreadsheet/Spreadsheet/parsing.swift index 65ca165..2722538 100644 --- a/Spreadsheet/Spreadsheet/parsing.swift +++ b/Spreadsheet/Spreadsheet/parsing.swift @@ -1,14 +1,13 @@ import Foundation - struct Parser { - typealias Stream = String.CharacterView + typealias Stream = Substring let parse: (Stream) -> (A, Stream)? } extension Parser { func run(_ string: String) -> (A, String)? { - guard let (result, remainder) = parse(string.characters) else { return nil } + guard let (result, remainder) = parse(string[...]) else { return nil } return (result, String(remainder)) } @@ -61,8 +60,6 @@ extension Parser { } } - - precedencegroup SequencePrecedence { associativity: left higherThan: AdditionPrecedence @@ -93,9 +90,7 @@ func <|>(lhs: Parser, rhs: Parser) -> Parser { return lhs.or(rhs) } - - -func character(condition: @escaping (Character) -> Bool) -> Parser { +func character(matching condition: @escaping (Character) -> Bool) -> Parser { return Parser { input in guard let char = input.first, condition(char) else { return nil } return (char, input.dropFirst()) @@ -105,7 +100,7 @@ func character(condition: @escaping (Character) -> Bool) -> Parser { func string(_ string: String) -> Parser { return Parser { input in var remainder = input - for c in string.characters { + for c in string { let parser = character { $0 == c } guard let (_, newRemainder) = parser.parse(remainder) else { return nil } remainder = newRemainder @@ -119,9 +114,6 @@ func lazy(_ parser: @autoclosure @escaping () -> Parser) -> Parser { } -let digit = character { CharacterSet.decimalDigits.contains($0) } +let digit = character { $0.isNumber } let integer = digit.many1.map { Int(String($0))! } -let capitalLetter = character { CharacterSet.uppercaseLetters.contains($0) } - - - +let capitalLetter = character { $0.isUppercase }