11protocol Expression : CustomStringConvertible {
2- func evaluate( context: Context ) throws -> Bool
2+ func evaluate( context: Context ) throws -> Any
33}
44
55
@@ -20,7 +20,7 @@ final class StaticExpression: Expression, CustomStringConvertible {
2020 self . value = value
2121 }
2222
23- func evaluate( context: Context ) throws -> Bool {
23+ func evaluate( context: Context ) throws -> Any {
2424 return value
2525 }
2626
@@ -29,8 +29,7 @@ final class StaticExpression: Expression, CustomStringConvertible {
2929 }
3030}
3131
32-
33- final class VariableExpression : Expression , CustomStringConvertible {
32+ class VariableExpression : Expression , CustomStringConvertible {
3433 let variable : Resolvable
3534
3635 init ( variable: Resolvable ) {
@@ -42,7 +41,7 @@ final class VariableExpression: Expression, CustomStringConvertible {
4241 }
4342
4443 /// Resolves a variable in the given context as boolean
45- func resolve ( context: Context , variable : Resolvable ) throws -> Bool {
44+ func evaluate ( context: Context ) throws -> Any {
4645 let result = try variable. resolve ( context)
4746 var truthy = false
4847
@@ -62,13 +61,8 @@ final class VariableExpression: Expression, CustomStringConvertible {
6261
6362 return truthy
6463 }
65-
66- func evaluate( context: Context ) throws -> Bool {
67- return try resolve ( context: context, variable: variable)
68- }
6964}
7065
71-
7266final class NotExpression : Expression , PrefixOperator , CustomStringConvertible {
7367 let expression : Expression
7468
@@ -80,8 +74,8 @@ final class NotExpression: Expression, PrefixOperator, CustomStringConvertible {
8074 return " not \( expression) "
8175 }
8276
83- func evaluate( context: Context ) throws -> Bool {
84- return try ! expression. evaluate ( context: context)
77+ func evaluate( context: Context ) throws -> Any {
78+ return try ! ( expression. evaluate ( context: context) as! Bool )
8579 }
8680}
8781
@@ -98,7 +92,7 @@ final class InExpression: Expression, InfixOperator, CustomStringConvertible {
9892 return " ( \( lhs) in \( rhs) ) "
9993 }
10094
101- func evaluate( context: Context ) throws -> Bool {
95+ func evaluate( context: Context ) throws -> Any {
10296 if let lhs = lhs as? VariableExpression , let rhs = rhs as? VariableExpression {
10397 let lhsValue = try lhs. variable. resolve ( context)
10498 let rhsValue = try rhs. variable. resolve ( context)
@@ -130,8 +124,8 @@ final class OrExpression: Expression, InfixOperator, CustomStringConvertible {
130124 return " ( \( lhs) or \( rhs) ) "
131125 }
132126
133- func evaluate( context: Context ) throws -> Bool {
134- let lhs = try self . lhs. evaluate ( context: context)
127+ func evaluate( context: Context ) throws -> Any {
128+ let lhs = try self . lhs. evaluate ( context: context) as! Bool
135129 if lhs {
136130 return lhs
137131 }
@@ -154,8 +148,8 @@ final class AndExpression: Expression, InfixOperator, CustomStringConvertible {
154148 return " ( \( lhs) and \( rhs) ) "
155149 }
156150
157- func evaluate( context: Context ) throws -> Bool {
158- let lhs = try self . lhs. evaluate ( context: context)
151+ func evaluate( context: Context ) throws -> Any {
152+ let lhs = try self . lhs. evaluate ( context: context) as! Bool
159153 if !lhs {
160154 return lhs
161155 }
@@ -178,7 +172,7 @@ class EqualityExpression: Expression, InfixOperator, CustomStringConvertible {
178172 return " ( \( lhs) == \( rhs) ) "
179173 }
180174
181- func evaluate( context: Context ) throws -> Bool {
175+ func evaluate( context: Context ) throws -> Any {
182176 if let lhs = lhs as? VariableExpression , let rhs = rhs as? VariableExpression {
183177 let lhsValue = try lhs. variable. resolve ( context)
184178 let rhsValue = try rhs. variable. resolve ( context)
@@ -214,16 +208,26 @@ class NumericExpression: Expression, InfixOperator, CustomStringConvertible {
214208 return " ( \( lhs) \( op) \( rhs) ) "
215209 }
216210
217- func evaluate( context: Context ) throws -> Bool {
211+ func evaluate( context: Context ) throws -> Any {
218212 if let lhs = lhs as? VariableExpression , let rhs = rhs as? VariableExpression {
219213 let lhsValue = try lhs. variable. resolve ( context)
220214 let rhsValue = try rhs. variable. resolve ( context)
221215
222- if let lhs = lhsValue, let rhs = rhsValue {
223- if let lhs = toNumber ( value: lhs) , let rhs = toNumber ( value: rhs) {
224- return compare ( lhs: lhs, rhs: rhs)
225- }
216+ guard let lhs = lhsValue else {
217+ throw TemplateSyntaxError ( " left value is nil " )
218+ }
219+ guard let lhsNumber = toNumber ( value: lhs) else {
220+ throw TemplateSyntaxError ( " left value is not a number " )
221+ }
222+
223+ guard let rhs = rhsValue else {
224+ throw TemplateSyntaxError ( " right value is nil " )
225+ }
226+ guard let rhsNumber = toNumber ( value: rhs) else {
227+ throw TemplateSyntaxError ( " right value is not a number " )
226228 }
229+
230+ return compare ( lhs: lhsNumber, rhs: rhsNumber)
227231 }
228232
229233 return false
@@ -239,7 +243,7 @@ class NumericExpression: Expression, InfixOperator, CustomStringConvertible {
239243}
240244
241245
242- class MoreThanExpression : NumericExpression {
246+ final class MoreThanExpression : NumericExpression {
243247 override var op : String {
244248 return " > "
245249 }
@@ -250,7 +254,7 @@ class MoreThanExpression: NumericExpression {
250254}
251255
252256
253- class MoreThanEqualExpression : NumericExpression {
257+ final class MoreThanEqualExpression : NumericExpression {
254258 override var op : String {
255259 return " >= "
256260 }
@@ -261,7 +265,7 @@ class MoreThanEqualExpression: NumericExpression {
261265}
262266
263267
264- class LessThanExpression : NumericExpression {
268+ final class LessThanExpression : NumericExpression {
265269 override var op : String {
266270 return " < "
267271 }
@@ -272,7 +276,7 @@ class LessThanExpression: NumericExpression {
272276}
273277
274278
275- class LessThanEqualExpression : NumericExpression {
279+ final class LessThanEqualExpression : NumericExpression {
276280 override var op : String {
277281 return " <= "
278282 }
@@ -283,13 +287,13 @@ class LessThanEqualExpression: NumericExpression {
283287}
284288
285289
286- class InequalityExpression : EqualityExpression {
290+ final class InequalityExpression : EqualityExpression {
287291 override var description : String {
288292 return " ( \( lhs) != \( rhs) ) "
289293 }
290294
291- override func evaluate( context: Context ) throws -> Bool {
292- return try ! super. evaluate ( context: context)
295+ override func evaluate( context: Context ) throws -> Any {
296+ return try ! ( super. evaluate ( context: context) as! Bool )
293297 }
294298}
295299
@@ -329,3 +333,105 @@ func toNumber(value: Any) -> Number? {
329333
330334 return nil
331335}
336+
337+ class ArithmeticExpression : Expression , InfixOperator , CustomStringConvertible {
338+ let lhs : Expression
339+ let rhs : Expression
340+
341+ required init ( lhs: Expression , rhs: Expression ) {
342+ self . lhs = lhs
343+ self . rhs = rhs
344+ }
345+
346+ var description : String {
347+ return " ( \( lhs) \( op) \( rhs) ) "
348+ }
349+
350+ func evaluate( context: Context ) throws -> Any {
351+ let lhsResult : Number
352+ if let lhs = lhs as? ArithmeticExpression {
353+ lhsResult = try lhs. evaluate ( context: context) as! Number
354+ } else if let lhs = lhs as? VariableExpression {
355+ let lhsValue = try lhs. variable. resolve ( context)
356+
357+ guard let lhs = lhsValue else {
358+ throw TemplateSyntaxError ( " left value is nil " )
359+ }
360+ guard let lhsNumber = toNumber ( value: lhs) else {
361+ throw TemplateSyntaxError ( " left value ' \( lhs) ' is not a number " )
362+ }
363+ lhsResult = lhsNumber
364+ } else {
365+ throw TemplateSyntaxError ( " invalid arithmetic expression " )
366+ }
367+
368+ let rhsResult : Number
369+ if let rhs = rhs as? ArithmeticExpression {
370+ rhsResult = try rhs. evaluate ( context: context) as! Number
371+ } else if let rhs = rhs as? VariableExpression {
372+ let rhsValue = try rhs. variable. resolve ( context)
373+
374+ guard let rhs = rhsValue else {
375+ throw TemplateSyntaxError ( " right value is nil " )
376+ }
377+ guard let rhsNumber = toNumber ( value: rhs) else {
378+ throw TemplateSyntaxError ( " right value ' \( rhs) ' is not a number " )
379+ }
380+ rhsResult = rhsNumber
381+ } else {
382+ throw TemplateSyntaxError ( " invalid arithmetic expression " )
383+ }
384+
385+ return calculate ( lhs: lhsResult, rhs: rhsResult)
386+ }
387+
388+ var op : String {
389+ return " "
390+ }
391+
392+ func calculate( lhs: Number , rhs: Number ) -> Number {
393+ return 0
394+ }
395+ }
396+
397+ final class SumExpression : ArithmeticExpression {
398+ override var op : String {
399+ return " + "
400+ }
401+
402+ override func calculate( lhs: Number , rhs: Number ) -> Number {
403+ return lhs + rhs
404+ }
405+ }
406+
407+ final class SubstractExpression : ArithmeticExpression {
408+ override var op : String {
409+ return " - "
410+ }
411+
412+ override func calculate( lhs: Number , rhs: Number ) -> Number {
413+ return lhs - rhs
414+ }
415+ }
416+
417+ final class MultiplyExpression : ArithmeticExpression {
418+ override var op : String {
419+ return " * "
420+ }
421+
422+ override func calculate( lhs: Number , rhs: Number ) -> Number {
423+ return lhs * rhs
424+ }
425+ }
426+
427+ final class DevideExpression : ArithmeticExpression {
428+ override var op : String {
429+ return " / "
430+ }
431+
432+ override func calculate( lhs: Number , rhs: Number ) -> Number {
433+ return lhs / rhs
434+ }
435+ }
436+
437+
0 commit comments