├── .gitignore ├── LICENSE ├── README.md ├── baz └── baz.go ├── bench_test.go ├── cljs ├── binding_test │ └── binding_test.go ├── binding_test_other_ns │ └── binding_test_other_ns.go ├── core │ ├── core.go │ ├── core_test.go │ ├── overrides.go │ └── rt.go ├── core_test │ └── core_test.go ├── keyword_other │ └── keyword_other.go ├── keyword_test │ └── keyword_test.go ├── letfn_test │ └── letfn_test.go ├── macro_test │ └── macro_test.go ├── ns_test │ ├── bar │ │ └── bar.go │ ├── foo │ │ └── foo.go │ └── ns_test.go ├── reader │ ├── overrides.go │ └── reader.go ├── reader_test │ └── reader_test.go └── top_level_test │ └── top_level_test.go ├── clojure ├── data │ ├── data.go │ └── overrides.go ├── data_test │ └── data_test.go ├── set │ └── set.go ├── string │ ├── overrides.go │ └── string.go ├── string_test │ └── string_test.go ├── walk │ └── walk.go └── zip │ └── zip.go ├── foo └── ns_shadow_test │ └── ns_shadow_test.go ├── goog ├── array │ └── array.go ├── goog.go ├── goog_test.go ├── object │ └── object.go └── string │ └── string.go ├── js ├── Math │ └── Math.go ├── js.go └── js_test.go ├── main.go ├── project.clj ├── samples ├── hello.cljs └── hello │ ├── hello.go │ └── main.go ├── src ├── cljs │ ├── core │ │ └── overrides.cljs │ ├── go.clj │ ├── go │ │ ├── compiler.clj │ │ └── core.clj │ └── reader │ │ └── overrides.cljs └── clojure │ ├── data │ └── overrides.cljs │ └── string │ └── overrides.cljs ├── test ├── baz.cljs ├── cljs │ ├── binding_test.cljs │ ├── binding_test_other_ns.cljs │ ├── core_test.cljs │ ├── go_test.clj │ ├── keyword_other.cljs │ ├── keyword_test.cljs │ ├── letfn_test.cljs │ ├── macro_test.cljs │ ├── macro_test │ │ └── macros.clj │ ├── ns_test.cljs │ ├── ns_test │ │ ├── bar.cljs │ │ └── foo.cljs │ ├── reader_test.cljs │ └── top_level_test.cljs ├── clojure │ ├── data_test.cljs │ └── string_test.cljs └── foo │ └── ns_shadow_test.cljs └── vendor └── github.com └── stretchr └── testify ├── LICENCE.txt └── assert ├── assertions.go ├── doc.go ├── errors.go └── forward_assertions.go /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /out 3 | /classes 4 | /checkouts 5 | pom.xml 6 | pom.xml.asc 7 | *.jar 8 | *.class 9 | /.lein-* 10 | /.rlwrap-completions 11 | /.nrepl-port 12 | *~ 13 | *.test 14 | cljs.go 15 | cpu.out 16 | mem.out -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 2 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 3 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 4 | 5 | 1. DEFINITIONS 6 | 7 | "Contribution" means: 8 | 9 | a) in the case of the initial Contributor, the initial code and 10 | documentation distributed under this Agreement, and 11 | 12 | b) in the case of each subsequent Contributor: 13 | 14 | i) changes to the Program, and 15 | 16 | ii) additions to the Program; 17 | 18 | where such changes and/or additions to the Program originate from and are 19 | distributed by that particular Contributor. A Contribution 'originates' from 20 | a Contributor if it was added to the Program by such Contributor itself or 21 | anyone acting on such Contributor's behalf. Contributions do not include 22 | additions to the Program which: (i) are separate modules of software 23 | distributed in conjunction with the Program under their own license 24 | agreement, and (ii) are not derivative works of the Program. 25 | 26 | "Contributor" means any person or entity that distributes the Program. 27 | 28 | "Licensed Patents" mean patent claims licensable by a Contributor which are 29 | necessarily infringed by the use or sale of its Contribution alone or when 30 | combined with the Program. 31 | 32 | "Program" means the Contributions distributed in accordance with this 33 | Agreement. 34 | 35 | "Recipient" means anyone who receives the Program under this Agreement, 36 | including all Contributors. 37 | 38 | 2. GRANT OF RIGHTS 39 | 40 | a) Subject to the terms of this Agreement, each Contributor hereby grants 41 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 42 | reproduce, prepare derivative works of, publicly display, publicly perform, 43 | distribute and sublicense the Contribution of such Contributor, if any, and 44 | such derivative works, in source code and object code form. 45 | 46 | b) Subject to the terms of this Agreement, each Contributor hereby grants 47 | Recipient a non-exclusive, worldwide, royalty-free patent license under 48 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 49 | transfer the Contribution of such Contributor, if any, in source code and 50 | object code form. This patent license shall apply to the combination of the 51 | Contribution and the Program if, at the time the Contribution is added by the 52 | Contributor, such addition of the Contribution causes such combination to be 53 | covered by the Licensed Patents. The patent license shall not apply to any 54 | other combinations which include the Contribution. No hardware per se is 55 | licensed hereunder. 56 | 57 | c) Recipient understands that although each Contributor grants the licenses 58 | to its Contributions set forth herein, no assurances are provided by any 59 | Contributor that the Program does not infringe the patent or other 60 | intellectual property rights of any other entity. Each Contributor disclaims 61 | any liability to Recipient for claims brought by any other entity based on 62 | infringement of intellectual property rights or otherwise. As a condition to 63 | exercising the rights and licenses granted hereunder, each Recipient hereby 64 | assumes sole responsibility to secure any other intellectual property rights 65 | needed, if any. For example, if a third party patent license is required to 66 | allow Recipient to distribute the Program, it is Recipient's responsibility 67 | to acquire that license before distributing the Program. 68 | 69 | d) Each Contributor represents that to its knowledge it has sufficient 70 | copyright rights in its Contribution, if any, to grant the copyright license 71 | set forth in this Agreement. 72 | 73 | 3. REQUIREMENTS 74 | 75 | A Contributor may choose to distribute the Program in object code form under 76 | its own license agreement, provided that: 77 | 78 | a) it complies with the terms and conditions of this Agreement; and 79 | 80 | b) its license agreement: 81 | 82 | i) effectively disclaims on behalf of all Contributors all warranties and 83 | conditions, express and implied, including warranties or conditions of title 84 | and non-infringement, and implied warranties or conditions of merchantability 85 | and fitness for a particular purpose; 86 | 87 | ii) effectively excludes on behalf of all Contributors all liability for 88 | damages, including direct, indirect, special, incidental and consequential 89 | damages, such as lost profits; 90 | 91 | iii) states that any provisions which differ from this Agreement are offered 92 | by that Contributor alone and not by any other party; and 93 | 94 | iv) states that source code for the Program is available from such 95 | Contributor, and informs licensees how to obtain it in a reasonable manner on 96 | or through a medium customarily used for software exchange. 97 | 98 | When the Program is made available in source code form: 99 | 100 | a) it must be made available under this Agreement; and 101 | 102 | b) a copy of this Agreement must be included with each copy of the Program. 103 | 104 | Contributors may not remove or alter any copyright notices contained within 105 | the Program. 106 | 107 | Each Contributor must identify itself as the originator of its Contribution, 108 | if any, in a manner that reasonably allows subsequent Recipients to identify 109 | the originator of the Contribution. 110 | 111 | 4. COMMERCIAL DISTRIBUTION 112 | 113 | Commercial distributors of software may accept certain responsibilities with 114 | respect to end users, business partners and the like. While this license is 115 | intended to facilitate the commercial use of the Program, the Contributor who 116 | includes the Program in a commercial product offering should do so in a 117 | manner which does not create potential liability for other Contributors. 118 | Therefore, if a Contributor includes the Program in a commercial product 119 | offering, such Contributor ("Commercial Contributor") hereby agrees to defend 120 | and indemnify every other Contributor ("Indemnified Contributor") against any 121 | losses, damages and costs (collectively "Losses") arising from claims, 122 | lawsuits and other legal actions brought by a third party against the 123 | Indemnified Contributor to the extent caused by the acts or omissions of such 124 | Commercial Contributor in connection with its distribution of the Program in 125 | a commercial product offering. The obligations in this section do not apply 126 | to any claims or Losses relating to any actual or alleged intellectual 127 | property infringement. In order to qualify, an Indemnified Contributor must: 128 | a) promptly notify the Commercial Contributor in writing of such claim, and 129 | b) allow the Commercial Contributor tocontrol, and cooperate with the 130 | Commercial Contributor in, the defense and any related settlement 131 | negotiations. The Indemnified Contributor may participate in any such claim 132 | at its own expense. 133 | 134 | For example, a Contributor might include the Program in a commercial product 135 | offering, Product X. That Contributor is then a Commercial Contributor. If 136 | that Commercial Contributor then makes performance claims, or offers 137 | warranties related to Product X, those performance claims and warranties are 138 | such Commercial Contributor's responsibility alone. Under this section, the 139 | Commercial Contributor would have to defend claims against the other 140 | Contributors related to those performance claims and warranties, and if a 141 | court requires any other Contributor to pay any damages as a result, the 142 | Commercial Contributor must pay those damages. 143 | 144 | 5. NO WARRANTY 145 | 146 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON 147 | AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER 148 | EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR 149 | CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A 150 | PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the 151 | appropriateness of using and distributing the Program and assumes all risks 152 | associated with its exercise of rights under this Agreement , including but 153 | not limited to the risks and costs of program errors, compliance with 154 | applicable laws, damage to or loss of data, programs or equipment, and 155 | unavailability or interruption of operations. 156 | 157 | 6. DISCLAIMER OF LIABILITY 158 | 159 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 160 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 161 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 162 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 163 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 164 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 165 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 166 | OF SUCH DAMAGES. 167 | 168 | 7. GENERAL 169 | 170 | If any provision of this Agreement is invalid or unenforceable under 171 | applicable law, it shall not affect the validity or enforceability of the 172 | remainder of the terms of this Agreement, and without further action by the 173 | parties hereto, such provision shall be reformed to the minimum extent 174 | necessary to make such provision valid and enforceable. 175 | 176 | If Recipient institutes patent litigation against any entity (including a 177 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 178 | (excluding combinations of the Program with other software or hardware) 179 | infringes such Recipient's patent(s), then such Recipient's rights granted 180 | under Section 2(b) shall terminate as of the date such litigation is filed. 181 | 182 | All Recipient's rights under this Agreement shall terminate if it fails to 183 | comply with any of the material terms or conditions of this Agreement and 184 | does not cure such failure in a reasonable period of time after becoming 185 | aware of such noncompliance. If all Recipient's rights under this Agreement 186 | terminate, Recipient agrees to cease use and distribution of the Program as 187 | soon as reasonably practicable. However, Recipient's obligations under this 188 | Agreement and any licenses granted by Recipient relating to the Program shall 189 | continue and survive. 190 | 191 | Everyone is permitted to copy and distribute copies of this Agreement, but in 192 | order to avoid inconsistency the Agreement is copyrighted and may only be 193 | modified in the following manner. The Agreement Steward reserves the right to 194 | publish new versions (including revisions) of this Agreement from time to 195 | time. No one other than the Agreement Steward has the right to modify this 196 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 197 | Eclipse Foundation may assign the responsibility to serve as the Agreement 198 | Steward to a suitable separate entity. Each new version of the Agreement will 199 | be given a distinguishing version number. The Program (including 200 | Contributions) may always be distributed subject to the version of the 201 | Agreement under which it was received. In addition, after a new version of 202 | the Agreement is published, Contributor may elect to distribute the Program 203 | (including its Contributions) under the new version. Except as expressly 204 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 205 | licenses to the intellectual property of any Contributor under this 206 | Agreement, whether expressly, by implication, estoppel or otherwise. All 207 | rights in the Program not expressly granted under this Agreement are 208 | reserved. 209 | 210 | This Agreement is governed by the laws of the State of New York and the 211 | intellectual property laws of the United States of America. No party to this 212 | Agreement will bring a legal action under this Agreement more than one year 213 | after the cause of action arose. Each party waives its rights to a jury trial 214 | in any resulting litigation. 215 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cljs2go 2 | 3 | *Way to Go!* -- [Siobhan Sharpe](http://londonist.com/2012/07/did-boris-write-twenty-twelve-way-to-go-gag.php) 4 | 5 | **[2015-08-01] Was based on ClojureScript 0.0-2411 in 2014, and passes (most of) the tests, though the compiler is JVM based. Should be redone on top of self hosted [ClojureScript 1.7](http://swannodette.github.io/2015/07/29/clojurescript-17/) at some point.** 6 | 7 | **ClojureScript to Go**. Implemented as an overlay onto ClojureScript, instead of a fork. Go is emitted from `cljs.go.compiler`, which is a patched version of `cljs.compiler`. At run time, a thin JS compatibility is provided to avoid having to touch `cljs.core`, these `js` and `goog` packages aren't intended for end-user usage. 8 | 9 | Once the compiler starts working, the plan is to provide a second monkey patch in spirit of the first, but this time for the Java dependencies, like `java.io.File` and their Clojure counterpart, `clojure.java.io`. This patch is to be able to compile the compiler itself to Go. This won't change the run-time characteristics of the compiled programs, nor will it introduce `eval`, it's simply done to leverage the Go build pipeline. ClojureScript has a reader in `cljs.reader` that potentially can replace `tools.reader`. Macros used via `:require-macros` needs to be compiled to Go first, and an ad-hoc wrapper for the compiler depending on them will be created to compile the actual source (the basic compiler has the `cljs.core` macros built in). 10 | 11 | While not introducing `eval`, it does open up for adding it as a third layer, the problem lies on the Go side, as you need a way to build and link code into the running process. This is certainly doable in various ways, but not yet sure what the right way to do so is. One potential way is to use Go's own `cgo` to both call and expose Go packages as C combined with `dlopen`, potentially using [go-ffi](https://bitbucket.org/binet/go-ffi). Another is via `net/rpc`. A third interesting option is to model the namespaces using [go9p](http://code.google.com/p/go9p/). Regardless the approach, it will need a way to keep or migrate the state of vars. There's also [Go Execution Modes](https://docs.google.com/document/d/1nr-TQHw*er6GOQRsF6T43GGhFDelrAP0NqSS*00RgZQ/preview?sle=true) which hints at a future `-buildmode=plugin`, potentially in Go 1.5. 12 | 13 | ### Why? 14 | 15 | Mainly for fun and to learn Go. But it is also trying to address issues around fast compilation and start-up time (a current concern in the Clojure world, see below). On the other side, see Fernando's [motivation](https://github.com/eudoxia0/corvus#why) for his corvus LLVM Lisp: "The era of dynamic languages is over. There is currently a 'race to the bottom': Languages like Rust and Nimrod are merging the world of low-level programming with high-level compiler features." The reason to start this exploration with Go itself is most pragmatically explained in Rob's motivating [talk](https://talks.golang.org/2012/splash.article). And, Go has momentum. 16 | 17 | The goal isn't to compete with the JVM or V8 on performance. Another obvious reason would be to leverage the Go ecosystem using ClojureScript. It's also meant to simplify creating new emitters (at least for myself) for ClojureScript. I'm aware of `tools.analyzer` etc., but they don't help you implement `clojure.core` and the actual language run-time. That said, building on a fork of `tools.analyzer.js` instead of `cljs.analyzer` is a likely future direction. Currently, ClojureScript's analyzer is not modified, and a lot of extra mess happens in the Go compiler. Some of this could / should be moved to analyzer passes. 18 | 19 | ### How? 20 | 21 | The easiest way to start understanding how the compiler works is to look at the emitted Go code. `core.go` is `core.cljs` compiled to Go. `overrides.go` are Go specific overrides compiled from `overrides.cljs`. `rt.go` is a handwritten Go file providing the implementation needed, mainly `AFn` and wrappers around Go `reflect` capabilities and some coercing functions (like `Truth_`) used by the emitted code. ClojureScript functions are represented by this `AFn` struct, which bundles up potentially more than one Go function into a ClojureScript one. `deftype` compiles to Go structs, `defprotocol` to Go interfaces. Protocol methods are real Go methods, not `AFn`s. `number`, `boolean`, `array`, `string` and `seq` are recognized and compiled to `float64`, `bool`, `[]interface{}`, `string` and `CljsCoreISeq`. Like in JavaScript there are no real integers, all numbers are `float64` for simplicity, but this is likely to change. 22 | 23 | As can be seen on `ISeq` above, types and protocols are ns-prefixed to not clash with functions (like `Symbol` vs. `symbol`). Public functions in Go must start with an uppercase character. Functions starting with a `_` (munged from `-`) have an `X` in front of them. The arity is appended, so a full compiled name will look like this: `X_invoke_Arity1`. `ArityVariadic` is a special case which regardless of how many fixed parameters take a single varargs parameter which is then unpacked inside the generated body. This is to simplify dispatch and avoid having 20+ different varargs signatures (this might change). Functions with primitives (up to 3 arguments) are compiled into something like `Arity1FF` (takes one `float64` and returns a `float64`). These functions live beneath the normal protocol `IFn` dispatch. A normal (without primitives) bridge `IFn` function is also generated (using [MakeFunc](http://golang.org/pkg/reflect/#MakeFunc)) for the matching arity. Like in ClojureScript, there's a special protocol `Object` that allow creating of methods that look like real Go methods (no `_ArityN`). These methods, like any host methods or functions, are invoked by the dot notation, like `(.toString x)`. There's currently no way to create a plain Go `func`, but this will likely become a macro. 24 | 25 | When compiling, the unaltered `cljs.analyzer` from ClojureScript is used to build the AST (see Nicola's [AST Quickref](http://clojure.github.io/tools.analyzer/spec/quickref.html)). The analyzer depends on the `cljs.core` macros (`core.clj`), which (like all ClojureScript macros) are written in Clojure. This file is replaced by `cljs.go.core`, and heavily uses the `js*` macro to emit literal Go code. Once the AST has been generated, it's fed into the `cljs.go.compiler`, which emits the Go source code. This is in turn (usually) fed into [`goimports`](http://godoc.org/code.google.com/p/go.tools/cmd/goimports) (a version of `gofmt` that also fixes the imports) and then finally `go build` (or `go install`). 26 | 27 | ### Usage 28 | 29 | *Not ready yet.* 30 | 31 | Ensure you have [Go 1.6.x](https://golang.org/dl/) installed and `GOPATH` setup properly, see [How to Write Go Code](https://golang.org/doc/code.html). Then clone this repo like this: 32 | 33 | ```bash 34 | # Clone and build the Go packages: 35 | $ go get github.com/hraberg/cljs2go 36 | # The repo itself lives under src by convention: 37 | $ cd $GOPATH/src/github.com/hraberg/cljs2go 38 | 39 | # go test, for Go tests checked into git, both generated and handwritten ones: 40 | $ go test -v ./... 41 | # To re-generate the tests from ClojureScript (this might dirty the repo): 42 | $ lein test 43 | # (This also generates and runs some tests under target/generated which aren't checked in.) 44 | 45 | # To re-generate the Go for ClojureScript itself: 46 | $ go generate 47 | ``` 48 | 49 | The tests use [testify](https://github.com/stretchr/testify) partially forked from [da775f0](https://github.com/stretchr/testify/tree/da775f0337260efbac0fce9764cee5bd3e8c85b8), living under [vendor](https://golang.org/cmd/go/#hdr-Vendor_Directories). 50 | 51 | While the compiler more or less works, and passes most of ClojureScript's test suite, it's not packaged for actual use, as I first intend to compile it to Go. If you want to play with it, it's easiest to fire up a REPL and look at the `cljs.go` namespace. 52 | 53 | The Hello World sample can be built like this: 54 | 55 | ```clj 56 | ;; Generate the Go source from a Clojure REPL: 57 | cljs.go> (compile-file "samples" "samples/hello.cljs") 58 | ``` 59 | 60 | ```bash 61 | # go run, < 1s 62 | $ cd samples/hello 63 | $ go run main.go 64 | Hello World 65 | 66 | # go build 67 | $ go build -o hello main.go 68 | # Native binary, < 50ms, 7.5M 69 | $ ./hello 70 | Hello World 71 | 72 | ``` 73 | 74 | ### Road Map 75 | 76 | *We're currently in phase 1. `cljs.core-tests` now pass.* 77 | 78 | #### Phase 0 79 | 80 | * Generate compiling ClojureScript with mapping for all basic constructs to Go. 81 | * Minimal JavaScript host libraries assumed by ClojureScript. 82 | 83 | #### Phase 1 84 | 85 | * Getting the relevant parts of ClojureScript's test suite to run. 86 | * Ability to build an app with more than one namespace and a main fn which depends on the core. 87 | * Go interop, `func` macro, coercions functions, ability to write moderately useful programs. 88 | 89 | #### Phase 2 90 | 91 | * Ability transform `core.clj`, `analyzer.clj` and `compiler.clj` to compiling ClojureScript. 92 | * Compiling one reader, either `cljs.reader` (which might need extensions) or `tools.reader` to ClojureScript. 93 | * Bootstrap the compiler using the above to Go. 94 | * Ability to build new wrapping compilers for `require-macros` to work. Assume the macros are valid ClojureScript. 95 | 96 | #### Phase 3 97 | 98 | * Performance. Revisit all the basic assumptions. Generate cleaner code, remove redundant constructs. 99 | * Move to the `tools.analyzer` stack. 100 | * Full bootstrap, porting the hacks that allow the compiler to compile itself. 101 | * `core.async` using real Go blocks and channels. 102 | * ClojureScript to Go REPL 103 | 104 | #### Phase 4 105 | 106 | * Porting to other targets. 107 | 108 | ### See Also 109 | 110 | * http://martintrojer.github.io/clojure/2014/04/05/the-clojure-repl-a-blessing-and-a-curse/ 111 | * https://al3x.net/2014/09/16/thoughts-on-five-years-of-emerging-languages.html 112 | * http://blog.cognitect.com/blog/2014/10/20/results-of-2014-state-of-clojure-and-clojurescript-survey 113 | 114 | #### Lisp's in Go: 115 | 116 | * https://github.com/tcard/gojure 117 | * https://github.com/bjeanes/gojure 118 | * https://github.com/zhemao/glisp 119 | 120 | #### Dialects of Clojure 121 | 122 | * http://dev.clojure.org/display/design/Release.Next+Planning 123 | * https://github.com/clojure/tools.analyzer/ 124 | * http://clojure-android.info/blog/2014/08/12/gsoc-2014-skummet-alpha1/ 125 | * https://github.com/arrdem/oxcart 126 | * https://github.com/mikera/kiss/ 127 | 128 | ### Ports of ClojureScript 129 | 130 | * https://github.com/schani/clojurec 131 | * https://github.com/takeoutweight/clojure-scheme 132 | * https://github.com/raph-amiard/clojurescript-lua 133 | * https://github.com/kanaka/clojurescript (in ClojureScript) 134 | 135 | ### Lower-level Lisps 136 | 137 | * https://github.com/pixie-lang/pixie 138 | * https://github.com/artagnon/rhine 139 | * https://github.com/eudoxia0/corvus 140 | * http://piumarta.com/software/maru/ 141 | * https://github.com/hraberg/akeem 142 | 143 | ### Other potential targets 144 | 145 | * http://nim-lang.org/ 146 | * http://www.gnu.org/software/libjit/ 147 | * http://www.rust-lang.org/ 148 | * http://julialang.org/ 149 | * http://llvm.org/ 150 | * http://openjdk.java.net/projects/graal/ / Indy JVM 151 | * https://software.intel.com/en-us/articles/introduction-to-x64-assembly 152 | 153 | ## License 154 | 155 | **cljs2go** 156 | 157 | Copyright © 2014 Håkan Råberg 158 | 159 | Distributed under the Eclipse Public License either version 1.0 or (at 160 | your option) any later version. 161 | 162 | **ClojureScript** 163 | 164 | Copyright (c) Rich Hickey. All rights reserved. The use and 165 | distribution terms for this software are covered by the Eclipse 166 | Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 167 | which can be found in the file epl-v10.html at the root of this 168 | distribution. By using this software in any fashion, you are 169 | agreeing to be bound by the terms of this license. You must 170 | not remove this notice, or any other, from this software. 171 | -------------------------------------------------------------------------------- /baz/baz.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // baz 3 | 4 | package baz 5 | 6 | import cljs_core "github.com/hraberg/cljs2go/cljs/core" 7 | 8 | func init() { 9 | F = func(f *cljs_core.AFn) *cljs_core.AFn { 10 | return cljs_core.Fn(f, 1, func(x interface{}) interface{} { 11 | return x 12 | }) 13 | }(&cljs_core.AFn{}) 14 | 15 | } 16 | 17 | var F *cljs_core.AFn 18 | -------------------------------------------------------------------------------- /bench_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | 5 | import "github.com/stretchr/testify/assert" 6 | 7 | import . "github.com/hraberg/cljs2go/cljs/core" 8 | 9 | func Benchmark_RecursiveDirectCall(t *testing.B) { 10 | fib := func(this *AFn) *AFn { 11 | return Fn(this, func(n interface{}) interface{} { 12 | if n == 0.0 { 13 | return 0.0 14 | } else if n == 1.0 { 15 | return 1.0 16 | } else { 17 | return this.X_invoke_Arity1(n.(float64)-1.0).(float64) + 18 | this.X_invoke_Arity1(n.(float64)-2.0).(float64) 19 | } 20 | }) 21 | }(&AFn{}) 22 | assert.Equal(t, 832040, fib.X_invoke_Arity1(30.0)) 23 | } 24 | 25 | func Benchmark_RecursiveDirectPrimitiveCall(t *testing.B) { 26 | fib := func(this *AFn) *AFn { 27 | return Fn(this, func(n float64) float64 { 28 | if n == 0.0 { 29 | return 0.0 30 | } else if n == 1.0 { 31 | return 1.0 32 | } else { 33 | return this.Arity1FF(n-1.0) + this.Arity1FF(n-2.0) 34 | } 35 | }) 36 | }(&AFn{}) 37 | assert.Equal(t, 832040, fib.X_invoke_Arity1(30.0)) 38 | } 39 | 40 | func Benchmark_RecursiveDispatch(t *testing.B) { 41 | fib := func(this *AFn) *AFn { 42 | return Fn(this, func(a interface{}) interface{} { 43 | var n = a.(float64) 44 | if n == 0.0 { 45 | return 0.0 46 | } else if n == 1.0 { 47 | return 1.0 48 | } else { 49 | return this.Call(n-1.0).(float64) + this.Call(n-2.0).(float64) 50 | } 51 | }) 52 | }(&AFn{}) 53 | assert.Equal(t, 832040, fib.Call(30.0)) 54 | } 55 | 56 | func Benchmark_RecursiveGo(t *testing.B) { 57 | fib := func() func(float64) float64 { 58 | var this func(float64) float64 59 | this = func(n float64) float64 { 60 | if n == 0 { 61 | return 0 62 | } else if n == 1 { 63 | return 1 64 | } else { 65 | return this(n-1) + this(n-2) 66 | } 67 | } 68 | return this 69 | }() 70 | assert.Equal(t, 832040, fib(30)) 71 | } 72 | -------------------------------------------------------------------------------- /cljs/binding_test/binding_test.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // cljs.binding-test 3 | 4 | package binding_test 5 | 6 | import ( 7 | "strings" 8 | "testing" 9 | 10 | cljs_binding_test_other_ns "github.com/hraberg/cljs2go/cljs/binding_test_other_ns" 11 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 12 | "github.com/hraberg/cljs2go/js" 13 | "github.com/stretchr/testify/assert" 14 | ) 15 | 16 | func init() { 17 | Test_binding = func(test_binding *cljs_core.AFn) *cljs_core.AFn { 18 | return cljs_core.Fn(test_binding, 0, func() interface{} { 19 | { 20 | var _STAR_foo_STAR_2_3 = cljs_binding_test_other_ns.X_STAR_foo_STAR_ 21 | _ = _STAR_foo_STAR_2_3 22 | func() { 23 | defer func() { 24 | cljs_binding_test_other_ns.X_STAR_foo_STAR_ = _STAR_foo_STAR_2_3 25 | 26 | }() 27 | { 28 | cljs_binding_test_other_ns.X_STAR_foo_STAR_ = float64(2) 29 | 30 | if cljs_core.X_EQ_.Arity2IIB(cljs_binding_test_other_ns.X_STAR_foo_STAR_, float64(2)) { 31 | } else { 32 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= o/*foo* 2)").(string)}, ``)})) 33 | } 34 | } 35 | }() 36 | } 37 | if cljs_core.X_EQ_.Arity2IIB(cljs_binding_test_other_ns.X_STAR_foo_STAR_, float64(1)) { 38 | return nil 39 | } else { 40 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= o/*foo* 1)").(string)}, ``)})) 41 | } 42 | }) 43 | }(&cljs_core.AFn{}) 44 | 45 | Test_with_redefs = func(test_with_redefs *cljs_core.AFn) *cljs_core.AFn { 46 | return cljs_core.Fn(test_with_redefs, 0, func() interface{} { 47 | { 48 | var bar5_6 = cljs_binding_test_other_ns.Bar 49 | _ = bar5_6 50 | func() { 51 | defer func() { 52 | cljs_binding_test_other_ns.Bar = bar5_6 53 | 54 | }() 55 | { 56 | cljs_binding_test_other_ns.Bar = float64(2) 57 | 58 | if cljs_core.X_EQ_.Arity2IIB(cljs_binding_test_other_ns.Bar, float64(2)) { 59 | } else { 60 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= o/bar 2)").(string)}, ``)})) 61 | } 62 | } 63 | }() 64 | } 65 | if cljs_core.X_EQ_.Arity2IIB(cljs_binding_test_other_ns.Bar, float64(10)) { 66 | return nil 67 | } else { 68 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= o/bar 10)").(string)}, ``)})) 69 | } 70 | }) 71 | }(&cljs_core.AFn{}) 72 | 73 | } 74 | 75 | var Test_binding *cljs_core.AFn 76 | 77 | var Test_with_redefs *cljs_core.AFn 78 | 79 | func Test_runner(t *testing.T) { 80 | Test_binding.X_invoke_Arity0() 81 | Test_with_redefs.X_invoke_Arity0() 82 | assert.True(t, true) 83 | } 84 | -------------------------------------------------------------------------------- /cljs/binding_test_other_ns/binding_test_other_ns.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // cljs.binding-test-other-ns 3 | 4 | package binding_test_other_ns 5 | 6 | func init() { 7 | X_STAR_foo_STAR_ = float64(1) 8 | 9 | Bar = float64(10) 10 | 11 | } 12 | 13 | var X_STAR_foo_STAR_ float64 14 | 15 | var Bar float64 16 | -------------------------------------------------------------------------------- /cljs/core/core_test.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | "testing" 8 | ) 9 | import ( 10 | gstring "github.com/hraberg/cljs2go/goog/string" 11 | "github.com/hraberg/cljs2go/js" 12 | "github.com/hraberg/cljs2go/js/Math" 13 | "github.com/stretchr/testify/assert" 14 | ) 15 | 16 | func Test_Main(t *testing.T) { 17 | var mainArgs []interface{} 18 | X_STAR_main_cli_fn_STAR_ = Fn(func(args__ ...interface{}) interface{} { 19 | mainArgs = args__ 20 | return nil 21 | }) 22 | Main_() 23 | assert.Equal(t, 1, len(mainArgs)) 24 | } 25 | 26 | var Baz = Fn(1, func(args ...interface{}) interface{} { 27 | x := args[0] 28 | xs := args[1] 29 | _ = x 30 | return Into_array.X_invoke_Arity1(xs) 31 | }, func(x interface{}) interface{} { 32 | return x 33 | }) 34 | 35 | func Test_Invoke(t *testing.T) { 36 | assert.True(t, Native_satisfies_QMARK_.X_invoke_Arity2(reflect.TypeOf((*CljsCoreIFn)(nil)).Elem(), Baz).(bool)) 37 | PanicsWith(t, "Invalid arity: 0", func() { Baz.Call() }) 38 | PanicsWith(t, "Invalid arity: 0", func() { Baz.X_invoke_Arity0() }) 39 | assert.Equal(t, 1, Baz.MaxFixedArity) 40 | assert.True(t, Baz.isVariadic()) 41 | assert.Equal(t, "Hello", Baz.X_invoke_Arity1("Hello")) 42 | assert.Equal(t, "Hello", X_invoke.X_invoke_Arity2(Baz, "Hello")) 43 | assert.Equal(t, []interface{}{"World"}, Baz.Call("Hello", Array_seq.X_invoke_Arity1([]interface{}{"World"}))) 44 | assert.Equal(t, []interface{}{"World"}, Baz.X_invoke_ArityVariadic("Hello", Array_seq.X_invoke_Arity1([]interface{}{"World"}))) 45 | assert.Equal(t, []interface{}{"World"}, X_invoke.X_invoke_ArityVariadic(Baz, "Hello", Array_seq.X_invoke_Arity1([]interface{}{"World"}))) 46 | assert.Equal(t, []interface{}{"World"}, X_invoke.Call(Baz, "Hello", Array_seq.X_invoke_Arity1([]interface{}{"World"}))) 47 | assert.Equal(t, []interface{}{"World"}, Apply.X_invoke_Arity2(Baz, Array_seq.X_invoke_Arity1([]interface{}{"Hello", "World"}))) 48 | assert.Equal(t, []interface{}{"World"}, Apply.X_invoke_Arity3(Baz, "Hello", Array_seq.X_invoke_Arity1([]interface{}{"World"}))) 49 | 50 | assert.Equal(t, []interface{}{"Another", "Brave", "And", "New", "World"}, 51 | Apply.X_invoke_ArityVariadic(Baz, "Hello", "Another", "Brave", "And", Array_seq.X_invoke_Arity1([]interface{}{"New", Array_seq.X_invoke_Arity1([]interface{}{"World"})}))) 52 | 53 | assert.Equal(t, 0, Apply.X_invoke_Arity2(X_PLUS_, Array_seq.X_invoke_Arity1([]interface{}{}))) 54 | assert.Equal(t, 0, Apply.X_invoke_Arity2(X_PLUS_, CljsCorePersistentVector_EMPTY)) 55 | assert.Equal(t, 5, Apply.X_invoke_Arity2(X_PLUS_, Array_seq.X_invoke_Arity1([]interface{}{5.0}))) 56 | assert.Equal(t, 5, Apply.X_invoke_Arity2(X_PLUS_, Array_seq.X_invoke_Arity1([]interface{}{2.0, 3.0}))) 57 | assert.Equal(t, 1, Apply.X_invoke_Arity3(X_PLUS_, 1.0, CljsCorePersistentVector_EMPTY)) 58 | assert.Equal(t, 6, Apply.X_invoke_Arity3(X_PLUS_, 1.0, Array_seq.X_invoke_Arity1([]interface{}{2.0, 3.0}))) 59 | assert.Equal(t, 8, Apply.X_invoke_Arity4(X_PLUS_, 1.0, 2.0, Array_seq.X_invoke_Arity1([]interface{}{5.0}))) 60 | assert.Equal(t, 15, Apply.X_invoke_ArityVariadic(X_PLUS_, 1.0, 2.0, 3.0, 4.0, Array_seq.X_invoke_Arity1([]interface{}{Array_seq.X_invoke_Arity1([]interface{}{5.0})}))) 61 | 62 | assert.Equal(t, 3, Apply.X_invoke_Arity3(X_PLUS_, float64(1), CljsCoreList_EMPTY.X_conj_Arity2(float64(2)))) 63 | assert.Equal(t, 1, Count.X_invoke_Arity1(Apply.X_invoke_Arity3(List, 1.0, CljsCorePersistentVector_EMPTY))) 64 | assert.Equal(t, 1, Count.X_invoke_Arity1(Apply.X_invoke_Arity2(List, Array_seq.X_invoke_Arity1([]interface{}{5.0})))) 65 | assert.Equal(t, 0, Count.X_invoke_Arity1(Apply.X_invoke_Arity2(List, CljsCorePersistentVector_EMPTY))) 66 | 67 | assert.Equal(t, []interface{}{"World"}, Baz.X_invoke_Arity2("Hello", "World")) 68 | assert.Equal(t, []interface{}{"World", "Space"}, Baz.X_invoke_Arity3("Hello", "World", "Space")) 69 | 70 | assert.Equal(t, "", Str.X_invoke_Arity0()) 71 | assert.Equal(t, "Hello", Str.X_invoke_Arity1("Hello")) 72 | assert.Equal(t, "1", Str.X_invoke_Arity1(1.0)) 73 | assert.Equal(t, "HelloClojureWorld", Str.X_invoke_ArityVariadic("Hello", Array_seq.X_invoke_Arity1([]interface{}{"Clojure", "World"}))) 74 | } 75 | 76 | func Test_Int32BitOperations(t *testing.T) { 77 | assert.Equal(t, -2023406815.0, Bit_or.X_invoke_Arity2(float64(0x87654321), 0.0)) 78 | assert.Equal(t, 1985229336.0, Bit_or.X_invoke_Arity2(float64(0x76543218), 0.0)) 79 | assert.Equal(t, 1985229328.0, Bit_shift_left.X_invoke_Arity2(float64(0x87654321), 4.0)) 80 | assert.Equal(t, 141972530.0, Unsigned_bit_shift_right.X_invoke_Arity2(float64(0x87654321), 4.0)) 81 | assert.Equal(t, 8.0, Unsigned_bit_shift_right.X_invoke_Arity2(float64(0x87654321), -4.0)) 82 | 83 | assert.Equal(t, 8.0, Unsigned_bit_shift_right.X_invoke_Arity2(Bit_or.X_invoke_Arity2(float64(0x87654321), 0.0), -4.0)) 84 | assert.Equal(t, 141972530.0, Unsigned_bit_shift_right.X_invoke_Arity2(Bit_or.X_invoke_Arity2(float64(0x87654321), 0.0), 4.0)) 85 | assert.Equal(t, 1985229336.0, Int_rotate_left.X_invoke_Arity2(Bit_or.X_invoke_Arity2(float64(0x87654321), 0.0), 4.0)) 86 | assert.Equal(t, 1985229336.0, Bit_or.X_invoke_Arity2(float64(0x76543218), 0.0)) 87 | 88 | assert.Equal(t, Int_rotate_left.X_invoke_Arity2(Bit_or.X_invoke_Arity2(float64(0x87654321), 0.0), 4.0), 89 | Bit_or.X_invoke_Arity2(float64(0x76543218), 0.0)) 90 | 91 | assert.Equal(t, -2023406815, Int32_(float64(int(float64(2271560481))|int(float64(0)))), 0) 92 | 93 | assert.Equal(t, Hash.X_invoke_Arity1((&CljsCoreKeyword{Ns: nil, Name: "a", Fqn: "a", X_hash: float64(-2123407586)})), 94 | Hash.X_invoke_Arity1(Keyword.X_invoke_Arity1("a"))) 95 | } 96 | 97 | func Test_PrimitiveFn(t *testing.T) { 98 | fib := func(this *AFn) *AFn { 99 | return Fn(this, func(n float64) float64 { 100 | if n == 0.0 { 101 | return 0.0 102 | } else if n == 1.0 { 103 | return 1.0 104 | } else { 105 | return this.Arity1FF(n-1.0) + this.Arity1FF(n-2.0) 106 | } 107 | }) 108 | }(&AFn{}) 109 | PanicsWith(t, "Invalid arity: 0", func() { fib.Call() }) 110 | assert.Equal(t, 832040, fib.X_invoke_Arity1(30.0)) 111 | 112 | odd := Fn(func(n interface{}) bool { 113 | return int(n.(float64))%2 != 0 114 | }) 115 | assert.NotNil(t, odd.Arity1IB) 116 | assert.NotNil(t, odd.Arity1) 117 | assert.True(t, odd.X_invoke_Arity1(1.0).(bool)) 118 | assert.False(t, odd.Arity1IB(2.0)) 119 | 120 | assert.True(t, Not.X_invoke_Arity1(false).(bool)) 121 | assert.False(t, Not.Arity1IB(true)) 122 | } 123 | 124 | func Test_Protocols(t *testing.T) { 125 | symbol := Symbol.X_invoke_Arity2("foo", "bar") 126 | 127 | assert.True(t, symbol.(CljsCoreObject).Equiv(Symbol.X_invoke_Arity2("foo", "bar"))) 128 | assert.True(t, Native_satisfies_QMARK_.X_invoke_Arity2(reflect.TypeOf((*CljsCoreObject)(nil)).Elem(), symbol).(bool)) 129 | assert.True(t, Native_satisfies_QMARK_.X_invoke_Arity2(reflect.TypeOf((*CljsCoreINamed)(nil)).Elem(), symbol).(bool)) 130 | assert.True(t, Native_satisfies_QMARK_.X_invoke_Arity2(reflect.TypeOf((*CljsCoreIFn)(nil)).Elem(), symbol).(bool)) 131 | assert.Equal(t, "foo", symbol.(CljsCoreINamed).X_namespace_Arity1()) 132 | assert.Equal(t, "foo", X_namespace.X_invoke_Arity1(symbol)) 133 | PanicsWith(t, "Invalid arity: 0", func() { symbol.(*CljsCoreSymbol).X_invoke_Arity0() }) 134 | PanicsWith(t, "Invalid arity: 0", func() { X_invoke.X_invoke_Arity1(symbol) }) 135 | 136 | assert.Equal(t, "foo", Namespace.X_invoke_Arity1(symbol)) 137 | PanicsWith(t, "Doesn't support namespace: 2", func() { Namespace.X_invoke_Arity1(2.0) }) 138 | 139 | assert.Equal(t, "bar", Name.X_invoke_Arity1(symbol)) 140 | PanicsWith(t, "Doesn't support name: 2", func() { Name.X_invoke_Arity1(2.0) }) 141 | assert.Equal(t, "baz", Name.X_invoke_Arity1("baz")) 142 | 143 | assert.Equal(t, "foo", X_invoke.X_invoke_Arity2(X_namespace, symbol)) 144 | assert.Equal(t, "bar", symbol.(CljsCoreINamed).X_name_Arity1()) 145 | assert.Equal(t, "foo/bar", symbol.(fmt.Stringer).String()) 146 | 147 | assert.Equal(t, 0, Decorate_(nil).(CljsCoreICounted).X_count_Arity1()) 148 | } 149 | 150 | func Test_InteropViaReflection(t *testing.T) { 151 | sb := &gstring.StringBuffer{"foo"} 152 | assert.Equal(t, "foo", Native_get_instance_field.X_invoke_Arity2(sb, "Buffer"), 153 | "(.-buffer sb)") 154 | Native_set_instance_field.X_invoke_Arity3(sb, "Buffer", "bar") 155 | assert.Equal(t, "bar", sb.Buffer, 156 | "(set! (.-buffer sb) \"bar\")") 157 | assert.Equal(t, sb, Native_invoke_instance_method.X_invoke_Arity3(sb, "Append", []interface{}{"baz"})) 158 | assert.Equal(t, "barbaz", sb.String(), 159 | "(.append sb \"baz\")") 160 | 161 | assert.Equal(t, "H", Native_invoke_instance_method.X_invoke_Arity3("Hello", "CharAt", []interface{}{0.0})) 162 | 163 | assert.Equal(t, js.Number.MAX_VALUE, Native_get_instance_field.X_invoke_Arity2(js.Number, "MAX_VALUE"), 164 | "(.-MAX-VALUE js/Number)") 165 | 166 | assert.Equal(t, 3, Native_invoke_func.X_invoke_Arity2(Math.Floor, []interface{}{3.14}), 167 | "(Math/floor 3.14)") 168 | assert.Equal(t, "3.14", Native_invoke_func.X_invoke_Arity2(fmt.Sprint, []interface{}{3.14}), 169 | "(fmt/Sprint 3.14)") 170 | assert.Equal(t, 3.14, Native_invoke_func.X_invoke_Arity2(js.ParseFloat, []interface{}{"3.14"}), 171 | "(js/parseFloat \"3.14\")") 172 | 173 | assert.Equal(t, "ABC", Native_invoke_func.X_invoke_Arity2(js.String.FromCharCode, []interface{}{65.0, 66.0, 67.0}), 174 | "(.fromCharCode js/String 65 66 67)") 175 | } 176 | 177 | func PanicsWith(t *testing.T, message string, f assert.PanicTestFunc) { 178 | assert.Equal(t, message, func() (message string) { 179 | defer func() { message = fmt.Sprint(recover()) }() 180 | f() 181 | assert.Fail(t, "should panic") 182 | return 183 | }()) 184 | } 185 | -------------------------------------------------------------------------------- /cljs/keyword_other/keyword_other.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // cljs.keyword-other 3 | 4 | package keyword_other 5 | 6 | import cljs_core "github.com/hraberg/cljs2go/cljs/core" 7 | 8 | func init() { 9 | Foo = func(foo___1 *cljs_core.AFn) *cljs_core.AFn { 10 | return cljs_core.Fn(foo___1, 2, func(a interface{}, b interface{}) interface{} { 11 | return (a.(float64) + b.(float64)) 12 | }) 13 | }(&cljs_core.AFn{}) 14 | 15 | } 16 | 17 | var Foo *cljs_core.AFn 18 | -------------------------------------------------------------------------------- /cljs/keyword_test/keyword_test.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // cljs.keyword-test 3 | 4 | package keyword_test 5 | 6 | import ( 7 | "strings" 8 | "testing" 9 | 10 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 11 | "github.com/hraberg/cljs2go/js" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | func init() { 16 | Test_keyword = func(test_keyword *cljs_core.AFn) *cljs_core.AFn { 17 | return cljs_core.Fn(test_keyword, 0, func() interface{} { 18 | if cljs_core.X_EQ_.Arity2IIB((&cljs_core.CljsCoreKeyword{Ns: "cljs.keyword-test", Name: "bar", Fqn: "cljs.keyword-test/bar", X_hash: float64(757060530)}), (&cljs_core.CljsCoreKeyword{Ns: "cljs.keyword-test", Name: "bar", Fqn: "cljs.keyword-test/bar", X_hash: float64(757060530)})) { 19 | } else { 20 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= :cljs.keyword-test/bar :cljs.keyword-test/bar)").(string)}, ``)})) 21 | } 22 | if cljs_core.X_EQ_.Arity2IIB((&cljs_core.CljsCoreKeyword{Ns: "cljs.keyword-other", Name: "foo", Fqn: "cljs.keyword-other/foo", X_hash: float64(-1299575836)}), (&cljs_core.CljsCoreKeyword{Ns: "cljs.keyword-other", Name: "foo", Fqn: "cljs.keyword-other/foo", X_hash: float64(-1299575836)})) { 23 | } else { 24 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= :cljs.keyword-other/foo :cljs.keyword-other/foo)").(string)}, ``)})) 25 | } 26 | if cljs_core.X_EQ_.Arity2IIB((&cljs_core.CljsCoreKeyword{Ns: "clojure.core", Name: "foo", Fqn: "clojure.core/foo", X_hash: float64(2105943067)}), (&cljs_core.CljsCoreKeyword{Ns: "clojure.core", Name: "foo", Fqn: "clojure.core/foo", X_hash: float64(2105943067)})) { 27 | return nil 28 | } else { 29 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= :clojure.core/foo :clojure.core/foo)").(string)}, ``)})) 30 | } 31 | }) 32 | }(&cljs_core.AFn{}) 33 | 34 | } 35 | 36 | var Test_keyword *cljs_core.AFn 37 | 38 | func Test_runner(t *testing.T) { 39 | Test_keyword.X_invoke_Arity0() 40 | assert.True(t, true) 41 | } 42 | -------------------------------------------------------------------------------- /cljs/letfn_test/letfn_test.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // cljs.letfn-test 3 | 4 | package letfn_test 5 | 6 | import ( 7 | "strings" 8 | "testing" 9 | 10 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 11 | "github.com/hraberg/cljs2go/js" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | func init() { 16 | Test_letfn = func(test_letfn *cljs_core.AFn) *cljs_core.AFn { 17 | return cljs_core.Fn(test_letfn, 0, func() interface{} { 18 | { 19 | var ev_QMARK_, od_QMARK_ *cljs_core.AFn 20 | ev_QMARK_ = func(ev_QMARK_ *cljs_core.AFn) *cljs_core.AFn { 21 | return cljs_core.Fn(ev_QMARK_, 1, func(x interface{}) interface{} { 22 | if x.(float64) == float64(0) { 23 | return true 24 | } else { 25 | return od_QMARK_.X_invoke_Arity1((x.(float64) - float64(1))) 26 | } 27 | }) 28 | }(&cljs_core.AFn{}) 29 | od_QMARK_ = func(od_QMARK_ *cljs_core.AFn) *cljs_core.AFn { 30 | return cljs_core.Fn(od_QMARK_, 1, func(x interface{}) interface{} { 31 | if x.(float64) == float64(0) { 32 | return false 33 | } else { 34 | return ev_QMARK_.X_invoke_Arity1((x.(float64) - float64(1))) 35 | } 36 | }) 37 | }(&cljs_core.AFn{}) 38 | _, _ = ev_QMARK_, od_QMARK_ 39 | if cljs_core.Truth_(ev_QMARK_.X_invoke_Arity1(float64(0))) { 40 | } else { 41 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(ev? 0)").(string)}, ``)})) 42 | } 43 | if cljs_core.Truth_(ev_QMARK_.X_invoke_Arity1(float64(10))) { 44 | } else { 45 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(ev? 10)").(string)}, ``)})) 46 | } 47 | if cljs_core.Not.Arity1IB(ev_QMARK_.X_invoke_Arity1(float64(1))) { 48 | } else { 49 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(not (ev? 1))").(string)}, ``)})) 50 | } 51 | if cljs_core.Not.Arity1IB(ev_QMARK_.X_invoke_Arity1(float64(11))) { 52 | } else { 53 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(not (ev? 11))").(string)}, ``)})) 54 | } 55 | if cljs_core.Not.Arity1IB(od_QMARK_.X_invoke_Arity1(float64(0))) { 56 | } else { 57 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(not (od? 0))").(string)}, ``)})) 58 | } 59 | if cljs_core.Not.Arity1IB(od_QMARK_.X_invoke_Arity1(float64(10))) { 60 | } else { 61 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(not (od? 10))").(string)}, ``)})) 62 | } 63 | if cljs_core.Truth_(od_QMARK_.X_invoke_Arity1(float64(1))) { 64 | } else { 65 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(od? 1)").(string)}, ``)})) 66 | } 67 | if cljs_core.Truth_(od_QMARK_.X_invoke_Arity1(float64(11))) { 68 | return nil 69 | } else { 70 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(od? 11)").(string)}, ``)})) 71 | } 72 | } 73 | }) 74 | }(&cljs_core.AFn{}) 75 | 76 | } 77 | 78 | var Test_letfn *cljs_core.AFn 79 | 80 | func Test_runner(t *testing.T) { 81 | Test_letfn.X_invoke_Arity0() 82 | assert.True(t, true) 83 | } 84 | -------------------------------------------------------------------------------- /cljs/macro_test/macro_test.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // cljs.macro-test 3 | 4 | package macro_test 5 | 6 | import ( 7 | "strings" 8 | "testing" 9 | 10 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 11 | "github.com/hraberg/cljs2go/js" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | func init() { 16 | Test_macros = func(test_macros *cljs_core.AFn) *cljs_core.AFn { 17 | return cljs_core.Fn(test_macros, 0, func() interface{} { 18 | if cljs_core.X_EQ_.Arity2IIB((float64(1) + float64(1)), float64(2)) { 19 | return nil 20 | } else { 21 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= (== 1 1) 2)").(string)}, ``)})) 22 | } 23 | }) 24 | }(&cljs_core.AFn{}) 25 | 26 | } 27 | 28 | var Test_macros *cljs_core.AFn 29 | 30 | func Test_runner(t *testing.T) { 31 | Test_macros.X_invoke_Arity0() 32 | assert.True(t, true) 33 | } 34 | -------------------------------------------------------------------------------- /cljs/ns_test/bar/bar.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // cljs.ns-test.bar 3 | 4 | package bar 5 | 6 | import cljs_core "github.com/hraberg/cljs2go/cljs/core" 7 | 8 | func init() { 9 | Quux = func(quux *cljs_core.AFn) *cljs_core.AFn { 10 | return cljs_core.Fn(quux, 0, func() interface{} { 11 | return float64(123) 12 | }) 13 | }(&cljs_core.AFn{}) 14 | 15 | } 16 | 17 | var Quux *cljs_core.AFn 18 | -------------------------------------------------------------------------------- /cljs/ns_test/foo/foo.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // cljs.ns-test.foo 3 | 4 | package foo 5 | 6 | import ( 7 | "strings" 8 | 9 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 10 | "github.com/hraberg/cljs2go/js" 11 | ) 12 | 13 | func init() { 14 | Baz = func(baz *cljs_core.AFn) *cljs_core.AFn { 15 | return cljs_core.Fn(baz, 0, func() interface{} { 16 | return float64(123) 17 | }) 18 | }(&cljs_core.AFn{}) 19 | 20 | Kw = (&cljs_core.CljsCoreKeyword{Ns: "cljs.ns-test.foo", Name: "foo", Fqn: "cljs.ns-test.foo/foo", X_hash: float64(-1760770742)}) 21 | 22 | Qkw = (&cljs_core.CljsCoreKeyword{Ns: "cljs.ns-test.foo", Name: "foo", Fqn: "cljs.ns-test.foo/foo", X_hash: float64(-1760770742)}) 23 | 24 | if cljs_core.X_EQ_.Arity2IIB(strings.Join([]string{cljs_core.Str.X_invoke_Arity1(Kw).(string)}, ``), ":cljs.ns-test.foo/foo") { 25 | } else { 26 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= (str kw) \":cljs.ns-test.foo/foo\")").(string)}, ``)})) 27 | } 28 | if cljs_core.X_EQ_.Arity2IIB(strings.Join([]string{cljs_core.Str.X_invoke_Arity1(Qkw).(string)}, ``), ":cljs.ns-test.foo/foo") { 29 | } else { 30 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= (str qkw) \":cljs.ns-test.foo/foo\")").(string)}, ``)})) 31 | } 32 | } 33 | 34 | var Baz *cljs_core.AFn 35 | 36 | var Kw *cljs_core.CljsCoreKeyword 37 | 38 | var Qkw *cljs_core.CljsCoreKeyword 39 | -------------------------------------------------------------------------------- /cljs/ns_test/ns_test.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // cljs.ns-test 3 | 4 | package ns_test 5 | 6 | import ( 7 | "strings" 8 | "testing" 9 | 10 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 11 | cljs_ns_test_bar "github.com/hraberg/cljs2go/cljs/ns_test/bar" 12 | cljs_ns_test_foo "github.com/hraberg/cljs2go/cljs/ns_test/foo" 13 | clojure_set "github.com/hraberg/cljs2go/clojure/set" 14 | "github.com/hraberg/cljs2go/js" 15 | "github.com/stretchr/testify/assert" 16 | ) 17 | 18 | func init() { 19 | X_PLUS_ = cljs_core.X___ 20 | 21 | Test_ns = func(test_ns *cljs_core.AFn) *cljs_core.AFn { 22 | return cljs_core.Fn(test_ns, 0, func() interface{} { 23 | if cljs_core.X_EQ_.Arity2IIB(float64(4), ((float64(2) + float64(1)) + float64(1))) { 24 | } else { 25 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= 4 (clojure.core/+ 2 1 1))").(string)}, ``)})) 26 | } 27 | if cljs_core.X_EQ_.Arity2IIB(float64(0), func() interface{} { 28 | var G__13 = float64(2) 29 | var G__14 = float64(1) 30 | var G__15 = float64(1) 31 | _, _, _ = G__13, G__14, G__15 32 | return X_PLUS_.(cljs_core.CljsCoreIFn).X_invoke_Arity3(G__13, G__14, G__15) 33 | }()) { 34 | } else { 35 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= 0 (cljs.ns-test/+ 2 1 1))").(string)}, ``)})) 36 | } 37 | if cljs_core.X_EQ_.Arity2IIB(float64(0), func() interface{} { 38 | var G__16 = float64(2) 39 | var G__17 = float64(1) 40 | var G__18 = float64(1) 41 | _, _, _ = G__16, G__17, G__18 42 | return X_PLUS_.(cljs_core.CljsCoreIFn).X_invoke_Arity3(G__16, G__17, G__18) 43 | }()) { 44 | } else { 45 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= 0 (+ 2 1 1))").(string)}, ``)})) 46 | } 47 | if cljs_core.X_EQ_.Arity2IIB(float64(123), cljs_ns_test_foo.Baz.X_invoke_Arity0().(float64)) { 48 | } else { 49 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= 123 (baz))").(string)}, ``)})) 50 | } 51 | if cljs_core.X_EQ_.Arity2IIB(float64(123), cljs_ns_test_bar.Quux.X_invoke_Arity0().(float64)) { 52 | } else { 53 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= 123 (quux))").(string)}, ``)})) 54 | } 55 | if cljs_core.X_EQ_.Arity2IIB(cljs_core.Range_.X_invoke_Arity1(float64(5)).(*cljs_core.CljsCoreRange), func() *cljs_core.CljsCoreLazySeq { 56 | var iter__4951__auto__ = func(iter__19 *cljs_core.AFn) *cljs_core.AFn { 57 | return cljs_core.Fn(iter__19, 1, func(s__20 interface{}) interface{} { 58 | return (&cljs_core.CljsCoreLazySeq{nil, func(G__25 *cljs_core.AFn) *cljs_core.AFn { 59 | return cljs_core.Fn(G__25, 0, func() interface{} { 60 | { 61 | var s__20___1 interface{} = s__20 62 | _ = s__20___1 63 | for { 64 | { 65 | var temp__4388__auto__ = cljs_core.Seq.Arity1IQ(s__20___1) 66 | _ = temp__4388__auto__ 67 | if cljs_core.Truth_(temp__4388__auto__) { 68 | { 69 | var s__20___2 = temp__4388__auto__ 70 | _ = s__20___2 71 | if cljs_core.Chunked_seq_QMARK_.Arity1IB(s__20___2) { 72 | { 73 | var c__4949__auto__ = cljs_core.Chunk_first.X_invoke_Arity1(s__20___2) 74 | var size__4950__auto__ = float64(cljs_core.Int32_(cljs_core.Count.X_invoke_Arity1(c__4949__auto__).(float64))) 75 | var b__22 = cljs_core.Chunk_buffer.X_invoke_Arity1(size__4950__auto__).(*cljs_core.CljsCoreChunkBuffer) 76 | _, _, _ = c__4949__auto__, size__4950__auto__, b__22 77 | if func() bool { 78 | var i__21 = float64(cljs_core.Int32_(float64(0))) 79 | _ = i__21 80 | for { 81 | if i__21 < size__4950__auto__ { 82 | { 83 | var x = cljs_core.Native_invoke_instance_method.X_invoke_Arity3(c__4949__auto__, "Nth", []interface{}{i__21}) 84 | _ = x 85 | cljs_core.Chunk_append.X_invoke_Arity2(b__22, x) 86 | i__21 = (i__21 + float64(1)) 87 | continue 88 | } 89 | } else { 90 | return true 91 | } 92 | } 93 | }() { 94 | return cljs_core.Chunk_cons.X_invoke_Arity2(cljs_core.Chunk.X_invoke_Arity1(b__22), iter__19.X_invoke_Arity1(cljs_core.Chunk_rest.X_invoke_Arity1(s__20___2)).(*cljs_core.CljsCoreLazySeq)) 95 | } else { 96 | return cljs_core.Chunk_cons.X_invoke_Arity2(cljs_core.Chunk.X_invoke_Arity1(b__22), nil) 97 | } 98 | } 99 | } else { 100 | { 101 | var x = cljs_core.First.X_invoke_Arity1(s__20___2) 102 | _ = x 103 | return cljs_core.Cons.X_invoke_Arity2(x, iter__19.X_invoke_Arity1(cljs_core.Rest.Arity1IQ(s__20___2)).(*cljs_core.CljsCoreLazySeq)).(*cljs_core.CljsCoreCons) 104 | } 105 | } 106 | } 107 | } else { 108 | return nil 109 | } 110 | } 111 | } 112 | } 113 | }) 114 | }(&cljs_core.AFn{}), nil, nil}) 115 | }) 116 | }(&cljs_core.AFn{}) 117 | _ = iter__4951__auto__ 118 | return iter__4951__auto__.X_invoke_Arity1(cljs_core.Range_.X_invoke_Arity1(float64(5)).(*cljs_core.CljsCoreRange)).(*cljs_core.CljsCoreLazySeq) 119 | }()) { 120 | } else { 121 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= (range 5) (lang/for [x (range 5)] x))").(string)}, ``)})) 122 | } 123 | if cljs_core.X_EQ_.Arity2IIB((&cljs_core.CljsCorePersistentHashSet{nil, &cljs_core.CljsCorePersistentArrayMap{nil, float64(3), []interface{}{float64(1), nil, float64(3), nil, float64(2), nil}, nil}, nil}), clojure_set.Union.X_invoke_Arity2((&cljs_core.CljsCorePersistentHashSet{nil, &cljs_core.CljsCorePersistentArrayMap{nil, float64(1), []interface{}{float64(1), nil}, nil}, nil}), (&cljs_core.CljsCorePersistentHashSet{nil, &cljs_core.CljsCorePersistentArrayMap{nil, float64(2), []interface{}{float64(3), nil, float64(2), nil}, nil}, nil}))) { 124 | } else { 125 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= #{1 3 2} (s/union #{1} #{3 2}))").(string)}, ``)})) 126 | } 127 | return (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "ok", Fqn: "ok", X_hash: float64(967785236)}) 128 | }) 129 | }(&cljs_core.AFn{}) 130 | 131 | } 132 | 133 | var X_PLUS_ interface{} 134 | 135 | var Test_ns *cljs_core.AFn 136 | 137 | func Test_runner(t *testing.T) { 138 | assert.Equal(t, (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "ok", Fqn: "ok", X_hash: float64(967785236)}), Test_ns.X_invoke_Arity0().(*cljs_core.CljsCoreKeyword)) 139 | } 140 | -------------------------------------------------------------------------------- /cljs/reader/overrides.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // cljs.reader 3 | 4 | // Go overrides. 5 | package reader 6 | 7 | import ( 8 | "reflect" 9 | "strings" 10 | 11 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 12 | goog_string "github.com/hraberg/cljs2go/goog/string" 13 | "github.com/hraberg/cljs2go/js" 14 | ) 15 | 16 | func init() { 17 | Read_2_chars = func(read_2_chars *cljs_core.AFn) *cljs_core.AFn { 18 | return cljs_core.Fn(read_2_chars, 1, func(reader interface{}) interface{} { 19 | return strings.Join([]string{cljs_core.Str.X_invoke_Arity1(cljs_core.Decorate_(reader).(CljsReaderPushbackReader).Read_char_Arity1()).(string), cljs_core.Str.X_invoke_Arity1(cljs_core.Decorate_(reader).(CljsReaderPushbackReader).Read_char_Arity1()).(string)}, ``) 20 | }) 21 | }(&cljs_core.AFn{}) 22 | 23 | Read_4_chars = func(read_4_chars *cljs_core.AFn) *cljs_core.AFn { 24 | return cljs_core.Fn(read_4_chars, 1, func(reader interface{}) interface{} { 25 | return strings.Join([]string{cljs_core.Str.X_invoke_Arity1(cljs_core.Decorate_(reader).(CljsReaderPushbackReader).Read_char_Arity1()).(string), cljs_core.Str.X_invoke_Arity1(cljs_core.Decorate_(reader).(CljsReaderPushbackReader).Read_char_Arity1()).(string), cljs_core.Str.X_invoke_Arity1(cljs_core.Decorate_(reader).(CljsReaderPushbackReader).Read_char_Arity1()).(string), cljs_core.Str.X_invoke_Arity1(cljs_core.Decorate_(reader).(CljsReaderPushbackReader).Read_char_Arity1()).(string)}, ``) 26 | }) 27 | }(&cljs_core.AFn{}) 28 | 29 | Read_token = func(read_token *cljs_core.AFn) *cljs_core.AFn { 30 | return cljs_core.Fn(read_token, 2, func(rdr interface{}, initch interface{}) interface{} { 31 | { 32 | var sb = (&goog_string.StringBuffer{initch}) 33 | var ch interface{} = cljs_core.Decorate_(rdr).(CljsReaderPushbackReader).Read_char_Arity1() 34 | _, _ = sb, ch 35 | for { 36 | if (cljs_core.Nil_(ch)) || (Whitespace_QMARK_.Arity1IB(ch)) || (Macro_terminating_QMARK_.Arity1IB(ch)) { 37 | cljs_core.Decorate_(rdr).(CljsReaderPushbackReader).Unread_Arity2(ch) 38 | return cljs_core.Native_invoke_instance_method.X_invoke_Arity3(sb, "ToString", []interface{}{}) 39 | } else { 40 | sb, ch = func() *goog_string.StringBuffer { 41 | cljs_core.Native_invoke_instance_method.X_invoke_Arity3(sb, "Append", []interface{}{ch}) 42 | return sb 43 | }(), cljs_core.Decorate_(rdr).(CljsReaderPushbackReader).Read_char_Arity1() 44 | continue 45 | } 46 | } 47 | } 48 | }) 49 | }(&cljs_core.AFn{}) 50 | 51 | Macros = func(macros *cljs_core.AFn) *cljs_core.AFn { 52 | return cljs_core.Fn(macros, 1, func(c interface{}) interface{} { 53 | if reflect.DeepEqual(c, "\"") { 54 | return Read_string_STAR_ 55 | } else { 56 | if reflect.DeepEqual(c, ":") { 57 | return Read_keyword 58 | } else { 59 | if reflect.DeepEqual(c, ";") { 60 | return Read_comment 61 | } else { 62 | if reflect.DeepEqual(c, "'") { 63 | return Wrapping_reader.X_invoke_Arity1((&cljs_core.CljsCoreSymbol{Ns: nil, Name: "quote", Str: "quote", X_hash: float64(1377916282), X_meta: nil})).(cljs_core.CljsCoreIFn) 64 | } else { 65 | if reflect.DeepEqual(c, "@") { 66 | return Wrapping_reader.X_invoke_Arity1((&cljs_core.CljsCoreSymbol{Ns: nil, Name: "deref", Str: "deref", X_hash: float64(1494944732), X_meta: nil})).(cljs_core.CljsCoreIFn) 67 | } else { 68 | if reflect.DeepEqual(c, "^") { 69 | return Read_meta 70 | } else { 71 | if reflect.DeepEqual(c, "`") { 72 | return Not_implemented 73 | } else { 74 | if reflect.DeepEqual(c, "~") { 75 | return Not_implemented 76 | } else { 77 | if reflect.DeepEqual(c, "(") { 78 | return Read_list 79 | } else { 80 | if reflect.DeepEqual(c, ")") { 81 | return Read_unmatched_delimiter 82 | } else { 83 | if reflect.DeepEqual(c, "[") { 84 | return Read_vector 85 | } else { 86 | if reflect.DeepEqual(c, "]") { 87 | return Read_unmatched_delimiter 88 | } else { 89 | if reflect.DeepEqual(c, "{") { 90 | return Read_map 91 | } else { 92 | if reflect.DeepEqual(c, "}") { 93 | return Read_unmatched_delimiter 94 | } else { 95 | if reflect.DeepEqual(c, "\\") { 96 | return func(G__169 *cljs_core.AFn) *cljs_core.AFn { 97 | return cljs_core.Fn(G__169, 2, func(rdr interface{}, ___ interface{}) interface{} { 98 | return cljs_core.Decorate_(rdr).(CljsReaderPushbackReader).Read_char_Arity1() 99 | }) 100 | }(&cljs_core.AFn{}) 101 | } else { 102 | if reflect.DeepEqual(c, "#") { 103 | return Read_dispatch 104 | } else { 105 | return nil 106 | 107 | } 108 | } 109 | } 110 | } 111 | } 112 | } 113 | } 114 | } 115 | } 116 | } 117 | } 118 | } 119 | } 120 | } 121 | } 122 | } 123 | }) 124 | }(&cljs_core.AFn{}) 125 | 126 | Days_in_month = func() interface{} { 127 | var dim_norm = (&cljs_core.CljsCorePersistentVector{nil, float64(13), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{nil, float64(31), float64(28), float64(31), float64(30), float64(31), float64(30), float64(31), float64(31), float64(30), float64(31), float64(30), float64(31)}, nil}) 128 | var dim_leap = (&cljs_core.CljsCorePersistentVector{nil, float64(13), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{nil, float64(31), float64(29), float64(31), float64(30), float64(31), float64(30), float64(31), float64(31), float64(30), float64(31), float64(30), float64(31)}, nil}) 129 | _, _ = dim_norm, dim_leap 130 | return cljs_core.Identity.X_invoke_Arity1(func(G__170 *cljs_core.AFn, dim_norm cljs_core.CljsCoreIVector, dim_leap cljs_core.CljsCoreIVector) *cljs_core.AFn { 131 | return cljs_core.Fn(G__170, 2, func(month interface{}, leap_year_QMARK_ interface{}) interface{} { 132 | return cljs_core.Get.X_invoke_Arity2(func() cljs_core.CljsCoreIVector { 133 | if cljs_core.Truth_(leap_year_QMARK_) { 134 | return dim_leap 135 | } else { 136 | return dim_norm 137 | } 138 | }(), month) 139 | }) 140 | }(&cljs_core.AFn{}, dim_norm, dim_leap)) 141 | }() 142 | 143 | Parse_timestamp = func(parse_timestamp *cljs_core.AFn) *cljs_core.AFn { 144 | return cljs_core.Fn(parse_timestamp, 1, func(ts interface{}) interface{} { 145 | { 146 | var temp__4386__auto__ = Parse_and_validate_timestamp.X_invoke_Arity1(ts).(cljs_core.CljsCoreIVector) 147 | _ = temp__4386__auto__ 148 | if cljs_core.Truth_(temp__4386__auto__) { 149 | { 150 | var vec__172 = temp__4386__auto__ 151 | var years = cljs_core.Nth.X_invoke_Arity3(vec__172, float64(0), nil) 152 | var months = cljs_core.Nth.X_invoke_Arity3(vec__172, float64(1), nil) 153 | var days = cljs_core.Nth.X_invoke_Arity3(vec__172, float64(2), nil) 154 | var hours = cljs_core.Nth.X_invoke_Arity3(vec__172, float64(3), nil) 155 | var minutes = cljs_core.Nth.X_invoke_Arity3(vec__172, float64(4), nil) 156 | var seconds = cljs_core.Nth.X_invoke_Arity3(vec__172, float64(5), nil) 157 | var ms = cljs_core.Nth.X_invoke_Arity3(vec__172, float64(6), nil) 158 | var offset = cljs_core.Nth.X_invoke_Arity3(vec__172, float64(7), nil) 159 | _, _, _, _, _, _, _, _, _ = vec__172, years, months, days, hours, minutes, seconds, ms, offset 160 | return (&js.Date{ts}) 161 | } 162 | } else { 163 | return Reader_error.X_invoke_ArityVariadic(nil, cljs_core.Array_seq.X_invoke_Arity1([]interface{}{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Unrecognized date/time syntax: ").(string), cljs_core.Str.X_invoke_Arity1(ts).(string)}, ``)})) 164 | } 165 | } 166 | }) 167 | }(&cljs_core.AFn{}) 168 | 169 | Read_queue = func(read_queue *cljs_core.AFn) *cljs_core.AFn { 170 | return cljs_core.Fn(read_queue, 1, func(elems interface{}) interface{} { 171 | if cljs_core.Vector_QMARK_.Arity1IB(elems) { 172 | return cljs_core.Into.X_invoke_Arity2(cljs_core.CljsCorePersistentQueue_EMPTY, elems) 173 | } else { 174 | return Reader_error.X_invoke_ArityVariadic(nil, cljs_core.Array_seq.X_invoke_Arity1([]interface{}{"Queue literal expects a vector for its elements."})) 175 | } 176 | }) 177 | }(&cljs_core.AFn{}) 178 | 179 | Read_date = func(read_date *cljs_core.AFn) *cljs_core.AFn { 180 | return cljs_core.Fn(read_date, 1, func(s interface{}) interface{} { 181 | if cljs_core.Value_(s).Kind() == reflect.String { 182 | return Parse_timestamp.X_invoke_Arity1(s).(*js.Date) 183 | } else { 184 | return Reader_error.X_invoke_ArityVariadic(nil, cljs_core.Array_seq.X_invoke_Arity1([]interface{}{"Instance literal expects a string for its timestamp."})) 185 | } 186 | }) 187 | }(&cljs_core.AFn{}) 188 | 189 | Read_uuid = func(read_uuid *cljs_core.AFn) *cljs_core.AFn { 190 | return cljs_core.Fn(read_uuid, 1, func(uuid interface{}) interface{} { 191 | if cljs_core.Value_(uuid).Kind() == reflect.String { 192 | return (&cljs_core.CljsCoreUUID{uuid}) 193 | } else { 194 | return Reader_error.X_invoke_ArityVariadic(nil, cljs_core.Array_seq.X_invoke_Arity1([]interface{}{"UUID literal expects a string as its representation."})) 195 | } 196 | }) 197 | }(&cljs_core.AFn{}) 198 | 199 | X_STAR_tag_table_STAR_ = cljs_core.Atom.X_invoke_Arity1((&cljs_core.CljsCorePersistentArrayMap{nil, float64(3), []interface{}{"inst", Read_date, "uuid", Read_uuid, "queue", Read_queue}, nil})).(*cljs_core.CljsCoreAtom) 200 | 201 | } 202 | 203 | var Read_2_chars *cljs_core.AFn 204 | 205 | var Read_4_chars *cljs_core.AFn 206 | 207 | var Read_token *cljs_core.AFn 208 | 209 | var Macros *cljs_core.AFn 210 | 211 | var Days_in_month interface{} 212 | 213 | var Parse_timestamp *cljs_core.AFn 214 | 215 | var Read_queue *cljs_core.AFn 216 | 217 | var Read_date *cljs_core.AFn 218 | 219 | var Read_uuid *cljs_core.AFn 220 | 221 | var X_STAR_tag_table_STAR_ *cljs_core.CljsCoreAtom 222 | -------------------------------------------------------------------------------- /cljs/top_level_test/top_level_test.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // cljs.top-level-test 3 | 4 | package top_level_test 5 | 6 | import ( 7 | "strings" 8 | "testing" 9 | 10 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 11 | "github.com/hraberg/cljs2go/js" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | func init() { 16 | { 17 | var foo_1___1 = float64(1) 18 | _ = foo_1___1 19 | Bar = func(bar *cljs_core.AFn, foo_1___1 float64) *cljs_core.AFn { 20 | return cljs_core.Fn(bar, 0, func() interface{} { 21 | return foo_1___1 22 | }) 23 | }(&cljs_core.AFn{}, foo_1___1) 24 | 25 | } 26 | { 27 | var foo_2___1 = float64(2) 28 | _ = foo_2___1 29 | Baz = func(baz___1 *cljs_core.AFn, foo_2___1 float64) *cljs_core.AFn { 30 | return cljs_core.Fn(baz___1, 0, func() interface{} { 31 | return foo_2___1 32 | }) 33 | }(&cljs_core.AFn{}, foo_2___1) 34 | 35 | } 36 | Test = func(test *cljs_core.AFn) *cljs_core.AFn { 37 | return cljs_core.Fn(test, 0, func() interface{} { 38 | if cljs_core.X_EQ_.Arity2IIB(Bar.X_invoke_Arity0().(float64), float64(1)) { 39 | } else { 40 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= (bar) 1)").(string)}, ``)})) 41 | } 42 | if cljs_core.X_EQ_.Arity2IIB(Baz.X_invoke_Arity0().(float64), float64(2)) { 43 | return nil 44 | } else { 45 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= (baz) 2)").(string)}, ``)})) 46 | } 47 | }) 48 | }(&cljs_core.AFn{}) 49 | 50 | } 51 | 52 | var Bar *cljs_core.AFn 53 | 54 | var Baz *cljs_core.AFn 55 | 56 | var Test *cljs_core.AFn 57 | 58 | func Test_runner(t *testing.T) { 59 | Test.X_invoke_Arity0() 60 | assert.True(t, true) 61 | } 62 | -------------------------------------------------------------------------------- /clojure/data/data.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // clojure.data 3 | 4 | // Non-core data functions. 5 | // Author: Stuart Halloway 6 | package data 7 | 8 | import ( 9 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 10 | 11 | clojure_set "github.com/hraberg/cljs2go/clojure/set" 12 | ) 13 | 14 | func init() { 15 | Atom_diff = func(atom_diff *cljs_core.AFn) *cljs_core.AFn { 16 | return cljs_core.Fn(atom_diff, 2, func(a interface{}, b interface{}) interface{} { 17 | if cljs_core.X_EQ_.Arity2IIB(a, b) { 18 | return (&cljs_core.CljsCorePersistentVector{nil, float64(3), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{nil, nil, a}, nil}) 19 | } else { 20 | return (&cljs_core.CljsCorePersistentVector{nil, float64(3), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{a, b, nil}, nil}) 21 | } 22 | }) 23 | }(&cljs_core.AFn{}) 24 | 25 | Vectorize = func(vectorize *cljs_core.AFn) *cljs_core.AFn { 26 | return cljs_core.Fn(vectorize, 1, func(m interface{}) interface{} { 27 | if cljs_core.Truth_(cljs_core.Seq.Arity1IQ(m)) { 28 | return cljs_core.Reduce.X_invoke_Arity3(func(G__5 *cljs_core.AFn) *cljs_core.AFn { 29 | return cljs_core.Fn(G__5, 2, func(result interface{}, p__3 interface{}) interface{} { 30 | { 31 | var vec__4 = p__3 32 | var k = cljs_core.Nth.X_invoke_Arity3(vec__4, float64(0), nil) 33 | var v = cljs_core.Nth.X_invoke_Arity3(vec__4, float64(1), nil) 34 | _, _, _ = vec__4, k, v 35 | return cljs_core.Assoc.X_invoke_Arity3(result, k, v) 36 | } 37 | }) 38 | }(&cljs_core.AFn{}), cljs_core.Vec.X_invoke_Arity1(cljs_core.Repeat.X_invoke_Arity2(cljs_core.Apply.X_invoke_Arity2(cljs_core.Max, cljs_core.Keys.X_invoke_Arity1(m)), nil).(*cljs_core.CljsCoreLazySeq)), m) 39 | } else { 40 | return nil 41 | } 42 | }) 43 | }(&cljs_core.AFn{}) 44 | 45 | Diff_associative_key = func(diff_associative_key *cljs_core.AFn) *cljs_core.AFn { 46 | return cljs_core.Fn(diff_associative_key, 3, func(a interface{}, b interface{}, k interface{}) interface{} { 47 | { 48 | var va = cljs_core.Get.X_invoke_Arity2(a, k) 49 | var vb = cljs_core.Get.X_invoke_Arity2(b, k) 50 | var vec__9 = func() interface{} { 51 | var G__10 = va 52 | var G__11 = vb 53 | _, _ = G__10, G__11 54 | return Diff.X_invoke_Arity2(G__10, G__11) 55 | }() 56 | var a_STAR_ = cljs_core.Nth.X_invoke_Arity3(vec__9, float64(0), nil) 57 | var b_STAR_ = cljs_core.Nth.X_invoke_Arity3(vec__9, float64(1), nil) 58 | var ab = cljs_core.Nth.X_invoke_Arity3(vec__9, float64(2), nil) 59 | var in_a = cljs_core.Contains_QMARK_.Arity2IIB(a, k) 60 | var in_b = cljs_core.Contains_QMARK_.Arity2IIB(b, k) 61 | var same = (in_a) && (in_b) && ((!(cljs_core.Nil_(ab))) || ((cljs_core.Nil_(va)) && (cljs_core.Nil_(vb)))) 62 | _, _, _, _, _, _, _, _, _ = va, vb, vec__9, a_STAR_, b_STAR_, ab, in_a, in_b, same 63 | return (&cljs_core.CljsCorePersistentVector{nil, float64(3), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{func() interface{} { 64 | if (in_a) && ((!(cljs_core.Nil_(a_STAR_))) || (!(same))) { 65 | return cljs_core.CljsCorePersistentArrayMap_FromArray.X_invoke_Arity3([]interface{}{k, a_STAR_}, true, false).(*cljs_core.CljsCorePersistentArrayMap) 66 | } else { 67 | return nil 68 | } 69 | }(), func() interface{} { 70 | if (in_b) && ((!(cljs_core.Nil_(b_STAR_))) || (!(same))) { 71 | return cljs_core.CljsCorePersistentArrayMap_FromArray.X_invoke_Arity3([]interface{}{k, b_STAR_}, true, false).(*cljs_core.CljsCorePersistentArrayMap) 72 | } else { 73 | return nil 74 | } 75 | }(), func() interface{} { 76 | if cljs_core.Truth_(same) { 77 | return cljs_core.CljsCorePersistentArrayMap_FromArray.X_invoke_Arity3([]interface{}{k, ab}, true, false).(*cljs_core.CljsCorePersistentArrayMap) 78 | } else { 79 | return nil 80 | } 81 | }()}, nil}) 82 | } 83 | }) 84 | }(&cljs_core.AFn{}) 85 | 86 | Diff_associative = func(diff_associative *cljs_core.AFn) *cljs_core.AFn { 87 | return cljs_core.Fn(diff_associative, 3, func(a interface{}, b interface{}) interface{} { 88 | return diff_associative.X_invoke_Arity3(a, b, clojure_set.Union.X_invoke_Arity2(cljs_core.Keys.X_invoke_Arity1(a), cljs_core.Keys.X_invoke_Arity1(b))) 89 | }, func(a interface{}, b interface{}, ks interface{}) interface{} { 90 | return cljs_core.Reduce.X_invoke_Arity3(func(G__15 *cljs_core.AFn) *cljs_core.AFn { 91 | return cljs_core.Fn(G__15, 2, func(diff1 interface{}, diff2 interface{}) interface{} { 92 | return cljs_core.Doall.X_invoke_Arity1(cljs_core.Map_.X_invoke_Arity3(cljs_core.Merge, diff1, diff2).(*cljs_core.CljsCoreLazySeq)) 93 | }) 94 | }(&cljs_core.AFn{}), (&cljs_core.CljsCorePersistentVector{nil, float64(3), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{nil, nil, nil}, nil}), cljs_core.Map_.X_invoke_Arity2(cljs_core.Partial.X_invoke_Arity3(Diff_associative_key, a, b).(cljs_core.CljsCoreIFn), ks).(*cljs_core.CljsCoreLazySeq)) 95 | }) 96 | }(&cljs_core.AFn{}) 97 | 98 | Diff_sequential = func(diff_sequential *cljs_core.AFn) *cljs_core.AFn { 99 | return cljs_core.Fn(diff_sequential, 2, func(a interface{}, b interface{}) interface{} { 100 | return cljs_core.Vec.X_invoke_Arity1(cljs_core.Map_.X_invoke_Arity2(Vectorize, Diff_associative.X_invoke_Arity3(func() interface{} { 101 | if cljs_core.Vector_QMARK_.Arity1IB(a) { 102 | return a 103 | } else { 104 | return cljs_core.Vec.X_invoke_Arity1(a) 105 | } 106 | }(), func() interface{} { 107 | if cljs_core.Vector_QMARK_.Arity1IB(b) { 108 | return b 109 | } else { 110 | return cljs_core.Vec.X_invoke_Arity1(b) 111 | } 112 | }(), cljs_core.Range_.X_invoke_Arity1(func(x, y float64) float64 { 113 | if x > y { 114 | return x 115 | } else { 116 | return y 117 | } 118 | }(cljs_core.Count.X_invoke_Arity1(a).(float64), cljs_core.Count.X_invoke_Arity1(b).(float64))).(*cljs_core.CljsCoreRange))).(*cljs_core.CljsCoreLazySeq)) 119 | }) 120 | }(&cljs_core.AFn{}) 121 | 122 | Diff_set = func(diff_set *cljs_core.AFn) *cljs_core.AFn { 123 | return cljs_core.Fn(diff_set, 2, func(a interface{}, b interface{}) interface{} { 124 | return (&cljs_core.CljsCorePersistentVector{nil, float64(3), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{cljs_core.Not_empty.X_invoke_Arity1(clojure_set.Difference.X_invoke_Arity2(a, b)), cljs_core.Not_empty.X_invoke_Arity1(clojure_set.Difference.X_invoke_Arity2(b, a)), cljs_core.Not_empty.X_invoke_Arity1(clojure_set.Intersection.X_invoke_Arity2(a, b))}, nil}) 125 | }) 126 | }(&cljs_core.AFn{}) 127 | 128 | Equality_partition = func(equality_partition *cljs_core.AFn) *cljs_core.AFn { 129 | return cljs_core.Fn(equality_partition, 1, func(x interface{}) interface{} { 130 | return cljs_core.Decorate_(x).(ClojureDataEqualityPartition).Equality_partition_Arity1() 131 | }) 132 | }(&cljs_core.AFn{}) 133 | 134 | Diff_similar = func(diff_similar *cljs_core.AFn) *cljs_core.AFn { 135 | return cljs_core.Fn(diff_similar, 2, func(a interface{}, b interface{}) interface{} { 136 | return cljs_core.Decorate_(a).(ClojureDataDiff).Diff_similar_Arity2(b) 137 | }) 138 | }(&cljs_core.AFn{}) 139 | 140 | } 141 | 142 | // Internal helper for diff. 143 | var Atom_diff *cljs_core.AFn 144 | 145 | // Convert an associative-by-numeric-index collection into 146 | // an equivalent vector, with nil for any missing keys 147 | var Vectorize *cljs_core.AFn 148 | 149 | // Diff associative things a and b, comparing only the key k. 150 | var Diff_associative_key *cljs_core.AFn 151 | 152 | // Diff associative things a and b, comparing only keys in ks (if supplied). 153 | var Diff_associative *cljs_core.AFn 154 | 155 | var Diff_sequential *cljs_core.AFn 156 | 157 | var Diff_set *cljs_core.AFn 158 | 159 | type ClojureDataEqualityPartition interface { 160 | ClojureDataEqualityPartition__() 161 | Equality_partition_Arity1() interface{} 162 | } 163 | 164 | var Equality_partition *cljs_core.AFn 165 | 166 | type ClojureDataDiff interface { 167 | ClojureDataDiff__() 168 | Diff_similar_Arity2(b interface{}) interface{} 169 | } 170 | 171 | var Diff_similar *cljs_core.AFn 172 | -------------------------------------------------------------------------------- /clojure/data/overrides.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // clojure.data 3 | 4 | // Go overrides. 5 | package data 6 | 7 | import ( 8 | "reflect" 9 | "strings" 10 | 11 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 12 | "github.com/hraberg/cljs2go/js" 13 | ) 14 | 15 | func init() { 16 | Ep = func(ep *cljs_core.AFn) *cljs_core.AFn { 17 | return cljs_core.Fn(ep, 1, func(x interface{}) interface{} { 18 | if cljs_core.Nil_(x) { 19 | return (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "atom", Fqn: "atom", X_hash: float64(-397043653)}) 20 | } else { 21 | if cljs_core.Value_(x).Kind() == reflect.String { 22 | return (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "atom", Fqn: "atom", X_hash: float64(-397043653)}) 23 | } else { 24 | if cljs_core.Value_(x).Kind() == reflect.Float64 { 25 | return (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "atom", Fqn: "atom", X_hash: float64(-397043653)}) 26 | } else { 27 | if cljs_core.Value_(x).Kind() == reflect.Slice { 28 | return (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "sequential", Fqn: "sequential", X_hash: float64(-1082983960)}) 29 | } else { 30 | if cljs_core.Fn_QMARK_.Arity1IB(x) { 31 | return (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "atom", Fqn: "atom", X_hash: float64(-397043653)}) 32 | } else { 33 | if cljs_core.Value_(x).Kind() == reflect.Bool { 34 | return (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "atom", Fqn: "atom", X_hash: float64(-397043653)}) 35 | } else { 36 | if cljs_core.DecoratedValue_(x).Type().Implements(reflect.TypeOf((*cljs_core.CljsCoreIMap)(nil)).Elem()) { 37 | return (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "map", Fqn: "map", X_hash: float64(1371690461)}) 38 | } else { 39 | if cljs_core.DecoratedValue_(x).Type().Implements(reflect.TypeOf((*cljs_core.CljsCoreISet)(nil)).Elem()) { 40 | return (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "set", Fqn: "set", X_hash: float64(304602554)}) 41 | } else { 42 | if cljs_core.DecoratedValue_(x).Type().Implements(reflect.TypeOf((*cljs_core.CljsCoreISequential)(nil)).Elem()) { 43 | return (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "sequential", Fqn: "sequential", X_hash: float64(-1082983960)}) 44 | } else { 45 | return (&cljs_core.CljsCoreKeyword{Ns: nil, Name: "atom", Fqn: "atom", X_hash: float64(-397043653)}) 46 | 47 | } 48 | } 49 | } 50 | } 51 | } 52 | } 53 | } 54 | } 55 | } 56 | }) 57 | }(&cljs_core.AFn{}) 58 | 59 | Ds = func(ds *cljs_core.AFn) *cljs_core.AFn { 60 | return cljs_core.Fn(ds, 2, func(a interface{}, b interface{}) interface{} { 61 | return func() interface{} { 62 | var G__17 = func() interface{} { 63 | if cljs_core.Value_(Ep.X_invoke_Arity1(a).(*cljs_core.CljsCoreKeyword)).Type().AssignableTo(reflect.TypeOf((**cljs_core.CljsCoreKeyword)(nil)).Elem()) { 64 | return cljs_core.Native_get_instance_field.X_invoke_Arity2(cljs_core.Keyword.X_invoke_Arity1(Ep.X_invoke_Arity1(a).(*cljs_core.CljsCoreKeyword)), "Fqn") 65 | } else { 66 | return nil 67 | } 68 | }() 69 | _ = G__17 70 | switch G__17 { 71 | case "map": 72 | return Diff_associative 73 | 74 | case "sequential": 75 | return Diff_sequential 76 | 77 | case "set": 78 | return Diff_set 79 | 80 | case "atom": 81 | return Atom_diff 82 | 83 | default: 84 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("No matching clause: ").(string), cljs_core.Str.X_invoke_Arity1(Ep.X_invoke_Arity1(a).(*cljs_core.CljsCoreKeyword)).(string)}, ``)})) 85 | 86 | } 87 | }().(cljs_core.CljsCoreIFn).X_invoke_Arity2(a, b) 88 | }) 89 | }(&cljs_core.AFn{}) 90 | 91 | Diff = func(diff *cljs_core.AFn) *cljs_core.AFn { 92 | return cljs_core.Fn(diff, 2, func(a interface{}, b interface{}) interface{} { 93 | if cljs_core.X_EQ_.Arity2IIB(a, b) { 94 | return (&cljs_core.CljsCorePersistentVector{nil, float64(3), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{nil, nil, a}, nil}) 95 | } else { 96 | if cljs_core.X_EQ_.Arity2IIB(Ep.X_invoke_Arity1(a).(*cljs_core.CljsCoreKeyword), Ep.X_invoke_Arity1(b).(*cljs_core.CljsCoreKeyword)) { 97 | return Ds.X_invoke_Arity2(a, b) 98 | } else { 99 | return Atom_diff.X_invoke_Arity2(a, b).(cljs_core.CljsCoreIVector) 100 | } 101 | } 102 | }) 103 | }(&cljs_core.AFn{}) 104 | 105 | } 106 | 107 | var Ep *cljs_core.AFn 108 | 109 | var Ds *cljs_core.AFn 110 | 111 | // Recursively compares a and b, returning a tuple of 112 | // [things-only-in-a things-only-in-b things-in-both]. 113 | // Comparison rules: 114 | // 115 | // * For equal a and b, return [nil nil a]. 116 | // * Maps are subdiffed where keys match and values differ. 117 | // * Sets are never subdiffed. 118 | // * All sequential things are treated as associative collections 119 | // by their indexes, with results returned as vectors. 120 | // * Everything else (including strings!) is treated as 121 | // an atom and compared for equality. 122 | var Diff *cljs_core.AFn 123 | -------------------------------------------------------------------------------- /clojure/string/overrides.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // clojure.string 3 | 4 | // Go overrides. 5 | package string 6 | 7 | import ( 8 | "reflect" 9 | "strings" 10 | 11 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 12 | goog_string "github.com/hraberg/cljs2go/goog/string" 13 | "github.com/hraberg/cljs2go/js" 14 | ) 15 | 16 | func init() { 17 | Replace = func(replace *cljs_core.AFn) *cljs_core.AFn { 18 | return cljs_core.Fn(replace, 3, func(s interface{}, match interface{}, replacement interface{}) interface{} { 19 | if cljs_core.Value_(match).Kind() == reflect.String { 20 | return cljs_core.Native_invoke_instance_method.X_invoke_Arity3(s, "Replace", []interface{}{(&js.RegExp{func() interface{} { 21 | var G__31 = match 22 | _ = G__31 23 | return cljs_core.Native_invoke_func.X_invoke_Arity2(goog_string.RegExpEscape, []interface{}{G__31}) 24 | }(), "g"}), replacement}) 25 | } else { 26 | if cljs_core.Value_(match).Type().AssignableTo(reflect.TypeOf((**js.RegExp)(nil)).Elem()) { 27 | return cljs_core.Native_invoke_instance_method.X_invoke_Arity3(s, "Replace", []interface{}{(&js.RegExp{cljs_core.Native_get_instance_field.X_invoke_Arity2(match, "Pattern"), strings.Join([]string{cljs_core.Str.X_invoke_Arity1(cljs_core.Native_get_instance_field.X_invoke_Arity2(match, "Flags")).(string), cljs_core.Str.X_invoke_Arity1("g").(string)}, ``)}), func() interface{} { 28 | if cljs_core.Fn_QMARK_.Arity1IB(replacement) { 29 | return func(x interface{}) interface{} { return replacement.(cljs_core.CljsCoreIFn).X_invoke_Arity1(x) } 30 | } else { 31 | return replacement 32 | } 33 | }()}) 34 | } else { 35 | panic(strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Invalid match arg: ").(string), cljs_core.Str.X_invoke_Arity1(match).(string)}, ``)) 36 | 37 | } 38 | } 39 | }) 40 | }(&cljs_core.AFn{}) 41 | 42 | Replace_first = func(replace_first *cljs_core.AFn) *cljs_core.AFn { 43 | return cljs_core.Fn(replace_first, 3, func(s interface{}, match interface{}, replacement interface{}) interface{} { 44 | return cljs_core.Native_invoke_instance_method.X_invoke_Arity3(s, "Replace", []interface{}{match, func() interface{} { 45 | if cljs_core.Fn_QMARK_.Arity1IB(replacement) { 46 | return func(x interface{}) interface{} { return replacement.(cljs_core.CljsCoreIFn).X_invoke_Arity1(x) } 47 | } else { 48 | return replacement 49 | } 50 | }()}) 51 | }) 52 | }(&cljs_core.AFn{}) 53 | 54 | } 55 | 56 | // Replaces all instance of match with replacement in s. 57 | // match/replacement can be: 58 | // 59 | // string / string 60 | // pattern / (string or function of match). 61 | var Replace *cljs_core.AFn 62 | 63 | // Replaces the first instance of match with replacement in s. 64 | // match/replacement can be: 65 | // 66 | // string / string 67 | // pattern / (string or function of match). 68 | var Replace_first *cljs_core.AFn 69 | -------------------------------------------------------------------------------- /clojure/string/string.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // clojure.string 3 | 4 | package string 5 | 6 | import ( 7 | "strings" 8 | 9 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 10 | goog_string "github.com/hraberg/cljs2go/goog/string" 11 | "github.com/hraberg/cljs2go/js" 12 | ) 13 | 14 | func init() { 15 | Seq_reverse = func(seq_reverse *cljs_core.AFn) *cljs_core.AFn { 16 | return cljs_core.Fn(seq_reverse, 1, func(coll interface{}) interface{} { 17 | return cljs_core.Reduce.X_invoke_Arity3(cljs_core.Conj, cljs_core.CljsCoreIEmptyList(cljs_core.CljsCoreList_EMPTY), coll) 18 | }) 19 | }(&cljs_core.AFn{}) 20 | 21 | Re_surrogate_pair = (&js.RegExp{"([\\uD800-\\uDBFF])([\\uDC00-\\uDFFF])", "g"}) 22 | 23 | Reverse = func(reverse *cljs_core.AFn) *cljs_core.AFn { 24 | return cljs_core.Fn(reverse, 1, func(s interface{}) interface{} { 25 | return cljs_core.Native_invoke_instance_method.X_invoke_Arity3(cljs_core.Native_invoke_instance_method.X_invoke_Arity3(cljs_core.Native_invoke_instance_method.X_invoke_Arity3(cljs_core.Native_invoke_instance_method.X_invoke_Arity3(s, "Replace", []interface{}{Re_surrogate_pair, "$2$1"}), "Split", []interface{}{""}), "Reverse", []interface{}{}), "Join", []interface{}{""}) 26 | }) 27 | }(&cljs_core.AFn{}) 28 | 29 | Join = func(join *cljs_core.AFn) *cljs_core.AFn { 30 | return cljs_core.Fn(join, 2, func(coll interface{}) interface{} { 31 | return cljs_core.Apply.X_invoke_Arity2(cljs_core.Str, coll) 32 | }, func(separator interface{}, coll interface{}) interface{} { 33 | return cljs_core.Apply.X_invoke_Arity2(cljs_core.Str, cljs_core.Interpose.X_invoke_Arity2(separator, coll).(*cljs_core.CljsCoreLazySeq)) 34 | }) 35 | }(&cljs_core.AFn{}) 36 | 37 | Upper_case = func(upper_case *cljs_core.AFn) *cljs_core.AFn { 38 | return cljs_core.Fn(upper_case, 1, func(s interface{}) interface{} { 39 | return cljs_core.Native_invoke_instance_method.X_invoke_Arity3(s, "ToUpperCase", []interface{}{}) 40 | }) 41 | }(&cljs_core.AFn{}) 42 | 43 | Lower_case = func(lower_case *cljs_core.AFn) *cljs_core.AFn { 44 | return cljs_core.Fn(lower_case, 1, func(s interface{}) interface{} { 45 | return cljs_core.Native_invoke_instance_method.X_invoke_Arity3(s, "ToLowerCase", []interface{}{}) 46 | }) 47 | }(&cljs_core.AFn{}) 48 | 49 | Capitalize = func(capitalize *cljs_core.AFn) *cljs_core.AFn { 50 | return cljs_core.Fn(capitalize, 1, func(s interface{}) interface{} { 51 | if cljs_core.Count.X_invoke_Arity1(s).(float64) < float64(2) { 52 | return Upper_case.X_invoke_Arity1(s) 53 | } else { 54 | return strings.Join([]string{cljs_core.Str.X_invoke_Arity1(Upper_case.X_invoke_Arity1(cljs_core.Subs.X_invoke_Arity3(s, float64(0), float64(1)))).(string), cljs_core.Str.X_invoke_Arity1(Lower_case.X_invoke_Arity1(cljs_core.Subs.X_invoke_Arity2(s, float64(1)))).(string)}, ``) 55 | } 56 | }) 57 | }(&cljs_core.AFn{}) 58 | 59 | Pop_last_while_empty = func(pop_last_while_empty *cljs_core.AFn) *cljs_core.AFn { 60 | return cljs_core.Fn(pop_last_while_empty, 1, func(v interface{}) interface{} { 61 | { 62 | var v___1 interface{} = v 63 | _ = v___1 64 | for { 65 | if cljs_core.X_EQ_.Arity2IIB("", cljs_core.Peek.X_invoke_Arity1(v___1)) { 66 | v___1 = cljs_core.Pop.X_invoke_Arity1(v___1) 67 | continue 68 | } else { 69 | return v___1 70 | } 71 | } 72 | } 73 | }) 74 | }(&cljs_core.AFn{}) 75 | 76 | Discard_trailing_if_needed = func(discard_trailing_if_needed *cljs_core.AFn) *cljs_core.AFn { 77 | return cljs_core.Fn(discard_trailing_if_needed, 2, func(limit interface{}, v interface{}) interface{} { 78 | if cljs_core.X_EQ_.Arity2IIB(float64(0), limit) { 79 | return Pop_last_while_empty.X_invoke_Arity1(v) 80 | } else { 81 | return v 82 | } 83 | }) 84 | }(&cljs_core.AFn{}) 85 | 86 | Split_with_empty_regex = func(split_with_empty_regex *cljs_core.AFn) *cljs_core.AFn { 87 | return cljs_core.Fn(split_with_empty_regex, 2, func(s interface{}, limit interface{}) interface{} { 88 | if (limit.(float64) <= float64(0)) || (limit.(float64) >= (float64(2) + cljs_core.Count.X_invoke_Arity1(s).(float64))) { 89 | return cljs_core.Conj.X_invoke_Arity2(cljs_core.Vec.X_invoke_Arity1(cljs_core.Cons.X_invoke_Arity2("", cljs_core.Map_.X_invoke_Arity2(cljs_core.Str, cljs_core.Seq.Arity1IQ(s)).(*cljs_core.CljsCoreLazySeq)).(*cljs_core.CljsCoreCons)), "") 90 | } else { 91 | { 92 | var pred__10 = cljs_core.X_EQ_ 93 | var expr__11 = limit 94 | _, _ = pred__10, expr__11 95 | if cljs_core.Truth_(func() interface{} { 96 | var G__13 = float64(1) 97 | var G__14 = expr__11 98 | _, _ = G__13, G__14 99 | return pred__10.X_invoke_Arity2(G__13, G__14) 100 | }()) { 101 | return (&cljs_core.CljsCorePersistentVector{nil, float64(1), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{s}, nil}) 102 | } else { 103 | if cljs_core.Truth_(func() interface{} { 104 | var G__15 = float64(2) 105 | var G__16 = expr__11 106 | _, _ = G__15, G__16 107 | return pred__10.X_invoke_Arity2(G__15, G__16) 108 | }()) { 109 | return (&cljs_core.CljsCorePersistentVector{nil, float64(2), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{"", s}, nil}) 110 | } else { 111 | { 112 | var c = (limit.(float64) - float64(2)) 113 | _ = c 114 | return cljs_core.Conj.X_invoke_Arity2(cljs_core.Vec.X_invoke_Arity1(cljs_core.Cons.X_invoke_Arity2("", cljs_core.Subvec.X_invoke_Arity3(cljs_core.Vec.X_invoke_Arity1(cljs_core.Map_.X_invoke_Arity2(cljs_core.Str, cljs_core.Seq.Arity1IQ(s)).(*cljs_core.CljsCoreLazySeq)), float64(0), c).(*cljs_core.CljsCoreSubvec)).(*cljs_core.CljsCoreCons)), cljs_core.Subs.X_invoke_Arity2(s, c)) 115 | } 116 | } 117 | } 118 | } 119 | } 120 | }) 121 | }(&cljs_core.AFn{}) 122 | 123 | Split = func(split *cljs_core.AFn) *cljs_core.AFn { 124 | return cljs_core.Fn(split, 3, func(s interface{}, re interface{}) interface{} { 125 | return split.X_invoke_Arity3(s, re, float64(0)) 126 | }, func(s interface{}, re interface{}, limit interface{}) interface{} { 127 | return Discard_trailing_if_needed.X_invoke_Arity2(limit, func() interface{} { 128 | if cljs_core.X_EQ_.Arity2IIB(strings.Join([]string{cljs_core.Str.X_invoke_Arity1(re).(string)}, ``), "/(?:)/") { 129 | return Split_with_empty_regex.X_invoke_Arity2(s, limit) 130 | } else { 131 | return func() interface{} { 132 | if limit.(float64) < float64(1) { 133 | return cljs_core.Vec.X_invoke_Arity1(js.JSString_(strings.Join([]string{cljs_core.Str.X_invoke_Arity1(s).(string)}, ``)).Split(re)) 134 | } else { 135 | return func() interface{} { 136 | var s___1 interface{} = s 137 | var limit___1 interface{} = limit 138 | var parts interface{} = cljs_core.CljsCorePersistentVector_EMPTY 139 | _, _, _ = s___1, limit___1, parts 140 | for { 141 | if cljs_core.X_EQ_.Arity2IIB(limit___1, float64(1)) { 142 | return cljs_core.Conj.X_invoke_Arity2(parts, s___1) 143 | } else { 144 | { 145 | var temp__4386__auto__ = cljs_core.Re_find.X_invoke_Arity2(re, s___1) 146 | _ = temp__4386__auto__ 147 | if cljs_core.Truth_(temp__4386__auto__) { 148 | { 149 | var m = temp__4386__auto__ 150 | _ = m 151 | { 152 | var index = cljs_core.Native_invoke_instance_method.X_invoke_Arity3(s___1, "IndexOf", []interface{}{m}) 153 | _ = index 154 | s___1, limit___1, parts = cljs_core.Native_invoke_instance_method.X_invoke_Arity3(s___1, "Substring", []interface{}{(index.(float64) + cljs_core.Count.X_invoke_Arity1(m).(float64))}), (limit___1.(float64) - float64(1)), cljs_core.Conj.X_invoke_Arity2(parts, cljs_core.Native_invoke_instance_method.X_invoke_Arity3(s___1, "Substring", []interface{}{float64(0), index})) 155 | continue 156 | } 157 | } 158 | } else { 159 | return cljs_core.Conj.X_invoke_Arity2(parts, s___1) 160 | } 161 | } 162 | } 163 | } 164 | }() 165 | } 166 | }() 167 | } 168 | }()) 169 | }) 170 | }(&cljs_core.AFn{}) 171 | 172 | Split_lines = func(split_lines *cljs_core.AFn) *cljs_core.AFn { 173 | return cljs_core.Fn(split_lines, 1, func(s interface{}) interface{} { 174 | return Split.X_invoke_Arity2(s, (&js.RegExp{Pattern: `\n|\r\n`, Flags: ``})) 175 | }) 176 | }(&cljs_core.AFn{}) 177 | 178 | Trim = func(trim *cljs_core.AFn) *cljs_core.AFn { 179 | return cljs_core.Fn(trim, 1, func(s interface{}) interface{} { 180 | { 181 | var G__21 = s 182 | _ = G__21 183 | return cljs_core.Native_invoke_func.X_invoke_Arity2(goog_string.Trim, []interface{}{G__21}) 184 | } 185 | }) 186 | }(&cljs_core.AFn{}) 187 | 188 | Triml = func(triml *cljs_core.AFn) *cljs_core.AFn { 189 | return cljs_core.Fn(triml, 1, func(s interface{}) interface{} { 190 | { 191 | var G__23 = s 192 | _ = G__23 193 | return cljs_core.Native_invoke_func.X_invoke_Arity2(goog_string.TrimLeft, []interface{}{G__23}) 194 | } 195 | }) 196 | }(&cljs_core.AFn{}) 197 | 198 | Trimr = func(trimr *cljs_core.AFn) *cljs_core.AFn { 199 | return cljs_core.Fn(trimr, 1, func(s interface{}) interface{} { 200 | { 201 | var G__25 = s 202 | _ = G__25 203 | return cljs_core.Native_invoke_func.X_invoke_Arity2(goog_string.TrimRight, []interface{}{G__25}) 204 | } 205 | }) 206 | }(&cljs_core.AFn{}) 207 | 208 | Trim_newline = func(trim_newline *cljs_core.AFn) *cljs_core.AFn { 209 | return cljs_core.Fn(trim_newline, 1, func(s interface{}) interface{} { 210 | { 211 | var index interface{} = cljs_core.Native_get_instance_field.X_invoke_Arity2(s, "Length") 212 | _ = index 213 | for { 214 | if index.(float64) == float64(0) { 215 | return "" 216 | } else { 217 | { 218 | var ch = cljs_core.Get.X_invoke_Arity2(s, (index.(float64) - float64(1))) 219 | _ = ch 220 | if (cljs_core.X_EQ_.Arity2IIB(ch, "\n")) || (cljs_core.X_EQ_.Arity2IIB(ch, "\r")) { 221 | index = (index.(float64) - float64(1)) 222 | continue 223 | } else { 224 | return cljs_core.Native_invoke_instance_method.X_invoke_Arity3(s, "Substring", []interface{}{float64(0), index}) 225 | } 226 | } 227 | } 228 | } 229 | } 230 | }) 231 | }(&cljs_core.AFn{}) 232 | 233 | Blank_QMARK_ = func(blank_QMARK_ *cljs_core.AFn) *cljs_core.AFn { 234 | return cljs_core.Fn(blank_QMARK_, 1, func(s interface{}) interface{} { 235 | { 236 | var G__27 = s 237 | _ = G__27 238 | return cljs_core.Native_invoke_func.X_invoke_Arity2(goog_string.IsEmptySafe, []interface{}{G__27}) 239 | } 240 | }) 241 | }(&cljs_core.AFn{}) 242 | 243 | Escape = func(escape___1 *cljs_core.AFn) *cljs_core.AFn { 244 | return cljs_core.Fn(escape___1, 2, func(s interface{}, cmap interface{}) interface{} { 245 | { 246 | var buffer = (&goog_string.StringBuffer{}) 247 | var length = cljs_core.Native_get_instance_field.X_invoke_Arity2(s, "Length") 248 | _, _ = buffer, length 249 | { 250 | var index = float64(0) 251 | _ = index 252 | for { 253 | if cljs_core.X_EQ_.Arity2IIB(length, index) { 254 | return buffer.ToString() 255 | } else { 256 | { 257 | var ch = cljs_core.Native_invoke_instance_method.X_invoke_Arity3(s, "CharAt", []interface{}{index}) 258 | _ = ch 259 | { 260 | var temp__4386__auto___28 = cljs_core.Get.X_invoke_Arity2(cmap, ch) 261 | _ = temp__4386__auto___28 262 | if cljs_core.Truth_(temp__4386__auto___28) { 263 | { 264 | var replacement_29 = temp__4386__auto___28 265 | _ = replacement_29 266 | buffer.Append(strings.Join([]string{cljs_core.Str.X_invoke_Arity1(replacement_29).(string)}, ``)) 267 | } 268 | } else { 269 | buffer.Append(ch) 270 | } 271 | } 272 | index = (index + float64(1)) 273 | continue 274 | } 275 | } 276 | } 277 | } 278 | } 279 | }) 280 | }(&cljs_core.AFn{}) 281 | 282 | } 283 | 284 | var Seq_reverse *cljs_core.AFn 285 | 286 | var Re_surrogate_pair *js.RegExp 287 | 288 | // Returns s with its characters reversed. 289 | var Reverse *cljs_core.AFn 290 | 291 | // Returns a string of all elements in coll, as returned by (seq coll), 292 | // separated by an optional separator. 293 | var Join *cljs_core.AFn 294 | 295 | // Converts string to all upper-case. 296 | var Upper_case *cljs_core.AFn 297 | 298 | // Converts string to all lower-case. 299 | var Lower_case *cljs_core.AFn 300 | 301 | // Converts first character of the string to upper-case, all other 302 | // characters to lower-case. 303 | var Capitalize *cljs_core.AFn 304 | 305 | var Pop_last_while_empty *cljs_core.AFn 306 | 307 | var Discard_trailing_if_needed *cljs_core.AFn 308 | 309 | var Split_with_empty_regex *cljs_core.AFn 310 | 311 | // Splits string on a regular expression. Optional argument limit is 312 | // the maximum number of splits. Not lazy. Returns vector of the splits. 313 | var Split *cljs_core.AFn 314 | 315 | // Splits s on 316 | // or 317 | // . 318 | var Split_lines *cljs_core.AFn 319 | 320 | // Removes whitespace from both ends of string. 321 | var Trim *cljs_core.AFn 322 | 323 | // Removes whitespace from the left side of string. 324 | var Triml *cljs_core.AFn 325 | 326 | // Removes whitespace from the right side of string. 327 | var Trimr *cljs_core.AFn 328 | 329 | // Removes all trailing newline \n or return \r characters from 330 | // string. Similar to Perl's chomp. 331 | var Trim_newline *cljs_core.AFn 332 | 333 | // True is s is nil, empty, or contains only whitespace. 334 | var Blank_QMARK_ *cljs_core.AFn 335 | 336 | // Return a new string, using cmap to escape each character ch 337 | // from s as follows: 338 | // 339 | // If (cmap ch) is nil, append ch to the new string. 340 | // If (cmap ch) is non-nil, append (str (cmap ch)) instead. 341 | var Escape *cljs_core.AFn 342 | -------------------------------------------------------------------------------- /clojure/walk/walk.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // clojure.walk 3 | 4 | // This file defines a generic tree walker for Clojure data 5 | // structures. It takes any data structure (list, vector, map, set, 6 | // seq), calls a function on every element, and uses the return value 7 | // of the function in place of the original. This makes it fairly 8 | // easy to write recursive search-and-replace functions, as shown in 9 | // the examples. 10 | // 11 | // Note: "walk" supports all Clojure data structures EXCEPT maps 12 | // created with sorted-map-by. There is no (obvious) way to retrieve 13 | // the sorting function. 14 | // Author: Stuart Sierra 15 | package walk 16 | 17 | import ( 18 | "reflect" 19 | 20 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 21 | ) 22 | 23 | func init() { 24 | Walk = func(walk *cljs_core.AFn) *cljs_core.AFn { 25 | return cljs_core.Fn(walk, 3, func(inner interface{}, outer interface{}, form interface{}) interface{} { 26 | if cljs_core.Seq_QMARK_.Arity1IB(form) { 27 | { 28 | var G__4 = cljs_core.Doall.X_invoke_Arity1(cljs_core.Map_.X_invoke_Arity2(inner, form).(*cljs_core.CljsCoreLazySeq)) 29 | _ = G__4 30 | return outer.(cljs_core.CljsCoreIFn).X_invoke_Arity1(G__4) 31 | } 32 | } else { 33 | if cljs_core.Coll_QMARK_.Arity1IB(form) { 34 | { 35 | var G__5 = cljs_core.Into.X_invoke_Arity2(cljs_core.Empty.X_invoke_Arity1(form), cljs_core.Map_.X_invoke_Arity2(inner, form).(*cljs_core.CljsCoreLazySeq)) 36 | _ = G__5 37 | return outer.(cljs_core.CljsCoreIFn).X_invoke_Arity1(G__5) 38 | } 39 | } else { 40 | { 41 | var G__6 = form 42 | _ = G__6 43 | return outer.(cljs_core.CljsCoreIFn).X_invoke_Arity1(G__6) 44 | } 45 | 46 | } 47 | } 48 | }) 49 | }(&cljs_core.AFn{}) 50 | 51 | Postwalk = func(postwalk *cljs_core.AFn) *cljs_core.AFn { 52 | return cljs_core.Fn(postwalk, 2, func(f interface{}, form interface{}) interface{} { 53 | return Walk.X_invoke_Arity3(cljs_core.Partial.X_invoke_Arity2(postwalk, f).(cljs_core.CljsCoreIFn), f, form) 54 | }) 55 | }(&cljs_core.AFn{}) 56 | 57 | Prewalk = func(prewalk *cljs_core.AFn) *cljs_core.AFn { 58 | return cljs_core.Fn(prewalk, 2, func(f interface{}, form interface{}) interface{} { 59 | return Walk.X_invoke_Arity3(cljs_core.Partial.X_invoke_Arity2(prewalk, f).(cljs_core.CljsCoreIFn), cljs_core.Identity, func() interface{} { 60 | var G__8 = form 61 | _ = G__8 62 | return f.(cljs_core.CljsCoreIFn).X_invoke_Arity1(G__8) 63 | }()) 64 | }) 65 | }(&cljs_core.AFn{}) 66 | 67 | Keywordize_keys = func(keywordize_keys *cljs_core.AFn) *cljs_core.AFn { 68 | return cljs_core.Fn(keywordize_keys, 1, func(m interface{}) interface{} { 69 | { 70 | var f = func(G__13 *cljs_core.AFn) *cljs_core.AFn { 71 | return cljs_core.Fn(G__13, 1, func(p__11 interface{}) interface{} { 72 | { 73 | var vec__12 = p__11 74 | var k = cljs_core.Nth.X_invoke_Arity3(vec__12, float64(0), nil) 75 | var v = cljs_core.Nth.X_invoke_Arity3(vec__12, float64(1), nil) 76 | _, _, _ = vec__12, k, v 77 | if cljs_core.Value_(k).Kind() == reflect.String { 78 | return (&cljs_core.CljsCorePersistentVector{nil, float64(2), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{cljs_core.Keyword.X_invoke_Arity1(k), v}, nil}) 79 | } else { 80 | return (&cljs_core.CljsCorePersistentVector{nil, float64(2), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{k, v}, nil}) 81 | } 82 | } 83 | }) 84 | }(&cljs_core.AFn{}) 85 | _ = f 86 | return Postwalk.X_invoke_Arity2(func(G__14 *cljs_core.AFn, f cljs_core.CljsCoreIFn) *cljs_core.AFn { 87 | return cljs_core.Fn(G__14, 1, func(x interface{}) interface{} { 88 | if cljs_core.Map_QMARK_.Arity1IB(x) { 89 | return cljs_core.Into.X_invoke_Arity2(cljs_core.CljsCorePersistentArrayMap_EMPTY, cljs_core.Map_.X_invoke_Arity2(f, x).(*cljs_core.CljsCoreLazySeq)) 90 | } else { 91 | return x 92 | } 93 | }) 94 | }(&cljs_core.AFn{}, f), m) 95 | } 96 | }) 97 | }(&cljs_core.AFn{}) 98 | 99 | Stringify_keys = func(stringify_keys *cljs_core.AFn) *cljs_core.AFn { 100 | return cljs_core.Fn(stringify_keys, 1, func(m interface{}) interface{} { 101 | { 102 | var f = func(G__19 *cljs_core.AFn) *cljs_core.AFn { 103 | return cljs_core.Fn(G__19, 1, func(p__17 interface{}) interface{} { 104 | { 105 | var vec__18 = p__17 106 | var k = cljs_core.Nth.X_invoke_Arity3(vec__18, float64(0), nil) 107 | var v = cljs_core.Nth.X_invoke_Arity3(vec__18, float64(1), nil) 108 | _, _, _ = vec__18, k, v 109 | if cljs_core.Value_(k).Type().AssignableTo(reflect.TypeOf((**cljs_core.CljsCoreKeyword)(nil)).Elem()) { 110 | return (&cljs_core.CljsCorePersistentVector{nil, float64(2), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{cljs_core.Name.X_invoke_Arity1(k), v}, nil}) 111 | } else { 112 | return (&cljs_core.CljsCorePersistentVector{nil, float64(2), float64(5), cljs_core.CljsCorePersistentVector_EMPTY_NODE, []interface{}{k, v}, nil}) 113 | } 114 | } 115 | }) 116 | }(&cljs_core.AFn{}) 117 | _ = f 118 | return Postwalk.X_invoke_Arity2(func(G__20 *cljs_core.AFn, f cljs_core.CljsCoreIFn) *cljs_core.AFn { 119 | return cljs_core.Fn(G__20, 1, func(x interface{}) interface{} { 120 | if cljs_core.Map_QMARK_.Arity1IB(x) { 121 | return cljs_core.Into.X_invoke_Arity2(cljs_core.CljsCorePersistentArrayMap_EMPTY, cljs_core.Map_.X_invoke_Arity2(f, x).(*cljs_core.CljsCoreLazySeq)) 122 | } else { 123 | return x 124 | } 125 | }) 126 | }(&cljs_core.AFn{}, f), m) 127 | } 128 | }) 129 | }(&cljs_core.AFn{}) 130 | 131 | Prewalk_replace = func(prewalk_replace *cljs_core.AFn) *cljs_core.AFn { 132 | return cljs_core.Fn(prewalk_replace, 2, func(smap interface{}, form interface{}) interface{} { 133 | return Prewalk.X_invoke_Arity2(func(G__23 *cljs_core.AFn) *cljs_core.AFn { 134 | return cljs_core.Fn(G__23, 1, func(x interface{}) interface{} { 135 | if cljs_core.Contains_QMARK_.Arity2IIB(smap, x) { 136 | { 137 | var G__22 = x 138 | _ = G__22 139 | return smap.(cljs_core.CljsCoreIFn).X_invoke_Arity1(G__22) 140 | } 141 | } else { 142 | return x 143 | } 144 | }) 145 | }(&cljs_core.AFn{}), form) 146 | }) 147 | }(&cljs_core.AFn{}) 148 | 149 | Postwalk_replace = func(postwalk_replace *cljs_core.AFn) *cljs_core.AFn { 150 | return cljs_core.Fn(postwalk_replace, 2, func(smap interface{}, form interface{}) interface{} { 151 | return Postwalk.X_invoke_Arity2(func(G__26 *cljs_core.AFn) *cljs_core.AFn { 152 | return cljs_core.Fn(G__26, 1, func(x interface{}) interface{} { 153 | if cljs_core.Contains_QMARK_.Arity2IIB(smap, x) { 154 | { 155 | var G__25 = x 156 | _ = G__25 157 | return smap.(cljs_core.CljsCoreIFn).X_invoke_Arity1(G__25) 158 | } 159 | } else { 160 | return x 161 | } 162 | }) 163 | }(&cljs_core.AFn{}), form) 164 | }) 165 | }(&cljs_core.AFn{}) 166 | 167 | } 168 | 169 | // Traverses form, an arbitrary data structure. inner and outer are 170 | // functions. Applies inner to each element of form, building up a 171 | // data structure of the same type, then applies outer to the result. 172 | // Recognizes all Clojure data structures. Consumes seqs as with doall. 173 | var Walk *cljs_core.AFn 174 | 175 | // Performs a depth-first, post-order traversal of form. Calls f on 176 | // each sub-form, uses f's return value in place of the original. 177 | // Recognizes all Clojure data structures. Consumes seqs as with doall. 178 | var Postwalk *cljs_core.AFn 179 | 180 | // Like postwalk, but does pre-order traversal. 181 | var Prewalk *cljs_core.AFn 182 | 183 | // Recursively transforms all map keys from strings to keywords. 184 | var Keywordize_keys *cljs_core.AFn 185 | 186 | // Recursively transforms all map keys from keywords to strings. 187 | var Stringify_keys *cljs_core.AFn 188 | 189 | // Recursively transforms form by replacing keys in smap with their 190 | // values. Like clojure/replace but works on any data structure. Does 191 | // replacement at the root of the tree first. 192 | var Prewalk_replace *cljs_core.AFn 193 | 194 | // Recursively transforms form by replacing keys in smap with their 195 | // values. Like clojure/replace but works on any data structure. Does 196 | // replacement at the leaves of the tree first. 197 | var Postwalk_replace *cljs_core.AFn 198 | -------------------------------------------------------------------------------- /foo/ns_shadow_test/ns_shadow_test.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2411 2 | // foo.ns-shadow-test 3 | 4 | package ns_shadow_test 5 | 6 | import ( 7 | "strings" 8 | "testing" 9 | 10 | cljs_core "github.com/hraberg/cljs2go/cljs/core" 11 | "github.com/hraberg/cljs2go/js" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | func init() { 16 | Bar = func(bar *cljs_core.AFn) *cljs_core.AFn { 17 | return cljs_core.Fn(bar, 0, func() interface{} { 18 | return float64(1) 19 | }) 20 | }(&cljs_core.AFn{}) 21 | 22 | Quux = func(quux *cljs_core.AFn) *cljs_core.AFn { 23 | return cljs_core.Fn(quux, 1, func(foo___1 interface{}) interface{} { 24 | return (Bar.X_invoke_Arity0().(float64) + foo___1.(float64)) 25 | }) 26 | }(&cljs_core.AFn{}) 27 | 28 | Id = func(id *cljs_core.AFn) *cljs_core.AFn { 29 | return cljs_core.Fn(id, 1, func(x interface{}) interface{} { 30 | return x 31 | }) 32 | }(&cljs_core.AFn{}) 33 | 34 | Foo = func(foo___1 *cljs_core.AFn) *cljs_core.AFn { 35 | return cljs_core.Fn(foo___1, 0, func() interface{} { 36 | return Id.X_invoke_Arity1(float64(42)) 37 | }) 38 | }(&cljs_core.AFn{}) 39 | 40 | Baz = func(baz___1 *cljs_core.AFn) *cljs_core.AFn { 41 | return cljs_core.Fn(baz___1, 1, func() interface{} { 42 | return baz___1.X_invoke_Arity1(float64(2)).(float64) 43 | }, func(x interface{}) interface{} { 44 | return Quux.X_invoke_Arity1(float64(2)).(float64) 45 | }) 46 | }(&cljs_core.AFn{}) 47 | 48 | Test_shadow = func(test_shadow *cljs_core.AFn) *cljs_core.AFn { 49 | return cljs_core.Fn(test_shadow, 0, func() interface{} { 50 | if cljs_core.X_EQ_.Arity2IIB(Quux.X_invoke_Arity1(float64(2)).(float64), float64(3)) { 51 | } else { 52 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= (quux 2) 3)").(string)}, ``)})) 53 | } 54 | if cljs_core.X_EQ_.Arity2IIB(Foo.X_invoke_Arity0(), float64(42)) { 55 | } else { 56 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= (foo) 42)").(string)}, ``)})) 57 | } 58 | if cljs_core.X_EQ_.Arity2IIB(Baz.X_invoke_Arity0().(float64), float64(3)) { 59 | return nil 60 | } else { 61 | panic((&js.Error{strings.Join([]string{cljs_core.Str.X_invoke_Arity1("Assert failed: ").(string), cljs_core.Str.X_invoke_Arity1("(= (baz) 3)").(string)}, ``)})) 62 | } 63 | }) 64 | }(&cljs_core.AFn{}) 65 | 66 | } 67 | 68 | var Bar *cljs_core.AFn 69 | 70 | var Quux *cljs_core.AFn 71 | 72 | var Id *cljs_core.AFn 73 | 74 | var Foo *cljs_core.AFn 75 | 76 | var Baz *cljs_core.AFn 77 | 78 | var Test_shadow *cljs_core.AFn 79 | 80 | func Test_runner(t *testing.T) { 81 | Test_shadow.X_invoke_Arity0() 82 | assert.True(t, true) 83 | } 84 | -------------------------------------------------------------------------------- /goog/array/array.go: -------------------------------------------------------------------------------- 1 | package array 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "sort" 7 | ) 8 | 9 | //func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] || isNaN(p[i]) && !isNaN(p[j]) } 10 | 11 | func DefaultCompare(x, y interface{}) interface{} { 12 | switch y := y.(type) { 13 | case string: 14 | if y == x { 15 | return 0.0 16 | } else if y < x.(string) { 17 | return 1.0 18 | } else { 19 | return -1.0 20 | } 21 | case float64: 22 | if y == x { 23 | return 0.0 24 | } else if y < x.(float64) { 25 | return 1.0 26 | } else { 27 | return -1.0 28 | } 29 | case bool: 30 | if y == x { 31 | return 0.0 32 | } else if y { 33 | return -1.0 34 | } else { 35 | return 1.0 36 | } 37 | default: 38 | panic(fmt.Sprintf("Cannot compare %v", y)) 39 | } 40 | } 41 | 42 | type JSComparator struct { 43 | a []interface{} 44 | comp func(a, b interface{}) interface{} 45 | } 46 | 47 | func (this JSComparator) Len() int { return len(this.a) } 48 | func (this JSComparator) Swap(i, j int) { this.a[i], this.a[j] = this.a[j], this.a[i] } 49 | func (this JSComparator) Less(i, j int) bool { return this.comp(this.a[i], this.a[j]).(float64) < 0 } 50 | 51 | func StableSort(a []interface{}, comp func(a, b interface{}) interface{}) interface{} { 52 | sort.Sort(JSComparator{a, comp}) 53 | return nil 54 | } 55 | 56 | func Shuffle(a []interface{}) interface{} { 57 | for i := range a { 58 | j := rand.Intn(i + 1) 59 | a[i], a[j] = a[j], a[i] 60 | } 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /goog/goog.go: -------------------------------------------------------------------------------- 1 | package goog 2 | 3 | import "reflect" 4 | 5 | func TypeOf(x interface{}) string { 6 | if x == nil { 7 | return reflect.ValueOf(&x).Elem().Type().String() 8 | } 9 | return reflect.ValueOf(x).Type().String() 10 | } 11 | 12 | func IsArray(x interface{}) bool { 13 | return reflect.ValueOf(x).Kind() == reflect.Slice 14 | } 15 | 16 | func IsObject(x interface{}) bool { 17 | return reflect.ValueOf(x).Kind() == reflect.Map 18 | } 19 | 20 | func IsString(x interface{}) bool { 21 | return reflect.ValueOf(x).Kind() == reflect.String 22 | } 23 | 24 | func IsFunction(x interface{}) bool { 25 | return reflect.ValueOf(x).Kind() == reflect.Func 26 | } 27 | 28 | func GetUid(obj interface{}) float64 { 29 | return float64(reflect.ValueOf(&obj).Pointer()) 30 | } 31 | -------------------------------------------------------------------------------- /goog/goog_test.go: -------------------------------------------------------------------------------- 1 | package goog 2 | 3 | import "testing" 4 | 5 | import ( 6 | goog_array "github.com/hraberg/cljs2go/goog/array" 7 | goog_object "github.com/hraberg/cljs2go/goog/object" 8 | goog_string "github.com/hraberg/cljs2go/goog/string" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func Test_Goog(t *testing.T) { 13 | is := []interface{}{1.0, 2.0, 3.0, 4.0, 5.0} 14 | goog_array.Shuffle(is) 15 | goog_array.StableSort(is, func(a, b interface{}) interface{} { return b.(float64) - a.(float64) }) 16 | assert.Equal(t, []interface{}{5.0, 4.0, 3.0, 2.0, 1.0}, is) 17 | goog_array.Shuffle(is) 18 | goog_array.StableSort(is, goog_array.DefaultCompare) 19 | assert.Equal(t, []interface{}{1.0, 2.0, 3.0, 4.0, 5.0}, is) 20 | 21 | ss := []interface{}{"foo", "bar"} 22 | assert.True(t, IsArray(ss)) 23 | assert.False(t, IsObject(ss)) 24 | goog_array.StableSort(ss, goog_array.DefaultCompare) 25 | assert.Equal(t, []interface{}{"bar", "foo"}, ss) 26 | 27 | obj := goog_object.Create("foo", 2, "bar", 3) 28 | assert.True(t, IsObject(obj)) 29 | assert.False(t, IsArray(obj)) 30 | copy := map[string]interface{}{} 31 | goog_object.ForEach(obj, func(k, v, o interface{}) interface{} { 32 | assert.Equal(t, obj, o) 33 | assert.Equal(t, v, o.(map[string]interface{})[k.(string)]) 34 | copy[k.(string)] = v 35 | return nil 36 | }) 37 | assert.Equal(t, obj, copy) 38 | 39 | sb := goog_string.StringBuffer{} 40 | assert.Equal(t, "Hello JavaScript World", sb.Append("Hello Java").Append("Script World").String()) 41 | assert.Equal(t, "Hello JavaScript World", sb.String()) 42 | assert.Equal(t, 3.012568359e+09, (goog_string.HashCode("Hello World"))) 43 | 44 | s := "Hello World" 45 | assert.False(t, IsObject(s)) 46 | assert.True(t, IsString(s)) 47 | assert.Equal(t, "string", TypeOf(s)) 48 | assert.Equal(t, "interface {}", TypeOf(nil)) 49 | 50 | assert.True(t, IsFunction(func() {})) 51 | 52 | x, y := "Hello", "Hello" 53 | assert.Equal(t, x, y) 54 | assert.NotEqual(t, GetUid(x), GetUid(y)) 55 | 56 | assert.Equal(t, "\\[\\]\\(\\)", goog_string.RegExpEscape("[]()")) 57 | 58 | assert.Equal(t, "Hello", goog_string.Trim(" Hello\t\n")) 59 | assert.Equal(t, "Hello\t\n", goog_string.TrimLeft(" Hello\t\n")) 60 | assert.Equal(t, " Hello", goog_string.TrimRight(" Hello\t\n")) 61 | 62 | assert.False(t, goog_string.IsEmptySafe("Hello")) 63 | assert.False(t, goog_string.IsEmptySafe(" Hello")) 64 | assert.True(t, goog_string.IsEmptySafe(" \t \r")) 65 | assert.True(t, goog_string.IsEmptySafe("")) 66 | assert.True(t, goog_string.IsEmptySafe(nil)) 67 | 68 | assert.True(t, goog_string.IsNumeric("2")) 69 | assert.True(t, goog_string.IsNumeric("314")) 70 | assert.False(t, goog_string.IsNumeric("-1")) 71 | assert.False(t, goog_string.IsNumeric("2.0")) 72 | assert.False(t, goog_string.IsNumeric(" ")) 73 | assert.False(t, goog_string.IsNumeric("Foo")) 74 | 75 | assert.True(t, goog_string.IsBreakingWhitespace(" \t \r")) 76 | assert.False(t, goog_string.IsBreakingWhitespace(" \t Hello \r")) 77 | 78 | assert.False(t, goog_string.Contains("Hello", "foo")) 79 | assert.True(t, goog_string.Contains("Hello", "ello")) 80 | 81 | assert.Equal(t, ``, goog_string.BuildString()) 82 | assert.Equal(t, ``, goog_string.BuildString(``)) 83 | assert.Equal(t, ``, goog_string.BuildString(nil)) 84 | assert.Equal(t, `HelloWorld`, goog_string.BuildString(`Hello`, `World`)) 85 | } 86 | -------------------------------------------------------------------------------- /goog/object/object.go: -------------------------------------------------------------------------------- 1 | package object 2 | 3 | func Create(keyvals ...interface{}) map[string]interface{} { 4 | obj := make(map[string]interface{}, len(keyvals)/2) 5 | for i := 0; i < len(keyvals); i++ { 6 | obj[keyvals[i].(string)] = keyvals[i+1] 7 | i++ 8 | } 9 | return obj 10 | } 11 | 12 | func ForEach(obj map[string]interface{}, f func(k, v, obj interface{}) interface{}) interface{} { 13 | for k, v := range obj { 14 | f(k, v, obj) 15 | } 16 | return nil 17 | } 18 | -------------------------------------------------------------------------------- /goog/string/string.go: -------------------------------------------------------------------------------- 1 | package string 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "hash/fnv" 7 | "regexp" 8 | "strings" 9 | "unicode" 10 | ) 11 | 12 | type StringBuffer struct { 13 | Buffer interface{} 14 | } 15 | 16 | func (this *StringBuffer) buffer() *bytes.Buffer { 17 | switch this.Buffer.(type) { 18 | case *bytes.Buffer: 19 | case nil: 20 | this.Buffer = &bytes.Buffer{} 21 | default: 22 | this.Buffer = bytes.NewBufferString(fmt.Sprint(this.Buffer)) 23 | } 24 | return this.Buffer.(*bytes.Buffer) 25 | } 26 | 27 | func (this *StringBuffer) Equiv(other interface{}) bool { 28 | if ptr, instanceof := other.(*StringBuffer); instanceof { 29 | other = *ptr 30 | } 31 | return *this == other 32 | } 33 | 34 | func (this *StringBuffer) ToString() string { 35 | return this.buffer().String() 36 | } 37 | 38 | func (this *StringBuffer) String() string { 39 | return this.ToString() 40 | } 41 | 42 | func (this *StringBuffer) GetLength() float64 { 43 | return float64(this.buffer().Len()) 44 | } 45 | 46 | func (this *StringBuffer) Append(a1 interface{}) *StringBuffer { 47 | _, _ = this.buffer().WriteString(fmt.Sprint(a1)) 48 | return this 49 | } 50 | 51 | func HashCode(str string) float64 { 52 | h := fnv.New32a() 53 | _, _ = h.Write([]byte(str)) 54 | return float64(h.Sum32()) 55 | } 56 | 57 | func RegExpEscape(s string) string { 58 | return regexp.QuoteMeta(s) 59 | } 60 | 61 | func Trim(str string) string { 62 | return strings.TrimSpace(str) 63 | } 64 | 65 | func TrimLeft(str string) string { 66 | return strings.TrimLeftFunc(str, unicode.IsSpace) 67 | } 68 | 69 | func TrimRight(str string) string { 70 | return strings.TrimRightFunc(str, unicode.IsSpace) 71 | } 72 | 73 | func IsEmptySafe(str interface{}) bool { 74 | switch str := str.(type) { 75 | case string: 76 | return IsBreakingWhitespace(str) 77 | case nil: 78 | return true 79 | default: 80 | return false 81 | } 82 | } 83 | 84 | func IsNumeric(str string) bool { 85 | return len(strings.FieldsFunc(str, unicode.IsNumber)) == 0 86 | } 87 | 88 | func IsBreakingWhitespace(str string) bool { 89 | return len(strings.FieldsFunc(str, unicode.IsSpace)) == 0 90 | } 91 | 92 | func Contains(str, subString string) bool { 93 | return strings.Contains(str, subString) 94 | } 95 | 96 | func BuildString(var_args ...interface{}) string { 97 | ss := make([]string, len(var_args)) 98 | for i, v := range var_args { 99 | if v == nil { 100 | ss[i] = `` 101 | } else { 102 | ss[i] = fmt.Sprint(v) 103 | } 104 | } 105 | return strings.Join(ss, ``) 106 | } 107 | -------------------------------------------------------------------------------- /js/Math/Math.go: -------------------------------------------------------------------------------- 1 | package Math 2 | 3 | import ( 4 | "math" 5 | "math/rand" 6 | ) 7 | 8 | var PI = math.Pi 9 | 10 | func Floor(x float64) float64 { 11 | return math.Floor(x) 12 | } 13 | 14 | func Ceil(x float64) float64 { 15 | return math.Ceil(x) 16 | } 17 | 18 | func Random() float64 { 19 | return rand.Float64() 20 | } 21 | 22 | func Imul(a, b float64) float64 { 23 | return float64(int32(int32(int(a)) * int32(int(b)))) 24 | } 25 | -------------------------------------------------------------------------------- /js/js.go: -------------------------------------------------------------------------------- 1 | package js 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "math" 7 | "regexp" 8 | "strconv" 9 | "strings" 10 | "time" 11 | ) 12 | 13 | // This file contains a thin js runtime layer so ClojureScript itself can run with minimal modifications. 14 | 15 | type Error struct { 16 | Message interface{} 17 | } 18 | 19 | type TypeError struct { 20 | Message interface{} 21 | } 22 | 23 | func (e *Error) Error() string { 24 | return fmt.Sprint(e.Message) 25 | } 26 | 27 | func (e *TypeError) Error() string { 28 | return fmt.Sprint(e.Message) 29 | } 30 | 31 | type JSObject map[string]interface{} 32 | type JSNil struct{} 33 | type JSBoolean bool 34 | type JSNumber float64 35 | 36 | var Undefined interface{} 37 | var Symbol interface{} 38 | 39 | type Date struct { 40 | Millis interface{} 41 | } 42 | 43 | func (this *Date) time() time.Time { 44 | switch d := this.Millis.(type) { 45 | case time.Time: 46 | return d 47 | case string: 48 | for _, f := range []string{ 49 | "2006-01-02T15:04:05.000-07:00", 50 | "2006-01-02T15:04:05.000", 51 | "2006-01-02T15:04:05", 52 | "2006-01-02T15:04", 53 | "2006-01-02T15", 54 | "2006-01-02", 55 | "2006-01", 56 | "2006"} { 57 | if t, ok := time.Parse(f, d); ok == nil { 58 | this.Millis = t 59 | break 60 | } 61 | } 62 | case float64: 63 | this.Millis = time.Unix(int64(d)/1000, 1000*1000*(int64(d)%1000)) 64 | case int: 65 | this.Millis = time.Unix(int64(d)/1000, 1000*1000*(int64(d)%1000)) 66 | case nil: 67 | this.Millis = time.Now() 68 | } 69 | if d, ok := this.Millis.(time.Time); ok { 70 | return d 71 | } 72 | panic(&Error{fmt.Sprint("Unknown date type: %v", this.Millis)}) 73 | } 74 | 75 | func (this *Date) GetTime() float64 { 76 | return float64(this.time().UTC().UnixNano() / (1000 * 1000)) 77 | } 78 | 79 | func (this *Date) ValueOf() float64 { 80 | return this.GetTime() 81 | } 82 | 83 | func (this *Date) GetUTCFullYear() float64 { 84 | return float64(this.time().UTC().Year()) 85 | } 86 | 87 | func (this *Date) GetUTCMonth() float64 { 88 | return float64(this.time().UTC().Month() - 1) 89 | } 90 | 91 | func (this *Date) GetUTCDate() float64 { 92 | return float64(this.time().UTC().Day()) 93 | } 94 | 95 | func (this *Date) GetUTCHours() float64 { 96 | return float64(this.time().UTC().Hour()) 97 | } 98 | 99 | func (this *Date) GetUTCMinutes() float64 { 100 | return float64(this.time().UTC().Minute()) 101 | } 102 | 103 | func (this *Date) GetUTCSeconds() float64 { 104 | return float64(this.time().UTC().Second()) 105 | } 106 | 107 | func (this *Date) GetUTCMilliseconds() float64 { 108 | return float64(this.time().UTC().Nanosecond() / (1000 * 1000)) 109 | } 110 | 111 | func (this *Date) String() string { 112 | return this.time().String() 113 | } 114 | 115 | func (this *Date) ToString() string { 116 | return this.String() 117 | } 118 | 119 | type RegExp struct { 120 | Pattern interface{} 121 | Flags interface{} 122 | } 123 | 124 | var unicodeEscapeRegExp = regexp.MustCompile("\\\\u[[:xdigit:]]+") 125 | 126 | func (this *RegExp) pattern() string { 127 | if p, ok := this.Pattern.(string); ok { 128 | return unicodeEscapeRegExp.ReplaceAllStringFunc(p, 129 | func(s string) string { 130 | return String.FromCharCode(ParseInt(s[2:], 16)) 131 | }) 132 | } 133 | return "" 134 | } 135 | 136 | func (this *RegExp) flags() string { 137 | if f, ok := this.Flags.(string); ok { 138 | return f 139 | } 140 | return "" 141 | } 142 | 143 | func (this *RegExp) compile() *regexp.Regexp { 144 | pattern := this.pattern() 145 | flags := this.flags() 146 | if len(flags) != 0 { 147 | pattern = "(?" + strings.Replace(flags, "g", "", -1) + ")" + pattern 148 | } 149 | return regexp.MustCompile(pattern) 150 | } 151 | 152 | func (this *RegExp) Exec(str string) []interface{} { 153 | if match := this.compile().FindStringSubmatchIndex(str); match != nil { 154 | strs := make([]interface{}, len(match)/2) 155 | for i := range strs { 156 | idx := i * 2 157 | if match[idx] != -1 { 158 | strs[i] = str[match[idx]:match[idx+1]] 159 | } 160 | } 161 | return strs 162 | } 163 | return nil 164 | } 165 | 166 | func (this *RegExp) String() string { 167 | pattern := this.pattern() 168 | if pattern == "" { 169 | pattern = "(?:)" 170 | } 171 | return "/" + pattern + "/" + this.flags() 172 | } 173 | 174 | var Number = struct{ MAX_VALUE float64 }{math.MaxFloat64} 175 | 176 | var Infinity = math.Inf(1) 177 | var NaN = math.NaN() 178 | 179 | func IsNaN(x float64) bool { 180 | return math.IsNaN(x) 181 | } 182 | 183 | func ParseFloat(str interface{}) float64 { 184 | if str, ok := str.(string); ok { 185 | if val, err := strconv.ParseFloat(str, 64); err == nil { 186 | return val 187 | } 188 | } 189 | return math.NaN() 190 | } 191 | 192 | func ParseInt(str interface{}, radix float64) float64 { 193 | if str, ok := str.(string); ok { 194 | if val, err := strconv.ParseInt(str, int(radix), 64); err == nil { 195 | return float64(val) 196 | } 197 | } 198 | return math.NaN() 199 | } 200 | 201 | var String = struct { 202 | FromCharCode func(...float64) string 203 | }{func(num ...float64) string { 204 | var buffer bytes.Buffer 205 | for _, n := range num { 206 | _, _ = buffer.WriteRune(rune(int(n))) 207 | } 208 | return buffer.String() 209 | }} 210 | 211 | type JSString struct { 212 | Length float64 213 | str string 214 | } 215 | 216 | func JSString_(str string) *JSString { 217 | return &JSString{float64(len(str)), str} 218 | } 219 | 220 | func (this *JSString) Replace(match interface{}, replacement interface{}) string { 221 | var re *RegExp 222 | if exp, ok := match.(*RegExp); ok { 223 | re = exp 224 | } else { 225 | re = &RegExp{regexp.QuoteMeta(fmt.Sprint(match)), ``} 226 | } 227 | global := strings.Contains(re.Flags.(string), "g") 228 | var f func(string) string 229 | if rf, ok := replacement.(func(interface{}) interface{}); ok { 230 | f = func(x string) string { 231 | return fmt.Sprint(rf(x)) 232 | } 233 | } else { 234 | f = func(_ string) string { 235 | return fmt.Sprint(replacement) 236 | } 237 | } 238 | if global { 239 | return re.compile().ReplaceAllStringFunc(this.String(), f) 240 | } else { 241 | s := this.String() 242 | loc := re.compile().FindStringIndex(s) 243 | return s[:loc[0]] + f(s[loc[0]:loc[1]]) + s[loc[1]:] 244 | } 245 | } 246 | 247 | func (this *JSString) Search(re *RegExp) float64 { 248 | match := re.compile().FindStringIndex(this.String()) 249 | if match == nil { 250 | return -1 251 | } 252 | return float64(match[0]) 253 | } 254 | 255 | func (this *JSString) CharAt(index float64) string { 256 | return string([]rune(this.String())[int(index)]) 257 | } 258 | 259 | func (this *JSString) CharCodeAt(index float64) float64 { 260 | return float64([]rune(this.String())[int(index)]) 261 | } 262 | 263 | func (this *JSString) ToUpperCase() string { 264 | return strings.ToUpper(this.String()) 265 | } 266 | 267 | func (this *JSString) ToLowerCase() string { 268 | return strings.ToLower(this.String()) 269 | } 270 | 271 | func (this *JSString) IndexOf(x_limit ...interface{}) float64 { 272 | x := x_limit[0] 273 | limit := len(this.String()) 274 | if len(x_limit) > 1 { 275 | limit = int(x_limit[1].(float64)) - 1 276 | } 277 | return float64(strings.Index(this.String()[:limit], fmt.Sprint(x))) 278 | } 279 | 280 | func (this *JSString) Substring(indexA_indexB ...float64) string { 281 | indexA := indexA_indexB[0] 282 | indexB := float64(len(this.String())) 283 | if len(indexA_indexB) > 1 { 284 | indexB = indexA_indexB[1] 285 | } 286 | if indexA > indexB { 287 | indexA, indexB = indexB, indexA 288 | } 289 | if indexA < 0 { 290 | indexA = 0 291 | } 292 | if indexB < 0 { 293 | indexB = 0 294 | } 295 | return string(this.String()[int(indexA):int(indexB)]) 296 | } 297 | 298 | func (this *JSString) Split(separator_limit ...interface{}) []interface{} { 299 | var parts []string 300 | argc := len(separator_limit) 301 | if argc == 0 { 302 | parts = strings.Split(this.String(), "") 303 | } 304 | if argc > 0 { 305 | switch separator := separator_limit[0].(type) { 306 | case string: 307 | parts = strings.Split(this.String(), separator) 308 | case *RegExp: 309 | parts = separator.compile().Split(this.String(), -1) 310 | default: 311 | parts = []string{this.String()} 312 | } 313 | } 314 | limit := -1 315 | if argc == 2 { 316 | limit = int(separator_limit[1].(float64)) 317 | } 318 | strs := make([]interface{}, len(parts)) 319 | for i, v := range parts { 320 | strs[i] = v 321 | } 322 | if limit < 0 { 323 | return strs 324 | } 325 | return strs[:limit] 326 | } 327 | 328 | func (this *JSString) ToString() string { 329 | return this.str 330 | } 331 | 332 | func (this *JSString) String() string { 333 | return this.ToString() 334 | } 335 | 336 | func (this JSNumber) ToString() string { 337 | return fmt.Sprint(float64(this)) 338 | } 339 | 340 | func (this JSNumber) String() string { 341 | return this.ToString() 342 | } 343 | 344 | func (this JSBoolean) ToString() string { 345 | return fmt.Sprint(bool(this)) 346 | } 347 | 348 | func (this JSBoolean) String() string { 349 | return this.ToString() 350 | } 351 | 352 | func (this JSNil) ToString() string { 353 | return "" 354 | } 355 | 356 | func (this JSNil) String() string { 357 | return this.ToString() 358 | } 359 | 360 | type JSArray struct { 361 | Length float64 362 | array interface{} 363 | } 364 | 365 | func JSArray_(a interface{}) *JSArray { 366 | var arr []interface{} 367 | switch a := a.(type) { 368 | case *[]interface{}: 369 | arr = *a 370 | case *interface{}: 371 | arr = (*a).([]interface{}) 372 | default: 373 | panic("Unknown array type: " + fmt.Sprint(a)) 374 | } 375 | return &JSArray{float64(len(arr)), a} 376 | } 377 | 378 | func (this *JSArray) arr() []interface{} { 379 | switch a := this.array.(type) { 380 | case *[]interface{}: 381 | return *a 382 | case *interface{}: 383 | return (*a).([]interface{}) 384 | default: 385 | panic("Unknown array type: " + fmt.Sprint(a)) 386 | } 387 | } 388 | 389 | func (this *JSArray) setArr(arr []interface{}) *JSArray { 390 | switch a := this.array.(type) { 391 | case *[]interface{}: 392 | *a = arr 393 | case *interface{}: 394 | *a = arr 395 | } 396 | this.Length = float64(len(arr)) 397 | return this 398 | } 399 | 400 | // Untyped arguments, only used by ObjMap dissoc. We need to choose how to deal with this in general. 401 | func (this *JSArray) Splice(index_, howMany_ interface{}, elements ...interface{}) []interface{} { 402 | index, howMany := index_.(float64), howMany_.(float64) 403 | if index < 0 { 404 | index = this.Length + index 405 | } 406 | removed := make([]interface{}, int(howMany)) 407 | arr := this.arr() 408 | copy(removed, arr[int(index):int(index+howMany)]) 409 | this.setArr(append(arr[:int(index)], append(elements, arr[int(index+howMany):]...)...)) 410 | return removed 411 | } 412 | 413 | func (this *JSArray) Slice(index, end float64) []interface{} { 414 | arr := this.arr() 415 | if end < 0 { 416 | end = float64(len(arr)) + end 417 | } 418 | return arr[int(index):int(end)] 419 | } 420 | 421 | func (this *JSArray) Reverse() []interface{} { 422 | arr := this.arr() 423 | end := len(arr) - 1 424 | for i, v := range arr { 425 | if i > end/2 { 426 | break 427 | } 428 | arr[end-i], arr[i] = v, arr[end-i] 429 | } 430 | return arr 431 | } 432 | 433 | func (this *JSArray) Pop() interface{} { 434 | arr := this.arr() 435 | idx := len(arr) - 1 436 | this.setArr(arr[:idx]) 437 | return arr[idx] 438 | } 439 | 440 | func (this *JSArray) Push(x interface{}) float64 { 441 | return this.setArr(append(this.arr(), x)).Length 442 | } 443 | 444 | func (this *JSArray) Join(separator ...interface{}) string { 445 | sep := "," 446 | if len(separator) > 0 { 447 | sep = fmt.Sprint(separator[0]) 448 | } 449 | arr := this.arr() 450 | ss := make([]string, len(arr)) 451 | for i, v := range arr { 452 | ss[i] = fmt.Sprint(v) 453 | } 454 | return strings.Join(ss, sep) 455 | } 456 | 457 | func (this *JSArray) ToString() string { 458 | return fmt.Sprint(this.arr()) 459 | } 460 | 461 | func (this *JSArray) String() string { 462 | return this.ToString() 463 | } 464 | 465 | // Base Type Protocols 466 | // There are other extend-type calls at start of core.cljs we aren't dealing with. 467 | 468 | func (_ JSNil) CljsCoreICounted__() {} 469 | 470 | func (___ JSNil) X_count_Arity1() float64 { 471 | return 0 472 | } 473 | -------------------------------------------------------------------------------- /js/js_test.go: -------------------------------------------------------------------------------- 1 | package js 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "strings" 7 | "testing" 8 | "time" 9 | ) 10 | import ( 11 | "github.com/hraberg/cljs2go/js/Math" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | func Test_JS(t *testing.T) { 16 | assert.Equal(t, math.Inf(1), Infinity) 17 | assert.Equal(t, math.MaxFloat64, Number.MAX_VALUE) 18 | assert.Equal(t, 0.6046602879796196, Math.Random()) 19 | assert.Equal(t, 3, Math.Ceil(2.6)) 20 | assert.Equal(t, 2, Math.Floor(2.6)) 21 | assert.Equal(t, 12, Math.Imul(2.3, 6.7)) 22 | assert.Equal(t, -5.0, Math.Imul(float64(0xffffffff), 5.0)) 23 | assert.Equal(t, -10.0, Math.Imul(float64(0xfffffffe), 5.0)) 24 | 25 | assert.Equal(t, "ABC", String.FromCharCode(65, 66, 67)) 26 | assert.Nil(t, (&RegExp{"Hello", ""}).Exec("World")) 27 | assert.Equal(t, []interface{}{"Hello"}, (&RegExp{"hello", "i"}).Exec("World Hello Hello")) 28 | assert.Equal(t, []interface{}{"Wo", "o", nil}, (&RegExp{"W(o)(x)?", ""}).Exec("World")) 29 | assert.Equal(t, []interface{}{" \u00a1"}, (&RegExp{"\\s\\u00a1", ""}).Exec(" \u00a1 ")) 30 | 31 | assert.Equal(t, "HELLO World", JSString_("Hello World").Replace(&RegExp{"hello", "i"}, 32 | func(match interface{}) interface{} { 33 | return strings.ToUpper(fmt.Sprint(match)) 34 | }, 35 | )) 36 | assert.Equal(t, "HELLO World", JSString_("Hello World").Replace(&RegExp{"hello", "i"}, "HELLO")) 37 | assert.Equal(t, "HELLO World", JSString_("Hello World").Replace("Hello", "HELLO")) 38 | assert.Equal(t, "bar bar foo", JSString_("foo bar foo").Replace("foo", "bar")) 39 | assert.Equal(t, "bar bar bar", JSString_("foo bar foo").Replace(&RegExp{"foo", "g"}, "bar")) 40 | assert.Equal(t, "bar bar foo", JSString_("foo bar foo").Replace(&RegExp{"foo", ""}, "bar")) 41 | 42 | assert.Equal(t, 6, JSString_("Hello World").Search(&RegExp{"world", "i"})) 43 | assert.Equal(t, "/Hello/i", (&RegExp{"Hello", "i"}).String()) 44 | assert.Equal(t, "/(?:)/", (&RegExp{"", ""}).String()) 45 | 46 | date := &Date{1407962432671} 47 | assert.Equal(t, 2014, date.GetUTCFullYear()) 48 | assert.Equal(t, 7, date.GetUTCMonth()) 49 | assert.Equal(t, 13, date.GetUTCDate()) 50 | assert.Equal(t, 20, date.GetUTCHours()) 51 | assert.Equal(t, 40, date.GetUTCMinutes()) 52 | assert.Equal(t, 32, date.GetUTCSeconds()) 53 | assert.Equal(t, 671, date.GetUTCMilliseconds()) 54 | assert.Equal(t, 1407962432671.0, date.GetTime()) 55 | assert.Equal(t, 1407962432671.0, date.ValueOf()) 56 | assert.Equal(t, "2014-08-13 21:40:32.671 +0100 BST", date.String()) 57 | 58 | date = &Date{"2010-11-12T13:14:15.666-05:00"} 59 | assert.Equal(t, 2010, date.GetUTCFullYear()) 60 | assert.Equal(t, 10, date.GetUTCMonth()) 61 | assert.Equal(t, 12, date.GetUTCDate()) 62 | assert.Equal(t, 18, date.GetUTCHours()) 63 | assert.Equal(t, 14, date.GetUTCMinutes()) 64 | assert.Equal(t, 15, date.GetUTCSeconds()) 65 | assert.Equal(t, 666, date.GetUTCMilliseconds()) 66 | assert.Equal(t, 1289585655666.0, date.GetTime()) 67 | assert.Equal(t, 1289585655666.0, date.ValueOf()) 68 | assert.True(t, (&Date{}).time().Before(time.Now())) 69 | 70 | assert.Equal(t, 3.14, ParseFloat("3.14")) 71 | assert.Equal(t, math.NaN(), ParseFloat("")) 72 | assert.Equal(t, 0, ParseInt("0", 10)) 73 | assert.Equal(t, 42, ParseInt("52", 8)) 74 | assert.Equal(t, 42, ParseInt("2a", 16)) 75 | assert.Equal(t, 42, ParseInt("101010", 2)) 76 | assert.Equal(t, 42, ParseInt("16", 36)) 77 | assert.Equal(t, 3, ParseInt("3", 10)) 78 | assert.Equal(t, 10, ParseInt("a", 16)) 79 | assert.Equal(t, math.NaN(), ParseInt("3.14", 10)) 80 | assert.Equal(t, math.NaN(), ParseInt("x", 10)) 81 | assert.Equal(t, math.NaN(), ParseInt(nil, 10)) 82 | assert.Equal(t, math.NaN(), ParseInt([]interface{}{}, 10)) 83 | 84 | assert.Equal(t, "1", JSNumber(1).ToString()) 85 | assert.Equal(t, "3.14", JSNumber(3.14).ToString()) 86 | assert.Equal(t, "true", JSBoolean(true).ToString()) 87 | assert.Equal(t, "", JSNil{}.ToString()) 88 | assert.Equal(t, "Hello", JSString_("Hello").ToString()) 89 | assert.Equal(t, "[Hello World]", JSArray_(&[]interface{}{"Hello", "World"}).ToString()) 90 | 91 | assert.Equal(t, "l", (JSString_("Hello").CharAt(2))) 92 | assert.Equal(t, 108, (JSString_("Hello").CharCodeAt(2))) 93 | 94 | assert.Equal(t, []interface{}{"Hello", "World"}, JSString_("Hello World").Split(" ")) 95 | assert.Equal(t, []interface{}{"Hello"}, JSString_("Hello World").Split(" ", 1.0)) 96 | assert.Equal(t, []interface{}{"Hello", "World"}, JSString_("Hello World").Split(&RegExp{"\\s+", ""})) 97 | assert.Equal(t, []interface{}{"F", "o", "o"}, JSString_("Foo").Split()) 98 | assert.Equal(t, []interface{}{"Foo"}, JSString_("Foo").Split(1.0)) 99 | 100 | assert.Equal(t, "HELLO", JSString_("Hello").ToUpperCase()) 101 | assert.Equal(t, "hello", JSString_("Hello").ToLowerCase()) 102 | 103 | assert.Equal(t, "llo", JSString_("Hello").Substring(2.0)) 104 | assert.Equal(t, "ell", JSString_("Hello").Substring(1.0, 4.0)) 105 | assert.Equal(t, "l", JSString_("Hello").Substring(3.0, 2.0)) 106 | assert.Equal(t, "", JSString_("Hello").Substring(2.0, 2.0)) 107 | 108 | assert.Equal(t, 1.0, JSString_("Hello").IndexOf("e")) 109 | assert.Equal(t, -1.0, JSString_("Hello").IndexOf("x")) 110 | assert.Equal(t, -1.0, JSString_("Hello").IndexOf("e", 2.0)) 111 | assert.Equal(t, 3.0, JSString_("foo/").IndexOf("/")) 112 | 113 | arr := []interface{}{"Hello", "Earth", "World", "!"} 114 | assert.Equal(t, []interface{}{"Earth", "World"}, JSArray_(&arr).Splice(1.0, 2.0, "Hyper", "Space")) 115 | assert.Equal(t, []interface{}{"Hello", "Hyper", "Space", "!"}, arr) 116 | 117 | assert.Equal(t, []interface{}{"Hyper", "Space"}, JSArray_(&arr).Slice(1, -1)) 118 | assert.Equal(t, []interface{}{"Hello", "Hyper", "Space", "!"}, arr) 119 | 120 | arr = []interface{}{"Hello", "World"} 121 | assert.Equal(t, "World", JSArray_(&arr).Pop()) 122 | assert.Equal(t, []interface{}{"Hello"}, arr) 123 | 124 | arr = []interface{}{"Hello", "World"} 125 | assert.Equal(t, 3, JSArray_(&arr).Push("Space")) 126 | assert.Equal(t, []interface{}{"Hello", "World", "Space"}, arr) 127 | 128 | arr = []interface{}{1.0, 2.0} 129 | assert.Equal(t, "1,2", JSArray_(&arr).Join()) 130 | assert.Equal(t, "1 2", JSArray_(&arr).Join(" ")) 131 | assert.Equal(t, "102", JSArray_(&arr).Join(0.0)) 132 | 133 | arr = []interface{}{"Hello", "World", "Space"} 134 | assert.Equal(t, "Hello-World-Space", JSArray_(&arr).Join("-")) 135 | assert.Equal(t, "HelloWorldSpace", JSArray_(&arr).Join("")) 136 | 137 | arr = []interface{}{"Hello", "World", "Space", "!"} 138 | assert.Equal(t, []interface{}{"!", "Space", "World", "Hello"}, JSArray_(&arr).Reverse()) 139 | assert.Equal(t, []interface{}{"!", "Space", "World", "Hello"}, arr) 140 | 141 | arr = []interface{}{} 142 | assert.Equal(t, []interface{}{}, JSArray_(&arr).Reverse()) 143 | 144 | arr = []interface{}{"Hello"} 145 | assert.Equal(t, "Hello", JSArray_(&arr).Join("-")) 146 | 147 | arr = []interface{}{} 148 | assert.Equal(t, "", JSArray_(&arr).Join("-")) 149 | 150 | var xs interface{} = []interface{}{"Hello", "World"} 151 | assert.Equal(t, 2, JSArray_(&xs).Length) 152 | assert.Equal(t, "World", JSArray_(&xs).Pop()) 153 | assert.Equal(t, 1, JSArray_(&xs).Length) 154 | assert.Equal(t, []interface{}{"Hello"}, xs) 155 | 156 | assert.Equal(t, 0, JSNil{}.X_count_Arity1()) 157 | } 158 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | //go:generate lein do compile-clojurescript, compile-clojurescript-tests 2 | package main 3 | 4 | import ( 5 | "log" 6 | "os/exec" 7 | ) 8 | 9 | import . "github.com/hraberg/cljs2go/cljs/core" 10 | 11 | var _main = Fn(func(args ...interface{}) interface{} { 12 | Println.X_invoke_ArityVariadic(Array_seq.X_invoke_Arity1([]interface{}{"ClojureScript to Go [go]"})) 13 | goGet := exec.Command("go", "get", "code.google.com/p/go.tools/cmd/goimports") 14 | if out, err := goGet.CombinedOutput(); err != nil { 15 | log.Fatal(string(out[:])) 16 | } 17 | return nil 18 | }) 19 | 20 | func init() { 21 | X_STAR_main_cli_fn_STAR_ = _main 22 | } 23 | 24 | func main() { 25 | Main_() 26 | } 27 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject cljs2go "0.1.0-SNAPSHOT" 2 | :description "ClojureScript to Go" 3 | :url "http://github.com/hraberg/cljs.go" 4 | :license {:name "Eclipse Public License" 5 | :url "http://www.eclipse.org/legal/epl-v10.html"} 6 | :main cljs.go 7 | :aliases {"compile-clojurescript" ["run" "-m" "cljs.go/compile-clojurescript"] 8 | "compile-clojurescript-tests" ["run" "-m" "cljs.go-test/clojurescript-tests"]} 9 | :dependencies [[org.clojure/clojure "1.7.0-alpha4"] 10 | [org.clojure/clojurescript "0.0-2411"] 11 | [org.clojure/tools.analyzer.js "0.1.0-beta5"] 12 | [org.clojure/core.async "0.1.346.0-17112a-alpha"]]) 13 | -------------------------------------------------------------------------------- /samples/hello.cljs: -------------------------------------------------------------------------------- 1 | (ns hello) 2 | 3 | (defn -main [& args] 4 | (println "Hello World")) 5 | -------------------------------------------------------------------------------- /samples/hello/hello.go: -------------------------------------------------------------------------------- 1 | // Compiled by ClojureScript to Go 0.0-2371 2 | // hello 3 | 4 | package hello 5 | 6 | import cljs_core "github.com/hraberg/cljs2go/cljs/core" 7 | 8 | func init() { 9 | X_main = func(_main *cljs_core.AFn) *cljs_core.AFn { 10 | return cljs_core.Fn(_main, 0, func(args__ ...interface{}) interface{} { 11 | var args = cljs_core.Seq.Arity1IQ(args__[0]) 12 | _ = args 13 | return cljs_core.Println.X_invoke_ArityVariadic(cljs_core.Array_seq.X_invoke_Arity1([]interface{}{"Hello World"})) 14 | }) 15 | }(&cljs_core.AFn{}) 16 | 17 | } 18 | 19 | // @param {...*} var_args 20 | var X_main *cljs_core.AFn 21 | -------------------------------------------------------------------------------- /samples/hello/main.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import cljs_core `github.com/hraberg/cljs2go/cljs/core` 6 | import main_ns `.` 7 | 8 | func main() { 9 | cljs_core.X_STAR_main_cli_fn_STAR_ = main_ns.X_main 10 | cljs_core.Main_() 11 | } 12 | -------------------------------------------------------------------------------- /src/cljs/core/overrides.cljs: -------------------------------------------------------------------------------- 1 | (ns ^{:doc "Go overrides."} 2 | cljs.core 3 | (:require [goog.array :as garray])) 4 | 5 | (def *clojurescript-version* (clojurescript-version)) 6 | 7 | (def ^:dynamic *print-length* ^number js/NaN) 8 | (def ^:dynamic *print-level* ^number js/NaN) 9 | 10 | (defn set-print-fn! 11 | "Set *print-fn* to f." 12 | [f] (set! *print-fn* (js* "~{}.(*AFn)" f))) 13 | 14 | (defn ^boolean symbol? [x] 15 | (cljs.core/instance? Symbol x)) 16 | 17 | (defn complement 18 | "Takes a fn f and returns a fn that takes the same arguments as f, 19 | has the same effects, if any, and returns the opposite truth value." 20 | [f] 21 | (fn complement-fn 22 | ([] (not (f))) 23 | ([x] (not (f x))) 24 | ([x y] (not (f x y))) 25 | ([x y & zs] (not (apply f x y zs))))) 26 | 27 | (defn remove 28 | "Returns a lazy sequence of the items in coll for which 29 | (pred item) returns false. pred must be free of side-effects. 30 | Returns a transducer when no collection is provided." 31 | ([pred] (filter (complement pred))) 32 | ([pred coll] 33 | (filter (complement pred) coll))) 34 | 35 | (defn identity 36 | ([x] x) 37 | ([x & _] x)) 38 | 39 | (defn ^number rand 40 | "Returns a random floating point number between 0 (inclusive) and 41 | n (default 1) (exclusive)." 42 | ([] (rand 1)) 43 | ([n] (* (Math/random) n))) 44 | 45 | (defn ^boolean = 46 | "Equality. Returns true if x equals y, false if not. Compares 47 | numbers and collections in a type-independent manner. Clojure's immutable data 48 | structures define -equiv (and thus =) as a value, not an identity, 49 | comparison." 50 | ([x] true) 51 | ([x y] 52 | (if (nil? x) 53 | (nil? y) 54 | (or (identical? x y) 55 | (if (implements? IEquiv x) 56 | ^boolean (-equiv x y) 57 | false)))) 58 | ([x y & more] 59 | (if (= x y) 60 | (if (next more) 61 | (recur y (first more) (next more)) 62 | (= y (first more))) 63 | false))) 64 | 65 | (defn sort 66 | "Returns a sorted sequence of the items in coll. Comp can be 67 | boolean-valued comparison funcion, or a -/0/+ valued comparator. 68 | Comp defaults to compare." 69 | ([coll] 70 | (sort compare coll)) 71 | ([comp coll] 72 | (if (seq coll) 73 | (let [a (to-array coll) 74 | comp ^function (fn->comparator comp)] 75 | ;; matching Clojure's stable sort, though docs don't promise it 76 | (garray/stableSort a (js* "func(x, y interface{}) interface{} { return ~{}.X_invoke_Arity2(x, y) }" comp)) 77 | (seq a)) 78 | ()))) 79 | 80 | (defn get 81 | "Returns the value mapped to key, not-found or nil if key not present." 82 | ([o k] 83 | (when-not (nil? o) 84 | (cond 85 | (implements? ILookup o) 86 | (-lookup ^not-native o k) 87 | 88 | (array? o) 89 | (when (and (number? k) (< k (.-length o))) 90 | (aget ^array (js* "~{}.([]interface{})" o) k)) 91 | 92 | (string? o) 93 | (when (and (number? k) (< k (.-length o))) 94 | (js* "string(~{})" (aget ^string (js* "~{}.(string)" o) k))) 95 | 96 | (native-satisfies? ILookup o) 97 | (-lookup o k) 98 | 99 | :else nil))) 100 | ([o k not-found] 101 | (if-not (nil? o) 102 | (cond 103 | (implements? ILookup o) 104 | (-lookup ^not-native o k not-found) 105 | 106 | (array? o) 107 | (if (and (number? k) (< k (.-length o))) 108 | (aget ^array (js* "~{}.([]interface{})" o) k) 109 | not-found) 110 | 111 | (string? o) 112 | (if (and (number? k) (< k (.-length o))) 113 | (js* "string(~{})" (aget ^string (js* "~{}.(string)" o) k)) 114 | not-found) 115 | 116 | (native-satisfies? ILookup o) 117 | (-lookup o k not-found) 118 | 119 | :else not-found) 120 | not-found))) 121 | 122 | (defn ^:private quote-string 123 | [s] 124 | ^string (js* "strconv.Quote(~{}.(string))" s)) 125 | 126 | (defn- pr-writer 127 | "Prefer this to pr-seq, because it makes the printing function 128 | configurable, allowing efficient implementations such as appending 129 | to a StringBuffer." 130 | [obj writer opts] 131 | (cond 132 | (nil? obj) (-write writer "nil") 133 | :else (do 134 | (when (and (get opts :meta) 135 | (satisfies? IMeta obj) 136 | (meta obj)) 137 | (-write writer "^") 138 | (pr-writer (meta obj) writer opts) 139 | (-write writer " ")) 140 | (cond 141 | (nil? obj) (-write writer "nil") 142 | 143 | ;; handle CLJS ctors 144 | ;; ^boolean (.-cljs$lang$type obj) 145 | ;; (.cljs$lang$ctorPrWriter obj obj writer opts) 146 | 147 | ; Use the new, more efficient, IPrintWithWriter interface when possible. 148 | (implements? IPrintWithWriter obj) 149 | (-pr-writer ^not-native obj writer opts) 150 | 151 | (or (boolean? obj) (number? obj)) 152 | (-write writer (str obj)) 153 | 154 | (array? obj) 155 | (pr-sequential-writer writer pr-writer "#js [" " " "]" opts obj) 156 | 157 | ^boolean (goog/isString obj) 158 | (if (:readably opts) 159 | (-write writer (quote-string obj)) 160 | (-write writer obj)) 161 | 162 | (fn? obj) 163 | (write-all writer "#<" (str obj) ">") 164 | 165 | (instance? js/Date obj) 166 | (let [normalize (fn [n len] 167 | (loop [ns (str n)] 168 | (if (< (count ns) len) 169 | (recur (str "0" ns)) 170 | ns)))] 171 | (write-all writer 172 | "#inst \"" 173 | (str (.getUTCFullYear obj)) "-" 174 | (normalize (inc (.getUTCMonth obj)) 2) "-" 175 | (normalize (.getUTCDate obj) 2) "T" 176 | (normalize (.getUTCHours obj) 2) ":" 177 | (normalize (.getUTCMinutes obj) 2) ":" 178 | (normalize (.getUTCSeconds obj) 2) "." 179 | (normalize (.getUTCMilliseconds obj) 3) "-" 180 | "00:00\"")) 181 | 182 | (regexp? obj) (write-all writer "#\"" (.-pattern obj) "\"") 183 | 184 | (satisfies? IPrintWithWriter obj) 185 | (-pr-writer obj writer opts) 186 | 187 | :else (write-all writer "#<" (str obj) ">"))))) 188 | 189 | (defn pr-sequential-writer [writer print-one begin sep end opts coll] 190 | (binding [*print-level* (if (== js/NaN *print-level*) ^number *print-level* (dec *print-level*))] 191 | (if (neg? *print-level*) 192 | (-write writer "#") 193 | (do 194 | (-write writer begin) 195 | (when (seq coll) 196 | (print-one (first coll) writer opts)) 197 | (loop [coll (next coll) n (dec (:print-length opts))] 198 | (if (and coll (or (nil? n) (not (zero? n)))) 199 | (do 200 | (-write writer sep) 201 | (print-one (first coll) writer opts) 202 | (recur (next coll) (dec n))) 203 | (when (and (seq coll) (zero? n)) 204 | (-write writer sep) 205 | (-write writer "...")))) 206 | (-write writer end))))) 207 | 208 | (defn type [x] 209 | (when-not (nil? x) 210 | (js* "reflect.TypeOf(~{})" x))) 211 | 212 | (defn type->str [ty] 213 | (str ty)) 214 | 215 | (defn ^boolean integer? 216 | "Returns true if n is an integer." 217 | [n] 218 | (and (number? n) 219 | (not ^boolean (js/isNaN n)) 220 | (not (identical? n js/Infinity)) 221 | (== n ^number (js* "float64(int(~{}.(float64)))" n)))) 222 | 223 | (defn ^array array 224 | "Creates a new javascript array. 225 | @param {...*} var_args" ;;array is a special case, don't emulate this doc string 226 | [& items] 227 | (into-array items)) 228 | 229 | (defn ^array make-array 230 | ([size] 231 | (make-array nil size)) 232 | ([type size] 233 | (cljs.core/make-array size))) 234 | 235 | (defn char 236 | "Coerce to char" 237 | [x] 238 | (cond 239 | (number? x) (js* "js.String.FromCharCode(~{}.(float64))" x) 240 | (and (string? x) (== (.-length x) 1)) x 241 | :else (throw (js/Error. "Argument to char must be a character or number")))) 242 | 243 | ;; Simple caching of string hashcode 244 | (def string-hash-cache ^"map[interface{}]interface{}" (js* "map[interface{}]interface{}{}")) 245 | 246 | (defn add-to-string-hash-cache [k] 247 | (let [h (hash-string* k)] 248 | (js* "~{}[~{}] = ~{}" string-hash-cache k h) 249 | (set! string-hash-cache-count (inc string-hash-cache-count)) 250 | h)) 251 | 252 | (defn hash-string [k] 253 | (when (> string-hash-cache-count 255) 254 | (set! string-hash-cache (js* "map[interface{}]interface{}{}")) 255 | (set! string-hash-cache-count 0)) 256 | (let [h (js* "~{}[~{}]" string-hash-cache k)] 257 | (if (number? h) 258 | h 259 | (add-to-string-hash-cache k)))) 260 | 261 | (defn enable-console-print! 262 | "Set *print-fn* to console.log" 263 | [] 264 | (set! *print-newline* false) 265 | (set! *print-fn* 266 | (fn fmt-println [x] 267 | (js* "fmt.Println(~{})" x) 268 | nil))) 269 | 270 | (defn apply 271 | "Applies fn f to the argument list formed by prepending intervening arguments to args. 272 | First cut. Not lazy. Needs to use emitted toApply." 273 | ([f args] 274 | (let [fixed-arity ^number (js* "MaxFixedArity_(~{})" f)] 275 | (if (or (= -1 fixed-arity) 276 | (<= (bounded-count args (inc fixed-arity)) fixed-arity)) 277 | (js* "Call_(~{}.(CljsCoreIFn), ~{}...)" f (into-array args)) 278 | (if (empty? args) 279 | (js* "~{}.(*AFn).X_invoke_ArityVariadic(~{})" f args) 280 | (js* "~{}.(*AFn).X_invoke_ArityVariadic(append(~{}, ~{})...)" 281 | f (into-array (take fixed-arity args)) (drop fixed-arity args)))))) 282 | ([f x args] 283 | (let [arglist (list* x args) 284 | fixed-arity ^number (js* "MaxFixedArity_(~{})" f)] 285 | (if (or (= -1 fixed-arity) 286 | (<= (bounded-count arglist (inc fixed-arity)) fixed-arity)) 287 | (js* "Call_(~{}.(CljsCoreIFn), ~{}...)" f (into-array arglist)) 288 | (js* "~{}.(*AFn).X_invoke_ArityVariadic(append(~{}, ~{})...)" 289 | f (into-array (take fixed-arity arglist)) (drop fixed-arity arglist))))) 290 | ([f x y args] 291 | (let [arglist (list* x y args) 292 | fixed-arity ^number (js* "MaxFixedArity_(~{})" f)] 293 | (if (or (= -1 fixed-arity) 294 | (<= (bounded-count arglist (inc fixed-arity)) fixed-arity)) 295 | (js* "Call_(~{}.(CljsCoreIFn), ~{}...)" f (into-array arglist)) 296 | (js* "~{}.(*AFn).X_invoke_ArityVariadic(append(~{}, ~{})...)" 297 | f (into-array (take fixed-arity arglist)) (drop fixed-arity arglist))))) 298 | ([f x y z args] 299 | (let [arglist (list* x y z args) 300 | fixed-arity ^number (js* "MaxFixedArity_(~{})" f)] 301 | (if (or (= -1 fixed-arity) 302 | (<= (bounded-count arglist (inc fixed-arity)) fixed-arity)) 303 | (js* "Call_(~{}.(CljsCoreIFn), ~{}...)" f (into-array arglist)) 304 | (js* "~{}.(*AFn).X_invoke_ArityVariadic(append(~{}, ~{})...)" 305 | f (into-array (take fixed-arity arglist)) (drop fixed-arity arglist))))) 306 | ([f a b c d & args] 307 | (let [arglist (cons a (cons b (cons c (cons d (spread args))))) 308 | fixed-arity ^number (js* "MaxFixedArity_(~{})" f)] 309 | (if (or (= -1 fixed-arity) 310 | (<= (bounded-count arglist (inc fixed-arity)) fixed-arity)) 311 | (js* "Call_(~{}.(CljsCoreIFn), append(~{}, ~{}...))" f (into-array (butlast arglist)) (into-array (last arglist))) 312 | (js* "~{}.(*AFn).X_invoke_ArityVariadic(append(~{}, ~{})...)" 313 | f (into-array (take fixed-arity arglist)) (drop fixed-arity arglist)))))) 314 | 315 | (defn ^boolean native-satisfies? 316 | "Internal - do not use!" 317 | [p x] 318 | ^boolean (js* "DecoratedValue_(~{}).Type().Implements(~{}.(reflect.Type))" x p)) 319 | 320 | (defn test 321 | "test [v] finds fn at key :test in var metadata and calls it, 322 | presuming failure will throw exception" 323 | [v] 324 | (let [f (:test (meta v))] 325 | (if f 326 | (do (f) :ok) 327 | :no-test))) 328 | 329 | (extend-type TransientArrayMap 330 | ITransientMap 331 | (-dissoc! [tcoll key] 332 | (if (.-editable? tcoll) 333 | (let [idx (array-map-index-of tcoll key)] 334 | (when (>= idx 0) 335 | (aset (.-arr tcoll) idx (aget (.-arr tcoll) (- (.-len tcoll) 2))) 336 | (aset (.-arr tcoll) (inc idx) (aget (.-arr tcoll) (dec (.-len tcoll)))) 337 | (.pop (.-arr tcoll)) 338 | (.pop (.-arr tcoll)) 339 | (set! (.-len tcoll) (- (.-len tcoll) 2))) 340 | tcoll) 341 | (throw (js/Error. "dissoc! after persistent!"))))) 342 | 343 | (extend-type PersistentTreeSet 344 | ISorted 345 | (-sorted-seq [coll ascending?] 346 | (seq (map key (-sorted-seq (.-tree-map coll) ascending?)))) 347 | 348 | (-sorted-seq-from [coll k ascending?] 349 | (seq (map key (-sorted-seq-from (.-tree-map coll) k ascending?)))) 350 | 351 | (-entry-key [coll entry] entry) 352 | 353 | (-comparator [coll] (-comparator (.-tree-map coll)))) 354 | -------------------------------------------------------------------------------- /src/cljs/go.clj: -------------------------------------------------------------------------------- 1 | (ns cljs.go 2 | (:require [cljs.analyzer :as ana] 3 | [cljs.env :as env] 4 | [cljs.go.compiler :as cljs.compiler] 5 | [clojure.string :as s] 6 | [clojure.pprint :as pp] 7 | [clojure.repl :as repl] 8 | [clojure.walk :as w] 9 | [clojure.java.io :as io] 10 | [clojure.java.shell :as sh])) 11 | 12 | (set! *warn-on-reflection* true) 13 | 14 | (defn elide-children [_ ast] 15 | (dissoc ast :children)) 16 | 17 | (defn simplify-env [_ {:keys [op] :as ast}] 18 | (cond-> ast 19 | (= op :fn) (update-in [:methods] #(map (partial simplify-env nil) %)) 20 | (= op :set!) (update-in [:target] (partial simplify-env nil)) 21 | :then (update-in [:env] #(select-keys % [:context :column :line])))) 22 | 23 | (defn cljs->ast 24 | ([in] (cljs->ast in (ana/empty-env))) 25 | ([in env] 26 | (env/ensure 27 | (binding [ana/*passes* [elide-children simplify-env ana/infer-type] 28 | ana/*cljs-ns* (or ana/*cljs-ns* 'cljs.user)] 29 | (cljs.compiler/setup-native-defs env) 30 | (doall (map #(ana/analyze (cljs.compiler/ensure-ns-exist env) %) in)))))) 31 | 32 | (defn ast->go [in] 33 | (try 34 | (env/ensure 35 | (with-out-str 36 | (binding [ana/*cljs-static-fns* true 37 | cljs.compiler/*go-defs* (or cljs.compiler/*go-defs* (atom []))] 38 | (dorun (map cljs.compiler/emit in))))) 39 | (catch Throwable t 40 | (.printStackTrace t) 41 | (throw t)))) 42 | 43 | (defn godef 44 | ([var] (godef nil var)) 45 | ([package var] 46 | (let [in (str "package _;" 47 | (when (seq (str package)) 48 | (str "import \"" package "\";")) 49 | "var _ = " (cond->> var package (str (last (s/split package #"\.")) "."))) 50 | {:keys [exit err out]} (sh/sh "godef" "-i" "-t" "-o" (str (count in)) :in in)] 51 | (if (zero? exit) 52 | (let [[loc & def] (s/split-lines out) 53 | [file line col] (s/split loc #":")] 54 | (merge 55 | {:file file :def (s/trim (s/join "\n" (remove (comp empty? s/trim) def)))} 56 | (when (and line col) 57 | {:line (biginteger line) :col (biginteger col)}) )) 58 | (println err))))) 59 | 60 | (defn go-signature [package var] 61 | (when-let [def (:def (godef package var))] 62 | (let [ret-tag (symbol (last (s/split def #"\s+"))) 63 | [type method] (s/split var #"\.") 64 | params (s/split (last (re-find #"\((.+)\)" def)) #",") 65 | params (map #(s/split (s/trim %) #"\s+") params) 66 | params (loop [last-t nil [[v t] & params] (reverse params) acc []] 67 | (if v 68 | (let [t (symbol (or t last-t))] 69 | (recur t params (conj acc (with-meta (symbol v) {:tag t})))) 70 | (vec (reverse acc))))] 71 | (cond-> 72 | {:ns package :ret-tag ret-tag :method-params (list params)} 73 | method (assoc :type (symbol type) :method (symbol method)) 74 | (not method) (assoc :func (symbol var)))))) 75 | 76 | (defn godoc [package name] 77 | (let [{:keys [exit err out]} (sh/sh "godoc" package name) 78 | out (s/trim out)] 79 | (if (and (zero? exit) (not= "No match found." out)) 80 | (->> (s/split out #"\n\n+") 81 | (group-by #(let [[what name s-or-i method ] (s/split % #" ") 82 | name (-> (if (= \( (first name)) method name) 83 | (s/split #"\(") 84 | first 85 | symbol)] 86 | (or 87 | (when (= "type" what) 88 | (some->> s-or-i keyword #{:struct :interface} (vector name))) 89 | [name (keyword what)])))) 90 | (println err)))) 91 | 92 | (defn go-get [package] 93 | (let [{:keys [exit err]} (sh/sh "go" "get" package)] 94 | (assert (zero? exit) err))) 95 | 96 | (defn get-goimports [] 97 | (go-get "code.google.com/p/go.tools/cmd/goimports")) 98 | 99 | (defn goimports [in] 100 | (get-goimports) 101 | (let [{:keys [exit out err]} (sh/sh "goimports" :in in)] 102 | (if (zero? exit) 103 | out 104 | (do (println err) in)))) 105 | 106 | (defn goimports-file [file] 107 | (get-goimports) 108 | (let [{:keys [exit out err]} (sh/sh "goimports" "-e=true" "-w=true" (str file))] 109 | (when-not (zero? exit) 110 | (println err) 111 | {:file file :errors (count (s/split-lines err))}))) 112 | 113 | (defn error-summary [dir {:keys [exit out err]}] 114 | (when-not (zero? exit) 115 | (println err) 116 | {:dir dir :errors (count (filter #(re-find #"^.+.go:\d+: " %) (s/split-lines err)))})) 117 | 118 | (defn go-test-compile [dir] 119 | (->> (sh/sh "go" "test" "-c" "--gcflags" "-e" :dir dir) (error-summary dir))) 120 | 121 | (defn go-install [dir] 122 | (->> (sh/sh "go" "install" "--gcflags" "-e" :dir dir) (error-summary dir))) 123 | 124 | (defn go-path-prefix [dir] 125 | (s/replace (str (.getCanonicalPath (io/file dir)) "/") 126 | (re-pattern (str "^" (io/file (System/getenv "GOPATH")) "/src/")) "")) 127 | 128 | (defn ns-to-resource [ns ext] 129 | (io/resource (str (-> ns str (s/replace "." "/") (s/replace "-" "_")) "." ext))) 130 | 131 | (defmacro with-fresh-ids [& body] 132 | `(let [^java.util.concurrent.atomic.AtomicInteger id# (.get (doto (.getDeclaredField clojure.lang.RT "id") 133 | (.setAccessible true)) 134 | nil) 135 | current-id# (.get id#)] 136 | (try 137 | (.set id# 1) 138 | ~@body 139 | (finally 140 | (.set id# current-id#) )))) 141 | 142 | (defn defs-in-file [f] 143 | (let [clj (read-string (str \[ (slurp f) \])) 144 | [[_ ns]] (filter (comp #{'ns} first) clj)] 145 | (for [[def? name] clj :when ('#{def defn} def?)] 146 | (symbol (str ns) (str name))))) 147 | 148 | (defn maybe-add-overrides [dir] 149 | (when-let [overrides (io/resource (str (s/replace (str ana/*cljs-ns*) "." "/") "/overrides.cljs"))] 150 | (let [target (io/file dir "overrides.go")] 151 | (binding [cljs.compiler/*go-defs* (atom [])] 152 | (cljs.compiler/compile-file (io/file overrides) target {:overrides? true}) 153 | (goimports-file target))))) 154 | 155 | (defn compile-file 156 | ([] (compile-file "." (io/resource "cljs/core.cljs"))) 157 | ([target src] 158 | (let [src (io/file src) 159 | target (if (.isDirectory (io/file target)) 160 | (cljs.compiler/to-go-target-file target src) 161 | (io/file target)) 162 | dir (.getParentFile target) 163 | compile #(env/ensure 164 | (binding [ana/*passes* [elide-children simplify-env ana/infer-type] 165 | ana/*cljs-static-fns* true 166 | cljs.compiler/*go-def-vars* false 167 | cljs.compiler/*go-defs* (or cljs.compiler/*go-defs* (atom []))] 168 | (with-fresh-ids 169 | (when-let [compiled-ns (:ns (cljs.compiler/compile-file src target))] 170 | (binding [ana/*cljs-ns* compiled-ns 171 | cljs.compiler/*go-skip-protocol* {} 172 | cljs.compiler/*go-skip-def* #{}] 173 | (maybe-add-overrides dir)) 174 | (goimports-file target) 175 | (if (re-find #"-test$" (str compiled-ns)) 176 | (go-test-compile dir) 177 | (go-install dir))))))] 178 | (if cljs.compiler/*go-verbose* 179 | (time 180 | (do 181 | (println "compiling" (str src)) 182 | (compile))) 183 | (compile))))) 184 | 185 | (defn compile-clojurescript 186 | ([] (compile-clojurescript 187 | "." 188 | '[cljs.core 189 | cljs.reader 190 | ;; cljs.test ;; issue with .cljs$lang$test and .cljs$lang$body 191 | ;; clojure.core.reducers ;; fails to macroexpand a destructure during analyzing. 192 | clojure.set clojure.data clojure.string clojure.walk clojure.zip])) 193 | ([target-dir namespaces] 194 | (env/ensure 195 | (with-fresh-ids 196 | (reset! ana/-cljs-macros-loaded false) 197 | (ana/load-core)) 198 | (doseq [ns namespaces 199 | :let [resource (ns-to-resource ns "cljs")]] 200 | (compile-file target-dir resource))))) 201 | 202 | 203 | ;; Doesn't work yet by far, will require at least three things: 204 | ;; 1. thin java.io compability layer. 205 | ;; 2. a working reader, including syntax quoting once we want to support macros. 206 | ;; 3. compiling macro fns and ability for the analyzer to use them to macroexpand. 207 | (defn compile-clojurescript-compiler 208 | ([] (compile-clojurescript-compiler 209 | "." 210 | '[cljs.env ;; will mostly be replaced, drags in js-deps. 211 | cljs.util ;; partly overridden in our compiler 212 | cljs.tagged-literals ;; drags in clojure.instant, so we'll probably skip these for a bit. 213 | cljs.analyzer ;; requires clojure.tools.reader, we need either to extend cljs.reader or compile this. 214 | cljs.go.compiler ;; same deps as analyzer. 215 | cljs.go.core ;; drags in lots of macros from clojure.core 216 | ])) 217 | ([target-dir namespaces] 218 | (env/ensure 219 | (doseq [ns namespaces 220 | :let [resource (ns-to-resource ns "clj") 221 | src (io/file "target/generated" 222 | (str (s/join "/" (cljs.compiler/relative-path-parts resource)) 223 | ".cljs"))]] 224 | (time 225 | (do 226 | (println "compiling" (str resource)) 227 | (io/make-parents src) 228 | (spit src (with-out-str 229 | (binding [*ns* (find-ns ('{cljs.go.core cljs.core} ns ns)) 230 | *print-meta* true] 231 | (doseq [f (read-string (str "[" (slurp resource) "]"))] 232 | (pp/pprint ((fn expander [f] 233 | (w/prewalk 234 | (fn [x] (if (and (seq? x) (symbol? (first x)) 235 | (not ('#{deftype defmulti defmethod ns case binding} 236 | (symbol (name (first x)))))) 237 | (case (first x) 238 | defmacro 239 | (when (= 'cljs.go.core ns) 240 | (macroexpand x)) 241 | import-macros 242 | (let [from (second x)] 243 | (apply list 'do 244 | (for [m (nth x 2)] 245 | (expander 246 | (read-string (repl/source-fn (symbol (str from) (str m)))))))) 247 | (macroexpand x)) 248 | x)) f)) f)))))) 249 | (compile-file (if (= 'cljs.go.core ns) 250 | (str target-dir "/cljs/core/macros.go") 251 | target-dir) src))))))) 252 | 253 | (defn -main [& args] 254 | (println "ClojureScript to Go [clojure]") 255 | (compile-clojurescript)) 256 | -------------------------------------------------------------------------------- /src/cljs/reader/overrides.cljs: -------------------------------------------------------------------------------- 1 | (ns ^{:doc "Go overrides."} 2 | cljs.reader 3 | (:require [goog.string :as gstring])) 4 | 5 | (defn read-2-chars [reader] 6 | (str 7 | (read-char reader) 8 | (read-char reader))) 9 | 10 | (defn read-4-chars [reader] 11 | (str 12 | (read-char reader) 13 | (read-char reader) 14 | (read-char reader) 15 | (read-char reader))) 16 | 17 | (defn read-token 18 | [rdr initch] 19 | (loop [sb (gstring/StringBuffer. initch) 20 | ch (read-char rdr)] 21 | (if (or (nil? ch) 22 | (whitespace? ch) 23 | (macro-terminating? ch)) 24 | (do (unread rdr ch) (.toString sb)) 25 | (recur (do (.append sb ch) sb) (read-char rdr))))) 26 | 27 | (defn macros [c] 28 | (cond 29 | (identical? c \") read-string* 30 | (identical? c \:) read-keyword 31 | (identical? c \;) read-comment 32 | (identical? c \') (wrapping-reader 'quote) 33 | (identical? c \@) (wrapping-reader 'deref) 34 | (identical? c \^) read-meta 35 | (identical? c \`) not-implemented 36 | (identical? c \~) not-implemented 37 | (identical? c \() read-list 38 | (identical? c \)) read-unmatched-delimiter 39 | (identical? c \[) read-vector 40 | (identical? c \]) read-unmatched-delimiter 41 | (identical? c \{) read-map 42 | (identical? c \}) read-unmatched-delimiter 43 | (identical? c \\) (fn [rdr _] (read-char rdr)) 44 | (identical? c \#) read-dispatch 45 | :else nil)) 46 | 47 | (def ^:private days-in-month 48 | (let [dim-norm [nil 31 28 31 30 31 30 31 31 30 31 30 31] 49 | dim-leap [nil 31 29 31 30 31 30 31 31 30 31 30 31]] 50 | (identity (fn [month leap-year?] 51 | (get (if leap-year? dim-leap dim-norm) month))))) 52 | 53 | (defn parse-timestamp 54 | [ts] 55 | (if-let [[years months days hours minutes seconds ms offset] 56 | (parse-and-validate-timestamp ts)] 57 | (js/Date. ts) 58 | (reader-error nil (str "Unrecognized date/time syntax: " ts)))) 59 | 60 | (defn ^:private read-queue 61 | [elems] 62 | (if (vector? elems) 63 | (into (.-EMPTY cljs.core/PersistentQueue) elems) 64 | (reader-error nil "Queue literal expects a vector for its elements."))) 65 | 66 | (defn ^:private read-date 67 | [s] 68 | (if (string? s) 69 | (parse-timestamp s) 70 | (reader-error nil "Instance literal expects a string for its timestamp."))) 71 | 72 | (defn ^:private read-uuid 73 | [uuid] 74 | (if (string? uuid) 75 | (UUID. uuid) 76 | (reader-error nil "UUID literal expects a string as its representation."))) 77 | 78 | (def ^:dynamic *tag-table* 79 | (atom {"inst" read-date 80 | "uuid" read-uuid 81 | "queue" read-queue})) 82 | -------------------------------------------------------------------------------- /src/clojure/data/overrides.cljs: -------------------------------------------------------------------------------- 1 | (ns ^{:doc "Go overrides."} 2 | clojure.data) 3 | 4 | 5 | (defn ep [x] 6 | (cond 7 | (nil? x) :atom 8 | (string? x) :atom 9 | (number? x) :atom 10 | (array? x) :sequential 11 | (fn? x) :atom 12 | (boolean? x) :atom 13 | (satisfies? IMap x) :map 14 | (satisfies? ISet x) :set 15 | (satisfies? ISequential x) :sequential 16 | :default :atom)) 17 | 18 | (defn ds [a b] 19 | ((case (ep a) 20 | :atom atom-diff 21 | :set diff-set 22 | :sequential diff-sequential 23 | :map diff-associative) 24 | a b)) 25 | 26 | (defn diff 27 | "Recursively compares a and b, returning a tuple of 28 | [things-only-in-a things-only-in-b things-in-both]. 29 | Comparison rules: 30 | 31 | * For equal a and b, return [nil nil a]. 32 | * Maps are subdiffed where keys match and values differ. 33 | * Sets are never subdiffed. 34 | * All sequential things are treated as associative collections 35 | by their indexes, with results returned as vectors. 36 | * Everything else (including strings!) is treated as 37 | an atom and compared for equality." 38 | [a b] 39 | (if (= a b) 40 | [nil nil a] 41 | (if (= (ep a) (ep b)) 42 | (ds a b) 43 | (atom-diff a b)))) 44 | -------------------------------------------------------------------------------- /src/clojure/string/overrides.cljs: -------------------------------------------------------------------------------- 1 | (ns ^{:doc "Go overrides."} 2 | clojure.string 3 | (:refer-clojure :exclude [replace reverse]) 4 | (:require [goog.string :as gstring])) 5 | 6 | (defn replace 7 | "Replaces all instance of match with replacement in s. 8 | match/replacement can be: 9 | 10 | string / string 11 | pattern / (string or function of match)." 12 | [s match replacement] 13 | (cond (string? match) 14 | (.replace s (js/RegExp. (gstring/regExpEscape match) "g") replacement) 15 | (instance? js/RegExp match) 16 | (.replace s (js/RegExp. (.-pattern match) (str (.-flags match) "g")) 17 | (if (fn? replacement) 18 | (js* "func(x interface{}) interface{} { return ~{}.(cljs_core.CljsCoreIFn).X_invoke_Arity1(x) }" 19 | replacement) 20 | replacement)) 21 | :else (throw (str "Invalid match arg: " match)))) 22 | 23 | (defn replace-first 24 | "Replaces the first instance of match with replacement in s. 25 | match/replacement can be: 26 | 27 | string / string 28 | pattern / (string or function of match)." 29 | [s match replacement] 30 | (.replace s match (if (fn? replacement) 31 | (js* "func(x interface{}) interface{} { return ~{}.(cljs_core.CljsCoreIFn).X_invoke_Arity1(x) }" 32 | replacement) 33 | replacement))) 34 | -------------------------------------------------------------------------------- /test/baz.cljs: -------------------------------------------------------------------------------- 1 | (ns baz) 2 | 3 | (defn f [x] x) 4 | -------------------------------------------------------------------------------- /test/cljs/binding_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.binding-test 2 | (:require [cljs.binding-test-other-ns :as o])) 3 | 4 | (defn test-binding [] 5 | (binding [o/*foo* 2] 6 | (assert (= o/*foo* 2))) 7 | (assert (= o/*foo* 1))) 8 | 9 | (defn test-with-redefs [] 10 | (with-redefs [o/bar 2] 11 | (assert (= o/bar 2))) 12 | (assert (= o/bar 10))) 13 | 14 | ^:top-level (js* 15 | "func Test_runner(t *testing.T) { 16 | ~{} 17 | ~{} 18 | assert.True(t, true) 19 | }" (test-binding) (test-with-redefs)) 20 | -------------------------------------------------------------------------------- /test/cljs/binding_test_other_ns.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.binding-test-other-ns) 2 | 3 | (def ^:dynamic *foo* 1) 4 | 5 | (def bar 10) 6 | -------------------------------------------------------------------------------- /test/cljs/go_test.clj: -------------------------------------------------------------------------------- 1 | (ns cljs.go-test 2 | (:refer-clojure :exclude [test]) 3 | (:require [clojure.test :refer :all] 4 | [cljs.go :refer :all] 5 | [cljs.go.compiler :as cljs.compiler] 6 | [cljs.analyzer :as ana] 7 | [cljs.env :as env] 8 | [cljs.tagged-literals] 9 | [clojure.pprint :as pp] 10 | [clojure.string :as s] 11 | [clojure.java.io :as io] 12 | [clojure.java.shell :as sh]) 13 | (:import [java.io Writer] 14 | [cljs.tagged_literals JSValue])) 15 | 16 | (defn pp [x] 17 | (binding [pp/*print-right-margin* 80] 18 | (pp/pprint x))) 19 | 20 | (def core-env nil) 21 | 22 | (defn cache-core! [] 23 | (def core-env (env/ensure 24 | (cljs.compiler/with-core-cljs {} 25 | (fn [] env/*compiler*))))) 26 | 27 | (defmacro tdd [& body] 28 | `(binding [env/*compiler* core-env] 29 | (env/ensure 30 | (cljs.compiler/with-core-cljs {} 31 | (fn [] 32 | (with-fresh-ids 33 | (def *ast (cljs->ast '[~@body])) 34 | (def *go (s/trim (goimports (ast->go *ast)))) 35 | (def *ns (ana/get-namespace ana/*cljs-ns*)) 36 | (pp *ast) 37 | (println) 38 | (println *go))))))) 39 | 40 | (defn combined-output [out err] 41 | (s/replace (s/replace (str err out) "\r" "\n") "\n\t\t" "")) 42 | 43 | (defn go-test [package] 44 | (let [{:keys [out err exit]} (sh/sh "go" "test" (str package))] 45 | (is (zero? exit) (combined-output out err)))) 46 | 47 | (defn test-header [package & imports] 48 | (with-out-str 49 | (println "package" package) 50 | (println "import" "cljs_core" (pr-str "github.com/hraberg/cljs2go/cljs/core")))) 51 | 52 | (def ^:dynamic *ast-debug* false) 53 | 54 | (defn test-comment [code ast] 55 | (println "/*") 56 | (pp code) 57 | (when *ast-debug* 58 | (println) 59 | (pp ast)) 60 | (println"*/")) 61 | 62 | (defn test-setup [setup] 63 | (with-out-str 64 | (let [ast (cljs->ast setup)] 65 | (test-comment setup ast) 66 | (printf "\t%s\n" (ast->go ast))))) 67 | 68 | (defn test-assertions [assertions] 69 | (doseq [[expected actual] (partition 2 assertions) 70 | :let [ast (-> [actual] (cljs->ast (assoc (cljs.analyzer/empty-env) :context :expr)))]] 71 | (test-comment actual (first ast)) 72 | (printf "\tassert.Equal(t,\n %s,\n %s)\n" expected (ast->go ast)))) 73 | 74 | (defn test [test & assertions] 75 | (with-out-str 76 | (printf "func Test_%s(t *testing.T) {\n" (name test)) 77 | (test-assertions assertions) 78 | (printf "}\n\n"))) 79 | 80 | (defn bench [benchmark & assertions] 81 | (with-out-str 82 | (printf "func Benchmark_%s(t *testing.B) {\n" (name benchmark)) 83 | (test-assertions assertions) 84 | (printf "}\n\n"))) 85 | 86 | (defn emit-test [package file tests] 87 | (go-get "github.com/stretchr/testify/assert") 88 | (doto (io/file (str "target/generated/" package) (str file ".go")) 89 | io/make-parents 90 | (spit (goimports (apply str (test-header package) tests))))) 91 | 92 | (defn constants [] 93 | (->> 94 | [(test "Constants" 95 | "nil" nil 96 | true true 97 | false false 98 | 1 1 99 | 3.14 3.14 100 | 2 '(inc 1) 101 | 10 '(* 4 2.5) 102 | "`foo`" "foo" 103 | "`x`" \x 104 | "map[string]interface{}{`foo`: `bar`}" (read-string "#js {:foo \"bar\"}") 105 | "[]interface{}{\"foo\", \"bar\"}" (read-string "#js [\"foo\", \"bar\"])") 106 | "&js.Date{Millis: 1408642409602}" #inst "2014-08-21T17:33:29.602-00:00" 107 | "&cljs_core.CljsCoreUUID{Uuid: `15c52219-a8fd-4771-87e2-42ee33b79bca`}" #uuid "15c52219-a8fd-4771-87e2-42ee33b79bca" 108 | "&js.RegExp{Pattern: `x`, Flags: ``}" #"x" 109 | "&js.RegExp{Pattern: ``, Flags: ``}" #"" 110 | "&cljs_core.CljsCoreSymbol{Ns: nil, Name: `x`, Str: `x`, X_hash: float64(-555367584), X_meta: nil}" ''x 111 | "&cljs_core.CljsCoreSymbol{Ns: `user`, Name: `x`, Str: `user/x`, X_hash: float64(-568535109), X_meta: nil}" ''user/x 112 | "&cljs_core.CljsCoreKeyword{Ns: nil, Name: `x`, Fqn: `x`, X_hash: float64(2099068185)}" :x 113 | "&cljs_core.CljsCoreKeyword{Ns: `user`, Name: `x`, Fqn: `user/x`, X_hash: float64(2085900660)}" :user/x)] 114 | (emit-test "go_test" "constants_test"))) 115 | 116 | (defn special-forms [] 117 | (->> 118 | [(test "Let" 119 | 1 '(let [y 1] 120 | y) 121 | "nil" '(let [x nil] 122 | x)) 123 | (test "Letfn" 124 | "`bar`" '(letfn [(foo [] "bar")] 125 | (foo)) 126 | true '(letfn [(even? [x] 127 | (or (zero? x) 128 | (odd? (dec x)))) 129 | (odd? [x] 130 | (and (not (zero? x)) 131 | (even? (dec x))))] 132 | (odd? 5))) 133 | (test "If" 134 | true '(let [y :foo] 135 | (if y true false)) 136 | 1 '(let [y true 137 | z (if y 1 0)] 138 | z) 139 | 1 '(letfn [(y [] true)] 140 | (if (y) 1 2)) 141 | 1 '(letfn [(y [] "")] 142 | (if (y) 1 2)) 143 | 2 (letfn [(^seq y [])] 144 | (if (y) 1 2)) 145 | 2 (letfn [(y [])] 146 | (if (y) 1 2))) 147 | (test "Loop" 148 | 5 '(loop [y 0] 149 | (if (== y 5) 150 | y 151 | (recur (inc y))))) 152 | (test "Do" 153 | 3 '(do 1 2 3)) 154 | (test-setup '[(def x 2)]) 155 | (test "Def" 156 | 2 'x) 157 | (test-setup '[(defn foo [] "bar")]) 158 | (test "Defn" 159 | "`bar`" '(foo)) 160 | (test-setup '[(defn bar 161 | ([x] x) 162 | ([x y] y)) 163 | (defn baz 164 | ([] (foo)) 165 | ([x] x) 166 | ([x & ys] (into-array ys)))]) 167 | (test "Invoke" 168 | "`bar`" '(letfn [(bar [f] (f))] 169 | (bar foo)) 170 | 1 '(bar 1) 171 | 2 '(bar 1 2) 172 | "`bar`" '(baz) 173 | 1 '(baz 1) 174 | "[]interface{}{2, 3}" '(baz 1 2 3) 175 | ;; last arg here to apply should be a seq 176 | "[]interface{}{2, 3, 4}" '(apply baz 1 2 [3 4]) 177 | "`bar`" '((fn [x] x) "bar") 178 | 3.14 '(js/ParseFloat "3.14") 179 | 3 '(Math/floor 3.14) 180 | 832040 '((fn fib [n] 181 | (cond (zero? n) 0 182 | (== 1 n) 1 183 | :else (+ (fib (dec n)) (fib (- n 2))))) 30)) 184 | (test "New" 185 | "&js.Date{Millis: 0}" '(js/Date. 0) 186 | "&js.Date{Millis: 0}" '(new js/Date 0)) 187 | (test "Dot" 188 | 1970 '(.getUTCFullYear (js/Date. 0)) 189 | "`f`" '(.charAt "foo" 0) 190 | 3 '(.-length "foo") 191 | "`o`" '(let [x "foo"] 192 | (.charAt x 1)) 193 | "`15c52219-a8fd-4771-87e2-42ee33b79bca`" '(.-uuid (UUID. "15c52219-a8fd-4771-87e2-42ee33b79bca"))) 194 | (test-setup '[(deftype MyPoint [x y]) 195 | 196 | (defprotocol IFoo 197 | (-bar [foo x])) 198 | 199 | (deftype MyFooWithArg [] 200 | IFoo 201 | (-bar [_ x] x)) 202 | 203 | (deftype MyFooWithThis [] 204 | IFoo 205 | (-bar [this _] this)) 206 | 207 | (def foo-with-this (MyFooWithThis.)) 208 | 209 | (deftype MyFooWithField [field] 210 | IFoo 211 | (-bar [_ _] field)) 212 | 213 | (deftype AnObject [] 214 | Object 215 | (toString [_] "baz") 216 | (equiv [this other] false) 217 | 218 | IFoo 219 | (-bar [this x] (str this x))) 220 | 221 | (defprotocol MyIEquiv 222 | (^boolean -my-equiv [o other])) 223 | 224 | (defprotocol IMarker) 225 | 226 | (deftype MyFooEquiv [str] 227 | IMarker 228 | Object 229 | (toString [_] str) 230 | (equiv [this other] 231 | (-my-equiv this other)) 232 | 233 | MyIEquiv 234 | (-my-equiv [_ _] 235 | false)) 236 | 237 | (defn foo-str [x] 238 | (str "foo" x)) 239 | 240 | (deftype MyInferenceType [] 241 | Object 242 | (toString [this] (foo-str "bar")))]) 243 | (test "Deftype" 244 | "&CljsUserMyPoint{X: 1, Y: 2}" '(MyPoint. 1 2) 245 | "&CljsUserMyPoint{X: 1, Y: 2}" '(->MyPoint 1 2) 246 | 3 '(.-x (MyPoint. 3 4)) 247 | "`CljsUserIFoo`" '(js* "reflect.TypeOf((*CljsUserIFoo)(nil)).Elem().Name()") 248 | 2 '(js* "reflect.TypeOf((*CljsUserIFoo)(nil)).Elem().NumMethod()") 249 | "`foo`" '(-bar (MyFooWithArg.) "foo") 250 | "`foo`" '(apply -bar (MyFooWithArg.) ["foo"]) 251 | "Foo_with_this" '(-bar (MyFooWithThis.) "foo") 252 | 0 '(-bar (MyFooWithField. 0) nil) 253 | true '(satisfies? cljs.user/IFoo foo-with-this) 254 | true '(satisfies? IFoo foo-with-this) 255 | false '(satisfies? cljs.user/IFoo (MyPoint. 0 0)) 256 | "`baz`" '(.toString (AnObject.)) 257 | "`baz`" '(.string (AnObject.)) 258 | false '(.equiv (AnObject.) "foo") 259 | true '(satisfies? Object (AnObject.)) 260 | "`bazbar`" '(-bar (AnObject.) "bar") 261 | false '(satisfies? IMarker (AnObject.)) 262 | 263 | "`bar`" '(str (MyFooEquiv. "bar")) 264 | false '(-my-equiv (MyFooEquiv. "bar") nil) 265 | true '(satisfies? IMarker (MyFooEquiv. "bar")) 266 | "`foobar`" '(str (MyInferenceType.))) 267 | (test "Var" 268 | "math.Inf(1)" 'js/Infinity) 269 | (test-setup '[(def y 2) 270 | (deftype HasFields [x]) 271 | (deftype HasStaticFields []) 272 | (set! (.-ZERO HasStaticFields) 0) 273 | (set! (.-newFoo HasStaticFields) (fn [] "foo"))]) 274 | (test "Set_BANG_" 275 | 2 'y 276 | 3 '(do (set! y 3) y) 277 | 4 '(set! y 4) 278 | "`foo`" '(set! (.-x (HasFields. "bar")) "foo") 279 | "`foo`" '((fn [o] (set! (.-x o) "foo")) (HasFields. "bar")) 280 | 0 '(.-ZERO HasStaticFields) 281 | "`foo`" '(.newFoo HasStaticFields) 282 | -1 '(set! (.-ZERO HasStaticFields) -1)) 283 | (test "Case_STAR_" 284 | true '(let [x 2] 285 | (case x 286 | 2 true 287 | 1 false 288 | 0))) 289 | (test "Js_STAR_" 290 | "reflect.Float64" '(let [x 1] 291 | (js* "reflect.ValueOf(x).Kind()")) 292 | "reflect.Int" '(let [v (js* "reflect.ValueOf(1)")] 293 | (-> v .Type .Kind))) 294 | (test "Try" 295 | "&js.Error{`Foo`}" '(try 296 | (throw (js/Error. "Foo")) 297 | (catch js/Error e 298 | e)) 299 | "`TypeError`" '(try 300 | (throw (js/TypeError. "Foo")) 301 | (catch js/Error _ 302 | "Error") 303 | (catch js/TypeError _ 304 | "TypeError")) 305 | "`Bar`" '(try 306 | "Bar" 307 | (catch js/Error e 308 | e) 309 | (finally 310 | "Baz")) 311 | "map[string]interface{}{`finally`: true}" 312 | '(let [x (js* "map[string]interface{}{}")] 313 | (try 314 | x 315 | (finally 316 | (js* "x[`finally`] = true")))) 317 | "map[string]interface{}{`catch`: true, `finally`: true, `last`: `finally`}" 318 | '(let [x (js* "map[string]interface{}{}")] 319 | (try 320 | (throw (js/Error. "Foo")) 321 | (catch js/Error _ 322 | (js* "x[`catch`] = true") 323 | (js* "x[`last`] = `catch`") 324 | x) 325 | (finally 326 | (js* "x[`finally`] = true") 327 | (js* "x[`last`] = `finally`")))))] 328 | (emit-test "go_test" "special_forms_test"))) 329 | 330 | ;; these are generated and compiled, but not actually run during the tests 331 | (defn benchmarks [] 332 | (->> 333 | [(bench "Fibonacci" 334 | 832040 '((fn fib [n] 335 | (cond (zero? n) 0 336 | (== 1 n) 1 337 | :else (+ (fib (dec n)) (fib (- n 2))))) 30)) 338 | (bench "FibonacciPrimtitves" 339 | 832040 '((fn ^number fib [^number n] 340 | (cond (zero? n) 0 341 | (== 1 n) 1 342 | :else (+ (fib (dec n)) (fib (- n 2))))) 30)) 343 | (bench "Factorial" 344 | 2432902008176640000 345 | '((fn fact 346 | ([n] (fact n 1)) 347 | ([n f] 348 | (if (== n 1) 349 | f 350 | (recur (dec n) (* f n))))) 20))] 351 | (emit-test "go_test" "benchmarks_test"))) 352 | 353 | (defn clojurescript-tests 354 | ([] (clojurescript-tests 355 | "." 356 | '[cljs.core-test 357 | cljs.reader-test 358 | cljs.binding-test-other-ns 359 | cljs.binding-test 360 | cljs.macro-test 361 | cljs.letfn-test 362 | cljs.ns-test.bar 363 | cljs.ns-test.foo 364 | cljs.ns-test 365 | clojure.string-test 366 | clojure.data-test 367 | baz 368 | foo.ns-shadow-test 369 | cljs.top-level-test 370 | cljs.keyword-other 371 | cljs.keyword-test])) 372 | ([target namespaces] 373 | (doseq [:let [go-project-path (go-path-prefix target)] 374 | ns namespaces] 375 | (binding [cljs.compiler/*go-import-prefix* (merge cljs.compiler/*go-import-prefix* 376 | (zipmap namespaces (repeat go-project-path)))] 377 | (compile-file target (io/file (ns-to-resource ns "cljs"))))))) 378 | 379 | (deftest go-all-tests 380 | (binding [cljs.analyzer/*cljs-file* (:file (meta #'go-test)) 381 | cljs.compiler/*go-line-numbers* true 382 | *ast-debug* false 383 | cljs.compiler/*go-def-vars* true 384 | cljs.compiler/*go-verbose* false 385 | *data-readers* cljs.tagged-literals/*cljs-data-readers*] 386 | (doseq [gen [constants special-forms benchmarks clojurescript-tests]] 387 | (with-fresh-ids 388 | (env/ensure 389 | (cljs.compiler/with-core-cljs {} gen)))) 390 | (go-test "./..."))) 391 | 392 | (defn run-benchmarks [] 393 | (doseq [dir ["." "target/generated/go_test"]] 394 | (let [{:keys [out err exit]} (sh/sh "go" "test" "-bench" "." :dir dir)] 395 | (println (combined-output out err))))) 396 | 397 | (defmethod print-method cljs.tagged_literals.JSValue 398 | [^JSValue d ^Writer w] 399 | (.write w "#js ") 400 | (print-method (.val d) w)) 401 | -------------------------------------------------------------------------------- /test/cljs/keyword_other.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.keyword-other) 2 | 3 | (defn foo [a b] 4 | (+ a b)) 5 | -------------------------------------------------------------------------------- /test/cljs/keyword_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.keyword-test 2 | (:require [cljs.keyword-other :as other]) 3 | (:require-macros [clojure.core :as cc])) 4 | 5 | (defn test-keyword [] 6 | (assert (= ::bar :cljs.keyword-test/bar)) 7 | (assert (= ::other/foo :cljs.keyword-other/foo)) 8 | (assert (= ::cc/foo :clojure.core/foo))) 9 | 10 | ^:top-level (js* 11 | "func Test_runner(t *testing.T) { 12 | ~{} 13 | assert.True(t, true) 14 | }" (test-keyword)) 15 | -------------------------------------------------------------------------------- /test/cljs/letfn_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.letfn-test) 2 | 3 | (defn test-letfn [] 4 | (letfn [(ev? [x] 5 | (if (zero? x) 6 | true 7 | (od? (dec x)))) 8 | (od? [x] 9 | (if (zero? x) 10 | false 11 | (ev? (dec x))))] 12 | (assert (ev? 0)) 13 | (assert (ev? 10)) 14 | (assert (not (ev? 1))) 15 | (assert (not (ev? 11))) 16 | (assert (not (od? 0))) 17 | (assert (not (od? 10))) 18 | (assert (od? 1)) 19 | (assert (od? 11)))) 20 | 21 | ^:top-level (js* 22 | "func Test_runner(t *testing.T) { 23 | ~{} 24 | assert.True(t, true) 25 | }" (test-letfn)) 26 | -------------------------------------------------------------------------------- /test/cljs/macro_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.macro-test 2 | (:refer-clojure :exclude [==]) 3 | (:use-macros [cljs.macro-test.macros :only [==]])) 4 | 5 | (defn test-macros [] 6 | (assert (= (== 1 1) 2))) 7 | 8 | ^:top-level (js* 9 | "func Test_runner(t *testing.T) { 10 | ~{} 11 | assert.True(t, true) 12 | }" (test-macros)) 13 | -------------------------------------------------------------------------------- /test/cljs/macro_test/macros.clj: -------------------------------------------------------------------------------- 1 | (ns cljs.macro-test.macros 2 | (:refer-clojure :exclude [==])) 3 | 4 | (defmacro == [a b] 5 | `(+ ~a ~b)) -------------------------------------------------------------------------------- /test/cljs/ns_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.ns-test 2 | (:refer-clojure :exclude [+ for]) 3 | (:require-macros [clojure.core :as lang]) 4 | (:require [cljs.ns-test.foo :refer [baz]] 5 | [clojure.set :as s]) 6 | (:use [cljs.ns-test.bar :only [quux]])) 7 | 8 | (def + -) 9 | 10 | (defn test-ns [] 11 | (assert (= 4 (clojure.core/+ 2 1 1))) 12 | (assert (= 0 (cljs.ns-test/+ 2 1 1))) 13 | (assert (= 0 (+ 2 1 1))) 14 | (assert (= 123 (baz))) 15 | (assert (= 123 (quux))) 16 | 17 | (assert (= (range 5) (lang/for [x (range 5)] x))) 18 | (assert (= #{1 2 3} (s/union #{1} #{2 3}))) 19 | :ok) 20 | 21 | ^:top-level (js* 22 | "func Test_runner(t *testing.T) { 23 | assert.Equal(t, ~{}, ~{}) 24 | }" :ok (test-ns)) 25 | -------------------------------------------------------------------------------- /test/cljs/ns_test/bar.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.ns-test.bar) 2 | 3 | (defn quux [] 123) 4 | -------------------------------------------------------------------------------- /test/cljs/ns_test/foo.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.ns-test.foo) 2 | 3 | (defn baz [] 123) 4 | 5 | (def kw ::foo) 6 | (def qkw '::foo) 7 | 8 | (assert (= (str kw) ":cljs.ns-test.foo/foo")) 9 | (assert (= (str qkw) ":cljs.ns-test.foo/foo")) 10 | -------------------------------------------------------------------------------- /test/cljs/reader_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.reader-test 2 | (:require [cljs.reader :as reader] 3 | [goog.object :as o])) 4 | 5 | (deftype T [a b]) 6 | (defrecord R [a b]) 7 | 8 | (defn test-reader 9 | [] 10 | (assert (= 1 (reader/read-string "1"))) 11 | (assert (= 2 (reader/read-string "#_nope 2"))) 12 | (assert (= -1 (reader/read-string "-1"))) 13 | (assert (= -1.5 (reader/read-string "-1.5"))) 14 | (assert (= [3 4] (reader/read-string "[3 4]"))) 15 | (assert (= "foo" (reader/read-string "\"foo\""))) 16 | (assert (= :hello (reader/read-string ":hello"))) 17 | (assert (= 'goodbye (reader/read-string "goodbye"))) 18 | (assert (= '% (reader/read-string "%"))) 19 | (assert (= #{1 2 3} (reader/read-string "#{1 2 3}"))) 20 | (assert (= '(7 8 9) (reader/read-string "(7 8 9)"))) 21 | (assert (= '(deref foo) (reader/read-string "@foo"))) 22 | (assert (= '(quote bar) (reader/read-string "'bar"))) 23 | (assert (= 'foo/bar (reader/read-string "foo/bar"))) 24 | (assert (= \a (reader/read-string "\\a"))) 25 | (assert (= {:tag 'String} (meta (reader/read-string "^String {:a 1}")))) 26 | (assert (= [:a 'b #{'c {:d [:e :f :g]}}] 27 | (reader/read-string "[:a b #{c {:d [:e :f :g]}}]"))) 28 | (assert (= :foo/bar (reader/read-string ":foo/bar"))) 29 | (assert (= nil (reader/read-string "nil"))) 30 | (assert (= true (reader/read-string "true"))) 31 | (assert (= false (reader/read-string "false"))) 32 | (assert (= "string" (reader/read-string "\"string\""))) 33 | (assert (= "escape chars \t \r \n \\ \" \b \f" (reader/read-string "\"escape chars \\t \\r \\n \\\\ \\\" \\b \\f\""))) 34 | 35 | ;; number literals 36 | ;; (assert (apply = 0 (map reader/read-string "0" "+0" "-0" " 0 "))) 37 | (assert (apply = 0 (map reader/read-string ["0" "+0" "-0" " 0 "]))) 38 | (assert (apply = 42 (map reader/read-string ["052" "0x2a" "2r101010" "8R52" "16r2a" "36r16"]))) 39 | (assert (apply = 42 (map reader/read-string ["+052" "+0x2a" "+2r101010" "+8r52" "+16R2a" "+36r16"]))) 40 | (assert (apply = -42 (map reader/read-string ["-052" "-0X2a" "-2r101010" "-8r52" "-16r2a" "-36R16"]))) 41 | 42 | ;; queue literals 43 | (assert (= (.-EMPTY cljs.core/PersistentQueue) 44 | (reader/read-string "#queue []"))) 45 | 46 | (assert (= (-> (.-EMPTY cljs.core/PersistentQueue) (conj 1)) 47 | (reader/read-string "#queue [1]"))) 48 | 49 | (assert (= (into (.-EMPTY cljs.core/PersistentQueue) [1 2]) 50 | (reader/read-string "#queue [1 2]"))) 51 | 52 | ;; comments 53 | (assert (nil? (reader/read-string ";foo"))) 54 | 55 | (assert (= 3 (try 56 | (reader/read-string ";foo\n3") 57 | (catch js/Error e :threw)))) 58 | (assert (= 3 (try 59 | (reader/read-string ";foo\n3\n5") 60 | (catch js/Error e :threw)))) 61 | 62 | ;; inst 63 | (let [est-inst (reader/read-string "#inst \"2010-11-12T13:14:15.666-05:00\"") 64 | utc-inst (reader/read-string "#inst \"2010-11-12T18:14:15.666-00:00\"") 65 | pad (fn [n] 66 | (if (< n 10) 67 | (str "0" n) 68 | n))] 69 | 70 | (assert (= (.valueOf (js/Date. "2010-11-12T13:14:15.666-05:00")) 71 | (.valueOf est-inst))) 72 | 73 | (assert (= (.valueOf est-inst) 74 | (.valueOf (reader/read-string (pr-str est-inst))))) 75 | 76 | (assert (= (.valueOf est-inst) 77 | (.valueOf utc-inst))) 78 | 79 | (doseq [month (range 1 13) day (range 1 29) hour (range 1 23)] 80 | (let [s (str "#inst \"2010-" (pad month) "-" (pad day) "T" (pad hour) ":14:15.666-06:00\"")] 81 | (assert (= (-> s reader/read-string .valueOf) 82 | (-> s reader/read-string pr-str reader/read-string .valueOf)))))) 83 | 84 | (let [insts [(reader/read-string "#inst \"2012\"") 85 | (reader/read-string "#inst \"2012-01\"") 86 | (reader/read-string "#inst \"2012-01-01\"") 87 | (reader/read-string "#inst \"2012-01-01T00\"") 88 | (reader/read-string "#inst \"2012-01-01T00:00:00.000\"") 89 | ;; Won't Fix 90 | ;; (reader/read-string "#inst \"2012-01-01T00:00:00.000123456\"") 91 | ;; (reader/read-string "#inst \"2012-01-01T00:00:00.000123456789+00:00\"") 92 | ]] 93 | (assert (apply = (map #(.valueOf %) insts)))) 94 | 95 | ;; uuid literals 96 | (let [u (reader/read-string "#uuid \"550e8400-e29b-41d4-a716-446655440000\"")] 97 | (assert (= u (reader/read-string "#uuid \"550e8400-e29b-41d4-a716-446655440000\""))) 98 | 99 | ;; Won't Fix 100 | ;; (assert (not (identical? u (reader/read-string "#uuid \"550e8400-e29b-41d4-a716-446655440000\"")))) 101 | 102 | (assert (= u (-> u pr-str reader/read-string)))) 103 | 104 | ;; new tag parsers 105 | 106 | (reader/register-tag-parser! 'foo identity) 107 | 108 | (assert (= [1 2] (reader/read-string "#foo [1 2]"))) 109 | 110 | ;; tag elements with prefix component 111 | (reader/register-tag-parser! 'foo.bar/baz identity) 112 | (assert (= [1 2] (reader/read-string "#foo.bar/baz [1 2]"))) 113 | 114 | ;; default tag parser 115 | (reader/register-default-tag-parser! (fn [tag val] val)) 116 | (assert (= [1 2] (reader/read-string "#a.b/c [1 2]"))) 117 | 118 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 119 | ;; Unicode Tests 120 | 121 | ; sample unicode strings, symbols, keywords 122 | (doseq [unicode 123 | ["اختبار" ; arabic 124 | "ทดสอบ" ; thai 125 | "こんにちは" ; japanese hiragana 126 | "你好" ; chinese traditional 127 | "אַ גוט יאָר" ; yiddish 128 | "cześć" ; polish 129 | "привет" ; russian 130 | 131 | ;; RTL languages skipped below because tricky to insert 132 | ;; ' and : at the "start" 133 | 134 | 'ทดสอบ 135 | 'こんにちは 136 | '你好 137 | 'cześć 138 | 'привет 139 | 140 | :ทดสอบ 141 | :こんにちは 142 | :你好 143 | :cześć 144 | :привет 145 | 146 | ;compound data 147 | {:привет :ru "你好" :cn} 148 | ]] 149 | (let [input (pr-str unicode) 150 | read (reader/read-string input)] 151 | (assert (= unicode read) 152 | (str "Failed to read-string \"" unicode "\" from: " input)))) 153 | 154 | ;; ; unicode error cases 155 | (doseq [unicode-error 156 | ["\"abc \\ua\"" ; truncated 157 | "\"abc \\x0z ...etc\"" ; incorrect code 158 | "\"abc \\u0g00 ..etc\"" ; incorrect code 159 | ]] 160 | (let [r (try 161 | (reader/read-string unicode-error) 162 | :failed-to-throw 163 | (catch js/Error e :ok))] 164 | (assert (= r :ok) (str "Failed to throw reader error for: " unicode-error)))) 165 | 166 | ;; CLJS-717 167 | 168 | ;; (assert (array? (reader/read-string "#js [1 2 3]"))) 169 | ;; (assert (= (alength (reader/read-string "#js [1 2 3]")) 3)) 170 | ;; (assert (= (seq (reader/read-string "#js [1 2 3]")) (seq [1 2 3]))) 171 | ;; (assert (= (set (js-keys (reader/read-string "#js {:foo \"bar\" :baz \"woz\"}"))) #{"foo" "baz"})) 172 | ;; (assert (= (aget (reader/read-string "#js {:foo \"bar\"}") "foo") "bar")) 173 | ;; (assert (= (aget (reader/read-string "#js {\"foo\" \"bar\"}") "foo") "bar")) 174 | ;; (assert (array? (aget (reader/read-string "#js {\"foo\" #js [1 2 3]}") "foo"))) 175 | ;; (assert (= (seq (aget (reader/read-string "#js {\"foo\" #js [1 2 3]}") "foo")) '(1 2 3))) 176 | 177 | ;; CLJS-787 178 | 179 | (assert (nil? (reader/read-string ""))) 180 | 181 | ;; CLJS-819 182 | (let [re (reader/read-string "#\"\\s\\u00a1\"") 183 | m (re-find re " \u00a1 ")] 184 | (assert (= m " \u00a1"))) 185 | 186 | :ok) 187 | 188 | ^:top-level (js* 189 | "func Test_runner(t *testing.T) { 190 | assert.Equal(t, ~{}, ~{}) 191 | }" :ok (test-reader)) 192 | -------------------------------------------------------------------------------- /test/cljs/top_level_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.top-level-test 2 | (:refer-clojure :exclude [test])) 3 | 4 | (let [foo 1] 5 | (defn bar [] 6 | foo)) 7 | 8 | (let [foo 2] 9 | (defn baz [] 10 | foo)) 11 | 12 | (defn test [] 13 | (assert (= (bar) 1)) 14 | (assert (= (baz) 2))) 15 | 16 | ^:top-level (js* 17 | "func Test_runner(t *testing.T) { 18 | ~{} 19 | assert.True(t, true) 20 | }" (test)) 21 | -------------------------------------------------------------------------------- /test/clojure/data_test.cljs: -------------------------------------------------------------------------------- 1 | (ns clojure.data-test 2 | (:require [clojure.data :refer [diff]])) 3 | 4 | (defn test-data [] 5 | (assert (= [nil nil nil] (diff nil nil))) 6 | (assert (= [1 2 nil] (diff 1 2))) 7 | (assert (= [nil nil [1 2 3]] (diff [1 2 3] '(1 2 3)))) 8 | (assert (= [1 [:a :b] nil] (diff 1 [:a :b]))) 9 | (assert (= [{:a 1} :b nil] (diff {:a 1} :b))) 10 | (assert (= [:team #{:p1 :p2} nil] (diff :team #{:p1 :p2}))) 11 | (assert (= [{0 :a} [:a] nil] (diff {0 :a} [:a]))) 12 | (assert (= [nil [nil 2] [1]] (diff [1] [1 2]))) 13 | (assert (= [nil nil [1 2]] (diff [1 2] (into-array [1 2])))) 14 | (assert (= [#{:a} #{:b} #{:c :d}] (diff #{:a :c :d} #{:b :c :d}))) 15 | (assert (= [nil nil {:a 1}] (diff {:a 1} {:a 1}))) 16 | (assert (= [{:a #{2}} {:a #{4}} {:a #{3}}] (diff {:a #{2 3}} {:a #{3 4}}))) 17 | (assert (= [nil nil [1 2]] (diff [1 2] (into-array [1 2])))) 18 | (assert (= [nil nil [1 2]] (diff (into-array [1 2]) [1 2]))) 19 | (assert (= [{:a {:c [1]}} {:a {:c [0]}} {:a {:c [nil 2] :b 1}}] 20 | (diff {:a {:b 1 :c [1 2]}} {:a {:b 1 :c [0 2]}}))) 21 | (assert (= [{:a nil} {:a false} {:b nil :c false}] 22 | (diff {:a nil :b nil :c false} {:a false :b nil :c false})))) 23 | 24 | ^:top-level (js* 25 | "func Test_runner(t *testing.T) { 26 | ~{} 27 | assert.True(t, true) 28 | }" (test-data)) 29 | -------------------------------------------------------------------------------- /test/clojure/string_test.cljs: -------------------------------------------------------------------------------- 1 | (ns clojure.string-test 2 | (:require [clojure.string :as s])) 3 | 4 | (defn test-string 5 | [] 6 | ;; reverse 7 | (assert (= "" (s/reverse ""))) 8 | (assert (= "tab" (s/reverse "bat"))) 9 | ;; CLJS-814 10 | ;; FAILURE 11 | ;; (assert (= "c\uD834\uDD1Ea" (s/reverse "a\uD834\uDD1Ec"))) ;; U+1D11E MUSICAL SYMBOL G CLEF 12 | ;; replace 13 | (assert (= "faabar" (s/replace "foobar" \o \a))) 14 | (assert (= "barbarbar" (s/replace "foobarfoo" "foo" "bar"))) 15 | (assert (= "FOObarFOO" (s/replace "foobarfoo" #"foo" s/upper-case))) 16 | (assert (= "barbar)foo" (s/replace "foo(bar)foo" "foo(" "bar"))) 17 | ;; join 18 | (assert (= "" (s/join nil))) 19 | (assert (= "" (s/join []))) 20 | (assert (= "1" (s/join [1]))) 21 | (assert (= "12" (s/join [1 2]))) 22 | (assert (= "1,2,3" (s/join \, [1 2 3]))) 23 | (assert (= "" (s/join \, []))) 24 | (assert (= "1 and-a 2 and-a 3" (s/join " and-a " [1 2 3]))) 25 | ;; capitalize 26 | (assert (= "FOOBAR" (s/upper-case "Foobar"))) 27 | (assert (= "foobar" (s/lower-case "FooBar"))) 28 | (assert (= "Foobar" (s/capitalize "foobar"))) 29 | (assert (= "Foobar" (s/capitalize "FOOBAR"))) 30 | ;; split 31 | (assert (= ["a" "b"] (s/split "a-b" #"-"))) 32 | (assert (= ["a" "b" "c"] (s/split "a-b-c" #"-" -1))) 33 | (assert (= ["a" "b" "c"] (s/split "a-b-c" #"-" 0))) 34 | (assert (= ["a-b-c"] (s/split "a-b-c" #"-" 1))) 35 | (assert (= ["a" "b-c"] (s/split "a-b-c" #"-" 2))) 36 | (assert (= ["a" "b" "c"] (s/split "a-b-c" #"-" 3))) 37 | (assert (= ["a" "b" "c"] (s/split "a-b-c" #"-" 4))) 38 | (assert (vector? (s/split "abc" #"-"))) 39 | (assert (= ["a-b-c"] (s/split "a-b-c" #"x" 2))) 40 | (assert (= ["" "a" "b" "c" ""] (s/split "abc" (re-pattern "") 5))) 41 | (assert (= ["a"] (s/split "ab" #"b"))) 42 | (assert (= [] (s/split "ab" #"ab"))) 43 | ;; split-lines 44 | (let [result (s/split-lines "one\ntwo\r\nthree")] 45 | (assert (= ["one" "two" "three"] result)) 46 | (assert (vector? result))) 47 | (assert (= (list "foo") (s/split-lines "foo"))) 48 | ;; blank 49 | (assert (s/blank? nil)) 50 | (assert (s/blank? "")) 51 | (assert (s/blank? " ")) 52 | (assert (s/blank? " \t \n \r ")) 53 | (assert (not (s/blank? " foo "))) 54 | ;; escape 55 | (assert (= "<foo&bar>" 56 | (s/escape "" {\& "&" \< "<" \> ">"}))) 57 | (assert (= " \\\"foo\\\" " 58 | (s/escape " \"foo\" " {\" "\\\""}))) 59 | (assert (= "faabor" 60 | (s/escape "foobar" {\a \o, \o \a}))) 61 | ;; replace-first 62 | (assert (= "barbarfoo" (s/replace-first "foobarfoo" "foo" "bar"))) 63 | (assert (= "barbarfoo" (s/replace-first "foobarfoo" #"foo" "bar"))) 64 | (assert (= "z.ology" (s/replace-first "zoology" \o \.))) 65 | (assert (= "FOObarfoo" (s/replace-first "foobarfoo" #"foo" s/upper-case))) 66 | ;; trim 67 | (assert (= "foo " (s/triml " foo "))) 68 | (assert (= "" (s/triml " "))) 69 | (assert (= " foo" (s/trimr " foo "))) 70 | (assert (= "" (s/trimr " "))) 71 | (assert (= "foo" (s/trim " foo \r\n"))) 72 | ;; trim-newline 73 | (assert (= "foo" (s/trim-newline "foo\n"))) 74 | (assert (= "foo" (s/trim-newline "foo\r\n"))) 75 | (assert (= "foo" (s/trim-newline "foo"))) 76 | (assert (= "foo\r " (s/trim-newline "foo\r "))) 77 | (assert (= "" (s/trim-newline ""))) 78 | :ok) 79 | 80 | (comment 81 | 82 | (deftest char-sequence-handling 83 | (are [result f args] (let [[^CharSequence s & more] args] 84 | (= result (apply f (StringBuffer. s) more))) 85 | "paz" s/reverse ["zap"] 86 | "foo:bar" s/replace ["foo-bar" \- \:] 87 | "ABC" s/replace ["abc" #"\w" s/upper-case] 88 | "faa" s/replace ["foo" #"o" (StringBuffer. "a")] 89 | "baz::quux" s/replace-first ["baz--quux" #"--" "::"] 90 | "baz::quux" s/replace-first ["baz--quux" (StringBuffer. "--") (StringBuffer. "::")] 91 | "zim-zam" s/replace-first ["zim zam" #" " (StringBuffer. "-")] 92 | "Pow" s/capitalize ["POW"] 93 | "BOOM" s/upper-case ["boom"] 94 | "whimper" s/lower-case ["whimPER"] 95 | ["foo" "bar"] s/split ["foo-bar" #"-"] 96 | "calvino" s/trim [" calvino "] 97 | "calvino " s/triml [" calvino "] 98 | " calvino" s/trimr [" calvino "] 99 | "the end" s/trim-newline ["the end\r\n\r\r\n"] 100 | true s/blank? [" "] 101 | ["a" "b"] s/split-lines ["a\nb"] 102 | "fa la la" s/escape ["fo lo lo" {\o \a}])) 103 | ) 104 | 105 | ^:top-level (js* 106 | "func Test_runner(t *testing.T) { 107 | assert.Equal(t, ~{}, ~{}) 108 | }" :ok (test-string)) 109 | -------------------------------------------------------------------------------- /test/foo/ns_shadow_test.cljs: -------------------------------------------------------------------------------- 1 | (ns foo.ns-shadow-test 2 | (:require baz)) 3 | 4 | (defn bar [] 1) 5 | 6 | (defn quux [foo] 7 | (+ (foo.ns-shadow-test/bar) foo)) 8 | 9 | (defn id [x] x) 10 | 11 | (defn foo [] (id 42)) 12 | 13 | (defn baz 14 | ([] (baz 2)) 15 | ([x] (quux 2))) 16 | 17 | (defn test-shadow [] 18 | (assert (= (quux 2) 3)) 19 | (assert (= (foo) 42)) 20 | (assert (= (baz) 3))) 21 | 22 | ^:top-level (js* 23 | "func Test_runner(t *testing.T) { 24 | ~{} 25 | assert.True(t, true) 26 | }" (test-shadow)) 27 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/LICENCE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell 2 | 3 | Please consider promoting this project if you find it useful. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/doc.go: -------------------------------------------------------------------------------- 1 | // A set of comprehensive testing tools for use with the normal Go testing system. 2 | // 3 | // Example Usage 4 | // 5 | // The following is a complete example using assert in a standard test function: 6 | // import ( 7 | // "testing" 8 | // "github.com/stretchr/testify/assert" 9 | // ) 10 | // 11 | // func TestSomething(t *testing.T) { 12 | // 13 | // var a string = "Hello" 14 | // var b string = "Hello" 15 | // 16 | // assert.Equal(t, a, b, "The two words should be the same.") 17 | // 18 | // } 19 | // 20 | // if you assert many times, use the below: 21 | // 22 | // import ( 23 | // "testing" 24 | // "github.com/stretchr/testify/assert" 25 | // ) 26 | // 27 | // func TestSomething(t *testing.T) { 28 | // assert := assert.New(t) 29 | // 30 | // var a string = "Hello" 31 | // var b string = "Hello" 32 | // 33 | // assert.Equal(a, b, "The two words should be the same.") 34 | // } 35 | // 36 | // Assertions 37 | // 38 | // Assertions allow you to easily write test code, and are global funcs in the `assert` package. 39 | // All assertion functions take, as the first argument, the `*testing.T` object provided by the 40 | // testing framework. This allows the assertion funcs to write the failings and other details to 41 | // the correct place. 42 | // 43 | // Every assertion function also takes an optional string message as the final argument, 44 | // allowing custom error messages to be appended to the message the assertion method outputs. 45 | // 46 | // Here is an overview of the assert functions: 47 | // 48 | // assert.Equal(t, expected, actual [, message [, format-args]) 49 | // 50 | // assert.NotEqual(t, notExpected, actual [, message [, format-args]]) 51 | // 52 | // assert.True(t, actualBool [, message [, format-args]]) 53 | // 54 | // assert.False(t, actualBool [, message [, format-args]]) 55 | // 56 | // assert.Nil(t, actualObject [, message [, format-args]]) 57 | // 58 | // assert.NotNil(t, actualObject [, message [, format-args]]) 59 | // 60 | // assert.Empty(t, actualObject [, message [, format-args]]) 61 | // 62 | // assert.NotEmpty(t, actualObject [, message [, format-args]]) 63 | // 64 | // assert.Len(t, actualObject, expectedLength, [, message [, format-args]]) 65 | // 66 | // assert.Error(t, errorObject [, message [, format-args]]) 67 | // 68 | // assert.NoError(t, errorObject [, message [, format-args]]) 69 | // 70 | // assert.EqualError(t, theError, errString [, message [, format-args]]) 71 | // 72 | // assert.Implements(t, (*MyInterface)(nil), new(MyObject) [,message [, format-args]]) 73 | // 74 | // assert.IsType(t, expectedObject, actualObject [, message [, format-args]]) 75 | // 76 | // assert.Contains(t, string, substring [, message [, format-args]]) 77 | // 78 | // assert.NotContains(t, string, substring [, message [, format-args]]) 79 | // 80 | // assert.Panics(t, func(){ 81 | // 82 | // // call code that should panic 83 | // 84 | // } [, message [, format-args]]) 85 | // 86 | // assert.NotPanics(t, func(){ 87 | // 88 | // // call code that should not panic 89 | // 90 | // } [, message [, format-args]]) 91 | // 92 | // assert.WithinDuration(t, timeA, timeB, deltaTime, [, message [, format-args]]) 93 | // 94 | // assert.InDelta(t, numA, numB, delta, [, message [, format-args]]) 95 | // 96 | // assert.InEpsilon(t, numA, numB, epsilon, [, message [, format-args]]) 97 | // 98 | // assert package contains Assertions object. it has assertion methods. 99 | // 100 | // Here is an overview of the assert functions: 101 | // assert.Equal(expected, actual [, message [, format-args]) 102 | // 103 | // assert.NotEqual(notExpected, actual [, message [, format-args]]) 104 | // 105 | // assert.True(actualBool [, message [, format-args]]) 106 | // 107 | // assert.False(actualBool [, message [, format-args]]) 108 | // 109 | // assert.Nil(actualObject [, message [, format-args]]) 110 | // 111 | // assert.NotNil(actualObject [, message [, format-args]]) 112 | // 113 | // assert.Empty(actualObject [, message [, format-args]]) 114 | // 115 | // assert.NotEmpty(actualObject [, message [, format-args]]) 116 | // 117 | // assert.Len(actualObject, expectedLength, [, message [, format-args]]) 118 | // 119 | // assert.Error(errorObject [, message [, format-args]]) 120 | // 121 | // assert.NoError(errorObject [, message [, format-args]]) 122 | // 123 | // assert.EqualError(theError, errString [, message [, format-args]]) 124 | // 125 | // assert.Implements((*MyInterface)(nil), new(MyObject) [,message [, format-args]]) 126 | // 127 | // assert.IsType(expectedObject, actualObject [, message [, format-args]]) 128 | // 129 | // assert.Contains(string, substring [, message [, format-args]]) 130 | // 131 | // assert.NotContains(string, substring [, message [, format-args]]) 132 | // 133 | // assert.Panics(func(){ 134 | // 135 | // // call code that should panic 136 | // 137 | // } [, message [, format-args]]) 138 | // 139 | // assert.NotPanics(func(){ 140 | // 141 | // // call code that should not panic 142 | // 143 | // } [, message [, format-args]]) 144 | // 145 | // assert.WithinDuration(timeA, timeB, deltaTime, [, message [, format-args]]) 146 | // 147 | // assert.InDelta(numA, numB, delta, [, message [, format-args]]) 148 | // 149 | // assert.InEpsilon(numA, numB, epsilon, [, message [, format-args]]) 150 | package assert 151 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/errors.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // AnError is an error instance useful for testing. If the code does not care 8 | // about error specifics, and only needs to return the error for example, this 9 | // error should be used to make the test code more readable. 10 | var AnError = errors.New("assert.AnError general error for testing") 11 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/forward_assertions.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import "time" 4 | 5 | type Assertions struct { 6 | t TestingT 7 | } 8 | 9 | func New(t TestingT) *Assertions { 10 | return &Assertions{ 11 | t: t, 12 | } 13 | } 14 | 15 | // Fail reports a failure through 16 | func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { 17 | return Fail(a.t, failureMessage, msgAndArgs...) 18 | } 19 | 20 | // Implements asserts that an object is implemented by the specified interface. 21 | // 22 | // assert.Implements((*MyInterface)(nil), new(MyObject), "MyObject") 23 | func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { 24 | return Implements(a.t, interfaceObject, object, msgAndArgs...) 25 | } 26 | 27 | // IsType asserts that the specified objects are of the same type. 28 | func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { 29 | return IsType(a.t, expectedType, object, msgAndArgs...) 30 | } 31 | 32 | // Equal asserts that two objects are equal. 33 | // 34 | // assert.Equal(123, 123, "123 and 123 should be equal") 35 | // 36 | // Returns whether the assertion was successful (true) or not (false). 37 | func (a *Assertions) Equal(expected, actual interface{}, msgAndArgs ...interface{}) bool { 38 | return Equal(a.t, expected, actual, msgAndArgs...) 39 | } 40 | 41 | // Exactly asserts that two objects are equal is value and type. 42 | // 43 | // assert.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal") 44 | // 45 | // Returns whether the assertion was successful (true) or not (false). 46 | func (a *Assertions) Exactly(expected, actual interface{}, msgAndArgs ...interface{}) bool { 47 | return Exactly(a.t, expected, actual, msgAndArgs...) 48 | } 49 | 50 | // NotNil asserts that the specified object is not nil. 51 | // 52 | // assert.NotNil(err, "err should be something") 53 | // 54 | // Returns whether the assertion was successful (true) or not (false). 55 | func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { 56 | return NotNil(a.t, object, msgAndArgs...) 57 | } 58 | 59 | // Nil asserts that the specified object is nil. 60 | // 61 | // assert.Nil(err, "err should be nothing") 62 | // 63 | // Returns whether the assertion was successful (true) or not (false). 64 | func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { 65 | return Nil(a.t, object, msgAndArgs...) 66 | } 67 | 68 | // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or a 69 | // slice with len == 0. 70 | // 71 | // assert.Empty(obj) 72 | // 73 | // Returns whether the assertion was successful (true) or not (false). 74 | func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { 75 | return Empty(a.t, object, msgAndArgs...) 76 | } 77 | 78 | // Empty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or a 79 | // slice with len == 0. 80 | // 81 | // if assert.NotEmpty(obj) { 82 | // assert.Equal("two", obj[1]) 83 | // } 84 | // 85 | // Returns whether the assertion was successful (true) or not (false). 86 | func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { 87 | return NotEmpty(a.t, object, msgAndArgs...) 88 | } 89 | 90 | // Len asserts that the specified object has specific length. 91 | // Len also fails if the object has a type that len() not accept. 92 | // 93 | // assert.Len(mySlice, 3, "The size of slice is not 3") 94 | // 95 | // Returns whether the assertion was successful (true) or not (false). 96 | func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { 97 | return Len(a.t, object, length, msgAndArgs...) 98 | } 99 | 100 | // True asserts that the specified value is true. 101 | // 102 | // assert.True(myBool, "myBool should be true") 103 | // 104 | // Returns whether the assertion was successful (true) or not (false). 105 | func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { 106 | return True(a.t, value, msgAndArgs...) 107 | } 108 | 109 | // False asserts that the specified value is true. 110 | // 111 | // assert.False(myBool, "myBool should be false") 112 | // 113 | // Returns whether the assertion was successful (true) or not (false). 114 | func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { 115 | return False(a.t, value, msgAndArgs...) 116 | } 117 | 118 | // NotEqual asserts that the specified values are NOT equal. 119 | // 120 | // assert.NotEqual(obj1, obj2, "two objects shouldn't be equal") 121 | // 122 | // Returns whether the assertion was successful (true) or not (false). 123 | func (a *Assertions) NotEqual(expected, actual interface{}, msgAndArgs ...interface{}) bool { 124 | return NotEqual(a.t, expected, actual, msgAndArgs...) 125 | } 126 | 127 | // Contains asserts that the specified string contains the specified substring. 128 | // 129 | // assert.Contains("Hello World", "World", "But 'Hello World' does contain 'World'") 130 | // 131 | // Returns whether the assertion was successful (true) or not (false). 132 | func (a *Assertions) Contains(s, contains string, msgAndArgs ...interface{}) bool { 133 | return Contains(a.t, s, contains, msgAndArgs...) 134 | } 135 | 136 | // NotContains asserts that the specified string does NOT contain the specified substring. 137 | // 138 | // assert.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'") 139 | // 140 | // Returns whether the assertion was successful (true) or not (false). 141 | func (a *Assertions) NotContains(s, contains string, msgAndArgs ...interface{}) bool { 142 | return NotContains(a.t, s, contains, msgAndArgs...) 143 | } 144 | 145 | // Uses a Comparison to assert a complex condition. 146 | func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { 147 | return Condition(a.t, comp, msgAndArgs...) 148 | } 149 | 150 | // Panics asserts that the code inside the specified PanicTestFunc panics. 151 | // 152 | // assert.Panics(func(){ 153 | // GoCrazy() 154 | // }, "Calling GoCrazy() should panic") 155 | // 156 | // Returns whether the assertion was successful (true) or not (false). 157 | func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { 158 | return Panics(a.t, f, msgAndArgs...) 159 | } 160 | 161 | // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. 162 | // 163 | // assert.NotPanics(func(){ 164 | // RemainCalm() 165 | // }, "Calling RemainCalm() should NOT panic") 166 | // 167 | // Returns whether the assertion was successful (true) or not (false). 168 | func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { 169 | return NotPanics(a.t, f, msgAndArgs...) 170 | } 171 | 172 | // WithinDuration asserts that the two times are within duration delta of each other. 173 | // 174 | // assert.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s") 175 | // 176 | // Returns whether the assertion was successful (true) or not (false). 177 | func (a *Assertions) WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { 178 | return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) 179 | } 180 | 181 | // InDelta asserts that the two numerals are within delta of each other. 182 | // 183 | // assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) 184 | // 185 | // Returns whether the assertion was successful (true) or not (false). 186 | func (a *Assertions) InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { 187 | return InDelta(a.t, expected, actual, delta, msgAndArgs...) 188 | } 189 | 190 | // InEpsilon asserts that expected and actual have a relative error less than epsilon 191 | // 192 | // Returns whether the assertion was successful (true) or not (false). 193 | func (a *Assertions) InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { 194 | return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) 195 | } 196 | 197 | // NoError asserts that a function returned no error (i.e. `nil`). 198 | // 199 | // actualObj, err := SomeFunction() 200 | // if assert.NoError(err) { 201 | // assert.Equal(actualObj, expectedObj) 202 | // } 203 | // 204 | // Returns whether the assertion was successful (true) or not (false). 205 | func (a *Assertions) NoError(theError error, msgAndArgs ...interface{}) bool { 206 | return NoError(a.t, theError, msgAndArgs...) 207 | } 208 | 209 | // Error asserts that a function returned an error (i.e. not `nil`). 210 | // 211 | // actualObj, err := SomeFunction() 212 | // if assert.Error(err, "An error was expected") { 213 | // assert.Equal(err, expectedError) 214 | // } 215 | // 216 | // Returns whether the assertion was successful (true) or not (false). 217 | func (a *Assertions) Error(theError error, msgAndArgs ...interface{}) bool { 218 | return Error(a.t, theError, msgAndArgs...) 219 | } 220 | 221 | // EqualError asserts that a function returned an error (i.e. not `nil`) 222 | // and that it is equal to the provided error. 223 | // 224 | // actualObj, err := SomeFunction() 225 | // if assert.Error(err, "An error was expected") { 226 | // assert.Equal(err, expectedError) 227 | // } 228 | // 229 | // Returns whether the assertion was successful (true) or not (false). 230 | func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { 231 | return EqualError(a.t, theError, errString, msgAndArgs...) 232 | } 233 | --------------------------------------------------------------------------------