feat: rudimentary float support
This commit is contained in:
parent
1ed451e696
commit
e49dbab859
5 changed files with 31 additions and 2 deletions
16
src/env/core.rs
vendored
16
src/env/core.rs
vendored
|
@ -102,6 +102,10 @@ pub(super) fn core() -> HashMap<String, Node> {
|
||||||
Node::Int128(lhs as i128 + rhs as i128)
|
Node::Int128(lhs as i128 + rhs as i128)
|
||||||
}
|
}
|
||||||
(Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs + rhs as i128),
|
(Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs + rhs as i128),
|
||||||
|
|
||||||
|
(Node::Float(lhs), Node::Float(rhs)) => Node::Float(lhs + rhs),
|
||||||
|
(Node::Int(lhs), Node::Float(rhs)) => Node::Float(lhs as f64 + rhs),
|
||||||
|
(Node::Float(lhs), Node::Int(rhs)) => Node::Float(lhs + rhs as f64),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
})
|
})
|
||||||
.unwrap_or(Node::Int(0));
|
.unwrap_or(Node::Int(0));
|
||||||
|
@ -124,6 +128,10 @@ pub(super) fn core() -> HashMap<String, Node> {
|
||||||
Node::Int128(lhs as i128 - rhs as i128)
|
Node::Int128(lhs as i128 - rhs as i128)
|
||||||
}
|
}
|
||||||
(Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs - rhs as i128),
|
(Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs - rhs as i128),
|
||||||
|
|
||||||
|
(Node::Float(lhs), Node::Float(rhs)) => Node::Float(lhs - rhs),
|
||||||
|
(Node::Float(lhs), Node::Int(rhs)) => Node::Float(lhs - rhs as f64),
|
||||||
|
(Node::Int(lhs), Node::Float(rhs)) => Node::Float(lhs as f64 - rhs),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
})
|
})
|
||||||
.unwrap_or(Node::Int(0));
|
.unwrap_or(Node::Int(0));
|
||||||
|
@ -146,6 +154,10 @@ pub(super) fn core() -> HashMap<String, Node> {
|
||||||
Node::Int128(lhs as i128 * rhs as i128)
|
Node::Int128(lhs as i128 * rhs as i128)
|
||||||
}
|
}
|
||||||
(Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs * rhs as i128),
|
(Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs * rhs as i128),
|
||||||
|
|
||||||
|
(Node::Float(lhs), Node::Float(rhs)) => Node::Float(lhs * rhs),
|
||||||
|
(Node::Float(lhs), Node::Int(rhs)) => Node::Float(lhs * rhs as f64),
|
||||||
|
(Node::Int(lhs), Node::Float(rhs)) => Node::Float(lhs as f64 * rhs),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
})
|
})
|
||||||
.unwrap_or(Node::Int(0));
|
.unwrap_or(Node::Int(0));
|
||||||
|
@ -168,6 +180,10 @@ pub(super) fn core() -> HashMap<String, Node> {
|
||||||
Node::Int128(lhs as i128 / rhs as i128)
|
Node::Int128(lhs as i128 / rhs as i128)
|
||||||
}
|
}
|
||||||
(Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs / rhs as i128),
|
(Node::Int128(lhs), Node::Int(rhs)) => Node::Int128(lhs / rhs as i128),
|
||||||
|
|
||||||
|
(Node::Float(lhs), Node::Float(rhs)) => Node::Float(lhs / rhs),
|
||||||
|
(Node::Float(lhs), Node::Int(rhs)) => Node::Float(lhs / rhs as f64),
|
||||||
|
(Node::Int(lhs), Node::Float(rhs)) => Node::Float(lhs as f64 / rhs),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
})
|
})
|
||||||
.unwrap_or(Node::Int(0));
|
.unwrap_or(Node::Int(0));
|
||||||
|
|
|
@ -109,6 +109,10 @@ mod test {
|
||||||
#[case("(* 8 9)", "72")]
|
#[case("(* 8 9)", "72")]
|
||||||
#[case("(/ 86 2)", "43")]
|
#[case("(/ 86 2)", "43")]
|
||||||
#[case("(+ 1 2 (- 3 4))", "2")]
|
#[case("(+ 1 2 (- 3 4))", "2")]
|
||||||
|
#[case("(+ 1 0.5)", "1.5")]
|
||||||
|
#[case("(- 1 0.5)", "0.5")]
|
||||||
|
#[case("(* 1 0.5)", "0.5")]
|
||||||
|
#[case("(/ 1.0 2.0)", "0.5")]
|
||||||
// Native functions defaults
|
// Native functions defaults
|
||||||
#[case("(+)", "0")]
|
#[case("(+)", "0")]
|
||||||
#[case("(-)", "0")]
|
#[case("(-)", "0")]
|
||||||
|
@ -198,6 +202,7 @@ mod test {
|
||||||
#[case("(str (+ 1 2))", "3")]
|
#[case("(str (+ 1 2))", "3")]
|
||||||
#[case("(str (list 1 2 3))", "(1 2 3)")]
|
#[case("(str (list 1 2 3))", "(1 2 3)")]
|
||||||
fn test_evaluator(#[case] input: &str, #[case] expected: &str) {
|
fn test_evaluator(#[case] input: &str, #[case] expected: &str) {
|
||||||
|
dbg!(input);
|
||||||
let env = Environment::default();
|
let env = Environment::default();
|
||||||
let ast = parser::parse_str(input).unwrap();
|
let ast = parser::parse_str(input).unwrap();
|
||||||
let res = eval(&env, ast)
|
let res = eval(&env, ast)
|
||||||
|
|
|
@ -12,6 +12,7 @@ pub enum Node {
|
||||||
Keyword(String),
|
Keyword(String),
|
||||||
Int(i64),
|
Int(i64),
|
||||||
Int128(i128),
|
Int128(i128),
|
||||||
|
Float(f64),
|
||||||
String(String),
|
String(String),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Nil,
|
Nil,
|
||||||
|
@ -44,6 +45,7 @@ impl std::fmt::Display for Node {
|
||||||
|
|
||||||
Node::Int(val) => write!(f, "{}", val),
|
Node::Int(val) => write!(f, "{}", val),
|
||||||
Node::Int128(val) => write!(f, "{}", val),
|
Node::Int128(val) => write!(f, "{}", val),
|
||||||
|
Node::Float(val) => write!(f, "{}", val),
|
||||||
Node::Boolean(true) => write!(f, "true"),
|
Node::Boolean(true) => write!(f, "true"),
|
||||||
Node::Boolean(false) => write!(f, "false"),
|
Node::Boolean(false) => write!(f, "false"),
|
||||||
Node::Symbol(val) => write!(f, "{}", val),
|
Node::Symbol(val) => write!(f, "{}", val),
|
||||||
|
|
|
@ -34,6 +34,7 @@ pub enum Token {
|
||||||
// Values
|
// Values
|
||||||
Keyword(String),
|
Keyword(String),
|
||||||
Int(i64),
|
Int(i64),
|
||||||
|
Float(f64),
|
||||||
String(String),
|
String(String),
|
||||||
Ident(String),
|
Ident(String),
|
||||||
True,
|
True,
|
||||||
|
@ -178,15 +179,19 @@ fn read_int(input: &mut Peekable<Chars>, first: char) -> Token {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.is_ascii_digit() {
|
if !c.is_ascii_digit() && *c != '.' {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_int.push(input.next().unwrap());
|
raw_int.push(input.next().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if raw_int.iter().any(|c| *c == '.') {
|
||||||
|
Token::Float(raw_int.iter().collect::<String>().parse::<f64>().unwrap())
|
||||||
|
} else {
|
||||||
Token::Int(raw_int.iter().collect::<String>().parse::<i64>().unwrap())
|
Token::Int(raw_int.iter().collect::<String>().parse::<i64>().unwrap())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn read_ident(input: &mut Peekable<Chars>, first: char) -> Token {
|
fn read_ident(input: &mut Peekable<Chars>, first: char) -> Token {
|
||||||
let special_characters = ['!', '?', '*', '-', '_'];
|
let special_characters = ['!', '?', '*', '-', '_'];
|
||||||
|
|
|
@ -60,6 +60,7 @@ fn next_statement(tokens: &mut Peekable<IntoIter<Token>>) -> Result<Option<Node>
|
||||||
Token::Ident(val) => Node::Symbol(val),
|
Token::Ident(val) => Node::Symbol(val),
|
||||||
Token::String(val) => Node::String(val),
|
Token::String(val) => Node::String(val),
|
||||||
Token::Int(int) => Node::Int(int),
|
Token::Int(int) => Node::Int(int),
|
||||||
|
Token::Float(float) => Node::Float(float),
|
||||||
Token::True => Node::Boolean(true),
|
Token::True => Node::Boolean(true),
|
||||||
Token::False => Node::Boolean(false),
|
Token::False => Node::Boolean(false),
|
||||||
Token::Nil => Node::Nil,
|
Token::Nil => Node::Nil,
|
||||||
|
|
Loading…
Reference in a new issue