diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
index 2400bc8fe76c7070f0f6fd940073e6772e22f7af..43577a897b3322edfc027ff3c0e8f67d89c9eabb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
@@ -22,32 +22,27 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.unary.CastStringNode;
-import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
-@RBuiltin(name = "nzchar", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
+@RBuiltin(name = "nzchar", kind = PRIMITIVE, parameterNames = {"x", "keepNA"}, behavior = PURE)
 public abstract class NZChar extends RBuiltinNode {
-    @Child private CastStringNode convertString;
 
-    private String coerceContent(Object content) {
-        if (convertString == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            convertString = insert(CastStringNodeGen.create(false, false, false));
-        }
-        return (String) convertString.execute(content);
+    @Override
+    protected void createCasts(CastBuilder casts) {
+        casts.arg("x").asStringVector();
+        casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
     }
 
     private static byte isNonZeroLength(String s) {
@@ -55,42 +50,23 @@ public abstract class NZChar extends RBuiltinNode {
     }
 
     @Specialization
-    protected RLogicalVector rev(@SuppressWarnings("unused") RNull value) {
+    protected RLogicalVector rev(RNull value, boolean keepNA) {
         return RDataFactory.createEmptyLogicalVector();
     }
 
     @Specialization
-    protected byte rev(int value) {
-        return isNonZeroLength(coerceContent(value));
-    }
-
-    @Specialization
-    protected byte rev(double value) {
-        return isNonZeroLength(coerceContent(value));
-    }
-
-    @Specialization
-    protected byte rev(byte value) {
-        return isNonZeroLength(coerceContent(value));
-    }
-
-    @Specialization
-    protected RLogicalVector rev(RStringVector vector) {
-        int len = vector.getLength();
-        byte[] result = new byte[len];
-        for (int i = 0; i < len; i++) {
-            result[i] = isNonZeroLength(vector.getDataAt(i));
-        }
-        return RDataFactory.createLogicalVector(result, RDataFactory.COMPLETE_VECTOR);
-    }
-
-    @Specialization
-    protected RLogicalVector rev(RAbstractVector vector) {
+    protected RLogicalVector rev(RAbstractStringVector vector, boolean keepNA) {
         int len = vector.getLength();
         byte[] result = new byte[len];
+        boolean hasNA = false;
         for (int i = 0; i < len; i++) {
-            result[i] = isNonZeroLength(coerceContent(vector.getDataAtAsObject(i)));
+            if (keepNA && RRuntime.isNA(vector.getDataAt(i))) {
+                result[i] = RRuntime.LOGICAL_NA;
+                hasNA = true;
+            } else {
+                result[i] = isNonZeroLength(vector.getDataAt(i));
+            }
         }
-        return RDataFactory.createLogicalVector(result, RDataFactory.COMPLETE_VECTOR);
+        return RDataFactory.createLogicalVector(result, /* complete: */ keepNA && !hasNA);
     }
-}
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
index 35132b07c91e675949d1117f6319f9e9954205e7..b0207c785bc8598ea96387f0b36d8b3aeb8834ae 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
@@ -12,6 +12,9 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LOGICAL;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -85,7 +88,8 @@ public abstract class Order extends RPrecedenceBuiltinNode {
 
     @Override
     protected void createCasts(CastBuilder casts) {
-        casts.firstBoolean(0, "na.last").firstBoolean(1, "decreasing");
+        casts.arg("na.last").mustBe(numericValue(), INVALID_LOGICAL, "na.last").asLogicalVector().findFirst().map(toBoolean());
+        casts.arg("decreasing").mustBe(numericValue(), INVALID_LOGICAL, "decreasing").asLogicalVector().findFirst().map(toBoolean());
     }
 
     private int cmp(Object v, int i, int j, boolean naLast) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index febba87ed01063906cf99c0d7dc6ed323333ebd4..71eeb64be26cd3ca15a229f2ca789039adbcb35b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -32172,6 +32172,22 @@ Warning messages:
 #argv <- structure(list(x = structure(c(0, 3313, 2963, 3175, 3339,     2762, 3276, 2610, 4485, 2977, 3030, 4532, 2753, 3949, 2865,     2282, 2179, 3000, 817, 3927, 1991, 3313, 0, 1318, 1326, 1294,     1498, 2218, 803, 1172, 2018, 1490, 1305, 645, 636, 521, 1014,     1365, 1033, 1460, 2868, 1802, 2963, 1318, 0, 204, 583, 206,     966, 677, 2256, 597, 172, 2084, 690, 1558, 1011, 925, 747,     285, 1511, 1616, 1175, 3175, 1326, 204, 0, 460, 409, 1136,     747, 2224, 714, 330, 2052, 739, 1550, 1059, 1077, 977, 280,     1662, 1786, 1381, 3339, 1294, 583, 460, 0, 785, 1545, 853,     2047, 1115, 731, 1827, 789, 1347, 1101, 1209, 1160, 340,     1794, 2196, 1588, 2762, 1498, 206, 409, 785, 0, 760, 1662,     2436, 460, 269, 2290, 714, 1764, 1035, 911, 583, 465, 1497,     1403, 937, 3276, 2218, 966, 1136, 1545, 760, 0, 1418, 3196,     460, 269, 2971, 1458, 2498, 1778, 1537, 1104, 1176, 2050,     650, 1455, 2610, 803, 677, 747, 853, 1662, 1418, 0, 1975,     1118, 895, 1936, 158, 1439, 425, 328, 591, 513, 995, 2068,     1019, 4485, 1172, 2256, 2224, 2047, 2436, 3196, 1975, 0,     2897, 2428, 676, 1817, 698, 1693, 2185, 2565, 1971, 2631,     3886, 2974, 2977, 2018, 597, 714, 1115, 460, 460, 1118, 2897,     0, 550, 2671, 1159, 2198, 1479, 1238, 805, 877, 1751, 949,     1155, 3030, 1490, 172, 330, 731, 269, 269, 895, 2428, 550,     0, 2280, 863, 1730, 1183, 1098, 851, 457, 1683, 1500, 1205,     4532, 1305, 2084, 2052, 1827, 2290, 2971, 1936, 676, 2671,     2280, 0, 1178, 668, 1762, 2250, 2507, 1799, 2700, 3231, 2937,     2753, 645, 690, 739, 789, 714, 1458, 158, 1817, 1159, 863,     1178, 0, 1281, 320, 328, 724, 471, 1048, 2108, 1157, 3949,     636, 1558, 1550, 1347, 1764, 2498, 1439, 698, 2198, 1730,     668, 1281, 0, 1157, 1724, 2010, 1273, 2097, 3188, 2409, 2865,     521, 1011, 1059, 1101, 1035, 1778, 425, 1693, 1479, 1183,     1762, 320, 1157, 0, 618, 1109, 792, 1011, 2428, 1363, 2282,     1014, 925, 1077, 1209, 911, 1537, 328, 2185, 1238, 1098,     2250, 328, 1724, 618, 0, 331, 856, 586, 2187, 898, 2179,     1365, 747, 977, 1160, 583, 1104, 591, 2565, 805, 851, 2507,     724, 2010, 1109, 331, 0, 821, 946, 1754, 428, 3000, 1033,     285, 280, 340, 465, 1176, 513, 1971, 877, 457, 1799, 471,     1273, 792, 856, 821, 0, 1476, 1827, 1249, 817, 1460, 1511,     1662, 1794, 1497, 2050, 995, 2631, 1751, 1683, 2700, 1048,     2097, 1011, 586, 946, 1476, 0, 2707, 1209, 3927, 2868, 1616,     1786, 2196, 1403, 650, 2068, 3886, 949, 1500, 3231, 2108,     3188, 2428, 2187, 1754, 1827, 2707, 0, 2105, 1991, 1802,     1175, 1381, 1588, 937, 1455, 1019, 2974, 1155, 1205, 2937,     1157, 2409, 1363, 898, 428, 1249, 1209, 2105, 0), .Dim = c(21L,     21L), .Dimnames = list(c('Athens', 'Barcelona', 'Brussels',     'Calais', 'Cherbourg', 'Cologne', 'Copenhagen', 'Geneva',     'Gibraltar', 'Hamburg', 'Hook of Holland', 'Lisbon', 'Lyons',     'Madrid', 'Marseilles', 'Milan', 'Munich', 'Paris', 'Rome',     'Stockholm', 'Vienna'), c('Athens', 'Barcelona', 'Brussels',     'Calais', 'Cherbourg', 'Cologne', 'Copenhagen', 'Geneva',     'Gibraltar', 'Hamburg', 'Hook of Holland', 'Lisbon', 'Lyons',     'Madrid', 'Marseilles', 'Milan', 'Munich', 'Paris', 'Rome',     'Stockholm', 'Vienna')))), .Names = 'x');do.call('NROW', argv)
 [1] 21
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.keepNATests
+#nzchar(c('asdasd', NA), keepNA=FALSE)
+[1] TRUE TRUE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.keepNATests
+#nzchar(c('asdasd', NA), keepNA=TRUE)
+[1] TRUE   NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs
+#nzchar(NULL)
+logical(0)
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs
+#nzchar(list('x', 42, list('a'), list()))
+[1] TRUE TRUE TRUE TRUE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.testnzchar1
 #argv <- list('./myTst2/man/DocLink-class.Rd');nzchar(argv[[1]]);
 [1] TRUE
@@ -32213,8 +32229,8 @@ logical(0)
 [1] TRUE
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.testnzchar9
-#argv <- list(c('  \036 The other major change was an error for asymmetric loss matrices,', '    prompted by a user query.  With L=loss asymmetric, the altered', '    priors were computed incorrectly - they were using L' instead of L.', '    Upshot - the tree would not not necessarily choose optimal splits', '    for the given loss matrix.  Once chosen, splits were evaluated', '    correctly.  The printed “improvement” values are of course the', '    wrong ones as well.  It is interesting that for my little test', '    case, with L quite asymmetric, the early splits in the tree are', '    unchanged - a good split still looks good.'));nzchar(argv[[1]]);
-Error: unexpected symbol in "argv <- list(c('  \036 The other major change was an error for asymmetric loss matrices,', '    prompted by a user query.  With L=loss asymmetric, the altered', '    priors were computed incor"
+#argv <- list(c('  \036 The other major change was an error for asymmetric loss matrices,', '    prompted by a user query.  With L=loss asymmetric, the altered', '    priors were computed incorrectly - they were using L\' instead of L.', '    Upshot - the tree would not not necessarily choose optimal splits', '    for the given loss matrix.  Once chosen, splits were evaluated', '    correctly.  The printed “improvement” values are of course the', '    wrong ones as well.  It is interesting that for my little test', '    case, with L quite asymmetric, the early splits in the tree are', '    unchanged - a good split still looks good.'));nzchar(argv[[1]]);
+[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_oldClass.testGetClass
 #{ oldClass(NULL) }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java
index 829f43019c2d1f91e4349d75ae0a68f00fefac67..380381a450387666b55f024cd76ce8e197ddea6a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java
@@ -59,8 +59,7 @@ public class TestBuiltin_nzchar extends TestBase {
 
     @Test
     public void testnzchar9() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c('  \\036 The other major change was an error for asymmetric loss matrices,', '    prompted by a user query.  With L=loss asymmetric, the altered', '    priors were computed incorrectly - they were using L' instead of L.', '    Upshot - the tree would not not necessarily choose optimal splits', '    for the given loss matrix.  Once chosen, splits were evaluated', '    correctly.  The printed “improvement” values are of course the', '    wrong ones as well.  It is interesting that for my little test', '    case, with L quite asymmetric, the early splits in the tree are', '    unchanged - a good split still looks good.'));nzchar(argv[[1]]);");
+        assertEval("argv <- list(c('  \\036 The other major change was an error for asymmetric loss matrices,', '    prompted by a user query.  With L=loss asymmetric, the altered', '    priors were computed incorrectly - they were using L\\' instead of L.', '    Upshot - the tree would not not necessarily choose optimal splits', '    for the given loss matrix.  Once chosen, splits were evaluated', '    correctly.  The printed “improvement” values are of course the', '    wrong ones as well.  It is interesting that for my little test', '    case, with L quite asymmetric, the early splits in the tree are', '    unchanged - a good split still looks good.'));nzchar(argv[[1]]);");
     }
 
     @Test
@@ -72,4 +71,16 @@ public class TestBuiltin_nzchar extends TestBase {
     public void testnzchar12() {
         assertEval("argv <- list('');do.call('nzchar', argv)");
     }
-}
+
+    @Test
+    public void keepNATests() {
+        assertEval("nzchar(c('asdasd', NA), keepNA=TRUE)");
+        assertEval("nzchar(c('asdasd', NA), keepNA=FALSE)");
+    }
+
+    @Test
+    public void nonStringArgs() {
+        assertEval("nzchar(list('x', 42, list('a'), list()))");
+        assertEval("nzchar(NULL)");
+    }
+}
\ No newline at end of file