diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 1670fad52945019ecf3c76ff840c658ab0925a50..f7a538efcb30b60ecc2e58b55c4394d720d35ad2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -354,6 +354,7 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRTry.class, FastRTryNodeGen::create);
         add(FastRInspect.class, FastRInspectNodeGen::create);
         add(FastRInterop.Eval.class, FastRInteropFactory.EvalNodeGen::create);
+        add(FastRInterop.EvalFile.class, FastRInteropFactory.EvalFileNodeGen::create);
         add(FastRInterop.Export.class, FastRInteropFactory.ExportNodeGen::create);
         add(FastRInterop.HasSize.class, FastRInteropFactory.HasSizeNodeGen::create);
         add(FastRInterop.Import.class, FastRInteropFactory.ImportNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
index ce5c3dae4dc188754d89052895ff69e884dd5d6c..f0a1eaaf6eadefcfdc832fa191210af6fe13681e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
@@ -31,6 +31,9 @@ import static com.oracle.truffle.r.runtime.RVisibility.ON;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import java.io.File;
+import java.io.IOException;
+
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -44,6 +47,7 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.DirectCallNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.source.Source.Builder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -99,6 +103,46 @@ public class FastRInterop {
         }
     }
 
+    @RBuiltin(name = ".fastr.interop.evalFile", visibility = OFF, kind = PRIMITIVE, parameterNames = {"path", "mimeType"}, behavior = COMPLEX)
+    public abstract static class EvalFile extends RBuiltinNode {
+
+        @Override
+        protected void createCasts(CastBuilder casts) {
+            casts.arg("path").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+            casts.arg("mimeType").allowMissing().mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+        }
+
+        protected CallTarget parse(String path, String mimeType) {
+            CompilerAsserts.neverPartOfCompilation();
+
+            File file = new File(path);
+            try {
+                Builder<IOException, RuntimeException, RuntimeException> sourceBuilder = Source.newBuilder(file).name(file.getName()).internal();
+                if (mimeType != null) {
+                    sourceBuilder.mimeType(mimeType);
+                }
+                Source sourceObject = sourceBuilder.build();
+                return RContext.getInstance().getEnv().parse(sourceObject);
+            } catch (IOException e) {
+                throw RError.error(this, Message.GENERIC, "Error reading file: " + e.getMessage());
+            } catch (Throwable t) {
+                throw RError.error(this, Message.GENERIC, "Error while parsing: " + t.getMessage());
+            }
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected Object eval(String path, @SuppressWarnings("unused") RMissing missing) {
+            return parse(path, null).call();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected Object eval(String path, String mimeType) {
+            return parse(path, mimeType).call();
+        }
+    }
+
     @RBuiltin(name = ".fastr.interop.export", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name", "value"}, behavior = COMPLEX)
     public abstract static class Export extends RBuiltinNode {
 
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 8191e482278b2673d2ed8c0291d57969c952ca8a..c46aae65e00a8572a16547834981372ab0e2eb3e 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
@@ -111348,6 +111348,16 @@ a b c d e
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { as.character(123) } else { .fastr.interop.eval('application/x-r', 'as.character(123)') }
 [1] "123"
 
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEvalFile#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "Error reading file: /a/b.R"\n') } else { tryCatch(.fastr.interop.evalFile("/a/b.R"),  error = function(e) e$message) }
+[1] "Error reading file: /a/b.R"
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEvalFile#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { x<-c(1);cat(x) } else { fileConn<-file("testScript.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("testScript.R") }
+1
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEvalFile#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { x<-c(1);cat(x) } else { fileConn<-file("testScript.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("testScript.R","application/x-r") }
+1
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', 'foo') }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
index 4633fbe6cea36712abcfa82e76de810cfd1160d8..2250149cb2075b762143b4d249ff3d3c5a5ddc6c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
@@ -47,6 +47,14 @@ public class TestInterop extends TestBase {
         assertEvalFastR(".fastr.interop.export('foo', new.env())", "invisible()");
     }
 
+    @Test
+    public void testInteropEvalFile() {
+        assertEvalFastR("fileConn<-file(\"testScript.R\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);.fastr.interop.evalFile(\"testScript.R\",\"application/x-r\")",
+                        "x<-c(1);cat(x)");
+        assertEvalFastR("fileConn<-file(\"testScript.R\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);.fastr.interop.evalFile(\"testScript.R\")", "x<-c(1);cat(x)");
+        assertEvalFastR("tryCatch(.fastr.interop.evalFile(\"/a/b.R\"),  error = function(e) e$message)", "cat('[1] \"Error reading file: /a/b.R\"\\n')");
+    }
+
     /**
      * Used for testing interop functionality.
      */