rss feed atom feed

gtksourceview highlighting for ooc – gedit & anjuta

it’s with great pleasure that I announce you the addition of an ooc language file to the gtksourceview trunk!

more infos on the bug tracker thread. a zillion thanks to the gtksourceview guys for being so nice and open =)

among others, it implies that we have syntax highlighting out-of-the-box in gedit:

sudoocku (sudoku solver) source opened in gedit

sudoocku (sudoku solver) source opened in gedit

and anjuta, which I know use to hack on rock:

rock opened in the anjuta IDE

rock opened in the anjuta IDE

until the next gtksourceview major release, you may want to install the syntax file by hand. enjoy!

speaking of rock, the mad hacking month has begun, and there’s been significant progress on the generics front, we expect collections (ArrayList, LinkedList, Stack, HashMap, etc.) to be working quite soon. stay tuned! exciting times.

here’s a performance comparison of j/ooc vs rock, on some generics-heavy code, that shows rock to be approx. 24x as fast as j/ooc at generating code, and 4.5x as fast when running gcc too. That is a noticeable difference in everyday work.
(the bench should be somewhat fair, as rock gets nearer to feature completion.)

a word of thanks to itrekkie, fredreichbier, tsion (aka scott_) for their rock patches – your work is appreciated.

on a lighter note, here’s a simple sudoku solver in ooc. the code is very simple & nice, and uses a Matrix class with operator overloading, making it very handy. a good read for a soft introduction to ooc:

UTF-8 ftw!

UTF-8 ftw!

finalizers in j/ooc, meta-classes in rock, yajit, deadlogger, woot, oos, arbitrary precision arithmetic

finalizers

At last, finalizers have been added to j/ooc (the Java implementation of the ooc compiler). Just overload the __destroy__ method (a-la-python names!), like that:

PCRE: class extends RegexpBackend {
    // …
    __destroy__: func {
        pcre_free(re)
    }
}

Since j/ooc’s implementation still uses the Boehm GC, it’s just a matter of calling GC_register_finalizer on the member method.

For performance, however, GC_register_finalizer is only called if the __destroy__ method is non-empty. Indeed, an object tracked for finalizing can be up to 3-5x more expensive in CPU time, according to the Boehm GC. While this is unlikely to be a bottleneck for your program, just be aware of that fact!

Note: what about the __methodName__ naming convention? Here’s the rule: methods enclosed in two underscores shouldn’t be called directly. There’s no point in calling __destroy__ yourself, right?

meta-classes

ooc started as a series of hack to bake OOP in C. Since then, change has happened for the best, to make the model more consistent, simple, intuitive, and avoiding ugly hacks. It’s time for another such change.

in j/ooc, classes were implemented as C structs, and “Class” was an ooc class, but accessing e.g. member methods of classes was black magic. “Class” was never sub-classed, so other classes didn’t have proper meta-classes.

In rock, the new (experimental) ooc compiler written in ooc, the implementation has changed, and all classes now have proper meta-classes. With the upcoming addition of an (optional) HashMap of methods and variables, it will allow introspection of classes, faking interfaces (e.g. implementing answersTo), etc.

Here’s an example of code that will soon compile under rock:

StdoutPrinter: class {
  print: func (str: String) {
    str print()
  }
}
echo: func (msg: String, printer: Object) {
  print := printer class getFunction("print", [String]) // name and type of arguments
  if(!print) Exception new("Trying to print a message with printer %s, which doesn’t have a print function")
  print(msg)
}
// in Class
Class: class {
  //…
  getFunction: func (name: String, args: ArrayList<String>) -> Func {
    // …
  }
}

yajit

yajit, “yet another just-in-time compiler”, is compiling and running under the latest j/ooc! congrats to showstopper (contribution to the initial code), fredreichbier (reporting so many bugs, adding workaround), and nddrylliog (actual fixes for the bugs). Private joke: IWMFF.

This announce is, in fact, significant! Yajit implements most of the runtime we need for real closures. Which means we’re not far from closures support in j/ooc or rock! Stay tuned.

deadlogger

fredreichbier felt the need for a good logging library in ooc, so.. he’s done it! Here’s a small example usage, for the curious:

import deadlogger/[Log, Handler, Level, Formatter, Filter]
main: func {
    /* console handler */
    console := StdoutHandler new()
    console setFormatter(ColoredFormatter new(NiceFormatter new()))
    Log root attachHandler(console)
    /* file handler */
    file := FileHandler new("test.log")
    file setFormatter(NiceFormatter new("{{level}}: {{msg}}"))
    Log root attachHandler(file)
    /* test */
    logger := Log getLogger("main")
    logger debug("debug")
    logger info("info")
    logger warn("warn")
    logger error("error")
    logger critical("critical")
    logger log(1234, "nothing!")
}

