carbonate 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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).