@@ -1282,9 +1282,21 @@ extension Expression {
12821282 case . minus:
12831283 switch value {
12841284 case let . tuple( values) :
1285- return . tuple( values. map { . number( - $0. doubleValue) } )
1285+ return . tuple( values. map {
1286+ switch $0 {
1287+ case let . number( value) :
1288+ return . number( - value)
1289+ case let . radians( value) :
1290+ return . radians( - value)
1291+ default :
1292+ assertionFailure ( )
1293+ return value
1294+ }
1295+ } )
12861296 case let . number( value) :
12871297 return . number( - value)
1298+ case let . radians( value) :
1299+ return . radians( - value)
12881300 default :
12891301 assertionFailure ( )
12901302 return value
@@ -1357,52 +1369,46 @@ extension Expression {
13571369 in: context
13581370 ) . boolValue)
13591371 case let . infix( lhs, op, rhs) :
1360- func doubleValue( _ exp: Expression , index: Int = 0 ) throws -> Double {
1361- try exp. evaluate (
1362- as: . number,
1363- for: String ( op. rawValue) ,
1364- index: index,
1365- in: context
1366- ) . doubleValue
1372+ func evaluate( _ exp: Expression , as type: ValueType , at index: Int = 0 ) throws -> Value {
1373+ try exp. evaluate ( as: type, for: op. rawValue, index: index, in: context)
13671374 }
1368- func tupleValue( _ exp: Expression , index: Int = 0 ) throws -> Value {
1369- try exp. evaluate (
1370- as: . union( [ . number, . list( . number) ] ) ,
1371- for: String ( op. rawValue) ,
1372- index: index,
1373- in: context
1374- )
1375+ func doubleValue( for exp: Expression , at index: Int = 0 ) throws -> Double {
1376+ try evaluate ( exp, as: . number, at: index) . doubleValue
13751377 }
1376- func apply(
1377- _ lhs: Value ,
1378- _ rhs: Value ,
1379- _ fn: ( Double , Double ) -> Double
1380- ) -> Value {
1381- switch ( lhs, rhs) {
1382- case let ( . number( lhs) , . number( rhs) ) :
1383- return . number( fn ( lhs, rhs) )
1384- case let ( . tuple( lhs) , _) where lhs. count == 1 :
1378+ func numberOrVectorValue( for exp: Expression , at index: Int = 0 ) throws -> Value {
1379+ try evaluate ( exp, as: . numberOrVector, at: index)
1380+ }
1381+ func apply( _ lhs: Value , _ rhs: Value , _ fn: ( Double , Double ) -> Double ) -> Value {
1382+ switch ( lhs, rhs, op) {
1383+ case let ( . number( lhs) , . radians( rhs) , . plus) , let ( . number( lhs) , . radians( rhs) , . minus) ,
1384+ let ( . radians( lhs) , . number( rhs) , . plus) , let ( . radians( lhs) , . number( rhs) , . minus) ,
1385+ let ( . radians( lhs) , . radians( rhs) , . times) , // TODO: should this be an error?
1386+ let ( . radians( lhs) , . radians( rhs) , . divide) , // TODO: should this be halfTurns?
1387+ let ( . number( lhs) , . number( rhs) , _) :
1388+ return . number( fn ( lhs, rhs) ) // TODO: should this be an error?
1389+ case let ( . number( lhs) , . radians( rhs) , . divide) :
1390+ return . radians( fn ( lhs, rhs) ) // TODO: should this be a reciprocal radians type?
1391+ case let ( . radians( lhs) , . radians( rhs) , _) , let ( . number( lhs) , . radians( rhs) , _) ,
1392+ let ( . radians( lhs) , . number( rhs) , _) :
1393+ return . radians( fn ( lhs, rhs) )
1394+ case let ( . tuple( lhs) , _, _) where lhs. count == 1 :
13851395 return apply ( lhs [ 0 ] , rhs, fn)
1386- case let ( _, . tuple( rhs) ) where rhs. count == 1 :
1396+ case let ( _, . tuple( rhs) , _ ) where rhs. count == 1 :
13871397 return apply ( lhs, rhs [ 0 ] , fn)
1388- case let ( . tuple( lhs) , . tuple( rhs) ) :
1398+ case let ( . tuple( lhs) , . tuple( rhs) , _ ) :
13891399 return . tuple( zip ( lhs, rhs) . map { apply ( $0, $1, fn) } )
1390- case let ( . tuple( lhs) , . number) :
1400+ case let ( . tuple( lhs) , . number, _ ) :
13911401 return . tuple( lhs. map { apply ( $0, rhs, fn) } )
1392- case let ( . number, . tuple( rhs) ) :
1402+ case let ( . number, . tuple( rhs) , _ ) :
13931403 return . tuple( rhs. map { apply ( lhs, $0, fn) } )
13941404 default :
13951405 assertionFailure ( )
13961406 return . number( 0 )
13971407 }
13981408 }
1399- func tupleApply(
1400- _ fn: ( Double , Double ) -> Double ,
1401- lhs value: Value ? = nil ,
1402- widen: Bool
1403- ) throws -> Value {
1404- let lhs = try value ?? tupleValue ( lhs)
1405- let rhs = try tupleValue ( rhs, index: 1 )
1409+ func tupleApply( _ fn: ( Double , Double ) -> Double , widen: Bool ) throws -> Value {
1410+ let lhs = try numberOrVectorValue ( for: lhs)
1411+ let rhs = try numberOrVectorValue ( for: rhs, at: 1 )
14061412 switch ( apply ( lhs, rhs, fn) , lhs) {
14071413 case let ( . tuple( values) , . tuple( lhs) ) where widen:
14081414 return . tuple( values + lhs[ values. count... ] )
@@ -1411,21 +1417,26 @@ extension Expression {
14111417 }
14121418 }
14131419 func tupleOrTextureApply( _ fn: ( Double , Double ) -> Double ) throws -> Value {
1414- let lhs = try lhs. evaluate (
1415- as: . union( [ . number, . list( . number) , . texture] ) ,
1416- for: String ( op. rawValue) ,
1417- index: 0 ,
1418- in: context
1419- )
1420- if case let . texture( texture) = lhs {
1420+ let lhs = try evaluate ( lhs, as: . union( [
1421+ . number,
1422+ . radians,
1423+ . list( . number) ,
1424+ . list( . radians) ,
1425+ . texture,
1426+ ] ) )
1427+ switch lhs {
1428+ case let . texture( texture) :
14211429 guard let texture else {
14221430 return . texture( nil )
14231431 }
1424- let rhs = try doubleValue ( rhs)
1432+ let rhs = try doubleValue ( for : rhs)
14251433 return . texture( texture. withIntensity ( fn ( texture. intensity, rhs) ) )
1434+ default :
1435+ let rhs = try numberOrVectorValue ( for: rhs, at: 1 )
1436+ return apply ( lhs, rhs, fn)
14261437 }
1427- return try tupleApply ( fn, lhs: lhs, widen: false )
14281438 }
1439+
14291440 switch op {
14301441 case . minus:
14311442 return try tupleApply ( - , widen: true )
@@ -1438,16 +1449,15 @@ extension Expression {
14381449 case . modulo:
14391450 return try tupleApply ( fmod, widen: false )
14401451 case . lt:
1441- return try . boolean( doubleValue ( lhs) < doubleValue ( rhs, index : 1 ) )
1452+ return try . boolean( doubleValue ( for : lhs) < doubleValue ( for : rhs, at : 1 ) )
14421453 case . gt:
1443- return try . boolean( doubleValue ( lhs) > doubleValue ( rhs, index : 1 ) )
1454+ return try . boolean( doubleValue ( for : lhs) > doubleValue ( for : rhs, at : 1 ) )
14441455 case . lte:
1445- return try . boolean( doubleValue ( lhs) <= doubleValue ( rhs, index : 1 ) )
1456+ return try . boolean( doubleValue ( for : lhs) <= doubleValue ( for : rhs, at : 1 ) )
14461457 case . gte:
1447- return try . boolean( doubleValue ( lhs) >= doubleValue ( rhs, index : 1 ) )
1458+ return try . boolean( doubleValue ( for : lhs) >= doubleValue ( for : rhs, at : 1 ) )
14481459 case . in, . to, . step, . equal, . unequal, . and, . or:
1449- throw RuntimeErrorType
1450- . assertionFailure ( " \( op. rawValue) should be handled by earlier case " )
1460+ throw RuntimeErrorType . assertionFailure ( " \( op. rawValue) should be handled by earlier case " )
14511461 }
14521462 case let . member( expression, member) :
14531463 let value = try expression. evaluate ( in: context)
0 commit comments