iode 0.0.3 → 0.0.4

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: 10252bb4757e9c4d3cdbb7177e142418f392b212
4
+ data.tar.gz: 75522eef2c8d52839309381993811fc5e365053d
5
+ SHA512:
6
+ metadata.gz: a3f403e1b8149bc875d8e32f3d20745143bfbc68d55568038c4077ac1745f528f2bfc6fe33e63d659fac713c665d04db0539203ede36a0e156549d4597dc9687
7
+ data.tar.gz: efe9309b7b749a962c1456f282f1c634b611e854f82111c126d9ecb067e706ed616d4d9f87639925bd9f931cf4f4fee0b246ae3aea26de5672498a957a21add5
data/README.md CHANGED
@@ -63,31 +63,106 @@ Of course, functions can be defined recursively too.
63
63
  ``` lisp
64
64
  ;; Recursive function example.
65
65
  (def loop
66
- (lambda (n)
67
- (if (= n 0)
68
- (quote done)
69
- (progn
70
- (puts n)
71
- (loop (- n 1))))))
66
+ (lambda (n)
67
+ (if (= n 0)
68
+ (quote done)
69
+ (progn
70
+ (puts n)
71
+ (loop (- n 1))))))
72
72
 
73
73
  (loop 20)
74
74
  ```
75
75
 
76
- The above code will print 20 through 1 to the screen and finally return the
77
- Symbol `:done` to Ruby (quoted Iode Symbols are also Ruby Symbols). Note that
78
- I haven't yet done tail call elimination.
79
-
80
76
  Similarly, closures can be returned from functions.
81
77
 
82
78
  ``` lisp
83
- ;; Provides partial application of a function
84
- (def curry
85
- (lambda (fn a)
86
- (lambda (b) (fn a b))))
79
+ (def dec
80
+ (lambda (n)
81
+ (- n 1)))
82
+
83
+ (def expt
84
+ (lambda (n x)
85
+ (if (= x 0)
86
+ 1
87
+ (* n (expt n (dec x))))))
88
+
89
+ (def make-expt-fn
90
+ (lambda (x)
91
+ (lambda (n) (expt n x))))
92
+
93
+ (def square
94
+ (make-expt-fn 2))
95
+
96
+ (def cube
97
+ (make-expt-fn 3))
98
+
99
+ (puts (square 4))
100
+ (puts (cube 4))
101
+ ```
102
+
103
+ Or something that updates some internal state.
104
+
105
+ ``` lisp
106
+ (def make-counter
107
+ (lambda (n)
108
+ (lambda () (set! n (inc n)))))
109
+
110
+ (def counter
111
+ (make-counter 0))
112
+
113
+ (puts (counter)) ; 1
114
+ (puts (counter)) ; 2
115
+ (puts (counter)) ; 3
116
+ (puts (counter)) ; 4
117
+ ```
118
+
119
+ #### Macros
120
+
121
+ Yes, iode has macros. In fact, very powerful macros. You can think of macros in
122
+ the same way you think about lambdas. They are 100% first-class to iode and
123
+ have values that can be assigned to variables, passed into functions etc. Like
124
+ lambdas, they also provide a lexical closure over their environment. The
125
+ difference between a macro and a lambda is that a macro receives unevaluated
126
+ *code* as input and produces *code* as output.
127
+
128
+ The syntax for returning code is a little cumbersome at this point, since I
129
+ haven't yet added quasiquoting to provide that magical "templating" that lisps
130
+ offer. Lots of `list` and `quote` for now. Quasiquoting is coming, however.
131
+
132
+ Since iode doesn't yet have a `let` form, let's make our own with a macro.
133
+
134
+ ``` lisp
135
+ (def cadr
136
+ (lambda (v) (car (cdr v))))
137
+
138
+ (def let
139
+ (macro (bindings body)
140
+ (list
141
+ (quote apply)
142
+ (list (quote lambda)
143
+ (map car bindings)
144
+ body)
145
+ (map cadr bindings))))
146
+
147
+ (let ((x 7)
148
+ (y 8))
149
+ (puts (* x y)))
150
+ ```
87
151
 
88
- ((curry + 2) 3) ; 5
152
+ Note that the body of the macro in this version must be a single s-expression,
153
+ since variadic arguments are not yet implemented in the language. You may use
154
+ a `progn`, however.
155
+
156
+ ``` lisp
157
+ (let ((x 7)
158
+ (y 8))
159
+ (progn
160
+ (puts (str "x = " x))
161
+ (puts (str "y = " y))
162
+ (puts (str "x * y = " (* x y)))))
89
163
  ```
