@@ -4014,7 +4014,7 @@ end
40144014local function isValueNumberOrString (v )
40154015 return type (v ) == " number" or type (v ) == " string"
40164016end
4017- local function isValueFiniteNumber (v )
4017+ local function isValueFiniteNumber (v ) -- Should we actually use the logic of isValueNumberLike() where this function is used? @Incomplete
40184018 return type (v ) == " number" and v == v and v ~= 1 / 0 and v ~= - 1 / 0
40194019end
40204020local function isValueNumberLike (v )
@@ -4030,78 +4030,129 @@ local bits2 = {}
40304030
40314031local unaryFolders = {
40324032 [" -" ] = function (unary , expr )
4033+ -- -numberLike -> number
40334034 if expr .type == " literal" and isValueNumberLike (expr .value ) then
4034- return AstLiteral (unary .token , - expr .value )
4035+ return AstLiteral (unary .token , - expr .value ) -- This may convert a string to a number.
40354036 end
4037+
40364038 return nil
40374039 end ,
4040+
40384041 [" not" ] = function (unary , expr )
4039- -- @Incomplete: Fold ' not (expr1 ~= expr2)' into 'expr1 == expr2'.
4040- if expr .type == " literal" then
4042+ -- not literal -> boolean
4043+ if expr .type == " literal" then -- :SimplifyTruthfulValues
40414044 return AstLiteral (unary .token , (not expr .value ))
4045+
4046+ -- not (x == y) -> x ~= y
4047+ -- not (x ~= y) -> x == y
4048+ elseif expr .type == " binary" then
4049+ if expr .operator == " ==" then
4050+ local binary = AstBinary (unary .token , " ~=" )
4051+ binary .left = expr .left
4052+ binary .right = expr .right
4053+ return binary
4054+ elseif expr .operator == " ~=" then
4055+ local binary = AstBinary (unary .token , " ==" )
4056+ binary .left = expr .left
4057+ binary .right = expr .right
4058+ return binary
4059+ end
40424060 end
4061+
40434062 return nil
40444063 end ,
4064+
40454065 [" #" ] = function (unary , expr )
4046- -- I don't think there's ever anything to do here.
4066+ -- #string -> number
4067+ if expr .type == " literal" and type (expr .value ) == " string" then
4068+ return AstLiteral (unary .token , # expr .value )
4069+ end
4070+
4071+ -- We could get the length of tables containing only constants, but who in their right mind writes #{}?
4072+
40474073 return nil
40484074 end ,
4075+
40494076 [" ~" ] = function (unary , expr )
4077+ -- ~number -> number
40504078 if expr .type == " literal" and isValueFiniteNumber (expr .value ) then
40514079 intToBits (expr .value , bits1 )
40524080 for i = 1 , INT_SIZE do
40534081 bits1 [i ] = 1 - bits1 [i ]
40544082 end
40554083 return AstLiteral (unary .token , bitsToInt (bits1 ))
40564084 end
4085+
40574086 return nil
40584087 end ,
40594088}
40604089
40614090local binaryFolders = {
40624091 [" +" ] = function (binary , l , r )
4092+ -- numberLike + numberLike -> number
40634093 if l .type == " literal" and r .type == " literal" and isValueNumberLike (l .value ) and isValueNumberLike (r .value ) then
40644094 return AstLiteral (binary .token , l .value + r .value )
40654095 end
4096+
40664097 return nil
40674098 end ,
4099+
40684100 [" -" ] = function (binary , l , r )
4101+ -- numberLike - numberLike -> number
40694102 if l .type == " literal" and r .type == " literal" and isValueNumberLike (l .value ) and isValueNumberLike (r .value ) then
40704103 return AstLiteral (binary .token , l .value - r .value )
40714104 end
4105+
40724106 return nil
40734107 end ,
4108+
40744109 [" *" ] = function (binary , l , r )
4110+ -- numberLike * numberLike -> number
40754111 if l .type == " literal" and r .type == " literal" and isValueNumberLike (l .value ) and isValueNumberLike (r .value ) then
40764112 return AstLiteral (binary .token , l .value * r .value )
40774113 end
4114+
40784115 return nil
40794116 end ,
4117+
40804118 [" /" ] = function (binary , l , r )
4119+ -- numberLike / numberLike -> number
40814120 if l .type == " literal" and r .type == " literal" and isValueNumberLike (l .value ) and isValueNumberLike (r .value ) then
40824121 return AstLiteral (binary .token , l .value / r .value )
40834122 end
4123+
40844124 return nil
40854125 end ,
4126+
40864127 [" //" ] = function (binary , l , r )
4128+ -- numberLike // numberLike -> number
40874129 if l .type == " literal" and r .type == " literal" and isValueNumberLike (l .value ) and isValueNumberLike (r .value ) then
40884130 return AstLiteral (binary .token , mathFloor (l .value / r .value ))
40894131 end
4132+
40904133 return nil
40914134 end ,
4135+
40924136 [" ^" ] = function (binary , l , r )
4137+ -- numberLike ^ numberLike -> number
40934138 if l .type == " literal" and r .type == " literal" and isValueNumberLike (l .value ) and isValueNumberLike (r .value ) then
40944139 return AstLiteral (binary .token , l .value ^ r .value )
40954140 end
4141+
40964142 return nil
40974143 end ,
4144+
40984145 [" %" ] = function (binary , l , r )
4146+ -- numberLike % numberLike -> number
40994147 if l .type == " literal" and r .type == " literal" and isValueNumberLike (l .value ) and isValueNumberLike (r .value ) then
41004148 return AstLiteral (binary .token , l .value % r .value )
41014149 end
4150+
41024151 return nil
41034152 end ,
4153+
41044154 [" &" ] = function (binary , l , r )
4155+ -- number & number -> number
41054156 if l .type == " literal" and r .type == " literal" and isValueFiniteNumber (l .value ) and isValueFiniteNumber (r .value ) then
41064157 intToBits (l .value , bits1 )
41074158 intToBits (r .value , bits2 )
@@ -4110,9 +4161,12 @@ local binaryFolders = {
41104161 end
41114162 return AstLiteral (binary .token , bitsToInt (bits1 ))
41124163 end
4164+
41134165 return nil
41144166 end ,
4167+
41154168 [" ~" ] = function (binary , l , r )
4169+ -- number ~ number -> number
41164170 if l .type == " literal" and r .type == " literal" and isValueFiniteNumber (l .value ) and isValueFiniteNumber (r .value ) then
41174171 intToBits (l .value , bits1 )
41184172 intToBits (r .value , bits2 )
@@ -4121,9 +4175,12 @@ local binaryFolders = {
41214175 end
41224176 return AstLiteral (binary .token , bitsToInt (bits1 ))
41234177 end
4178+
41244179 return nil
41254180 end ,
4181+
41264182 [" |" ] = function (binary , l , r )
4183+ -- number | number -> number
41274184 if l .type == " literal" and r .type == " literal" and isValueFiniteNumber (l .value ) and isValueFiniteNumber (r .value ) then
41284185 intToBits (l .value , bits1 )
41294186 intToBits (r .value , bits2 )
@@ -4132,9 +4189,12 @@ local binaryFolders = {
41324189 end
41334190 return AstLiteral (binary .token , bitsToInt (bits1 ))
41344191 end
4192+
41354193 return nil
41364194 end ,
4195+
41374196 [" >>" ] = function (binary , l , r )
4197+ -- number >> number -> number
41384198 if l .type == " literal" and r .type == " literal" and isValueFiniteNumber (l .value ) and type (r .value ) == " number" then
41394199 intToBits (l .value , bits1 )
41404200
@@ -4157,7 +4217,9 @@ local binaryFolders = {
41574217
41584218 return nil
41594219 end ,
4220+
41604221 [" <<" ] = function (binary , l , r )
4222+ -- number << number -> number
41614223 if l .type == " literal" and r .type == " literal" and isValueFiniteNumber (l .value ) and type (r .value ) == " number" then
41624224 intToBits (l .value , bits1 )
41634225
@@ -4180,54 +4242,87 @@ local binaryFolders = {
41804242
41814243 return nil
41824244 end ,
4245+
41834246 [" .." ] = function (binary , l , r )
4247+ -- numberOrString .. numberOrString -> string
41844248 if l .type == " literal" and r .type == " literal" and isValueNumberOrString (l .value ) and isValueNumberOrString (r .value ) then
41854249 return AstLiteral (binary .token , l .value .. r .value )
41864250 end
4251+
41874252 return nil
41884253 end ,
4254+
41894255 [" <" ] = function (binary , l , r )
4256+ -- number < number -> boolean
4257+ -- string < string -> boolean
41904258 if l .type == " literal" and r .type == " literal" and areValuesNumbersOrStringsAndOfSameType (l .value , r .value ) then
41914259 return AstLiteral (binary .token , (l .value < r .value ))
41924260 end
4261+
41934262 return nil
41944263 end ,
4264+
41954265 [" <=" ] = function (binary , l , r )
4266+ -- number <= number -> boolean
4267+ -- string <= string -> boolean
41964268 if l .type == " literal" and r .type == " literal" and areValuesNumbersOrStringsAndOfSameType (l .value , r .value ) then
41974269 return AstLiteral (binary .token , (l .value <= r .value ))
41984270 end
4271+
41994272 return nil
42004273 end ,
4274+
42014275 [" >" ] = function (binary , l , r )
4276+ -- number > number -> boolean
4277+ -- string > string -> boolean
42024278 if l .type == " literal" and r .type == " literal" and areValuesNumbersOrStringsAndOfSameType (l .value , r .value ) then
42034279 return AstLiteral (binary .token , (l .value > r .value ))
42044280 end
4281+
42054282 return nil
42064283 end ,
4284+
42074285 [" >=" ] = function (binary , l , r )
4286+ -- number >= number -> boolean
4287+ -- string >= string -> boolean
42084288 if l .type == " literal" and r .type == " literal" and areValuesNumbersOrStringsAndOfSameType (l .value , r .value ) then
42094289 return AstLiteral (binary .token , (l .value >= r .value ))
42104290 end
4291+
42114292 return nil
42124293 end ,
4294+
42134295 [" ==" ] = function (binary , l , r )
4296+ -- literal == literal -> boolean
42144297 if l .type == " literal" and r .type == " literal" then
42154298 return AstLiteral (binary .token , (l .value == r .value ))
42164299 end
4300+
42174301 return nil
42184302 end ,
4303+
42194304 [" ~=" ] = function (binary , l , r )
4305+ -- literal ~= literal -> boolean
42204306 if l .type == " literal" and r .type == " literal" then
42214307 return AstLiteral (binary .token , (l .value ~= r .value ))
42224308 end
4309+
42234310 return nil
42244311 end ,
4312+
42254313 [" and" ] = function (binary , l , r )
4314+ -- truthfulLiteral and x -> x
4315+ -- untruthfulLiteral and x -> untruthfulLiteral
42264316 if l .type == " literal" then return l .value and r or l end
4317+
42274318 return nil
42284319 end ,
4320+
42294321 [" or" ] = function (binary , l , r )
4322+ -- truthfulLiteral or x -> untruthfulLiteral
4323+ -- untruthfulLiteral or x -> x
42304324 if l .type == " literal" then return l .value and l or r end
4325+
42314326 return nil
42324327 end ,
42334328}
@@ -4246,12 +4341,12 @@ local function simplifyNode(node, parent, container, key)
42464341 if replacement then replace (node , replacement , parent , container , key , statsForSimplify ) end
42474342
42484343 elseif node .type == " binary" then
4249- -- @Incomplete: Fold 'expr - -n' into 'expr + n' etc.
4344+ -- @Incomplete: Fold 'expr - -n' into 'expr + n' etc. (Actually, this will probably mess up metamethods.)
42504345 local replacement = binaryFolders [node .operator ](node , node .left , node .right )
42514346 if replacement then replace (node , replacement , parent , container , key , statsForSimplify ) end
42524347
42534348 elseif node .type == " if" then
4254- -- @Incomplete: Fold 'if not not expr' into 'if expr'. (Also for 'while' and 'repeat'.)
4349+ -- @Incomplete: Fold 'if not not expr' into 'if expr'. (Also for 'while' and 'repeat' etc., i.e. all conditional expressions .)
42554350 local ifNode = node
42564351
42574352 if ifNode .condition .type == " literal" then -- @Incomplete: There are more values that make simplification possible (e.g. functions, but who would put that here anyway). :SimplifyTruthfulValues
@@ -4272,7 +4367,7 @@ local function simplifyNode(node, parent, container, key)
42724367
42734368 if whileLoop .condition .type == " literal" then -- :SimplifyTruthfulValues
42744369 if whileLoop .condition .value then
4275- whileLoop .condition .value = true
4370+ whileLoop .condition .value = true -- Convert literal's value to boolean.
42764371 else
42774372 tableRemove (container , key )
42784373 tableInsert (statsForSimplify .nodeRemovals , Location (whileLoop ))
@@ -4288,7 +4383,7 @@ local function simplifyNode(node, parent, container, key)
42884383 replace (repeatLoop , repeatLoop .body , parent , container , key , statsForSimplify )
42894384 return simplifyNode (repeatLoop .body , parent , container , key )
42904385 else
4291- repeatLoop .condition .value = false
4386+ repeatLoop .condition .value = false -- Convert literal's value to boolean.
42924387 end
42934388 end
42944389
0 commit comments