^

Documentation

This is the reference manual for the Cor programming language. It will guide you inside language aspects and concepts. Cor is a language designed with large web development in mind. Hence, is possible to develop your software without to execute any command to compile the source code, CLI tools are only needed to make the product able for production environments.

Table of Content

Quick recapInlcuding modulesFunctionsString InterpolationCoroutines/ChannelsSlices/Coalesce Operator/Conditional OperatorClasses/Inheritance/InstanceIf/For/SwitchType Assertion/ErrorsPlatform CompatibilityServersBrowsersSemicolon InsertionWhite SpacesExpressionsCommentsVariables and Lexical ScopingObjectsParenthesis ExpressionsStringsTemplates (String Interpolation)NumbersOperatorsCoalesceExist ConditionalArraysSlicesType AssertionCoroutinesAsynchronic OperatorClassesInitializationInheritanceBuiltin FunctionsCopySuperRegexChanTimeoutModulesStatementsFor loopFor/InFor/In/RangeIf/ElseSwitch/Case/DefaultSelectInc/DecUseCatch/ErrorCommandsHelpRunBuildCompileHttpThe LoaderConfigurationDependence injectionCor in the BrowserThe CRL (Cor Runtime Library)

Quick recap

Inlcuding modules

use './module'     // cor module
use '../jquery.js' // javascript module

Functions

// as a statement
func sum(a, b) {
    return a + b
}

// simplified statement
func sums(a, b) a + b

// as expression
mult = func(a, b) {
    return a * b
}

// simplified expression
mults = func(a, b) a * b


// module initializer
func init() {
    jquery('.panel').html(render())
}

String Interpolation

str = $'hello my name is {person.name}'

Coroutines/Channels

// corotines starts with `go`
go {
    // block until the result is resolved
    accounts = <- fetch.get('http://api.com/accounts')
    for account in accounts {
        //...
    }
}
// unbuffered channel
ch = chan()
go {
    for num in 1:100 {
        // send
        ch <- num
    }
}

go {
    // receive
    c = <- ch
    console.log(c)
}

Slices/Coalesce Operator/Conditional Operator

---
Coalesce operator
---
// if `null` or `undefined` then be an empty array
panels = getPanels() ?? (,)

---
Slice
---
// first 5 panels
five = panels[0:5]

---
Conditional operator
---
five.forEach(func(pan) pan.maximize?())

pan.maximize?()
h = pan?.height
c = pan.children?[0]

Classes/Inheritance/Instance

---
classes are prototype based underlaying
---

class Model {
    // property with default value
    id = genId()
    conn

    // method
    func save() {}
}

---
you can use either a property block, or initializer
but not both
---
class WithInit {
    // initializer
    func init() {}
}
---
inheritance is fully compatible with javascript prototypal inheritance
---
class Person : Model {
    name
    age
    func getName() me.name
    func getAge()  me.age

    // method overriding
    func save() {
        me.beforeSave()
        // super call
        super()
    }
}
---
use `&` symbol to create instances
---

// new instance
person = &Person

// instance and properties setting
person = &Person(
    name : 'John',
    age  : 23,
)

// positional properties setting
person = &Person('John', 23)

// person.name == 'John'
// person.age == 23

If/For/Switch

// module initializer
func init() {
    // if
    if foo == 'bar' {
        sum()
    }

    // infinite for
    for { }

    // like `while (a) { ... }`
    for a { }

    // for-in, works for arrays and objects own properties
    for value in array { }
    for key, value in array { }

    // for-in-range
    for i in 0:10 {
        val = arr[i]
    }

    // classic for
    for i = 0; i < arr.length; i++ { }

    // switch
    switch foo {
        case 1     : doOne()
        case 2     : doTwo()
        // multiple cases
        case 3,4,5 : doThreeFourFive()
        // default case
        default    : doOtherwise()
    }
}

Type Assertion/Errors

func init() {

    // type assertion `expression.(Class/Constructor)`
    func isString(obj) {
        return obj.(String)
    }

    isPerson = obj.(Person)

    func launchError() {
        // throw an error
        error('Error launched')
    }

    ---
    catch evaluates a expression and executes a block
    of code if an error happends
    ---
    catch launchError() {
        // the builtin `error()` function returns the error object
        console.log(error())

        // also can be used to throw an error
        // it rethrows the caught error if no parametter is passed
        error()
    }

}

