nydp 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitattributes +1 -0
- data/README.md +228 -14
- data/lib/lisp/bm.nydp +18 -0
- data/lib/lisp/boot.nydp +69 -10
- data/lib/lisp/tests/boot-tests.nydp +65 -1
- data/lib/lisp/tests/error-tests.nydp +22 -0
- data/lib/lisp/tests/foundation-test.nydp +14 -22
- data/lib/lisp/tests/parser-tests.nydp +55 -0
- data/lib/nydp.rb +22 -12
- data/lib/nydp/assignment.rb +3 -1
- data/lib/nydp/builtin.rb +2 -5
- data/lib/nydp/builtin/ensuring.rb +3 -0
- data/lib/nydp/builtin/eval.rb +5 -1
- data/lib/nydp/builtin/handle_error.rb +39 -0
- data/lib/nydp/builtin/parse_in_string.rb +11 -0
- data/lib/nydp/builtin/sqrt.rb +5 -0
- data/lib/nydp/context_symbol.rb +38 -6
- data/lib/nydp/core.rb +9 -6
- data/lib/nydp/error.rb +4 -0
- data/lib/nydp/function_invocation.rb +1 -1
- data/lib/nydp/lexical_context.rb +13 -3
- data/lib/nydp/parser.rb +19 -18
- data/lib/nydp/runner.rb +9 -4
- data/lib/nydp/string_atom.rb +6 -7
- data/lib/nydp/symbol_lookup.rb +2 -1
- data/lib/nydp/tokeniser.rb +7 -1
- data/lib/nydp/version.rb +1 -1
- data/lib/nydp/vm.rb +35 -12
- data/nydp.gemspec +2 -2
- data/spec/parser_spec.rb +10 -0
- metadata +11 -4
@@ -0,0 +1,22 @@
|
|
1
|
+
(register-test '(suite "Error Tests"
|
2
|
+
("'ensuring gets called on the way out"
|
3
|
+
(let x 10
|
4
|
+
(ensure (assign x (+ x 11))
|
5
|
+
(assign x (+ x 22)))
|
6
|
+
x)
|
7
|
+
43)
|
8
|
+
|
9
|
+
("'on-err handles errors"
|
10
|
+
(let x nil
|
11
|
+
(on-err (= x "impossible")
|
12
|
+
(= x (nil nil nil)))
|
13
|
+
x)
|
14
|
+
"impossible")
|
15
|
+
|
16
|
+
("'on-err handles errors but any ensuring clause gets called first"
|
17
|
+
(with (x nil y nil)
|
18
|
+
(on-err (= x 'impossible)
|
19
|
+
(ensure (assign y 'ensure-clause)
|
20
|
+
(nil nil nil)))
|
21
|
+
(list x y))
|
22
|
+
(impossible ensure-clause))))
|
@@ -1,4 +1,9 @@
|
|
1
1
|
(register-test '(suite "Foundation Tests"
|
2
|
+
(suite "maths"
|
3
|
+
("sqrt"
|
4
|
+
(sqrt 6.25)
|
5
|
+
2.5))
|
6
|
+
|
2
7
|
(suite "strings"
|
3
8
|
(suite "string-split"
|
4
9
|
("splits a string using given expression"
|
@@ -23,6 +28,15 @@
|
|
23
28
|
(type-of "foobar %%(+ 1 2)")
|
24
29
|
string)))
|
25
30
|
|
31
|
+
(suite "eq?"
|
32
|
+
("true for two empty symbols"
|
33
|
+
(eq? '|| '||)
|
34
|
+
t)
|
35
|
+
|
36
|
+
("nil for two different symbols"
|
37
|
+
(eq? 'foo 'bar)
|
38
|
+
nil))
|
39
|
+
|
26
40
|
(suite "truth and nil"
|
27
41
|
("t is boolean true"
|
28
42
|
(if t "hello" "goodbye")
|
@@ -40,14 +54,6 @@
|
|
40
54
|
(type-of nil)
|
41
55
|
nil))
|
42
56
|
|
43
|
-
(suite "Ensuring"
|
44
|
-
("gets called on the way out"
|
45
|
-
(let x 10
|
46
|
-
(ensuring (fn () (assign x (+ x 11)))
|
47
|
-
(fn () (assign x (+ x 22))))
|
48
|
-
x)
|
49
|
-
43))
|
50
|
-
|
51
57
|
(suite "assignment with '="
|
52
58
|
("assigns a symbol"
|
53
59
|
(pre-compile '(= this 'that))
|
@@ -66,20 +72,6 @@
|
|
66
72
|
(pre-compile '(= a.b.c.d 42))
|
67
73
|
(hash-set (hash-get (hash-get a 'b) 'c) 'd 42)))
|
68
74
|
|
69
|
-
|
70
|
-
(suite "parse"
|
71
|
-
("parses a colon-syntax symbol"
|
72
|
-
(parse "this:that")
|
73
|
-
((colon-syntax this that)) )
|
74
|
-
|
75
|
-
("parses a dot-syntax symbol"
|
76
|
-
(parse "this.that.zozo")
|
77
|
-
((dot-syntax this that zozo)) )
|
78
|
-
|
79
|
-
("parses an expression"
|
80
|
-
(parse "(foo bar \"hello, String\") 1 2 (3 t nil) nil")
|
81
|
-
((foo bar "hello, String") 1 2 (3 t nil))))
|
82
|
-
|
83
75
|
(suite "isa"
|
84
76
|
("t for 'pair for list"
|
85
77
|
(isa 'pair '(a b c))
|
@@ -0,0 +1,55 @@
|
|
1
|
+
(register-test '(suite "Parser tests"
|
2
|
+
(suite "brace-list"
|
3
|
+
("parses an empty brace list"
|
4
|
+
(parse "{}")
|
5
|
+
((brace-list)))
|
6
|
+
|
7
|
+
("parses a single-item list"
|
8
|
+
(parse "{foo}")
|
9
|
+
((brace-list foo)))
|
10
|
+
|
11
|
+
("parses a list"
|
12
|
+
(parse "{foo bar 1 2 3}")
|
13
|
+
((brace-list foo bar 1 2 3))))
|
14
|
+
|
15
|
+
(suite "parse"
|
16
|
+
("parses an empty symbol"
|
17
|
+
(parse "||")
|
18
|
+
(||) )
|
19
|
+
|
20
|
+
("parses a colon-syntax symbol"
|
21
|
+
(parse "this:that")
|
22
|
+
((colon-syntax this that)) )
|
23
|
+
|
24
|
+
("parses a dot-syntax symbol"
|
25
|
+
(parse "this.that.zozo")
|
26
|
+
((dot-syntax this that zozo)) )
|
27
|
+
|
28
|
+
("parses a mixed-syntax symbol"
|
29
|
+
(parse "this$that.zozo")
|
30
|
+
((dot-syntax (dollar-syntax this that) zozo)))
|
31
|
+
|
32
|
+
("parses a mixed-syntax prefix symbol"
|
33
|
+
(parse "$this.that.zozo")
|
34
|
+
((dot-syntax (dollar-syntax || this) that zozo)))
|
35
|
+
|
36
|
+
("parses a prefix dollar"
|
37
|
+
(parse "$this")
|
38
|
+
((dollar-syntax || this)))
|
39
|
+
|
40
|
+
("parses a prefix dollar-dot"
|
41
|
+
(parse "$.this")
|
42
|
+
((dot-syntax (dollar-syntax || ||) this)))
|
43
|
+
|
44
|
+
("parses an expression"
|
45
|
+
(parse "(foo bar \"hello, String\") 1 2 (3 t nil) nil")
|
46
|
+
((foo bar "hello, String") 1 2 (3 t nil))))
|
47
|
+
|
48
|
+
(suite "parse-in-string"
|
49
|
+
("parses a plain string"
|
50
|
+
(parse-in-string "hello, world, take me to your dealer")
|
51
|
+
"hello, world, take me to your dealer")
|
52
|
+
|
53
|
+
("parses a plain string with interpolations"
|
54
|
+
(parse-in-string (joinstr "" (list "hello, " '~ "(world), take me to your " '~ "dealer please")))
|
55
|
+
(string-pieces "hello, " (world) ", take me to your " dealer " please")))))
|
data/lib/nydp.rb
CHANGED
@@ -7,33 +7,43 @@ module Nydp
|
|
7
7
|
def self.loadfiles; PLUGINS.map(&:loadfiles).flatten ; end
|
8
8
|
def self.testfiles; PLUGINS.map(&:testfiles).flatten ; end
|
9
9
|
def self.plugin_names ; PLUGINS.map(&:name) ; end
|
10
|
-
def self.loadall
|
10
|
+
def self.loadall ns, files
|
11
|
+
vm = VM.new
|
11
12
|
files.each { |f|
|
12
13
|
reader = Nydp::StreamReader.new(File.new(f))
|
13
14
|
Nydp::Runner.new(vm, ns, reader).run
|
14
15
|
}
|
15
16
|
end
|
16
17
|
|
17
|
-
def self.
|
18
|
-
puts "welcome to nydp"
|
18
|
+
def self.build_nydp extra_files=nil
|
19
19
|
ns = { }
|
20
20
|
setup(ns)
|
21
|
-
|
22
|
-
loadall
|
21
|
+
loadall ns, loadfiles
|
22
|
+
loadall ns, extra_files if extra_files
|
23
|
+
ns
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.apply_function ns, function_name, *args
|
27
|
+
function = Nydp::Symbol.mk(function_name, ns).value
|
28
|
+
args = Nydp::Pair.from_list args
|
29
|
+
vm = VM.new
|
30
|
+
|
31
|
+
function.invoke vm, args
|
32
|
+
return vm.pop_arg
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.repl
|
36
|
+
puts "welcome to nydp"
|
37
|
+
puts "^D to exit"
|
23
38
|
reader = Nydp::ReadlineReader.new $stdin, "nydp > "
|
24
|
-
Nydp::Runner.new(
|
39
|
+
Nydp::Runner.new(VM.new, build_nydp, reader, $stdout).run
|
25
40
|
end
|
26
41
|
|
27
42
|
def self.tests *options
|
28
43
|
verbose = options.include?(:verbose) ? "t" : "nil"
|
29
44
|
puts "welcome to nydp : running tests"
|
30
|
-
ns = { }
|
31
|
-
setup(ns)
|
32
|
-
vm = VM.new
|
33
|
-
loadall vm, ns, loadfiles
|
34
|
-
loadall vm, ns, testfiles
|
35
45
|
reader = Nydp::StringReader.new "(run-all-tests #{verbose})"
|
36
|
-
Nydp::Runner.new(
|
46
|
+
Nydp::Runner.new(VM.new, build_nydp(testfiles), reader).run
|
37
47
|
end
|
38
48
|
|
39
49
|
end
|
data/lib/nydp/assignment.rb
CHANGED
@@ -30,9 +30,11 @@ module Nydp
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def to_s
|
33
|
-
"#assignment #{@instructions.cdr.car} #{@value_src}"
|
33
|
+
"#assignment #{@instructions.cdr.car} #{@value_src.inspect}"
|
34
34
|
end
|
35
35
|
|
36
|
+
def inspect; to_s ; end
|
37
|
+
|
36
38
|
def execute vm
|
37
39
|
vm.push_instructions @instructions, vm.peek_context
|
38
40
|
end
|
data/lib/nydp/builtin.rb
CHANGED
@@ -1,15 +1,12 @@
|
|
1
1
|
require 'nydp'
|
2
|
+
require 'nydp/error'
|
2
3
|
|
3
4
|
module Nydp::Builtin
|
4
5
|
module Base
|
5
|
-
def indent_text txt
|
6
|
-
txt.split(/\n/).map { |line| " #{line}"}.join("\n")
|
7
|
-
end
|
8
|
-
|
9
6
|
def invoke vm, args
|
10
7
|
builtin_invoke vm, args
|
11
8
|
rescue Exception => e
|
12
|
-
new_msg = "Invoking #{self.class.name}\nwith args #{args}\nraised\n#{indent_text e.message}"
|
9
|
+
new_msg = "Invoking #{self.class.name}\nwith args #{args}\nraised\n#{Nydp.indent_text e.message}"
|
13
10
|
raise $!, new_msg, $!.backtrace
|
14
11
|
end
|
15
12
|
end
|
data/lib/nydp/builtin/eval.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
require "nydp/vm"
|
2
|
+
|
3
|
+
class Nydp::Builtin::HandleError
|
4
|
+
include Nydp::Helper
|
5
|
+
|
6
|
+
class CatchError
|
7
|
+
include Nydp::Helper, Nydp::VM::HandleError
|
8
|
+
|
9
|
+
attr_reader :handler, :vm_arg_array_size
|
10
|
+
|
11
|
+
def initialize handler, vm_arg_array_size
|
12
|
+
@handler, @vm_arg_array_size = handler, vm_arg_array_size
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute vm
|
16
|
+
e = vm.unhandled_error
|
17
|
+
vm.unhandled_error = nil
|
18
|
+
return unless e
|
19
|
+
|
20
|
+
vm.args = vm.args[0...vm_arg_array_size]
|
21
|
+
|
22
|
+
handler.invoke vm, cons(r2n e.message, nil)
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
"(on-err: #{handler})"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def invoke vm, args
|
31
|
+
fn_handle = args.car
|
32
|
+
fn_tricky = args.cdr.car
|
33
|
+
|
34
|
+
catcher_instructions = Nydp::Pair.from_list [CatchError.new(fn_handle, vm.args.size)]
|
35
|
+
vm.push_instructions catcher_instructions, vm.peek_context
|
36
|
+
|
37
|
+
fn_tricky.invoke vm, Nydp.NIL
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Nydp::Builtin::ParseInString
|
2
|
+
def initialize ns
|
3
|
+
@parser = Nydp::Parser.new(ns)
|
4
|
+
end
|
5
|
+
|
6
|
+
def invoke vm, args
|
7
|
+
tokens = Nydp::Tokeniser.new Nydp::StringReader.new args.car.to_s
|
8
|
+
expr = @parser.string(tokens, "", :eof)
|
9
|
+
vm.push_arg expr
|
10
|
+
end
|
11
|
+
end
|
data/lib/nydp/context_symbol.rb
CHANGED
@@ -1,22 +1,54 @@
|
|
1
1
|
module Nydp
|
2
|
+
class ContextLookup0 ; def self.get_context ctx; ctx; end; end
|
3
|
+
class ContextLookup1 ; def self.get_context ctx; ctx.parent; end; end
|
4
|
+
class ContextLookup2 ; def self.get_context ctx; ctx.parent.parent; end; end
|
5
|
+
class ContextLookup3 ; def self.get_context ctx; ctx.parent.parent.parent; end; end
|
6
|
+
class ContextLookup4 ; def self.get_context ctx; ctx.parent.parent.parent.parent; end; end
|
7
|
+
class ContextLookup5 ; def self.get_context ctx; ctx.parent.parent.parent.parent.parent; end; end
|
8
|
+
class ContextLookup6 ; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent; end; end
|
9
|
+
class ContextLookup7 ; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent; end; end
|
10
|
+
class ContextLookup8 ; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent.parent; end; end
|
11
|
+
class ContextLookup9 ; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent.parent.parent; end; end
|
12
|
+
class ContextLookup10; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent; end; end
|
13
|
+
class ContextLookup11; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent; end; end
|
14
|
+
class ContextLookup12; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent; end; end
|
15
|
+
class ContextLookup13; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent; end; end
|
16
|
+
class ContextLookup14; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent; end; end
|
17
|
+
class ContextLookup15; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent; end; end
|
18
|
+
class ContextLookup16; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent; end; end
|
19
|
+
class ContextLookup17; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent; end; end
|
20
|
+
class ContextLookup18; def self.get_context ctx; ctx.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent.parent; end; end
|
21
|
+
class ContextLookupN
|
22
|
+
def initialize depth ; @depth = depth ; end
|
23
|
+
def get_context ctx ; ctx.nth(@depth) ; end
|
24
|
+
end
|
25
|
+
|
2
26
|
class ContextSymbol
|
3
|
-
attr_accessor :depth, :name
|
27
|
+
attr_accessor :depth, :name, :binding_index
|
4
28
|
|
5
|
-
def initialize depth, name
|
6
|
-
@
|
29
|
+
def initialize depth, name, binding_index
|
30
|
+
@ctx_lookup = build_lookup depth
|
31
|
+
@depth, @name, @binding_index = depth, name, binding_index
|
7
32
|
end
|
8
33
|
|
34
|
+
def get_context(context); @ctx_lookup.get_context context; end
|
35
|
+
|
9
36
|
def value context
|
10
|
-
context
|
37
|
+
get_context(context).at_index(binding_index)
|
11
38
|
end
|
12
39
|
|
13
40
|
def assign value, context
|
14
|
-
context
|
41
|
+
get_context(context).set_index(binding_index, value)
|
15
42
|
end
|
16
43
|
|
17
44
|
def inspect; to_s; end
|
18
45
|
def to_s
|
19
|
-
"[#{depth}]#{name}"
|
46
|
+
"[#{depth}##{binding_index}]#{name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def build_lookup depth
|
50
|
+
fast = Nydp.const_get "ContextLookup#{depth}" rescue nil
|
51
|
+
return fast || ContextLookupN.new(depth)
|
20
52
|
end
|
21
53
|
end
|
22
54
|
end
|
data/lib/nydp/core.rb
CHANGED
@@ -41,6 +41,7 @@ module Nydp
|
|
41
41
|
Symbol.mk(:p, ns).assign(Nydp::Builtin::Puts.new)
|
42
42
|
Symbol.mk(:PI, ns).assign Literal.new(3.1415)
|
43
43
|
Symbol.mk(:nil, ns).assign Nydp.NIL
|
44
|
+
Symbol.mk(:sqrt, ns).assign Nydp::Builtin::Sqrt.new
|
44
45
|
Symbol.mk(:t, ns).assign Nydp.T
|
45
46
|
Symbol.mk(:sym, ns).assign Nydp::Builtin::ToSym.new(ns)
|
46
47
|
Symbol.mk(:ensuring, ns).assign(Nydp::Builtin::Ensuring.new)
|
@@ -48,12 +49,14 @@ module Nydp
|
|
48
49
|
Symbol.mk(:comment, ns).assign(Nydp::Builtin::Comment.new)
|
49
50
|
Symbol.mk(:millisecs, ns).assign(Nydp::Builtin::Millisecs.new)
|
50
51
|
Symbol.mk("load-tests", ns).assign(Nydp::Builtin::LoadTests.new(ns))
|
51
|
-
Symbol.mk("
|
52
|
-
Symbol.mk("
|
53
|
-
Symbol.mk("string
|
54
|
-
Symbol.mk("string
|
55
|
-
Symbol.mk("string-
|
56
|
-
Symbol.mk("
|
52
|
+
Symbol.mk("handle-error" , ns).assign(Nydp::Builtin::HandleError.new)
|
53
|
+
Symbol.mk("parse-in-string", ns).assign(Nydp::Builtin::ParseInString.new(ns))
|
54
|
+
Symbol.mk("random-string" , ns).assign(Nydp::Builtin::RandomString.new)
|
55
|
+
Symbol.mk("to-string" , ns).assign(Nydp::Builtin::ToString.new)
|
56
|
+
Symbol.mk("string-pieces" , ns).assign(Nydp::Builtin::StringPieces.new)
|
57
|
+
Symbol.mk("string-replace" , ns).assign(Nydp::Builtin::StringReplace.new)
|
58
|
+
Symbol.mk("string-split" , ns).assign(Nydp::Builtin::StringSplit.new )
|
59
|
+
Symbol.mk("thread-locals" , ns).assign(Nydp::Builtin::ThreadLocals.new)
|
57
60
|
Symbol.mk("type-of", ns).assign(Nydp::Builtin::TypeOf.new(ns))
|
58
61
|
Symbol.mk(:"eq?", ns).assign(Nydp::Builtin::IsEqual.new)
|
59
62
|
Symbol.mk(:"pair?", ns).assign(Nydp::Builtin::IsPair.new)
|
data/lib/nydp/error.rb
CHANGED
@@ -19,7 +19,7 @@ module Nydp
|
|
19
19
|
msg = "failed to execute invocation #{args.inspect}"
|
20
20
|
msg += "\nsource was #{source.inspect}"
|
21
21
|
msg += "\nfunction name was #{source.car.inspect}"
|
22
|
-
i_f = InvocationFailed.new "#{msg}\n#{
|
22
|
+
i_f = InvocationFailed.new "#{msg}\n#{e.message}"
|
23
23
|
i_f.set_backtrace e.backtrace
|
24
24
|
raise i_f
|
25
25
|
end
|
data/lib/nydp/lexical_context.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
class Nydp::LexicalContext
|
2
|
-
attr_reader :values, :parent
|
2
|
+
attr_reader :names, :values, :parent
|
3
3
|
|
4
4
|
def initialize parent
|
5
5
|
@parent = parent
|
6
|
-
@
|
6
|
+
@names = []
|
7
|
+
@values = []
|
7
8
|
end
|
8
9
|
|
9
10
|
def nth n
|
@@ -21,8 +22,17 @@ class Nydp::LexicalContext
|
|
21
22
|
values[name]
|
22
23
|
end
|
23
24
|
|
25
|
+
def at_index index
|
26
|
+
values[index]
|
27
|
+
end
|
28
|
+
|
24
29
|
def set name, value
|
25
|
-
|
30
|
+
names << name
|
31
|
+
values << value
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_index index, value
|
35
|
+
values[index] = value
|
26
36
|
end
|
27
37
|
|
28
38
|
def to_s_with_indent str
|