From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Artyom Poptsov Newsgroups: gmane.lisp.guile.user Subject: Guile 2.0.9, reader: Cannot 'read' an '*unspecified*' value Date: Tue, 03 Nov 2015 16:56:32 +0300 Message-ID: <87611jxk33.fsf@elephant.savannah> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/signed; boundary="==-=-="; micalg=pgp-sha512; protocol="application/pgp-signature" X-Trace: ger.gmane.org 1446559076 16378 80.91.229.3 (3 Nov 2015 13:57:56 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 3 Nov 2015 13:57:56 +0000 (UTC) To: Guile Users' Mailing List Original-X-From: guile-user-bounces+guile-user=m.gmane.org@gnu.org Tue Nov 03 14:57:48 2015 Return-path: Envelope-to: guile-user@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Ztc5p-0004EC-Ko for guile-user@m.gmane.org; Tue, 03 Nov 2015 14:57:45 +0100 Original-Received: from localhost ([::1]:48583 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ztc5p-0003ys-0o for guile-user@m.gmane.org; Tue, 03 Nov 2015 08:57:45 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:48142) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ztc5e-0003yc-C9 for guile-user@gnu.org; Tue, 03 Nov 2015 08:57:36 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Ztc5Z-0002qJ-Ai for guile-user@gnu.org; Tue, 03 Nov 2015 08:57:34 -0500 Original-Received: from mail-lf0-x22e.google.com ([2a00:1450:4010:c07::22e]:35420) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ztc5Y-0002pz-VQ for guile-user@gnu.org; Tue, 03 Nov 2015 08:57:29 -0500 Original-Received: by lfbn126 with SMTP id n126so18568247lfb.2 for ; Tue, 03 Nov 2015 05:57:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:user-agent:mime-version :content-type; bh=U+lFzlrNJf0ptCoxctRrRaDF71XuHkkMmNZgCLUryH0=; b=cOyLacRKS/J0aZVuynr4tV6B9Lv63OSYy/Ss8TqRWm+dGzeb2JWMSAN++qekoJbedY FA29qc/Z5+qKgFNza9Yf67qo1D0gbTLbC4Iv3aF496UR26gmibcN+64hEaO7B3GBhhYo QxUrrW2N5MZv8c6Pw2vgVnKp9e/XAjLTwkcKv3nkLxiPadUIxm9KIfcqXqUnTRbMaDHZ c+LxnBVKCPSUncBkKy08WKkPqvpkNr8xqd/jG52uvQ4nsaJ7Xne3r2vesQ0DFFOI+7NA yCqe8RHCUOLs3M4ooPSuKQcXnwuV7PLNtfHOriKwYFmV6farhdwWcDNg/ugCEk4Ac8vg 1ftw== X-Received: by 10.112.235.65 with SMTP id uk1mr12630573lbc.118.1446559047725; Tue, 03 Nov 2015 05:57:27 -0800 (PST) Original-Received: from elephant.savannah (109-184-186-180.dynamic.mts-nn.ru. [109.184.186.180]) by smtp.gmail.com with ESMTPSA id f138sm415143lfd.6.2015.11.03.05.57.25 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 03 Nov 2015 05:57:26 -0800 (PST) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:4010:c07::22e X-BeenThere: guile-user@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: General Guile related discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-user-bounces+guile-user=m.gmane.org@gnu.org Original-Sender: guile-user-bounces+guile-user=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.user:12128 Archived-At: --==-=-= Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= Content-Type: text/plain Content-Transfer-Encoding: quoted-printable Hello Guilers, it seems that currently there's no way to 'read' back an '*unspecified*' value, but in some cases such a feature might be handy. Here's the description of the problem; a patch is attached as well. To be more specific, this expression fails in GNU Guile 2.0.9 and 2.1.0.455-73f61-dirty (which I compiled from the master branch): =2D-8<---------------cut here---------------start------------->8--- (read (open-input-string (object->string *unspecified*))) =2D| ERROR: In procedure read: =2D| ERROR: In procedure scm_lreadr: #:1:3: Unknown # object:= #\< =2D| =2D| Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. =2D-8<---------------cut here---------------end--------------->8--- I faced with this problem when tried to 'read' back a vector returned by 'make-vector' with the default filling (that are '*unspecified*' values). Looking through the Guile sources I found that one could fix a problem with reading of a (custom) object using 'read-hash-extend' procedure. But alas -- the problem, again, that I cannot return an unspecified value from my Guile reader callback because 'scm_read_sharp' from 'libguile/read.c' considers such a value as an indication that the procedure is unable to read an object. With that said, I think the fix could be pretty simple -- we could return a multiple values object from the Guile reader callback in the case when we need to 'read' an unspecified value where the 2nd value could indicate whether the returned unspecified value is *the* value or an indication that we could not read the value. As far as I understand, this solution is backward compatible so current callbacks will work as usual. As an example: =2D-8<---------------cut here---------------start------------->8--- (read-hash-extend #\< (lambda (c port) (let ((str "") (pending 0) (c (read-char port))) (while (not (and (char=3D? c #\>) (=3D pending 0))) (and (char=3D? c #\<) (set! pending (1+ pending))) (and (char=3D? c #\>) (set! pending (1- pending))) (set! str (string-append str (string c))) (set! c (read-char port))) (if (string=3D? str "unspecified") (values *unspecified* #t) *unspecified*)))) (define (read-string str) (read (open-input-string str))) (write (read-string (object->string (make-vector 2)))) ;; =3D> #(# #) (write (read-string (object->string *unspecified*))) ;; =3D> # =2D-8<---------------cut here---------------end--------------->8--- As I said, the patch is attached. I'd love to hear any comments on the patch, especially given that this patch is my first attempt to make a contribution to GNU Guile. Thanks, =2D Artyom =2D-=20 Artyom V. Poptsov ; GPG Key: 0898A02F Home page: http://poptsov-artyom.narod.ru/ --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-Provide-means-to-read-an-unspecified-object.patch Content-Transfer-Encoding: quoted-printable Content-Description: [PATCH] Provide means to 'read' an unspecified object From=20c593bdd8b7c62ea857fb196ceeb003bb87caf9fa Mon Sep 17 00:00:00 2001 From: "Artyom V. Poptsov" Date: Tue, 6 Oct 2015 10:20:57 +0300 Subject: [PATCH] Provide means to 'read' an # object Currently there's no way to 'read' back an unspecified value, but in some cases such a feature might be handy (eg. in case of reading a vector filled with unspecified objects.) This patch changes the way the reader treats the returned value of a reader extension callback set by 'read-hash-extend': now when the callback returns a multiple values object and the second value is '#t', the 1st value returned as is, even if it is an unspecified object. If a callback returns an unspecified object alone, it is considered as an indication that the callback could not read an object -- in other words, the solution should be backward compatible with existing reader extenstions. * libguile/read.c (scm_read_sharp): Check whether the value returned by 'scm_read_sharp_extension' is a multiple values object and handle it appropriately if so. (read_inner_expression): Handle multiple values object returned by 'scm_read_sharp'. * test-suite/tests/reader.test: Add a test for 'read-hash-extend' to ensure that the callback can return an unspecified object. Add a test for the same procedure that ensures that the callback can indicate an unknown object by returning an unspecified value alone. * doc/ref/api-evaluation.texi: Update description of 'read-hash-extend'. =2D-- doc/ref/api-evaluation.texi | 8 ++++++++ libguile/read.c | 19 +++++++++++++------ test-suite/tests/reader.test | 11 +++++++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/doc/ref/api-evaluation.texi b/doc/ref/api-evaluation.texi index 296f1da..8278ab9 100644 =2D-- a/doc/ref/api-evaluation.texi +++ b/doc/ref/api-evaluation.texi @@ -298,6 +298,14 @@ starting with the character sequence @code{#} and @var= {chr}. @var{proc} will be called with two arguments: the character @var{chr} and the port to read further data from. The object returned will be the return value of @code{read}.=20 + +Returning of an unspecified value (value of the @code{*unspecified*} +constant) alone from @var{proc} means that the procedure cannot parse +the character sequence. Despite of this, in some cases you may want to +read and return an unspecified value as the correct value. This can be +achieved by returning of two values: an unspecified value as the first +value and @code{#t} as the second, see (@pxref{Multiple Values}). + Passing @code{#f} for @var{proc} will remove a previous setting.=20 =20 @end deffn diff --git a/libguile/read.c b/libguile/read.c index ecf27ff..e9bb6f0 100644 =2D-- a/libguile/read.c +++ b/libguile/read.c @@ -1656,8 +1656,15 @@ scm_read_sharp (scm_t_wchar chr, SCM port, scm_t_rea= d_opts *opts, chr =3D scm_getc_unlocked (port); =20 result =3D scm_read_sharp_extension (chr, port, opts); =2D if (!scm_is_eq (result, SCM_UNSPECIFIED)) =2D return result; + if (! SCM_VALUESP (result)) + { + if (! scm_is_eq (result, SCM_UNSPECIFIED)) + return result; + } + else if (scm_is_true (scm_c_value_ref (result, 1))) + { + return result; + } =20 switch (chr) { @@ -1713,7 +1720,7 @@ scm_read_sharp (scm_t_wchar chr, SCM port, scm_t_read= _opts *opts, return (scm_read_nil (chr, port, opts)); default: result =3D scm_read_sharp_extension (chr, port, opts); =2D if (scm_is_eq (result, SCM_UNSPECIFIED)) + if ((! SCM_VALUESP (result)) && scm_is_eq (result, SCM_UNSPECIFIED)) { /* To remain compatible with 1.8 and earlier, the following characters have lower precedence than `read-hash-extend' @@ -1728,7 +1735,7 @@ scm_read_sharp (scm_t_wchar chr, SCM port, scm_t_read= _opts *opts, } } else =2D return result; + return scm_c_value_ref (result, 0); } =20 return SCM_UNSPECIFIED; @@ -1807,11 +1814,11 @@ read_inner_expression (SCM port, scm_t_read_opts *o= pts) long line =3D SCM_LINUM (port); int column =3D SCM_COL (port) - 1; SCM result =3D scm_read_sharp (chr, port, opts, line, column); =2D if (scm_is_eq (result, SCM_UNSPECIFIED)) + if ((! SCM_VALUESP (result)) && scm_is_eq (result, SCM_UNSPECIFIED)) /* We read a comment or some such. */ break; else =2D return result; + return scm_c_value_ref (result, 0); } case ')': scm_i_input_error (FUNC_NAME, port, "unexpected \")\"", SCM_EOL); diff --git a/test-suite/tests/reader.test b/test-suite/tests/reader.test index 5eb368d..b860abe 100644 =2D-- a/test-suite/tests/reader.test +++ b/test-suite/tests/reader.test @@ -169,6 +169,17 @@ (pass-if "square brackets are parens" (equal? '() (read-string "[]"))) =20 + (pass-if "reader callback can read an unspecified value" + (with-fluids ((%read-hash-procedures (fluid-ref %read-hash-procedures)= )) + (read-hash-extend #\< (lambda (c port) (values *unspecified* #t))) + (eq? *unspecified* (read-string (object->string *unspecified*))))) + + (pass-if-exception "reader callback can indicate an unknown object" + exception:unknown-sharp-object + (with-fluids ((%read-hash-procedures (fluid-ref %read-hash-procedures)= )) + (read-hash-extend #\< (lambda (c port) *unspecified*)) + (eq? *unspecified* (read-string (object->string *unspecified*))))) + (pass-if-exception "paren mismatch" exception:unexpected-rparen (read-string "'[)")) =20 =2D-=20 2.4.6 --=-=-=-- --==-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAEBCgAGBQJWOL0zAAoJEOnFotkImKAvwYIH/1AmMKEOscF6iJTUlAgG2VLv W8hPUFVHP73LrpY/OqUjWpe5PIo73aFczUAPiN0n8GhNOLadJGGc8qgSSZo2VRpW m4h5EoYDS5eRGzFMXiuXdN+pWxfqXkvd7iDl7uJ92x/k14WJhj/x7ehhh+HIdgAH FsD+tpJjiDHLsvB9J3dnWbz/xacUiBK+u5TTaUdhw8u56lfVKQqHiVXp5yrChCWn 8ixF60ZgcJ/dXdDM9FNGOSK4jqLbzVoQGAG/vLVCaDCbtDc09VNwUS7S595C2kMg hPQx6oy7+FDaKt8ODHsJ+pEgkZuR6XcY/jcBttlrMv0+sUlsj8t1yUIf0hoA23o= =XIG9 -----END PGP SIGNATURE----- --==-=-=--