lasp 0.1.1 → 0.2.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 +4 -4
- data/CHANGELOG.md +11 -0
- data/EXAMPLES.md +143 -0
- data/README.md +57 -9
- data/Rakefile +5 -0
- data/bin/lasp +5 -0
- data/bin/lasp-repl +3 -3
- data/lib/lasp.rb +3 -1
- data/lib/lasp/corelib.rb +18 -14
- data/lib/lasp/stdlib.lasp +1 -1
- data/lib/lasp/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 68dbe78c047584740bc6f5347986c79f91509e9f
|
4
|
+
data.tar.gz: 59e1576d2daba17a0a3226d19582e01f5f645f64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86c24ac9ca3517ce90176832250197d27508dc2ab9fc4823c2e22195b0f9ae9f8f724f0d8e13837bbf17809553f4b06de91c84b3f3a37d667782d801da032931
|
7
|
+
data.tar.gz: 3d20db7ce8ffba5e3e6aba5fffbbfc064fb91f5058910987ee5b0bf26bc0e4373fdd7e064d92883cb1c882e0d99e9d022cd1de53ae00f484c1b88420e15875f9
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# Läsp changelog
|
2
2
|
|
3
|
+
## v0.2.0
|
4
|
+
|
5
|
+
Add support for hash-maps with the following added functions to the core library:
|
6
|
+
|
7
|
+
- `hash-map`
|
8
|
+
- `get`
|
9
|
+
- `assoc`
|
10
|
+
- `dissoc`
|
11
|
+
|
12
|
+
Also adds exit instructions to the REPL welcome message.
|
13
|
+
|
3
14
|
## v0.1.1
|
4
15
|
|
5
16
|
Fix broken `lasp` executable.
|
data/EXAMPLES.md
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# Examples
|
2
|
+
|
3
|
+
```lisp
|
4
|
+
; Notes:
|
5
|
+
;
|
6
|
+
; A complete list of the available functions can be found in the README.
|
7
|
+
;
|
8
|
+
; Since Läsp is very similar to Clojure, you can get pretty decent syntax
|
9
|
+
; highlighting by just setting your editor to treat .lasp files as .clj
|
10
|
+
;
|
11
|
+
; In this document output is shown with ;; and normal comments with ;.
|
12
|
+
|
13
|
+
; Number types
|
14
|
+
1
|
15
|
+
1.5
|
16
|
+
|
17
|
+
; Booleans and nil
|
18
|
+
true
|
19
|
+
false
|
20
|
+
nil
|
21
|
+
|
22
|
+
; Strings
|
23
|
+
"hello world!" ;; => "hello world!"
|
24
|
+
|
25
|
+
; Symbol-style strings (not its own type)
|
26
|
+
:hey ;; => "hey"
|
27
|
+
|
28
|
+
; Lists
|
29
|
+
(list 1 2 3) ;; => [1, 2, 3]
|
30
|
+
(list) ;; => []
|
31
|
+
|
32
|
+
; Basic function call
|
33
|
+
; inc is a function that increments its argument, and 1 is the single argument
|
34
|
+
(inc 1) ;; => 2
|
35
|
+
|
36
|
+
; Simple maths functions takes any number of arguments
|
37
|
+
(/ 20 2) ;; => 10
|
38
|
+
(+ 1 3 5) ;; => 9
|
39
|
+
(* 2 5 6 10) ;; => 600
|
40
|
+
|
41
|
+
; Equality operators also do
|
42
|
+
(= 1 5) ;; => false
|
43
|
+
(= 3 3 3) ;; => true
|
44
|
+
(> 3 2 1 0) ;; => true
|
45
|
+
|
46
|
+
; Boolean inversion
|
47
|
+
(not true) ;; => false
|
48
|
+
|
49
|
+
; List operations
|
50
|
+
|
51
|
+
(head (list 1 2 3)) ;; => 1
|
52
|
+
(first (list 1 2 3)) ;; => 1
|
53
|
+
|
54
|
+
(tail (list 1 2 3)) ;; => [2, 3]
|
55
|
+
(rest (list 1 2 3)) ;; => [2, 3]
|
56
|
+
|
57
|
+
(cons 0 (list 1 2 3)) ;; => [0, 1, 2, 3]
|
58
|
+
|
59
|
+
(nth 1 (list 1 2 3)) ;; => 2
|
60
|
+
(nth 3 (list 1 2 3)) ;; => nil
|
61
|
+
|
62
|
+
; get does the same as nth on lists (although implemented differently)
|
63
|
+
(get 1 (list 1 2 3)) ;; => 2
|
64
|
+
(get 3 (list 1 2 3)) ;; => nil
|
65
|
+
|
66
|
+
; assoc returns a new array with the specified index updated
|
67
|
+
(assoc (list 1 2 3) 0 "one") ;; => ["one", 2, 3]
|
68
|
+
|
69
|
+
(last (list 1 2 3)) ;; => 3
|
70
|
+
|
71
|
+
(take 2 (list 1 2 3)) ;; => [1, 2]
|
72
|
+
(drop 2 (list 1 2 3)) ;; => [3]
|
73
|
+
|
74
|
+
(max (list 1 3 2)) ;; => 3
|
75
|
+
|
76
|
+
(reverse (list 1 2 3)) ;; => [3, 2, 1]
|
77
|
+
|
78
|
+
; Ranges
|
79
|
+
(range 1 10) ;; => [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
80
|
+
|
81
|
+
; Hash-maps
|
82
|
+
(hash-map :one 1 :two 2) ;; => {"one"=>1, "two"=>2}
|
83
|
+
|
84
|
+
; get also works with hash-maps
|
85
|
+
(get :one (hash-map :one 1 :two 2)) ;; => 1
|
86
|
+
|
87
|
+
; assoc works with hash-maps too
|
88
|
+
(assoc (hash-map :one 1 :two 2) :three 3) ;; => {"one"=>1, "two"=>2, "three"=>3}
|
89
|
+
|
90
|
+
; dissoc removes values
|
91
|
+
(dissoc (hash-map :one 1 :two 2) :one) ;; => {"two"=>2}
|
92
|
+
|
93
|
+
; Apply a function to all items in a list
|
94
|
+
(map inc (list 1 2 3)) ;; => [2, 3, 4]
|
95
|
+
|
96
|
+
; Accumulate a value with a function
|
97
|
+
; The function (here +) will receive a memo (the running total)
|
98
|
+
; and each item in the list in order. The 0 is the starting value
|
99
|
+
(reduce + 0 (list 1 2 3)) ;; => 6
|
100
|
+
|
101
|
+
; This is how sum is implemented
|
102
|
+
(sum (list 1 2 3)) ;; => 6
|
103
|
+
|
104
|
+
; The starting value is important.
|
105
|
+
(reduce * 1 (list 1 2 3)) ;; => 6
|
106
|
+
|
107
|
+
; Filtering
|
108
|
+
(filter odd? (list 1 2 3)) ;; => [1, 3]
|
109
|
+
|
110
|
+
; Variables
|
111
|
+
(def x (list 1 2 3)) ;; => [1, 2, 3]
|
112
|
+
x ;; => [1, 2, 3]
|
113
|
+
|
114
|
+
; Outputting to the terminal
|
115
|
+
(println "hello world!")
|
116
|
+
;; hello world!
|
117
|
+
;; => nil
|
118
|
+
|
119
|
+
; If
|
120
|
+
(if (< 4.9 5)
|
121
|
+
(println "yep!")
|
122
|
+
(println "nope!"))
|
123
|
+
;; yep!
|
124
|
+
;; => nil
|
125
|
+
|
126
|
+
(if (< 5.1 5)
|
127
|
+
(println "yep!")
|
128
|
+
(println "nope!"))
|
129
|
+
;; nope!
|
130
|
+
;; => nil
|
131
|
+
|
132
|
+
; Functions
|
133
|
+
; A function has 2 forms, one with the parameters and one with the body.
|
134
|
+
; Here's a function that adds 10 to its argument
|
135
|
+
(fn (x) (+ 10 x))
|
136
|
+
|
137
|
+
; You can call it just like one of the named functions
|
138
|
+
((fn (x) (+ 10 x)) 50) ;; => 60
|
139
|
+
|
140
|
+
; You can give it a name yourself
|
141
|
+
(def add-ten (fn (x) (+ 10 x)))
|
142
|
+
(add-ten 50) ;; => 60
|
143
|
+
```
|
data/README.md
CHANGED
@@ -1,23 +1,50 @@
|
|
1
1
|
# Läsp
|
2
2
|
|
3
|
-
A very simple
|
4
|
-
|
3
|
+
A very simple programming language implemented in Ruby.
|
4
|
+
|
5
|
+
It is just a toy Lisp implementation and should not be used seriously by anyone.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
It needs Ruby to work, on Mac or most Linux OS:s it's already there and you can simply
|
10
|
+
|
11
|
+
```bash
|
12
|
+
gem install lasp
|
13
|
+
|
14
|
+
# If it doesn't work you might need to sudo
|
15
|
+
sudo gem install lasp
|
16
|
+
```
|
17
|
+
|
18
|
+
## Running
|
19
|
+
|
20
|
+
After installing there are two commands available to you:
|
21
|
+
|
22
|
+
```bash
|
23
|
+
# An interactive prompt that lets you play with the language
|
24
|
+
lasp-repl
|
25
|
+
|
26
|
+
# Run lasp-files
|
27
|
+
lasp path/to/program.lasp
|
28
|
+
```
|
5
29
|
|
6
30
|
## The language
|
7
31
|
|
8
32
|
### Examples
|
9
33
|
|
34
|
+
More advanced examples can be found in [EXAMPLES.md](EXAMPLES.md), you can also
|
35
|
+
look at the [standard library](lib/lasp/stdlib.lasp) which is implemented in
|
36
|
+
Läsp itself.
|
37
|
+
|
10
38
|
```lisp
|
11
|
-
(+ 1 2 3)
|
12
|
-
; => 6
|
39
|
+
(+ 1 2 3) ;; => 6
|
13
40
|
|
14
41
|
(def x 5)
|
15
|
-
x
|
16
|
-
|
42
|
+
x ;; => 6
|
43
|
+
|
44
|
+
(sum (list 5 10 15)) ;; => 30
|
17
45
|
|
18
46
|
(def inc (fn (x) (+ x 1)))
|
19
|
-
(inc 5)
|
20
|
-
; => 6
|
47
|
+
(inc 5) ;; => 6
|
21
48
|
```
|
22
49
|
|
23
50
|
### Data types
|
@@ -29,6 +56,7 @@ Supports these datatypes (implemented as their Ruby counterparts)
|
|
29
56
|
- boolean
|
30
57
|
- nil
|
31
58
|
- string
|
59
|
+
- list
|
32
60
|
|
33
61
|
### Comments
|
34
62
|
|
@@ -50,11 +78,17 @@ Implemented as Ruby lambdas.
|
|
50
78
|
- `<`
|
51
79
|
- `>`
|
52
80
|
- `=`
|
81
|
+
- `list`
|
53
82
|
- `head`
|
54
83
|
- `tail`
|
55
84
|
- `cons`
|
85
|
+
- `hash-map`
|
86
|
+
- `get`
|
87
|
+
- `assoc`
|
88
|
+
- `dissoc`
|
56
89
|
- `not`
|
57
90
|
- `println`
|
91
|
+
- `.`
|
58
92
|
|
59
93
|
### Special forms
|
60
94
|
|
@@ -94,4 +128,18 @@ Implemented in Läsp itself.
|
|
94
128
|
|
95
129
|
## Developing
|
96
130
|
|
97
|
-
Run the
|
131
|
+
### Run the specs
|
132
|
+
|
133
|
+
```bash
|
134
|
+
rspec
|
135
|
+
|
136
|
+
# or more verbose
|
137
|
+
rspec --format=documentation
|
138
|
+
```
|
139
|
+
|
140
|
+
### Dev REPL
|
141
|
+
|
142
|
+
```bash
|
143
|
+
# This is basically just a shorthand for `rake install && lasp-repl`
|
144
|
+
rake repl
|
145
|
+
```
|
data/Rakefile
CHANGED
data/bin/lasp
CHANGED
data/bin/lasp-repl
CHANGED
@@ -5,13 +5,13 @@ Lasp::load_stdlib!
|
|
5
5
|
|
6
6
|
trap("SIGINT") { puts "\n\nBye!"; exit! }
|
7
7
|
|
8
|
-
puts "((( Läsp v#{Lasp::VERSION} REPL )))\n\n"
|
8
|
+
puts "((( Läsp v#{Lasp::VERSION} REPL (ctrl+c to exit) )))\n\n"
|
9
9
|
loop do
|
10
10
|
begin
|
11
11
|
print "lasp> "
|
12
12
|
result = Lasp::execute(gets.chomp)
|
13
|
-
puts "
|
13
|
+
puts " => #{result.inspect}"
|
14
14
|
rescue
|
15
|
-
puts "
|
15
|
+
puts " *> #{$!}"
|
16
16
|
end
|
17
17
|
end
|
data/lib/lasp.rb
CHANGED
@@ -2,6 +2,8 @@ require "lasp/version"
|
|
2
2
|
require "lasp/eval"
|
3
3
|
|
4
4
|
module Lasp
|
5
|
+
STDLIB_PATH = File.expand_path("../lasp/stdlib.lasp", __FILE__)
|
6
|
+
|
5
7
|
module_function
|
6
8
|
|
7
9
|
def execute_file(path)
|
@@ -13,6 +15,6 @@ module Lasp
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def load_stdlib!
|
16
|
-
Lasp::execute_file(
|
18
|
+
Lasp::execute_file(STDLIB_PATH)
|
17
19
|
end
|
18
20
|
end
|
data/lib/lasp/corelib.rb
CHANGED
@@ -1,18 +1,22 @@
|
|
1
1
|
module Lasp
|
2
2
|
CORELIB = {
|
3
|
-
:+
|
4
|
-
:-
|
5
|
-
:*
|
6
|
-
:/
|
7
|
-
:<
|
8
|
-
:>
|
9
|
-
:"="
|
10
|
-
:list
|
11
|
-
:head
|
12
|
-
:tail
|
13
|
-
:cons
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
3
|
+
:+ => -> (_, *args) { args.reduce(:+) },
|
4
|
+
:- => -> (_, *args) { args.reduce(:-) },
|
5
|
+
:* => -> (_, *args) { args.reduce(:*) },
|
6
|
+
:/ => -> (_, *args) { args.reduce(:/) },
|
7
|
+
:< => -> (_, *args) { args.sort == args },
|
8
|
+
:> => -> (_, *args) { args.sort.reverse == args },
|
9
|
+
:"=" => -> (_, *args) { args.uniq.count == 1 },
|
10
|
+
:list => -> (_, *args) { args },
|
11
|
+
:head => -> (_, list) { list.first },
|
12
|
+
:tail => -> (_, list) { list.drop(1) },
|
13
|
+
:cons => -> (_, item, list) { [item] + list },
|
14
|
+
:"hash-map" => -> (_, *args) { Hash[*args] },
|
15
|
+
:get => -> (_, key, a) { a[key] },
|
16
|
+
:assoc => -> (_, a, key, val) { a.dup.tap { |a| a[key]=val } },
|
17
|
+
:dissoc => -> (_, a, key) { a.dup.tap { |a| a.delete(key) } },
|
18
|
+
:not => -> (_, arg) { !arg },
|
19
|
+
:println => -> (_, output) { puts output },
|
20
|
+
:"." => -> (_, obj, meth) { obj.send(meth) }
|
17
21
|
}
|
18
22
|
end
|
data/lib/lasp/stdlib.lasp
CHANGED
data/lib/lasp/version.rb
CHANGED
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.
|
4
|
+
version: 0.2.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: 2015-08-
|
11
|
+
date: 2015-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -49,6 +49,7 @@ extra_rdoc_files: []
|
|
49
49
|
files:
|
50
50
|
- ".gitignore"
|
51
51
|
- CHANGELOG.md
|
52
|
+
- EXAMPLES.md
|
52
53
|
- Gemfile
|
53
54
|
- LICENSE.txt
|
54
55
|
- README.md
|