« February 2005 | Main | April 2005 »

March 28, 2005

Goals for release 0.38

I've rolled over a goal from .37 and I've defined my goals for this next release. 0.38 'Eagle' is going to have some big changes.


Goal 1: Lexical scope- for real this time. I'll experiment with having dynamic scoping as default and lexical scoping as default. I've used @ for dynamic scope, and $ for unscoped- maybe I can use that skipped # for lexical? I'll figure it out.

Goal 2: Cross-context references. ConteX uses contexts because it seems to fit for more programming situations. A context is the closest thing to an 'object' from the object oriented languages. A context is just a set of slots that return values and perform actions on request. Im going to make it possible to copy contexts and request the slots found in remote contexts.

Goal 3: User defined types. I'm going to make it possible to design specifications for a context to have slots that return certain contexts of another specification! At the bottom of this, strings, numbers, and such primitive types will be contexts with built-in convenience slots.

Posted by Rex at 12:51 PM | Comments (0)

March 27, 2005

Release 0.37 (Dove)

Contex 'Dove' is released, with a speed-tuned variable binding system that supplies the developer with dynamic scoping in addition to verbose parsing errors.

I planned on getting more done in the beginning, but I hadn't realized how much trouble dynamic scoping was going to be. Now, there is a major change regarding how 'inp' works, which will remind people of CBN (call by name), a feature that makes some people ball a fist. The 'CBN' found in CX is completely optional and would only be done intentionally:

(cx:) make["eval" ${inp}]
(cx:) eval @{print-line "hello"}
hello

Wowsers- that's the official definition of eval! any quote you send to eval must be live. It can be live scoped or unscoped. See,

When a variable is used and it points to a dead quote, the quote is just referred to.
When a variable is used and it points to a live quote, the quote is run. There are two types of 'live' quotes: scoped and unscoped.

{ blah } (<- that is a dead quote)
@{ blah } (<-- that is a live quote. it is scoped)
${ blah } (<-- that is a live unscoped quote)

Ok, so looking back at that definition of eval, the quote used to define it was unscoped. This means that when we say 'eval', it is JUST like we typed out the definition, except inp is a variable that points to the input to eval:

(cx:)eval 43 (is just like typing:)
43

so, let's use it the right way:

(cx:) set["x" {set["x" 4] print-line "set x to 4" }]
(cx:) eval x
{ set [ "x" 4 ] print-line "set x to 4" }
(now, the 'inp' found in the definition of eval executes the unscoped quote: )
(cx:) eval $ x
set x to 4
(cx:) x
4

Anyway, you can read the last entry to see the details on cx's dynamic scoping and parsing errors. This inp thing is all that has changed since then.

Now it's time for me to write a cheat sheet for anyone wanting to take a fast attempt at CX. I'll do it in tex and add a 'docs' section to the top of this site when I'm ready with the different formats of this cheat sheet.

Posted by Rex at 05:46 PM | Comments (0)

March 22, 2005

parsing and scoping for 0.37

So I've accomplished two of the three goals I set for 0.37 . Here is how CX parsing and scoping works:

The parsing part isn't fancy enough to print your text and point to the area of interest. Instead, I allowed for that to be done later, by making a small parsing system that reports the line and column. To print back the line and point to the column, CX will have to read over the file again, counting to the line, and printing the right one. Then, the parsing error system would have to act differently for repl errors... It will be more worth-it to do the fancy errors when Im on the C implementation of CX. Here is an example parsing error:

(cx:) [}
Parsing Exception: Non-matching list closing
line: 2
column: 3
Runtime Error: - Couldn't cross the bridge -
subject: class contex.Parser
verb: parse
arguments given: [ "[}" ]
true types: [ java.lang.String ]
type list given: [ "java.lang.String" ]
-- environmental stacks reset --
(cx:)

What happened here? You see the parsing exception say the 'line' and column of the problem, but then we see a Runtime Error about crossing a bridge? The bridge is the java-impl.cx file in my project. It is the file made up of invoke and invoke-static that builds CX up from the reflection API in java. java-impl.cx defines 'parse' to just call on the existing java parser. The repl calls the Parser class's 'parse(String)' method, and if the parser throws something, then the 'bridge could not be crossed'. It just means that CX couldn't invoke a method reflectively.

