Simple Reader Macros for Dylan 
Author Message
 Simple Reader Macros for Dylan

As promised here is a very brief description of a very simple reader macro
facility that permits Dylan to have friendly literal formats for popular
data types. This was thought up by Andrew Armstrong, Keith Playford and
myself while at Harlequin.  We would love to get your feedback on it.  The
following is Keith's description of it.

Jonathan Bachrach
President, Functional Objects, Inc.

Simple Reader Macros

The syntax:

#<name>:<text>

gets transformed, setter-like, into:

<name>-parser(<text>)

The <text> part can be either delimited or undelimited. Undelimited text
can contain anything but commas, semicolons, brackets of any kind, and
whitespace. There is no \ escape processing. All the following are valid:

# http://www.*-*-*.com/
#time:12:30am
#date:12/3/2000
#file:D:\dylan\sources\

In the delimited form, you have a choice of delimiters: "...", (...), [...],
{...}. Within the delimiters, only the matching close delimiter must be
escaped. The selection allows you to choose the delimiter requiring least
escaping for the enclosed data. The text (less the delimiters) is passed
to the parsing function. Examples:

#file:"C:\Program Files\Functional Objects\."
#html:{<html>
<head><title>Foo</title></head>
<body bgcolor="#FFFFFF">
</body>
</html>}

An example parser:

define method html-parser
     (text :: <byte-string>) => (doc :: <html-document>)
   make(<html-document>, text: text);
end method;

If an appropriate function isn't defined, you get a standard unbound variable
reference message indicating the # literal.

Also in order to allow these sort of literals in literal lists and vectors,
we further propose to allow arbitrary expressions in "literal" lists
and vectors. The same constancy/sharing rules would still apply to the
lists and vectors themselves. That is:

let times = #[#time:12:30am, #time:4:15pm];
==
let times = #[time-parser("12:30am"), time-parser("4:15pm")];

which is allowed, but still:

times[0] := times[1];

"is an error" in case the compiler can work its magic.



Sat, 04 May 2002 03:00:00 GMT  
 Simple Reader Macros for Dylan
Quote:
----- Original Message -----


Sent: Tuesday, November 16, 1999 8:14 AM
Subject: Simple Reader Macros for Dylan

[...]
> Simple Reader Macros

> The syntax:

> #<name>:<text>

> gets transformed, setter-like, into:

> <name>-parser(<text>)

Hmmm, so these are not so much reader macros as just a new bit of syntactic
sugar, correct? <name>-parser doesn't actually get called at compile-time,
correct?

[...]
> An example parser:

> define method html-parser
>      (text :: <byte-string>) => (doc :: <html-document>)
>    make(<html-document>, text: text);
> end method;

> If an appropriate function isn't defined, you get a standard unbound
variable
> reference message indicating the # literal.

I assume errors are reported by the parser throwing some condition?

> Also in order to allow these sort of literals in literal lists and
vectors,
> we further propose to allow arbitrary expressions in "literal" lists
> and vectors. The same constancy/sharing rules would still apply to the
> lists and vectors themselves. That is:

> let times = #[#time:12:30am, #time:4:15pm];
> ==
> let times = #[time-parser("12:30am"), time-parser("4:15pm")];

> which is allowed, but still:

> times[0] := times[1];

> "is an error" in case the compiler can work its magic.

You've lost me here... Why is the above assignment an error?

-- Kaelin



Sat, 04 May 2002 03:00:00 GMT  
 Simple Reader Macros for Dylan

Quote:
> [...]

> > The syntax:

> > #<name>:<text>

> > gets transformed, setter-like, into:

> > <name>-parser(<text>)

> Hmmm, so these are not so much reader macros as just a new bit of syntactic
> sugar, correct? <name>-parser doesn't actually get called at compile-time,
> correct?

Well, if <name>-parser is a macro rather than a function, then it will
get called at compile-time. You need an extended macro system to be able to
take a string apart usefully, however.

Certainly <name>-parser doesn't get called at read time with a stream like
Common Lisp reader macros do, so the mechanism is less general than that.
The benefit is that Dylan implementations that don't support compile-time
evaluation can still provide this facility.

Quote:
> [...]

> > An example parser:

> > define method html-parser
> >      (text :: <byte-string>) => (doc :: <html-document>)
> >    make(<html-document>, text: text);
> > end method;

> > If an appropriate function isn't defined, you get a standard unbound
> > variable reference message indicating the # literal.

> I assume errors are reported by the parser throwing some condition?

If you mean the <name>-parser function or macro, then yes (a macro might
signal a parse error to the compiler either implicitly, due to a match
error, or perhaps explicitly in the case of a procedural macro).

Quote:
> [...]

> > Also in order to allow these sort of literals in literal lists and
> > vectors,
> > we further propose to allow arbitrary expressions in "literal" lists
> > and vectors. The same constancy/sharing rules would still apply to the
> > lists and vectors themselves. That is:

> > let times = #[#time:12:30am, #time:4:15pm];
> > ==
> > let times = #[time-parser("12:30am"), time-parser("4:15pm")];

