AngelScript

Global script entities

All global declarations share the same namespace so their names may not conflict. This includes extended data types and built-in functions registered by the host application. Also, all declarations are visible to all, e.g. a function to be called does not have to be declared above the function that calls it.

- Functions
- Variables
- Classes
- Interfaces
- Imports
- Enums
- Typedefs
- Funcdefs
- Namespaces

## Functions

Global functions are declared normally, just as in C/C++. The function body must be defined, i.e. it is not possible to declare prototypes, nor is it necessary as the compiler can resolve the function names anyway.

For parameters sent by reference, i.e. with the `&` modifier it is necessary to specify in which direction the value is passed, `in`, `out`, or `inout`, e.g. `&out`. If no keyword is used, the compiler assumes the `inout` modifier. For parameters marked with `in`, the value is passed in to the function, and for parameters marked with `out` the value is returned from the function.

Parameters can also be declared as `const` which prohibits the alteration of their value. It is good practice to declare variables that will not be changed as `const`, because it makes for more readable code and the compiler is also able to take advantage of it some times. Especially for `const &in` the compiler is many times able to avoid a copy of the value.

Parameters can have default arguments. When a function with default arguments is called, it is not necessary to explicitly inform the value of the arguments, as the compiler can automatically use the default arg. This is especially useful when functions have some arguments that rarely change.

      // Declaration of a normal function
      int MyFunction(int a, int b)
      {
        return a + b;
      }

      // Declaration of a function with default argument
      int MyFuncWithDefArg(int a, int b = 0)
      {
        return a + b;
      }

Todo:
  Promote to individual article, that should explain function overloading, default args, and parameter references

## Variables

Global variables may be declared in the scripts, which will then be shared between all contexts accessing the script module.

Variables declared globally like this are accessible from all functions. The value of the variables are initialized at compile time and any changes are maintained between calls. If a global variable holds a memory resource, e.g. a string, its memory is released when the module is discarded or the script engine is reset.

      int MyValue = 0;
      const uint Flag1 = 0x01;

Variables of primitive types are initialized before variables of non-primitive types. This allows class constructors to access other global variables already with their correct initial value. The exception is if the other global variable also is of a non-primitive type, in which case there is no guarantee which variable is initialized first, which may lead to null-pointer exceptions being thrown during initialization.

Be careful with calling functions that may access global variables from within the initialization expression of global variables. While the compiler tries to initialize the global variables in the order they are needed, there is no guarantee that it will always succeed. Should a function access a global variable that has not yet been initialized you will get unpredictable behaviour or a null-pointer exception.

## Classes

Script classes are declared globally and provides an easy way of grouping properties and methods into logical units. The syntax for classes is similar to C++ and Java.

See also:
  Script classes

## Interfaces

An interface works like a contract, the classes that implements an interface are guaranteed to implement the methods declared in the interface. This allows for the use of polymorphism in that a function can specify that it wants an object handle to an object that implements a certain interface. The function can then call the methods on this interface without having to know the exact type of the object that it is working with.

      // The interface declaration
      interface MyInterface
      {
        void DoSomething();
      }

      // A class that implements the interface MyInterface
      class MyClass : MyInterface
      {
        void DoSomething()
        {
          // Do something
        }
      }

A class can implement multiple interfaces; Simply list all the interfaces separated by a comma.

## Imports

Sometimes it may be useful to load script modules dynamically without having to recompile the main script, but still let the modules interact with each other. In that case the script may import functions from another module. This declaration is written using the import keyword, followed by the function signature, and then specifying which module to import from.

This allows the script to be compiled using these imported functions, without them actually being available at compile time. The application can then bind the functions at a later time, and even unbind them again.

If a script is calling an imported function that has not yet been bound the script will be aborted with a script exception.

      import void MyFunction(int a, int b) from "Another module";

## Enums

Enums are a convenient way of registering a family of integer constants that may be used throughout the script as named literals instead of numeric constants. Using enums often help improve the readability of the code, as the named literal normally explains what the intention is without the reader having to look up what a numeric value means in the manual.

Even though enums list the valid values, you cannot rely on a variable of the enum type to only contain values from the declared list. Always have a default action in case the variable holds an unexpected value.

The enum values are declared by listing them in an enum statement. Unless a specific value is given for an enum constant it will take the value of the previous constant + 1. The first constant will receive the value 0, unless otherwise specified.

      enum MyEnum
      {
        eValue0,
        eValue2 = 2,
        eValue3,
        eValue200 = eValue2 * 100
      }

## Typedefs

Typedefs are used to define aliases for other types.

Currently a typedef can only be used to define an alias for primitive types, but a future version will have more complete support for all kinds of types.

      typedef float  real32;
      typedef double real64;

## Funcdefs

Funcdefs are used to define a function signature that will be used to store pointers to functions with matching signatures. With this a function pointer can be created, which is able to store dynamic pointers that can be invoked at a later time as a normal function call.

      // Define a function signature for the function pointer
      funcdef bool CALLBACK(int, int);

See also:
  Function pointers for more information on how to use this

## Namespaces

Namespaces can be used to organize large projects in logical units that may be easier to remember. When using namespaces it is also not necessary to worry about using names for entities that may exist in a different part of the project under a different namespace.

      namespace A
      {
        // Entities in a namespace see each other normally.
        void function() { variable++; }
        int variable;
      }

      namespace B
      {
        // Entities in different namespaces don't immediately see each other and
        // can reuse the same name without causing name conflicts. By using the
        // scoping operator the entity from the desired namespace can be explicitly
        // informed.
        void function() { A::function(); }
      }