tcompilerapi.nim 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. discard """
  2. output: '''top level statements are executed!
  3. (ival: 10, fval: 2.0)
  4. 2.0
  5. my secret
  6. 11
  7. 12
  8. raising VMQuit
  9. '''
  10. joinable: "false"
  11. """
  12. ## Example program that demonstrates how to use the
  13. ## compiler as an API to embed into your own projects.
  14. import "../../compiler" / [ast, vmdef, vm, nimeval, llstream, lineinfos, options]
  15. import std / [os]
  16. proc initInterpreter(script: string): Interpreter =
  17. let std = findNimStdLibCompileTime()
  18. result = createInterpreter(script, [std, parentDir(currentSourcePath),
  19. std / "pure", std / "core"])
  20. proc main() =
  21. let i = initInterpreter("myscript.nim")
  22. i.implementRoutine("nim", "exposed", "addFloats", proc (a: VmArgs) =
  23. setResult(a, getFloat(a, 0) + getFloat(a, 1) + getFloat(a, 2))
  24. )
  25. i.evalScript()
  26. let foreignProc = i.selectRoutine("hostProgramRunsThis")
  27. if foreignProc == nil:
  28. quit "script does not export a proc of the name: 'hostProgramRunsThis'"
  29. let res = i.callRoutine(foreignProc, [newFloatNode(nkFloatLit, 0.9),
  30. newFloatNode(nkFloatLit, 0.1)])
  31. doAssert res.kind == nkFloatLit
  32. echo res.floatVal
  33. let foreignValue = i.selectUniqueSymbol("hostProgramWantsThis")
  34. if foreignValue == nil:
  35. quit "script does not export a global of the name: hostProgramWantsThis"
  36. let val = i.getGlobalValue(foreignValue)
  37. doAssert val.kind in {nkStrLit..nkTripleStrLit}
  38. echo val.strVal
  39. i.destroyInterpreter()
  40. main()
  41. block issue9180:
  42. proc evalString(code: string, moduleName = "script.nim") =
  43. let stream = llStreamOpen(code)
  44. let std = findNimStdLibCompileTime()
  45. var intr = createInterpreter(moduleName, [std, std / "pure", std / "core"])
  46. intr.evalScript(stream)
  47. destroyInterpreter(intr)
  48. llStreamClose(stream)
  49. evalString("echo 10+1")
  50. evalString("echo 10+2")
  51. block error_hook:
  52. type VMQuit = object of CatchableError
  53. let i = initInterpreter("invalid.nim")
  54. i.registerErrorHook proc(config: ConfigRef; info: TLineInfo; msg: string;
  55. severity: Severity) {.gcsafe.} =
  56. if severity == Error and config.errorCounter >= config.errorMax:
  57. echo "raising VMQuit"
  58. raise newException(VMQuit, "Script error")
  59. doAssertRaises(VMQuit):
  60. i.evalScript()
  61. block resetmacrocache:
  62. let std = findNimStdLibCompileTime()
  63. let intr = createInterpreter("script.nim", [std, std / "pure", std / "core"])
  64. proc evalString(intr: Interpreter; code: string) =
  65. let stream = llStreamOpen(code)
  66. intr.evalScript(stream)
  67. llStreamClose(stream)
  68. let code = """
  69. import std/[macrocache, macros]
  70. static:
  71. let counter = CacheCounter"valTest"
  72. inc counter
  73. assert counter.value == 1
  74. const mySeq = CacheSeq"addTest"
  75. mySeq.add(newLit(5))
  76. mySeq.add(newLit("hello ic"))
  77. assert mySeq.len == 2
  78. const mcTable = CacheTable"subTest"
  79. mcTable["toAdd"] = newStmtList() #would crash if not empty
  80. assert mcTable.len == 1
  81. """
  82. intr.evalString(code)
  83. intr.evalString(code)
  84. destroyInterpreter(intr)