90
164
 
165
+ Macros as values are a powerful feature of iode.
91
166
 
92
167
  ### In Ruby Code
93
168
 
@@ -18,8 +18,11 @@ require "iode/version"
18
18
  require "iode/core/comparisons"
19
19
  require "iode/core/lists"
20
20
  require "iode/core/math"
21
+ require "iode/core/strings"
21
22
  require "iode/core/output"
22
23
  require "iode/scope"
24
+ require "iode/lambda"
25
+ require "iode/macro"
23
26
  require "iode/interpreter"
24
27
  require "iode/reader"
25
28
 
@@ -32,6 +32,10 @@ module Iode
32
32
  _, *v = list
33
33
  v
34
34
  end
35
+
36
+ def map(fn, list)
37
+ list.map(&fn)
38
+ end
35
39
  end
36
40
  end
37
41
  end
@@ -15,6 +15,7 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require "iode/core"
18
+ require "pp"
18
19
 
19
20
  module Iode
20
21
  module Core
@@ -26,6 +27,10 @@ module Iode
26
27
  def p(*args, &block)
27
28
  Kernel.p(*args, &block)
28
29
  end
30
+
31
+ def pp(*args, &block)
32
+ Kernel.pp(*args, &block)
33
+ end
29
34
  end
30
35
  end
31
36
  end
@@ -0,0 +1,31 @@
1
+ # iode: core/lists.rb
2
+ #
3
+ # Copyright 2014 Chris Corbyn <chris@w3style.co.uk>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module Iode
18
+ module Core
19
+ module Strings
20
+ def str(*args)
21
+ args.map(&:to_s).join
22
+ end
23
+
24
+ def format(s, *args)
25
+ s % args
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ Iode::Core.register Iode::Core::Strings
@@ -63,7 +63,7 @@ module Iode
63
63
  sexps.inject(nil){|_,s| eval(s)}
64
64
  end
65
65
 
66
- # Create a new lambda for Iode.
66
+ # Create a new lambda.
67
67
  #
68
68
  # These lambdas act as closures in their environment.
69
69
  #
@@ -73,10 +73,31 @@ module Iode
73
73
  # @param [Object...] *sexps
74
74
  # variadic list of S-Expressions for the body
75
75
  #
76
- # @return [Proc]
76
+ # @return [Lambda]
77
77
  # a callable lambda
78
78
  def lambda(argnames, *sexps)
79
- Proc.new do |*args|
79
+ Lambda.new do |*args|
80
+ Interpreter.new(
81
+ @env.push_scope(Hash[argnames.zip(args)])
82
+ ).progn(*sexps)
83
+ end
84
+ end
85
+
86
+ # Create a new macro.
87
+ #
88
+ # Macros are acually just a special case of lambda and also close their
89
+ # environment and can be passed as arguments.
90
+ #
91
+ # @param [Array] argnames
92
+ # a list of argument names as macro inputs
93
+ #
94
+ # @param [Object...] *sexps
95
+ # variadic list of S-Expressions for the body
96
+ #
97
+ # @return [Macro]
98
+ # a callable macro
99
+ def macro(argnames, *sexps)
100
+ Macro.new do |*args|
80
101
  Interpreter.new(
81
102
  @env.push_scope(Hash[argnames.zip(args)])
82
103
  ).progn(*sexps)
@@ -116,6 +137,8 @@ module Iode
116
137
  nil
117
138
  when :quote
118
139
  car(cdr(sexp))
140
+ when :quasiquote
141
+ car(cdr(sexp))
119
142
  when :if
120
143
  if eval(car(cdr(sexp)))
121
144
  eval(car(cdr(cdr(sexp))))
@@ -130,8 +153,18 @@ module Iode
130
153
  @env.define(car(cdr(sexp)), eval(car(cdr(cdr(sexp)))))
131
154
  when :lambda
132
155
  lambda(car(cdr(sexp)), *cdr(cdr(sexp)))
156
+ when :macro
157
+ macro(car(cdr(sexp)), *cdr(cdr(sexp)))
158
+ when :apply
159
+ eval([car(cdr(sexp)), *car(cdr(cdr(sexp)))])
133
160
  else
134
- apply(eval(car(sexp)), cdr(sexp).map(&method(:eval)))
161
+ callee = eval(car(sexp))
162
+ case callee
163
+ when Macro
164
+ eval(apply(callee, cdr(sexp)))
165
+ else
166
+ apply(callee, cdr(sexp).map(&method(:eval)))
167
+ end
135
168
  end
136
169
  when Symbol
137
170
  @env[sexp]