Platform Compatibility

Coroutines are based in generators, so, if you plan to use concurrency features in old versions of Node.js or browsers without generator support, you must use gnode and/or regenerator. The following platforms are supported without 3rd party tools:

Servers

When using Node.js 0.11.x or greater, you must use the --harmony-generators flag or just --harmony to get access to generators.

Browsers

Chrome between 28 and 38 are supported by turning on an experimental flag.

Semicolon Insertion

Cor grammar uses semicolon to terminate statements, but those semicolons doesn't need to appear in the source. Instead, the lexer applies a simple rule to insert semicolons automatically as it scans, so you can avoid write it. The rule is: If the last token before a newline is an identifier (which includes keywords), a basic literal such as a number or string constant, or one of the tokens: ++ -- ) } the lexer always inserts a semicolon after the token.

White Spaces

The Cor lexer ignores all whitespace characters if they are not part of a token. The tokens that may contain whitespaces are strings and templates. Operators that are composed by the combination of two or more characters, for example, <-, ==, +=... may not contain any whitespace between its characters. See the following example that shows how the semantic differs by splitting a composed operator:

ch <- val  // send `val` to `ch`
ch < -val  // `ch` less than negative `val`

Expressions

Functions

Functions may be defined using syntax such as the following:

// as a statement
func sum(a, b) {
    return a + b
}

// as expression
mult = func(a, b) {
    return a * b
}

It can be used in a simplified way.

func sums(a, b) a + b

mults = func(a, b) a * b

The body of the simplified way is an expression to be returned. This kind of syntax is usefull for callbacks passing, functional nuances ors compact code style.

func init() {
    array.map(func(o) o.id).filter(func(o) o.age >= 18)
}

Comments

Cor supports two types of comments, one line comments, and multi-line comments. The first type starts when the lexer finds // and terminates in the first end of line. The second type starts once the lexer finds --- and ends in the next occurrence of ---. This style is also known as docblock.

Example:

---
sum(a int, b int) int
This function returns the result of a plus b
---
func sum(a, b) {
    // sum two numbers
    return a + b
}

Variables and Lexical Scoping

Cor does not has a keyword to declare variables, instead, Cor declares it for you the first time it is used. If a variable with equal name is declared in outer scope the compiler will assume you are using the declared outside. Unless you write the variable as a simple statement. This technique is called variable announcing.

Example:

outer = 'outer value'

func changeGlobal() {
    outer = 'inner value'
}

func init() {
    changeGlobal()
    console.log(outer) // 'inner value'
}

changeScope function changes the value of outer variable defined in module scope.

outer = 'outer value'

func changeLocal() {
    outer // force to use it as local, even if is declared in outer scope
    outer = 'inner value'
}

func init() {
    changeLocal()
    console.log(outer) // 'outer value'
}

In above fragment, outer variable will be declared in a local scope by announcing it inside changeLocal function.

Objects

Objects are a collection of variables and functions. It may be created using & operator.

// creates an empty object
obj = &Object

// filling properties
obj.name = 'Aaron'
obj.age  = 20

Object properties can be assigned in more declarative way by using Literal Constructors

client = (
    name : 'Aaron',
    age  : 20,
    pet  : (
        name : 'Kitty',
        kind : 'Cat',
    ),
)

There is two ways to access object properties, by using . symbol or by using [ ] wrappers.

client.age = 20
console.log(client.age)
// will print '20'

client['age'] = 20
console.log(client['age'])
// will print '20'

Parenthesis Expressions

A parenthesis expression is bouded by ( and ) symbols, it evaluates depending on what is inside, followig the rules:

  1. If there is just one value it evaluates to that value.
  2. If at least a : symbol, it returns an object.
  3. If at least a , symbol, it return an array.

If one element inside is key-value type, all other elements has to be key-value in the same declaration.

// rule #1, expression
expr = (4)

// rule #2, object
obj  = (:)
obj  = (name: 'john')

// rule #3, array
arr  = (,)
arr  = (1,)
arr  = (1, 2, 3)

Example using key-value pair list:

walter = &Client(
    name : 'Walter',
    age  : 12,
)

Example using expression list:

aaron = &Client('Aaron', 20)

// aaron.name = 'Aaron'
// aaron.age  = 20

