poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v3 2/2] pkl: Return exception value instead of exit_status


From: Mohammad-Reza Nabipoor
Subject: [PATCH v3 2/2] pkl: Return exception value instead of exit_status
Date: Thu, 13 Jan 2022 03:35:24 +0330

2022-01-12  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>

        * libpoke/pvm.h (pvm_run): Add new arg for exception.
        * libpoke/pvm.c (pvm_run): Report exception.
        (pvm_call_closure): Fix pvm_run invocation.
        (PVM_STATE_EXCEPTION_VALUE): New macro.
        * libpoke/pkl.h (pkl_execute_file): Add new arg for exception.
        (pkl_execute_buffer): Likewise.
        (pkl_execute_expression): Likewise.
        (pkl_execute_statement): Likewise.
        * libpoke/pkl.c (pkl_execute_file): Likewise.
        (pkl_execute_buffer): Likewise.
        (pkl_execute_expression): Likewise.
        (pkl_execute_statement): Likewise.
        * libpoke/libpoke.h (pk_file_compile): Likewise.
        (pk_compile_buffer): Likewise.
        (pk_compile_statement): Likewise.
        (pk_compile_expression): Likewise.
        * libpoke/libpoke.c (pk_file_compile): Likewise.
        (pk_compile_buffer): Likewise.
        (pk_compile_statement): Likewise.
        (pk_compile_expression): Likewise.
        (pk_call): Fix pvm_run invocation.
        * libpoke/pvm.jitter (state-struct-backing-c): Add new field.
        (popexite): Add new instruction.
        * libpoke/pkl-insn.def: Likewise.
        * libpoke/pkl-rt-1.pk (_pkl_exception_handler): Change return value
        to `Exception` from `int<32>`.
        * libpoke/pkl-asm.c (pkl_asm_finish): Update to report exception.
        * poke/pk-cmd-ios.c (pk_cmd_load_file): Fix comment.
        * poke/pk-map.c (pk_map_load_parsed_map): Likewise.
        * poke/poke.c (parse_args_2): Update to use exception value.
        * libpoke/std.pk (exit): Set `name` field.
---
 ChangeLog            | 34 +++++++++++++++++++++++++++++++++
 libpoke/libpoke.c    | 20 +++++++++++---------
 libpoke/libpoke.h    | 28 +++++++++++++++------------
 libpoke/pkl-asm.c    | 10 +++++++++-
 libpoke/pkl-insn.def |  1 +
 libpoke/pkl-rt-1.pk  |  4 ++--
 libpoke/pkl.c        | 32 +++++++++----------------------
 libpoke/pkl.h        | 18 ++++++++++--------
 libpoke/pvm.c        |  9 +++++++--
 libpoke/pvm.h        |  7 ++++++-
 libpoke/pvm.jitter   | 15 +++++++++++++++
 libpoke/std.pk       |  2 +-
 poke/pk-cmd-ios.c    |  2 +-
 poke/pk-map.c        |  4 ++--
 poke/poke.c          | 45 +++++++++++++++++++++++++++++++++++++++-----
 15 files changed, 164 insertions(+), 67 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5dc360bd..bab5ec83 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2022-01-12  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
+
+       * libpoke/pvm.h (pvm_run): Add new arg for exception.
+       * libpoke/pvm.c (pvm_run): Report exception.
+       (pvm_call_closure): Fix pvm_run invocation.
+       (PVM_STATE_EXCEPTION_VALUE): New macro.
+       * libpoke/pkl.h (pkl_execute_file): Add new arg for exception.
+       (pkl_execute_buffer): Likewise.
+       (pkl_execute_expression): Likewise.
+       (pkl_execute_statement): Likewise.
+       * libpoke/pkl.c (pkl_execute_file): Likewise.
+       (pkl_execute_buffer): Likewise.
+       (pkl_execute_expression): Likewise.
+       (pkl_execute_statement): Likewise.
+       * libpoke/libpoke.h (pk_file_compile): Likewise.
+       (pk_compile_buffer): Likewise.
+       (pk_compile_statement): Likewise.
+       (pk_compile_expression): Likewise.
+       * libpoke/libpoke.c (pk_file_compile): Likewise.
+       (pk_compile_buffer): Likewise.
+       (pk_compile_statement): Likewise.
+       (pk_compile_expression): Likewise.
+       (pk_call): Fix pvm_run invocation.
+       * libpoke/pvm.jitter (state-struct-backing-c): Add new field.
+       (popexite): Add new instruction.
+       * libpoke/pkl-insn.def: Likewise.
+       * libpoke/pkl-rt-1.pk (_pkl_exception_handler): Change return value
+       to `Exception` from `int<32>`.
+       * libpoke/pkl-asm.c (pkl_asm_finish): Update to report exception.
+       * poke/pk-cmd-ios.c (pk_cmd_load_file): Fix comment.
+       * poke/pk-map.c (pk_map_load_parsed_map): Likewise.
+       * poke/poke.c (parse_args_2): Update to use exception value.
+       * libpoke/std.pk (exit): Set `name` field.
+
 2022-01-12  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
 
        * libpoke/libpoke.h (PK_E_*): Add macros for standard exception
