pirate refactoring update
Hello! Here's an update on pirate (the python to parrot compiler) from the trenches. Pirate started as an example that fit in one small file and it stayed in that single file over the years while it grew into a *huge* mess: one monolithic object performing a variety of transformations on python's syntax tree, all in one single pass. Thanks to a Summer of Code grant from Google and the Perl Foundation, Curtis Hall and I have been working to refactor that mess. Our long term goal is to allow pirate to support multiple language front ends (for example, PyPy and Pugs) but our immediate goal was to make the refactoring easier to handle. So far, we've created a generic transformation module that greatly simplifies the work done by Visitors in the compiler module (it's called transform.py in the pirate repository - see below) With the generic Transformer in place, we were able to separate out a simplification pass, so that list comprehensions (eg: [x for x in range(10) if x 5] which evaluates to [6, 7, 8, 9]) are converted into their corresponding for and if blocks up front, before PirateVisitor ever sees the tree. Curt is currently working to use this same principle to separate out function definitions from generator definitions, another chunk of the single-pass system that would work much better as a separate pass through the tree. The big questions we'v been dealing with, though, is what will pirate look like after the refactoring? Well, we think we have a good answer, and we'd like your feedback. We recognize that there are very few people out there that understand how pirate works *today* so what we've done is create a much simplified toy version of pirate and shown, though actual code, how that toy version can be refactored, all in one easy to read narrative python script. Hopefully, you'll be able to understand what's going on even if you're not a python developer. So... Without further ado, here is the plan: http://pirate.versionhost.com/viewcvs.cgi/pirate/toys/refactor.py?rev=HEADcontent-type=text/vnd.viewcvs-markup Or, if that's probably mangled: http://tinyurl.com/d92f3 It's short, contains test cases, and you can actually run it from python, or step through it with a debugger. It does *not* take us all the way to a language-neutral compiler, but it will make that step much easier. Anyway, Curt will be using this plan as a guide to actually implement as much of the refactoring as possible in the time he has left for the Summer of Code, so if you've got feedback, please share it on the pirate list: http://www.cornerhost.com/mailman/listinfo/pirate Other links: The priate home page is here: http://pirate.tangentcode.com/ The code for pirate is available for browsing here: http://pirate.versionhost.com/viewcvs.cgi/pirate/ Thanks for reading! Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -
Re: [pirate] Re: Python PMC's
On Wed, 24 Aug 2005, Sam Ruby wrote: [huge cut] Below is from the sample that Leo provided. # print foo.f(2) # emulate python find_name, which checks attributes too push_eh m_nf $P0 = foo.f(2) clear_eh goto m_f m_nf: # getattribute would also check if __get__ is there $P1 = getattribute foo, f $P0 = foo.$P1(2) m_f: print_item $P0 print_newline Note that the code above would need to be emitted for *every* method call, as there is no way of knowing at compile time what property you will get and how it is defined. Hey Sam, I agree with what you're saying in this thread. This is slightly off topic, but I wanted to point something out. In general, python has so many places where things have to be dynamic that you really can't know this kind of thing at compile time, especially if you allow for eval/exec, or if you allow the code to be used as a module. However if you treat the code as a closed system, *and* you have access to python at compile time, then we can optimize away a lot of these questions. For example, in your original code: def f(x,y): return y class Foo: f = f def g(self,y): return y foo = Foo() g=foo.g print f(0,1) print foo.f(2) print g(3) Once you know how python works, it's *obvious* that this prints 1,2,3. I see no reason why the compiler couldn't figure this out up front just by walking the tree. In fact, a good optimizing compiler would see the return y lines and just get rid of those methods completely. I'd like to allow for the ability to do certain optimizations like this up front, sacrificing flexibility for speed. I know there are many programs that won't allow for this, but for the ones that do, I'd like to be able to do a sort of static compile like this. In other words, sometimes a python-like language is a desirable thing. (But of course this should all be optional so that we can also be 100% python compatible) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -
Re: [pirate] OSCON slides
On Fri, 5 Aug 2005, Leopold Toetsch wrote: There are still issues e.g. with namespaces. I've put out numberless mails on p6i where I invited HLL folks to discuss it and make some proposals. Guess how many answers these mails got. Zero? I don't think p6i is the right place for that. We should have a low-traffic compiler list. Like... this one here for pirate, which is all about generic compiler issues. :) And there is: http://svn.perl.org/parrot/trunk/docs/req/model_users.pod I like that! Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -
Re: urgent parrot bug / PR opportunity
On Thu, 4 Aug 2005, Leopold Toetsch wrote: Michal Wallace wrote: And wouldn't you know it... A bug on the parrot side cropped up out of nowhere to break them! ==17366== valgrind's libpthread.so: IGNORED call to: pthread_attr_destroy ==17366== Invalid read of size 4 ==17366==at 0x43D5123E: Parrot_PyTuple_get_iter (in /home/lt/svn/parrot/leo/runtime/parrot/dynext/python_group.so) ==17366==by 0x8115576: Parrot_iter_p_p (ops/experimental.ops:231) Unfortunately valgrind doesn't show line numbers from the shared lib, but PyTuple.get_iter() is short enough so that you should be able to track down the problem. Thanks, Leo!! I'm afraid this is gibberish to me, but I gave it a shot. I compared the code for pytuple to pylist and pystring and noticed they use the python iterator instead of the enum_class one. Also, pylist references in there several times but it only appears once for pytuple, which can't change its length. It looks like the other length tests for pytuple use PMC_int_val instead so I changed that. Anyway, I have no idea what I'm doing here but it seems to have fixed the tests. I don't have commit access. Assuming you don't see anything horribly wrong here, would you mind applying this patch? BTW, the problem is on red hat enterprise linux 3.0 with a fresh build from subversion) - Michal http://withoutane.com/ Index: pytuple.pmc === --- pytuple.pmc (revision 8800) +++ pytuple.pmc (working copy) @@ -155,12 +155,12 @@ */ PMC* get_iter () { -PMC *iter = pmc_new_init(INTERP, enum_class_Iterator, SELF); +PMC *iter = pmc_new_init(INTERP, PyBuiltin_PyIter, SELF); PMC *key = pmc_new(INTERP, enum_class_Key); PMC_struct_val(iter) = key; PObj_get_FLAGS(key) |= KEY_integer_FLAG; PMC_int_val(key) = 0; -if (!((List *) PMC_data(SELF))-length) +if (!((List *) PMC_int_val(SELF))) PMC_int_val(key) = -1; return iter; }
Re: PMCs: Should We Use Them?
On Thu, 7 Jul 2005, Larry Wall wrote: On Thu, Jul 07, 2005 at 09:28:04PM -0400, Michal Wallace wrote: : What I'd want is to be able to download the language : specific extensions as a library from cpan. Better : yet if users can do it themselves without having : to bug me. Hmm... : Sure, I'd probably install as much as I could, but : there's always someone who wants the version you're : not running. :) My new language has several additional instruction: break_out_of_sandbox be_a_zombie rm_minusrf melt_cpu Cool! It's still not as dangerous as letting users run PHP. :) Dangerous or runaway user programs are just part of what you have to deal with when running a hosting company. You set up scripts and monitors to catch most of the problems, and if something slips through the cracks, you address it. That's how I do things anyway, and it seems to keep my customers happy. :) In any case, my understanding is that right now parrot requires all the dynclasses to be built as part of the parrot source tree, so they might as well not by dynamic after all. At some point that's supposed to change, so we'd be able to bundle each set of PMC's separately anyway. I also really like Dan's idea about using the built-in pmc's as the base for other languages. I'll see what I can do about python. A year and a half ago, I read the specs and didn't think this would be possible... but maybe things have changed enough that we can do it now. - Michal http://withoutane.com/
Re: PMCs: Should We Use Them?
On Thu, 7 Jul 2005, Roger Browne wrote: Leopold Toetsch wrote: Well, if you have some mixed environment, you'd probably build parrot on all machines with the PMC's needed. Something like: perl Configure.pl --with-tcl --with-python to get these PMCs built on it. I'm thinking of situations like web hosting, where the provider will in future offer parrot alongside php etc. But you probably won't be able to convince the average web hosting provider to reconfigure their parrot installation to include PMCs that support your preferred niche language. Speaking as someone who runs a web hosting company: you're absolutely right. This would be a nightmare. What I'd want is to be able to download the language specific extensions as a library from cpan. Better yet if users can do it themselves without having to bug me. Sure, I'd probably install as much as I could, but there's always someone who wants the version you're not running. :) - Michal http://withoutane.com/
Re: [pirate] Setting up Pirate Parrot
On Fri, 1 Jul 2005, Leopold Toetsch wrote: Kevin Tew wrote: I've been working on a python compiler also, feel free to take a look,, svn co http://svn.openfoundry.org/pyparrot languages/python/pyparrot My current boggle is how to handle the self parameter to method functions. You can do things like this in python def foobar( arg1, arg2 ): print arg1, arg2 class A(): self.__add__ = foobar aa = A() print aa + 5 Well, the Python translator has to recognice that __add__ and such has a special meaning in CPython. Therefore the getattribute (in that case of the class - but not only) has to check for such special names and in that case store the Sub object for foobar into the A namespace under the name __add - that is Parrot's notation for the thingy. The rest i.e. calling the sub on the last line, is done by Parrot's MMD implementation. Hmm. I'm pretty sure this is handled automagically by the Python pmc's in pirate... Using the + in pir (or the add op) actually invokes a dispatch method in the PMC that handles the situation. I'm not 100% sure if Sam implemented it, but if so it would be in the pmc's, not the code generator. Pirate doesn't have to know anything special about __add__ because foobar is just another pmc - one that happens to be a callable. The only tricky part I see is that because foobar doesn't have the explicit self parameter, it has to be handled differently by getattr. (In cpython there's a difference beween a function and a 'bound' method, and I think the magic happens in getattr) Anyway, I *think* the existing pmc's solve all these problems. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -
new list for pirate [python on parrot]
I just set up a new list for pirate, a python compiler for parrot. Quite a bit of work has been done on pirate since I last updated the website back in 2003, mostly by Sam Ruby of http://intertwingly.net/ Sam is giving a python-on-parrot presentation at OSCON on August 4, so I'd like to get a few things cleaned up before then - for example, updating the site, creating a development roadmap, an fixing the code to work with the latest version of parrot, etc. If you're interested in helping out with any of these things, or just want to talk about pirate, then feel free to hop on board. The signup page is here: http://cornerhost.com/mailman/listinfo/pirate Thanks! - Michal http://withoutane.com/
Re: about python on parrot
On Wed, 25 May 2005, [EMAIL PROTECTED] wrote: hi python on parrot already have not develop? Hi there, I'm not sure I understand your question either... But maybe this will help? http://pirate.tangentcode.com/ - Michal http://withoutane.com/
refcounts and DOD
Hi all, So I'm still thinking about a generic wrapper for python modules. I would like to be able to recompile the python standard library (and other libraries) to run on parrot with only a few minor patches. I realize this is probably completely foolish, but I'm lazy, so... :) I've done experiments in the past running PythonObjects outside the python VM. This should be possible by replacing a few generic routines that refer to the interpreter. One of the major issues is garbage collection. Python's VM does refcounting. There are two macros it uses: Py_INCREF(x) and Py_DECREF(x). They're pretty self-explanitory, but the docs are here: http://www.python.org/doc/2.4/ext/refcountsInPython.html It seems to me that these macros could be replaced with something that puts the objects in the right place for parrot to deal with them. I've read the memory_internals and pdd09_gc docs but I'm still trying to understand how this would work. It seems that instead of looking at the *count* of references, the DOD system actually walks through the graph of references. So it seems you could fake refcounting just by adding references and removing pointers from somewhere in the tree that gets walked. So: Py_INCREF(x) could be rewritten to (for example) append a reference to x in a parrot array, and Py_DECREF(x) would pop it off the array. Am I on the right track here? I'm sure this is a very naive and inefficient implementation, but I don't see why it wouldn't work. If it would work, is there a better way? Also, my understanding is that parrot uses only a Mark and Sweep system. Is that correct? pdd09 describes the three general methods, but doesn't say which one(s) parrot actually usess. memory_internals.html seems to imply the mark and sweep system only... Or does parrot do all three? - Michal http://withoutane.com/
Re: Python on parrot
On Sun, 15 May 2005, Kevin Tew wrote: I've taken the code from http://www.intertwingly.net/stories/2004/10/05/pyrate.zip, which I assume to be Sam's code. It was basically stubs with a few AST nodes implemented when I started with it. Er. Yes. I can't speak for Sam, but I interpreted his post as a spike of how a pirate refactoring could go, not a call to start a whole new incompatible project. And am working to generate a python to pir translator/compiler that uses Sam's python pmc's I've attached the source as it stands now. I'm just an aspiring parrot hacker. I'm sure that there are a lot of things I'm doing wrong or inefficiently. I'm looking for feedback and suggestions for improvement. Please comment. Well, one thing that's innefficient is to write your own compiler when there are already two mostly working examples out there. I want to get my patches on top of Sam's initial work imported into the parrot SVN tree. I believe that having the python compiler code in parrots svn tree is imperative to build a python/parrot community. I'm absolutely bewildered that you would take that route in order to build a community. Between pie-thon and pirate there already are two python compilers, and pie-thon already *is* in the parrot tree... As far as I can tell, you didn't approach either existing group and see if you could help. You just went off and did your own thing. You're not building a community, you're creating yet another faction. A python compiler in the parrot tree will lead to more widespread exposure to other parrot developers, increased peer review, testing by more people on a greater variety of platforms, etc. This is a great goal, but I'm not sure it follows that having it in the source tree would lead to more exposure. To me, if you want exposure, a much better idea would be to *talk* to people, either on mailing lists or blogs or whatever. In other words, market the project. You need things like documentation and a website. Where the code lives is a fairly trivial concern. It sounds like you just want parrot developers to stumble on to your code in the tree and pitch in. In my mind, the target audience for pirate is python developers (like yourself). People who might have heard about parrot, but don't necessarily know much about it or how it works. But if you can tell all the nice things we get: - this buys us continuations without the genius-level hacks required by stackless - we'll be able to leverage CPAN and code written in other languages... - we'll have a native call interface - (etc) ... then maybe python hackers will be interested. So they should be able to download a python file and run it. The python file should work like every other python file, and leverage the distutils. It should have a setup.py install script and if necessary, a windows installer and rpms. There should be a link to download a binary version of parrot so that the first step isn't to compile a virtual machine they know nothing about - especially if they're developing on windows without a compiler. To me, having the code burried in the middle of the parrot tree is a huge barrier to entry to new developers. Of course if you're targeting parrot developers who may or may not know python, that's another story... But from what I can tell, the other compilers in the parrot svn tree just aren't getting the kind of exposure you're talking about. I don't know, maybe I'm just rambling, but I don't see how putting the source in the parrot repository is either necessary or sufficient for widespread exposure. :/ Michal could you expound on your thoughts here, they sound interesting. I'm not sure what Kevin meant by self hosted but I've been thinking about this lately, and what we can do today is creating a back-end for the compiler that emits simplified python code in a way that would give us things like continuations (though with some loss of speed) without the need to duplicate the python library. Sure. This is kind of off topic for the parrot list. I posted a blog entry here: http://sabren.com/index.php?p=62 I meant a python to pir translator/compiler written in python. Like this one: http://pirate.tangentcode.com/ ?? I've looked at the PyPy project. They are doing cool stuff. I would eventually like to use their work to emit optimized pir for python, but they still have work to do. So why don't you want to help them with that work? Right now you're just reinventing the wheel. If you were writing a backend for pypy, that would be one thing. That would actually be useful. Better yet, not write up a little report about what it would take to get pirate to work with pypy? We could almost certainly leverage their type inference engine. I'd love to see pirate become just another backend for pypy. It seems to me that would do a lot more to build community than the approach you're taking. - Michal http://withoutane.com/
Re: Objects: Now or forever (well, for a while) hold your peace
On Thu, 19 Feb 2004, Dan Sugalski wrote: I tried to unify attributes and properties--I really did. The problem is that they're horribly semantically different. Attributes are class private and guaranteed across all objects of a class, while properties are ad hoc and can be thrown on anything. Python attributes, since they're really done per-object, correspond to our properties. I don't want to force things to be one or the other, because then you'd be in the unpleasant position of not being able to add pythonic attributes to a non-python object. Hey Dan, Thanks for taking the time to respond. What you're doing makes a lot more sense now. Not being able to do both would definitely suck. So keeping them separate solves that problem. However, I think there's an alternate solution that would work for both of us. First of all, in recent versions of python you CAN create classes that have fixed slots: class Fixed(object): __slots__=[foo] An instance of this class will demonstrate the problem you're worried about: f = Fixed() f.foo = 5 # no problem f.bar = 6 # big trouble Traceback (most recent call last): File stdin, line 1, in ? AttributeError: 'Fixed' object has no attribute 'bar' But that's EXACTLY what SHOULD happen if I try to set .bar on one of these objects, or on any java/perl6/ruby/whatever instance that doesn't have a .bar slot. However, in rare cases I might just need to do stick something extra on that object. If you don't mind a LITTLE kool-ade, you can use the Decorator design pattern to solve this without having to change the class at all: class PropDecorator(object): This class lets you add properties to something that wouldn't normally allow it. def __init__(self, other): super(PropDecorator, self).__setattr__(other, other) def __getattr__(self, name): try: return super(PropDecorator, self).__getattr__(name) except AttributeError: return getattr(self.other, name) def __setattr__(self, name, value): try: setattr(self.other, name, value) except AttributeError: super(PropDecorator, self).__setattr__(name, value) Now you have it both ways: p = PropDecorator(f) assert p.foo == 5 p.foo = 2 assert p.foo == 2 assert f.foo == 2 p.bar = 6 assert p.bar == 6 The nice thing about this is that you only have to incur the overhead of checking both attributes and properties when you're actually dealing with both. The compiler doesn't have to emit anything to check... It just emits getprop, and the PMC does the right thing. Unfortunately the semantics of the two systems don't have any overlap, at least no overlap that I can tease out. To me, the semantics are exactly the same. I have a thing, and I want to record some information about it. Now some types of things might have their own ideas about what I can know about them, and that's cool. Just because I have a box doesn't mean I get to open it. I suppose python code could see all properties and all attributes as fully-qualified names, with anything new going into the property list, but that's kinda nasty too. Plus there's the issue of python code easily seeing attributes that, arguably, it ought not see since they're supposed to be mostly class-private. This is definitely something to think about. The python attitude is like perl 5's... You can do whatever you want with an object. But just because you CAN, doesn't mean you SHOULD. To me, privacy rules are like the law of the land. An American object can't legally smoke marijuana... But if you send it over to Amsterdam, then it's okay. :) I think it should be the compiler's job to enforce the correct access privileges. But in any case, this problem exists regardless of whether you call the opcode setprop or setattr... I'm tempted to punt this one to Guido for his opinion. For callmeth, callmethcc, and tailcallmeth... I can understand the versions with the string... It looks up the method off of the PMC in P2, right? But what good is the version without the string? One of the string registers is the name of the sub or method being called. The no-string version is supposed to use that. I need to document that better. I also need to add in the redispatch ops, which I forgot. Right. I understood that's what you meant. I'm just saying that that's equivalent to invoke. So what good is it? :) It's nice to have something that finds the right method, but since the same work has to be done (move the object into P2, find the method, invoke it)... Why not leave the syntactic sugar up to imcc? Again, I'm wary of the separate interface for object stuff. Well... on the one hand I agree, on the other, method and sub dispatch really are very different things. (That might just be the dislike of the OO
Re: Objects: Now or forever (well, for a while) hold your peace
On Wed, 18 Feb 2004, Dan Sugalski wrote: Just to let everyone know, if there aren't any comments on the scheme in PDD 15, I'm going to implement it as-is and be done with it, at least for now. This would be a good time to speak up--can't guarantee that I'll put the changes in for this rev, but I certainly can't think about it if I don't have them. I think you're doing a great job here. This is a TOUGH problem and you've really boiled it down into a clear and simple spec. I do have a few comments/questions: You said in an earlier post that python won't be able to talk to objects with attributes without a syntax change. I don't think a syntax change will be required -- we just need a wrapper class. But it would be *SO* much nicer if properties and attributes were mutually exclusive, and the same interface worked for both. I thought that was the point of having vtables. I'm all for having both, but the implemenation should be encapsulated. I think it's a big mistake to create two separate interfaces. For callmeth, callmethcc, and tailcallmeth... I can understand the versions with the string... It looks up the method off of the PMC in P2, right? But what good is the version without the string? How are they different from the normal function invocation ops? Again, I'm wary of the separate interface for object stuff. For these two: addattr Px, Sy, Sz Add attribute Sy, with a fully-qualified name Sz, to class Px. This will add the attribute slot to all objects of class Px and children of class Px, with a default value of Null removeattr Px, Sy, Sz Remove the attribute Sy (fully qualified name Sz) from class Px, all objects of class Px, and all objects of a child of class Px. Shouldn't there be correspdonding vtable methods for these? And shouldn't those methods get to decide how/if the instances are affected? There were two parts of the spec where I just plain didn't understand the language. First: The catalog metadata for objects is considered to be attributes on the class, so to get the offset for a class for an object, you fetch the object's class then look up the offset attribute from it. (The class attributes are detailed later) This is safe in general, since the only code reasonably querying a class' attribute list is the class code itself, and if a class doesn't know whether it's a ParrotClass-style class or not you've got bigger problems. Does this catalog have something to do with mapping strings to the appropriate position in the attribute array? catalog isn't mentioned anywhere else in the file, and metadata only shows up for the instantiate op... So I really don't get this at all. The reason I thought a catalog might map strings to ints is because there doesn't seem to be a vtable method for looking attributes up by string. What's the mechanism for making this happen? I also don't understand this opcode: classoffset Ix, Py, Sz Returns the offset of the first attribute for class Sz in object Py. What do you do with it once you have it? Is it for when a class has two parents with attribute X and I want to find the one for one superclass or the other? That sounds useful, but it's just my guess at what you're talking about. :) I don't mean to be so grouchy, but you said to speak now or forever hold my peace, so... This is it. I'll do my best to make pirate work with whatever you come up with, but I'll say this one more time: Encapsulation is our friend! Please don't complicate the system with duplicate interfaces. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -
Re: Rules for method resolution?
On Sun, 15 Feb 2004, Luke Palmer wrote: As with Perl 6. A sub object has a Cdo trait which specifies what to do when it's called. Cool. But I think findmethod is a good idea, cross-language-wise. Each language has a different idea of what a method is, and they can store it that way. As long as findmethod is vtableable, you can hook it up to whatever system your language uses. I was thinking the same thing as I wrote my post last night... But I'm not convinced. Suppose I do something like this: x = parrot.find(perl::whatever) x.method() Is that second line a method call or a function call? It depends whether x is an object or not. Now maybe in SOME cases (no dynamic input) a compiler could be smart enough to tell for python... But how could I ever know cross language? How will the compiler know to emit findmethod here rather than getproperty? I would suggest that since perl and python both work this way, this is the way it should work for parrot. If a language happens to let you do something like: class MultiAttribute { x : int = 2; method x() { return 1; } } Then getattr(x) should return some kind of smart attribute that knows how to evaluate to 2 if it's used as an int or 5 if it's called. And what about this? class MultiMethod { method x(a:int) { return a+1; } method x(a:str) { return 200; } } Which x does the get? or does my compiler have to be smart enough to look at the arguments that get passed in? I submit that's impossible to determine, too: args = input(enter arguments) foo.multimethod(*args) I think all methods for all languages should act the perl/python way for this reason. Or at least all languages that want to talk to each other should emit getprop (or something like it) and then if the property is invoked, it should be called just like a normal function. If it needs a magic self variable or does some kind of dispatch based on the arguments, then that should be handled internally by the method PMC. In fact, since I'm on the subject, properties and attributes also have this problem. If we want our languages to work together there should be one and only one type of slot on an object. It should be up to the PMC itself to determine how that works internally. If a more static language has objects that are all the same size and wants attributes instead of properties then it should handle that internally. The interface should be the same either way. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -
Re: Rules for method resolution?
On Fri, 13 Feb 2004, Dan Sugalski wrote: We also have to have a way to fetch the method PMC for a named method for later use, which is where the interesting bits come in. This is required for a number of reasons, including Python, so we have to have it. The question is... *When* is the name resolved? That is, if we do: findmethod P4, Pobject, methodname does the method PMC that gets stuck in P4 represent the method methodname for the object *at that point in time* or does it represent the method *at the time it is invoked*? That is, do we defer actual lookup until invocation, or do we resolve at method find time? For python, you want P4 to contain the method as it is when this op is run. But the whole idea of a findmethod seems very unpythonic to me. In python, a method is just another attribute... One that happens to be callable and also happens to know what instance it's bound to. Consider the second line in this code: x = input() x.foo() Is that a method call or a function call? The compiler has no possible way of knowing, so the second line should be compiled as if it were: _temp_ = getattr(x, foo) _temp_() del _temp_ Maybe for python, findmethod and getprop (or whatever the new eqivalent is) are the same... But I'd suspect that getprop is all any (working) python compiler will use. Here are a couple examples of python weirdness: EXAMPLE 1 - whose method is this, anyway? class Alice: def whoami(self): return Alice class Bruce: def whoami(self): return Bruce a = Alice() b = Bruce() a.whoami, b.whoami = b.whoami, a.whoami assert a.whoami()==Bruce assert b.whoami()==Alice # and just for kicks: freestanding = a.whoami assert freestanding() == Bruce EXAMPLE 2 - callable classes as methods class Methodical: def __call__(self): return muahahahaha class Owner: pass x = Owner() x.method = Methodical() assert x.method() == muahahahaha Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -
Re: Rules for method resolution?
On Sat, 14 Feb 2004, Michal Wallace wrote: class Alice: def whoami(self): return Alice class Bruce: def whoami(self): return Bruce a = Alice() b = Bruce() a.whoami, b.whoami = b.whoami, a.whoami assert a.whoami()==Bruce assert b.whoami()==Alice I'm not sure it affects my argument, but here's a better example: class Person: def __init__(self, name): self.name = name def whoami(self): return self.name a = Person(alice) b = Person(bob) a.whoami, b.whoami = b.whoami, a.whoami assert (a.name == alice) and (a.whoami() == bob) assert (b.name == bob) and (b.whoami() == alice) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -
Re: RT Cleanup
On Mon, 9 Feb 2004, Melvin Smith wrote: At 07:26 PM 2/5/2004 -0500, Will Coleda wrote: Melvin: Here's a warnocked imcc issue for you: int main () { int if = 1; if (if) { if = 0; } } My take on it is, since it is an intermediate language, we don't need ability to have keywords as variables. Compilers can generate all variables with names like $T01JHGJ_001 That can make it kind of nasty to debug compilers. I'm trying to move pirate towards generating names that match the actual variables (though I do still use _000 counters) Would it be valuable if all variables had (or could have) a $ in front of them? The ones that match /\$[PINS]\d+/ would still have implicit types, and anything else would require a .local or .global for the type declaration. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -
Re: RT Cleanup
On Mon, 9 Feb 2004, Melvin Smith wrote: At 02:00 PM 2/9/2004 -0500, Michal Wallace wrote: On Mon, 9 Feb 2004, Melvin Smith wrote: My take on it is, since it is an intermediate language, we don't need ability to have keywords as variables. Compilers can generate all variables with names like $T01JHGJ_001 That can make it kind of nasty to debug compilers. I'm trying to move pirate towards generating names that match the actual variables (though I do still use _000 counters) Which can make it nasty, not having keywords as variables or naming them weird things? I assume you meant the latter, I agree, and my example was probably overexaggerated. You could simply mangle the high-level symbol name so if your language allows you to use 'if' as a variable, do $_if. Take your pick of the thousands of possibilities. Yes, I meant the latter. :) I will at least commit a patch so IMCC will immediately flag the declaration of an illegal symbol name rather than allowing it and then getting confused later. Good idea. Would it be valuable if all variables had (or could have) a $ in front of them? The ones that match /\$[PINS]\d+/ would still have implicit types, and anything else would require a .local or .global for the type declaration. I know how I want to answer the question, but I'd be lying if I said I had actually put a lot of thought in it. Any solution can be made to work: I was just throwing that out there by the way. I haven't thought much about it either. :) I'm perfectly happy with things the way they are, but requiring the $ gets rid of the keyword problem. Possibilities: 1) Mangling scheme - potential issues with various languages as well as potential issues with importing external symbols unless we all agree on the same scheme. You know this brings up another point for hierarchical namespaces. Python would freak out if it saw an expression like perl.object.if. But it'll cope with getattr(perl.object, if)... There probably ought to be a standard API for grabbing objects across namespaces that goes beyond just simple syntax. (Like parrot.find(perl::object::if) or something) 2) Quoting symbol names - pretty much works in all cases but is a little annoying for hand written code I'll think more on the issues before giving an opinion since I'm sure there are some people that have already thought on it more than me; Larry, for instance. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -
python PMCs?
Dan, What is your plan for getting python objects working for the pie-thon? I've made a small start on wrapping PythonObjects as PMC's and that seems to work. It's also a whole lot easier than trying to recode them as PMCs directly or writing them in imc/pir. They just need to be tricked into thinking they have a reference-counting python interpreterer lying around. Code is in http://pirate.versionhost.com/ under pirate/python/pmc/piobject.pmc (it's VERY sketchy right now - only a few lines to prove the concept). Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: Backward branch, warnocked.
On Tue, 3 Feb 2004, Pete Lomax wrote: .sub _main goto L1 test: $I1 = 1 ret L1: $I2 = 2 call test print $I2 # prints 1, not 2 end .end ... Again, sorry to be a pain, but I'd like the truth/an update, please! Or some hints... file level variables... better ways to code this... Pete PS use parrot -o and examine the output .pasm:, $I1 and $I2 (or .local int i, .local int j) get assigned the same register. Huh. That is pretty funky. The problem is that imcc doesn't realize the two variables ought to be distinct, right? A workaround is to call pushtopi and poptopi around the call statement... What's the benefit of doing it this way, rather than using separate subs? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: how to subclass dynamic PMCs?
On Thu, 22 Jan 2004, Leopold Toetsch wrote: Michal Wallace [EMAIL PROTECTED] wrote: I'm trying to make a dynamically loaded PMC that subclasses another dynamically loaded PMC. Its a linker problem, but not too simple. Your analysis is correct: pistring needs the symbol Parrot_PiSequence_get_integer, so you have to provide it: Thanks Leo! You rock!!! I did something like this: $ make -C dynclasses $ cp dynclasses/pisequence.so blib/lib/libpisequence.so Aha! I was trying to figure out how to do -lpisequence. It didn't occur to me to just RENAME it. :) $ cd dynclasses; cc -shared -L/usr/local/lib -o pistring.so \ -I../include -I../classes -L../blib/lib -lparrot pistring.c \ -lpisequence ; cd .. $ cp dynclasses/pistring.so runtime/parrot/dynext/ $ parrot wl.imc # run your test program 51 52 Awesome! Thanks again! :) I also had -Wl,-E in the Makefile, when compiling pisquence. I don't know if its necessary. Another (untested) possibility: you could try to append the 2 pi*.c files into another one and then compile the combined source to a shared lib. That makes sense. I'll try it. If it works, I'll patch pmc2c2.pl to do do this automatically. I'm sure this won't be the last time someone wants to provide a whole set of classes at once. leo Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: How does perl handle HLL Ceval?
On Fri, 23 Jan 2004 [EMAIL PROTECTED] wrote: The subject says it all. As parrot is designed to be targetted by many langauges, how will it handle 'eval' opcodes for those different languages? Shell out to a seperate process? You could do that, or you can provide a C-based compiler as a PMC or you can teach your language to compile itself... Or you can even write your language in some other language that targets parrot. :) Nigel. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
how to subclass dynamic PMCs?
Hi all, I'm hoping this is just a simple linker option, but I've been reading ld manuals for the past few hours and I just don't get it. :) I'm trying to make a dynamically loaded PMC that subclasses another dynamically loaded PMC. I made two files in parrot/dynclasses/ : // file 1: pisequence.pmc #include parrot/parrot.h #define enum_class_PiSequence -1 pmclass PiSequence need_ext dynpmc { INTVAL get_integer () { return 0; } } // file 2: piobject.pmc #include parrot/parrot.h #define enum_class_PiString -1 pmclass PiString extends PiSequence need_ext dynpmc { } I added these to the Makefile, ran make -C dynclasses and now, I have two *.so files: % find runtime -name pi*.so runtime/parrot/dynext/pisequence.so runtime/parrot/dynext/pistring.so Then I try to run this: .sub __main__ loadlib P0, pisequence find_type I0, PiSequence print I0 print \n loadlib P1, pistring find_type I1, PiString print I1 print \n end .end Output is: Couldn't load 'runtime/parrot/dynext/pistring': \ runtime/parrot/dynext/pistring: cannot open shared object file: \ No such file or directory 51 Couldn't load 'runtime/parrot/dynext/pistring': \ runtime/parrot/dynext/pistring: cannot open shared object file: \ No such file or directory 0 If I copy the get_integer function to PiString instead of trying to inhert, everything works: 51 52 It seems the problem is that pistring.so can't load because it can't find a definition for Parrot_PiSequence_get_integer... Even though it's defined in the other *.so file that's already loaded. I don't think this is a bug... I think I just don't know what I'm doing. Can someone help? :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: Events and JIT
On Fri, 16 Jan 2004, Dan Sugalski wrote: 2) Those that explicitly check for events ... Ops like spin_in_event_loop (or whatever we call it) or checkevent is in category two. They check events because, well, that's what they're supposed to do. Compilers should emit these with some frequency, though it's arguable how frequent they ought to be. I don't understand that part. Why the compiler? If the high-level code doesn't do anything with the events, then there's no point in checking. If it does use the events, then shouldn't developers call the even loop explicitly? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: [PATCH] new_noinit and init ops
On Mon, 12 Jan 2004, Luke Palmer wrote: I have somewhat a predicament. I want to create a continuation, and have that continuation stored in the register stack that it closes over (this is how I'm implementing a loop with continuations). Unless I'm having a major braino, I don't think this is possible at the moment. I got around this by adding two ops: new_noinit and init. I've included a patch that implements them. Other solutions welcome. Hmm. That sounds like Coroutine. Also, when you invoke any kind of sub with the calling conventions, it's already in P0. Can't you store that in a local variable on the invoke? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: [PATCH] new_noinit and init ops
On Mon, 12 Jan 2004, Luke Palmer wrote: Michal Wallace writes: On Mon, 12 Jan 2004, Luke Palmer wrote: I have somewhat a predicament. I want to create a continuation, and have that continuation stored in the register stack that it closes over (this is how I'm implementing a loop with continuations). Hmm. That sounds like Coroutine. Uh, how so? Are we mixing up Continuation/Coroutine vocabulary again? :) Well... A Coroutine is a pausable, resumable continuation, right? Or basically a closure with a continuation inside it. I was just guessing how you might be implementing the loop. It sounds like a recursive tail call, but that struck me as a job for goto instead of a continuation. So I thought maybe you needed the continuation to save for later, and that made me think of a Coroutine. That's what was running through my head anyway. As for why I mentioned it based on all those assumptions... uhh, beats me. My real point was just the part about the calling conventions the thing you're calling in P0. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Mr Parrot's Neighborhood
On Mon, 12 Jan 2004, Luke Palmer wrote: Well... A Coroutine is a pausable, resumable continuation, right? Or basically a closure with a continuation inside it. Both of those sentences seem wildly redundant to me. I think we might be stuck on vocabulary. We're surely both understanding the same thing in different ways. Yes. I was understanding it in the wrong way. :) A continuation is one snapshot -- it never changes, it never runs. To invoke the continuation is to take you back to that snapshot and start running from there. To invoke it a second time is exactly like invoking it the first time. Thanks. I'd heard this a million times but putting it this way made it click for me. I've been thinking about continuations as if they were like python functions. In python, functions are objects. You can define them interactively at the prompt and then look inside them and see some representation of their bytecode. But with parrot, there's just one big long line of instructions. A .pcc_sub isn't an object, just a little segment of the list of instructions. Okay... Here's a metaphor I'm working on to try and help me understand how to picture all this. It's not finished (see the end). Feedback appreciated: === MR PARROT'S NEIGHBORHOOD Mr Parrot lives on a very long street. Each house on the street contains an opcode. His job is to go door to door and follow the instructions of the little ops. Mr Parrot carries with him as much paper as he can carry. Each sheet has 16 boxes on it, and he has eight different stacks of them: int 0..15 int 16..31 num 0..15 num 16..31 str 0..15 str 16..31 # should be string, I know pmc 0..15 pmc 16..31 He also has about a zillion pockets on him. He can put things in his pockets (and of course keep track of where they are by writing it down in a pmc box). Every once in a while, he goes through his pockets and throws out anything he doesn't need anymore. So starts at the first address, performs the instruction, and then goes to whatever that opcode says. She might ask him to write a number down in one of the boxes (set I0, 3) or to copy one box to another (set I0, I1) or an object to keep track of, or something equally simple. Usually when he's done with the op, he just goes next door, but sometimes the op tells him to go somewhere else, either explicitly (goto label) or based on the values in the boxes (le I0, I1, label) or the objects in his pockets (le P0, P1, label). Often, an op will tell him to copy the top sheet on one (or some or all) of the stacks and put the copy on top (push) or throw away the top sheet (pop). He gets really mad if you tell him to throw away the last sheet, or if a stack gets so big he can't carry it anymore. Every once in a while, the op will tell Mr. Parrot to do something like this: - make copies of all your stacks of paper - put the copies inside a briefcase - write this delivery address on the briefcase - (possibly) write a return address on the briefcase - put the briefcase in your pocket Is that an accurate portrayal of a continuation? ## Now... I only described the register stacks. In docs/pmc/subs.pod it lays out the differences between the different kinds of Subs. It has this table: Subtype ControlstackPadStack UserStack Warnings Sub- - - C Closure- C - C Continuation C C C C Coroutine C C C C RetContinuationX X X X C ... COWed copy is in context X ... is in context - ... isn't. My problem is that I don't know what a Control stack, pad stack, user stack, and warnings are. Here's my guess: ControlStack { This is another set of smaller papers. One box each. if Mr. Parrot meets a ret op, he takes the top sheet and goes to whatever address is on it. When we call a Sub, we write the return address on the top sheet. Same with a closure. ** I don't understand what happens here when we call a continuation. } PadStack { Hmm. Does this mean lexical pads? In which case, it's a list of friendly names that he uses to remind him which box or pocket a particular thing is in. } UserStack { By process of elimination, this would be the eight register stacks? } Warnings { ** Beats me. Is this for holding exception handlers? } Final questions: What's a context? How would I picture Eval? Does that involve building new houses? A coroutine is like a variable that holds continuations, and updates itself whenever it yields. I guess that's the best way I can put it with my affliction
Re: yield op?
On Sun, 11 Jan 2004, Leopold Toetsch wrote: Michal Wallace [EMAIL PROTECTED] wrote: When you invoke a Coroutine, it calls swap_context() from src/sub.c ... There's an else clause in there that either swaps or restores theinterpreter stack, but as far as I can tell, swap_context() is ONLY called when entering a coroutine - not when we're suspending it. No, swap_context() is called for each invoke of the Coroutine, that is ok. But (as with Continuations) the register frame stacks are *not* swapped. So the zero in your example (in P16) is shared between the Coroutine and main. Yes, that's what I meant. It's called each time you invoke the coroutine. I don't understand why it doesn't have to be swapped back each time you suspend the coroutine. But then again, I tried fixing it myself and it didn't work... Maybe I'll understand once I see how you fix it. If no one hollers, I'll apply Luke's patch WRT register stacks and Continuations and then fix Coroutines. Awesome! Thanks! Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
yield op?
Hey all, When you invoke a Coroutine, it calls swap_context() from src/sub.c ... There's an else clause in there that either swaps or restores theinterpreter stack, but as far as I can tell, swap_context() is ONLY called when entering a coroutine - not when we're suspending it. That means all sorts of nasty things happen when the either coroutine or the calling context gets modified. For example, the code below counts up from 1 to forever. But if you uncomment the zero=0 line, it never gets higher than 1 because zero in __main__ and x in _iterator get assigned to the same register, and the context isn't properly restored. It seems to me that invoke() is doing the right thing by swapping the context, but that there needs to be a yield() method (and opcode?) to balance it out. It definitely needs more than a savetop or an invoke of ther return continuation, because neither of these things would let you fire a method on the coroutine instance. That's why I'm thinking we need a yield op. Am I on the right track here? Either way, what can I do to get this working? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -- #!/bin/env parrot # uncomment the second zero=0 line to see the magic bug :) .sub __main__ .local Coroutine itr .local object return .local object counter newsub itr, .Coroutine, _iterator .local object zero zero = new PerlInt zero = 0 newsub return, .Coroutine, return_here loop: .pcc_begin non_prototyped .pcc_call itr, return return_here: .result counter .pcc_end print counter print ### zero = 0 print zero print \n goto loop end .end .pcc_sub _iterator non_prototyped .local object x x = new PerlInt x = 0 iloop: .pcc_begin_yield .return x .pcc_end_yield x = x + 1 goto iloop .end
Re: BUG: coroutine + exception = stack_height segfault
On Fri, 9 Jan 2004, Jeff Clites wrote: On Jan 9, 2004, at 12:24 AM, Leopold Toetsch wrote: Michal Wallace [EMAIL PROTECTED] wrote: #!/bin/env parrot # # yieldbug.imc # # This program should print dots forever. # Instead it prints a few dots and then segfaults. It does print dots forever here. It does for me too. But based on a previous email, I assume you are getting the crash after applying Luke's continuations patch? (I haven't tried your script with that applied.) Crap. Yes, this code works for me too on the unpatched version. I should have been more careful. But... I had based this example on a much larger program that has the same bug in either version of parrot. It loops through a list of iterators. It works fine if I comment out the two exception handler lines: newsub P0, .Exception_Handler, __py__catch set_eh P0 But with those two lines there it segfaults immediately with the stack_height assertion failure. I'll try to boil it down again tonight. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: [PATCH] Continuations now close over register stacks
On Fri, 9 Jan 2004, Leopold Toetsch wrote: Michal Wallace [EMAIL PROTECTED] wrote: newsub $P1, .Continuation, done For returning just use a .RetContinuation. Or still better, just omit $P1 totally here: .pcc_call $P0, $P1 Aha! I like that even better. :) Thanks! Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: [PATCH] Continuations now close over register stacks
On Fri, 9 Jan 2004, Luke Palmer wrote: Very rarely would you not savetop before creating a *real* continuation. But again, very rarely would you actually create a *real* continuation (depending on your language). RetContinuations are almost always a better choice for traditional languages, and languages like Python with no support for continuations. Gotcha. It just looked odd to me that you had to call savetop... But now I see that's because I was doing the wrong thing all along. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: yield op?
On Fri, 9 Jan 2004, Leopold Toetsch wrote: Michal Wallace [EMAIL PROTECTED] wrote: Hey all, When you invoke a Coroutine, it calls swap_context() Can you have a look at imcc/t/syn/pcc.t, there is an coroutine iterator test. Yep, it has the same problem. The patch below exposes it. Comment out the first zero=0 line and you get an infinite stream of sixes. With both in there it prints two numbers and ends. (This is without Luke's patch) The principle seems to be that you can't modify anything in the context without screwing up the continuation's registers. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -- Index: t/syn/pcc.t === RCS file: /cvs/public/parrot/imcc/t/syn/pcc.t,v retrieving revision 1.28 diff -u -r1.28 pcc.t --- t/syn/pcc.t 16 Dec 2003 08:53:44 - 1.28 +++ t/syn/pcc.t 10 Jan 2004 03:41:28 - @@ -489,6 +489,8 @@ output_is('CODE', 'OUT', coroutine iterator); .sub _main + .local int zero + zero=0 .local int i i=5 newsub $P0, .Coroutine, _addtwo @@ -500,6 +502,7 @@ ret_addr: .result $I2 .pcc_end +zero = 0 print $I2 print \n savetop
RESOLVED: how do I instantiate?
On Wed, 7 Jan 2004, Luke Palmer wrote: Er, sorry, that's IMCC's fault. This works: new felix, $I0 Yep! Thanks! Here's a short example of the final script: .sub _main .local object Cat .local object felix newclass Cat, Cat find_type $I0, Cat new felix, $I0 $P0 = new PerlString $P0 = felix setprop felix, name, $P0 getprop $P1, name, felix print the cat's name is print $P1 print .\n end .end I know PerlArray accepts and stores properties: my compiler uses them. PerlHash probably does too. Yeah, but I felt silly passing around a Hash or Array. :) I ALMOST went withi this though until you showed me how to get the instantiation working. :) And thanks again for all the work you're doing on Python :-) Thanks for the register-stacks-for-continuations patch! That should fix some bugs I've got with generators. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: how do I instantiate? -- was: Objects!
On Thu, 8 Jan 2004, Leopold Toetsch wrote: Michal Wallace [EMAIL PROTECTED] wrote: I'm not even trying to get objects working yet. I just need something that'll let me run setprop on it You can attach properties to all PMCs. And WRT object instantiation: t/pmc/object*.t but only integer attributes are done. Thanks. I looked at those last night but I didn't get what I was looking at. Guess I should have been more careful. What exactly is the difference between an attribute and a property? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: how do I instantiate? -- was: Objects!
On Thu, 8 Jan 2004, Leopold Toetsch wrote: Michal Wallace [EMAIL PROTECTED] wrote: What exactly is the difference between an attribute and a property? $ perldoc docs/pdds/pdd15_objects.pod /TRANSLATION AND GLOSSARY Thanks. Don't mind me. I'm going to go make a card that says RTFM on my monitor here... :) So let me see if I have this right. Attributes are slots in a class, that get created on each instance. Properties don't have predefined slots, you can just attach whatever you want to any PMC. So: a language like java would probably use attributes, because the shape of the class is defined before hand, whereas python would tend to use properties... Right? But when I actually go to fill in the slots, I still use getprop/setprop for both types, right? So if I setprop on an attribute-based-class it would fill in the attribute first, and then if the attribute slot isn't there, do something else (like throw an exception or just make a property?) I guess what I'm asking is: is getprop/setprop a universal interface, or will we need some kind of logic to know whether a particular object uses attributes instead? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
re: [PATCH] Continuations now close over register stacks
Luke Palmer wrote: This patch re-implements the register backing stacks as PObjs (so they can be garbage-collected), honors their COW flags, and adds them to the interpreter context (where they should be, honest!). As a healthy side-effect, it encapsulates their behavior nicely into register.c, when before their guts were splattered all over the source. Hey Luke, I applied this patch, ran make realclean and rebuilt parrot. All the parrot tests pass (except the two about numbers, and I think they were failing before) but it doesn't like the code that pirate's generating. I boiled the problem down to this: ### .sub __main__ newsub $P0, .Closure, _func newsub $P1, .Continuation, done .pcc_begin non_prototyped .pcc_call $P0, $P1 done: .local object result .result result .pcc_end print result print \n end .end .pcc_sub _func non_prototyped .local object res res = new PerlString res = hello! .pcc_begin_return .return res .pcc_end_return .end When I run this, parrot says: No more I register frames to pop! I think the problem is coming from the .pcc_begin_return line. This code works fine if I change the .Continuation to a .Closure or .Coroutine... It also worked before the patch. Do I have my calling conventions screwed up or is this a bug? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
weird bug w/new imcc syntax
I love the new syntax for calling functions! Thanks Melvin!!! And... here's a weird bug. :) The following code fails with the message No Entries on UserStack! But, if you delete either/both of the empty comment lines and it works fine. :) .sub _main $P0 = new PerlString $P0 = hello\n $P1 = _do_print($P0) end .end .pcc_sub _do_print non_prototyped # # .param object s print s .pcc_begin_return .pcc_end_return .end Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
BUG: coroutine + exception = stack_height segfault
#!/bin/env parrot # # yieldbug.imc # # This program should print dots forever. # Instead it prints a few dots and then segfaults. # # parrot -t shows this bug: # #parrot: src/stacks.c:95: stack_height: #Assertion `height == (top-n_chunks - 1) * 256 + top-used' failed. #Aborted # # It works fine if I comment out the set_eh line. # Can anyone help here? # # (Sorry for the long listing. It's as short as I could make it.) # # - Michal # .sub __main__ .local Continuation retcon .local Coroutine it .local object res # create an exception handler. (this is the problem) newsub $P0, .Exception_Handler, _on_exception set_eh $P0 # it doesn't matter whether this comes before or # after the exception handler newsub it, .Coroutine, _iterator_logic # main loop: loop0: savetop newsub retcon, .Continuation, return .pcc_begin non_prototyped .pcc_call it return: .result res .pcc_end print res goto loop0 .end # this iterator just yields dots forever: .pcc_sub _iterator_logic non_prototyped .local object dot loop: dot = new PerlString dot = '.' .pcc_begin_yield .return dot .pcc_end_yield goto loop .end # note that this is never actually invoked: .pcc_sub _on_exception non_prototyped end .pcc_begin_return .pcc_end_return .end # Sincerely, # # Michal J Wallace # Sabren Enterprises, Inc. # - # contact: [EMAIL PROTECTED] # hosting: http://www.cornerhost.com/ # my site: http://www.withoutane.com/ # --
Re: [PATCH] Continuations now close over register stacks
On Thu, 8 Jan 2004, Luke Palmer wrote: @pcc_sub_call_4: set P0, P17 set P1, P16 set I0, 0 set I1, 0 set I2, 0 set I3, -2 updatecc savetop invoke done: restoretop set P16, P5 When the continuation is invoked, that savetop it just did is completely nullified, and you're back to the state before you created the continuation. So, in order to get this to work properly, your first four lines must be: .sub __main__ newsub $P0, .Closure, _func savetop newsub $P0, .Continuation, done So the restoretop after the invoke has something to pop (and so your register state isn't screwed up when you get back). Thanks Luke. I changed my compiler to call savetop before every function call, and that passes my tests but I'm having trouble visualizing why. Would I ever NOT want to call savetop before creating a continuation? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
how do I instantiate? -- was: Objects!
On Tue, 2 Dec 2003, Dan Sugalski wrote: *) Creating new objects involves calling the -init vtable entry *on the class*. Because of this each class gets a custom vtable where the init method has been swapped out for one (from objects.c) that creates a new object instead. Well, cool! How do I this from parrot? I've been trying things along the lines of: .sub _main .local object Cat .local object felix newclass Cat, Cat P2 = Cat S0 = init callmeth felix = P0 #... end .end ... But haven't figured out the magic formula yet That code above gives: Method 'init' not found in file '(unknown file)' near line -1 (If anyone can post a working example of the code above I'd really appreciate it!) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: how do I instantiate? -- was: Objects!
On Wed, 7 Jan 2004, Luke Palmer wrote: Should go something like this: .sub _main .local object Cat .local object felix newclass Cat, Cat find_type $I0, Cat felix = new $I0 # ... .end Thanks, but that doesn't work either. :/ The new op expects an identifier. It won't take a VAR, IREG, or REG. But note that objects are unfinished. I ran into a certain problem when I assumed that attributes could be any type of data; not so -- they can only be integers (at the moment). I needed object support right away, so I simulated using a hash. The hash has a CLASS key which holds the class to which it belongs. I then use this to get the methods. I'm not even trying to get objects working yet. I just need something that'll let me run setprop on it so my generators can make iterator things with a .next() attached to them... I was using ParrotObjects and ParrotClasss for a while but now you can't make a new ParrotObject directly either. :/ Incidentally, anyone know why not? In python or javascript it's easy to just create an object of no particular class just to have a place to stick things. foo = object() foo.x = 1 It was working fine in parrot too, but then it went away. :/ Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: More object stuff
On Wed, 3 Dec 2003, Leopold Toetsch wrote: Dan Sugalski [EMAIL PROTECTED] wrote: At 12:17 PM +0100 12/3/03, Leopold Toetsch wrote: Create an Exception class hierarchy? I'm not 100% sure I want to go with a real OO style of exceptions, but that might just be the neo-luddite in me. It probably depends what HLL want to have. Anyway, I was thinking of pre-constructing a bunch of constant exception objects for internal usage. I'm trying to understand the question here: What is the _return_cc attribute on an exception? Can I use it to resume the code as if the exception never happened? Do I have to fill it in manually? Or could it be automatic? I'm picturing exceptions as continuations with an arbitrary message attached... Right now that message is a string, but eventually it could be any PMC... Is that about right? So, if I throw a WarningException, could I just say ignore it... go to the next line? As for the message, I'm trying to think of a good reason to standardize that attached PMC. For example, if I try to open a file in python and it fails, I get an exception of class IOError... But if I call a perl routine that throws the perl equivalent... What should happen? Should I just catch PerlException instead? Each HLL is going to want its own class hierarchy for exceptions... But it might be nice to have a predefined hierarchy that parrot uses internally. I know perl uses a return value instead of throwing an exception (open or die, right?).. So would parrot's internal file-opener just throw a ParrotFileException? So perl's open() command catches it and returns 0, while python's open() command catches it and throws a new IOError? Am I on the right track? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
feature request: line numbers in errors?
Is it possible to print out the line number of the bad instruction when parrot encounters an error and fails? I'm trying to get my generated code to work with the latest version of pirate and I'm having to rely on GOT THIS FAR print statements to find the lines that are giving me errors. I don't suppose there's one magic error routine that controls all the error messages, and someone could just add a line or two to handle this? :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
python exceptions broken
Looking more at exceptions here... I used to be able to put arbitrary stuff in the _message slot of a ParrotException... Now we can only use strings. Is that permanent? PythonException will need to be able to hold an arbitrary python object. I'm faking it by stuffing my PMC into a string register for now... But it would be REALLY nice to be able to use the base ParrotException and not have to write my own subclass just to get a PMC slot. Would it be possible to get a ['_pmc'] or something in addition to ['_message']? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: Languages status (attention compiler maintainers)
On Mon, 6 Oct 2003, Melvin Smith wrote: In an attempt to get a handle on what the status is of all the language compilers we have (in various states) I added a file called LANGUAGES.STATUS under parrot/languages Just read the file and it explains itself. Please, if you are the author of one of the compilers and you don't have commit access, mail a 2 line summary of the state of your compiler to someone with commit privs. Python: Mostly working except for classes/exec/import. For licensing reasons, not in parrot's cvs tree. See http://pirate.tangentcode.com/ Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
setline?
Sorry, I've been following this list with one eye tied behind my back... What happened to setline? Should I emit something else instead? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: Of AST and YAL
On Sun, 7 Sep 2003, Leopold Toetsch wrote: I'm currently investigating the AST (abstract syntax tree) interface for Parrot. For getting a feeling, how this could look like, I've implemented (some parts) of Yet Another Language (YAL). I like it. What is this written in? C or Perl or what? If it's in perl (or python of course) I'd like to merge in all the pirate code generation stuff. (My plan for this week was to do something very similar, and try to get a simple lisplike language to integrate with python) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: Should I target Parrot?
On Fri, 22 Aug 2003, Benjamin Goldberg wrote: Michal Wallace wrote: On Thu, 21 Aug 2003, Benjamin Goldberg wrote: If you want, instead, to serialize interpreter-microthreads, however... well, you'd *still* get almost the whole interpreter serialized, but you're getting more bang for your buck :) Well how else are we going to implement squeak? :) Squeak uses synchronous communication channels, right? Writing blocks until there's a reader, and reading blocks until there's a writer. Beats me. I was kind of being silly. But squeak does save the state of the entire interpreter in an image file. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: Method call parameters
On Sun, 24 Aug 2003, Benjamin Goldberg wrote: Togos wrote: What's the reasoning behind putting the object a method is being called on in P2 instead of in the first parameter of the method? I have a feeling that putting it as the first parameter of the method would make the lives of the python folks a little bit easier. Would it make it harder for someone else? While I've no idea about that, I don't see why you can't have it both ways... put it in P2 *and* as the first param, if that's the way your language wants it. I think this would be useful for both Python and Perl5. For what it's worth, you can do this in python: class Whatever: def method(self, arg): pass w = Whatever() Whatever.method(w, arg=1) This is the same as: w = Whatever() w.method(arg=1) For both of those, the P2 and P5 should be w Not to mention this looks exactly like a function call on a module: import module as m m.function(arg=1) ... Which doesn't get a self parameter passed in. Old-style classes actually do that Class.meth(instance, arg) fairly often when overriding methods. New style classes use: super(Thing, self).parentMethod(x,y,z) I'm pretty sure new-style classes can also have classmethods that don't get passed a self parameter either. I haven't really thought about how to implement any of this stuff, but it looks like fun. :) I guess if the python compiler knows how to send the right things, it can't be too hard to figure out. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: [CVS ci] PackFile-15: print warning location
On Sun, 24 Aug 2003, Leopold Toetsch wrote: We have two kinds of file/line information: Parrot source and HLL source. So the C.currentline macro needs duplication or an argument specifying, which source it should denote. And when parrot throws an error and complains about line 5, which one will it mean? :) Seems like normally you'd want the high-level source line, unless you're debugging the compiler, in which case you want the low level one. Maybe this should be a command line argument to parrot? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: Should I target Parrot?
On Thu, 21 Aug 2003, Tom Locke wrote: (not sure who you're quoting here... dan I think) But Parrot has continuations. Doesn't this gives me (cooperative) microthreads? (with a little work on my part). Sure... So these would be real cheap right? Time and space overheads similar to regular procedure calls? Yes. This isn't working 100% (at least I couldn't get it working without tweaking the opcodes a bit) but you can see an example of some microthreads at http://pirate.tangentcode.com/ ) ... Microthreads is kind of a loose word for it because it's just a list of generators that increment at each tick. The bytecode I'm generating there is really really bad, so it runs pretty slow, but it definitely works. You might try playing around with that. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: Should I target Parrot?
On Thu, 21 Aug 2003, Benjamin Goldberg wrote: I hope you aren't planning on serializing just a single isolated microthread... that wouldn't work well with what I've got in mind due to how much stuff comes along when you serialize a continuation -- you'd get almost the whole interpreter serialized. If you want, instead, to serialize interpreter-microthreads, however... well, you'd *still* get almost the whole interpreter serialized, but you're getting more bang for your buck :) Well how else are we going to implement squeak? :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: Should I target Parrot?
On Wed, 20 Aug 2003, Tom Locke wrote: I am currently embarking on a project to create a new language. Right now I'm in the process of selecting the platform that's going to give me the best starting point. My first choice is whether to go for a VM, or a C-Python style implementation. Right now I'm leaning towards VM. Hey Tom, I'm not sure what you mean by the difference here. CPython does have a VM, it's just a stack-based one. The language will be dynamically typed, and I understand that Parrot is a better fit for such languages than the JVM or the CLR. I'm sure you're all good Parrot advocates in here, so... If I post some requirements I have to support my language features, would you folks care to talk me into targetting Parrot. Is this the right group for such a discussion? Do you have a website for the language? I've been working on a python-parrot compiler and managed to get quite a bit working. If your language is strongly O-O, you may need to dive into the parrot guts and submit some patches if you want to move quickly (as classes and objects aren't quite ready yet) but for a more functional or imprerative style language you should be able to get pretty far already. If you've got some seriously weird features, who knows? Ask and see, or try it out. :) But: I would say, in general, if you target parrot, and you make your language compatible with other languages, you're more likely to get people to try your language for a small chunk of code here and there, as people will be able to use libraries they're familiar with your syntax. It'll help people shorten their learning curve, in other words. (But that's just my prediction) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
bug with parrot -O2
I haven't looked into this at ALL, but I was curious about the IMCC optimization flags: [~/pirate]: ./pirate.py -d weightless.py weightless.imc [~/pirate]: parrot weightless.imc ended with: L 450 total time: 23 [~/pirate]: parrot -O=1 weightless.imc ended with: L 450 total time: 22 [~/pirate]: parrot -O=2 weightless.imc get_pmc_keyed() not implemented in class 'PerlInt' Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: there's no undef!
On Sun, 17 Aug 2003, Benjamin Goldberg wrote: Michal Wallace wrote: Uh-oh. I just went to implement del x and there's no op to remove a variable from a lexical pad! :) Why would you want to remove a variable from a lexical pad? Surely the right thing to do would be to create a new pad (scope), then add your 'x' variable which you plan to 'delete' in the future, then when you want to delete that variable, pop off that pad. Hmm. Do you mean if for stmt in block: if stmt.type == undef: flag_as_going_to_delet(stmt.varname) So I can create a new pad when it's assigned? It can't be a simple pop though, can it? #!/usr/bin/perl $x = cat; $y = pop $x?; undef $x; print x = $x \n; print y = $y \n; Because here, $x has to be defined before $y, so I'd have to delete the -2nd scope. Unless the code was smart enough to work out that y is in -2 and x is in -1... In any case, what does it buy me? it seems like a lot of work when there's already a delete_keyed op, and leo just made an implementation for pads. :) I guess in perl it's not bad, since that's the whole point of undef, you can just $x = PerlUndef it... But in python, this throws a NameError: x = 1 del x x So the easiest thing to me is just to translate del x as remove this from the current pad. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: set vs. assign, continued: 'add' vs. 'add!'
On Sun, 17 Aug 2003, Luke Palmer wrote: Benjamin Goldberg writes: Hmm... I just thought of something. Since 'set' semantics can be easily simulated when we have only ops for 'assign' semantics, maybe imcc itself could do this for us. That is, by default, $P0 = $P1 + $P2 will be translated by imcc into add $P0, $P1, $P2 but, if some command is given to imcc, then it will be translated into new $P0, .PerlUndef add $P0, $P1, $P2 Or, instead of PerlUndef, the command to change to set semantics would indicate what to put into $P0 prior to using it as the target of an add (so we can initialize $P0 with any of PerlInt, PerlNum, BigInt, BigFloat, BigRat, ContinuedFraction, etc.) Hmm, I wonder whether this is the right approach. What about operator overloading? Let's say Python overloads + (can it do that?) and passes that variable to Perl. If Perl creates a .PerlUndef and assigns to it, you lose the overloaded semantics. Sure, you can do that in python: class Add: ...def __add__(self, other): ...print we don't need no steenkin, other ... x = Add() x + 1 we don't need no steenkin 1 But if you know the types of the objects, it makes sense to do the change Benjamin is talking about. So this probably ought to be done at the AST code generation level. Leo sent me a patch that does some basic type inference in pirate and figures out when not to generate the extra PerlUndef. It's in the method binaryExpression. (It's just not used yet because at the time it wasn't compatible with the way I was handling expressions; I've been trying to get my code to work his way, but didn't go back and check whether it worked yet.) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: there's no undef!
On Mon, 18 Aug 2003, Benjamin Goldberg wrote: Hmm. Do you mean if for stmt in block: if stmt.type == undef: flag_as_going_to_delet(stmt.varname) So I can create a new pad when it's assigned? Right. You'd create a new pad just before the for, and put stmt into it. After the for loop ends, you pop off that pad. It can't be a simple pop though, can it? Why not? Because in my examples, I don't see how you know it's the topmost lexical pad. These are dynamic variables here; could you give an example of what you're trying to do with lexicals (my variables)? Sure. It does the exact same thing if you put my in front of each variable: #!/usr/bin/perl my $x = cat; my $y = pop $x?; undef $x; print x = $x \n; print y = $y \n; And remember, undef doesn't get rid of a variable; it merely stores an undef value into it. But it has the same effect as getting rid of the variable, since a variable that doesn't exist also returns undef. :) I mean, consider: #!/usr/bin/perl use strict; { my $x = cat; { my $y = pop $x; # $x and $y are both in scope. undef $x; # $x and $y are still both in scope. $x = 2; # no error here! } # $y goes out of scope. $x = 42; # ok. $y = 6*9; # but this is an error. } # $x goes out of scope now. $x = 13; # this is an error. __END__ There's no way, in this program, for $x to be out of scope while $y is in scope. Yes, but this is just normal lexical scoping behavior. I'm already doing the same thing for python. You say that in perl, undef $x means $x = PerlUndef, which is fine. But in python, that's not the case. del x gets rid of the variable, so that the next find_lex should throw a NameError. I don't see the point in creating an extra lexical scope for every variable that gets deleted. And that's not what you're telling me anyway. In your innermost block, you're telling me that on the python equivalent of the undef $x line i should be popping off a lexical pad in python. I'm saying that's not the case. I should be removing x from the lexical pad. If perl does the same thing, then you get the same behavior as undef x, because an unfound lexical in perl just returns PerlUndef anyway. x = 1 del x x So the easiest thing to me is just to translate del x as remove this from the current pad. Maybe. But, what happens with: x = 1 y = lambda: x del x z = y() Does/should this also throw a NameError? Looks like it: x = 1 y = lambda : x del x z = y() Traceback (most recent call last): File stdin, line 1, in ? File stdin, line 1, in lambda NameError: global name 'x' is not defined Anyway, the short answer is I'm happy with the solution I've got now. It's easy and it does what I expect. But I'll happily change it if you send me a patch. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: thanks and pow / div ops
On Fri, 15 Aug 2003, Leopold Toetsch wrote: PS: have a look at the rather new Cunless a op b opcode in PIR ;-) Cool! :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
there's no undef!
Uh-oh. I just went to implement del x and there's no op to remove a variable from a lexical pad! :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
save/restore on yield?
Just tried out Kenneth Grave's yield stuff -- it works great! But shouldn't .pcc_begin_yield and .pcc_end_yield do saveall and restoreall, respectively? Is there a case where we wouldn't want this? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: save/restore on yield?
I said: But shouldn't .pcc_begin_yield and .pcc_end_yield do saveall and restoreall, respectively? Is there a case where we wouldn't want this? Yes, because for python anyway, I also need to put pop_pad in there: saveall pop_pad .pcc_begin_yield .return whatever .pcc_end_yield restoreall So nevermind. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
try/catch bug with coroutines
It seems that exception handlers get tied to subroutines when they're created, not when they're actually used. For example: ## this works: try: f = make_function() f.die() # raise some error except: pass ## this does not work: f = make_function() try: f.die() # raise some error except: pass This is a problem in general, but especially for me because in python, a generator returns an object, and you call that object's next() over and over until you get a StopIteration. Unfortunately, I can't *trap* that StopIteration in a try block unless I create the generator inside that same block. Following is a detailed test case in imc that illustrates the problem. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -- ## generator_try_bug.imc ## this exposes a bug in parrot exception handling ## a function returns a function and that function ## throws an error. The error is not caught. .sub __main__ new_pad 0 # count() returns a generator .local object count newsub count, .Closure, _count # here's where we'll store it .local object generator # if try: is around the CREATION of the generator, # everything works fine. but we don't want that, so # this is commented out. # #.local Sub handler #newsub handler, .Exception_Handler, catch0 #set_eh handler # call count and get the generator .local Sub retlabel0 newsub retlabel0, .Continuation, ret0 .pcc_begin non_prototyped .pcc_call count, retlabel0 ret0: .result generator .pcc_end ## HERE IS where we want the try block to start .local Sub handler newsub handler, .Exception_Handler, catch0 set_eh handler # now call the generator, which throws 'StopIteration' .local Sub retlabel1 newsub retlabel1, .Continuation, ret1 .pcc_begin non_prototyped .pcc_call generator, retlabel1 ret1: .result $P3 .pcc_end # end the try block (we never get here) clear_eh goto endtry0 catch0: print caught it! endtry0: end .end # here is count(), which returns the generator .pcc_sub _count non_prototyped .local object gen_fun .local object gen_obj newsub gen_fun, .Coroutine, _count_g .pcc_begin_return .return gen_fun .pcc_end_return .end # here is the generator itself # all it does is throw StopIteration .pcc_sub _count_g non_prototyped .local object ex0 .local object msg0 ex0 = new Exception msg0 = new PerlString msg0 = 'StopIteration' ex0['_message'] = msg0 throw ex0 .end ## end of test case ###
Re: there's no undef!
On Sat, 16 Aug 2003, Leopold Toetsch wrote: I have put in scratchpad_delete peek_pad P0 delete P0[foo] deletes names only. Thanks! works great! Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
getprop and find_lex?
I expected getprop to behave like find_lex and throw an exception if the property doesn't exist, but it doesn't: .sub _main .local object Class .local object setv .local object getv Class = new ParrotClass setv = new PerlString setv = value\n setprop Class, name, setv # ok delprop Class, name# ok getprop getv, name, Class # inconsistent! print getv # prints empty string print \n print type is: # this print prints typeof S0, getv # type is: PerlUndef print S0 print \n end .end Maybe that's just what parrotclasses do, which is fine, but a pythonclass would need an exception here. In any case, it might be nice to have a 'hasprop' or a version of 'defined' for properties. (Nicer than making prophash and then checking that to see if it has a particular key) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: getprop and find_lex?
On Sat, 16 Aug 2003, Sean O'Rourke wrote: Michal Wallace [EMAIL PROTECTED] writes: I expected getprop to behave like find_lex and throw an exception if the property doesn't exist, but it doesn't: Are you sure that properties are what you want to use here, rather than attributes (via get_pmc_keyed() or similar)? IIRC parrot's properties are supposed to support out-of-band data like Lisp's plists or Perl 6 properties (http://dev.perl.org/perl6/apocalypse/2#properties) Yes, I think so. I asked about this earlier in a thread called in vs on. Python objects have both __getitem__ (for x[y]) and __getattr__ (for x.y) Dan agreed that for python, using get_pmc_keyed and getprop (respecitvely) was the way to go. Granted, python *classes* wouldn't normally allow __getitem__, but since you can pass them around like any other object, I want to treat classes and objects the same way and handle their differences in the vtable. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: pirate 0.01 ALPHA!
On Sat, 16 Aug 2003, Sean O'Rourke wrote: Michal Wallace [EMAIL PROTECTED] writes: Tadaa! /me blinks at the list comprehensions. :) Cool stuff. test_microthreads failed for some reason I still need to look into, but there's a lot of cool stuff working already. Time for Dan to begin thinking about which direction the pie will fly. D'oh! :/ I didn't mean to include that. It's really broken, because things get lost when I invoke the continuation. That's why the weightless.py has the two PARROT_INLINE(...) macros in the generator dispatch loop at the bottom. The fix for the test is probably something similar, but I'm not sure how to handle it. I think the problem is some standard step that needs to be done around .pcc_begin_yield and .pcc_end_yield, but I haven't thought it through completely. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
thanks and pow / div ops
raise hell is working great with the new find_lex exceptions. Thanks! :) Any plans to to add pow for PMC's? What about separate ops for floor/true division? http://www.python.org/doc/2.2.1/whatsnew/node7.html Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: A certain 4 letter word (was Re: Parrot and STDOUT/STDERR)
On Fri, 15 Aug 2003, Leopold Toetsch wrote: When we have more classes like a Python hierarchy, we will see, how and how far the functionality does match. If we find some, we can put in an intermediate ParrotScalar. I was thinking about this earlier today. Once dynamic PMCs are working, Perl* probably ought to be loaded dynamically, especially if perls 5 and 6 wind up needing different implementations. As far as python goes... I've done some reading on C and I think I feel confident enough to try tackling a pyobject - pmc two-way bridge (just a generic wrapper for the two vtables). I figure it would be nice if we could just wrap the generic pyobject interface, and then hopefully all the existing python modules will just work. :) Aside from that, I was going to follow Dan's lead. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
bug: clear_eh patricide after catch
Here's a new test case for t/pmc/sub.t output_is('CODE', 'OUTPUT', set_eh - throw - clear_eh); print start\n newsub P20, .Exception_Handler, _handler set_eh P20 new P30, .Exception throw P30 print not reached\n end _handler: clear_eh print caught it\n end CODE start caught it OUTPUT # If I run this code from the perl test harness or from my python test suite, it actually kills perl/python, leaving nothing but the message Quit. If I run the code directly from parrot, I get: static Parrot VM: PANIC: Tried to clear_eh a non Exception_Handler! C file exceptions.c, line 143 Parrot file (unknown file), line 0 We highly suggest you notify the Parrot team if you have not been working on Parrot. Use bugs6.perl.org or send an e-mail to [EMAIL PROTECTED] Include the entire text of this error message and the text of the script that generated the error. If you've made any modifications to Parrot, please describe them as well. Version : 0.0.10-devel Configured : Sun Aug 10 16:34:12 2003 Architecture: i386-linux JIT Capable : Yes Interp Flags: 0x40 Exceptions : (missing from core) Dumping Core... Quit ### I don't know if my test is right or not, but I'm expecting the exception handler to still be around after the exception is caught. I don't care if it goes away after the exception is caught, but I need a way to clear the exception handler after I get out of the try/except or try/finally block... Otherwise later exceptions will bring me backward in the code. :/ Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
RE: help raise hell
On Mon, 11 Aug 2003, Joseph F. Ryan wrote: How are you currently throwing/catching exceptions? I think it might be much more difficult to create a model that traps exceptions, rather than setting up code that just figures out how to handle an exception when it occurs. Both JVM-PIR and P6C use continuations to handle exceptions, albeit in different ways. Anyways, since I can't read python, could you explain what you are using now? (-: Sure. This: try: raise 'hell' except: pass Becomes this: 1: .sub __main__ 2: new_pad 0 3: setline 1 # (set_lineno:85) 4: .local Sub handler0 # (visitTryExcept:723) 5: newsub handler0, .Exception_Handler, catch0 # (visitTryExcept:724) 6: set_eh handler0 # (visitTryExcept:726) 7: setline 3 # (set_lineno:85) 8: .local object ex0 # (visitRaise:701) 9: .local object msg0# (visitRaise:702) 10: ex0 = new Exception # (visitRaise:703) 11: msg0 = new PerlString # (expressConstant:164) 12: msg0 = 'hell' # (expressConstant:165) 13: ex0['_message'] = msg0# (visitRaise:705) 14: throw ex0 # (visitRaise:706) 15: goto endtry0 # (visitTryExcept:728) 16: catch0: 17: noop # (visitPass:688) 18: endtry0: 19: end # (compile:817) 20: .end 21: .include 'pirate.imc' If you throw an uncaught exception in python, python has a default handler that prints out the traceback (call stack) shows the error message, and then terminates (or optionally invokes the python prompt). So... I'm saying all generated python programs should have one of these giant try-except blocks around them, and that's what I mean by trapping the exception. In the above example, if I did raise hell instead of raise 'hell', python would throw a NameError that I could trap just like any other exception: try: raise hell except NameError: print There is no hell. except: print Something else went wrong. (my code only gives you one except: block so far, but real python lets you have as many as you like for different types of exceptions) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: parrot bug: continuations/multiple return
On Sat, 9 Aug 2003, Benjamin Goldberg wrote: Michal Wallace wrote: [snip] def f(): return g() [snip] # f from line 3 .pcc_sub _sub1 non_prototyped .local object res1# (visitReturn:528) find_lex $P2, 'g' # (callingExpression:325) newsub $P3, .Continuation, ret0# (callingExpression:331) .pcc_begin non_prototyped # (callingExpression:332) .pcc_call $P2, $P3# (callingExpression:335) ret0: .result res1 # (callingExpression:338) .pcc_end # (callingExpression:339) .pcc_begin_return # (visitReturn:530) .return res1 # (visitReturn:531) .pcc_end_return # (visitReturn:532) .end Does python allow tail calls to be optomized? That is, would it be legal python semantics if f were to become: .pcc_sub _sub1 non_prototyped find_lex $P2, 'g' .pcc_begin non_prototyped .pcc_call $P2, P1 .pcc_end .end Well, the real python doesn't optimize tail-calls at all. You'll get a nasty max recursion depth exceeded traceback if you try running def f(x): return f(x+1) But I don't see any reason pirate shouldn't do it, since the difference is pretty much transparent. (untested) Also... why is $P2 merely an imcc temporary, without a real name? That is, why not do: .pcc_sub _sub1 non_prototyped .local object sub1 find_lex sub1, 'g' .pcc_begin non_prototyped .pcc_call sub1, P1 .pcc_end .end The more different prefixes you use (res, sub, $P), the lower the numbers you'll need to append to them to make the names unique. Not to mention, it'll make the generated code more meaningful. Another advantage is that with '.local' names, if you accidentally use a name declared in one subroutine, in another, imcc will consider this to be an error. Such a mistake might be otherwise difficult to spot. Hmmm. The counters are global so there shouldn't be any conflicts. I'd actually been trying to move away from .local now that I started using lexicals... If there's going to be two sets of names for everything I'd rather one of them was just $Pxx... Now, if I could say: .lexical g That would be really nice... :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
pirate status / need help with instances
Just wrapping up an all-night coding spree... Py-pirate can now handle: - functions (closures, recursion, etc) - global variables - tuples (but they turn into lists) - dictionaries (create, setitem, getitem, print) - list comprehensions - raise (strings only) - try...except (partial) - try...finally - assert The only tricky parts left for the code generator are classes, exec/eval/import, and possibly slices. Right now, I'm a bit stuck with classes. I've got the class statement working, and it creates a parrot class... But I'm not quite sure how to instantiate a class. The problem is that for: class Clown: pass I have a lexical variable Clown pointing at a parrotclass pmc. However, when I go to instantiate Clown, I do this: bozo = Clown() There's no new operator like in java, so the problem is that this looks just like a function call to python. So I have to figure out whether to call invoke or new... Though now that I think about it, I'm not really sure what operator to use to make a new instance. Anyway, there's no way to tell at compile-time whether something is a constructor or a normal function... So I'm trying to decide between two approaches: * make parrotclass handle invoke this strikes me as the most efficient, but I'm not really confident with C so I'm hesitant to try it * grab the lexical, check whether it's a class, and if so, do newclass instead of invoke. I also thought about making a constructor into just a normal function, but then the lexical would have to bind to either the class or the function, and that's no good because classes and functions can both have attributes in python. Any advice? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: why ~ for xor?
On Mon, 11 Aug 2003, Thomas Vesper wrote: Michal Wallace wrote: Out of curiosity, why does ~ map to both unary bitwise-not and binary bitwise-xor in imcc? I was expecting xor to be ^ and ^^ See Apocalypse 3 for this. ^ was reclaimed for hyperoperators. Binary ~ was chosen as replacement since bitwise-not is already somehow like bitwise xor with only one operand. And so ~~ became logical xor. Aha. I remember that now. Thanks. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
why ~ for xor?
Out of curiosity, why does ~ map to both unary bitwise-not and binary bitwise-xor in imcc? I was expecting xor to be ^ and ^^ Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: generic code generator? [was: subroutines and python status]
On Tue, 5 Aug 2003, Dan Sugalski wrote: The original thought was to use the new perl 6 grammar engine/code to do this, but I think it'll be a while before that's ready to go. I think perl6 is definitely the way to go, once it's ready. BTW, what's the deal with Bundle::Perl6? I tried installing it from cpan yesterday but it wouldn't install with my perl. (I forget why) Is it meant to be usable today? Rather than invent an entirely new language for this (which is somewhat problematic) why not go for something already reasonably well-known? YACC and BNF grammars seem like a good place to start, especially as most of the languages have some form of grammar defined for them. Well the new language was just for the imcc code templates. Now I think the better path is to define a code-generating class for each ast node. Then PythonWhileNode can be a subclass of the generic WhileNode. (Python while statements have an extra else block that most languages don't have) It's only a first step, as then everyone beats the heck out of the resulting token stream, but it's a place to start. 80-90% of the result will end up being generically parseable as well--x + y will generate the same code for all languages if x and y are PMCs, for example, so I'd bet we could have a lot of standard products designed. Yep. For now, everything pypirate generates *is* pmc based, since python doesn't have type declarations. Generic pirate should probably have a declare node though. (Especially if it's to handle perl6, right?) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: generic code generator? [was: subroutines and python status]
On Tue, 5 Aug 2003, Joseph Ryan wrote: Okay, I don't have a good syntax in mind yet, the point is it's a template language and you can subclass/override/extend the template. Maybe there's no syntax and it just uses cleanly coded classes in some oo language. Or perl6 with it's grammars and rules. I don't know. I think that trying to define a new syntax for a new meta-language is a bad idea. The goal of a GCG (Generic Code Generator) should be to allieviate the compiler writers of the responsiblity of generating code. Forcing them to generate different code doesn't help solve the problem. (-: Good point. I don't think I was very clear yesterday. Let me try again. Let's say you're generating... I dunno.. haskell: haskell_parser - ast - pirate - parrot_code -- imcc - pbc ^ | parrot_code__templates So the haskell parser only has to generate a pirate ast structure. Either that's a very basic string (I like your XML idea) *or*, in the future, the parser calls pirate tree-building-methods directly. The tree-building methods are why I was talking about C, but for now, I don't mind doing a bunch of xml-generation every time we call eval/exec. (It's probably the simplest thing to do right now and should be pretty easy for everyone) 1.) Instead of forcing the compiler writer to generate code, the compiler writer would only have to transform the parse tree into a structure that is name-consistant with the GCG's standard, and then use any of a number of existing libraries to dump the tree as YAML/XML. I like it! :) 2.) Since there are more YAML/XML parsers than I can count implemented in nearly modern useful language I can think of, the GCG could be generated in any language without causing a stall on starting on the generic code generation part of the project. (you know, the important part) Agreed! 3.) It would be possible to handle language-specific nodes by defining some sort of raw node whose value could be raw imcc code. That's where the templates come in, but since my crack at a template language last night sucked so bad, I'm thinking that at least for prototyping I'm going to use a python class. So I'm thinking I'm going to try refactoring so that I can do this: pypirate something.py something.xml cat something.xml pirate -l python something.imc imcc something.imc or just: pypirate something.py | pirate -l python | imcc or just: pypyrate -r something.py That also means the pirate command can be written in any language we like. Probably eventually that'll be perl6, but for now (unless someone else wants to volunteer some code) I plan to work from the code I have for python. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: parrot bug: continuations/multiple return
On Sat, 9 Aug 2003, Leopold Toetsch wrote: As calling conventions clearly state, that the caller has to save everything, its probably up to imcc/pcc.c to insert above statements, if another sub gets called from a sub. I'll fix that in a minute ;-) I just synced up with cvs and now everything works! Thanks! Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: This Week's Perl 6 Summary
On Tue, 5 Aug 2003, Piers Cawley wrote: Approaching Python Discussions (and coding) of the Parrot implementation of Python continued this week. Michal Wallace is working on taking a preexisting (but incomplete, it's a proof of concept only) python parse tree - Wow, after reading these things for the past year or so I feel famous. :) IMCC supports the Parrot Calling Conventions Leo announced that IMCC's brand of assembler, PIR (I can't remember what it stands for, Parrot Intermediate Representation perhaps). Of course, there are things it doesn't quite do yet (tail call detection, only preserving 'necessary' registers...) and it's somewhat lacking on the test front, but it's a start. Yay Leo! http://xrl.us/crv75 I missed this the first time. Leo, this rocks! Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: bug: clear_eh patricide after catch
On Mon, 11 Aug 2003, Leopold Toetsch wrote: No, the exception object isn't around anymore in the handler, so you don't Cclear_eh there. This could of course be just my wrong implementation. No, it makes sense. You wouldn't want an exception in the catch: block to trigger an infinite loop. But if that's the way to go, there ought to be a note in the docs. (see patch below) I don't care if it goes away after the exception is caught, but I need a way to clear the exception handler after I get out of the try/except or try/finally block... Otherwise later exceptions will bring me backward in the code. :/ Can you insert Cclear_eh before you fall through to except/finally? Yep. That works perfectly. Thanks. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -- Index: core.ops === RCS file: /cvs/public/parrot/core.ops,v retrieving revision 1.316 diff -c -r1.316 core.ops *** core.ops8 Aug 2003 08:15:05 - 1.316 --- core.ops11 Aug 2003 23:30:55 - *** *** 479,485 =item Bclear_eh() ! Clear out the most recently placed exception. =item Bthrow(in PMC) --- 479,486 =item Bclear_eh() ! Clear out the most recently placed exception. This also ! happens automatically if an exception is thrown. =item Bthrow(in PMC)
Re: pirate status / need help with instances
On Tue, 12 Aug 2003, Leopold Toetsch wrote: ... So I'm trying to decide between two approaches: 3) wait until classes and objects are done ;-) 4) simulate an object system with closures :) I wound up getting a couple C books today. I'm trying to see what I can do about wrapping PyObject as a PMC... Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: IMCC hangs
On Sun, 10 Aug 2003, Vladimir Lipskiy wrote: Seems to be related with the multiple freeing reported by Michael. I thought his name was Michal (:8 yes, I was born without an e. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
why new_pad *INT*?
Hey all, I'm just starting to get into using pads, and I'm not sure I understand new_pad. Specifically, why does it take an int? It seems to me, that 9 times out of 10, you're going to want to create a new pad at the next lower depth than the one before. So, two questions: 1. Should there be a new_pad that takes no arguments to do this, so we don't have to keep count manually? 2. When would you NOT want to use new_pad (current_depth+1) ? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: generic code generator? [was: subroutines and python status]
On Thu, 7 Aug 2003, Dan Sugalski wrote: haskell_parser - ast - pirate - parrot_code -- imcc - pbc ^ | parrot_code__templates So the haskell parser only has to generate a pirate ast structure. Either that's a very basic string (I like your XML idea) *or*, in the future, the parser calls pirate tree-building-methods directly. I'd much rather go for the AST directly for a number of reasons. Not the least of which is a deep personal loathing for XML, but putting that aside it seems sub-optimal to have a binary structure which we then serialize to text and then deserialize all as part of a single parse and compile stage. XML has the added disadvantage of needing a good XML parser, which probably means expat or something like it. (Yeah, I know, we could restrict ourselves to a subset of XML so we don't have to have a full parser, but that'll never last--someone'll expand it to a full parser at some point) Klaas-Jan and I spiked out a prototype last night that took s-expressions. We got this working: (while (const 1) (pass)) Where While was a class that could be subclassed for PythonWhile (python has an extra else clause in there) I think everyone agrees that long term, there's no point in passing around xml or s-expressions because it'll be dog slow, but for now, for prototyping, passing the flattened AST in as an s-expression on STDIN means that anyone can write to it and we don't have to worry about a tree-building interface until after the code is working. Going for a full-fledged AST builder/flattener meets some of the long-term goals as well, as it's been planned to be the stage between the parser and IMCC for ages (pretty much since IMCC first appeared) so it'd be worthwhile. I agree. The main reason to hold off *FOR NOW* is bindings. If everyone wrote their parsers in C, then we could just use that. But I don't feel like learning C, so... Right now the code is in python. I suspect eventually this will be written in perl6 or someting. We should consider AST transforms as well, since a number of optimizations are best performed on the AST, and many languages will want to get hold of the AST before it goes any further and process it in some way. (This would be how Lisp macros would act, for example) Absolutely. I suspect that for python, I'll be turning list comprehensions into the corresponding foreach nodes before serializing the tree. 1.) Instead of forcing the compiler writer to generate code, the compiler writer would only have to transform the parse tree into a structure that is name-consistant with the GCG's standard, and then use any of a number of existing libraries to dump the tree as YAML/XML. I like it! :) This'd be a cool thing to be sure, and useful as a human-readable form. (Though I'd prefer the AST that's frozen into the bytecode be in a form that's more efficient to deserialize) I'd best go and update the license terms then, to make sure there aren't any problems. (Old issues raised by GCC an age ago) I'm not sure I follow this. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: pirate status / need help with instances
On Tue, 12 Aug 2003, Michal Wallace wrote: I wound up getting a couple C books today. I'm trying to see what I can do about wrapping PyObject as a PMC... What's the secret to making parrot recognize a new PMC? I've got my .pmc file but I'm not sure what to do next. The article about making PMC's on perl.com is WAY out of date. (I don't care if I can't load it dynamically yet, I just want to get it running at all!) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
help raise hell
Here is how I usually trigger a generic exception in python: raise hell Traceback (most recent call last): File stdin, line 1, in ? NameError: name 'hell' is not defined Unfortunately, I can't seem to trap that in parrot, because a find_lex failure isn't an exception. Or am I missing something? CAN trap this though: raise 'hell' So it's not a showstopper, but still... Is this easily fixable? I miss my idiom... :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: parrot bug: continuations/multiple return
On Sun, 10 Aug 2003, Leopold Toetsch wrote: Piers Cawley [EMAIL PROTECTED] wrote: Leopold Toetsch [EMAIL PROTECTED] writes: As calling conventions clearly state, that the caller has to save everything, its probably up to imcc/pcc.c to insert above statements, if another sub gets called from a sub. I'll fix that in a minute ;-) If and only if that's not a tail call of course. Good point. But I can imagine, that's by far more simple to detect tail calls at the AST level then inside the flattened code parrot sees. So the HL can emit (a TBD) flag like tailcall appended to the .pcc_call sequence. Then the call can be optimized to a Cjump opcode. The construction of the subroutine object (which is outside of the call sequence) will lead to an used once LHS, which the optimizer already can get rid of. Well, if you write it, I'll have pirate inspect the AST and try it out for you. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
bug: two segfaults
The following code segfaults immediately. If you uncomment the second line (print ) it works. However, if you then uncomment the #non_prototyped keyword in _depth1, it segfaults immediately again. When I say it segfaults immediately, I mean that the initial 0 is not printed. (Should I be reporting these somewhere else?) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -- .sub __main__ #print new_pad 0 print 0 newsub $P0, .Sub, _depth1 newsub $P1, .Continuation, ret0 .pcc_begin non_prototyped .pcc_call $P0, $P1 ret0: .pcc_end print \n end .end .pcc_sub _depth1 #non_prototyped new_pad 1 print 1 newsub $P2, .Sub, _depth2 newsub $P3, .Continuation, ret1 .pcc_begin non_prototyped .pcc_call $P2, $P3 ret1: .pcc_end pop_pad .pcc_begin_return .pcc_end_return .end .pcc_sub _depth2 non_prototyped new_pad 2 print 2 pop_pad .pcc_begin_return .pcc_end_return .end
RE: pirate status / need help with instances
On Mon, 11 Aug 2003, Brent Dax wrote: Sean O'Rourke: # * make parrotclass handle invoke # this strikes me as the most efficient, # but I'm not really confident with C # so I'm hesitant to try it # # This seems to me like the way to go, except you might # subclass parrotclass to pythonclass (since this lack- # of-new seems to be the Pythonic way). The C should # pretty much just turn around and call pmc_new, then # return the original return address that was passed in. I don't think this is the answer, because... use PythonClass; $pyobj=PythonClass.new(); #Doesn't work--need to somehow invoke # the class #Sorry, I'm not very familiar with Python... import PerlClass plobj=PerlClass() #Doesn't work--need .new I think this is a syntactic issue, not a semantic issue; as such, it needs to be dealt with at the syntactic (bytecode) level, not the semantic (PMC) level. Actually, python has a magic method called __new__. __new__ actually creates an object (so it gives you the ability to make meta-classes, which we'd also need for ruby. Once __new__ is called and the object is around, python then calls __init__. plobj=PerlClass() #Doesn't work--need .new What DOES this do? It seems to me that parrotclass could still have invoke for languages that use it, and that perlclass should just throw an exception if you try it. There's no problem doing PerlClass.new() from python. It wouldn't be transparent, but that's fine. It's a small price to pay, and if PerlClass() threw an exception remind us to use it, then it probably wouldn't be a problem at all. So I think invoke on the parrotclass is the way to go. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
okay to use iterator?
perlhash.pod says: TODO: Steve Fink sayd: And if there were a keys() method, then 'defined' and 'exists' are very different. (And there ought to be, and would be if we weren't all ignoring Leo's iterator proposal.) I need to read that proposal :-) Looks like the proposal got accepted? I see iterator.c and read the recorresponding tests... I went ahead and used it. Is that cool? # s is a PerlHash dict: unless s goto empty .local object iter .local object key .local object val .local string skey key = new PerlString print { iter = new Iterator, s iter = 0 # reset it unless iter goto enddict shift skey, iter key = skey .arg 1 .arg key call __py__print print : val = s[skey] .arg 1 .arg val call __py__print enddict: print } empty: print {} goto done Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
parrot bug: continuations/multiple return
Hey all, Sorry for the huge code listing here, but I don't have a simpler case. This is what pirate outputs when it compiles the following program: def f(x): if x: return 1 else: return 0 print f(1), f(0) As far as I can tell, I'm doing exactly the same thing for the return 1 and return 0 branches... But the output of this program is: 1 get_string() not implemented in class 'Continuation'\n Calling f(0) causes the bug even if f(1) isn't called first. I think this is a bug in parrot's register allocation scheme. Or am I just doing something stupid? :) BTW: It would be SO nice if parrot could print a line number for ALL its error messages. (Or if the debugger didn't segfault g) ## .sub __main__ new_pad 0 setline 1 newsub $P0, .Sub, _sub0 store_lex -1, 'f', $P0 .local object arg0 arg0 = new PerlInt arg0 = 1 find_lex $P2, 'f' newsub $P3, .Continuation, ret0 .pcc_begin non_prototyped .arg arg0 .pcc_call $P2, $P3 ret0: .result $P1 .pcc_end .arg $P1 call __py__print print .local object arg1 arg1 = new PerlInt arg1 = 0 find_lex $P5, 'f' newsub $P6, .Continuation, ret1 .pcc_begin non_prototyped .arg arg1 .pcc_call $P5, $P6 ret1: .result $P4 .pcc_end .arg $P4 call __py__print print \n end .end .include 'pirate.imc' # f from line 1 .pcc_sub _sub0 non_prototyped .param object x setline 2 .local object test0 test0 = new PerlInt test0 = x unless test0 goto elif0 ### if x return 1 .local object res0 res0 = new PerlInt res0 = 1 .pcc_begin_return .return res0 .pcc_end_return goto endif0 elif0: ### else return 0 .local object res1 res1 = new PerlInt res1 = 0 .pcc_begin_return .return res1 .pcc_end_return endif0: .end ## Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: calling conventions, variable-length parameter lists
On Fri, 8 Aug 2003, TOGoS wrote: I want to be able to have a function with this kind of signature: func ($param1, *$otherparams) AFAIK, there is no way to implement this with the current calling conventions. You would have to do something with variable register IDs, which we don't have and which would probably be a bad idea, anyway. Maybe non_prototyped pcc subs should always have all their parameters shoved into an array? (and likewise for return values :-). Hopefully most subroutine calls will be prototyped, anyway, so it wouldn't cause too much of an overall speed-hit, and it would make many things a lot simpler (not to mention even *possible*). Why not make $otherparams a PerlArray? I haven't gotten this far with python, but I'm not sure I understand why that wouldn't work? Maybe there should be a register reserved for an Array and another for a Hash (for extra keyword arguments)? Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: why new_pad *INT*?
On Sat, 9 Aug 2003, Sean O'Rourke wrote: The problem is that when adder() gets returned, it needs to remember the enclosing pad. So this needs to be newsub $P1, .Closure, _sub1 which (IIRC) will save the lexical environment in which it was created (see closure.pmc), then restore that when it is invoked. Thanks! I see the light. :) I just made all python routines closures for now, and all my tests passed. Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: parrot bug: continuations/multiple return
On Sat, 9 Aug 2003, Leopold Toetsch wrote: Nice coincidence. S. Togos' bug report too. Anyway, its already fixed. Gosh you're quick. Thanks! Want another one? :) def g(): return 0 def f(): return g() print f() This prints: 'No more I register frames to pop!' I was hoping those two were the same problem, but it doesn't look like it. This happens any time one function calls another, whether it passes in arguments or not. The bug seems to happen on the return 0 line. (It may very well be my generated code, but I can't find it if it is) ## .sub __main__ new_pad 0 setline 1 # (set_lineno:81) newsub $P0, .Sub, _sub0 # (genFunction:378) store_lex -1, 'g', $P0# (genFunction:380) setline 3 # (set_lineno:81) newsub $P1, .Sub, _sub1 # (genFunction:378) store_lex -1, 'f', $P1# (genFunction:380) find_lex $P5, 'f' # (callingExpression:325) newsub $P6, .Continuation, ret1# (callingExpression:331) .pcc_begin non_prototyped # (callingExpression:332) .pcc_call $P5, $P6# (callingExpression:335) ret1: .result $P4 # (callingExpression:338) .pcc_end # (callingExpression:339) .arg $P4 # (visitPrint:394) call __py__print # (visitPrint:395) print \n# (visitPrintnl:403) end # (compile:574) .end .include 'pirate.imc' # g from line 1 .pcc_sub _sub0 non_prototyped .local object res0# (visitReturn:528) res0 = new PerlInt# (expressConstant:153) res0 = 0 # (expressConstant:154) .pcc_begin_return # (visitReturn:530) .return res0 # (visitReturn:531) .pcc_end_return # (visitReturn:532) .end # f from line 3 .pcc_sub _sub1 non_prototyped .local object res1# (visitReturn:528) find_lex $P2, 'g' # (callingExpression:325) newsub $P3, .Continuation, ret0# (callingExpression:331) .pcc_begin non_prototyped # (callingExpression:332) .pcc_call $P2, $P3# (callingExpression:335) ret0: .result res1 # (callingExpression:338) .pcc_end # (callingExpression:339) .pcc_begin_return # (visitReturn:530) .return res1 # (visitReturn:531) .pcc_end_return # (visitReturn:532) .end Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
pirate guide
Just got the parrot calling conventions working for Py-Pirate. I also wrote a guide that explains how the code is laid out for people who don't know python: http://pirate.versionhost.com/viewcvs.cgi/pirate/GUIDE?rev=1.1 Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: why new_pad *INT*?
On Sat, 9 Aug 2003, Sean O'Rourke wrote: Remember, the pad depth reflects lexical scope nesting, not dynamic scoping. So if you mean current_depth as current compile-time depth above, then you're right, but the VM would have no way to tell. If you mean run-time depth, which the compiler could know about... A top-level sub should not create a new pad at depth + 1, since that would put it inside its caller's lexical scope, which would just be weird. Okay, I definitely need some help understanding this. Here's some python code that defines a closure: def make_adder(base): def adder(x): return base+x return adder h = make_adder(10) print h(5) When I run this in python 2.2, it prints 15. When I run it through pirate, I get this: -scratch_pad: too deep Now, in my mind: depth 0 has: make_adder, h depth 1 has: base, adder depth 2 has: x The top level .sub should start with 'new_pad 0' The make_adder .pcc_sub should start with 'new_pad 1' The adder .pcc_sub should start with 'new_pad 2' I think the error happens because I'm calling a depth 2 function from depth 0, but if I change adder's new_pad depth to 1, it can't find base. I don't know how to get this to work the way I want. Can anyone help me out here? (Generated code follows - note the GETS HERE line) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ -- .sub __main__ new_pad 0 setline 2 newsub $P0, .Sub, _sub0 store_lex -1, 'make_adder', $P0 .local object h .local object arg0 arg0 = new PerlInt arg0 = 10 find_lex $P5, 'make_adder' newsub $P6, .Continuation, ret0 .pcc_begin non_prototyped .arg arg0 .pcc_call $P5, $P6 ret0: .result h .pcc_end store_lex -1, 'h', h .local object arg1 arg1 = new PerlInt arg1 = 5 find_lex $P8, 'h' newsub $P9, .Continuation, ret1 .pcc_begin non_prototyped .arg arg1 .pcc_call $P8, $P9 ret1: .result $P7 .pcc_end .arg $P7 call __py__print print \n end .end .include 'pirate.imc' # make_adder from line 2 .pcc_sub _sub0 non_prototyped .param object base new_pad 1 store_lex -1, 'base', base setline 3 newsub $P1, .Sub, _sub1 store_lex -1, 'adder', $P1 .local object res1 find_lex res1, 'adder' pop_pad .pcc_begin_return .return res1 .pcc_end_return .end # adder from line 3 .pcc_sub _sub1 non_prototyped print GETS HERE!\n new_pad 2 print WON'T GET HERE!\n .param object x store_lex -1, 'x', x .local object res0 find_lex $P2, 'base' find_lex $P3, 'x' $P4 = new PerlUndef $P4 = $P2 + $P3 res0 = $P4 pop_pad .pcc_begin_return .return res0 .pcc_end_return .end
repeat() not implemented in PerlInt
After running cvs up -d and then make, a bunch of my tests broke. Here's the problem boiled down to the simplest case I can find: [~/pirate]: cat bug.imc .sub __main__ $P2 = new PerlInt $P2 = 1 $P3 = new PerlInt $P3 = 1 if $P2 == $P3 goto cmp1 cmp1: end .end [~/pirate]: imcc bug.imc repeat() not implemented for PerlInt What happened!? :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: generic code generator? [was: subroutines and python status]
On Sun, 3 Aug 2003, K Stol wrote: What do you think? Want to try squishing pirate/python and pirate/lua together? :) Yeah, I like the idea. Let's try this out. Well, I finished reading your report[1] and posted some of my (rather unorganized) thoughts up at [2] It does seem like there are some snags getting languages to talk to each other, even with the calling conventions, but even so, I'm even more convinced now that a generic, overridable code-generator is the way to go. It seems to me that if we want to maximize the number of languages using it, the generic compiler shouldn't depend on anything but C and parrot... But until we get it working, I'd like to stick to a dynamic language like python/perl/lua/scheme. And, well, my code's already in python... :) [though I'd actually love to try out some lua 5] What I'm picturing is a template system for specifying chunks of IMCC. Something like this: ast generic: on @while(test, body): % while= gensym(while) % endwhile = gensym(endwhile) % test = gensym($I) {while}: {test} = @expr unless {test} goto {endwhile} @body {endwhile}: on @if(test, elif*, else?): ... ast python(generic): on @while(test, body, else?): ... Okay, I don't have a good syntax in mind yet, the point is it's a template language and you can subclass/override/extend the template. Maybe there's no syntax and it just uses cleanly coded classes in some oo language. Or perl6 with it's grammars and rules. I don't know. Once the templates are defined, you pass the compiler your AST and it walks it and applies the template. So the C api basically is just about building the tree and saying generate with this language file. Then the language designer's job is just to transform an outside ast into a generic ast. Anyway, I'm talking a lot of nonsense. I'd rather just see what I can do about decoupling my code generator from python and sharing it with another language instead. [1] lua report: http://members.home.nl/joeijoei/parrot/report.pdf [2] http://pirate.versionhost.com/viewcvs.cgi/pirate/INTEROP?rev=1.1 Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
Re: generic code generator? [was: subroutines and python status]
On Tue, 5 Aug 2003, Stephen Thorne wrote: It seems to me that if we want to maximize the number of languages using it, the generic compiler shouldn't depend on anything but C and parrot... But until we get it working, I'd like to stick to a dynamic language like python/perl/lua/scheme. And, well, my code's already in python... :) [though I'd actually love to try out some lua 5] I like the concept, but I have a comment about the implementation. For PHP, and even for Python, it is necessery to do code generation on the fly, for things like eval() and dynamic imports (php's include is always a dynamic import). definitely. Thus the code generator is best suited to be in a language that can be run from within the parrot machine, otherwise statements like 'eval()' would not be possible without binding parrot to a non-portable C library. I would instead suggest that we pick a suitable 'dynamic' language to write the code generator in, so it can be self-hosting. Sure. That's why I said stick to C or parrot. I'm not sure I understand why C wouldn't be portable... (I don't know c at all but I thought that was the point)?? I'd much rather use parrot. Where parrot means something else compiled down to parrot, and something else means python. :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --
generic code generator? [was: subroutines and python status]
On Fri, 1 Aug 2003, K Stol wrote: From: Leon Brocard [EMAIL PROTECTED] ... I don't like things becoming dead-ends. How much work do you think it'd be to extend it some more and update it to latest Lua? ... 2: I misdesigned the code generator; that is, at the point where I couldn't start over, it was too late, the code generator was too big already (it was unmaintainable). But because I had a time schedule, I kept it this way (the product itself wasn't the most important thing, I was writing an undergraduate report for the last semester of my education (for the record: the project served me well, I finished this education)) Would it be worth checking this into parrot CVS? Only if the thing would be working, otherwise it would only be a source of confusion and frustration. Now I'm just thinking very hard to decide if I've got enough spare time to rewrite the code generator Hmm. I've only messed around with Lua for a few hours though, and it was several months ago, but the Lua language seems to be pretty similar to python. Really, there's a ton of overlap between the various high level languages that parrot wants to support. Maybe we could put together a generic code generator that everyone could use? Obviously, it would have to be set up so you could override the parts for each language, but it shouldn't be too terribly hard. What do you think? Want to try squishing pirate/python and pirate/lua together? :) Sincerely, Michal J Wallace Sabren Enterprises, Inc. - contact: [EMAIL PROTECTED] hosting: http://www.cornerhost.com/ my site: http://www.withoutane.com/ --