unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Guile Assembler
@ 2015-06-22 18:32 Sjoerd van Leent
  2015-06-22 20:49 ` Panicz Maciej Godek
  0 siblings, 1 reply; 19+ messages in thread
From: Sjoerd van Leent @ 2015-06-22 18:32 UTC (permalink / raw)
  To: Andy Wingo, guile-devel

[-- Attachment #1: Type: text/plain, Size: 242 bytes --]

Dear Andy,

I am still busy with creating a proper assembler within Guile. The first
step was to be able to execute a page, which I have been able to create.

If you are interested, I can put a git repository somewhere.

Kind Regards,
Sjoerd

[-- Attachment #2: Type: text/html, Size: 400 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-22 18:32 Guile Assembler Sjoerd van Leent
@ 2015-06-22 20:49 ` Panicz Maciej Godek
  2015-06-23  6:28   ` Nala Ginrut
  0 siblings, 1 reply; 19+ messages in thread
From: Panicz Maciej Godek @ 2015-06-22 20:49 UTC (permalink / raw)
  To: Sjoerd van Leent; +Cc: Andy Wingo, guile-devel

[-- Attachment #1: Type: text/plain, Size: 855 bytes --]

2015-06-22 20:32 GMT+02:00 Sjoerd van Leent <svanleent@gmail.com>:

> Dear Andy,
>
> I am still busy with creating a proper assembler within Guile. The first
> step was to be able to execute a page, which I have been able to create.
>
> If you are interested, I can put a git repository somewhere.
>

Hi,
interestingly, I recently started a very similar project, and took the very
same first step. However, it quickly turned out that going through the
documentation of x86-64 is somewhat tedious, so the project lost its
initial impetus.

Perhaps it could be valuable or mutually motivating to join forces?

My repo is available here:

https://bitbucket.org/panicz/envy/src

(the project uses an extension module from another project that is not
contained in the repo, but can be easily obtained from
https://bitbucket.org/panicz/slayer/src)

Regards,
M.

[-- Attachment #2: Type: text/html, Size: 1860 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-22 20:49 ` Panicz Maciej Godek
@ 2015-06-23  6:28   ` Nala Ginrut
  2015-06-23  9:12     ` tomas
  0 siblings, 1 reply; 19+ messages in thread
From: Nala Ginrut @ 2015-06-23  6:28 UTC (permalink / raw)
  To: Panicz Maciej Godek; +Cc: Andy Wingo, guile-devel

hi Panicz!

On Mon, 2015-06-22 at 22:49 +0200, Panicz Maciej Godek wrote:
> My repo is available here:
> 
> https://bitbucket.org/panicz/envy/src

Thanks for the hint!
There's tiny problem IMO, (define ((number/base base) (l ...)) is not
supported in Guile, but I do see something similar in Racket, say:
==========================code==================
(define ((number/base base) l) l)
===========================end==================

Anyway, I'm interested in this topic too. ;-)

