ajlisp 0.0.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.
- data/LICENSE +23 -0
- data/README.md +33 -0
- data/ajlisp.gemspec +20 -0
- data/lib/ajlisp.rb +128 -0
- data/lib/ajlisp/at_constant_atom.rb +30 -0
- data/lib/ajlisp/context.rb +27 -0
- data/lib/ajlisp/dot_verb_atom.rb +31 -0
- data/lib/ajlisp/file_source.rb +10 -0
- data/lib/ajlisp/fprimitive.rb +23 -0
- data/lib/ajlisp/fprimitive_closure.rb +48 -0
- data/lib/ajlisp/fprimitive_define.rb +30 -0
- data/lib/ajlisp/fprimitive_definef.rb +30 -0
- data/lib/ajlisp/fprimitive_definem.rb +30 -0
- data/lib/ajlisp/fprimitive_do.rb +25 -0
- data/lib/ajlisp/fprimitive_flambda.rb +21 -0
- data/lib/ajlisp/fprimitive_if.rb +34 -0
- data/lib/ajlisp/fprimitive_lambda.rb +21 -0
- data/lib/ajlisp/fprimitive_let.rb +38 -0
- data/lib/ajlisp/fprimitive_macro_closure.rb +13 -0
- data/lib/ajlisp/fprimitive_mlambda.rb +21 -0
- data/lib/ajlisp/fprimitive_quote.rb +19 -0
- data/lib/ajlisp/input_source.rb +37 -0
- data/lib/ajlisp/lexer.rb +132 -0
- data/lib/ajlisp/list.rb +106 -0
- data/lib/ajlisp/named_atom.rb +34 -0
- data/lib/ajlisp/nil_atom.rb +39 -0
- data/lib/ajlisp/parser.rb +80 -0
- data/lib/ajlisp/primitive.rb +19 -0
- data/lib/ajlisp/primitive_add.rb +29 -0
- data/lib/ajlisp/primitive_closure.rb +49 -0
- data/lib/ajlisp/primitive_comparisons.rb +84 -0
- data/lib/ajlisp/primitive_cons.rb +19 -0
- data/lib/ajlisp/primitive_divide.rb +25 -0
- data/lib/ajlisp/primitive_eval.rb +19 -0
- data/lib/ajlisp/primitive_first.rb +19 -0
- data/lib/ajlisp/primitive_list.rb +19 -0
- data/lib/ajlisp/primitive_load.rb +34 -0
- data/lib/ajlisp/primitive_multiply.rb +25 -0
- data/lib/ajlisp/primitive_predicates.rb +58 -0
- data/lib/ajlisp/primitive_rest.rb +19 -0
- data/lib/ajlisp/primitive_subtract.rb +25 -0
- data/lib/ajlisp/string_source.rb +28 -0
- data/lib/ajlisp/token.rb +23 -0
- data/lib/core.lsp +40 -0
- data/test/and.lsp +1 -0
- data/test/append.lsp +1 -0
- data/test/backquote.lsp +7 -0
- data/test/cond.lsp +1 -0
- data/test/define123.lsp +4 -0
- data/test/definem.lsp +1 -0
- data/test/dodefine123.lsp +5 -0
- data/test/mapcond.lsp +13 -0
- data/test/mapfirst.lsp +10 -0
- data/test/mycons.lsp +3 -0
- data/test/test.rb +42 -0
- data/test/test_at_constant_atom.rb +34 -0
- data/test/test_context.rb +37 -0
- data/test/test_dot_verb_atom.rb +29 -0
- data/test/test_evaluate.rb +289 -0
- data/test/test_evaluate_files.rb +136 -0
- data/test/test_file_source.rb +11 -0
- data/test/test_fprimitive_closure.rb +29 -0
- data/test/test_fprimitive_define.rb +65 -0
- data/test/test_fprimitive_definef.rb +20 -0
- data/test/test_fprimitive_definem.rb +20 -0
- data/test/test_fprimitive_do.rb +18 -0
- data/test/test_fprimitive_flambda.rb +15 -0
- data/test/test_fprimitive_if.rb +29 -0
- data/test/test_fprimitive_lambda.rb +15 -0
- data/test/test_fprimitive_let.rb +18 -0
- data/test/test_fprimitive_macro_closure.rb +17 -0
- data/test/test_fprimitive_mlambda.rb +12 -0
- data/test/test_fprimitive_quote.rb +35 -0
- data/test/test_lexer.rb +208 -0
- data/test/test_list.rb +102 -0
- data/test/test_load.rb +74 -0
- data/test/test_named_atom.rb +33 -0
- data/test/test_parser.rb +252 -0
- data/test/test_primitive_add.rb +26 -0
- data/test/test_primitive_closure.rb +29 -0
- data/test/test_primitive_cons.rb +39 -0
- data/test/test_primitive_eval.rb +13 -0
- data/test/test_primitive_first.rb +25 -0
- data/test/test_primitive_list.rb +27 -0
- data/test/test_primitive_rest.rb +29 -0
- data/test/test_string_source.rb +10 -0
- data/test/test_token.rb +14 -0
- metadata +131 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module AjLisp
|
3
|
+
|
4
|
+
class FPrimitiveDefinem < FPrimitive
|
5
|
+
private_class_method :new
|
6
|
+
|
7
|
+
@@instance = nil
|
8
|
+
|
9
|
+
def self.instance
|
10
|
+
@@instance = new unless @@instance
|
11
|
+
return @@instance
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(context, args)
|
15
|
+
atom = args[0]
|
16
|
+
|
17
|
+
if args.length > 2
|
18
|
+
args.shift
|
19
|
+
arguments = args.shift
|
20
|
+
value = AjLisp::FPrimitiveMacroClosure.new arguments, args
|
21
|
+
else
|
22
|
+
value = AjLisp::evaluate(context, args[1])
|
23
|
+
end
|
24
|
+
|
25
|
+
AjLisp::context.setValue atom.name, value
|
26
|
+
return value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
module AjLisp
|
3
|
+
|
4
|
+
class FPrimitiveDo < FPrimitive
|
5
|
+
private_class_method :new
|
6
|
+
|
7
|
+
@@instance = nil
|
8
|
+
|
9
|
+
def self.instance
|
10
|
+
@@instance = new unless @@instance
|
11
|
+
return @@instance
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(context, args)
|
15
|
+
result = nil
|
16
|
+
|
17
|
+
args.each do |arg|
|
18
|
+
result = AjLisp::evaluate context, arg
|
19
|
+
end
|
20
|
+
|
21
|
+
return result
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
module AjLisp
|
3
|
+
|
4
|
+
class FPrimitiveFLambda < FPrimitive
|
5
|
+
private_class_method :new
|
6
|
+
|
7
|
+
@@instance = nil
|
8
|
+
|
9
|
+
def self.instance
|
10
|
+
@@instance = new unless @@instance
|
11
|
+
return @@instance
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(context, args)
|
15
|
+
arguments = args[0]
|
16
|
+
args.shift
|
17
|
+
return FPrimitiveClosure.new arguments, args, context
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
module AjLisp
|
3
|
+
|
4
|
+
class FPrimitiveIf < FPrimitive
|
5
|
+
private_class_method :new
|
6
|
+
|
7
|
+
@@instance = nil
|
8
|
+
|
9
|
+
def self.instance
|
10
|
+
@@instance = new unless @@instance
|
11
|
+
return @@instance
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(context, args)
|
15
|
+
condition = args[0]
|
16
|
+
args.shift
|
17
|
+
thenform = args[0]
|
18
|
+
args.shift
|
19
|
+
|
20
|
+
if AjLisp::evaluate context, condition
|
21
|
+
return AjLisp::evaluate context, thenform
|
22
|
+
end
|
23
|
+
|
24
|
+
result = nil
|
25
|
+
|
26
|
+
args.each do |arg|
|
27
|
+
result = AjLisp::evaluate context, arg
|
28
|
+
end
|
29
|
+
|
30
|
+
return result
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
module AjLisp
|
3
|
+
|
4
|
+
class FPrimitiveLambda < FPrimitive
|
5
|
+
private_class_method :new
|
6
|
+
|
7
|
+
@@instance = nil
|
8
|
+
|
9
|
+
def self.instance
|
10
|
+
@@instance = new unless @@instance
|
11
|
+
return @@instance
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(context, args)
|
15
|
+
arguments = args[0]
|
16
|
+
args.shift
|
17
|
+
return PrimitiveClosure.new arguments, args, context
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
module AjLisp
|
3
|
+
|
4
|
+
class FPrimitiveLet < FPrimitive
|
5
|
+
private_class_method :new
|
6
|
+
|
7
|
+
@@instance = nil
|
8
|
+
|
9
|
+
def self.instance
|
10
|
+
@@instance = new unless @@instance
|
11
|
+
return @@instance
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(context, args)
|
15
|
+
arguments = args[0]
|
16
|
+
args.shift
|
17
|
+
|
18
|
+
newcontext = AjLisp::Context.new context
|
19
|
+
|
20
|
+
while arguments
|
21
|
+
pair = arguments.first
|
22
|
+
atom = pair.first
|
23
|
+
value = AjLisp::evaluate(context, pair.rest.first)
|
24
|
+
newcontext.setValue atom.name, value
|
25
|
+
arguments = arguments.rest
|
26
|
+
end
|
27
|
+
|
28
|
+
result = nil
|
29
|
+
|
30
|
+
args.each do |arg|
|
31
|
+
result = AjLisp::evaluate context, arg
|
32
|
+
end
|
33
|
+
|
34
|
+
return result
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
module AjLisp
|
3
|
+
|
4
|
+
class FPrimitiveMLambda < FPrimitive
|
5
|
+
private_class_method :new
|
6
|
+
|
7
|
+
@@instance = nil
|
8
|
+
|
9
|
+
def self.instance
|
10
|
+
@@instance = new unless @@instance
|
11
|
+
return @@instance
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(context, args)
|
15
|
+
arguments = args[0]
|
16
|
+
args.shift
|
17
|
+
return FPrimitiveMacroClosure.new arguments, args, context
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module AjLisp
|
3
|
+
|
4
|
+
class FPrimitiveQuote < FPrimitive
|
5
|
+
private_class_method :new
|
6
|
+
|
7
|
+
@@instance = nil
|
8
|
+
|
9
|
+
def self.instance
|
10
|
+
@@instance = new unless @@instance
|
11
|
+
return @@instance
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(context, args)
|
15
|
+
return args[0]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
module AjLisp
|
3
|
+
|
4
|
+
class InputSource
|
5
|
+
def initialize
|
6
|
+
@line = ""
|
7
|
+
@position = 0
|
8
|
+
@chars = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def nextChar
|
12
|
+
char = @chars.pop
|
13
|
+
|
14
|
+
if char
|
15
|
+
return char
|
16
|
+
end
|
17
|
+
|
18
|
+
while @line.length <= @position
|
19
|
+
@line = gets
|
20
|
+
@position = 0
|
21
|
+
|
22
|
+
if @line == nil
|
23
|
+
return nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
char = @line[@position]
|
28
|
+
@position += 1
|
29
|
+
return char
|
30
|
+
end
|
31
|
+
|
32
|
+
def pushChar(ch)
|
33
|
+
@chars.push ch
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
data/lib/ajlisp/lexer.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
|
2
|
+
module AjLisp
|
3
|
+
|
4
|
+
class Lexer
|
5
|
+
@@separators = "()"
|
6
|
+
|
7
|
+
def initialize(source)
|
8
|
+
@source = source
|
9
|
+
@tokens = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def nextToken
|
13
|
+
if @tokens.length > 0
|
14
|
+
return @tokens.pop
|
15
|
+
end
|
16
|
+
|
17
|
+
char = @source.nextChar
|
18
|
+
|
19
|
+
while char and char =~ /\s/
|
20
|
+
char = @source.nextChar
|
21
|
+
end
|
22
|
+
|
23
|
+
if char == nil
|
24
|
+
return nil
|
25
|
+
end
|
26
|
+
|
27
|
+
if char == ?"
|
28
|
+
return nextString
|
29
|
+
end
|
30
|
+
|
31
|
+
if @@separators.include? char
|
32
|
+
return Token.new char, TokenType::SEPARATOR
|
33
|
+
end
|
34
|
+
|
35
|
+
if char =~ /\d/
|
36
|
+
return nextInteger char
|
37
|
+
end
|
38
|
+
|
39
|
+
if char == ?. or char == ?@
|
40
|
+
return nextSpecialAtom char
|
41
|
+
end
|
42
|
+
|
43
|
+
if char =~ /\w/
|
44
|
+
return nextAtom char
|
45
|
+
end
|
46
|
+
|
47
|
+
if char == ?' or char == ?` or char == ?,
|
48
|
+
return Token.new char, TokenType::ATOM
|
49
|
+
end
|
50
|
+
|
51
|
+
return nextSpecialAtom char
|
52
|
+
end
|
53
|
+
|
54
|
+
def pushToken(token)
|
55
|
+
@tokens.push(token)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def nextString
|
61
|
+
value = ""
|
62
|
+
|
63
|
+
char = @source.nextChar
|
64
|
+
|
65
|
+
while char
|
66
|
+
if char != ?"
|
67
|
+
value += char
|
68
|
+
char = @source.nextChar
|
69
|
+
else
|
70
|
+
break
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
return Token.new value, TokenType::STRING
|
75
|
+
end
|
76
|
+
|
77
|
+
def nextAtom(firstch)
|
78
|
+
value = firstch
|
79
|
+
|
80
|
+
char = @source.nextChar
|
81
|
+
|
82
|
+
while char
|
83
|
+
if not char =~ /\s/ and not @@separators.include? char
|
84
|
+
value += char
|
85
|
+
char = @source.nextChar
|
86
|
+
else
|
87
|
+
@source.pushChar char
|
88
|
+
break
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
return Token.new value, TokenType::ATOM
|
93
|
+
end
|
94
|
+
|
95
|
+
def nextSpecialAtom(firstch)
|
96
|
+
value = firstch
|
97
|
+
|
98
|
+
char = @source.nextChar
|
99
|
+
|
100
|
+
while char
|
101
|
+
if not char =~ /\s/ and not @@separators.include? char
|
102
|
+
value += char
|
103
|
+
char = @source.nextChar
|
104
|
+
else
|
105
|
+
@source.pushChar char
|
106
|
+
break
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
return Token.new value, TokenType::ATOM
|
111
|
+
end
|
112
|
+
|
113
|
+
def nextInteger(firstch)
|
114
|
+
value = firstch
|
115
|
+
|
116
|
+
char = @source.nextChar
|
117
|
+
|
118
|
+
while char
|
119
|
+
if char =~ /\d/
|
120
|
+
value += char
|
121
|
+
char = @source.nextChar
|
122
|
+
else
|
123
|
+
@source.pushChar char
|
124
|
+
break
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
return Token.new value, TokenType::INTEGER
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
data/lib/ajlisp/list.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
|
2
|
+
module AjLisp
|
3
|
+
|
4
|
+
class List
|
5
|
+
attr_reader :first
|
6
|
+
attr_reader :rest
|
7
|
+
|
8
|
+
def initialize(first=nil, rest=nil)
|
9
|
+
@first = first
|
10
|
+
@rest = rest
|
11
|
+
end
|
12
|
+
|
13
|
+
def evaluate(context)
|
14
|
+
form = AjLisp::evaluate(context, @first)
|
15
|
+
form.evaluate(context, self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
result = "("
|
20
|
+
|
21
|
+
first = @first
|
22
|
+
|
23
|
+
result += AjLisp::to_s(first)
|
24
|
+
|
25
|
+
rest = @rest
|
26
|
+
|
27
|
+
while rest
|
28
|
+
result += " "
|
29
|
+
first = rest.first
|
30
|
+
result += AjLisp::to_s(first)
|
31
|
+
rest = rest.rest
|
32
|
+
end
|
33
|
+
|
34
|
+
result += ")"
|
35
|
+
|
36
|
+
return result
|
37
|
+
end
|
38
|
+
|
39
|
+
def isEqualTo(list)
|
40
|
+
if not list.is_a? List
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
|
44
|
+
if @first != list.first
|
45
|
+
if @first.is_a? List or @first.is_a? NamedAtom
|
46
|
+
if !@first.isEqualTo(list.first)
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
else
|
50
|
+
return false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if @rest == nil and list.rest == nil
|
55
|
+
return true
|
56
|
+
end
|
57
|
+
|
58
|
+
if @rest.is_a? List
|
59
|
+
return @rest.isEqualTo(list.rest)
|
60
|
+
end
|
61
|
+
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.make(array)
|
66
|
+
if array and array.length > 0
|
67
|
+
first = array.shift
|
68
|
+
|
69
|
+
if first.is_a? Array
|
70
|
+
first = make(first)
|
71
|
+
elsif first.is_a? Symbol
|
72
|
+
first = NamedAtom.new first
|
73
|
+
end
|
74
|
+
|
75
|
+
if array.length == 0
|
76
|
+
return List.new first, nil
|
77
|
+
end
|
78
|
+
|
79
|
+
return List.new first, make(array)
|
80
|
+
end
|
81
|
+
|
82
|
+
return nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class EmptyList < List
|
87
|
+
#private_class_method :new
|
88
|
+
|
89
|
+
@@instance = nil
|
90
|
+
|
91
|
+
def self.instance
|
92
|
+
@@instance = new unless @@instance
|
93
|
+
return @@instance
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_s
|
97
|
+
return "()"
|
98
|
+
end
|
99
|
+
|
100
|
+
def isEqualTo(list)
|
101
|
+
return list.is_a? EmptyList
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
end
|