From c7b620edbe7c4bb86d346b873e8893ea5d60ac13 Mon Sep 17 00:00:00 2001 From: quephird Date: Sat, 23 Mar 2024 16:05:57 -0700 Subject: [PATCH] Added two new helper methods in `LoxValue` and refactored switch in `handleBinaryExpression()`. --- slox/Interpreter.swift | 57 +++++--------------------------- slox/LoxValue.swift | 22 ++++++++++++ slox/RuntimeError.swift | 3 ++ sloxTests/InterpreterTests.swift | 12 +++---- 4 files changed, 40 insertions(+), 54 deletions(-) diff --git a/slox/Interpreter.swift b/slox/Interpreter.swift index d24510f..4bc102a 100644 --- a/slox/Interpreter.swift +++ b/slox/Interpreter.swift @@ -379,7 +379,10 @@ class Interpreter { default: break } - case (.double(let leftNumber), .double(let rightNumber)): + case (.int, .double), (.double, .int), (.double, .double): + let leftNumber = try leftValue.convertToRawDouble() + let rightNumber = try rightValue.convertToRawDouble() + switch oper.type { case .plus: return .double(leftNumber + rightNumber) @@ -400,47 +403,18 @@ class Interpreter { default: break } - case (.int(let leftNumber), .double(let rightNumber)): - let leftNumber = Double(leftNumber) + case (.string(let leftString), .string(let rightString)): switch oper.type { case .plus: - return .double(leftNumber + rightNumber) - case .minus: - return .double(leftNumber - rightNumber) - case .star: - return .double(leftNumber * rightNumber) - case .slash: - return .double(leftNumber / rightNumber) - case .greater: - return .boolean(leftNumber > rightNumber) - case .greaterEqual: - return .boolean(leftNumber >= rightNumber) - case .less: - return .boolean(leftNumber < rightNumber) - case .lessEqual: - return .boolean(leftNumber <= rightNumber) + return .string(leftString + rightString) default: break } - case (.double(let leftNumber), .int(let rightNumber)): - let rightNumber = Double(rightNumber) + case (.instance(let leftList as LoxList), .instance(let rightList as LoxList)): switch oper.type { case .plus: - return .double(leftNumber + rightNumber) - case .minus: - return .double(leftNumber - rightNumber) - case .star: - return .double(leftNumber * rightNumber) - case .slash: - return .double(leftNumber / rightNumber) - case .greater: - return .boolean(leftNumber > rightNumber) - case .greaterEqual: - return .boolean(leftNumber >= rightNumber) - case .less: - return .boolean(leftNumber < rightNumber) - case .lessEqual: - return .boolean(leftNumber <= rightNumber) + let newElements = leftList.elements + rightList.elements + return try makeList(elements: newElements) default: break } @@ -448,19 +422,6 @@ class Interpreter { break } - if case .string(let leftString) = leftValue, - case .string(let rightString) = rightValue, - case .plus = oper.type { - return .string(leftString + rightString) - } - - if case .instance(let leftList as LoxList) = leftValue, - case .instance(let rightList as LoxList) = rightValue, - case .plus = oper.type { - let newElements = leftList.elements + rightList.elements - return try makeList(elements: newElements) - } - switch oper.type { case .bangEqual: return .boolean(!leftValue.isEqual(to: rightValue)) diff --git a/slox/LoxValue.swift b/slox/LoxValue.swift index 26ce295..dcc5ec4 100644 --- a/slox/LoxValue.swift +++ b/slox/LoxValue.swift @@ -83,4 +83,26 @@ enum LoxValue: CustomStringConvertible, Equatable { return true } } + + func convertToRawInt() throws -> Int { + switch self { + case .int(let number): + return number + case .double(let number): + return Int(number) + default: + throw RuntimeError.notANumber + } + } + + func convertToRawDouble() throws -> Double { + switch self { + case .int(let number): + return Double(number) + case .double(let number): + return number + default: + throw RuntimeError.notANumber + } + } } diff --git a/slox/RuntimeError.swift b/slox/RuntimeError.swift index 1c79a0b..19c4fa2 100644 --- a/slox/RuntimeError.swift +++ b/slox/RuntimeError.swift @@ -18,6 +18,7 @@ enum RuntimeError: CustomStringConvertible, Equatable, LocalizedError { case notACallableObject case notAnInstance case notAList + case notANumber case onlyInstancesHaveProperties case undefinedProperty(String) case wrongArity(Int, Int) @@ -48,6 +49,8 @@ enum RuntimeError: CustomStringConvertible, Equatable, LocalizedError { return "Error: expected an instance" case .notAList: return "Error: expected a list" + case .notANumber: + return "Error: expected a number" case .onlyInstancesHaveProperties: return "Error: can only get/set properties of instances" case .undefinedProperty(let name): diff --git a/sloxTests/InterpreterTests.swift b/sloxTests/InterpreterTests.swift index 7e6dfee..ef702f5 100644 --- a/sloxTests/InterpreterTests.swift +++ b/sloxTests/InterpreterTests.swift @@ -521,12 +521,12 @@ xyzzy } let actual = list.elements let expected: [LoxValue] = [ - .number(1), - .number(2), - .number(3), - .number(4), - .number(5), - .number(6), + .int(1), + .int(2), + .int(3), + .int(4), + .int(5), + .int(6), ] XCTAssertEqual(actual, expected) }