> (the project uses an extension module from another project that is not
> contained in the repo, but can be easily obtained from
> https://bitbucket.org/panicz/slayer/src)
> 
> Regards,
> M.





^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-23  6:28   ` Nala Ginrut
@ 2015-06-23  9:12     ` tomas
  2015-06-23  9:19       ` Nala Ginrut
  0 siblings, 1 reply; 19+ messages in thread
From: tomas @ 2015-06-23  9:12 UTC (permalink / raw)
  To: Nala Ginrut; +Cc: Andy Wingo, guile-devel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Tue, Jun 23, 2015 at 02:28:41PM +0800, Nala Ginrut wrote:
> hi Panicz!
> 
> On Mon, 2015-06-22 at 22:49 +0200, Panicz Maciej Godek wrote:
> > My repo is available here:
> > 
> > https://bitbucket.org/panicz/envy/src
> 
> Thanks for the hint!
> There's tiny problem IMO, (define ((number/base base) (l ...)) is not
> supported in Guile, but I do see something similar in Racket, say:
> ==========================code==================
> (define ((number/base base) l) l)
> ===========================end==================

What does number/base do? Does it change the read syntax of numbers?

- -- t
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlWJIxMACgkQBcgs9XrR2kbEGwCggNu2MaiEGUVBEnE9Mc/AHE8p
ztgAn0IAZXfu9S+DvnKpkFrPeCwoHCpv
=K4F9
-----END PGP SIGNATURE-----



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-23  9:12     ` tomas
@ 2015-06-23  9:19       ` Nala Ginrut
  2015-06-23  9:27         ` tomas
  2015-06-23 12:54         ` Barry Fishman
  0 siblings, 2 replies; 19+ messages in thread
From: Nala Ginrut @ 2015-06-23  9:19 UTC (permalink / raw)
  To: tomas; +Cc: Andy Wingo, guile-devel

On Tue, 2015-06-23 at 11:12 +0200, tomas@tuxteam.de wrote:
> What does number/base do? Does it change the read syntax of numbers?
> 

I think it defines a function (number/base base) first, then use it as
argument of the outer function...

http://docs.racket-lang.org/reference/define.html


> -- t





^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-23  9:19       ` Nala Ginrut
@ 2015-06-23  9:27         ` tomas
  2015-06-23  9:30           ` Nala Ginrut
  2015-06-23 12:54         ` Barry Fishman
  1 sibling, 1 reply; 19+ messages in thread
From: tomas @ 2015-06-23  9:27 UTC (permalink / raw)
  To: Nala Ginrut; +Cc: Andy Wingo, guile-devel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Tue, Jun 23, 2015 at 05:19:56PM +0800, Nala Ginrut wrote:
> On Tue, 2015-06-23 at 11:12 +0200, tomas@tuxteam.de wrote:
> > What does number/base do? Does it change the read syntax of numbers?
> > 
> 
> I think it defines a function (number/base base) first, then use it as
> argument of the outer function...
> 
> http://docs.racket-lang.org/reference/define.html

Hm. Where's the difference to Guile's define? And why do you have double
parentheses in your example?

Still a bit lost.

Regards
- -- t
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlWJJnMACgkQBcgs9XrR2kZd6wCeP0SNvz+/6KxiizHrPn/kMR37
QqIAniGp6tORga2nPZ+qcFiyBF4UiBMf
=P5LB
-----END PGP SIGNATURE-----



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-23  9:27         ` tomas
@ 2015-06-23  9:30           ` Nala Ginrut
  2015-06-23  9:45             ` tomas
  0 siblings, 1 reply; 19+ messages in thread
From: Nala Ginrut @ 2015-06-23  9:30 UTC (permalink / raw)
  To: tomas; +Cc: Andy Wingo, guile-devel

On Tue, 2015-06-23 at 11:27 +0200, tomas@tuxteam.de wrote:
> Hm. Where's the difference to Guile's define? And why do you have double
> parentheses in your example?
> 
> Still a bit lost.

hmm...do you read the pasted code in the repo? ;-)

Anyway, it's not standard Scheme grammar, so that's why I mention it.

> Regards
> -- t





^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-23  9:30           ` Nala Ginrut
@ 2015-06-23  9:45             ` tomas
  2015-06-23 21:33               ` Panicz Maciej Godek
  0 siblings, 1 reply; 19+ messages in thread
From: tomas @ 2015-06-23  9:45 UTC (permalink / raw)
  To: Nala Ginrut; +Cc: Andy Wingo, guile-devel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Tue, Jun 23, 2015 at 05:30:42PM +0800, Nala Ginrut wrote:
> On Tue, 2015-06-23 at 11:27 +0200, tomas@tuxteam.de wrote:
> > Hm. Where's the difference to Guile's define? And why do you have double
> > parentheses in your example?
> > 
> > Still a bit lost.
> 
> hmm...do you read the pasted code in the repo? ;-)

Not yet, I must admit. But nevermind, got it. It looks like a definition
for a parametric func or for a half-curried func, depending on how you
squint at it ;-)

That explains the second set of parens.

thanks, regards
- -- t
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlWJKrYACgkQBcgs9XrR2kYA2ACcDO9pimsVDHUrWmb9gP5vsTAk
tlMAnAmBAyJmLoTRiP1NPuqjAfoSWIQF
=a+Ly
-----END PGP SIGNATURE-----



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-23  9:19       ` Nala Ginrut
  2015-06-23  9:27         ` tomas
@ 2015-06-23 12:54         ` Barry Fishman
  2015-06-23 21:00           ` Panicz Maciej Godek
  1 sibling, 1 reply; 19+ messages in thread
From: Barry Fishman @ 2015-06-23 12:54 UTC (permalink / raw)
  To: guile-devel


On 2015-06-23 17:19:56 +0800, Nala Ginrut wrote:
> On Tue, 2015-06-23 at 11:12 +0200, tomas@tuxteam.de wrote:
>> What does number/base do? Does it change the read syntax of numbers?
>> 
>
> I think it defines a function (number/base base) first, then use it as
> argument of the outer function...
>
> http://docs.racket-lang.org/reference/define.html
>

How is this syntax macro style improve on a more direct and simple
standard scheme implementation of:

(define (number/base base)
  (lambda (lst)
    (let loop ((digits lst)
	       (accumulator 0))
      (if (null? digits)
	  accumulator
	  (loop (cdr digits)
		(+ (car digits) (* accumulator base)))))))

This amalgam of 'match' and 'define-syntax's style '...', and
'destructuring-bind' syntax just seems to add complexity to a language
whose prime benefit is the clarity of its explicitness and lack of
syntax.

--
Barry Fishman




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-23 12:54         ` Barry Fishman
@ 2015-06-23 21:00           ` Panicz Maciej Godek
  2015-06-24  2:18             ` Barry Fishman
  0 siblings, 1 reply; 19+ messages in thread
