Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
More progress on typed arrays and hashes. This patch allows them to b…
…e declared, gets them responding correctly to .of, allows checking for (potentially typed) positionals/associatives/callables in the signature and allows the sigils and the Positional/Associative/Callable parametric types to participate in multi dispatch.
  • Loading branch information
jnthn committed Apr 7, 2009
1 parent 6eef54b commit fb553bd
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 36 deletions.
14 changes: 13 additions & 1 deletion src/builtins/assign.pir
Expand Up @@ -16,13 +16,25 @@ src/builtins/assign.pir - assignments
.param pmc cont
.param pmc source

source = '!CALLMETHOD'('Scalar', source)
.local pmc ro, type
getprop ro, 'readonly', cont
if null ro goto ro_ok
unless ro goto ro_ok
'die'('Cannot assign to readonly variable.')
ro_ok:

# This is a workaround because Parrot's multi-dispatch sometimes gets us
# here by accident when we have a Perl6Array that got re-blessed.
$I0 = isa cont, 'Perl6Array'
unless $I0 goto not_array
.tailcall cont.'!STORE'(source)
not_array:
$I0 = isa cont, 'Perl6Hash'
unless $I0 goto not_hash
.tailcall cont.'!STORE'(source)
not_hash:

source = '!CALLMETHOD'('Scalar', source)
$I0 = defined source
unless $I0 goto do_assign
getprop type, 'type', cont
Expand Down
64 changes: 31 additions & 33 deletions src/classes/Signature.pir
Expand Up @@ -62,19 +62,17 @@ the Signature.
attr['multi_invocant'] = 1
have_mi:
# Work out any role type that the sigil implies.
.local pmc role_type, default_type
# Work out any role type that the sigil implies. (Skip for slurpy, though.)
$I0 = attr["slurpy"]
if $I0 goto sigil_done
.local pmc role_type
.local string sigil
sigil = substr varname, 0, 1
if sigil == '$' goto sigil_scalar
default_type = get_hll_global 'Object'
if sigil == '$' goto sigil_done
if sigil == '@' goto sigil_array
if sigil == '%' goto sigil_hash
if sigil == '&' goto sigil_code
goto sigil_done
sigil_scalar:
default_type = get_hll_global 'Any'
goto sigil_done
if sigil == ':' goto sigil_done
goto sigil_code
sigil_array:
role_type = get_hll_global 'Positional'
goto sigil_done
Expand All @@ -94,10 +92,7 @@ the Signature.
constraints = new 'ResizablePMCArray'
type = null
cur_list = attr["type"]
unless null cur_list goto have_type_attr
$P0 = get_hll_global 'Any'
cur_list = 'infix:&'($P0) # Unlike C<all>, doesn't call !flatten (too early in bootstrap)
attr["type"] = cur_list
if null cur_list goto cur_list_loop_end
have_type_attr:
cur_list = cur_list.'eigenstates'()
cur_list_iter = iter cur_list
Expand Down Expand Up @@ -125,16 +120,31 @@ the Signature.
type = null
constraints = cur_list
cur_list_loop_end:
# Set parametric type, if any.
.local pmc all_types
all_types = new 'ResizablePMCArray'
unless null type goto have_type
unless null role_type goto simple_role_type
type = get_hll_global 'Any'
goto done_role_type
simple_role_type:
type = role_type
goto done_role_type
have_type:
if null role_type goto done_role_type
type = role_type.'!select'(type)
done_role_type:
attr["nom_type"] = type
$I0 = elements constraints
if $I0 == 0 goto no_constraints
constraints = 'all'(constraints)
$P0 = 'infix:&'(type, constraints :flat)
attr["type"] = $P0
constraints = 'infix:&'(constraints :flat)
goto set_constraints
no_constraints:
constraints = new 'Undef'
attr["type"] = type
set_constraints:
attr["cons_type"] = constraints
Expand Down Expand Up @@ -337,7 +347,6 @@ lexicals as needed and performing type checks.
orig = callerlex[name]
if sigil == '@' goto param_array
if sigil == '%' goto param_hash
if sigil != '$' goto param_sub
var = '!CALLMETHOD'('Scalar', orig)
## typecheck the argument unless it's undef (for optional parameter)
if null optional goto not_optional
Expand All @@ -350,22 +359,17 @@ lexicals as needed and performing type checks.
unless $P0 goto err_param_type
goto param_val_done
param_array:
$I0 = does orig, 'Positional'
if $I0 goto param_array_1
$I0 = does orig, 'array'
unless $I0 goto err_array
param_array_1:
$P0 = type.'ACCEPTS'(orig)
unless $P0 goto err_array
var = '!DEREF'(orig)
var = '!CALLMETHOD'('Array', var)
goto param_val_done
param_hash:
$I0 = does orig, 'Associative'
if $I0 goto param_hash_1
$I0 = does orig, 'hash'
unless $I0 goto err_hash
param_hash_1:
$P0 = type.'ACCEPTS'(orig)
unless $P0 goto err_hash
var = '!DEREF'(orig)
var = '!CALLMETHOD'('Hash', var)
goto param_val_done
param_val_done:
## handle readonly/copy traits
$S0 = param['readtype']
Expand Down Expand Up @@ -397,10 +401,6 @@ lexicals as needed and performing type checks.
## place the updated variable back into lex
callerlex[name] = var
goto param_loop
param_sub:
$I0 = isa orig, 'Sub'
unless $I0 goto err_sub
if $I0 goto param_loop
param_done:
end:
Expand All @@ -417,13 +417,11 @@ lexicals as needed and performing type checks.
errmsg = 'Parameter type check failed'
goto err_throw
err_array:
errmsg = 'Non-Positional argument'
errmsg = 'Non-Positional argument or Positional of wrong element type'
goto err_throw
err_hash:
errmsg = 'Non-Associative argument'
errmsg = 'Non-Associative argument or Associative of wrong value type'
goto err_throw
err_sub:
errmsg = 'Non-Callable argument'
err_throw:
.local string callername
callername = callersub
Expand Down
7 changes: 5 additions & 2 deletions src/parser/actions.pm
Expand Up @@ -1164,13 +1164,16 @@ method signature($/, $key) {
my $sigparam := PAST::Op.new( :pasttype('callmethod'),
:name('!add_param'), $sigobj, $name );

## if it's named or optional, note that in the signature object
## if it's named optional or slurpy, note that in the signature object
if $var.named() ne "" {
$sigparam.push(PAST::Val.new( :value($var.named()), :named('named') ));
}
if $var.viviself() {
$sigparam.push(PAST::Val.new( :value(1), :named('optional') ));
}
if $var.slurpy() {
$sigparam.push(PAST::Val.new( :value(1), :named('slurpy') ));
}

## add any typechecks
my $type := $var<type>;
Expand Down Expand Up @@ -1271,7 +1274,7 @@ method parameter($/) {
our @?BLOCK;
my $name := ~$<type_constraint>[0];
$var := PAST::Var.new( :scope('parameter') );
$var.name($var.unique());
$var.name($var.unique('::TYPE_CAPTURE'));
@?BLOCK[0].symbol( $var.name(), :scope('lexical') );
}

Expand Down

0 comments on commit fb553bd

Please sign in to comment.