Strings

A string is a series of characters delimited by ' symbol, can be defined as following:

aaron  = 'Aaron Swartz'
walter = 'Walter O\'Brian'

// multi-line
query = '
    SELECT
        *
    FROM Article
    WHERE slug = ?
'

Templates (String Interpolation)

Templates or string interpolation is a string literal with trailing $ symbol and curly braces to define the bounds of the expressions within the string, example:

str  = $'Hello {person.name}!'

It is possible to use string delimiters inside the expressions:

str  = $'Hello {person['name']}!'

Numbers

Numbers can be specified using any of the following syntaxes:

// integer
n = 3

// signed
n = +4
n = -8

// with floating point
n = 4.7
n = +6.3
n = -50.2

// with exponential part
n = 4e12
n = 4E12
n = 3e+4
n = 3e-10

Operators

Operators are the following:

// 1 - Assignment
*=  /=  %=  +=  -=  <<=  >>=  >>>=  &=  ^=  |=

// 2 - Comparison
<=  >=  ==  !=  <   >

// 3 - Arithmetic
++  --  +   -

// 4 - Binary Bitwise
&   |   ^

// 5 - Binary Logical
&&  ||  !

// 6 - Binary Shift
<<  >>  >>>

// 7 - Existential
??  ?

// 8 - Async Operator
<-

The operators == and != are translated to === and !== in the same order.

Coalesce

The coalesce operator returns the first value that is not nil nor undefined. nil is returned only if all operands are nil or undefined. It replaces javascript || when substituting default value for nil or undefined values.

Examle:

summary = article.summary ?? article.content ?? '(no content)'

This returns the articles's summary if exists, otherwise returns the content of the article if exists, otherwise retuns (no content).

Exist Conditional

Sometimes code tends to drown a bit in existence-checking. The exist-conditional operator lets you access members and elements only when the receiver exists, providing an empty result otherwise:

Example:

someFunc?()

The above example should be translated to: if someFunc exists, call it. It also can be used with indexes, selectors and slices.

len  = customers?.length
frst = customers?[0]
copy = customers?[:]

Arrays

An array is a collection of ordered values. It may be defined using literal constructor with expressions as elements. Example:

empty  = (,)
colors = ('red', 'green', 'blue')
foo    = (bar(), 56, 'baz')

// accessing
color1 = colors[0]
color2 = colors[1]

// color1 == 'red'
// color2 == 'green'

Slices

Slice expression constructs an array from an existing array, it is a syntactic sugar for the javascript slice method. You can use the syntax: array[start:length], start and length are optionals.

colors = ('red', 'green', 'blue')

sliced = colors[1:3] // sliced is ('green', 'blue')
sliced = colors[:1]  // sliced is ('red')
sliced = colors[1:]  // sliced is ('green', 'blue')

Type Assertion

Type assertions checks if a value is an instance of a class. Having the following syntax:

value.(Class)

The result of type assertion evaluation is a Boolean value.

obj = &Object
isObject = obj.(Object) // true

class Runner {}

rnr = &Runner
isRunner = rnr.(Runner) // true
isRunner = obj.(Runner) // false

Coroutines

Coroutines are blocks containig code that executes asynchronously. It can be defined using the go keyword followed by a block. Coroutines can be also used as expressions, its execution starts once evaluated, it returns a Promise object.

Example:

go {
    // code...
}

Used as expression:

prom = go {
    return 'yosbelms'
}

prom.then(func(s) console.log(s))

// will print 'yosbelms'

Coroutines are based in generators, see platform compatibility

Asynchronic Operator

The asynchronic operator <- allows to block coroutines and wait to receive future values (Promises) if a Promise is returned, also can be used to send values to Channels. Asynchronic operators can be used only inside coroutines (go blocks)

go {
    accounts = <- fetch.get('http://api.com/accounts')
    for account in accounts {
        //...
    }
}

Awaiting a coroutine (idiomatic Cor):

// get articles in the las hour
func findArticlesByTag(tag) go {
    articles <- fetch.get('http://api.com/articles')
    return articles.filter(func(a) a.tag == tag)
}

func renderArticles() go {
    &ArticlesView(<- findArticlesByTag(tag))
}

Classes

A class is a "blueprint" for objects, Cor has its own approach and keeps compatibility with javascript. Unlike javascript's this which references the execution scope, Cor's me identifier is available as a reference to the class instance.

