[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] pkl: Use `format` function in `assert` implementation
From: |
Mohammad-Reza Nabipoor |
Subject: |
[PATCH] pkl: Use `format` function in `assert` implementation |
Date: |
Thu, 17 Jun 2021 01:49:59 +0430 |
This commit changes the implementation of `assert` statement to
pass source location info (FILENAME, LINE and COLUMN) separately,
instead of passing a pre-formated string
("<FILENAME>:<LINE>:<COLUMN>"). And makes `msg` string using `format`
function.
The reason that this commit, separates the runtime library (`pkl-rt.pk`)
into two separate files (`pkl-rt-1.pk` and `pkl-rt-2.pk`) is that
codegen of `format` generates a function call to
`_pkl_reduce_string_array`, and it's inaccessible to codegen at this
stage. Because `_pkl_reduce_string_array` is also defined in the runtime
library. Moving `_pkl_assert` function to `pkl-rt-2.pk` makes codegen
happy!
2021-06-16 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
* libpoke/pkl-tab.y (pkl_make_assertion): Change the invocation of
`_pkl_assert` to pass FILENAME, LINE and COLUMN as separate arguments
instead of passing as a pre-formated string.
* libpoke/pkl.c (pkl_load_rt): New function to load runtime library.
(pkl_new): Load `pkl-rt-1.pk` and `pkl-rt-2.pk` runtime libraries.
* libpoke/pkl-rt.pk: Rename to `libpoke/pkl-rt-1`.
(_pkl_assert): Remove.
* libpoke/pkl-rt-1.pk: New file.
* libpoke/pkl-rt-2.pk: New file. New implementation of `_pkl_assert`
which uses `format` to report FILENAME, LINE and COLUMN.
* libpoke/Makefile.am (dist_pkgdata_DATA): Update
* etc/hacking.org: Rename `pkl-rt.pk` to what's appropriate.
* HACKING: Likewise.
* doc/learn-poke-language-in-y-minutes.pk: Likewise.
* libpoke/pvm.h: Likewise.
* libpoke/pvm-val.c: Likewise.
* libpoke/ras: Likewise.
---
Hi, Jose.
Side suggestion: WDYT about having an ASTREF_CHAIN function?
In `pkl_make_assertion` function in `libpoke/pkl-tab.y`,
I've called `ASTREF` for `arg_{name,msg,fname,line,col}` AST nodes
explicitly. But ASTREF will be called on `arg_cond` (the first
funcall_arg) in `pkl_ast_make_funcall` function.
Isn't it more consistent if `pkl_ast_make_funcall` calls `ASTREF`
for all chained arguments?
Regards,
Mohammad-Reza
ChangeLog | 20 +++++++++
HACKING | 10 ++---
doc/learn-poke-language-in-y-minutes.pk | 2 +-
etc/hacking.org | 10 ++---
libpoke/Makefile.am | 2 +-
libpoke/{pkl-rt.pk => pkl-rt-1.pk} | 22 +---------
libpoke/pkl-rt-2.pk | 39 +++++++++++++++++
libpoke/pkl-tab.y | 58 +++++++++++++++----------
libpoke/pkl.c | 43 ++++++++++++------
libpoke/pvm-val.c | 2 +-
libpoke/pvm.h | 2 +-
libpoke/ras | 2 +-
12 files changed, 138 insertions(+), 74 deletions(-)
rename libpoke/{pkl-rt.pk => pkl-rt-1.pk} (95%)
create mode 100644 libpoke/pkl-rt-2.pk
diff --git a/ChangeLog b/ChangeLog
index 76ea7c5d..5c6ba08a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2021-06-16 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
+
+ * libpoke/pkl-tab.y (pkl_make_assertion): Change the invocation of
+ `_pkl_assert` to pass FILENAME, LINE and COLUMN as separate arguments
+ instead of passing as a pre-formated string.
+ * libpoke/pkl.c (pkl_load_rt): New function to load runtime library.
+ (pkl_new): Load `pkl-rt-1.pk` and `pkl-rt-2.pk` runtime libraries.
+ * libpoke/pkl-rt.pk: Rename to `libpoke/pkl-rt-1`.
+ (_pkl_assert): Remove.
+ * libpoke/pkl-rt-1.pk: New file.
+ * libpoke/pkl-rt-2.pk: New file. New implementation of `_pkl_assert`
+ which uses `format` to report FILENAME, LINE and COLUMN.
+ * libpoke/Makefile.am (dist_pkgdata_DATA): Update
+ * etc/hacking.org: Rename `pkl-rt.pk` to what's appropriate.
+ * HACKING: Likewise.
+ * doc/learn-poke-language-in-y-minutes.pk: Likewise.
+ * libpoke/pvm.h: Likewise.
+ * libpoke/pvm-val.c: Likewise.
+ * libpoke/ras: Likewise.
+
2021-06-06 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
* common/pk-utils.h (pk_format_binary): New function declaration.
diff --git a/HACKING b/HACKING
index 815096ca..a09a4ea5 100644
--- a/HACKING
+++ b/HACKING
@@ -631,7 +631,7 @@ with GNU poke. If not, see [https://www.gnu.org/licenses/].
to perform some operation defined recursively.
In these situations, the solution is to first write a Poke function in
- the compiler's runtime library, `pkl-rt.pk', like:
+ the compiler's runtime library, `pkl-rt*.pk', like:
,----
| fun _pkl_foo = (uint<64> ival, uint<64> eval,
@@ -1572,7 +1572,7 @@ with GNU poke. If not, see
[https://www.gnu.org/licenses/].
,----
| The final step is to define the built-in function proper, in the
- | compiler run-time, in =pkl-rt.pk=:
+ | compiler run-time, in =pkl-rt-1.pk=:
`----
,----
@@ -1587,10 +1587,10 @@ with GNU poke. If not, see
[https://www.gnu.org/licenses/].
~~~~~~~~~~~~~~~~~~~~~~~
Exception types or codes are signed 32-bit integers, and are defined
- in `libpoke/pkl-rt.pk' as `EC_*' variables.
+ in `libpoke/pkl-rt-1.pk' as `EC_*' variables.
The exceptions themselves are struct values of type Exception, also
- defined in `libpoke/pkl-rt.pk'.
+ defined in `libpoke/pkl-rt-1.pk'.
There are two ways an exception can be raised in the PVM:
@@ -1611,7 +1611,7 @@ with GNU poke. If not, see
[https://www.gnu.org/licenses/].
is installed by the macro-assembler in `libpoke/pkl-asm.c:pkl_asm_new'
and `libpoke/pkl-asm.c:pkl_asm_finish'. It calls the function
`_pkl_exception_handler', that is defined in the compiler runtime in
- `libpoke/pkl-rt.pkl'.
+ `libpoke/pkl-rt-1.pkl'.
12.2 Signal Handling
diff --git a/doc/learn-poke-language-in-y-minutes.pk
b/doc/learn-poke-language-in-y-minutes.pk
index 738319d4..9b4e05b7 100644
--- a/doc/learn-poke-language-in-y-minutes.pk
+++ b/doc/learn-poke-language-in-y-minutes.pk
@@ -581,7 +581,7 @@ catch (Exception e)
}
/* Exception codes in the range `0..254` are reserved for Poke. These codes
- * are defined by `EC_*` variables in `pkl-rt.pk` file.
+ * are defined by `EC_*` variables in `pkl-rt-1.pk` file.
*
* Users also can define their own exceptions by calling `exception_code`
* function.
diff --git a/etc/hacking.org b/etc/hacking.org
index cd6a21f2..87cb40c2 100644
--- a/etc/hacking.org
+++ b/etc/hacking.org
@@ -451,7 +451,7 @@ Indu Bhagat <indu.bhagat@oracle.com>
complex formulae or to perform some operation defined recursively.
In these situations, the solution is to first write a Poke
- function in the compiler's runtime library, =pkl-rt.pk=, like:
+ function in the compiler's runtime library, =pkl-rt*.pk=, like:
: fun _pkl_foo = (uint<64> ival, uint<64> eval,
: uint<32> ivalw, uint<32> fieldw) uint<64>:
@@ -1256,7 +1256,7 @@ have a testsuite in =testsuite/poke.FOO= with a driver
: break;
: The final step is to define the built-in function proper, in the
- : compiler run-time, in =pkl-rt.pk=:
+ : compiler run-time, in =pkl-rt-1.pk=:
: fun rand = int<32>: __PKL_BUILTIN_RAND__;
@@ -1265,10 +1265,10 @@ have a testsuite in =testsuite/poke.FOO= with a driver
** Exception Handling
Exception types or codes are signed 32-bit integers, and are
- defined in =libpoke/pkl-rt.pk= as =EC_*= variables.
+ defined in =libpoke/pkl-rt-1.pk= as =EC_*= variables.
The exceptions themselves are struct values of type Exception, also
- defined in =libpoke/pkl-rt.pk=.
+ defined in =libpoke/pkl-rt-1.pk=.
There are two ways an exception can be raised in the PVM:
@@ -1291,7 +1291,7 @@ have a testsuite in =testsuite/poke.FOO= with a driver
=libpoke/pkl-asm.c:pkl_asm_new= and
=libpoke/pkl-asm.c:pkl_asm_finish=. It calls the function
=_pkl_exception_handler=, that is defined in the compiler runtime
- in =libpoke/pkl-rt.pkl=.
+ in =libpoke/pkl-rt-1.pkl=.
** Signal Handling
diff --git a/libpoke/Makefile.am b/libpoke/Makefile.am
index d549f662..428cd827 100644
--- a/libpoke/Makefile.am
+++ b/libpoke/Makefile.am
@@ -22,7 +22,7 @@ CLEANFILES =
DISTCLEANFILES =
MAINTAINERCLEANFILES =
-dist_pkgdata_DATA = pkl-rt.pk std.pk std-types.pk
+dist_pkgdata_DATA = pkl-rt-1.pk pkl-rt-2.pk std.pk std-types.pk
dist_pkgconfig_lib_DATA = $(pkgconfig_libfile)
lib_LTLIBRARIES = libpoke.la
diff --git a/libpoke/pkl-rt.pk b/libpoke/pkl-rt-1.pk
similarity index 95%
rename from libpoke/pkl-rt.pk
rename to libpoke/pkl-rt-1.pk
index 9535f22e..14f70c96 100644
--- a/libpoke/pkl-rt.pk
+++ b/libpoke/pkl-rt-1.pk
@@ -1,4 +1,4 @@
-/* pkl-rt.pkl - Run-time library for the poke compiler. */
+/* pkl-rt-1.pk - Run-time library for the poke compiler. */
/* Copyright (C) 2019, 2020, 2021 Jose E. Marchesi. */
@@ -196,26 +196,6 @@ fun _pkl_exception_handler = (Exception exception) int<32>:
return exception.exit_status;
}
-/* Assertion function.
-
- The compiler transforms assert statement to invocation of this
- function. COND is first argument of assert statement, and MSG is
- the optional second argument. LINEINFO contains the source location
- of the assert statement formatted like "<FILENAME>:<LINE>:<COLUMN>".
- */
-
-fun _pkl_assert = (uint<64> cond, string msg, string lineinfo) void:
- {
- if (cond)
- return;
-
- raise Exception {
- code = EC_assert,
- msg = "assertion failed at " + lineinfo + (msg'length ? ": " + msg : ""),
- exit_status = 1,
- };
- }
-
/* Exit a Poke program with the given exit status code. This is equivalent
to raise an E_exit exception, but provides a more conventional
syntax. */
diff --git a/libpoke/pkl-rt-2.pk b/libpoke/pkl-rt-2.pk
new file mode 100644
index 00000000..bdc73f77
--- /dev/null
+++ b/libpoke/pkl-rt-2.pk
@@ -0,0 +1,39 @@
+/* pkl-rt-2.pkl - Run-time library for the poke compiler. */
+
+/* Copyright (C) 2021 The poke authors. */
+
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Assertion function.
+
+ The compiler transforms assert statement to invocation of this
+ function. COND is first argument of assert statement, and MSG is
+ the optional second argument. FILENAME is the name of source
+ file. LINE and COL are, respectively, line and column number
+ of the assert statement in the source file. */
+
+fun _pkl_assert = (uint<64> cond, string msg, string filename,
+ uint<64> line, uint<64> col) void:
+ {
+ if (cond)
+ return;
+
+ raise Exception {
+ code = EC_assert,
+ msg = format ("assertion failed at %s:%u64d:%u64d%s",
+ filename, line, col, msg'length ? ": " + msg : ""),
+ exit_status = 1,
+ };
+ }
diff --git a/libpoke/pkl-tab.y b/libpoke/pkl-tab.y
index f8ce36c2..8c1913b4 100644
--- a/libpoke/pkl-tab.y
+++ b/libpoke/pkl-tab.y
@@ -134,7 +134,8 @@ pkl_make_assertion (struct pkl_parser *p, pkl_ast_node
cond, pkl_ast_node msg,
struct pkl_ast_loc stmt_loc)
{
pkl_ast_node vfunc, call, call_arg;
- pkl_ast_node arg_cond, arg_msg, arg_lineinfo; /* _pkl_assert args */
+ /* _pkl_assert args */
+ pkl_ast_node arg_cond, arg_msg, arg_fname, arg_line, arg_col;
/* Make variable for `_pkl_assert` function */
{
@@ -154,43 +155,52 @@ pkl_make_assertion (struct pkl_parser *p, pkl_ast_node
cond, pkl_ast_node msg,
vfunc_init, back, over);
}
- /* First argument of _pkl_assert */
+ /* First argument of _pkl_assert: condition */
arg_cond = pkl_ast_make_funcall_arg (p->ast, cond, NULL);
PKL_AST_LOC (arg_cond) = PKL_AST_LOC (cond);
- /* Second argument of _pkl_assert */
+ /* Second argument of _pkl_assert: user message */
if (msg == NULL)
{
- pkl_ast_node stype = pkl_ast_make_string_type (p->ast);
-
msg = pkl_ast_make_string (p->ast, "");
- PKL_AST_TYPE (msg) = ASTREF (stype);
+ PKL_AST_TYPE (msg) = ASTREF (pkl_ast_make_string_type (p->ast));
}
arg_msg = pkl_ast_make_funcall_arg (p->ast, msg, NULL);
arg_msg = ASTREF (arg_msg);
PKL_AST_LOC (arg_msg) = PKL_AST_LOC (msg);
- /* Third argument of _pkl_assert to report the location of the assert
- statement with the following format "<FILENAME>:<LINE>:<COLUMN>". */
+ /* Third argument of _pkl_assert: file name */
+ {
+ pkl_ast_node fname
+ = pkl_ast_make_string (p->ast, p->filename ? p->filename : "<stdin>");
+
+ PKL_AST_TYPE (fname) = ASTREF (pkl_ast_make_string_type (p->ast));
+ arg_fname = pkl_ast_make_funcall_arg (p->ast, fname, NULL);
+ arg_fname = ASTREF (arg_fname);
+ }
+
+ /* Fourth argument of _pkl_assert: line */
{
- char *str;
- pkl_ast_node lineinfo, stype;
-
- if (asprintf (&str, "%s:%d:%d", p->filename ? p->filename : "<stdin>",
- stmt_loc.first_line, stmt_loc.first_column)
- == -1)
- return NULL;
- lineinfo = pkl_ast_make_string (p->ast, str);
- free (str);
- stype = pkl_ast_make_string_type (p->ast);
- PKL_AST_TYPE (lineinfo) = ASTREF (stype);
-
- arg_lineinfo = pkl_ast_make_funcall_arg (p->ast, lineinfo, NULL);
- arg_lineinfo = ASTREF (arg_lineinfo);
+ pkl_ast_node line = pkl_ast_make_integer (p->ast, stmt_loc.first_line);
+
+ PKL_AST_TYPE (line) = ASTREF (pkl_ast_make_integral_type (p->ast, 64, 0));
+ arg_line = pkl_ast_make_funcall_arg (p->ast, line, NULL);
+ arg_line = ASTREF (arg_line);
+ }
+
+ /* Fifth argument of _pkl_assert: column */
+ {
+ pkl_ast_node col = pkl_ast_make_integer (p->ast, stmt_loc.first_column);
+
+ PKL_AST_TYPE (col) = ASTREF (pkl_ast_make_integral_type (p->ast, 64, 0));
+ arg_col = pkl_ast_make_funcall_arg (p->ast, col, NULL);
+ arg_col = ASTREF (arg_col);
}
- call_arg
- = pkl_ast_chainon (arg_cond, pkl_ast_chainon (arg_msg, arg_lineinfo));
+ call_arg = pkl_ast_chainon (arg_line, arg_col);
+ call_arg = pkl_ast_chainon (arg_fname, call_arg);
+ call_arg = pkl_ast_chainon (arg_msg, call_arg);
+ call_arg = pkl_ast_chainon (arg_cond, call_arg);
call = pkl_ast_make_funcall (p->ast, vfunc, call_arg);
return pkl_ast_make_exp_stmt (p->ast, call);
}
diff --git a/libpoke/pkl.c b/libpoke/pkl.c
index 46d4bc7e..2f5c274f 100644
--- a/libpoke/pkl.c
+++ b/libpoke/pkl.c
@@ -72,6 +72,27 @@ struct pkl_compiler
pkl_alien_token_handler_fn alien_token_fn;
};
+
+static int
+pkl_load_rt(pkl_compiler compiler, char *poke_rt_pk)
+{
+ if (!pkl_execute_file (compiler, poke_rt_pk, NULL))
+ {
+ free (poke_rt_pk);
+
+ pk_term_class ("error");
+ pk_puts ("internal error: ");
+ pk_term_end_class ("error");
+ pk_puts ("compiler failed to bootstrap itself\n");
+
+ pkl_free (compiler);
+ return 0;
+ }
+ free (poke_rt_pk);
+ compiler->bootstrapped = 1;
+ return 1;
+}
+
pkl_compiler
pkl_new (pvm vm, const char *rt_path, uint32_t flags)
{
@@ -99,25 +120,19 @@ pkl_new (pvm vm, const char *rt_path, uint32_t flags)
/* Bootstrap the compiler. An error bootstraping is an internal
error and should be reported as such. */
{
- char *poke_rt_pk = pk_str_concat (rt_path, "/pkl-rt.pk", NULL);
+ char *poke_rt_pk = pk_str_concat (rt_path, "/pkl-rt-1.pk", NULL);
if (!poke_rt_pk)
goto out_of_memory;
- if (!pkl_execute_file (compiler, poke_rt_pk, NULL))
- {
- free (poke_rt_pk);
-
- pk_term_class ("error");
- pk_puts ("internal error: ");
- pk_term_end_class ("error");
- pk_puts ("compiler failed to bootstrap itself\n");
+ if (!pkl_load_rt (compiler, poke_rt_pk))
+ return NULL;
- pkl_free (compiler);
- return NULL;
- }
- free (poke_rt_pk);
+ poke_rt_pk = pk_str_concat (rt_path, "/pkl-rt-2.pk", NULL);
+ if (!poke_rt_pk)
+ goto out_of_memory;
- compiler->bootstrapped = 1;
+ if (!pkl_load_rt (compiler, poke_rt_pk))
+ return NULL;
}
#define LOAD_STD(NAME) \
diff --git a/libpoke/pvm-val.c b/libpoke/pvm-val.c
index b938c3ea..d6fc812a 100644
--- a/libpoke/pvm-val.c
+++ b/libpoke/pvm-val.c
@@ -1650,7 +1650,7 @@ pvm_call_pretty_printer (pvm vm, pvm_val val)
}
/* IMPORTANT: please keep pvm_make_exception in sync with the
- definition of the struct Exception in pkl-rt.pk. */
+ definition of the struct Exception in pkl-rt-1.pk. */
pvm_val
pvm_make_exception (int code, char *message, int exit_status)
diff --git a/libpoke/pvm.h b/libpoke/pvm.h
index ad9e9939..87082c62 100644
--- a/libpoke/pvm.h
+++ b/libpoke/pvm.h
@@ -477,7 +477,7 @@ enum pvm_exit_code
};
/* Exceptions. These should be in sync with the exception code
- variables, and the exception messages, declared in pkl-rt.pkl */
+ variables, and the exception messages, declared in pkl-rt-1.pk */
#define PVM_E_GENERIC 0
#define PVM_E_GENERIC_MSG "generic"
diff --git a/libpoke/ras b/libpoke/ras
index 3f300332..3dc6709b 100755
--- a/libpoke/ras
+++ b/libpoke/ras
@@ -160,7 +160,7 @@
#
# The called function should be defined in the global environment.
# Most typically this directive is used to call functions defined in
-# the compiler's run-time library (pkl-rt.pk).
+# the compiler's run-time library (pkl-rt*.pk).
#
# Literal C Code
# --------------
--
2.32.0
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] pkl: Use `format` function in `assert` implementation,
Mohammad-Reza Nabipoor <=