Re: junctions and conditionals

2009-04-03 Thread Miroslav Silovic

Dave Whipp wrote:
I'm thinking that the solution to this issue may be a little more 
radical than to-date: don't permit junctions to be stored in $ 
variables! Instead, require junctions to use a twiggle, to alert the 
reader that the surprises may be lurking.


my $x = 1|2; #error
my $|x = 1|2; # ok

Then you just need to invent some syntax to say that collapse is (or 
perhaps isn't) desired:


if [[ $|x  1 ]] { say $|x collapsed }

The most important thing that this does is that it leaves open the 
option to allow $ variables to hold junctions in some future version 
of Perl, without that future version being constrained by legacy 
semantics.




I'd second the twigil idea. Reason: I'd -really- like perl6 to be 
compilable into an efficient machine code without a JIT magic that we 
can currently only handwave about.


For that, I'd propose a rule of a thumb: ints are ints. Of course, 
floats and other unboxed types should also be just plain unboxed types, 
but I'd like the rule of a thumb to be short and to the point.


So,

int $x = 1|2;

should be an error.

Also,

int $x = 1 but not really a number;

should also be an error or at least a warning that mixin stripping and 
unboxing took place. If you want polymorphic here, use Ints. That'd also 
mean that


my @x of int;

can be implemented as a homogenous int vector, meaning -really- 
efficient and manipulable through the kind of code that modern CPUs are 
really good at (since as soon as you know you won't be lazy, you only 
need to be polymorphic about asking for the beginning of the in-memory 
buffer that can be manipulated directly. Even if that buffer doesn't 
contain all the elements, you can refill it as needed, and that could 
still be fast as long as the other side of the partially-lazy barrier 
also speaks int). Also, as far as I'm aware, there is no tracing VM that 
can create a homogenous arrays for you if you can't already do them.


From the above, the need for twigils in junctions should be apparent.

   Miro



Re: ***SPAM*** Re: perl 6 grammar

2007-12-04 Thread Miroslav Silovic
cdumont wrote:
 In japanese it could even be :

 wa {
   '' no baai ni { ... }
 }

 Getting rid off the thema or I guess here taking $_ as the default.

 is this possible : 

 given $operator {
 '' {}
 '' {}
 }

 ?

   
If Larry doesn't mind me elbowing into the conversation... The
unmentioned detail here is that given and when are decoupled; they're
not two keywords in the same construct. In other words, given can be
used without when and when can be used inside any block.

Cgiven only binds $_ and executes a block, it's kind of a single-shot
Cfor. So you can do this:

given $long_expression_that_is_difficult_to_type_more_than_once {
.trim;
s:g/!alpha//;
.prettify;
.indent;
say $_;
}

And Cwhen simply matches the current $_ with its argument. So you can,
for example, use it inside Cfor or Cmap:

@encoded = map @list:{
when 'black' { 1 }
when 'white' { 2 }
when /#(.*)/ { $1 }
}

Miro



Implementing junctions

2007-08-06 Thread Miroslav Silovic
I've been looking at various Perl6 operators in terms of what their 
implementation would look at the Parrot level. Junctions struck me as 
possibly highly problematic. The issue is, how would one go about 
compiling them at the point when they get passed to a function call as 1 
of the parameters.


For instance, in pugs, this works:

pugs my $a = 1|2
(1 | 2)
pugs sin $a
(0.8414709848078965 | 0.9092974268256817)
pugs sub foo() { return 1|2; }
pugs foo()
(1 | 2)
pugs sin foo
(0.8414709848078965 | 0.9092974268256817)

I came up with two ways:

1) Use Junction PMC that overloads various conversion entries in its 
vtable. Operators will have to use continuations to loop over junction 
contents.


-- This seems a non-starter, as vtable entries can't spawn a 
continuation that can reenter them. (right?)


2) Expand explicitly.

-- Problem is, you need to insert checks for each parameter before each 
function call, if a junction can be assigned to a variable like above.


This means that perl6 calling convention would have to explicitly 
typecheck parameters everywhere. This strikes me as much less efficient 
then, say, checking for ties everywhere. And ties have to be explicitly 
declared.


Would it make sense to require that Junctional variables *MUST* be 
declared as such, and same with function that return junctions? Strict 
reading of S9 seems to imply that this already is the case, but possibly 
a clarification with some examples might be in order.


So the example above would read:

my Junction $a = 1|2
sub foo(-- Junction) { return 1|2; }

And hope this topic hasn't already been rehashed. :)

   Miro



Re: Runtime role issues

2006-10-12 Thread Miroslav Silovic

Paul Seamons wrote:


On closer inspection, is it even possible to add a Role to a Class at 
runtime?  



If it isn't now, I would certainly like to have a hook available through 
MOP (which is, to the best of my knowledge, still unspecified).




I thought that Class and Role composition outside of compile time 
resulted in

a new pseudo Class for the subsequent instances of that composition - in
which case the original Class would remain unmodified.



I believe 'does' and 'but' operators work that way, yep. Additionally, 
they're per instance. Offhand I don't even recall any way to create an 
uninstantiated class with a role mixed at runtime (would my 
$class_foobar = ::Foo but ::Bar do the trick?)


  Miro



Re: RFC: multi assertions/prototypes: a step toward programming by contract

2006-09-29 Thread Miroslav Silovic

Aaron Sherman wrote:


In the RFC, I was trying to develop a method by which a module could
assert a stricture (consider this part of use strict in Perl 6 if you
will) that would constrain the CALLER of that module (as well as the
module itself, of course) to a particular signature template for a
multi. This allows us to centrally document a multi that might be
defined in many places, and have that documentation actively constrain
the multi to match. In this way, the user doesn't have to figure out
that max is a method on Array in order to find its documentation, and a
module that uses Array gets



Um, so if I get this right, you want to restrict the users of the module 
from *EVER* extending that particular part of the module's functionality?


I would be strongly opposed to the existence of this feature. Firstly, 
what you propose is not DBC. Design by contract is about requiring 
minimal functionality from the parties in the contract, not about 
banning them from going above the requirements. Secondly, what happens 
when you use two modules with two different prototypes for the same 
multi? Without this declaration, and assuming the modules don't try to 
dispatch on the same argument lists, everything just works. But with 
this stricture, you simply aren't allowed to do this, and I don't see 
any justification for it. Frankly, sometimes things -will- be named the 
same and yes, sometimes you need to use grep to find the docs. Not sure 
why this is a problem, though.


   Miro




Re: RFC: multi assertions/prototypes: a step toward programming by contract

2006-09-28 Thread Miroslav Silovic

Aaron Sherman wrote:


