<< Previous | Next >>

Theory behind Hotel

In hotel there are a few basic building blocks: numbers, strings, arrays, tables (hashtables; a.k.a associative arrays or dictionaries) and scopes. Scopes are not necessarily functions, because some scopes you cannot explicitly call, they will be executed when encountered.

The idea behind hotel is that as a scope is executing its code, a table is formed containing the locally defined names. Normally when a scope has finished, a value is returned and the table is discarded. However, if the returned value is a scope, that new scope might use names from the returning scope, so the table will stay around (a closure). Also a scope can explicitly return its own local table and because this table will include all defined functions and fields of the scope, this would be considered an object in other languages. To do this you use the new keyword.

The second idea is that scopes are fully lexically scoped, but can import more scopes to be used for looking up variable names. Imported scopes are searched before the lexical scope. Actually, imported scopes behave as if names defined in the imported scopes are actually in the local scope. For example:

var x = ":("
var foo = {"x": "hello world"}
fun bar() {
   import foo
   print(x)
}

Will print "hello world!" when bar() is executed. And, when using the new keyword to make an object out of bar:

var b = new bar()
print(b.x)
print(b["x"])

The imported name x can be accessed, both using object access, and using table lookup. So this will print "hello world" three times (once because of the new bar() so the function is executed). This means tables can be linked to other tables, which can in term be linked to other tables ... etc.

Some Syntax Sugar

Certain constructs in hotel are actually syntax sugar. We have already seen the keyword new:

fun foo() { var y }
var x = new foo()

this is syntax sugar for (if there would be a way to reference the local table):

fun foo() { var y; return local }
var x = foo()

or:

fun foo() { var y; return {"y": y }}
var x = foo()

and results in completely the same thing if we did (but only because this function doesn't do anything):

var x = {"y": null}

Another area where syntax sugar helps out is named and anonymous scopes:

foo {
    var x = 10
    print(x)
}

is syntax sugar for:

var foo = new fun() {
  var x = 10
  print(x)
}()

And the anonymous scope:

{
    var z
    print(z)
}

is syntax sugar for:

fun() {
   var z
   print(z)
}()

And (not decided yet) giving the last argument of a function as an anonymous function:

def log(message, block) {
   print(message + " starting")
   block()
   print(message + " ending")
}

log("complicated") {
   ... long calculation ...
}

That last part would be syntax sugar for:

log("complicated", fun() {
   ... long calculation ...
})

Unexpected but useful

var y = "me"
var x = {"y": "hello", "z": fun() { print(y) }
x.z()

would print "hello" and not "me" because the lexical scope of z is first the table it is defined in, so when looking for the free variable y, "hello" is found.

Don't worry, there are more building blocks

In the beginning I said there were only a few basic building blocks. Well, actually there are more in hotel: boolean, tuple, char (the things inside strings), byte and binary (same as char and string, but for non string data), symbols and/or types. And likely even more like regex, xml, database ...

Status

Well ... I was a bit under the weather last weekend, so hardly any progress. Tuesday and wednesday (evenings) I did some major refactoring on how values are managed, hopefully I get fibonacci and some other basic functionality back up by saturday. Lets see how it goes from there.

It is both going faster and slower then I thought. But I think the theory behind the language is quite balanced, and different enough and new enough to warrant the effort. So I will continue slowly but gradually.

Last modified: 2007-11-19 20:18 GMT