diff --git a/src/parseCmtProperties.h b/src/parseCmtProperties.h index 357debd7e..768e7c71e 100644 --- a/src/parseCmtProperties.h +++ b/src/parseCmtProperties.h @@ -195,11 +195,11 @@ static inline int handleRemainingAssignmentsCalcPropComplexAssign(nodeInfo ni, c if (tb.lh[tb.ix] == isLHSstr || tb.lh[tb.ix] == isSuppressedLHSstr) { D_ParseNode *xpn = d_get_child(pn, 2); - /* Free(v); */ const char* v2 = (char*)rc_dup_str(xpn->start_loc.s, xpn->end); double d = 0.0; int nd = sscanf(v2, "%lf", &d); if (nd == 1) { + if (v2[0] == '-') return 1; if (round(d) != d) { errorStrAssign(v); return 0; @@ -211,9 +211,6 @@ static inline int handleRemainingAssignmentsCalcPropComplexAssign(nodeInfo ni, c return 0; } } - } else { - errorStrAssign(v); - return 0; } } else if (tb.lh[tb.ix] == notLHS){ tb.lh[tb.ix] = isLHSparam; diff --git a/src/rxode2_df.cpp b/src/rxode2_df.cpp index a5455094c..028336069 100644 --- a/src/rxode2_df.cpp +++ b/src/rxode2_df.cpp @@ -710,11 +710,18 @@ extern "C" SEXP rxode2_df(int doDose0, int doTBS) { if (nlhs){ for (j = 0; j < nlhs; j++){ if (op->lhs_str[j] == 1) { - dfi = INTEGER(VECTOR_ELT(df, jj)); + // factor; from string + IntegerVector cur = VECTOR_ELT(df, jj); + CharacterVector curL = cur.attr("levels"); + dfi = INTEGER(cur); + int len = curL.size(); if (ISNA(ind->lhs[j])) { dfi[ii] = NA_INTEGER; } else { dfi[ii] = (int)(ind->lhs[j]); + if (dfi[ii] < 1 || dfi[ii] > len) { + dfi[ii] = NA_INTEGER; + } } jj++; } else { diff --git a/tests/testthat/test-lhs-str.R b/tests/testthat/test-lhs-str.R index 1a057e01a..a3bb65a68 100644 --- a/tests/testthat/test-lhs-str.R +++ b/tests/testthat/test-lhs-str.R @@ -86,6 +86,10 @@ f <- function() { expect_error(rxode2parse('a <- "matt"; alag(a)<- 2')) expect_error(rxode2parse("a <- \"str\"; a(0) <- -kel")) expect_error(rxode2parse("a <- \"str\"; a(0) <- 1")) + # so that pruned expressions can work + expect_error(rxode2parse("a <- \"str\"; a <- 1+5"), NA) + expect_error(rxode2parse("a <- \"str\"; a <- -1+5"), NA) + expect_error(rxode2parse("a <- \"str\"; a <- +1+5"), NA) } test_that("test lhs string assign rxode2.syntax.allow.ini=TRUE", { @@ -126,6 +130,47 @@ test_that("lhs solve; tests lhs assign & str equals with lhs", { expect_true(all(s$b[s$time >= 10] == 1)) }) +test_that("out of bounds solve gives NA for factors", { + + rx <- rxode2({ + if (t < 10) { + a <- "<10" + } else { + a <- ">=10" + } + a <- 1-3 + b <- 1 + if (a == "<10") { + b <- 0; + } + }) + + e <- et(1:20) + + s <-rxSolve(rx, e, returnType = "data.frame") + + expect_true(all(is.na(s$a))) + + rx <- rxode2({ + if (t < 10) { + a <- "<10" + } else { + a <- ">=10" + } + a <- 1+20 + b <- 1 + if (a == "<10") { + b <- 0; + } + }) + + s <-rxSolve(rx, e, returnType = "data.frame") + + expect_true(all(is.na(s$a))) + + +}) + test_that("lhs solve; tests lhs levels & str equals with lhs", {