nydp 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +77 -56
- data/lib/lisp/core-000.nydp +1 -1
- data/lib/lisp/core-010-precompile.nydp +49 -29
- data/lib/lisp/core-012-utils.nydp +12 -8
- data/lib/lisp/core-015-documentation.nydp +41 -15
- data/lib/lisp/core-017-builtin-dox.nydp +621 -100
- data/lib/lisp/core-020-utils.nydp +33 -6
- data/lib/lisp/core-025-warnings.nydp +1 -1
- data/lib/lisp/core-030-syntax.nydp +64 -48
- data/lib/lisp/core-035-flow-control.nydp +20 -28
- data/lib/lisp/core-037-list-utils.nydp +84 -21
- data/lib/lisp/core-040-utils.nydp +8 -5
- data/lib/lisp/core-041-string-utils.nydp +17 -11
- data/lib/lisp/core-043-list-utils.nydp +140 -77
- data/lib/lisp/core-045-dox-utils.nydp +1 -0
- data/lib/lisp/core-050-test-runner.nydp +8 -12
- data/lib/lisp/core-070-prefix-list.nydp +19 -15
- data/lib/lisp/core-080-pretty-print.nydp +13 -5
- data/lib/lisp/core-090-hook.nydp +11 -11
- data/lib/lisp/core-100-utils.nydp +51 -66
- data/lib/lisp/core-110-hash-utils.nydp +34 -7
- data/lib/lisp/core-120-settings.nydp +14 -9
- data/lib/lisp/core-130-validations.nydp +28 -13
- data/lib/lisp/core-900-benchmarking.nydp +420 -47
- data/lib/lisp/tests/000-empty-args-examples.nydp +5 -0
- data/lib/lisp/tests/andify-examples.nydp +1 -1
- data/lib/lisp/tests/auto-hash-examples.nydp +6 -1
- data/lib/lisp/tests/best-examples.nydp +1 -1
- data/lib/lisp/tests/boot-tests.nydp +1 -1
- data/lib/lisp/tests/date-examples.nydp +129 -102
- data/lib/lisp/tests/destructuring-examples.nydp +1 -1
- data/lib/lisp/tests/dox-tests.nydp +2 -2
- data/lib/lisp/tests/hash-examples.nydp +58 -33
- data/lib/lisp/tests/list-tests.nydp +137 -1
- data/lib/lisp/tests/pretty-print-tests.nydp +12 -0
- data/lib/lisp/tests/rotate-2d-array-examples.nydp +26 -0
- data/lib/lisp/tests/sort-examples.nydp +5 -5
- data/lib/lisp/tests/string-tests.nydp +30 -5
- data/lib/lisp/tests/syntax-tests.nydp +10 -2
- data/lib/lisp/tests/time-examples.nydp +8 -1
- data/lib/lisp/tests/unparse-tests.nydp +13 -7
- data/lib/nydp/assignment.rb +15 -28
- data/lib/nydp/builtin/abs.rb +4 -3
- data/lib/nydp/builtin/apply.rb +8 -10
- data/lib/nydp/builtin/cdr_set.rb +1 -1
- data/lib/nydp/builtin/comment.rb +1 -3
- data/lib/nydp/builtin/date.rb +11 -28
- data/lib/nydp/builtin/divide.rb +3 -10
- data/lib/nydp/builtin/ensuring.rb +6 -21
- data/lib/nydp/builtin/error.rb +2 -4
- data/lib/nydp/builtin/eval.rb +9 -4
- data/lib/nydp/builtin/greater_than.rb +7 -8
- data/lib/nydp/builtin/handle_error.rb +10 -34
- data/lib/nydp/builtin/hash.rb +24 -45
- data/lib/nydp/builtin/inspect.rb +1 -3
- data/lib/nydp/builtin/is_equal.rb +4 -7
- data/lib/nydp/builtin/less_than.rb +6 -7
- data/lib/nydp/builtin/log.rb +7 -0
- data/lib/nydp/builtin/math_ceiling.rb +1 -3
- data/lib/nydp/builtin/math_floor.rb +1 -3
- data/lib/nydp/builtin/math_power.rb +1 -3
- data/lib/nydp/builtin/math_round.rb +2 -2
- data/lib/nydp/builtin/minus.rb +7 -14
- data/lib/nydp/builtin/parse.rb +5 -5
- data/lib/nydp/builtin/parse_in_string.rb +5 -7
- data/lib/nydp/builtin/plus.rb +14 -31
- data/lib/nydp/builtin/pre_compile.rb +1 -3
- data/lib/nydp/builtin/puts.rb +4 -8
- data/lib/nydp/builtin/quit.rb +1 -1
- data/lib/nydp/builtin/rand.rb +6 -11
- data/lib/nydp/builtin/random_string.rb +2 -4
- data/lib/nydp/builtin/rng.rb +25 -0
- data/lib/nydp/builtin/ruby_wrap.rb +27 -14
- data/lib/nydp/builtin/script_run.rb +1 -3
- data/lib/nydp/builtin/set_intersection.rb +3 -4
- data/lib/nydp/builtin/set_union.rb +3 -4
- data/lib/nydp/builtin/sort.rb +2 -7
- data/lib/nydp/builtin/string_match.rb +5 -13
- data/lib/nydp/builtin/string_replace.rb +2 -7
- data/lib/nydp/builtin/string_split.rb +3 -8
- data/lib/nydp/builtin/sym.rb +2 -9
- data/lib/nydp/builtin/thread_locals.rb +2 -2
- data/lib/nydp/builtin/time.rb +38 -44
- data/lib/nydp/builtin/times.rb +6 -15
- data/lib/nydp/builtin/to_integer.rb +8 -14
- data/lib/nydp/builtin/to_string.rb +2 -13
- data/lib/nydp/builtin/type_of.rb +10 -16
- data/lib/nydp/builtin/vm_info.rb +2 -10
- data/lib/nydp/builtin.rb +15 -37
- data/lib/nydp/compiler.rb +29 -19
- data/lib/nydp/cond.rb +95 -88
- data/lib/nydp/context_symbol.rb +11 -9
- data/lib/nydp/core.rb +74 -73
- data/lib/nydp/core_ext.rb +88 -24
- data/lib/nydp/date.rb +22 -19
- data/lib/nydp/error.rb +2 -3
- data/lib/nydp/function_invocation.rb +76 -289
- data/lib/nydp/helper.rb +18 -9
- data/lib/nydp/interpreted_function.rb +159 -25
- data/lib/nydp/lexical_context.rb +9 -8
- data/lib/nydp/lexical_context_builder.rb +1 -1
- data/lib/nydp/literal.rb +3 -7
- data/lib/nydp/loop.rb +72 -0
- data/lib/nydp/namespace.rb +52 -0
- data/lib/nydp/pair.rb +146 -50
- data/lib/nydp/parser.rb +9 -11
- data/lib/nydp/plugin.rb +88 -19
- data/lib/nydp/runner.rb +141 -23
- data/lib/nydp/symbol.rb +16 -26
- data/lib/nydp/symbol_lookup.rb +3 -2
- data/lib/nydp/tokeniser.rb +1 -1
- data/lib/nydp/truth.rb +2 -37
- data/lib/nydp/version.rb +1 -1
- data/lib/nydp.rb +33 -44
- data/nydp.gemspec +2 -1
- data/spec/date_spec.rb +26 -32
- data/spec/embedded_spec.rb +22 -22
- data/spec/error_spec.rb +12 -16
- data/spec/foreign_hash_spec.rb +21 -36
- data/spec/hash_non_hash_behaviour_spec.rb +12 -29
- data/spec/hash_spec.rb +36 -49
- data/spec/literal_spec.rb +6 -6
- data/spec/nydp_spec.rb +14 -14
- data/spec/pair_spec.rb +8 -8
- data/spec/parser_spec.rb +41 -37
- data/spec/rand_spec.rb +1 -4
- data/spec/spec_helper.rb +3 -3
- data/spec/string_atom_spec.rb +15 -16
- data/spec/symbol_spec.rb +27 -52
- data/spec/thread_local_spec.rb +23 -8
- data/spec/time_spec.rb +4 -10
- data/spec/tokeniser_spec.rb +10 -10
- metadata +25 -13
- data/lib/nydp/builtin/modulo.rb +0 -11
- data/lib/nydp/builtin/regexp.rb +0 -7
- data/lib/nydp/builtin/sqrt.rb +0 -7
- data/lib/nydp/builtin/string_pad_left.rb +0 -7
- data/lib/nydp/builtin/string_pad_right.rb +0 -7
- data/lib/nydp/hash.rb +0 -9
- data/lib/nydp/image_store.rb +0 -21
- data/lib/nydp/vm.rb +0 -129
data/lib/nydp/symbol.rb
CHANGED
@@ -10,6 +10,7 @@ class Nydp::Symbol
|
|
10
10
|
def initialize name
|
11
11
|
name = name.to_s
|
12
12
|
@name = name.to_sym
|
13
|
+
raise "cannot be symbol : #{name.inspect}" if @name == :nil || @name == :t
|
13
14
|
@inspection = "|#{name.gsub(/\|/, '\|')}|" if untidy(name)
|
14
15
|
end
|
15
16
|
|
@@ -20,19 +21,21 @@ class Nydp::Symbol
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def value context=nil
|
23
|
-
raise Unbound.new("unbound symbol: #{self.inspect}") if @value == nil
|
24
24
|
@value
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
def ruby_name
|
28
|
+
"ns_#{name.to_s._nydp_name_to_rb_name}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def compile_to_ruby indent, src, opts=nil
|
32
|
+
"#{indent}ns.#{ruby_name}"
|
31
33
|
end
|
32
34
|
|
33
|
-
def self.
|
34
|
-
name
|
35
|
-
|
35
|
+
def self.special name
|
36
|
+
return nil if name == :nil
|
37
|
+
return true if name == :t
|
38
|
+
nil
|
36
39
|
end
|
37
40
|
|
38
41
|
def self.find name, ns ; ns[name.to_sym] ; end
|
@@ -47,7 +50,11 @@ class Nydp::Symbol
|
|
47
50
|
def < other ; self.name < other.name ; end
|
48
51
|
def <=> other ; self.name <=> other.name ; end
|
49
52
|
def assign value, _=nil ; @value = value ; end
|
50
|
-
|
53
|
+
|
54
|
+
def ns_assign ns, value
|
55
|
+
value.is_named(@name) if value.respond_to?(:is_named)
|
56
|
+
ns.send(:"#{ruby_name}=", value)
|
57
|
+
end
|
51
58
|
|
52
59
|
def == other
|
53
60
|
other.is_a?(Nydp::Symbol) && (self.name == other.name)
|
@@ -55,20 +62,3 @@ class Nydp::Symbol
|
|
55
62
|
|
56
63
|
alias eql? ==
|
57
64
|
end
|
58
|
-
|
59
|
-
class Nydp::FrozenSymbol < Nydp::Symbol
|
60
|
-
@@frozen = { }
|
61
|
-
|
62
|
-
def self.mk name
|
63
|
-
name = name.to_s.to_sym
|
64
|
-
@@frozen[name] ||= new(name)
|
65
|
-
end
|
66
|
-
|
67
|
-
def value _=nil
|
68
|
-
raise Unbound.new("frozen symbol: #{self.inspect}")
|
69
|
-
end
|
70
|
-
|
71
|
-
def assign v, _=nil
|
72
|
-
raise "can't assign to frozen: #{self.inspect}"
|
73
|
-
end
|
74
|
-
end
|
data/lib/nydp/symbol_lookup.rb
CHANGED
@@ -11,7 +11,7 @@ module Nydp
|
|
11
11
|
bindings
|
12
12
|
end
|
13
13
|
|
14
|
-
def self.build name, original_bindings
|
14
|
+
def self.build name, original_bindings, ns
|
15
15
|
effective_bindings = skip_empty original_bindings
|
16
16
|
depth = 0
|
17
17
|
while NIL != effective_bindings
|
@@ -24,7 +24,8 @@ module Nydp
|
|
24
24
|
effective_bindings = skip_empty effective_bindings.cdr
|
25
25
|
end
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
|
+
Nydp::Symbol.new name.to_s.to_sym
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
data/lib/nydp/tokeniser.rb
CHANGED
@@ -89,7 +89,7 @@ module Nydp
|
|
89
89
|
@finished = true
|
90
90
|
return nil
|
91
91
|
elsif comment = s.scan(COMMENT)
|
92
|
-
tok = [:comment, comment.gsub(/^;;?\s
|
92
|
+
tok = [:comment, comment.gsub(/^;;?\s?/, '')]
|
93
93
|
elsif open_str = s.scan(QUOTE)
|
94
94
|
tok = [:string_open_delim, open_str]
|
95
95
|
elsif open_sym = s.scan(PIPE)
|
data/lib/nydp/truth.rb
CHANGED
@@ -1,41 +1,6 @@
|
|
1
1
|
require 'singleton'
|
2
2
|
|
3
3
|
module Nydp
|
4
|
-
|
5
|
-
|
6
|
-
def init_with *; Nydp::T ; end
|
7
|
-
def to_s ; 't' ; end
|
8
|
-
def inspect ; 't' ; end
|
9
|
-
def assign *_ ; self ; end
|
10
|
-
def nydp_type ; :truth ; end
|
11
|
-
def to_ruby ; true ; end
|
12
|
-
def _nydp_get a ; Nydp::T ; end
|
13
|
-
def _nydp_set a, v ; Nydp::T ; end
|
14
|
-
end
|
15
|
-
|
16
|
-
class Nil
|
17
|
-
include Singleton, Enumerable
|
18
|
-
def init_with * ; Nydp::NIL ; end
|
19
|
-
def car ; self ; end
|
20
|
-
def cdr ; self ; end
|
21
|
-
def size ; 0 ; end
|
22
|
-
def is? other ; self.equal? other ; end
|
23
|
-
def isnt? other ; !self.equal? other ; end
|
24
|
-
def to_s ; "" ; end
|
25
|
-
def + other ; other ; end
|
26
|
-
def copy ; self ; end
|
27
|
-
def assign *_ ; self ; end
|
28
|
-
def inspect ; "nil" ; end
|
29
|
-
def nydp_type ; :nil ; end
|
30
|
-
def to_ruby ; nil ; end
|
31
|
-
def execute vm ; vm.push_arg self ; end
|
32
|
-
def _nydp_get a ; Nydp::NIL ; end
|
33
|
-
def _nydp_set a, v ; Nydp::NIL ; end
|
34
|
-
def each ; ; end # nil behaves like an empty list
|
35
|
-
def & other ; self ; end
|
36
|
-
def | other ; other ; end
|
37
|
-
end
|
38
|
-
|
39
|
-
NIL = Nil.instance
|
40
|
-
T = Truth.instance
|
4
|
+
NIL = nil
|
5
|
+
T = true
|
41
6
|
end
|
data/lib/nydp/version.rb
CHANGED
data/lib/nydp.rb
CHANGED
@@ -2,30 +2,19 @@ require 'date'
|
|
2
2
|
require 'set'
|
3
3
|
|
4
4
|
module Nydp
|
5
|
-
|
6
|
-
attr_accessor :logger # not used by this gem but very useful in your app
|
7
|
-
end
|
8
|
-
|
9
|
-
class Namespace < Hash
|
10
|
-
end
|
5
|
+
GENERATED_CLASS_PREFIX = "NydpGenerated"
|
11
6
|
|
12
|
-
|
13
|
-
|
14
|
-
vm = VM.new(ns)
|
15
|
-
function = Symbol.mk(function_name.to_sym, ns).value
|
16
|
-
function.invoke vm, r2n(args)
|
17
|
-
vm.thread
|
18
|
-
rescue StandardError => e
|
19
|
-
friendly_args = args.map { |a| a.respond_to?(:_nydp_compact_inspect) ? a._nydp_compact_inspect : a }
|
20
|
-
raise Nydp::Error.new("Invoking #{function_name}\nwith args #{friendly_args.inspect}")
|
7
|
+
class << self
|
8
|
+
attr_accessor :logger # set this if you plan on using 'log
|
21
9
|
end
|
22
10
|
|
23
|
-
def self.
|
24
|
-
def self.
|
25
|
-
def self.
|
26
|
-
def self.
|
27
|
-
def self.
|
28
|
-
def self.
|
11
|
+
def self.apply_function ns, name, *args ; ns.apply name, *args ; end
|
12
|
+
def self.reader name, txt ; Nydp::StringReader.new name, txt ; end
|
13
|
+
def self.eval_src ns, src_txt, name=nil ; eval_with Nydp::Runner, ns, src_txt, name ; end
|
14
|
+
def self.eval_with runner, ns, src_txt, name ; runner.new(ns, reader(name, src_txt), nil, name).run ; end
|
15
|
+
def self.ms t1, t0 ; ((t1 - t0) * 1000).to_i ; end
|
16
|
+
def self.new_tokeniser reader ; Nydp::Tokeniser.new reader ; end
|
17
|
+
def self.new_parser ; Nydp::Parser.new ; end
|
29
18
|
|
30
19
|
def self.indent_message indent, msg
|
31
20
|
msg.split(/\n/).map { |line| "#{indent}#{line}" }.join("\n")
|
@@ -39,7 +28,7 @@ module Nydp
|
|
39
28
|
puts "\n#{indent}Caused by:"
|
40
29
|
handle_run_error e.cause, "#{indent} "
|
41
30
|
else
|
42
|
-
e.backtrace.each do |b|
|
31
|
+
Nydp.enhance_backtrace(e.backtrace).each do |b|
|
43
32
|
puts "#{indent}#{b}"
|
44
33
|
end
|
45
34
|
end
|
@@ -54,34 +43,34 @@ module Nydp
|
|
54
43
|
end
|
55
44
|
|
56
45
|
def self.repl options={ }
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
46
|
+
launch_time = Time.now
|
47
|
+
silent = options.delete :silent
|
48
|
+
ns = options.delete :ns
|
49
|
+
last_script_time = Time.now
|
50
|
+
puts "welcome to nydp #{options.inspect}" unless silent
|
51
|
+
reader = Nydp::ReadlineReader.new $stdin, "nydp > "
|
52
|
+
ns ||= build_nydp do |script|
|
53
|
+
this_script_time = Time.now
|
54
|
+
puts "script #{script} time #{ms this_script_time, last_script_time}ms" if options[:verbose]
|
55
|
+
last_script_time = this_script_time
|
56
|
+
end
|
57
|
+
load_time = Time.now
|
58
|
+
puts "nydp v#{Nydp::VERSION} repl ready in #{ms(load_time, launch_time)}ms" unless silent
|
59
|
+
puts "^D to exit" unless silent
|
60
|
+
while !options[:exit]
|
61
|
+
toplevel do
|
62
|
+
Nydp::Runner.new(ns, reader, $stdout, "<stdin>").run
|
63
|
+
options[:exit] = true
|
68
64
|
end
|
69
|
-
load_time = Time.now
|
70
|
-
puts "nydp v#{Nydp::VERSION} repl ready in #{ms(load_time, launch_time)}ms" unless silent
|
71
|
-
puts "^D to exit" unless silent
|
72
|
-
return if options[:exit]
|
73
|
-
Nydp::Runner.new(VM.new(ns), ns, reader, $stdout, "<stdin>").run
|
74
|
-
# Nydp::Invocation.whazzup
|
75
65
|
end
|
66
|
+
# Nydp::Invocation.whazzup
|
76
67
|
end
|
77
68
|
|
78
69
|
def self.tests *options
|
79
70
|
toplevel do
|
80
|
-
verbose = options.include?(:verbose) ?
|
71
|
+
verbose = options.include?(:verbose) ? true : nil
|
81
72
|
puts "welcome to nydp : running tests"
|
82
|
-
|
83
|
-
ns = build_nydp
|
84
|
-
Nydp::Runner.new(VM.new(ns), ns, reader, nil, "<test-runner>").run
|
73
|
+
build_nydp.apply :"run-all-tests", verbose
|
85
74
|
end
|
86
75
|
end
|
87
76
|
end
|
@@ -105,4 +94,4 @@ require "nydp/string_token"
|
|
105
94
|
require "nydp/tokeniser"
|
106
95
|
require "nydp/parser"
|
107
96
|
require "nydp/compiler"
|
108
|
-
require "nydp/
|
97
|
+
require "nydp/namespace"
|
data/nydp.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency "
|
21
|
+
spec.add_development_dependency "irb"
|
22
|
+
spec.add_development_dependency "rake", "~> 13"
|
22
23
|
spec.add_development_dependency 'rspec' #, '~> 3.1'
|
23
24
|
end
|
data/spec/date_spec.rb
CHANGED
@@ -2,33 +2,29 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Nydp::Date do
|
4
4
|
|
5
|
-
let(:ns) { { } }
|
6
|
-
let(:vm) { Nydp::VM.new(ns) }
|
7
5
|
|
8
6
|
it "converts ruby Date to Nydp::Date" do
|
9
7
|
rd = Date.parse "2015-06-08"
|
10
8
|
nd = Nydp.r2n rd
|
11
9
|
|
12
|
-
expect(nd). to be_a
|
10
|
+
expect(nd). to be_a ::Date
|
13
11
|
expect(nd.to_s). to eq "2015-06-08"
|
14
|
-
expect(nd.
|
12
|
+
expect(nd._nydp_inspect).to eq "#<Date: 2015-06-08 ((2457182j,0s,0n),+0s,2299161j)>"
|
15
13
|
expect(nd.to_ruby).to eq Date.parse("2015-06-08")
|
16
14
|
end
|
17
15
|
|
18
16
|
it "creates a new date" do
|
19
17
|
df = Nydp::Builtin::Date.instance
|
20
|
-
df.
|
21
|
-
nd
|
22
|
-
expect(nd).to
|
23
|
-
expect(nd.ruby_date).to eq Date.parse("2015-11-18")
|
18
|
+
nd = df.call 2015, 11, 18
|
19
|
+
expect(nd).to be_a ::Date
|
20
|
+
expect(nd).to eq Date.parse("2015-11-18")
|
24
21
|
end
|
25
22
|
|
26
23
|
it "returns today" do
|
27
24
|
df = Nydp::Builtin::Date.instance
|
28
|
-
df.
|
29
|
-
nd
|
30
|
-
expect(nd).to
|
31
|
-
expect(nd.ruby_date).to eq Date.today
|
25
|
+
nd = df.call
|
26
|
+
expect(nd).to be_a ::Date
|
27
|
+
expect(nd).to eq Date.today
|
32
28
|
end
|
33
29
|
|
34
30
|
it "returns date components" do
|
@@ -47,10 +43,9 @@ describe Nydp::Date do
|
|
47
43
|
it "works with builtin minus" do
|
48
44
|
minus = Nydp::Builtin::Minus.instance
|
49
45
|
|
50
|
-
minus.
|
51
|
-
diff = vm.args.pop
|
46
|
+
diff = minus.call d1, d0
|
52
47
|
|
53
|
-
expect(d0).to be_a
|
48
|
+
expect(d0).to be_a ::Date
|
54
49
|
expect(diff).to eq 6
|
55
50
|
end
|
56
51
|
|
@@ -58,25 +53,25 @@ describe Nydp::Date do
|
|
58
53
|
it "works with builtin greater-than when true" do
|
59
54
|
f = Nydp::Builtin::GreaterThan.instance
|
60
55
|
|
61
|
-
f.
|
56
|
+
a = f.call d1, d0
|
62
57
|
|
63
|
-
expect(
|
58
|
+
expect(a).to eq d0
|
64
59
|
end
|
65
60
|
|
66
61
|
it "compares with nil" do
|
67
62
|
f = Nydp::Builtin::GreaterThan.instance
|
68
63
|
|
69
|
-
f.
|
64
|
+
a = f.call d1, nil
|
70
65
|
|
71
|
-
expect(
|
66
|
+
expect(a).to eq Nydp::NIL
|
72
67
|
end
|
73
68
|
|
74
69
|
it "works with builtin greater-than when false" do
|
75
70
|
f = Nydp::Builtin::GreaterThan.instance
|
76
71
|
|
77
|
-
f.
|
72
|
+
a = f.call d0, d1
|
78
73
|
|
79
|
-
expect(
|
74
|
+
expect(a).to eq Nydp::NIL
|
80
75
|
end
|
81
76
|
end
|
82
77
|
|
@@ -84,37 +79,36 @@ describe Nydp::Date do
|
|
84
79
|
it "works with builtin less-than when true" do
|
85
80
|
f = Nydp::Builtin::LessThan.instance
|
86
81
|
|
87
|
-
f.
|
82
|
+
a = f.call d0, d1
|
88
83
|
|
89
|
-
expect(
|
84
|
+
expect(a).to eq d1
|
90
85
|
end
|
91
86
|
|
92
87
|
it "works with builtin less-than when false" do
|
93
88
|
f = Nydp::Builtin::LessThan.instance
|
94
89
|
|
95
|
-
f.
|
90
|
+
a = f.call d1, d0
|
96
91
|
|
97
|
-
expect(
|
92
|
+
expect(a).to eq Nydp::NIL
|
98
93
|
end
|
99
94
|
|
100
95
|
it "compares with nil" do
|
101
96
|
f = Nydp::Builtin::LessThan.instance
|
102
97
|
|
103
|
-
f.
|
98
|
+
a = f.call d1, nil
|
104
99
|
|
105
|
-
expect(
|
100
|
+
expect(a).to eq Nydp::NIL
|
106
101
|
end
|
107
102
|
end
|
108
103
|
|
109
104
|
it "works with builtin plus" do
|
110
105
|
plus = Nydp::Builtin::Plus.instance
|
111
106
|
|
112
|
-
plus.
|
113
|
-
sum = vm.args.pop
|
107
|
+
sum = plus.call d0, 5
|
114
108
|
|
115
|
-
expect(d0) .to be_a
|
116
|
-
expect(sum).to be_a
|
117
|
-
expect(sum
|
109
|
+
expect(d0) .to be_a ::Date
|
110
|
+
expect(sum).to be_a ::Date
|
111
|
+
expect(sum).to eq(Date.today + 5)
|
118
112
|
end
|
119
113
|
end
|
120
114
|
|
data/spec/embedded_spec.rb
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Nydp::Parser do
|
4
|
-
let(:aa) {
|
5
|
-
let(:a) {
|
6
|
-
let(:b) {
|
7
|
-
let(:c) {
|
8
|
-
let(:d) {
|
9
|
-
let(:zz) {
|
10
|
-
let(:foo) {
|
11
|
-
let(:bar) {
|
12
|
-
let(:zab) {
|
13
|
-
let(:quote) {
|
14
|
-
let(:quasiquote) {
|
15
|
-
let(:unquote) {
|
16
|
-
let(:unquote_splicing) {
|
17
|
-
let(:comment) {
|
18
|
-
let(:dotsyn) {
|
19
|
-
let(:cocosyn) {
|
20
|
-
let(:colosyn) {
|
4
|
+
let(:aa) { :aa }
|
5
|
+
let(:a) { :a }
|
6
|
+
let(:b) { :b }
|
7
|
+
let(:c) { :c }
|
8
|
+
let(:d) { :d }
|
9
|
+
let(:zz) { :zz }
|
10
|
+
let(:foo) { :foo }
|
11
|
+
let(:bar) { :bar }
|
12
|
+
let(:zab) { :zab }
|
13
|
+
let(:quote) { :quote }
|
14
|
+
let(:quasiquote) { :quasiquote }
|
15
|
+
let(:unquote) { :unquote }
|
16
|
+
let(:unquote_splicing) { :"unquote-splicing" }
|
17
|
+
let(:comment) { :comment }
|
18
|
+
let(:dotsyn) { :"dot-syntax" }
|
19
|
+
let(:cocosyn) { :"colon-colon-syntax" }
|
20
|
+
let(:colosyn) { :"colon-syntax" }
|
21
21
|
|
22
22
|
def parse_string txt
|
23
|
-
reader = Nydp::StringReader.new txt
|
24
|
-
Nydp.new_parser
|
23
|
+
reader = Nydp::StringReader.new "test", txt
|
24
|
+
Nydp.new_parser.embedded(Nydp.new_tokeniser(reader))
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should parse empty string" do
|
@@ -33,14 +33,14 @@ describe Nydp::Parser do
|
|
33
33
|
it "should parse external text" do
|
34
34
|
actual = parse_string "a fluffy bunny!"
|
35
35
|
expect(actual) .to eq "a fluffy bunny!"
|
36
|
-
expect(actual.
|
36
|
+
expect(actual._nydp_inspect).to eq '"a fluffy bunny!"'
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should parse a string delimited by eof" do
|
40
40
|
expected = pair_list([sym('string-pieces'), Nydp::StringFragmentCloseToken.new('a fluffy bunny!','a fluffy bunny!')])
|
41
41
|
actual = parse_string "a fluffy bunny!"
|
42
42
|
expect(actual) .to eq "a fluffy bunny!"
|
43
|
-
expect(actual.
|
43
|
+
expect(actual._nydp_inspect).to eq '"a fluffy bunny!"'
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should parse a string with embedded code, delimited by eof" do
|
@@ -104,6 +104,6 @@ describe Nydp::Parser do
|
|
104
104
|
|
105
105
|
it "parses a string that looks like html with little bits of embedded code in it" do
|
106
106
|
parsed = parse_string "<div id='item_~{id}'><label>~{data-label-1}</label> ~{data-content-1}</div>"
|
107
|
-
expect(parsed.
|
107
|
+
expect(parsed._nydp_inspect).to eq '(string-pieces "<div id=\'item_" (brace-list id) "\'><label>" (brace-list data-label-1) "</label> " (brace-list data-content-1) "</div>")'
|
108
108
|
end
|
109
109
|
end
|
data/spec/error_spec.rb
CHANGED
@@ -1,40 +1,36 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Nydp
|
4
|
-
let(:ns) { { } }
|
5
|
-
let(:vm) { Nydp::VM.new(ns) }
|
3
|
+
describe Nydp do
|
6
4
|
|
7
5
|
def run txt
|
8
6
|
Nydp.setup ns
|
9
|
-
Nydp::Runner.new(
|
7
|
+
Nydp::Runner.new(ns, Nydp::StringReader.new("test", txt)).run
|
10
8
|
end
|
11
9
|
|
12
10
|
describe "unhandled_error" do
|
13
11
|
it "raises a helpful error" do
|
14
12
|
error = nil
|
15
13
|
begin
|
16
|
-
run "
|
14
|
+
run "(/ 10 0)"
|
17
15
|
rescue StandardError => e
|
18
16
|
error = e
|
19
17
|
end
|
20
18
|
|
21
19
|
expect(error).to be_a Nydp::Error
|
22
|
-
expect(error.message).to eq "failed to eval
|
20
|
+
expect(error.message).to eq "failed to eval (/ 10 0) from src (/ 10 0)"
|
23
21
|
|
24
|
-
expect(error.cause).to be_a
|
25
|
-
expect(error.cause.message).to eq "
|
22
|
+
expect(error.cause).to be_a RuntimeError
|
23
|
+
expect(error.cause.message).to eq "Called builtin//
|
24
|
+
with args
|
25
|
+
10
|
26
|
+
0"
|
26
27
|
|
27
|
-
expect(
|
28
|
+
expect(error.cause.cause).to be_a ZeroDivisionError
|
29
|
+
expect(error.cause.cause.message).to eq "divided by 0"
|
28
30
|
end
|
29
31
|
|
30
32
|
it "recovers quickly from an error" do
|
31
|
-
|
32
|
-
run "dflkjdgjeirgjeoi"
|
33
|
-
rescue
|
34
|
-
end
|
35
|
-
|
36
|
-
expect(vm.unhandled_error).to eq nil
|
37
|
-
|
33
|
+
run "dflkjdgjeirgjeoi"
|
38
34
|
expect(run "(+ 2 3 4)").to eq 9
|
39
35
|
end
|
40
36
|
end
|
data/spec/foreign_hash_spec.rb
CHANGED
@@ -1,75 +1,61 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe
|
4
|
-
let(:vm) { Nydp::VM.new(ns) }
|
3
|
+
describe ::Hash do
|
5
4
|
|
6
5
|
describe "foreign hashes" do
|
7
6
|
let(:ahash) { Hash.new }
|
8
7
|
|
9
8
|
describe "hash set" do
|
10
9
|
it "returns a new Nydp hash" do
|
11
|
-
k =
|
10
|
+
k = :keysym
|
12
11
|
v = "foobar"
|
13
|
-
|
14
|
-
Nydp::Builtin::HashSet.instance.invoke vm, args
|
12
|
+
a = Nydp::Builtin::HashSet.instance.call ahash, k, v
|
15
13
|
|
16
14
|
expect(ahash[:keysym]). to eq "foobar"
|
17
15
|
expect(ahash[:keysym].class).to eq String
|
18
16
|
expect(ahash.keys). to eq [:keysym]
|
19
17
|
|
20
|
-
expect(
|
18
|
+
expect(a).to eq v
|
21
19
|
end
|
22
20
|
end
|
23
21
|
|
24
22
|
describe "hash get" do
|
25
23
|
it "converts ruby value to nydp value" do
|
26
24
|
ahash[:keysym] = "avalue"
|
27
|
-
k = sym("keysym")
|
28
|
-
args = [ ahash, k ]
|
29
25
|
|
30
|
-
Nydp::Builtin::HashGet.instance.
|
26
|
+
a = Nydp::Builtin::HashGet.instance.call ahash, :keysym
|
31
27
|
|
32
|
-
expect(
|
28
|
+
expect(a).to eq "avalue"
|
33
29
|
end
|
34
30
|
|
35
31
|
it "converts ruby nil to nydp value" do
|
36
|
-
|
37
|
-
args = [ ahash, k ]
|
32
|
+
a = Nydp::Builtin::HashGet.instance.call ahash, :keysym
|
38
33
|
|
39
|
-
|
40
|
-
|
41
|
-
expect(vm.args.pop).to eq Nydp::NIL
|
34
|
+
expect(a).to eq nil
|
42
35
|
end
|
43
36
|
|
44
37
|
it "converts ruby true to nydp value" do
|
45
38
|
ahash[:keysym] = true
|
46
|
-
k = sym("keysym")
|
47
|
-
args = [ ahash, k ]
|
48
39
|
|
49
|
-
Nydp::Builtin::HashGet.instance.
|
40
|
+
a = Nydp::Builtin::HashGet.instance.call ahash, :keysym
|
50
41
|
|
51
|
-
expect(
|
42
|
+
expect(a).to eq true
|
52
43
|
end
|
53
44
|
end
|
54
45
|
|
55
46
|
describe "key?" do
|
56
47
|
it "returns t when key is present" do
|
57
48
|
ahash[:simon] = 24
|
58
|
-
k = sym("simon")
|
59
|
-
args = [ ahash, k ]
|
60
49
|
|
61
|
-
Nydp::Builtin::HashKeyPresent.instance.
|
50
|
+
a = Nydp::Builtin::HashKeyPresent.instance.call ahash, :simon
|
62
51
|
|
63
|
-
expect(
|
52
|
+
expect(a).to eq true
|
64
53
|
end
|
65
54
|
|
66
55
|
it "returns nil when key is absent" do
|
67
|
-
|
68
|
-
args = [ ahash, k ]
|
69
|
-
|
70
|
-
Nydp::Builtin::HashKeyPresent.instance.invoke vm, pair_list(args)
|
56
|
+
a = Nydp::Builtin::HashKeyPresent.instance.call ahash, :simon
|
71
57
|
|
72
|
-
expect(
|
58
|
+
expect(a).to eq nil
|
73
59
|
end
|
74
60
|
end
|
75
61
|
|
@@ -77,23 +63,22 @@ describe Nydp::Hash do
|
|
77
63
|
it "returns a list of keys" do
|
78
64
|
ahash[:k0] = 42
|
79
65
|
ahash[:k1] = 84
|
80
|
-
args = [ahash]
|
81
66
|
|
82
|
-
Nydp::Builtin::HashKeys.instance.
|
67
|
+
a = Nydp::Builtin::HashKeys.instance.call ahash
|
83
68
|
|
84
|
-
expect(
|
69
|
+
expect(a).to eq pair_list [:k0, :k1]
|
85
70
|
end
|
86
71
|
end
|
87
72
|
|
88
73
|
describe "hash-slice" do
|
89
74
|
it "returns a new hash containing only the given keys from the old hash" do
|
90
|
-
ahash[:k0] =
|
91
|
-
ahash[:k1] =
|
92
|
-
|
75
|
+
ahash[:k0] = 42
|
76
|
+
ahash[:k1] = 84
|
77
|
+
ahash[:k2] = 126
|
93
78
|
|
94
|
-
Nydp::Builtin::HashSlice.instance.
|
79
|
+
a = Nydp::Builtin::HashSlice.instance.call ahash, pair_list([:k0, :k1])
|
95
80
|
|
96
|
-
expect(
|
81
|
+
expect(a).to eq({ k0: 42, k1: 84 })
|
97
82
|
end
|
98
83
|
end
|
99
84
|
end
|