rubymotionlisp 0.1.3

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.
@@ -0,0 +1,189 @@
1
+ module Lisp
2
+
3
+ class Parser
4
+
5
+ def initialize
6
+ end
7
+
8
+ def make_number(str)
9
+ Lisp::Number.with_value(str.to_i)
10
+ end
11
+
12
+ def make_hex_number(str)
13
+ Lisp::Number.with_value(str.gsub("#x", "0x").to_i(0))
14
+ end
15
+
16
+ def make_float(str)
17
+ Lisp::Number.with_value(str.to_f)
18
+ end
19
+
20
+ def make_string(str)
21
+ Lisp::String.with_value(str[1...-1])
22
+ end
23
+
24
+ def make_symbol(str)
25
+ Lisp::Symbol.named(str)
26
+ end
27
+
28
+ def make_character(ch)
29
+ Lisp::Character.with_value(ch)
30
+ end
31
+
32
+ def parse_cons_cell(tokens)
33
+ tok, lit = tokens.next_token
34
+ if tok == :RPAREN
35
+ tokens.consume_token
36
+ return nil
37
+ end
38
+
39
+ car = nil
40
+ cdr = nil
41
+ cells = []
42
+ while tok != :RPAREN
43
+ if tok == :PERIOD
44
+ tokens.consume_token
45
+ cdr = self.parse_sexpr(tokens)
46
+ return nil if tokens.next_token[0] == :EOF
47
+ tok, lit = tokens.next_token
48
+ raise "Expected ')' on line #{tokens.line_number}" if tok != :RPAREN
49
+ tokens.consume_token
50
+ return Lisp::ConsCell.array_to_list(cells, cdr)
51
+ else
52
+ car = self.parse_sexpr(tokens)
53
+ raise "Unexpected EOF (expected closing parenthesis) on line #{tokens.line_number}" if tokens.next_token[0] == :EOF
54
+ cells << car
55
+ end
56
+ tok, lit = tokens.next_token
57
+ end
58
+
59
+ tokens.consume_token
60
+ return Lisp::ConsCell.array_to_list(cells)
61
+ end
62
+
63
+ def parse_map(tokens)
64
+ m = {}
65
+ tok, lit = tokens.next_token
66
+ if tok == :RBRACE
67
+ tokens.consume_token
68
+ return ConsCell.cons(Symbol.named("make-frame"), nil)
69
+ end
70
+
71
+ cells = []
72
+ while tok != :RBRACE
73
+ item = self.parse_sexpr(tokens)
74
+ raise "Unexpected EOF (expected closing brace) on line #{tokens.line_number}" if tokens.next_token[0] == :EOF
75
+ cells << item
76
+ tok, lit = tokens.next_token
77
+ end
78
+
79
+ tokens.consume_token
80
+ return ConsCell.cons(Symbol.named("make-frame"), ConsCell.array_to_list(cells))
81
+ end
82
+
83
+
84
+ def parse_vector(tokens)
85
+ v = []
86
+ tok, lit = tokens.next_token
87
+ if tok == :RBRACKET
88
+ tokens.consume_token
89
+ return ConsCell.cons(Symbol.named("make-vector"), nil)
90
+ end
91
+
92
+ cells = []
93
+ while tok != :RBRACKET
94
+ item = self.parse_sexpr(tokens)
95
+ raise "Unexpected EOF (expected closing bracket) on line #{tokens.line_number}" if tokens.next_token[0] == :EOF
96
+ cells << item
97
+ tok, lit = tokens.next_token
98
+ end
99
+
100
+ tokens.consume_token
101
+ return ConsCell.cons(Symbol.named("make-vector"), ConsCell.array_to_list(cells))
102
+ end
103
+
104
+
105
+ def parse_sexpr(tokens)
106
+ while true
107
+ tok, lit = tokens.next_token
108
+ #puts "token: <#{tok}, #{lit}>"
109
+ return nil if tok == :EOF
110
+ tokens.consume_token
111
+ case tok
112
+ when :COMMENT
113
+ next
114
+ when :NUMBER
115
+ return make_number(lit)
116
+ when :FLOAT
117
+ return make_float(lit)
118
+ when :HEXNUMBER
119
+ return make_hex_number(lit)
120
+ when :STRING
121
+ return make_string(lit)
122
+ when :CHARACTER
123
+ return make_character(lit)
124
+ when :LPAREN
125
+ return parse_cons_cell(tokens)
126
+ when :LBRACE
127
+ return parse_map(tokens)
128
+ when :LBRACKET
129
+ return parse_vector(tokens)
130
+ when :SYMBOL
131
+ return make_symbol(lit)
132
+ when :FFI_NEW_SYMBOL
133
+ return FfiNew.new(lit)
134
+ when :FFI_SEND_SYMBOL
135
+ return FfiSend.new(lit)
136
+ when :FFI_STATIC_SYMBOL
137
+ return FfiStatic.new(lit)
138
+ when :FALSE
139
+ return Lisp::FALSE
140
+ when :TRUE
141
+ return Lisp::TRUE
142
+ when :QUOTE
143
+ expr = parse_sexpr(tokens)
144
+ return ConsCell.array_to_list([Symbol.named('quote'), expr])
145
+ when :BACKQUOTE
146
+ expr = parse_sexpr(tokens)
147
+ return ConsCell.array_to_list([Symbol.named('quasiquote'), expr])
148
+ when :COMMA
149
+ expr = parse_sexpr(tokens)
150
+ return ConsCell.array_to_list([Symbol.named('unquote'), expr])
151
+ when :COMMAAT
152
+ expr = parse_sexpr(tokens)
153
+ return ConsCell.array_to_list([Symbol.named('unquote-splicing'), expr])
154
+ when :ILLEGAL
155
+ raise "Illegal token: #{lit} on line #{tokens.line_number}"
156
+ else
157
+ return make_symbol(lit)
158
+ end
159
+ end
160
+ end
161
+
162
+ def parse(src)
163
+ tokenizer = Tokenizer.new(src)
164
+ tokenizer.init
165
+
166
+ sexpr = self.parse_sexpr(tokenizer)
167
+ return sexpr
168
+ end
169
+
170
+ def parse_and_eval(src, env=Lisp::EnvironmentFrame.global)
171
+ sexpr = self.parse(src)
172
+ return sexpr.evaluate(env)
173
+ end
174
+
175
+ def parse_and_eval_all(src, env=Lisp::EnvironmentFrame.global)
176
+ tokenizer = Tokenizer.new(src)
177
+ tokenizer.init
178
+ result = nil
179
+ until tokenizer.eof?
180
+ sexpr = self.parse_sexpr(tokenizer)
181
+ result = sexpr.evaluate(env)
182
+ end
183
+ result
184
+ end
185
+
186
+
187
+ end
188
+
189
+ end
@@ -0,0 +1,45 @@
1
+ module Lisp
2
+
3
+ class Primitive < Atom
4
+
5
+ attr_reader :doc
6
+
7
+ def self.register(name, doc="", special=false, env=Lisp::EnvironmentFrame.global, &implementation)
8
+ instance = self.new(name, doc, special, &implementation)
9
+ env.bind(Symbol.named(name), instance)
10
+ end
11
+
12
+ def initialize(name, doc, special, &implementation)
13
+ @name = name
14
+ @doc = doc
15
+ @special = special
16
+ @implementation = implementation
17
+ end
18
+
19
+ def apply_to(args, env)
20
+ @implementation.call(args, env)
21
+ end
22
+
23
+ def apply_to_without_evaluating(args, env)
24
+ @implementation.call(args, env)
25
+ end
26
+
27
+ def to_s
28
+ "<prim: #{@name}>"
29
+ end
30
+
31
+ def primitive?
32
+ true
33
+ end
34
+
35
+ def special?
36
+ @special
37
+ end
38
+
39
+ def type
40
+ :primitive
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,46 @@
1
+ module Lisp
2
+
3
+ class Relational
4
+
5
+ def self.register
6
+ Primitive.register("<", "(< number number)\n\nReturns whether the first argument is less than the second argument.") do |args, env|
7
+ Lisp::Relational::lt_impl(args, env)
8
+ end
9
+
10
+ Primitive.register(">", "(> number number)\n\nReturns whether the first argument is greater than the second argument.") do |args, env|
11
+ Lisp::Relational::gt_impl(args, env)
12
+ end
13
+
14
+ Primitive.register("<=", "(<= number number)\n\nReturns whether the first argument is less than or equal to the second argument.") do |args, env|
15
+ Lisp::Relational::lteq_impl(args, env)
16
+ end
17
+
18
+ Primitive.register(">=", "(>= number number)\n\nReturns whether the first argument is greater than or equal to the second argument.") do |args, env|
19
+ Lisp::Relational::gteq_impl(args, env)
20
+ end
21
+ end
22
+
23
+
24
+ def self.lt_impl(args, env)
25
+ raise "< needs at least 2 arguments" unless args.length > 1
26
+ return Lisp::Boolean.with_value(args.car.evaluate(env).value < args.cadr.evaluate(env).value)
27
+ end
28
+
29
+ def self.gt_impl(args, env)
30
+ raise "> needs at least 2 arguments" unless args.length > 1
31
+ return Lisp::Boolean.with_value(args.car.evaluate(env).value > args.cadr.evaluate(env).value)
32
+ end
33
+
34
+ def self.lteq_impl(args, env)
35
+ raise "<= needs at least 2 arguments" unless args.length > 1
36
+ return Lisp::Boolean.with_value(args.car.evaluate(env).value <= args.cadr.evaluate(env).value)
37
+ end
38
+
39
+ def self.gteq_impl(args, env)
40
+ raise ">= needs at least 2 arguments" unless args.length > 1
41
+ return Lisp::Boolean.with_value(args.car.evaluate(env).value >= args.cadr.evaluate(env).value)
42
+ end
43
+
44
+
45
+ end
46
+ end