dunno if this is the kind of thing that is on-topic/of-interest here, I will see...

figured I would include it (this being from an email to someone I know):

---


did start a little bit implementing some of the things I mentioned a few days ago (restructuring the MI mechanism, making initial plans for the implementation of delegation, ..).

I am wondering if a hybrid of class/instance and prototype OO (as I am imagining it) is at all interesting


It can be if you are breaking new ground. I am wondering about all the restrictions and problems/bugs such a language has. Thats the first thing to look at.

   I am not sure if I am breaking new ground or not...


 I have not really seen anything in this area before of late.

yeah, it is odd at least...


well, clearly at least some of the object system internals have become a little horrid...
   class/instance and delegation don't really like mixing.


I believe V8 uses classes shadowed behind objects. This is the approach I would probably take, so an object methods or slots are altered in definition then a new cloned class is created with the modifications made to it, and the objects class pointer is then pointed to this new class.


This seems the most logical and sensible approach and could also support classes.

yes.

I have anonymous classes, but I did not use them this way in my case, the main reason being that classes are not exactly free (they have a number of fields, tables, and sub-pieces). so, creating lots of specialized classes would waste lots of memory...

so, my trick is that the base class stores most of the fields (the class-defined fields), and a special side-object holds any new slots. in this way, the storage and performance overhead is not much worse than other use of prototype objects, however accessing prototype object slots, in general, incur worse costs than class-slots (slot has to be looked up, rather than consisting simply of a few pointer operations).

granted though, much of this can be sped up via hash tables.


now, however, if one were going to make a whole lot of these objects (bunches of copies of a single tupple, ...), then the use of anonymous classes makes more sense.


the use of prototype features then makes more sense for dictionaries and dynamically constructed/modified objects.


actually, the more 'elegant' option would be to basically implement class/instance as an abstraction over a prototype system, exposing some of the internals at least as far as features go. my system is, however, going the reverse and hacking prototype features on top of a class-instance model.


I like V8's approach its the one I would take, it seems most logical for both prototype and class based approaches.

yes, ok.

well, I don't specify the internals, only that there are objects and it is possible to add slots at runtime, and that these will not effect the base class.


there is a slight issue related to the semantics though, namely it would be possible to make the delegation model completely formal/provable, but at a certain cost: new slots/methods in delegated-to objects, beyond the delegated base class, would remain effectively hidden.

conventional prototype/delegate semantics will remain possible within the implementation, but at the cost of not being statically checkable.

       examples (again, hypothetical language):

       class A {
           double x, y;
           delegates double len() { return(sqrt(x*x+y*y)); }
       }

       class A1 extends A {
           double z;
           delegates double len() { return(sqrt(x*x+y*y+z*z)); }
       }

       class B {
           delegates A a;
           void B(A ra) { a=ra; }
       }

       B obj=new B(new A1);

       obj.x //OK
       obj.y //OK


don't you mean 'obj.a.x' ? Or just 'class B { deleages A; ...}' ... or something ?

   this is the whole thing with delegation.
the accesses see "through" 'a', as if the contents of class 'A' were incorporated into 'B', only that the state for 'A' is located in a different object. and so, writing 'obj.a.x' is not needed (this is not delegation, but would be allowable), whereas leaving out the name would make it essentially no longer possible to reference or modify the delegates.

so, basically, the behavior of delegation is essentially analogous to runtime assignable inheritence (this is actually the role it typically serves in many prototype-based languages, such as Self).


 Okay so you still have a handle to the delegate.


My only worries are name clashes, what happens there is there are two delegates and a subscribing class that all have an 'x'. How do you resolve that logically ?


I suppose at least you still have the handle and can explicitly access it and its sub objects.

yes, one can explicitly access it...

as for name lookup, usually it is looked up according to rules similar to Self:
first the current object is checked;
then any delegates are checked in-turn.

at present, it first checks the first delegate, then the next, ...
the rule is that the first found match is used.

like Self, the lookup allows cyclic graphs (a stack is used to prevent infinite recursion), and like Self, multiple delegates are allowed per-object.




so, basically I am trying to merge together the object models from Java and Self...


Yeah. V8 was developed by Lars Bak who did the Java HotSpot engine, and Self too.

may need to look into this...



       obj.z //BAD, A1::z is not statically visible from B

obj.len(); //OK, A1::z is provably visible from the method A1::len()


       now, a big question is one of interfaces:

       interface C {
           double x, y, z;
       }

       C obj1;

       obj1=obj;    //?, B not statically provable to conform to C
//?, B does not implement C (interface injection, of sorts...)

       obj1.x        //OK
       obj1.y        //OK
obj1.z //?, would work in implementation, but is not statically verifiable.


?, these features could be made to work in practice, but are theoretically unsafe and could be rejected by a verifier (likely the default case for 'secure' code). also possible would be to allow these, but also allow an exception to be thrown should the operation fail (VM level, the object system API currently does not throw exceptions).


fully dynamic prototype OO may be possible in the implementation by adding a feature similar to that used for implementing prototype objects: the addition of a virtual "super-interface" capable of interfacing with "any possible object" (in effect the interface would contain every possible slot and method it has seen).

