diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java
new file mode 100644
index 0000000000000000000000000000000000000000..8180a40c81aab0ab113e233038c39c1b55685160
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.stats.deriv;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.RASTUtils;
+import com.oracle.truffle.r.nodes.access.ConstantNode;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RExpression;
+import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
+
+public abstract class D extends RExternalBuiltinNode.Arg2 {
+
+    static {
+        Casts casts = new Casts(D.class);
+        casts.arg(0, "expr").mustBe(instanceOf(RExpression.class).or(instanceOf(RLanguage.class)).or(instanceOf(RSymbol.class)).or(numericValue()).or(complexValue()),
+                        RError.Message.INVALID_EXPRESSION_TYPE, typeName());
+        casts.arg(1, "namevec").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.GENERIC, "variable must be a character string").shouldBe(size(1),
+                        RError.Message.ONLY_FIRST_VARIABLE_NAME).findFirst();
+    }
+
+    public static D create() {
+        return DNodeGen.create();
+    }
+
+    protected static boolean isConstant(Object expr) {
+        return !(expr instanceof RLanguage || expr instanceof RExpression || expr instanceof RSymbol);
+    }
+
+    @Specialization(guards = "isConstant(expr)")
+    @TruffleBoundary
+    protected Object doD(Object expr, String var) {
+        return doD(ConstantNode.create(expr), var);
+    }
+
+    @Specialization
+    @TruffleBoundary
+    protected Object doD(RSymbol expr, String var) {
+        return doD(RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, expr.getName(), false), var);
+    }
+
+    @Specialization
+    @TruffleBoundary
+    protected Object doD(RLanguage expr, String var) {
+        return doD((RSyntaxElement) expr.getRep(), var);
+    }
+
+    @Specialization
+    @TruffleBoundary
+    protected Object doD(RExpression expr, String var,
+                    @Cached("create()") D dNode) {
+        return dNode.execute(expr.getDataAt(0), var);
+    }
+
+    private static Object doD(RSyntaxElement elem, String var) {
+        RSyntaxVisitor<RSyntaxElement> vis = new DerivVisitor(var);
+        RSyntaxElement dExpr = vis.accept(elem);
+        dExpr = Deriv.addParens(dExpr);
+        return RASTUtils.createLanguageElement(dExpr);
+    }
+
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
new file mode 100644
index 0000000000000000000000000000000000000000..36aa40831565010b6d586d365c774143b1879bc4
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
@@ -0,0 +1,703 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2013,  The R Core Team
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.stats.deriv;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.boxPrimitive;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthGte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthLte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.nodes.RASTUtils;
+import com.oracle.truffle.r.nodes.RRootNode;
+import com.oracle.truffle.r.nodes.access.ConstantNode;
+import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.nodes.function.FormalArguments;
+import com.oracle.truffle.r.nodes.function.RCallSpecialNode;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.REmpty;
+import com.oracle.truffle.r.runtime.data.RExpression;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument;
+import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
+
+//Transcribed from GnuR, library/stats/src/deriv.c
+
+public abstract class Deriv extends RExternalBuiltinNode {
+
+    static {
+        Casts casts = new Casts(Deriv.class);
+        casts.arg(1, "namevec").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.INVALID_VARIABLE_NAMES);
+        casts.arg(2, "function.arg").mapIf(logicalValue(), chain(asLogicalVector()).with(findFirst().logicalElement()).with(map(toBoolean())).end()).mapIf(stringValue(), boxPrimitive());
+        casts.arg(3, "tag").defaultError(RError.Message.INVALID_VARIABLE_NAMES).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst().mustBe(lengthGte(1).and(lengthLte(60)));
+        casts.arg(4, "hessian").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+    }
+
+    static final String LEFT_PAREN = "(";
+    static final String PLUS = "+";
+    static final String MINUS = "-";
+    static final String TIMES = "*";
+    static final String DIVIDE = "/";
+    static final String POWER = "^";
+    static final String LOG = "log";
+    static final String EXP = "exp";
+    static final String COS = "cos";
+    static final String SIN = "sin";
+    static final String TAN = "tan";
+    static final String COSH = "cosh";
+    static final String SINH = "sinh";
+    static final String TANH = "tanh";
+    static final String SQRT = "sqrt";
+    static final String PNORM = "pnorm";
+    static final String DNORM = "dnorm";
+    static final String ASIN = "asin";
+    static final String ACOS = "acos";
+    static final String ATAN = "atan";
+    static final String GAMMA = "gamma";
+    static final String LGAMMA = "lgamma";
+    static final String DIGAMMA = "digamma";
+    static final String TRIGAMMA = "trigamma";
+    static final String PSIGAMMA = "psigamma";
+
+    public static Deriv create() {
+        return DerivNodeGen.create();
+    }
+
+    public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5);
+
+    @Override
+    public Object call(VirtualFrame frame, RArgsValuesAndNames args) {
+        checkLength(args, 5);
+        return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4));
+    }
+
+    @Override
+    protected Object call(RArgsValuesAndNames args) {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    protected static boolean isConstant(Object expr) {
+        return !(expr instanceof RLanguage || expr instanceof RExpression || expr instanceof RSymbol);
+    }
+
+    @Specialization(guards = "isConstant(expr)")
+    protected Object derive(VirtualFrame frame, Object expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return derive(frame, RDataFactory.createLanguage(ConstantNode.create(expr)), names, functionArg, tag, hessian);
+    }
+
+    @Specialization
+    protected Object derive(VirtualFrame frame, RSymbol expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return derive(frame, (RBaseNode) RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, expr.getName(), false), names, functionArg, tag, hessian);
+    }
+
+    @Specialization
+    protected Object derive(VirtualFrame frame, RExpression expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian,
+                    @Cached("create()") Deriv derivNode) {
+        return derivNode.execute(frame, expr.getDataAt(0), names, functionArg, tag, hessian);
+    }
+
+    @Specialization
+    protected Object derive(VirtualFrame frame, RLanguage expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return derive(frame, expr.getRep(), names, functionArg, tag, hessian);
+    }
+
+    private Object derive(VirtualFrame frame, RBaseNode elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        LinkedList<RSyntaxNode> exprlist = new LinkedList<>();
+        int fIndex = findSubexpression(elem, exprlist, tag);
+
+        int nderiv = names.getLength();
+        int[] dIndex = new int[nderiv];
+        int[] d2Index = hessian ? new int[(nderiv * (1 + nderiv)) / 2] : null;
+        for (int i = 0, k = 0; i < nderiv; i++) {
+            RBaseNode dExpr = d(elem, names.getDataAt(i));
+            dIndex[i] = findSubexpression(dExpr, exprlist, tag);
+
+            if (hessian) {
+                for (int j = i; j < nderiv; j++) {
+                    RBaseNode d2Expr = d(dExpr, names.getDataAt(j));
+                    d2Index[k] = findSubexpression(d2Expr, exprlist, tag);
+                    k++;
+                }
+            }
+        }
+
+        int nexpr = exprlist.size();
+
+        if (fIndex > 0) {
+            exprlist.add(ReadVariableNode.create(tag + fIndex));
+        } else {
+            exprlist.add(cloneElement(elem.asRSyntaxNode()));
+        }
+
+        exprlist.add(null);
+        if (hessian) {
+            exprlist.add(null);
+        }
+
+        for (int i = 0, k = 0; i < nderiv; i++) {
+            if (dIndex[i] > 0) {
+                exprlist.add(ReadVariableNode.create(tag + dIndex[i]));
+
+                if (hessian) {
+                    RBaseNode dExpr = d(elem, names.getDataAt(i));
+                    for (int j = i; j < nderiv; j++) {
+                        if (d2Index[k] > 0) {
+                            exprlist.add(ReadVariableNode.create(tag + d2Index[k]));
+                        } else {
+                            exprlist.add((RSyntaxNode) d(dExpr, names.getDataAt(j)));
+                        }
+                        k++;
+                    }
+                }
+
+            } else {
+                // the first derivative is constant or simple variable
+                // TODO: do not call the d twice
+                RBaseNode dExpr = d(elem, names.getDataAt(i));
+                exprlist.add((RSyntaxNode) dExpr);
+
+                if (hessian) {
+                    for (int j = i; j < nderiv; j++) {
+                        if (d2Index[k] > 0) {
+                            exprlist.add(ReadVariableNode.create(tag + d2Index[k]));
+                        } else {
+                            RBaseNode d2Expr = d(dExpr, names.getDataAt(j));
+                            if (isZero((RSyntaxElement) d2Expr)) {
+                                exprlist.add(null);
+                            } else {
+                                exprlist.add((RSyntaxNode) d2Expr);
+                            }
+                        }
+                        k++;
+                    }
+                }
+            }
+        }
+
+        exprlist.add(null);
+        exprlist.add(null);
+        if (hessian) {
+            exprlist.add(null);
+        }
+
+        for (int i = 0; i < nexpr; i++) {
+            String subexprName = tag + (i + 1);
+            if (countOccurences(subexprName, exprlist, i + 1) < 2) {
+                replace(subexprName, exprlist.get(i), exprlist, i + 1);
+                exprlist.set(i, null);
+            } else {
+                exprlist.set(i, createAssignNode(subexprName, exprlist.get(i)));
+            }
+        }
+
+        int p = nexpr;
+        exprlist.set(p++, createAssignNode(".value", exprlist.get(nexpr))); // .value <-
+        exprlist.set(p++, createGrad(names)); // .grad <-
+        if (hessian) {
+            exprlist.set(p++, createHess(names)); // .hessian
+        }
+        // .grad[, "..."] <- ...
+        for (int i = 0; i < nderiv; i++) {
+            RSyntaxNode ans = exprlist.get(p);
+            exprlist.set(p, derivAssign(names.getDataAt(i), ans));
+            p++;
+
+            if (hessian) {
+                for (int j = i; j < nderiv; j++, p++) {
+                    ans = exprlist.get(p);
+                    if (ans != null) {
+                        if (i == j) {
+                            exprlist.set(p, hessAssign1(names.getDataAt(i), addParens(ans)));
+                        } else {
+                            exprlist.set(p, hessAssign2(names.getDataAt(i), names.getDataAt(j), addParens(ans)));
+                        }
+                    }
+                }
+            }
+
+        }
+        // attr(.value, "gradient") <- .grad
+        exprlist.set(p++, addGrad());
+        if (hessian) {
+            exprlist.set(p++, addHess());
+        }
+
+        // .value
+        exprlist.set(p++, ReadVariableNode.create(".value"));
+
+        // prune exprlist
+        exprlist.removeAll(Collections.singleton(null));
+
+        List<Argument<RSyntaxNode>> blockStatements = exprlist.stream().map(e -> RCodeBuilder.argument(e)).collect(Collectors.toList());
+        RSyntaxNode blockCall = RContext.getASTBuilder().call(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.create("{"), blockStatements);
+
+        if (functionArg instanceof RAbstractStringVector) {
+            RAbstractStringVector funArgNames = (RAbstractStringVector) functionArg;
+            List<Argument<RSyntaxNode>> targetArgs = new ArrayList<>();
+            for (int i = 0; i < funArgNames.getLength(); i++) {
+                targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, funArgNames.getDataAt(i), ConstantNode.create(RMissing.instance)));
+            }
+
+            return createFunction(frame, blockCall, targetArgs);
+        } else if (functionArg == Boolean.TRUE) {
+            List<Argument<RSyntaxNode>> targetArgs = new ArrayList<>();
+            for (int i = 0; i < names.getLength(); i++) {
+                targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, names.getDataAt(i), ConstantNode.create(RMissing.instance)));
+            }
+
+            return createFunction(frame, blockCall, targetArgs);
+        } else if (functionArg instanceof RFunction) {
+            RFunction funTemplate = (RFunction) functionArg;
+            FormalArguments formals = ((RRootNode) funTemplate.getRootNode()).getFormalArguments();
+            RNode[] defArgs = formals.getArguments();
+            List<Argument<RSyntaxNode>> targetArgs = new ArrayList<>();
+            for (int i = 0; i < defArgs.length; i++) {
+                targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, formals.getSignature().getName(i), cloneElement((RSyntaxNode) defArgs[i])));
+            }
+
+            return createFunction(frame, blockCall, targetArgs);
+        } else {
+            RLanguage lan = RDataFactory.createLanguage(blockCall.asRNode());
+            RExpression res = RDataFactory.createExpression(new Object[]{lan});
+            return res;
+        }
+
+    }
+
+    private static RFunction createFunction(VirtualFrame frame, RSyntaxNode blockCall, List<Argument<RSyntaxNode>> targetArgs) {
+        RootCallTarget callTarget = RContext.getASTBuilder().rootFunction(RSyntaxNode.LAZY_DEPARSE, targetArgs, blockCall, null);
+        FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), frame);
+        return RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, callTarget, null, frame.materialize());
+    }
+
+    private int findSubexpression(RBaseNode expr, List<RSyntaxNode> exprlist, String tag) {
+        if (!(expr instanceof RSyntaxElement)) {
+            throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
+        }
+
+        RSyntaxVisitor<Integer> vis = new RSyntaxVisitor<Integer>() {
+            @Override
+            protected Integer visit(RSyntaxCall call) {
+                if (call.getSyntaxLHS() instanceof RSyntaxLookup && ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier() == LEFT_PAREN) {
+                    return accept(call.getSyntaxArguments()[0]);
+                }
+
+                RSyntaxElement[] args = call.getSyntaxArguments();
+                List<Argument<RSyntaxNode>> newArgs = new ArrayList<>();
+                for (int i = 0; i < args.length; i++) {
+                    int k = accept(args[i]);
+                    if (k > 0) {
+                        newArgs.add(RCodeBuilder.argument(ReadVariableNode.create(tag + k)));
+                    } else {
+                        newArgs.add(RCodeBuilder.argument(cloneElement(args[i])));
+                    }
+                }
+                RSyntaxNode newCall = RContext.getASTBuilder().call(call.getSourceSection(), cloneElement(call.getSyntaxLHS()), newArgs);
+                return accumulate(newCall, exprlist);
+            }
+
+            @Override
+            protected Integer visit(RSyntaxConstant element) {
+                return checkConstant(element.getValue());
+            }
+
+            @Override
+            protected Integer visit(RSyntaxLookup element) {
+                return 0;
+            }
+
+            @Override
+            protected Integer visit(RSyntaxFunction element) {
+                throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
+            }
+
+        };
+        return vis.accept((RSyntaxElement) expr);
+    }
+
+    private static int checkConstant(Object val) {
+        if (val instanceof Double || val instanceof Integer || val instanceof RComplex || val instanceof Byte || val instanceof RSymbol) {
+            return 0;
+        } else {
+            throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
+        }
+    }
+
+    private static boolean isDoubleValue(RSyntaxElement elem, double value) {
+        if (elem instanceof RSyntaxConstant) {
+            Object val = ((RSyntaxConstant) elem).getValue();
+            if (val instanceof Number) {
+                return ((Number) val).doubleValue() == value;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    static boolean isZero(RSyntaxElement elem) {
+        return isDoubleValue(elem, 0.);
+    }
+
+    static boolean isOne(RSyntaxElement elem) {
+        return isDoubleValue(elem, 1.);
+    }
+
+    private int accumulate(RSyntaxElement expr, List<RSyntaxNode> exprlist) {
+        for (int k = 0; k < exprlist.size(); k++) {
+            if (equal(expr, exprlist.get(k))) {
+                return k + 1;
+            }
+        }
+        exprlist.add((RSyntaxNode) expr);
+        return exprlist.size();
+    }
+
+    // TODO: move to a utility class
+    private boolean equal(RSyntaxElement expr1, RSyntaxElement expr2) {
+        if (expr1.getClass() != expr2.getClass()) {
+            return false;
+        }
+        if (expr1 instanceof RSyntaxLookup) {
+            return ((RSyntaxLookup) expr1).getIdentifier() == ((RSyntaxLookup) expr2).getIdentifier();
+        }
+        if (expr1 instanceof RSyntaxConstant) {
+            return ((RSyntaxConstant) expr1).getValue().equals(((RSyntaxConstant) expr2).getValue());
+        }
+        if (expr1 instanceof RSyntaxCall) {
+            RSyntaxElement[] args1 = ((RSyntaxCall) expr1).getSyntaxArguments();
+            RSyntaxElement[] args2 = ((RSyntaxCall) expr2).getSyntaxArguments();
+            if (args1.length != args2.length) {
+                return false;
+            }
+            if (!equal(((RSyntaxCall) expr1).getSyntaxLHS(), ((RSyntaxCall) expr2).getSyntaxLHS())) {
+                return false;
+            }
+            for (int i = 0; i < args1.length; i++) {
+                if (!equal(args1[i], args2[i])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "equal");
+    }
+
+    static String getFunctionName(RSyntaxElement expr) {
+        if (expr instanceof RSyntaxCall) {
+            RSyntaxCall call = (RSyntaxCall) expr;
+            return call.getSyntaxLHS() instanceof RSyntaxLookup ? ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier() : null;
+        } else {
+            return null;
+        }
+    }
+
+    static RSyntaxNode cloneElement(RSyntaxElement element) {
+        return (RSyntaxNode) RASTUtils.cloneNode(((RBaseNode) element));
+    }
+
+    private static RBaseNode d(RBaseNode expr, String var) {
+        if (!(expr instanceof RSyntaxElement)) {
+            throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
+        }
+
+        RSyntaxVisitor<RSyntaxElement> vis = new DerivVisitor(var);
+        return (RBaseNode) vis.accept((RSyntaxElement) expr);
+    }
+
+    private static int argsLength(RSyntaxElement elem) {
+        if (elem instanceof RSyntaxCall) {
+            return ((RSyntaxCall) elem).getSyntaxArguments().length;
+        } else {
+            return 0;
+        }
+    }
+
+    static RSyntaxElement arg(RSyntaxElement elem, int argIndex) {
+        assert elem instanceof RSyntaxCall && (argIndex < ((RSyntaxCall) elem).getSyntaxArguments().length);
+        return ((RSyntaxCall) elem).getSyntaxArguments()[argIndex];
+    }
+
+    private static RSyntaxElement setArg(RSyntaxElement elem, int argIndex, RSyntaxElement arg) {
+        assert elem instanceof RSyntaxCall && (argIndex < ((RSyntaxCall) elem).getSyntaxArguments().length);
+        RSyntaxCall call = (RSyntaxCall) elem;
+        RSyntaxElement[] args = call.getSyntaxArguments();
+        RSyntaxNode[] newArgs = new RSyntaxNode[args.length];
+        for (int i = 0; i < args.length; i++) {
+            if (i == argIndex) {
+                newArgs[i] = (RSyntaxNode) arg;
+            } else {
+                newArgs[i] = cloneElement(args[i]);
+            }
+        }
+        return RCallSpecialNode.createCall(call.getSourceSection(), (RNode) cloneElement(call.getSyntaxLHS()), ArgumentsSignature.empty(args.length), newArgs);
+    }
+
+    static RSyntaxNode newCall(String functionName, RSyntaxElement arg1, RSyntaxElement arg2) {
+        if (arg2 == null) {
+            return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create(functionName), (RSyntaxNode) arg1);
+        } else {
+            return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create(functionName), (RSyntaxNode) arg1, (RSyntaxNode) arg2);
+        }
+    }
+
+    private static int countOccurences(String subexprName, List<RSyntaxNode> exprlist, int fromIndex) {
+        if (fromIndex >= exprlist.size()) {
+            return 0;
+        }
+
+        RSyntaxNode exprListNode = exprlist.get(fromIndex);
+        if (exprListNode == null) {
+            return countOccurences(subexprName, exprlist, fromIndex + 1);
+        }
+
+        RSyntaxVisitor<Integer> vis = new RSyntaxVisitor<Integer>() {
+            @Override
+            protected Integer visit(RSyntaxCall element) {
+                RSyntaxElement[] args = element.getSyntaxArguments();
+                int cnt = 0;
+                for (int i = 0; i < args.length; i++) {
+                    cnt += accept(args[i]);
+                }
+                return cnt;
+            }
+
+            @Override
+            protected Integer visit(RSyntaxConstant element) {
+                return 0;
+            }
+
+            @Override
+            protected Integer visit(RSyntaxLookup element) {
+                return subexprName.equals(element.getIdentifier()) ? 1 : 0;
+            }
+
+            @Override
+            protected Integer visit(RSyntaxFunction element) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        };
+
+        return vis.accept(exprListNode) + countOccurences(subexprName, exprlist, fromIndex + 1);
+    }
+
+    private static void replace(String subexprName, RSyntaxNode replacement, List<RSyntaxNode> exprlist, int fromIndex) {
+        if (fromIndex >= exprlist.size()) {
+            return;
+        }
+
+        RSyntaxElement exprListNode = exprlist.get(fromIndex);
+        if (exprListNode == null) {
+            replace(subexprName, replacement, exprlist, fromIndex + 1);
+            return;
+        }
+
+        RSyntaxVisitor<RSyntaxElement> vis = new RSyntaxVisitor<RSyntaxElement>() {
+
+            // TODO: do not create a new call node after the first replacement
+
+            @Override
+            protected RSyntaxElement visit(RSyntaxCall call) {
+                RSyntaxElement[] args = call.getSyntaxArguments();
+                RSyntaxNode[] newArgs = new RSyntaxNode[args.length];
+                for (int i = 0; i < args.length; i++) {
+                    newArgs[i] = (RSyntaxNode) accept(args[i]);
+                }
+                return RCallSpecialNode.createCall(call.getSourceSection(), (RNode) call.getSyntaxLHS(), ArgumentsSignature.empty(args.length), newArgs);
+            }
+
+            @Override
+            protected RSyntaxElement visit(RSyntaxConstant element) {
+                return element;
+            }
+
+            @Override
+            protected RSyntaxElement visit(RSyntaxLookup element) {
+                return subexprName.equals(element.getIdentifier()) ? replacement : element;
+            }
+
+            @Override
+            protected RSyntaxElement visit(RSyntaxFunction element) {
+                throw RInternalError.shouldNotReachHere();
+            }
+
+        };
+
+        exprlist.set(fromIndex, (RSyntaxNode) vis.accept(exprListNode));
+
+        replace(subexprName, replacement, exprlist, fromIndex + 1);
+    }
+
+    private static RSyntaxNode createAssignNode(String varName, RSyntaxNode rhs) {
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(varName.intern()), addParens(rhs));
+    }
+
+    private static RSyntaxNode hessAssign1(String varName, RSyntaxNode rhs) {
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance),
+                        ConstantNode.create(varName.intern()), ConstantNode.create(varName.intern()));
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, rhs);
+    }
+
+    private static RSyntaxNode hessAssign2(String varName1, String varName2, RSyntaxNode rhs) {
+        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance),
+                        ConstantNode.create(varName1.intern()), ConstantNode.create(varName2.intern()));
+        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance),
+                        ConstantNode.create(varName2.intern()), ConstantNode.create(varName1.intern()));
+
+        RSyntaxNode tmp3 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp2, rhs);
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp1, tmp3);
+    }
+
+    private static RSyntaxNode createGrad(RAbstractStringVector names) {
+        int n = names.getLength();
+        List<Argument<RSyntaxNode>> cArgs = new ArrayList<>();
+        for (int i = 0; i < n; i++) {
+            cArgs.add(RCodeBuilder.argument(ConstantNode.create(names.getDataAt(i).intern())));
+        }
+        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), cArgs);
+        RSyntaxNode dimnames = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("list"), ConstantNode.create(RNull.instance), tmp1);
+
+        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("length"), ReadVariableNode.create(".value"));
+        RSyntaxNode dim = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), tmp2, ConstantNode.create(n));
+        ConstantNode data = ConstantNode.create(0.);
+
+        RSyntaxNode p = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("array"), data, dim, dimnames);
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(".grad"), p);
+    }
+
+    private static RSyntaxNode createHess(RAbstractStringVector names) {
+        int n = names.getLength();
+        List<Argument<RSyntaxNode>> cArgs = new ArrayList<>();
+        for (int i = 0; i < n; i++) {
+            cArgs.add(RCodeBuilder.argument(ConstantNode.create(names.getDataAt(i).intern())));
+        }
+        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), cArgs);
+        RSyntaxNode tmp1Clone = cloneElement(tmp1);
+        RSyntaxNode dimnames = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("list"), ConstantNode.create(RNull.instance), tmp1, tmp1Clone);
+
+        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("length"), ReadVariableNode.create(".value"));
+        RSyntaxNode dim = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), tmp2, ConstantNode.create(n), ConstantNode.create(n));
+        ConstantNode data = ConstantNode.create(0.);
+
+        RSyntaxNode p = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("array"), data, dim, dimnames);
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(".hessian"), p);
+    }
+
+    private static RSyntaxNode derivAssign(String name, RSyntaxNode expr) {
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".grad"), ConstantNode.create(REmpty.instance),
+                        ConstantNode.create(name.intern()));
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, expr);
+    }
+
+    private static RSyntaxNode addGrad() {
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("attr"), ReadVariableNode.create(".value"), ConstantNode.create("gradient"));
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, ReadVariableNode.create(".grad"));
+    }
+
+    private static RSyntaxNode addHess() {
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("attr"), ReadVariableNode.create(".value"), ConstantNode.create("hessian"));
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, ReadVariableNode.create(".hessian"));
+    }
+
+    private static boolean isForm(RSyntaxElement expr, String functionName) {
+        return argsLength(expr) == 2 && getFunctionName(expr) == functionName;
+    }
+
+    static RSyntaxNode addParens(RSyntaxElement node) {
+        RSyntaxElement expr = node;
+        if (node instanceof RSyntaxCall) {
+            RSyntaxCall call = (RSyntaxCall) node;
+            RSyntaxElement[] args = call.getSyntaxArguments();
+            RSyntaxNode[] newArgs = new RSyntaxNode[args.length];
+            for (int i = 0; i < args.length; i++) {
+                newArgs[i] = addParens(args[i]);
+            }
+            expr = RCallSpecialNode.createCall(call.getSourceSection(), (RNode) cloneElement(call.getSyntaxLHS()), ArgumentsSignature.empty(args.length), newArgs);
+        }
+
+        if (isForm(expr, PLUS)) {
+            if (isForm(arg(expr, 1), PLUS)) {
+                expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null));
+            }
+        } else if (isForm(expr, MINUS)) {
+            if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS)) {
+                expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null));
+            }
+        } else if (isForm(expr, TIMES)) {
+            if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS) || isForm(arg(expr, 1), TIMES) ||
+                            isForm(arg(expr, 1), DIVIDE)) {
+                expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null));
+            }
+            if (isForm(arg(expr, 0), MINUS) || isForm(arg(expr, 0), MINUS)) {
+                expr = setArg(expr, 0, newCall(LEFT_PAREN, arg(expr, 0), null));
+            }
+        } else if (isForm(expr, DIVIDE)) {
+            if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS) || isForm(arg(expr, 1), TIMES) ||
+                            isForm(arg(expr, 1), DIVIDE)) {
+                expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null));
+            }
+            if (isForm(arg(expr, 0), PLUS) || isForm(arg(expr, 0), MINUS)) {
+                expr = setArg(expr, 0, newCall(LEFT_PAREN, arg(expr, 0), null));
+            }
+        } else if (isForm(expr, POWER)) {
+            if (isForm(arg(expr, 0), POWER)) {
+                expr = setArg(expr, 0, newCall(LEFT_PAREN, arg(expr, 0), null));
+            }
+            if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS) || isForm(arg(expr, 1), TIMES) ||
+                            isForm(arg(expr, 1), DIVIDE)) {
+                expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null));
+            }
+        }
+        return (RSyntaxNode) expr;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..8dc3708ecd3527565a524513b83072f1e4407a53
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java
@@ -0,0 +1,408 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2013,  The R Core Team
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.stats.deriv;
+
+import static com.oracle.truffle.r.library.stats.deriv.Deriv.*;
+
+import com.oracle.truffle.r.nodes.access.ConstantNode;
+import com.oracle.truffle.r.runtime.RDeparse;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
+
+//Transcribed from GnuR, library/stats/src/deriv.c
+
+public class DerivVisitor extends RSyntaxVisitor<RSyntaxElement> {
+
+    private final String var;
+
+    DerivVisitor(String var) {
+        this.var = var;
+    }
+
+    @Override
+    protected RSyntaxElement visit(RSyntaxCall call) {
+        String functionName = getFunctionName(call);
+        assert Utils.isInterned(functionName);
+
+        RSyntaxElement arg0 = call.getSyntaxArguments()[0];
+        RSyntaxElement arg1 = call.getSyntaxArguments().length > 1 ? call.getSyntaxArguments()[1] : null;
+
+        if (functionName == LEFT_PAREN) {
+            return accept(arg0);
+        }
+
+        if (functionName == PLUS) {
+            if (call.getSyntaxArguments().length == 1) {
+                return accept(arg0);
+            } else {
+                return simplify(PLUS, accept(arg0), accept(arg1));
+            }
+        }
+
+        if (functionName == MINUS) {
+            if (call.getSyntaxArguments().length == 1) {
+                return simplify(MINUS, accept(arg0), null);
+            } else {
+                return simplify(MINUS, accept(arg0), accept(arg1));
+            }
+        }
+
+        if (functionName == TIMES) {
+            return simplify(PLUS, simplify(TIMES, accept(arg0), cloneElement(arg1)),
+                            simplify(TIMES, cloneElement(arg0), accept(arg1)));
+        }
+
+        if (functionName == DIVIDE) {
+            return simplify(MINUS,
+                            simplify(DIVIDE, accept(arg0), cloneElement(arg1)),
+                            simplify(DIVIDE,
+                                            simplify(TIMES, cloneElement(arg0), accept(arg1)),
+                                            simplify(POWER, cloneElement(arg1), ConstantNode.create(2.))));
+        }
+
+        if (functionName == POWER) {
+            if (isNumeric(arg1)) {
+                return simplify(TIMES,
+                                arg1,
+                                simplify(TIMES,
+                                                accept(arg0),
+                                                simplify(POWER, cloneElement(arg0), decDouble(arg1))));
+
+            } else {
+                // (a^b)' = a^(b-1).b.a' + a^b.log(a).b'
+                RSyntaxElement expr1 = simplify(TIMES,
+                                simplify(POWER,
+                                                arg0,
+                                                simplify(MINUS, cloneElement(arg1), ConstantNode.create(1.))),
+                                simplify(TIMES, cloneElement(arg1), accept(arg0)));
+
+                RSyntaxElement expr2 = simplify(TIMES,
+                                simplify(POWER, cloneElement(arg0), cloneElement(arg1)),
+                                simplify(TIMES,
+                                                simplify(LOG, cloneElement(arg0), null),
+                                                accept(arg1)));
+                return simplify(PLUS, expr1, expr2);
+            }
+        }
+
+        if (functionName == EXP) {
+            return simplify(TIMES, cloneElement(call), accept(arg0));
+        }
+
+        if (functionName == LOG) {
+            if (call.getSyntaxArguments().length != 1) {
+                throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, "only single-argument calls are supported");
+            }
+            return simplify(DIVIDE, accept(arg0), cloneElement(arg0));
+        }
+
+        if (functionName == COS) {
+            return simplify(TIMES,
+                            simplify(SIN, cloneElement(arg0), null),
+                            simplify(MINUS, accept(arg0), null));
+        }
+
+        if (functionName == SIN) {
+            return simplify(TIMES,
+                            simplify(COS, cloneElement(arg0), null),
+                            accept(arg0));
+        }
+
+        if (functionName == TAN) {
+            return simplify(DIVIDE,
+                            accept(arg0),
+                            simplify(POWER,
+                                            simplify(COS, cloneElement(arg0), null),
+                                            ConstantNode.create(2.)));
+        }
+
+        if (functionName == COSH) {
+            return simplify(TIMES,
+                            simplify(SINH, cloneElement(arg0), null),
+                            accept(arg0));
+        }
+
+        if (functionName == SINH) {
+            return simplify(TIMES,
+                            simplify(COSH, cloneElement(arg0), null),
+                            accept(arg0));
+        }
+
+        if (functionName == TANH) {
+            return simplify(DIVIDE,
+                            accept(arg0),
+                            simplify(POWER,
+                                            simplify(COSH, cloneElement(arg0), null),
+                                            ConstantNode.create(2.)));
+        }
+
+        if (functionName == SQRT) {
+            return accept(simplify(POWER, cloneElement(arg0), ConstantNode.create(0.5)));
+        }
+
+        if (functionName == PNORM) {
+            return simplify(TIMES,
+                            simplify(DNORM, cloneElement(arg0), null),
+                            accept(arg0));
+        }
+
+        if (functionName == DNORM) {
+            return simplify(TIMES,
+                            simplify(MINUS, cloneElement(arg0), null),
+                            simplify(TIMES,
+                                            simplify(DNORM, cloneElement(arg0), null),
+                                            accept(arg0)));
+        }
+
+        if (functionName == ASIN) {
+            return simplify(DIVIDE,
+                            accept(arg0),
+                            simplify(SQRT,
+                                            simplify(MINUS,
+                                                            ConstantNode.create(1.),
+                                                            simplify(POWER, cloneElement(arg0), ConstantNode.create(2.))),
+                                            null));
+        }
+
+        if (functionName == ACOS) {
+            return simplify(MINUS,
+                            simplify(DIVIDE,
+                                            accept(arg0),
+                                            simplify(SQRT,
+                                                            simplify(MINUS,
+                                                                            ConstantNode.create(1.),
+                                                                            simplify(POWER, cloneElement(arg0), ConstantNode.create(2.))),
+                                                            null)),
+                            null);
+        }
+
+        if (functionName == ATAN) {
+            return simplify(DIVIDE,
+                            accept(arg0),
+                            simplify(PLUS,
+                                            ConstantNode.create(1.),
+                                            simplify(POWER, cloneElement(arg0), ConstantNode.create(2.))));
+        }
+
+        if (functionName == LGAMMA) {
+            return simplify(TIMES,
+                            accept(arg0),
+                            simplify(DIGAMMA, cloneElement(arg0), null));
+        }
+
+        if (functionName == GAMMA) {
+            return simplify(TIMES,
+                            accept(arg0),
+                            simplify(TIMES, cloneElement(call),
+                                            simplify(DIGAMMA, cloneElement(arg0), null)));
+        }
+
+        if (functionName == DIGAMMA) {
+            return simplify(TIMES,
+                            accept(arg0),
+                            simplify(TRIGAMMA, cloneElement(arg0), null));
+        }
+
+        if (functionName == TRIGAMMA) {
+            return simplify(TIMES,
+                            accept(arg0),
+                            simplify(PSIGAMMA, cloneElement(arg0), ConstantNode.create(2)));
+        }
+
+        if (functionName == PSIGAMMA) {
+            if (call.getSyntaxArguments().length == 1) {
+                return simplify(TIMES,
+                                accept(arg0),
+                                simplify(PSIGAMMA, cloneElement(arg0), ConstantNode.create(1)));
+            } else if (isIntegerOrDouble(arg1)) {
+                return simplify(TIMES,
+                                accept(arg0),
+                                simplify(PSIGAMMA, cloneElement(arg0), incInteger(arg1)));
+            } else {
+                return simplify(TIMES,
+                                accept(arg0),
+                                simplify(PSIGAMMA,
+                                                cloneElement(arg0),
+                                                simplify(PLUS, cloneElement(arg1), ConstantNode.create(1))));
+            }
+        }
+
+        throw RError.error(RError.SHOW_CALLER, RError.Message.NOT_IN_DERIVATIVE_TABLE, RDeparse.deparseSyntaxElement(call.getSyntaxLHS()));
+    }
+
+    @Override
+    protected RSyntaxElement visit(RSyntaxConstant element) {
+        return ConstantNode.create(0.);
+    }
+
+    @Override
+    protected RSyntaxElement visit(RSyntaxLookup element) {
+        double dVal = element.getIdentifier().equals(var) ? 1 : 0;
+        return ConstantNode.create(dVal);
+    }
+
+    @Override
+    protected RSyntaxElement visit(RSyntaxFunction element) {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    private RSyntaxElement simplify(String functionName, RSyntaxElement arg1, RSyntaxElement arg2) {
+        if (functionName == PLUS) {
+            if (arg2 == null) {
+                return arg1;
+            } else if (isZero(arg1)) {
+                return arg2;
+            } else if (isZero(arg2)) {
+                return arg1;
+            } else if (isUminus(arg1)) {
+                return simplify(MINUS, arg2, arg(arg1, 0));
+            } else if (isUminus(arg2)) {
+                return simplify(MINUS, arg1, arg(arg2, 0));
+            } else {
+                return newCall(PLUS, arg1, arg2);
+            }
+        } else if (functionName == MINUS) {
+            if (arg2 == null) {
+                if (isZero(arg1)) {
+                    return ConstantNode.create(0.);
+                } else if (isUminus(arg1)) {
+                    return arg(arg1, 0);
+                } else {
+                    return newCall(MINUS, arg1, arg2);
+                }
+            } else {
+                if (isZero(arg2)) {
+                    return arg1;
+                } else if (isZero(arg1)) {
+                    return simplify(MINUS, arg2, null);
+                } else if (isUminus(arg1)) {
+                    return simplify(MINUS,
+                                    simplify(PLUS, arg(arg1, 0), arg2),
+                                    null);
+                } else if (isUminus(arg2)) {
+                    return simplify(PLUS, arg1, arg(arg2, 0));
+                } else {
+                    return newCall(MINUS, arg1, arg2);
+                }
+            }
+        } else if (functionName == TIMES) {
+            if (isZero(arg1) || isZero(arg2)) {
+                return ConstantNode.create(0.);
+            } else if (isOne(arg1)) {
+                return arg2;
+            } else if (isOne(arg2)) {
+                return arg1;
+            } else if (isUminus(arg1)) {
+                return simplify(MINUS, simplify(TIMES, arg(arg1, 0), arg2), null);
+            } else if (isUminus(arg2)) {
+                return simplify(MINUS, simplify(TIMES, arg1, arg(arg2, 0)), null);
+            } else {
+                return newCall(TIMES, arg1, arg2);
+            }
+        } else if (functionName == DIVIDE) {
+            if (isZero(arg1)) {
+                return ConstantNode.create(0.);
+            } else if (isZero(arg2)) {
+                return ConstantNode.create(RRuntime.DOUBLE_NA);
+            } else if (isOne(arg2)) {
+                return arg1;
+            } else if (isUminus(arg1)) {
+                return simplify(MINUS, simplify(DIVIDE, arg(arg1, 0), arg2), null);
+            } else if (isUminus(arg2)) {
+                return simplify(MINUS, simplify(DIVIDE, arg1, arg(arg2, 0)), null);
+            } else {
+                return newCall(DIVIDE, arg1, arg2);
+            }
+        } else if (functionName == POWER) {
+            if (isZero(arg2)) {
+                return ConstantNode.create(1.);
+            } else if (isZero(arg1)) {
+                return ConstantNode.create(0.);
+            } else if (isOne(arg1)) {
+                return ConstantNode.create(1.);
+            } else if (isOne(arg2)) {
+                return arg1;
+            } else {
+                return newCall(POWER, arg1, arg2);
+            }
+        } else if (functionName == EXP) {
+            // FIXME: simplify exp(lgamma( E )) = gamma( E )
+            return newCall(EXP, arg1, null);
+        } else if (functionName == LOG) {
+            // FIXME: simplify log(gamma( E )) = lgamma( E )
+            return newCall(LOG, arg1, null);
+        } else if (functionName == COS || functionName == SIN || functionName == TAN || functionName == COSH || functionName == SINH || functionName == TANH || functionName == SQRT ||
+                        functionName == PNORM || functionName == DNORM || functionName == ASIN || functionName == ACOS || functionName == ATAN || functionName == GAMMA || functionName == LGAMMA ||
+                        functionName == DIGAMMA || functionName == TRIGAMMA || functionName == PSIGAMMA) {
+            return newCall(functionName, arg1, arg2);
+        } else {
+            return ConstantNode.create(RRuntime.DOUBLE_NA);
+        }
+    }
+
+    private static boolean isIntegerOrDouble(RSyntaxElement elem) {
+        if (elem instanceof RSyntaxConstant) {
+            Object val = ((RSyntaxConstant) elem).getValue();
+            return val instanceof Integer || val instanceof Double;
+        } else {
+            return false;
+        }
+    }
+
+    private static boolean isUminus(RSyntaxElement elem) {
+        if (elem instanceof RSyntaxCall && MINUS == getFunctionName(elem)) {
+            RSyntaxElement[] args = ((RSyntaxCall) elem).getSyntaxArguments();
+            switch (args.length) {
+                case 1:
+                    return true;
+                case 2:
+                    return false;
+                default:
+                    throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, "invalid form in unary minus check");
+            }
+        } else {
+            return false;
+        }
+    }
+
+    private static boolean isNumeric(RSyntaxElement elem) {
+        if (elem instanceof RSyntaxConstant) {
+            Object val = ((RSyntaxConstant) elem).getValue();
+            return val instanceof Integer || val instanceof Double || val instanceof Byte;
+        } else {
+            return false;
+        }
+    }
+
+    private static RSyntaxConstant decDouble(RSyntaxElement elem) {
+        assert elem instanceof RSyntaxConstant;
+        assert ((RSyntaxConstant) elem).getValue() instanceof Number;
+        Number n = (Number) ((RSyntaxConstant) elem).getValue();
+        return ConstantNode.create(n.doubleValue() - 1);
+    }
+
+    private static RSyntaxConstant incInteger(RSyntaxElement elem) {
+        assert elem instanceof RSyntaxConstant;
+        assert ((RSyntaxConstant) elem).getValue() instanceof Number;
+        Number n = (Number) ((RSyntaxConstant) elem).getValue();
+        return ConstantNode.create(n.intValue() + 1);
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index 037a66f6f7d9034bd65102b4af1278fc46b53cc2..ab28e791fd8d730b36e6b70e815fb86459e08692 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -55,6 +55,8 @@ import com.oracle.truffle.r.library.stats.RandFunctionsNodes.RandFunction3Node;
 import com.oracle.truffle.r.library.stats.SignrankFreeNode;
 import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineCoefNodeGen;
 import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineEvalNodeGen;
+import com.oracle.truffle.r.library.stats.deriv.D;
+import com.oracle.truffle.r.library.stats.deriv.Deriv;
 import com.oracle.truffle.r.library.stats.StatsFunctionsNodes;
 import com.oracle.truffle.r.library.stats.WilcoxFreeNode;
 import com.oracle.truffle.r.library.tools.C_ParseRdNodeGen;
@@ -744,6 +746,11 @@ public class CallAndExternalFunctions {
             switch (name) {
                 case "compcases":
                     return new CompleteCases();
+                // stats
+                case "doD":
+                    return D.create();
+                case "deriv":
+                    return Deriv.create();
                 // utils
                 case "countfields":
                     return CountFieldsNodeGen.create();
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
index 8b6d15fd217dab5b26a49b9ba64c163f26c7e3c6..98eb067b7a6a144ec15572ed5ce698a971c85cd2 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
@@ -101,6 +101,7 @@ public class ExtBuiltinsList {
                     com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_getGenericNodeGen.class,
                     com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_nextMethodCallNodeGen.class,
                     com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_externalPtrPrototypeObjectNodeGen.class,
+                    com.oracle.truffle.r.library.stats.deriv.DerivNodeGen.class,
     };
 
     @SuppressWarnings("unchecked")
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
index 76fb3d04577b1188b8cbea518df1d6cc276afd4f..ccaa151114c738a42ee2174ab5a8ab647be51b32 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
@@ -22,6 +22,12 @@
  */
 package com.oracle.truffle.r.nodes.test;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -30,6 +36,7 @@ import org.junit.Test;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ScalarValue;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.DoubleFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.MissingFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter;
@@ -42,6 +49,7 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
 import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardedValuesAnalyser;
 import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResult;
 import com.oracle.truffle.r.runtime.RType;
@@ -406,4 +414,26 @@ public class ForwardedValuesAnalyserTest {
         assertFalse(result.isStringForwarded());
         assertFalse(result.isMissingForwarded());
     }
+
+    @Test
+    public void testReturnIfWithTrueBranchChain() {
+        //@formatter:off
+        PipelineStep<?, ?> findFirstBoolean = new CoercionStep<>(RType.Logical, false).setNext(new FindFirstStep<>(null, Byte.class, null)).setNext(new MapStep<>(new MapByteToBoolean(false)));
+        PipelineStep<?, ?> firstStep = new MapIfStep<>(new RTypeFilter<>(RType.Logical), // the condition
+                        findFirstBoolean, null, true);
+        //@formatter:on
+
+        ForwardedValuesAnalyser fwdAn = new ForwardedValuesAnalyser();
+        ForwardingAnalysisResult result = fwdAn.analyse(firstStep);
+        // TODO: change it to the positive assertion when the selected mappers (such as
+        // MapByteToBoolean) are supported
+        assertFalse(result.isLogicalForwarded());
+        assertTrue(result.logicalForwarded.mapper instanceof MapByteToBoolean);
+        assertTrue(result.isDoubleForwarded());
+        assertTrue(result.isIntegerForwarded());
+        assertTrue(result.isNullForwarded());
+        assertTrue(result.isStringForwarded());
+        assertTrue(result.isMissingForwarded());
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
index c4f1c1b1027b5e5ecf2f0b8896461261a3c1959b..2ab3ac955ae37a9d70be769c8dc9672812c3dce1 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
@@ -431,13 +431,14 @@ public class RBuiltinDiagnostics {
             print(1, "\nUnhandled argument combinations: " + nonCoveredArgsSet.size());
             print(1, "");
 
-            printDeadSpecs();
-
             if (diagSuite.diagConfig.verbose) {
                 for (List<Type> uncoveredArgs : nonCoveredArgsSet) {
                     print(1, uncoveredArgs.stream().map(t -> typeName(t)).collect(Collectors.toList()));
                 }
             }
+            print(1, "");
+
+            printDeadSpecs();
         }
 
         private void printBuiltinHeader(int level) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index da3d7e2cdac4f5c63b62551ddf169dc28594d37f..61b20ae0af9b73459e1bbf93c03c203e48c9e8db 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -426,6 +426,10 @@ public final class CastBuilder {
             return new NotNAStep<>(null, null);
         }
 
+        public static <T> PipelineStep<T, T> boxPrimitive() {
+            return new PipelineStep.BoxPrimitiveStep<>();
+        }
+
         public static NullFilter nullValue() {
             return NullFilter.INSTANCE;
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java
index a59b7c04358ce5fb1082ad0ce8fc5e88288ccd3d..c8fb811228400ddc74a78045c5d8bb38f83da2cd 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java
@@ -39,7 +39,7 @@ public abstract class ForwardingStatus {
     };
     public static final ForwardingStatus FORWARDED = new Forwarded(null);
 
-    final Mapper<?, ?> mapper;
+    public final Mapper<?, ?> mapper;
     private final byte flag;
 
     protected ForwardingStatus(byte flag, Mapper<?, ?> mapper) {
@@ -97,7 +97,7 @@ public abstract class ForwardingStatus {
     }
 
     ForwardingStatus or(ForwardingStatus other) {
-        return fromFlag(or(this.flag, other.flag));
+        return fromFlag(or(this.flag, other.flag), this.mapper != null ? this.mapper : other.mapper);
     }
 
     ForwardingStatus not() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 12d944ccc087bbfe42d0fcd5d2124de5af982738..a73c50c1f77bbaeeee28f2096cb40fe1c101214a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -847,7 +847,12 @@ public final class RError extends RuntimeException {
         TRUNCATE_NOT_ENABLED("truncation not enabled for this connection"),
         TRUNCATE_UNSUPPORTED_FOR_CONN("cannot truncate connection: %s"),
         INCOMPLETE_STRING_AT_EOF_DISCARDED("incomplete string at end of file has been discarded"),
-        INVALID_CHANNEL_OBJECT("invalid channel object type: %s");
+        INVALID_CHANNEL_OBJECT("invalid channel object type: %s"),
+        INVALID_TAG("invalid tag"),
+        INVALID_VARIABLE_NAMES("invalid variable names"),
+        INVALID_EXPRESSION("invalid expression in '%s'"),
+        INVALID_EXPRESSION_TYPE("expression must not be type '%s'"),
+        NOT_IN_DERIVATIVE_TABLE("Function '%s' is not in the derivatives table");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
index 45eb98dceacf4427936a8021a8802062e44c5a97..50b52b7a7ef0e93896dfca6e108a376bda383a04 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -197,4 +197,11 @@ public interface RCodeBuilder<T> {
     default T call(SourceSection source, T lhs, T argument1, T argument2, T argument3) {
         return call(source, lhs, Arrays.asList(argument(argument1), argument(argument2), argument(argument3)));
     }
+
+    /**
+     * Helper function: create a call with four unnamed arguments.
+     */
+    default T call(SourceSection source, T lhs, T argument1, T argument2, T argument3, T argument4) {
+        return call(source, lhs, Arrays.asList(argument(argument1), argument(argument2), argument(argument3), argument(argument4)));
+    }
 }
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 f263e95c09ba7a7061c57e8701408ed1807fbfc9..5fc5fb2db8221b3e3d75f80c919c2a45921cac57 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
@@ -143,6 +143,31 @@ Error in Conj(as.raw(12)) : non-numeric argument to function
 attr(,"foo")
 [1] "foo"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
+#(df <- D(1, "x"));df(0)
+[1] 0
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
+#(df <- D(expression(x^2*sin(x)), "x"));df(0)
+2 * x * sin(x) + x^2 * cos(x)
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
+#(df <- D(quote(x^2*sin(x)), "x"));df(0)
+2 * x * sin(x) + x^2 * cos(x)
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
+#g<-quote(x^2);(df <- D(g, "x"));df(0)
+2 * x
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
+#x<-1;(df <- D(x, "x"));df(0)
+[1] 0
+Error in df(0) : argument "df1" is missing, with no default
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Date2POSIXlt.testDate2POSIXlt1#
 #argv <- list(structure(c(14712, 14712), class = 'Date')); .Internal(Date2POSIXlt(argv[[1]]))
 [1] "2010-04-13 UTC" "2010-04-13 UTC"
@@ -4827,11 +4852,11 @@ numeric(0)
 #argv <- list(structure(list(sec = 0, min = 0L, hour = 0L, mday = 22:27, mon = 3L, year = 108L, wday = 2L, yday = 112L, isdst = -1L), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt'), tzone = 'GMT'), 'GMT'); .Internal(as.POSIXct(argv[[1]], argv[[2]]))
 [1] 1208822400 1208908800 1208995200 1209081600 1209168000 1209254400
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#Output.MayIgnoreErrorContext#
 #.Internal(as.POSIXlt(, 1))
 Error in .Internal(as.POSIXlt(, 1)) : argument 1 is empty
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#Output.MayIgnoreErrorContext#
 #.Internal(as.POSIXlt(2, ))
 Error in .Internal(as.POSIXlt(2, )) : argument 2 is empty
 
@@ -9310,11 +9335,11 @@ Error in bitwOr(c(1, 2, 3, 4), c(3 + (0+3i))) :
 [25]   -33554432   -67108864  -134217728  -268435456  -536870912 -1073741824
 [31]          NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#Output.MayIgnoreErrorContext#
 #{ .Internal(bitwiseShiftL(, 1))}
 Error in .Internal(bitwiseShiftL(, 1)) : argument 1 is empty
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#Output.MayIgnoreErrorContext#
 #{ .Internal(bitwiseShiftL(200, ))}
 Error in .Internal(bitwiseShiftL(200, )) : argument 2 is empty
 
@@ -9357,11 +9382,11 @@ In bitwShiftL(c(3, 2, 4), c(3 + (0+3i))) :
 #{ bitwShiftL(c(8,4,2), NULL) }
 integer(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#Output.MayIgnoreErrorContext#
 #{ .Internal(bitwiseShiftR(, 1))}
 Error in .Internal(bitwiseShiftR(, 1)) : argument 1 is empty
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#Output.MayIgnoreErrorContext#
 #{ .Internal(bitwiseShiftR(200, ))}
 Error in .Internal(bitwiseShiftR(200, )) : argument 2 is empty
 
@@ -12944,15 +12969,15 @@ function() 42
 #{ x=1;class(x)<-"character"; x}
 [1] "1"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext#
 #{`class<-`(, "foo") }
 Error in `class<-`(, "foo") : argument 1 is empty
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext#
 #{`class<-`(, ) }
 Error in `class<-`(, ) : argument 1 is empty
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext#
 #{`class<-`(NULL, "first") }
 Error: attempt to set an attribute on NULL
 
@@ -13077,7 +13102,7 @@ Error in class(x) <- "array" :
 #{x<-c(2+3i,4+5i);class(x)<-"a";class(x)<-"complex";x;}
 [1] 2+3i 4+5i
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext#
 #{x=1; `class<-`(x, ) }
 Error in `class<-`(x, ) : argument 2 is empty
 
@@ -16782,6 +16807,2495 @@ invalid 'cutoff' value for 'deparse', using default
 #argv <- list(quote(utils::str), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "utils::str"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)*(x+2), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- x + 2
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- .expr2 + .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)*(x+2), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- x + 2
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- .expr2 + .expr1
+    .hessian[, "x", "x"] <- 1 + 1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr4 <- x + 2 * (x - 1)
+    .value <- .expr1 * .expr4
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- .expr4 + .expr1 * (1 + 2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr4 <- x + 2 * (x - 1)
+    .expr6 <- 1 + 2
+    .value <- .expr1 * .expr4
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- .expr4 + .expr1 * .expr6
+    .hessian[, "x", "x"] <- .expr6 + .expr6
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)+(x+2), c("x"), hessian=FALSE)
+expression({
+    .value <- x + 1 + (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1 + 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)+(x+2), c("x"), hessian=TRUE)
+expression({
+    .value <- x + 1 + (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1 + 1
+    .hessian[, "x", "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)-(x+2), c("x"), hessian=FALSE)
+expression({
+    .value <- x + 1 - (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1 - 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)-(x+2), c("x"), hessian=TRUE)
+expression({
+    .value <- x + 1 - (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1 - 1
+    .hessian[, "x", "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)/(x+2), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- x + 2
+    .value <- .expr1/.expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/.expr2 - .expr1/.expr2^2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#Output.IgnoreWhitespace#
+#deriv(~ (x+1)/(x+2), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- x + 2
+    .expr5 <- .expr2^2
+    .expr8 <- 1/.expr5
+    .value <- .expr1/.expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/.expr2 - .expr1/.expr5
+    .hessian[, "x", "x"] <- -(.expr8 + (.expr8 - .expr1 * (2 *
+        .expr2)/.expr5^2))
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#Ignored.OutputFormatting#
+#deriv(~ (x+1)^(x+2), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- x + 2
+    .expr3 <- .expr1^.expr2
+    .value <- .expr3
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- .expr1^(.expr2 - 1) * .expr2 + .expr3 * log(.expr1)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ -(x+1)+(x+2), c("x"), hessian=FALSE)
+expression({
+    .value <- -(x + 1) + (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1 - 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ -(x+1)+(x+2), c("x"), hessian=TRUE)
+expression({
+    .value <- -(x + 1) + (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1 - 1
+    .hessian[, "x", "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ -(x+1)-(x+2), c("x"), hessian=FALSE)
+expression({
+    .value <- -(x + 1) - (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- -(1 + 1)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ -(x+1)-(x+2), c("x"), hessian=TRUE)
+expression({
+    .value <- -(x + 1) - (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- -(1 + 1)
+    .hessian[, "x", "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ 1, c("x"), hessian=FALSE)
+expression({
+    .value <- 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ 1, c("x"), hessian=TRUE)
+expression({
+    .value <- 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ 2*x, c("x"), hessian=FALSE)
+expression({
+    .value <- 2 * x
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ 2*x, c("x"), hessian=TRUE)
+expression({
+    .value <- 2 * x
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#Ignored.OutputFormatting#
+#deriv(~ 2/x, c("x"), hessian=FALSE)
+expression({
+    .value <- 2/x
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- -(2/x^2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x+1, c("x"), hessian=FALSE)
+expression({
+    .value <- x + 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x+1, c("x"), hessian=TRUE)
+expression({
+    .value <- x + 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x, c("x"), hessian=FALSE)
+expression({
+    .value <- x
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x, c("x"), hessian=TRUE)
+expression({
+    .value <- x
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x/2, c("x"), hessian=FALSE)
+expression({
+    .value <- x/2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x/2, c("x"), hessian=TRUE)
+expression({
+    .value <- x/2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/2
+    .hessian[, "x", "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x^2, c("x"), hessian=FALSE)
+expression({
+    .value <- x^2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x^2, c("x"), hessian=TRUE)
+expression({
+    .value <- x^2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 2 * x
+    .hessian[, "x", "x"] <- 2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)*(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 2
+attr(,"gradient")
+     x
+[1,] 3
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)*(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 2
+attr(,"gradient")
+     x
+[1,] 3
+attr(,"hessian")
+, , x
+
+     x
+[1,] 2
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -2
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -2
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 6
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)+(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 3
+attr(,"gradient")
+     x
+[1,] 2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)+(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 3
+attr(,"gradient")
+     x
+[1,] 2
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)-(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -1
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)-(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -1
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)/(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+        x
+[1,] 0.25
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)/(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+        x
+[1,] 0.25
+attr(,"hessian")
+, , x
+
+         x
+[1,] -0.25
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)^(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ -(x+1)+(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ -(x+1)+(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ -(x+1)-(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -3
+attr(,"gradient")
+      x
+[1,] -2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ -(x+1)-(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -3
+attr(,"gradient")
+      x
+[1,] -2
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ 1, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ 1, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ 2*x, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ 2*x, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 2
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ 2/x, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] Inf
+attr(,"gradient")
+        x
+[1,] -Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x+1, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x+1, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x/2, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+       x
+[1,] 0.5
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x/2, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+       x
+[1,] 0.5
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x^2, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x^2, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+     x
+[1,] 2
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ (x+1)*(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- .expr2
+    .grad[, "y"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ (x+1)*(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr2
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 1
+    .grad[, "y"] <- .expr1
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr4 <- y + 2 * (x - 1)
+    .value <- .expr1 * .expr4
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- .expr4 + .expr1 * 2
+    .grad[, "y"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr4 <- y + 2 * (x - 1)
+    .value <- .expr1 * .expr4
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr4 + .expr1 * 2
+    .hessian[, "x", "x"] <- 2 + 2
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 1
+    .grad[, "y"] <- .expr1
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ (x+1)-(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .value <- x + 1 - (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- 1
+    .grad[, "y"] <- -1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ (x+1)-(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .value <- x + 1 - (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- 1
+    .grad[, "y"] <- -1
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ (x+1)/(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .value <- .expr1/.expr2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- 1/.expr2
+    .grad[, "y"] <- -(.expr1/.expr2^2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ (x+1)/(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .expr5 <- .expr2^2
+    .value <- .expr1/.expr2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- 1/.expr2
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- -(1/.expr5)
+    .grad[, "y"] <- -(.expr1/.expr5)
+    .hessian[, "y", "y"] <- .expr1 * (2 * .expr2)/.expr5^2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ (x+1)^(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .expr3 <- .expr1^.expr2
+    .value <- .expr3
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- .expr1^(.expr2 - 1) * .expr2
+    .grad[, "y"] <- .expr3 * log(.expr1)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ (x+1)^(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .expr3 <- .expr1^.expr2
+    .expr4 <- .expr2 - 1
+    .expr5 <- .expr1^.expr4
+    .expr11 <- log(.expr1)
+    .expr15 <- .expr3 * .expr11
+    .value <- .expr3
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr5 * .expr2
+    .hessian[, "x", "x"] <- .expr1^(.expr4 - 1) * .expr4 * .expr2
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- .expr5 *
+        .expr11 * .expr2 + .expr5
+    .grad[, "y"] <- .expr15
+    .hessian[, "y", "y"] <- .expr15 * .expr11
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ -(x+1)+(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .value <- -(x + 1) + (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- -1
+    .grad[, "y"] <- 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ -(x+1)+(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .value <- -(x + 1) + (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- -1
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 0
+    .grad[, "y"] <- 1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ -(x+1)-(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .expr5 <- -1
+    .value <- -(x + 1) - (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- .expr5
+    .grad[, "y"] <- .expr5
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ -(x+1)-(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .expr5 <- -1
+    .value <- -(x + 1) - (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr5
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 0
+    .grad[, "y"] <- .expr5
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ 2*x*y, c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .value <- .expr1 * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- 2 * y
+    .grad[, "y"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ 2*x*y, c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- 2 * x
+    .value <- .expr1 * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- 2 * y
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 2
+    .grad[, "y"] <- .expr1
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ 2/x*y, c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- 2/x
+    .value <- .expr1 * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- -(2/x^2 * y)
+    .grad[, "y"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ 2/x*y, c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- 2/x
+    .expr3 <- x^2
+    .expr4 <- 2/.expr3
+    .value <- .expr1 * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- -(.expr4 * y)
+    .hessian[, "x", "x"] <- 2 * (2 * x)/.expr3^2 * y
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- -.expr4
+    .grad[, "y"] <- .expr1
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ x + y, c("x","y"), hessian=FALSE)
+expression({
+    .value <- x + y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- 1
+    .grad[, "y"] <- 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ x + y, c("x","y"), hessian=TRUE)
+expression({
+    .value <- x + y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- 1
+    .grad[, "y"] <- 1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ x*y, c("x","y"), hessian=FALSE)
+expression({
+    .value <- x * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- y
+    .grad[, "y"] <- x
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ x*y, c("x","y"), hessian=TRUE)
+expression({
+    .value <- x * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- y
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 1
+    .grad[, "y"] <- x
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ x/y/2, c("x","y"), hessian=FALSE)
+expression({
+    .value <- x/y/2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- 1/y/2
+    .grad[, "y"] <- -(x/y^2/2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ x/y/2, c("x","y"), hessian=TRUE)
+expression({
+    .expr5 <- y^2
+    .value <- x/y/2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- 1/y/2
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- -(1/.expr5/2)
+    .grad[, "y"] <- -(x/.expr5/2)
+    .hessian[, "y", "y"] <- x * (2 * y)/.expr5^2/2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ x^y, c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- x^y
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- x^(y - 1) * y
+    .grad[, "y"] <- .expr1 * log(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ x^y, c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- x^y
+    .expr2 <- y - 1
+    .expr3 <- x^.expr2
+    .expr9 <- log(x)
+    .expr13 <- .expr1 * .expr9
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr3 * y
+    .hessian[, "x", "x"] <- x^(.expr2 - 1) * .expr2 * y
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- .expr3 *
+        .expr9 * y + .expr3
+    .grad[, "y"] <- .expr13
+    .hessian[, "y", "y"] <- .expr13 * .expr9
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)*(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 2
+attr(,"gradient")
+     x y
+[1,] 2 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)*(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 2
+attr(,"gradient")
+     x y
+[1,] 2 1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 1
+
+, , y
+
+     x y
+[1,] 1 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] -2
+attr(,"gradient")
+     x y
+[1,] 0 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] -2
+attr(,"gradient")
+     x y
+[1,] 0 1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 4 1
+
+, , y
+
+     x y
+[1,] 1 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)-(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] -1
+attr(,"gradient")
+     x  y
+[1,] 1 -1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)-(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] -1
+attr(,"gradient")
+     x  y
+[1,] 1 -1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 0
+
+, , y
+
+     x y
+[1,] 0 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)/(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+       x     y
+[1,] 0.5 -0.25
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)/(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+       x     y
+[1,] 0.5 -0.25
+attr(,"hessian")
+, , x
+
+     x     y
+[1,] 0 -0.25
+
+, , y
+
+         x    y
+[1,] -0.25 0.25
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)^(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x y
+[1,] 2 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)^(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x y
+[1,] 2 0
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 2 1
+
+, , y
+
+     x y
+[1,] 1 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)^(y+2), c("x","y"), hessian=TRUE); x<-1; y<-1; eval(df)
+[1] 8
+attr(,"gradient")
+      x        y
+[1,] 12 5.545177
+attr(,"hessian")
+, , x
+
+      x        y
+[1,] 12 12.31777
+
+, , y
+
+            x        y
+[1,] 12.31777 3.843624
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ -(x+1)+(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+      x y
+[1,] -1 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ -(x+1)+(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+      x y
+[1,] -1 1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 0
+
+, , y
+
+     x y
+[1,] 0 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ -(x+1)-(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] -3
+attr(,"gradient")
+      x  y
+[1,] -1 -1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ -(x+1)-(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] -3
+attr(,"gradient")
+      x  y
+[1,] -1 -1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 0
+
+, , y
+
+     x y
+[1,] 0 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ 2*x*y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 0 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ 2*x*y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 0 0
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 2
+
+, , y
+
+     x y
+[1,] 2 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ 2/x*y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x   y
+[1,] NaN Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ 2/x*y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x   y
+[1,] NaN Inf
+attr(,"hessian")
+, , x
+
+       x    y
+[1,] NaN -Inf
+
+, , y
+
+        x y
+[1,] -Inf 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x + y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 1 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x + y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 1 1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 0
+
+, , y
+
+     x y
+[1,] 0 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x*y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 0 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x*y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 0 0
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 1
+
+, , y
+
+     x y
+[1,] 1 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x/y/2, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x   y
+[1,] Inf NaN
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x/y/2, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x   y
+[1,] Inf NaN
+attr(,"hessian")
+, , x
+
+     x    y
+[1,] 0 -Inf
+
+, , y
+
+        x   y
+[1,] -Inf NaN
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x^y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+       x    y
+[1,] NaN -Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x^y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+       x    y
+[1,] NaN -Inf
+attr(,"hessian")
+, , x
+
+       x   y
+[1,] NaN NaN
+
+, , y
+
+       x   y
+[1,] NaN Inf
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ acos(x), c("x"), hessian=FALSE)
+expression({
+    .value <- acos(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- -(1/sqrt(1 - x^2))
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ asin(x), c("x"), hessian=FALSE)
+expression({
+    .value <- asin(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/sqrt(1 - x^2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ asin(x), c("x"), hessian=TRUE)
+expression({
+    .expr3 <- 1 - x^2
+    .expr4 <- sqrt(.expr3)
+    .value <- asin(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/.expr4
+    .hessian[, "x", "x"] <- 0.5 * (2 * x * .expr3^-0.5)/.expr4^2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ atan(x), c("x"), hessian=FALSE)
+expression({
+    .value <- atan(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/(1 + x^2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ atan(x), c("x"), hessian=TRUE)
+expression({
+    .expr3 <- 1 + x^2
+    .value <- atan(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/.expr3
+    .hessian[, "x", "x"] <- -(2 * x/.expr3^2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ cos(x), c("x"), hessian=FALSE)
+expression({
+    .value <- cos(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- -sin(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ cos(x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- cos(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- -sin(x)
+    .hessian[, "x", "x"] <- -.expr1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ cosh(x), c("x"), hessian=FALSE)
+expression({
+    .value <- cosh(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- sinh(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ cosh(x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- cosh(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- sinh(x)
+    .hessian[, "x", "x"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ digamma(x), c("x"), hessian=FALSE)
+expression({
+    .value <- digamma(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- trigamma(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ dnorm(x), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- dnorm(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- -(x * .expr1)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ exp(x), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- exp(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ exp(x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- exp(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- .expr1
+    .hessian[, "x", "x"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ gamma(x), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- gamma(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- .expr1 * digamma(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ lgamma(x), c("x"), hessian=FALSE)
+expression({
+    .value <- lgamma(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- digamma(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ log(x), c("x"), hessian=FALSE)
+expression({
+    .value <- log(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/x
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ log(x), c("x"), hessian=TRUE)
+expression({
+    .value <- log(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/x
+    .hessian[, "x", "x"] <- -(1/x^2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ pnorm(x), c("x"), hessian=FALSE)
+expression({
+    .value <- pnorm(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- dnorm(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ pnorm(x), c("x"), hessian=TRUE)
+expression({
+    .expr2 <- dnorm(x)
+    .value <- pnorm(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- .expr2
+    .hessian[, "x", "x"] <- -(x * .expr2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ psigamma(x), c("x"), hessian=FALSE)
+expression({
+    .value <- psigamma(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- psigamma(x, 1L)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sin(x), c("x"), hessian=FALSE)
+expression({
+    .value <- sin(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sin(x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- sin(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- cos(x)
+    .hessian[, "x", "x"] <- -.expr1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sinh(x), c("x"), hessian=FALSE)
+expression({
+    .value <- sinh(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- cosh(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sinh(x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- sinh(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- cosh(x)
+    .hessian[, "x", "x"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sqrt(x), c("x"), hessian=FALSE)
+expression({
+    .value <- sqrt(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 0.5 * x^-0.5
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sqrt(x), c("x"), hessian=TRUE)
+expression({
+    .value <- sqrt(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 0.5 * x^-0.5
+    .hessian[, "x", "x"] <- 0.5 * (-0.5 * x^-1.5)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ tan(x), c("x"), hessian=FALSE)
+expression({
+    .value <- tan(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/cos(x)^2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ tan(x), c("x"), hessian=TRUE)
+expression({
+    .expr2 <- cos(x)
+    .expr3 <- .expr2^2
+    .value <- tan(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/.expr3
+    .hessian[, "x", "x"] <- 2 * (sin(x) * .expr2)/.expr3^2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ tanh(x), c("x"), hessian=FALSE)
+expression({
+    .value <- tanh(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/cosh(x)^2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ tanh(x), c("x"), hessian=TRUE)
+expression({
+    .expr2 <- cosh(x)
+    .expr3 <- .expr2^2
+    .value <- tanh(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/.expr3
+    .hessian[, "x", "x"] <- -(2 * (sinh(x) * .expr2)/.expr3^2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ trigamma(x), c("x"), hessian=FALSE)
+expression({
+    .value <- trigamma(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- psigamma(x, 2L)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ acos(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1.570796
+attr(,"gradient")
+      x
+[1,] -1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ asin(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ asin(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ atan(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ atan(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ cos(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ cos(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+      x
+[1,] -1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ cosh(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ cosh(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+     x
+[1,] 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented#
+#df <- deriv(~ digamma(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x
+[1,] Inf
+Warning message:
+In digamma(x) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ dnorm(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0.3989423
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ exp(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ exp(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented#
+#df <- deriv(~ gamma(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x
+[1,] NaN
+Warning messages:
+1: In gamma(x) : NaNs produced
+2: In digamma(x) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ lgamma(x), c("x"), hessian=FALSE); x<-0.5; eval(df)
+[1] 0.5723649
+attr(,"gradient")
+            x
+[1,] -1.96351
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ log(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.MissingWarning#
+#df <- deriv(~ log(x), c("x"), hessian=TRUE); x<--1; eval(df)
+[1] NaN
+attr(,"gradient")
+      x
+[1,] -1
+attr(,"hessian")
+, , x
+
+      x
+[1,] -1
+
+Warning message:
+In log(x) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ log(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+attr(,"hessian")
+, , x
+
+        x
+[1,] -Inf
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ log(x), c("x"), hessian=TRUE); x<-1; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+      x
+[1,] -1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ pnorm(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+             x
+[1,] 0.3989423
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ pnorm(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+             x
+[1,] 0.3989423
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented#
+#df <- deriv(~ psigamma(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x
+[1,] Inf
+Warning message:
+In psigamma(x) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sin(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sin(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sinh(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sinh(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sqrt(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+       x
+[1,] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sqrt(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+       x
+[1,] Inf
+attr(,"hessian")
+, , x
+
+        x
+[1,] -Inf
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tan(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tan(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tanh(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tanh(x), c("x"), hessian=TRUE); x<--1; eval(df)
+[1] -0.7615942
+attr(,"gradient")
+             x
+[1,] 0.4199743
+attr(,"hessian")
+, , x
+
+          x
+[1,] 0.6397
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tanh(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tanh(x), c("x"), hessian=TRUE); x<-1; eval(df)
+[1] 0.7615942
+attr(,"gradient")
+             x
+[1,] 0.4199743
+attr(,"hessian")
+, , x
+
+           x
+[1,] -0.6397
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented#
+#df <- deriv(~ trigamma(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] Inf
+attr(,"gradient")
+       x
+[1,] NaN
+Warning message:
+In psigamma(x, 2L) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#deriv(~ log(2*x), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .value <- log(.expr1)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2/.expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Ignored.OutputFormatting#
+#deriv(~ log(2*x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- 2 * x
+    .value <- log(.expr1)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 2/.expr1
+    .hessian[, "x", "x"] <- -(2 * 2/.expr1^2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#deriv(~ log(sin(2*x)), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .expr2 <- sin(.expr1)
+    .value <- log(.expr2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- cos(.expr1) * 2/.expr2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Output.IgnoreWhitespace#
+#deriv(~ log(sin(2*x)), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- 2 * x
+    .expr2 <- sin(.expr1)
+    .expr5 <- cos(.expr1) * 2
+    .value <- log(.expr2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- .expr5/.expr2
+    .hessian[, "x", "x"] <- -(.expr2 * 2 * 2/.expr2 + .expr5 *
+        .expr5/.expr2^2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Output.IgnoreWhitespace#
+#deriv(~ log(sin(2*x)*cos(x^2)), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .expr2 <- sin(.expr1)
+    .expr3 <- x^2
+    .expr4 <- cos(.expr3)
+    .expr5 <- .expr2 * .expr4
+    .value <- log(.expr5)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- (cos(.expr1) * 2 * .expr4 - .expr2 * (sin(.expr3) *
+        .expr1))/.expr5
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Output.IgnoreWhitespace#
+#deriv(~ pnorm(sin(2*x)^log(x+1)), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .expr2 <- sin(.expr1)
+    .expr3 <- x + 1
+    .expr4 <- log(.expr3)
+    .expr5 <- .expr2^.expr4
+    .value <- pnorm(.expr5)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- dnorm(.expr5) * (.expr2^(.expr4 - 1) * (.expr4 *
+        (cos(.expr1) * 2)) + .expr5 * (log(.expr2) * (1/.expr3)))
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ log(2*x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ log(2*x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+attr(,"hessian")
+, , x
+
+        x
+[1,] -Inf
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ log(sin(2*x)), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ log(sin(2*x)), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+attr(,"hessian")
+, , x
+
+       x
+[1,] NaN
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ log(sin(2*x)*cos(x^2)), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ pnorm(sin(2*x)^log(x+1)), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0.8413447
+attr(,"gradient")
+       x
+[1,] NaN
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testFunctionGenereration#Output.IgnoreWhitespace#
+#(df <- deriv(~x^2*sin(x), "x", function.arg=TRUE));df(0)
+function (x)
+{
+    .expr1 <- x^2
+    .expr2 <- sin(x)
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+}
+[1] 0
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testFunctionGenereration#Output.IgnoreWhitespace#
+#(df <- deriv(~x^2*sin(x), "x", function.arg=c("x")));df(0)
+function (x)
+{
+    .expr1 <- x^2
+    .expr2 <- sin(x)
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+}
+[1] 0
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testFunctionGenereration#Output.IgnoreWhitespace#
+#(df <- deriv(~x^2*sin(x), "x", function.arg=function(x=1){}));df(0)
+function (x = 1)
+{
+    .expr1 <- x^2
+    .expr2 <- sin(x)
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+}
+[1] 0
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression#Output.IgnoreWhitespace#
+#deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .expr4 <- log(.expr1) + sin(x)
+    .expr5 <- y^x
+    .expr6 <- exp(x)
+    .expr7 <- .expr5 * .expr6
+    .expr8 <- cos(.expr7)
+    .expr9 <- .expr4 * .expr8
+    .expr11 <- x^y
+    .expr13 <- x + y + 1
+    .expr15 <- x * y + .expr11/.expr13
+    .expr21 <- sin(.expr7)
+    .expr35 <- .expr11/.expr13^2
+    .value <- .expr9 * .expr15
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- ((2/.expr1 + cos(x)) * .expr8 - .expr4 *
+        (.expr21 * (.expr5 * log(y) * .expr6 + .expr7))) * .expr15 +
+        .expr9 * (y + (x^(y - 1) * y/.expr13 - .expr35))
+    .grad[, "y"] <- .expr9 * (x + (.expr11 * log(x)/.expr13 -
+        .expr35)) - .expr4 * (.expr21 * (y^(x - 1) * x * .expr6)) *
+        .expr15
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression#Ignored.OutputFormatting#
+#deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- 2 * x
+    .expr3 <- sin(x)
+    .expr4 <- log(.expr1) + .expr3
+    .expr5 <- y^x
+    .expr6 <- exp(x)
+    .expr7 <- .expr5 * .expr6
+    .expr8 <- cos(.expr7)
+    .expr9 <- .expr4 * .expr8
+    .expr11 <- x^y
+    .expr13 <- x + y + 1
+    .expr15 <- x * y + .expr11/.expr13
+    .expr19 <- 2/.expr1 + cos(x)
+    .expr21 <- sin(.expr7)
+    .expr22 <- log(y)
+    .expr23 <- .expr5 * .expr22
+    .expr24 <- .expr23 * .expr6
+    .expr25 <- .expr24 + .expr7
+    .expr26 <- .expr21 * .expr25
+    .expr28 <- .expr19 * .expr8 - .expr4 * .expr26
+    .expr30 <- y - 1
+    .expr31 <- x^.expr30
+    .expr32 <- .expr31 * y
+    .expr34 <- .expr13^2
+    .expr35 <- .expr11/.expr34
+    .expr37 <- y + (.expr32/.expr13 - .expr35)
+    .expr40 <- .expr28 * .expr37
+    .expr41 <- .expr19 * .expr26
+    .expr66 <- .expr32/.expr34
+    .expr71 <- .expr11 * (2 * .expr13)/.expr34^2
+    .expr77 <- log(x)
+    .expr78 <- .expr11 * .expr77
+    .expr81 <- x + (.expr78/.expr13 - .expr35)
+    .expr83 <- x - 1
+    .expr85 <- y^.expr83 * x
+    .expr86 <- .expr85 * .expr6
+    .expr87 <- .expr21 * .expr86
+    .expr89 <- .expr8 * .expr86
+    .expr108 <- .expr78/.expr34
+    .expr109 <- .expr108 - .expr71
+    .expr113 <- .expr4 * .expr87
+    .expr125 <- .expr113 * .expr81
+    .value <- .expr9 * .expr15
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr28 * .expr15 + .expr9 * .expr37
+    .hessian[, "x", "x"] <- .expr40 - (.expr41 + (.expr3 + 2 *
+        2/.expr1^2) * .expr8 + (.expr41 + .expr4 * (.expr8 *
+        .expr25 * .expr25 + .expr21 * (.expr23 * .expr22 * .expr6 +
+        .expr24 + .expr25)))) * .expr15 + (.expr40 + .expr9 *
+        (x^(.expr30 - 1) * .expr30 * y/.expr13 - .expr66 - (.expr66 -
+            .expr71)))
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- .expr28 *
+        .expr81 - (.expr19 * .expr87 + .expr4 * (.expr89 * .expr25 +
+        .expr21 * ((.expr85 * .expr22 + .expr5 * (1/y)) * .expr6 +
+            .expr86))) * .expr15 + (.expr9 * (1 + ((.expr31 *
+        .expr77 * y + .expr31)/.expr13 - .expr66 - .expr109)) -
+        .expr113 * .expr37)
+    .grad[, "y"] <- .expr9 * .expr81 - .expr113 * .expr15
+    .hessian[, "y", "y"] <- .expr9 * (.expr78 * .expr77/.expr13 -
+        .expr108 - .expr109) - .expr125 - (.expr4 * (.expr89 *
+        .expr86 + .expr21 * (y^(.expr83 - 1) * .expr83 * x *
+        .expr6)) * .expr15 + .expr125)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression#
+#df <- deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x   y
+[1,] NaN NaN
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression#
+#df <- deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x   y
+[1,] NaN NaN
+attr(,"hessian")
+, , x
+
+       x   y
+[1,] NaN NaN
+
+, , y
+
+       x   y
+[1,] NaN NaN
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs#
+#(df <- deriv(1, "x"));df(0)
+expression({
+    .value <- 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    .value
+})
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs#
+#(df <- deriv(expression(x^2*sin(x)), "x"));df(0)
+expression({
+    .expr1 <- x^2
+    .expr2 <- sin(x)
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs#
+#(df <- deriv(quote(x^2*sin(x)), "x"));df(0)
+expression({
+    .expr1 <- x^2
+    .expr2 <- sin(x)
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs#
+#g<-quote(x^2);(df <- deriv(g, "x"));df(0)
+expression({
+    .value <- x^2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x
+    attr(.value, "gradient") <- .grad
+    .value
+})
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs#
+#x<-1;(df <- deriv(x, "x"));df(0)
+expression({
+    .value <- 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    .value
+})
+Error in df(0) : argument "df1" is missing, with no default
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_det.testDet#
 #{ det(matrix(c(1,-3,4,-5),nrow=2)) }
 [1] 7
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java
new file mode 100644
index 0000000000000000000000000000000000000000..6fd2878571ecbc2930acd06ac4419c7daf4aa65e
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+public class TestBuiltin_D extends TestBase {
+
+    @Test
+    public void testD() {
+        assertEval("(df <- D(expression(x^2*sin(x)), \"x\"));df(0)");
+        assertEval("(df <- D(quote(x^2*sin(x)), \"x\"));df(0)");
+        assertEval("g<-quote(x^2);(df <- D(g, \"x\"));df(0)");
+        assertEval("(df <- D(1, \"x\"));df(0)");
+        assertEval("x<-1;(df <- D(x, \"x\"));df(0)");
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
new file mode 100644
index 0000000000000000000000000000000000000000..13eae8aaf36d8b65cd6a89324b32744c8ea6686c
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+import com.oracle.truffle.r.test.TestTrait;
+
+public class TestBuiltin_deriv extends TestBase {
+
+    final class DerivExpr {
+        final String expr;
+        final String assertedExpr;
+        final int dn;
+        final boolean hessian;
+
+        DerivExpr(String expr, int dn) {
+            this(expr, dn, false);
+        }
+
+        DerivExpr(String expr, int dn, boolean hessian) {
+            this.expr = expr;
+            this.dn = dn;
+            this.hessian = hessian;
+            String vars = dn == 1 ? "c(\"x\")" : "c(\"x\",\"y\")";
+            String h = hessian ? "TRUE" : "FALSE";
+            this.assertedExpr = "deriv(~ " + expr + ", " + vars + ", hessian=" + h + ")";
+        }
+
+        DerivEval derive() {
+            assertEval(assertedExpr);
+            return new DerivEval(this);
+        }
+
+        DerivEval derive(TestTrait trait) {
+            assertEval(trait, assertedExpr);
+            return new DerivEval(this);
+        }
+    }
+
+    final class DerivEval {
+        final DerivExpr de;
+        final String assertedExpr;
+
+        DerivEval(DerivExpr de) {
+            this.de = de;
+            String vars = de.dn == 1 ? "x<-%s" : "x<-%s; y<-%s";
+            this.assertedExpr = "df <- " + de.assertedExpr + "; " + vars + "; eval(df)";
+        }
+
+        DerivEval eval(Object... vals) {
+            String ex = String.format(this.assertedExpr, vals);
+            assertEval(ex);
+            return this;
+        }
+
+        DerivEval eval(TestTrait trait, Object... vals) {
+            String ex = String.format(this.assertedExpr, vals);
+            assertEval(trait, ex);
+            return this;
+        }
+
+        DerivExpr withHessian() {
+            return new DerivExpr(de.expr, de.dn, true);
+        }
+    }
+
+    private DerivExpr deriv1(String expr) {
+        return new DerivExpr(expr, 1);
+    }
+
+    private DerivExpr deriv2(String expr) {
+        return new DerivExpr(expr, 2);
+    }
+
+    private void assertDerivAndEval1(String expr) {
+        deriv1(expr).derive().eval(0).withHessian().derive().eval(0);
+    }
+
+    private void assertDerivAndEval1(TestTrait trait, String expr) {
+        deriv1(expr).derive(trait).eval(0, 0);
+    }
+
+    private DerivEval assertDeriv1(String expr) {
+        return deriv1(expr).derive();
+    }
+
+    private void assertDerivAndEval2(String expr) {
+        deriv2(expr).derive().eval(0, 0).withHessian().derive().eval(0, 0);
+    }
+
+    @Test
+    public void testDeriveBasicExpressions1() {
+        assertDerivAndEval1("1");
+        assertDerivAndEval1("x");
+        assertDerivAndEval1("x+1");
+        assertDerivAndEval1("2*x");
+        assertDerivAndEval1("x/2");
+        assertDerivAndEval1(Ignored.OutputFormatting, "2/x");
+        assertDerivAndEval1("x^2");
+        assertDerivAndEval1("(x+1)+(x+2)");
+        assertDerivAndEval1("(x+1)-(x+2)");
+        assertDerivAndEval1("-(x+1)+(x+2)");
+        assertDerivAndEval1("-(x+1)-(x+2)");
+        assertDerivAndEval1("(x+1)*(x+2)");
+        deriv1("(x+1)/(x+2)").derive().eval(0).withHessian().derive(Output.IgnoreWhitespace).eval(0);
+        assertDerivAndEval1("(x+1)*(x+2*(x-1))");
+        assertDerivAndEval1(Ignored.OutputFormatting, "(x+1)^(x+2)");
+    }
+
+    @Test
+    public void testDeriveFunctions1() {
+        deriv1("log(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0).eval(1).eval(Ignored.MissingWarning,
+                        -1);
+        assertDerivAndEval1("exp(x)");
+        assertDerivAndEval1("cos(x)");
+        assertDerivAndEval1("sin(x)");
+        assertDerivAndEval1("tan(x)");
+        assertDerivAndEval1("cosh(x)");
+        assertDerivAndEval1("sinh(x)");
+        deriv1("tanh(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0).eval(1).eval(-1);
+        assertDerivAndEval1("sqrt(x)");
+        deriv1("pnorm(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0);
+        assertDerivAndEval1(Ignored.OutputFormatting, "dnorm(x)");
+        assertDerivAndEval1("asin(x)");
+        assertDerivAndEval1(Ignored.OutputFormatting, "acos(x)");
+        deriv1("atan(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0);
+        assertDeriv1("gamma(x)").eval(Ignored.Unimplemented, 0);
+        assertDeriv1("lgamma(x)").eval(0.5);
+        assertDeriv1("digamma(x)").eval(Ignored.Unimplemented, 0);
+        assertDeriv1("trigamma(x)").eval(Ignored.Unimplemented, 0);
+        assertDeriv1("psigamma(x)").eval(Ignored.Unimplemented, 0);
+    }
+
+    @Test
+    public void testDeriveFunctionsWithCompArg1() {
+        deriv1("log(2*x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0);
+        deriv1("log(sin(2*x))").derive().eval(0).withHessian().derive(Output.IgnoreWhitespace).eval(0);
+        assertDerivAndEval1(Output.IgnoreWhitespace, "log(sin(2*x)*cos(x^2))");
+        assertDerivAndEval1(Output.IgnoreWhitespace, "pnorm(sin(2*x)^log(x+1))");
+    }
+
+    @Test
+    public void testDeriveBasicExpressions2() {
+        assertDerivAndEval2("x + y");
+        deriv2("x*y").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("2*x*y").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("x/y/2").derive(Ignored.OutputFormatting).eval(0,
+                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("2/x*y").derive(Ignored.OutputFormatting).eval(0,
+                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("x^y").derive(Ignored.OutputFormatting).eval(0,
+                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("(x+1)*(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
+                        0);
+        assertDerivAndEval2("(x+1)-(y+2)");
+        deriv2("-(x+1)+(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
+                        0);
+        deriv2("-(x+1)-(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
+                        0);
+        deriv2("(x+1)/(y+2)").derive(Ignored.OutputFormatting).eval(0,
+                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("(x+1)*(y+2*(x-1))").derive().eval(0,
+                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("(x+1)^(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
+                        0).eval(1, 1);
+    }
+
+    @Test
+    public void testLongExpression() {
+        deriv2("(log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1))").derive(Output.IgnoreWhitespace).eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+    }
+
+    @Test
+    public void testFunctionGenereration() {
+        assertEval(Output.IgnoreWhitespace, "(df <- deriv(~x^2*sin(x), \"x\", function.arg=TRUE));df(0)");
+        assertEval(Output.IgnoreWhitespace, "(df <- deriv(~x^2*sin(x), \"x\", function.arg=c(\"x\")));df(0)");
+        assertEval(Output.IgnoreWhitespace, "(df <- deriv(~x^2*sin(x), \"x\", function.arg=function(x=1){}));df(0)");
+    }
+
+    @Test
+    public void testUnusualExprs() {
+        assertEval("(df <- deriv(expression(x^2*sin(x)), \"x\"));df(0)");
+        assertEval("(df <- deriv(quote(x^2*sin(x)), \"x\"));df(0)");
+        assertEval("g<-quote(x^2);(df <- deriv(g, \"x\"));df(0)");
+        assertEval("(df <- deriv(1, \"x\"));df(0)");
+        assertEval("x<-1;(df <- deriv(x, \"x\"));df(0)");
+    }
+
+}
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 9ace1ab1d3a27e419cea334c91beb3be453f17cd..f6786e5110ab80a04fbc540258a0b5e20b71bfcc 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -764,3 +764,5 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/p
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright