nydp 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,7 @@
1
1
  module Nydp
2
+ class InvocationFailed < StandardError
3
+ end
4
+
2
5
  class InvokeFunctionInstruction
3
6
  def initialize arg_count, source_expression
4
7
  @source_expression = source_expression
@@ -8,24 +11,22 @@ module Nydp
8
11
  def execute vm
9
12
  args = vm.pop_args @arg_count
10
13
  args.car.invoke vm, args.cdr
14
+ rescue Nydp::Error => ne
15
+ raise ne
16
+ rescue InvocationFailed => i_f
17
+ raise i_f
11
18
  rescue Exception => e
12
- puts "failed to execute fn #{args.inspect}"
13
- puts "source was #{source}"
14
- puts "function was #{args.car.inspect}"
15
- vm.error e
16
- end
17
-
18
- def inspect
19
- "#{self.class.name}:#{source}"
19
+ msg = "failed to execute invocation #{args.inspect}"
20
+ msg += "\nsource was #{source.inspect}"
21
+ msg += "\nfunction name was #{source.car.inspect}"
22
+ i_f = InvocationFailed.new "#{msg}\n#{vm.error}#{e.message}"
23
+ i_f.set_backtrace e.backtrace
24
+ raise i_f
20
25
  end
21
26
 
22
- def source
23
- @source_expression
24
- end
25
-
26
- def to_s
27
- source
28
- end
27
+ def inspect ; source.inspect ; end
28
+ def source ; @source_expression ; end
29
+ def to_s ; source.to_s ; end
29
30
  end
30
31
 
31
32
  class FunctionInvocation
@@ -44,9 +45,7 @@ module Nydp
44
45
  vm.push_instructions @argument_instructions, vm.peek_context
45
46
  end
46
47
 
47
- def inspect; "#function_invocation:#{to_s}"; end
48
- def to_s
49
- @source.to_s
50
- end
48
+ def inspect ; @source.inspect ; end
49
+ def to_s ; @source.to_s ; end
51
50
  end
52
51
  end
@@ -73,7 +73,7 @@ module Nydp
73
73
 
74
74
  def inspect; to_s; end
75
75
  def to_s
76
- "(fn #{arg_names.to_s} #{body.map { |b| b.to_s}.join(' ')})"
76
+ "(fn #{arg_names.to_s} #{body.map { |b| b.inspect}.join(' ')})"
77
77
  end
78
78
  end
79
79
  end
@@ -12,10 +12,11 @@ class Nydp::Pair
12
12
  new a, b
13
13
  end
14
14
 
15
- def caar; car.car; end
16
- def cadr; cdr.car; end
17
- def cdar; car.cdr; end
18
- def cddr; cdr.cdr; end
15
+ def nydp_type ; :pair ; end
16
+ def caar ; car.car ; end
17
+ def cadr ; cdr.car ; end
18
+ def cdar ; car.cdr ; end
19
+ def cddr ; cdr.cdr ; end
19
20
 
20
21
  def self.parse_list list
21
22
  if sym? list.slice(-2), "."
@@ -10,8 +10,7 @@ module Nydp
10
10
  Nydp::Symbol.mk name.to_sym, ns
11
11
  end
12
12
 
13
- def read_list token_stream, termination_token
14
- list = []
13
+ def read_list token_stream, termination_token, list=[]
15
14
  token = token_stream.next_token
16
15
  while token != nil && token.first != termination_token
17
16
  list << next_form(token, token_stream)
@@ -51,19 +50,19 @@ module Nydp
51
50
  Pair.from_list [sym(:unquote), parse_symbol($1)]
52
51
  else
53
52
  syms = txt.to_s.split /\./
54
- return split_sym syms, sym(:"dot-syntax") if syms.length > 1
53
+ return split_sym syms, sym("dot-syntax") if syms.length > 1
55
54
 
56
55
  syms = txt.split /::/
57
- return split_sym syms, sym(:"colon-colon-syntax") if syms.length > 1
56
+ return split_sym syms, sym("colon-colon-syntax") if syms.length > 1
58
57
 
59
58
  syms = txt.split /:/
