diff --git a/schala-lang/language/src/ast/mod.rs b/schala-lang/language/src/ast/mod.rs index 4a06e67..f0883d5 100644 --- a/schala-lang/language/src/ast/mod.rs +++ b/schala-lang/language/src/ast/mod.rs @@ -6,7 +6,7 @@ mod walker; mod visitor; mod visitor_test; mod operators; -pub use operators::*; +pub use operators::{PrefixOp, BinOp}; pub use visitor::ASTVisitor; pub use walker::walk_ast; use crate::tokenizing::Location; diff --git a/schala-lang/language/src/ast/operators.rs b/schala-lang/language/src/ast/operators.rs index 0e3f2b0..d02b6c5 100644 --- a/schala-lang/language/src/ast/operators.rs +++ b/schala-lang/language/src/ast/operators.rs @@ -1,20 +1,21 @@ use std::rc::Rc; -use std::str::FromStr; use crate::tokenizing::TokenKind; -use crate::builtin::Builtin; #[derive(Debug, PartialEq, Clone)] pub struct PrefixOp { sigil: Rc, - pub builtin: Option, } impl PrefixOp { - #[allow(dead_code)] - pub fn sigil(&self) -> &Rc { + pub fn from_sigil(sigil: &str) -> PrefixOp { + PrefixOp { sigil: Rc::new(sigil.to_string()) } + } + + pub fn sigil(&self) -> &str { &self.sigil } + pub fn is_prefix(op: &str) -> bool { match op { "+" => true, @@ -25,37 +26,20 @@ impl PrefixOp { } } -impl FromStr for PrefixOp { - type Err = (); - - fn from_str(s: &str) -> Result { - use Builtin::*; - - let builtin = match s { - "+" => Ok(Increment), - "-" => Ok(Negate), - "!" => Ok(BooleanNot), - _ => Err(()) - }; - - builtin.map(|builtin| PrefixOp { sigil: Rc::new(s.to_string()), builtin: Some(builtin) }) - } -} - #[derive(Debug, PartialEq, Clone)] pub struct BinOp { sigil: Rc, - pub builtin: Option, } impl BinOp { pub fn from_sigil(sigil: &str) -> BinOp { - let builtin = Builtin::from_str(sigil).ok(); - BinOp { sigil: Rc::new(sigil.to_string()), builtin } + BinOp { sigil: Rc::new(sigil.to_string()) } } - pub fn sigil(&self) -> &Rc { + + pub fn sigil(&self) -> &str { &self.sigil } + pub fn from_sigil_token(tok: &TokenKind) -> Option { let s = token_kind_to_sigil(tok)?; Some(BinOp::from_sigil(s)) diff --git a/schala-lang/language/src/builtin.rs b/schala-lang/language/src/builtin.rs index 09176cd..0d12bda 100644 --- a/schala-lang/language/src/builtin.rs +++ b/schala-lang/language/src/builtin.rs @@ -1,7 +1,10 @@ use std::str::FromStr; +use std::convert::TryFrom; use crate::typechecking::{TypeConst, Type}; +use crate::ast::{BinOp, PrefixOp}; +/// "Builtin" computational operations with some kind of semantics, mostly mathematical operations. #[derive(Debug, Clone, Copy, PartialEq)] pub enum Builtin { Add, @@ -66,6 +69,29 @@ impl Builtin { } } +impl TryFrom<&BinOp> for Builtin { + type Error = (); + + fn try_from(binop: &BinOp) -> Result { + FromStr::from_str(binop.sigil()) + } +} + +impl TryFrom<&PrefixOp> for Builtin { + type Error = (); + + fn try_from(prefix_op: &PrefixOp) -> Result { + use Builtin::*; + + match prefix_op.sigil() { + "+" => Ok(Increment), + "-" => Ok(Negate), + "!" => Ok(BooleanNot), + _ => Err(()) + } + } +} + impl FromStr for Builtin { type Err = (); diff --git a/schala-lang/language/src/parsing/mod.rs b/schala-lang/language/src/parsing/mod.rs index 93e7115..aac1534 100644 --- a/schala-lang/language/src/parsing/mod.rs +++ b/schala-lang/language/src/parsing/mod.rs @@ -161,7 +161,6 @@ mod test; use std::rc::Rc; -use std::str::FromStr; use crate::tokenizing::*; use crate::tokenizing::Kw::*; @@ -658,7 +657,7 @@ impl Parser { _ => unreachable!(), }; let expr = self.primary()?; - let prefix_op = PrefixOp::from_str(sigil.as_str()).unwrap(); + let prefix_op = PrefixOp::from_sigil(sigil.as_str()); Ok(Expression::new( self.id_store.fresh(), ExpressionKind::PrefixExp(prefix_op, Box::new(expr)) diff --git a/schala-lang/language/src/parsing/test.rs b/schala-lang/language/src/parsing/test.rs index 4575953..9bfdfe4 100644 --- a/schala-lang/language/src/parsing/test.rs +++ b/schala-lang/language/src/parsing/test.rs @@ -1,6 +1,5 @@ #![cfg(test)] use std::rc::Rc; -use std::str::FromStr; use crate::tokenizing::Location; use super::{Parser, ParseResult, tokenize}; @@ -109,7 +108,7 @@ macro_rules! binexp { ($op:expr, $lhs:expr, $rhs:expr) => { BinExp(BinOp::from_sigil($op), bx!(Expression::new(ItemIdStore::new_id(), $lhs).into()), bx!(Expression::new(ItemIdStore::new_id(), $rhs).into())) } } macro_rules! prefexp { - ($op:expr, $lhs:expr) => { PrefixExp(PrefixOp::from_str($op).unwrap(), bx!(Expression::new(ItemIdStore::new_id(), $lhs).into())) } + ($op:expr, $lhs:expr) => { PrefixExp(PrefixOp::from_sigil($op), bx!(Expression::new(ItemIdStore::new_id(), $lhs).into())) } } macro_rules! exst { ($expr_type:expr) => { make_statement(StatementKind::Expression(Expression::new(ItemIdStore::new_id(), $expr_type).into())) }; diff --git a/schala-lang/language/src/reduced_ast.rs b/schala-lang/language/src/reduced_ast.rs index 839ef3c..b3a9a6c 100644 --- a/schala-lang/language/src/reduced_ast.rs +++ b/schala-lang/language/src/reduced_ast.rs @@ -14,6 +14,7 @@ //! built from the ReducedAST. use std::rc::Rc; use std::str::FromStr; +use std::convert::TryFrom; use crate::ast::*; use crate::symbol_table::{Symbol, SymbolSpec, SymbolTable, FullyQualifiedSymbolName}; @@ -337,7 +338,8 @@ impl<'a> Reducer<'a> { } fn prefix(&mut self, prefix: &PrefixOp, arg: &Box) -> Expr { - match prefix.builtin { + let builtin: Option = TryFrom::try_from(prefix).ok(); + match builtin { Some(op) => { let f = Box::new(Expr::Func(Func::BuiltIn(op))); Expr::Call { f, args: vec![self.expression(arg)] } diff --git a/schala-lang/language/src/typechecking.rs b/schala-lang/language/src/typechecking.rs index 802edbd..3f8fa49 100644 --- a/schala-lang/language/src/typechecking.rs +++ b/schala-lang/language/src/typechecking.rs @@ -1,8 +1,10 @@ use std::rc::Rc; use std::fmt::Write; +use std::convert::TryFrom; use ena::unify::{UnifyKey, InPlaceUnificationTable, UnificationTable, EqUnifyValue}; +use crate::builtin::Builtin; use crate::ast::*; use crate::util::ScopeStack; use crate::util::deref_optional_box; @@ -332,7 +334,8 @@ impl<'a> TypeContext<'a> { } fn prefix(&mut self, op: &PrefixOp, expr: &Expression) -> InferResult { - let tf = match op.builtin.map(|b| b.get_type()) { + let builtin: Option = TryFrom::try_from(op).ok(); + let tf = match builtin.map(|b| b.get_type()) { Some(ty) => ty, None => return TypeError::new("no type found") }; @@ -342,7 +345,8 @@ impl<'a> TypeContext<'a> { } fn binexp(&mut self, op: &BinOp, lhs: &Expression, rhs: &Expression) -> InferResult { - let tf = match op.builtin.map(|b| b.get_type()) { + let builtin: Option = TryFrom::try_from(op).ok(); + let tf = match builtin.map(|b| b.get_type()) { Some(ty) => ty, None => return TypeError::new("no type found"), };