clementine 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/.gitignore +1 -0
- data/Gemfile +4 -2
- data/LICENSE.txt +22 -0
- data/README.md +11 -6
- data/Rakefile +22 -0
- data/clementine.gemspec +2 -1
- data/ext/clojure-clojurescript-bef56a7/.gitignore +13 -0
- data/ext/clojure-clojurescript-bef56a7/Clojurescript.iml +12 -0
- data/ext/clojure-clojurescript-bef56a7/README.md +29 -0
- data/ext/clojure-clojurescript-bef56a7/benchmark/cljs/benchmark_runner.cljs +155 -0
- data/ext/clojure-clojurescript-bef56a7/bin/cljsc +21 -0
- data/ext/clojure-clojurescript-bef56a7/bin/cljsc.bat +18 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/bin/cljsc.clj +0 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/README.org +35 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/bcrepl.org +13 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/cljs.org +500 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/corelib.org +583 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/day1.org +203 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/day2.org +44 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/talk.org +126 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/testing +13 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/todo.org +121 -0
- data/ext/clojure-clojurescript-bef56a7/epl-v10.html +261 -0
- data/ext/clojure-clojurescript-bef56a7/pom.template.xml +88 -0
- data/ext/clojure-clojurescript-bef56a7/samples/dom/.gitignore +2 -0
- data/ext/clojure-clojurescript-bef56a7/samples/dom/src/dom/test.cljs +48 -0
- data/ext/clojure-clojurescript-bef56a7/samples/dom/test.html +30 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/.gitignore +2 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/README.md +53 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/externed-lib.js +7 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/externs.js +3 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-extern.html +14 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-js-dev.html +18 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-js.html +17 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/my-external-lib.js +3 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/src/hello-js/core.cljs +9 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/src/hello-js/extern-example.cljs +5 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/.gitignore +2 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/README.md +34 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/hello-dev.html +18 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/hello.html +13 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/src/hello/core.cljs +8 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/src/hello/foo/bar.cljs +4 -0
- data/ext/clojure-clojurescript-bef56a7/samples/nodehello.cljs +18 -0
- data/ext/clojure-clojurescript-bef56a7/samples/nodels.cljs +17 -0
- data/ext/clojure-clojurescript-bef56a7/samples/repl/.gitignore +2 -0
- data/ext/clojure-clojurescript-bef56a7/samples/repl/README.md +101 -0
- data/ext/clojure-clojurescript-bef56a7/samples/repl/index.html +27 -0
- data/ext/clojure-clojurescript-bef56a7/samples/repl/src/repl/test.cljs +73 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/.gitignore +2 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/README.md +42 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/index-advanced.html +80 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/index.html +88 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/reset.css +48 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/anneal.cljs +66 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/core.cljs +307 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/dom-helpers.cljs +95 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/layout.cljs +100 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/leaderboard.cljs +40 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/radial.cljs +91 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/showgraph.cljs +121 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/timeline.cljs +39 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/style.css +301 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/test_data.txt +1 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/tweet_maps.txt +1 -0
- data/ext/clojure-clojurescript-bef56a7/script/benchmark +30 -0
- data/ext/clojure-clojurescript-bef56a7/script/bootstrap +70 -0
- data/ext/clojure-clojurescript-bef56a7/script/browser-repl +16 -0
- data/ext/clojure-clojurescript-bef56a7/script/build +59 -0
- data/ext/clojure-clojurescript-bef56a7/script/clean +5 -0
- data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/google-closure-library-third-party.pom.template +59 -0
- data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/google-closure-library.pom.template +54 -0
- data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/make-closure-library-jars.sh +87 -0
- data/ext/clojure-clojurescript-bef56a7/script/compile +41 -0
- data/ext/clojure-clojurescript-bef56a7/script/repl +13 -0
- data/ext/clojure-clojurescript-bef56a7/script/repl.bat +13 -0
- data/ext/clojure-clojurescript-bef56a7/script/repljs +15 -0
- data/ext/clojure-clojurescript-bef56a7/script/repljs.bat +14 -0
- data/ext/clojure-clojurescript-bef56a7/script/test +38 -0
- data/ext/clojure-clojurescript-bef56a7/script/test-compile +30 -0
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/analyzer.clj +975 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/closure.clj +173 -73
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/compiler.clj +1081 -0
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/core.clj +1158 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/repl.clj +51 -25
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/browser.clj +258 -0
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/reflect.clj +75 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/repl/rhino.clj +6 -5
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/server.clj +173 -0
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/tagged_literals.clj +30 -0
- data/ext/clojure-clojurescript-bef56a7/src/cljs/cljs/core.cljs +7197 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejs.cljs +1 -1
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejs_externs.js +0 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejscli.cljs +1 -1
- data/ext/clojure-clojurescript-bef56a7/src/cljs/cljs/reader.cljs +551 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/dom.cljs +59 -13
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/event.cljs +0 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/net.cljs +8 -7
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/repl.cljs +2 -2
- data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/core/reducers.cljs +298 -0
- data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/data.cljs +162 -0
- data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/reflect.cljs +48 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/set.cljs +0 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/string.cljs +4 -10
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/walk.cljs +0 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/zip.cljs +0 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/binding_test.cljs +7 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/binding_test_other_ns.cljs +3 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/core_test.cljs +1678 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/import_test.cljs +11 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/import_test/foo.cljs +5 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/letfn_test.cljs +19 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/macro_test.cljs +6 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/macro_test/macros.clj +5 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test.cljs +14 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test/bar.cljs +3 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test/foo.cljs +7 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/reader_test.cljs +124 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/clojure/data_test.cljs +22 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/clojure/string_test.cljs +97 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/foo/ns_shadow_test.cljs +9 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/test_runner.cljs +26 -0
- data/lib/clementine.rb +3 -24
- data/lib/clementine/clojurescript_engine.rb +9 -48
- data/lib/clementine/clojurescript_engine/base.rb +15 -0
- data/lib/clementine/clojurescript_engine/jruby.rb +46 -0
- data/lib/clementine/{clojurescript_engine_mri.rb → clojurescript_engine/mri.rb} +17 -10
- data/lib/clementine/version.rb +1 -1
- data/test/clojurescript_engine_test.rb +36 -14
- metadata +177 -83
- data/vendor/assets/lib/clojure.jar +0 -0
- data/vendor/assets/lib/compiler.jar +0 -0
- data/vendor/assets/lib/goog.jar +0 -0
- data/vendor/assets/lib/js.jar +0 -0
- data/vendor/assets/src/clj/cljs/compiler.clj +0 -1341
- data/vendor/assets/src/clj/cljs/core.clj +0 -702
- data/vendor/assets/src/clj/cljs/repl/browser.clj +0 -341
- data/vendor/assets/src/cljs/cljs/core.cljs +0 -3330
- data/vendor/assets/src/cljs/cljs/reader.cljs +0 -360
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2011 - 2012 Yoko Harada
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
|
@@ -19,13 +19,8 @@ Clementine supports JRuby and CRuby. When you use from CRuby, make sure java com
|
|
|
19
19
|
Installation
|
|
20
20
|
-----------
|
|
21
21
|
|
|
22
|
-
Clone https://github.com/yokolet/clementine, then
|
|
23
|
-
edit your Gemfile with specific path to Clemetine.
|
|
24
|
-
|
|
25
|
-
For example:
|
|
26
|
-
|
|
27
22
|
```ruby
|
|
28
|
-
gem
|
|
23
|
+
gem install clementine
|
|
29
24
|
```
|
|
30
25
|
|
|
31
26
|
Configuration
|
|
@@ -50,3 +45,13 @@ Available options:
|
|
|
50
45
|
:output_dir directory name (:output_dir will be converted to ":output-dir")
|
|
51
46
|
:output_to file name (:output_to will be converted to ":output-to")
|
|
52
47
|
```
|
|
48
|
+
|
|
49
|
+
Copyright and License
|
|
50
|
+
-----------
|
|
51
|
+
Clementine is Copyright (c) 2011-2012 [Yoko Harada](https://github.com/yokolet) and
|
|
52
|
+
distributed under the MIT license.
|
|
53
|
+
|
|
54
|
+
Clojure and ClojureSript are Copyright (c) Rich Hickey and covered by the Eclipse
|
|
55
|
+
Public License 1.0 [http://opensource.org/licenses/eclipse-1.0.php](http://opensource.org/licenses/eclipse-1.0.php)
|
|
56
|
+
|
|
57
|
+
Google Closure Compiler and Library are covered by Apache License 2.0 license.
|
data/Rakefile
CHANGED
|
@@ -1 +1,23 @@
|
|
|
1
1
|
require "bundler/gem_tasks"
|
|
2
|
+
require 'rake/testtask'
|
|
3
|
+
|
|
4
|
+
task :default => :bootstrap
|
|
5
|
+
|
|
6
|
+
task :bootstrap do
|
|
7
|
+
# clojurescript home
|
|
8
|
+
CLOJURESCRIPT_HOME = File.join(File.dirname(__FILE__), "ext/clojure-clojurescript-bef56a7")
|
|
9
|
+
|
|
10
|
+
$stdout.print "Bootrapping ClojureScript"
|
|
11
|
+
|
|
12
|
+
# command to download and create jar archives
|
|
13
|
+
cmd = "#{CLOJURESCRIPT_HOME}/script/bootstrap"
|
|
14
|
+
%x( #{cmd} )
|
|
15
|
+
|
|
16
|
+
# removes unnecessary temporary directory to create google closure jar archives
|
|
17
|
+
require 'fileutils'
|
|
18
|
+
FileUtils.rm_rf File.join(File.dirname(__FILE__), './closure')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Rake::TestTask.new do |t|
|
|
22
|
+
t.pattern = "test/*_test.rb"
|
|
23
|
+
end
|
data/clementine.gemspec
CHANGED
|
@@ -11,7 +11,8 @@ Gem::Specification.new do |s|
|
|
|
11
11
|
s.summary = %q{clojurescript tilt template gem}
|
|
12
12
|
s.description = %q{clojurescript tilt template gem and available to use on Rails asset pipeline.}
|
|
13
13
|
|
|
14
|
-
s.files = `git ls-files`.split(
|
|
14
|
+
s.files = `git ls-files`.split($/)
|
|
15
|
+
s.extensions = ['Rakefile']
|
|
15
16
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
16
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
17
18
|
s.require_paths = ["lib"]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<module type="JAVA_MODULE" version="4">
|
|
3
|
+
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
4
|
+
<exclude-output />
|
|
5
|
+
<content url="file://$MODULE_DIR$">
|
|
6
|
+
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
|
7
|
+
</content>
|
|
8
|
+
<orderEntry type="inheritedJdk" />
|
|
9
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
|
10
|
+
</component>
|
|
11
|
+
</module>
|
|
12
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
## What is ClojureScript? ##
|
|
2
|
+
|
|
3
|
+
ClojureScript is a new compiler for [Clojure](http://clojure.org) that targets JavaScript. It is designed to emit JavaScript code which is compatible with the advanced compilation mode of the [Google Closure](http://code.google.com/closure/) optimizing compiler.
|
|
4
|
+
|
|
5
|
+
## Getting Started ##
|
|
6
|
+
|
|
7
|
+
* [Compare with JavaScript](http://himera.herokuapp.com/synonym.html)
|
|
8
|
+
* [Try it online](http://himera.herokuapp.com/index.html)
|
|
9
|
+
* Read the [Quick Start](https://github.com/clojure/clojurescript/wiki/Quick-Start) guide.
|
|
10
|
+
* Read the [Documentation](https://github.com/clojure/clojurescript/wiki).
|
|
11
|
+
* Look at the [Sample Applications](https://github.com/clojure/clojurescript/tree/master/samples).
|
|
12
|
+
|
|
13
|
+
## Questions, Feedback? ##
|
|
14
|
+
|
|
15
|
+
Please point all of your questions and feedback [here](http://groups.google.com/group/clojure).
|
|
16
|
+
|
|
17
|
+
## Developers Welcome ##
|
|
18
|
+
|
|
19
|
+
ClojureScript operates under the same license as Clojure. All contributors must have a signed CA (Contributor's Agreement) and submit their patch via the appropriate channels. If you're interested in contributing to the project, please see the [contributing](http://clojure.org/contributing) page on [clojure.org](http://clojure.org).
|
|
20
|
+
|
|
21
|
+
## License ##
|
|
22
|
+
|
|
23
|
+
Copyright (c) Rich Hickey. All rights reserved. The use and
|
|
24
|
+
distribution terms for this software are covered by the Eclipse
|
|
25
|
+
Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
|
26
|
+
which can be found in the file epl-v10.html at the root of this
|
|
27
|
+
distribution. By using this software in any fashion, you are
|
|
28
|
+
agreeing to be bound by the terms of this license. You must
|
|
29
|
+
not remove this notice, or any other, from this software.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
(ns cljs.benchmark-runner
|
|
2
|
+
(:refer-clojure :exclude [println])
|
|
3
|
+
(:require [cljs.reader :as reader]))
|
|
4
|
+
|
|
5
|
+
(def println print)
|
|
6
|
+
|
|
7
|
+
(set! *print-fn* js/print)
|
|
8
|
+
|
|
9
|
+
(simple-benchmark [x 1] (identity x) 1000000)
|
|
10
|
+
|
|
11
|
+
(println ";; array-reduce & ci-reduce")
|
|
12
|
+
(def arr (let [arr (array)]
|
|
13
|
+
(dotimes [i 1000000]
|
|
14
|
+
(.push arr i))
|
|
15
|
+
arr))
|
|
16
|
+
(defn sum [a b] (+ a b))
|
|
17
|
+
(simple-benchmark [coll (seq arr)] (ci-reduce coll + 0) 1)
|
|
18
|
+
(simple-benchmark [coll (seq arr)] (ci-reduce coll sum 0) 1)
|
|
19
|
+
(simple-benchmark [coll arr] (array-reduce coll + 0) 1)
|
|
20
|
+
(simple-benchmark [coll arr] (array-reduce coll sum 0) 1)
|
|
21
|
+
|
|
22
|
+
(println ";;; instance?")
|
|
23
|
+
;; WARNING: will get compiled away under advanced
|
|
24
|
+
(simple-benchmark [coll []] (instance? PersistentVector coll) 1000000)
|
|
25
|
+
(println ";;; satisfies?")
|
|
26
|
+
(simple-benchmark [coll (list 1 2 3)] (satisfies? ISeq coll) 1000000)
|
|
27
|
+
(simple-benchmark [coll [1 2 3]] (satisfies? ISeq coll) 1000000)
|
|
28
|
+
(println)
|
|
29
|
+
|
|
30
|
+
(println ";;; list ops")
|
|
31
|
+
(simple-benchmark [coll (list 1 2 3)] (first coll) 1000000)
|
|
32
|
+
(simple-benchmark [coll (list 1 2 3)] (-first coll) 1000000)
|
|
33
|
+
(simple-benchmark [coll (list 1 2 3)] (rest coll) 1000000)
|
|
34
|
+
(simple-benchmark [coll (list 1 2 3)] (-rest coll) 1000000)
|
|
35
|
+
(simple-benchmark [] (list) 1000000)
|
|
36
|
+
(simple-benchmark [] (list 1 2 3) 1000000)
|
|
37
|
+
(println)
|
|
38
|
+
|
|
39
|
+
(println ";;; vector ops")
|
|
40
|
+
(simple-benchmark [] [] 1000000)
|
|
41
|
+
(simple-benchmark [] [1 2 3] 1000000)
|
|
42
|
+
(simple-benchmark [coll [1 2 3]] (transient coll) 100000)
|
|
43
|
+
(simple-benchmark [coll [1 2 3]] (nth coll 0) 1000000)
|
|
44
|
+
(simple-benchmark [coll [1 2 3]] (-nth coll 0) 1000000)
|
|
45
|
+
(simple-benchmark [coll [1 2 3]] (conj coll 4) 1000000)
|
|
46
|
+
(simple-benchmark [coll [1 2 3]] (-conj coll 4) 1000000)
|
|
47
|
+
(simple-benchmark [coll [1 2 3]] (seq coll) 1000000)
|
|
48
|
+
(simple-benchmark [coll (seq [1 2 3])] (first coll) 1000000)
|
|
49
|
+
(simple-benchmark [coll (seq [1 2 3])] (-first coll) 1000000)
|
|
50
|
+
(simple-benchmark [coll (seq [1 2 3])] (rest coll) 1000000)
|
|
51
|
+
(simple-benchmark [coll (seq [1 2 3])] (-rest coll) 1000000)
|
|
52
|
+
(simple-benchmark [coll (seq [1 2 3])] (next coll) 1000000)
|
|
53
|
+
(println)
|
|
54
|
+
|
|
55
|
+
(println ";;; large vector ops")
|
|
56
|
+
(simple-benchmark [] (reduce conj [] (range 40000)) 10)
|
|
57
|
+
(simple-benchmark [coll (reduce conj [] (range (+ 32768 32)))] (conj coll :foo) 100000)
|
|
58
|
+
(simple-benchmark [coll (reduce conj [] (range 40000))] (assoc coll 123 :foo) 100000)
|
|
59
|
+
(simple-benchmark [coll (reduce conj [] (range (+ 32768 33)))] (pop coll) 100000)
|
|
60
|
+
(println)
|
|
61
|
+
|
|
62
|
+
(println ";;; transients")
|
|
63
|
+
(print "transient vector, conj! 1000000 items")
|
|
64
|
+
(time
|
|
65
|
+
(let [v (transient [])]
|
|
66
|
+
(loop [i 0 v v]
|
|
67
|
+
(if (> i 1000000)
|
|
68
|
+
(persistent! v)
|
|
69
|
+
(recur (inc i) (conj! v i))))))
|
|
70
|
+
|
|
71
|
+
(println ";;; reduce lazy-seqs, vectors, ranges")
|
|
72
|
+
(simple-benchmark [coll (take 100000 (iterate inc 0))] (reduce + 0 coll) 1)
|
|
73
|
+
(simple-benchmark [coll (range 1000000)] (reduce + 0 coll) 1)
|
|
74
|
+
(simple-benchmark [coll (into [] (range 1000000))] (reduce + 0 coll) 1)
|
|
75
|
+
(println)
|
|
76
|
+
|
|
77
|
+
(println ";; apply")
|
|
78
|
+
(simple-benchmark [coll (into [] (range 1000000))] (apply + coll) 1)
|
|
79
|
+
(println)
|
|
80
|
+
|
|
81
|
+
(println ";;; map / record ops")
|
|
82
|
+
(simple-benchmark [coll {:foo 1 :bar 2}] (get coll :foo) 1000000)
|
|
83
|
+
(simple-benchmark [coll {:foo 1 :bar 2}] (-lookup coll :foo nil) 1000000)
|
|
84
|
+
(simple-benchmark [coll {:foo 1 :bar 2}] (:foo coll) 1000000)
|
|
85
|
+
(defrecord Foo [bar baz])
|
|
86
|
+
(simple-benchmark [coll (Foo. 1 2)] (:bar coll) 1000000)
|
|
87
|
+
(simple-benchmark [coll {:foo 1 :bar 2}] (assoc coll :baz 3) 100000)
|
|
88
|
+
(simple-benchmark [coll {:foo 1 :bar 2}] (assoc coll :foo 2) 100000)
|
|
89
|
+
(simple-benchmark [coll {:foo 1 :bar 2}]
|
|
90
|
+
(loop [i 0 m coll]
|
|
91
|
+
(if (< i 100000)
|
|
92
|
+
(recur (inc i) (assoc m :foo 2))
|
|
93
|
+
m))
|
|
94
|
+
1)
|
|
95
|
+
(println ";;; persistent hash maps")
|
|
96
|
+
(def pmap (into cljs.core.PersistentHashMap/EMPTY
|
|
97
|
+
[[:a 0] [:b 1] [:c 2] [:d 3] [:e 4] [:f 5] [:g 6] [:h 7]
|
|
98
|
+
[:i 8] [:j 9] [:k 10] [:l 11] [:m 12] [:n 13] [:o 14] [:p 15]
|
|
99
|
+
[:q 16] [:r 17] [:s 18] [:t 19] [:u 20] [:v 21] [:w 22] [:x 23]
|
|
100
|
+
[:y 24] [:z 25] [:a0 26] [:b0 27] [:c0 28] [:d0 29] [:e0 30] [:f0 31]]))
|
|
101
|
+
(simple-benchmark [key :f0] (hash key) 1000000)
|
|
102
|
+
(simple-benchmark [key :unsynchronized-mutable] (hash key false) 1000000)
|
|
103
|
+
(simple-benchmark [key :unsynchronized-mutable] (hash key) 1000000)
|
|
104
|
+
(def hash-coll-test
|
|
105
|
+
(loop [i 0 r []]
|
|
106
|
+
(if (< i 1000)
|
|
107
|
+
(recur (inc i) (conj r (str "foo" i)))
|
|
108
|
+
r)))
|
|
109
|
+
(simple-benchmark [coll hash-coll-test] (hash-coll coll) 100)
|
|
110
|
+
(simple-benchmark [coll pmap] (:f0 coll) 1000000)
|
|
111
|
+
(simple-benchmark [coll pmap] (get coll :f0) 1000000)
|
|
112
|
+
(simple-benchmark [coll pmap] (-lookup coll :f0 nil) 1000000)
|
|
113
|
+
(simple-benchmark [coll pmap] (assoc coll :g0 32) 1000000)
|
|
114
|
+
(simple-benchmark [coll pmap]
|
|
115
|
+
(loop [i 0 m coll]
|
|
116
|
+
(if (< i 1000000)
|
|
117
|
+
(recur (inc i) (assoc m :a 1))
|
|
118
|
+
m))
|
|
119
|
+
1)
|
|
120
|
+
(simple-benchmark [coll cljs.core.PersistentHashMap/EMPTY] (assoc coll :f0 1) 1000000)
|
|
121
|
+
(println)
|
|
122
|
+
|
|
123
|
+
(println ";;; set ops")
|
|
124
|
+
(simple-benchmark [] #{} 100000)
|
|
125
|
+
(simple-benchmark [] #{1 2 3} 100000)
|
|
126
|
+
(simple-benchmark [coll #{1 2 3}] (conj coll 4) 100000)
|
|
127
|
+
(println)
|
|
128
|
+
|
|
129
|
+
(println ";;; seq ops")
|
|
130
|
+
(simple-benchmark [coll (range 500000)] (reduce + coll) 1)
|
|
131
|
+
(println)
|
|
132
|
+
|
|
133
|
+
(println ";;; reader")
|
|
134
|
+
(simple-benchmark [s "{:foo [1 2 3]}"] (reader/read-string s) 1000)
|
|
135
|
+
(println)
|
|
136
|
+
|
|
137
|
+
(println ";;; range")
|
|
138
|
+
(simple-benchmark [r (range 1000000)] (last r) 1)
|
|
139
|
+
(println)
|
|
140
|
+
|
|
141
|
+
(defn ints-seq
|
|
142
|
+
([n] (ints-seq 0 n))
|
|
143
|
+
([i n]
|
|
144
|
+
(when (< i n)
|
|
145
|
+
(lazy-seq
|
|
146
|
+
(cons i (ints-seq (inc i) n))))))
|
|
147
|
+
(def r (ints-seq 1000000))
|
|
148
|
+
(println ";;; lazy-seq")
|
|
149
|
+
(println ";;; first run")
|
|
150
|
+
(simple-benchmark [r r] (last r) 1)
|
|
151
|
+
(println ";;; second run")
|
|
152
|
+
(simple-benchmark [r r] (last r) 1)
|
|
153
|
+
(println)
|
|
154
|
+
|
|
155
|
+
(println "\n")
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
|
|
3
|
+
# Compile a single cljs file or a directory of cljs files into a
|
|
4
|
+
# single JavaScript file.
|
|
5
|
+
|
|
6
|
+
if [ "$CLOJURESCRIPT_HOME" = "" ]; then
|
|
7
|
+
CLOJURESCRIPT_HOME="`dirname $0`/.."
|
|
8
|
+
fi
|
|
9
|
+
|
|
10
|
+
CLJSC_CP=''
|
|
11
|
+
for next in lib/*: src/clj: src/cljs: test/cljs; do
|
|
12
|
+
CLJSC_CP="${CLJSC_CP}${CLOJURESCRIPT_HOME}/${next}"
|
|
13
|
+
done
|
|
14
|
+
|
|
15
|
+
if test "$#" -eq 0
|
|
16
|
+
then
|
|
17
|
+
echo 'Usage: cljsc <file-or-dir>'
|
|
18
|
+
echo ' cljsc <file-or-dir> "{:optimizations :advanced}"'
|
|
19
|
+
else
|
|
20
|
+
java -server -cp "$CLJSC_CP" clojure.main "$CLOJURESCRIPT_HOME/bin/cljsc.clj" "$@"
|
|
21
|
+
fi
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
@echo off
|
|
3
|
+
setLocal EnableDelayedExpansion
|
|
4
|
+
|
|
5
|
+
if "%CLOJURESCRIPT_HOME%" == "" set CLOJURESCRIPT_HOME=%~dp0..\
|
|
6
|
+
|
|
7
|
+
set CLASSPATH=%CLOJURESCRIPT_HOME%src\clj;%CLOJURESCRIPT_HOME%src\cljs"
|
|
8
|
+
for /R "%CLOJURESCRIPT_HOME%\lib" %%a in (*.jar) do (
|
|
9
|
+
set CLASSPATH=!CLASSPATH!;%%a
|
|
10
|
+
)
|
|
11
|
+
set CLASSPATH=!CLASSPATH!"
|
|
12
|
+
|
|
13
|
+
if (%1) == () (
|
|
14
|
+
echo Usage: "cljsc <file-or-dir> > out.js"
|
|
15
|
+
echo "cljsc <file-or-dir> {:optimiztions :advanced} > out.js"
|
|
16
|
+
) else (
|
|
17
|
+
java -server -cp "%CLASSPATH%" clojure.main "%CLOJURESCRIPT_HOME%\bin\cljsc.clj" %*
|
|
18
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
* ClojureScript
|
|
2
|
+
- What: Clojure running on Javascript VMs
|
|
3
|
+
- Why: Clojure rocks, Javascript reaches
|
|
4
|
+
- When: Now! - a compiler exists, we need libraries and tool integration. Full day sessions 6/10 and 6/17
|
|
5
|
+
- Where: In stealth mode 'here' at Clojure/core
|
|
6
|
+
- How: ClojureScript -> ClojureScript-Compiler -> Javascript -> [Google-Closure-JS->JS-Compiler -> Optimized-Javascript] ->Browser/V8/Node/PhoneGap...
|
|
7
|
+
- Who: You, if you're interested in:
|
|
8
|
+
- How hand-written recursive descent compilers work (the ClojureScript compiler is about 1/6 the code of the CoffeeScript compiler)
|
|
9
|
+
- Writing libraries using Clojure's latest type and polymorphism tools
|
|
10
|
+
- How Clojure works - its data structures and abstractions
|
|
11
|
+
- Extending the reach of Clojure
|
|
12
|
+
- Google's industrial-strength JS tools
|
|
13
|
+
- Investigating how powerful code-emitting tools can change the face
|
|
14
|
+
of web and mobile development...
|
|
15
|
+
* Getting Started
|
|
16
|
+
- Clone the repo
|
|
17
|
+
- cd clojurescript
|
|
18
|
+
- run script/bootstrap
|
|
19
|
+
- copy clojure.jar into /lib
|
|
20
|
+
- script/repl will start a properly-classpathed repl
|
|
21
|
+
* Starting the clojurescript repl
|
|
22
|
+
- (require '[cljs.compiler :as comp])
|
|
23
|
+
- (def jse (comp/repl-env))
|
|
24
|
+
- (comp/repl jse)
|
|
25
|
+
* Reading list
|
|
26
|
+
- If you are interested in participating, please read:
|
|
27
|
+
- [[http://www.amazon.com/Closure-Definitive-Guide-Michael-Bolin/dp/1449381871][Closure-Definitive-Guide-Michael-Bolin]]
|
|
28
|
+
- and maybe:
|
|
29
|
+
- [[http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742][JavaScript-Good-Parts-Douglas-Crockford]]
|
|
30
|
+
- [[http://www.amazon.com/Performance-JavaScript-Faster-Application-Interfaces/dp/059680279X][Performance-JavaScript-Faster-Application-Interfaces]]
|
|
31
|
+
- [[http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752][JavaScript-Patterns-Stoyan-Stefanov]]
|
|
32
|
+
- Those looking to cram tonight can get the O'Reilly Closure book on kindle above or ebook directly:
|
|
33
|
+
- [[http://oreilly.com/catalog/0636920001416/]]
|
|
34
|
+
* More info
|
|
35
|
+
[[https://github.com/relevance/clojurescript/wiki][Check the Wiki]]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
* ClojureScript browser connected REPL
|
|
2
|
+
** send cljs compiler output to the browser to be evaluated
|
|
3
|
+
** send results back to the command line process to be printed
|
|
4
|
+
** side effects happen in the browser
|
|
5
|
+
** abstract communication away using goog library
|
|
6
|
+
*** Goog abstraction for websockets? Ideal!
|
|
7
|
+
*** Polling? It will work everywhere.
|
|
8
|
+
*** Ideally an abstraction over both that prefers websockets but doesn't fail and doesn't complain loudly.
|
|
9
|
+
** evaluation daemon for the browser
|
|
10
|
+
** launch browser
|
|
11
|
+
** transparent update of bound symbols? We should test.
|
|
12
|
+
** brepl has its own solution for deps, we'd like to tie into the ClojureScript dependency story
|
|
13
|
+
** require mechanisms are out; the source that forms the repl's environment will need to be updated and the page reloaded
|
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
* ClojureScript
|
|
2
|
+
* Rationale
|
|
3
|
+
** What
|
|
4
|
+
*** Compiler that compiles (a subset of?) Clojure to Javascript
|
|
5
|
+
** Why?
|
|
6
|
+
*** Because js is the only universally available client target
|
|
7
|
+
**** and can't be supplanted due to its browser integration and installed base
|
|
8
|
+
**** yet isn't very good, expressive, concise, or robust
|
|
9
|
+
**** but JS engines continue to get lots of optimization love, and are now quite capable perf-wise
|
|
10
|
+
*** Use same skillset and libs for client and server
|
|
11
|
+
**** only other similar options are:
|
|
12
|
+
***** JS native client, JS (e.g. node) server
|
|
13
|
+
****** node still much less powerful than JVM, and might be a mere fad
|
|
14
|
+
***** Java (GWT) client, Java native server
|
|
15
|
+
****** GWT has lots of baggage due to semantic mismatches etc
|
|
16
|
+
****** but familiar tooling if already a Java dev
|
|
17
|
+
***** esoteric, open question as to skills and libs:
|
|
18
|
+
****** [[http://clamato.net/][Clamato Smalltalk]]
|
|
19
|
+
****** [[http://www.wescheme.org/][Moby Scheme]]
|
|
20
|
+
*** Clojure semantics can fit well on JS
|
|
21
|
+
**** i.e. defn/type/protocol won't fight with js core model
|
|
22
|
+
*** ClojureJS arguably becomes most powerful lang on client
|
|
23
|
+
**** Robust, simple Clojure model
|
|
24
|
+
**** Macros etc
|
|
25
|
+
*** Might be best way to run Clojure on mobile
|
|
26
|
+
*** js a possible path to delivering Clojure libs to C-linkage clients
|
|
27
|
+
**** via embedded Google V8 js engine
|
|
28
|
+
**** somewhat speculative, but considering for M
|
|
29
|
+
**** V8 wrappers exist for Python, Ruby, PHP etc
|
|
30
|
+
** How?
|
|
31
|
+
*** Compiler written in Clojure, generates (readable?) JS
|
|
32
|
+
*** Optionally run that JS through Google Closure js->js compiler
|
|
33
|
+
**** for minification, dead code elimination etc
|
|
34
|
+
*** Use Google Closure js library where needed for implementation support
|
|
35
|
+
**** e.g. goog.math has Long arithmetic
|
|
36
|
+
**** module system
|
|
37
|
+
**** use gclosure annotations for stronger type checking or better code gen?
|
|
38
|
+
**** dependency system
|
|
39
|
+
*** Macros written in Clojure proper, run by the compiler
|
|
40
|
+
**** stick to subset in macros if eval supported
|
|
41
|
+
*** Any runtime support written completely in itself
|
|
42
|
+
**** make deftype and protocols work early
|
|
43
|
+
** Non-objectives
|
|
44
|
+
*** complete Clojure
|
|
45
|
+
**** feel free to subset, especially at first
|
|
46
|
+
**** but try to make anything present in both work identically
|
|
47
|
+
*** compiling e.g. core.clj as-is
|
|
48
|
+
**** don't want to touch Clojure itself for this
|
|
49
|
+
**** bootstrap will differ anyway
|
|
50
|
+
** Ancillary benefits
|
|
51
|
+
*** Analysis component of compiler might serve Clojure-in-Clojure, or other tooling
|
|
52
|
+
**** maybe - we'll need far less analysis support in js than we do in Java
|
|
53
|
+
*** Boost for Clojure adoption due to increased reach
|
|
54
|
+
*** Power tool for exploring next-gen client approach
|
|
55
|
+
* Implementation
|
|
56
|
+
** Primitives
|
|
57
|
+
*** DONE def
|
|
58
|
+
*** fn*
|
|
59
|
+
**** DONE basics
|
|
60
|
+
**** DONE recur
|
|
61
|
+
**** DONE variable arity
|
|
62
|
+
**** DONE arity overloading
|
|
63
|
+
**** closures shouldn't map directly to js closures? - no, they should
|
|
64
|
+
***** they capture entire surrounding environment
|
|
65
|
+
****** hearsay, V8 already better
|
|
66
|
+
***** premature optimization to avoid that? - yes
|
|
67
|
+
***** shouldn't js engines do that for us? - yes
|
|
68
|
+
***** try goog.partial? - not for this
|
|
69
|
+
**** variable arity how?
|
|
70
|
+
***** switch on arguments.length
|
|
71
|
+
*** DONE if
|
|
72
|
+
**** need to match Clojure semantics (nil/false)
|
|
73
|
+
***** must deal with undefined (group with nil/false?)
|
|
74
|
+
*** DONE let*
|
|
75
|
+
**** must fix local scoping problem
|
|
76
|
+
***** nested fns or renaming?
|
|
77
|
+
**** let* semantics
|
|
78
|
+
*** DONE do
|
|
79
|
+
**** as with Java, not an expression
|
|
80
|
+
**** doFn(...) -> returns last arg
|
|
81
|
+
***** must alloc array for arguments?
|
|
82
|
+
*** TODO global
|
|
83
|
+
**** use 'var for this?
|
|
84
|
+
***** already Clojure special op
|
|
85
|
+
***** but wrong semantics, (var x) is *ns*-relative
|
|
86
|
+
***** no true unqualified globals in Clojure
|
|
87
|
+
*** DONE recur
|
|
88
|
+
**** to loop
|
|
89
|
+
**** to fn head
|
|
90
|
+
***** can't do in single pass
|
|
91
|
+
*** DONE invoke
|
|
92
|
+
*** DONE macros
|
|
93
|
+
*** DONE ns
|
|
94
|
+
**** (ns my.ns (:require your.ns ...) (:macros a-clojure-ns ...))
|
|
95
|
+
***** aliases?
|
|
96
|
+
**** =>
|
|
97
|
+
***** make a clojure ns? cljs.my.ns?
|
|
98
|
+
***** goog.provide('my.ns'); goog.require('your.ns');
|
|
99
|
+
***** (
|
|
100
|
+
*** DONE deftype*
|
|
101
|
+
**** maps to prototype/contructor combo
|
|
102
|
+
**** deftype macro is deftype* + extend-type
|
|
103
|
+
***** extend-type with ::fields meta on param vectors
|
|
104
|
+
*** TODO reify*
|
|
105
|
+
**** yes, for one-off protocol impls
|
|
106
|
+
**** no ctor created, just put impls on object
|
|
107
|
+
***** can share code with putting impls on prototype?
|
|
108
|
+
*** DONE defprotocol*
|
|
109
|
+
**** not primitive in Clojure proper
|
|
110
|
+
**** extend, when given ctor, modifies prototype with slot
|
|
111
|
+
***** slot is ns-qualified
|
|
112
|
+
***** what about core prototypes - Object, Array et al (String, Number, Boolean, Function)?
|
|
113
|
+
****** poor citizenship to modify these?
|
|
114
|
+
****** Object different in that it is used as map
|
|
115
|
+
****** nested window scope issues?
|
|
116
|
+
**** protocol fns just turn (my.ns/foo x a b c) into x["my.ns/foo"](a, b ,c)
|
|
117
|
+
***** foo(x, a, b, c)
|
|
118
|
+
****** must pass target
|
|
119
|
+
***** better - x.my$ns$foo(a, b ,c)
|
|
120
|
+
****** can be minified
|
|
121
|
+
*** DONE extend-type
|
|
122
|
+
*** defrecord?
|
|
123
|
+
**** any way to get (:foo x) => x.foo?
|
|
124
|
+
***** beware GClojure renaming
|
|
125
|
+
*** DONE new
|
|
126
|
+
**** what to do? ordinary invoke works fine
|
|
127
|
+
***** new could be aliased, not special form then
|
|
128
|
+
***** not ordinary - first arg not evaluated
|
|
129
|
+
****** but should be in JS since new is an operator on a function, not a name
|
|
130
|
+
**** new itself shouldn't be evaluated, won't pass fnOf
|
|
131
|
+
**** (my.ns.Blah. x y z) - just macroexpander stuff
|
|
132
|
+
**** (Blah. x y z) - requires import and registry
|
|
133
|
+
***** class aliases a bigger issue, will there be more conflicts?
|
|
134
|
+
***** any interpretation will fit only one ns strategy (e.g. gclosure's, and thus ClojureScript's)
|
|
135
|
+
***** start without this
|
|
136
|
+
*** DONE dot
|
|
137
|
+
**** field/zero-arg-method distinguished how?
|
|
138
|
+
***** not, just support scoped var and be done
|
|
139
|
+
*** DONE set! (assign)
|
|
140
|
+
**** same binding rules?
|
|
141
|
+
***** no
|
|
142
|
+
**** or just allow assign to scoped 'vars'?
|
|
143
|
+
*** DONE name munging
|
|
144
|
+
**** special chars
|
|
145
|
+
**** js reserved words
|
|
146
|
+
*** DONE (js* code-string)
|
|
147
|
+
**** with name escaping
|
|
148
|
+
*** TODO exceptions
|
|
149
|
+
**** throw
|
|
150
|
+
**** try
|
|
151
|
+
**** catch
|
|
152
|
+
***** won't have exception type
|
|
153
|
+
**** finally
|
|
154
|
+
*** quote?
|
|
155
|
+
*** TODO Evaluated collections
|
|
156
|
+
**** Map
|
|
157
|
+
**** Vector
|
|
158
|
+
*** vars?
|
|
159
|
+
*** case?
|
|
160
|
+
*** callable non-function types?
|
|
161
|
+
**** seems not possible portably
|
|
162
|
+
**** could do with __proto__ (non-standard, all but IE support, even IE9 doesn't)
|
|
163
|
+
**** how would Clojure feel without callable collections and keywords?
|
|
164
|
+
**** could do with conditional every invocation:
|
|
165
|
+
***** (f instanceof Function?f:f.cljs_lang_invoke)(args)
|
|
166
|
+
***** but where to put f (in expr context)?
|
|
167
|
+
****** needs helper fn
|
|
168
|
+
****** fnOf(f)(args)
|
|
169
|
+
******* function fnOf(x){return (f instanceof Function?f:f.cljs_lang_invoke);}
|
|
170
|
+
****** i.e. every call is 2 calls
|
|
171
|
+
******* tracing jit will inline?
|
|
172
|
+
** Translation
|
|
173
|
+
| Op | JS | Notes | Questions |
|
|
174
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
175
|
+
| (def x 42) | cljs.my.ns['x'] = 42 | Following gclosure module system | No vars? Compilation-time representation of ns? |
|
|
176
|
+
| | cljs.my.ns.x = 42 | only this one will get minified | but this precludes special chars in names |
|
|
177
|
+
| | | | def returns var in Clojure, no var here |
|
|
178
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
179
|
+
| (fn [x y] ...) | (function (x, y) {...}) | never do named function, use anon + def | Use for closures too? |
|
|
180
|
+
| (fn [x y] ... (recur...) | | rewrite as fn + nested loop | require analysis to transmit recur fact up |
|
|
181
|
+
| | | | rewrite when? |
|
|
182
|
+
| | | block always in return context | access to this for methods? |
|
|
183
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
184
|
+
| (if test then else) | (test ? then : else) | | |
|
|
185
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
186
|
+
| (do e1 e2 e3) | cljs.dofn(e1,e2,e3) | dofn returns last arg, allocs array? | requires js bootstrap file? |
|
|
187
|
+
| | | no, forces all to be exprs | no fn needed when not expr context |
|
|
188
|
+
| | (function () {e1;e2;return e3;})() | | |
|
|
189
|
+
| | | expr context becomes return except when | |
|
|
190
|
+
| | | single expr | |
|
|
191
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
192
|
+
| (let [x 1 y 2] ...) | (function [x,y] {...})(1, 2) | need to create nested functions for let* | how to detect ref to earlier? |
|
|
193
|
+
| | var x__42 = 1;var y__43 = 2; ... | var numbering | statement/expr dichotomy if inline? |
|
|
194
|
+
| | (function [] | could wrap in no-arg function always | needed for expr anyhow |
|
|
195
|
+
| | {var x = 1; var y = 2; ...})() | if always wrapped, don't need numbers? | can we do var x = 42; var x = 43? |
|
|
196
|
+
| | | might still when nested | yes, but not var x = 42 ...nesting... var x = x |
|
|
197
|
+
| | | | |
|
|
198
|
+
| | | expr always becomes return context | |
|
|
199
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
200
|
+
| (. x y) | x.y or x.y()? | no type info to distinguish | bigger problem, both calling and retrieving |
|
|
201
|
+
| | | | fn in slot are viable, Clojure says method wins |
|
|
202
|
+
| (. x y ...) | x.y(...) | | |
|
|
203
|
+
| | | | |
|
|
204
|
+
| (: x y) ? | x.y | | make all calls, add special field accessor |
|
|
205
|
+
| x.y | x.y | . not used for classes in JS | so not global, but scoped? |
|
|
206
|
+
| | | can't test from Clojure | but would want resolution of first segment to locals |
|
|
207
|
+
| | | | what do macros use? |
|
|
208
|
+
| | | | |
|
|
209
|
+
| (. x (y)) | already defined for this case | wasn't going to carry this into cljs, but | no arg == field, penalize no-arg methods? |
|
|
210
|
+
| ((. x y)) | more correct, it's a slot | | rationale, it's not a method, just a slot, |
|
|
211
|
+
| (-> (. x y) ()) | doesn't currently work, could | | but then why do the arg-taking ones work? |
|
|
212
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
213
|
+
| (set! (. x y) 42) | x.y = 42 | | whither vars and binding?? |
|
|
214
|
+
| (set! some.global.x 42) | some.global.x = 42 | | |
|
|
215
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
216
|
+
| (loop [bindings] | while(true){ | | wrap in function? depends on context |
|
|
217
|
+
| ... (recur)) | ... rebind-continue | | |
|
|
218
|
+
| | ret=xxx;break;} | | |
|
|
219
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
220
|
+
| (deftype Foo [a b c]) | my.ns.Foo = function(a,b,c) | turn inline defs into explicit extends? | deftype inline methods split out arities |
|
|
221
|
+
| | {this.a = a;...this.c=c;} | can't access this and fields. | |
|
|
222
|
+
| | | in locals map, bind a to this.a etc | |
|
|
223
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
224
|
+
| (new Foo 1 2 3) | (new Foo(1,2,3)) | | |
|
|
225
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
226
|
+
| (defprotocol P | my.ns.foo = function(obj args) | | How to extend built-ins, default, nil, undefined |
|
|
227
|
+
| (foo [args])) | {obj['my.ns.foo'](obj, args);} | can't minify | |
|
|
228
|
+
| | | | |
|
|
229
|
+
| | obj.my$ns$foo(obj, args) | | |
|
|
230
|
+
| | P.ns = 'my.ns' | this only compile-time need, but compiler | |
|
|
231
|
+
| | | not in js world, can't see it | |
|
|
232
|
+
| | | Require fully qualified protocol names? | |
|
|
233
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
234
|
+
| (extend Foo my.ns.P | for each fn in map: | if no reified protocols, extend can't be | or use Object.defineProperty to add method to |
|
|
235
|
+
| {:foo (fn [foo]...)} | Foo.prototype['my.ns.foo'] = fn | a function, unless protocol quoted | prototype? can then set enumerable to false |
|
|
236
|
+
| | Foo.prototype.my$ns$foo = fn | or string | |
|
|
237
|
+
| | | if extend is a macro or special, could | |
|
|
238
|
+
| | | still evaluate fn map, but then can't be | |
|
|
239
|
+
| | | minified | |
|
|
240
|
+
| | | evaluated extend requires maps, keywords | |
|
|
241
|
+
| | | high bar for bootstrap if protocols | |
|
|
242
|
+
| | | at bottom - extend* unevaluated? | |
|
|
243
|
+
| | | make extend-type primitive instead? YES | |
|
|
244
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
245
|
+
| constants | | | |
|
|
246
|
+
| nil | null | | |
|
|
247
|
+
| "foo", true, false, 42.0 | same | | |
|
|
248
|
+
| 42 | goog.Long? | | |
|
|
249
|
+
| 'foo | symbol ctor | | |
|
|
250
|
+
| :foo | ? | | how to do keyword interning? |
|
|
251
|
+
| | | | don't want intern every reference |
|
|
252
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
253
|
+
| (ns my.ns | | | |
|
|
254
|
+
| (:require [foo.bar :as fb]...) | | | |
|
|
255
|
+
| (:macros [my.macros :as mm]...)) | :require-macros? | | |
|
|
256
|
+
|----------------------------------+------------------------------------+-------------------------------------------+------------------------------------------------------|
|
|
257
|
+
** Library
|
|
258
|
+
*** persistent data structures?
|
|
259
|
+
**** make base literals create JS base literals? (array, object-as-map)
|
|
260
|
+
***** seems a big waste not to leverage js optimization of dynamic properties
|
|
261
|
+
****** or, that's what deftype is about, maps have always added overhead
|
|
262
|
+
***** we care more about accessors than assignment/modification
|
|
263
|
+
****** i.e. we will superimpose copy-on-write
|
|
264
|
+
***** string/keyword problem
|
|
265
|
+
****** can make {:a 1 :b 2 :c 3} => {a: 1, b: 2, c: 3}
|
|
266
|
+
****** but (keys that) => ["a" "b" "c"]
|
|
267
|
+
****** could use internal array of keys trick
|
|
268
|
+
******* keys used as strings in property map
|
|
269
|
+
******* kept intact in internal arrays, which is what is returned by keys fn
|
|
270
|
+
******* means keys must be string distinct - ick
|
|
271
|
+
**** promote only on conj?
|
|
272
|
+
***** or on size as well?
|
|
273
|
+
** Questions
|
|
274
|
+
*** equality and hashing
|
|
275
|
+
*** undefined
|
|
276
|
+
**** turn into nil?
|
|
277
|
+
**** can't catch everywhere
|
|
278
|
+
*** vars
|
|
279
|
+
**** def should create slots in global ns objects?
|
|
280
|
+
**** what var semantics matter?
|
|
281
|
+
*** keywords and symbols
|
|
282
|
+
**** make separate object types?
|
|
283
|
+
***** not many symbols make it into runtime use, but keywords do
|
|
284
|
+
**** need to make sure {:key val} and (:key obj) are fast
|
|
285
|
+
**** native maps can have only string keys
|
|
286
|
+
*** metadata
|
|
287
|
+
**** just claim a slot?
|
|
288
|
+
*** namespaces
|
|
289
|
+
**** tie into gclosure module system?
|
|
290
|
+
**** compile-time enumerability?
|
|
291
|
+
*** eval
|
|
292
|
+
**** runtime compiler?
|
|
293
|
+
**** would let you develop in the browser, repl etc
|
|
294
|
+
**** means compiler must self-host
|
|
295
|
+
***** and needs runtime reader
|
|
296
|
+
***** and syntax-quote
|
|
297
|
+
**** no macros?
|
|
298
|
+
***** can't do without, as so many basic things are macros
|
|
299
|
+
**** won't have google closure compiler there
|
|
300
|
+
***** ok, shouldn't rely on that
|
|
301
|
+
*** laziness
|
|
302
|
+
**** not a great fit
|
|
303
|
+
**** GC probably not as good
|
|
304
|
+
**** unlikely to be working with bigger-than-memory
|
|
305
|
+
**** non-lazy mapping/filtering or mapv, filterv
|
|
306
|
+
***** can make it back into Clojure
|
|
307
|
+
*** Immutability
|
|
308
|
+
**** enforced?
|
|
309
|
+
***** or just use safe lib fns to avoid
|
|
310
|
+
****** lets you use base types
|
|
311
|
+
****** no final on which to base it anyway
|
|
312
|
+
****** would need fancy encapsulation techniques
|
|
313
|
+
******* how fancy?
|
|
314
|
+
***** correct (non-assigning) code does the same thing, but incorrect not caught
|
|
315
|
+
****** fair compromise?
|
|
316
|
+
**** gclosure compiler can do some enforcement
|
|
317
|
+
***** given some const hints in comment-based annotations
|
|
318
|
+
*** Interactive development
|
|
319
|
+
**** REPL
|
|
320
|
+
***** easiest:
|
|
321
|
+
***** Clojure read -> cljs analyze -> cljs emits -> embedded Rhino eval+print
|
|
322
|
+
**** Incompatible constructs
|
|
323
|
+
***** for host interop
|
|
324
|
+
****** preclude development in Clojure
|
|
325
|
+
**** Missing JS things
|
|
326
|
+
***** e.g. DOM etc
|
|
327
|
+
***** headless JS environment with DOM mocks?
|
|
328
|
+
* Namespaces and macros
|
|
329
|
+
** Macro problem?
|
|
330
|
+
*** syntax quote in the reader uses Clojure namespaces
|
|
331
|
+
*** hardwired to Compiler.currentNS().getMapping() Compiler.resolveSymbol(), isSpecial() etc
|
|
332
|
+
*** ::keyword resolution uses Compiler.currentNS(), namespaceFor()
|
|
333
|
+
*** if it expands to calls to other macros, those need to be in clojure-land
|
|
334
|
+
**** maybe - they need to be the cljs-compatible versions
|
|
335
|
+
***** argument for calling core clojure.core in cljs too?
|
|
336
|
+
****** but we can't have 2 clojure.core namespaces during compilation
|
|
337
|
+
***** translate/consider clojure.core/xxx => cljs.core/xxx during cljs compilation?
|
|
338
|
+
****** doesn't work if we have separate cljs.macros
|
|
339
|
+
******* some core things will be in cljs.core, some in cljs.macros
|
|
340
|
+
******* put core macros on cljs/core.clj
|
|
341
|
+
******* other core code in cljs/core.cljs
|
|
342
|
+
******* both contain ns declarations - ok?
|
|
343
|
+
*** but expansions destined for cljs compilation need to be resolved in cljs-land
|
|
344
|
+
**** dummy vars in dummy namespaces?
|
|
345
|
+
***** no - doesn't cover external nses, cljs aliases
|
|
346
|
+
***** just fully qualify everything non-core in macroexpansions
|
|
347
|
+
**** different specials set a problem
|
|
348
|
+
***** e.g. global, ns, defprotocol* not specials
|
|
349
|
+
****** could use var for global
|
|
350
|
+
****** could make ns a special?
|
|
351
|
+
******* probably not
|
|
352
|
+
******* but what macro would emit that?
|
|
353
|
+
***** install all cljs specials in dummy nses?
|
|
354
|
+
****** no, doesn't help macros file
|
|
355
|
+
*** inline defmacro in cljs?
|
|
356
|
+
**** calls Clojure eval of defmacro call
|
|
357
|
+
**** can expand to calls to enclosing cljs ns
|
|
358
|
+
***** but expander can't call code in enclosing cljs ns
|
|
359
|
+
***** convention - all macro helper fns are local fns in macro
|
|
360
|
+
**** gets icky for load/require purposes, as must be loaded with cljs compiler
|
|
361
|
+
***** better to keep public macros separate - can use ordinary Clojure require then
|
|
362
|
+
***** local macros would be ok for same-file consumption though
|
|
363
|
+
**** convention - portable libs that expose macros package them separately
|
|
364
|
+
** Want some equivalent of refer clojure.core
|
|
365
|
+
*** else practically everything will be qualified
|
|
366
|
+
**** e.g. core/defn - ick
|
|
367
|
+
*** but fewer things brought in by default?
|
|
368
|
+
**** requires selectivity control, or just a smaller core.cljs?
|
|
369
|
+
*** this is equivalent to a 'use', which we otherwise aren't supporting
|
|
370
|
+
**** unfair or don't care?
|
|
371
|
+
** Any 'use' equivalent (e.g. refer core) means compile-time disambiguation of unqualified references
|
|
372
|
+
*** if names a referred thing, that thing, else current.ns.name
|
|
373
|
+
**** like current namespaces
|
|
374
|
+
**** but if refers are limited to (entirety of) core, just look there first
|
|
375
|
+
**** so double lookup instead of copying core vars into name table
|
|
376
|
+
** Some core things defined in js
|
|
377
|
+
*** where we don't want to otherwise expose things needed for their impl
|
|
378
|
+
**** e.g. ==, ===, math ops, instanceOf typeof etc
|
|
379
|
+
*** how to reserve names?
|
|
380
|
+
**** declare in core.cljs?
|
|
381
|
+
*** if in actual .js file, separate ns for deps purposes?
|
|
382
|
+
**** i.e. it will be a different file than that produced by compiling core.cljs
|
|
383
|
+
**** or just a wad of js injected into core.cljs?
|
|
384
|
+
***** include a (js code-string) primitive for this purpose?
|
|
385
|
+
****** yes, much better than js files
|
|
386
|
+
****** accept only at top level? - no
|
|
387
|
+
****** using in local scope means knowing how locals are represented
|
|
388
|
+
****** some sort of escaping construct for getting (local and other) names resolved
|
|
389
|
+
******* ~{identifier}
|
|
390
|
+
** Are we doing forward reference detection here?
|
|
391
|
+
*** requires listing of contents of current ns
|
|
392
|
+
**** like namespaces
|
|
393
|
+
** Are we doing extern-ns name validation?
|
|
394
|
+
*** could do for cljs names, but not others
|
|
395
|
+
**** e.g. goog.whatever not enumerable in cljs
|
|
396
|
+
**** can we discern this situation?
|
|
397
|
+
***** probably not, when compiling from files
|
|
398
|
+
****** since 'require' doesn't load code at compile time
|
|
399
|
+
**** another reason we can't support 'use'
|
|
400
|
+
***** we do want to be able to (:require goog.foo)
|
|
401
|
+
****** but not a compile-time enumerable ns
|
|
402
|
+
***** or especially: (:require [goog.foo :as gfoo])
|
|
403
|
+
***** means alias map, like namespaces
|
|
404
|
+
** Macros written in separate Clojure files
|
|
405
|
+
*** Clojure code, in regular namespaces
|
|
406
|
+
*** Means core split into core.cljs, and core-macros.clj
|
|
407
|
+
**** both need to be auto-referred
|
|
408
|
+
*** if no use/only for macro ns, then can only get as succinct as (alias/macro ...)
|
|
409
|
+
**** could allow explicit aliasing of vars instead of use
|
|
410
|
+
**** extend alias for this?
|
|
411
|
+
***** not really extending, alias will do this due to how nses are just vars
|
|
412
|
+
***** but need not be used in that pat of resolution
|
|
413
|
+
** goog.provide throws called-twice exception
|
|
414
|
+
*** intended to prevent providing the same ns in more than one file
|
|
415
|
+
*** actually prevents reloading same file? - aargh
|
|
416
|
+
*** can't wrap, since deps checkers look for it at top level
|
|
417
|
+
**** will we need to track at compilation-time?
|
|
418
|
+
**** will we still need *compile-file* notion?
|
|
419
|
+
** Compilation needs
|
|
420
|
+
*** current ns
|
|
421
|
+
**** *cljs-ns* ?
|
|
422
|
+
**** is this a Clojure ns?
|
|
423
|
+
***** not a fit
|
|
424
|
+
****** map is sym->Var or Class
|
|
425
|
+
****** aliases are sym->Namespace
|
|
426
|
+
*** ns has:
|
|
427
|
+
**** *cljs-namespaces* - {name->ns}
|
|
428
|
+
**** {:name "my.ns" :defs {sym qualified.sym} :deps {alias Namepsace-or-qualified.sym}}
|
|
429
|
+
**** defs
|
|
430
|
+
***** just set of names? no map
|
|
431
|
+
***** or map to fully qualified self?
|
|
432
|
+
**** deps
|
|
433
|
+
***** can't merge macros and cljs ns in deps
|
|
434
|
+
****** same ns might map to both
|
|
435
|
+
******* i.e. cljs.core will
|
|
436
|
+
***** aliases
|
|
437
|
+
****** sym->fully-qualified-sym
|
|
438
|
+
****** is this a separate mapping vs macros and requires?
|
|
439
|
+
******* if not, fn alias can mask out ns alias
|
|
440
|
+
******* that can't happen in Clojure
|
|
441
|
+
***** macro nses
|
|
442
|
+
****** map of sym->Namespaces?
|
|
443
|
+
******* require an alias?
|
|
444
|
+
******* (:macros {mm my.macros, ym your.macros})
|
|
445
|
+
****** aliases for these same as others?
|
|
446
|
+
***** required libs must have aliases too?
|
|
447
|
+
****** (:require [goog.math.Long :as gml])
|
|
448
|
+
****** or new (:require {gml goog.math.Long})
|
|
449
|
+
*** lookup 'foo - no ns, no dots
|
|
450
|
+
**** if special - done
|
|
451
|
+
**** if local - done
|
|
452
|
+
**** if found in cljs.macros Namespace, the macro cljs.macros/foo
|
|
453
|
+
**** if found in cljs.core ns, cljs.core.foo
|
|
454
|
+
**** whatever 'foo maps to in (-> env :ns :requires)
|
|
455
|
+
**** no use of deps
|
|
456
|
+
*** lookup 'foo.bar.baz - no ns, dot(s)
|
|
457
|
+
**** if foo is a local, foo_nnnn.bar.baz
|
|
458
|
+
**** if foo has a mapping in (:ns env) - that.mapping.bar.baz - no
|
|
459
|
+
***** really? covered by alias/whatever
|
|
460
|
+
****** more idiomatic for goog.stuff than goog.stuff/foo
|
|
461
|
+
****** but no :as there
|
|
462
|
+
***** leave out for now
|
|
463
|
+
**** else foo.bar.baz
|
|
464
|
+
*** lookup 'foo/bar - ns with no dots
|
|
465
|
+
**** get what 'foo maps to in (:ns env) deps
|
|
466
|
+
***** if nothing - error "no alias foo"
|
|
467
|
+
**** if maps to Namespace, the macro 'bar in that ns
|
|
468
|
+
**** else a symbol, e.g. 'fred.ethel => fred.ethel.bar
|
|
469
|
+
*** lookup fully.qualified/foo - ns with dots
|
|
470
|
+
**** would only use this if local shadowed (and no alias)?
|
|
471
|
+
**** what doesn't have alias?
|
|
472
|
+
***** cljs.core, cljs.macros
|
|
473
|
+
***** could use cljs.core.foo for former
|
|
474
|
+
***** always interpret as macro ns?
|
|
475
|
+
****** or check deps vals for Namespace, else not
|
|
476
|
+
***** if Namespace, the macro foo in Namespace
|
|
477
|
+
***** fully.quallified.foo
|
|
478
|
+
**** everything might have alias, but macros/syntax-quote need to emit full expansions
|
|
479
|
+
*** how to refer to true globals?
|
|
480
|
+
**** e.g. Object, String, goog
|
|
481
|
+
**** [[https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects][JS Globals]]
|
|
482
|
+
**** (var Name)?
|
|
483
|
+
***** that doesn't match Clojure, where (var x) means 'whatever x means in current ns'
|
|
484
|
+
***** there are no unqualified globals in Clojure
|
|
485
|
+
**** means (extend (var Object) ...) needs to work
|
|
486
|
+
***** ok if extend evaluates first arg
|
|
487
|
+
***** it does in Clojure, as it is a function
|
|
488
|
+
* Setup
|
|
489
|
+
** V8
|
|
490
|
+
svn co http://v8.googlecode.com/svn/trunk v8
|
|
491
|
+
cd v8/
|
|
492
|
+
scons console=readline d8
|
|
493
|
+
** Closure Library
|
|
494
|
+
svn checkout http://closure-library.googlecode.com/svn/trunk/ closure-library
|
|
495
|
+
*** or download?
|
|
496
|
+
[[http://code.google.com/p/closure-library/downloads/detail%3Fname%3Dclosure-library-20110323-r790.zip&can%3D1&q%3D][Zip download]]
|
|
497
|
+
** Closure Compiler
|
|
498
|
+
http://closure-compiler.googlecode.com/files/compiler-latest.zip
|
|
499
|
+
*** better(?):
|
|
500
|
+
[[http://code.google.com/p/closure-compiler/wiki/Maven][Compiler in Maven]]
|