Permalink
Browse files

refactor dispatch with an eye towards enabling curly-bracket cell ind…

…exing. broke some tests, will revisit tomorrow
  • Loading branch information...
1 parent c0df4b4 commit e94ad9b621e33e024d5201ddfcffa0d50e8e5d0e @Whiteknight committed Dec 9, 2009
Showing with 111 additions and 137 deletions.
  1. +4 −1 matrixy.pir
  2. +75 −10 src/internals/dispatch.pir
  3. +23 −90 src/parser/actions.pm
  4. +9 −36 src/parser/grammar.pg
View
@@ -73,6 +73,9 @@ object.
$P0 = box 0
set_hll_global ['Matrixy';'Grammar';'Actions'], '$?MATRIXSQUARE', $P0
+ $P0 = box 0
+ set_hll_global ['Matrixy';'Grammar';'Actions'], '$?LVALUECELL', $P0
+
# list of functions that we've compiled. We cache them to prevent needing
# to recompile.
# TODO: This isn't part of the parser, find a better namespace to hold this
@@ -132,7 +135,7 @@ to the Matrixy compiler.
# TODO: We might want to add this sequence as a method on the compiler
# object, so we can call it from a library load too.
# load start up file
-
+
errorsoff .PARROT_ERRORS_PARAM_COUNT_FLAG
errorsoff .PARROT_ERRORS_RESULT_COUNT_FLAG
$P0 = null
View
@@ -108,7 +108,13 @@ Handles equations of the following types:
a = var(b, ...)
-Returns the value
+Returns the value. Matrices can be indexed with foo(...) style, which returns
+the scalar item at that position. Cells can be indexed with foo{...} to return
+the item, or with foo(...) to return another cell containing those items.
+
+ foo parens == 0
+ foo(...) parens == 1
+ foo{...} parens == 2
=cut
@@ -119,24 +125,63 @@ Returns the value
.param int parens
.param pmc args
+ # Figure out which type it is, to determine where to go
$S0 = typeof var
- # If it's a function handle variable, dispatch it.
- unless $S0 == 'Sub' goto its_a_variable
- if parens == 1 goto execute_sub_handle
+ if $S0 == 'Sub' goto have_func_handle
+ if $S0 == 'PMCMatrix2D' goto have_cell_array
+ $I0 = does var, "matrix"
+ if $I0 == 1 goto have_matrix_type
+ $I0 = args
+ if $I0 != 0 goto error_index_scalar
.return(var)
- execute_sub_handle:
+
+ # For Subs, if we have parens execute it. Otherwise it's an error. If we
+ # want a sub reference, need to use the @ operator
+ have_func_handle:
+ if parens == 0 goto error_bad_func_call
+ if parens == 2 goto error_func_not_cell
.tailcall var(nargout, nargin, args :flat)
- # If it's an ordinary variable, do the indexing
- its_a_variable:
+ have_cell_array:
+ if parens == 1 goto index_cell_as_cell
+ if parens == 2 goto index_cell_as_matrix
+ .return(var)
+ index_cell_as_matrix:
+ .tailcall '!scalar_indexing'(var, args)
+ index_cell_as_cell:
+ # TODO: Do this right!
+ $P0 = '!scalar_indexing'(var, args)
+ $P1 = new ['PMCMatrix2D']
+ $P1[0;0] = $P0
+ .return($P1)
+
+ have_matrix_type:
+ if parens == 1 goto index_matrix_as_matrix
+ if parens == 2 goto error_matrix_not_cell
+ .return(var)
+ index_matrix_as_matrix:
+ .tailcall '!scalar_indexing'(var, args)
+
+ error_index_scalar:
+ _error_all("Cannot index a scalar")
+ error_bad_func_call:
+ _error_all("Sub cannot be used like a variable")
+ error_func_not_cell:
+ _error_all("Cannot index function with {}")
+ error_matrix_not_cell:
+ _error_all("Cannot index matrix with {}")
+.end
+.sub '!scalar_indexing'
+ .param pmc var
+ .param pmc args
# If we only have a 1-ary index, we need to use a separate vector indexing
# algorithm instead of the nested matrix indexing.
$I0 = args
if $I0 == 0 goto non_indexing
if $I0 == 1 goto vector_indexing
if $I0 == 2 goto matrix_indexing
- _error_all("Only 0, 1, 2 indexes are supported")
+ _error_all("Only 0, 1, 2 indexes are currently supported")
non_indexing:
.return(var)
@@ -153,8 +198,6 @@ Returns the value
dec $I1
$P0 = var[$I0;$I1]
.return($P0)
- negative_index_attempt:
- _error_all("invalid index")
.end
=item !is_scalar
@@ -186,6 +229,28 @@ Returns the modified variable.
=cut
+# TODO: What is the difference between foo() and foo{}, besides the later
+# not working for non-cells? At the moment we do basic type checking and
+# Then redirect to normal indexed assignment.
+# TODO: We can refactor these two assignment functions to both call a common
+# indexing kernel, I think
+.sub '!indexed_assign_cell'
+ .param pmc var
+ .param pmc value
+ .param pmc indices :slurpy
+
+ if null var goto autovivify_cell
+ $S0 = typeof var
+ if $S0 != "PMCMatrix2D" goto not_a_cell
+ .tailcall '!indexed_assign'(var, value, indices :flat)
+
+ not_a_cell:
+ _error_all("cell indexing on a non-cell")
+ autovivify_cell:
+ var = new ['PMCMatrix2D']
+ .tailcall '!indexed_assign'(var, value, indices :flat)
+.end
+
.sub '!indexed_assign'
.param pmc var
.param pmc value
View
@@ -269,20 +269,27 @@ method assignment($/, $key) {
our $?BLOCK;
our %?GLOBALS;
our @?PARAMS;
+ our $?LVALUECELL;
if $key eq "open" {
@?PARAMS := _new_empty_array();
}
else {
+ my $indexer := '!indexed_assign';
+ if $?LVALUECELL {
+ $indexer := '!indexed_assign_cell';
+ $?LVALUECELL := 0;
+ }
my $rhs := $( $<expression> );
my $lhs := $( $<variable> );
$lhs.lvalue(1);
my $name := $lhs.name();
if %?GLOBALS{$name} {
+ # TODO: Make sure we want "Matrixy::globals", not ["Matrixy","globals"]
$lhs.namespace("Matrixy::globals");
}
$rhs := PAST::Op.new(
:pasttype('call'),
- :name('!indexed_assign'),
+ :name($indexer),
PAST::Var.new(
:name($lhs.name()),
:scope('package')
@@ -304,12 +311,17 @@ method assignment($/, $key) {
method lvalue_postfix_index($/, $key) {
our @?PARAMS;
- if $key eq "expressions" {
+ our $?LVALUECELL;
+ if $key eq "cellexpression" {
+ $?LVALUECELL := 1;
+ }
+ if $key eq "expressions" || $key eq "cellexpression" {
for $<expression> {
@?PARAMS.push($($_));
}
}
else {
+ # TODO: This isn't right for structures
my $name := $( $<identifier> ).name();
@?PARAMS.push(
PAST::Val.new(
@@ -522,7 +534,14 @@ method sub_or_var($/, $key) {
our %?GLOBALS;
my $invocant := $( $<primary> );
my $name := $invocant.name();
+ my $parens := 0;
+ if $key eq "args" {
+ $parens := 1;
+ } elsif $key eq "cellargs" {
+ $parens := 2;
+ }
if %?GLOBALS{$name} {
+ # TODO: "Matrixy";"globals"
$invocant.namespace("Matrixy::globals");
}
my $nargin := 0;
@@ -540,7 +559,7 @@ method sub_or_var($/, $key) {
}
$past.unshift(
PAST::Val.new(
- :value($key eq "args"),
+ :value($parens),
:returns('Integer')
)
);
@@ -577,15 +596,6 @@ method bare_words($/) {
method primary($/) {
my $past := $( $<identifier> );
- for $<postfix_expression> {
- my $expr := $( $_ );
- ## set the current $past as the first child of $expr;
- ## $expr is either a key or an index; both are "keyed"
- ## variable access, where the first child is assumed
- ## to be the aggregate.
- $expr.unshift($past);
- $past := $expr;
- }
make $past;
}
@@ -595,68 +605,6 @@ method primary($/) {
method variable($/) {
our $?BLOCK;
my $past := $( $<identifier> );
- my $name := $past.name();
- for $<postfix_expression> {
- my $expr := $( $_ );
- $expr.unshift($past);
- $past := $expr;
- }
- make $past;
-}
-
-method postfix_expression($/, $key) {
- make $( $/{$key} );
-}
-
-method key($/) {
- my $key := $( $<expression> );
-
- make PAST::Var.new(
- $key,
- :scope('keyed'),
- :vivibase('Hash'),
- :viviself('Undef'),
- :node($/)
- );
-}
-
-method member($/) {
- my $member := $( $<identifier> );
- ## x.y is syntactic sugar for x{"y"}, so stringify the identifier:
- my $key := PAST::Val.new(
- :returns('String'),
- :value($member.name()),
- :node($/)
- );
-
- ## the rest of this method is the same as method key() above.
- make PAST::Var.new(
- $key,
- :scope('keyed'),
- :vivibase('Hash'),
- :viviself('Undef'),
- :node($/)
- );
-}
-
-method index($/) {
- my $index := $( $<expression> );
-
- make PAST::Var.new(
- $index,
- :scope('keyed'),
- :vivibase('ResizablePMCArray'),
- :viviself('Undef'),
- :node($/)
- );
-}
-
-method named_field($/) {
- my $past := $( $<expression> );
- my $name := $( $<string_constant> );
- ## the passed expression is in fact a named argument,
- ## use the named() accessor to set that name.
- $past.named($name);
make $past;
}
@@ -724,21 +672,6 @@ method subexpression($/, $key) {
make $( $/{$key} );
}
-method hash_constructor($/) {
- ## use the parrot calling conventions to
- ## create a hash, using the "anonymous" sub
- ## !hash (which is not a valid Squaak name)
- my $past := PAST::Op.new(
- :name('!hash'),
- :pasttype('call'),
- :node($/)
- );
- for $<named_field> {
- $past.push($($_));
- }
- make $past;
-}
-
method term($/, $key) {
make $( $/{$key} );
}
@@ -799,7 +732,7 @@ method expression($/, $key) {
else {
$past.pasttype('call');
$past.push(
- PAST::Var.new(
+ PAST::Var.new(
:name(~$<type>),
:namespace("_Matrixy","builtins")
)
Oops, something went wrong.

0 comments on commit e94ad9b

Please sign in to comment.