From mboxrd@z Thu Jan 1 00:00:00 1970 From: Efraim Flashner Subject: Re: Adding wc to Bournish Date: Tue, 7 Jun 2016 10:41:55 +0300 Message-ID: <20160607074155.GB32264@debian-netbook> References: <20160524184720.GA27449@debian-netbook> <20160605124033.GB859@debian-netbook> <87eg8bpe2v.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="qtZFehHsKgwS5rPz" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:52866) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bABeP-0002Qh-Fz for guix-devel@gnu.org; Tue, 07 Jun 2016 03:42:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bABeK-00033u-Bu for guix-devel@gnu.org; Tue, 07 Jun 2016 03:42:12 -0400 Content-Disposition: inline In-Reply-To: <87eg8bpe2v.fsf@gnu.org> List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: "Guix-devel" To: Ludovic =?utf-8?Q?Court=C3=A8s?= Cc: guix-devel@gnu.org --qtZFehHsKgwS5rPz Content-Type: multipart/mixed; boundary="St7VIuEGZ6dlpu13" Content-Disposition: inline --St7VIuEGZ6dlpu13 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sun, Jun 05, 2016 at 10:37:12PM +0200, Ludovic Court=C3=A8s wrote: > Efraim Flashner skribis: > > + > > +(define* (wc-command-implementation file #:optional args) > > + (let-values (((lines chars) > > + (call-with-input-file file lines+chars))) > > + (match args > > + (#\l > > + (format #t "~a ~a~%" lines file)) > > + (#\c > > + (format #t "~a ~a~%" chars file)) > > + (_ > > + (format #t "~a ~a ~a~%" lines chars file))))) > > + > > +(define (wc-command args . rest) > > + (let* ((flags (cond ((string=3D? args "-l") #\l) > > + ((string=3D? args "-c") #\c) > > + (else #\nul))) ; no flags, "args" is a file > > + (files (filter (lambda (file) > > + (catch 'system-error > > + (lambda () > > + (lstat file)) > > + (lambda args > > + (let ((errno (system-error-errno args))) > > + (format (current-error-port) "~a: ~a~%" > > + file (strerror errno)) > > + #f)))) > > + (if (char=3D? flags #\nul) (cons args rest) re= st)))) > > + (for-each > > + (lambda (file) > > + ((@@ (guix build bournish) wc-command-implementation) file fla= gs)) > > + files))) >=20 > As discussed at > , > remember that =E2=80=98wc-command=E2=80=99 is called by the compiler to g= enerate Scheme > code from the input shell code. Thus, it must emit code that does the > job. However, here, it does the job directly, at compilation time, and > emits the result of =E2=80=98for-each=E2=80=99 as code. copied from that email: Thus, you must similarly distinguish those two stages by providing: 1. A =E2=80=98wc-command-implementation=E2=80=99 procedure that implements = =E2=80=98wc=E2=80=99; 2. A =E2=80=98wc-command=E2=80=99 procedure that emits the code that calls wc-command-implementation=E2=80=99; so something like: (define (wc-command args) `((@@ (guix build bournish) wc-command-implementation) ,@args)) Better yet, =E2=80=98wc-command=E2=80=99 could check for the presence of = =E2=80=9C-l=E2=80=9D or =E2=80=9C-c=E2=80=9D at compile time and emit a call to the right thing. >=20 > I=E2=80=99ll commit a couple of fixes for bugs I just found and that prev= ent us > from doing: >=20 > (compile "ls" #:from %bournish-language #:to 'scheme). >=20 > This is useful to clearly understand what code is generated from the > input. >=20 > Ludo=E2=80=99. I've refactored the code so now in wc-command it checks if theres a flag or not, and then passes the list of files to wc-command-implementation to do the actual computation. Does it make sense to switch it to something like the case-lambda setup that `ls' uses or is for-each ok? --=20 Efraim Flashner =D7=90=D7=A4=D7=A8=D7=99=D7=9D = =D7=A4=D7=9C=D7=A9=D7=A0=D7=A8 GPG key =3D A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351 Confidentiality cannot be guaranteed on emails sent or received unencrypted --St7VIuEGZ6dlpu13 Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename="0001-bournish-Add-wc-command.patch" Content-Transfer-Encoding: quoted-printable =46rom ebce5076177314bfd17a53019b3f6b6888762b01 Mon Sep 17 00:00:00 2001 =46rom: Efraim Flashner Date: Sun, 22 May 2016 14:56:06 +0300 Subject: [PATCH] bournish: Add `wc' command. * guix/build/bournish.scm (file-size, wc-c-command, wc-l-command, lines+chars, wc-command, wc-command-implementation): New variables. (%commands): Add wc command. --- guix/build/bournish.scm | 64 +++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/guix/build/bournish.scm b/guix/build/bournish.scm index 1f17e0a..46e6e1c 100644 --- a/guix/build/bournish.scm +++ b/guix/build/bournish.scm @@ -1,5 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright =C2=A9 2016 Ludovic Court=C3=A8s +;;; Copyright =C2=A9 2016 Efraim Flashner ;;; ;;; This file is part of GNU Guix. ;;; @@ -25,7 +26,9 @@ #:use-module (ice-9 match) #:use-module (ice-9 ftw) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) #:use-module (srfi srfi-26) + #:use-module (srfi srfi-41) #:export (%bournish-language)) =20 ;;; Commentary: @@ -103,6 +106,64 @@ characters." ((@ (guix build utils) dump-port) port (current-output-port)) *unspecified*))) =20 +(define (file-size file) + (stat:size (stat file))) + +(define (wc-c-command file) + ;; Faster when only `wc -c' is called + (file-size file)) + +(define (wc-l-command file) + ;; Faster when only `wc -l' is called + (stream-length + (stream-filter + (lambda (chr) + (char=3D? chr #\newline)) + (port->stream (open-file file "r"))))) + +(define (lines+chars port) + ;; Return the number of lines and number of chars read from PORT. + ;; TODO: Also return the number of words. + (let loop ((lines 0) (chars 0)) + (match (read-char port) ; get the next char ready + ((? eof-object?) ;done! + (values lines chars)) + (#\newline ;recurse + (loop (1+ lines) (1+ chars))) + (_ ;recurse + (loop lines (1+ chars)))))) + +(define* (wc-command-implementation filelist #:optional args) + (let ((files (filter (lambda (file) + (catch 'system-error + (lambda () + (lstat file)) + (lambda args + (let ((errno (system-error-errno args))) + (format (current-error-port) "~a: ~a~%" + file (strerror errno)) + #f)))) + filelist))) + (for-each + (lambda (file) + (let-values (((lines chars) + (call-with-input-file file lines+chars))) + (match args + (#\l + (format #t "~a ~a~%" lines file)) + (#\c + (format #t "~a ~a~%" chars file)) + (_ + (format #t "~a ~a ~a~%" lines chars file))))) + files))) + +(define (wc-command args . rest) + (let* ((flags (cond ((string=3D? args "-l") #\l) + ((string=3D? args "-c") #\c) + (else #\nul)))) ; no flags, "args" is a file + ((@@ (guix build bournish) wc-command-implementation) + (if (char=3D? flags #\nul) (cons args rest) rest) flags))) + (define (help-command . _) (display "\ Hello, this is Bournish, a minimal Bourne-like shell in Guile! @@ -129,7 +190,8 @@ commands such as 'ls' and 'cd'; it lacks globbing, pipe= s---everything.\n")) ("help" ,help-command) ("ls" ,ls-command) ("which" ,which-command) - ("cat" ,cat-command))) + ("cat" ,cat-command) + ("wc" ,wc-command))) =20 (define (read-bournish port env) "Read a Bournish expression from PORT, and return the corresponding Sche= me --=20 2.8.3 --St7VIuEGZ6dlpu13-- --qtZFehHsKgwS5rPz Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCgAGBQJXVnq/AAoJEPTB05F+rO6TNFsP/25+QyVH9L1k8lA47Gaj4TQG nmYEkGH8NIz3CmtaFmpOtUawY3r6xokzmk0Qitimubm9g+3/vgAzjZWWUZi/+27B YntemcwedGVcvV7sJxK2+yGjIpowVytoLZtHVcvn+rBOSBj8iijLoeOy8FqaqgUe w0kQI0QxDps1Nb0QR6pIdoP8ReLW3lZIeeTmHXrlx3MM+96R36Ep1hkukFJ9mmGn Dm0mO9bZlut+fhUvP5GlV9G/5WXQ2DQqjWKuSR6lvIUDJNorlXJkISY1eOs4cBtO GhjY6/xHmRlHxDq4uw2QowOpJBIKo+2qwwn4PxFdEo4A9Y6R40gR2mCd96CrJqp6 HvhuOW9wb2rtiXKavRlvgF52DY9N5lErcGhBhFct6WmlsuY9e00yPm9FJstlddCG d0Z4mSPca/+2njAwJt8aTXDB+EN+fXgGAtkTxieNh1Pn7XQQnRepRvkthyHs5g+6 BIrTsiVBEgcmj+C90fzCpFQs0Lj5TeL55ZZDkSI2T/6rvIC87ieG/esKUAaQcLGc 35inIkODeolRww1LaJeuEOEH3dVt0GOiXO9Zgrgz3mnpbDCpIY0AuoWrftAtgpD4 cyotYje5ycyiGs+Q5FyTB0I7cOjL8+AvTCCskCBVwMjOmT70eSXKc7MGH5cb8x5l Lue8eIcuRA5K1S2/5HSv =y5wf -----END PGP SIGNATURE----- --qtZFehHsKgwS5rPz--