clementine 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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]]
|