a similar mechanism might be needed for the VM-level implementation of delegating methods (that or, as considered before, having an explicitly defined interface associated with the method).


I can imagine a few points of awkwardness though in trying to make ES3 efficiently operate on top of this system (by default ES3 may use a few "cheap tricks" to make itself work, but absent specific declarations and type annotations may be slower than is ideal).

some semantic restrictions may also be placed on objects created "ex nihilo" is ES3 land, namely that these objects will not be compatible with Java-land (likely even via interfaces), although it could be possible to make them accessible via an API.

so, the same object system could be used in both cases, but not all objects will be compatible due to language-level semantic differences.


a common superset language, such as likely ES4, could probably handle these cases though (such as being able to produce usable objects and utilize objects from both langs).

ES4 is going to be a damb site easier to implement now. But I would still start with ES3.1

   I would have to look into the specific differences...

   but, whatever one has static types and classes is worth consideration.
actually, my last major script language included a lot of things that have apparently been borrowed by ES4 (but, then again, I borrowed a lot of ideas from JavaScript and ActionScript as well, so I guess ES4 had them first in a way...).


ES3.1 is only 3 + things like object accessors (get/set) plus Object.freeze and lambda coding which will be used by the _new_ ES4 called "Harmony" to create classes.

ok, ok.
well at least they added lamba...

now this brings up a thought:
I thought ES3 already had closures?...

will have to look into this...



 Here's Brendan Eich's email to the es-discuss list :-


     https://mail.mozilla.org/pipermail/es-discuss/2008-August/006837.html


 Just in case you did not read it.


 And here's the es3.1 drafts :-


     http://wiki.ecmascript.org/doku.php?id=es3.1:es3.1_proposal_working_draft


 Have not read them myself yet.


yes, I will probably need to look into all this...

for many things though a "least common denominator" approach may be needed.


       or such...


I am now going back to looking at separate languages in a framework much like .NET CLR & DLR but with Multiple Inheritance.


     I still continue to study ES4 RI for a while longer though.

   yeah...


I am writing a framework, but right at this point I don't intend to try to innovate much with languages, more rather to try to implement a framework that can handle several different languages.

as for .NET, well they have achieved a good deal more goals in this direction, but as has often been noted NET makes a good deal more legal pain as well...


Mono seems all right legally they are doing a moonlight to mirror silverlight.

Mono itself has some legal issues.

it exists, but there are I think some MS liscense and patent issues in the mix (many parts of the .NET framework are under MS patents), so Mono exists more because MS allows it to exist, but it is not entirely free of legal issues. I guess the current standing is that there is a an agreement between MS and the Mono developers that MS will not sue over the patent issues.

I just don't really trust all this, I would much rather things stayed more in "clear water" (ie: well away from patented technologies).


I guess this is actually a notable reason for Mozilla focusing more attention on Tamarin, and generally not looking much into .NET or Mono...


 Moonlight is going to be in Firefox soonish when its ready.


ok.

I would suspect probably as a plugin rather than a core component.

I read some things before over all this, namely that I guess their official position was to develop and pursue Tamarin rather than Mono largely on the grounds of concern over possible patent issues (ie: Mono may be ok, but Firefox may not be, since FF is the primary competitor of IE, and so although Mono itself is safe, FF may fall outside the agreement if Mono were to be integrated as a core component, whereas for a plugin people can just stop using it without compromising the whole project...).




similarly, for this and several other reasons, I have focused more effort on using the JVM design as a base.


I never like the JVM, specs where not that great, or well defined, too much like a toy machine for my liking. Only has single inheritance, generics came late and were not that powerful, basically using type erasure I believe.