diff --git a/libpoke/libpoke.c b/libpoke/libpoke.c
index 21bed8e3..99d784ad 100644
--- a/libpoke/libpoke.c
+++ b/libpoke/libpoke.c
@@ -122,29 +122,30 @@ pk_errno (pk_compiler pkc)
 
 int
 pk_compile_file (pk_compiler pkc, const char *filename,
-                 int *exit_status)
+                 pk_val *exit_exception)
 {
-  PK_RETURN (pkl_execute_file (pkc->compiler, filename, exit_status)
+  PK_RETURN (pkl_execute_file (pkc->compiler, filename, exit_exception)
                  ? PK_OK
                  : PK_ERROR);
 }
 
 int
 pk_compile_buffer (pk_compiler pkc, const char *buffer,
-                   const char **end, int *exit_status)
+                   const char **end, pk_val *exit_exception)
 {
   PK_RETURN (pkl_execute_buffer (pkc->compiler, buffer,
-                                 end, exit_status) ? PK_OK : PK_ERROR);
+                                 end, exit_exception) ? PK_OK : PK_ERROR);
 }
 
 int
 pk_compile_statement (pk_compiler pkc, const char *buffer,
                       const char **end, pk_val *valp,
-                      int *exit_status)
+                      pk_val *exit_exception)
 {
   pvm_val val;
 
-  if (!pkl_execute_statement (pkc->compiler, buffer, end, &val, exit_status))
+  if (!pkl_execute_statement (pkc->compiler, buffer, end, &val,
+                              exit_exception))
     PK_RETURN (PK_ERROR);
 
   if (valp)
@@ -155,11 +156,12 @@ pk_compile_statement (pk_compiler pkc, const char *buffer,
 
 int
 pk_compile_expression (pk_compiler pkc, const char *buffer,
-                       const char **end, pk_val *valp, int *exit_status)
+                       const char **end, pk_val *valp, pk_val *exit_exception)
 {
   pvm_val val;
 
-  if (!pkl_execute_expression (pkc->compiler, buffer, end, &val, exit_status))
+  if (!pkl_execute_expression (pkc->compiler, buffer, end, &val,
+                               exit_exception))
     PK_RETURN (PK_ERROR);
 
   if (valp)
@@ -741,7 +743,7 @@ pk_call (pk_compiler pkc, pk_val cls, pk_val *ret, int 
narg, ...)
 
   /* Run the program in the poke VM.  */
   pvm_program_make_executable (program);
-  rret = pvm_run (pkc->vm, program, ret);
+  rret = pvm_run (pkc->vm, program, ret, NULL);
 
   pvm_destroy_program (program);
   PK_RETURN (rret == PVM_EXIT_OK ? PK_OK : PK_ERROR);
diff --git a/libpoke/libpoke.h b/libpoke/libpoke.h
index 8fb12356..14223c5d 100644
--- a/libpoke/libpoke.h
+++ b/libpoke/libpoke.h
@@ -157,14 +157,15 @@ int pk_errno (pk_compiler pkc) LIBPOKE_API;
 
 /* Compile an execute a Poke program from the given file FILENAME.
 
-   If not NULL, *EXIT_STATUS is set to the status resulting from the
-   execution of the program.
+   If not NULL, *EXIT_EXCEPTION is set to an exception value if the
+   execution of the program gets interrupted by an unhandled exception.
+   Otherwise *EXIT_EXCEPTION is set to PK_NULL.
 
    Return PK_ERROR in case of a compilation error.  Otherwise,
    return PK_OK.  */
 
 int pk_compile_file (pk_compiler pkc, const char *filename,
-                     int *exit_status) LIBPOKE_API;
+                     pk_val *exit_exception) LIBPOKE_API;
 
 /* Compile an execute a Poke program from a memory buffer.
 
@@ -176,11 +177,12 @@ int pk_compile_file (pk_compiler pkc, const char 
*filename,
    Return PK_ERROR in case of a compilation error.  Otherwise,
    return PK_OK.
 
-   If not NULL, *EXIT_STATUS is set to the status resulting from the
-   execution of the buffer contents.  */
+   If not NULL, *EXIT_EXCEPTION is set to an exception value if the
+   execution of the program gets interrupted by an unhandled exception.
+   Otherwise *EXIT_EXCEPTION is set to PK_NULL.  */
 
 int pk_compile_buffer (pk_compiler pkc, const char *buffer,
-                       const char **end, int *exit_status) LIBPOKE_API;
+                       const char **end, pk_val *exit_exception) LIBPOKE_API;
 
 /* Like pk_compile_buffer but compile and execute a single Poke
    statement, which may evaluate to a value if it is an "expression
@@ -189,12 +191,13 @@ int pk_compile_buffer (pk_compiler pkc, const char 
*buffer,
    VAL, if given, is a pointer to a pk_val variable that is set to the
    result value of an expression-statement, or to PK_NULL.
 
-   If not NULL, *EXIT_STATUS is set to the status resulting from the
-   execution of the buffer contents.  */
+   If not NULL, *EXIT_EXCEPTION is set to an exception value if the
+   execution of the program gets interrupted by an unhandled exception.
+   Otherwise *EXIT_EXCEPTION is set to PK_NULL.  */
 
 int pk_compile_statement (pk_compiler pkc, const char *buffer,
                           const char **end, pk_val *val,
-                          int *exit_status) LIBPOKE_API;
+                          pk_val *exit_exception) LIBPOKE_API;
 
 /* Like pk_compile_buffer but compile and execute a single Poke
    expression, which evaluates to a value.
@@ -204,12 +207,13 @@ int pk_compile_statement (pk_compiler pkc, const char 
*buffer,
 
    Return PK_ERROR in case of a compilation error, PK_OK otherwise.
 
-   If not NULL, *EXIT_STATUS is set to the status resulting from the
-   execution of the buffer contents.  */
+   If not NULL, *EXIT_EXCEPTION is set to an exception value if the
+   execution of the program gets interrupted by an unhandled exception.
+   Otherwise *EXIT_EXCEPTION is set to PK_NULL.  */
 
 int pk_compile_expression (pk_compiler pkc, const char *buffer,
                            const char **end, pk_val *val,
-                           int *exit_status) LIBPOKE_API;
+                           pk_val *exit_exception) LIBPOKE_API;
 
 /* Load a module using the given compiler.
 
diff --git a/libpoke/pkl-asm.c b/libpoke/pkl-asm.c
index c6a4258e..9e614f20 100644
--- a/libpoke/pkl-asm.c
+++ b/libpoke/pkl-asm.c
@@ -1236,7 +1236,15 @@ pkl_asm_finish (pkl_asm pasm, int epilogue)
          assembly.  Otherwise, call the _pkl_exception_handler
          function which is part of the compiler run-time.  */
       if (pkl_bootstrapped_p (pasm->compiler))
