nydp 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.zeiger.yml +28 -0
- data/lib/lisp/core-000.nydp +1 -1
- data/lib/lisp/core-015-documentation.nydp +6 -9
- data/lib/lisp/core-017-builtin-dox.nydp +33 -0
- data/lib/lisp/core-025-warnings.nydp +15 -0
- data/lib/lisp/core-030-syntax.nydp +38 -2
- data/lib/lisp/core-035-flow-control.nydp +2 -2
- data/lib/lisp/core-037-list-utils.nydp +7 -5
- data/lib/lisp/core-040-utils.nydp +15 -4
- data/lib/lisp/core-043-list-utils.nydp +1 -0
- data/lib/lisp/core-045-dox-utils.nydp +6 -0
- data/lib/lisp/core-050-test-runner.nydp +9 -9
- data/lib/lisp/core-070-prefix-list.nydp +2 -2
- data/lib/lisp/core-090-hook.nydp +24 -0
- data/lib/lisp/core-100-utils.nydp +38 -10
- data/lib/lisp/tests/ampersand-syntax-examples.nydp +26 -0
- data/lib/lisp/tests/boot-tests.nydp +1 -1
- data/lib/lisp/tests/collect-tests.nydp +4 -0
- data/lib/lisp/tests/destructuring-examples.nydp +18 -1
- data/lib/lisp/tests/fill-bucket-examples.nydp +46 -2
- data/lib/lisp/tests/floor-examples.nydp +58 -0
- data/lib/lisp/tests/k-examples.nydp +5 -0
- data/lib/lisp/tests/power-examples.nydp +16 -0
- data/lib/lisp/tests/string-tests.nydp +8 -0
- data/lib/lisp/tests/syntax-tests.nydp +6 -0
- data/lib/lisp/tests/zip-examples.nydp +16 -0
- data/lib/nydp.rb +6 -2
- data/lib/nydp/assignment.rb +1 -2
- data/lib/nydp/builtin/ensuring.rb +1 -2
- data/lib/nydp/builtin/greater_than.rb +2 -2
- data/lib/nydp/builtin/handle_error.rb +1 -2
- data/lib/nydp/builtin/less_than.rb +2 -2
- data/lib/nydp/builtin/math_ceiling.rb +7 -0
- data/lib/nydp/builtin/math_floor.rb +7 -0
- data/lib/nydp/builtin/math_power.rb +7 -0
- data/lib/nydp/builtin/math_round.rb +7 -0
- data/lib/nydp/builtin/parse.rb +2 -2
- data/lib/nydp/builtin/parse_in_string.rb +3 -3
- data/lib/nydp/builtin/pre_compile.rb +0 -1
- data/lib/nydp/compiler.rb +1 -1
- data/lib/nydp/cond.rb +3 -6
- data/lib/nydp/context_symbol.rb +40 -32
- data/lib/nydp/core.rb +8 -2
- data/lib/nydp/function_invocation.rb +3 -5
- data/lib/nydp/image_store.rb +21 -0
- data/lib/nydp/interpreted_function.rb +8 -12
- data/lib/nydp/lexical_context_builder.rb +19 -35
- data/lib/nydp/pair.rb +2 -1
- data/lib/nydp/parser.rb +4 -0
- data/lib/nydp/plugin.rb +15 -8
- data/lib/nydp/runner.rb +3 -3
- data/lib/nydp/symbol.rb +3 -1
- data/lib/nydp/symbol_lookup.rb +2 -2
- data/lib/nydp/truth.rb +2 -2
- data/lib/nydp/version.rb +1 -1
- data/lib/nydp/vm.rb +47 -27
- data/spec/date_spec.rb +2 -2
- data/spec/embedded_spec.rb +16 -16
- data/spec/error_spec.rb +1 -1
- data/spec/nydp_spec.rb +13 -4
- data/spec/parser_spec.rb +63 -16
- data/spec/spec_helper.rb +1 -2
- data/spec/string_atom_spec.rb +2 -2
- data/spec/symbol_spec.rb +2 -2
- data/spec/tokeniser_spec.rb +101 -0
- metadata +16 -2
@@ -0,0 +1,26 @@
|
|
1
|
+
(examples-for ampersand-syntax
|
2
|
+
("shortcut for hash-get"
|
3
|
+
(&key { key 'value })
|
4
|
+
value)
|
5
|
+
|
6
|
+
("acts as function"
|
7
|
+
(map &key (list { key 1 } { key 2 } { key 3 }))
|
8
|
+
(1 2 3))
|
9
|
+
|
10
|
+
("assigns to key"
|
11
|
+
(let h { key 12 }
|
12
|
+
(= (&key h) 13)
|
13
|
+
h.key)
|
14
|
+
13)
|
15
|
+
|
16
|
+
("assigns to key.subkey"
|
17
|
+
(let h { key { subkey 41 } }
|
18
|
+
(= (&key.subkey h) 42)
|
19
|
+
h.key.subkey)
|
20
|
+
42)
|
21
|
+
|
22
|
+
("even works with 'push"
|
23
|
+
(let h { key { subkey '(1 2 3) } }
|
24
|
+
(push 99 (&key.subkey h))
|
25
|
+
h.key.subkey)
|
26
|
+
(99 1 2 3)))
|
@@ -22,6 +22,10 @@
|
|
22
22
|
(collect (fn (x) (eq? (len x) 2)) '("aa" "bbb" "cc" "ddd" . "ee"))
|
23
23
|
("aa" "cc" . "ee"))
|
24
24
|
|
25
|
+
("preserves structure of improper list: returns just the lastcdr"
|
26
|
+
(collect (fn (x) (eq? (len x) 2)) '("aaa" "bbb" "ccc" "ddd" . "ee"))
|
27
|
+
"ee")
|
28
|
+
|
25
29
|
("returns nil if it's an atom and doesn't match"
|
26
30
|
(collect (fn (x) (eq? (len x) 20))
|
27
31
|
"zz")
|
@@ -16,7 +16,7 @@
|
|
16
16
|
(b c) (nth 1 xxx)
|
17
17
|
(d (e f)) (nth 2 xxx)
|
18
18
|
g (nth 3 xxx)
|
19
|
-
h (
|
19
|
+
h (nthcdr 4 xxx))))
|
20
20
|
|
21
21
|
(examples-for destructure/build
|
22
22
|
("with no args"
|
@@ -56,6 +56,23 @@
|
|
56
56
|
(nth 0 destructure-2)
|
57
57
|
(nth 1 destructure-2))) (nth 0 destructure-1) (nth 1 destructure-1))))
|
58
58
|
|
59
|
+
("nested improper arguments"
|
60
|
+
(let (a (b c . d) e) (list "A" (list "B" "C" "D0" "D1" "D2") "E")
|
61
|
+
(string-pieces a b c d e))
|
62
|
+
"ABCD0D1D2E")
|
63
|
+
|
64
|
+
; a lot of ceremony here to suppress side-effects of compiling really crap code and just get the warnings
|
65
|
+
("warns about arg names shadowing macro names"
|
66
|
+
(do (without-hooks 'warnings/new
|
67
|
+
λ(on-err nil
|
68
|
+
(pre-compile '(fun (aif (and or) . when)
|
69
|
+
"ignore"))))
|
70
|
+
warnings/list)
|
71
|
+
((arg-shadows-macro "arg " when " shadows macro " when " in arg list " (aif (and or) . when))
|
72
|
+
(arg-shadows-macro "arg " or " shadows macro " or " in arg list " (aif (and or) . when))
|
73
|
+
(arg-shadows-macro "arg " and " shadows macro " and " in arg list " (aif (and or) . when))
|
74
|
+
(arg-shadows-macro "arg " aif " shadows macro " aif " in arg list " (aif (and or) . when))))
|
75
|
+
|
59
76
|
("implicit in 'let and 'with"
|
60
77
|
(with ((a b) (list "h" "e")
|
61
78
|
(c (d e f)) (list "l" (list "l" "o" " ")))
|
@@ -1,6 +1,6 @@
|
|
1
1
|
(examples-for fill-bucket
|
2
2
|
("fills a bucket with 12 characters"
|
3
|
-
(fill
|
3
|
+
(bucket/fill '("1" "2345" "67" "890" "1" "2345" "678")
|
4
4
|
nil
|
5
5
|
len
|
6
6
|
0
|
@@ -10,7 +10,7 @@
|
|
10
10
|
("2345" "678")))
|
11
11
|
|
12
12
|
("fills a bucket up to 100"
|
13
|
-
(fill
|
13
|
+
(bucket/fill '(1 2 3 4 5 6 7 8 9 10)
|
14
14
|
nil
|
15
15
|
λx(* x x)
|
16
16
|
0
|
@@ -18,3 +18,47 @@
|
|
18
18
|
((1 2 3 4 5 6)
|
19
19
|
91
|
20
20
|
(7 8 9 10))))
|
21
|
+
|
22
|
+
(examples-for fill-buckets
|
23
|
+
("returns an empty list for no items"
|
24
|
+
(let pages (fill-buckets '() 30 nil λx(* x x) 'line-items)
|
25
|
+
(= pages (fill-buckets '() 30 pages len 'history ))
|
26
|
+
(= pages (fill-buckets '() 30 pages (k 1) 'payments ))
|
27
|
+
(rev:map λb(list 'size b.bucket-size 'line-items b.line-items 'history b.history 'payments b.payments)
|
28
|
+
pages))
|
29
|
+
())
|
30
|
+
|
31
|
+
("returns a single bucket for few items"
|
32
|
+
(let pages (fill-buckets '() 30 nil λx(* x x) 'line-items)
|
33
|
+
(= pages (fill-buckets '("aa" "bbbb" "c" "ddddd" "eeee") 30 pages len 'history ))
|
34
|
+
(= pages (fill-buckets '() 30 pages (k 1) 'payments ))
|
35
|
+
(rev:map λb(list 'size b.bucket-size 'line-items b.line-items 'history b.history 'payments b.payments)
|
36
|
+
pages))
|
37
|
+
((size 16 line-items nil history ("aa" "bbbb" "c" "ddddd" "eeee") payments nil)))
|
38
|
+
|
39
|
+
("returns a single overfilled bucket for an oversized item"
|
40
|
+
(let pages (fill-buckets '("aa34567890123456" "eeee") 12 nil len 'history )
|
41
|
+
(rev:map λb(list 'size b.bucket-size b.history)
|
42
|
+
pages))
|
43
|
+
((size 16 ("aa34567890123456"))
|
44
|
+
(size 4 ("eeee"))))
|
45
|
+
|
46
|
+
("accumulates subsequent items in subsequent buckets"
|
47
|
+
(let pages (fill-buckets '(1 2 2 4 3 3 1) 30 nil λx(* x x) 'line-items)
|
48
|
+
(= pages (fill-buckets '() 30 pages len 'history ))
|
49
|
+
(= pages (fill-buckets '(pay pay pay pay) 30 pages (k 3) 'payments ))
|
50
|
+
(rev:map λb(list 'size b.bucket-size 'line-items b.line-items 'history b.history 'payments b.payments)
|
51
|
+
pages))
|
52
|
+
((size 25 line-items (1 2 2 4) history nil payments nil)
|
53
|
+
(size 28 line-items (3 3 1) history nil payments (pay pay pay))
|
54
|
+
(size 3 line-items nil history nil payments (pay))))
|
55
|
+
|
56
|
+
("use fill-buckets for complex pagination where you have several sets of elements, each element having a different size"
|
57
|
+
(let pages (fill-buckets '(1 2 2 4 3 3 1) 30 nil λx(* x x) 'line-items)
|
58
|
+
(= pages (fill-buckets '("aa" "bbbb" "c" "ddddd" "eeee") 30 pages len 'history ))
|
59
|
+
(= pages (fill-buckets '(pay pay pay pay) 30 pages (k 1) 'payments ))
|
60
|
+
(rev:map λb(list 'size b.bucket-size 'line-items b.line-items 'history b.history 'payments b.payments)
|
61
|
+
pages))
|
62
|
+
((size 25 line-items (1 2 2 4) history nil payments nil)
|
63
|
+
(size 26 line-items (3 3 1) history ("aa" "bbbb" "c") payments nil)
|
64
|
+
(size 13 line-items nil history ("ddddd" "eeee") payments (pay pay pay pay)))))
|
@@ -0,0 +1,58 @@
|
|
1
|
+
(examples-for ⌊
|
2
|
+
("rounds the given to the nearest integer below"
|
3
|
+
(⌊ 12.5)
|
4
|
+
12)
|
5
|
+
|
6
|
+
("rounds the given to the nearest integer below"
|
7
|
+
(⌊ 32.32)
|
8
|
+
32)
|
9
|
+
|
10
|
+
("rounds the given to the nearest integer below negatively"
|
11
|
+
(⌊ -32.32)
|
12
|
+
-33)
|
13
|
+
|
14
|
+
("alias for 'math-floor"
|
15
|
+
(math-floor 3.1415)
|
16
|
+
3))
|
17
|
+
|
18
|
+
(examples-for ⌈
|
19
|
+
("rounds the given to the nearest integer above"
|
20
|
+
(⌈ 25.25)
|
21
|
+
26)
|
22
|
+
|
23
|
+
("rounds the given to the nearest integer above"
|
24
|
+
(⌈ 12.5)
|
25
|
+
13)
|
26
|
+
|
27
|
+
("rounds the given to the nearest integer above negatively"
|
28
|
+
(⌈ -25.25)
|
29
|
+
-25)
|
30
|
+
|
31
|
+
("alias for 'math-ceiling"
|
32
|
+
(math-ceiling 3.1415)
|
33
|
+
4))
|
34
|
+
|
35
|
+
(examples-for round
|
36
|
+
("rounds the given to the nearest integer"
|
37
|
+
(math-round 3.1415)
|
38
|
+
3)
|
39
|
+
|
40
|
+
("rounds the given to the nearest integer"
|
41
|
+
(math-round -3.1415)
|
42
|
+
-3)
|
43
|
+
|
44
|
+
("rounds the given to the nearest negative integer"
|
45
|
+
(math-round -3.999)
|
46
|
+
-4)
|
47
|
+
|
48
|
+
("rounds the given to the nearest integer"
|
49
|
+
(math-round 3.999)
|
50
|
+
4)
|
51
|
+
|
52
|
+
("rounds half-away from zero"
|
53
|
+
(math-round 12.5)
|
54
|
+
13)
|
55
|
+
|
56
|
+
("rounds negatively half-away from zero"
|
57
|
+
(math-round -1.5)
|
58
|
+
-2))
|
@@ -3,6 +3,10 @@
|
|
3
3
|
(string-split "a and b and c and d" " and ")
|
4
4
|
("a" "b" "c" "d"))
|
5
5
|
|
6
|
+
("with no delimiter argument, returns chars in string"
|
7
|
+
(collect !empty? (string-split "word"))
|
8
|
+
("w" "o" "r" "d"))
|
9
|
+
|
6
10
|
("returns empty leading, internal, and trailing segments"
|
7
11
|
(string-split "and" "and")
|
8
12
|
("" ""))
|
@@ -21,6 +25,10 @@
|
|
21
25
|
"a x b x c x d"))
|
22
26
|
|
23
27
|
(examples-for string-match
|
28
|
+
("no match returns nil"
|
29
|
+
(string-match "this that another" "XXXX")
|
30
|
+
nil)
|
31
|
+
|
24
32
|
("match with regexp"
|
25
33
|
(let m (string-match "a and b and c and d" "and")
|
26
34
|
(list m.match m.captures))
|
@@ -0,0 +1,16 @@
|
|
1
|
+
(examples-for zip
|
2
|
+
("joins two lists"
|
3
|
+
(zip '(a b c) '(1 2 3))
|
4
|
+
((a 1) (b 2) (c 3)))
|
5
|
+
|
6
|
+
("joins more lists"
|
7
|
+
(zip '(a b) '(1 2) '(p q) '(41 42 43) '(x y zip))
|
8
|
+
((a 1 p 41 x) (b 2 q 42 y)))
|
9
|
+
|
10
|
+
("resulting list is as long as first list"
|
11
|
+
(zip '(a b) '(1 2 3 4 5 6) nil)
|
12
|
+
((a 1 nil) (b 2 nil)))
|
13
|
+
|
14
|
+
("resulting list is nil if first list is nil"
|
15
|
+
(zip nil '(1 2 3 4 5) '(p q r))
|
16
|
+
nil))
|
data/lib/nydp.rb
CHANGED
@@ -5,6 +5,7 @@ module Nydp
|
|
5
5
|
class Namespace < Hash
|
6
6
|
end
|
7
7
|
|
8
|
+
# TODO: write VM #apply_function so we have fewer calls to VM.new
|
8
9
|
def self.apply_function ns, function_name, *args
|
9
10
|
function = r2n(function_name.to_sym, ns).value
|
10
11
|
args = r2n args, ns
|
@@ -18,6 +19,8 @@ module Nydp
|
|
18
19
|
def self.eval_src ns, src_txt, name=nil ; eval_with Nydp::Runner, ns, src_txt, name ; end
|
19
20
|
def self.eval_with runner, ns, src_txt, name ; runner.new(VM.new(ns), ns, reader(src_txt), nil, name).run ; end
|
20
21
|
def self.ms t1, t0 ; ((t1 - t0) * 1000).to_i ; end
|
22
|
+
def self.new_tokeniser reader ; Nydp::Tokeniser.new reader ; end
|
23
|
+
def self.new_parser ns ; Nydp::Parser.new(ns) ; end
|
21
24
|
|
22
25
|
def self.indent_message indent, msg
|
23
26
|
msg.split(/\n/).map { |line| "#{indent}#{line}" }.join("\n")
|
@@ -47,12 +50,13 @@ module Nydp
|
|
47
50
|
|
48
51
|
def self.repl options={ }
|
49
52
|
toplevel do
|
50
|
-
silent = options
|
53
|
+
silent = options.delete :silent
|
54
|
+
ns = options.delete :ns
|
51
55
|
launch_time = Time.now
|
52
56
|
last_script_time = Time.now
|
53
57
|
puts "welcome to nydp #{options.inspect}" unless silent
|
54
58
|
reader = Nydp::ReadlineReader.new $stdin, "nydp > "
|
55
|
-
ns
|
59
|
+
ns ||= build_nydp do |script|
|
56
60
|
this_script_time = Time.now
|
57
61
|
puts "script #{script} time #{ms this_script_time, last_script_time}ms" if options[:verbose]
|
58
62
|
last_script_time = this_script_time
|
data/lib/nydp/assignment.rb
CHANGED
@@ -21,8 +21,7 @@ class Nydp::Builtin::Ensuring
|
|
21
21
|
fn_tricky = args.cdr.car
|
22
22
|
|
23
23
|
protection_instructions = Nydp::Pair.from_list [InvokeProtection.new(fn_ensure), Nydp::PopArg]
|
24
|
-
vm.
|
25
|
-
vm.contexts.push vm.current_context
|
24
|
+
vm.push_ctx_instructions protection_instructions
|
26
25
|
|
27
26
|
fn_tricky.invoke vm, Nydp::NIL
|
28
27
|
end
|
@@ -2,11 +2,11 @@ class Nydp::Builtin::GreaterThan
|
|
2
2
|
include Nydp::Builtin::Base, Singleton
|
3
3
|
|
4
4
|
def builtin_invoke vm, args
|
5
|
-
vm.push_arg
|
5
|
+
vm.push_arg(greater_than(args.car, args.cdr) || Nydp::NIL)
|
6
6
|
end
|
7
7
|
|
8
8
|
def greater_than arg, args
|
9
|
-
return
|
9
|
+
return arg if Nydp::NIL.is? args
|
10
10
|
(arg > args.car) && greater_than(args.car, args.cdr)
|
11
11
|
end
|
12
12
|
|
@@ -39,8 +39,7 @@ class Nydp::Builtin::HandleError
|
|
39
39
|
fn_tricky = args.cdr.car
|
40
40
|
|
41
41
|
catcher_instructions = Nydp::Pair.from_list [CatchError.new(fn_handle, vm.args.size)]
|
42
|
-
vm.
|
43
|
-
vm.contexts.push vm.current_context
|
42
|
+
vm.push_ctx_instructions catcher_instructions
|
44
43
|
|
45
44
|
fn_tricky.invoke vm, Nydp::NIL
|
46
45
|
end
|
@@ -2,11 +2,11 @@ class Nydp::Builtin::LessThan
|
|
2
2
|
include Nydp::Builtin::Base, Singleton
|
3
3
|
|
4
4
|
def builtin_invoke vm, args
|
5
|
-
vm.push_arg
|
5
|
+
vm.push_arg(less_than(args.car, args.cdr) || Nydp::NIL)
|
6
6
|
end
|
7
7
|
|
8
8
|
def less_than arg, args
|
9
|
-
return
|
9
|
+
return arg if Nydp::NIL.is? args
|
10
10
|
(arg < args.car) && less_than(args.car, args.cdr)
|
11
11
|
end
|
12
12
|
|
data/lib/nydp/builtin/parse.rb
CHANGED
@@ -2,8 +2,8 @@ class Nydp::Builtin::Parse
|
|
2
2
|
include Nydp::Builtin::Base, Singleton
|
3
3
|
|
4
4
|
def builtin_invoke vm, args
|
5
|
-
parser = Nydp
|
6
|
-
tokens = Nydp
|
5
|
+
parser = Nydp.new_parser(vm.ns)
|
6
|
+
tokens = Nydp.new_tokeniser Nydp::StringReader.new args.car.to_s
|
7
7
|
exprs = []
|
8
8
|
while !tokens.finished
|
9
9
|
expr = parser.expression(tokens)
|
@@ -2,10 +2,10 @@ class Nydp::Builtin::ParseInString
|
|
2
2
|
include Nydp::Builtin::Base, Singleton
|
3
3
|
|
4
4
|
def builtin_invoke vm, args
|
5
|
-
parser = Nydp
|
5
|
+
parser = Nydp.new_parser(vm.ns)
|
6
6
|
parsable = args.car.to_s
|
7
|
-
tokens = Nydp
|
8
|
-
expr = parser.
|
7
|
+
tokens = Nydp.new_tokeniser Nydp::StringReader.new parsable
|
8
|
+
expr = parser.embedded(tokens)
|
9
9
|
vm.push_arg expr
|
10
10
|
rescue StandardError => e
|
11
11
|
new_msg = "parse error: #{e.message.inspect} in\n#{Nydp.indent_text parsable}"
|