Skip to content

Commit 3349072

Browse files
Алекс Мозаидзеalexmozaidze
Алекс Мозаидзе
authored andcommitted
BigInt support, Configurable Int and Float, and refactors
1 parent b1f2c1b commit 3349072

9 files changed

+309
-159
lines changed

Cargo.lock

Lines changed: 47 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,19 @@ doc = true
1717
[[bin]]
1818
name = "rust_lisp"
1919
path = "src/main.rs"
20+
21+
[features]
22+
# What integer to use for Value::Int
23+
bigint = ["num-bigint", "num-traits"]
24+
i128 = []
25+
i64 = []
26+
i16 = []
27+
i8 = []
28+
29+
# Use f64 for Value::Float, if unset, use f32
30+
f64 = []
31+
32+
[dependencies]
33+
cfg-if = "1.0"
34+
num-traits = { version = "0.2", optional = true }
35+
num-bigint = { version = "0.4", optional = true }

src/default_environment.rs

Lines changed: 96 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ use crate::{
55
utils::{require_int_parameter, require_list_parameter, require_parameter},
66
};
77
use std::collections::HashMap;
8+
use cfg_if::cfg_if;
9+
cfg_if! {
10+
if #[cfg(feature = "bigint")] {
11+
use num_traits::ToPrimitive;
12+
} else {
13+
use crate::model::IntType;
14+
}
15+
}
816

917
/// Initialize an instance of `Env` with several core Lisp functions implemented
1018
/// in Rust. **Without this, you will only have access to the functions you
@@ -18,7 +26,7 @@ pub fn default_env() -> Env {
1826
let expr = require_parameter("print", args, 0)?;
1927

2028
println!("{}", &expr);
21-
return Ok(expr.clone());
29+
Ok(expr.clone())
2230
}),
2331
);
2432

@@ -99,7 +107,7 @@ pub fn default_env() -> Env {
99107
Value::NativeFunc(|_env, args| {
100108
let list = require_list_parameter("car", args, 0)?;
101109

102-
return list.car().map(|c| c.clone());
110+
list.car()
103111
}),
104112
);
105113

@@ -108,7 +116,7 @@ pub fn default_env() -> Env {
108116
Value::NativeFunc(|_env, args| {
109117
let list = require_list_parameter("cdr", args, 0)?;
110118

111-
return Ok(Value::List(list.cdr()));
119+
Ok(Value::List(list.cdr()))
112120
}),
113121
);
114122

@@ -118,26 +126,33 @@ pub fn default_env() -> Env {
118126
let car = require_parameter("cons", args, 0)?;
119127
let cdr = require_list_parameter("cons", args, 1)?;
120128

121-
return Ok(Value::List(cdr.cons(car.clone())));
129+
Ok(Value::List(cdr.cons(car.clone())))
122130
}),
123131
);
124132

125133
entries.insert(
126134
String::from("list"),
127-
Value::NativeFunc(|_env, args| Ok(Value::List(args.into_iter().collect::<List>()))),
135+
Value::NativeFunc(|_env, args| Ok(Value::List(args.iter().collect::<List>()))),
128136
);
129137

130138
entries.insert(
131139
String::from("nth"),
132140
Value::NativeFunc(|_env, args| {
133-
let index = require_int_parameter("nth", args, 0)?;
141+
cfg_if! {
142+
if #[cfg(feature = "bigint")] {
143+
let index = require_int_parameter("nth", args, 0)?
144+
.to_usize()
145+
.ok_or(RuntimeError::new("Failed converting `BigInt` to `usize`"))?;
146+
} else {
147+
let index = require_int_parameter("nth", args, 0)? as usize;
148+
}
149+
}
134150
let list = require_list_parameter("nth", args, 1)?;
135151

136-
return Ok(list
152+
Ok(list
137153
.into_iter()
138-
.nth(index as usize)
139-
.map(|v| v.clone())
140-
.unwrap_or(Value::NIL));
154+
.nth(index)
155+
.unwrap_or(Value::NIL))
141156
}),
142157
);
143158

@@ -150,7 +165,7 @@ pub fn default_env() -> Env {
150165

151166
v.sort();
152167

153-
return Ok(Value::List(v.into_iter().collect()));
168+
Ok(Value::List(v.into_iter().collect()))
154169
}),
155170
);
156171

