Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Bring Arcterus++ sized array work into a branch.
Can evaluate/tweak it from here.
  • Loading branch information
jnthn committed Jul 25, 2013
2 parents 787295d + ec7842b commit 6493e48
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 10 deletions.
5 changes: 5 additions & 0 deletions CREDITS
Expand Up @@ -27,6 +27,11 @@ N: Alex Elsayed
U: eternaleye
E: eternaleye@gmail.com

N: Alex Lyon
U: Arcterus
E: arcterus@mail.com
D: Shaped arrays

N: Allison Randal
D: Parrot Architect (0.4.6...)
E: allison@parrot.org
Expand Down
8 changes: 7 additions & 1 deletion src/Perl6/Actions.nqp
Expand Up @@ -184,7 +184,13 @@ class Perl6::Actions is HLL::Actions does STDActions {
%info<value_type> := $*W.find_symbol(['Mu']);
}
if $shape {
$*W.throw($/, 'X::Comp::NYI', feature => 'Shaped arrays');
%info<container_shape> := $shape[0].ast;
} else {
my $whatever := $*W.find_symbol(['Whatever']);
%info<container_shape> := QAST::Op.new(
:op('callmethod'), :node($/), :name('new'), :returns($whatever),
QAST::Var.new(:name('Whatever'), :scope('lexical'))
);
}
}
elsif $sigil eq '%' {
Expand Down
4 changes: 2 additions & 2 deletions src/Perl6/Grammar.nqp
Expand Up @@ -2140,9 +2140,9 @@ grammar Perl6::Grammar is HLL::Grammar does STD {
reserved => '() shape syntax in variable declarations');
}
}
| :dba('shape definition') '[' ~ ']' <semilist> <.NYI: "Shaped variable declarations">
| :dba('shape definition') '[' ~ ']' <semilist>
| :dba('shape definition') '{' ~ '}' <semilist>
| <?before '<'> <postcircumfix> <.NYI: "Shaped variable declarations">
| <?before '<'> <postcircumfix>
]+
]**0..1
<.ws>
Expand Down
9 changes: 9 additions & 0 deletions src/Perl6/Metamodel/BOOTSTRAP.nqp
Expand Up @@ -77,6 +77,7 @@ my stub Grammar metaclass Perl6::Metamodel::ClassHOW { ... };
my stub Junction metaclass Perl6::Metamodel::ClassHOW { ... };
my stub Metamodel metaclass Perl6::Metamodel::PackageHOW { ... };
my stub ForeignCode metaclass Perl6::Metamodel::ClassHOW { ... };
my stub Whatever metaclass Perl6::Metamodel::ClassHOW { ... };