I certainly hope not, as I agree with you! That's not the goal at all,
and in fact if that were a side effect, I would not want this to be
implemented. The idea of having types AT ALL for protos was something
that I threw in because it seemed to make sense at the end. The really
interesting thing is to match signature shapes, not types. That is, max
doesn't take two positional arguments, and a max that does is probably
doing something that users of max will be shocked by. To this end, a
programmer of a library *can* issue an assertion: all implementations of
max will take one (no type specified) positional parameter and any
number of adverbial named parameters (again, no type specified).



What bugs me is a possible duplication of functionality. I believe that 
declarative requirements should go on roles. And then packages could do 
them, like this:


package Foo does FooMultiPrototypes {
...
}

Of course, I hadn't quite thought this through - as packages aren't 
classes, there would probably have to be heavy constraints on what 
FooMultiPrototypes may declare.


This would also allow you to reuse multi prototype sets.

Also, I don't think you answered Trey's concern, that your mechanism 
allows you to declare what classes may export but not what they *have* 
to export, which I would also view as more important - your mechanism 
seems to only serve to ban extensions and convenience methods, but 
doesn't give any extra promises on the class behaviour. To extend your 
example, if a library developer provides a three-argument max, it won't 
get in the way and won't break any existing contracts. But if the same 
developer doesn't also provide 2-argument max on that same class, it may 
very well break any code that works with that class.






Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread Miroslav Silovic

TSa wrote:


   role Set[::T = Item] does Collection[T] where {
   all(.members) =:= one(.members);
   };

Nice usage of junctions!



But buggy - one means *exactly* one. So for an array of more than 1 
element, all(@array) never equals one(@array) - if they're all the same, 
it's more than 1, otherwise it's 0.


all(.members) =:= any(.members) would also not work, as it will try to 
match each member with some other or same member of the array. It will 
always return true, in other words, as each element of the array is 
equal to itself.


This leaves all(.members) =:= .members[0], possibly extra with 
non-emptiness test.


   Miro




Re: [svn:perl6-synopsis] r11969 - doc/trunk/design/syn

2006-09-13 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


+=head1 Cross operators
+
+The final metaoperator is the CX metaoperator.  It applies the
+modified operator across all permutations of its list arguments.  All
+CX operators are of list infix precedence, and are list associative.
+
+The bare form of CX is considered an operator in its own right.
+Saying:
+
+a b X 1,2 X x y
+
+produces
+
+['a', 1, 'x'],
+['a', 1, 'y'],
+['a', 2, 'x'],
+['a', 2, 'y'],
+['b', 1, 'x'],
+['b', 1, 'y'],
+['b', 2, 'x'],
+['b', 2, 'y']



Would it be possible to extend Cnext to pass its arguments to the 
iterator being 'nexted'. Along with proper arguments to whichever lazy 
object it generated by X, it'd enable this:


(where :$slice argument would cause X to increment the member of the 
tuple at the appropriate index, and resets all the other ones):


for 1,2,3 X 1,2,3 - [$i, $j] {
   if $j  $i { next(slice = 0); }
   say $i, $j;
}

11
21
22
31
32
33

As another example, if a tree iterator has :right keyword argument to 
return the node to the right, you could do:


for $tree.each - $node {
   if $node.value  $goal { next; }
   if $node.value  $goal {next :right; }
   return $node;
}

Alternative proposal could be to allow expression after next, which gets 
evaluated instead of incrementing the iterator, iterator is topic in 
that expression and is replaced by the result.


So next True; causes infinite loop, next .left calls .left accessor and 
next .right calls right accessor before reentering loop (but doesn't do 
the default increment that for does).







Re: [svn:perl6-synopsis] r8573 - doc/trunk/design/syn

2006-04-06 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


We can't. The problem is that:

foo .bar

has to mean:

foo($_.bar)

So the only way to allow whitespace in dot operations is to put it 
after the dot.


Damian



I believe Larry's latest updates to Synopses allow for some syntactic 
categories to be disabled in certain context, and to allow priorities 
between categories. So would this make sense? --


   - C.bar can be successfully parsed as both method call (postfixish 
something?) and term
   - when postfix is disallowed, such as at the beginning of an 
expression or after a paren, C.bar is a term and means C$_.bar
   - otherwise, it's a method call, and to get Cfoo ($_.bar) you have 
to at least say Cfoo (.bar) -- requiring this actually seems more 
readable to me.


   Miro




Re: Class methods vs. Instance methods

2006-01-20 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


: class Dog {
: method tail { brown and short }
: };
:
: class Chihuahua is Dog {
: has $.color;
: method tail { $.color _  and short }
: };
:
: You can say Dog.tail, Dog.new.tail, Chihuahua.new.tail, but not
: Chihuahua.tail. That's extremely counter-intuitive.

I don't think it's counterintuitive.  You've defined Dog with an
invariant .tail but not Chihuahua.  It's doing exactly what you asked
for under a prototype view of reality.
   



Except there are no such things as classes in a prototype view of
reality. Everything is an instance and there are no such things as
class methods. The entire idea that an object (::Dog) can call methods
that are for another object ($fido) is ... well ... it's a little off.

That's like saying any object can call any method from any other
object so long as that method is invariant.
 



In a prototype-instance system,

instance(Dog) isa class(Dog)
instance(Chihuahua) isa class(Chihuahua) isa class(Dog)
instance(Chihuahua) isa instance(Dog)

Note that instances inherit doubly, from own class and from parent's 
instance.


But this does not imply that:

class(Chihuahua) isa instance(Dog)

So I don't see a problem.

   Miro




Re: choice of signatures

2006-01-04 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


Jonathan Lang wrote:


Instead of

multi sub *infix:~(ArabicStr $s1, ArabicStr $s2) {...}
multi sub *infix:~(Str $s1, ArabicStr $s2) {...}
multi sub *infix:~(ArabicStr $s1, Str $s2) {...}



as S13 say

 multi sub infix:+ (Us $us, Them $them) is commutative { 
myadd($us,$them) }


I believe this declares that $a + $b == $b + $a, not just that you can 
swap the types of the arguments. I.e. it implements


multi sub infix:+ (Them $them, Us $us) { $us + $them }

for you. And string concatenation isn't commutative.

   Miro




Re: given too little

2005-11-10 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


If so then my and Eric's wishes are answered:

when { $_  5 } { ... }
when { .caloric_value  $doctors_orders } { ... }

This isn't implemented in pugs yet, but I guess it can be once this is 
clarified.
 


Actually

   when $_  5 { ... }
   when .caloric_value  $doctors_orders { ... }

should also work because ~~ match table states that Anything ~~ boolean 
returns the boolean on the right.


   Miro



Re: Re(vised): Proposal to make class method non-inheritable

2005-10-18 Thread Miroslav Silovic

Disclaimer: I don't ~~ @larry :)

[EMAIL PROTECTED] wrote:


