The perils of ooc arguments
Dec 31, 2012
2 minute read

The ooc language is known to be friendly to C libraries, and we have a slew of them covered on GitHub, but one common hurdle is how to correctly declare extern functions.

Argument types

For an ooc function prototype, there are many types of arguments. You can go with regular variable declarations, like so:

something: func (a: Int, b: Int, c: String)

But in this case, a and b have the same type, so you can also use multi-declarations to shorten it a bit:

something: func (a, b: Int, c: String)

In a type declaration (class, cover), you can also use dot-args and assign-args, like so:

Dog: class {

  age: Int
  name: String

  // assign-args
  init: func (=age, =name)

}

and so:

UI: class {

  level: Level

  // assign-args and dot args mixed
  init: func (=level, .input) {
    this input = input clone()
  }

}

However, for extern functions, we also have the lazy option to only specify the types and not the parameter name, since we have no body and won’t be using it anyway:

cos: extern func (Double) -> Double

It gets ugly

All fancy so far, what’s the problem then? The problem arises for certain extern functions, let’s say you have a function that takes an SdlWindow and an Int:

doStuff: extern func (SdlWindow, a: Int)

This probably doesn’t do what you think. Why? Because it parses as if it took two arguments, SdlWindow and a, both of type Int.

How can we get out of this pickle? We have two options: either go full lazy, or full pedantic, but for the love of Cthulhu, don’t mix styles!

Full lazy:

doStuff: extern func (SdlWindow, Int)

Full pedantic:

doStuff: extern func (window: SdlWindow, a: Int)

It gets uglier

In ooc-sdl2, I just committed a change that has everything to do with what I wrote above. But the workaround geckojsc employed seemed to work. Why?

The workaround was to use Void* instead of SdlWindow as a type, and have prototypes that looked like:

doStuff: extern func (Void*, a: Int)

Here, it works because Void* can’t be a variable name, so it’s parsed as a type and thus there is no ambiguity as to the signature of the function. However, it’s not correct, because it doesn’t use the type we covered from C.

Conclusion

In future versions, we might deprecate the lazy style, or at least throw warnings when there’s an ambiguity. In the meantime, don’t mix styles! And if you have time, go full pedantic. I’m sure future automatic doc generation tools will thank you.