Monday, January 25, 2010

Well that was hard work, but was it worth it?

Not sure... I've replace the java implemented List with a DOS version, and it is immutable as well. It is pretty much a LISP list made of head and tail nodes. No need yet for much support, so only supplies those two values.

The difficult bit is that list is used to store both opcodes and arguments when constructing a new function/constructor. This means that these list changes had very far reaching effects. But it also means that a very important part of the system is now written in the system, rather than Java.

I have a feeling that more and more of the system will be converted in the coming (days? seems a bit optimistic). The more that's written in the VM opcodes, the smaller the VM will be, the better! Or at least that's the approach for this iteration. Once we have a feel for how small the VM is, we can start optimising some things (like replacing list with a native version...!).

Here is list (it has to be hacked a bit because we can't create new functions until list has actually been defined... so the comments are used to extract the functions to be manually created and applied to the emptyList object)


(constructor emptyList

// function start
(function prepend: object
newListWithHead: $object tail: $this
)
// function end

// function start
(function newListWithHead: head tail: tail
listConstructor: $head tail: $tail prototype: $this
)
// function end

// constructor start
(constructor listConstructor: head tail: tail prototype: listPrototype
parent: $listPrototype
)
// constructor end

// function start
(function head
$head
)
// function end

// function start
(function tail
$tail
)
// function end

// function start
(function at: index
$head // obviously wrong!
)
// function end
)

Thursday, January 21, 2010

Happy with that!

Here is the definition of zero, the prototype for all numbers (integer ones at least...)

(constructor zero: vm

(function addValue: addedValue
numberFrom: ($vm add: $addedValue to: $value)
)

(function plus: number
addValue: ($number value)
)

(function minus: number
numberFrom: ($vm subtract: ($number value) from: $value)
)

(function isLessThan: number
$vm value: $value isLessThan: ($number value)
)

(function value // not so happy with this, but not end of world..
$value
)

(function numberFrom: value
numberConstructor: value prototype: $this
)

(constructor numberConstructor: value prototype: numberPrototype
parent: $numberPrototype
)

$value: .0
)

I really like it. I was initially doing all kinds of stuff creating prototypes, but that's too classical inheritance - zero IS the prototype. I like.

I think this is easier to read as well. (you didn't see it before, did you :)

Also I've put list onto Activation, but haven't immutabled it yet

I have a compiler going!

And the test for this is 'Number' - so I have essentially bootstrapped the Number library. It's all a bit first iteration; the opcode output is appallingly inefficient. Makes me shudder to think about it, but it works.

I'm in a conundrum (that's all this blog is about really :). Primitive things, such as Undefined, Null, List, Map, Number and String, are essential to nearly all programs. It seems painful to require that everything have these injected. If there was class nesting it wouldn't be such a faff because only the outermost class would need to include the primitive stuff.

Ahhhh.

So what I need is a way of nesting classes :) Back to newspeak. Not so bad though; I can simply add the enclosing class to the list of traits for that class. Call it something imaginative like 'EnclosingType'.

The biggest problem here being that EVERYTHING needs List to be able to create functions (which require a list of arguments). So the compiler will need access to this even if the programmer doesn't think it's necessary... oh dear. So maybe just list gets put onto RootObject.

Actually, how about ArgumentList gets put on - and all it can do is be used as an argument list. Oh hang on! I can add it to Activation, which is used to create functions anyway. That feels better.

Oh, BTW, I've decided that all primitives (as listed above) must be immutable. So the List object will return a new List object when you add something to it.

So what I'm going to do (right now) is
  • Add ArgumentList to Activation
  • Create 'primitive' object that can be passed as a parameter and be used to access the primitives
  • Make current primitives immutable
  • remove primitives from environment, so they must be accessed via the parameter (basically, get the compiled version of fibonacci working)
  • Create String primitive
  • Implement compiler in OpCodes!
Nothing too ambitious