class Bar {
our $.bar;
{
my $.foo;
}
}

I assume that the leading $. is what makes the difference, however,  
IIRC the $. is just part of the name, and no more special than  
that. Which means that I can choose that name (yes, it is evil, but I  
assume I can still do it).


U... I'm not sure that allowing $. injection from the nested blocks 
is a good thing. I don't think it's ambiguous, but to me it looks weird 
and confusing - if a user put the variable in the nested block like 
that, it's almost certain he actually meant to write


{
   my $foo;
}

and the . was put there erroneously.



But given that the variable will be accessible to all methods via the  
closure mechanism, the only thing missing I think is the ability to  
get at the variable via introspection.


Now, as for class methods, I suppose it is possible to just stash  
then in the classes symbol table like with variables. However, do we  
then loose the method call syntax? 


Well, if it belongs to the module part of the class, the syntax would be 
Bar::method(...), right?


This also means that they would  not (directly) be inheritable since 
inheritence moves along  superclass lines, and not with @ISA.


Well, namespaces should generally be inheritable. How else would lexical 
namespaces inject variables from outer block into the inner? I guess at 
the package level declaration that Class1 is Class2 would just inject 
symbols from one module into the other? (yes, this is kinda handwavy :/ )


I am also not sure what you mean  about multi-methods either, could 
you please explain more?


Uhm. I'm not sure either. :) The way I read Larry's mail, multimethods 
use .isa operator to detect whether $foo belongs to Foo. And for every 
class, Foo.isa(Foo) is true (this is exceptional behaviour of .isa). So


multi bla (Foo $f);

would accept both bla(Foo.new()) and bla(::Foo). (Larry, please correct 
me on this if I'm misparaphrasing you :) )


Anyway, this makes me cringe on a certain level, although I'm not sure I 
can put the reason into words. Strictly speaking, it's bad only if there 
are cases where multimethod should behave differently for a class and an 
instance. One case I can think of is


class AutoCreation { ... };

multi dwimmy_instance(class AutoCreation $obj) { $obj.new() }
multi dwimmy_instance(AutoCreation $obj) { $obj }

(I pulled the syntax out of my nose for this). Anyhow, this looks like a 
pretty contrieved usage. I'm still trying to think of a non-contrieved, 
more realistic situation when you might actually want something like this.


   Miro




Re: Re(vised): Proposal to make class method non-inheritable

2005-10-18 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:

U... I'm not sure that allowing $. injection from the nested  
blocks is a good thing. I don't think it's ambiguous, but to me it  
looks weird and confusing - if a user put the variable in the  nested 
block like that, it's almost certain he actually meant to write


{
   my $foo;
}

and the . was put there erroneously.




Gack, furthermore, I was thinking 'has' and reading/writing 'my'. Sorry. :(



But given that the variable will be accessible to all methods via  
the  closure mechanism, the only thing missing I think is the  
ability to  get at the variable via introspection.


Now, as for class methods, I suppose it is possible to just stash   
then in the classes symbol table like with variables. However, do  
we  then loose the method call syntax?




Well, if it belongs to the module part of the class, the syntax  
would be Bar::method(...), right?



Yes, but the . is the method invocation operator, the :: is package  
symbol table access. I think they really mean different things.



Yes.

Now to be literal-minded, if Foo is a class...

Foo::method() would mean package(Foo)::method() (do package access, call 
method. No invocant, but you can access the proper child of Foo as $*MODULE)
Foo.method() would mean Class::method(Foo:) (forward to metaclass, with 
class as an invocant)


Nicely symetric, and (IMHO) completely unintuitive. So what exactly 
means to say that a class is a module?




This also means that they would  not (directly) be inheritable  
since inheritence moves along  superclass lines, and not with @ISA.



Well, namespaces should generally be inheritable.



I don't think this is true, this is a Perl 5-ism.

How else would lexical namespaces inject variables from outer block  
into the inner?



I think you are confusing namespacing with scoping. The scope rules  
are as such that the inner can access see the outer.



Fair enough. I was talking about implementation - this means you need 
symbol table import and shadowing (with the symbols defined in the inner 
scope). Same (or similar) policy could be used for class methods and 
attributes.





I guess at the package level declaration that Class1 is Class2  would 
just inject symbols from one module into the other? (yes,  this is 
kinda handwavy :/ )



I don't think this would be so, unless you explicitly asked for it.



I'm not sure I understand, why not?

Anyway, this makes me cringe on a certain level, although I'm not  
sure I can put the reason into words. Strictly speaking, it's bad  
only if there are cases where multimethod should behave differently  
for a class and an instance. One case I can think of is


class AutoCreation { ... };

multi dwimmy_instance(class AutoCreation $obj) { $obj.new() }
multi dwimmy_instance(AutoCreation $obj) { $obj }



I think we need some ability to differentiate between the class  
version of Foo and the instance version of Foo.


I think we agree here. :)

   Miro



Re: Re(vised): Proposal to make class method non-inheritable

2005-10-17 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:



I think what bothers me most about this is that it seems there is no  
way to tell the difference between class methods and instance  
methods. That the distinction is only made when the body of the  
method does something which is is not supposed to do (method called  
with a class invocant attempts to access an instance variable, etc).


This is one of the major problems that I have always had with Perl 5  
OO. That there is a very fuzzy fuzzy line between the  
responsibilities of a class and an instance.


I can see the notion of a class which is not yet instantiated, this  
makes sense in many contexts. But I don't think that in order to have  
this, we need to bring back this element of Perl 5 OO. I think we can  
still have all the behaviors you have been describing, and still keep  
classes and their instances as distinct entities.


It just recently occured to me that Class is a Package. So, on the 
object model level, class methods/attributes belong to the Package part 
of a class, while instance methods/attributes belong to the Class part 
of a class - insofar as they're made distinct by use of my/our.


Larry's proposal is to remove that difference for multimethods. 
Personally I can't think of a good objection to that idea (except if it 
may be bad for performance - is there a plan to infer types and 
auto-inline? I that case, declaring that you don't care about instance 
part of the object's functionality can really help).


   Miro




Re: Sane (less insane) pair semantics

2005-10-10 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


Stuart Cook skribis 2005-10-10 22:58 (+1100):
 


 @args = (a = 1, get_overrides());
 foo([EMAIL PROTECTED]);
 


Not if you want that a=1 to be a named argument.
Under the proposal, the only ways to pass a named argument are:
1) By using a literal pair in the syntactic top-level of the arg list
2) By splatting a pair, hash, or arg-list-object
   



I find this counterintuitive, and also want arrays to be included in
option 2.
 


How would you splat an array of pairs if you want to preserve the pairs?


It is consistent with the idea that * expands its RHS and evaluate it as
if it was written literally.