-        pkl_asm_call (pasm, "_pkl_exception_handler");
+        {
+          pkl_asm_call (pasm, "_pkl_exception_handler");  /* EXC */
+          pkl_asm_insn (pasm, PKL_INSN_PUSH,
+                        pvm_make_string ("exit_status")); /* EXC STR */
+          pkl_asm_insn (pasm, PKL_INSN_SREF);             /* EXC STR VAL */
+          pkl_asm_insn (pasm, PKL_INSN_NIP);              /* EXC VAL */
+          pkl_asm_insn (pasm, PKL_INSN_SWAP);             /* VAL EXC */
+          pkl_asm_insn (pasm, PKL_INSN_POPEXITE);         /* VAL */
+        }
       else
         {
           pkl_asm_insn (pasm, PKL_INSN_DROP); /* Discard the exception.  */
diff --git a/libpoke/pkl-insn.def b/libpoke/pkl-insn.def
index 918c6435..4a70eae2 100644
--- a/libpoke/pkl-insn.def
+++ b/libpoke/pkl-insn.def
@@ -441,6 +441,7 @@ PKL_DEF_INSN(PKL_INSN_GETENV,"","getenv")
 PKL_DEF_INSN(PKL_INSN_PUSHE,"l","pushe")
 PKL_DEF_INSN(PKL_INSN_POPE,"","pope")
 PKL_DEF_INSN(PKL_INSN_RAISE,"","raise")
+PKL_DEF_INSN(PKL_INSN_POPEXITE,"","popexite")
 
 /* IOS related instructions.  */
 
diff --git a/libpoke/pkl-rt-1.pk b/libpoke/pkl-rt-1.pk
index c90d3770..6e1c3b91 100644
--- a/libpoke/pkl-rt-1.pk
+++ b/libpoke/pkl-rt-1.pk
@@ -187,7 +187,7 @@ var exception_code = lambda _ExceptionCodeGenerator:
    or be ready to underflow the exception handlers stack and face some
    ugly shit.  You have been warned!  */
 
-fun _pkl_exception_handler = (Exception exception) int<32>:
+fun _pkl_exception_handler = (Exception exception) Exception:
   {
    if (exception.code != EC_exit && exception.code != EC_signal)
      {
@@ -203,7 +203,7 @@ fun _pkl_exception_handler = (Exception exception) int<32>:
          }
      }
 
-   return exception.exit_status;
+   return exception;
   }
 
 /* Find the greatest common divisor of two unsigned 64-bit integrals A
diff --git a/libpoke/pkl.c b/libpoke/pkl.c
index bb52be9b..52a4d4bb 100644
--- a/libpoke/pkl.c
+++ b/libpoke/pkl.c
@@ -305,7 +305,8 @@ rest_of_compilation (pkl_compiler compiler,
 
 int
 pkl_execute_buffer (pkl_compiler compiler,
-                    const char *buffer, const char **end, int *exit_status)
+                    const char *buffer, const char **end,
+                    pvm_val *exit_exception)
 {
   pkl_ast ast = NULL;
   pvm_program program;
@@ -336,12 +337,8 @@ pkl_execute_buffer (pkl_compiler compiler,
   /* Execute the program in the poke vm.  */
   {
     pvm_val val;
-    int status = pvm_run (compiler->vm, program, &val);
 
-    if (exit_status)
-      *exit_status = status;
-
-    if (status != PVM_EXIT_OK)
+    if (pvm_run (compiler->vm, program, &val, exit_exception) != PVM_EXIT_OK)
       goto error;
 
     /* Discard the value.  */
@@ -360,13 +357,12 @@ pkl_execute_buffer (pkl_compiler compiler,
 int
 pkl_execute_statement (pkl_compiler compiler,
                        const char *buffer, const char **end,
-                       pvm_val *val, int *exit_status)
+                       pvm_val *val, pvm_val *exit_exception)
 {
   pkl_ast ast = NULL;
   pvm_program program;
   int ret;
   pkl_env env = NULL;
-  int status;
 
   compiler->compiling = PKL_COMPILING_STATEMENT;
   env = pkl_env_dup_toplevel (compiler->env);
@@ -389,10 +385,7 @@ pkl_execute_statement (pkl_compiler compiler,
   pvm_program_make_executable (program);
 
   /* Execute the routine in the poke vm.  */
-  status = pvm_run (compiler->vm, program, val);
-  if (exit_status)
-    *exit_status = status;
-  if (status != PVM_EXIT_OK)
+  if (pvm_run (compiler->vm, program, val, exit_exception) != PVM_EXIT_OK)
     goto error;
 
   pvm_destroy_program (program);
@@ -413,7 +406,6 @@ pkl_compile_expression (pkl_compiler compiler,
   pvm_program program;
   int ret;
   pkl_env env = NULL;
-  int status;
 
    compiler->compiling = PKL_COMPILING_EXPRESSION;
    env = pkl_env_dup_toplevel (compiler->env);
@@ -447,13 +439,12 @@ pkl_compile_expression (pkl_compiler compiler,
 int
 pkl_execute_expression (pkl_compiler compiler,
                         const char *buffer, const char **end,
-                        pvm_val *val, int *exit_status)
+                        pvm_val *val, pvm_val *exit_exception)
 {
   pkl_ast ast = NULL;
   pvm_program program;
   int ret;
   pkl_env env = NULL;
-  int status;
 
   compiler->compiling = PKL_COMPILING_EXPRESSION;
   env = pkl_env_dup_toplevel (compiler->env);
@@ -476,10 +467,7 @@ pkl_execute_expression (pkl_compiler compiler,
   pvm_program_make_executable (program);
 
   /* Execute the routine in the poke vm.  */
-  status = pvm_run (compiler->vm, program, val);
-  if (exit_status)
-    *exit_status = status;
-  if (status != PVM_EXIT_OK)
+  if (pvm_run (compiler->vm, program, val, exit_exception) != PVM_EXIT_OK)
     goto error;
 
   pvm_destroy_program (program);
@@ -494,7 +482,7 @@ pkl_execute_expression (pkl_compiler compiler,
 
 int
 pkl_execute_file (pkl_compiler compiler, const char *fname,
-                  int *exit_status)
+                  pvm_val *exit_exception)
 {
   int ret;
   pkl_ast ast = NULL;
@@ -532,10 +520,8 @@ pkl_execute_file (pkl_compiler compiler, const char *fname,
   /* Execute the program in the poke vm.  */
   {
     pvm_val val;
-    int status = pvm_run (compiler->vm, program, &val);
 
-    if (exit_status)
-      *exit_status = status;
+    pvm_run (compiler->vm, program, &val, exit_exception);
   }
 
   pvm_destroy_program (program);
diff --git a/libpoke/pkl.h b/libpoke/pkl.h
index ebbdf5ab..9b0b6904 100644
--- a/libpoke/pkl.h
+++ b/libpoke/pkl.h
@@ -88,36 +88,38 @@ void pkl_free (pkl_compiler compiler);
 /* Compile an execute a Poke program from the given file FNAME.
    Return 1 if the compilation was successful, 0 otherwise.
 
-   If EXIT_STATUS is not NULL, set it to the status in which the
-   executed program terminated.  */
+   If not NULL, *EXIT_EXCEPTION is set to an exception value if the
+   execution of the program gets interrupted by an unhandled exception.
+   Otherwise *EXIT_EXCEPTION is set to PK_NULL.  */
 
 int pkl_execute_file (pkl_compiler compiler, const char *fname,
-                      int *exit_status);
+                      pvm_val *exit_exception);
 
 /* Compile and execute Poke program from a NULL-terminated string
    BUFFER.  Return 0 in case of a compilation error, 1 otherwise.  If
    not NULL, END is set to the first character in BUFFER that is not
    part of the compiled entity.
 
-   If EXIT_STATUS is not NULL, set it to the status in which the
-   executed program terminated.  */
+   If not NULL, *EXIT_EXCEPTION is set to an exception value if the
+   execution of the program gets interrupted by an unhandled exception.
+   Otherwise *EXIT_EXCEPTION is set to PK_NULL.  */
 
 int pkl_execute_buffer (pkl_compiler compiler, const char *buffer,
-                        const char **end, int *exit_status);
+                        const char **end, pvm_val *exit_exception);
 
 /* Like pkl_execute_buffer, but compile and execute a single Poke
    expression, that generates a value in VAL. */
 
 int pkl_execute_expression (pkl_compiler compiler,
                             const char *buffer, const char **end,
-                            pvm_val *val, int *exit_status);
+                            pvm_val *val, pvm_val *exit_exception);
 
 /* Like pkl_execute_expression but compile and execute a single Poke statement,
    which may generate a value in VAL if it is an "expression
    statement".  Otherwise VAL is set to PVM_NULL.  */
 
 int pkl_execute_statement (pkl_compiler compiler, const char *buffer, const 
char **end,
-                           pvm_val *val, int *exit_status);
+                           pvm_val *val, pvm_val *exit_exception);
 
 /* Compile a single Poke expression and return the resulting PVM
    program.  */
diff --git a/libpoke/pvm.c b/libpoke/pvm.c
index 7529891b..6e2edfc2 100644
--- a/libpoke/pvm.c
+++ b/libpoke/pvm.c
@@ -35,6 +35,8 @@
 
 #define PVM_STATE_RESULT_VALUE(PVM)                     \
   (PVM_STATE_BACKING_FIELD (& (PVM)->pvm_state, result_value))
+#define PVM_STATE_EXIT_EXCEPTION_VALUE(PVM)             \
+  (PVM_STATE_BACKING_FIELD (& (PVM)->pvm_state, exit_exception_value))
 #define PVM_STATE_EXIT_CODE(PVM)                        \
   (PVM_STATE_BACKING_FIELD (& (PVM)->pvm_state, exit_code))
 #define PVM_STATE_VM(PVM)                               \
@@ -155,12 +157,13 @@ pvm_get_env (pvm apvm)
 }
 
 enum pvm_exit_code
-pvm_run (pvm apvm, pvm_program program, pvm_val *res)
+pvm_run (pvm apvm, pvm_program program, pvm_val *res, pvm_val *exc)
 {
   sighandler_t previous_handler;
   pvm_routine routine = pvm_program_routine (program);
 
   PVM_STATE_RESULT_VALUE (apvm) = PVM_NULL;
+  PVM_STATE_EXIT_EXCEPTION_VALUE (apvm) = PVM_NULL;
   PVM_STATE_EXIT_CODE (apvm) = PVM_EXIT_OK;
 
   previous_handler = signal (SIGINT, pvm_handle_signal);
@@ -169,6 +172,8 @@ pvm_run (pvm apvm, pvm_program program, pvm_val *res)
 
   if (res != NULL)
     *res = PVM_STATE_RESULT_VALUE (apvm);
+  if (exc != NULL)
+    *exc = PVM_STATE_EXIT_EXCEPTION_VALUE (apvm);
 
   return PVM_STATE_EXIT_CODE (apvm);
 }
@@ -197,7 +202,7 @@ pvm_call_closure (pvm vm, pvm_val cls, ...)
   /* Run the program in the poke VM.  */
   program = pkl_asm_finish (pasm, 1 /* epilogue */);
   pvm_program_make_executable (program);
-  (void) pvm_run (vm, program, NULL);
+  (void) pvm_run (vm, program, NULL, NULL);
   pvm_destroy_program (program);
 
 }
diff --git a/libpoke/pvm.h b/libpoke/pvm.h
index 78d5471b..64345bf7 100644
--- a/libpoke/pvm.h
+++ b/libpoke/pvm.h
@@ -595,12 +595,17 @@ void pvm_reset_profile (pvm pvm);
    If the execution of PROGRAM generates a result value, it is put in
    RES.
 
+   If not NULL, *EXIT_EXCEPTION is set to an exception value if the
+   execution of the program gets interrupted by an unhandled exception.
+   Otherwise *EXIT_EXCEPTION is set to PK_NULL.
+
    This function returns an exit code, indicating whether the
    execution was successful or not.  */
 
 enum pvm_exit_code pvm_run (pvm vm,
                             pvm_program program,
-                            pvm_val *res);
+                            pvm_val *res,
+                            pvm_val *exit_exception);
 
 /* Given a PVM and a closure value, call the closure.
 
diff --git a/libpoke/pvm.jitter b/libpoke/pvm.jitter
index 1ff133fe..bb16bf08 100644
--- a/libpoke/pvm.jitter
+++ b/libpoke/pvm.jitter
@@ -963,6 +963,7 @@ state-struct-backing-c
   code
       enum pvm_exit_code exit_code;
       pvm_val result_value;
+      pvm_val exit_exception_value;
       jitter_stack_height canary_stack;
       jitter_stack_height canary_returnstack;
       jitter_stack_height canary_exceptionstack;
@@ -6119,6 +6120,20 @@ instruction raise ()
   end
 end
 
+# Instruction: popexite
+#
+# Pops the exception on the stack and sets it in the VM.
+#
+# Stack: ( EXCEPTION  -- )
+# Exceptions Stack: ( -- )
+
+instruction popexite ()
+  code
+    PVM_STATE_BACKING_FIELD (exit_exception_value) = JITTER_TOP_STACK ();
+    JITTER_DROP_STACK ();
+  end
+end
+
 
 ## Debugging Instructions
 
diff --git a/libpoke/std.pk b/libpoke/std.pk
index dfe75a76..fd6829ac 100644
--- a/libpoke/std.pk
+++ b/libpoke/std.pk
@@ -374,5 +374,5 @@ fun alignto = (offset<uint<64>,b> offset,
 
 fun exit = (int<32> exit_code = 0) void:
   {
-    raise Exception { code = EC_exit, exit_status = exit_code };
+    raise Exception { code = EC_exit, name = "exit", exit_status = exit_code };
   }
diff --git a/poke/pk-cmd-ios.c b/poke/pk-cmd-ios.c
index 3723b932..1f494e46 100644
--- a/poke/pk-cmd-ios.c
+++ b/poke/pk-cmd-ios.c
@@ -398,7 +398,7 @@ pk_cmd_load_file (int argc, struct pk_cmd_arg argv[], 
uint64_t uflags)
   else
     goto no_file;
 
-  if (pk_compile_file (poke_compiler, filename, NULL /* exit_status */)
+  if (pk_compile_file (poke_compiler, filename, NULL /* exception */)
       != PK_OK)
     /* Note that the compiler emits its own error messages.  */
     goto error;