@@ -0,0 +1,21 @@
1
+ # iode: lambda.rb
2
+ #
3
+ # Copyright 2014 Chris Corbyn <chris@w3style.co.uk>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module Iode
18
+ # Class that represents a lambda function in iode.
19
+ class Lambda < Proc
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # iode: macro.rb
2
+ #
3
+ # Copyright 2014 Chris Corbyn <chris@w3style.co.uk>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module Iode
18
+ # Class that represents a macro function in iode.
19
+ class Macro < Lambda
20
+ end
21
+ end
@@ -28,6 +28,7 @@ module Iode
28
28
  # syntax
29
29
  rule("(")
30
30
  rule(")")
31
+ rule("'")
31
32
 
32
33
  # fractions as literals
33
34
  rule(:rational => /[0-9]+\/[0-9]+/).as{|n| Rational(n)}
@@ -43,7 +44,7 @@ module Iode
43
44
  end
44
45
 
45
46
  # variables/symbols
46
- rule(symbol: /[^\(\)\s;]+/).as do |v|
47
+ rule(symbol: /[^\(\)\s;'"`:]+/).as do |v|
47
48
  case v
48
49
  when "nil"
49
50
  nil
@@ -75,6 +76,7 @@ module Iode
75
76
  # s-exprs
76
77
  rule(:sexp) do |r|
77
78
  r[:atom]
79
+ r["'", :sexp].as {|_, sexp| [:quote, sexp]}
78
80
  r["(", :sexp_list, ")"].as {|_, list, _| list}
79
81
  end
80
82
 
@@ -15,5 +15,5 @@
15
15
  # limitations under the License.
16
16
 
17
17
  module Iode
18
- VERSION = "0.0.3"
18
+ VERSION = "0.0.4"
19
19
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
5
- prerelease:
4
+ version: 0.0.4
6
5
  platform: ruby
7
6
  authors:
8
7
  - Chris Corbyn
@@ -14,55 +13,50 @@ dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: whittle
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: 0.0.8
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: 0.0.8
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: bundler
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
33
  version: '1.5'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
40
  version: '1.5'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rake
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - ">="
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
- description: ! " Iode is a work in progress real language on LLVM.\n This Ruby Gem
63
- exists solely so the author can experiment with new language\n features before
64
- committing those ideas to the real language. It is not\n intended for general use,
65
- nor is it intended to be fast or concise.\n"
55
+ description: |2
56
+ Iode is a work in progress real language on LLVM.
57
+ This Ruby Gem exists solely so the author can experiment with new language
58
+ features before committing those ideas to the real language. It is not
59
+ intended for general use, nor is it intended to be fast or concise.
66
60
  email:
67
61
  - chris@w3style.co.uk
68
62
  executables:
@@ -70,7 +64,7 @@ executables:
70
64
  extensions: []
71
65
  extra_rdoc_files: []
72
66
  files:
73
- - .gitignore
67
+ - ".gitignore"
74
68
  - Gemfile
75
69
  - LICENSE.txt
76
70
  - README.md
@@ -83,33 +77,35 @@ files:
83
77
  - lib/iode/core/lists.rb
84
78
  - lib/iode/core/math.rb
85
79
  - lib/iode/core/output.rb
80
+ - lib/iode/core/strings.rb
86
81
  - lib/iode/interpreter.rb
82
+ - lib/iode/lambda.rb
83
+ - lib/iode/macro.rb
87
84
  - lib/iode/reader.rb
88
85
  - lib/iode/scope.rb
89
86
  - lib/iode/version.rb
90
87
  homepage: https://github.com/d11wtq/iode-rb
91
88
  licenses:
92
89
  - MIT
90
+ metadata: {}
93
91
  post_install_message:
94
92
  rdoc_options: []
95
93
  require_paths:
96
94
  - lib
97
95
  required_ruby_version: !ruby/object:Gem::Requirement
98
- none: false
99
96
  requirements:
100
- - - ! '>='
97
+ - - ">="
101
98
  - !ruby/object:Gem::Version
102
99
  version: '0'
103
100
  required_rubygems_version: !ruby/object:Gem::Requirement
104
- none: false
105
101
  requirements:
106
- - - ! '>='
102
+ - - ">="
107
103
  - !ruby/object:Gem::Version
108
104
  version: '0'
109
105
  requirements: []
110
106
  rubyforge_project:
111
- rubygems_version: 1.8.23
107
+ rubygems_version: 2.2.0
112
108
  signing_key:
113
- specification_version: 3
109
+ specification_version: 4
114
110
  summary: An experimental lisp-family language hosted on Ruby
115
111
  test_files: []