I'd like @_ or @?ARGS or something like that to be a *-able array that
will be guaranteed to be compatible with the current sub's signature.

 

This sounds nice, though. Maybe it suggests that the 'named splat' 
should be something other than *?


   Miro




Re: Exceptuations

2005-10-07 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


I'm not bashing your idea, because I think it has uses.  But I'll
point out that all of these can be easily accompilshed by writing a
wrapper for open().  That would be the usual way to abstract this kind
of thing.

 



My take on this: resumable exceptions break encapsulation no more (and 
no less) than using callbacks. The function that throws a resumable 
exception can only do this knowingly, and it could just as well offer a 
callback for that specific patchable error. So why take away a 
potentially highly useful tool?


BTW, two languages I know of have resumable exceptions: Common LISP and 
TOM. Neither supports continuations, instead, they separate raising 
exception (which runs a handler; this is implemented as a callback) from 
unwinding stack (which happens when the handler actually throws; it can 
choose to return instead, resuming execution if the raising function is 
okay with it). At least in Common LISP this is used a *lot* during 
interactive development, as it allows the developer to quickly patch 
things up without reruning the failed test. Assuming perl6 keeps the 
pugs-style interactive shell, I suspect resumable exceptions will be 
quickly added into the standard library if they don't pass into the 
standard. Yes, they're that useful.


   Miro




Re: $value but lexically ...

2005-10-07 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


Would this work too?

   0 but role {}
   



Most certainly, but you would have no way to refer to that role later,
so it is questionable how useful that construct is.  No, it's not
questionable.  That is a useless construct.

Luke

 


Can an inline role be named?

0 but role is_default {}


   Miro


A listop, a block and a dot

2005-10-05 Thread Miroslav Silovic
Playing with pugs, I ran into this corner case:

sub f($x) { say $x; }
f {1}.(); # ok, outputs 1

sub f([EMAIL PROTECTED]) { say @_; }
f {1}.(); # outputs block, tries to call a method from the return of say,
dies

Whitespace after f doesn't change the behaviour (in either case). Is this
behaviour a bug in pugs? Should . bind stronger than non-parenthesised
function call regardless of slurpy?

Miro


Re: Look-ahead arguments in for loops

2005-10-03 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


And that was never quite resolved.  The biggest itch was with
operators that have no identity, and operators whose codomain is not
the same as the domain (like , which takes numbers but returns
bools).

Anyway, that syntax was

   $sum = [+] @items;

And the more general form was:

   $sum = reduce { $^a + $^b } @items;

Yes, it is called reduce, because foldl is a miserable name.

 



To pick some nits, reduce and fold are different concepts. By 
definition, reduce doesn't take the initial value, while fold does.


So reduce using fold is something like

   @items || die horribly;
   foldl fn, @items[0], @items[1..]

... while fold using reduce is:

   reduce fn, ($initial, @items)

I think both are useful, depending on the circumstances.


   Miro






Re: Do slurpy parameters auto-flatten arrays?

2005-08-03 Thread Miroslav Silovic

[EMAIL PROTECTED] wrote:


So how *do* I pass an unflattened array to a function with a slurpy parameter?
 


I don't ~~ @larry, but my guess(es) would be bar([EMAIL PROTECTED]) or 
bar([EMAIL PROTECTED])

   Miro



Re: Syntax for specifying role parameters

2005-05-19 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
I don't think that a role has a long and a short name. This is
because they aren't subject to MMD. I think of them more as
beeing expanded like C++ templates even though the actual mechanism
will be much more sophisticated. Actually I think of them as F-bounds
as well ;)
Uhm, but C++ templates are subject to (compile-time) MMD, once you 
specialise them. In other words,

role Something[Int $num] {...}
role Something[String $num] {...}
could just as well work. :)
   Miro


A regression test

2005-05-11 Thread Miroslav Silovic
This is an addition to t/operators/hyper.t. It regression-checks for
the bug discussed on #perl6 (in a nutshell, hyper ops used to only
work on list literals, but not on array variables).



{ # regression test, ensure that hyper works on arrays
my @r1;
my @r2;
my @e1 = (2, 4, 6);
my @e2 = (2, 3, 4);
my @a = (1, 2, 3);
@r1 = @a + @a;
@r2 = @a + 1;
is([EMAIL PROTECTED], [EMAIL PROTECTED], hyper op works on variables, 
too.);
is([EMAIL PROTECTED], [EMAIL PROTECTED], hyper op and correctly 
promotes scalars);
};


Re: Parameter and trait questions - just how 'only' _is_ 'read-only'?

2005-03-31 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
Er, isn't that not just the wrong way around? The point is to do the
bookkeeping that an object is needed that does .meth() and that it
is stored in $a, and to complain when that is not the case when it
should be. The earlier the better.
I don't understand why writing 'my X $a' needs at least a declaration
of X, but then '$a.meth()' does not consider '.meth' as a bare method
that needs a declaration in X?
Because you can do
sub infect(X $a is rw)
{
   role bla {
  method meth() {...}
   }
   $a does bla;
}
my X $a;
infect($a);
a.meth();
Remember, you can even change the class of instanced objects using 
'does' (or 'but', but it'll at least copy the object). And as the 
example above shows, this is statically intractable - it can happen in a 
sub in a different autoloaded module.

Also, what do you want to do if you actually want $a.meth() to throw a 
catchable exception if $a doesn't implement meth? It's what many OO 
languages do. In fact, I can't recall a single OO language that isn't 
derived from C++ that does /not/ just throw a runtime exception on 
unknown method.

   Miro



Re: Perl 6 Summary for 2005-03-07 through 2005-03-22

2005-03-23 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
  pugs too lazy
   Miroslav Silovic noticed that closing a file handle in pugs did not
   force all the thunks associated with the file. While this was a bug in
   pugs, it led to conversation about whether = should be lazy or eager.
   Larry thinks that it will be safer to start eager and become lazy then
   vice versa.
   http://xrl.us/fijd
 

Accused of the original burst of insight, pleading not guilty! ;) The 
original post was to perl6-compiler by Andrew Savige.

http://groups-beta.google.com/group/perl.perl6.compiler/browse_frm/thread/2aca524a1203cd41/912bea4d0d05554a?q=surprised#912bea4d0d05554a
   Miro


Re: [Pugs] Closing a file handle surprised the heck out of me

2005-03-15 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
On the other hand, we can alternatively specify that closing a
file handle must force all thunks associated to it, i.e. in this
case fill @lines with real data.  Pugs can do that just fine, but I
have no idea how parrot is to achieve that...
 

But it gets worse.
my $lines = [ =$fh ];
seek($fh, 0);
my $lines2 = [ =$fh ];
close $fh;
$lines2 must somehow remember that seek has happened.
Miro