> > which is allowed, but still:

> > times[0] := times[1];

> > "is an error" in case the compiler can work its magic.

> You've lost me here... Why is the above assignment an error?

Because Dylan compilers are allowed to apply literal constant merging: i.e.
using the same object to represent more than one literal (or part of a
literal) if those literals are structurally identical. The objects
corresponding to literal constants are also often located in read-only
sections. For these reasons, attempting to mutate a literal string, list,
or vector is an error in Dylan.

-- Keith



Sat, 04 May 2002 03:00:00 GMT  
 Simple Reader Macros for Dylan

Quote:

> #<name>:<text>

> gets transformed, setter-like, into:

> <name>-parser(<text>)

This is a great idea. I can see it before me:

#regex:"(\s+)[a-q]?"

Using regexes in Dylan has been a nightmare due to all the escaping.

Quote:
> There is no \ escape processing. [...]
> In the delimited form, you have a choice of delimiters: "...", (...), [...],
> {...}. Within the delimiters, only the matching close delimiter must be
> escaped.

Ok, when there is no escape processing, then how do I escape the close
delimiter? Please specify how the following cases are to be handled:

#foo:"\"
#foo:"\""
#foo:"\\"
#foo:"\\""
#foo:"\\\""

Andreas (who is wondering how to tell that to the Gwydion parser)

--
"We should be willing to look at the source code we produce not as the
end product of a more interesting process, but as an artifact in its
own right. It should look good stuck up on the wall."
 -- http://www.ftech.net/~honeyg/progstone/progstone.html



Sat, 04 May 2002 03:00:00 GMT  
 Simple Reader Macros for Dylan

Quote:
> > #<name>:<text>

> > gets transformed, setter-like, into:

> > <name>-parser(<text>)

> This is a great idea. I can see it before me:

> #regex:"(\s+)[a-q]?"

> Using regexes in Dylan has been a nightmare due to all the escaping.

> > There is no \ escape processing. [...]
> > In the delimited form, you have a choice of delimiters: "...", (...), [...],
> > {...}. Within the delimiters, only the matching close delimiter must be
> > escaped.

> Ok, when there is no escape processing, then how do I escape the close
> delimiter?

The "there is no escape processing" bit is only meant to refer to the
undelimited version. As for the delimited form, we'd be open to suggestions
that get in the way as little as possible. I think the {*filter*} prototype
we wrote just did \} -> } and \\ -> \ but it wasn't given much thought.
Under that scheme, though:

Quote:
> Please specify how the following cases are to be handled:

> #foo:"\"

Char: "
Char: <more until an unescaped end delimiter is found>

Quote:
> #foo:"\""

Char: "

Quote:
> #foo:"\\"

Char: \

Quote:
> #foo:"\\""

Char: \

with a " left over

Quote:
> #foo:"\\\""

Char: \
Char: "

Not a great choice if you have to work much with MS network file names,
however. Perhaps something more heavyweight but less likely to look like
content, \}\ -> } maybe.

I guess another issue is, where there are distinct begin and end delimiters
(i.e. brackets of some kind), should scanning be nesting-aware & so should
escaping have to be applied to both delimiters? Example:

  #dylan:{ define macro when
             { when (?test:expression) ?:body end } => { if (?test) ?body end }
           end macro }

-- Keith



Tue, 07 May 2002 03:00:00 GMT  
 Simple Reader Macros for Dylan
On Fri, 19 Nov 1999 23:39:45 -0000, "Keith Playford"

Quote:

> Re: Simple Reader Macros for Dylan

What did you think about my idea for adopting Perl's convention for regexp
delimiters in Dylan reader macros? Perl lets you use any character as the
delimiter, then it just searches for another one of those. In practice, this
lets you sidestep the problem of escaping the delimiter character when you
want to refer to it in the literal. Instead of escaping the fixed delimiter
you simply use a different character. Sort of "lexer judo".

e.g.

        #regexp:"foo.*bar"

or if you need to match on double quote characters:

        #regexp:/baz(".*")/

However, this would mean that you couldn't use balanced pairs of 'opposite'
characters like '(' and ')' unless the you extended Perl's notion of "another
one" to include opposites.

__Jason



Mon, 13 May 2002 03:00:00 GMT  
 Simple Reader Macros for Dylan

Quote:

> However, this would mean that you couldn't use balanced pairs of 'opposite'
> characters like '(' and ')' unless the you extended Perl's notion of "another
> one" to include opposites.

Uh, Perl already did that.


helzz there

-- Bruce



Tue, 14 May 2002 03:00:00 GMT  
 Simple Reader Macros for Dylan


Quote:

> > However, this would mean that you couldn't use balanced pairs of 'opposite'
> > characters like '(' and ')' unless the you extended Perl's notion of "another
> > one" to include opposites.

> Uh, Perl already did that.


> helzz there

Okay great. So what about it?

__Jason (whose knowledge of Perl was an intensive snapshot taken of Perl4
several years ago)



Tue, 14 May 2002 03:00:00 GMT  
 Simple Reader Macros for Dylan

