lasp 0.8.0 → 0.9.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.
@@ -8,6 +8,7 @@
8
8
  (list 'def name
9
9
  (list 'macro params body))))
10
10
 
11
+
11
12
  ; Shorthand for defining functions
12
13
  ;
13
14
  ; (defn f (x) (+ x 1))
@@ -18,6 +19,36 @@
18
19
  (list 'def name
19
20
  (list 'fn params (cons 'do body))))
20
21
 
22
+
23
+ ; Creates local bindings.
24
+ ;
25
+ ; It does this by (ab)using closures. It rewrites the form as a recursively
26
+ ; nested tree of functions, declaring parameters and instantly executing the
27
+ ; function passing in corresponding arguments. This should be considered an
28
+ ; implementation detail, let can (and should) be used without knowledge or
29
+ ; regard to that it creates closures behind the scenes.
30
+
31
+ ; Example:
32
+ ; (let (one 1
33
+ ; two (+ one 1)) ; Previous bindings are available
34
+ ; (+ one two))
35
+ ; ; => 3
36
+ ;
37
+ ; expands to:
38
+ ; ((fn (one) ((fn (two) (do (+ one two))) (+ one 1))) 1)
39
+ (defn let*
40
+ (bindings body)
41
+ (if (empty? bindings)
42
+ (cons 'do body)
43
+ (list
44
+ (list 'fn (list (first bindings)) (let* (drop 2 bindings) body))
45
+ (second bindings))))
46
+
47
+ (defm let
48
+ (bindings & body)
49
+ (let* bindings body))
50
+
51
+
21
52
  ; See unevaluated form the macro expands to for debugging macros
22
53
  ;
23
54
  ; This simply uses the fact that `apply` already has this effect
@@ -1,3 +1,3 @@
1
1
  module Lasp
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lasp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jimmy Börjesson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-04 00:00:00.000000000 Z
11
+ date: 2016-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -48,6 +48,7 @@ extra_rdoc_files: []
48
48
  files:
49
49
  - ".gitignore"
50
50
  - CHANGELOG.md
51
+ - DOCUMENTATION.md
51
52
  - EXAMPLES.md
52
53
  - Gemfile
53
54
  - LICENSE.txt
@@ -59,14 +60,13 @@ files:
59
60
  - lib/lasp/corelib.rb
60
61
  - lib/lasp/env.rb
61
62
  - lib/lasp/errors.rb
62
- - lib/lasp/eval.rb
63
+ - lib/lasp/ext.rb
63
64
  - lib/lasp/fn.rb
65
+ - lib/lasp/interpreter.rb
64
66
  - lib/lasp/macro.rb
65
- - lib/lasp/parameters.rb
66
67
  - lib/lasp/params.rb
67
68
  - lib/lasp/parser.rb
68
69
  - lib/lasp/repl.rb
69
- - lib/lasp/representation.rb
70
70
  - lib/lasp/stdlib.lasp
71
71
  - lib/lasp/stdmacros.lasp
72
72
  - lib/lasp/version.rb
@@ -1,66 +0,0 @@
1
- require "lasp/env"
2
- require "lasp/fn"
3
- require "lasp/macro"
4
-
5
- module Lasp
6
- module_function
7
-
8
- def eval(form, env)
9
- case form
10
- when Symbol then env.fetch(form)
11
- when Array then eval_form(form, env)
12
- else form
13
- end
14
- end
15
-
16
- def eval_form(form, env)
17
- head, *tail = *form
18
-
19
- case head
20
- when :def then def_special_form(tail, env)
21
- when :fn then fn_special_form(tail, env)
22
- when :do then do_special_form(tail, env)
23
- when :if then if_special_form(tail, env)
24
- when :quote then quote_special_form(tail, env)
25
- when :macro then macro_special_form(tail, env)
26
- else call_function(head, tail, env)
27
- end
28
- end
29
-
30
- def call_function(symbol, args, env)
31
- fn = Lasp::eval(symbol, env)
32
-
33
- case fn
34
- when Macro then Lasp::eval(fn.(*args), env)
35
- else fn.(*args.map { |form| Lasp::eval(form, env) })
36
- end
37
- end
38
-
39
- def def_special_form(form, env)
40
- key, value = form
41
- env[key] = Lasp::eval(value, env)
42
- end
43
-
44
- def fn_special_form(form, env)
45
- params, func = form
46
- Fn.new(params, func, env)
47
- end
48
-
49
- def do_special_form(form, env)
50
- form.map { |form| Lasp::eval(form, env) }.last
51
- end
52
-
53
- def if_special_form(form, env)
54
- conditional, true_form, false_form = form
55
- Lasp::eval(conditional, env) ? Lasp::eval(true_form, env) : Lasp::eval(false_form, env)
56
- end
57
-
58
- def quote_special_form(form, _)
59
- form.first
60
- end
61
-
62
- def macro_special_form(form, env)
63
- params, func = form
64
- Macro.new(params, func, env)
65
- end
66
- end
@@ -1,93 +0,0 @@
1
- module Lasp
2
- module Parameters
3
- def self.new(params)
4
- if params.include?(:&)
5
- RestParameters.new(params)
6
- else
7
- FixedParameters.new(params)
8
- end
9
- end
10
-
11
- class FixedParameters
12
- attr_reader :parameter_list
13
-
14
- def initialize(parameter_list)
15
- @parameter_list = parameter_list
16
- valid_signature!
17
- end
18
-
19
- def to_h(args)
20
- enforce_arity!(args)
21
- Hash[parameter_list.zip(args)]
22
- end
23
-
24
- def to_s
25
- "(" + parameter_list.join(" ") + ")"
26
- end
27
-
28
- private
29
-
30
- def enforce_arity!(args)
31
- if args.count != arity
32
- fail ArgumentError, "wrong number of arguments (#{args.count} for #{arity})"
33
- end
34
- end
35
-
36
- def valid_signature!
37
- if duplicate_parameter?
38
- fail SyntaxError, "Parameter names have to be unique. a is used more than once"
39
- end
40
- end
41
-
42
- def duplicate_parameter?
43
- parameter_list.uniq.length != parameter_list.length
44
- end
45
-
46
- def arity
47
- parameter_list.count
48
- end
49
- end
50
-
51
- class RestParameters < FixedParameters
52
- def to_h(args)
53
- enforce_arity!(args)
54
-
55
- ordered = parameter_list[0, minimum_arguments]
56
- rest = parameter_list.last
57
-
58
- env = ordered.zip(args.take(ordered.length))
59
- env << [ rest, args.drop(ordered.length) ]
60
-
61
- Hash[env]
62
- end
63
-
64
- private
65
-
66
- def valid_signature!
67
- if multiple_rest_arguments? || ampersand_not_second_to_last?
68
- fail SyntaxError, "Rest-arguments may only be used once, at the end, with a single binding."
69
- end
70
- super
71
- end
72
-
73
- def multiple_rest_arguments?
74
- parameter_list.select { |b| b == :& }.length > 1
75
- end
76
-
77
- def ampersand_not_second_to_last?
78
- parameter_list.find_index(:&) != minimum_arguments
79
- end
80
-
81
- def minimum_arguments
82
- parameter_list.count - 2
83
- end
84
-
85
- def enforce_arity!(args)
86
- if args.count < minimum_arguments
87
- fail ArgumentError, "wrong number of arguments (#{args.count} for #{minimum_arguments}+)"
88
- end
89
- end
90
- end
91
-
92
- end
93
- end
@@ -1,17 +0,0 @@
1
- class Array
2
- def inspect
3
- "(#{ map(&:inspect).join(" ") })"
4
- end
5
- end
6
-
7
- class Symbol
8
- def inspect
9
- to_s
10
- end
11
- end
12
-
13
- class Hash
14
- def inspect
15
- "{#{ map { |pair| pair.map(&:inspect).join(" ")}.join(", ") }}"
16
- end
17
- end