diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..21a2208f1664412db23a9fba42873b2b579ab081
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
@@ -0,0 +1,99 @@
+/*
+ * 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) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asInt;
+
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+
+public class DrawArrowsNode extends Node {
+    // Structure of an arrow description
+    public static final int ARROWANGLE = 0;
+    public static final int ARROWLENGTH = 1;
+    public static final int ARROWENDS = 2;
+    public static final int ARROWTYPE = 3;
+    // known values of ARROWTYPE
+    public static final int ARROWTYPE_LINES = 1;
+    public static final int ARROWTYPE_POLYGON = 2;
+
+    @Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
+
+    /**
+     * Draws arrows at the start and end of given lines.
+     *
+     * @param x x-positions of the line(s)
+     * @param y y-positions of the line(s)
+     * @param startIndex consider arrays x,y to start from this index
+     * @param length consider arrays x,y to have this length
+     * @param parentIndex the index of the line we are drawing, this is used for choosing the right
+     *            index into vectors extracted from arrow
+     * @param arrow list with various attributes of the arrow
+     * @param start should we draw start arrow if the arrow list says so. Otherwise never draw it.
+     * @param end should we draw end arrow if the arrow list says so. Otherwise never draw it.
+     * @param conversionCtx needed for unit conversions.
+     */
+    public void drawArrows(double[] x, double[] y, int startIndex, int length, int parentIndex, RList arrow, boolean start, boolean end, UnitConversionContext conversionCtx) {
+        assert x.length == y.length;
+        int endsVal = asInt(arrow.getDataAt(ARROWENDS), parentIndex);
+        boolean first = endsVal != 2;
+        boolean last = endsVal != 1;
+        if ((!first || !start) && (!last || !end)) {
+            // if we are not going to draw any arrow anyway, just finish
+            return;
+        }
+        // extract angle, length in inches and arrow type from 'arrow'
+        double angle = asDouble(arrow.getDataAt(ARROWANGLE), parentIndex);
+        int arrowType = asInt(arrow.getDataAt(ARROWTYPE), parentIndex);
+        RAbstractContainer lengthVec = asAbstractContainer(arrow.getDataAt(ARROWLENGTH));
+        double arrowLength = unitToInches.convertHeight(lengthVec, parentIndex, conversionCtx);
+        arrowLength = Math.max(arrowLength, unitToInches.convertWidth(lengthVec, parentIndex, conversionCtx));
+        // draw the arrows
+        GridDevice device = conversionCtx.device;
+        DrawingContext drawingCtx = conversionCtx.drawingContext;
+        if (first && start) {
+            drawArrow(drawingCtx, device, arrowType, x[startIndex], y[startIndex], x[startIndex + 1], y[startIndex + 1], angle, arrowLength);
+        }
+        if (last && end) {
+            int n = startIndex + length;
+            drawArrow(drawingCtx, device, arrowType, x[n - 1], y[n - 1], x[n - 2], y[n - 2], angle, arrowLength);
+        }
+    }
+
+    private void drawArrow(DrawingContext drawingCtx, GridDevice device, int arrowType, double x0, double y0, double x1, double y1, double angle, double length) {
+        double a = Math.toRadians(angle);
+        double xc = x1 - x0;
+        double yc = y1 - y0;
+        double rot = Math.atan2(yc, xc);
+        double[] vertx = new double[3];
+        double[] verty = new double[3];
+        vertx[0] = x0 + length * Math.cos(rot + a);
+        verty[0] = y0 + length * Math.sin(rot + a);
+        vertx[1] = x0;
+        verty[1] = y0;
+        vertx[2] = x0 + length * Math.cos(rot - a);
+        verty[2] = y0 + length * Math.sin(rot - a);
+        if (arrowType == ARROWTYPE_LINES) {
+            device.drawPolyLines(drawingCtx, vertx, verty, 0, 3);
+        } else if (arrowType == ARROWTYPE_POLYGON) {
+            device.drawPolyLines(drawingCtx, vertx, verty, 0, 3);
+            // TODO: real polygon
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index 24cb71abc5bd43d09fa64d4c97790293c3a0119f..11946cb521b7cbecf7857795fc26748d434a47d2 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -42,8 +42,9 @@ public abstract class GridLinesNode extends Node {
 
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private DrawArrowsNode drawArrowsNode = new DrawArrowsNode();
 
-    void execute(RAbstractVector x, RAbstractVector y, RList lengths) {
+    void execute(RAbstractVector x, RAbstractVector y, RList lengths, RList arrow) {
         GridContext ctx = GridContext.getContext();
         GridDevice dev = ctx.getCurrentDevice();
 
@@ -90,6 +91,11 @@ public abstract class GridLinesNode extends Node {
                         // it's last iteration. This seems slightly weird, but that's how GnuR seems
                         // to work
                         drawPolylines(dev, drawingCtx, yy, xx, start, (i - start) + 1);
+                        if (arrow != null) {
+                            // Can draw an arrow at the start if the points include the first point.
+                            // Draw an arrow at the end only if this is the last series
+                            drawArrowsNode.drawArrows(xx, yy, start, (i - start) + 1, unitIndex, arrow, start == 0, lastIter, conversionCtx);
+                        }
                     }
                 }
                 oldIsFinite = currIsFinite;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index 1b7ff9197a90621615f2628037cd26df56593c6b..c7680a918f6ef6518023b6cb14dcbbe1258d6e68 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -124,6 +124,30 @@ final class GridUtils {
         throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double/integer value " + val.getClass().getSimpleName());
     }
 
+    static double asDouble(Object val, int cyclicIndex) {
+        if (val instanceof Double) {
+            return (int) val;
+        } else if (val instanceof RAbstractDoubleVector) {
+            RAbstractDoubleVector vec = (RAbstractDoubleVector) val;
+            if (vec.getLength() > 0) {
+                return vec.getDataAt(cyclicIndex % vec.getLength());
+            }
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double value " + val.getClass().getSimpleName());
+    }
+
+    static int asInt(Object val, int cyclicIndex) {
+        if (val instanceof Integer) {
+            return (int) val;
+        } else if (val instanceof RAbstractIntVector) {
+            RAbstractIntVector vec = (RAbstractIntVector) val;
+            if (vec.getLength() > 0) {
+                return vec.getDataAt(cyclicIndex % vec.getLength());
+            }
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non integer value " + val.getClass().getSimpleName());
+    }
+
     static RAbstractIntVector asIntVector(Object value) {
         if (value instanceof Integer) {
             return RDataFactory.createIntVectorFromScalar((Integer) value);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
index de270734525fa83add0e666a969031c40c1ec98d..e38149b8f1da4283dc5986c7e42032678fcc7b84 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
@@ -38,6 +38,7 @@ public abstract class LLines extends RExternalBuiltinNode.Arg4 {
         casts.arg(0).mustBe(abstractVectorValue());
         casts.arg(1).mustBe(abstractVectorValue());
         casts.arg(2).mustBe(RList.class);
+        casts.arg(2).allowNull().mustBe(RList.class);
     }
 
     public static LLines create() {
@@ -45,9 +46,14 @@ public abstract class LLines extends RExternalBuiltinNode.Arg4 {
     }
 
     @Specialization
-    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, @SuppressWarnings("unused") Object arrowIgnored) {
-        // TODO: implement arrows
-        gridLinesNode.execute(x, y, lengths);
+    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, RNull arrowIgnored) {
+        gridLinesNode.execute(x, y, lengths, null);
+        return RNull.instance;
+    }
+
+    @Specialization
+    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, @SuppressWarnings("unused") RList arrow) {
+        gridLinesNode.execute(x, y, lengths, arrow);
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java
index 8d4343e9ab8267fb2732e90a6fa6568f8bb14376..a4d8a917bd2bc2387d1faa7cb8b5026ee5fb37c3 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java
@@ -46,7 +46,7 @@ public abstract class LPolygon extends RExternalBuiltinNode.Arg3 {
 
     @Specialization
     Object doLines(RAbstractVector x, RAbstractVector y, RList lengths) {
-        gridLinesNode.execute(x, y, lengths);
+        gridLinesNode.execute(x, y, lengths, null);
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index 33e8f7d514746ddb8cd051186cf3c7fe9b06a146..6ec185aef101492430df1e2bcc70870fc69c9663 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -31,6 +31,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private DrawArrowsNode drawArrowsNode = new DrawArrowsNode();
 
     static {
         Casts casts = new Casts(LSegments.class);
@@ -38,6 +39,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
         casts.arg(1).mustBe(abstractVectorValue());
         casts.arg(2).mustBe(abstractVectorValue());
         casts.arg(3).mustBe(abstractVectorValue());
+        casts.arg(4).allowNull().mustBe(RList.class);
     }
 
     public static LSegments create() {
@@ -45,7 +47,12 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
     }
 
     @Specialization
-    Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, Object arrowIgnored) {
+    Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, RNull arrow) {
+        return doSegments(x0, y0, x1, y1, (RList) null);
+    }
+
+    @Specialization
+    Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, RList arrow) {
         GridContext ctx = GridContext.getContext();
         GridDevice dev = ctx.getCurrentDevice();
 
@@ -69,6 +76,9 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
             yy[0] = loc1.y;
             yy[1] = loc2.y;
             dev.drawPolyLines(drawingCtx, xx, yy, 0, 2);
+            if (arrow != null) {
+                drawArrowsNode.drawArrows(xx, yy, 0, 2, i, arrow, true, true, conversionCtx);
+            }
         }
         return RNull.instance;
     }
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 7c18b674af82fa67a5378855747a905b446ecfca..8dc2bf1018ce4a56a935a0346e28f0c49e17a721 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -767,6 +767,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/p
 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
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java,gnu_r_murrel_core.copyright