From 56f2a6a18890a20190d2099395a7e32e80e7ca0a Mon Sep 17 00:00:00 2001
From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>
Date: Tue, 13 Mar 2018 14:57:35 +0100
Subject: [PATCH] Add Try/Catch Blocks within driver

As a step towards making the driver the main function.
---
 python/dune/perftool/cgen/__init__.py         |  1 +
 python/dune/perftool/cgen/exceptions.py       | 39 +++++++++++++++++++
 .../dune/perftool/pdelab/driver/__init__.py   | 15 +++++++
 3 files changed, 55 insertions(+)
 create mode 100644 python/dune/perftool/cgen/exceptions.py

diff --git a/python/dune/perftool/cgen/__init__.py b/python/dune/perftool/cgen/__init__.py
index 128c4ded..24af73e0 100644
--- a/python/dune/perftool/cgen/__init__.py
+++ b/python/dune/perftool/cgen/__init__.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import
 from cgen import *
 
 from dune.perftool.cgen.clazz import Class
+from dune.perftool.cgen.exceptions import TryCatchBlock, CatchBlock
 
 
 class Namespace(PrivateNamespace):
diff --git a/python/dune/perftool/cgen/exceptions.py b/python/dune/perftool/cgen/exceptions.py
new file mode 100644
index 00000000..bda54cf5
--- /dev/null
+++ b/python/dune/perftool/cgen/exceptions.py
@@ -0,0 +1,39 @@
+""" Add Try/Catch blocks to cgen """
+
+from cgen import Block, Generable, Value
+
+
+class CatchBlock(Generable):
+    def __init__(self, exc_decl, catch_block):
+        assert isinstance(exc_decl, Value)
+        self.exc_decl = exc_decl
+        assert isinstance(catch_block, Block)
+        self.catch_block = catch_block
+
+    def generate(self):
+        yield "catch ({})\n".format("".join(self.exc_decl.generate(with_semicolon=False)))
+        for item in self.catch_block.generate():
+            yield item
+        yield "\n"
+
+class TryCatchBlock(Generable):
+    def __init__(self, try_block, catch_blocks):
+        # Store the try block
+        assert isinstance(try_block, Block)
+        self.try_block = try_block
+
+        assert all(isinstance(b, CatchBlock) for b in catch_blocks)
+        self.catch_blocks = catch_blocks
+
+    def generate(self):
+        # Yield the try block
+        yield "\n"
+        yield "try\n"
+        for item in self.try_block.generate():
+            yield item
+        yield "\n"
+
+        # and now yield all the catch blocks
+        for catch_block in self.catch_blocks:
+            for item in catch_block.generate():
+                yield item
diff --git a/python/dune/perftool/pdelab/driver/__init__.py b/python/dune/perftool/pdelab/driver/__init__.py
index 4a832ba7..5b768b14 100644
--- a/python/dune/perftool/pdelab/driver/__init__.py
+++ b/python/dune/perftool/pdelab/driver/__init__.py
@@ -307,6 +307,21 @@ def generate_driver():
         contents.insert(len(contents) - 1, Line(text="DUMP_TIMER({}, driver, {}, true);\n".format(get_option("instrumentation_level"), timestream)))
     contents.insert(0, Line(text="\n"))
     driver_body = Block(contents)
+
+    # Wrap a try/catch block around the driver body
+    from dune.perftool.cgen import CatchBlock, TryCatchBlock, Value, Block, Line
+    catch_blocks = [CatchBlock(Value("Dune::Exception&", "e"),
+                               Block([Line("std::cerr << \"Dune reported error: \" << e << std::endl;\n"),
+                                      Line("return 1;\n"),
+                                      ])
+                               ),
+                    CatchBlock(Value("std::exception&", "e"),
+                               Block([Line("std::cerr << \"Unknown exception thrown!\" << std::endl;\n"),
+                                      Line("return 1;\n"),
+                                      ])
+                               )
+                    ]
+    driver_body = Block([TryCatchBlock(driver_body, catch_blocks)])
     driver = FunctionBody(driver_signature, driver_body)
 
     filename = get_option("driver_file")
-- 
GitLab