Tuesday, February 23, 2010

Watch out HelenOS, here comes Sysel!

It is alive! I had to put in some hacks to avoid name conflicts and I had to implement fgets() in the HelenOS C library, but SBI now works in HelenOS. It's not really a big deal, as SBI still doesn't do so much, but it's still nice.

If you're eager to try it, check out this Bazaar branch.

Build the system as usual and boot it. There are some really trivial demos in the sysel/ directory. Just run SBI with the source file pathname as argument. For example:


# sbi sysel/hello.sy


Well... back to work!

Monday, February 22, 2010

A Rodent is Born

I guess I cannot pretend it's a secret anymore. I am working on Sysel. What is sysel? Well, sysel is the Czech name for the European ground squirrel, or, in layman's terms, the European gopher.

Sysel with capital S is a programming language, however. From the previous posts you should already have some idea how Sysel should look like. Right now (in the 'first phase') I am developing Sysel Bootstrap Interpreter (or SBI for short). This is an interpreter of Sysel written in C.

The main purpose of SBI is to bootstrap the prospective self-hosting Sysel compiler, as well as serving as a testbed and refining the language design. Nevertheless, SBI will run under both POSIX-based systems and, of course, HelenOS. SBI as well as other Sysel tools that I will produce will be available under the same BSD-like license that is used by HelenOS.

Only real geeks develop alternative operating systems. Therefore, hopefully, by creating an alternative programming language to develop an alternative operating system in, I will be able to achieve whole new levels of geekiness.

I have created a project on Launchpad where you can now track my progress. I will also publish a HelenOS+SBI branch when that's ready.

Stay tuned!

Sunday, February 14, 2010

Inheritance Quiz

Now pay attention, class! Try to guess what does this fine C# program do?


using System;

public class A {
public static void hello()
{
Console.WriteLine("Hello World!");
}
public class B : A {
}
}

class Test {
public static void Main(string[] args)
{
A.hello();
A.B.hello();
A.B.B.hello();
A.B.B.B.hello();
A.B.B.B.B.hello();
}
}



I'll give you a few options. This C# program, when compiled with GMCS will:

(a) Compile without error and print "Hello World!" five times.
(b) Compile without error, but abort with a runtime error.
(c) Abort compilation because of the cyclic inheritance.
(d) Abort compilation because A.B is not defined.
(e) Abort compilation because A.B.B is not defined.
(f) Crash the compiler.


No cheating, please!

Wednesday, February 3, 2010

Syntax Silliness

I started to play around with the Mono C# compiler. Since all my previous experience with C# has been just passive (i.e. reading tutorials), I started with something very simple: a class implementing a generic doubly linked list. (It's completely brain dead, but should be sufficient for this example.)

I thought it would be fun to convert it to an alternative syntax, so here it is. Note for example the syntax for type parameters. I also added some more specific ideas, like translatable strings with annotations, Python-like for loop, or the with-except-finally statement. The snippet is rather long, which is good, as it should deliver a more authentic experience. For the most part, this a transcription of real C# code, while some of it is completely constructed. If you don't know C# please be careful not to credit me with its inventions.

What I like about this syntactic style is that it avoid C#'s sort of 'German' word order. Public static override void ... wait, where was I? Here, the name of the object being declared is reasonably close to the beginning (just the second word). Also the first word let's us know what kind of object we are dealing with (function, variable, class, etc.).

My fingers didn't really object. Even though 'end' has three characters while '}' has one, short keywords are actually easier to write than special symbols which require Shift to type. My eyes were O.K with it, too -- each declaration is visibly anchored and appears to be balanced. So I am reasonably happy with this creation.

What about you? Do you like it?


