Compare commits
2 Commits
df22460010
...
4fa78336d0
Author | SHA1 | Date |
---|---|---|
bad | 4fa78336d0 | |
bad | 7d49fc53ae |
|
@ -1,6 +1,7 @@
|
|||
use super::astnode;
|
||||
use super::astnode::{ASTNode, BinaryExpr};
|
||||
use crate::lexer::{token, token::TokenType};
|
||||
|
||||
use std::iter;
|
||||
use std::result::Result as StdResult;
|
||||
|
||||
|
@ -8,6 +9,7 @@ type Result<T> = StdResult<T, ASTParsingError>;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub enum ASTParsingError {
|
||||
IncorrectToken(TokenType),
|
||||
UnmatchedBrace,
|
||||
}
|
||||
|
||||
|
@ -15,6 +17,7 @@ impl std::fmt::Display for ASTParsingError {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match *self {
|
||||
Self::UnmatchedBrace => write!(f, "Unmatched brace"),
|
||||
Self::IncorrectToken(ref token) => write!(f, "Incorrect token {:?}", token),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +147,7 @@ impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
|||
fn primary(&mut self) -> Result<ASTNode> {
|
||||
let node = match self.token_iter.next().map(|it| it.token_type) {
|
||||
Some(TokenType::False) => ASTNode::Literal(astnode::Literal::Bool(false)),
|
||||
Some(TokenType::True) => ASTNode::Literal(astnode::Literal::Bool(false)),
|
||||
Some(TokenType::True) => ASTNode::Literal(astnode::Literal::Bool(true)),
|
||||
Some(TokenType::Int(i)) => ASTNode::Literal(astnode::Literal::Int(i)),
|
||||
Some(TokenType::String(i)) => ASTNode::Literal(astnode::Literal::String(i)),
|
||||
Some(TokenType::Float(f)) => ASTNode::Literal(astnode::Literal::Float(f)),
|
||||
|
@ -159,7 +162,7 @@ impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
|
|||
None => return Err(ASTParsingError::UnmatchedBrace),
|
||||
}
|
||||
}
|
||||
Some(a) => panic!("{:#?}", a),
|
||||
Some(a) => return Err(ASTParsingError::IncorrectToken(a)),
|
||||
None => todo!(),
|
||||
};
|
||||
Ok(node)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use super::types;
|
||||
use super::types::Value;
|
||||
use crate::ast::astnode::{self, UnaryOperator};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -14,23 +14,23 @@ impl Display for RuntimeError {
|
|||
impl std::error::Error for RuntimeError {}
|
||||
|
||||
pub trait Interpret {
|
||||
fn interpret(&self) -> Result<types::Value, RuntimeError>;
|
||||
fn interpret(&self) -> Result<Value, RuntimeError>;
|
||||
}
|
||||
|
||||
impl Interpret for astnode::ASTNode {
|
||||
fn interpret(&self) -> Result<types::Value, RuntimeError> {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
astnode::all_variants!(self, n => n.interpret())
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret for astnode::Literal {
|
||||
fn interpret(&self) -> Result<types::Value, RuntimeError> {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
Ok(self.clone().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret for astnode::BinaryExpr {
|
||||
fn interpret(&self) -> Result<types::Value, RuntimeError> {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
let left_val = self.left.interpret().expect("expected lval");
|
||||
let right_val = self.right.interpret().expect("expected rval");
|
||||
match self.operator {
|
||||
|
@ -46,17 +46,21 @@ impl Interpret for astnode::BinaryExpr {
|
|||
}
|
||||
|
||||
impl Interpret for astnode::UnaryExpr {
|
||||
fn interpret(&self) -> Result<types::Value, RuntimeError> {
|
||||
let _val = self.right.interpret();
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
let val = self.right.interpret()?;
|
||||
match self.operator {
|
||||
UnaryOperator::Bang => todo!(),
|
||||
UnaryOperator::Minus => todo!(),
|
||||
UnaryOperator::Bang => Ok(Value::Bool(!val.truthy())),
|
||||
UnaryOperator::Minus => match val {
|
||||
Value::Int(i) => Ok(Value::Int(-i)),
|
||||
Value::Float(f) => Ok(Value::Float(-f)),
|
||||
_ => Err(RuntimeError),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret for astnode::GroupingExpr {
|
||||
fn interpret(&self) -> Result<types::Value, RuntimeError> {
|
||||
fn interpret(&self) -> Result<Value, RuntimeError> {
|
||||
self.0.interpret()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,48 +2,31 @@ use crate::ast::astnode;
|
|||
use from_variants::FromVariants;
|
||||
|
||||
#[derive(Debug, PartialEq, PartialOrd, FromVariants)]
|
||||
pub enum Primitive {
|
||||
pub enum Value {
|
||||
Int(i32),
|
||||
Float(f32),
|
||||
Bool(bool),
|
||||
Null,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, PartialOrd, FromVariants)]
|
||||
pub enum Value {
|
||||
#[from_variants(into)]
|
||||
Primitive(Primitive),
|
||||
// TODO: create a cow(not rust cow) string instead of cloning a normal string
|
||||
String(String),
|
||||
}
|
||||
|
||||
impl From<astnode::Literal> for Value {
|
||||
fn from(l: astnode::Literal) -> Self {
|
||||
match_any::match_any!(l,
|
||||
astnode::Literal::Int(v) | astnode::Literal::Bool(v)| astnode::Literal::Float(v) => v.into(),
|
||||
astnode::Literal::String(_s) => todo!()
|
||||
astnode::Literal::Int(v) | astnode::Literal::Bool(v) | astnode::Literal::Float(v) | astnode::Literal::String(v) => v.into()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn int(i: i32) -> Value {
|
||||
Value::Primitive(Primitive::Int(i))
|
||||
}
|
||||
|
||||
pub fn float(f: f32) -> Value {
|
||||
Value::Primitive(Primitive::Float(f))
|
||||
}
|
||||
|
||||
pub fn bool(b: bool) -> Value {
|
||||
Value::Primitive(Primitive::Bool(b))
|
||||
}
|
||||
|
||||
pub fn null() -> Value {
|
||||
Value::Primitive(Primitive::Null)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Value {
|
||||
fn default() -> Self {
|
||||
Self::null()
|
||||
Self::Null
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn truthy(&self) -> bool {
|
||||
!(matches!(*self, Self::Bool(false)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crftng_intrprtrs::interpreter::types;
|
||||
use crftng_intrprtrs::run;
|
||||
|
||||
#[test]
|
||||
|
@ -12,5 +11,5 @@ fn test_one_equality() {
|
|||
}
|
||||
|
||||
fn run_check_result_eq_bool(code: &str, value: bool) {
|
||||
assert_eq!(run(code).unwrap(), types::Value::bool(value))
|
||||
assert_eq!(run(code).unwrap(), value.into())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue