if (Perl6 == undefined) var Perl6 = {};
Perl6.MetaModel = function () {};
function require (classname) {
document.write("<SCRIPT LANGUAGE='javascript' SRC='" + require.INC + "/" + classname.split('.').join('/') + ".js'></SCR" + "IPT>");
}
require.INC = '.';
function iv (label, value) {
var self = SELF();
if (value != undefined) self.attributes[label] = value;
return self.attributes[label];
}
Perl6.MetaModel.CURRENT_DISPATCHER = [];
function call_method (inv, label, args) {
var dispatcher;
var options;
if (inv['_class']) {
dispatcher = inv._class.meta().dispatcher();
options = { 'for' : 'instance' };
}
else {
dispatcher = inv.meta().dispatcher();
options = { 'for' : 'class' };
}
var method = WALKMETH(dispatcher, label, options);
Perl6.MetaModel.CURRENT_DISPATCHER.push([ dispatcher, label, options, inv, args ]);
if (method == undefined) throw "Method " + label + " not found for " + inv;
var rval = method.call(inv, args);
Perl6.MetaModel.CURRENT_DISPATCHER.pop();
return rval;
}
function next_METHOD () {
var curr_context = Perl6.MetaModel.CURRENT_DISPATCHER[Perl6.MetaModel.CURRENT_DISPATCHER.length - 1];
var dispatcher = curr_context[0];
var label = curr_context[1];
var options = curr_context[2];
var inv = curr_context[3];
var args = curr_context[4];
var method = WALKMETH(dispatcher, label, options);
if (method == undefined) throw "Method " + label + " not found for " + inv;
return method.call(inv, args);
}
function WALKCLASS (dispacther, options) {
return dispacther.next();
}
function WALKMETH (dispatcher, label, options) {
options = options || {};
var current;
while (current = WALKCLASS(dispatcher, options)) {
//alert(current);
if (current.has_method(label, options['for'])) {
//alert(current + " has " + label);
break;
}
}
if (current == undefined) {
//alert(current + " does not have " + label);
return undefined;
}
return current.get_method(label, options['for']);
}
function CLASS () {
if (Perl6.Method.CURRENT_CLASS_STACK.length == 0) {
throw "You cannot call \$?CLASS from outside of a MetaModel method";
}
return Perl6.Method.CURRENT_CLASS_STACK[Perl6.Method.CURRENT_CLASS_STACK.length - 1];
}
function SELF () {
if (Perl6.Method.CURRENT_INVOCANT_STACK.length == 0) {
throw "You cannot call \$?SELF from outside of a MetaModel method";
}
return Perl6.Method.CURRENT_INVOCANT_STACK[Perl6.Method.CURRENT_INVOCANT_STACK.length - 1];
}
/*
=pod
=head1 NAME
Perl6.MetaModel - Javascript Prototype of the Perl 6 Metaclass model
=head1 DESCRIPTION
This set of javascript modules is a prototype for the Perl 6 Metaclass model, which
is the model which descibes the interactions of classes, objects and roles in the Perl
6 object space.
I am prototyping this in Javascript as part of the PIL -> JS compiler to run on
a JS VM. It is a port of the Perl 5 prototype.
=head1 A NOTE ABOUT DEPENDENCIES
When using the Perl6.MetaModel, this file needs to be loaded first. This is for 2 reasons.
First, this module implements a (simplistic) C<require> method which can be used to load
other modules. And secondly, many of the modules in the C<Perl6.> namespace utilize some
of the function found in this module.
=head1 FUNCTIONS
=over 4
=item B<WALKMETH (dispatcher, label, options)>
=item B<WALKCLASS (dispatcher, options)>
=item B<SELF>
=item B<CLASS>
=back
=head1 SEE ALSO
=over 4
=item All the Perl 6 documentation.
In particular the Apocolypse and Synopsis 12 which describes the object system.
=item L<Class::Role>, L<Class::Roles> & L<Class::Trait>
The first two are early attempts to prototype role behavior, and the last is an implementation
of the Trait system based on the paper which originally inspired Roles.
=item Any good Smalltalk book.
I prefer the Brown book by Adele Goldberg and David Robinson, but any one which talks about the
smalltalk metaclasses is a good reference.
=item CLOS
The Common Lisp Object System has a very nice meta-model, and plently of reference on it. In
particular there is a small implementation of CLOS called TinyCLOS which is very readable (if
you know enough Scheme that is)
=back
=head1 AUTHOR
Stevan Little E<lt>stevan@iinteractive.comE<gt>
=cut
*/