@@ -163,7 +178,7 @@ pub fn default_env() -> Env {
163178

164179
v.reverse();
165180

166-
return Ok(Value::List(v.into_iter().collect()));
181+
Ok(Value::List(v.into_iter().collect()))
167182
}),
168183
);
169184

@@ -173,15 +188,15 @@ pub fn default_env() -> Env {
173188
let func = require_parameter("map", args, 0)?;
174189
let list = require_list_parameter("map", args, 1)?;
175190

176-
return list
191+
list
177192
.into_iter()
178193
.map(|val| {
179-
let expr = lisp! { ({func.clone()} {val.clone()}) };
194+
let expr = lisp! { ({func.clone()} {val}) };
180195

181196
eval(env.clone(), &expr)
182197
})
183198
.collect::<Result<List, RuntimeError>>()
184-
.map(|l| Value::List(l));
199+
.map(Value::List)
185200
}),
186201
);
187202

@@ -208,7 +223,13 @@ pub fn default_env() -> Env {
208223
Value::NativeFunc(|_env, args| {
209224
let list = require_list_parameter("length", args, 0)?;
210225

211-
return Ok(Value::Int(list.into_iter().len() as i32));
226+
cfg_if! {
227+
if #[cfg(feature = "bigint")] {
228+
Ok(Value::Int(list.into_iter().len().into()))
229+
} else {
230+
Ok(Value::Int(list.into_iter().len() as IntType))
231+
}
232+
}
212233
}),
213234
);
214235

@@ -218,9 +239,24 @@ pub fn default_env() -> Env {
218239
let start = require_int_parameter("range", args, 0)?;
219240
let end = require_int_parameter("range", args, 1)?;
220241

221-
Ok(Value::List(
222-
(start..end).map(|i| Value::Int(i)).collect::<List>(),
223-
))
242+
cfg_if! {
243+
if #[cfg(feature = "bigint")] {
244+
let mut i = start.clone();
245+
let mut res = Vec::with_capacity((end.clone() - start)
246+
.to_usize()
247+
.ok_or(RuntimeError::new("Failed converting `BigInt` to `usize`"))?
248+
);
249+
250+
while i <= end {
251+
res.push(i.clone());
252+
i += 1;
253+
}
254+
255+
Ok(Value::List(res.into_iter().map(Value::Int).collect::<List>()))
256+
} else {
257+
Ok(Value::List((start..=end).map(Value::Int).collect::<List>()))
258+
}
259+
}
224260
}),
225261
);
226262

@@ -230,24 +266,21 @@ pub fn default_env() -> Env {
230266
let a = require_parameter("+", args, 0)?;
231267
let b = require_parameter("+", args, 1)?;
232268

233-
match (a.as_int(), b.as_int()) {
234-
(Some(a), Some(b)) => return Ok(Value::Int(a + b)),
235-
_ => (),
236-
};
269+
if let (Some(a), Some(b)) = (a.as_int(), b.as_int()) {
270+
return Ok(Value::Int(a + b))
271+
}
237272

238-
match (a.as_float(), b.as_float()) {
239-
(Some(a), Some(b)) => return Ok(Value::Float(a + b)),
240-
_ => (),
241-
};
273+
if let (Some(a), Some(b)) = (a.as_float(), b.as_float()) {
274+
return Ok(Value::Float(a + b))
275+
}
242276

243-
match (a.as_string(), b.as_string()) {
244-
(Some(a), Some(b)) => return Ok(Value::String(String::from(a) + b)),
245-
_ => (),
246-
};
277+
if let (Some(a), Some(b)) = (a.as_string(), b.as_string()) {
278+
return Ok(Value::String(String::from(a) + b))
279+
}
247280

248-
return Err(RuntimeError {
281+
Err(RuntimeError {
249282
msg: String::from("Function \"+\" requires arguments to be numbers or strings"),
250-
});
283+
})
251284
}),
252285
);
253286

@@ -257,19 +290,17 @@ pub fn default_env() -> Env {
257290
let a = require_parameter("-", args, 0)?;
258291
let b = require_parameter("-", args, 1)?;
259292

260-
match (a.as_int(), b.as_int()) {
261-
(Some(a), Some(b)) => return Ok(Value::Int(a - b)),
262-
_ => (),
263-
};
293+
if let (Some(a), Some(b)) = (a.as_int(), b.as_int()) {
294+
return Ok(Value::Int(a - b))
295+
}
264296

265-
match (a.as_float(), b.as_float()) {
266-
(Some(a), Some(b)) => return Ok(Value::Float(a - b)),
267-
_ => (),
268-
};
297+
if let (Some(a), Some(b)) = (a.as_float(), b.as_float()) {
298+
return Ok(Value::Float(a - b))
299+
}
269300

270-
return Err(RuntimeError {
301+
Err(RuntimeError {
271302
msg: String::from("Function \"-\" requires arguments to be numbers"),
272-
});
303+
})
273304
}),
274305
);
275306

@@ -279,19 +310,17 @@ pub fn default_env() -> Env {
279310
let a = require_parameter("*", args, 0)?;
280311
let b = require_parameter("*", args, 1)?;
281312

282-
match (a.as_int(), b.as_int()) {
283-
(Some(a), Some(b)) => return Ok(Value::Int(a * b)),
284-
_ => (),
285-
};
313+
if let (Some(a), Some(b)) = (a.as_int(), b.as_int()) {
314+
return Ok(Value::Int(a * b))
315+
}
286316

287-
match (a.as_float(), b.as_float()) {
288-
(Some(a), Some(b)) => return Ok(Value::Float(a * b)),
289-
_ => (),
290-
};
317+
if let (Some(a), Some(b)) = (a.as_float(), b.as_float()) {
318+
return Ok(Value::Float(a * b))
319+
}
291320

292-
return Err(RuntimeError {
321+
Err(RuntimeError {
293322
msg: String::from("Function \"*\" requires arguments to be numbers"),
294-
});
323+
})
295324
}),
296325
);
297326

@@ -301,19 +330,17 @@ pub fn default_env() -> Env {
301330
let a = require_parameter("/", args, 0)?;
302331
let b = require_parameter("/", args, 1)?;
303332

304-
match (a.as_int(), b.as_int()) {
305-
(Some(a), Some(b)) => return Ok(Value::Int(a / b)),
306-
_ => (),
307-
};
333+
if let (Some(a), Some(b)) = (a.as_int(), b.as_int()) {
334+
return Ok(Value::Int(a / b))
335+
}
308336

309-
match (a.as_float(), b.as_float()) {
310-
(Some(a), Some(b)) => return Ok(Value::Float(a / b)),
311-
_ => (),
312-
};
337+
if let (Some(a), Some(b)) = (a.as_float(), b.as_float()) {
338+
return Ok(Value::Float(a / b))
339+
}
313340

314-
return Err(RuntimeError {
341+
Err(RuntimeError {
315342
msg: String::from("Function \"/\" requires arguments to be numbers"),
316-
});
343+
})
317344
}),
318345
);
319346

@@ -323,14 +350,13 @@ pub fn default_env() -> Env {
323350
let a = require_parameter("truncate", args, 0)?;
324351
let b = require_parameter("truncate", args, 1)?;
325352

326-
match (a.as_int(), b.as_int()) {
327-
(Some(a), Some(b)) => return Ok(Value::Int(a / b)),
328-
_ => (),
329-
};
353+
if let (Some(a), Some(b)) = (a.as_int(), b.as_int()) {
354+
return Ok(Value::Int(a / b))
355+
}
330356

331-
return Err(RuntimeError {
357+
Err(RuntimeError {
332358
msg: String::from("Function \"truncate\" requires arguments to be integers"),
333-
});
359+
})
334360
}),
335361
);
336362

@@ -418,7 +444,7 @@ pub fn default_env() -> Env {
418444
let func = require_parameter("apply", args, 0)?;
419445
let params = require_list_parameter("apply", args, 1)?;
420446

421-
eval(env.clone(), &Value::List(params.cons(func.clone())))
447+
eval(env, &Value::List(params.cons(func.clone())))
422448
}),
423449
);
424450

0 commit comments

Comments
 (0)