calcula 0.1.0 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: acb99c969e886a94ca30cc534dc3db8c76f0ea0a
4
- data.tar.gz: f5801be3a546e8aef049aa56cd566dcf53e27d0f
3
+ metadata.gz: 397e946ee023cbfbe15fbd3c78e7fda729e9fa41
4
+ data.tar.gz: ad9f8f5b4da62221b96e08e4ff3afd2887317f40
5
5
  SHA512:
6
- metadata.gz: 6c254c1b82fd8b658e28b876fbaa8c2bde737e57360cc748640cca4253b5d2a451845d1196fc4ee0645cb5769faec78ecb014f7495c90967580fccdc94b60c46
7
- data.tar.gz: 92c14c7803111bde6c62e52b128fccc6bc7f40d175b348f6178a67fd6def282222dea3407416076ad63bbd822255d75450ff7dc6d4d2caae982549a70142eecd
6
+ metadata.gz: 9017478c73db894b546a21bd0563a5e40cbca71281831223fe345b581a0d5c585791195fc1f10c988a413ba81715ddd792967c95882cca31cfe573e573a15817
7
+ data.tar.gz: f4033ce6ce081fbf36995db752a7f90c96844663949d78abdc5fa7846b4cef0e808728940dcce1a4bc1508f996c6fdb6092f7a69b7d08f9ab0136bca527c9778
data/.travis.yml CHANGED
@@ -3,3 +3,6 @@ language: ruby
3
3
  rvm:
4
4
  - 2.3.1
5
5
  before_install: gem install bundler -v 1.13.2
6
+ addons:
7
+ code_climate:
8
+ repo_token: 4ca379840aee24144c568378f1425a8a330e1e1ab46043ffcf16660d0ffa9de2
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in calcula.gemspec
4
4
  gemspec
