[Chicken-users] struggling with macros

2012-11-11 Thread Răzvan Rotaru
Hi,

I'm trying to write a simple javascript DSL, and got stuck in the macros
:). (I'm coming from lisp macros)  Take for example this one:

(define-syntax js
  (ir-macro-transformer
(lambda (expr inject compare)
  (let ((body (cdr expr)) (next (cadr expr)))
  (printf next=~a~n next)
(cond
  [(string? next) (string-append \ next \)]
  [(number? next) (number-string next)]
  [(null? next) ]
  [(list? next) `(string-append (js ,(car next)) (  ))]
  )


It is supposed to handle numbers and function calls, without building the
parameter list in the function calls.

CSI (js 1)
next=1
1
CSI (js (1 2 3))
next=(1 2 3)
next=1
1()


However, when trying to build the parameter list I get and error which I
don't understand:

(define-syntax js
  (ir-macro-transformer
(lambda (expr inject compare)
  (let ((body (cdr expr)) (next (cadr expr)))
  (printf next=~a~n next)
(cond
  [(string? next) (string-append \ next \)]
  [(number? next) (number-string next)]
  [(null? next) ]
  [(list? next) `(string-append (js ,(car next)) ( (apply
string-append (map js ,(cdr next))) ))]
  )

CSI (js (1 2 3))
next=(1 2 3)
next=1
Error: unbound variable: js
[ inspect ]

Restarts:
  0: [ABORT] Return to SLIME's top level

Backtrace:
  0: eval   [ more... ] (map248 js245 (2 3))
  1: eval   [ more... ] (apply247 string-append246 (map248 js245 (2 3)))
  2: eval   [ more... ] (string-append246 (js245 1) ( (apply247
string-append246 (map248 js245 (2 3))) ))
  3: syntax (2 3)
  4: syntax (map248 js245 (2 3))
  5: syntax (apply247 string-append246 (map248 js245 (2 3)))
  6: eval   [ more... ] (number-string next)
  7: eval   [ more... ] (number? next)
  8: eval   [ more... ] (printf next=~a~n next)
  9: eval   [ more... ] (cadr expr)
 10: eval   [ more... ] (cdr expr)
 11: syntax (js245 1)
 12: syntax (string-append246 (js245 1) ( (apply247
string-append246 (map248 js245 (2 3))) ))
 13: eval   [ more... ] (cdr next)
 14: eval   [ more... ] (##sys#list (##core#quote map) (##core#quote js)
(cdr next))
 15: eval   [ more... ] (##sys#list (##core#quote apply) (##core#quote
string-append) (##sys#list (##core#quote map) (##core#quote js) (cdr next)))

So, my questions are:
1/ Why is js not bound in the second example? I also tried to use
letrec-syntax but with same result.
2/ Are there other ways to achieve what I want?
3/ I also tried to use syntax-rules, but from what I understood this is not
possible, because you can't execute arbitrary expressions (in this case a
cond) at macroexpansion time. Am I right here?

Thanks,
Răzvan
___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] struggling with macros

2012-11-11 Thread Peter Bex
On Sun, Nov 11, 2012 at 01:23:13PM +0100, Răzvan Rotaru wrote:
 Hi,

Hi!

 I'm trying to write a simple javascript DSL, and got stuck in the macros
 :). (I'm coming from lisp macros)  Take for example this one:
 
 (define-syntax js
   (ir-macro-transformer
 (lambda (expr inject compare)
   (let ((body (cdr expr)) (next (cadr expr)))
   (printf next=~a~n next)
 (cond
   [(string? next) (string-append \ next \)]
   [(number? next) (number-string next)]
   [(null? next) ]
   [(list? next) `(string-append (js ,(car next)) (  ))]
   )
 
 It is supposed to handle numbers and function calls, without building the
 parameter list in the function calls.

It's doing this correctly, is it?

 However, when trying to build the parameter list I get and error which I
 don't understand:
 
 (define-syntax js
   (ir-macro-transformer
 (lambda (expr inject compare)
   (let ((body (cdr expr)) (next (cadr expr)))
   (printf next=~a~n next)
 (cond
   [(string? next) (string-append \ next \)]
   [(number? next) (number-string next)]
   [(null? next) ]
   [(list? next) `(string-append (js ,(car next)) ( (apply
 string-append (map js ,(cdr next))) ))]
   )
 
 CSI (js (1 2 3))
 next=(1 2 3)
 next=1
 Error: unbound variable: js

You're trying to use MAP on a macro.  That's not possible because
macros are not first-class (this is true in Common Lisp as well).

 1/ Why is js not bound in the second example? I also tried to use
 letrec-syntax but with same result.

Because of map.

 2/ Are there other ways to achieve what I want?

I don't understand what you're trying to do here.

 3/ I also tried to use syntax-rules, but from what I understood this is not
 possible, because you can't execute arbitrary expressions (in this case a
 cond) at macroexpansion time. Am I right here?

Indeed.  You can expand to a cond, but that would be less efficient.
On the other hand, this macro will only work on string literals.  Perhaps
the user would like to be able to use variables containing strings, which
would be impossible in this case.

Cheers,
Peter
-- 
http://sjamaan.ath.cx
--
The process of preparing programs for a digital computer
 is especially attractive, not only because it can be economically
 and scientifically rewarding, but also because it can be an aesthetic
 experience much like composing poetry or music.
-- Donald Knuth

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] struggling with macros

2012-11-11 Thread Răzvan Rotaru
On 11 November 2012 13:30, Peter Bex peter@xs4all.nl wrote:

 On Sun, Nov 11, 2012 at 01:23:13PM +0100, Răzvan Rotaru wrote:
  Hi,

 Hi!

  I'm trying to write a simple javascript DSL, and got stuck in the macros
  :). (I'm coming from lisp macros)  Take for example this one:
 
  (define-syntax js
(ir-macro-transformer
  (lambda (expr inject compare)
(let ((body (cdr expr)) (next (cadr expr)))
(printf next=~a~n next)
  (cond
[(string? next) (string-append \ next \)]
[(number? next) (number-string next)]
[(null? next) ]
[(list? next) `(string-append (js ,(car next)) (  ))]
)
 
  It is supposed to handle numbers and function calls, without building the
  parameter list in the function calls.

 It's doing this correctly, is it?


Yes, behaviour is correct, but implementation is not complete, hence the
next version of js-macro.


 You're trying to use MAP on a macro.  That's not possible because
 macros are not first-class (this is true in Common Lisp as well).


Well, essentially what I have here is a macro calling itself. How can I do
that?

I don't understand what you're trying to do here.


I am trying to build a javascript DSL, similar to parenscript. The code
above is very simple and should behave like this:

(js 123) = 123
(js 123) = \123\
(js (1 2 3)) = 1(2, 3)

The first two are primitives, the last is a function call. For simplicity,
I ignored the comma that separates parameters in the function call. So the
output I'm expecting from my code is actually:

(js (1 2 3)) = 1(23)


Răzvan
___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] struggling with macros

2012-11-11 Thread Peter Bex
On Sun, Nov 11, 2012 at 02:24:17PM +0100, Răzvan Rotaru wrote:
 On 11 November 2012 13:30, Peter Bex peter@xs4all.nl wrote:
 Yes, behaviour is correct, but implementation is not complete, hence the
 next version of js-macro.
 
  You're trying to use MAP on a macro.  That's not possible because
  macros are not first-class (this is true in Common Lisp as well).
 
 
 Well, essentially what I have here is a macro calling itself. How can I do
 that?

Generally, you can't.  There are a few things you can do instead:
- Expand to a new call to (js ...) for each of the elements.
- Loop manually over the cdr inside the macro (maybe using map and
   an anonymous lambda).
- Move the real conversion work into a procedure.  This can be used
   by the macro, and the procedure can call itself.  This is a bit
   tricky because you'll need to define the procedure in a
   begin-for-syntax block or put it in a separate module and 
   require-for-syntax it.

 I am trying to build a javascript DSL, similar to parenscript. The code
 above is very simple and should behave like this:
 
 (js 123) = 123
 (js 123) = \123\
 (js (1 2 3)) = 1(2, 3)

 The first two are primitives, the last is a function call. For simplicity,
 I ignored the comma that separates parameters in the function call. So the
 output I'm expecting from my code is actually:
 
 (js (1 2 3)) = 1(23)

I think that should be pretty easy.

Cheers,
Peter
-- 
http://sjamaan.ath.cx
--
The process of preparing programs for a digital computer
 is especially attractive, not only because it can be economically
 and scientifically rewarding, but also because it can be an aesthetic
 experience much like composing poetry or music.
-- Donald Knuth

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] struggling with macros

2012-11-11 Thread Kristian Lein-Mathisen
Hi Răzvan,

Just as a side-note: It may be a good idea to play around with your
implementation as a normal function, and them wrap that in a macro once
it's up on its feet. That way you can isolate problems with your
implementation and problems with the macros.

This approach is taken by the bind egg (see
bind.scmhttp://bugs.call-cc.org/browser/release/4/bind/trunk/bind.scmand
bind-translator.scmhttp://bugs.call-cc.org/browser/release/4/bind/trunk/bind-translator.scm).
It could for example be setup like this:

- js-transformer.scm
;; define a function js-transformer that does this:
;;(js-transformer 123) = 123
;;(js-transformer 123) = \123\
;;(js-transformer '(1 2 3)) = 1(2, 3) ;; note the quote!

- js.scm
;; import js-transformer into syntax env
(begin-for-syntax (include js-transformer.scm)) ;; or (import-for-syntax
js-transformer.scm) if you have a module (I think)

;; define a macro that uses js-transformer at expansion-time
(define-syntax js
  (ir-macro-transformer
(lambda (expr inject compare)
(js-transform (cdr expr)


K.


On Sun, Nov 11, 2012 at 1:23 PM, Răzvan Rotaru razvan.rot...@gmail.comwrote:

 Hi,

 I'm trying to write a simple javascript DSL, and got stuck in the macros
 :). (I'm coming from lisp macros)  Take for example this one:

 (define-syntax js
   (ir-macro-transformer
 (lambda (expr inject compare)
   (let ((body (cdr expr)) (next (cadr expr)))
   (printf next=~a~n next)
 (cond
   [(string? next) (string-append \ next \)]
   [(number? next) (number-string next)]
   [(null? next) ]
   [(list? next) `(string-append (js ,(car next)) (  ))]
   )


 It is supposed to handle numbers and function calls, without building the
 parameter list in the function calls.

 CSI (js 1)
 next=1
 1
 CSI (js (1 2 3))
 next=(1 2 3)
 next=1
 1()


 However, when trying to build the parameter list I get and error which I
 don't understand:

 (define-syntax js
   (ir-macro-transformer
 (lambda (expr inject compare)
   (let ((body (cdr expr)) (next (cadr expr)))
   (printf next=~a~n next)
 (cond
   [(string? next) (string-append \ next \)]
   [(number? next) (number-string next)]
   [(null? next) ]
   [(list? next) `(string-append (js ,(car next)) ( (apply
 string-append (map js ,(cdr next))) ))]
   )

 CSI (js (1 2 3))
 next=(1 2 3)
 next=1
 Error: unbound variable: js
 [ inspect ]

 Restarts:
   0: [ABORT] Return to SLIME's top level

 Backtrace:
   0: eval   [ more... ] (map248 js245 (2 3))
   1: eval   [ more... ] (apply247 string-append246 (map248 js245 (2 3)))
   2: eval   [ more... ] (string-append246 (js245 1) ( (apply247
 string-append246 (map248 js245 (2 3))) ))
   3: syntax (2 3)
   4: syntax (map248 js245 (2 3))
   5: syntax (apply247 string-append246 (map248 js245 (2 3)))
   6: eval   [ more... ] (number-string next)
   7: eval   [ more... ] (number? next)
   8: eval   [ more... ] (printf next=~a~n next)
   9: eval   [ more... ] (cadr expr)
  10: eval   [ more... ] (cdr expr)
  11: syntax (js245 1)
  12: syntax (string-append246 (js245 1) ( (apply247
 string-append246 (map248 js245 (2 3))) ))
  13: eval   [ more... ] (cdr next)
  14: eval   [ more... ] (##sys#list (##core#quote map) (##core#quote js)
 (cdr next))
  15: eval   [ more... ] (##sys#list (##core#quote apply) (##core#quote
 string-append) (##sys#list (##core#quote map) (##core#quote js) (cdr next)))

 So, my questions are:
 1/ Why is js not bound in the second example? I also tried to use
 letrec-syntax but with same result.
 2/ Are there other ways to achieve what I want?
 3/ I also tried to use syntax-rules, but from what I understood this is
 not possible, because you can't execute arbitrary expressions (in this case
 a cond) at macroexpansion time. Am I right here?

 Thanks,
 Răzvan

 ___
 Chicken-users mailing list
 Chicken-users@nongnu.org
 https://lists.nongnu.org/mailman/listinfo/chicken-users


___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users