Added type information to binop definitions
Also started centralizing precedence there too
This commit is contained in:
parent
df86e0c16e
commit
d3ef980dc5
@ -1,15 +1,14 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use schala_lang::typechecking::{Type, TypeResult, TConst};
|
||||||
|
use self::Type::*; use self::TConst::*;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct BinOp {
|
pub struct BinOp {
|
||||||
sigil: Rc<String>
|
sigil: Rc<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
|
||||||
pub struct PrefixOp {
|
|
||||||
sigil: Rc<String>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BinOp {
|
impl BinOp {
|
||||||
pub fn from_sigil(sigil: Rc<String>) -> BinOp {
|
pub fn from_sigil(sigil: Rc<String>) -> BinOp {
|
||||||
BinOp { sigil }
|
BinOp { sigil }
|
||||||
@ -17,10 +16,16 @@ impl BinOp {
|
|||||||
pub fn sigil(&self) -> &Rc<String> {
|
pub fn sigil(&self) -> &Rc<String> {
|
||||||
&self.sigil
|
&self.sigil
|
||||||
}
|
}
|
||||||
|
pub fn get_type(&self) -> TypeResult<Type> {
|
||||||
|
let s = self.sigil.as_str();
|
||||||
|
BINOPS.get(s).map(|x| x.0.clone()).ok_or(format!("Binop {} not found", s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BinOp {
|
||||||
pub fn min_precedence() -> i32 {
|
pub fn min_precedence() -> i32 {
|
||||||
i32::min_value()
|
i32::min_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_precedence(op: &str) -> i32 {
|
pub fn get_precedence(op: &str) -> i32 {
|
||||||
match op {
|
match op {
|
||||||
"+" | "-" => 10,
|
"+" | "-" => 10,
|
||||||
@ -30,6 +35,11 @@ impl BinOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct PrefixOp {
|
||||||
|
sigil: Rc<String>
|
||||||
|
}
|
||||||
|
|
||||||
impl PrefixOp {
|
impl PrefixOp {
|
||||||
pub fn from_sigil(sigil: Rc<String>) -> PrefixOp {
|
pub fn from_sigil(sigil: Rc<String>) -> PrefixOp {
|
||||||
PrefixOp { sigil }
|
PrefixOp { sigil }
|
||||||
@ -44,3 +54,18 @@ impl PrefixOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* the second tuple member is a placeholder for when I want to make evaluation rules tied to the
|
||||||
|
* binop definition */
|
||||||
|
lazy_static! {
|
||||||
|
static ref BINOPS: HashMap<&'static str, (Type, (), i32)> =
|
||||||
|
hashmap! {
|
||||||
|
"+" => (Func(bx!(Const(Int)), bx!(Func(bx!(Const(Int)), bx!(Const(Int))))), (), 10),
|
||||||
|
"-" => (Func(bx!(Const(Int)), bx!(Func(bx!(Const(Int)), bx!(Const(Int))))), (), 10),
|
||||||
|
"*" => (Func(bx!(Const(Int)), bx!(Func(bx!(Const(Int)), bx!(Const(Int))))), (), 20),
|
||||||
|
"/" => (Func(bx!(Const(Int)), bx!(Func(bx!(Const(Int)), bx!(Const(Int))))), (), 20),
|
||||||
|
"%" => (Func(bx!(Const(Int)), bx!(Func(bx!(Const(Int)), bx!(Const(Int))))), (), 20),
|
||||||
|
"++" => (Func(bx!(Const(StringT)), bx!(Func(bx!(Const(StringT)), bx!(Const(StringT))))), (), 30),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -2,7 +2,6 @@ use std::rc::Rc;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use schala_lang::parsing;
|
use schala_lang::parsing;
|
||||||
use schala_lang::builtin;
|
|
||||||
|
|
||||||
pub struct TypeContext {
|
pub struct TypeContext {
|
||||||
bindings: HashMap<Rc<String>, Type>
|
bindings: HashMap<Rc<String>, Type>
|
||||||
@ -45,7 +44,7 @@ impl parsing::TypeName {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type TypeResult<T> = Result<T, String>;
|
pub type TypeResult<T> = Result<T, String>;
|
||||||
|
|
||||||
impl TypeContext {
|
impl TypeContext {
|
||||||
pub fn new() -> TypeContext {
|
pub fn new() -> TypeContext {
|
||||||
@ -100,7 +99,7 @@ impl TypeContext {
|
|||||||
&StringLiteral(_) => Ok(Const(StringT)),
|
&StringLiteral(_) => Ok(Const(StringT)),
|
||||||
&BoolLiteral(_) => Ok(Const(Bool)),
|
&BoolLiteral(_) => Ok(Const(Bool)),
|
||||||
&BinExp(ref op, ref lhs, ref rhs) => { /* remember there are both the haskell convention talk and the write you a haskell ways to do this! */
|
&BinExp(ref op, ref lhs, ref rhs) => { /* remember there are both the haskell convention talk and the write you a haskell ways to do this! */
|
||||||
match self.infer_optype(op)? {
|
match op.get_type()? {
|
||||||
Func(box t1, box Func(box t2, box t3)) => {
|
Func(box t1, box Func(box t2, box t3)) => {
|
||||||
let lhs_ty = self.infer(lhs)?;
|
let lhs_ty = self.infer(lhs)?;
|
||||||
let rhs_ty = self.infer(rhs)?;
|
let rhs_ty = self.infer(rhs)?;
|
||||||
@ -130,11 +129,6 @@ impl TypeContext {
|
|||||||
_ => Err(format!("Type not yet implemented"))
|
_ => Err(format!("Type not yet implemented"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn infer_optype(&mut self, _op: &builtin::BinOp) -> TypeResult<Type> {
|
|
||||||
use self::Type::*; use self::TConst::*;
|
|
||||||
//this is a shim; not all ops are binops from int -> int -> int
|
|
||||||
Ok(Func(bx!(Const(Int)), bx!(Func(bx!(Const(Int)), bx!(Const(Int))))))
|
|
||||||
}
|
|
||||||
fn unify(&mut self, t1: Type, t2: Type) -> TypeResult<Type> {
|
fn unify(&mut self, t1: Type, t2: Type) -> TypeResult<Type> {
|
||||||
use self::Type::*;// use self::TConst::*;
|
use self::Type::*;// use self::TConst::*;
|
||||||
match (t1, t2) {
|
match (t1, t2) {
|
||||||
|
Loading…
Reference in New Issue
Block a user