You can find deadlogger on GitHub. It’s BSD, as usual.

woot

woot, our upcoming testing tool for ooc, has been receiving some loving from showstopper! It can walk directories recursively, run each test, compare outputs, generate reports. It’s still rough around the edges, use with care!

oos

tsion has started coding an operating system in ooc! it boots correctly in bochs and also on real hardware =) It doesn’t do much right now, but you can contribute to the effort. A good printf implementation is needed, for example. Then, when interruptions and hardware exceptions are in, who knows, some graphic drivers?

arbitrary precision arithmetic – gmp

based on the initial work of Denis Shepelin, I’m happy to present you ooc-gmp, an (incomplete) GNU MP BigNum binding. Many types and functions are missing, but it should be completed, especially since an RSA implementation in ooc is in progress.

Abusing the ooc object model for insane modularity

In rock, we use the visitor pattern to generate the C code from the AST. Nodes should implement the accept function, and CGenerator extends the Visitor class.

But with every code generation function in CGenerator, it would make a huge file, e.g.

visitType: func (type: Type) {
  /* lots of code… */
 }
visitFunctionDecl: func (fDecl: FunctionDecl) {
  /* lots of code… */
}
// etc.
 

Each of these functions are between 2 and 30 lines. Hard to read, hard to maintain, so I thought of a way to separate those functions. I moved CGenerator’s members into an abstract class Skeleton extending Visitor (so that CGenerator now extends Skeleton instead).

Skeleton: abstract class extends Visitor {
  cw, hw, current : AwesomeWriter
}
 

Then I added a FunctionDeclWriter class, which also extends Skeleton, and add a static method. Or is it?

// declare it abstract so the compiler doesn’t choke on the lack of proper constructors
FunctionDeclWriter: abstract class extends Skeleton {
  write: static func (this: This, fDecl: FunctionDecl) {
    // write the function decl, accessing Skeleton’s members the usual way
    current = cw
    current app(fDecl returnType). app(fDecl name)
  }
}
 

See? This is very idiomatic ooc. Since ‘this’ isn’t a keyword, you can declare such an argument, here of type ‘This’ (which refers to the type we’re currently defining, here it’s equivalent to ‘FunctionDeclWriter’). We can now call the function from CGenerator:

visitFunctionDecl: func (fDecl: FunctionDecl) {
  FunctionDeclWriter write(this, fDecl)
}
 

And it Just Works(TM) =) Now.

P.S: If you wondered how I modularized CGenerator in the java implementation – take a look yourself, but beware, it’s fugly (additional args/vars, etc.)

JDLL debriefing, rpm packages, array literals, regular for, work on rock

Hi everyone, nddrylliog here, welcome to the latest ooc progress report blog post – sorry for the long silence, we’ve been really busy and i’ts more than time to keep you up.

JDLL ‘09

So first, some feedback of the JDLL (Journées Du Logiciel Libre = Free Software Days) 2009, in Lyon. The conference was given in this room (got no photos of the actual talk, sorry) :

It was my first public talk, in front of a ~45 people, and it went great! I explained the major challenges programmers were confronted to nowadays, what were the solutions usually used, and the importance of a good programming language.

People were also shown a few examples of ooc code, and by judging the “oohs” and the “aahs”, even people that came here for the PHP talk (given by Patrice Ferlet aka Metal3d in the second half-hour) had some good surprises!

When shown the match statement with strings, someone argued you could do the same in Java 7, before realizing that it could be not only strings, but *anything* that overloads the “==” operator.

There was a few questions about ooc (e.g. licensing, name mangling, actual toolchain), but the overall feedback was really good. Apart from the usual bored people, it seems like ooc really scratches an itch for many people out there.

After talk, I went to talk with the guys at the AmigaOS booth. I told them about ooc, and how we’d love to support alternative OSes/platforms (AmiagaOS runs on ppc arch now, apparently). At first, they were like “why another language?” so I did a small demo. Everything worked out-of-the-box: functions, classes, generics, match, gcc/tcc/etc. backends, showed the generated C. The programmer among them seemed to be impressed, and said he’d talk about it to fellow Amiga devs.

If Amiga-ers or Haiku-ists are reading, please contact us! We need testers. The more portable, the merrier.

RPM packages

