2018-02-23 19:06:37 -08:00
|
|
|
use std::rc::Rc;
|
2018-02-24 17:37:23 -08:00
|
|
|
use std::collections::HashMap;
|
2019-08-12 13:49:39 -07:00
|
|
|
use std::str::FromStr;
|
2018-02-23 19:06:37 -08:00
|
|
|
|
2019-01-07 13:00:37 -08:00
|
|
|
use crate::tokenizing::TokenKind;
|
2019-02-10 04:30:37 -08:00
|
|
|
use crate::typechecking::{TypeConst, Type};
|
2018-05-20 20:47:24 -07:00
|
|
|
|
2019-08-13 04:17:17 -07:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
2019-08-12 14:10:07 -07:00
|
|
|
pub enum Builtin {
|
2019-08-12 13:10:22 -07:00
|
|
|
Add,
|
|
|
|
Subtract,
|
|
|
|
Multiply,
|
|
|
|
Divide,
|
|
|
|
Quotient,
|
|
|
|
Modulo,
|
|
|
|
Exponentiation,
|
|
|
|
BitwiseAnd,
|
|
|
|
BitwiseOr,
|
|
|
|
BooleanAnd,
|
|
|
|
BooleanOr,
|
|
|
|
BooleanNot,
|
|
|
|
Equality,
|
|
|
|
LessThan,
|
2019-08-12 13:49:39 -07:00
|
|
|
LessThanOrEqual,
|
2019-08-12 13:10:22 -07:00
|
|
|
GreaterThan,
|
2019-08-12 13:49:39 -07:00
|
|
|
GreaterThanOrEqual,
|
2019-08-12 13:10:22 -07:00
|
|
|
Comparison,
|
|
|
|
FieldAccess,
|
|
|
|
IOPrint,
|
|
|
|
IOPrintLn,
|
|
|
|
IOGetLine,
|
2019-08-12 13:49:39 -07:00
|
|
|
Assignment,
|
|
|
|
Concatenate,
|
|
|
|
}
|
|
|
|
|
2019-08-13 04:17:17 -07:00
|
|
|
impl Builtin {
|
|
|
|
pub fn get_type(&self) -> Type {
|
2019-08-13 04:28:21 -07:00
|
|
|
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),
|
|
|
|
}
|
2019-08-13 04:17:17 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-12 13:49:39 -07:00
|
|
|
impl FromStr for Builtin {
|
|
|
|
type Err = ();
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
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(())
|
|
|
|
})
|
|
|
|
}
|
2019-08-12 13:10:22 -07:00
|
|
|
}
|
|
|
|
|
2018-02-23 19:06:37 -08:00
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
2018-02-24 17:37:23 -08:00
|
|
|
pub struct BinOp {
|
2018-02-24 14:39:45 -08:00
|
|
|
sigil: Rc<String>
|
2018-02-23 19:06:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl BinOp {
|
2018-02-24 17:50:57 -08:00
|
|
|
pub fn from_sigil(sigil: &str) -> BinOp {
|
|
|
|
BinOp { sigil: Rc::new(sigil.to_string()) }
|
2018-02-23 19:06:37 -08:00
|
|
|
}
|
2018-02-24 14:39:45 -08:00
|
|
|
pub fn sigil(&self) -> &Rc<String> {
|
|
|
|
&self.sigil
|
|
|
|
}
|
2018-11-16 23:17:34 -08:00
|
|
|
pub fn from_sigil_token(tok: &TokenKind) -> Option<BinOp> {
|
|
|
|
use self::TokenKind::*;
|
2018-08-19 20:33:50 -07:00
|
|
|
let s = match tok {
|
|
|
|
Operator(op) => op,
|
|
|
|
Period => ".",
|
|
|
|
Pipe => "|",
|
|
|
|
Slash => "/",
|
2018-08-19 21:11:43 -07:00
|
|
|
LAngleBracket => "<",
|
|
|
|
RAngleBracket => ">",
|
2019-06-16 16:07:27 -07:00
|
|
|
Equals => "=",
|
2018-08-19 20:33:50 -07:00
|
|
|
_ => return None
|
|
|
|
};
|
|
|
|
Some(BinOp::from_sigil(s))
|
|
|
|
}
|
2019-02-20 03:27:46 -08:00
|
|
|
|
2018-05-20 20:47:24 -07:00
|
|
|
pub fn get_type(&self) -> Result<Type, String> {
|
2018-02-24 17:37:23 -08:00
|
|
|
let s = self.sigil.as_str();
|
|
|
|
BINOPS.get(s).map(|x| x.0.clone()).ok_or(format!("Binop {} not found", s))
|
|
|
|
}
|
2019-02-20 03:27:46 -08:00
|
|
|
|
2018-02-23 19:06:37 -08:00
|
|
|
pub fn min_precedence() -> i32 {
|
|
|
|
i32::min_value()
|
|
|
|
}
|
2018-11-16 23:17:34 -08:00
|
|
|
pub fn get_precedence_from_token(op: &TokenKind) -> Option<i32> {
|
|
|
|
use self::TokenKind::*;
|
2018-08-19 20:33:50 -07:00
|
|
|
let s = match op {
|
|
|
|
Operator(op) => op,
|
|
|
|
Period => ".",
|
|
|
|
Pipe => "|",
|
|
|
|
Slash => "/",
|
2018-08-19 21:11:43 -07:00
|
|
|
LAngleBracket => "<",
|
|
|
|
RAngleBracket => ">",
|
2019-06-16 16:07:27 -07:00
|
|
|
Equals => "=",
|
2018-08-19 20:33:50 -07:00
|
|
|
_ => return None
|
|
|
|
};
|
2018-08-19 21:40:30 -07:00
|
|
|
let default = 10_000_000;
|
|
|
|
Some(BINOPS.get(s).map(|x| x.2.clone()).unwrap_or_else(|| {
|
|
|
|
default
|
|
|
|
}))
|
2018-02-23 19:06:37 -08:00
|
|
|
}
|
2018-10-19 11:02:10 -07:00
|
|
|
|
|
|
|
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
|
|
|
|
})
|
|
|
|
}
|
2018-02-23 19:06:37 -08:00
|
|
|
}
|
|
|
|
|
2018-02-24 17:37:23 -08:00
|
|
|
|
2019-08-13 04:17:17 -07:00
|
|
|
//TODO mapping between sigil string and precedence should live in ast.rs
|
|
|
|
//mapping between operation and type should live here in builtins.rs
|
2018-02-24 17:37:23 -08:00
|
|
|
|
|
|
|
/* the second tuple member is a placeholder for when I want to make evaluation rules tied to the
|
|
|
|
* binop definition */
|
2019-02-10 04:30:37 -08:00
|
|
|
//TODO some of these types are going to have to be adjusted
|
2018-02-24 17:37:23 -08:00
|
|
|
lazy_static! {
|
2019-02-10 04:30:37 -08:00
|
|
|
static ref BINOPS: HashMap<&'static str, (Type, (), i32)> =
|
2018-02-24 17:37:23 -08:00
|
|
|
hashmap! {
|
2019-02-17 03:38:15 -08:00
|
|
|
"+" => (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
|
2018-02-24 17:37:23 -08:00
|
|
|
};
|
|
|
|
}
|