class Client {
    firstName
    lastName
    accounts

    func getName() {
        return me.firstName + ' ' + me.lastName
    }
}

client           = &Client
client.firstName = 'Walter'
client.lastName  = 'Martinez'

name = client.getName()
//name == Walter Martinez

A complex example:

class Client {
    firstName
    lastName
    accounts
}

class Account {
    code
    ammount
}

client = &Client(
    firstName : 'Aaron',
    lastName  : 20,
    accounts  : (
        &Account(
            code    : '3980-121970',
            ammount : 5000,
        ),
    ),
)

me keyword always references the internal scope of the class regardless its actual scope:

class Foo {
    func bar() { }    
    func baz() {
        f = func() {
            me.bar() // call bar method of Foo class
        }
    }
}

In the above example me keyword is used inside a lambda scope, however it references the instance object of the Foo class.

The this keyword is intact, you can use it as in javascript, however it may lead to unsafe code, use this at your own risk.

Initialization

There is two ways to define class initialization. The first way is by declaring a property-set before any method declaration:

class Animal {
    name
    movement

    // methods...
}


// a = &Animal('snake', 'slithering')
// a = &Animal(
//      name:     'snake',
//      movement: 'slithering',
//  )

The second one is by declaring init as the first member of the class. You should use this way case of inheriting from a class defined in a javascript library which relays in constructor e.g: views and models of Backbone.js. Using this approach does not mean there is a init method in the compiled js, it will be translated to constructor, so that if you use super builtin function, it will call the constructor of the super class, see Super (Builtin Function).

Example:

class Animal : Model {
    func init(name, movement) {
        me.name     = name
        me.movement = movement
        super()
    }

    // methods...
}

// a = &Animal('snake', 'slithering')

You can use eiter, init method or property-set, but not both.

Inheritance

Cor supports single inheritance by using : operator. It embraces javascript prototype chain, so it is safe to use it along with any javascript libraries.

Example:

class Shape {
    func getArea() {
        //...
    }
}

class Triangle : Shape {
    func getArea() {
        //custom area
    }
}

In above example Triangle class inherits from Shape class.

Builtin Functions

Copy

The function copy copies object own properties from a source src to a destination dst and returns the destination object.

Example:

orc = (name: 'Orgrim')
copy(orc, (clan: 'Frostwolf'))

---
orc is now
(
    name: 'Orgrim',
    clan: 'Frostwolf'
)
---

Super

The super function calls a method of the super class. It will call the method with equal name to the current method where super is located. It should compile to <SuperClass>.prototype.<Method>.apply(this, arguments)

Example:

class Employee {
    func getSalary() {
        return 3000
    }
}

class Chairman : Employee {
    func getSalary() {        
        return super()*2
    }
}

Calling super with parameters:

class Window {
    func show(position) {
        me.renderTo(position)
    }
}

class DialogBox : Window {
    func show() {
        super('center')
    }
}

Regex

The regex function enables to use regular expressions in Cor. The regular expression syntax is equal to JavaScript regular expressions.

reg  = regex('pla[a-z]?')
// with flags
regf = regex('gi(t)+', 'ig')

Furthemore, it can be multilined:

