schala/schala-lang/language/src/builtin.rs

189 lines
4.6 KiB
Rust
Raw Normal View History

2018-02-23 19:06:37 -08:00
use std::rc::Rc;
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;
use crate::typechecking::{TypeConst, Type};
#[derive(Debug)]
enum Builtin {
Add,
Subtract,
Multiply,
Divide,
Quotient,
Modulo,
Exponentiation,
BitwiseAnd,
BitwiseOr,
BooleanAnd,
BooleanOr,
BooleanNot,
Equality,
LessThan,
2019-08-12 13:49:39 -07:00
LessThanOrEqual,
GreaterThan,
2019-08-12 13:49:39 -07:00
GreaterThanOrEqual,
Comparison,
FieldAccess,
IOPrint,
IOPrintLn,
IOGetLine,
2019-08-12 13:49:39 -07:00
Assignment,
Concatenate,
}
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(())
})
}
}
2018-02-23 19:06:37 -08:00
#[derive(Debug, PartialEq, Clone)]
pub struct BinOp {
2018-02-24 14:39:45 -08:00
sigil: Rc<String>
2018-02-23 19:06:37 -08:00
}
impl BinOp {
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 => "/",
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
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))
}
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 => "/",
LAngleBracket => "<",
RAngleBracket => ">",
2019-06-16 16:07:27 -07:00
Equals => "=",
2018-08-19 20:33:50 -07:00
_ => return None
};
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
}
#[derive(Debug, PartialEq, Clone)]
pub struct PrefixOp {
sigil: Rc<String>
}
2018-02-23 19:06:37 -08:00
impl PrefixOp {
pub fn from_sigil(sigil: &str) -> PrefixOp {
PrefixOp { 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-02-23 19:06:37 -08:00
pub fn is_prefix(op: &str) -> bool {
2018-02-24 17:43:26 -08:00
PREFIX_OPS.get(op).is_some()
2018-02-23 19:06:37 -08:00
}
pub fn get_type(&self) -> Result<Type, String> {
2018-02-26 02:21:21 -08:00
let s = self.sigil.as_str();
PREFIX_OPS.get(s).map(|x| x.0.clone()).ok_or(format!("Prefix op {} not found", s))
}
2018-02-23 19:06:37 -08:00
}
2018-02-24 17:43:26 -08:00
lazy_static! {
static ref PREFIX_OPS: HashMap<&'static str, (Type, ())> =
2018-02-24 17:43:26 -08:00
hashmap! {
"+" => (ty!(Nat -> Int), ()),
"-" => (ty!(Nat -> Int), ()),
"!" => (ty!(Bool -> Bool), ()),
2018-02-24 17:43:26 -08:00
};
}
/* 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
};
}