Re: for @list sub;

2005-03-14 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
   for [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED] - $x { say $x };
should work. Are there any non-slashy versions of this?
I'd guess
for @a; @b; @c - $x { say $x;}
or
for (@a; @b; @c) - $x { say $x;}
(are parens mandatory here?)
   Miro


Re: MMD as an object.

2005-03-11 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
Ok. If you'd really need such random dispatch, it could be done like
this, when I interpret A12 correctly:
 sub run_random_bar($x) {
my @meths = WALKMETH($x, :method('bar'));
my $meth = @meths[rand(@meths.elems)];
$meth($x);
 }
or even with
 my sub bar($x) {...} # same body as above
 bar($x);
 

This is enough to make me completely happy. :)
   Miro


Re: MMD as an object.

2005-03-10 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
It would behave like a tied sub (or method), with a .dispatch method 
to decide which of the contained routines should be called this 
particular time. Manhattan would be the default. However, one can 
override the dispatch logic; implementing Luke's Patterns idea, for 
example.

Hmm, that ties into my wishlist item. Would it be possible to implement 
method combinators (or rather, multimethod combinators) from Common LISP 
in addition to this? The only CLOS feature that A12 doesn't mention, 
can't let that happen. ;)

class A { ... }
class B is A { ... }
1 multi foo ($a) is before { ... }
2 multi foo (B $a) { ... next METHOD; ...}
3 multi foo (A $a) { ... }
4 multi foo ($a) is after { ... }
5 multi foo ($a) is around { ... next METHOD; }
6 multi foo ($a) is before { ... }
 and this runs all 5 methods, in order 5  1  2  6  3  (returns 
to 2)  4  (returns to 5)
And yes, 6 and 1 do have the same signature. The rule is to run all 
before methods in order of the currently selected distance (ties broken 
in random order ;) ), and all after methods in the reverse order.

Oh, and the reason why around methods are useful?
multi foo ($a) is around {
   CATCH { ... }
   next METHOD;
}
Note that this catches the exceptions thrown by any version of foo, even 
though at this point you don't know whether foo will be specialised. 
before methods aren't useful for this since their stack frame and 
handler blocks don't linger during the executions of other methods.

Common LISP references:
Standard method combination (before, after, around)
http://www.lispworks.com/documentation/HyperSpec/Body/07_ffb.htm
Other method combinations (+, and, etc)
http://www.lispworks.com/documentation/HyperSpec/Body/07_ffd.htm
Creating your own method combinations (define-method-combination)
http://www.lispworks.com/documentation/HyperSpec/Body/m_defi_4.htm
Come to think of this, it seems that the only thing that'd need to be 
modified to accomodate both Rod's and mine proposal is to move CALLONE 
and CALLALL from the class to be MMD object somehow. Perhaps

multi CALLONE ($obj, $method where { $_ == func }, [EMAIL PROTECTED]) { ... }
Hmm, but this syntax strikes me as icky.
   Miro


Re: MMD as an object.

2005-03-10 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
What about multi subs? They can be defined everywhere. Given:
 multi sub *foo(A $a, B $b) {...}
Is this something like:
 %globals{foo}  --  MultiSub{foo_A_B = Sub, ...}
What about a not so global multi:
 multi sub foo(A $a, B $b) {...}
Thanks for clarifying,
leo
 

Uh, the real problem is the interaction between multisubs and modules. 
If you import a multi with the same short name from another module, you 
get a real issue that needs resolving. Especially if they do 
fundamentally different things and you don't expect a clash. Like

module Users;
multi get(Stream $f, UserDescriptor $u) {...}
...
module FileTransfer;
multi get(Server $s, File $f) {...}
Even if this is easy to fix by renaming, the error message would take a 
while to track down and it'd be annoying distraction during development. 
I believe the DWIM thing to do would be to merge multis into the same 
MMD object on module load. This would have to happen during runtime, 
since that's when the module load can occur.

   Miro


Re: [rbw3@cse.nau.edu: Re: Junctive puzzles.]

2005-02-10 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
Yes... but perhaps instead of the above transform we should just make
sure that  is transitive in the first place... so that no matter what
if ab and bc then ac. OTOH... perhaps we are working with partially
ordered sets (rather than completely ordered sets)? In that case maybe
the above suggestion is useful after all.
 

Partial ordering relations are also transitive by definition.
Of course, you can overload '' to be something other than ordering 
relation, but I'd invoke PEBKAC on that. :)

   Miro


Re: Junctive puzzles.

2005-02-10 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
What if junctions collapsed into junctions of the valid options under
some circumstances, so
my $x = any(1,2,3,4,5,6,7);
if(is_prime($x) # $x = any(2,3,5,7)
and is_even($x) # $x = any(2)
and $x  2) # $x = any()

This is Just Wrong, IMO. How confusing is it going to be to find that 
calling is_prime($x) modifies the value of $x despite it being a very 
simple test operation which appears to have no side effects?

As far as I can see it, in the example, it's perfectly logical for 
is_prime($x), is_even($x) and $x  2 to all be true, because an any() 
junction was used. If an all() junction was used it would be quite a 
different matter of course, but I would see is_prime() called on an 
any() junction as returning true the moment it finds a value inside 
that junction which is prime. It doesn't need to change $x at all.

In a way, you're sort of asking 'has $x got something that has the 
characteristics of a prime number?' and of course, $x has - several of 
them, in fact (but the count is not important).

Well, yes, unexpected side-effects are not so great, however, in this 
case they're sequestered behind junctions. In fact, the other post 
suggested using implicit backtracking for this (something that can have 
a real problem with *expected* side-effects). If you just think of 
junctions as 'Just Works', side effects are implementation detail.

To address your idea, problem is, you generally don't know whether 
you've been passed a junction (short of very specific type query), and 
writing code without being  able to rely on the fact that (is_prime($x) 
 !!is_prime($x)) == false is Just Plain Evil. For example, something 
as simple as

if (is_prime($x)) { ... }
else { ... }
may be buggy if $x is a junction. To make it work correctly, you will 
want to write

if (is_prime($x)) { ... }
if (!is_prime($x)) { ... }
Evil, no? :)
   Miro


Re: Perl 6 Summary for 2005-01-31 through 2004-02-8

2005-02-10 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
i think so but i can't read larry's mind (nor would i want to! :)
XP = extreme programming
DBC = design by contract (or even designed by conway :)
MP = ??

Modular Programming
David
I think it's Metaprogramming. :)
   Miro


Re: Junctive puzzles.

2005-02-08 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
Yup.  My mathematic intuition cannot suffer that:
   4  X  2
