use std::rc::Rc; use std::collections::HashMap; use std::str::FromStr; use crate::tokenizing::TokenKind; use crate::typechecking::{TypeConst, Type}; #[derive(Debug, Clone, Copy, PartialEq)] pub enum Builtin { Add, Increment, Subtract, Negate, Multiply, Divide, Quotient, Modulo, Exponentiation, BitwiseAnd, BitwiseOr, BooleanAnd, BooleanOr, BooleanNot, Equality, LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual, Comparison, FieldAccess, IOPrint, IOPrintLn, IOGetLine, Assignment, Concatenate, } impl Builtin { pub fn get_type(&self) -> Type { use Builtin::*; match self { Add => ty!(Nat -> Nat -> Nat), Subtract => ty!(Nat -> Nat -> Nat), Multiply => ty!(Nat -> Nat -> Nat), Divide => ty!(Nat -> Nat -> Float), Quotient => ty!(Nat -> Nat -> Nat), Modulo => ty!(Nat -> Nat -> Nat), Exponentiation => ty!(Nat -> Nat -> Nat), BitwiseAnd => ty!(Nat -> Nat -> Nat), BitwiseOr => ty!(Nat -> Nat -> Nat), BooleanAnd => ty!(Bool -> Bool -> Bool), BooleanOr => ty!(Bool -> Bool -> Bool), BooleanNot => ty!(Bool -> Bool), Equality => ty!(Nat -> Nat -> Bool), LessThan => ty!(Nat -> Nat -> Bool), LessThanOrEqual => ty!(Nat -> Nat -> Bool), GreaterThan => ty!(Nat -> Nat -> Bool), GreaterThanOrEqual => ty!(Nat -> Nat -> Bool), Comparison => ty!(Nat -> Nat -> Ordering), FieldAccess => ty!(Unit), IOPrint => ty!(Unit), IOPrintLn => ty!(Unit) , IOGetLine => ty!(StringT), Assignment => ty!(Unit), Concatenate => ty!(StringT -> StringT -> StringT), Increment => ty!(Nat -> Int), Negate => ty!(Nat -> Int) } } } impl FromStr for Builtin { type Err = (); fn from_str(s: &str) -> Result { use Builtin::*; Ok(match s { "+" => Add, "-" => Subtract, "*" => Multiply, "/" => Divide, "quot" => Quotient, "%" => Modulo, "++" => Concatenate, "^" => Exponentiation, "&" => BitwiseAnd, "&&" => BooleanAnd, "|" => BitwiseOr, "||" => BooleanOr, "!" => BooleanNot, ">" => GreaterThan, ">=" => GreaterThanOrEqual, "<" => LessThan, "<=" => LessThanOrEqual, "==" => Equality, "=" => Assignment, "<=>" => Comparison, "." => FieldAccess, "print" => IOPrint, "println" => IOPrintLn, "getline" => IOGetLine, _ => return Err(()) }) } } #[derive(Debug, PartialEq, Clone)] pub struct BinOp { sigil: Rc, pub builtin: Option, } impl BinOp { pub fn from_sigil(sigil: &str) -> BinOp { let builtin = Builtin::from_str(sigil).ok(); BinOp { sigil: Rc::new(sigil.to_string()), builtin } } pub fn sigil(&self) -> &Rc { &self.sigil } pub fn from_sigil_token(tok: &TokenKind) -> Option { use self::TokenKind::*; let s = match tok { Operator(op) => op, Period => ".", Pipe => "|", Slash => "/", LAngleBracket => "<", RAngleBracket => ">", Equals => "=", _ => return None }; Some(BinOp::from_sigil(s)) } pub fn min_precedence() -> i32 { i32::min_value() } pub fn get_precedence_from_token(op: &TokenKind) -> Option { use self::TokenKind::*; let s = match op { Operator(op) => op, Period => ".", Pipe => "|", Slash => "/", LAngleBracket => "<", RAngleBracket => ">", Equals => "=", _ => return None }; let default = 10_000_000; Some(BINOPS.get(s).map(|x| x.2.clone()).unwrap_or_else(|| { default })) } pub fn get_precedence(&self) -> i32 { let s: &str = &self.sigil; let default = 10_000_000; BINOPS.get(s).map(|x| x.2.clone()).unwrap_or_else(|| { default }) } } //TODO mapping between sigil string and precedence should live in ast.rs //mapping between operation and type should live here in builtins.rs /* the second tuple member is a placeholder for when I want to make evaluation rules tied to the * binop definition */ //TODO some of these types are going to have to be adjusted lazy_static! { static ref BINOPS: HashMap<&'static str, (Type, (), i32)> = hashmap! { "+" => (ty!(Nat -> Nat -> Nat), (), 10), "-" => (ty!(Nat -> Nat -> Nat), (), 10), "*" => (ty!(Nat -> Nat -> Nat), (), 20), "/" => (ty!(Nat -> Nat -> Float), (), 20), "quot" => (ty!(Nat -> Nat -> Nat), (), 20), "%" => (ty!(Nat -> Nat -> Nat), (), 20), "++" => (ty!(StringT -> StringT -> StringT), (), 30), "^" => (ty!(Nat -> Nat -> Nat), (), 20), "&" => (ty!(Nat -> Nat -> Nat), (), 20), "|" => (ty!(Nat -> Nat -> Nat), (), 20), ">" => (ty!(Nat -> Nat -> Bool), (), 20), ">=" => (ty!(Nat -> Nat -> Bool), (), 20), "<" => (ty!(Nat -> Nat -> Bool), (), 20), "<=" => (ty!(Nat -> Nat -> Bool), (), 20), "==" => (ty!(Nat -> Nat -> Bool), (), 20), "=" => (ty!(Unit), (), 20), //TODO not sure what the type of this should be b/c special fmr "<=>" => (ty!(Nat -> Nat -> Ordering), (), 20), //TODO figure out how to treat Order }; }