# HG changeset patch # User jwe # Date 749702218 0 # Node ID 7849db4b6dbcc1e5934ce60e341146c932d609d7 # Parent 6906d6591452a1f3a8fbbfa6d64dbf674a2b58fc [project @ 1993-10-04 02:36:45 by jwe] diff --git a/src/arith-ops.cc b/src/arith-ops.cc --- a/src/arith-ops.cc +++ b/src/arith-ops.cc @@ -76,6 +76,129 @@ }; /* + * Check row and column dimensions for binary matrix operations. + */ +static inline int +m_add_conform (Matrix& a, Matrix& b, int warn) +{ + int ar = a.rows (); + int ac = a.columns (); + int br = b.rows (); + int bc = b.columns (); + + int ok = (ar == br && ac == bc); + + if (! ok && warn) + gripe_nonconformant (ar, ac, br, bc); + + return ok; +} + +static inline int +m_add_conform (Matrix& a, ComplexMatrix& b, int warn) +{ + int ar = a.rows (); + int ac = a.columns (); + int br = b.rows (); + int bc = b.columns (); + + int ok = (ar == br && ac == bc); + + if (! ok && warn) + gripe_nonconformant (ar, ac, br, bc); + + return ok; +} + +static inline int +m_add_conform (ComplexMatrix& a, Matrix& b, int warn) +{ + int ar = a.rows (); + int ac = a.columns (); + int br = b.rows (); + int bc = b.columns (); + + int ok = (ar == br && ac == bc); + + if (! ok && warn) + gripe_nonconformant (ar, ac, br, bc); + + return ok; +} + +static inline int +m_add_conform (ComplexMatrix& a, ComplexMatrix& b, int warn) +{ + int ar = a.rows (); + int ac = a.columns (); + int br = b.rows (); + int bc = b.columns (); + + int ok = (ar == br && ac == bc); + + if (! ok && warn) + gripe_nonconformant (ar, ac, br, bc); + + return ok; +} + +static inline int +m_mul_conform (Matrix& a, Matrix& b, int warn) +{ + int ac = a.columns (); + int br = b.rows (); + + int ok = (ac == br); + + if (! ok && warn) + gripe_nonconformant (a.rows (), ac, br, b.columns ()); + + return ok; +} + +static inline int +m_mul_conform (Matrix& a, ComplexMatrix& b, int warn) +{ + int ac = a.columns (); + int br = b.rows (); + + int ok = (ac == br); + + if (! ok && warn) + gripe_nonconformant (a.rows (), ac, br, b.columns ()); + + return ok; +} + +static inline int +m_mul_conform (ComplexMatrix& a, Matrix& b, int warn) +{ + int ac = a.columns (); + int br = b.rows (); + + int ok = (ac == br); + + if (! ok && warn) + gripe_nonconformant (a.rows (), ac, br, b.columns ()); + + return ok; +} + +static inline int +m_mul_conform (ComplexMatrix& a, ComplexMatrix& b, int warn) +{ + int ac = a.columns (); + int br = b.rows (); + + int ok = (a.columns () == br); + + if (! ok && warn) + gripe_nonconformant (a.rows (), ac, br, b.columns ()); + + return ok; +} + +/* * Stupid binary comparison operations like the ones Matlab provides. * One for each type combination, in the order given here: * @@ -97,7 +220,9 @@ { int ar = a.rows (); int ac = a.columns (); + Matrix t (ar, ac); + for (int j = 0; j < ac; j++) for (int i = 0; i < ar; i++) { @@ -132,6 +257,7 @@ break; } } + return t; } @@ -141,7 +267,9 @@ { int ar = a.rows (); int ac = a.columns (); + Matrix t (ar, ac); + for (int j = 0; j < ac; j++) for (int i = 0; i < ar; i++) { @@ -176,6 +304,7 @@ break; } } + return t; } @@ -185,7 +314,9 @@ { int ar = a.rows (); int ac = a.columns (); + Matrix t (ar, ac); + for (int j = 0; j < ac; j++) for (int i = 0; i < ar; i++) { @@ -220,6 +351,7 @@ break; } } + return t; } @@ -229,7 +361,9 @@ { int ar = a.rows (); int ac = a.columns (); + Matrix t (ar, ac); + for (int j = 0; j < ac; j++) for (int i = 0; i < ar; i++) { @@ -264,6 +398,7 @@ break; } } + return t; } @@ -271,15 +406,12 @@ static Matrix mx_stupid_bool_op (Matrix_bool_op op, Matrix& a, Matrix& b) { + if (! m_add_conform (a, b, 1)) + return Matrix (); + int ar = a.rows (); int ac = a.columns (); - if (ar != b.rows () || ac != b.columns ()) - { - gripe_nonconformant (); - jump_to_top_level (); - } - Matrix c (ar, ac); for (int j = 0; j < ac; j++) @@ -316,6 +448,7 @@ break; } } + return c; } @@ -323,15 +456,12 @@ static Matrix mx_stupid_bool_op (Matrix_bool_op op, Matrix& a, ComplexMatrix& b) { + if (! m_add_conform (a, b, 1)) + return Matrix (); + int ar = a.rows (); int ac = a.columns (); - if (ar != b.rows () || ac != b.columns ()) - { - gripe_nonconformant (); - jump_to_top_level (); - } - Matrix c (ar, ac); for (int j = 0; j < ac; j++) @@ -377,7 +507,9 @@ { int ar = a.rows (); int ac = a.columns (); + Matrix t (ar, ac); + for (int j = 0; j < ac; j++) for (int i = 0; i < ar; i++) { @@ -412,6 +544,7 @@ break; } } + return t; } @@ -421,7 +554,9 @@ { int ar = a.rows (); int ac = a.columns (); + Matrix t (ar, ac); + for (int j = 0; j < ac; j++) for (int i = 0; i < ar; i++) { @@ -456,6 +591,7 @@ break; } } + return t; } @@ -465,7 +601,9 @@ { int ar = a.rows (); int ac = a.columns (); + Matrix t (ar, ac); + for (int j = 0; j < ac; j++) for (int i = 0; i < ar; i++) { @@ -500,6 +638,7 @@ break; } } + return t; } @@ -509,7 +648,9 @@ { int ar = a.rows (); int ac = a.columns (); + Matrix t (ar, ac); + for (int j = 0; j < ac; j++) for (int i = 0; i < ar; i++) { @@ -544,6 +685,7 @@ break; } } + return t; } @@ -551,15 +693,12 @@ static Matrix mx_stupid_bool_op (Matrix_bool_op op, ComplexMatrix& a, Matrix& b) { + if (! m_add_conform (a, b, 1)) + return Matrix (); + int ar = a.rows (); int ac = a.columns (); - if (ar != b.rows () || ac != b.columns ()) - { - gripe_nonconformant (); - jump_to_top_level (); - } - Matrix c (ar, ac); for (int j = 0; j < ac; j++) @@ -603,15 +742,12 @@ static Matrix mx_stupid_bool_op (Matrix_bool_op op, ComplexMatrix& a, ComplexMatrix& b) { + if (! m_add_conform (a, b, 1)) + return Matrix (); + int ar = a.rows (); int ac = a.columns (); - if (ar != b.rows () || ac != b.columns ()) - { - gripe_nonconformant (); - jump_to_top_level (); - } - Matrix c (ar, ac); for (int j = 0; j < ac; j++) @@ -648,85 +784,11 @@ break; } } + return c; } /* - * Check row and column dimensions for binary matrix operations. - */ -static inline int -m_add_conform (Matrix& m1, Matrix& m2, int warn) -{ - int ok = (m1.rows () == m2.rows () && m1.columns () == m2.columns ()); - if (!ok && warn) - gripe_nonconformant (); - return ok; -} - -static inline int -m_add_conform (Matrix& m1, ComplexMatrix& m2, int warn) -{ - int ok = (m1.rows () == m2.rows () && m1.columns () == m2.columns ()); - if (!ok && warn) - gripe_nonconformant (); - return ok; -} - -static inline int -m_add_conform (ComplexMatrix& m1, Matrix& m2, int warn) -{ - int ok = (m1.rows () == m2.rows () && m1.columns () == m2.columns ()); - if (!ok && warn) - gripe_nonconformant (); - return ok; -} - -static inline int -m_add_conform (ComplexMatrix& m1, ComplexMatrix& m2, int warn) -{ - int ok = (m1.rows () == m2.rows () && m1.columns () == m2.columns ()); - if (!ok && warn) - gripe_nonconformant (); - return ok; -} - -static inline int -m_mul_conform (Matrix& m1, Matrix& m2, int warn) -{ - int ok = (m1.columns () == m2.rows ()); - if (!ok && warn) - gripe_nonconformant (); - return ok; -} - -static inline int -m_mul_conform (Matrix& m1, ComplexMatrix& m2, int warn) -{ - int ok = (m1.columns () == m2.rows ()); - if (!ok && warn) - gripe_nonconformant (); - return ok; -} - -static inline int -m_mul_conform (ComplexMatrix& m1, Matrix& m2, int warn) -{ - int ok = (m1.columns () == m2.rows ()); - if (!ok && warn) - gripe_nonconformant (); - return ok; -} - -static inline int -m_mul_conform (ComplexMatrix& m1, ComplexMatrix& m2, int warn) -{ - int ok = (m1.columns () == m2.rows ()); - if (!ok && warn) - gripe_nonconformant (); - return ok; -} - -/* * Unary operations. One for each numeric data type: * * scalar @@ -740,6 +802,7 @@ do_unary_op (double d, tree::expression_type t) { double result = 0.0; + switch (t) { case tree::not: @@ -764,6 +827,7 @@ do_unary_op (Matrix& a, tree::expression_type t) { Matrix result; + switch (t) { case tree::not: @@ -788,6 +852,7 @@ do_unary_op (Complex& c, tree::expression_type t) { Complex result = 0.0; + switch (t) { case tree::not: @@ -814,6 +879,7 @@ do_unary_op (ComplexMatrix& a, tree::expression_type t) { ComplexMatrix result; + switch (t) { case tree::not: @@ -857,6 +923,7 @@ do_binary_op (double a, double b, tree::expression_type t) { double result = 0.0; + switch (t) { case tree::add: @@ -914,6 +981,9 @@ break; } + if (error_state) + return tree_constant (); + return tree_constant (result); } @@ -922,6 +992,7 @@ do_binary_op (double a, Matrix& b, tree::expression_type t) { Matrix result; + switch (t) { case tree::add: @@ -944,8 +1015,7 @@ return x_el_div (a, b); break; case tree::divide: - error ("nonconformant right division"); - return tree_constant (); + gripe_nonconformant (1, 1, b.rows (), b.columns ()); break; case tree::power: return xpow (a, b); @@ -982,6 +1052,9 @@ break; } + if (error_state) + return tree_constant (); + return tree_constant (result); } @@ -994,6 +1067,7 @@ double result = 0.0; Complex complex_result; + switch (t) { case tree::add: @@ -1064,7 +1138,11 @@ break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else @@ -1080,6 +1158,7 @@ Matrix result; ComplexMatrix complex_result; + switch (t) { case tree::add: @@ -1105,8 +1184,7 @@ return x_el_div (a, b); break; case tree::divide: - error ("nonconformant right division"); - return tree_constant (); + gripe_nonconformant (1, 1, b.rows (), b.columns ()); break; case tree::power: return xpow (a, b); @@ -1151,7 +1229,11 @@ break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else @@ -1163,6 +1245,7 @@ do_binary_op (Matrix& a, double b, tree::expression_type t) { Matrix result; + switch (t) { case tree::add: @@ -1183,8 +1266,7 @@ return x_el_div (b, a); break; case tree::leftdiv: - error ("nonconformant left division"); - return tree_constant (); + gripe_nonconformant (a.rows (), a.columns (), 1, 1); break; case tree::power: return xpow (a, b); @@ -1221,6 +1303,9 @@ break; } + if (error_state) + return tree_constant (); + return tree_constant (result); } @@ -1230,45 +1315,31 @@ { Matrix result; - int error_cond = 0; - switch (t) { case tree::add: if (m_add_conform (a, b, 1)) result = a + b; - else - error_cond = 1; break; case tree::subtract: if (m_add_conform (a, b, 1)) result = a - b; - else - error_cond = 1; break; case tree::el_mul: if (m_add_conform (a, b, 1)) result = a.product (b); - else - error_cond = 1; break; case tree::multiply: if (m_mul_conform (a, b, 1)) result = a * b; - else - error_cond = 1; break; case tree::el_div: if (m_add_conform (a, b, 1)) result = a.quotient (b); - else - error_cond = 1; break; case tree::el_leftdiv: if (m_add_conform (a, b, 1)) result = b.quotient (a); - else - error_cond = 1; break; case tree::leftdiv: return xleftdiv (a, b); @@ -1278,71 +1349,52 @@ break; case tree::power: error ("can't do A ^ B for A and B both matrices"); - error_cond = 1; break; case tree::elem_pow: if (m_add_conform (a, b, 1)) return elem_xpow (a, b); - else - error_cond = 1; break; case tree::cmp_lt: if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_LT, a, b); - else - error_cond = 1; break; case tree::cmp_le: if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_LE, a, b); - else - error_cond = 1; break; case tree::cmp_eq: if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_EQ, a, b); - else - error_cond = 1; break; case tree::cmp_ge: if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_GE, a, b); - else - error_cond = 1; break; case tree::cmp_gt: if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_GT, a, b); - else - error_cond = 1; break; case tree::cmp_ne: if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_NE, a, b); - else - error_cond = 1; break; case tree::and: if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_AND, a, b); - else - error_cond = 1; break; case tree::or: if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_OR, a, b); - else - error_cond = 1; break; default: panic_impossible (); break; } - if (error_cond) + if (error_state) return tree_constant (); - else - return tree_constant (result); + + return tree_constant (result); } /* 7 */ @@ -1354,6 +1406,7 @@ Matrix result; ComplexMatrix complex_result; + switch (t) { case tree::add: @@ -1378,8 +1431,7 @@ return x_el_div (b, a); break; case tree::leftdiv: - error ("nonconformant left division"); - return tree_constant (); + gripe_nonconformant (a.rows (), a.columns (), 1, 1); break; case tree::power: return xpow (a, b); @@ -1424,7 +1476,11 @@ break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else @@ -1440,49 +1496,38 @@ Matrix result; ComplexMatrix complex_result; + switch (t) { case tree::add: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a + b; - else - return tree_constant (); break; case tree::subtract: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a - b; - else - return tree_constant (); break; case tree::el_mul: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a.product (b); - else - return tree_constant (); break; case tree::multiply: result_type = RT_complex; if (m_mul_conform (a, b, 1)) complex_result = a * b; - else - return tree_constant (); break; case tree::el_div: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a.quotient (b); - else - return tree_constant (); break; case tree::el_leftdiv: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = b.quotient (a); - else - return tree_constant (); break; case tree::leftdiv: return xleftdiv (a, b); @@ -1492,76 +1537,61 @@ break; case tree::power: error ("can't do A ^ B for A and B both matrices"); - return tree_constant (); break; case tree::elem_pow: if (m_add_conform (a, b, 1)) return elem_xpow (a, b); - else - return tree_constant (); break; case tree::cmp_lt: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_LT, a, b); - else - return tree_constant (); break; case tree::cmp_le: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_LE, a, b); - else - return tree_constant (); break; case tree::cmp_eq: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_EQ, a, b); - else - return tree_constant (); break; case tree::cmp_ge: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_GE, a, b); - else - return tree_constant (); break; case tree::cmp_gt: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_GT, a, b); - else - return tree_constant (); break; case tree::cmp_ne: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_NE, a, b); - else - return tree_constant (); break; case tree::and: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_AND, a, b); - else - return tree_constant (); break; case tree::or: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_OR, a, b); - else - return tree_constant (); break; default: panic_impossible (); break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else @@ -1577,6 +1607,7 @@ double result = 0.0; Complex complex_result; + switch (t) { case tree::add: @@ -1647,7 +1678,11 @@ break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else @@ -1663,6 +1698,7 @@ Matrix result; ComplexMatrix complex_result; + switch (t) { case tree::add: @@ -1688,8 +1724,7 @@ return x_el_div (a, b); break; case tree::divide: - error ("nonconformant right division"); - return tree_constant (); + gripe_nonconformant (1, 1, b.rows (), b.columns ()); break; case tree::power: return xpow (a, b); @@ -1734,7 +1769,11 @@ break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else @@ -1750,6 +1789,7 @@ double result = 0.0; Complex complex_result; + switch (t) { case tree::add: @@ -1820,7 +1860,11 @@ break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else @@ -1836,6 +1880,7 @@ Matrix result; ComplexMatrix complex_result; + switch (t) { case tree::add: @@ -1861,8 +1906,7 @@ return x_el_div (a, b); break; case tree::divide: - error ("nonconformant right division"); - return tree_constant (); + gripe_nonconformant (1, 1, b.rows (), b.columns ()); break; case tree::power: return xpow (a, b); @@ -1907,7 +1951,11 @@ break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else @@ -1923,6 +1971,7 @@ Matrix result; ComplexMatrix complex_result; + switch (t) { case tree::add: @@ -1947,8 +1996,7 @@ return x_el_div (b, a); break; case tree::leftdiv: - error ("nonconformant left division"); - return tree_constant (); + gripe_nonconformant (a.rows (), a.columns (), 1, 1); break; case tree::power: return xpow (a, b); @@ -1993,7 +2041,11 @@ break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else @@ -2009,49 +2061,38 @@ Matrix result; ComplexMatrix complex_result; + switch (t) { case tree::add: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a + b; - else - return tree_constant (); break; case tree::subtract: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a - b; - else - return tree_constant (); break; case tree::el_mul: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a.product (b); - else - return tree_constant (); break; case tree::multiply: result_type = RT_complex; if (m_mul_conform (a, b, 1)) complex_result = a * b; - else - return tree_constant (); break; case tree::el_div: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a.quotient (b); - else - return tree_constant (); break; case tree::el_leftdiv: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a.quotient (b); - else - return tree_constant (); break; case tree::leftdiv: return xleftdiv (a, b); @@ -2061,76 +2102,61 @@ break; case tree::power: error ("can't do A ^ B for A and B both matrices"); - return tree_constant (); break; case tree::elem_pow: if (m_add_conform (a, b, 1)) return elem_xpow (a, b); - else - return tree_constant (); break; case tree::cmp_lt: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_LT, a, b); - else - return tree_constant (); break; case tree::cmp_le: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_LE, a, b); - else - return tree_constant (); break; case tree::cmp_eq: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_EQ, a, b); - else - return tree_constant (); break; case tree::cmp_ge: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_GE, a, b); - else - return tree_constant (); break; case tree::cmp_gt: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_GT, a, b); - else - return tree_constant (); break; case tree::cmp_ne: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_NE, a, b); - else - return tree_constant (); break; case tree::and: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_AND, a, b); - else - return tree_constant (); break; case tree::or: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_OR, a, b); - else - return tree_constant (); break; default: panic_impossible (); break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else @@ -2146,6 +2172,7 @@ Matrix result; ComplexMatrix complex_result; + switch (t) { case tree::add: @@ -2170,8 +2197,7 @@ return x_el_div (b, a); break; case tree::leftdiv: - error ("nonconformant left division"); - return tree_constant (); + gripe_nonconformant (a.rows (), a.columns (), 1, 1); break; case tree::power: return xpow (a, b); @@ -2216,7 +2242,11 @@ break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else @@ -2232,49 +2262,38 @@ Matrix result; ComplexMatrix complex_result; + switch (t) { case tree::add: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a + b; - else - return tree_constant (); break; case tree::subtract: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a - b; - else - return tree_constant (); break; case tree::el_mul: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a.product (b); - else - return tree_constant (); break; case tree::multiply: result_type = RT_complex; if (m_mul_conform (a, b, 1)) complex_result = a * b; - else - return tree_constant (); break; case tree::el_div: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = a.quotient (b); - else - return tree_constant (); break; case tree::el_leftdiv: result_type = RT_complex; if (m_add_conform (a, b, 1)) complex_result = b.quotient (a); - else - return tree_constant (); break; case tree::leftdiv: return xleftdiv (a, b); @@ -2284,76 +2303,61 @@ break; case tree::power: error ("can't do A ^ B for A and B both matrices"); - return tree_constant (); break; case tree::elem_pow: if (m_add_conform (a, b, 1)) return elem_xpow (a, b); - else - return tree_constant (); break; case tree::cmp_lt: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_LT, a, b); - else - return tree_constant (); break; case tree::cmp_le: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_LE, a, b); - else - return tree_constant (); break; case tree::cmp_eq: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_EQ, a, b); - else - return tree_constant (); break; case tree::cmp_ge: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_GE, a, b); - else - return tree_constant (); break; case tree::cmp_gt: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_GT, a, b); - else - return tree_constant (); break; case tree::cmp_ne: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_NE, a, b); - else - return tree_constant (); break; case tree::and: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_AND, a, b); - else - return tree_constant (); break; case tree::or: result_type = RT_real; if (m_add_conform (a, b, 1)) result = mx_stupid_bool_op (Matrix_OR, a, b); - else - return tree_constant (); break; default: panic_impossible (); break; } + if (error_state) + return tree_constant (); + assert (result_type != RT_unknown); + if (result_type == RT_real) return tree_constant (result); else diff --git a/src/error.cc b/src/error.cc --- a/src/error.cc +++ b/src/error.cc @@ -31,6 +31,9 @@ #include "error.h" +// Current error state. +int error_state; + static void verror (const char *name, const char *fmt, va_list args) { @@ -72,6 +75,9 @@ void error (const char *fmt, ...) { + if (! error_state) + error_state = 1; + va_list args; va_start (args, fmt); verror ("error", fmt, args); diff --git a/src/error.h b/src/error.h --- a/src/error.h +++ b/src/error.h @@ -38,6 +38,9 @@ extern void error (const char *fmt, ...); extern void volatile panic (const char *fmt, ...); +// Current error state. +extern int error_state; + #endif /* diff --git a/src/gripes.cc b/src/gripes.cc --- a/src/gripes.cc +++ b/src/gripes.cc @@ -47,6 +47,13 @@ } void +gripe_nonconformant (int r1, int c1, int r2, int c2) +{ + error ("nonconformant matrices (op1 is %dx%d, op2 is %dx%d)", + r1, c1, r2, c2); +} + +void gripe_empty_arg (const char *name, int is_error) { if (is_error) diff --git a/src/gripes.h b/src/gripes.h --- a/src/gripes.h +++ b/src/gripes.h @@ -31,6 +31,7 @@ extern void gripe_string_invalid (void); extern void gripe_range_invalid (void); extern void gripe_nonconformant (void); +extern void gripe_nonconformant (int r1, int c1, int r2, int c2); extern void gripe_empty_arg (const char *name, int is_error); extern void gripe_square_matrix_required (const char *name); extern void gripe_user_supplied_eval (const char *name); diff --git a/src/lex.h b/src/lex.h --- a/src/lex.h +++ b/src/lex.h @@ -24,6 +24,54 @@ #if !defined (_lex_h) #define _lex_h 1 +// Arrange to get input via readline. + +#ifdef YY_INPUT +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ((result = octave_read (buf, max_size)) < 0) \ + YY_FATAL_ERROR ("octave_read () in flex scanner failed"); +#endif + +// Try to avoid crashing out completely on fatal scanner errors. + +#ifdef YY_FATAL_ERROR +#undef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) \ + do \ + { \ + error (msg); \ + jump_to_top_level (); \ + } \ + while (0) +#endif + +#define DO_COMMA_INSERT_CHECK yyless (do_comma_insert_check ()) + +#define TOK_RETURN(tok) \ + do \ + { \ + current_input_column += yyleng; \ + quote_is_transpose = 0; \ + cant_be_identifier = 0; \ + convert_spaces_to_comma = 1; \ + return (tok); \ + } \ + while (0) + +#define BIN_OP_RETURN(tok,convert) \ + do \ + { \ + yylval.tok_val = new token (input_line_number, current_input_column); \ + token_stack.push (yylval.tok_val); \ + current_input_column += yyleng; \ + quote_is_transpose = 0; \ + cant_be_identifier = 0; \ + convert_spaces_to_comma = convert; \ + return (tok); \ + } \ + while (0) + typedef struct yy_buffer_state *YY_BUFFER_STATE; // Associate a buffer with a new file to read. diff --git a/src/lex.l b/src/lex.l --- a/src/lex.l +++ b/src/lex.l @@ -30,52 +30,19 @@ %{ -// Arrange to get input via readline. - -#ifdef YY_INPUT -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ((result = octave_read (buf, max_size)) < 0) \ - YY_FATAL_ERROR ("octave_read () in flex scanner failed"); -#endif - -// Try to avoid crashing out completely on fatal scanner errors. - -#ifdef YY_FATAL_ERROR -#undef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) \ - do \ - { \ - error (msg); \ - jump_to_top_level (); \ - } \ - while (0) -#endif - #include "input.h" - -// The type of an END token. This declaration is repeated in parse.y. -// It must appear before y.tab.h is included. -enum end_tok_type - { - simple_end, - for_end, - function_end, - if_end, - while_end, - }; - -// The type of a PLOT token. This declaration is repeated in parse.y. -// It must appear before y.tab.h is included. -enum plot_tok_type - { - two_dee = 2, - three_dee = 3, - }; +#include "token.h" #include "SLStack.h" +// Stack to hold tokens so that we can delete them when the parser is +// reset and avoid growing forever just because we are stashing some +// information. This has to appear before lex.h is included, because +// one of the macros defined there uses token_stack. +static SLStack token_stack; + #include "variables.h" +#include "octave.h" #include "symtab.h" #include "error.h" #include "utils.h" @@ -128,30 +95,6 @@ static int next_token_is_postfix_unary_op (int spc_prev, char *yytext); static char *strip_trailing_whitespace (char *s); -#define DO_COMMA_INSERT_CHECK yyless (do_comma_insert_check ()) - -#define RETURN(token) \ - do \ - { \ - current_input_column += yyleng; \ - quote_is_transpose = 0; \ - cant_be_identifier = 0; \ - convert_spaces_to_comma = 1; \ - return (token); \ - } \ - while (0) - -#define BIN_OP_RETURN(token) \ - do \ - { \ - current_input_column += yyleng; \ - quote_is_transpose = 0; \ - cant_be_identifier = 0; \ - convert_spaces_to_comma = 0; \ - return (token); \ - } \ - while (0) - %} D [0-9] @@ -182,14 +125,14 @@ \n { BEGIN 0; - current_input_column = 0; + current_input_column = 1; quote_is_transpose = 0; cant_be_identifier = 0; convert_spaces_to_comma = 1; return '\n'; } -<> { RETURN (END_OF_INPUT); } +<> { TOK_RETURN (END_OF_INPUT); } .*$ { current_input_column += yyleng; } @@ -206,7 +149,7 @@ \n | \n { BEGIN 0; - current_input_column = 0; + current_input_column = 1; quote_is_transpose = 0; cant_be_identifier = 0; convert_spaces_to_comma = 1; @@ -216,43 +159,47 @@ [\;\,] { if (doing_set) { - yylval.string = strsave (yytext); - RETURN (TEXT); + yylval.tok_val = new token (yytext); + token_stack.push (yylval.tok_val); + TOK_RETURN (TEXT); } else { BEGIN 0; - RETURN (','); + TOK_RETURN (','); } } [^ \t\n]*{S}* | [^ \t\n\;\,]*{S}* { - - static char *tok = (char *) NULL; - delete [] tok; - tok = strip_trailing_whitespace (yytext); - - yylval.string = strsave (tok); - RETURN (TEXT); - } + static char *tok = (char *) NULL; + delete [] tok; + tok = strip_trailing_whitespace (yytext); + yylval.tok_val = new token (tok); + token_stack.push (yylval.tok_val); + TOK_RETURN (TEXT); + } \'{QSTR}*[\n\'] { if (yytext[yyleng-1] == '\n') { error ("unterminated string constant"); - current_input_column = 0; + current_input_column = 1; jump_to_top_level (); } else { + static char *tok = (char *) NULL; + delete [] tok; int off1 = doing_set ? 0 : 1; int off2 = doing_set ? 0 : 2; - yylval.string = strsave (&yytext[off1]); - yylval.string[yyleng-off2] = '\0'; + tok = strsave (&yytext[off1]); + tok[yyleng-off2] = '\0'; + do_string_escapes (tok); + yylval.tok_val = new token (tok); + token_stack.push (yylval.tok_val); current_input_column += yyleng; } - do_string_escapes (yylval.string); return TEXT; } @@ -260,18 +207,22 @@ if (yytext[yyleng-1] == '\n') { error ("unterminated string constant"); - current_input_column = 0; + current_input_column = 1; jump_to_top_level (); } else { + static char *tok = (char *) NULL; + delete [] tok; int off1 = doing_set ? 0 : 1; int off2 = doing_set ? 0 : 2; - yylval.string = strsave (&yytext[off1]); - yylval.string[yyleng-off2] = '\0'; + tok = strsave (&yytext[off1]); + tok[yyleng-off2] = '\0'; + do_string_escapes (tok); + yylval.tok_val = new token (tok); + token_stack.push (yylval.tok_val); current_input_column += yyleng; } - do_string_escapes (yylval.string); return TEXT; } @@ -286,19 +237,23 @@ if (yytext[yyleng-1] == '\n') { error ("unterminated string constant"); - current_input_column = 0; + current_input_column = 1; jump_to_top_level (); } else { - yylval.string = strsave (yytext); - yylval.string[yyleng-1] = '\0'; + static char *tok = (char *) NULL; + delete [] tok; + tok = strsave (yytext); + tok[yyleng-1] = '\0'; + do_string_escapes (tok); + yylval.tok_val = new token (tok); + token_stack.push (yylval.tok_val); + quote_is_transpose = 1; + cant_be_identifier = 1; + convert_spaces_to_comma = 1; current_input_column += yyleng; } - do_string_escapes (yylval.string); - quote_is_transpose = 1; - cant_be_identifier = 1; - convert_spaces_to_comma = 1; return TEXT; } @@ -312,19 +267,23 @@ if (yytext[yyleng-1] == '\n') { error ("unterminated string constant"); - current_input_column = 0; + current_input_column = 1; jump_to_top_level (); } else { - yylval.string = strsave (yytext); - yylval.string[yyleng-1] = '\0'; + static char *tok = (char *) NULL; + delete [] tok; + tok = strsave (yytext); + tok[yyleng-1] = '\0'; + do_string_escapes (tok); + yylval.tok_val = new token (tok); + token_stack.push (yylval.tok_val); + quote_is_transpose = 1; + cant_be_identifier = 1; + convert_spaces_to_comma = 1; current_input_column += yyleng; } - do_string_escapes (yylval.string); - quote_is_transpose = 1; - cant_be_identifier = 1; - convert_spaces_to_comma = 1; return TEXT; } @@ -347,7 +306,7 @@ braceflag--; if (braceflag == 0) { - if (!defining_func) + if (! defining_func) promptflag++; BEGIN 0; } @@ -364,7 +323,7 @@ if (braceflag == 0) { BEGIN 0; - if (!defining_func) + if (! defining_func) promptflag++; } fixup_column_count (yytext); @@ -384,7 +343,7 @@ braceflag--; if (braceflag == 0) { - if (!defining_func) + if (! defining_func) promptflag++; BEGIN 0; } @@ -417,7 +376,7 @@ return ']'; } -{S}*\,{S}* { RETURN (','); } +{S}*\,{S}* { TOK_RETURN (','); } {S}+ { int bin_op = next_token_is_bin_op (1, yytext); @@ -427,7 +386,7 @@ if (! (postfix_un_op || bin_op) && in_brace_or_paren.top () && convert_spaces_to_comma) - RETURN (','); + TOK_RETURN (','); } {SN}*\;{SN}* | @@ -446,22 +405,27 @@ if (plotting && ! past_plot_range) { in_plot_range = 0; - RETURN (CLOSE_BRACE); + TOK_RETURN (CLOSE_BRACE); } else - RETURN (']'); + TOK_RETURN (']'); } {D}+{EXPON}?{Im} | {D}+\.{D}*{EXPON}?{Im} | \.{D}+{EXPON}?{Im} { - int nread = sscanf (yytext, "%lf", &(yylval.number)); + double value; + int nread = sscanf (yytext, "%lf", &value); assert (nread == 1); quote_is_transpose = 1; cant_be_identifier = 1; convert_spaces_to_comma = 1; if (plotting && ! in_plot_range) past_plot_range = 1; + yylval.tok_val = new token (value, + input_line_number, + current_input_column); + token_stack.push (yylval.tok_val); current_input_column += yyleng; DO_COMMA_INSERT_CHECK; return IMAG_NUM; @@ -471,13 +435,18 @@ {D}+\.{D}*{EXPON}? | \.{D}+{EXPON}? | { - int nread = sscanf (yytext, "%lf", &(yylval.number)); + double value; + int nread = sscanf (yytext, "%lf", &value); assert (nread == 1); quote_is_transpose = 1; cant_be_identifier = 1; convert_spaces_to_comma = 1; if (plotting && ! in_plot_range) past_plot_range = 1; + yylval.tok_val = new token (value, + input_line_number, + current_input_column); + token_stack.push (yylval.tok_val); current_input_column += yyleng; DO_COMMA_INSERT_CHECK; return NUM; @@ -488,7 +457,7 @@ if (plotting && ! past_plot_range) { in_plot_range = 1; - RETURN (OPEN_BRACE); + TOK_RETURN (OPEN_BRACE); } if (do_comma_insert) @@ -506,7 +475,7 @@ braceflag++; promptflag--; BEGIN NEW_MATRIX; - RETURN ('['); + TOK_RETURN ('['); } } @@ -517,10 +486,10 @@ // Line continuation. promptflag--; - current_input_column = 0; + current_input_column = 1; } -<> RETURN (END_OF_INPUT); +<> TOK_RETURN (END_OF_INPUT); {IDENT}{S}* { @@ -533,7 +502,7 @@ int kw_token = is_keyword (tok); if (kw_token) - RETURN (kw_token); + TOK_RETURN (kw_token); if (plotting && cant_be_identifier) { @@ -556,11 +525,12 @@ char *sty = plot_style_token (&tok[1]); if (sty != (char *) NULL) { - yylval.string = strsave (sty); + yylval.tok_val = new token (sty); + token_stack.push (yylval.tok_val); if (in_plot_style) { in_plot_style = 0; - RETURN (STYLE); + TOK_RETURN (STYLE); } } } @@ -577,14 +547,25 @@ BEGIN TEXT_FCN; if (strcmp (tok, "clear") == 0) - return CLEAR; + { + symbol_record *sr = + global_sym_tab->lookup ("clear", 1, 0); + assert (sr != (symbol_record *) NULL); + yylval.tok_val = new token (sr, input_line_number, + current_input_column); + token_stack.push (yylval.tok_val); + return CLEAR; + } else if (strcmp (tok, "help") == 0) BEGIN HELP_FCN; else if (strcmp (tok, "set") == 0) doing_set = 1; } - yylval.sym_rec = lookup_identifier (tok); + yylval.tok_val = new token (lookup_identifier (tok), + input_line_number, + current_input_column); + token_stack.push (yylval.tok_val); quote_is_transpose = 1; current_input_column += yyleng; @@ -631,7 +612,7 @@ int kw_token = is_keyword (yytext); if (kw_token) - RETURN (kw_token); + TOK_RETURN (kw_token); if (plotting && cant_be_identifier) { @@ -657,7 +638,15 @@ BEGIN TEXT_FCN; if (strcmp (yytext, "clear") == 0) - return CLEAR; + { + symbol_record *sr = + global_sym_tab->lookup ("clear", 1, 0); + assert (sr != (symbol_record *) NULL); + yylval.tok_val = new token (sr, input_line_number, + current_input_column); + token_stack.push (yylval.tok_val); + return CLEAR; + } else if (strcmp (yytext, "help") == 0) BEGIN HELP_FCN; else if (strcmp (yytext, "set") == 0) @@ -667,7 +656,10 @@ if (defining_func && maybe_screwed) curr_sym_tab = tmp_local_sym_tab; - yylval.sym_rec = lookup_identifier (yytext); + yylval.tok_val = new token (lookup_identifier (yytext), + input_line_number, + current_input_column); + token_stack.push (yylval.tok_val); convert_spaces_to_comma = 1; current_input_column += yyleng; @@ -686,7 +678,7 @@ "\n" { quote_is_transpose = 0; cant_be_identifier = 0; - current_input_column = 0; + current_input_column = 1; convert_spaces_to_comma = 1; return '\n'; } @@ -706,65 +698,65 @@ ":" { if (plotting && (in_plot_range || in_plot_using)) - RETURN (COLON); + BIN_OP_RETURN (COLON, 1); else - BIN_OP_RETURN (':'); + BIN_OP_RETURN (':', 0); } \" { BEGIN DQSTRING; } -".**" { BIN_OP_RETURN (EPOW); } -".*" { BIN_OP_RETURN (EMUL); } -"./" { BIN_OP_RETURN (EDIV); } -".\\" { BIN_OP_RETURN (ELEFTDIV); } -".^" { BIN_OP_RETURN (EPOW); } -".'" { DO_COMMA_INSERT_CHECK; RETURN (TRANSPOSE); } -"++" { DO_COMMA_INSERT_CHECK; RETURN (PLUS_PLUS); } -"--" { DO_COMMA_INSERT_CHECK; RETURN (MINUS_MINUS); } -"<=" { BIN_OP_RETURN (EXPR_LE); } -"==" { BIN_OP_RETURN (EXPR_EQ); } -"~=" { BIN_OP_RETURN (EXPR_NE); } -"!=" { BIN_OP_RETURN (EXPR_NE); } -"<>" { BIN_OP_RETURN (EXPR_NE); } -">=" { BIN_OP_RETURN (EXPR_GE); } -"||" { BIN_OP_RETURN (EXPR_OR); } -"&&" { BIN_OP_RETURN (EXPR_AND); } -"|" { BIN_OP_RETURN (EXPR_OR); } -"&" { BIN_OP_RETURN (EXPR_AND); } +".**" { BIN_OP_RETURN (EPOW, 0); } +".*" { BIN_OP_RETURN (EMUL, 0); } +"./" { BIN_OP_RETURN (EDIV, 0); } +".\\" { BIN_OP_RETURN (ELEFTDIV, 0); } +".^" { BIN_OP_RETURN (EPOW, 0); } +".'" { DO_COMMA_INSERT_CHECK; BIN_OP_RETURN (TRANSPOSE, 1); } +"++" { DO_COMMA_INSERT_CHECK; BIN_OP_RETURN (PLUS_PLUS, 1); } +"--" { DO_COMMA_INSERT_CHECK; BIN_OP_RETURN (MINUS_MINUS, 1); } +"<=" { BIN_OP_RETURN (EXPR_LE, 0); } +"==" { BIN_OP_RETURN (EXPR_EQ, 0); } +"~=" { BIN_OP_RETURN (EXPR_NE, 0); } +"!=" { BIN_OP_RETURN (EXPR_NE, 0); } +"<>" { BIN_OP_RETURN (EXPR_NE, 0); } +">=" { BIN_OP_RETURN (EXPR_GE, 0); } +"||" { BIN_OP_RETURN (EXPR_OR, 0); } +"&&" { BIN_OP_RETURN (EXPR_AND, 0); } +"|" { BIN_OP_RETURN (EXPR_OR, 0); } +"&" { BIN_OP_RETURN (EXPR_AND, 0); } "!" { if (plotting && ! in_plot_range) past_plot_range = 1; - RETURN (EXPR_NOT); + BIN_OP_RETURN (EXPR_NOT, 1); } "~" { if (plotting && ! in_plot_range) past_plot_range = 1; - BIN_OP_RETURN (EXPR_NOT); + BIN_OP_RETURN (EXPR_NOT, 0); } -"<" { BIN_OP_RETURN (EXPR_LT); } -">" { BIN_OP_RETURN (EXPR_GT); } +"<" { BIN_OP_RETURN (EXPR_LT, 0); } +">" { BIN_OP_RETURN (EXPR_GT, 0); } "+" { if (plotting && ! in_plot_range) past_plot_range = 1; - BIN_OP_RETURN ('+'); + BIN_OP_RETURN ('+', 0); } "-" { if (plotting && ! in_plot_range) past_plot_range = 1; - BIN_OP_RETURN ('-'); + BIN_OP_RETURN ('-', 0); } -"**" { BIN_OP_RETURN (POW); } -"*" { BIN_OP_RETURN ('*'); } -"/" { BIN_OP_RETURN ('/'); } -"\\" { BIN_OP_RETURN (LEFTDIV); } -";" { RETURN (';'); } -"," { RETURN (','); } -"^" { BIN_OP_RETURN (POW); } -"=" { RETURN ('='); } +"**" { BIN_OP_RETURN (POW, 0); } +"*" { BIN_OP_RETURN ('*', 0); } +"/" { BIN_OP_RETURN ('/', 0); } +"\\" { BIN_OP_RETURN (LEFTDIV, 0); } +";" { BIN_OP_RETURN (';', 1); } +"," { BIN_OP_RETURN (',', 1); } +"^" { BIN_OP_RETURN (POW, 0); } +"=" { BIN_OP_RETURN ('=', 1); } "(" { if (plotting && ! in_plot_range) past_plot_range = 1; in_brace_or_paren.push (0); - RETURN ('('); + TOK_RETURN ('('); } ")" { if (! in_brace_or_paren.empty ()) @@ -780,7 +772,7 @@ // We return everything else as single character tokens, which should // eventually result in a parse error. - RETURN (yytext[0]); + TOK_RETURN (yytext[0]); } %% @@ -801,7 +793,8 @@ } /* - * Fix things up for errors or interrupts. + * Fix things up for errors or interrupts. This could use a few + * comments now, eh? */ void reset_parser (void) @@ -820,7 +813,9 @@ curr_sym_tab = top_level_sym_tab; get_input_from_eval_string = 0; quote_is_transpose = 0; - current_input_column = 0; + current_input_column = 1; +// Might have been reset by defining a function. + input_line_number = current_command_number - 1; do_comma_insert = 0; plotting = 0; past_plot_range = 0; @@ -831,6 +826,8 @@ convert_spaces_to_comma = 1; beginning_of_function = 0; in_brace_or_paren.clear (); + while (! token_stack.empty ()) + delete token_stack.pop (); yyrestart (stdin); } @@ -906,7 +903,7 @@ while ((c = *s++) != '\0') { if (c == '\n') - current_input_column = 0; + current_input_column = 1; else current_input_column++; } @@ -1027,32 +1024,68 @@ if (sty != (char *) NULL) { in_plot_style = 0; - yylval.string = strsave (sty); + yylval.tok_val = new token (sty); + token_stack.push (yylval.tok_val); return STYLE; } } + int l = input_line_number; + int c = current_input_column; + int end_found = 0; if (strcmp ("break", s) == 0) - return BREAK; + { + return BREAK; + } else if (strcmp ("continue", s) == 0) - return CONTINUE; + { + return CONTINUE; + } else if (strcmp ("else", s) == 0) - { return ELSE; } + { + return ELSE; + } else if (strcmp ("elseif", s) == 0) - { return ELSEIF; } + { + return ELSEIF; + } else if (strcmp ("end", s) == 0) - { end_found = 1; yylval.ettype = simple_end; } + { + end_found = 1; + yylval.tok_val = new token (token::simple_end, l, c); + token_stack.push (yylval.tok_val); + } else if (strcmp ("endfor", s) == 0) - { end_found = 1; yylval.ettype = for_end; } + { + end_found = 1; + yylval.tok_val = new token (token::for_end, l, c); + token_stack.push (yylval.tok_val); + } else if (strcmp ("endfunction", s) == 0) - { end_found = 1; yylval.ettype = function_end; } + { + end_found = 1; + yylval.tok_val = new token (token::function_end, l, c); + token_stack.push (yylval.tok_val); + } else if (strcmp ("endif", s) == 0) - { end_found = 1; yylval.ettype = if_end; } + { + end_found = 1; + yylval.tok_val = new token (token::if_end, l, c); + token_stack.push (yylval.tok_val); + } else if (strcmp ("endwhile", s) == 0) - { end_found = 1; yylval.ettype = while_end; } + { + end_found = 1; + yylval.tok_val = new token (token::while_end, l, c); + token_stack.push (yylval.tok_val); + } else if (strcmp ("for", s) == 0) - { promptflag--; looping++; return FOR; } + { + promptflag--; + looping++; + return FOR; + } else if (strcmp ("function", s) == 0) { if (defining_func) @@ -1068,25 +1101,47 @@ promptflag--; beginning_of_function = 1; help_buf[0] = '\0'; + input_line_number = 1; return FCN; } } else if (strcmp ("global", s) == 0) - return GLOBAL; + { + return GLOBAL; + } else if (strcmp ("gplot", s) == 0) - { plotting = 1; yylval.pttype = two_dee; return PLOT; } + { + plotting = 1; + yylval.tok_val = new token (token::two_dee, l, c); + return PLOT; + } else if (strcmp ("gsplot", s) == 0) - { plotting = 1; yylval.pttype = three_dee; return PLOT; } + { + plotting = 1; + yylval.tok_val = new token (token::three_dee, l, c); + token_stack.push (yylval.tok_val); + return PLOT; + } else if (strcmp ("if", s) == 0) - { iffing++; promptflag--; return IF; } + { + iffing++; + promptflag--; + return IF; + } else if (strcmp ("return", s) == 0) - return FUNC_RET; + { + return FUNC_RET; + } else if (strcmp ("while", s) == 0) - { promptflag--; looping++; return WHILE; } + { + promptflag--; + looping++; + return WHILE; + } if (end_found) { - if (!defining_func && !looping) + if (! defining_func && ! looping) promptflag++; return END; } diff --git a/src/octave.cc b/src/octave.cc --- a/src/octave.cc +++ b/src/octave.cc @@ -229,7 +229,7 @@ unwind_protect_int (echo_input); input_line_number = 0; - current_input_column = 0; + current_input_column = 1; echo_input = 0; parse_and_execute (f, print); @@ -479,6 +479,7 @@ retval = yyparse (); if (retval == 0 && global_command != NULL_TREE) { + error_state = 0; global_command->eval (1); delete global_command; current_command_number++; diff --git a/src/parse.y b/src/parse.y --- a/src/parse.y +++ b/src/parse.y @@ -1,4 +1,4 @@ -/* parse.y -*- text -*- +/* parse.y -*- text -*- Copyright (C) 1992, 1993 John W. Eaton @@ -43,6 +43,7 @@ #include "octave.h" #include "parse.h" #include "lex.h" +#include "token.h" // Identifier to define if we are reading an M-fie. tree_identifier *id_to_define; @@ -79,7 +80,7 @@ int input_line_number = 0; // The column of the current token. -int current_input_column = 0; +int current_input_column = 1; // Buffer for help text snagged from M-files. // Probably shouldn't be a fixed size... @@ -101,25 +102,11 @@ // Nonzero means we're looking at the style part of a plot command. int in_plot_style = 0; -// The type of an END token. This declaration is repeated in lex.l. -enum end_tok_type - { - simple_end, - for_end, - function_end, - if_end, - while_end, - }; - -// The type of a PLOT token. This declaration is repeated in lex.l. -enum plot_tok_type - { - two_dee = 2, - three_dee = 3, - }; +// Check to see that end statements are properly matched. +static int check_end (token *tok, token::end_tok_type expected); // Error mesages for mismatched end statements. -static void end_error (char *type, end_tok_type ettype); +static void end_error (char *type, token::end_tok_type ettype, int l, int c); // Generic error messages. static void yyerror (char *s); @@ -147,6 +134,10 @@ */ %union { +// The type of the basic tokens returned by the lexer. + token *tok_val; + +// Types for the nonterminals we generate. tree *tree_type; tree_constant *tree_constant_type; tree_matrix *tree_matrix_type; @@ -167,91 +158,49 @@ tree_plot_range *tree_plot_range_type; tree_subplot_using *tree_subplot_using_type; tree_subplot_style *tree_subplot_style_type; - symbol_record *sym_rec; - double number; - char *string; - end_tok_type ettype; - plot_tok_type pttype; } -/* - * There are 20 shift/reduce conflicts, ok? - */ -%expect 20 +// Tokens with line and column information. +%token '=' ':' '-' '+' '*' '/' +%token EXPR_AND EXPR_OR EXPR_NOT +%token EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT +%token LEFTDIV EMUL EDIV ELEFTDIV QUOTE TRANSPOSE +%token PLUS_PLUS MINUS_MINUS POW EPOW +%token NUM IMAG_NUM +%token NAME SCREW CLEAR +%token END +%token PLOT +%token TEXT STYLE -/* - * Reserved words. - */ +// Other tokens. %token FOR WHILE IF ELSEIF ELSE FCN BREAK CONTINUE FUNC_RET SCREW_TWO -%token END_OF_INPUT GLOBAL CLEAR - +%token END_OF_INPUT GLOBAL %token USING TITLE WITH COLON OPEN_BRACE CLOSE_BRACE -// tree +// Nonterminals we construct. %type input command %type ans_expression expression simple_expr simple_expr1 %type title - -// tree_matrix %type matrix - -// tree_identifier %type identifier - -// tree_function %type func_def func_def1 func_def2 func_def3 - -// tree_index_expression %type variable - -// tree_colon_expression %type colon_expr - -// tree_argument_list %type arg_list arg_list1 - -// tree_parameter_list %type param_list param_list1 func_def1a - -// tree_word_list %type word_list word_list1 - -// tree_command %type statement - -// tree_if_command %type elseif - -// tree_command_list %type simple_list simple_list1 list list1 opt_list - -// tree_word_list_command %type word_list_cmd - -// tree_plot_command %type plot_command - -// tree_subplot_list %type plot_command1 plot_command2 plot_options - -// tree_plot_limits %type ranges - -// tree_plot_range %type ranges1 - -// tree_subplot_using %type using using1 - -// tree_subplot_style %type style -%token NUM IMAG_NUM -%token NAME SCREW -%token TEXT STYLE -%token END -%token PLOT - +// Precedence and associativity. %left ';' ',' '\n' %right '=' %left EXPR_AND EXPR_OR @@ -263,6 +212,10 @@ %left UNARY PLUS_PLUS MINUS_MINUS EXPR_NOT %right POW EPOW +// There are 20 shift/reduce conflicts, ok? +%expect 20 + +// Where to start. %start input /* @@ -397,7 +350,7 @@ plot_command : PLOT plot_command1 { tree_subplot_list *tmp = $2->reverse (); - $$ = new tree_plot_command (tmp, $1); + $$ = new tree_plot_command (tmp, $1->pttype ()); plotting = 0; past_plot_range = 0; in_plot_range = 0; @@ -407,7 +360,7 @@ | PLOT ranges plot_command1 { tree_subplot_list *tmp = $3->reverse (); - $$ = new tree_plot_command (tmp, $2, $1); + $$ = new tree_plot_command (tmp, $2, $1->pttype ()); plotting = 0; past_plot_range = 0; in_plot_range = 0; @@ -506,11 +459,11 @@ ; style : WITH STYLE - { $$ = new tree_subplot_style ($2); } + { $$ = new tree_subplot_style ($2->string ()); } | WITH STYLE expression - { $$ = new tree_subplot_style ($2, $3); } + { $$ = new tree_subplot_style ($2->string (), $3); } | WITH STYLE expression bogus_syntax expression - { $$ = new tree_subplot_style ($2, $3, $5); } + { $$ = new tree_subplot_style ($2->string (), $3, $5); } ; bogus_syntax : // empty @@ -525,23 +478,27 @@ ; global_decl1 : NAME - { force_global ($1->name ()); } + { force_global ($1->sym_rec()->name ()); } | NAME '=' expression { - symbol_record *sr = force_global ($1->name ()); - tree_identifier *id = new tree_identifier (sr); + symbol_record *sr = force_global ($1->sym_rec()->name ()); + tree_identifier *id = new tree_identifier + (sr, $1->line (), $1->column ()); tree_simple_assignment_expression *expr = - new tree_simple_assignment_expression (id, $3); + new tree_simple_assignment_expression + (id, $3, $2->line () , $2->column ()); expr->eval (0); } | global_decl1 optcomma NAME - { force_global ($3->name ()); } + { force_global ($3->sym_rec()->name ()); } | global_decl1 optcomma NAME '=' expression { - symbol_record *sr = force_global ($3->name ()); - tree_identifier *id = new tree_identifier (sr); + symbol_record *sr = force_global ($3->sym_rec()->name ()); + tree_identifier *id = new tree_identifier + (sr, $3->line (), $3->column ()); tree_simple_assignment_expression *expr = - new tree_simple_assignment_expression (id, $5); + new tree_simple_assignment_expression + (id, $5, $4->line (), $4->column ()); expr->eval (0); } ; @@ -558,47 +515,31 @@ statement : WHILE expression optsep opt_list END { maybe_warn_assign_as_truth_value ($2); - if ($5 != while_end && $5 != simple_end) - { - yyerror ("parse error"); - end_error ("while", $5); - ABORT_PARSE; - } + if (check_end ($5, token::while_end)) + ABORT_PARSE; looping--; $$ = new tree_while_command ($2, $4); } | FOR variable '=' expression optsep opt_list END { - if ($7 != for_end && $7 != simple_end) - { - yyerror ("parse error"); - end_error ("for", $7); - ABORT_PARSE; - } + if (check_end ($7, token::for_end)) + ABORT_PARSE; looping--; $$ = new tree_for_command ($2, $4, $6); } | IF expression optsep opt_list END { maybe_warn_assign_as_truth_value ($2); - if ($5 != if_end && $5 != simple_end) - { - yyerror ("parse error"); - end_error ("if", $5); - ABORT_PARSE; - } + if (check_end ($5, token::if_end)) + ABORT_PARSE; iffing--; $$ = new tree_if_command ($2, $4); } | IF expression optsep opt_list ELSE optsep opt_list END { maybe_warn_assign_as_truth_value ($2); - if ($8 != if_end && $8 != simple_end) - { - yyerror ("parse error"); - end_error ("if", $8); - ABORT_PARSE; - } + if (check_end ($8, token::if_end)) + ABORT_PARSE; iffing--; tree_if_command *t1 = new tree_if_command ($7); $$ = t1->chain ($2, $4); @@ -606,12 +547,8 @@ | IF expression optsep opt_list elseif END { maybe_warn_assign_as_truth_value ($2); - if ($6 != if_end && $6 != simple_end) - { - yyerror ("parse error"); - end_error ("if", $6); - ABORT_PARSE; - } + if (check_end ($6, token::if_end)) + ABORT_PARSE; iffing--; tree_if_command *t1 = $5->reverse (); // Add the if list to the new head of the elseif @@ -621,12 +558,8 @@ | IF expression optsep opt_list elseif ELSE optsep opt_list END { maybe_warn_assign_as_truth_value ($2); - if ($9 != if_end && $9 != simple_end) - { - yyerror ("parse error"); - end_error ("if", $9); - ABORT_PARSE; - } + if (check_end ($9, token::if_end)) + ABORT_PARSE; iffing--; // Add the else list to the head of the elseif list, // then reverse the list. @@ -699,12 +632,13 @@ ; expression : variable '=' expression - { $$ = new tree_simple_assignment_expression ($1, $3); } + { $$ = new tree_simple_assignment_expression + ($1, $3, $2->line (), $2->column ()); } | '[' screwed_again matrix_row SCREW_TWO '=' expression { // Will need a way to convert the matrix list to a list of -// identifiers. If that fails, we can abort here, without losing +// identifiers. If that fails, we can abort here, without losing // anything -- no other possible syntax is valid if we've seen the // equals sign as the next token after the `]'. @@ -716,12 +650,13 @@ if (id_list == NULL_TREE) { yyerror ("parse error"); - error ("invalid identifier list for assignment"); + error ("invalid identifier list for assignment"); $$ = (tree_multi_assignment_expression *) NULL; ABORT_PARSE; } else - $$ = new tree_multi_assignment_expression (id_list, $6); + $$ = new tree_multi_assignment_expression + (id_list, $6, $5->line (), $5->column ()); } | NUM '=' expression { @@ -737,58 +672,79 @@ simple_expr : simple_expr1 { $$ = $1; } | identifier PLUS_PLUS - { $$ = new tree_postfix_expression ($1, tree::increment); } + { $$ = new tree_postfix_expression + ($1, tree::increment, $2->line (), $2->column ()); } | identifier MINUS_MINUS - { $$ = new tree_postfix_expression ($1, tree::decrement); } + { $$ = new tree_postfix_expression + ($1, tree::decrement, $2->line (), $2->column ()); } | simple_expr QUOTE - { $$ = new tree_unary_expression ($1, tree::hermitian); } + { $$ = new tree_unary_expression + ($1, tree::hermitian, $2->line (), $2->column ()); } | simple_expr TRANSPOSE - { $$ = new tree_unary_expression ($1, tree::transpose); } + { $$ = new tree_unary_expression + ($1, tree::transpose, $2->line (), $2->column ()); } | simple_expr POW simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::power); } + { $$ = new tree_binary_expression + ($1, $3, tree::power, $2->line (), $2->column ()); } | simple_expr EPOW simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::elem_pow); } + { $$ = new tree_binary_expression + ($1, $3, tree::elem_pow, $2->line (), $2->column ()); } | simple_expr '+' simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::add); } + { $$ = new tree_binary_expression + ($1, $3, tree::add, $2->line (), $2->column ()); } | simple_expr '-' simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::subtract); } + { $$ = new tree_binary_expression + ($1, $3, tree::subtract, $2->line (), $2->column ()); } | simple_expr '*' simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::multiply); } + { $$ = new tree_binary_expression + ($1, $3, tree::multiply, $2->line (), $2->column ()); } | simple_expr '/' simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::divide); } + { $$ = new tree_binary_expression + ($1, $3, tree::divide, $2->line (), $2->column ()); } | simple_expr EMUL simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::el_mul); } + { $$ = new tree_binary_expression + ($1, $3, tree::el_mul, $2->line (), $2->column ()); } | simple_expr EDIV simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::el_div); } + { $$ = new tree_binary_expression + ($1, $3, tree::el_div, $2->line (), $2->column ()); } | simple_expr LEFTDIV simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::leftdiv); } + { $$ = new tree_binary_expression + ($1, $3, tree::leftdiv, $2->line (), $2->column ()); } | simple_expr ELEFTDIV simple_expr - { $$ = new tree_binary_expression ($1, $3, - tree::el_leftdiv); } + { $$ = new tree_binary_expression + ($1, $3, tree::el_leftdiv, $2->line (), $2->column ()); } | simple_expr EXPR_LT simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::cmp_lt); } + { $$ = new tree_binary_expression + ($1, $3, tree::cmp_lt, $2->line (), $2->column ()); } | simple_expr EXPR_LE simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::cmp_le); } + { $$ = new tree_binary_expression + ($1, $3, tree::cmp_le, $2->line (), $2->column ()); } | simple_expr EXPR_EQ simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::cmp_eq); } + { $$ = new tree_binary_expression + ($1, $3, tree::cmp_eq, $2->line (), $2->column ()); } | simple_expr EXPR_GE simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::cmp_ge); } + { $$ = new tree_binary_expression + ($1, $3, tree::cmp_ge, $2->line (), $2->column ()); } | simple_expr EXPR_GT simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::cmp_gt); } + { $$ = new tree_binary_expression + ($1, $3, tree::cmp_gt, $2->line (), $2->column ()); } | simple_expr EXPR_NE simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::cmp_ne); } + { $$ = new tree_binary_expression + ($1, $3, tree::cmp_ne, $2->line (), $2->column ()); } | simple_expr EXPR_AND simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::and); } + { $$ = new tree_binary_expression + ($1, $3, tree::and, $2->line (), $2->column ()); } | simple_expr EXPR_OR simple_expr - { $$ = new tree_binary_expression ($1, $3, tree::or); } + { $$ = new tree_binary_expression + ($1, $3, tree::or, $2->line (), $2->column ()); } ; simple_expr1 : NUM - { $$ = new tree_constant ($1); } + { $$ = new tree_constant ($1->number ()); } | IMAG_NUM - { $$ = new tree_constant (Complex (0.0, $1)); } + { $$ = new tree_constant (Complex (0.0, $1->number ())); } | TEXT - { $$ = new tree_constant ($1); } + { $$ = new tree_constant ($1->string ()); } | word_list_cmd { $$ = $1; } | '(' expression ')' @@ -804,19 +760,24 @@ | colon_expr { $$ = $1; } | PLUS_PLUS identifier %prec UNARY - { $$ = new tree_prefix_expression ($2, tree::increment); } + { $$ = new tree_prefix_expression + ($2, tree::increment, $1->line (), $1->column ()); } | MINUS_MINUS identifier %prec UNARY - { $$ = new tree_prefix_expression ($2, tree::decrement); } + { $$ = new tree_prefix_expression + ($2, tree::decrement, $1->line (), $1->column ()); } | EXPR_NOT simple_expr - { $$ = new tree_unary_expression ($2, tree::not); } + { $$ = new tree_unary_expression + ($2, tree::not, $1->line (), $1->column ()); } | '+' simple_expr %prec UNARY { $$ = $2; } | '-' simple_expr %prec UNARY - { $$ = new tree_unary_expression ($2, tree::uminus); } + { $$ = new tree_unary_expression + ($2, tree::uminus, $1->line (), $1->column ()); } ; colon_expr : simple_expr ':' simple_expr - { $$ = new tree_colon_expression ($1, $3); } + { $$ = new tree_colon_expression + ($1, $3, $2->line (), $2->column ()); } | colon_expr ':' simple_expr { $$ = $1->chain ($3); @@ -838,9 +799,8 @@ error ("clear: invalid within function body"); ABORT_PARSE; } - symbol_record *sr = global_sym_tab->lookup ("clear", 1, 0); - assert (sr != (symbol_record *) NULL); - tree_identifier *tmp = new tree_identifier (sr); + tree_identifier *tmp = new tree_identifier + ($1->sym_rec (), $1->line (), $1->column ()); $$ = new tree_word_list_command (tmp, (tree_word_list *) NULL); } @@ -852,9 +812,8 @@ error ("clear: invalid within function body"); ABORT_PARSE; } - symbol_record *sr = global_sym_tab->lookup ("clear", 1, 0); - assert (sr != (symbol_record *) NULL); - tree_identifier *tmp = new tree_identifier (sr); + tree_identifier *tmp = new tree_identifier + ($1->sym_rec (), $1->line (), $1->column ()); $$ = new tree_word_list_command (tmp, $2); } ; @@ -864,9 +823,9 @@ ; word_list1 : TEXT - { $$ = new tree_word_list ($1); } + { $$ = new tree_word_list ($1->string ()); } | word_list1 TEXT - { $$ = $1->chain ($2); } + { $$ = $1->chain ($2->string ()); } ; // This is truly disgusting. @@ -903,7 +862,8 @@ func_def1 : SCREW safe g_symtab '=' func_def2 { - tree_identifier *tmp = new tree_identifier ($1); + tree_identifier *tmp = new tree_identifier + ($1->sym_rec (), $1->line (), $1->column ()); tree_parameter_list *tpl = new tree_parameter_list (tmp); tpl = tpl->reverse (); tpl->mark_as_formal_parameters (); @@ -958,6 +918,7 @@ top_level_sym_tab->clear (id_name); } + $4->stash_function_name (id_name); $$ = $4; } ; @@ -975,12 +936,8 @@ fcn_end_or_eof : END { - if ($1 != function_end && $1 != simple_end) - { - yyerror ("parse error"); - end_error ("function", $1); + if (check_end ($1, token::function_end)) ABORT_PARSE; - } if (reading_m_file) check_for_garbage_after_fcn_def (); @@ -1035,7 +992,8 @@ ; identifier : NAME - { $$ = new tree_identifier ($1); } + { $$ = new tree_identifier + ($1->sym_rec (), $1->line (), $1->column ()); } arg_list : arg_list1 { $$ = $1->reverse (); } @@ -1101,7 +1059,7 @@ { mlnm.pop (); mlnm.push (0); - tree_matrix *tmp = new tree_matrix ($1, tree::md_none); + tree_matrix *tmp = new tree_matrix ($1, tree::md_none); ml.push (tmp); } else @@ -1126,7 +1084,7 @@ yyerror (char *s) { char *line = current_input_line; - int err_col = current_input_column; + int err_col = current_input_column - 1; if (err_col == 0) err_col = strlen (current_input_line) + 1; @@ -1152,25 +1110,62 @@ fprintf (stderr, ":\n\n %s\n %*s\n\n", line, err_col, "^"); } +static int +check_end (token *tok, token::end_tok_type expected) +{ + token::end_tok_type ettype = tok->ettype (); + if (ettype != expected && ettype != token::simple_end) + { + yyerror ("parse error"); + + int l = tok->line (); + int c = tok->column (); + + switch (expected) + { + case token::for_end: + end_error ("for", ettype, l, c); + break; + case token::function_end: + end_error ("function", ettype, l, c); + break; + case token::if_end: + end_error ("if", ettype, l, c); + break; + case token::while_end: + end_error ("while", ettype, l, c); + break; + default: + panic_impossible (); + break; + } + return 1; + } + else + return 0; +} + static void -end_error (char *type, end_tok_type ettype) +end_error (char *type, token::end_tok_type ettype, int l, int c) { + static char *fmt = "%s command matched by `%s' near line %d column %d"; + switch (ettype) { - case simple_end: - error ("%s command matched by `end'", type); + case token::simple_end: + error (fmt, type, "end", l, c); break; - case for_end: - error ("%s command matched by `endfor'", type); + case token::for_end: + error (fmt, type, "endfor", l, c); break; - case function_end: - error ("%s command matched by `endfunction'", type); + case token::function_end: + error (fmt, type, "endfunction", l, c); break; - case if_end: - error ("%s command matched by `endif'", type); + case token::if_end: + error (fmt, type, "endif", l, c); break; - case while_end: - error ("%s command matched by `endwhile'", type); + case token::while_end: + error (fmt, type, "endwhile", l, c); break; default: panic_impossible (); diff --git a/src/pt-base.h b/src/pt-base.h --- a/src/pt-base.h +++ b/src/pt-base.h @@ -151,6 +151,13 @@ virtual int save (ostream& os, int mark_as_global = 0) { assert (0); return 0; } + + virtual int line (void) { return line_num; } + virtual int column (void) { return column_num; } + +protected: + int line_num; + int column_num; }; #endif diff --git a/src/pt-const.cc b/src/pt-const.cc --- a/src/pt-const.cc +++ b/src/pt-const.cc @@ -865,6 +865,8 @@ tree_constant do_binary_op (tree_constant& a, tree_constant& b, tree::expression_type t) { + tree_constant ans; + int first_empty = (a.rows () == 0 || a.columns () == 0); int second_empty = (b.rows () == 0 || b.columns () == 0); @@ -876,7 +878,7 @@ else if (flag == 0) { error ("invalid binary operation on empty matrix"); - jump_to_top_level (); + return ans; } } @@ -891,8 +893,6 @@ Complex c1, c2; ComplexMatrix cm1, cm2; - tree_constant ans; - switch (a_type) { case tree_constant_rep::scalar_constant: @@ -1010,6 +1010,8 @@ tree_constant do_unary_op (tree_constant& a, tree::expression_type t) { + tree_constant ans; + if (a.rows () == 0 || a.columns () == 0) { int flag = user_pref.propagate_empty_matrices; @@ -1018,14 +1020,12 @@ else if (flag == 0) { error ("invalid unary operation on empty matrix"); - jump_to_top_level (); + return ans; } } tree_constant tmp_a = a.make_numeric (); - tree_constant ans; - switch (tmp_a.const_type ()) { case tree_constant_rep::scalar_constant: @@ -1118,6 +1118,9 @@ void tree_constant_rep::eval (int print) { + if (error_state) + return; + switch (type_tag) { case complex_scalar_constant: @@ -1149,11 +1152,44 @@ break; } + int nr = rows (); + int nc = columns (); + + if (nr == 1 && nc == 1) + { + switch (type_tag) + { + case matrix_constant: + { + double d = matrix->elem (0, 0); + delete matrix; + scalar = d; + type_tag = scalar_constant; + } + break; + case complex_matrix_constant: + { + Complex c = complex_matrix->elem (0, 0); + delete complex_matrix; + complex_scalar = new Complex (c); + type_tag = complex_scalar_constant; + } + break; + case range_constant: + { + double d = range->base (); + delete range; + scalar = d; + type_tag = scalar_constant; + } + break; + default: + break; + } + } + if (print) { - int nr = rows (); - int nc = columns (); - ostrstream output_buf; switch (type_tag) { @@ -1206,6 +1242,9 @@ tree_constant_rep::eval (tree_constant *args, int nargin, int nargout, int print) { + if (error_state) + return NULL_TREE_CONST; + tree_constant *retval = new tree_constant [2]; switch (type_tag) { diff --git a/src/pt-plot.cc b/src/pt-plot.cc --- a/src/pt-plot.cc +++ b/src/pt-plot.cc @@ -81,6 +81,9 @@ { tree_constant retval; + if (error_state) + return retval; + ostrstream plot_buf; switch (ndim) diff --git a/src/tc-assign.cc b/src/tc-assign.cc --- a/src/tc-assign.cc +++ b/src/tc-assign.cc @@ -88,7 +88,7 @@ else { error ("invalid assignment to scalar"); - jump_to_top_level (); + return; } } else @@ -106,12 +106,14 @@ else { error ("invalid assignment to scalar"); - jump_to_top_level (); + return; } } } else if (user_pref.resize_on_range_error) { + tree_constant_rep::constant_type old_type_tag = type_tag; + if (type_tag == complex_scalar_constant) { Complex *old_complex = complex_scalar; @@ -124,18 +126,30 @@ matrix = new Matrix (1, 1, scalar); type_tag = matrix_constant; } + +// If there is an error, the call to do_matrix_assignment should not +// destroy the current value. tree_constant_rep::eval(int) will take +// care of converting single element matrices back to scalars. + do_matrix_assignment (rhs, args, nargs); + +// I don't think there's any other way to revert back to unknown +// constant types, so here it is. + + if (old_type_tag == unknown_constant && error_state) + { + if (type_tag == matrix_constant) + delete matrix; + else if (type_tag == complex_matrix_constant) + delete complex_matrix; + + type_tag = unknown_constant; + } } else if (nargs > 3 || nargs < 2) - { - error ("invalid index expression for scalar type"); - jump_to_top_level (); - } + error ("invalid index expression for scalar type"); else - { - error ("index invalid or out of range for scalar type"); - jump_to_top_level (); - } + error ("index invalid or out of range for scalar type"); } void @@ -228,11 +242,12 @@ case scalar_constant: { int i = NINT (tmp_i.double_value ()); - index_check (i-1, ""); + if (index_check (i-1, "") < 0) + return; if (nr <= 1 || nc <= 1) maybe_resize (i-1); - else - range_max_check (i-1, nr * nc); + else if (range_max_check (i-1, nr * nc) < 0) + return; nr = rows (); nc = columns (); @@ -240,7 +255,7 @@ if (! indexed_assign_conforms (1, 1, rhs_nr, rhs_nc)) { error ("for A(int) = X: X must be a scalar"); - jump_to_top_level (); + return; } int ii = fortran_row (i, nr) - 1; int jj = fortran_column (i, nr) - 1; @@ -257,14 +272,14 @@ if (nr <= 1 || nc <= 1) maybe_resize (imax-1); - else - range_max_check (imax-1, len); + else if (range_max_check (imax-1, len) < 0) + return; if (ii.capacity () != rhs_nr * rhs_nc) { error ("A(matrix) = X: X and matrix must have the same\ number of elements"); - jump_to_top_level (); + return; } fortran_style_matrix_assignment (rhs, ii); } @@ -303,7 +318,8 @@ case scalar_constant: { int i = tree_to_mat_idx (tmp_i.double_value ()); - index_check (i, ""); + if (index_check (i, "") < 0) + return; do_vector_assign (rhs, i); } break; @@ -329,7 +345,8 @@ else { int imax; - index_check (ri, imax, ""); + if (index_check (ri, imax, "") < 0) + return; do_vector_assign (rhs, ri, imax); } } @@ -342,7 +359,7 @@ if (! indexed_assign_conforms (nr, nc, rhs_nr, rhs_nc)) { error ("A(:) = X: X and A must have the same dimensions"); - jump_to_top_level (); + return; } do_matrix_assignment (rhs, magic_colon, magic_colon); } @@ -363,29 +380,20 @@ if (nr == 1 && nc == 1) // No orientation to preserve { if (! ( ilen == rhs_nr || ilen == rhs_nc)) - { - error ("A(%s) = X: X and %s must have the same number of\ + error ("A(%s) = X: X and %s must have the same number of\ elements", rm, rm); - jump_to_top_level (); - } } else if (nr == 1) // Preserve current row orientation { if (! (rhs_nr == 1 && rhs_nc == ilen)) - { - error ("A(%s) = X: where A is a row vector, X must also be a\ + error ("A(%s) = X: where A is a row vector, X must also be a\ row vector with the same number of elements as %s", rm, rm); - jump_to_top_level (); - } } else if (nc == 1) // Preserve current column orientation { if (! (rhs_nc == 1 && rhs_nr == ilen)) - { - error ("A(%s) = X: where A is a column vector, X must also\ + error ("A(%s) = X: where A is a column vector, X must also\ be a column vector with the same number of elements as %s", rm, rm); - jump_to_top_level (); - } } else panic_impossible (); @@ -400,7 +408,7 @@ if (! indexed_assign_conforms (1, 1, rhs_nr, rhs_nc)) { error ("for A(int) = X: X must be a scalar"); - jump_to_top_level (); + return; } maybe_resize (i); @@ -530,7 +538,7 @@ else if (nr*nc != rhs_size) { error ("A(:) = X: X and A must have the same number of elements"); - jump_to_top_level (); + return; } if (rhs.const_type () == matrix_constant) @@ -588,10 +596,7 @@ } } else - { - error ("number of rows and columns must match for indexed assignment"); - jump_to_top_level (); - } + error ("number of rows and columns must match for indexed assignment"); } void @@ -603,16 +608,14 @@ tree_constant_rep::constant_type itype = tmp_i.const_type (); -// index_check() and matrix_to_index_vector() jump to the top level on -// errors. - switch (itype) { case complex_scalar_constant: case scalar_constant: { int i = tree_to_mat_idx (tmp_i.double_value ()); - index_check (i, "row"); + if (index_check (i, "row") < 0) + return; do_matrix_assignment (rhs, i, j_arg); } break; @@ -637,7 +640,8 @@ else { int imax; - index_check (ri, imax, "row"); + if (index_check (ri, imax, "row") < 0) + return; do_matrix_assignment (rhs, ri, imax, j_arg); } } @@ -662,20 +666,18 @@ int rhs_nr = rhs.rows (); int rhs_nc = rhs.columns (); -// index_check() and matrix_to_index_vector() jump to the top level on -// errors. - switch (jtype) { case complex_scalar_constant: case scalar_constant: { int j = tree_to_mat_idx (tmp_j.double_value ()); - index_check (j, "column"); + if (index_check (j, "column") < 0) + return; if (! indexed_assign_conforms (1, 1, rhs_nr, rhs_nc)) { error ("A(int,int) = X, X must be a scalar"); - jump_to_top_level (); + return; } maybe_resize (i, j); do_matrix_assignment (rhs, i, j); @@ -691,7 +693,7 @@ { error ("A(int,matrix) = X: X must be a row vector with the\ same number of elements as matrix"); - jump_to_top_level (); + return; } maybe_resize (i, jv.max ()); do_matrix_assignment (rhs, i, jv); @@ -707,7 +709,7 @@ { error ("A(int,range) = X: X must be a row vector with the\ same number of elements as range"); - jump_to_top_level (); + return; } if (columns () == 2 && is_zero_one (rj) && rhs_nc == 1) { @@ -716,7 +718,8 @@ else { int jmax; - index_check (rj, jmax, "column"); + if (index_check (rj, jmax, "column") < 0) + return; maybe_resize (i, jmax); do_matrix_assignment (rhs, i, rj); } @@ -745,7 +748,7 @@ { error ("A(int,:) = X: X must be a row vector with the\ same number of columns as A"); - jump_to_top_level (); + return; } do_matrix_assignment (rhs, i, magic_colon); @@ -768,21 +771,19 @@ int rhs_nr = rhs.rows (); int rhs_nc = rhs.columns (); -// index_check() and matrix_to_index_vector() jump to the top level on -// errors. - switch (jtype) { case complex_scalar_constant: case scalar_constant: { int j = tree_to_mat_idx (tmp_j.double_value ()); - index_check (j, "column"); + if (index_check (j, "column") < 0) + return; if (! indexed_assign_conforms (iv.capacity (), 1, rhs_nr, rhs_nc)) { error ("A(matrix,int) = X: X must be a column vector with\ the same number of elements as matrix"); - jump_to_top_level (); + return; } maybe_resize (iv.max (), j); do_matrix_assignment (rhs, iv, j); @@ -800,7 +801,7 @@ error ("A(r_matrix,c_matrix) = X: the number of rows in X\ must match the number of elements in r_matrix and the number of\ columns in X must match the number of elements in c_matrix"); - jump_to_top_level (); + return; } maybe_resize (iv.max (), jv.max ()); do_matrix_assignment (rhs, iv, jv); @@ -818,7 +819,7 @@ error ("A(matrix,range) = X: the number of rows in X must\ match the number of elements in matrix and the number of columns in X\ must match the number of elements in range"); - jump_to_top_level (); + return; } if (columns () == 2 && is_zero_one (rj) && rhs_nc == 1) { @@ -827,7 +828,8 @@ else { int jmax; - index_check (rj, jmax, "column"); + if (index_check (rj, jmax, "column") < 0) + return; maybe_resize (iv.max (), jmax); do_matrix_assignment (rhs, iv, rj); } @@ -841,7 +843,7 @@ error ("A(matrix,:) = X: the number of rows in X must\ match the number of elements in matrix, and the number of columns in\ X must match the number of columns in A"); - jump_to_top_level (); + return; } maybe_resize (iv.max (), nc-1); do_matrix_assignment (rhs, iv, magic_colon); @@ -865,22 +867,19 @@ int rhs_nr = rhs.rows (); int rhs_nc = rhs.columns (); -// index_check() and matrix_to_index_vector() jump to the top level on -// errors. - switch (jtype) { case complex_scalar_constant: case scalar_constant: { int j = tree_to_mat_idx (tmp_j.double_value ()); - index_check (j, "column"); + if (index_check (j, "column") < 0) + return; if (! indexed_assign_conforms (ri.nelem (), 1, rhs_nr, rhs_nc)) { error ("A(range,int) = X: X must be a column vector with\ the same number of elements as range"); - jump_to_top_level (); - jump_to_top_level (); + return; } maybe_resize (imax, j); do_matrix_assignment (rhs, ri, j); @@ -898,7 +897,7 @@ error ("A(range,matrix) = X: the number of rows in X must\ match the number of elements in range and the number of columns in X\ must match the number of elements in matrix"); - jump_to_top_level (); + return; } maybe_resize (imax, jv.max ()); do_matrix_assignment (rhs, ri, jv); @@ -916,7 +915,7 @@ error ("A(r_range,c_range) = X: the number of rows in X\ must match the number of elements in r_range and the number of\ columns in X must match the number of elements in c_range\n"); - jump_to_top_level (); + return; } if (columns () == 2 && is_zero_one (rj) && rhs_nc == 1) { @@ -925,7 +924,8 @@ else { int jmax; - index_check (rj, jmax, "column"); + if (index_check (rj, jmax, "column") < 0) + return; maybe_resize (imax, jmax); do_matrix_assignment (rhs, ri, rj); } @@ -939,7 +939,7 @@ error ("A(range,:) = X: the number of rows in X must match\ the number of elements in range, and the number of columns in X must\ match the number of columns in A"); - jump_to_top_level (); + return; } maybe_resize (imax, nc-1); do_matrix_assignment (rhs, ri, magic_colon); @@ -963,16 +963,14 @@ int rhs_nr = rhs.rows (); int rhs_nc = rhs.columns (); -// index_check() and matrix_to_index_vector() jump to the top level on -// errors. - switch (jtype) { case complex_scalar_constant: case scalar_constant: { int j = tree_to_mat_idx (tmp_j.double_value ()); - index_check (j, "column"); + if (index_check (j, "column") < 0) + return; int nr = rows (); if (nr == 0 && columns () == 0 && rhs_nc == 1) { @@ -994,7 +992,7 @@ { error ("A(:,int) = X: X must be a column vector with the\ same number of rows as A"); - jump_to_top_level (); + return; } do_matrix_assignment (rhs, magic_colon, j); @@ -1012,7 +1010,7 @@ error ("A(:,matrix) = X: the number of rows in X must\ match the number of rows in A, and the number of columns in X must\ match the number of elements in matrix"); - jump_to_top_level (); + return; } maybe_resize (nr-1, jv.max ()); do_matrix_assignment (rhs, magic_colon, jv); @@ -1030,7 +1028,7 @@ error ("A(:,range) = X: the number of rows in X must match\ the number of rows in A, and the number of columns in X must match\ the number of elements in range"); - jump_to_top_level (); + return; } if (columns () == 2 && is_zero_one (rj) && rhs_nc == 1) { @@ -1039,7 +1037,8 @@ else { int jmax; - index_check (rj, jmax, "column"); + if (index_check (rj, jmax, "column") < 0) + return; maybe_resize (nr-1, jmax); do_matrix_assignment (rhs, magic_colon, rj); } diff --git a/src/tc-extras.cc b/src/tc-extras.cc --- a/src/tc-extras.cc +++ b/src/tc-extras.cc @@ -104,7 +104,7 @@ nc = a.columns (); } - check_dimensions (nr, nc, warn_for); // No return on error. + check_dimensions (nr, nc, warn_for); // May set error_state. } static void @@ -119,20 +119,20 @@ nr = NINT (tmpa.double_value ()); nc = NINT (tmpb.double_value ()); - check_dimensions (nr, nc, warn_for); // No return on error. + check_dimensions (nr, nc, warn_for); // May set error_state. } else - { - error ("%s: expecting two scalar arguments", warn_for); - jump_to_top_level (); - } + error ("%s: expecting two scalar arguments", warn_for); } tree_constant fill_matrix (tree_constant& a, double val, char *warn_for) { int nr, nc; - get_dimensions (a, warn_for, nr, nc); // No return on error. + get_dimensions (a, warn_for, nr, nc); + + if (error_state) + return tree_constant (); Matrix m (nr, nc, val); @@ -143,7 +143,10 @@ fill_matrix (tree_constant& a, tree_constant& b, double val, char *warn_for) { int nr, nc; - get_dimensions (a, b, warn_for, nr, nc); // No return on error. + get_dimensions (a, b, warn_for, nr, nc); // May set error_state. + + if (error_state) + return tree_constant (); Matrix m (nr, nc, val); @@ -154,7 +157,10 @@ identity_matrix (tree_constant& a) { int nr, nc; - get_dimensions (a, "eye", nr, nc); // No return on error. + get_dimensions (a, "eye", nr, nc); // May set error_state. + + if (error_state) + return tree_constant (); Matrix m (nr, nc, 0.0); @@ -172,7 +178,10 @@ identity_matrix (tree_constant& a, tree_constant& b) { int nr, nc; - get_dimensions (a, b, "eye", nr, nc); // No return on error. + get_dimensions (a, b, "eye", nr, nc); // May set error_state. + + if (error_state) + return tree_constant (); Matrix m (nr, nc, 0.0); diff --git a/src/tc-index.cc b/src/tc-index.cc --- a/src/tc-index.cc +++ b/src/tc-index.cc @@ -47,8 +47,6 @@ tree_constant tree_constant_rep::do_scalar_index (tree_constant *args, int nargs) { - tree_constant retval; - if (valid_scalar_indices (args, nargs)) { if (type_tag == scalar_constant) @@ -133,15 +131,13 @@ break; default: error ("illegal number of arguments for scalar type"); - jump_to_top_level (); + return tree_constant (); break; } } error ("index invalid or out of range for scalar type"); - jump_to_top_level (); - - return retval; + return tree_constant (); } tree_constant @@ -215,8 +211,10 @@ int i = NINT (tmp_i.double_value ()); int ii = fortran_row (i, nr) - 1; int jj = fortran_column (i, nr) - 1; - index_check (i-1, ""); - range_max_check (i-1, nr * nc); + if (index_check (i-1, "") < 0) + return tree_constant (); + if (range_max_check (i-1, nr * nc) < 0) + return tree_constant (); retval = do_matrix_index (ii, jj); } break; @@ -238,11 +236,9 @@ break; case string_constant: gripe_string_invalid (); - jump_to_top_level (); break; case range_constant: gripe_range_invalid (); - jump_to_top_level (); break; case magic_colon: retval = do_matrix_index (magic_colon); @@ -334,7 +330,7 @@ error ("empty matrix invalid as index"); else error ("invalid matrix index"); - jump_to_top_level (); + return tree_constant (); } return retval; @@ -364,15 +360,18 @@ case scalar_constant: { int i = tree_to_mat_idx (tmp_i.double_value ()); - index_check (i, ""); + if (index_check (i, "") < 0) + return tree_constant (); if (swap_indices) { - range_max_check (i, nc); + if (range_max_check (i, nc) < 0) + return tree_constant (); retval = do_matrix_index (0, i); } else { - range_max_check (i, nr); + if (range_max_check (i, nr) < 0) + return tree_constant (); retval = do_matrix_index (i, 0); } } @@ -392,12 +391,14 @@ int imax = iv.max (); if (swap_indices) { - range_max_check (imax, nc); + if (range_max_check (imax, nc) < 0) + return tree_constant (); retval = do_matrix_index (0, iv); } else { - range_max_check (imax, nr); + if (range_max_check (imax, nr) < 0) + return tree_constant (); retval = do_matrix_index (iv, 0); } } @@ -419,15 +420,18 @@ else { int imax; - index_check (ri, imax, ""); + if (index_check (ri, imax, "") < 0) + return tree_constant (); if (swap_indices) { - range_max_check (imax, nc); + if (range_max_check (imax, nc) < 0) + return tree_constant (); retval = do_matrix_index (0, ri); } else { - range_max_check (imax, nr); + if (range_max_check (imax, nr) < 0) + return tree_constant (); retval = do_matrix_index (ri, 0); } } @@ -462,7 +466,8 @@ case scalar_constant: { int i = tree_to_mat_idx (tmp_i.double_value ()); - index_check (i, "row"); + if (index_check (i, "row") < 0) + return tree_constant (); retval = do_matrix_index (i, j_arg); } break; @@ -493,7 +498,8 @@ else { int imax; - index_check (ri, imax, "row"); + if (index_check (ri, imax, "row") < 0) + return tree_constant (); retval = do_matrix_index (ri, imax, j_arg); } } @@ -527,8 +533,10 @@ case scalar_constant: { int j = tree_to_mat_idx (tmp_j.double_value ()); - index_check (j, "column"); - range_max_check (i, j, nr, nc); + if (index_check (j, "column") < 0) + return tree_constant (); + if (range_max_check (i, j, nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (i, j); } break; @@ -544,7 +552,8 @@ } else { - range_max_check (i, jv.max (), nr, nc); + if (range_max_check (i, jv.max (), nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (i, jv); } } @@ -562,14 +571,17 @@ else { int jmax; - index_check (rj, jmax, "column"); - range_max_check (i, jmax, nr, nc); + if (index_check (rj, jmax, "column") < 0) + return tree_constant (); + if (range_max_check (i, jmax, nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (i, rj); } } break; case magic_colon: - range_max_check (i, 0, nr, nc); + if (range_max_check (i, 0, nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (i, magic_colon); break; default: @@ -598,8 +610,10 @@ case scalar_constant: { int j = tree_to_mat_idx (tmp_j.double_value ()); - index_check (j, "column"); - range_max_check (iv.max (), j, nr, nc); + if (index_check (j, "column") < 0) + return tree_constant (); + if (range_max_check (iv.max (), j, nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (iv, j); } break; @@ -615,7 +629,8 @@ } else { - range_max_check (iv.max (), jv.max (), nr, nc); + if (range_max_check (iv.max (), jv.max (), nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (iv, jv); } } @@ -633,14 +648,17 @@ else { int jmax; - index_check (rj, jmax, "column"); - range_max_check (iv.max (), jmax, nr, nc); + if (index_check (rj, jmax, "column") < 0) + return tree_constant (); + if (range_max_check (iv.max (), jmax, nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (iv, rj); } } break; case magic_colon: - range_max_check (iv.max (), 0, nr, nc); + if (range_max_check (iv.max (), 0, nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (iv, magic_colon); break; default: @@ -669,8 +687,10 @@ case scalar_constant: { int j = tree_to_mat_idx (tmp_j.double_value ()); - index_check (j, "column"); - range_max_check (imax, j, nr, nc); + if (index_check (j, "column") < 0) + return tree_constant (); + if (range_max_check (imax, j, nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (ri, j); } break; @@ -686,7 +706,8 @@ } else { - range_max_check (imax, jv.max (), nr, nc); + if (range_max_check (imax, jv.max (), nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (ri, jv); } } @@ -704,8 +725,10 @@ else { int jmax; - index_check (rj, jmax, "column"); - range_max_check (imax, jmax, nr, nc); + if (index_check (rj, jmax, "column") < 0) + return tree_constant (); + if (range_max_check (imax, jmax, nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (ri, rj); } } @@ -740,8 +763,10 @@ case scalar_constant: { int j = tree_to_mat_idx (tmp_j.double_value ()); - index_check (j, "column"); - range_max_check (0, j, nr, nc); + if (index_check (j, "column") < 0) + return tree_constant (); + if (range_max_check (0, j, nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (magic_colon, j); } break; @@ -757,7 +782,8 @@ } else { - range_max_check (0, jv.max (), nr, nc); + if (range_max_check (0, jv.max (), nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (magic_colon, jv); } } @@ -775,8 +801,10 @@ else { int jmax; - index_check (rj, jmax, "column"); - range_max_check (0, jmax, nr, nc); + if (index_check (rj, jmax, "column") < 0) + return tree_constant (); + if (range_max_check (0, jmax, nr, nc) < 0) + return tree_constant (); retval = do_matrix_index (magic_colon, rj); } } diff --git a/src/tc-inlines.h b/src/tc-inlines.h --- a/src/tc-inlines.h +++ b/src/tc-inlines.h @@ -39,28 +39,31 @@ if (i > imax) { error ("matrix index = %d exceeds maximum dimension = %d", i, imax); - jump_to_top_level (); + return -1; } + return 0; } static inline int range_max_check (int i, int j, int nr, int nc) { + int status = 0; i++; if (i > nr) { error ("matrix row index = %d exceeds maximum row dimension = %d", i, nr); - jump_to_top_level (); + status = -1; } j++; if (j > nc) { error ("matrix column index = %d exceeds maximum column dimension = %d", - j, nc); - jump_to_top_level (); + j, nc); + status = -1; } + return status; } static inline int @@ -77,43 +80,46 @@ return (NINT (b) == 0 && NINT (l) == 1 && r.nelem () == 2); } -static inline void +static inline int index_check (int i, char *rc) { if (i < 0) { error ("invalid %s index = %d", rc, i+1); - jump_to_top_level (); + return -1; } + return 0; } -static inline void +static inline int index_check (const Range& r, int& max_val, char *rc) { - double b = r.base (); - int ib = tree_to_mat_idx (b); - if (r.nelem () < 1) { error ("range invalid as %s index", rc); - jump_to_top_level (); + return -1; } + double b = r.base (); + int ib = tree_to_mat_idx (b); + if (ib < 0) { error ("invalid %s index = %d", rc, ib+1); - jump_to_top_level (); + return -1; } double lim = r.limit (); max_val = tree_to_mat_idx (lim); + + return 0; } -static inline void +static inline int index_check (const Range& r, char *rc) { int max_val; - index_check (r, max_val, rc); + return index_check (r, max_val, rc); } static inline int diff --git a/src/tree.h.old b/src/tree.h.old --- a/src/tree.h.old +++ b/src/tree.h.old @@ -175,8 +175,8 @@ friend class tree_index_expression; public: - tree_identifier (void); - tree_identifier (symbol_record *s); + tree_identifier (int l = -1, int c = -1); + tree_identifier (symbol_record *s, int l = -1, int c = -1); ~tree_identifier (void); @@ -240,6 +240,9 @@ char *m_file_name (void); time_t time_parsed (void); + void stash_function_name (char *s); + char *function_name (void); + tree_constant eval (int print); tree_constant *eval (int print, int nargout); @@ -250,14 +253,17 @@ int max_expected_args (void); + void traceback_error (void); + private: int call_depth; tree_parameter_list *param_list; tree_parameter_list *ret_list; symbol_table *sym_tab; tree *cmd_list; + char *file_name; + char *fcn_name; time_t t_parsed; - char *file_name; }; /* @@ -284,13 +290,16 @@ tree_prefix_expression : public tree_expression { public: - tree_prefix_expression (void); - tree_prefix_expression (tree_identifier *t, tree::expression_type et); + tree_prefix_expression (int l = -1, int c = -1); + tree_prefix_expression (tree_identifier *t, tree::expression_type et, + int l = -1, int c = -1); ~tree_prefix_expression (void); tree_constant eval (int print); + void eval_error (void); + private: tree_identifier *id; }; @@ -302,13 +311,16 @@ tree_postfix_expression : public tree_expression { public: - tree_postfix_expression (void); - tree_postfix_expression (tree_identifier *t, tree::expression_type et); + tree_postfix_expression (int l = -1, int c = -1); + tree_postfix_expression (tree_identifier *t, tree::expression_type et, + int l = -1, int c = -1); ~tree_postfix_expression (void); tree_constant eval (int print); + void eval_error (void); + private: tree_identifier *id; }; @@ -320,13 +332,16 @@ tree_unary_expression : public tree_expression { public: - tree_unary_expression (void); - tree_unary_expression (tree *a, tree::expression_type t); + tree_unary_expression (int l = -1, int c = -1); + tree_unary_expression (tree *a, tree::expression_type t, int l = -1, + int c = -1); ~tree_unary_expression (void); tree_constant eval (int print); + void eval_error (void); + private: tree *op; }; @@ -338,13 +353,16 @@ tree_binary_expression : public tree_expression { public: - tree_binary_expression (void); - tree_binary_expression (tree *a, tree *b, tree::expression_type t); + tree_binary_expression (int l = -1, int c = -1); + tree_binary_expression (tree *a, tree *b, tree::expression_type t, + int l = -1, int c = -1); ~tree_binary_expression (void); tree_constant eval (int print); + void eval_error (void); + private: tree *op1; tree *op2; @@ -375,14 +393,18 @@ tree_simple_assignment_expression : public tree_assignment_expression { public: - tree_simple_assignment_expression (void); - tree_simple_assignment_expression (tree_identifier *i, tree *r); - tree_simple_assignment_expression (tree_index_expression *idx_expr, tree *r); + tree_simple_assignment_expression (int l = -1, int c = -1); + tree_simple_assignment_expression (tree_identifier *i, tree *r, + int l = -1, int c = -1); + tree_simple_assignment_expression (tree_index_expression *idx_expr, + tree *r, int l = -1, int c = -1); ~tree_simple_assignment_expression (void); tree_constant eval (int print); + void eval_error (void); + private: tree_identifier *lhs; tree_argument_list *index; @@ -396,8 +418,9 @@ tree_multi_assignment_expression : public tree_assignment_expression { public: - tree_multi_assignment_expression (void); - tree_multi_assignment_expression (tree_return_list *l, tree *r); + tree_multi_assignment_expression (int l = -1, int c = -1); + tree_multi_assignment_expression (tree_return_list *lst, tree *r, + int l = -1, int c = -1); ~tree_multi_assignment_expression (void); @@ -405,6 +428,8 @@ tree_constant *eval (int print, int nargout); + void eval_error (void); + private: tree_return_list *lhs; tree *rhs; @@ -417,8 +442,8 @@ tree_colon_expression : public tree_expression { public: - tree_colon_expression (void); - tree_colon_expression (tree *a, tree *b); + tree_colon_expression (int l = -1, int c = -1); + tree_colon_expression (tree *a, tree *b, int l = -1, int c = -1); ~tree_colon_expression (void); @@ -426,6 +451,8 @@ tree_constant eval (int print); + void eval_error (const char *s); + private: tree *op1; tree *op2; @@ -439,9 +466,10 @@ tree_index_expression : public tree_expression { public: - tree_index_expression (void); - tree_index_expression (tree_identifier *i); - tree_index_expression (tree_identifier *i, tree_argument_list *l); + tree_index_expression (int l = -1, int c = -1); + tree_index_expression (tree_identifier *i, int l = -1, int c = -1); + tree_index_expression (tree_identifier *i, tree_argument_list *lst, + int l = -1, int c = -1); ~tree_index_expression (void); @@ -455,6 +483,8 @@ tree_constant *eval (int print, int nargout); + void eval_error (void); + private: tree_identifier *id; tree_argument_list *list; @@ -619,7 +649,7 @@ public: tree_while_command (void); tree_while_command (tree *e); - tree_while_command (tree *e, tree *l); + tree_while_command (tree *e, tree *lst); ~tree_while_command (void); @@ -638,7 +668,7 @@ { public: tree_for_command (void); - tree_for_command (tree_index_expression *id, tree *e, tree *l); + tree_for_command (tree_index_expression *id, tree *e, tree *lst); ~tree_for_command (void); diff --git a/src/utils.cc b/src/utils.cc --- a/src/utils.cc +++ b/src/utils.cc @@ -190,10 +190,8 @@ if (user_pref.treat_neg_dim_as_zero) nr = nc = 0; else - { - message (warnfor, "can't create a matrix with negative dimensions"); - jump_to_top_level (); - } + error ("%s: can't create a matrix with negative dimensions", + warnfor); } }