Joy Online Manual
Objective C-Style Declarations
Joy allows you to declare variables, functions, and user defined types as you do in Objective-C. Like in C++, a declaration is just another kind of statement, so you don't have to group declarations together at the beginning of a block.
Scoping |
Declarations in Joy are always local to the enclosing function or method, while in Objective-C they are local to the enclosing block. This means that you cannot redeclare a variable in a sub-block without affecting the rest of the function. This is because all JavaScript variables are implemented as properties of objects, and a block does not have any object associated with it at runtime, while a function does. |
Storage classes |
Joy accepts all C storage classes, such as static and extern. At global scope, the default storage class is extern, while inside a method or function it defaults to auto for variables and extern for functions. Declared variables will have a pointer address (you can use the & operator on them), which is not the case for other JavaScript variables.
If you declare a variable extern, Joy will try to resolve the variable name as an external linker symbol (an underscore ("_") is automatically prepended if necessary). If successful, Joy will establish the JavaScript variable at the same external address, so assignments to that variable from JavaScript will automatically propagate to the external variable and any read access will get the most current value. If the symbol cannot be resolved, Joy will silently create a static variable with its own private memory instead. Like in C, a static variable inside a function has local scope but lives across function calls, and it is initialized just once. At global scope, a static variable will just be a global variable in the current interpreter with its own private memory address. Variables with storage class auto or register will both reside on the stack of the currently executing JavaScript function, so their address will become invalid after control has returned from the function. If you declare an extern function prototype, Joy will try to resolve the symbol with the linker, and if successful you can then call the function from JavaScript. Function prototypes declared static are ignored. You can also have C-style function definitions (JavaScript functions with declared return and argument types). The inline keyword is accepted, but ignored. Joy allows you to define new types using standard C typedef syntax. For greater flexibility in parsing system header files, Joy also understands tbe extern "C" { ... } construct. The Joy parser will switch to the C keyword set inside the curly brackets, allowing you to use identifiers that are normally reserved by JavaScript (like var, catch, class, ...). |
EXAMPLES |
Let's declare and access the external variable environ, that contains the environment strings for the current task: |
js> extern char **environ
js> *environ
HOME=/Users/joy
We can also access the environment through the C getenv function: |
js> char *getenv(char *)
js> getenv("HOME")
/Users/joy
Joy understands typedefs: |
js> typedef struct {
int x;
float y;
} Struct
Declare and initialize a variable of the new type (you can pass JavaScript array literals for structs): |
js> Struct s = [10,100]
js> s
{x:10, y:100}
Since we declared that variable, we can take its address: |
js> &s
(struct {
int x;
float y;
} *)0x435164
If we had declared a JavaScript variable instead, we would not have been able to take its address: |
js> var s = [10,100]
js> &s
can't take address of s
Joy understands C-style function definitions. Let's define a function that illustrates the difference between static and stack variables: |
js> int count(void) {
static int x = 0;
int y = 0;
print(x++, y++, &x, &y);
return x;
}
js> count()
0 0 (int *)0x3f1e4c (int *)0x4fb030
1
js> count()
1 0 (int *)0x3f1e4c (int *)0x4fb030
2
The output shows that x is initialized just once, while y is initialized again on each call. Static variables live across function calls, but are not visible from outside the function: |
js> x
x is not defined
Since we know the addresses of both x and y, let's peek at them: |
js> *(int *)0x3f1e4c
2
js> *(int *)0x4fb030
-623191334
The static variable contains the correct value, while the stack variable contains garbage. This is because the function has already returned, making y's address invalid. |
Index |