Skip to content

cappuccino/objjc

Repository files navigation

Objective-J Compiler

A tiny, fast JavaScript and/or Objective-J compiler with built in preprocessor. Written in JavaScript.

It uses a parser extended from the Acorn JavaScript parser by Marijn Haverbeke.

Format generated code

The generated code can be formatted by providing a format description file with the '--formatDescription' option There are some example files in the format folder.

It can also include comments with the '--includeComments' option.

Beautifier

Objective-J is a superset of Javascript. If it compiles a pure Javascript file it will generate the same code back again. This allows the compiler to be used as a beautifier for Javascript.

Preprocessor

The parser has a built in C like preprocessor.

Example:

#define MAX(x, y) (x > y ? x : y)
var m1 = MAX(a, b);
var m2 = MAX(14, 20);

Will be compiled to:

var m1 = a > b ? a : b;
var m2 = 14 > 20 ? 14 : 20;

For more info see http://www.cappuccino-project.org/blog/2013/05/the-new-objective-j-2-0-compiler.html

Objective-J limitations: It can't compile Objective-J code that depends on other Objective-J files. The Objective-J load and runtime is needed for this. But it will work as long as you declare any superclass in the same file. This will be fixed when the Objective-J load and runtime will be a node module

Error checking

objjc has extensive error checking to catch potential errors before runtime. Warnings and errors are displayed in the following format:

<file path>:<line>:<column>: \[warning\|error\]: <message>
<offending line>
<caret column marker>

is relative to the file being compiled. and are one-based.

Here are some examples:

identifiers.j:114:25: warning: local declaration of 'foobar' shadows a variable in a containing closure
                    var foobar = "foobar";
                        ^
identifiers.j:105:17: note: declaration is here
            var foobar = 27,
                ^
protocols.j:34:45: error: cannot find protocol declaration for 'Unknown'
@implementation SomeParent <Person, Parent, Unknown>
                                             ^

As you can see in the above example, objjc adds helpful notes in addition to the warning or error when necessary.

Following is a list of sample warnings and errors caught by objjc, each followed by example code that generated the warning or error. Note in the examples that function is the equivalent of an Objective-J method in terms of scoping variables.

Warnings

local declaration of 'foo' shadows a global variable
foo = 7;

function bar()
{
    var foo = 13;   // warning
}

local declaration of 'foo' shadows a @global declaration
@global foo;

function bar()
{
    var foo = 13;   // warning
}

local declaration of 'foo' shadows a file variable
var foo = 7;

function bar()
{
    var foo = 13;   // warning
}

local declaration of 'foo' shadows a class
@class foo;

function bar()
{
    var foo = 13;   // warning
}

local declaration of 'SomeClass' shadows a class
@implementation SomeClass
@end

@implementation AnotherClass

- (void)haveSomeClass
{
    var SomeClass = 7;   // warning
}

@end

local declaration of 'bar' shadows an instance variable
@implementation Foo
{
    int bar;
}

- (void)foo
{
    var bar = 13;   // warning
}

reference to local variable 'bar' shadows an instance variable
@implementation Foo
{
    int bar;
}

- (void)foo
{
    bar = 13;  // reference shadow warning
    var bar;   // declaration shadow warning
}

This warning only occurs if a reference to a local variable occurs before its declaration.


local declaration of 'window' shadows a predefined global
function bar()
{
    var window = 13;   // warning
}

See the section Predefined globals for information on what names are considered predefined.


local declaration of 'foo' shadows a variable in a containing closure
function bar()
{
    var foo = 13;
    
    setTimeout(function()
    {
        var foo = 7;  // warning
    },
    100);
}

reference to unknown identifier 'baz'
function bar()
{
    var foo = baz;  // warning
}

reference to unknown identifier 'foo'; did you mean 'Foo'?
@class Foo

@implementation Bar
- (void)bar
{
    [foo doSomething];  // warning
}
@end

If an unknown identifier differs from a class or protocol name in case only, the class or protocol name is suggested.


assigning to a read-only predefined global
function bar()
{
    window = 13;
}

conflicting return type in implementation of 'addOneTo': 'double' vs 'int'
@implementation Foo

- (int)addOneTo:(int)value
{
    return value + 1;
}

@end

@implementation Bar : Foo

- (double)addOneTo:(int)value  // warning
{
    return value + 1;
}

@end

conflicting parameter type in implementation of 'addOneTo': 'double' vs 'int'
@implementation Foo

- (int)addOneTo:(int)value
{
    return value + 1;
}

@end

@implementation Bar : Foo

- (int)addOneTo:(double)value  // warning
{
    return value + 1;
}

@end

implicitly creating a global variable in the method 'foo'; did you mean to use 'var c'?
- (void)foo
{
    var a = 7,
        b = 13;
        c = 27;  // oops, this is an unintentional global
}

debugger statement
- (void)foo
{
    debugger;  // warning
}

reserved word used for variable name
var NaN = 7;  // NaN is a JavaScript reserved word

cannot find protocol declaration for 'Unknown'
- (void)foo:(id<Unknown>)  // warning

multiple declarations of method 'foo' found and ignored
@protocol Foo
- (void)foo;
- (void)foo;  // warning
@end

method 'foo' in protocol 'Foo' not implemented
@protocol Foo
- (void)foo;
@end

@implementation Bar <Foo>  // warning
@end

unknown type 'badType'
@implementation Foo
{
    badType ivar;  // warning
}

- (badType)foo  // warning
{
}

- (void)bar:(badType)something  // warning
{
}

Errors

duplicate definition of method 'foo'
@implementation Foo
- (void)foo {}
- (void)foo {}  // error
@end

cannot find protocol declaration for 'Unknown'
@implementation Foo <Unknown>
@end

cannot find implementation declaration for 'Bar', superclass of 'Foo'
@implementation Foo : Bar  // error
@end

dereference expressions may not have side effects
@deref([self someRef]) += 7;  // [self someRef] may have side effects

redeclaration of instance variable 'foo' in class 'Bar'
@implementation Foo
{
    int foo;
}
@end

@implementation Bar
{
    double foo;  // error
}
@end

duplicate definition of class 'Foo'
@implementation Foo
@end

@implementation Foo  // error
@end

duplicate definition of protocol 'Foo'
@protocol Foo
@end

@protocol Foo  // error
@end

'foo' previously defined as a global
@global foo
@class foo  // error

When a global declaration is encountered, the identifier is checked to see if it has already been declared as a global of a different type. This applies to @class, @global, global variables, @interface, @implementation and @protocol.


setter cannot be specified for a readonly property
@implementation Foo
{
    int badProperty @accessors(setter=setBad, readonly);  // error
}
@end

Predefined globals

When checking identifiers, the compiler checks against a list of known predefined globals. Predefined globals refers to the set of globals that are defined as part of the runtime enviroment under which the compiled file will run: browser or node. The predefined globals the compiler checks are contained in the file lib/globals.js. The complete set of predefined globals is defined by the exported objects:

  • reserved
  • nonstandard
  • ecmaIdentifiers
  • newEcmaIdentifiers
  • exports[<environment>]
  • devel (if <environment> is "browser")

The value of each name in these objects is used as follows:

  • If true, the global is writable.
  • If false, it is read only and an attempt to change its value will generate a compiler warning.
  • If an object, the field writable determines whether its value can be changed, and if the field ignoreShadow is true, the compiler will not generate a warning if a local variable uses the same name.

About

JavaScript and Objective-J compiler

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published