iode 0.0.3 → 0.0.4

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: 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: []