to be true in any circumstances -- as it violates associativity.
If one wants to violate associativity, one should presumably *not*
use the chained comparison notation!
So Pugs will evaluate that to (#f|#f), by lifting all junctions
out of a multiway comparison, and treat the comparison itself as
a single variadic operator that is evaluated as a chain individually.
 

I think this is correct, however... this is not what I meat in my 
comment. Note I didn't use chained comparison anywhere.

What I meant is that for any form with two parameters (in the example, 4 
 ___ and ___  2), aparently it's not the same whether the two 
parameters refer to the same junction or to two equal (but distinct) 
junctions.

   Miro


Re: Junctive puzzles.

2005-02-08 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
Well, we see the same kind of thing with standard interval arithmetic:
   (-1, 1) * (-1, 1) = (-1, 1)
   (-1, 1) ** 2 = [0, 1)
The reason that junctions behave this way is because they don't
collapse.  You'll note the same semantics don't arise in
Quantum::Entanglement (when you set the try to be true option).
But you can force a collapse like this:
   my $x = 4  $j;
   if $j  2 { say never executed }
   

By which I mean:
   my $x = 4  $j;
   if $x  2 { say never executed }
 

Uh, I'm not sure this does what I think you wanted to say it does. ;) $x 
is a boolean, unless  returns a magical object... in which case, the 
magical part of $x ought to be a reference to the original $j, no?

I'm wonding if we should allow a method that returns a junction that is
allowed to collapse the original:
   if 4  $j.collapse and $j.collapse  2 {
   say never executed;
   }
But that's probably not a good idea, just by looking at the
implementation complexity of Quantum::Entanglement.  People will just
have to learn that junctions don't obey ordering laws.
   

Well, I suspect that junctions will have to be references and just 
collapse every time. Observe:

my $x = any(1, 2, 3, 4, 5);
print SHOULD NOT RUN if (is_prime($x)  is_even($x)  $x  2);
This only works if $x collapses. Same for matching junctioned strings:
my $a = any (a b c);
print Boo! if $a ~ /a/ and $a ~ /b/ and $a ~ /c/;
(perhaps I meant to use ~~, I don't quite remember :) )
Either way, autocollapsing juntions is a Good Thing IMHO, and the only 
remaining confusion (to go back to my initial post) is that the only 
case that doesn't work is when you instance a junction twice as a pair 
of same literals:

print SUCCESS, unfortunately if (is_prime(any(1, 2, 3, 4, 5))  
is_even(any(1, 2, 3, 4, 5))  any(1, 2, 3, 4, 5)  2);

Hope I'm making sense. Been a hard day at work. ;)
   Miro


Re: Junctive puzzles.

2005-02-07 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
   pugs ? 4  (0 | 6)  2
   (#t|#f)
 

Here's my take on it.
Compare
my $a = (0 | 6);
say 4  $a and $a  2;
vs
say 4  (0 | 6) and (0 | 6)  2;
The difference is that in the first case the junction refers to the same 
object, and the result should probably be expanded only once:

(4  0 and 0  2) | (4  6 and 6  2)
while in the second case, we have two different junctions, and each gets 
threaded separately:

(4  0 and 0  2) | (4  6 and 6  2) | (4  0 and 6  2) | (4  6 and 0 
 2)

The first expansion gives the correct result, while the other is really 
a variant on what you have. And I believe this becomes highly dangerous 
if you start assigning junctions around. :)

   Miro


Re: Retry: ITypes and VTypes.

2005-02-04 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
However, I wonder how to talk about an array that can contain elements
of any value type, but all the elements must have the same type.
Is Perl6 capable of expressing such a restraint?
Thanks,
/Autrijus/
 

The problem (in general) with this requirement is that it conflicts with 
inhericance. Perl6 allows you to extend any type (using 'but' operator, 
for example) and so, any time you promise that something will be of a 
certain type, the type's children will be allowed. That's at least the 
way I read A12. I also think that juntions will have their elements' 
type's interface and so they can also pose for any type. In other words, 
you need a real polymorphic object system in Haskell for this to work.

Fortunately there's one handily described at 
http://homepages.cwi.nl/~ralf/OOHaskell/

While we're on the topic, which of the following are true?
3 but three ~ int   (false?)
3 but three ~ Integer (true?)
3  5 ~ int (true?)
3  5 ~ Integer (true?)
(Skipping off topic, to Parrot. Sorry. :) ) If 3  5 is actually int, 
and this is only determinable at runtime, to me this seems like a 
problem with I# register allocation - ints can't be reliably assigned to 
I# registers. Unless, of course, you autothread at the point when a 
junction has to be cast into an int. Do I understand junction semantics 
correctly?
   Miro




Re: continuation enhanced arcs

2004-12-09 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
What this means is that care must be taken when you are writing code
that you expects to be invoked multiple times.  However, if you are a
function that on your second invocation returns via the continuation
from you first invocation, you should probably expect to be called
again because it happened the first time!
The contentious point is precisely that there is no way to tell at the 
compile time that you will be invoked multiple times. If something you 
pull from a library or a callback passed to you captures the 
continuation, you may notice that your return continuation had been 
promoted, but at that point it's already too late to kill all I/N/S 
register usage and to double-reference all PMCs. Of course, unless you 
keep the original AST and keep recompiling it to PIR. I'd argue that 
it's vastly more complex and error prone than Leo's solution he refered 
to in his post. It's also no better than refetching all lexicals.

Also, note that return-continuation-restores semantics is simply a 
(possibly premature) optimisation in its own right. CPS is supposed to 
treat every continuation the same (which turned out to be inefficient), 
and then return continuations were added to simplify the most common 
case. So, while return continuation is unpromoted, it's perfectly okay 
for it to behave any way it wants. Once it does get promoted, I'd argue 
that it should behave like a normal continuation first because it's more 
practical (see above) and second because that way it doesn't break CPS 
semantics.

   Miro



Re: Exceptions, sub cleanup, and scope exit

2004-11-19 Thread Miroslav Silovic
Dan Sugalski wrote:
It's also important for people writing these things to take into 
account the possibility that their exit actions may potentially be 
triggered multiple times, courtesy of the joys of continuations.

Hmm, the first thing to take into the account is that return 
continuations can be promoted to the fully blown continuations. This 
should affect the handlers in the same way - so exception handlers could 
have become arbitrary invokable objects at the point when the exception 
is thrown.

   Miro


Re: Exceptions, sub cleanup, and scope exit

2004-11-19 Thread Miroslav Silovic
Dan Sugalski wrote:
Hmm, the first thing to take into the account is that return 
continuations can be promoted to the fully blown continuations. This 
should affect the handlers in the same way - so exception handlers 
could have become arbitrary invokable objects at the point when the 
exception is thrown.

I'd rather not, if we can avoid it. Assumptions on control flow and 
such are likely to be very different, and I can't think of a good 
reason to treat an error handler as a normal sub. (If you have one 
then we can think on it some)
While that's not what I commented on, sure. Common LISP and TOM both 
invoke error handler -before- unwinding the stack (then the handler 
explicitely unwinds if it can't recover). I still don't think it's 
something Parrot should care about, as their (hypothetical) compilers 
can install their own error handling, and other languages don't expect 
their own throw to ever return - so I wouldn't call this a good reason. :)

   Miro


Re: calling conventions, tracebacks, and register allocator

2004-11-09 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
On Nov 8, 2004, at 11:15 AM, Matt Fowles wrote:
Dan~
On Mon, 8 Nov 2004 13:45:08 -0500, Dan Sugalski [EMAIL PROTECTED] wrote:
The calling conventions and code surrounding them will *not* change
now. When all the sub stuff, and the things that depend on it, are
fully specified and implemented... *then* we can consider changes.
Until then, things stand the way they are.

I missunderstood.  I though you were saying that what is currently in
is final and will *never* be changed.  Thanks for the clarification.

Nevertheless, this is a legitimate topic for discussion, and the 
issues are fresh in people's minds. That's independent of any 
impediments that might block implementing changes at the current time.

I think it'd be a good idea to at least agree on a good TODO list, and 
commit that to the bugtracker. Because it may turn out that some changes 
are fine to delay, while some must be implemented now or never (because, 
for example, a large ammount of compiler code will get broken because of 
them).

   Miro


Re: Why is the fib benchmark still slow - part 1

2004-11-05 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
a) accessing a new register frame and context
b) during DOD/GC
We have to address both areas to get rid of the majority of cache
misses.
ad a)
For each level of recursion, we are allocating a new context structure
and a new register frame. Half of these is coming from the recently
implemented return continuation and register frame chaches. The other
half has to be freshly allocated. We get exactly for every second
function call L2 cache misses for both the context and the register
structure.
 