Quote:

> > Uh, Perl already did that.


> > helzz there

> Okay great. So what about it?

So do it, I guess, and let us know how it works out.

I'd suggest not allowing *quite* the full generality of Perl's syntax.
Allowing multiple arguments to be specified would be useful (e.g. as in
the s/// example above).  But you could restrict the allowable single
delimiters to maybe /,\,!, and |.  Having the pairs be ",',{},(),[],<>
seems ok as all those are used in Dylan anyway.

I really hope that Dylan doens't become a kitchen-sink language, but
extendable literals doesn't seem like the straw that will break the
camel's back, and it might forstall a bunch of others, such as a special
literal format for complex numbers, or for dates, or whatever.  Of course
everyone proposing an extension to any language *always* says that... :-)

But if the function that processes the literal is written so as to not
modify global state then we're even likely to see it optomised out by a
suitably smart compiler.

-- Bruce



Wed, 15 May 2002 03:00:00 GMT  
 Simple Reader Macros for Dylan
When Keith first suggested this, I thought it
looked really neat.  After some reflection, I
wonder whether it really offers much over simple
strings.  Instead of converting a simple name
into a longer function name, why not just use a
simple function name?

Quote:
> #http://www.functionalobjects.com/

http("//www.functionalobjects.com")

Quote:
> #time:12:30am

time("12:20am")

Quote:
> #date:12/3/2000

date("3/12/2000")
    ;-)
Quote:
> #file:D:\dylan\sources\

file("D:\\dylan\\sources")


The only advantage I can see for the literal
syntax is the option of using different
delimiters and escape processing.  Where I've
most often wanted this is when dealing with
strings containing backslashes, as with the
Windows path above.  Perhaps a simpler change
would be the ability to change the string escape
character, either as a compiler option, or by a
declaration in the code.  E.g.

string-escape('^');
file("D:\dylan\sources");
print("hello, world^n");

Obviously STRING-ESCAPE would have to be a
declaration that the compiler recognises, not a
regular Dylan expression.

(Please pardon any lapses in my Dylan syntax).

Dave.

P.S. Hi!

In article



Quote:
> As promised here is a very brief description of

a very simple reader macro
Quote:
> facility that permits Dylan to have friendly

literal formats for popular
Quote:
> data types. This was thought up by Andrew

Armstrong, Keith Playford and
Quote:
> myself while at Harlequin.  We would love to

get your feedback on it.  The
Quote:
> following is Keith's description of it.

> Jonathan Bachrach
> President, Functional Objects, Inc.

> Simple Reader Macros

> The syntax:

> #<name>:<text>

> gets transformed, setter-like, into:

> <name>-parser(<text>)

> The <text> part can be either delimited or

undelimited. Undelimited text
Quote:
> can contain anything but commas, semicolons,

brackets of any kind, and
Quote:
> whitespace. There is no \ escape processing.

All the following are valid:
Quote:

> #http://www.functionalobjects.com/
> #time:12:30am
> #date:12/3/2000
> #file:D:\dylan\sources\

> In the delimited form, you have a choice of

delimiters: "...", (...), [...],
Quote:
> {...}. Within the delimiters, only the matching

close delimiter must be
Quote:
> escaped. The selection allows you to choose the

delimiter requiring least
Quote:
> escaping for the enclosed data. The text (less

the delimiters) is passed

- Show quoted text -

Quote:
> to the parsing function. Examples:

> #file:"C:\Program Files\Functional Objects\."
> #html:{<html>
> <head><title>Foo</title></head>
> <body bgcolor="#FFFFFF">
> </body>
> </html>}

> An example parser:

> define method html-parser
>      (text :: <byte-string>) => (doc :: <html-
document>)
>    make(<html-document>, text: text);
> end method;

> If an appropriate function isn't defined, you

get a standard unbound variable
Quote:
> reference message indicating the # literal.

> Also in order to allow these sort of literals

in literal lists and vectors,
Quote:
> we further propose to allow arbitrary

expressions in "literal" lists
Quote:
> and vectors. The same constancy/sharing rules

would still apply to the

Quote:
> lists and vectors themselves. That is:

> let times = #[#time:12:30am, #time:4:15pm];
> ==
> let times = #[time-parser("12:30am"), time-
parser("4:15pm")];

> which is allowed, but still:

> times[0] := times[1];

> "is an error" in case the compiler can work its
magic.

Sent via Deja.com http://www.deja.com/
Before you buy.


Sat, 25 May 2002 03:00:00 GMT  
 
 [ 10 post ] 

 Relevant Pages 

1. Simple Reader Macros for Dylan

2. reader macros?

3. from a reader macro

4. Using EVAL-WHEN and Reader Macros

5. Reader Macro Characters

6. Selective compilation of reader macro forms...

7. reader macros in scheme

8. A Simple Mail Reader

9. A Simple Mail Reader

10. RSSGUI, simple RSS reader

11. are dylan macros Turing-complete?

12. C++ Templates used like Dylan Macros

 

 
Powered by phpBB® Forum Software