generics exist at the language level, and I have not looked into how they are implemented (the JVM, at the bytecode level, doesn't really care about many things).

now, granted the JVM itself is a much smaller and in many ways cruftier design, but it can be implemented in such a way that the interpreter runs fairly efficiently, whereas both .NET and AVM2 would require JIT to run efficiently (or, at least an internal bytecode rewrite pass).

the main difference is that the JVM fully specifies most types in the bytecode, and focuses more on their concrete representation (after all, this is why long and double are defined to require 2 stack elements, ...).

both .NET and AVM2 seem to define the bytecodes a little more abstractly, requiring either a dynamically typed interpreter (slow), or recompiling the bytecode into another representation (a lower-level bytecode, or full JIT).

so, as I view it, both MSIL and AVM2 are probably better as far as an IR goes, but JBC is better as far as an interpreted bytecode goes.

JIT more or less "levels the field" though, since any likely effective JIT will have to do much of the same things anyways (stack tracing, code restructuring, ...).



if I ever produce something really usable/useful, it would be worthwhile to have a fairly open and not "too" novel design...

if I can manage to get it implemented, and get several existing languages targetted to it, this would be a worthwhile goal I think...

as well, it is good to have an implementation and design that is clonable...


 You need good specs for that.


yes, my specs thus far are not so good, but I document things where I can.
sadly, most of my documentation is strewn about various text files, and it is not clear which parts are valid, which were just ideas, which are out of date, ...

at one point, I had a convention for this (reviewing files and adding special "marks" to the filenames), but I have not kept up with this...

sadly, properly documenting everything would be no small task...


as far as the JVM goes, the specs can hardly be called "good", but they are understandable if one puts some effort into it (and goes in search of the proper pieces of documentation...).


so, I am partly using it as a "base", but I am developing many of my own things as well (in its full form, my VM will use a somewhat modified bytecode, ...).

also, the major emphasis is not on the bytecode (as is the case with most VMs), rather a good deal of emphasis is placed on all the internal machinery and frameworks, for which I am trying to develop clean and usable APIs.

so, it is not a centralized "ivory tower" design, but is intended to be more of an open-ended toolbox of loosely coupled parts (much more like OpenGL or POSIX).

what it "is" is what you make from it, not something intrinsic in the "design"...


however, a bytecoded VM is itself a fairly powerful tool, and so is being developed to be added to the "toolbox", however many of the parts this VM will depend on are also independent and exposed elsewhere with their own APIs...

of course, the big catch is that all of this is C based, and so not of as much use if one doesn't like C, or wants a centrally-integrated "whole".


sadly, the JVM, as are most other VMs in existence, is by default a very centralized and "ivory tower" design, but oh well, I can try to make it work as a component, and maybe generalize it so that it can interoperate nicely with my other stuff...

in most VMs, the "toolbox" AKA "framework" is built on top of the VM, whereas in this case the idea is that it "is" the VM, and that the design more "digs downwards" than builds upwards.


so, rather than getting all this flexibility by building yet another "layer of abstraction", one tries to dig through what things already exist, to be able to handle all of this already existing stuff (common APIs, ...) as one big and reflective piece of machinery.

for example, I would want, for example, ECMAScript, rather than having everything wrapped up nicely for itself, is able to play in the bigger "outside world" of all of the code that already exists (C land and similar).

a capable script may well have access to the same VM and machinery used to implement itself, and the C compiler, so for example a piece of JS code could very well construct a piece of code that compiles itself to machine code and accesses C API's, or FWIW is self-modifying.


now, granted such capabilities are as much dangerous as they are useful, and so it is my eventual plan to integrate a fairly strict security model into everything as well (bytecode also has this use as well, as I realize that strictly enforcing a security model within C code would be nearly impossible, but bytecode makes this kind of thing far more plausible without compromising the power of the system).

also this is another reason why static typing and formal checking is being pursued for many components (beyond performance and optimization reasons).


as well, bytecode may also allow higher performance, at least in terms of dynamic facilities, since it adds more capabilities for both separation of issues and optimization, vs a more traditional linear-compilation design (where nearly everything has to go through the whole compiler tower).

for example, the one-off results of an eval expression need not get compiled all the way down to machine code (wasting both time and creating potentially non-collectable garbage), and as well, bytecode fragments can be crafted explicitly (rather than having to go through preprocessing and having to grind though a whole bunch of contents from various system headers, ...).


so, in some ways, bytecode could also fill a similar role to what I am doing in many places with dynamically crafting specialized chunks of assembler (but at a much higher level of abstraction).

ok... granted I would probably need an abstraction over the bytecode, such as it would be far more convinient to craft a chunk of PostScript-like code than a JBC class-file, but yeah...


so, yeah, FWIW I will probably need to add a specialized PostScript-like VM somewhere in the mix as well...

hmm, I could partly/temporarily redirect my efforts since this would be probably of more immediate use (and less work) than a JVM anyways...


a few notes:

I have used specialized PostScript like languages in the past to good effect, only that PS is not good for a script language IME (too damn awkward, and then later one forgets just what the hell their scripts were doing anyways).

internally, the upper and middle/lower stages of my C compiler communicate using a somewhat PS-infuenced language as the IR, and in general a PS-like structure is very convinient for dynamically crafted code, only that it is rather poor for end-user scripts, where a more conventional syntax (C-style) is by far more preferable.

however, as-is, my compiler IR is not particularly suitible for use in non-compiled dynamic crafting, where something far more similar to proper PS is needed (non-modular, includes an external visible scope rather than having to declare everything, ...). oh yes, and likely being compiled to bytecode rather than necessarily going all the way down to machine code...

very likely, such a language will have visibility of the C toplevel and functions (my framework already has this, but for different reasons), and as such would need little or no explicit FFI (although granted external function calls would use a different syntax than internal block-based calls).

potentially, it would also make sense for it to have access to the object system.


note, further:
this would not halt or redirect the JVM effort (just as the JVM effort did not entirely halt my plans to get an ECMAScript VM working, this goal having somewhat infuenced the design of the object system).

rather, it would be a much smaller effort than either of these 2, and will likely have much more immediately useful effects (aka: serving a similar role to, but being distinct from, specialized ASM crafting...).


or such...



_______________________________________________
fonc mailing list
fonc@vpri.org
http://vpri.org/mailman/listinfo/fonc

Reply via email to