The best kittens, technology, and video games blog in the world.

Tuesday, May 08, 2007

RLisp syntax for literals

Evil cat by scooter.john from flickr (CC-NC)Every language nowadays requires rich syntax for literals.

Here's a table for RLisp. The lists may seems a bit redundant, but it's basically nicely formatted test set data.

I don't think there's sufficient support for String and Regexp literal syntax.

ClassRLispRubyAST RepresentationNotes
TrueClasstruetrueGlobal identifier true
#ttrueGlobal identifier true (translated inside parser)Scheme compatibility only.
FalseClassfalsefalseGlobal identifier false
#ffalseGlobal identifier false (translated inside parser)Scheme compatibility only.
NilClassnilnilGlobal identifier nil
Integer (Fixnum and Bignum)00Integer object
-0-0
55
-5-5
1234567890123456789012345678901234567890Bignum
-12345678901234567890-12345678901234567890
0x12340x1234Hex
-0x1234-0x1234
07550755Octal
-0755-0755
0b100110b10011Binary
-0b10011-0b10011
Float0.00.0Float objects
-0.0-0.0
5.05.0
-5.0-5.0
3.143.14
-3.14-3.14
1e61e6
-1e6-1e6
1.234e61.234e6
-1.234e6-1.234e6
1.234e+61.234e+6
-1.234e+6-1.234e+6
1.234e-61.234e-6
-1.234e-6-1.234e-6
Array (like "lists" in other Lisps)()[][]Bare non-empty lists are considered function applications.
(list 1 2 3)[1, 2, 3][:list, 1, 2, 3]
'(1 2 3)[1, 2, 3][:quote, [1, 2, 3]]
`(1 2 3)[1, 2, 3][:quasiquote, [1, 2, 3]]
`(1 ,(+ 2 3) 6)[1, 2+3, 6][:quasiquote, [1, [:unquote, [:+, 2, 3]], 6]]
`(1 2 ,@(list 3 4 5))[1, 2, *[3, 4, 5]][:quasiquote, [1, [:"unquote-splicing", [:list, 3, 4, 5]], 6]]
(list 1 2 . (list 3 4 5))[1, 2, *[3, 4, 5]][:list, 1, 2, :".", [:list, 3, 4, 5]]. and & have special meaning in function applications, a bit like Scheme "."/Ruby "*", and Ruby "&".
Range[Range new 1 25]1..25Plain method call
[Range new 2 25 false]2..25
[Range new 3 25 true]3...25
(.. 4 25)4..25Global function ..
(... 5 25)5...25Global function ...
[6 .. 25]6..25Method Object#.. in rlisp_support.rb
[7 ... 25]7...25Method Object#... in rlisp_support.rb
Symbol'foo:foo[:quote :foo]When symbols are evaluated, ., & and self are magical, lowercase are RLisp variables, and uppercase (possibly with ::s inside) are Ruby global constants (but RLisp Array means Ruby ::Array really). In data mode (when quoted, or passed to macros) all symbols are equal. To create unique symbol use (gensym).
foo-bar:"foo-bar"[:quote :"foo-bar"]Symbols can contain some characters that require special escaping in Ruby, like -.
'@foo:@foo[:quote :@foo]
'foo?!?!:"foo?!?!"[:quote :"foo?!?!"]
Hash(hash){}(hash ...) is a macro which expands to [Hash new] and some Hash#[]= calls.
(hash 1 => 2 3 => 4){1 => 2, 3 => 4}
(hash 'foo => 42 'bar => 96){:foo => 42, :bar => 96}
(hash foo: 42 bar: 96){:foo => 42, :bar => 96}Hashes indexed by constant Symbols are so common that they have special syntax (generic syntax still works).
Time[Time now]Time.nowPlain method call.
[Time at 1178573823]Time.at(1178573823)Seconds since Unix epoch
String"Hello""Hello"String object
"Hello, world!\n""Hello, world!\n"Backslash escapes work, #{...} does not.
(str "2 + 2 = " (+ 2 2))"2 + 2 = #{2 + 2}"(str ...) global function which calls #to_s and joins results.
Regexp(rx "foo")/foo/Calls to global function (rx ...) which calls Regexp.new.
(rx "(?i:foo)")/foo/i or /(?i:foo)/
(rx "\\d+")/\d+/Double-escaping is necessary.

2 comments:

Zverok said...

Two small comments.
1. In the table
RLisp 1..25
Ruby [Range new 1 25]
shouldn't it be vice versa?

2. double escaping in Regexps is really annoying (tested years back on C++ with Boost::Regexp :)

taw said...

Zverok: Thanks for spotting the mistake, I fixed it.

I think I'll make the parser convert "Hello, #{obj}!\n" to (str "Hello, " obj "!\n") and /\d+/ to (rx "\\d+") or to Regexp object. Division will have to become (div x y), as there's not enough context in RLisp to make / character do both, but that's a small price.