Commit 23eae3c9 authored by Haochen Xie's avatar Haochen Xie

update README.md

parent 16ed4348
<!-- -*- mode: markdown; fill-column: 100 -*- -->
# Scripting Language Lilacs
This is a draft description of the scripting language Lilacs.
Lilacs is a LISP inspired little language that compiles into JavaScript. It is initially designed to
be used as the server side scripting language in the Git Blogger system.
## Language specification
### Special forms
- `=>`
(x y ... => body1 ... body2)
->
(function (x, y ...) {
body1;
...
return body2;
})
or this alternative form to allow recursion:
([func] x y ... => body1 ... body2)
->
(function func(x, y ...) {
body1;
...
return body2;
})
- `exact`
(exact var)
->
var
(exact obj/field)
->
obj.field
- `new`
(new func arg1 arg2 ...)
->
new func(arg1, arg2 ...)
- `@@`
(@@ idx arr)
->
arr[idx]
(@@ key obj)
->
obj[key]
- `if`
(if a b c)
->
if (a) { return b; } else { return c; }
- `case`
(case k
((a ... b) body1)
((c ... d) body2)
(else body3))
->
(function () {
switch (k) {
case a:
...
case b:
return body1;
case c:
...
case d:
return body2;
default:
return body3;
}
})()
you can specify multiple expression bodies and omit the else clause. it would be equivalent with
the following:
(case k
((a ... b) body1 ... body2))
->
(case k
((a ... b) (begin body1 ... body2))
(else (throw% "case matching failed")))
- `w%` (`w%` as an alternative of `w/`, which comes from "with handler")
(w% (handler fin) body1 ... body2)
->
(function () {
try {
body1;
...
return body2;
} catch (__lilacs_e) {
return handler(__lilacs_e);
} finally {
fin();
}
})
you can also omit `fin`.
as an obvious observation, you should avoid using `__lilacs_e` as a variable name in your code.
- `throw%`
(throw% e)
->
(function () { throw e; return; })()
### Special constants
- `#undefined` -> `undefined`
- `#null` -> `null`
- `#t` -> `true`
- `#f` -> `false`
### Syntax sugars
- `let`
(let ((x var1) (y var2) ...) body1 ... body2)
->
((x y => body1 ... body2) var1 var2)
- `begin`
(begin body1 ... body2)
->
((=> body1 ... body2))
- `for`
(for (x arr) body1 ... body2)
->
(arr/map (x => body1 ... body2))
- `for-in`
(for-in (k v obj) body1 ... body2)
->
((__lilacs_obj =>
((Object/keys __lilacs_obj)/map
(k => (let ((v (@@ k __lilacs_obj))) body1 ... body2)))) obj)
which is basically the same as
((Object/keys obj)/map (k => (let ((v (@@ k obj))) body1 ... body2)))
but make sure obj is only evaluated once.
note that this doesn't have the same behavior as the `for ... in ...` loop in JavaScript. See
the JavaScript documentation for `Object.keys` for more information.
also as an obvious observation, you should avoid using `__lilacs_obj` as a variable name in your
code.
- `@`-shorthand
(@func :A a ... :B b :: p1 ... p2)
->
(_shat/func {:A a ... :B b} [p1 p2])
(obj/@method :A a ... :B b :: p1 ... p2)
->
(obj/_shat/method {:A a ... :B b} [p1 p2])
with this shorthand, it provides a standard yet convenient and clear way to define and use
functions that generates HTML tags. e.g:
(@ul :class "fancy-list" ::
(@li :: (@a :href "/article-1" :: "article-1"))
(@li :: (@a :href "/article-2" :: "article-2")))
### Numbers
Lilacs recognizes numbers as JavaScript does. Thus
`345, 34.5, 3.45e2, 0377, 0xFF, 0xff, Infinity, NaN`
are all valid numbers in Lilacs.
### Strings
Lilacs only recognizes double quoted strings, and uses the same escaping sequences as JavaScript.
Additionally, Lilacs support its own form of raw string literal enclosed between `::!` and `!::`.
Raw string literal can also be post-processed if needed.
::!
raw string
second line
!::
->
"raw string\n second line"
::! func
raw string
second line
!::
->
(func "raw string\n second line")
### Regular expressions
Currently, Lilacs doesn't have specific grammar for regular expressions, but you can create regular
expressions with the RegExp class:
(new RegExp "https?://.+")
->
new RegExp("https?://.+")
### Invocation
(func arg1 arg2 ...)
->
func(arg1, arg2 ...)
(obj/method arg1 arg2 ...)
->
obj.method(arg1, arg2 ...)
### Access
var
->
var
obj/field
->
obj.field
### Assignment
Lilacs provides assignments to work with the rest of JavaScript world, but it's usage is discourage.
(<- var val)
->
var = val
### Object creation
{:key1 val1 :key2 val2 ...}
->
{key1 : val1, key2 : val2 ...}
### Array creation
[a b ...]
->
[a b ...]
### Operators
Lilacs provides polish style operators for the following JavaScript's binary operators with the same
name:
`+, -, *, /, %, >, >=, <, <=, &&, ||, &, |, ^, <<, >>, >>>`
and the following with a different name:
- `eq?` -> `==`
- `eq??` -> `===`
- `neq?` -> `!=`
- `neq??` -> `!==`
and also the following unary operators with the same name:
`+, -, !, ~`
Lilacs doesn't provide assignment arithmetic operators on purpose, nor increment/decrement
operators.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment