rubymotionlisp 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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