nydp 0.3.0 → 0.4.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/.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}"
|