summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorScott Wadden <scott.wadden@emc.com>2020-09-07 15:05:07 -0300
committerGitHub <noreply@github.com>2020-09-07 20:05:07 +0200
commit098a8a7c522986ce250d4e52dc42182e5d9d7352 (patch)
tree44f27a292a845e968d781ebe140ff5e75d30cfd6
parent0b74d26d0c45e0fe16126bd264072783afacd12a (diff)
downloadNim-098a8a7c522986ce250d4e52dc42182e5d9d7352.tar.gz
nimeval errorHook support (#15255)
-rw-r--r--compiler/nimeval.nim11
-rw-r--r--tests/compilerapi/invalid.nim1
-rw-r--r--tests/compilerapi/tcompilerapi.nim41
3 files changed, 37 insertions, 16 deletions
diff --git a/compiler/nimeval.nim b/compiler/nimeval.nim
index df3cb2079..5d4fea9f3 100644
--- a/compiler/nimeval.nim
+++ b/compiler/nimeval.nim
@@ -10,9 +10,9 @@
 ## exposes the Nim VM to clients.
 import
   ast, astalgo, modules, passes, condsyms,
-  options, sem, semdata, llstream, vm, vmdef,
-  modulegraphs, idents, os, pathutils, passaux,
-  scriptconfig
+  options, sem, semdata, llstream, lineinfos, vm,
+  vmdef, modulegraphs, idents, os, pathutils,
+  passaux, scriptconfig
 
 type
   Interpreter* = ref object ## Use Nim as an interpreter with this object
@@ -134,6 +134,11 @@ proc destroyInterpreter*(i: Interpreter) =
   ## destructor.
   discard "currently nothing to do."
 
+proc registerErrorHook*(i: Interpreter, hook:
+                        proc (config: ConfigRef; info: TLineInfo; msg: string;
+                              severity: Severity) {.gcsafe.}) =
+  i.graph.config.structuredErrorHook = hook
+
 proc runRepl*(r: TLLRepl;
               searchPaths: openArray[string];
               supportNimscript: bool) =
diff --git a/tests/compilerapi/invalid.nim b/tests/compilerapi/invalid.nim
new file mode 100644
index 000000000..3c9364402
--- /dev/null
+++ b/tests/compilerapi/invalid.nim
@@ -0,0 +1 @@
+noSuchProc()
diff --git a/tests/compilerapi/tcompilerapi.nim b/tests/compilerapi/tcompilerapi.nim
index 9d5e0e3f2..d8489c763 100644
--- a/tests/compilerapi/tcompilerapi.nim
+++ b/tests/compilerapi/tcompilerapi.nim
@@ -5,6 +5,7 @@ discard """
 my secret
 11
 12
+raising VMQuit
 '''
   joinable: "false"
 """
@@ -12,34 +13,35 @@ my secret
 ## Example program that demonstrates how to use the
 ## compiler as an API to embed into your own projects.
 
-import "../../compiler" / [ast, vmdef, vm, nimeval, llstream]
+import "../../compiler" / [ast, vmdef, vm, nimeval, llstream, lineinfos, options]
 import std / [os]
 
-proc main() =
+proc initInterpreter(script: string): Interpreter =
   let std = findNimStdLibCompileTime()
-  var intr = createInterpreter("myscript.nim", [std, parentDir(currentSourcePath),
+  result = createInterpreter(script , [std, parentDir(currentSourcePath),
     std / "pure", std / "core"])
-  intr.implementRoutine("*", "exposed", "addFloats", proc (a: VmArgs) =
+
+proc main() =
+  let i = initInterpreter("myscript.nim")
+  i.implementRoutine("*", "exposed", "addFloats", proc (a: VmArgs) =
     setResult(a, getFloat(a, 0) + getFloat(a, 1) + getFloat(a, 2))
   )
-
-  intr.evalScript()
-
-  let foreignProc = selectRoutine(intr, "hostProgramRunsThis")
+  i.evalScript()
+  let foreignProc = i.selectRoutine("hostProgramRunsThis")
   if foreignProc == nil:
     quit "script does not export a proc of the name: 'hostProgramRunsThis'"
-  let res = intr.callRoutine(foreignProc, [newFloatNode(nkFloatLit, 0.9),
-                                           newFloatNode(nkFloatLit, 0.1)])
+  let res = i.callRoutine(foreignProc, [newFloatNode(nkFloatLit, 0.9),
+                                        newFloatNode(nkFloatLit, 0.1)])
   doAssert res.kind == nkFloatLit
   echo res.floatVal
 
-  let foreignValue = selectUniqueSymbol(intr, "hostProgramWantsThis")
+  let foreignValue = i.selectUniqueSymbol("hostProgramWantsThis")
   if foreignValue == nil:
     quit "script does not export a global of the name: hostProgramWantsThis"
-  let val = intr.getGlobalValue(foreignValue)
+  let val = i.getGlobalValue(foreignValue)
   doAssert val.kind in {nkStrLit..nkTripleStrLit}
   echo val.strVal
-  destroyInterpreter(intr)
+  i.destroyInterpreter()
 
 main()
 
@@ -54,3 +56,16 @@ block issue9180:
 
   evalString("echo 10+1")
   evalString("echo 10+2")
+
+block error_hook:
+  type VMQuit = object of CatchableError
+
+  let i = initInterpreter("invalid.nim")
+  i.registerErrorHook proc(config: ConfigRef; info: TLineInfo; msg: string;
+                           severity: Severity) {.gcsafe.} =
+    if severity == Error and config.errorCounter >= config.errorMax:
+      echo "raising VMQuit"
+      raise newException(VMQuit, "Script error")
+
+  doAssertRaises(VMQuit):
+    i.evalScript()