The scoping in CX is a big change. The end result is this:

make["x" 3]
eval @{set["x" 4] print-line x}
print-line x
(prints 4, then 4)

make["x" 3]
eval @{make["x" 2] print-line x}
print-line x
(prints 2, then 3)

You can use set to set a variable that doesn't exist. It will just make the variable right now, in the most specific scope. This is not a good idea though, because if the code is edited later, where the 'outer' context suddenly now has this variable, the inner context's set will refer to the existing variable, which may not be desired. For term's sake, CX's 'make' is just like a 'declaration'.

Now, all I need to do is add those simple java abilities such as constructing an instance with CX, and array access. Then I'll be writing that CX summary I talked about last entry. I might be done with ConteX 0.37 'Dove' very soon!

Posted by Rex at 08:45 AM | Comments (0)

March 17, 2005

Goals for release 0.37

Now I feel like I'm on a roll, and I can progress in releases , step by step. So here are the goals for release 0.37 :

Goal 1: Lexical scope. I've already been setting variables inside functions just for convenience throughout the rest of that function, but those variables need to be scoped to that function alone.

Goal 2: A parsing error system that tells the 'moment' something goes wrong, by printing the line of code, and then aligning a caret on the next line to point at the location of the parsing error.

Goal 3: Allow as many java abilities as possible. Cardinal only allows invokation of a java method on an existing object, and on a static method. Currently, only the parser can create object instances. Looking at the reflections API, I see that I can aquire array access, create objects via their constructor, and possibly tap into the power of these Proxy classes, though they look like a big hack. Most of this can be done in CX through invoke (reflectively invoking reflective methods), but I want to add it to the foundation as further development will rely on these things.

Finally, I'd like to make a 1-2 page summary of how to code in CX, for programmers who can catch on like that. This summary will not include how to program across contexts. It's like learning how to do java inside one class. CX essentially doesn't have the convenience for a developer to code across contexts right now anyway. That's 0.38 talk.

When these goals are met, and I can certainly verify that each goal is met with acceptance by some of my fellow programming friends, I will release CX 0.37.

Posted by Rex at 07:57 PM | Comments (0)

March 15, 2005

Release 0.36 ( Cardinal )

ConteX 0.36 'Cardinal' is finally released! Click the 'Download' link to get it.

I named this release "Cardinal" , after the state bird of Virginia. For now on, I'll be naming my releases after pretty birds.

On the more serious subject, this project has undergone a true rebirth. The only thing that hasn't changed is my StateMachine, the system used to tell the parser 'what' it is parsing as it parses character by character. From beginning to end, the evaluation system has a clean, comprehensible algorithm.

To understand the evaluation system of CX, one must have a knowledge of how cons cells work.

The parser now produces a cons list, made of linked objects of the class ConsCell. The Evaluator takes the head ConsCell (technically, the whole list) and pushes it onto the callstack. Next, the evaluator goes into a loop, where it evaluates the top of the callstack until the stack is empty. The cool thing is that the first cons cell will push the next cell on the callstack, and then it pushes its car, so the next thing evaluated is the wrapped object (the car) in this cons cell, and then the next cell! If the cell happened to be wrapping another cons cell, the wrapped cons list will do the 'roll out' onto the callstack, then the 'parent list' will continue again. If a cons cell has no cdr, it doesn't push anything but its car onto the callstack. This doesnt mean that the evaluator is done; there could still be something on the callstack because this cell was the CAR of the last cell, and there is another cell pushed before this one.

Wrap your mind around that, and you understand the evaluation loop of CX. This algorithm leads to automatic tail call elimination, though I'm fixing the same elimination for functions that end with a branch.

With this new codebase, the coding will mostly be done in CX, so almost all of the work will be in the 'kit' directory of the project. Cardinal now has a stable, reliable codebase, with the potential to accomplish the goals I originally planned.

Posted by Rex at 02:12 AM | Comments (0)