assimilate the awesomeness

things to keep in mind:

keywords

class, cover, interface, implement, func, abstract, extends, from, this, super, new, const, final, static, include, import, use, extern, inline, proto, break, continue, fallthrough, operator, if, else, for, while, do, switch, case, as, in, version, return, true, false, null, default

(note: things like 'new', and 'this' aren't really keywords, they are proper functions and variables, but it's still useful they stand out in syntax highlighting, for readability. Also a few other keywords aren't implemented yet, but reserved.)

operators

+, -, *, /, +=, -=, *=, /=, =, :=, ==, !=, !, %, ?, >, <, >=, <=, &&, ||, &, |, ^, ., ~, .., >>, <<, >>>, <<<, >>=, <<=, >>>=, <<<=

(note, '.' is the chaining operator in ooc, not the 'member access' one. To access a member of an object, just whitespace is needed as in Io, e.g. "dog name", or "dog barf()")

literals

  • string: "hi world\n"
  • char: 'c', '\0' (same escape sequences as C)
  • decimal: 234
  • hexa: 0xdeadbeef
  • octal: 0c777
  • binary: 0b1011
  • float: 3.14, 0.
  • array literal: [1, 2, 3]
  • range literal: 0..10

builtin-types

  • Int, Int8, Int16, Int32, Int64, Int80, Int128
  • UInt, UInt8, UInt16, UInt32, UInt64, UInt80, UInt128
  • Octet, Short, UShort, Long, ULong, LLong, ULLong
  • Float, Double, LDouble, Float32, Float64, Float128
  • Char, UChar, WChar, String
  • Void, Pointer, Bool, SizeT, This

(Note about 'This': it refers to the current type being defined, e.g. a clone method would be defined like clone: func -> This { /* return a copy */ })

(Note 2: some types above are redundant, some will be deprecated soon, but coloring all of them can't harm.)

statements

include, import, use

include header1, path/header2
include ./mylocalheader
import my/package/MyModule
import my/package/[MyModule1, MyModule2]
use mylib, mylib2

No backslashes, even on windows.

comments

// single-line comment
/* multi-line comment */
/** oocdoc comment (a-la javadoc/doxygen), with @tags */

function call

myFunction()
myFunction(arg1, arg2)
myObject doThing()
MyClass callStaticMethod()

declarations

i: Int // variable declaration
i = 3 : Int // variable declaration + assignment
i := 3 // variable declassignment. (the type is guessed)
a, b, c: Int // declare three variables
// useful for bitfields:
OPTION1 = 1, OPTION2 = 2, OPTION3 = 4, OPTION4 = 8 : const Int

casting

3.14 as Int // casting

function declaration

add: func (a: Int, b: Int) -> Int {
  return a + b
}
 
add: func (a, b: Int) -> Int { a + b } // multi-decl, and return is optional.
exit: extern func  // no '->' = void func, extern = defined elsewhere

classes

Animal: class {
  name: String
  age := 0
 
  /** Simple constructor with a member-assign-argument */
  init: func (=name) {}
  // equivalent to
  // init: func (name: String) { this name = name }
 
  /** Another constructor, we need to choose a suffix, here 'withAge' */
  init: func ~withAge (.name, =age) {
    this(name) // call another constructor
  }
  // equivalent to
  // init: func (name: String, age: Int) { this(name); this age = age }
 
  /** An abstract function, should be implemented by child classes */
  shout: abstract func
  // note: if we have no arguments, we don't need parenthesis
  // (heh, that's what the 'func' keyword is for!)
}
 
Dog: class extends Animal {
 
  shout: func {
    "Woof, woof!" println()
  }
 
}

static fields in classes

Ant: class {
  total = 0 : static Int
  init: func { total += 1 }
  getTotal: static func -> Int { total }
}
 
main: func {
  list := ArrayList<Ant>
  for(i in 0..20) {
    list add(Ant new())
  }
  printf("Created %d ants in total!\n", Ant getTotal())
}

covers

// this translates to a simple typedef
Int: cover from int
 
// typedef here..
String: cover from Char* {
 
  // and define the String_println(String this) function here. (in C)
  println: func {
    printf("%s\n", this)
  }
 
}
 
Button: cover from GtkButton extends Window {
 
  // inheritance works almost the same as with classes, e.g.
  // you can call methods from its super-cover
 
}
 
// Compound cover =)
Color4f : cover {
  r, g, b, a: Float
}

interfaces (note: not implemented yet)

Message: class {
  content: String
}
 
Printable: interface {
  print: func
}
 
implement Printable for Message {
  print: func {
    content println()
  }
}

operator overloading

operator + (left, right: String) -> String {
  // note: this is a horrible implementation, but it's just for the example
  return strcat(strdup(left), right)
}

pointer syntax

main: func {
  ptr := gc_malloc(Int size) as Int*
  ptr@ = 42
  printf("ptr's value is %d\n", ptr@)
  add(ptr, 3)
  printf("ptr's value is now %d\n", ptr@)
}
 
add: func(ptr: Int*, value: Int) {
  ptr@ += value
}

reference syntax

main: func {
  ptr := gc_malloc(Int size) as Int* // alloc an int on the heap
  ptr@ = 42
  printf("ptr's value is %d\n", ptr@)
  add(ptr, 3)
  printf("ptr's value is now %d\n", ptr@)
}
 
add: func(ptr: Int@, value: Int) {
  ptr += value
}

more fun with pointers & references

main: func {
  number := 42 // alloc an int on the stack
  printf("number is %d\n", number)
  add(number&, 3)
  printf("number is now %d\n", number)
}
 
add: func(ptr: Int@, value: Int) {
  ptr += value
}

foreach

for(i in 0..10) {
  printf("%d, ", i)
}

also, for collections

list := ArrayList<Int> new() .add(1) .add(2) .add(3)
for(i in list) {
  printf("%d, ", i)
}

Can also be a decl before the 'in', e.g.

for(i: UInt in 0..10) {
  printf("%d, ", i)
}

function pointers

action: Func // a dumb function pointer
 
doThing: func {
  "Oh, really?" println()
}
 
action = doThing
 
action() // call action, thus call doThing

typed function pointers

applyOperator: func(operator: Func (Int, Int) -> Int, left, right: Int) {
  return operator(left, right)
}
 
add: func (left, right: Int) { left + right }
sub: func (left, right: Int) { left - right }
mul: func (left, right: Int) { left * right }
div: func (left, right: Int) { left / right }
 
printf("1 + 2 = %d\n", applyOperator(add, 1, 2))
printf("10 - 5 = %d\n", applyOperator(sub, 10, 5))
printf("6 * 7 = %d\n", applyOperator(mul, 6, 7))
printf("10 / 2 = %d\n", applyOperator(div, 10, 2))

chain calls

list := ArrayList<Int> new()
list add(1) .add(2) .add(3)

closures

butt := Button new()
butt connect("clicked", func { "Button clicked!" println() })

generic functions

printType: func <T> (param: T) {
  printf("Got param of type %s and size %d\n", T name, T size)
  if(T == Int) printf("It's an Int! and its value is %d\n", param as Int)
  else if(T == Char) printf("It's a char! and its value is '%c'\n", param as Char)
}
 
printType('c')
printType(42)

prints:

Got param of type Char and size 1
It's a char! and its value is 'c'
Got param of type Int and size 4
It's an Int! and its value is 42
Container: class <T> {
  content: T
  init: func(=content)
  get: func -> T { content }
  set: func(=content)
}
 
main: func {
 
  cont1 := Container<Int> new(42)
  number := cont1 get()
  printf("number is an %s, and its value is %d\n", number class name, number)
 
  cont2 := Container<String> new("Hi, world!")
  message := cont2 get()
  printf("message is a %s, and its value is %s\n", message class name, message)
 
}

prints:

number is an Int, and its value is 42
message is a String, and its value is Hi, world!

the match statement

mark := stdin readLine() toInt()
match mark {
  case 0 => println("Oh, that's bad.")
  case 1 =>
    // there can be several statements
    mark = 3
    println("There, I helped you a little")
  case 2 =>
    println("So you like middles?")
  case => // default case
    println("Now what is that value?")
}

Note: there is a 'fallthrough' reserved keyword, which isn't implemented yet.

match can be used as an expression:

hello := match 42 { case 42 => "Hello!" }

match without an expression is the equivalent of match true {}

isPositive: func (i: Int) -> Int {
  return match {
    case (i > 0) => 1
    case (i < 0) => -1
    case => 0
  }
}

(parenthesis added for readability, but not actually needed)

a few other things in no particular order

qualifiers for decl-assigns

Math: class {
  PI := const static 3.14159
}

unusual qualifiers

Container: class {
  content: Pointer
  /** inline keyword: same meaning as C */
  getContent: inline func -> Pointer { content }
}
 
/** proto keyword adds function prototypes int the generated C file, e.g. when you're missing a header. */
usleep: extern proto func -> Int

extern symbols aliasing

c_exit extern(exit) func
 
main: func {
  c_exit(); // translates to exit() in C
}

for member functions (ie. methods)

include stdlib
 
String: cover from char* {
  length: extern(strlen) func -> Int
}
 
"blah" length() toString() println()

prints '4'

raw arrays

arr := [1, 2, 3] // array of ints, typed Int*
 
// the type is determined by the first element
arr2 := [1 as UInt, 2, 3] // typed UInt*
 
// this is invalid:
Dog: class {}
arr3 := [1, 2, 3, Dog new()] // error, incompatible type
 
 
Creative Commons License 2010, nddrylliog & the ooc crew