Просмотр полной версии : Занимательный ActionScript (Flash 5 only!!)
Открываем новый fla и в в Frame Action пишем одну строчку:
foo=0*++1.2345;
... запускаем на выполнение.....
Как вы думаете чему будет равна переменная foo? Очевидно - нулю.... Ноль умножить на любое число - ноль... Логично....
Нажимает Ctrl-Alt-V............. и тихонько сползаем со стула.......
............
теперь выбрасывем foo к чёрту... пишем, например ......
10#++1.23456;
где вместо '#' может стоять ЛЮБАЯ операция-'+','-','*','/,'%','<','>','<>','|','&' - результат от этого не меняется.....
Запускаем..... Нажимает Ctrl-Alt-V...... Протитаем глаза.... Пауза..........
Вобщем - Очевидное-невероятное..... :eek:
Nox Noctis
13.06.2002, 02:58
все абсолютно правильно
1.2345 - это НЕ леводопустимое выражение
(леводопустимое, это которое может стоять слева от знака присвоения)
что по сути выполняется если написано ++1 ?
– при трансляции все числовые значения в коде являются константами
– мы берем константу и увеличиваем ее значение на 1.
ну не фигня ли это ?
это то же самое что написать:
1 = 2;
вот если написать
i=1.2345;
foo=0*++i;
то все в порядке, потому что имя переменной - это леводопустимое выражение...
зы: вот мыкс за леводопустимостью следит строго... а пятерка стандарту (как там он называется ?) не соответствует, и ошибку эту выдает, но при компиляции о ней не сообщает...
2Nox Noctis
...Почему фигня то, что "мы берём константу и увеличиваем её значение на 1", я не понимаю....
А по поводу того, что 1.2345 не является леводопустимым выражением..... Давайте возьмём стандат ECMA-262 (он ТАК называется) и рассмотрим следующую цепочку из описания грамматики языка.....
UnaryExpression :
PostfixExpression
delete UnaryExpression
void UnaryExpression
typeof UnaryExpression
++ UnaryExpression
-- UnaryExpression
+ UnaryExpression
- UnaryExpression
~ UnaryExpression
! UnaryExpression
PostfixExpression :
LeftHandSideExpression
..............................................................
LeftHandSideExpression :
NewExpression
CallExpression
NewExpression :
MemberExpression
new NewExpression
MemberExpression :
PrimaryExpression
FunctionExpression
MemberExpression [ Expression ]
MemberExpression . Identifier
new MemberExpression Arguments
PrimaryExpression :
this
Identifier
Literal
ArrayLiteral
ObjectLiteral
( Expression )
Literal ::
NullLiteral
BooleanLiteral
NumericLiteral
StringLiteral
а 1.2345 - по сути является NumericLiteral...........
Это с одной стороны... С другой стороны...
Постфиксный инкримент выполнятеся согласно стандарту следующим образом-
11.4.4 Prefix Increment Operator
The production UnaryExpression : ++ UnaryExpression is evaluated as follows:
1. Evaluate UnaryExpression.
2. Call GetValue(Result(1)).
3. Call ToNumber(Result(2)).
4. Add the value 1 to Result(3), using the same rules as for the + operator (see 11.6.3).
5. Call PutValue(Result(1), Result(4)).
6. Return Result(4).
..............................................
8.7.2 PutValue (V, W)
1. If Type(V) is not Reference, throw a ReferenceError exception.
2. Call GetBase(V).
3. If Result(2) is null, go to step 6.
4. Call the [[Put]] method of Result(2), passing GetPropertyName(V) for the property name and W for
the value.
5. Return.
6. Call the [[Put]] method for the global object, passing GetPropertyName(V) for the property name and
W for the value.
7. Return.
Поскольку Численный литерал не имеет тип "Reference" (его имеют идентификаторы), то "++1.2345" должно выдавать "ReferenceError exception.", чего не происходит...
А происходит то, что Flash 5 вышеприведённом случае ведёт себя таким непонятным и нелогичным образом !!!
В этом-то вся и фигня......
Nox Noctis
13.06.2002, 07:07
так ты же сам и подтвердил все :)
проблема в не-леводопустимости выражения 1.2345 - это не "Reference" => "throw a ReferenceError exception".
...и компилятор пятерки не сообщает об ошибке, хотя код после этого работает черт знает как... это вроде евала в левой части... глюк из той же серии...
а насчет константы - это просто объяснение того же самого другими словами :)
1=2; не смотря ни на что приведет к ошибке, и если это дело замаскировать инкрементом, то это ничего не исправит :)
2Nox Noctis
.... eval в левой части не глюк... Это была возможность возвращать в левой части выражения переменную типа Reference (идентификаторы), что, кстати, допускается стандартом. Зачем эту возможность убрали в MX я пока не понимаю....
... На самом деле удивляет вот что - согласно грамматике языка допускается возможность некоторой операции (в данном случае ++const), но в АЛГОРИТМЕ РЕАЛИЗАЦИИ этой операции такая конструкция считается недопустимой!!! И как тут жить?? Возникает вопрос - что приоритетней: грамматика или алгоритм реализации этой грамматики????
Мне пока непонятно....
Может кто из гуру объяснит??
Nox Noctis
14.06.2002, 14:44
грамматика много чего разрешает...
но это всего лишь формальная правильность, а содержательная правильность проверяется либо во мремя компиляции, либо вообще в рантайме...
а сравнивать что важнее - форма или содержание, это как-то странно ;)
насчет евала в левой части присвоения : самый верхний пост (john'a) (http://www.flasher.ru/forum/showthread.php?s=&threadid=28096&perpage=15&pagenumber=12) :)
...ты видел, кстати, во что транслитруется выражение a = 0*++1.2345; в ассемблерном коде
(в сравнении с a = 0*++(b=1.2345); ) ?
...очень забавно :D
2Nox Noctis
.... Мда..... Мне эта ситуация напоминает поговорку - "Если нельзя, но очень хочется - то можно"! :) Или перефразируя для данной ситуации - "Если можно, но очень не хочется - то нельзя"..... Или нашу Конституцию и законы - Конституция (грамматика) вроде бы позволяет.... но законы (алгоритм реализации Конституции) ни фига...... :((((.... Ладно.... это уже флэйм и к делу не относится.....
Вывод - имеем в Flash 5 законченный БАГ.... Интересно, кстати, Micromedia о нём знает????
ЗЫ во что транслируется данные выражения - видел.... Наверное им можно пугать тех, кто смотрит коды с помощью ASV или SWF Scaner`а..... Кстати, в MX сгенерённый F5 код этой оперции прекрасно выполняется....
Спасибо за дискуссию.
С уважением. Suhoff :)
Nox Noctis
15.06.2002, 03:33
:) :) обращайтесь... ;)
напоследок я все-таки приведу этот кусочек кода c ошибкой... мало ли кому интересно...
из выражения a = 0*++1.2345; при трансляции получается:
push 'a', 0.0, 1.2345
increment
setRegister r:0
setVariable
push r:0
multiply
setVariable
расшифруем:
push 'a', 0.0, 1.2345 // имя и два числа заносиятся в стэк
increment // операция берет верхнее в стэке значение и увеличивает его на 1 прямо в стэке (т е 1.2345+1)
setRegister r:0 // в регистр r0 помещаем верхнее в стэке значение (т е 2.2345)
setVariable // берем последнее в стэке значение и запихиваем его в переменную с именем равному предпоследнему в стэке значению (в данном случае 0.0 = 2.2345 - уже хорошо :)) после присвоения операнды из стэка удаляются
push r:0 // заносим в стэк то, что до этого положили в регистр r0 (это было 2.2345)
multiply // перемножаем два оставшихся в стэке операнда (то есть 'a'*2.2345 :D ) и результат кладем в стэк...
setVariable // проделываем такую же операцию как см. выше... но учитывая, что в стэке у нас всего один операнд в данный момент (да и тот пустой :) ) - получаем полную лажу :D
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.