From: Panicz Maciej Godek @ 2015-06-23 21:00 UTC (permalink / raw)
  To: Barry Fishman; +Cc: guile-devel

[-- Attachment #1: Type: text/plain, Size: 1828 bytes --]

2015-06-23 14:54 GMT+02:00 Barry Fishman <barry_fishman@acm.org>:

>
> On 2015-06-23 17:19:56 +0800, Nala Ginrut wrote:
> > On Tue, 2015-06-23 at 11:12 +0200, tomas@tuxteam.de wrote:
> >> What does number/base do? Does it change the read syntax of numbers?
> >>
> >
> > I think it defines a function (number/base base) first, then use it as
> > argument of the outer function...
> >
> > http://docs.racket-lang.org/reference/define.html
> >
>
> How is this syntax macro style improve on a more direct and simple
> standard scheme implementation of:
>
> (define (number/base base)
>   (lambda (lst)
>     (let loop ((digits lst)
>                (accumulator 0))
>       (if (null? digits)
>           accumulator
>           (loop (cdr digits)
>                 (+ (car digits) (* accumulator base)))))))
>
>
I think it's the same improvement as between your version and the even more
"direct and simple" standard scheme implementation:

(define number/base
  (lambda (base)
    (lambda (lst)
       (let loop ((digits lst)
                      (accumulator 0))
          (if (null? digits)
             accumulator
             (loop (cdr digits)
                     (+ (car digits) (* accumulator base))))))))

(And using obscure names such as "car" and "cdr" in the code doesn't
enhance readability either)

This amalgam of 'match' and 'define-syntax's style '...', and
> 'destructuring-bind' syntax just seems to add complexity to a language
> whose prime benefit is the clarity of its explicitness and lack of
> syntax.
>

I agree that the presence of ellipsis in the pattern matcher is dubious. On
the other hand, since it's already there, it allows to make it clear to the
reader that a given argument is meant to be a list.

OTOH I see that it wasn't much of a problem for you to understand the code.

Best regards
M.

[-- Attachment #2: Type: text/html, Size: 2955 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-23  9:45             ` tomas
@ 2015-06-23 21:33               ` Panicz Maciej Godek
  2015-06-24  8:34                 ` tomas
  0 siblings, 1 reply; 19+ messages in thread
From: Panicz Maciej Godek @ 2015-06-23 21:33 UTC (permalink / raw)
  To: tomas; +Cc: Andy Wingo, guile-devel

[-- Attachment #1: Type: text/plain, Size: 2631 bytes --]

>
> > > Hm. Where's the difference to Guile's define? And why do you have
> double
> > > parentheses in your example?
> > >
> > > Still a bit lost.
> >
> > hmm...do you read the pasted code in the repo? ;-)
>
> Not yet, I must admit. But nevermind, got it. It looks like a definition
> for a parametric func or for a half-curried func, depending on how you
> squint at it ;-)
>
> That explains the second set of parens.
>

Hi,
sorry to answer that late, but I erroneously sent the previous answer only
to Nala.

I have another project (in another repo) which provides the (extra common)
module, which redefines "define" and "lambda" forms (among others):

https://bitbucket.org/panicz/slayer/src/cbfb3187edaba890b12b307d84bb9c4538407d20/guile-modules/extra/common.scm?at=default

(The module is rather huge -- it is a bag that I carry around)

The modification of "define" originates, I believe, from the book
"Structure and Interpretation of Classical Mechanics" by Gerald Sussman and
Jack Wisdom [1], but I stole that idea directly from Guile's (ice-9
curried-definitions) module [2]. The idea is that