## Generic list type.
#
# Really just an example of program syntax style. This list can be
# appended to or prepended. It implements an enumerator and an
# indexer. Backwards or random-direction iteration is not possible.
#
# This class has one generic parameter (t), implements the
# IEnumerable interface. t is subject to the constraint t : class
# (t is a reference type) and the class MyList't is public.
#
# Note that this is meant only to demonstrate syntax style and
# it's almost 1-1 translation of a C# program. (But some special
# syntactic ideas are also demonstrated.
#
class MyList't : IEnumerable, where t : class, public is

class Node, protected is
var prev, next : Node, public;
var data : t, public;

constructor(new_data : t), public is
data = new_data;
end

fun insertBetween(a, b : Node), public is
prev = a; next = b;
a.next = this; b.prev = this;
end
end

var head : Node, public;

constructor(), public is
head = new Node(null);
head.prev = head;
head.next = next;
end

fun append(data : t), public is
var e : Node;

e = new Node(data);
e.insertBetween(head.prev, head);
end

fun prepend(data: t), public is
var e : Node = new Node(data);
e.insertBetween(head, head.next);
end

fun printNodes(), public is
for data : t in this do
Console.writeLine(data.toString());
end
end

fun getLength() : int, protected is
var len : int;

len = 0;
for data : t in this do
len += 1;
end
end

## Get the node at the specified index.
#
# @param pos Index (0 = first, 1 = second, etc)
# @return Node at the specified position.
#
fun getNodeAt(pos : int) : Node, protected is
var e : Node;
var i : int;

i = 0;
e = head.next;
while true do
if e == head then
raise new Exception();
end
if i == pos then
break;
end
i += 1;
e = e.next;
end

return e;
end

## Number of nodes in the list.
#
# Property - looks like a member variable, but assigning
# to it or reading from it can have side effects.
#
prop length : int, public is
get is
return getLength();
end
end

## Indexer
#
# This a simpler variant of [] operator overloading. Here
# we can define the effects of reading from / writing to
# an object of this class with index (e.g. list[3]).
#
prop this[pos : int], public is
get is
return getNodeAt(pos).data;
end
set is
getNodeAt(pos).data = value;
end
end

fun toString() : string, public, override is
var s, sep : string;

s = ""; sep = "";
for data : t in this do
s = s + sep + data.toString();
sep = ",";
end

return "[" + s + "]";
end

generator is
var e : Node;

e = head.next;
while e != head do
yield e.data;
end
end

end

#
# An example how a variadic function might be declared (var
# attribute). The + means that the argument must not be null.
# The whole piece of code is disabled using a multi-line 'comment'
# block. Only single-line comments are meant to be used for comments
# per se, while multi-line blocks are meant for disabling sections
# of code quickly.
#

#{
class PrintFormatted, public is
fun format(fmt : +string; args : (+object)[], var) : string is
...
end
end
#}

class Test is
fun Main(args : string[]), public, static is
# Using a generic class
var list : MyList'string;

# Translatable string literal.
Console.writeLine("Hello World!"@);

# Translatable strings with annotations (these
# are used when have equal strings which are to
# be translated differently.
Console.writeLine("bug"@software);
Console.writeLine("bug"@insect);

list = new MyList'string();
list.append(1.toString());
list.append("hello"@greeting);

Console.writeLine("Objects in list:"@);

# It's really better always to iterate over some
# list. We don't need a C-style for(;;) so no need
# to call this foreach.
for o : string in list do
Console.writeLine("Node " + o);
end

# Instead of for (i = 0; i < 10; ++i)
for i : int in range(0, 9) do
Console.writeLine(i);
end

#
# It would be possible to combine a context-
# management statement with a try block. So,
# try/except/finally can be thought of as a special
# case where we do not need to guard any resources
# with the 'with' statement.
#
with f : TextFile = TextFile.OpenFile("test.txt") do
# If any exception happens here, f is cleaned up
# gracefully via f.dispose() (or similar)
var line : string = f.readLine();
Console.writeLine(line);
except e : Exception do
# And likely we also want to handle the exception
Console.writeLine("Error reading file.");
finally
Console.writeLine("Done");
end
end
end