Patrice Ferlet (aka Metal3d) has been working on RPM packages for ooc and related projects, mostly for Fedora and CentOS. After some path issues and other packaging-related glitches, it seems we now have fully working rpm packages for the latest ooc. So that when an official release is out, ooc will be a yum away from many users ;)

We’re still looking for packagers for Arch, Gentoo, *BSD, Debian/Ubuntu, Suse, Windows, OSX, and others. If you’d like to maintain any of these, send a message to the mailing list. Thanks in advance for your contributions, and thanks Patrice for the RPM packages!

Array literals

Array literals have been improved recently.

arr := [1, 2, 3]
// arr is an Int*
import structs/ArrayList
list := [1, 2, 3] as ArrayList
// arr is an ArrayList

This is good magic, achieved with a simple overload of the “as” operator, in ArrayList.ooc :

operator as  (data: T*, size: SizeT) -> ArrayList {
    ArrayList new(data, size)
}

Thus, you can write your own list implementation and benefit of the same magic. Equal opportunity ftw!

Also, in the near future, expect similar magic for map literals, e.g. [key => value, key2 => value2] probably (makes sense with the ‘match’ syntax, and is non-ambiguous).

Regular for

We had foreach for a long time, but regular for was missing (see bug #31) It’s now been added, and it works like this:

step := 5
limit := 100
for (i := 0; i < limit; i += step) {
    printf("%d\n", i)
}

It shows that reporting issues is effective – we’re listening, and reactive. If you have a better way, shout it now, before it breaks too many things.

Rock

Work on rock has been resumed, and is progressing pretty fast. The AST and CGenerator parts have basic functionality, and we’re looking into using Ian Piumarta’s peg/leg for the frontend, this time. We’ll keep you up to date =)

Check out the latest rock codebase here. You can help! Some code from j/ooc’s codebase can still be re-used (porting is quite easy). Come on #ooc-lang on IRC if you want to help.

P.S: Rock is looking for a mascot. If you are (sometimes) a 2D/3D artist or know one, submit your proposals on the mailing list!

pattern matching, ranges, ternary operator, rock progress

By popular demand, and out of tiredness to write endless if/elseif/else chains, I added pattern matching today to ooc.

Here’s a few code examples of how it works

classify: func (x: Int) {
  match x {
    case 0 => "Zero" println()
    case 1 => "One" println()
    case   => "Neither one, neither zero" println()
  }
}

Note that, unlike C/C++/Java’s switch, you don’t need to break at the end of a case, and there’s no way to fallthrough (yet)
There is no ‘default’ keyword, an empty case will always match.

Now a neat trick which is used in PHP also: match actually compares the match-variable and the case-variables, so you can write things like

classify: func (x: Int) {
  match true {
    case x < 0 => "Strictly negative" println()
    case x > 0 => "Strictly positive" println()
    case       => "Zero" println()
  }
}

By default, an empty match is equivalent to a match true. Also, instead of making actual actions you can use match as an expression, for example

classify: func (x: Int) {
  match {
    case x < 0 => "Strictly negative"
    case x > 0 => "Strictly positive"
    case       => "Zero"
  } println()
}

Also eventually added because of everyone whining it wasn’t there, the ternary operator:

printf("Is true true ? %s\n", true ? "hell yeah." : "wtf?")

As you can notice, it has the classic ?: syntax from C/C++/Java. To avoid syntax clashes, declarations are forbidden inside a ?: (otherwise the colon ‘:’ would be ambiguous)

‘lang/Range’ has been added to the SDK. Since it’s a very basic data structure, it’s been implemented as a cover, for speed. A range literal such as min..max will be transformed into a Range new(min, max). Also, there’s a new method in lang/Int, named ‘in’, which returns true if an int is contained in a range passed as an argument

// let’s assume we’re in a class with the member ’size: SizeT’
checkIndex: func (index: SizeT) {
  match {
    case index in (0..size) => return // alright
    case => Exception new(This, "Index " + index + " out of range (0, " + size + ")") throw()
  }
}

(Note: here we use the lang/Exception class, which is currently a fake implementation of exceptions, e.g. it pretty prints the error message with the class name (thus the ‘This’ passed as a parameter), and divides by zero so the program crashes and it’s easy to debug it via gdb and get a stack trace. Don’t forget to compile with -g ;) Real exceptions are coming soon)

As for rock, our bootstrapping attempt (an ooc compiler written in ooc), we’re making great progress! The code is quite clean, much nicer to read than Java’s, and it can already read and tokenize its own source code! I’m now working on a flexible parser, which would take its syntax definitions from simple text files (and yes – it really sounds like meta). Anyway, stay tuned by following rock on github.