(define ((f x) y)
  (list x y))

is equivalent to

(define f
  (lambda (x)
    (lambda (y)
       (list x y))))

This behaviour is consequent with the idea that

(define (g x)
  (* x x))

should be equivalent to

(define g
  (lambda (x)
    (* x x)))

The derivative variants are easier to read, because they make it apparent,
that e.g. (g 5) can be substituted with (* 5 5), and -- similarly -- ((f 2)
3) can be substituted with (list 2 3).

The other difficulty is that the original function header looked like this:

(define ((number/base base) (l ...))

so that the form of the second argument is "(l ...)". This is because the
(extra common) module allows to destructure the arguments using the (ice-9
match) pattern matcher, so that the above header is actually equivalent to

(define number/base
  (lambda (base)
    (lambda x
      (match x
        ((l ...)

In practice that form of argument doesn't do much. It just tells the reader
that the argument is a proper list (because only a proper list matches such
pattern)

Similarly, I could write code like

(map (lambda ((a . b)) (+ a b)) '((1 . 2)(3 . 4)(5 . 6)))

I also use that trick with let and let* forms:

(let (((x y) '(1 2)))
  (+ x y))

In addition, the module allows me to use the "let" and "let*" forms with
multiple values:

(let ((a (b c) (values 1 '(2 3))))
  (+ a b c))

Best regards

[1]
http://mitpress.mit.edu/sites/default/files/titles/content/sicm/book-Z-H-11.html
[2]
https://www.gnu.org/software/guile/manual/html_node/Curried-Definitions.html

[-- Attachment #2: Type: text/html, Size: 4199 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-23 21:00           ` Panicz Maciej Godek
@ 2015-06-24  2:18             ` Barry Fishman
  0 siblings, 0 replies; 19+ messages in thread
From: Barry Fishman @ 2015-06-24  2:18 UTC (permalink / raw)
  To: guile-devel


On 2015-06-23 23:00:19 +0200, Panicz Maciej Godek wrote:
> 2015-06-23 14:54 GMT+02:00 Barry Fishman <barry_fishman@acm.org>:
>> This amalgam of 'match' and 'define-syntax's style '...', and
>> 'destructuring-bind' syntax just seems to add complexity to a language
>> whose prime benefit is the clarity of its explicitness and lack of
>> syntax.
>>
>
> I agree that the presence of ellipsis in the pattern matcher is dubious. On
> the other hand, since it's already there, it allows to make it clear to the
> reader that a given argument is meant to be a list.
>
> OTOH I see that it wasn't much of a problem for you to understand the
> code.

I didn't understand the code.  I understood the documentation in its
source file that you referenced.
--
Barry Fishman




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-23 21:33               ` Panicz Maciej Godek
@ 2015-06-24  8:34                 ` tomas
  2015-06-24  9:44                   ` Panicz Maciej Godek
  0 siblings, 1 reply; 19+ messages in thread
From: tomas @ 2015-06-24  8:34 UTC (permalink / raw)
  To: Panicz Maciej Godek; +Cc: Andy Wingo, guile-devel

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Tue, Jun 23, 2015 at 11:33:06PM +0200, Panicz Maciej Godek wrote:
> >
> > > > Hm. Where's the difference to Guile's define? And why do you have
> > > > double parentheses in your example?

[...]

> Hi,
> sorry to answer that late, but I erroneously sent the previous answer only
> to Nala.

Thanks
 
[...]

> The modification of "define" originates, I believe, from the book
> "Structure and Interpretation of Classical Mechanics" by Gerald Sussman and
> Jack Wisdom [1] [...]

Thanks for the nice explanation. As stated upstream, once Nala hit me over
the head, I saw the light :-)

> curried-definitions) module [2]. The idea is that
> 
> (define ((f x) y)
>   (list x y))
> 
> is equivalent to

I agree that it is a nice extrapolation from (define foo ...) to
(define (foo x) ...).

[...]

> In addition, the module allows me to use the "let" and "let*" forms with
> multiple values:
> 
> (let ((a (b c) (values 1 '(2 3))))
>   (+ a b c))

Any chance to see that in Guile?

regards
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlWKa4wACgkQBcgs9XrR2kaneACeLoC3A0wv+gxEWgzxcVIrTd4C
K4EAn2RalYt5OYidPB6fI/rylblMEVUg
=+mEy
-----END PGP SIGNATURE-----



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-24  8:34                 ` tomas
@ 2015-06-24  9:44                   ` Panicz Maciej Godek
  2015-06-24 11:59                     ` dsmich
  2015-06-24 21:54                     ` Panicz Maciej Godek
  0 siblings, 2 replies; 19+ messages in thread
From: Panicz Maciej Godek @ 2015-06-24  9:44 UTC (permalink / raw)
  To: tomas; +Cc: Andy Wingo, guile-devel

[-- Attachment #1: Type: text/plain, Size: 659 bytes --]

24 cze 2015 10:34 <tomas@tuxteam.de> napisał(a):
>
> > In addition, the module allows me to use the "let" and "let*" forms with
> > multiple values:
> >
> > (let ((a (b c) (values 1 '(2 3))))
> >   (+ a b c))
>
> Any chance to see that in Guile?

The module actually works with guile (it replaces the default bindings for
lambda, let, let* and define), but it provides much more than that
(reexports most of srfi-1 or (ice-9 regex)), so some may argue that it's
too much.

I could prepare a smaller version of the module that perhaps could make it
into the official distribution, if guile maintainers have nothing against,
and send a patch

[-- Attachment #2: Type: text/html, Size: 858 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-24  9:44                   ` Panicz Maciej Godek
@ 2015-06-24 11:59                     ` dsmich
  2015-06-24 21:54                     ` Panicz Maciej Godek
  1 sibling, 0 replies; 19+ messages in thread
From: dsmich @ 2015-06-24 11:59 UTC (permalink / raw)
  To: Panicz Maciej Godek, tomas; +Cc: Andy Wingo, guile-devel


---- Panicz Maciej Godek <godek.maciek@gmail.com> wrote: 
> 24 cze 2015 10:34 <tomas@tuxteam.de> napisał(a):
> >
> > > In addition, the module allows me to use the "let" and "let*" forms with
> > > multiple values:
> > >
> > > (let ((a (b c) (values 1 '(2 3))))
> > >   (+ a b c))
> >
> > Any chance to see that in Guile?
> 
> The module actually works with guile (it replaces the default bindings for
> lambda, let, let* and define), but it provides much more than that
> (reexports most of srfi-1 or (ice-9 regex)), so some may argue that it's
> too much.
> 
> I could prepare a smaller version of the module that perhaps could make it
> into the official distribution, if guile maintainers have nothing against,
> and send a patch

Note that guile used to have curried definitions, but now they have been moved to the (ice-9 curried-definitions) module.  Pretty sure guile never had curried let or let* though.

-Dale 




^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-24  9:44                   ` Panicz Maciej Godek
  2015-06-24 11:59                     ` dsmich
@ 2015-06-24 21:54                     ` Panicz Maciej Godek
  2015-09-04  0:54                       ` Mark H Weaver
  1 sibling, 1 reply; 19+ messages in thread
From: Panicz Maciej Godek @ 2015-06-24 21:54 UTC (permalink / raw)
  To: tomas; +Cc: Andy Wingo, guile-devel


[-- Attachment #1.1: Type: text/plain, Size: 2112 bytes --]

2015-06-24 11:44 GMT+02:00 Panicz Maciej Godek <godek.maciek@gmail.com>:

> I could prepare a smaller version of the module that perhaps could make it
> into the official distribution, if guile maintainers have nothing against,
> and send a patch
>
I include the aforementioned.
It is not a patch though, but just a separate module called (ice-9 nice-9)
that is meant to be placed in the "ice-9" directory (e.g.
"/usr/share/guile/2.0/ice-9").

It would definitely need a more elaborate documentation, but the quick note
is that it:

* allows to destructure arguments to lambda, e.g.

(map (lambda ((a . b)) (+ a b)) '((1 . 2)(3 . 4)(5 . 6)))

* blends named-let with match-let and srfi-71-style let for multiple
values, legalizing usages like

(let loop ((a (b c) (values 1 (list 2 3))))
  ...
  (loop (values 4 (list 5 6))))

(although this may not seem to be a good way of programming, I think that
imposing artificial limitations on how the language can be used would be
even worse)

* blends match-let* with srfi-71-style let* for multiple values

* blends srfi-2 and-let* with pattern matcher, so that one can finally do
things like

(and-let* (((a b c d) '(1 2 3)))
  (+ a b c d))

(which evaluates to false, of course)

* allows to use curried definitions like (ice-9 curried-definitions), but
such that are already blended with the pattern-matching lambda

(define ((f (a b)) (c))
  (list a b c))

* in addition, it re-exports "match" from (ice-9 match) and "every", "any"
and "count" from (srfi srfi-1)


I think that this set of extensions is non-controversial and it is handy to
gather them in a single module. It only allows to use the commonly used
features that would otherwise be illegal, and it does so in a predictable
way.

I re-export "every" and "any" because they are used by some of the macros.
I also re-export "count" in order to make the count of (re)exported symbols
equal 9, so that the module deserves its name, but this is mostly for a pun.

Also, I just copied and modified the macros in order to get rid of some
dependencies, but I only tested the code superficially

Best regards

[-- Attachment #1.2: Type: text/html, Size: 3820 bytes --]

[-- Attachment #2: nice-9.scm --]
[-- Type: text/x-scheme, Size: 4415 bytes --]

(define-module (ice-9 nice-9)
  #:use-module (ice-9 match)
  #:use-module ((srfi srfi-1) #:select (every any count))
  #:re-export (match every any count)
  #:export ((and-let*/match . and-let*))
  #:replace ((cdefine . define)
	     (mlambda . lambda)
	     (named-match-let-values . let)
	     (match-let*-values . let*)))

(define-syntax mlambda
  (lambda (stx)
    (syntax-case stx ()

      ((_ (first-arg ... last-arg . rest-args) body ...)
       (and (every identifier? #'(first-arg ... last-arg))
	    (or (identifier? #'rest-args) (null? #'rest-args)))
       #'(lambda (first-arg ... last-arg . rest-args) body ...))

      ((_ arg body ...)
       (or (identifier? #'arg) (null? #'arg))
       #'(lambda arg body ...))

      ((_ args body ...)
       #'(match-lambda* (args body ...))))))

(define-syntax cdefine
  (syntax-rules ()
    ((_ ((head . tail) . args) body ...)
     (cdefine (head . tail)
       (mlambda args body ...)))
    ((_ (name . args) body ...)
     (define name (mlambda args body ...)))
    ((_ . rest)
     (define . rest))))

(define-syntax list<-values
  (syntax-rules ()
    ((_ call)
     (call-with-values (lambda () call) list))))

(define-syntax named-match-let-values
  (lambda (stx)
    (syntax-case stx ()
      ((_ ((identifier expression) ...) ;; optimization: plain "let" form
	  body + ...)
       (every identifier? #'(identifier ...))
       #'(let ((identifier expression) ...)
	   body + ...))

      ((_ name ((identifier expression) ...) ;; optimization: regular named-let
	  body + ...)
       (and (identifier? #'name) (every identifier? #'(identifier ...)))
       #'(let name ((identifier expression) ...)
	   body + ...))

      ((_ name ((structure expression) ...)
	  body + ...)
       (identifier? #'name)
       #'(letrec ((name (mlambda (structure ...) body + ...)))
	   (name expression ...)))

      ((_ ((structure expression) ...)
	  body + ...)
       #'(match-let ((structure expression) ...) 
	   body + ...))

      ;; it should generally be discouraged to use the plain let
      ;; with multiple values, because there's no natural way to implement
      ;; that when there's more than one (multiple-value) binding,
      ;; but it's added for completeness
      ((_ ((structures ... expression) ...)
	  body + ...)
       #'(match-let (((structures ...) (list<-values expression)) ...)
	   body + ...))
      
      ((_ name ((structures ... expression) ...)
	  body + ...)
       (identifier? #'name) 
       #'(letrec ((loop 
		   (mlambda ((structures ...) ...)
			    (let-syntax ((name (syntax-rules ()
						 ((_ args (... ...))
						  (loop (list<-values args)
							(... ...))))))
			      body + ...))))
	   (loop (list<-values expression) ...)))
      )))

(define-syntax match-let*-values
  (lambda (stx)
    (syntax-case stx ()
      ((_ ((identifier expression) ...) ;; optimization: regular let*
	  body + ...)
       (every identifier? #'(identifier ...))
       #'(let* ((identifier expression) ...)
	   body + ...))
      
      ((_ ((structure expression) ...)
	  body + ...)
       #'(match-let* ((structure expression) ...)
	   body + ...))

      ((_ ((identifier expression) remaining-bindings ...)
	  body + ...)
       (identifier? #'identifier)
       #'(let ((identifier expression))
	   (match-let*-values (remaining-bindings ...) body + ...)))

      ((_ ((structure expression) remaining-bindings ...)
	  body + ...)
       #'(match-let ((structure expression))
	   (match-let*-values (remaining-bindings ...) body + ...)))
      
      ((_ ((structure structures ... expression) remaining-bindings ...)
	  body + ...)
       #'(call-with-values (lambda () expression) 
	   (mlambda (structure structures ...)
		    (let*-replacement (remaining-bindings ...) body + ...))))
      )))

(define-syntax and-let*/match
  (lambda (stx)
    (syntax-case stx ()

      ((_)
       #'#t)

      ((_ ())
       #'#t)

      ((_ () body ...)
       #'(let () body ...))

      ((_ ((value binding) rest ...) body ...)
       (identifier? #'value)
       #'(let ((value binding))
	   (and value
		(and-let*/match (rest ...)
				body ...))))

      ((_ ((value binding) rest ...) body ...)
       #'(match binding
	   (value
	    (and-let*/match (rest ...)
	      body ...))
	   (_ #f)))

      ((_ ((condition) rest ...)
	  body ...)
       #'(and condition
	      (and-let*/match (rest ...)
		body ...)))

      )))

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-06-24 21:54                     ` Panicz Maciej Godek
@ 2015-09-04  0:54                       ` Mark H Weaver
  2015-09-04  9:31                         ` Panicz Maciej Godek
  0 siblings, 1 reply; 19+ messages in thread
From: Mark H Weaver @ 2015-09-04  0:54 UTC (permalink / raw)
  To: Panicz Maciej Godek; +Cc: Andy Wingo, guile-devel

Panicz Maciej Godek <godek.maciek@gmail.com> writes:

> It is not a patch though, but just a separate module called (ice-9
> nice-9) that is meant to be placed in the "ice-9" directory (e.g.
> "/usr/share/guile/2.0/ice-9").
>
> It would definitely need a more elaborate documentation, but the quick
> note is that it:
>
> * allows to destructure arguments to lambda, e.g.
>
> (map (lambda ((a . b)) (+ a b)) '((1 . 2)(3 . 4)(5 . 6)))
>
> * blends named-let with match-let and srfi-71-style let for multiple
> values, legalizing usages like
>
> (let loop ((a (b c) (values 1 (list 2 3))))
> ...
> (loop (values 4 (list 5 6))))

I only just recently noticed this message, but before people start
writing a lot of code like this, I should warn you that in the procedure
call (loop (values 4 (list 5 6))), by the semantics of Guile, that is
supposed to be equivalent to (loop 4).  If it does something else,
that's probably a bug in our optimizer, and it might well act
differently on our master branch already, because the multiple-values
stuff has been cleaned up a lot compared with 2.0.  Anyway, you
certainly should not rely on this behavior.  Sorry...

      Mark



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-09-04  0:54                       ` Mark H Weaver
@ 2015-09-04  9:31                         ` Panicz Maciej Godek
  2015-09-04 16:58                           ` Mark H Weaver
  0 siblings, 1 reply; 19+ messages in thread
From: Panicz Maciej Godek @ 2015-09-04  9:31 UTC (permalink / raw)
  To: Mark H Weaver; +Cc: Andy Wingo, guile-devel

[-- Attachment #1: Type: text/plain, Size: 2239 bytes --]

2015-09-04 2:54 GMT+02:00 Mark H Weaver <mhw@netris.org>:

> Panicz Maciej Godek <godek.maciek@gmail.com> writes:
>
> > It is not a patch though, but just a separate module called (ice-9
> > nice-9) that is meant to be placed in the "ice-9" directory (e.g.
> > "/usr/share/guile/2.0/ice-9").
> >
> > It would definitely need a more elaborate documentation, but the quick
> > note is that it:
> >
> > * allows to destructure arguments to lambda, e.g.
> >
> > (map (lambda ((a . b)) (+ a b)) '((1 . 2)(3 . 4)(5 . 6)))
> >
> > * blends named-let with match-let and srfi-71-style let for multiple
> > values, legalizing usages like
> >
> > (let loop ((a (b c) (values 1 (list 2 3))))
> > ...
> > (loop (values 4 (list 5 6))))
>
> I only just recently noticed this message, but before people start
> writing a lot of code like this, I should warn you that in the procedure
> call (loop (values 4 (list 5 6))), by the semantics of Guile, that is
> supposed to be equivalent to (loop 4).  If it does something else,
> that's probably a bug in our optimizer, and it might well act
> differently on our master branch already, because the multiple-values
> stuff has been cleaned up a lot compared with 2.0.  Anyway, you
> certainly should not rely on this behavior.  Sorry...


Actually, the code is written in such way that "loop" is actually a macro
such that

(loop (values 4 (list 5 6)))

would expand to

(loop* (values->list (values 4 (list 5 6))))

where loop* takes lists as inputs and (values->list call) is a syntax
defined as (call-with-values (lambda () call) list), so I think it is a
proper Scheme code which does not rely on any undefined behaviors.

It has some drawbacks -- among others, that loop is no longer first class
(although it could be made obtainable easily) and the resulting code is
rather inefficient, but it ought to behave properly.

There's also a comment in the module that
      ;; it should generally be discouraged to use the plain let
      ;; with multiple values, because there's no natural way to implement
      ;; that when there's more than one (multiple-value) binding,
      ;; but it's added for completeness
but for the time being I've actually only been using let* with multiple
values.


--
Panicz

[-- Attachment #2: Type: text/html, Size: 3178 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: Guile Assembler
  2015-09-04  9:31                         ` Panicz Maciej Godek
@ 2015-09-04 16:58                           ` Mark H Weaver
  0 siblings, 0 replies; 19+ messages in thread
From: Mark H Weaver @ 2015-09-04 16:58 UTC (permalink / raw)
  To: Panicz Maciej Godek; +Cc: Andy Wingo, guile-devel

Panicz Maciej Godek <godek.maciek@gmail.com> writes:

> Actually, the code is written in such way that "loop" is actually a
> macro such that
>
> (loop (values 4 (list 5 6)))
>
> would expand to
>
> (loop* (values->list (values 4 (list 5 6))))
>
> where loop* takes lists as inputs and (values->list call) is a syntax
> defined as (call-with-values (lambda () call) list), so I think it is
> a proper Scheme code which does not rely on any undefined behaviors.

Ah, okay.  You're right, this is fine, sorry for the noise.

> It has some drawbacks -- among others, that loop is no longer first
> class (although it could be made obtainable easily) and the resulting
> code is rather inefficient, but it ought to behave properly.

Indeed, it's not good for looping constructs to do heap allocation.  If
the loop would not otherwise require allocation, then using such a
looping construct will result in a dramatic slowdown.

      Mark



^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2015-09-04 16:58 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-22 18:32 Guile Assembler Sjoerd van Leent
2015-06-22 20:49 ` Panicz Maciej Godek
2015-06-23  6:28   ` Nala Ginrut
2015-06-23  9:12     ` tomas
2015-06-23  9:19       ` Nala Ginrut
2015-06-23  9:27         ` tomas
2015-06-23  9:30           ` Nala Ginrut
2015-06-23  9:45             ` tomas
2015-06-23 21:33               ` Panicz Maciej Godek
2015-06-24  8:34                 ` tomas
2015-06-24  9:44                   ` Panicz Maciej Godek
2015-06-24 11:59                     ` dsmich
2015-06-24 21:54                     ` Panicz Maciej Godek
2015-09-04  0:54                       ` Mark H Weaver
2015-09-04  9:31                         ` Panicz Maciej Godek
2015-09-04 16:58                           ` Mark H Weaver
2015-06-23 12:54         ` Barry Fishman
2015-06-23 21:00           ` Panicz Maciej Godek
2015-06-24  2:18             ` Barry Fishman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).