60
- return split_sym syms, sym(:"colon-syntax") if syms.length > 1
59
+ return split_sym syms, sym("colon-syntax") if syms.length > 1
61
60
 
62
61
  syms = txt.split /->/
63
- return split_sym syms, sym(:"arrow-syntax") if syms.length > 1
62
+ return split_sym syms, sym("arrow-syntax") if syms.length > 1
64
63
 
65
64
  syms = txt.split(/=>/)
66
- return split_sym syms, sym(:"rocket-syntax") if syms.length > 1
65
+ return split_sym syms, sym("rocket-syntax") if syms.length > 1
67
66
 
68
67
  sym txt
69
68
  end
@@ -89,6 +88,8 @@ module Nydp
89
88
  string token_stream, token.last, close_delimiter_for(token.last)
90
89
  when :left_paren
91
90
  prefix_list token[1], read_list(token_stream, :right_paren)
91
+ when :left_brace
92
+ prefix_list token[1], read_list(token_stream, :right_brace, [sym("brace-list")])
92
93
  when :symbol
93
94
  parse_symbol token.last
94
95
  when :comment
@@ -105,16 +106,15 @@ module Nydp
105
106
  def string token_stream, open_delimiter, close_delimiter
106
107
  fragments = [sym(:"string-pieces")]
107
108
  string_token = token_stream.next_string_fragment(open_delimiter, close_delimiter)
108
- fragments << string_token
109
+ fragments << Nydp::StringAtom.new(string_token.string, string_token)
109
110
  while !(string_token.is_a? StringFragmentCloseToken)
110
111
  fragments << expression(token_stream)
111
112
  string_token = token_stream.next_string_fragment('', close_delimiter)
112
- fragments << string_token
113
+ fragments << Nydp::StringAtom.new(string_token.string, string_token)
113
114
  end
114
115
 
115
116
  if fragments.size == 2
116
- tok = fragments[1]
117
- return Nydp::StringAtom.new tok.string, tok
117
+ return fragments[1]
118
118
  else
119
119
  return Pair.from_list fragments
120
120
  end
@@ -0,0 +1,66 @@
1
+ module Nydp
2
+ class Runner
3
+ attr_accessor :vm, :ns
4
+
5
+ def initialize vm, ns
6
+ @vm = vm
7
+ @ns = ns
8
+ @precompile = Symbol.mk(:"pre-compile", ns)
9
+ @quote = Symbol.mk(:quote, ns)
10
+ end
11
+
12
+ def compile_and_eval expr
13
+ vm.thread Pair.new(Compiler.compile(expr, Nydp.NIL), Nydp.NIL)
14
+ end
15
+
16
+ def quote expr
17
+ Pair.from_list [@quote, expr]
18
+ end
19
+
20
+ def precompile expr
21
+ Pair.from_list [@precompile, quote(expr)]
22
+ end
23
+
24
+ def pre_compile expr
25
+ compile_and_eval(precompile(expr))
26
+ end
27
+
28
+ def evaluate expr
29
+ compile_and_eval(pre_compile(expr))
30
+ end
31
+ end
32
+
33
+ class StreamRunner < Runner
34
+ attr_accessor :stream, :parser
35
+
36
+ def initialize vm, ns, stream
37
+ super vm, ns
38
+ @stream = stream
39
+ @parser = Nydp::Parser.new(ns)
40
+ @tokens = Nydp::Tokeniser.new stream
41
+ end
42
+
43
+ def prompt *_
44
+ end
45
+
46
+ def run
47
+ res = Nydp.NIL
48
+ prompt
49
+ while !@tokens.finished
50
+ expr = parser.expression(@tokens)
51
+ unless expr.nil?
52
+ res = evaluate expr
53
+ prompt res
54
+ end
55
+ end
56
+ res
57
+ end
58
+ end
59
+
60
+ class Repl < StreamRunner
61
+ def prompt val=nil
62
+ puts val if val
63
+ print "nydp > "
64
+ end
65
+ end
66
+ end
@@ -5,12 +5,11 @@ module Nydp
5
5
  @string, @token = string, token
6
6
  end
7
7
 
8
- def to_s
9
- string
10
- end
8
+ def nydp_type ; :string ; end
9
+ def to_s ; string ; end
11
10
 
12
11
  def inspect
13
- token ? token.rep : string.inspect
12
+ string.inspect
14
13
  end
15
14
 
16
15
  def == other
@@ -20,5 +19,6 @@ module Nydp
20
19
  def + other
21
20
  StringAtom.new "#{@string}#{other}"
22
21
  end
22
+
23
23
  end
24
24
  end
@@ -10,9 +10,7 @@ module Nydp
10
10
  end
11
11
 
12
12
  def == other
13
- %i{ string rep class }.inject(true) { |bool, attr|
14
- bool && (self.send(attr) == other.send(attr))
15
- }
13
+ (self.class == other.class) && (self.string == other.string)
16
14
  end
17
15
  end
18
16
 
@@ -29,13 +29,8 @@ class Nydp::Symbol
29
29
  ns[name.to_sym]
30
30
  end
31
31
 
32
- def inspect
33
- "(sym #{name.to_s})"
34
- end
35
-
36
- def to_s
37
- name.to_s
38
- end
32
+ def inspect ; to_s ; end
33
+ def to_s ; name.to_s ; end
39
34
 
40
35
  def == other
41
36
  other.is_a?(Nydp::Symbol) && (self.name == other.name)
@@ -28,8 +28,12 @@ module Nydp
28
28
  if esc = s.scan(/\\/)
29
29
  rep << esc
30
30
  ch = s.getch
31
- string << ch
32
- rep << ch
31
+ case ch
32
+ when "n" ; string << "\n"
33
+ when "t" ; string << "\t"
34
+ else string << ch
35
+ end
36
+ rep << ch
33
37
  elsif closer = close_delimiter?(s, close_delimiter)
34
38
  rep << closer
35
39
  return StringFragmentCloseToken.new(string, rep)
@@ -62,13 +66,15 @@ module Nydp
62
66
  tok = [:embed_suffix, embed_suffix]