Or it would make sense to use multi-frame register chunks. I kept 
locality of access in mind but somehow never spelled it out. But I 
*think* I mentioned 64kb as a good chunk size precisely because it fits 
well into the CPU cache - without ever specifying this as the reason.

Anyway, if you can pop both register frames -and- context structures, 
you won't run GC too often, and everything will nicely fit into the 
cache.  Is the context structure a PMC now (and does it have to be, if 
the code doesn't specifically request access to it?)

ad b)
The (currently broken) Parrot setting ARENA_DOD_FLAGS shows one
possibility to reduce cache misses in DOD. During a sweep (which runs
through all allocated object memory) the memory itself isn't touched,
just a nibble per object is used, which holds the relevant information
like is_live.
 

Is there a way to find out how many misses came out from DoD, compared 
to register frames allocation?

I believe that you shouldn't litter (i.e. create an immediately GCable 
object) on each function call - at least not without generational 
collector specifically optimised to work with this. This would entail 
the first generation that fits into the CPU cache and copying out live 
objects from it. And this means copying GC for Parrot, something that 
(IMHO) would be highly nontrivial to retrofit.

   Miro


Re: Why is the fib benchmark still slow - part 1

2004-11-05 Thread Miroslav Silovic
Leopold Toetsch wrote:
I believe that you shouldn't litter (i.e. create an immediately 
GCable object) on each function call - at least not without 
generational collector specifically optimised to work with this.

The problem isn't the object creation per se, but the sweep through 
the *whole object memory* to detect dead objects. It's of course true, 
that we don't need the return continuation PMC for the fib benchmark.
Well, creation is also the problem if you crawl the entire free heap
before triggering the next GC round. You get a potential cache miss on
each creation and on each mark and on each destruction. To keep GC out
of the way, the entire arena has to be confined to cache size or less.
But a HLL translated fib would use Integer PMCs for calculations.
Hmm, I'm nitpicking here, but it's not how e.g. Psyco works. It
specialises each function to specific argument types and recompiles for
each new argument type set. Assuming that you'll call only very few
functions with more than 1-2 type combinations, this is a good tradeoff.
It also removes a lot of consing, especially for arithmetics.

...  This would entail the first generation that fits into the CPU 
cache and copying out live objects from it. And this means copying GC 
for Parrot, something that (IMHO) would be highly nontrivial to 
retrofit.

A copying GC isn't really hard to implement. And it has the additional 
benefit of providing better cache locality. Nontrivial to retrofit or 
not, we need a generational GC.
Copying and generational are orthogonal concepts. It's quite possible to
have noncopying gengc (and nongenerational copying GC, but that's beside
the point). This gives you quick mark phases but without so much gain
with locality (I think Boehm GC can do this).
The problem with copying GC is that pointers can change under your feet
at every opportunity. Embedded C libraries that try to manipulate GCed
objects really hate when that happens - in particular where some
pointers get cached in the CPU registers - and telling GC to (un)protect
a pointer is a chore on C programmers (as bad as manual refcounting). I
suppose that there are good solutions to this, I'm just not aware of any.
The gain is that you can guarantee that the youngest generation will be
no bigger than X kb. This can be very good thing.
However, for the problem at hand - namely, littering during function
calls, custom deallocator (that'd be chunks) could be enough. In
particular, it makes sense to use it in conjunction with a non-copying
gengc.
   Miro



Re: [Summary] Register stacks again

2004-10-19 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
Could we have the chunks only hold one frame and avoid much of the
compaction work?  If we return to the inderict access mechanism, we
can switch register frames by changing one pointer.  But if we keep
the one frame per chunk, we do not need to compact frames, standard
DOD/GC will be able to reclaim frames.  I recall there being
efficiency issues with frames being frequently allocated/deallocated
too frequently, so we could have a special free list for frames.
This proposal feels to me like a slightly simpler version of yours. 
Thus I would argue for it on the grounds of do the simple thing first
and compare its efficiency.
 

Well, for the code that doesn't do call/cc, bigger chunks mean that that 
you can use them as a classical stack. So you won't ever have to 
allocate them, and never have to run the compaction. For call/cc, you 
still don't have to compact them as often, since the non-captured 
continuations will get popped normally, and the watermark lowering will 
take care of temporarily captured continuations (between two GC's).

Basically bigger chunks mean that frames are allocated using the special 
scheme just for them. Considering that you're going to allocate one on 
each function call, I would agree with LT that the complexity is 
justified (and is not too bad - the way I understand the Parrot 
internals, which is to say, not too well ;), arrays of PMC pointers 
already get copy-collected; stack frame chunks are not too different 
from these).

  Miro



[Summary] Register stacks again

2004-10-18 Thread Miroslav Silovic
This is a summary of a private mail conversation between Leo and myself. 
lieNo, it didn't start by me forgetting to fix Reply-To when trying to 
post follow-up on the list./lie ;)

