carbonate 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c37e5aef9fbc0edef926681f59511b35b7946ea6
4
+ data.tar.gz: 7d624dc7a2fd2ce5f04d07bc691f0f57aafdd297
5
+ SHA512:
6
+ metadata.gz: 1fed03d1b276ec929440206087b8f377dadbdc1e0fc58bf882a4d5bfcd550dd40584208200515c7022f7891be2889bb969dd9a8f84b9aaa55440dd97845ced59
7
+ data.tar.gz: 444f03109191cc664b619c16d947222dd1e5011ec9905c41eabeb5f5a6a750dbbac33e160a139fecdbc97dfcb44e2aed509bcfb9e82bee6d744bfc425bef7614
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in carbonate.gemspec
4
+ gemspec
@@ -0,0 +1,12 @@
1
+ guard :rspec, cmd: 'bundle exec rspec', all_on_start: true do
2
+ require 'guard/rspec/dsl'
3
+ dsl = Guard::RSpec::Dsl.new(self)
4
+
5
+ rspec = dsl.rspec
6
+ watch(rspec.spec_helper) { rspec.spec_dir }
7
+ watch(rspec.spec_support) { rspec.spec_dir }
8
+ watch(rspec.spec_files)
9
+
10
+ ruby = dsl.ruby
11
+ dsl.watch_spec_files_for(ruby.lib_files)
12
+ end
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Vsevolod Romashov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,669 @@
1
+ # Carbonate
2
+
3
+ Carbonate is a Lisp dialect heavily influenced by Clojure. It is transpiled into Ruby code.
4
+
5
+ Carbonate tries to cover all of Ruby's functionality while giving a more concise form to the code.
6
+
7
+ Here's what it looks like:
8
+
9
+ ``` clojure
10
+ (defclass User
11
+ (defmethod initialize [first-name last-name email]
12
+ (def @first-name first-name)
13
+ (def @last-name last-name)
14
+ (def @email email))
15
+ (defmethod full-name []
16
+ (join [@first_name @last_name]))
17
+ (defmethod each-name []
18
+ (each [@first-name @last-name] #([name] (@yield name)))))
19
+ ```
20
+
21
+ The code above is equvalent to the following ruby:
22
+
23
+ ``` ruby
24
+ class User
25
+ def initialize(first_name, last_name, email)
26
+ @first_name = first_name
27
+ @last_name = last_name
28
+ @email = email
29
+ end
30
+
31
+ def full_name
32
+ [@first_name, @last_name].join
33
+ end
34
+
35
+ def each_name
36
+ [@first_name, @last_name].each do |name|
37
+ yield name
38
+ end
39
+ end
40
+ end
41
+ ```
42
+
43
+ ## Installation
44
+
45
+ ``` ruby
46
+ # Gemfile
47
+ gem 'carbonate'
48
+ ```
49
+
50
+ ``` sh
51
+ $ bundle
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ Currently there are 2 ways to run Carbonate code: convert it to Ruby statically and use the resulting `.rb` files as you normally would or evaluate Carbonate source files dynamically.
57
+
58
+ ### Converting from Carbonate to Ruby
59
+
60
+ The gem ships with a `crb2rb` utility that converts Carbonate source code into Ruby source code. You can use it to convert a Carbonate file to a Ruby file:
61
+
62
+ ``` sh
63
+ $ crb2rb < source.crb > target.rb
64
+ # or
65
+ $ crb2rb -i source.crb -o target.rb
66
+ ```
67
+
68
+ ### Using Carbonate sources directly
69
+
70
+ Carbonate source code can be transpiled and instantly evaluated by Ruby code. This allows you to plug it in a Ruby application and use it right away.
71
+
72
+ Carbonate gives 2 functions to transpile and evaluate Carbonate sources: `Carbonate.require` and `Carbonate.require_relative` - they work exactly like their counterparts from Ruby's `Kernel` but they are searching for a `.crb` file instead of a `.rb` one, and they transpile it to Ruby before evaluating.
73
+
74
+ ## Syntax
75
+
76
+ ### Literal values
77
+
78
+ Numbers in Carbonate look exactly like they do in Ruby:
79
+
80
+ ``` clojure
81
+ 127
82
+ -32
83
+ 3.14
84
+ ```
85
+
86
+ Strings are always double-quoted and support all the usual control characters like `\n` and `\t`. Double quotes have to be escaped with a backslash. String interpolation is not supported.
87
+
88
+ ``` clojure
89
+ "Hello world!"
90
+ "Line 1\nLine 2\n\tIndented line"
91
+ "Yukihiro \"Matz\" Matsumoto"
92
+ ```
93
+
94
+ Symbols look similarly to Ruby symbols but use dashes (`-`) instead of underscores (`_`):
95
+
96
+ ``` clojure
97
+ :north
98
+ :user-name
99
+ :exists?
100
+ ```
101
+
102
+ Regular expressions are written as double-quoted strings prefixed with a pound sign (`#`). Like strings, they support control characters and require you to escape double quotes.
103
+
104
+ ``` clojure
105
+ #"[A-Za-z]+"
106
+ ```
107
+
108
+ `true`, `false`, and `nil` are the same as in Ruby.
109
+
110
+ Arrays are enclosed within brackets (`[]`) but do not require commas between elements. In fact, comma is treated as a whitespace character in Carbonate - you can use it but you don't have to.
111
+
112
+ ``` clojure
113
+ [1 2 3]
114
+ ["Yukihiro Matsumoto" "Rich Hickey"]
115
+ ```
116
+
117
+ Hashes are represented by key-value pairs inside curly brackets (`{}`). In contrast to Ruby, there are no delimiters between a key and a value. Separating pairs with commas can sometimes be useful to keep readability.
118
+
119
+ ``` clojure
120
+ {:type :book
121
+ :title "SICP"
122
+ :authors ["Harold Abelson" "Gerald Jay Sussman" "Julie Sussman"]}
123
+ ```
124
+
125
+ Sets are also enclosed within curly brackets but prefixed with a pound sign.
126
+
127
+ ``` clojure
128
+ #{"one" "two" "three"}
129
+ ```
130
+
131
+ Be sure to `require 'set'` to use them - sets live in a standard library package in Ruby (read on to learn how to call methods like `require` in Carbonate).
132
+
133
+ Ranges look exactly like in Ruby - values separated with two dots for inclusive ranges and values separated with three dots for exclusive ones:
134
+
135
+ ``` clojure
136
+ "a".."z"
137
+ 0...10
138
+ ```
139
+
140
+ Constants are written down using the same CamelCase'd words as in Ruby but `.` is used as a delimiter:
141
+
142
+ ``` clojure
143
+ Carbonate.Parser
144
+ ```
145
+
146
+ Explicit top-level constants are prefixed with `.` (exactly like they are with `::` in Ruby):
147
+
148
+ ``` clojure
149
+ .Hash
150
+ ```
151
+
152
+ The current object known as `self` in Ruby is written down as `@` in Carbonate.
153
+
154
+ ### Calling functions/methods
155
+
156
+ In Lisp function calls are written down using prefix notation in S-expressions; basically this means that every operation is a list of elements enclosed within parentheses where the first element represents the function and all the other elements are it's arguments.
157
+
158
+ Here's some basic arithmetic:
159
+
160
+ ``` clojure
161
+ (+ 2 2)
162
+ (- 2 1)
163
+ (* 2 3)
164
+ ```
165
+
166
+ Of course S-expressions can be nested:
167
+
168
+ ``` clojure
169
+ (/ (* 3 4) 2)
170
+ (** (- 4 2) 3)
171
+ ```
172
+
173
+ Comparison operators also mirror the Ruby ones with an exception of equality - it is represented with a single `=`:
174
+
175
+ ``` clojure
176
+ (= x y)
177
+ (!= x y)
178
+ (< 1 2)
179
+ (> 2 1)
180
+ (>= 2 2)
181
+ (<= 2 2)
182
+ (<=> a b)
183
+ (=== a b)
184
+ ```
185
+
186
+ Binary operators `&`, `|`, `^`, `~`, `<<` and `>>` follow their Ruby counterparts. Logic operators, on the other hand, are slightly changed:
187
+
188
+ ``` clojure
189
+ (and (= x y) (!= x z))
190
+ (or (> x z) (> y z))
191
+ (! false)
192
+ ```
193
+
194
+ ### Variables and assignment
195
+
196
+ Carbonate supports local and instance variables. They look like in Ruby but use `-` separator instead of `_`:
197
+
198
+ ``` clojure
199
+ local-variable
200
+ @instance-variable
201
+ ```
202
+
203
+ You can assign a value to a variable using `def` keyword:
204
+
205
+ ``` clojure
206
+ (def a 1)
207
+ (def @age 35)
208
+ ```
209
+
210
+ This also works for constants:
211
+
212
+ ``` clojure
213
+ (def DAYS-IN-WEEK 7)
214
+ ```
215
+
216
+ Carbonate also supports the so-called conditional assignment (`||=` in Ruby) using `def-or` keyword:
217
+
218
+ ``` clojure
219
+ (def-or name "Steve")
220
+ (def-or @city "NYC")
221
+ ```
222
+
223
+ (This is not supported with constants for obvious reasons)
224
+
225
+ There are a few more special cases. First you can assign a value to an object's attribute (like you would do with `user.name = 'John'` in Ruby):
226
+
227
+ ``` clojure
228
+ (def user.name "John")
229
+ ```
230
+
231
+ Second you can both read from and write to an array or a hash member using essentially the same syntax as in Ruby:
232
+
233
+ ``` clojure
234
+ user[:name]
235
+ (def user[:name] "John")
236
+ ```
237
+
238
+ Both attribute and collection member writers support conditional assignment with the aforementioned `def-or`.
239
+
240
+ ### Conditional statements
241
+
242
+ Almost any code contains conditional execution - you won't go far without `if` & `unless` statements so here they are:
243
+
244
+ ``` clojure
245
+ (if (> 2 1) "2 is greater" "1 is greater")
246
+ (if (= x 5) "x is 5")
247
+ (unless (>= age 18) "too young")
248
+ ```
249
+
250
+ As you can see from the snippet above, `if` can be used in 2 variations: if you pass it a condition and 2 more forms (S-expressions, literal values, variables or anything that returns a value) the first form will be used for "truthy" condition value and the second for "falsy". If you just pass one form it will be used for the "truthy" case.
251
+
252
+ `unless` doesn't have a 2-form mode - it's a bad practice anyway - so the only form after the condition will be used for the falsy condition.
253
+
254
+ If you need to group several statements inside one `if` or `unless` statement you can use a `do` statement - it allows you to join several S-expressions into one:
255
+
256
+ ``` clojure
257
+ (if (valid? user)
258
+ (do
259
+ (save user)
260
+ (@puts (name user))))
261
+ ```
262
+
263
+ Carbonate also has a `case` statement:
264
+
265
+ ``` clojure
266
+ (case x
267
+ 1 "one"
268
+ 2 "two")
269
+ ```
270
+
271
+ Pretty self-explanatory. It also supports an else clause as the last form of the statement:
272
+
273
+ ``` clojure
274
+ (case lang
275
+ "clojure" "great!"
276
+ "ruby" "cool"
277
+ "crap")
278
+ ```
279
+
280
+ ### Loop statements
281
+
282
+ There are 2 main loop statements in Carbonate: `while` and `until`. Both of them take a condition as the first argument and the loop body as the second:
283
+
284
+ ``` clojure
285
+ (while (< x 5)
286
+ (def x (+ x 1)))
287
+ (until (>= x 5)
288
+ (def x (+ x 1)))
289
+ ```
290
+
291
+ ### Calling methods
292
+
293
+ The most common construct in Ruby code is a method call. Carbonate allows you to call a method within an S-expression consisting of the method name and the receiver object:
294
+
295
+ ``` clojure
296
+ (name user)
297
+ ```
298
+
299
+ This is equivalent to the following Ruby:
300
+
301
+ ``` ruby
302
+ user.name
303
+ ```
304
+
305
+ *(all Carbonate snippets are followed by equivalent Ruby snippets later on)*
306
+
307
+ If you need to pass some arguments to a method you do so after the receiver:
308
+
309
+ ``` clojure
310
+ (include? [1 2 3] 4)
311
+ ```
312
+
313
+ ``` ruby
314
+ [1, 2, 3].include?(4)
315
+ ```
316
+
317
+ Carbonate supports splat arguments - if you have some `Enumerable` collection you can pass it to the method as several separate arguments. Ruby uses `*` for that goal, Carbonate uses `&` (note that `&` and the argument are separated by a space):
318
+
319
+ ``` clojure
320
+ (add-tags article & tags)
321
+ ```
322
+
323
+ ``` ruby
324
+ article.add_tags(*tags)
325
+ ```
326
+
327
+ Class methods are invoked a little differently - the method name is prefixed with the class name separated with `/`, and all following elements are method's arguments:
328
+
329
+ ``` clojure
330
+ (User/count)
331
+ (User/find-by {:first-name "John"})
332
+ ```
333
+
334
+ ``` ruby
335
+ User.count
336
+ User.find_by(first_name: 'John')
337
+ ```
338
+
339
+ Method calls without an explicit receiver (which are implicitly called on `self`) are written with a method name prefixed by `@`:
340
+
341
+ ``` clojure
342
+ (@attr-reader :first-name)
343
+ ```
344
+
345
+ ``` ruby
346
+ attr_reader :first_name
347
+ ```
348
+
349
+ Carbonate offers a special syntax for class constructor calls - it looks like a class name followed by a dot:
350
+
351
+ ``` clojure
352
+ (User. {:name "John"})
353
+ ```
354
+
355
+ ``` ruby
356
+ User.new(name: 'John')
357
+ ```
358
+
359
+ Another special case is `super` - a call to parent class' respective method:
360
+
361
+ ``` clojure
362
+ (super)
363
+ (super "parameter")
364
+ ```
365
+
366
+ ``` ruby
367
+ super()
368
+ super('parameter')
369
+ ```
370
+
371
+ The tricky part here is a call to `super` with implicit parameters - as you may know, calling `super` without parameters and without parentheses in Ruby actually passes it all the parameters passed to the enclosing method, and if you need to force `super` call without parameters you have to write `super()`. The latter is written as just `(super)` in Carbonate and the former is `(zsuper)` (Zero-arity super).
372
+
373
+ Like in Ruby, you can pass a block to a method - it is enclosed within parentheses prefixed with `#`, and the first element inside the parentheses is the block parameters list:
374
+
375
+ ``` clojure
376
+ (map users #([user] (upcase (name user))))
377
+ ```
378
+
379
+ ``` ruby
380
+ users.map do |user|
381
+ user.name.upcase
382
+ end
383
+ ```
384
+
385
+ You don't have to specify an empty parameters list if your block has no parameters - just type your block body inside `#(...)`:
386
+
387
+ ``` clojure
388
+ (times 5 #(@puts "Hello"))
389
+ ```
390
+
391
+ ``` ruby
392
+ 5.times { puts 'Hello' }
393
+ ```
394
+
395
+ If you want to use the `Symbol#to_proc` trick you can just pass the symbol after `#` (like `&`, it needs to be separated from the following element with a space):
396
+
397
+ ``` clojure
398
+ (map users # :name)
399
+ ```
400
+
401
+ ``` ruby
402
+ users.map(&:name)
403
+ ```
404
+
405
+ This works with plain procs too:
406
+
407
+ ``` clojure
408
+ (each users # some-proc)
409
+ ```
410
+
411
+ ``` ruby
412
+ users.each(&some_proc)
413
+ ```
414
+
415
+ ### Defining methods
416
+
417
+ A method definition consists of the `defmethod` keyword, then the name of the method, then the parameters list and the method body. As usual, all the identifiers (method name, parameters and variables) use `-` instead of `_`. It looks like this:
418
+
419
+ ``` clojure
420
+ (defmethod full-name []
421
+ (join [@first-name @last-name]))
422
+ ```
423
+
424
+ ``` ruby
425
+ def full_name
426
+ [@first_name, @last_name].join
427
+ end
428
+ ```
429
+
430
+ The parameters list supports splat arguments and blocks with basically the same syntax as in method invocation:
431
+
432
+ ``` clojure
433
+ (defmethod iterate [a b c & d # block]
434
+ (@puts a b c d)
435
+ (@yield a)
436
+ (@yield b)
437
+ (@yield c)
438
+ (each d # block))
439
+ ```
440
+
441
+ ``` ruby
442
+ def iterate(a, b, c, *d, &block)
443
+ puts a, b, c, d
444
+ yield a
445
+ yield b
446
+ yield c
447
+ d.each(&block)
448
+ end
449
+ ```
450
+
451
+ Carbonate also supports default parameter values - just put the parameter name with a default value inside the brackets:
452
+
453
+ ``` clojure
454
+ (defmethod int-to-string [int [base 10]]
455
+ (to-s int base))
456
+ ```
457
+
458
+ ``` ruby
459
+ def int_to_string(int, base = 10)
460
+ int.to_s(base)
461
+ end
462
+ ```
463
+
464
+ A `return` clause is used like this:
465
+
466
+ ``` clojure
467
+ (defmethod nothing [] (return))
468
+ (defmethod name [] (return "John"))
469
+ ```
470
+
471
+ ``` ruby
472
+ def nothing
473
+ return
474
+ end
475
+
476
+ def name
477
+ return 'John'
478
+ end
479
+ ```
480
+
481
+ ### Exception handling
482
+
483
+ If you need to use a `rescue` clause inside your method you can just put it at the end of the method body:
484
+
485
+ ``` clojure
486
+ (defmethod read-file [path]
487
+ (File/read path)
488
+ (rescue Errno.ENOENT e
489
+ (@puts "No file found.")))
490
+ ```
491
+
492
+ ``` ruby
493
+ def read_file(path)
494
+ File.read(path)
495
+ rescue Errno::ENOENT => e
496
+ puts 'No file found.'
497
+ end
498
+ ```
499
+
500
+ *(you can have as many `rescue` clauses as you want - just be sure to keep them at the end of method body)*
501
+
502
+ The `ensure` clause is available as well, you can put it after all `rescue` clauses (or at the end of the method body if you don't need to rescue anything):
503
+
504
+ ``` clojure
505
+ (defmethod read-file [path]
506
+ (File/read path)
507
+ (rescue Errno.ENOENT e (@puts "No file found."))
508
+ (ensure (@puts "Tried to read a file.")))
509
+ ```
510
+
511
+ ``` ruby
512
+ def read_file(path)
513
+ File.read(path)
514
+ rescue Errno::ENOENT => e
515
+ puts 'No file found.'
516
+ ensure
517
+ puts 'Tried to read a file.'
518
+ end
519
+ ```
520
+
521
+ There are cases when you need to intercept an exception from an arbitrary piece of code, not just method; a `try` statement can help you with that:
522
+
523
+ ``` clojure
524
+ (try (File/read path)
525
+ (rescue Errno.ENOENT e
526
+ (@puts (message e))
527
+ (@raise)))
528
+ ```
529
+
530
+ ``` ruby
531
+ begin
532
+ File.read(path)
533
+ rescue Errno::ENOENT => e
534
+ puts e.message
535
+ raise
536
+ end
537
+ ```
538
+
539
+ `try` allows you to put any number of `rescue` clauses and/or an `ensure` clause at the end, just like method bodies.
540
+
541
+ ### Lambdas
542
+
543
+ Lambda definitions look a lot like method definitions - they have a parameters list and a body:
544
+
545
+ ``` clojure
546
+ (-> [user] (email user))
547
+ (-> [user] (@p user) (save user))
548
+ ```
549
+
550
+ ``` ruby
551
+ -> (user) { user.email }
552
+
553
+ -> (user) do
554
+ p user
555
+ user.save
556
+ end
557
+ ```
558
+
559
+ If the lambda doesn't have parameters you can omit them altogether:
560
+
561
+ ``` clojure
562
+ (-> (@puts "Hello world!"))
563
+ ```
564
+
565
+ ``` ruby
566
+ -> { puts 'Hello world!' }
567
+ ```
568
+
569
+ ### Classes and modules
570
+
571
+ No serious Ruby application can exist without classes and modules. Carbonate allows defining classes with `defclass` keyword:
572
+
573
+ ``` clojure
574
+ (defclass User
575
+ (defmethod initialize [first-name last-name]
576
+ (def @first-name first-name)
577
+ (def @last-name last-name))
578
+ (defmethod full-name []
579
+ (join [@first-name @last-name])))
580
+ ```
581
+
582
+ ``` ruby
583
+ class User
584
+ def initialize(first_name, last_name)
585
+ @first_name = first_name
586
+ @last_name = last_name
587
+ end
588
+
589
+ def full_name
590
+ [@first_name, @last_name].join
591
+ end
592
+ end
593
+ ```
594
+
595
+ If you need to specify the parent class you can use an already familiar syntax:
596
+
597
+ ``` clojure
598
+ (defclass User < Base
599
+ (@include Naming))
600
+ ```
601
+
602
+ ``` ruby
603
+ class User < Base
604
+ include Naming
605
+ end
606
+ ```
607
+
608
+ Similarly a module can be defined with `defmodule`:
609
+
610
+ ``` clojure
611
+ (defmodule Naming
612
+ (@attr-reader :first-name :last-name)
613
+ (defmethod full-name []
614
+ (join [first-name last-name])))
615
+ ```
616
+
617
+ ``` ruby
618
+ module Naming
619
+ attr_reader :first_name, :last_name
620
+
621
+ def full_name
622
+ [first_name, last_name].join
623
+ end
624
+ end
625
+ ```
626
+
627
+ When you want to open up an object's singleton class you need `<<-`:
628
+
629
+ ``` clojure
630
+ (<<- user
631
+ (defmethod name []
632
+ @name))
633
+ ```
634
+
635
+ ``` ruby
636
+ class << user
637
+ def name
638
+ @name
639
+ end
640
+ end
641
+ ```
642
+
643
+ ## Acknowledgements
644
+
645
+ This project would not be possible without these wonderful libraries:
646
+
647
+ * [farcaller/rly](https://github.com/farcaller/rly)
648
+ * [whitequark/parser](https://github.com/whitequark/parser)
649
+ * [mbj/unparser](https://github.com/mbj/unparser)
650
+
651
+ ## Roadmap
652
+
653
+ * improve parser performance
654
+ * add meaningful stack traces
655
+ * add macros support
656
+
657
+ ## Development
658
+
659
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake[ spec]` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
660
+
661
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
662
+
663
+ ## Contributing
664
+
665
+ Bug reports and pull requests are welcome on GitHub at [7even/carbonate](https://github.com/7even/carbonate).
666
+
667
+ ## License
668
+
669
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).