sibilant 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +8 -4
- data/js/sibilant/.gitignore +4 -0
- data/js/sibilant/.travis.yml +6 -0
- data/js/sibilant/LICENSE +20 -0
- data/js/sibilant/README.md +70 -0
- data/js/sibilant/bin/sibilant +3 -0
- data/js/sibilant/cli-help +79 -0
- data/js/sibilant/include/functional.sibilant +57 -0
- data/js/sibilant/include/macros.sibilant +374 -0
- data/js/sibilant/include/node.sibilant +2 -0
- data/js/sibilant/lib/browser.js +685 -0
- data/js/sibilant/lib/cli.js +153 -0
- data/js/sibilant/lib/options.js +232 -0
- data/js/sibilant/lib/repl.js +78 -0
- data/js/sibilant/lib/sibilant.js +688 -0
- data/js/sibilant/misc/sibilant-mode.el +129 -0
- data/js/sibilant/package.json +19 -0
- data/js/sibilant/package.sibilant +16 -0
- data/js/sibilant/public/index.html +502 -0
- data/js/sibilant/public/javascripts/browser.js +685 -0
- data/js/sibilant/public/javascripts/jquery-ui.js +392 -0
- data/js/sibilant/public/javascripts/jquery.js +154 -0
- data/js/sibilant/public/javascripts/macros.sibilant +374 -0
- data/js/sibilant/public/javascripts/sibilant.info.sibilant +77 -0
- data/js/sibilant/public/sass/_mixins.sass +98 -0
- data/js/sibilant/public/sass/sibilant.sass +156 -0
- data/js/sibilant/public/stylesheets/Anonymous_Pro-webfont.eot +0 -0
- data/js/sibilant/public/stylesheets/Anonymous_Pro-webfont.svg +241 -0
- data/js/sibilant/public/stylesheets/Anonymous_Pro-webfont.ttf +0 -0
- data/js/sibilant/public/stylesheets/Anonymous_Pro-webfont.woff +0 -0
- data/js/sibilant/public/stylesheets/sibilant.css +166 -0
- data/js/sibilant/src/browser.sibilant +45 -0
- data/js/sibilant/src/cli.sibilant +93 -0
- data/js/sibilant/src/core.sibilant +338 -0
- data/js/sibilant/src/options.sibilant +65 -0
- data/js/sibilant/src/repl.sibilant +59 -0
- data/js/sibilant/src/sibilant.sibilant +78 -0
- data/js/sibilant/test/defvar.sibilant +5 -0
- data/js/sibilant/test/includeFile1.sibilant +1 -0
- data/js/sibilant/test/includeFile2.sibilant +1 -0
- data/js/sibilant/test/node.sibilant +10 -0
- data/js/sibilant/test/slice.sibilant +3 -0
- data/js/sibilant/test/test.sibilant +464 -0
- data/js/sibilant/test/testHelper.sibilant +80 -0
- data/lib/sibilant/version.rb +1 -1
- data/sibilant.gemspec +3 -1
- metadata +44 -1
data/README.md
CHANGED
@@ -4,18 +4,20 @@
|
|
4
4
|
# Sibilant Ruby Gem
|
5
5
|
|
6
6
|
This is a ruby wrapper for the sibilant compiler, which is written in
|
7
|
-
javascript.
|
8
|
-
|
7
|
+
javascript. It expects to find NodeJS available on the path as node.
|
8
|
+
Sibilant doesn't need to be installed.
|
9
9
|
|
10
10
|
# Tilt support
|
11
11
|
|
12
|
-
|
12
|
+
[Tilt](https://github.com/rtomayko/tilt/) support is provided by `sibilant/tilt`:
|
13
13
|
|
14
14
|
require 'sibilant/tilt'
|
15
15
|
Tilt['test.sibilant'].new { "(+ 1 2 3)" }.render #=> '(1 + 2 + 3)'
|
16
16
|
|
17
17
|
# Sinatra
|
18
18
|
|
19
|
+
[Sinatra](http://sinatrarb.com) support is provided by `sibilant/sinatra`:
|
20
|
+
|
19
21
|
require 'sinatra'
|
20
22
|
require 'sibilant/sinatra'
|
21
23
|
helpers Sinatra::Sibilant
|
@@ -24,7 +26,9 @@ Providing sibilant code inside of a [tilt](https://github.com/rtomayko/tilt/) en
|
|
24
26
|
#./views/templated.sibilant
|
25
27
|
get('/templated.js') { sibilant :templated }
|
26
28
|
|
27
|
-
##
|
29
|
+
## How to install
|
30
|
+
|
31
|
+
First, you'll need [NodeJS](http://nodejs.org/) installed.
|
28
32
|
|
29
33
|
Add this line to your application's Gemfile:
|
30
34
|
|
data/js/sibilant/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Jacob Rothstein
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,70 @@
|
|
1
|
+
[](https://travis-ci.org/jbr/sibilant)
|
2
|
+
|
3
|
+
# Sibilant
|
4
|
+
|
5
|
+
- Sibilant is a language that is parsed by javascript and compiles to
|
6
|
+
javascript.
|
7
|
+
- Sibilant is inspired by lisp and follows many lisp conventions,
|
8
|
+
although it is still relatively close to the underlying javascript.
|
9
|
+
- Macros can be defined in sibilant and included at compile time.
|
10
|
+
- Sibilant is entirely written in sibilant and can recompile itself.
|
11
|
+
|
12
|
+
## Language Priorities
|
13
|
+
|
14
|
+
- Prefer verbose names to abbreviations by default.
|
15
|
+
- Avoid line noise. Prefer established punctuation semantics from
|
16
|
+
natural languages and common programming languages (eg commas come
|
17
|
+
after things and mean a pause or separation).
|
18
|
+
- Prefer readable and idiomatic javascript output, which necessitates
|
19
|
+
sticking fairly closely to javascript semantics. Switching cost from
|
20
|
+
sibilant to directly editing the output javascript should be low.
|
21
|
+
- Prefer expressions to statements. This is the most notable exception
|
22
|
+
to the adherance to idiomatic javascript. Self-executing functions
|
23
|
+
are used extensively to this end.
|
24
|
+
- Allow as much of the language to be modified in-source as
|
25
|
+
possible. This includes the ability to rename/remove/redefine all
|
26
|
+
keywords and macros.
|
27
|
+
- Any language constructs that do not output readable javascript
|
28
|
+
should be opt-in.
|
29
|
+
- Add language features slowly, and only when there's a real use
|
30
|
+
case. Don't blindly implement Lisp features without reasoning
|
31
|
+
through the need.
|
32
|
+
- Provide tools to simplify avoidance of repetition.
|
33
|
+
|
34
|
+
## Try it before you install
|
35
|
+
|
36
|
+
[sibilantjs.info](http://sibilantjs.info) includes an in-browser
|
37
|
+
as-you-type sibilant compiler and tutorial, so you can get a sense of
|
38
|
+
the language without leaving your browser.
|
39
|
+
|
40
|
+
## Installation
|
41
|
+
|
42
|
+
First, install [node.js](http://nodejs.org) [
|
43
|
+
[github](http://github.com/ry/node) ] and [npm](http://npmjs.org) [
|
44
|
+
[github](http://github.com/isaacs/npm) ]. Then, it's as simple as:
|
45
|
+
|
46
|
+
$ npm install sibilant -g
|
47
|
+
$ sibilant --help
|
48
|
+
|
49
|
+
## Learning the language and examples
|
50
|
+
|
51
|
+
The most up to date documentation will always be
|
52
|
+
[sibilantjs.info](http://sibilantjs.info) which includes an
|
53
|
+
as-you-type in-browser sibilant compiler. Check out [sibilant itself,
|
54
|
+
which is written 100% in
|
55
|
+
sibilant](http://github.com/jbr/sibilant/tree/master/src) to get a
|
56
|
+
sense of what's possible.
|
57
|
+
|
58
|
+
## How to get involved or learn more
|
59
|
+
|
60
|
+
Send a blank email to
|
61
|
+
[sibilant@librelist.com](mailto:sibilant@librelist.com) to join the
|
62
|
+
mailing list. Add any bugs or feature requests to the
|
63
|
+
[issues](http://github.com/jbr/sibilant/issues) page or email the
|
64
|
+
list. Happy hacking, have fun!
|
65
|
+
|
66
|
+
## License
|
67
|
+
|
68
|
+
Sibilant is released under the [MIT
|
69
|
+
license](http://github.com/jbr/sibilant/blob/master/LICENSE)
|
70
|
+
([wikipedia](http://en.wikipedia.org/wiki/MIT_License)).
|
@@ -0,0 +1,79 @@
|
|
1
|
+
Hi there! Thanks for installing sibilant.
|
2
|
+
Please leave feedback on github issues (http://github.com/jbr/sibilant/issues)
|
3
|
+
|
4
|
+
The current commandline options are
|
5
|
+
--------------------------------------------------------------------------------
|
6
|
+
|
7
|
+
-v / --version Print out a version string and exit
|
8
|
+
|
9
|
+
-h / --help This message
|
10
|
+
|
11
|
+
--repl / [no args] Sibilant interactive command prompt
|
12
|
+
|
13
|
+
--eval [optional STRING] / -e [optional STRING]
|
14
|
+
Evaluate STRING if provided, otherwise evaluate STDIN.
|
15
|
+
This is the same as -x -i [optional STRING]
|
16
|
+
|
17
|
+
--execute / -x This is a flag. Execute input files in order supplied.
|
18
|
+
|
19
|
+
--output DIR / -o DIR Output input files to this dir, replacing .sibilant with .js.
|
20
|
+
|
21
|
+
--input [optional STRING / -i [optional STRING]
|
22
|
+
Interpret optional string as sibilant code. If the execute
|
23
|
+
flag is set, execute this code. If STRING is not provided,
|
24
|
+
read STDIN.
|
25
|
+
|
26
|
+
--file FILE / -f FILE / FILE
|
27
|
+
Add this file to the input files. If the execute flag is
|
28
|
+
set, input files will be executed. If an output dir is
|
29
|
+
specified, each file will be written to that dir.
|
30
|
+
Otherwise, each file will be written to STDOUT.
|
31
|
+
|
32
|
+
|
33
|
+
To pass arguments to an executed file, append them after a \"--\", as follows
|
34
|
+
$ sibilant -x myfile.sibilant -- --arg-for-my-program=stuff
|
35
|
+
|
36
|
+
myfile.sibilant will see process.argv as
|
37
|
+
[ 'sibilant', 'myfile.sibilant', '--arg-for-my-program=stuff' ]
|
38
|
+
|
39
|
+
--------------------------------------------------------------------------------
|
40
|
+
|
41
|
+
Examples
|
42
|
+
|
43
|
+
to compile sibilant
|
44
|
+
$ git clone git://github.com/jbr/sibilant.git
|
45
|
+
$ npm link .
|
46
|
+
$ sibilant src/*.sibilant -o lib
|
47
|
+
$ sibilant -x test/test.sibilant # you're now running a sibilant you just compiled.
|
48
|
+
|
49
|
+
to compile one file to stdout
|
50
|
+
$ sibilant test/test.sibilant
|
51
|
+
|
52
|
+
to compile a file to a directory
|
53
|
+
$ sibilant test/test.sibilant -o . # put test.js here
|
54
|
+
or
|
55
|
+
$ sibilant --file test/test.sibilant --output .
|
56
|
+
|
57
|
+
to run a file
|
58
|
+
$ sibilant -x test/test.sibilant
|
59
|
+
|
60
|
+
to enter the repl
|
61
|
+
$ sibilant
|
62
|
+
or
|
63
|
+
$ sibilant --repl
|
64
|
+
|
65
|
+
to see how something will translate to js,
|
66
|
+
$ sibilant -i "(console.log (+ 2 2))"
|
67
|
+
console.log((2 + 2));
|
68
|
+
|
69
|
+
to execute a quick snippet,
|
70
|
+
$ sibilant -e "(console.log (+ 2 2))" # this is the same as -x -i
|
71
|
+
4
|
72
|
+
|
73
|
+
to translate STDIN,
|
74
|
+
$ echo "(console.log 'hello 'world)" | sibilant -i
|
75
|
+
console.log("hello", "world");
|
76
|
+
|
77
|
+
to execute sibilant code on STDIN,
|
78
|
+
$ echo "console.log 'hello 'world)" | sibilant -e # or sibilant -x -i
|
79
|
+
hello world
|
@@ -0,0 +1,57 @@
|
|
1
|
+
(defun bulk-map (arr fn)
|
2
|
+
(defvar index 0
|
3
|
+
group-size fn.length
|
4
|
+
ret-arr [])
|
5
|
+
|
6
|
+
(while (< index arr.length)
|
7
|
+
(send ret-arr push
|
8
|
+
(apply fn (send arr slice
|
9
|
+
index (+ index group-size))))
|
10
|
+
(incr-by index group-size))
|
11
|
+
ret-arr)
|
12
|
+
|
13
|
+
(defun inject (start items fn)
|
14
|
+
(defvar value start)
|
15
|
+
(when (list? items)
|
16
|
+
(each (item index) items
|
17
|
+
(setf value (fn value item index))))
|
18
|
+
value)
|
19
|
+
|
20
|
+
(defun map (items fn)
|
21
|
+
(inject [] items
|
22
|
+
(lambda (collector item index)
|
23
|
+
(send collector push (fn item index))
|
24
|
+
collector)))
|
25
|
+
|
26
|
+
(defun select (items fn)
|
27
|
+
(inject [] items
|
28
|
+
(lambda (collector item index)
|
29
|
+
(when (fn item index)
|
30
|
+
(send collector push item))
|
31
|
+
collector)))
|
32
|
+
|
33
|
+
(defun detect (items fn)
|
34
|
+
(defvar return-item undefined
|
35
|
+
index 0
|
36
|
+
items items)
|
37
|
+
|
38
|
+
(until (or (= items.length index) return-item)
|
39
|
+
(when (fn (get items index) index)
|
40
|
+
(setf return-item (get items index)))
|
41
|
+
(incr index)))
|
42
|
+
|
43
|
+
(defun reject (items fn)
|
44
|
+
(defvar args [ items fn ])
|
45
|
+
(select items (thunk (not (apply fn arguments)))))
|
46
|
+
|
47
|
+
(defun compact (arr)
|
48
|
+
(select arr (lambda (item)
|
49
|
+
(as-boolean item))))
|
50
|
+
|
51
|
+
(defun flatten (&rest items)
|
52
|
+
(inject [] items
|
53
|
+
(lambda (collector item)
|
54
|
+
(collector.concat
|
55
|
+
(if (list? item)
|
56
|
+
(apply flatten item)
|
57
|
+
item)))))
|
@@ -0,0 +1,374 @@
|
|
1
|
+
(defmacro cons (first rest)
|
2
|
+
(macros.send (macros.list first) 'concat rest))
|
3
|
+
|
4
|
+
(defmacro join (glue arr)
|
5
|
+
(concat "(" (translate arr) ").join(" (translate glue) ")"))
|
6
|
+
|
7
|
+
(defmacro list (&rest args)
|
8
|
+
(concat "[ " (join ", " (map args translate)) " ]"))
|
9
|
+
|
10
|
+
(defmacro get (arr i) (concat "(" (translate arr) ")[" (translate i) "]"))
|
11
|
+
|
12
|
+
(defmacro + (&rest args)
|
13
|
+
(concat "(" (join " + " (map args translate)) ")"))
|
14
|
+
(defmacro - (&rest args)
|
15
|
+
(concat "(" (join " - " (map args translate)) ")"))
|
16
|
+
(defmacro * (&rest args)
|
17
|
+
(concat "(" (join " * " (map args translate)) ")"))
|
18
|
+
(defmacro / (&rest args)
|
19
|
+
(concat "(" (join " / " (map args translate)) ")"))
|
20
|
+
(defmacro or (&rest args)
|
21
|
+
(concat "(" (join " || " (map args translate)) ")"))
|
22
|
+
(defmacro and (&rest args)
|
23
|
+
(concat "(" (join " && " (map args translate)) ")"))
|
24
|
+
(defmacro mod (&rest args)
|
25
|
+
(concat "(" (join " % " (map args translate)) ")"))
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
(defmacro infix-comparator (comparator args)
|
30
|
+
(concat "("
|
31
|
+
(join " && "
|
32
|
+
(map (args.slice 0 -1)
|
33
|
+
(lambda (item index)
|
34
|
+
(concat item
|
35
|
+
" " comparator " "
|
36
|
+
(get args (+ 1 index))))))
|
37
|
+
")"))
|
38
|
+
|
39
|
+
(defmacro > (&rest args) (macros.infix-comparator ">" (map args translate)))
|
40
|
+
(defmacro < (&rest args) (macros.infix-comparator "<" (map args translate)))
|
41
|
+
(defmacro <= (&rest args) (macros.infix-comparator "<=" (map args translate)))
|
42
|
+
(defmacro >= (&rest args) (macros.infix-comparator ">=" (map args translate)))
|
43
|
+
(defmacro != (&rest args) (macros.infix-comparator "!==" (map args translate)))
|
44
|
+
|
45
|
+
(defmacro pow (base exponent)
|
46
|
+
(macros.call "Math.pow" base exponent))
|
47
|
+
|
48
|
+
(defmacro incr-by (item increment)
|
49
|
+
(concat (translate item) " += " (translate increment)))
|
50
|
+
|
51
|
+
(defmacro incr (item)
|
52
|
+
(concat "((" (translate item) ")++)"))
|
53
|
+
|
54
|
+
(defmacro decr (item)
|
55
|
+
(concat "((" (translate item) ")--)"))
|
56
|
+
|
57
|
+
(defmacro set (arr &rest kv-pairs)
|
58
|
+
(join "\n" (bulk-map kv-pairs
|
59
|
+
(lambda (k v)
|
60
|
+
(concat "(" (translate arr) ")"
|
61
|
+
"[" (translate k) "] = " (translate v) ";")))))
|
62
|
+
|
63
|
+
(defmacro send (object method &rest args)
|
64
|
+
(concat (translate object) "." (translate method)
|
65
|
+
"(" (join ", " (map args translate)) ")"))
|
66
|
+
|
67
|
+
(defmacro new (fn)
|
68
|
+
(concat "(new " (translate fn) ")"))
|
69
|
+
|
70
|
+
(defmacro regex (string &optional glim)
|
71
|
+
((get macros 'new) (macros.call "RegExp" string (or glim "undefined"))))
|
72
|
+
|
73
|
+
(defmacro timestamp ()
|
74
|
+
(concat "\"" (send (new (-date)) to-string) "\""))
|
75
|
+
|
76
|
+
(defmacro comment (&rest contents)
|
77
|
+
(map contents
|
78
|
+
(lambda (item)
|
79
|
+
(join "\n" (map (send (translate item) split "\n")
|
80
|
+
(lambda (line) (concat "// " line)))))))
|
81
|
+
|
82
|
+
(defmacro meta (body)
|
83
|
+
(eval (translate body)))
|
84
|
+
|
85
|
+
(defmacro apply (fn arglist)
|
86
|
+
(macros.send fn 'apply 'undefined arglist))
|
87
|
+
|
88
|
+
(defmacro zero? (item)
|
89
|
+
((get macros "=") (translate item) 0))
|
90
|
+
|
91
|
+
(defmacro empty? (arr)
|
92
|
+
(concat "((" (translate arr) ").length === 0)"))
|
93
|
+
|
94
|
+
(defmacro odd? (number)
|
95
|
+
((get macros "!=") 0
|
96
|
+
(macros.mod (translate number) 2)))
|
97
|
+
|
98
|
+
(defmacro even? (number)
|
99
|
+
((get macros "=") 0
|
100
|
+
(macros.mod (translate number) 2)))
|
101
|
+
|
102
|
+
|
103
|
+
(defmacro function? (thing)
|
104
|
+
(concat "typeof(" (translate thing) ") === 'function'"))
|
105
|
+
|
106
|
+
(defmacro undefined? (thing)
|
107
|
+
(concat "typeof(" (translate thing) ") === 'undefined'"))
|
108
|
+
|
109
|
+
(defmacro defined? (thing)
|
110
|
+
(concat "typeof(" (translate thing) ") !== 'undefined'"))
|
111
|
+
|
112
|
+
(defmacro number? (thing)
|
113
|
+
(concat "typeof(" (translate thing) ") === 'number'"))
|
114
|
+
|
115
|
+
(defmacro first (arr) (macros.get arr 0))
|
116
|
+
(defmacro second (arr) (macros.get arr 1))
|
117
|
+
(defmacro third (arr) (macros.get arr 2))
|
118
|
+
(defmacro fourth (arr) (macros.get arr 3))
|
119
|
+
(defmacro fifth (arr) (macros.get arr 4))
|
120
|
+
(defmacro sixth (arr) (macros.get arr 5))
|
121
|
+
(defmacro seventh (arr) (macros.get arr 6))
|
122
|
+
(defmacro eighth (arr) (macros.get arr 7))
|
123
|
+
(defmacro ninth (arr) (macros.get arr 8))
|
124
|
+
|
125
|
+
(defmacro rest (arr)
|
126
|
+
(macros.send arr 'slice 1))
|
127
|
+
|
128
|
+
(defmacro length (arr)
|
129
|
+
(macros.get arr "\"length\""))
|
130
|
+
|
131
|
+
(defmacro last (arr)
|
132
|
+
(macros.get (macros.send arr 'slice -1) 0))
|
133
|
+
|
134
|
+
(defmacro if (arg truebody falsebody)
|
135
|
+
(concat
|
136
|
+
"(function() {"
|
137
|
+
(indent (concat
|
138
|
+
"if (" (translate arg) ") {"
|
139
|
+
(indent (macros.progn truebody))
|
140
|
+
"} else {"
|
141
|
+
(indent (macros.progn falsebody))
|
142
|
+
"}"))
|
143
|
+
"})()"))
|
144
|
+
|
145
|
+
(defmacro defvar (&rest pairs)
|
146
|
+
(as-statement
|
147
|
+
(concat "var "
|
148
|
+
(join ",\n "
|
149
|
+
(bulk-map pairs
|
150
|
+
(lambda (name value)
|
151
|
+
(concat (translate name) " = "
|
152
|
+
(translate value)))))
|
153
|
+
";")))
|
154
|
+
|
155
|
+
(defmacro = (first-thing &rest other-things)
|
156
|
+
(defvar translated-first-thing (translate first-thing))
|
157
|
+
(concat "("
|
158
|
+
(join " &&\n "
|
159
|
+
(map other-things
|
160
|
+
(lambda (thing)
|
161
|
+
(concat translated-first-thing
|
162
|
+
" === "
|
163
|
+
(translate thing)))))
|
164
|
+
")"))
|
165
|
+
|
166
|
+
|
167
|
+
(defmacro string? (thing)
|
168
|
+
(concat "typeof(" (translate thing) ") === \"string\""))
|
169
|
+
|
170
|
+
(defmacro list? (thing)
|
171
|
+
(defvar translated (concat "(" (translate thing) ")"))
|
172
|
+
(concat translated " && "
|
173
|
+
translated ".constructor.name === \"Array\""))
|
174
|
+
|
175
|
+
|
176
|
+
(defmacro when (arg &rest body)
|
177
|
+
(concat
|
178
|
+
"(function() {"
|
179
|
+
(indent (concat
|
180
|
+
"if (" (translate arg) ") {"
|
181
|
+
(indent (apply macros.progn body))
|
182
|
+
"}"))
|
183
|
+
"})()"))
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
(defmacro not (exp)
|
188
|
+
(concat "(!" (translate exp) ")"))
|
189
|
+
|
190
|
+
(defmacro slice (arr start &optional end)
|
191
|
+
(macros.send (translate arr) "slice" start end))
|
192
|
+
|
193
|
+
(defmacro inspect (&rest args)
|
194
|
+
(join " + \"\\n\" + "
|
195
|
+
(map args
|
196
|
+
(lambda (arg)
|
197
|
+
(concat "\"" arg ":\" + " (translate arg))))))
|
198
|
+
|
199
|
+
(defmacro each (item array &rest body)
|
200
|
+
(macros.send (translate array) 'for-each
|
201
|
+
(apply macros.lambda (cons item body))))
|
202
|
+
|
203
|
+
|
204
|
+
(defmacro setf (&rest args)
|
205
|
+
(join "\n"
|
206
|
+
(bulk-map args (lambda (name value)
|
207
|
+
(as-statement (concat (translate name) " = "
|
208
|
+
(translate value)))))))
|
209
|
+
|
210
|
+
|
211
|
+
(defmacro macro-list ()
|
212
|
+
(concat "["
|
213
|
+
(indent (join ",\n"
|
214
|
+
(map (-object.keys macros)
|
215
|
+
macros.quote)))
|
216
|
+
"]"))
|
217
|
+
|
218
|
+
(defmacro macroexpand (name)
|
219
|
+
(defvar macro (get macros (translate name)))
|
220
|
+
(if macro
|
221
|
+
(concat "// macro: " name "\n" (send macro to-string))
|
222
|
+
"undefined"))
|
223
|
+
|
224
|
+
(defmacro throw (&rest string)
|
225
|
+
(concat "throw new Error (" (join " " (map string translate)) ")"))
|
226
|
+
|
227
|
+
(defmacro as-boolean (expr)
|
228
|
+
(concat "(!!(" (translate expr) "))"))
|
229
|
+
|
230
|
+
(defmacro chain (object &rest calls)
|
231
|
+
(concat (translate object) " // chain"
|
232
|
+
(indent (join "\n"
|
233
|
+
(map calls
|
234
|
+
(lambda (call, index)
|
235
|
+
(defvar method (first call))
|
236
|
+
(defvar args (rest call))
|
237
|
+
(concat "." (translate method)
|
238
|
+
"(" (join ", " (map args translate)) ")")))))))
|
239
|
+
|
240
|
+
(defmacro try (tryblock catchblock)
|
241
|
+
(concat
|
242
|
+
"(function() {"
|
243
|
+
(indent (concat
|
244
|
+
"try {"
|
245
|
+
(indent (macros.progn tryblock))
|
246
|
+
"} catch (e) {"
|
247
|
+
(indent (macros.progn catchblock))
|
248
|
+
"}"))
|
249
|
+
"})()"))
|
250
|
+
|
251
|
+
|
252
|
+
(defmacro while (condition &rest block)
|
253
|
+
(macros.scoped
|
254
|
+
(macros.defvar '**return-value**)
|
255
|
+
(concat "while (" (translate condition) ") {"
|
256
|
+
(indent (macros.setf '**return-value**
|
257
|
+
(apply macros.scoped block))))
|
258
|
+
"}"
|
259
|
+
'**return-value**))
|
260
|
+
|
261
|
+
(defmacro until (condition &rest block)
|
262
|
+
(apply (get macros 'while)
|
263
|
+
(cons ['not condition] block)))
|
264
|
+
|
265
|
+
|
266
|
+
(defmacro thunk (&rest args)
|
267
|
+
(apply macros.lambda (cons [] args)))
|
268
|
+
|
269
|
+
(defmacro keys (obj)
|
270
|
+
(macros.call "Object.keys" (translate obj)))
|
271
|
+
|
272
|
+
(defmacro delete (&rest objects)
|
273
|
+
(join "\n" (map objects (lambda (obj)
|
274
|
+
(concat "delete " (translate obj) ";")))))
|
275
|
+
|
276
|
+
(defmacro delmacro (macro-name)
|
277
|
+
(delete (get macros (translate macro-name)))
|
278
|
+
"")
|
279
|
+
|
280
|
+
(defmacro alias-macro (current-macro-name desired-macro-name)
|
281
|
+
(defvar current-macro-name (translate current-macro-name)
|
282
|
+
desired-macro-name (translate desired-macro-name))
|
283
|
+
(set macros desired-macro-name (get macros current-macro-name))
|
284
|
+
"")
|
285
|
+
|
286
|
+
(defmacro rename-macro (current-macro-name desired-macro-name)
|
287
|
+
(macros.alias-macro current-macro-name desired-macro-name)
|
288
|
+
(macros.delmacro current-macro-name)
|
289
|
+
"")
|
290
|
+
|
291
|
+
(defmacro defhash (name &rest pairs)
|
292
|
+
(macros.defvar name (apply macros.hash pairs)))
|
293
|
+
|
294
|
+
(defmacro arguments ()
|
295
|
+
"(Array.prototype.slice.apply(arguments))")
|
296
|
+
|
297
|
+
(defmacro scoped (&rest body)
|
298
|
+
(macros.call (apply macros.thunk body)))
|
299
|
+
|
300
|
+
(defmacro each-key (as obj &rest body)
|
301
|
+
(concat "(function() {"
|
302
|
+
(indent
|
303
|
+
(concat "for (var " (translate as) " in " (translate obj) ") "
|
304
|
+
(apply macros.scoped body)
|
305
|
+
";"))
|
306
|
+
"})();"))
|
307
|
+
|
308
|
+
(defmacro match? (regexp string)
|
309
|
+
(macros.send string 'match regexp))
|
310
|
+
|
311
|
+
(defmacro switch (obj &rest cases)
|
312
|
+
|
313
|
+
;; the complexity of this macro indicates there's a problem
|
314
|
+
;; I'm not quite sure where to fix this, but it has to do with quoting.
|
315
|
+
(defvar lines (list (concat "switch(" (translate obj) ") {")))
|
316
|
+
(each (case-def) cases
|
317
|
+
(defvar case-name (first case-def))
|
318
|
+
(when (and (list? case-name)
|
319
|
+
(= (first case-name) 'quote))
|
320
|
+
(defvar second (second case-name))
|
321
|
+
(setf case-name (if (list? second)
|
322
|
+
(map second macros.quote)
|
323
|
+
(macros.quote second))))
|
324
|
+
|
325
|
+
(defvar case-string
|
326
|
+
(if (list? case-name)
|
327
|
+
(join "\n" (map case-name (lambda (c)
|
328
|
+
(concat "case " (translate c) ":"))))
|
329
|
+
(if (= 'default case-name) "default:"
|
330
|
+
(concat "case " (translate case-name) ":"))))
|
331
|
+
|
332
|
+
(lines.push (concat case-string
|
333
|
+
(indent (apply macros.progn (case-def.slice 1))))))
|
334
|
+
|
335
|
+
;; the following two lines are to get the whitespace right
|
336
|
+
;; this is necessary because switches are indented weird
|
337
|
+
(set lines (- lines.length 1)
|
338
|
+
(chain (get lines (- lines.length 1)) (concat "}")))
|
339
|
+
|
340
|
+
(concat "(function() {" (apply indent lines) "})()"))
|
341
|
+
|
342
|
+
|
343
|
+
(defmacro if-else (&rest args)
|
344
|
+
(concat "(function() {"
|
345
|
+
(indent
|
346
|
+
(join " else "
|
347
|
+
(bulk-map args
|
348
|
+
(lambda (cond val)
|
349
|
+
(if (undefined? val)
|
350
|
+
(concat "{" (indent (macros.progn cond)) "}")
|
351
|
+
(concat "if (" (translate cond) ") {"
|
352
|
+
(indent (macros.progn val))
|
353
|
+
"}"))))))
|
354
|
+
"})()"))
|
355
|
+
|
356
|
+
(defmacro let (args &optional body)
|
357
|
+
(concat "let (" (bulk-map args
|
358
|
+
(lambda (h k v)
|
359
|
+
(concat (translate k) " = " (translate v))))
|
360
|
+
(if (undefined? body) ");"
|
361
|
+
(concat ") {" (indent (translate body)) "}"))))
|
362
|
+
|
363
|
+
(defmacro instance-of? (item type)
|
364
|
+
(concat "(" (translate item) " instanceof " (translate type) ")"))
|
365
|
+
|
366
|
+
(defmacro slice (list &optional begin &optional end)
|
367
|
+
(concat "Array.prototype.slice.call(" (translate list)
|
368
|
+
", " (or (translate begin) 0)
|
369
|
+
(if (defined? end) (concat ", " (translate end) ")") ")")))
|
370
|
+
|
371
|
+
(defmacro ternary (cond if-true if-false)
|
372
|
+
(concat "(" (translate cond) ") ? "
|
373
|
+
(translate if-true) " : "
|
374
|
+
(translate if-false)))
|