Made to Order Software Corporation Logo

ActionScript Compiler

Back to the SSWF project home page

ActionScript Compiler
(Started in July 2005 — last updated on )

Summary

  1. This document license
  2. This document organization
  3. Input Tokens (lexical)
    1. Identifiers
    2. Numbers
    3. Strings
    4. Keywords
    5. Operators
    6. Comments
  4. Language basic instructions (Grammar)
    1. Program
    2. Declaration
      1. Packages
      2. Classes
      3. Functions
    3. Statements
      1. Block
      2. Break & Continue
      3. For
      4. Goto
      5. If
      6. Switch
      7. Throw and Try/Catch/Finally
      8. Variable
      9. While and Do
      10. With
    4. Expressions
  5. Compiler (what the compiler does)
  6. Optimizer
  7. How identifiers are being resolved (scoping)
  8. ECMAScript basic instructions
    1. eval()
    2. parseInt()
    3. parseFloat()
  9. ECMAScript objects
    1. Object
    2. Boolean
    3. Number
    4. String
    5. Array
    6. Date
    7. Error
    8. Function
    9. arguments
    10. Math
  10. SWF basic instructions
    1. set()
    2. getVersion()
    3. setClipboard()
    4. eval()
  11. SWF instructions
    1. Timer functions
    2. MovieClip functions
  12. SWF objects
    1. Low level extensions (in Global package)
    2. System.accessibility
    3. Button
    4. Camera
    5. Color
    6. CustomActions
    7. Key
    8. LoadVars
    9. LocalConnection
    10. Menu
    11. Microphone
    12. Mouse
    13. MovieClip (or Sprite)
    14. NetConnection
    15. NetStream
    16. PrintJob
    17. Selection
    18. SharedObject
    19. Sound
    20. Stage
    21. TextField
    22. TextSnapshot
    23. Video
    24. XML
  13. SSWF extensions
    1. parseBoolean()
    2. Complex numbers



1. This document license

Copyright (c) 2005-2009 Made to Order Software Corp.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


2. This document organization

The document is divided in two main parts: the quick description of how the language works (lexical and grammar) and a lengthy list of all the objects available in the Flash Macromedia players.

Note that the description of the language is mainly for people who already know how to write programs in either Javascript, C, C++, ActionScript or any similar language. If you are not familiar with any of these languages you certainly want to look into a tutorial for these before to read on.

This document will especially list all the extra options available in the SSWF implementation of the language. For instance, you can use a label with the break and continue instructions which you can't with the Macromedia implementation (as of version 7.x). There are additional operators, functionalities in the grammar, different pragmas, extension classes and functions... and this documentation! 8-) [no kidding! no one else has this doc., right?]


3. Input Tokens

The different tokens in the ActionScript compiler are recognized by our lexer while reading some input text file.

The library only accepts USC-4 characters as input. If you need to convert your input file, use the iconv(1) tool. It is capable of converting almost any encoding to USC-4.

The recognized tokens are as follow:

  1. Identifiers (A-Za-z0-9_$)
Identifiers can't start with a digit. The $ character should not be used but by software generating ActionScripts. The case is significant. So the identifiers Test and TEST are different.
  1. Numbers
Literal numbers include:

Type
Simplified Lexical
Integers
[0-9]+
Hexadecimal
0[xX][0-9A-Fa-f]+
Floating Point
[0-9]+.[0-9]+[eE][-+][0-9]+
Infinity
Represents the positive infinity
NaN
Represents a value defined as a "Not a Number" value
Octal
0[0-7]* — optional, use -o on the command line or the use octal; pragma to have access to this feature
  1. Strings