Essentially we whipped up a GC scheme for collecting the register stacks 
that doesn't make call/cc-using code, well, unusably slow.

In addition to LT's original post on the register stack, here's how to 
allocate them and clean up after their use. LT, feel free to hit me with 
wet noodles if I forgot anything.

Terminology:
---
Register frame is an actual frame of 4x16 registers.
Register chunk is a flat chunk of memory containing multiple register 
frames. It has a water mark that points where a new frame should be 
pushed into the chunk. I'm using stack and chunk interchangably.

Frames are subject to DoD, and chunks are subject to GC. There are 
plenty of tricks that can prevent GC from happening in many cases (read 
on for details). DoD is necessary anyway (to retrieve the live PMCs 
pointed from the register frames).

A chunk is pinned if GC currently can't copy it over and kill it (read 
on for details).

Allocation:
---
Register stacks should be allocated in fairly big chunks. However, since 
there must be at least one active chunk per thread (and per coroutine), 
choosing anything actually huge will pose a scaling problem.

Frames are allocated from the current stack, simply by advancing the 
water mark of the currently active chunk. If this causes the water mark 
to overflow, a new chunk needs to be allocated.

Note that if a continuation has been captured and then invoked, the 
water mark will not necessarily point at the end of the current frame 
(since the invoked continuation may keep its registers deeper in the chunk)

Deallocation:
---
The stack frame can only be popped if the current continuation hasn't 
been captured (from the frame being popped). Here, pop means changing 
both frame pointer and the watermark. This ammounts to adding a flag to 
the current frame and bumping the flag if the return continuation gets 
moved into any directly accessible location. If the frame can't be 
popped, only the frame pointer should be changed to the caller's.

GC:
---
During DoD, the register frames should be marked (as parts of their 
chunks). Then the dead frames get dealt with in the following manner:

Remove the trailing dead frames from each chunk (by just lowering the 
water mark).

If after this the water mark remains high (e.g. past 50% of the chunk) 
but more than certain ammount of the chunk is salvagable as dead frames 
(50% seems like a good number again), the chunk should be copied, all 
the frame pointers fixed up, then the chunk gets killed. Essentially the 
chunks are treated as buffers. The watermark lowering won't help in 
cases when continuations get invoked in a round-robin manner (wish I 
could think of some simple Scheme example here that behaves this way), 
and start littering the chunk with interlaced dead frames.

Two caveats:
The frame pointer of the currently active frames (can be more than 1 due 
to threads) may be kept in a CPU register and can't be fixed-up. So the 
chunk containing currently active frame is pinned until it either 
overflows into another chunk or gets freed by popping.

Chunks can contain reverse pointers to the continuations that use its 
frames. When copying the frame, just go through these reverse pointers 
and fix the continuations they point to.

Performance:
---
This scheme requires some GC flags to each frame (as well as reverse 
pointers). Possibly also next pointers to the frames, if they are not 
cut to equal size.

Without continuations, this behaves like C function calling. Nothing 
will read return continuation and so the frames will simply get popped 
from the stack on return.

When continuations begin to prevent popping, the stack will start 
growing from the last captured continuation (even if its dead). 
Watermark will drop in GC if the GC happens to hit while the active 
frame is way down the stack (i.e. just between two function calls). 
Otherwise, GC will wait till the chunk overflows (so that the active 
frame is in a higher chunk) and then will copy the live frames to a 
newly allocated chunk, compacting several chunks together if possible. 
Copying can be skipped if the chunk is near-full of the live frames.

I think this about sums it up. Comments, corrections, wet noodles?
   Miro



Re: S5 updated

2004-09-23 Thread Miroslav Silovic
[EMAIL PROTECTED] wrote:
I'll show you.  Here are some of the generators.  This is very dense,
functional code.  Read at your own risk (but I'm certainly not writing
it to be executed!).
Quite. ;)
For the regexp /a aa aaa  a aa/, this would sequentially 
search through all possible ways to decompose 21 until it hit 
1+2+3+4+5+6; then it'd return ax21 as the single result. This... might 
take a while.

Since programming in Theoretic Perl6 (Terl6?) /is/ fun, here's my take:
# compositions2($length, @listoflists) gives all possible ways to depompose
# $length into the sum of the form a1+a2+a3+...+an so that a[i] is contained
# in @listoflists[i]
multi generate(Rule::Group $group: Int $length) {
   # For each assignent of lengths to each of $groups children
   # such that they sum to $length...
   compositions2($length, map(possible_lengths, $group.children)) == 
   map - @comp {
   @comp  $group.children == 
   map - $n, $pat {
   
   # Generate every string of length $n that the subpattern
   # matches
   [ $pat.generate($n) ]
   } ==

   # Join our results together
   outer == join ''
   }
}
use IntegerIntervalArithmetics  add_lists, mult_lists ;
# add_lists(@list1, @list2) returns the list of sums of all possible
# elements of the lists. However, it should take .. and ... operators
# into account. This generally requires range tree datastructure of some
# sort.
# mult_lists(@list1, @list2) returns the list of all products
multi possible_lengths(Rule::Group $group) {
   [ reduce(add_lists, map(possible_lengths, $group.children)) ];
}
multi possible_lengths(Rule::Plus $plus) {
   [ mult_lists($plus.expression, 1... ];
}   

multi possible_lengths(Rule::Constant $const) {
   [ length($const.chars) ];
}

I'm still not claiming that this is something one should use, but it /was/ fun
to tinker with. :)
   Miro


Re: S5 updated

2004-09-21 Thread Miroslav Silovic
On Tue, 2004-09-21 at 02:52 -0600, Luke Palmer wrote:
 If you replace the first line:
 
 method Rule::Group::generate(Int $n) {
 
 With
 
 multi generate (Rule::Group $group: Int $n) {
 
 Everything ought still to work.
 
 I think the best you can do is to implement it as a routine.  You can't
 really make it a modifier, because it's pretty separate from actually
 matching anything.

Minor nitpick, you can do away with the integer parameter - to me it
makes more sense to just lazily spew an infinite list of generated
matches. Then you'd do

@results = generate(/a*/) [0..999];

to get 1000 results, but you can also do

@results = generate(/a*/);
while !$hell.frozen() {
shift @results;
}

Miro




Re: S5: grammar compositions

2004-09-16 Thread Miroslav Silovic
On Wed, 2004-09-15 at 12:47 -0700, [EMAIL PROTECTED] wrote:
 Grammar roles?
 
 Larry

Hmm, actually a few questions on the topic:

S5 doesn't specify whether grammars can have attributes. Can they? Can
they have methods, or at least local subs, to call from the code within
the rules?

Can grammars inherit from classes/roles (to pull methods into their
namespace, for code within the rules)?

Can classes inherit from grammars? (to pull their rules into their
namespace)

Miro