63
67
  elsif list_prefix = s.scan(/[^\s()]*\(/)
64
68
  tok = [:left_paren, list_prefix[0...-1]]
69
+ elsif list_prefix = s.scan(/[^\s()]*\{/)
70
+ tok = [:left_brace, list_prefix[0...-1]]
65
71
  elsif s.scan(/\)/)
66
72
  tok = [:right_paren]
67
73
  elsif number = s.scan(/[-+]?[0-9]*\.[0-9]+([eE][-+]?[0-9]+)?/)
68
74
  tok = [:number, number.to_f]
69
75
  elsif integer = s.scan(/[-+]?[0-9]+/)
70
76
  tok = [:number, integer.to_i]
71
- elsif atom = s.scan(/[^\s()]+/)
77
+ elsif atom = s.scan(/[^\s()"{}]+/)
72
78
  tok = [:symbol, atom]
73
79
  else
74
80
  s.getch
@@ -3,22 +3,21 @@ module Nydp
3
3
  def to_s ; 't' ; end
4
4
  def inspect ; 't[nydp::Truth]' ; end
5
5
  def assign *_ ; self ; end
6
+ def nydp_type ; :truth ; end
6
7
  end
7
8
 
8
9
  class Nil
9
10
  def car ; self ; end
10
11
  def cdr ; self ; end
11
12
  def size ; 0 ; end
12
- def is? other ; other == self ; end
13
- def isnt? other ; other != self ; end
14
- def to_s ; "nil" ; end
13
+ def is? other ; (self.equal? other) ; end
14
+ def isnt? other ; !is?(other) ; end
15
+ def to_s ; "" ; end
15
16
  def + other ; other ; end
16
17
  def copy ; self ; end
17
18
  def assign *_ ; self ; end
18
-
19
- def inspect
20
- "nil[Nydp::Nil]"
21
- end
19
+ def inspect ; "nil" ; end
20
+ def nydp_type ; :nil ; end
22
21
 
23
22
  def execute vm
24
23
  vm.push_arg self
@@ -32,6 +31,9 @@ module Nydp
32
31
  @@nil = Nil.new
33
32
  @@t = Truth.new
34
33
 
34
+ class Nil
35
+ def self.new ; raise "no" ; end
36
+ end
35
37
  def self.NIL; @@nil; end
36
38
  def self.T; @@t; end
37
39
  end
@@ -1,3 +1,3 @@
1
1
  module Nydp
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -41,36 +41,29 @@ module Nydp
41
41
  end
42
42
  end
43
43
 
44
- def error e
45
- puts " error"
46
- puts e
47
- puts "================="
48
- puts
49
- puts "instruction stack"
50
- puts "================="
44
+ def error
45
+ msg = ""
46
+ msg << "\n"
47
+ msg << "\ninstruction stack"
48
+ msg << "\n================="
51
49
  instructions.each_with_index do |ii, ix|
52
- puts "instructions##{ix} : #{ii} #{ii.source if ii.respond_to?(:source)}"
50
+ msg << "\ninstructions##{ix} : #{ii} #{ii.source if ii.respond_to?(:source)}"
53
51
  end
54
- puts
55
- puts
56
- puts "context stack"
57
- puts "================="
52
+ msg << "\n"
53
+ msg << "\n"
54
+ msg << "\ncontext stack"
55
+ msg << "\n================="
58
56
  contexts.each_with_index do |ctx, ix|
59
- puts "context##{ix} : #{ctx}"
57
+ msg << "\ncontext##{ix} : #{ctx}"
60
58
  end
61
- puts
62
- puts
63
- puts "ruby backtrace"
64
- puts "================="
65
- (e.backtrace || []).each_with_index do |ctx, ix|
66
- puts "#{ctx}"
67
- end
68
- puts
69
- puts
59
+ msg << "\n"
60
+ msg << "\n"
70
61
 
71
62
  instructions = []
72
63
  contexts = []
73
64
  args = [Nydp.NIL]
65
+
66
+ msg
74
67
  end
75
68
  end
76
69
  end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Nydp do
4
- let(:ns) { { } }
5
4
  let(:vm) { Nydp::VM.new }
6
5
 
7
6
  before {
@@ -10,10 +9,6 @@ describe Nydp do
10
9
  Nydp::StreamRunner.new(vm, ns, File.new(boot_path)).run
11
10
  }
12
11
 
13
- def sym name
14
- Nydp::Symbol.mk name.to_sym, ns
15
- end
16
-
17
12
  def list *things
18
13
  Nydp::Pair.from_list things.map { |thing|
19
14
  case thing
@@ -102,7 +97,7 @@ describe Nydp do
102
97
  describe :or do
103
98
  it "should produce some nested conds" do
104
99
  result = run "(reset-uniq-counter) (pre-compile '(or a b c))"
105
- expect(result.to_s).to eq "((fn (ora-3) (cond ora-3 ora-3 ((fn (ora-4) (cond ora-4 ora-4 ((fn (ora-5) (cond ora-5 ora-5)) c))) b))) a)"
100
+ expect(result).to eq parse "((fn (ora-1) (cond ora-1 ora-1 ((fn (ora-2) (cond ora-2 ora-2 ((fn (ora-3) (cond ora-3 ora-3 nil)) c))) b))) a)"
106
101
  end
107
102
  end
108
103
 
@@ -1,8 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Nydp::Parser do
4
-
5
- let(:ns) { { } }
6
4
  let(:aa) { Nydp::Symbol.mk :aa, ns }
7
5
  let(:a) { Nydp::Symbol.mk :a, ns }
8
6
  let(:b) { Nydp::Symbol.mk :b, ns }
@@ -21,18 +19,10 @@ describe Nydp::Parser do
21
19
  let(:cocosyn) { Nydp::Symbol.mk :"colon-colon-syntax", ns }
22
20
  let(:colosyn) { Nydp::Symbol.mk :"colon-syntax", ns }
23
21
 
24
- def sym name
25
- Nydp::Symbol.mk name.to_sym, ns
26
- end
27
-
28
22
  def parse_string txt, open_delim, close_delim
29
23
  Nydp::Parser.new(ns).string(Nydp::Tokeniser.new(txt), open_delim, close_delim)
30
24
  end
31
25
 
32
- def pair_list xs, last=Nydp.NIL
33
- Nydp::Pair.from_list xs, last
34
- end
35
-
36
26
  it "should parse empty string" do
37
27
  expected = pair_list([sym('string-pieces'), Nydp::StringFragmentCloseToken.new('','$%')])
38
28
  actual = parse_string "%", '$', /%/
@@ -42,21 +32,23 @@ describe Nydp::Parser do
42
32
  it "should parse external text" do
43
33
  actual = parse_string "a fluffy bunny!", 'EAT ', /!/
44
34
  expect(actual) .to eq "a fluffy bunny"
45
- expect(actual.inspect).to eq "EAT a fluffy bunny!"
35
+ expect(actual.inspect).to eq '"a fluffy bunny"'
46
36
  end
47
37
 
48
38
  it "should parse a string delimited by eof" do
49
39
  expected = pair_list([sym('string-pieces'), Nydp::StringFragmentCloseToken.new('a fluffy bunny!','a fluffy bunny!')])
50
40
  actual = parse_string "a fluffy bunny!", '', :eof
51
41
  expect(actual) .to eq "a fluffy bunny!"
52
- expect(actual.inspect).to eq "a fluffy bunny!"
42
+ expect(actual.inspect).to eq '"a fluffy bunny!"'
53
43
  end
54
44
 
55
45
  it "should parse a string with embedded code, delimited by eof" do
56
46
  x1 = sym('string-pieces')
57
47
  x2 = Nydp::StringFragmentToken.new('a fluffy bunny! ',':a fluffy bunny! %%')
48
+ x2 = Nydp::StringAtom.new(x2.string, x2)
58
49
  x3 = sym('expr')
59
50
  x4 = Nydp::StringFragmentCloseToken.new(' a purple cow!',' a purple cow!')
51
+ x4 = Nydp::StringAtom.new(x4.string, x4)
60
52
 
61
53
  expected = pair_list([x1,x2,x3,x4])
62
54
  actual = parse_string "a fluffy bunny! %%expr a purple cow!", ':', :eof
@@ -71,8 +63,10 @@ describe Nydp::Parser do
71
63
 
72
64
  x1 = sym('string-pieces')
73
65
  x2 = Nydp::StringFragmentToken.new('a fluffy bunny! ','------->a fluffy bunny! %%')
66
+ x2 = Nydp::StringAtom.new(x2.string, x2)
74
67
  x3 = pair_list [n1, n2, n3, n4]
75
68
  x4 = Nydp::StringFragmentCloseToken.new(' a purple cow!',' a purple cow!')
69
+ x4 = Nydp::StringAtom.new(x4.string, x4)
76
70
 
77
71
  expected = pair_list([x1,x2,x3,x4])
78
72
  actual = parse_string "a fluffy bunny! %%(foo bar \"an embedded bunny :)\" zop) a purple cow!", '------->', :eof
@@ -85,8 +79,10 @@ describe Nydp::Parser do
85
79
 
86
80
  s1 = sym('string-pieces')
87
81
  s2 = Nydp::StringFragmentToken.new('a rather ','"a rather %%')
82
+ s2 = Nydp::StringAtom.new(s2.string, s2)
88
83
  s3 = pair_list [e1, e2]
89
84
  s4 = Nydp::StringFragmentCloseToken.new(' bunny :)',' bunny :)"')
85
+ s4 = Nydp::StringAtom.new(s4.string, s4)
90
86
 
91
87
  n1 = sym(:foo)
92
88
  n2 = sym(:bar)
@@ -95,8 +91,10 @@ describe Nydp::Parser do
95
91
 
96
92
  x1 = sym('string-pieces')
97
93
  x2 = Nydp::StringFragmentToken.new('a fluffy bunny! ','------->a fluffy bunny! %%')
94
+ x2 = Nydp::StringAtom.new(x2.string, x2)
98
95
  x3 = pair_list [n1, n2, n3, n4]
99
96
  x4 = Nydp::StringFragmentCloseToken.new(' a purple cow!',' a purple cow!')
97
+ x4 = Nydp::StringAtom.new(x4.string, x4)
100
98
 
101
99
  expected = pair_list([x1,x2,x3,x4])
102
100
  actual = parse_string "a fluffy bunny! %%(foo bar \"a rather %%(describe bunny) bunny :)\" zop) a purple cow!", '------->', :eof