# We stick all the declarative bits inside of a BEGIN, so they get
# serialized.
Expand Down Expand Up @@ -1577,10 +1578,12 @@ BEGIN {

# class Array is List {
# has $!descriptor;
# has $!shape;
# ...
# }
Array.HOW.add_parent(Array, List);
Array.HOW.add_attribute(Array, BOOTSTRAPATTR.new(:name<$!descriptor>, :type(Mu), :package(Array)));
Array.HOW.add_attribute(Array, scalar_attr('$!shape', Mu, Array));
Array.HOW.compose_repr(Array);

# class LoL is List {
Expand Down Expand Up @@ -1653,6 +1656,10 @@ BEGIN {
ForeignCode.HOW.set_invocation_attr(ForeignCode, ForeignCode, '$!do');
ForeignCode.HOW.compose_invocation(ForeignCode);

# class Whatever { }
Whatever.HOW.add_parent(Whatever, Any);
Whatever.HOW.compose_repr(Whatever);

# Set up Stash type, which is really just a hash.
Stash.HOW.add_parent(Stash, Hash);
Stash.HOW.compose_repr(Stash);
Expand Down Expand Up @@ -1689,6 +1696,7 @@ BEGIN {
Perl6::Metamodel::ClassHOW.add_stash(Hash);
Perl6::Metamodel::ClassHOW.add_stash(ObjAt);
Perl6::Metamodel::ClassHOW.add_stash(ForeignCode);
Perl6::Metamodel::ClassHOW.add_stash(Whatever);

# Default invocation behavior delegates off to postcircumfix:<( )>.
my $invoke_forwarder :=
Expand Down Expand Up @@ -1780,6 +1788,7 @@ BEGIN {
EXPORT::DEFAULT.WHO<Bool> := Bool;
EXPORT::DEFAULT.WHO<False> := $false;
EXPORT::DEFAULT.WHO<True> := $true;
EXPORT::DEFAULT.WHO<Whatever> := Whatever;
EXPORT::DEFAULT.WHO<ContainerDescriptor> := Perl6::Metamodel::ContainerDescriptor;
EXPORT::DEFAULT.WHO<MethodDispatcher> := Perl6::Metamodel::MethodDispatcher;
EXPORT::DEFAULT.WHO<MultiDispatcher> := Perl6::Metamodel::MultiDispatcher;
Expand Down
21 changes: 21 additions & 0 deletions src/Perl6/World.nqp
Expand Up @@ -615,6 +615,17 @@ class Perl6::World is HLL::World {
nqp::bindattr($cont, %cont_info<container_base>, '$!value',
%cont_info<default_value>);
}
if nqp::existskey(%cont_info, 'container_shape') {
$block[0].push(
QAST::Op.new(
:op('bindattr'),
QAST::Var.new(:scope('lexical'), :name($name)),
QAST::WVal.new(:value(%cont_info<container_base>)),
QAST::SVal.new(:value('$!shape')),
%cont_info<container_shape>
)
);
}
self.add_object($cont);
$block.symbol($name, :value($cont));
self.install_package_symbol($package, $name, $cont) if $scope eq 'our';
Expand Down Expand Up @@ -691,6 +702,16 @@ class Perl6::World is HLL::World {
QAST::SVal.new( :value('$!value') ),
QAST::WVal.new( :value(%cont_info<default_value>) )));
}

if nqp::existskey(%cont_info, 'container_shape') {
$cont_code.push(QAST::Op.new(
:op('bindattr'),
QAST::Var.new(:name($tmp), :scope('local')),
QAST::WVal.new(:value(%cont_info<container_base>)),
QAST::SVal.new(:value('$!shape')),
%cont_info<container_shape>
));
}

$cont_code
}
Expand Down
48 changes: 44 additions & 4 deletions src/core/Array.pm
Expand Up @@ -3,10 +3,13 @@ my class X::Item { ... };
class Array {
# Has attributes and parent List declared in BOOTSTRAP.

method new(|) {
method new(:$shape = *, |) {
my Mu $args := nqp::p6argvmarray();
nqp::shift($args);
nqp::p6list($args, self.WHAT, Bool::True);
fail "Too many elements for this shaped array" unless nqp::istype($shape, Whatever) or nqp::elems($args) < $shape;
my $array := nqp::p6list($args, self.WHAT, Bool::True);
nqp::bindattr($array, Array, '$!shape', $shape);
$array;
}

multi method at_pos(Array:D: $pos) is rw {
Expand All @@ -19,6 +22,7 @@ class Array {
X::Item.new(aggregate => self, index => $pos).throw;
}
my int $p = nqp::unbox_i($pos.Int);
fail "Index $p is too large for this shaped array" unless nqp::istype($!shape, Whatever) or $p < $!shape;
my Mu $items := nqp::p6listitems(self);
# hotpath check for element existence (RT #111848)
nqp::existspos($items, $p)
Expand All @@ -29,6 +33,7 @@ class Array {
-> { nqp::bindpos($items, $p, $v) } )
}
multi method at_pos(Array:D: int $pos) is rw {
fail "Index $pos is too large for this shaped array" unless nqp::istype($!shape, Whatever) or $pos < $!shape;
my Mu $items := nqp::p6listitems(self);
# hotpath check for element existence (RT #111848)
nqp::existspos($items, $pos)
Expand All @@ -42,10 +47,12 @@ class Array {
proto method bind_pos(|) { * }
multi method bind_pos($pos is copy, Mu \bindval) is rw {
$pos = $pos.Int;
fail "Index $pos is too large for this shaped array" unless nqp::istype($!shape, Whatever) or $pos < $!shape;
self.gimme($pos + 1);
nqp::bindpos(nqp::getattr(self, List, '$!items'), nqp::unbox_i($pos), bindval);
}
multi method bind_pos(int $pos, Mu \bindval) is rw {
fail "Index $pos is too large for this shaped array" unless nqp::istype($!shape, Whatever) or $pos < $!shape;
self.gimme($pos + 1);
nqp::bindpos(nqp::getattr(self, List, '$!items'), $pos, bindval)
}
Expand All @@ -62,16 +69,42 @@ class Array {

# next seems unnecessary but handles an obscure
# edge case
if $i == (@array - 1) {
#
# FIXME: does the shape addition work?
if $i == (@array - 1) and nqp::istype(@array.shape, Whatever) {
@array.pop;
}
}
@array.pop while ?@array && !defined @array[@array.elems - 1];
if nqp::istype(@array.shape, Whatever) {
@array.pop while ?@array && !defined @array[@array.elems - 1];
}
return @result;
}

method flattens() { 1 }

method shape() { $!shape }

method pop() is parcel {
fail 'Cannot pop from a shaped array' unless nqp::istype($!shape, Whatever);
nqp::findmethod(List, 'pop')(self)
}

multi method push(Array:D: *@values) {
fail 'Cannot push to a shaped array' unless nqp::istype($!shape, Whatever);
nqp::findmethod(List, 'push')(self, |@values)
}

method shift() is parcel {
fail 'Cannot shift from a shaped array' unless nqp::istype($!shape, Whatever);
nqp::findmethod(List, 'shift')(self)
}

multi method unshift(Array:D: *@values) {
fail 'Cannot unshift to a shaped array' unless nqp::istype($!shape, Whatever);
nqp::findmethod(List, 'unshift')(self, |@values);
}

multi method perl(Array:D \SELF:) {
nqp::iscont(SELF)
?? '[' ~ self.map({.perl}).join(', ') ~ ']'
Expand All @@ -90,6 +123,8 @@ class Array {
}

method STORE_AT_POS(Int \pos, Mu $v is copy) is rw {
fail "Index $pos is too large for this shaped array"
unless nqp::istype($!shape, Whatever) or $pos < $!shape;
nqp::bindpos(nqp::getattr(self, List, '$!items'),
nqp::unbox_i(pos), $v)
}
Expand All @@ -101,6 +136,7 @@ class Array {
# make an array from them (we can't just use ourself for this,
# or @a = @a will go terribly wrong); make it eager
my $list := nqp::p6list($args, Array, Mu);
nqp::bindattr($list, Array, '$!shape', $!shape);
nqp::bindattr($list, List, '$!flattens', True);
$list.eager;
# clear our items and set our next iterator to be one over
Expand All @@ -113,23 +149,27 @@ class Array {
my role TypedArray[::TValue] does Positional[TValue] {
multi method at_pos($pos is copy, TValue $v? is copy) is rw {
$pos = $pos.Int;
fail "Index $pos is too large for this shaped array" unless nqp::istype(self.shape, Whatever) or $pos < self.shape;
self.exists($pos)
?? nqp::atpos(nqp::getattr(self, List, '$!items'), nqp::unbox_i($pos))
!! nqp::p6bindattrinvres($v, Scalar, '$!whence',
-> { nqp::bindpos(nqp::getattr(self, List, '$!items'), nqp::unbox_i($pos), $v) } )
}
multi method at_pos(int $pos, TValue $v? is copy) is rw {
fail "Index $pos is too large for this shaped array" unless nqp::istype(self.shape, Whatever) or $pos < self.shape;
self.exists($pos)
?? nqp::atpos(nqp::getattr(self, List, '$!items'), $pos)
!! nqp::p6bindattrinvres($v, Scalar, '$!whence',
-> { nqp::bindpos(nqp::getattr(self, List, '$!items'), $pos, $v) } )
}
multi method bind_pos($pos is copy, TValue \bindval) is rw {
$pos = $pos.Int;
fail "Index $pos is too large for this shaped array" unless nqp::istype(self.shape, Whatever) or $pos < self.shape;
self.gimme($pos + 1);
nqp::bindpos(nqp::getattr(self, List, '$!items'), nqp::unbox_i($pos), bindval)
}
multi method bind_pos(int $pos, TValue \bindval) is rw {
fail "Index $pos is too large for this shaped array" unless nqp::istype(self.shape, Whatever) or $pos < self.shape;
self.gimme($pos + 1);
nqp::bindpos(nqp::getattr(self, List, '$!items'), $pos, bindval)
}
Expand Down
6 changes: 6 additions & 0 deletions src/vm/jvm/runtime/org/perl6/rakudo/RakOps.java
Expand Up @@ -46,6 +46,7 @@ public static class GlobalExt {
public SixModelObject ContainerDescriptor;
public SixModelObject False;
public SixModelObject True;
public SixModelObject Whatever;
public SixModelObject AutoThreader;
public SixModelObject EMPTYARR;
public SixModelObject EMPTYHASH;
Expand Down Expand Up @@ -75,6 +76,7 @@ public GlobalExt(ThreadContext tc) { }
private static final int HINT_LISTITER_nextiter = 1;
private static final int HINT_LISTITER_rest = 2;
private static final int HINT_LISTITER_list = 3;
private static final int HINT_ARRAY_shape = 0;

public static SixModelObject p6init(ThreadContext tc) {
GlobalExt gcx = key.getGC(tc);
Expand Down Expand Up @@ -112,6 +114,7 @@ public static SixModelObject p6settypes(SixModelObject conf, ThreadContext tc) {
gcx.ContainerDescriptor = conf.at_key_boxed(tc, "ContainerDescriptor");
gcx.False = conf.at_key_boxed(tc, "False");
gcx.True = conf.at_key_boxed(tc, "True");
gcx.Whatever = conf.at_key_boxed(tc, "Whatever");
return conf;
}

Expand Down Expand Up @@ -160,6 +163,9 @@ public static SixModelObject p6list(SixModelObject arr, SixModelObject type, Six
list.bind_attribute_boxed(tc, gcx.List, "$!nextiter", HINT_LIST_nextiter,
p6listiter(arr, list, tc));
list.bind_attribute_boxed(tc, gcx.List, "$!flattens", HINT_LIST_flattens, flattens);
if (type = gcx.Array)
list.bind_attribute_boxed(tc, gcx.Array, "$!shape", HINT_ARRAY_shape,
gcx.Whatever.st.REPR.allocate(tc, gcx.Whatever.st));
return list;
}

Expand Down
13 changes: 10 additions & 3 deletions src/vm/parrot/guts/bind.c
Expand Up @@ -27,6 +27,7 @@ static STRING *REST_str = NULL;
static STRING *LIST_str = NULL;
static STRING *HASH_str = NULL;
static STRING *FLATTENS_str = NULL;
static STRING *SHAPE_str = NULL;
static STRING *NEXTITER_str = NULL;
static STRING *HASH_SIGIL_str = NULL;
static STRING *ARRAY_SIGIL_str = NULL;
Expand All @@ -51,6 +52,7 @@ static void setup_binder_statics(PARROT_INTERP) {
LIST_str = Parrot_str_new_constant(interp, "$!list");
HASH_str = Parrot_str_new_constant(interp, "$!hash");
FLATTENS_str = Parrot_str_new_constant(interp, "$!flattens");
SHAPE_str = Parrot_str_new_constant(interp, "$!shape");
NEXTITER_str = Parrot_str_new_constant(interp, "$!nextiter");
HASH_SIGIL_str = Parrot_str_new_constant(interp, "%");
ARRAY_SIGIL_str = Parrot_str_new_constant(interp, "@");
Expand Down Expand Up @@ -155,13 +157,18 @@ Rakudo_binding_list_from_rpa(PARROT_INTERP, PMC *rpa, PMC *type, PMC *flattens)
VTABLE_set_attr_keyed(interp, list, List, FLATTENS_str, flattens);
return list;
}


/* Creates a Perl 6 Array. */
static PMC *
Rakudo_binding_create_positional(PARROT_INTERP, PMC *rpa) {
return Rakudo_binding_list_from_rpa(interp, rpa, Rakudo_types_array_get(),
Rakudo_types_bool_true_get());
PMC *Array = Rakudo_types_array_get();
PMC *Whatever = Rakudo_types_whatever_get();
PMC *list = Rakudo_binding_list_from_rpa(interp, rpa, Array,
Rakudo_types_bool_true_get());
VTABLE_set_attr_keyed(interp, list, Array, SHAPE_str,
REPR(Whatever)->allocate(interp, STABLE(Whatever)));
return list;
}


Expand Down
4 changes: 4 additions & 0 deletions src/vm/parrot/guts/types.c
Expand Up @@ -27,6 +27,7 @@ static PMC * Capture = NULL;
static PMC * Code = NULL;
static PMC * BoolFalse = NULL;
static PMC * BoolTrue = NULL;
static PMC * Whatever = NULL;
static PMC * JunctionThreader = NULL;

static INTVAL ownedhash_id = 0;
Expand Down Expand Up @@ -89,6 +90,9 @@ PMC * Rakudo_types_bool_false_get(void) { return BoolFalse; }
void Rakudo_types_bool_true_set(PMC * type) { BoolTrue = type; }
PMC * Rakudo_types_bool_true_get(void) { return BoolTrue; }

void Rakudo_types_whatever_set(PMC * type) { Whatever = type; }
PMC * Rakudo_types_whatever_get(void) { return Whatever; }

void Rakudo_types_junction_threader_set(PMC * threader) { JunctionThreader = threader; }
PMC * Rakudo_types_junction_threader_get(void) { return JunctionThreader; }

Expand Down
3 changes: 3 additions & 0 deletions src/vm/parrot/guts/types.h
Expand Up @@ -58,6 +58,9 @@ PMC * Rakudo_types_bool_false_get(void);
void Rakudo_types_bool_true_set(PMC * type);
PMC * Rakudo_types_bool_true_get(void);

void Rakudo_types_whatever_set(PMC * type);
PMC * Rakudo_types_whatever_get(void);

void Rakudo_types_junction_threader_set(PMC * threader);
PMC * Rakudo_types_junction_threader_get(void);

Expand Down
2 changes: 2 additions & 0 deletions src/vm/parrot/ops/perl6.ops
Expand Up @@ -654,6 +654,8 @@ inline op p6settypes(invar PMC) :base_core {
Parrot_str_new_constant(interp, "False")));
Rakudo_types_bool_true_set(VTABLE_get_pmc_keyed_str(interp, $1,
Parrot_str_new_constant(interp, "True")));
Rakudo_types_whatever_set(VTABLE_get_pmc_keyed_str(interp, $1,
Parrot_str_new_constant(interp, "Whatever")));
Rakudo_types_junction_set(VTABLE_get_pmc_keyed_str(interp, $1,
Parrot_str_new_constant(interp, "Junction")));
Rakudo_types_nil_set(VTABLE_get_pmc_keyed_str(interp, $1,
Expand Down

0 comments on commit 6493e48

Please sign in to comment.