Add basic float support
This commit is contained in:
parent
10a6a52c04
commit
1f195da2ad
4 changed files with 255 additions and 32 deletions
245
src/executor.rs
245
src/executor.rs
|
@ -26,51 +26,254 @@ impl LispState {
|
|||
vec![LispValue::Nil]
|
||||
});
|
||||
|
||||
add_function(&mut table, "add", |x| {
|
||||
if x.len() != 2 {
|
||||
return vec![LispValue::Nil]
|
||||
add_function(&mut table, "concat", |x| {
|
||||
let mut strings = Vec::new();
|
||||
for val in x {
|
||||
strings.push(val.to_string());
|
||||
}
|
||||
|
||||
if let (LispValue::Integer(lhs), LispValue::Integer(rhs)) = (&x[0], &x[1]) {
|
||||
return vec![LispValue::Integer(lhs + rhs)];
|
||||
} else if let (LispValue::String(lhs), LispValue::String(rhs)) = (&x[0], &x[1]) {
|
||||
return vec![LispValue::String(lhs.to_owned() + rhs)];
|
||||
} else {
|
||||
return vec![LispValue::Nil];
|
||||
let str = strings.concat();
|
||||
vec![LispValue::String(str)]
|
||||
});
|
||||
|
||||
add_function(&mut table, "add", |x| {
|
||||
if x.len() < 1 {
|
||||
return vec![LispValue::Nil]
|
||||
} else if x.len() == 1 {
|
||||
return vec![x[0].clone()];
|
||||
}
|
||||
|
||||
let mut t = "int";
|
||||
for v in &x {
|
||||
match v {
|
||||
LispValue::Float(_) => t = "float",
|
||||
LispValue::Integer(_) => (),
|
||||
_ => return vec![LispValue::Nil]
|
||||
}
|
||||
}
|
||||
|
||||
match t {
|
||||
"int" => {
|
||||
let mut sum = 0;
|
||||
for v in &x {
|
||||
if let LispValue::Integer(n) = v {
|
||||
sum += n;
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
return vec![LispValue::Integer(sum)];
|
||||
},
|
||||
"float" => {
|
||||
let mut sum = 0.0 as f32;
|
||||
for v in &x {
|
||||
if let LispValue::Float(n) = v {
|
||||
sum += n;
|
||||
} else if let LispValue::Integer(n) = v{
|
||||
sum += *n as f32;
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
return vec![LispValue::Float(sum)];
|
||||
},
|
||||
_ => unreachable!()
|
||||
}
|
||||
});
|
||||
|
||||
add_function(&mut table, "sub", |x| {
|
||||
if x.len() != 2 {
|
||||
if x.len() < 1 {
|
||||
return vec![LispValue::Nil]
|
||||
} else if x.len() == 1 {
|
||||
return vec![x[0].clone()];
|
||||
}
|
||||
|
||||
if let (LispValue::Integer(lhs), LispValue::Integer(rhs)) = (&x[0], &x[1]) {
|
||||
return vec![LispValue::Integer(lhs - rhs)];
|
||||
let mut t = "int";
|
||||
for v in &x {
|
||||
match v {
|
||||
LispValue::Float(_) => t = "float",
|
||||
LispValue::Integer(_) => (),
|
||||
_ => return vec![LispValue::Nil]
|
||||
}
|
||||
}
|
||||
|
||||
match t {
|
||||
"int" => {
|
||||
if let LispValue::Integer(n) = x[0] {
|
||||
let mut sum = n;
|
||||
for i in 1..x.len() {
|
||||
if let LispValue::Integer(n) = &x[i] {
|
||||
sum -= n;
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
return vec![LispValue::Integer(sum)];
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
"float" => {
|
||||
if let LispValue::Float(n) = x[0] {
|
||||
let mut sum = n;
|
||||
for i in 1..x.len() {
|
||||
if let LispValue::Float(n) = &x[i] {
|
||||
sum -= *n;
|
||||
} else if let LispValue::Integer(n) = &x[i] {
|
||||
sum -= *n as f32;
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
return vec![LispValue::Float(sum)];
|
||||
} else if let LispValue::Integer(n) = x[0] {
|
||||
let mut sum = n as f32;
|
||||
for i in 1..x.len() {
|
||||
if let LispValue::Float(n) = &x[i] {
|
||||
sum -= *n;
|
||||
} else if let LispValue::Integer(n) = &x[i] {
|
||||
sum -= *n as f32;
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
return vec![LispValue::Float(sum)];
|
||||
} {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
_ => unreachable!()
|
||||
}
|
||||
vec![LispValue::Nil]
|
||||
});
|
||||
|
||||
add_function(&mut table, "mul", |x| {
|
||||
if x.len() != 2 {
|
||||
if x.len() < 1 {
|
||||
return vec![LispValue::Nil]
|
||||
} else if x.len() == 1 {
|
||||
return vec![x[0].clone()];
|
||||
}
|
||||
|
||||
if let (LispValue::Integer(lhs), LispValue::Integer(rhs)) = (&x[0], &x[1]) {
|
||||
return vec![LispValue::Integer(lhs * rhs)];
|
||||
let mut t = "int";
|
||||
for v in &x {
|
||||
match v {
|
||||
LispValue::Float(_) => t = "float",
|
||||
LispValue::Integer(_) => (),
|
||||
_ => return vec![LispValue::Nil]
|
||||
}
|
||||
}
|
||||
|
||||
match t {
|
||||
"int" => {
|
||||
if let LispValue::Integer(n) = x[0] {
|
||||
let mut sum = n;
|
||||
for i in 1..x.len() {
|
||||
if let LispValue::Integer(n) = &x[i] {
|
||||
sum *= n;
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
return vec![LispValue::Integer(sum)];
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
"float" => {
|
||||
if let LispValue::Float(n) = x[0] {
|
||||
let mut product = n;
|
||||
for i in 1..x.len() {
|
||||
if let LispValue::Float(n) = &x[i] {
|
||||
product *= *n;
|
||||
} else if let LispValue::Integer(n) = &x[i] {
|
||||
product *= *n as f32;
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
return vec![LispValue::Float(product)];
|
||||
} else if let LispValue::Integer(n) = x[0] {
|
||||
let mut product = n as f32;
|
||||
for i in 1..x.len() {
|
||||
if let LispValue::Float(n) = &x[i] {
|
||||
product *= *n;
|
||||
} else if let LispValue::Integer(n) = &x[i] {
|
||||
product *= *n as f32;
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
return vec![LispValue::Float(product)];
|
||||
} {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
_ => unreachable!()
|
||||
}
|
||||
vec![LispValue::Nil]
|
||||
});
|
||||
|
||||
add_function(&mut table, "div", |x| {
|
||||
if x.len() != 2 {
|
||||
if x.len() < 1 {
|
||||
return vec![LispValue::Nil]
|
||||
} else if x.len() == 1 {
|
||||
return vec![x[0].clone()];
|
||||
}
|
||||
|
||||
if let (LispValue::Integer(lhs), LispValue::Integer(rhs)) = (&x[0], &x[1]) {
|
||||
return vec![LispValue::Integer(lhs / rhs)];
|
||||
let mut t = "int";
|
||||
for v in &x {
|
||||
match v {
|
||||
LispValue::Float(_) => t = "float",
|
||||
LispValue::Integer(_) => (),
|
||||
_ => return vec![LispValue::Nil]
|
||||
}
|
||||
}
|
||||
|
||||
match t {
|
||||
"int" => {
|
||||
if let LispValue::Integer(n) = x[0] {
|
||||
let mut sum = n;
|
||||
for i in 1..x.len() {
|
||||
if let LispValue::Integer(n) = &x[i] {
|
||||
sum /= n;
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
return vec![LispValue::Integer(sum)];
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
"float" => {
|
||||
if let LispValue::Float(n) = x[0] {
|
||||
let mut product = n;
|
||||
for i in 1..x.len() {
|
||||
if let LispValue::Float(n) = &x[i] {
|
||||
product /= *n;
|
||||
} else if let LispValue::Integer(n) = &x[i] {
|
||||
product /= *n as f32;
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
return vec![LispValue::Float(product)];
|
||||
} else if let LispValue::Integer(n) = x[0] {
|
||||
let mut product = n as f32;
|
||||
for i in 1..x.len() {
|
||||
if let LispValue::Float(n) = &x[i] {
|
||||
product /= *n;
|
||||
} else if let LispValue::Integer(n) = &x[i] {
|
||||
product /= *n as f32;
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
return vec![LispValue::Float(product)];
|
||||
} {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
_ => unreachable!()
|
||||
}
|
||||
vec![LispValue::Nil]
|
||||
});
|
||||
|
||||
LispState {
|
||||
|
|
|
@ -7,6 +7,7 @@ pub enum LispValue {
|
|||
Nil,
|
||||
String(String),
|
||||
Integer(i32),
|
||||
Float(f32),
|
||||
LispFunction(String, Vec<OpCode>),
|
||||
RustFunction(String, fn(Vec<LispValue>) -> Vec<LispValue>),
|
||||
Ref(String),
|
||||
|
@ -21,6 +22,7 @@ impl fmt::Display for LispValue {
|
|||
LispValue::LispFunction(name, _) => write!(f, "<'{}': Lisp Function>", name),
|
||||
LispValue::RustFunction(name, _) => write!(f, "<'{}': Rust Function>", name),
|
||||
LispValue::Integer(num) => write!(f, "{}", num),
|
||||
LispValue::Float(num) => write!(f, "{}", num),
|
||||
LispValue::Ref(name) => write!(f, "<'{}': Reference>", name),
|
||||
_ => todo!()
|
||||
}
|
||||
|
@ -106,9 +108,12 @@ fn parse_exp(tokens: Vec<Token>) -> Vec<OpCode> {
|
|||
Token::Integer(num) => {
|
||||
args.push(LispValue::Integer(*num));
|
||||
},
|
||||
Token::Float(num) => {
|
||||
args.push(LispValue::Float(*num));
|
||||
},
|
||||
Token::String(str) => {
|
||||
args.push(LispValue::String(str.to_owned()));
|
||||
}
|
||||
},
|
||||
Token::CloseParen => {
|
||||
panic!("Unexpected closing parenthesis");
|
||||
},
|
||||
|
@ -142,9 +147,5 @@ pub fn parse(tokens: Vec<Token>) -> Vec<OpCode> {
|
|||
i += 1;
|
||||
}
|
||||
|
||||
// opcodes.push(OpCode::Call("print".to_string(), vec![
|
||||
// LispValue::from("Hello, World!")
|
||||
// ]));
|
||||
|
||||
opcodes
|
||||
}
|
|
@ -1,3 +1,8 @@
|
|||
; This is a comment
|
||||
|
||||
(print (add 1 (mul (div 16 2) (mul 13 2))))
|
||||
(print
|
||||
(add
|
||||
1.0
|
||||
(mul 2 3)
|
||||
)
|
||||
)
|
|
@ -6,7 +6,8 @@ pub enum Token {
|
|||
CloseParen,
|
||||
Identifier(String),
|
||||
String(String),
|
||||
Integer(i32)
|
||||
Integer(i32),
|
||||
Float(f32)
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,6 +39,7 @@ pub struct Tokenizer {
|
|||
escape_next_char: bool,
|
||||
|
||||
reading_num: bool,
|
||||
is_float: bool,
|
||||
|
||||
reading_identifier: bool,
|
||||
skipping_comment: bool,
|
||||
|
@ -53,6 +55,7 @@ impl Tokenizer {
|
|||
column: 1,
|
||||
|
||||
reading_num: false,
|
||||
is_float: false,
|
||||
|
||||
reading_string: false,
|
||||
escape_next_char: false,
|
||||
|
@ -101,12 +104,20 @@ impl Tokenizer {
|
|||
|
||||
if self.reading_num {
|
||||
// Allow spacing numbers like 1_000_000
|
||||
if !char.is_numeric() && char != '_' {
|
||||
if !char.is_numeric() && char != '_' && char != '.' {
|
||||
self.reading_num = false;
|
||||
|
||||
if self.is_float {
|
||||
tokens.push(Token::Float(self.storage.iter().collect::<String>().parse().unwrap()));
|
||||
} else {
|
||||
tokens.push(Token::Integer(self.storage.iter().collect::<String>().parse().unwrap()));
|
||||
}
|
||||
|
||||
tokens.push(Token::Integer(self.storage.iter().collect::<String>().parse().unwrap()));
|
||||
self.storage.clear();
|
||||
} else {
|
||||
if char == '.' {
|
||||
self.is_float = true;
|
||||
}
|
||||
if char != '_' {
|
||||
self.storage.push(char);
|
||||
}
|
||||
|
@ -165,10 +176,13 @@ impl Tokenizer {
|
|||
// ______100_0__: 1,000
|
||||
|
||||
// TODO: delete this when I expand identifiers to include more symbols
|
||||
} else if c.is_numeric() || c == '_' {
|
||||
} else if c.is_numeric() || c == '_' || c == '.' {
|
||||
self.reading_num = true;
|
||||
self.storage.clear();
|
||||
if c != '_' {
|
||||
if c.is_numeric() {
|
||||
self.storage.push(c);
|
||||
} else if c == '.' {
|
||||
self.storage.push('0');
|
||||
self.storage.push(c);
|
||||
}
|
||||
continue;
|
||||
|
|
Reference in a new issue