From 51a8d559f7df8383e312384d9b1a42d33b39f78b Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Mon, 30 Jan 2017 15:13:16 +0100
Subject: [PATCH] Initial grid package support

---
 .gitignore                                    |  2 +
 .../library/grid/Makefile                     | 39 +++++++++++++---
 .../library/grid/src/sed_grid                 | 10 +++++
 .../library/grid/src/sed_state                | 18 ++++++++
 .../foreign/CallAndExternalFunctions.java     | 14 ++++--
 .../truffle/r/test/ExpectedTestOutput.test    | 16 +++++++
 .../r/test/library/grid/TestGridPackage.java  | 44 +++++++++++++++++++
 mx.fastr/mx_fastr.py                          |  2 +-
 8 files changed, 135 insertions(+), 10 deletions(-)
 create mode 100644 com.oracle.truffle.r.native/library/grid/src/sed_grid
 create mode 100644 com.oracle.truffle.r.native/library/grid/src/sed_state
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/grid/TestGridPackage.java

diff --git a/.gitignore b/.gitignore
index dd8ad6fc9f..9c8ffbab24 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,8 @@
 /com.oracle.truffle.r.native/library/*/lib/*
 /com.oracle.truffle.r.native/library/stats/src/fft.c
 /com.oracle.truffle.r.native/library/tools/src/gramRd.c
+/com.oracle.truffle.r.native/library/grid/src/grid.c
+/com.oracle.truffle.r.native/library/grid/src/state.c
 /com.oracle.truffle.r.native/platform.mk
 /com.oracle.truffle.r.native/gnur/Makeconf.done
 /com.oracle.truffle.r.native/gnur/platform.mk.temp*
diff --git a/com.oracle.truffle.r.native/library/grid/Makefile b/com.oracle.truffle.r.native/library/grid/Makefile
index 58f1789a96..4ef8f605d9 100644
--- a/com.oracle.truffle.r.native/library/grid/Makefile
+++ b/com.oracle.truffle.r.native/library/grid/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -21,14 +21,43 @@
 # questions.
 #
 
+.PHONY: cleanpkg
+
 OBJ = lib
 
-GNUR_C_FILES := $(notdir $(wildcard $(GNUR_HOME)/src/library/grid/src/*.c))
+GNUR_C_FILES := gpar.c just.c layout.c matrix.c register.c unit.c util.c viewport.c
+
+GNUR_GRID = $(addprefix $(GNUR_HOME)/src/library/grid/src/, grid.c)
+GRID_OBJECT = $(addprefix $(OBJ)/, grid.o)
+
+GNUR_GRID_STATE = $(addprefix $(GNUR_HOME)/src/library/grid/src/, state.c)
+GRID_STATE_OBJECT = $(addprefix $(OBJ)/, state.o)
 
-GNUR_C_OBJECTS := $(addprefix $(OBJ)/, $(GNUR_C_FILES:.c=.o))
-#$(info GNUR_C_OBJECTS=$(GNUR_C_OBJECTS))
+GNUR_C_OBJECTS := $(addprefix $(OBJ)/, $(GNUR_C_FILES:.c=.o)) $(GRID_OBJECT) $(GRID_STATE_OBJECT)
+LIB_PKG_PRE = $(GRID_OBJECT) $(GRID_STATE_OBJECT)
+CLEAN_PKG := cleanpkg
+
+# This is necessary so that #include "grid.h" works
+PKG_INCLUDES = -I $(GNUR_SRC) 
 
 include ../lib.mk
 
+# Why is this necessary? Because if grid.c and state.c have been created by editing, 
+# lib.mk will include them in C_OBJECTS but they're already in GNUR_C_OBJECTS (uncreated case)
+C_OBJECTS := $(filter-out $(GRID_OBJECT) $(GRID_STATE_OBJECT), $(C_OBJECTS))
+
+$(C_OBJECTS): | $(OBJ)
+
+$(SRC)/grid.c: $(GNUR_GRID) src/sed_grid
+	sed -f src/sed_grid $(GNUR_GRID) > src/grid.c
+
+$(SRC)/state.c: $(GNUR_GRID_STATE) src/sed_state
+	sed -f src/sed_state $(GNUR_GRID_STATE) > src/state.c
+
+# obj files from c.o.t.r.n/library/grid/src are handled in lib.mk
+# obj files from gnur to c.o.t.r.n/library/grid/lib are handled here
 $(OBJ)/%.o: $(GNUR_SRC)/%.c
-	$(CC) $(CFLAGS) $(INCLUDES)  $(SUPPRESS_WARNINGS) -c $< -o $@
+	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
+
+cleanpkg:
+	rm -f $(SRC)/grid.c $(SRC)/state.c
diff --git a/com.oracle.truffle.r.native/library/grid/src/sed_grid b/com.oracle.truffle.r.native/library/grid/src/sed_grid
new file mode 100644
index 0000000000..507382a2dc
--- /dev/null
+++ b/com.oracle.truffle.r.native/library/grid/src/sed_grid
@@ -0,0 +1,10 @@
+# L_initGrid gets environment from its caller, which is .External, and saves it 
+# into a static variable R_gridEvalEnv without calling R_PreserveObject. In the 
+# Gnu R world, the environment actually cannot be garbage collected, because it 
+# is grid's environment and there are references to it.
+# 
+# Moreover, grid also uses this environment to "preserve" other objects just by 
+# adding them to that environment. See ed_state where we fix code doing this to 
+# also call R_PreserveObject and R_ReleaseObject.
+# 
+s/R_gridEvalEnv = \([[:alnum:]]*\);/R_gridEvalEnv = R_PreserveObject(\1);/g
diff --git a/com.oracle.truffle.r.native/library/grid/src/sed_state b/com.oracle.truffle.r.native/library/grid/src/sed_state
new file mode 100644
index 0000000000..4cd242c4b4
--- /dev/null
+++ b/com.oracle.truffle.r.native/library/grid/src/sed_state
@@ -0,0 +1,18 @@
+# see ed_grid for description of what is going on here.
+# 
+# Note: the state cannot be 'preserved' in globaliseState(SEXP) 
+# function, which would seem as appropriate place, because the 
+# state is stored into a global variable before globaliseState
+# is invoked.
+#
+# prepend R_PreserveObject call to any sd->systemSpecific assignment 
+# in form of sd->systemSpecific = (void*) variablename;
+s/sd->systemSpecific[[:space:]]*=[[:space:]]*(void\*)[[:space:]]*\([[:alnum:]_]*\);/\1 = R_PreserveObject(\1); sd->systemSpecific = (void*)\1;/g
+#
+# rename deglobaliseState to deglobaliseStateOriginal and prepend a 
+# new definition of deglobaliseState that calls R_ReleaseObject and 
+# the original function (note we need deglobaliseStateOriginal 
+# forward declaration)
+s/static void deglobaliseState(SEXP state)/static void deglobaliseStateOriginal(SEXP state);\
+static void deglobaliseState(SEXP state) { deglobaliseStateOriginal(state); R_ReleaseObject(state); }\
+static void deglobaliseStateOriginal(SEXP state)/g
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 1288d98ba2..038de21300 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
@@ -621,6 +621,16 @@ public class CallAndExternalFunctions {
                 case "sockwrite":
                     return new UnimplementedExternal(name);
 
+                // parallel
+                case "mc_is_child":
+                    return MCIsChildNodeGen.create();
+                default:
+                    return FastROptions.UseInternalGraphics.getBooleanValue() ? lookupGraphicsBuiltin(name) : null;
+            }
+        }
+
+        private RExternalBuiltinNode lookupGraphicsBuiltin(String name) {
+            switch (name) {
                 // grDevices
                 case "cairoProps":
                     return CairoPropsNodeGen.create();
@@ -632,10 +642,6 @@ public class CallAndExternalFunctions {
                     return InitGridNodeGen.create();
                 case "L_validUnits":
                     return ValidUnitsNodeGen.create();
-
-                // parallel
-                case "mc_is_child":
-                    return MCIsChildNodeGen.create();
                 default:
                     return null;
             }
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 4d335cc1b9..6f6cf33436 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
@@ -125207,6 +125207,22 @@ attr(,"is.truffle.object")
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { { x<-rep(1, 100); xi1<-.fastr.identity(x); f<-function(x) { y<-x; y }; f(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 } }
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); 3 * (unit(1, 'mm')); }
+[1] 3*1mm
+
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); grid:::unit.list(3 * unit(1, 'mm')); }
+[1] 3*1mm
+
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); unit.c(unit(1,'mm'), 42*unit(1,'mm')); }
+[1] 1mm    42*1mm
+
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); unit.c(unit(1,'mm'), unit(1,'mm')) }
+[1] 1mm 1mm
+
 ##com.oracle.truffle.r.test.library.stats.TestDistributions.testDensityFunctions#Output.MayIgnoreWarningContext#
 #dbeta(0, -1,  0.5)
 [1] NaN
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/grid/TestGridPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/grid/TestGridPackage.java
new file mode 100644
index 0000000000..f0e5c6639a
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/grid/TestGridPackage.java
@@ -0,0 +1,44 @@
+/*
+ * 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.library.grid;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+/**
+ * Tests non-graphical functions in grid package.
+ */
+public class TestGridPackage extends TestBase {
+    @Test
+    public void testUnits() {
+        run("unit.c(unit(1,'mm'), unit(1,'mm'))");
+        run("3 * (unit(1, 'mm'));");
+        run("grid:::unit.list(3 * unit(1, 'mm'));");
+        run("unit.c(unit(1,'mm'), 42*unit(1,'mm'));");
+    }
+
+    private void run(String testCode) {
+        assertEval(String.format("{ library(grid); %s }", testCode));
+    }
+}
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 70f6f5e127..e215042965 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -407,7 +407,7 @@ def _test_subpackage(name):
     return '.'.join((_test_package(), name))
 
 def _simple_generated_unit_tests():
-    return ','.join(map(_test_subpackage, ['library.base', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'S4', 'rng', 'runtime.data']))
+    return ','.join(map(_test_subpackage, ['library.base', 'library.grid', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'S4', 'rng', 'runtime.data']))
 
 def _simple_unit_tests():
     return ','.join([_simple_generated_unit_tests(), _test_subpackage('tck')])
-- 
GitLab