sibilant 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/jbr/sibilant.png?branch=master)](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)))
|