Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 25 additions & 48 deletions src/exprs.c
Original file line number Diff line number Diff line change
Expand Up @@ -959,63 +959,40 @@ static Obj EvalListTildeExpr(Expr expr)
*/
static Obj EvalRangeExpr(Expr expr)
{
Obj range; // range, result
Obj val; // subvalue of range
Int low; // low (as C integer)
Int inc; // increment (as C integer)
Int high; // high (as C integer)

// evaluate the low value
val = EVAL_EXPR(READ_EXPR(expr, 0));
low = GetSmallIntEx("Range", val, "<first>");
Obj first; // first element of range
Obj second; // second element (if present)
Obj last; // last element of range

// evaluate the first value
first = EVAL_EXPR(READ_EXPR(expr, 0));
if (!IS_INT(first)) {
RequireArgumentEx("Range", first, "<first>", "must be an integer");
}

// evaluate the second value (if present)
if ( SIZE_EXPR(expr) == 3*sizeof(Expr) ) {
val = EVAL_EXPR(READ_EXPR(expr, 1));
Int ival = GetSmallIntEx("Range", val, "<second>");
if (ival == low) {
ErrorMayQuit("Range: <second> must not be equal to <first> (%d)",
(Int)low, 0);
if (SIZE_EXPR(expr) == 3 * sizeof(Expr)) {
second = EVAL_EXPR(READ_EXPR(expr, 1));
if (!IS_INT(second)) {
RequireArgumentEx("Range", second, "<second>", "must be an integer");
}
inc = ival - low;
}
else {
inc = 1;
}

// evaluate and check the high value
val = EVAL_EXPR(READ_EXPR(expr, SIZE_EXPR(expr) / sizeof(Expr) - 1));
high = GetSmallIntEx("Range", val, "<last>");
if ((high - low) % inc != 0) {
ErrorMayQuit(
"Range: <last>-<first> (%d) must be divisible by <inc> (%d)",
(Int)(high - low), (Int)inc);
}

// if <low> is larger than <high> the range is empty
if ( (0 < inc && high < low) || (inc < 0 && low < high) ) {
range = NewEmptyPlist();
}
// evaluate and check the last value
last = EVAL_EXPR(READ_EXPR(expr, 2));
if (!IS_INT(last)) {
RequireArgumentEx("Range", last, "<last>", "must be an integer");
}

// if <low> is equal to <high> the range is a singleton list
else if ( low == high ) {
range = NEW_PLIST( T_PLIST_CYC_SSORT, 1 );
SET_LEN_PLIST( range, 1 );
SET_ELM_PLIST( range, 1, INTOBJ_INT(low) );
return Range3CheckBigInt(first, second, last);
}

// else make the range
else {
// the length must be a small integer as well
if ((high-low) / inc + 1 > INT_INTOBJ_MAX) {
ErrorQuit("Range: the length of a range must be a small integer",
0, 0);
// evaluate and check the last value
last = EVAL_EXPR(READ_EXPR(expr, 1));
if (!IS_INT(last)) {
RequireArgumentEx("Range", last, "<last>", "must be an integer");
}
range = NEW_RANGE((high - low) / inc + 1, low, inc);
}

// return the range
return range;
return Range2CheckBigInt(first, last);
}
}


Expand Down
57 changes: 7 additions & 50 deletions src/intrprtr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2155,10 +2155,6 @@ void IntrListExprEnd(
{
Obj list; // the list, result
Obj old; // old value of '~'
Int low; // low value of range
Int inc; // increment of range
Int high; // high value of range
Obj val; // temporary value

// ignore or code
SKIP_IF_RETURNING();
Expand All @@ -2182,55 +2178,16 @@ void IntrListExprEnd(
// get the list
list = PopObj(intr);

// get the low value
val = ELM_LIST( list, 1 );
low = GetSmallIntEx("Range", val, "<first>");

// get the increment
if ( nr == 3 ) {
val = ELM_LIST( list, 2 );
Int v = GetSmallIntEx("Range", val, "<second>");
if ( v == low ) {
ErrorQuit("Range: <second> must not be equal to <first> (%d)",
(Int)low, 0);
}
inc = v - low;
}
else {
inc = 1;
}

// get and check the high value
val = ELM_LIST( list, LEN_LIST(list) );
Int v = GetSmallIntEx("Range", val, "<last>");
if ( (v - low) % inc != 0 ) {
ErrorQuit(
"Range: <last>-<first> (%d) must be divisible by <inc> (%d)",
(Int)(v-low), (Int)inc );
}
high = v;
// get the first, second (if present), and last values
Obj first = ELM_LIST(list, 1);
Obj last = ELM_LIST(list, LEN_LIST(list));

// if <low> is larger than <high> the range is empty
if ( (0 < inc && high < low) || (inc < 0 && low < high) ) {
list = NewEmptyPlist();
if (nr == 3) {
Obj second = ELM_LIST(list, 2);
list = Range3CheckBigInt(first, second, last);
}

// if <low> is equal to <high> the range is a singleton list
else if ( low == high ) {
list = NEW_PLIST( T_PLIST_CYC_SSORT, 1 );
SET_LEN_PLIST( list, 1 );
SET_ELM_PLIST( list, 1, INTOBJ_INT(low) );
}

// else make the range
else {
// length must be a small integer as well
if ((high-low) / inc >= INT_INTOBJ_MAX) {
ErrorQuit("Range: the length of a range must be a small integer",
0, 0);
}

list = NEW_RANGE((high - low) / inc + 1, low, inc);
list = Range2CheckBigInt(first, last);
}

// push the list again
Expand Down
Loading
Loading