Skip to content

Commit

Permalink
add preliminary cell support
Browse files Browse the repository at this point in the history
  • Loading branch information
Whiteknight committed Nov 17, 2009
1 parent 6591db1 commit ce63abc
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 44 deletions.
128 changes: 88 additions & 40 deletions src/internals/aggregates.pir
Expand Up @@ -11,13 +11,101 @@
.return(ary)
.end

.sub '!matrix_from_rows'
.param pmc ary :slurpy
.local pmc lengths
.local int has_numbers
.local int has_strings
.local int has_complex

# If there are no rows, just return an empty matrix
$I0 = ary
unless $I0 == 0 goto construct_the_matrix
$P0 = new ['NumMatrix2D']
.return($P0)

construct_the_matrix:
(lengths, has_numbers, has_strings, has_complex) = '!_get_rows_info'(ary)
unless has_numbers goto dont_check_length
'!_verify_array_lengths_equal'(lengths)

dont_check_length:
if has_complex goto build_complex_matrix
if has_strings goto build_string_matrix
.tailcall '!_build_numerical_matrix'(ary)
build_string_matrix:
.tailcall '!_build_string_matrix'(ary)
build_complex_matrix:
if has_strings goto cant_have_both
.tailcall '!_build_complex_matrix'(ary)
cant_have_both:
_error_all("Cannot have both complex and string values in one matrix")
.end

.sub '!matrix'
.param int x
.param int y
.param pmc args :slurpy
$P0 = new ['NumMatrix2D']
$P0.'initialize_from_array'(x, y, args)
.return($P0)
.end


.sub '!matrix_row'
.param pmc args :slurpy
$P0 = new ['matrix_row']
$P0.'build_row'(args)
.return($P0)
.end

.sub '!cell_from_rows'
.param pmc rows :slurpy
.local pmc cell
.local pmc row
.local int length
cell = new ['PMCMatrix2D']
$I0 = rows
if $I0 == 0 goto new_empty_cell
myiter = iter rows
row = shift myiter
length = row
$I0 = 0
loop_top:
'!_insert_cell_row'(cell, row, $I0)
unless myiter goto loop_bottom
row = shift myiter
$I1 = row
if $I1 != length goto lengths_not_equal
goto loop_top
loop_bottom:
new_empty_cell:
.return(cell)
lengths_not_equal:
_error_all("Row lengths must be equal ", $I1, " != ", length)
.end

.sub '!_insert_cell_row'
.param pmc cell
.param pmc row
.param int idx
.local int length
length = row
dec length
loop_top:
$P0 = row[length]
cell[idx;length] = $P0
if length == 0 goto loop_bottom
dec length
goto loop_top
loop_bottom:
.end

.sub '!cell_row'
.param pmc args :slurpy
.return(args)
.end

.sub '!_get_rows_info'
.param pmc ary

Expand Down Expand Up @@ -138,46 +226,6 @@
.return(matrix)
.end

.sub '!matrix_from_rows'
.param pmc ary :slurpy
.local pmc lengths
.local int has_numbers
.local int has_strings
.local int has_complex

# If there are no rows, just return an empty matrix
$I0 = ary
unless $I0 == 0 goto construct_the_matrix
$P0 = new ['NumMatrix2D']
.return($P0)

construct_the_matrix:
(lengths, has_numbers, has_strings, has_complex) = '!_get_rows_info'(ary)
unless has_numbers goto dont_check_length
'!_verify_array_lengths_equal'(lengths)

dont_check_length:
if has_complex goto build_complex_matrix
if has_strings goto build_string_matrix
.tailcall '!_build_numerical_matrix'(ary)
build_string_matrix:
.tailcall '!_build_string_matrix'(ary)
build_complex_matrix:
if has_strings goto cant_have_both
.tailcall '!_build_complex_matrix'(ary)
cant_have_both:
_error_all("Cannot have both complex and string values in one matrix")
.end

.sub '!matrix'
.param int x
.param int y
.param pmc args :slurpy
$P0 = new ['NumMatrix2D']
$P0.'initialize_from_array'(x, y, args)
.return($P0)
.end

# used in the parser
.sub '_new_empty_array'
$P0 = new ['ResizablePMCArray']
Expand Down
26 changes: 25 additions & 1 deletion src/parser/actions.pm
Expand Up @@ -661,7 +661,7 @@ method named_field($/) {
make $past;
}

method array_constructor($/, $key) {
method array_constructor($/) {
my $past := PAST::Op.new(
:name('!matrix_from_rows'),
:pasttype('call'),
Expand All @@ -685,6 +685,30 @@ method array_row($/) {
make $past;
}

method cell_constructor($/) {
my $past := PAST::Op.new(
:name('!cell_from_rows'),
:pasttype('call'),
:node($/)
);
for $<cell_row> {
$past.push($($_));
}
make $past;
}

method cell_row($/) {
my $past := PAST::Op.new(
:name('!cell_row'),
:pasttype('call'),
:node($/)
);
for $<expression> {
$past.push($($_));
}
make $past;
}

method range_constructor($/, $key) {
my $past := PAST::Op.new(
:name('!range_constructor_' ~ $key),
Expand Down
19 changes: 16 additions & 3 deletions src/parser/grammar.pg
Expand Up @@ -153,6 +153,7 @@ rule term {
| <string_constant> {*} #= string_constant
| <hash_constructor> {*} #= hash_constructor
| <array_constructor> {*} #= array_constructor
| <cell_constructor> {*} #= cell_constructor
| <function_handle> {*} #= function_handle
| <anon_func_constructor> {*} #= anon_func_constructor
| <sub_or_var> {*} #= sub_or_var
Expand Down Expand Up @@ -279,16 +280,28 @@ rule named_field {
# TODO: Should probably be renamed "matrix_constructor", but that's nitpickery
rule array_constructor {
'['
{*} #= open
[ <array_row> [<terminator> <array_row>]* ]? ']'
{*} #= close
[ <array_row> [<terminator> <array_row>]* ]?
']'
{*}
}

rule array_row {
<expression> [','? <expression>]*
{*}
}

rule cell_constructor {
'{'
[ <cell_row> [<terminator> <cell_row>]* ]?
'}'
{*}
}

rule cell_row {
<expression> [','? <expression>]*
{*}
}

rule range_constructor {
<subexpression> ':' <subexpression> ':' <subexpression> {*} #= three
| <subexpression> ':' <subexpression> {*} #= two
Expand Down

0 comments on commit ce63abc

Please sign in to comment.