It is possible to write strings. A string is written between single (') or double (") quotes. A string can't include a new line character. You can use the backslash character inside a string to include a special character, including a quote. To write really long strings, you can use the concatenation operator (+). The following table lists the available backslash sequences.

Similar to strings, you can define a regular expression using backward quotes (`). At this time, the SSWF implementation doesn't make use of regular expressions because the Flash Macromedia players don't support them. We may add an extension to support some basic regular expressions at some point (so we can support the match (~=) operator).

Sequence
Comment
\0##
Insert a Unicode character (up to 3 digits); The character is defined as an octal number
\b
Insert a backspace (0x08)
\e
Insert an escape character (0x1B); this character is available only when the extended escape sequences are supported
\f
Insert a form feed (0x0C)
\n
Insert a new-line (0x0A)
\r
Insert a carriage return (0x0D)
\t
Insert a tabulation (0x09)
\u####
Insert a Unicode character (4 digits); The character is defined as an hexadecimal number
\U########
Insert a Unicode character (8 digits); The character is defined as an hexadecimal number
\v
Insert a vertical tabulation (0x0B)
\x## or \X##
Insert a Unicode character (2 digits); The character is defined as an hexadecimal number
\' or \" or \\
Insert ', " or \ as is.
other
Any other sequence generates an error.

  1. Keywords
A Keyword is an Identifier representing a word used in the language. The following table list the keywords used in the ActionScript language:

Identifier
Comments
as
Compare two expressions for similarity
break
Break a for(), do/while() loop or a switch() statement. It can specify a label in which case it can break a loop or switch() other than the current one.
case
Defines an expression to compare with the expression defined in a switch() statement.
catch
Catch an error of a given type.
class
Starts the definition of a class.
const
Defines a constant variable.
continue
Restart a for(), do/while() loop. It can include a label in which case it can restart a loop other than the current loop. SSWF Extension: if the label references a switch(), then the switch() is repeated after the switch() expression was re-evaluated.
default
The default label to use in a switch() statement. It can appear anywhere, but just once per switch statement.
delete
Delete the specified instance of an object.
enum
Define a list of numeric variables with an automatic increment of 1.
extends
Used to extend a class definition. One class can only extend one class; in other words you can't have multiple inheritance like in C++ (the super instruction is one reason)
false
The boolean value false.
finally
The block to execute to terminate a try block whether an exception occurred or not.
for
Initialize, test and increment loop definition.
function
Starts the declaration of a function.
goto
Go to the specified label. This instruction is recognized only if extended statements were enabled. You can goto through any block except a function block.
if
Branch on a condition.
implements
Used to define a class that implements the named interface(s).
import
This instruction allows you to declare external packages and import them when you need them.
in
Check whether a property is defined in an object (expression). In a for() statement, it can be used to define a list of properties to walk through.
instanceof
To know whether an object is of a specific type.
interface
Starts the declaration of an interface.
is
To know whether an object is of a given type.
namespace
The name space or name of a package or class.
new
Operator used to create a new instance of an object.
null
The value used to initialize an undefined object reference.
package
Starts the definition of a package.
private
The private attribute.
public
The public attribute.
return
End a function by returning the result of the following expression. End a procedure (a function without a return type).
super
Reference to the class this object was derived from.
switch
Starts a switch()/case/default statement.
this
The special reference to this object. In an ActionScript, this is always available since at least you are in a MovieClip. [to be confirmed]
throw
Raises an exception.
true
The boolean value true.
try
Create a protected, exception wise, set of statements.
typeof
Defines the type of an expression as a string.
undefined
The value used when you try to access a variable which wasn't defined (set/assigned to) yet.
use
This keyword is used for pragma definitions and scope (namespace) extension.
var
Declares a variable.
void
The special type void. Used to cast expressions and declare procedures.
with
Extend the current scope with the specified namespace.
while
Loop on a condition.
  1. Operators
The ActionScript recognizes many single or sequence of punctuation characters as operators. The following table describes the available operators. Note that some operators are keywords. Also, some operators are only available when extended operators are turned on. These are specified in the following table as well.

The SSWF implementation supports operator overloading. It is actually used to make sure that the operators are used properly in your scripts (since an operator overloaded is a function and a function can be marked as intrinsic, we can use the language features to make sure that the compile works properly).

The following shows you the definition of the additive operator for integers:
	intrinsic function "+" (i: Integer, i: Integer): Integer;
Note that the conditional operator (?:) and the keyword operators can't be overloaded at this time (the new, delete, for+in should be available). Also, whenever the compiler finds an overloaded operator used in an expression, it will keep it as is if the function is marked as intrinsic, otherwise it transforms the operator syntax in the tree by a CALL of a member function.

At times, it makes more sense to define a function in the class defined in the right operand. In C++ this is done by creating a friend function. Since ECMAScript always defines functions for binary operators with two parameters, there is no need for any special attribute:
	function "&" (i: Integer, s: String): String;
This means writing 5 + "a" is resolved by this function. The integer will be converted to a string which is then concatenated to the other string.

Unary operators take one operand which needs to have its type defined to the class name which includes the operator. Note that operators can only be defined in a class to work properly.

The Netscape ECMAScript version 4 specification says that a few operators should not be overriden. These include all the assignment operators, "!=", "!==", "!", "||", "&&" and "^^". At this time, the SSWF implementation doesn't prevent you from implementing these operators. It is not unlikely that I will add an error later unless you use a specific command line option or pragma to enable overloading of non-intrinsic operators.

Operator
Comments
Unary
~
Bitwise not
!
Logical not
+
Positive
-
Negative
++
Increment
--
Decrement
delete
Deletes an instance
new
Creates a new instance
super
A reference to a class this object was derived from
typeof
Determines the type of an expression
void
Cast the result of an expression to void (undefined)
[ ]
Reference, array indice(s), array definition
( )
Expression grouping and arguments
{ }
Object definition
Binary
::
Scope
.
Access a property member
**
Power; the ** operator is available when  extended operators are accepted
*
Multiplication
/
Division
%
Modulo
+
Addition
-
Subtraction
<<
Shift left
!<
Rotate left; the !< operator is available when  extended operators are accepted
>>
Shift right (signed, also called arithmetic)
!>
Rotate right; the !> operator is available when  extended operators are accepted
>>>
Shift right unsigned (also called logical)
<
Less than
<=
Less than or equal to
>
Greater than
>=
Greater than or equal to
~=
Match; the ~= operator is available when  extended operators are accepted [not implemented yet]
as
Check whether the left handside expression is a member of the type specified on the right hand side
in
Check whether a property is defined in an object
instanceof
Check whether an object is an instance of a class
is
Check whether an object is an instance of a class
==
Equal
===
Strictly Equal
!= or <>
Not Equal; the <> operator is available when  extended operators are accepted
!==
Strictly Not Equal
&
Bitwise and
^
Bitwise exclusive or
|
Bitwise or
&&
Logical and
^^
Logical exclusive or
||
Logical or
?<
Return the minimum; the ?< operator is available when extended operators are accepted
?>
Return the maximum; the ?> operator is available when extended operators are accepted
= or :=
Assignment; the := operator is available when extended operators are accepted
**=
Power assignment; the **= operator is available when  extended operators are accepted
*=
Multiplication assignment
/=
Division assignment
%=
Modulo assignment
+=
Addition assignment
-=
Subtraction assignment
<<=
Shift left assignment
!<=
Rotate left assignment; the !<= operator is available when extended operators are accepted
>>=
Shift right assignment
!>=
Rotate right assignment; the !>= operator is available when extended operators are accepted
>>>=
Shift right unsigned assignment
&=
Bitwise and assignment
^=
Bitwise exclusive or assignment
|=
Bitwise or assignment
&&=
Logical and assignment
^^=
Logical exclusive or assignment
||=
Logical or assignment
?<=
Minimum assignment; the ?<= operator is available when extended operators are accepted
?>=
Maximum assignment; the ?>= operator is available when extended operators are accepted
,
List of expressions
Tertiary
?:
Conditional operator

  1. Comments
ActionScripts accept two types of comments like C/C++. The one line comment starting with // and going to the end of the line and the long comments introduced with /* and ending with */.

Note that either way, a comment is seen as a blank and thus the following defines two identifiers:

Start/* a comment */Stop




4. Language basic instructions

The following is a simplified reference on how to use the basic keyword in an ActionScript. Note that this is very similar to Javascript and thus if you want to have a tutorial, read a Javascript tutorial if you can't find an ActionScript tutorial. Note that the Macromedia website had quite many pages explaining how to use their objects and how to use their language. This implementation is mostly compatible.

The language in SSWF is based on the ECMAScript version 4 as written by Netscape in 1999 and enhanced until 2003. At the time of writing, the documentation could be found here: http://www.mozilla.org/js/language/es4/index.html. In case it doesn't work anymore, try to search for "ECMAScript 4 Netscape Proposal". This document is based on the ECMAScript version 3 and ECMAScript version 4 (note that version 4 of the ECMAScript is still being worked on).
  1. Program
Any ActionScript is a program. A program is composed of declarations and statements. Statements can include expressions which are described separately. When the program runs, the statements are executed. The statements will make use of the declarations as required.
  1. Declarations
A declaration defines an element which late can be reused in different statements or other declarations.

There are three major declarations: a package, a class and a function. Note that there isn't really a variable declaration. Variables are always being initialized and for this reason they are always viewed as statements in our implementation. Non the less, most people will consider those declarations. Yet, for the purpose of this documentation, it won't be defined in this chapter.

Packages can later be imported. This is how you create modules that you reuse as you write more and more ActionScripts.

Classes enable you to declare object definitions. These can be used to create object instances.

Functions are lists of statements to execute without having to replicate these over and over again. We often see function definitions in classes and packages.


    1. Packages
A package declaration goes like this:
	<attributes> package <name> '{' ... '}'
A package can receive the following attributes:

Attributes
Comments
false
A package marked false will be ignored. This can be used to create conditional parsing.
intrinsic
A package marked as intrinsic offers a set of objects which are always available in the executing environment. In case of the ActionScript, for instance, you always have access to the MovieClip class and all of its functionality.
true
A package marked true will be included in the parsed script.


    1. Classes
A class definition can be used to create a new object, to extend an existing object or to define one or more interfaces. The following shows a class definition:
	<attributes> class <name> [ extends <name> ] [ implements <name> {, <name>} ] '{' ... '}'
The extends and implements parts are optional. A class can implement as many interfaces as it wants. It can, however, only extend one other class. The order in which the extends and implements are given is important in ECMAScript, it isn't for us (you can first use implements and then extends). Also, the order in which the extends and implements are defined isn't important because the compiler will always test all of them to find the corresponding entry. Note that if two or more entries match, then an error is generated (you can't have two fields with the same name in two interfaces and inherit both and hope it works properly.) A class can receive the attributes as defined in the following table. Most of these attributes can individually be applied to the members of the class.

Attributes
Comments
dynamic
Objects of that class can dynamically receive new variable and function members.
enumarable
Whether the class members can be enumerated.
explicit
When marked explicit, a member can only be used with a qualifier.
false
A class marked false will be ignored. This can be used to create conditional parsing.
final
The entire class can't be extended.
intrinsic
A package marked as intrinsic offers a set of objects which are always available in the executing environment. In case of the ActionScript, for instance, you always have access to the MovieClip class and all of its functionality.
true
A class marked true will be included in the parsed script.

Note that when you don't specify any extends name, a class automatically extends Object.


    1. Functions
A function definition is very useful to avoid writing very long programs in one stretch. Not only can a function be reused in a program, when defined in a package, it can be re-used across projects. The following gives the definition of a function:
	<attributes> function [ <name> ] '(' [ parameter { , parameter } ] ')' [ ':' type ] '{' statements '}'
A function accepts the following attributes:

Attributes
Comments
abstract
The member function needs to be declared in an extension of this class.
constructor Defines a function member as a constructor.
enumarable
The function will be enumerated.
virtual
The function can be overloaded.
inline
The function statements will automatically be inlined.


Functions can be unnamed. In general this happens when a function is declared with a label or when they are to be assigned to an object. In that later case, the assignment will provide a name to an object member. That will be the name of the function. Note that when using a function in this way, it can be assigned to multiple objects as required.

The name of a function can be any valid identifier, which is the default. It can be one of the keywords get or set followed by an identifier which defines a getter and setter function. And finally, the name can be a string representing a valid ActionScript operator.

The getter and setter functions are actually functions used to simulate a variable member that you can read and write to. This is useful whenever a variable needs to be checked (i.e. only a value of 1 to 10 is valid, the setter function can make sure that you don't set the variable to 25 for instance).

The use of a string is to declare a function which is an operator. This should only be used in a class, thought it is possible to use it outside too. Operators are declared like in C++, except for the name which has to be a string. For instance, you can declare an addition to a class named foo like this:
	function "+" (right_hand : foo) : foo { ... }
The list of parameters defined for a function can be empty and as long as required. Each parameter can have attributes as follow and when calling a function the name of the parameter(s) can be used to make sure that the right parameter receives the right value. The last parameter can be defined as the rest (...) of the input parameters. This uses the ellipsis. Note that the rest can be named (but I think we won't be able to use that with the Flash player from Macromedia, but I'm thinking there is a way to use the arguments variable instead.)

Parameter
Attributes
Comments
void
Can appear only by itself. Used to mark a function as not having any parameters.
unprototyped
Used to specify that this function doesn't have a prototype. This is used to allow a return value definition (otherwise using the type Function is better) when a variable is of type Function. Like void, unprototyped can only appear by itself.
...
Called rest, this defines a function which can accept a variable number of parameters. The extract parameters can be accessed using the arguments array. A rest can be named:
MyFunc(a, b, ... rest) { ... }
const
Mark the parameter as a constant. This means the input variable can't be modified within the function.
in
This parameter is an input variable. It is expected to be defined (doesn't have to be) and it won't be modified for return by the function.
var
This is noise used to mark the parameter name as being a variable.
out
The variable will be modified by the function and its result is returned to the caller. An out variable can't be defined as a constant. A parameter can be an in and out variable at the same time. A function is not required to initialize an out variable. Note also that this is an SSWF extension.
named
This is noise used to mark the parameter as one which can be named whenever a function is being called. We always authorize all the variables to be named when a function is being called.
unchecked
Variables marked unchecked don't need to be initialized when the function is being called. This is useful whenever a function declares a variable without a default initializer and the caller doesn't define a value. In this case, the variable will be set to undefined.

The list of parameters of a function can be followed by a type declaration. When no type is defined or the type is void, the function is considered to be a procedure (i.e. it can't return anything). When there is a type other than void, the function must return a value of that type.

When a function is called, its statements are executed. At that time, you have an array called arguments which can be used to access all the parameters using an array notation. This is required if you use a rest (...) in your list of parameters. Some other special variables can eventually be set. These are this and super.

  1. Statements
The statements are very similar to C/C++ and javascript. The following are the statements supported by the SSWF implementation of ActionScript. Note that expressions weren't included since these are described below in chapter 4. Expressions.
    1. Block
	attributes '{' ... '}'
Create a list of statements and definitions with the specified attributes. Some statements such as the if(), for() and while() can be followed by one statement. If you need more than one, then you need to enclose the statements between curvely brackets.

Standalone blocks can be preceded by attributes. That is, a block following certain instructions can't receive attributes. For instance, the try instruction doesn't allow for attributes between the keyword and the opening curvely bracket ({). Note that all the attributes which you can apply to a block can also apply to other statements.

Attributes
Comments
false
When the attribute is defined as false, then the block is no compiled.
true
When the attribute is defined as true, then the block is compiled.

    1. Break & Continue
	break [ label ] ';'
continue [ label ] ';'
The break and continue instructions are used to exit and repeat loops respectively. The break can also be used to end a switch statement and the continue to repeat it (the latter only if the continue has a label). Both instructions can be followed by a label which allows to break or repeat any loop or switch statement. The label is optional in which case it is taken as being default and then the innermost loop is exited or repeated or the inner most switch is broken (you can't repeat a switch() if you don't use a label).

Note that using the continue instruction with a label of a loop which isn't the innermost loop very much acts like a break of all the inner loops until the loop to continue is reached.

The label specified after these instructions must directly precede the instruction to be broken or continued.

The break and continue can be used between any boundary other than a function. In other words, you can break a loop from a try/catch or a with statement. All the necessary unwinding will be done by the compiler as expected.
    1. For
	for '(' expression ';' expression ';' expression ')' statements
for '(' expression in expression ')' statements
Create a for loop. In the first case, the 1st expression is expected to declare one or more variable, the second expression compares the different variables and the third computes the next value for the variables declared in the first expression. Note that there is no tests to know what the expression really are and thus they don't actually need to match the default description.

The second version of the for instruction allows for loops over all the enumerable properties of an object, over a range or a list of expressions.

As long as the second expression is true or the for statement includes a property or other item to run, the statements following the for will be run. If you need more than one statement, put them in a block.
    1. Goto
	goto label ';'
The execution continues at <label>. This is an SSWF extension as neither Javascript nor ECMAScript support a goto instruction.

SSWF supports a goto to jump from anywhere to anywhere except between a function boundary (or within declarations in a function.) So you stop excution in a try/catch and continue outside it. The compiler will take care of the unwinding which in the case of a try/catch/finally will run the finally statements first.
    1. If
	if '(' expression ')' statements [ else statements ]
When expression is true, execute the following statements. If it is false, execute the statements after the else if it exists.
    1. Switch
	switch '(' expression ')' [ with ['('] operator [')'] ] '{' case/default '}'
Compute expression, then search for a matching case. If none of the expressions in the different case statements match, execute the default statements, if any. Otherwise go after the switch statement at once. Only the list of intructions within the one selected case are executed. The statements of the following case don't just follow the statements of the previous case (i.e. it is NOT like in C/C++).

The with operator in a switch() statement is an SSWF extension. By default, a switch() statement uses the strictly equal comparison operator (===). Here you can specify which operator you want to use: equal (==), strictly equal (===), match (~=), in as, instanceof, is, less (<), less or equal (<=), greater (>), greater or equal (>=), mask (&).

You can use the break instruction to exit a case statement right away (in an if() statement for instance). The break is not required at the end of a case. It is implicit.

SSWF has another extension which allows a continue statement to repeat a switch() statement when the continue is used with the label preceeding the switch() statement. This repeats the switch() by first re-evaluating the switch() expression and then by searching all the cases again.

NOTE: what we are missing:
  • A way to continue through to the next case statement (as in C/C++); I propose the special statement: false break; so just that one case can continue or the use of a special attribute on the switch statement: nobreak switch( ... ) ... in which case all the case statements will continue unless there is an explicit break.
  • A way to continue the search of a valid case which can be useful when the switch was used with the with operator and not the strictly equal operator. I propose the special statement: continue case; for case specific continuation and the special attribute foreach on the switch statement: foreach switch(...) with(...) { ... }.
    For instance, the in operator used with ranges could be used to match several overlapping cases. The search would still be stopped by a usual break, continue, goto and throw.
  • A way to check all the matching cases before any of their statements are executed. This is important in case the case expressions aren't constants and some of the case statements would change the following case value. This is similar to the previous case, and will work when the switch statement is used with the foreach attribute. We could also have two other attributes serial and parallel which would select the scheme to use here. At this time, SSWF only supports the foreach attribute and assumes the user wants parallelism.

    1. Throw and Try/Catch/Finally
	throw expression ';'
try '{' statements '}' [ catch '(' typed variable ')' '{' statements '}' ] [ finally '{' statements '}' ]
The throw statement is used to raise an exception. Exceptions can be caught using the try instruction.

The try block runs what is called a protected block of statements. If an exception occurs while running the statements in the block of statements following the try keyword, then it won't stop the script. Instead, the execution will continue with the corresponding catch (i.e. the catch which variable type is the same as the type of the exception expression). Either way, the execution passes on to the statements defined in the finally block.

Only one catch will be executed whenever an exception occurs. Each catch needs to define a variable name with a different type. The last catch can defined just a variable name in which case any other type will match. The comparison for the type is done with the strictly equal operator (===) and the typeof keyword.

Note that as an extension, SSWF accepts a standalone try statement. In this case, SSWF may have to add an empty finally for the loop to work with SWF players.
    1. Variable
	var name [ ':' type ] [ '=' expression ] ';'
Define a variable and initializes it. Note that a variable declaration is viewed as a statement because of the initialization. Thought, when defined as a member of a class, you aren't supposed to have an expression (thought we support it) and the variable is set to undefined by default (when no initializer is provided.)

The type is an expression which can be used to make sure that the variable is used properly. Note that the Flash Macromedia player doesn't actually test for the variable types and thus for now only obvious compile time errors will be reported. This will, however, be useful in different circumstances like when a try instruction caught an exception and the proper catch is searched (again, the player doesn't support more than one catch, so we have to simulate the multi-catch using the variable type at runtime).
    1. While and Do
	while '(' expression ')' statements
do statements while '(' expression ')'
Repeat the statements as long as expression is true. In case of the do/while(), the loop is executed at least once. In case of just while(), it is executed only if the expression is true at least once.
    1. With
	with '(' expression ')' statements
Compute expression which needs to result in a type. Add that type to the current scope. This means you can avoid writing many references within the statements following the with instruction.



  1. Expressions
Expressions are composed of all sorts of statements such as increment, decrement, function calls, assignments, construction and destruction of objects...

Expressions use operators as defined in the lexical (Operators). The order of the operators as defined in the lexical defines their priority. The following table shows you in more detail the priority since some operators such as * / and % share the same priority. Note that all the unary operators are considered to all have the same priority even thought they don't exactly are defined that way (i.e. in the expression ++a-- the decrement is called first; in general, postfix operators are called first). If you want to make sure of the order, then use parenthesis.

Operators by Priority
Comments
~ ! + - ++ -- [ ] ( ) { }
this, number, string, regular expression
null, true, false, undefined, infinity, NaN
delete, new, super, typeof, void
variable name (identifier)
+ as positive
- as negative
::
Scope
.
Member
**(1)
Power
* / %
Multiplicative
+ -
Additive
<< !< >> !> >>>
Shift
< <= > >= ~=
as in instanceof is
Relational
== === != <> !==
Equality
&
Bitwise And
^
Bitwise Xor
|
Bitwise Or
&&
Logical And
^^
Logical Xor
||
Logical Or
?< ?>
Min/Max
?:
Conditional
= := **= *= /= %= += -= <<= !<= >>= !>= >>>=
&= ^= |= &&= ^^= ||= ?<= ?>=
Assignments
,
List
(1) the power operator is the only one which works right to left:
a ** b ** c means a ** (b ** c) and not (a ** b) ** c

I'm not defining here all the possible conversion happening in an ActionScript because it would be very long. More or less, if you have two numbers, normal mathematical arithmetic is used. If you have a number of a string, the string may be transformed to a number if possible, in which case, normal mathematical arithmetic is used. In all other cases, string arithmetic is used.

You can add two string together in order to concatenate them. Our implementation accepts + and & for concatenation which can be misleading since if the string can be transformed to a number, it will be added (+) and not and'ed (&).

Only the typeof, +, &, [ ], ?<, ?>, relational and equality operators work with strings. We may later add support for some extensions such as * (repeat), positive (uppercase), negative (lowercase), ~ (swap case), !< and !> (rotate).

Numeric arithmetic will be done with doubles unless both operands are integers in which case 64 bits integers are used.

Operators can also be applied to objects whenever these overwrite the operators as required (See the extension implementation of complex numbers as a good example). Otherwise, only a few operators act on objects: member (.), array notation ([ ]), new, delete, super, typeof, instanceof, as, in, is, ==, ===, !=, !==.








5. Compiler

The following table describes what happens whenever the compiler transforms the tree created by the parser. The idea is that the final tree will be easily reusable by your own software to execute the result or compile the code to binary (in case of Macromedia ActionScript, we have to compile the result to binary).

There are two main things that the compiler will do for you:
  1. Check identifiers and resolve them (especially identifiers which represent constants, these are replaced by the content of the constant at once). Note that by default the compiler will be silent about non-existent variable and function members of dynamic objects. This is because dynamic objects can be grown to where it will not matter whether the function exists at compile time. With a command line flag to asc, you can get the compile to generate an error or a warning for these identifiers.
  2. It will also transform different constructions to other types of constructions so it is easier to implement the execution of the resulting code. For instance, a switch() + statements can be transformed to a list of if()'s. This can be useful since some cases can automatically be removed at compile time (i.e. switch() of an integer will never match a case of a floating point with a decimal part).
Note that the compiler will make use of the optimizer to know whether an expression is a constant expression or not and what its value is (of interest to optimize in many different cases).

Also, when the compiler finds a symbol which it can't resolve until it reaches a corresponding import (i.e. foo.blah matches import foo), it loads that import module. This means the compiler may use the lexer + parser internally. In all cases, the import is resolved into a file on your hard disk (see the -I option for the asc tool).


Construct
Transformation
Comments
Variable identifier in an expression
(i.e. a = b + c)
The identifiers will point to the corresponding declarative node (this is scope dependent and it can be pretty complicated.)
In this case there are two things which the compiler tries to determine:

(1) it searches for the identifier 'a'; if it can find a var (or const) declaration, then that one is used; if no such declaration is found, then the compiler can be setup to generate an error; by default, however, it will add a declaration automatically (i.e.  the a = b + c becomes var a = b + c)

(2) it searches for the identifiers 'b' and 'c'; if it finds a var declaration, it links to it; if it find a const declaration, then it replaces the identifier with the value of that constant
Member identifier in an expression
(i.e. a.b.c)
The first identifier will point to the corresponding class declaration and the second, third, etc. to the corresponding member in that class. The member can be a member function as well as a member variable.
Note that by default the compiler will accept identifiers as members even if these are not defined in any of the corresponding class unless the class is marked as non-dynamic (in which case no additional members can be added to that object at run time).

It is possible to ask for the compiler to either warn or err on such problems.
const name = <expr>;
Checks whether that <expr> is indeed a constant expression. When that's the case, this definition doesn't generate any statements in the final output.
References to a compile time constant will directly be replaced by the resulting constant expression. This is why the constant doesn't generate a statement in the final output.
switch() + statements
temp = <switch expression>
if(temp === case1) goto case1
if(temp === case2) goto case2
   ...
if(temp === casen) goto casen
goto default_statements;

statements of case1
statements of case2
statements of casen
   ...
statements of default
The transformation presented here is over simplified. More or less, we compute the switch expression once. We save it in a temporary variable which we reuse to compare to each case expression. If it matches, then execute the corresponding statements.

If the statements end with a break, then it will automatically add a goto statement to skip everything up to after the default statement. Similarly, if there is a continue, it will goto to the corresponding loop.

When there isn't a default label, the switch() statement doesn't have any reaction and the goto default_statements is replaced with a goto after_switch.
break <label>;
goto <label>;
A break is equivalent to a goto. It will be easier to only implement one instruction such as a goto rather than a break and a continue.

Note that a break used without a user label still is transformed to a goto with an automatically generated label.
continue <label>;
goto <label>;
This is very similar to a break except in the case of a for(), it goes to where the 3rd expression is defined and run the test as defined by the second expression. Also, in the case of a while() it will run the test again before to repeat the loop.
for(<expr1>;; <expr3>) + statements
<expr1>
$start$:
  statements
$repeat$
  <expr3>
goto $start$;
Repeat the statements forever. Whenever the 2nd expression is empty (or constant and resulting in true), this instruction is transformed to a loop forever program.

If the 2nd expression is a constant and it ends up being false, then the entire loop is removed except for the first expression.

The compiler can be setup to warn whenever a loop forever is created by putting a true or false constant in the 2nd expression.
for(<expr1>; <expr2>; <expr3>) + statements
<expr1>
$start$:
  compute <expr2>
  if false then goto $done$
  statements
$repeat$:
  compute <expr3>
  goto $start$
$done$:
Transform a for() loop into an initialization with the first expression; a test with the second expression (and the if() + goto as required); run the statements; a computation of the third expression and a goto back to the after the initialization.

A break without a label withing the for() statements generates a goto $done$; a continue generates a goto $repeat$.
while(constant) + statements
$start$:
  statements
  goto $start$;
Run the statements forever if the constant expression is true and remove everything if the constant expression is false.

The compiler can be setup to warn whenever a loop forever is created with a while.
while(<expr>) + statements
$start$:
  compute <expr>
  if false then goto $done$
  statements
  goto $start$
$done$:
Transform a while() loop into a test and an if() + goto().

This is particularly useful if your low level language only supports the if() construct.

A break without a label within the while() statements generates a goto $done$; a continue generates a goto $start$.
do statements while(<expr>);
$start$
  statements
$repeat$:
  compute <expr>
  if true then goto $start$
The do is very similar to the while except that the expression is only evaluated at the end. This means the statements will always be executed at least once.
do statements while(constant);
$start$
  statements
  goto $start$
In case of a constant in a do + while, the loop either runs forever or just once. The goto $start$ is inserted if the constant is true.
if(constant) + if-statements [+ else else-statements]
if-statements or else-statements
Replace the if() statement with one or the other part of the if() whenever the expression is constant at compile time.

The compiler will warn on constant if() since in most cases people don't want them (to remove an instruction, one needs to use an attribute of false instead.)
conditional (?:) versus if() statement
a ? b : c
if(a) b else c
We can, in general, change a conditional into an if() and vice versa. However, there is no point for the compiler to do such a transformation. The problem is that adding an if() statement within an expression may not work for everyone, and having an if() return expressions is not always practical... So for now, I just leave these two instructions alone the way they are.
function () + statements
inline the statements
With a specific flag, you can ask the compiler to replace function calls to user functions by the direct statements of that function. This can be useful in some circumstances, however, it usually won't be a good idea. By default, only functions marked as inline will be inlined if the compiler specify that it is compiling (rather than parsing for immediate execution).
with(<expr>) + statements
temp = <expr>
change statements as required with <expr>.<identifier>
Transform a with into the long syntax. The compiler will try its best at determining which variable should be transformed.
try/catch/finally
(when only one catch supported)
the compiler creates one catch() statement as follow:
catch(error) {
  temp = typeof error;
  if(temp == catch1-type) catch1-statements
  else if(temp == catch2-type) catch2-statements
     ...
  else if(temp == catchn-type) catchn-statements
  else default catch statements
}
If only limited support for the catch() is available (i.e. version 3 of ECMAScript which only supported one catch with an untyped variable) then the compiler can concatenate the catches as presented here. Note that of course this is based on the proper functioning of the typeof instruction.
try/catch/finally
(without exceptions support)
try statements
finally statements
If your implementation doesn't support exceptions, then the try/catch/finally is transformed to just the statements of the try block and the statements of the finally block (if any). The catch blocks are removed.
with block & try/catch block with a goto
...
goto_label = 3
goto $end_block$
...
$end_block$
from here we are not in the block anymore
...
if(goto_label == 3) goto label3;
...
Note that the block of statements after a with(), a try, a catch() and a finally all need to end before you can go to another place. For this reason, the goto instruction needs some special handling.

Note that the for(), while(), do/while() and switch() blocks are broken in regular statements and thus they don't need this trick to be exited.

From within a function, it is an error to try to go to a label outside the said function.





6. Optimizer

The ActionScript library of SSWF comes with an optimizer. In general, once the user script was read with the Lexer and parsed with the Parser, it needs to be compiled. In many places, the compiler expects constants. Because a constant can be expressed as a complex expression, we need an optimizer which can actually compute the expression and return the result.

The optimizer will also look at statements that it can optimize. For instance, a constant if() which is true is replaced by the statements following the if(); a constant if() which is false is replaced by the statements following the else and when no such statements exist, it will return nothing (the if() is removed from the tree). [NOTE: this may be moved to the compiler instead]

The following table shows you the different expressions and statements that the optimizer recognizes and optimize whenever a, b and c are constants. In some cases, we use x, y and z to represent an expression which doesn't need to be constant.

Note that a constant variable is not automatically a constant for the optimizer. The value of a constant variable may only be known at run time. A constant for the optimizer is an integer, a floating point, a string, true or false. Some other values, such as null, undefined and NaN will be taken as constants in some circumstances and will also be optimized.

On the other hand, whenever an expression calls an inline function (a function which was marked as inline when defined), it will be optimized by the compiler and not the optimizer. Also, only functions which access public members can be optimized in this way (for Macromedia Flash, that could certainly be releaved since the resulting objects don't have a concept of private anyway).

Statement
Optimized
Comments
+a
a
Positive is simply removed on intrinsic numbers
-a
(-a)
Negate, returns the negated value
!a
(¬a)
Logical not, returns the inverse of toBoolean() on value
~a
(~a)
Bitwise not, returns value with all of its bits inverted
++a or a++
(a + 1)
increment by 1
--a or a--
(a - 1)
decrement by 1
a ** b
(ab)
a power b
a * b
(a × b)
a multiplied by b
a / b
(a ÷ b)
a divided by b
a % b
(a ≡ b)
a modulo b
a + b
(a + b)
a plus b
a - b
(a - b)
a minus b
a << b
(a shl b)
a shifted left (b & 0x3F) bits*
a >> b
(a shr b)
a shifted right (b & 0x3F) bits*
a >>> b
(a shr b)
a shifted right unsigned (b & 0x3F) bits*
a !< b
(a rol b)
a rotated by (b & 0x3F) on the left*
a !> b
(a ror b)
a rotated by (b & 0x3F) on the right*
a < b
(a < b)
true if a < b, otherwise false
a <= b
(a ≤ b)
true if a <= b, otherwise false
a > b
(a > b)
true if a > b, otherwise false
a >= b
(a ≥ b)
true if a >= b, otherwise false
a == b
(a ≒ b)
true if a is mostly equal to b, otherwise false
a === b
(a = b)
true if a is exactly equal to b, otherwise false
a != b
(a ≠ b)
true if a is very much not equal to b, otherwise false
a !== b
(a ≠ b) true if a is exactly not equal to b, otherwise false
a & b
(a and b)
keep only the bits common to a and b
a ^ b
(a xor b)
keep only the bits not common to a and b
a | b
(a or b)
keep all the bits set from a and b
a && b
(a ∧ b)
true if both a and b are true, otherwise false
a ^^ b
(a ⊙ b)
true if either a or b is true but not both, otherwise false
a || b
(a ∨ b)
true if a or b is true (either one of them or both)
a ?> b
(a ≷ b)
return a if greater than b, otherwise return b
a ?< b
(a ≶ b)
return a if less than b, otherwise return b
a ? b : c
if(a) b else c
return b if a is true, otherwise c
* The (b & 0x3F) is changed to (b & 0x1F) when b is a floating point value.






7. How identifiers are being resolved

Whenever the compiler is invoked, it ensures that all the constructions are valid (i.e. that you used a break within a loop or a switch) and it searches for all identifiers which are not yet resolved (i.e. b and c in a statement such as a = b + c).

In order to search for an identifier, the compiler uses the current scope. This is determined by several factors:
  1. The current with() instructions which are in effect
  2. The current use namespace <name>; which are in effect
  3. The current enclosing block of directives
  4. The parent enclosing block of directives (repeat up to the program block)
  5. The import instructions
For instance, in a class definition, variable members can be defined before or after the different functions which uses them. Also, functions can use each others wherever they are defined in the class.

The program and package blocks works in a similar way as the class definitions. This means you can declare a class A which references class B and declare class B after class A. This can be very useful since in this way class B can also reference class A.

However, if package A requires a class defined in package B and vice versa, you will need to make forward declarations instead. This is done using the class as follow:

class A;

This defines the type A as a class (like in C++).

Whenever the search for an identifier goes through an import directive, it checks whether it matches. If it does, then the corresponding file is loaded, parsed and checked in order to resolve the identifier. In the following example, Math.sin and Math.PI match the import Math directive.

import Math;
...
// sine of angle in degree
var sine = Math.sin(angle * Math.PI / 180.0);

Note that if a use namespace or with() is active, then you can also avoid using the package name Math each time you reference a Math function:

import Math;
use namespace Math;
...
var sine = sin(angle * PI / 180.0);

or:

import Math;
...
with(Math)
{
    var sine = sin(angle * PI / 180.0);
}

The compiler will always try to resolve all the symbols. Symbols which can't be resolved at compile time may still be valid at run time. However, in many cases, the compile will err about those. One way to avoid errors is to declare the dynamic functions and variable members that you will use with an object or another. This way the compiler will know about them and it won't have to guess whether your script is functional or not.







This document was last updated on