diff --git a/schala-lang/language/src/builtin.rs b/schala-lang/language/src/builtin.rs index e309c15..dddcb2c 100644 --- a/schala-lang/language/src/builtin.rs +++ b/schala-lang/language/src/builtin.rs @@ -3,30 +3,8 @@ use std::collections::HashMap; use std::fmt; use crate::tokenizing::TokenKind; -use self::BuiltinTypeSpecifier::*; -use self::BuiltinTConst::*; - - -#[derive(Debug, PartialEq, Clone)] -pub enum BuiltinTypeSpecifier { - Const(BuiltinTConst), - Func(Box, Box), -} - -#[derive(Debug, PartialEq, Clone)] -pub enum BuiltinTConst { - Nat, - Int, - Float, - StringT, - Bool, -} - -impl fmt::Display for BuiltinTypeSpecifier { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self) - } -} +use crate::typechecking::{TypeConst, Type}; +use crate::typechecking::TypeConst::*; #[derive(Debug, PartialEq, Clone)] pub struct BinOp { @@ -110,36 +88,45 @@ impl PrefixOp { } */ } + +//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, (BuiltinTypeSpecifier, ())> = + static ref PREFIX_OPS: HashMap<&'static str, (Type, ())> = hashmap! { - "+" => (Func(bx!(Const(Int)), bx!(Const(Int))), ()), - "-" => (Func(bx!(Const(Int)), bx!(Const(Int))), ()), - "!" => (Func(bx!(Const(Bool)), bx!(Const(Bool))), ()), + "+" => (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, (BuiltinTypeSpecifier, (), i32)> = + static ref BINOPS: HashMap<&'static str, (Type, (), i32)> = hashmap! { - "+" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 10), - "-" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 10), - "*" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - "/" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Float))))), (), 20), - "quot" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - "%" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - "++" => (Func(bx!(Const(StringT)), bx!(Func(bx!(Const(StringT)), bx!(Const(StringT))))), (), 30), - "^" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - "&" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - "|" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - ">" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - ">=" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - "<" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - "<=" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - "==" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - "=" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), - "<=>" => (Func(bx!(Const(Nat)), bx!(Func(bx!(Const(Nat)), bx!(Const(Nat))))), (), 20), + "+" => (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 }; } diff --git a/schala-lang/language/src/typechecking.rs b/schala-lang/language/src/typechecking.rs index 4c10b73..fd5787a 100644 --- a/schala-lang/language/src/typechecking.rs +++ b/schala-lang/language/src/typechecking.rs @@ -22,6 +22,32 @@ impl TypeError { } } +#[derive(Debug)] +pub enum Type { + Const(TypeConst), + Arrow(Box, Box) +} + +#[derive(Debug)] +pub enum TypeConst { + Unit, + Nat, + Int, + Float, + StringT, + Bool, + Order, + UserDefined +} + +impl Type { + fn arrow(a: Type, b: Type) -> Type { + Type::Arrow(Box::new(a), Box::new(b)) + } +} + + + /* /// `Type` is parameterized by whether the type variables can be just universal, or universal or /// existential.