diff --git a/poke/pk-map.c b/poke/pk-map.c
index cc19c6f1..d4b61c81 100644
--- a/poke/pk-map.c
+++ b/poke/pk-map.c
@@ -502,7 +502,7 @@ pk_map_load_parsed_map (int ios_id, const char *mapname,
                                      condition,
                                      NULL /* end */,
                                      &val,
-                                     NULL /* exit_status */) != PK_OK)
+                                     NULL /* exception */) != PK_OK)
             goto error;
 
           if (pk_type_code (pk_typeof (val)) != PK_INT
@@ -538,7 +538,7 @@ pk_map_load_parsed_map (int ios_id, const char *mapname,
           if (pk_compile_buffer (poke_compiler,
                                  defvar_str,
                                  NULL /* end */,
-                                 NULL /* exit_status */) != PK_OK)
+                                 NULL /* exception */) != PK_OK)
             goto error;
         }
     }
diff --git a/poke/poke.c b/poke/poke.c
index e317bf5d..32671e7c 100644
--- a/poke/poke.c
+++ b/poke/poke.c
@@ -433,10 +433,40 @@ parse_args_2 (int argc, char *argv[])
           break;
         case 'l':
         case LOAD_ARG:
-          if (pk_compile_file (poke_compiler, optarg,
-                               NULL /* exit_status */) != PK_OK)
+          {
+            pk_val exception;
+            int exc_code;
+            const char *exc_name;
+            const char *exc_loc;
+            const char *exc_msg;
+
+            if (pk_compile_file (poke_compiler, optarg, &exception) != PK_OK)
+              goto exit_success;
+            if (exception == PK_NULL)
+              break; /* Everything is good.  */
+
+            /* There's an unhandled exception.  */
+
+            exc_code = pk_int_value (pk_struct_ref_field_value (exception,
+                                                                "code"));
+            if (exc_code == PK_E_EXIT || poke_quiet_p)
+              goto exit_success;
+
+            exc_name = pk_string_str (pk_struct_ref_field_value (exception,
+                                                                 "name"));
+            exc_loc = pk_string_str (pk_struct_ref_field_value (exception,
+                                                                "location"));
+            exc_msg = pk_string_str (pk_struct_ref_field_value (exception,
+                                                                "msg"));
+            pk_printf (_("error: unhandled %s exception while "
+                         "loading '%s'%s%s%s%s\n"),
+                       exc_name, optarg,
+                       STREQ (exc_loc, "") ? "" : " at ",
+                       STREQ (exc_loc, "") ? "" : exc_loc,
+                       STREQ (exc_msg, "") ? "" : " ",
+                       STREQ (exc_msg, "") ? "" : exc_msg);
             goto exit_success;
-          break;
+          }
         case 'c':
         case CMD_ARG:
           {
@@ -454,14 +484,19 @@ parse_args_2 (int argc, char *argv[])
           }
         case 'L':
           {
-            int exit_status;
+            pk_val exception;
+            int exit_status = 0;
 
             /* Build argv in the compiler, with the rest of the
                command-line arguments.  Then execute the script and
                return.  */
             set_script_args (argc, argv);
-            if (pk_compile_file (poke_compiler, optarg, &exit_status) != PK_OK)
+            if (pk_compile_file (poke_compiler, optarg, &exception) != PK_OK)
               goto exit_failure;
+            if (exception != PK_NULL)
+              exit_status
+                = pk_int_value (pk_struct_ref_field_value (exception,
+                                                           "exit_status"));
 
             finalize ();
             exit (exit_status);
-- 
2.34.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]