r = regex('
    pla
    [a-z]?
')

Chan

chan(bufferSize, tranformer)

The chan function creates a channel. A channel is a structure to allow comunication and synchronization between coroutines.

Channels can be buffered or unbuffered. When sending data through unbuffered channels it always blocks the sender until some other process receives. Once the data has been received, the sender will be unblocked and the receptor will be blocked until new data is received. Unbuffered channels are also known as synchronic channels. When some data is sent to a buffered channel it only blocks the coroutine if the buffer is full. The receiver only blocks if there is no data in the buffer.

The created channels are objects that can be closed using .close() method, to check whether is closed or not use .closed property.

Example:

// unbuffered channel
ch = chan()
go {
    for num in 1:100 {
        // send
        ch <- num
    }
}

go {
    // receive
    c = <- ch
    console.log(c)
}

Transformer example:

// transform value*2
ch = chan(nil, func(s) s*2)

go {
    ch <- 1
    ch <- 2
    ch <- 3
}

go {
    console.log(<- ch)
}

---
output:
2
4
6
---

Timeout

timeout(msecs) The timeout function blocks the execution of a coroutine during the specified milliseconds.

Example:

go {
    timeout(100)
    console.log('after 100 milliseconds')
}

Modules

A module is a .cor file containing definitions and declarations that can be used by other modules. Variables, classes and functions defined in a module are all exported without needing a keyword or a special statement. The name of the file is the name of the module with .cor suffix.

Cor modules are CommonJS compliant, so it is possible to use Cor modules from javascript and vice versa, whenever it implements CommonJS specifications.

Example:

// math.cor

PI = 3.141592

func circleArea(r) {
    return r * r * PI
}

class Circle {
    radius
    func area() {
        return circleArea(me.radius)
    }
}

This module exports PI variable, circleArea function and Circle class. Once a module is required, it initializes by executing(if exists) a function named init. Modules initializes the first time is required.

Example:

http = nil

func init() {
    http = &HttpServer
}

Once this module is initialized, http variable will have an instance of HttpServer class.

A module may only contain variable declarations, functions, classes, and use statements.

Modules which the first letter of its name is uppercased only exports the construction (variable, class or function) which has the name equal to the module name. This convention replaces CommonJS module.exports however is completely compatible whith it.

Example:

Let's suppose we have the following project structure:

app
  |── app.cor
  └── model
        └── User.cor

In model/User.cor

class User {
    username
    password    
}

There is a class named equal to the filename, so it will be exported by default. Any other function or variable defined in the module wil not be exported.

In app.cor

use 'model/User'

func init() {
    u = &User('ragnar', 'secretpass')
}

Don't need to qualify the name when importing throwgh use statement because the class User will be exported as default.

Statements

For loop

For loops similar to javascript For statement, but with higher flexibility. It has two syntaxes, the first is:

for Start; Continuation; Statement {
    Statements
}

Example:

fruits = ('orange', 'apple', 'pear')

for i = 0, len = fruits.length; i < len; i++ {
    console.log(fruits[i])
}

// orange
// apple
// pear

Each one of these expressions can be empty.

// infinite loop
for ;; {

}

// whith only ContinuationExpression
for ; i == len; i ++ {

}

The second syntax is more compact than previous, it replaces while statements founded in many programming languages. The syntax is:

for Condition {
    Statements
}

Example:

// executes while i is less than 10
for i < 10 {
    i++
}

// executes while cm is truthy
for cm = comments.next() {
    cm.show()
}

// infinite loop
for {

}

If you need to jump to the next iteration or to get out of the current curl, break and continue are there for you, it behaves exactly as in javascript.

array = (4, 3, 'Cor', 'PHP', 5, 'Go', 1, 7, 'Python')
langs = (,)

for item = array.shift() {
    if item.(Number) { continue }
    langs.push(item)
}

For/In

A for/in loop provides the easiest way to iterate collections. There are two syntaxes; the second one is a slight extension of the first.

The first syntax gives access to the current value in each iteration.

arr = (1, 2, 3)
sum = 0

for value in arr {
    sum += value
}

// sum == 6

The second way is similar but exposes the current index and value in each iteration.

arr = ('Niña', 'Pinta', 'Santa María')

for index, value in arr {
    console.log(index + ' ' + value)
}

// 0 Niña
// 1 Pinta
// 2 Santa María

For-In can be used to iterate over object properties

obj = (name: 'Bill', age: 50)

for index, value in obj {
    console.log(index + ' ' + value)
}

// name Bill
// age 50

For-In statements iterates through the object own prototype.

For/In/Range

The For/in/range flavor is a convenient syntanctic sugar that regards most of the iteration use cases.

for i in [0:100] {
    // ...
}

// is the same to
for i = 0; i < 100 ;i++ {

}

If/Else

if statement is one of the most important features in many languages including Cor. It allows the execution of conditional code fragments.

Example:

// if-else
if a < b {

} else {

}

// with else-if
if a < b {

} else if b == 0 {

}

Switch/Case/Default

With Cor you don't need to remember to break after every case. Cor switch statements prevents accidental fall-through by automatically breaking at the end of each case clause.

Switch statements in Cor can take multiple values for each case clause. If any of the values match, the clause runs.

switch good {
    case 'House' : fee = 50
    case 'Boat'  : fee = 20
    case 'Car'   : fee = 10
    default      :
        fee = 0
        console.log('The citizen has no House, Boat, or Car')
}

// with multiple values in a single case clause
switch num {
    case 0, 1 : alert('0 or 1')
    case 2, 3 : alert('2 or 3')
}

Switch statement is even more generic, one can omit the main expression, the true value will be evaluated in place of the omitted expression:

switch {
    case x > 2 : doSomething()
    case x < 2 : doOtherThing()
}

Select

Select statemet is like switch statement but for asynchronic operations. It executes all cases in the same order as defined, once one of them has been resolved, it executes the instructions associated to resolved case. If none of the cases are resolved will block forever.

select {

    // receive
    case <- chan :

    // assign receive
    case s = <- chan :

    // timeout
    case timeout(500) :

    // default
    default :
}

If default is provided and none of the other operations it will choose to execute the default instructions. The timeout builtin function is supported as a special case.

Inc/Dec

Inc/Dec statement increments or decrements an expression. Similar features are found in many languages but these are offered as an expression, in Cor it is a statement.

Example:

// correct usage
func init() {
    a = 0
    a++
    a--
}

The grammar enforces to be used as a statement.

// will cause a parsing error
// because it is used as an expression
b = a++

Use

Use statement imports modules previously defined. The use keyword behaves ruled by some conventions.

Example:

// importing math.cor
use './math'

func init() {
    console.log(math.PI)
}
// 3.141592

Aliases can be used for abbreviation or to avoid name collisions inside module scope

use './finance' fnc

func init() {
    m = fnc.newMortgage(352000)
}

You may see Modules and Configuration as a complement.

Catch/Error

Cor has a simple exception model that works very well with javascript exceptions, it guarantees full interoperability between both languages. The catch statement executes a defined block of instructions if a exception is thrown by a watched expression.

catch WatchedExpression {
    // ... instructions
}

Example:

catch someFunc() {
    console.log(error())
}

if error() builtin function is used as a value it will return the thrown error. It should throw otherwise.

Example:

catch someFunc() {
    // throw catched error
    error()

    // throw custom error
    error(&TypeError)
}

Commands

Cor cli is available as a Node.js utility, it allows you to compile and build sources. Commands are used as subcommands of Cor program, for instance cor build. Each command may have parameters and options, parameters are passed after the name of the command and options are specified using the following format: -option=value which must be specified after parameters. To know about usage, help command is there for you. Running cor help or just cor would show available commands, and cor help [command] will print usage of the specified command.

Help

help command prints documentation about available commands. Is a tool to guide cor cli usage without to get out of the console.

Usage:

cor help [command]

Will shows available commands. Also prints usage and documentation about a specified command.

Example:

cor help build

Prints documentation about cor build command

cor help compile

Prints documentation about cor compile command

Run

run command reads and executes a .cor file containing Cor source code.

Usage:

cor run <path> [run options]
Arguments:
path Specifies the path to the file to execute.
Options:
-conf Specifies the path to the .json file to use as configuration.

Example:

cor run path/to/file.cor

Runs a program located in the specified path.

Build

build command compiles .cor files and its dependencies, the resulting javascript code will be packed and written to a standalone .js. The CRL will be embedded in the head of the resulting file unless you use -no-crl oprtion. The build command supports four types of packages: AMD, CommonJS, Global and DOM Ready.

Usage:

cor build <path> [build options]
Arguments:
path Specifies the path to the entry file to build.
Options:
-o Specifies the name of the file where the resulting javascript code will be written, if not specified the file name will be the base name of the entry file with .js suffix.
-conf Specifies the path to the .json file to use as configuration.
-type Specifies the type of the resulting bundle. The supported types are domready, commonjs, amd and global. It must be provided separated by ,(do not write spaces between). domready type will be used by default if -type option is omitted.
-no-crl If used will not embed CRL(Cor Runtime Library) in the head of the compiling result.
-v If used will print additional information during building process.

Example:

cor build myapp.cor

Builds myapp program and its dependencies and creates a file named myapp.cor.js inside myapp directory containing the resulting javascript code.

cor build myapp.cor -crl -o=app.js

In this case the output file is named app.js and CRL will be embedded in the beginning of the file.

cor build myapp -env=myapp/env.json

Builds myapp.cor program and tells compiler the environment file is located at myapp/env.json.

cor build ./mylib.cor -type=amd,commonjs,global

Build ./mylib.cor file making it available through AMD, CommonJS and Global api.

Compile

compile command compiles source contained in a directory and put the result in the specified output directory. Every file contained in the source dir will be copied to the destination preserving the original directory structure as they are, except .cor or any other file processed by the loader. These files will be compiled and written to the file system as .js.

Usage:

cor compile <path> [compile options]
Arguments:
path Specifies the path to the directory which contains files to compile.
Options:
-o Specifies the path to the directory where the compiled files will be written. The default name has the format: compiled_{timestamp}
-v Specifies whether to print or not file names as they are compiled.

Example:

cor compile ./mylib

Compiles source inside mylib directory and creates a directory named mylib_js_ followed by a timestamp, here is where the compiled content will be written.

cor compile mylib -o=../delivery_dir/mylib

In this case the output directory is ../delivery_dir/mylib

Http

http command launch a simple http server using current directory (cwd) as the root. If a directory is requested it will list all files inside as a list of html links (<a href=""></a>). This server is for development purpose; do not use it in production.

Usage:

cor http [http options]
Options:
-port Specifies the port where the server will listen requests. Default is 9000

Example:

cor http

Launch an http server using 9000 port.

cor http -port=8790

Using 8790 port.

The Loader

The loader is a component which manages dependencies and dynamically loads files into the browser by using Ajax and using fs library on Node.js. It is extensible, so, it is possible to add support for any processor, for example, Markdown, or Mustache. It expects every requested file to be CommonJS compliant. It is intended to be used just for development, so, once the cource is compiled and packed the loader is not needed any more.

The loader supports .js files loading out of the box, hence it is possible to use thirth party javascript libraries compliant with CommonJS specifications.

This is a valid Cor project:

// filename: app.cor

use './jquery.js'   jquery
use './template.js' tpl

func show() {
    jquery.get('http://server.com/api.php', func(r) tpl.render(r))
}

func init() {
    show()
}

Configuration

The configuration file must be in JSON format, but not javascript object literal, it will affect the behavior of the loader beeing used to resolve dependencies. This file should be named conf.json just for convention, however you can choose de name you prefer. It must be used with -conf option in cor build command or with data-conf in HTML pages. All relative paths defined are relative to the configuration file. The file might look like this:

{    
    "paths" : {
        "jquery"     : "node_modules/jquery/dist/jquery.js",
        "underscore" : "node_modules/underscore/underscore.js",
        "backbone"   : "node_modules/backbone/backbone.js"
    },

    "ignore"         : ["fs", "child_process"]
}

Values:

With the above example we could write:

// Backbone.js requires jQuery and Underescore.js
// the loader will handle it

use 'backbone' bbone

class TodoModel : bbone.Model {
    // ...
}

Dependence injection

If you have not catched on, the configuration file is good resource for dependence injection. Check the following configuration:

{

    "paths" : {
        "jquery" : "node_modules/zepto/zepto.js"
    }
}

In the above case we inject Zepto.js to be used used as jquery replacement under the same route.

Cor in the Browser

Cor library (located at cor/dist/cor.js) should be inlcuded using a script tag inside a html page for development environments:

<html>
    <script type="text/javascript" src="cor/dist/cor.js"></script>
</html>

Once the DOM is ready the Loader will look for a script tag containig the data-entry or data-conf attribute, or both to boot the application. Example:

<script data-entry="myapp.cor"></script>

In the above example was setted myapp.cor module as the entry of the application.

Example using a .js module as entry:

<script data-entry="./myapp.js" data-conf="./conf.json"></script>

The Cor distribution for browsers is recomended only for development purpose, to take advantage of the hot-realod avoiding the compile step in the coding/compile/run/test worflow. However you must use the build command before to put an application in production, example: cor build ./myapp.cor -conf=./conf.json and utilize the resulting standalone .js file which will contain all the application and its dependences.

The CRL (Cor Runtime Library)

The CRL is a small (~11Kb unminified and uncompressed) library which makes possible to take advantage of features such as for/in statements, inheritance, type assertions, among others. Without the CRL, the javascript code obtained as the result of compilation could be repetitive and bigger in consequence, that's one of the reasons that CRL exits, to provide a small set of features that will be internally used by the javascript resulting code.