5
+
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2016 TODO: Write your name
3
+ Copyright (c) 2016 Paul T.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Calcula [![Build Status](https://travis-ci.org/plankp/Calcula.svg?branch=master)](https://travis-ci.org/plankp/Calcula) [![Inline docs](http://inch-ci.org/github/plankp/Calcula.svg?branch=master)](http://inch-ci.org/github/plankp/Calcula)
1
+ # Calcula [![Build Status](https://travis-ci.org/plankp/Calcula.svg?branch=master)](https://travis-ci.org/plankp/Calcula) [![Code Climate](https://codeclimate.com/github/plankp/Calcula/badges/gpa.svg)](https://codeclimate.com/github/plankp/Calcula) [![Inline docs](http://inch-ci.org/github/plankp/Calcula.svg?branch=master)](http://inch-ci.org/github/plankp/Calcula) [![Gem Version](https://badge.fury.io/rb/calcula.svg)](https://badge.fury.io/rb/calcula)
2
2
 
3
3
  When mathematics meets programming
4
4
 
@@ -22,17 +22,14 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- At the moment, all it does is converts source code into tokens and then a syntax tree.
26
- To do so, type in:
25
+ To compile Calcula code to ruby, type in:
27
26
 
28
27
  ```ruby
29
28
  require "calcula"
30
29
  src = <<-'EOS'
31
- # Write some calcula code here
30
+ # Write some Calcula code here
32
31
  EOS
33
- tokens = Calcula.lex(src)
34
- puts tokens.collect { |e| e.text }.to_s
35
- puts Calcula.parse(tokens).to_tree
32
+ puts Calcula::compile(src)
36
33
  ```
37
34
 
38
35
  ## Development
@@ -47,4 +44,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/plankp
47
44
 
48
45
  ## License
49
46
 
50
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
47
+ The gem is available as open source under the terms of the [MIT License](./LICENSE.txt).
data/lib/Expr.rb CHANGED
@@ -1,20 +1,40 @@
1
+ # @author Paul T.
1
2
  module Calcula
2
- class Expr
3
-
4
- def to_s()
5
- ""
6
- end
7
3
 
8
- def to_tree()
9
- "()"
10
- end
4
+ # All valid tree expression must be childrens of this class and should be
5
+ # placed under the module `Calcula::Exprs`
6
+ #
7
+ # @see Calcula::Exprs
8
+ # @abstract
9
+ # @author Paul T.
10
+ class Expr
11
11
 
12
- # binding: Hash[string, Any]
13
- def exec(binding)
14
- nil
12
+ # Converts the expression to a string. If the form is `:src`, then the
13
+ # resulting string should resemble as much as its source code as possible.
14
+ # If the form is `:tree`, the result string should resemble in a Lisp like
15
+ # form. If the form is `:ruby`, the result should be Ruby code that does the
16
+ # same thing. Otherwise, `nil` should be returned.
17
+ #
18
+ # @param form [Optional, Symbol] The type of format being converted into
19
+ # @return [String, nil] A string that resembles the specify form
20
+ def to_s(form: :src)
21
+ case form
22
+ when :src then
23
+ ""
24
+ when :tree then
25
+ "()"
26
+ when :ruby then
27
+ ""
28
+ else
29
+ nil
30
+ end
15
31
  end
16
32
 
17
- def children()
33
+ # Returns the child nodes as a list. Child nodes must be transversible
34
+ # (hence also expressions).
35
+ #
36
+ # @return [Array<Calcula::Expr>] A list of transversible child nodes
37
+ def children
18
38
  []
19
39
  end
20
40
  end
@@ -0,0 +1,39 @@
1
+ require_relative "../Expr"
2
+
3
+ # Expression for assigning value to variables
4
+ #
5
+ # @author Paul T.
6
+ class Calcula::Exprs::AssignExpr < Calcula::Expr
7
+
8
+ # @param ident [Calcula::Exprs::IdentExpr]
9
+ # @param value [Calcula::Expr]
10
+ def initialize(ident, value)
11
+ @ident = ident
12
+ @value = value
13
+ end
14
+
15
+ # @see Calcula::Expr#to_s
16
+ # @param (see Calcula::Expr#to_s)
17
+ # @return (see Calcula::Expr#to_s)
18
+ def to_s(form: :src)
19
+ identTxt = @ident.to_s(form: form)
20
+ valueTxt = @value.to_s(form: form)
21
+ case form
22
+ when :src then
23
+ "let #{identTxt}=#{valueTxt}"
24
+ when :tree then
25
+ "(let #{identTxt} #{valueTxt})"
26
+ when :ruby then
27
+ "#{identTxt} = #{valueTxt}"
28
+ else
29
+ nil
30
+ end
31
+ end
32
+
33
+ # @see Calcula::Expr#children
34
+ # @param (see Calcula::Expr#children)
35
+ # @return (see Calcula::Expr#children)
36
+ def children
37
+ [@ident, @value]
38
+ end
39
+ end
@@ -0,0 +1,53 @@
1
+ require_relative "../Expr"
2
+
3
+ # Expression for binary operators. An expression 10(2) is also a binary operator.
4
+ # Its operator will be `:PAREN_O`
5
+ #
6
+ # @author Paul T.
7
+ class Calcula::Exprs::BinopExpr < Calcula::Expr
8
+
9
+ # @param op [Calcula::Token] Should have type prefixed with `OP_`
10
+ # @param left [Calcula::Expr]
11
+ # @param right [Calcula::Expr]
12
+ def initialize(op, left, right)
13
+ @op = op
14
+ @left = left
15
+ @right = right
16
+ end
17
+
18
+ # @see Calcula::Expr#to_s
19
+ # @param (see Calcula::Expr#to_s)
20
+ # @return (see Calcula::Expr#to_s)
21
+ def to_s(form: :src)
22
+ leftTxt = @left.to_s(form: form)
23
+ rightTxt = @right.to_s(form: form)
24
+ case form
25
+ when :src, :ruby then
26
+ case @op.id
27
+ when :PAREN_O then
28
+ "#{leftTxt}#{"." if form == :ruby}(#{rightTxt})"
29
+ when :OP_EQ then
30
+ "#{leftTxt}#{form == :ruby ? "==" : "="}#{rightTxt}"
31
+ when :AND then
32
+ "#{leftTxt}#{form == :ruby ? "&&" : " and "}#{rightTxt}"
33
+ when :OR then
34
+ "#{leftTxt}#{form == :ruby ? "||" : " or "}#{rightTxt}"
35
+ when :COMPOSE then
36
+ "->(*x){#{leftTxt}.(#{rightTxt}.(*x))}"
37
+ else
38
+ "#{leftTxt}#{@op.text}#{rightTxt}"
39
+ end
40
+ when :tree then
41
+ "(#{@op.text} #{leftTxt} #{rightTxt})"
42
+ else
43
+ nil
44
+ end
45
+ end
46
+
47
+ # @see Calcula::Expr#children
48
+ # @param (see Calcula::Expr#children)
49
+ # @return (see Calcula::Expr#children)
50
+ def children
51
+ [@left, @right]
52
+ end
53
+ end
@@ -0,0 +1,48 @@
1
+ require_relative "../Expr"
2
+
3
+ # Expression for bracket operators. Floor operators also count as bracket
4
+ # operators.
5
+ #
6
+ # @author Paul T.
7
+ class Calcula::Exprs::BracedExpr < Calcula::Expr
8
+
9
+ # @param startTok [Calcula::Token] The starting token of this expression
10
+ # @param endTok [Calcula::Token] The ending token of this expression
11
+ # @param inner [Calcula::Expr]
12
+ def initialize(startTok, endTok, inner)
13
+ @startTok = startTok
14
+ @endTok = endTok
15
+ @inner = inner
16
+ end
17
+
18
+ # @see Calcula::Expr#to_s
19
+ # @param (see Calcula::Expr#to_s)
20
+ # @return (see Calcula::Expr#to_s)
21
+ def to_s(form: :src)
22
+ innerTxt = @inner.to_s(form: form)
23
+ case form
24
+ when :src then
25
+ "#{@startTok.text}#{innerTxt}#{@endTok.text}"
26
+ when :tree then
27
+ "#{@startTok.text} #{innerTxt} #{@endTok.text}"
28
+ when :ruby then
29
+ case @startTok.id
30
+ when :PAREN_O then
31
+ "(#{innerTxt})"
32
+ when :SQUARE_O then
33
+ "(#{innerTxt}).floor.to_r"
34
+ else
35
+ raise "Unknown delimiter #{@startTok.id}"
36
+ end
37
+ else
38
+ nil
39
+ end
40
+ end
41
+
42
+ # @see Calcula::Expr#children
43
+ # @param (see Calcula::Expr#children)
44
+ # @return (see Calcula::Expr#children)
45
+ def children
46
+ [@inner]
47
+ end
48
+ end
@@ -1,39 +1,39 @@
1
1
  require_relative "../Expr"
2
2
 
3
- module Calcula::Exprs
4
- class FuncExpr < Calcula::Expr
3
+ # Expression for functions and lambda expression
4
+ #
5
+ # @author Paul T.
6
+ class Calcula::Exprs::FuncExpr < Calcula::Expr
5
7
 
6
- # name: IdentExpr | Nil (for lambdas), params: ParamsExpr, action: Expr
7
- def initialize(name, params, action)
8
- @name = name
9
- @params = params
10
- @action = action
11
- end
12
-
13
- def to_s()
14
- return "\\#{@params.to_s}(#{@action.to_s})" if @name == nil
15
- return "#{@name.to_s}(#{@params.to_s})=#{@action.to_s}"
16
- end
17
-
18
- def to_tree()
19
- return "(lambda #{@params.to_tree} #{@action.to_tree})" if @name == nil
20
- return "(func #{@name.to_tree} #{@params.to_tree} #{@action.to_tree})"
21
- end
22
-
23
- def exec(binding)
24
- if @name == nil then
25
- # We return it (its a lambda function afterall...)
26
- else
27
- # We do not invoke this function. We just add it to the `binding`
28
- end
29
- end
8
+ # @param params [Calcula::Exprs::ParamsExpr] Parameters to the function
9
+ # @param action [Calcula::Expr] The body of the function
10
+ def initialize(params, action)
11
+ @params = params
12
+ @action = action
13
+ end
30
14
 
31
- def children()
32
- [@name, @params, @action]
15
+ # @see Calcula::Expr#to_s
16
+ # @param (see Calcula::Expr#to_s)
17
+ # @return (see Calcula::Expr#to_s)
18
+ def to_s(form: :src)
19
+ paramsTxt = @params.to_s(form: form)
20
+ actionTxt = @action.to_s(form: form)
21
+ case form
22
+ when :src then
23
+ "\\#{paramsTxt}(#{actionTxt})"
24
+ when :tree then
25
+ "(lambda #{paramsTxt} #{actionTxt})"
26
+ when :ruby then
27
+ "->#{paramsTxt}{#{actionTxt}}"
28
+ else
29
+ nil
33
30
  end
31
+ end
34
32
 
35
- def self.mkLambda(params, action)
36
- FuncExpr.new(nil, params, action)
37
- end
33
+ # @see Calcula::Expr#children
34
+ # @param (see Calcula::Expr#children)
35
+ # @return (see Calcula::Expr#children)
36
+ def children
37
+ [@params, @action]
38
38
  end
39
39
  end
@@ -1,27 +1,35 @@
1
1
  require_relative "../Expr"
2
2
 
3
- module Calcula::Exprs
4
- class IdentExpr < Calcula::Expr
3
+ # Expression for identifiers
4
+ #
5
+ # @author Paul T.
6
+ class Calcula::Exprs::IdentExpr < Calcula::Expr
5
7
 
6
- # name: Token
7
- def initialize(name)
8
- @name = name
9
- end
8
+ # @param name [Calcula::Token] This token should have the type ID
9
+ def initialize(name)
10
+ @name = name
11
+ end
10
12
 
11
- def to_s()
13
+ # @see Calcula::Expr#to_s
14
+ # @param (see Calcula::Expr#to_s)
15
+ # @return (see Calcula::Expr#to_s)
16
+ def to_s(form: :src)
17
+ case form
18
+ when :src then
12
19
  @name.text
13
- end
14
-
15
- def to_tree()
20
+ when :tree then
16
21
  "(ident #{@name.text})"
22
+ when :ruby then
23
+ @name.text.tr("'", "_")
24
+ else
25
+ nil
17
26
  end
27
+ end
18
28
 
19
- def exec(binding)
20
- binding[@name.text]
21
- end
22
-
23
- def children()
24
- []
25
- end
29
+ # @see Calcula::Expr#children
30
+ # @param (see Calcula::Expr#children)
31
+ # @return (see Calcula::Expr#children)
32
+ def children
33
+ []
26
34
  end
27
35
  end
data/lib/Exprs/NumExpr.rb CHANGED
@@ -1,27 +1,35 @@
1
1
  require_relative "../Expr"
2
2
 
3
- module Calcula::Exprs
4
- class NumExpr < Calcula::Expr
3
+ # Expression for representing real numbers
4
+ #
5
+ # @author Paul T.
6
+ class Calcula::Exprs::NumExpr < Calcula::Expr
5
7
 
6
- # num: Token
7
- def initialize(num)
8
- @num = num
9
- end
8
+ # @param num [Calcula::Token] The token should have the type of NUM
9
+ def initialize(num)
10
+ @num = num
11
+ end
10
12
 
11
- def to_s()
13
+ # @see Calcula::Expr#to_s
14
+ # @param (see Calcula::Expr#to_s)
15
+ # @return (see Calcula::Expr#to_s)
16
+ def to_s(form: :src)
17
+ case form
18
+ when :src then
12
19
  @num.text
13
- end
14
-
15
- def to_tree()
20
+ when :tree then
16
21
  "(num #{@num.text})"
22
+ when :ruby then
23
+ "#{@num.text}r"
24
+ else
25
+ nil
17
26
  end
27
+ end
18
28
 
19
- def exec(binding)
20
- return @num.text.to_f
21
- end
22
-
23
- def children()
24
- []
25
- end
29
+ # @see Calcula::Expr#children
30
+ # @param (see Calcula::Expr#children)
31
+ # @return (see Calcula::Expr#children)
32
+ def children
33
+ []
26
34
  end
27
35
  end