Juergen Boemmels <[EMAIL PROTECTED]> writes: > Piers Cawley <[EMAIL PROTECTED]> writes: > > > [...] > >> >> Cool, applied. How far from "real" scheme are we? >> > >> > I think its quite far. >> > The first thing is symbols and strings. But how do I represent them at >> > parrot-level. PerlString maybe, but then how will they be distinct >> > from each other. Or just leave out strings for a while. >> >> Symbol: [ '*symbol*', "symname" ] >> >> Held in a Hash (hashed on the string name). >> >> String: [ '*string*', "a string" ] >> >> Which means Pairs become: [ '*pair*', <car>, <cdr> ] > > That would be a possibility. The object-size increase would only be > 33-50%. To get a working prototype this is ok. Not everything is an > object, but everything is an array. > > The later way would be to have two PMCs SchemeSymbol and SchemePair, > both inheriting from PerlString (or maybe this will be renamed to > String). The only diffrence would be the type and maybe the stringify > function. > >> (Or, more likely) >> >> { type => '*symbol*', value => 'symbol', (vtable => ...)? } >> { type => '*string*', value => 'a string' } >> { type => '*pair*', value => [ <car>, <cdr> ] } >> { type => '*int*', value => 1 } >> { type => '*rational*', value => 1/2 } > > No, I don't think so. This would be a Scheme Interpreter written in > Perl, and compiled to Parrot, and not a Scheme program compiled to > Parrot. If language-independent means that you can write an > interpreter for any language the C is language independent too.
Um... I don't see what having appropriate datatypes inside the interpreter has to do with the language in which the interpreter is implemented. Personally I think there's a very good case for implementing the lot directly in IMCC (apart from the Object and Class PMCs, obviously -- see below). >> > Lexicals are also missing. I haven't looked closely to that. Without >> > variables a language is not very useful. >> >> { type => '*environment*' value => {scratchpad => aScratchPadPMC} > > There is already a ScratchPadPMC. Where is it? It's not in classes/, > is it. As a first implementation a PerlHash is sufficent, (I actually > have a patch doing exactly this, it just needs a little polish. Maybe > I will submit it tomorrow). But most of the lexical scope can resolved > at compile time. parrot_assembly.pod describes an op fetch_lex_p_i_i > but this seems not implemented yet. Up to a point Lord Copper. That's not going to fly (easily) once you have a read eval print loop in place. I want to be able to do, say repl> (define (make-adder n) (lambda (x) (+ n x))) #t repl> (define add1 (make-adder 1)) #t repl> (add1 10) 11 in an interactive session, otherwise what would be the point? >> > lambda-expression: this may compile just down to a sub.pmc >> > Functions like map, apply, list?, etc. have to be implemented. >> >> { type => '*function*', value => {env => anEnvironment, >> arglist => aListOfSymbols, >> sequence => aListOfForms} } >> >> { type => '*compiled-function*', value => aSubPMC } > > I haven't thought much about this yet. Ah. Now, to my way of thinking this is the most important part. Functions are absolutely fundamental to Scheme and you might as well not bother until you've worked out how you're going to implement them. > [...] > >> Implementation is a simple matter of coding. I've been reasonably >> convinced since PerlHashes became ready for primetime that one could >> implement a full blown, if not necessarily very *fast* version of >> scheme whilst maintaining one's own environments, continuations and >> all the other good stuff, but lack of tuits has tended to get in the >> way of implementing it. > > I also think it would be possible to implement scheme. The major > show-stopper the access to aggregates has been solved. > >> Things would almost certainly be easier with full blown PMCs handling >> dispatch for the 'thing' that a '*function*' points at, but not >> entirely necessary. Another option is to make first class PMCs of all >> the various types, but I'm not sure how one would go about >> implementing 'mixed' vtables, where some things are implemented in C, >> others PBC and still others in one interpreted language or >> another. > > IMHO this is the way to go. > SchemeString, SchemeSymbol -> Kind of PerlString, just diffrent type. > SchemePair -> Special Class abusing pmc->data and pmc->cache.pmc_val > as car and cdr (this needs a custom mark function) but getting rid > of one extra indirection. > Envoirments -> The find_lex/fetch_lex looks promising. > Functions -> Subs should be enough. Not even close to enough. Unless you're going to have the Read/Eval/Print thing I showed above compile any functions down to parrot immediately, which would be fine, but we don't yet have the capability to create and execute parrot code on the fly, so that's a showstopper right there. But we *can* represent scheme functions as environments + arglist + sequence of forms already. >> One option for that would be to have a single 'SchemeObject', >> which as well as having a vtable implemented in C would first do >> dispatch through its 'scheme_vtable' hash. > > The diffrence would be the subtype. But AFAIK there is no way to get > this subtype from the PMC in bytecode. Maybe a subtypeof_i_p op is > missing. But this would lead to an extra indirection at runtime: > SchemeObject->vtable->subtype->vtable > For the primary objects of a language this should not be necessary. typeof is a *really* bad idea. Let the 'Object' PMC handle the multilevel vtable look up (in exactly the same way that one does lexical lookup in the environment chain) and method invocation. So, for instance, the bare Object would have no 'cdr' method, so to do C<< call_method Pn, 'cdr' >> would throw an exception. But then one could do pair_cdr: ... ret ... new P1, .Class new P2, .Sub set_addr I0, pair_cdr set P1["cdr"], P2 set P1["classname"], "SchemePair" set P1["isa"], "SchemeObject" set P2["class"], P1 ... set I1, 0 set I2, 1 set P3, "foo" call_method P2, "set_car" set P3, "bar" call_method P2, "set_cdr" call_method P2, "car" print P3 # prints "foo" The thing is, we're going to need a Class/Object structure along these lines for Perl/Ruby/Parrot objects anyway, so even though scheme won't expose these PMCs to the end user, the effort in implementing them is definitely worth while. And I think the extra code organizing capability they give us is really important. Note too, that it wouldn't be hard to set up SchemeFunc, CompiledSchemeFunc and NativeFunc (he said, guessing at names) so that they all looked like Sub PMCs when it came to function call time... NB: I have a proof of concept scheme interpreter running in Perl that uses these OO techniques, and it works really neatly, which is why I've been thinking of doing the Parrot scheme interpreter in a similar fashion. -- Piers "It is a truth universally acknowledged that a language in possession of a rich syntax must be in need of a rewrite." -- Jane Austen?