e8f1f51639
Still need to figure out the macro export thing
133 lines
3.9 KiB
Rust
133 lines
3.9 KiB
Rust
use std::rc::Rc;
|
|
use std::collections::HashMap;
|
|
use std::fmt;
|
|
|
|
use crate::tokenizing::TokenKind;
|
|
use crate::typechecking::{TypeConst, Type};
|
|
use crate::typechecking::TypeConst::*;
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
pub struct BinOp {
|
|
sigil: Rc<String>
|
|
}
|
|
|
|
impl BinOp {
|
|
pub fn from_sigil(sigil: &str) -> BinOp {
|
|
BinOp { sigil: Rc::new(sigil.to_string()) }
|
|
}
|
|
pub fn sigil(&self) -> &Rc<String> {
|
|
&self.sigil
|
|
}
|
|
pub fn from_sigil_token(tok: &TokenKind) -> Option<BinOp> {
|
|
use self::TokenKind::*;
|
|
let s = match tok {
|
|
Operator(op) => op,
|
|
Period => ".",
|
|
Pipe => "|",
|
|
Slash => "/",
|
|
LAngleBracket => "<",
|
|
RAngleBracket => ">",
|
|
_ => return None
|
|
};
|
|
Some(BinOp::from_sigil(s))
|
|
}
|
|
/*
|
|
pub fn get_type(&self) -> Result<Type, String> {
|
|
let s = self.sigil.as_str();
|
|
BINOPS.get(s).map(|x| x.0.clone()).ok_or(format!("Binop {} not found", s))
|
|
}
|
|
*/
|
|
pub fn min_precedence() -> i32 {
|
|
i32::min_value()
|
|
}
|
|
pub fn get_precedence_from_token(op: &TokenKind) -> Option<i32> {
|
|
use self::TokenKind::*;
|
|
let s = match op {
|
|
Operator(op) => op,
|
|
Period => ".",
|
|
Pipe => "|",
|
|
Slash => "/",
|
|
LAngleBracket => "<",
|
|
RAngleBracket => ">",
|
|
_ => 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
|
|
})
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
pub struct PrefixOp {
|
|
sigil: Rc<String>
|
|
}
|
|
|
|
impl PrefixOp {
|
|
pub fn from_sigil(sigil: &str) -> PrefixOp {
|
|
PrefixOp { sigil: Rc::new(sigil.to_string()) }
|
|
}
|
|
pub fn sigil(&self) -> &Rc<String> {
|
|
&self.sigil
|
|
}
|
|
pub fn is_prefix(op: &str) -> bool {
|
|
PREFIX_OPS.get(op).is_some()
|
|
}
|
|
/*
|
|
pub fn get_type(&self) -> Result<Type, String> {
|
|
let s = self.sigil.as_str();
|
|
PREFIX_OPS.get(s).map(|x| x.0.clone()).ok_or(format!("Prefix op {} not found", s))
|
|
}
|
|
*/
|
|
}
|
|
|
|
//TODO make this macro exportable?
|
|
macro_rules! mk_type {
|
|
($type_name:ident) => { Type::Const(TypeConst::$type_name) };
|
|
($t1:ident -> $t2:ident) => { Type::Arrow(Box::new(mk_type!($t1)), Box::new(mk_type!($t2))) };
|
|
($t1:ident -> $t2:ident -> $t3:ident) => { Type::Arrow(Box::new(mk_type!($t1)), Box::new(mk_type!($t2 -> $t3))) };
|
|
}
|
|
|
|
lazy_static! {
|
|
static ref PREFIX_OPS: HashMap<&'static str, (Type, ())> =
|
|
hashmap! {
|
|
"+" => (mk_type!(Int -> Int), ()),
|
|
"-" => (mk_type!(Int -> Int), ()),
|
|
"!" => (mk_type!(Bool -> Bool), ()),
|
|
};
|
|
}
|
|
|
|
/* 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! {
|
|
"+" => (mk_type!(Nat -> Nat -> Nat), (), 10),
|
|
"-" => (mk_type!(Nat -> Nat -> Nat), (), 10),
|
|
"*" => (mk_type!(Nat -> Nat -> Nat), (), 20),
|
|
"/" => (mk_type!(Nat -> Nat -> Float), (), 20),
|
|
"quot" => (mk_type!(Nat -> Nat -> Nat), (), 20),
|
|
"%" => (mk_type!(Nat -> Nat -> Nat), (), 20),
|
|
"++" => (mk_type!(StringT -> StringT -> StringT), (), 30),
|
|
"^" => (mk_type!(Nat -> Nat -> Nat), (), 20),
|
|
"&" => (mk_type!(Nat -> Nat -> Nat), (), 20),
|
|
"|" => (mk_type!(Nat -> Nat -> Nat), (), 20),
|
|
">" => (mk_type!(Nat -> Nat -> Bool), (), 20),
|
|
">=" => (mk_type!(Nat -> Nat -> Bool), (), 20),
|
|
"<" => (mk_type!(Nat -> Nat -> Bool), (), 20),
|
|
"<=" => (mk_type!(Nat -> Nat -> Bool), (), 20),
|
|
"==" => (mk_type!(Nat -> Nat -> Bool), (), 20),
|
|
"=" => (mk_type!(Unit), (), 20), //TODO not sure what the type of this should be b/c special fmr
|
|
"<=>" => (mk_type!(Nat -> Nat -> Order), (), 20), //TODO figure out how to treat Order
|
|
};
|
|
}
|