From 08590430e45cbfcd1cb7bbf8c750f6412e313abe Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Wed, 27 Oct 2021 01:11:46 -0700 Subject: [PATCH] Move minimal typechecking code into directory-style module --- schala-lang/language/src/builtin.rs | 210 +++++++++--------- schala-lang/language/src/error.rs | 3 +- schala-lang/language/src/lib.rs | 3 +- schala-lang/language/src/reduced_ir/types.rs | 2 +- schala-lang/language/src/schala.rs | 9 +- schala-lang/language/src/symbol_table/mod.rs | 2 +- .../language/src/tree_walk_eval/mod.rs | 2 +- .../language/src/type_inference/mod.rs | 73 ++++++ schala-lang/language/src/util.rs | 6 +- 9 files changed, 191 insertions(+), 119 deletions(-) create mode 100644 schala-lang/language/src/type_inference/mod.rs diff --git a/schala-lang/language/src/builtin.rs b/schala-lang/language/src/builtin.rs index 0d12bda..fec7a9f 100644 --- a/schala-lang/language/src/builtin.rs +++ b/schala-lang/language/src/builtin.rs @@ -1,128 +1,130 @@ -use std::str::FromStr; -use std::convert::TryFrom; +use std::{convert::TryFrom, str::FromStr}; -use crate::typechecking::{TypeConst, Type}; -use crate::ast::{BinOp, PrefixOp}; +use crate::{ + ast::{BinOp, PrefixOp}, + type_inference::Type, +}; /// "Builtin" computational operations with some kind of semantics, mostly mathematical operations. #[derive(Debug, Clone, Copy, PartialEq)] pub enum Builtin { - Add, - Increment, - Subtract, - Negate, - Multiply, - Divide, - Quotient, - Modulo, - Exponentiation, - BitwiseAnd, - BitwiseOr, - BooleanAnd, - BooleanOr, - BooleanNot, - Equality, - LessThan, - LessThanOrEqual, - GreaterThan, - GreaterThanOrEqual, - Comparison, - FieldAccess, - IOPrint, - IOPrintLn, - IOGetLine, - Assignment, - Concatenate, + Add, + Increment, + Subtract, + Negate, + Multiply, + Divide, + Quotient, + Modulo, + Exponentiation, + BitwiseAnd, + BitwiseOr, + BooleanAnd, + BooleanOr, + BooleanNot, + Equality, + LessThan, + LessThanOrEqual, + GreaterThan, + GreaterThanOrEqual, + Comparison, + FieldAccess, + IOPrint, + IOPrintLn, + IOGetLine, + Assignment, + Concatenate, } impl Builtin { - pub fn get_type(&self) -> Type { - use Builtin::*; - match self { - Add => ty!(Nat -> Nat -> Nat), - Subtract => ty!(Nat -> Nat -> Nat), - Multiply => ty!(Nat -> Nat -> Nat), - Divide => ty!(Nat -> Nat -> Float), - Quotient => ty!(Nat -> Nat -> Nat), - Modulo => ty!(Nat -> Nat -> Nat), - Exponentiation => ty!(Nat -> Nat -> Nat), - BitwiseAnd => ty!(Nat -> Nat -> Nat), - BitwiseOr => ty!(Nat -> Nat -> Nat), - BooleanAnd => ty!(Bool -> Bool -> Bool), - BooleanOr => ty!(Bool -> Bool -> Bool), - BooleanNot => ty!(Bool -> Bool), - Equality => ty!(Nat -> Nat -> Bool), - LessThan => ty!(Nat -> Nat -> Bool), - LessThanOrEqual => ty!(Nat -> Nat -> Bool), - GreaterThan => ty!(Nat -> Nat -> Bool), - GreaterThanOrEqual => ty!(Nat -> Nat -> Bool), - Comparison => ty!(Nat -> Nat -> Ordering), - FieldAccess => ty!(Unit), - IOPrint => ty!(Unit), - IOPrintLn => ty!(Unit) , - IOGetLine => ty!(StringT), - Assignment => ty!(Unit), - Concatenate => ty!(StringT -> StringT -> StringT), - Increment => ty!(Nat -> Int), - Negate => ty!(Nat -> Int) + #[allow(dead_code)] + pub fn get_type(&self) -> Type { + use Builtin::*; + match self { + Add => ty!(Nat -> Nat -> Nat), + Subtract => ty!(Nat -> Nat -> Nat), + Multiply => ty!(Nat -> Nat -> Nat), + Divide => ty!(Nat -> Nat -> Float), + Quotient => ty!(Nat -> Nat -> Nat), + Modulo => ty!(Nat -> Nat -> Nat), + Exponentiation => ty!(Nat -> Nat -> Nat), + BitwiseAnd => ty!(Nat -> Nat -> Nat), + BitwiseOr => ty!(Nat -> Nat -> Nat), + BooleanAnd => ty!(Bool -> Bool -> Bool), + BooleanOr => ty!(Bool -> Bool -> Bool), + BooleanNot => ty!(Bool -> Bool), + Equality => ty!(Nat -> Nat -> Bool), + LessThan => ty!(Nat -> Nat -> Bool), + LessThanOrEqual => ty!(Nat -> Nat -> Bool), + GreaterThan => ty!(Nat -> Nat -> Bool), + GreaterThanOrEqual => ty!(Nat -> Nat -> Bool), + Comparison => ty!(Nat -> Nat -> Ordering), + FieldAccess => ty!(Unit), + IOPrint => ty!(Unit), + IOPrintLn => ty!(Unit), + IOGetLine => ty!(StringT), + Assignment => ty!(Unit), + Concatenate => ty!(StringT -> StringT -> StringT), + Increment => ty!(Nat -> Int), + Negate => ty!(Nat -> Int), + } } - } } impl TryFrom<&BinOp> for Builtin { - type Error = (); + type Error = (); - fn try_from(binop: &BinOp) -> Result { - FromStr::from_str(binop.sigil()) - } + fn try_from(binop: &BinOp) -> Result { + FromStr::from_str(binop.sigil()) + } } impl TryFrom<&PrefixOp> for Builtin { - type Error = (); + type Error = (); - fn try_from(prefix_op: &PrefixOp) -> Result { - use Builtin::*; + fn try_from(prefix_op: &PrefixOp) -> Result { + use Builtin::*; - match prefix_op.sigil() { - "+" => Ok(Increment), - "-" => Ok(Negate), - "!" => Ok(BooleanNot), - _ => Err(()) + match prefix_op.sigil() { + "+" => Ok(Increment), + "-" => Ok(Negate), + "!" => Ok(BooleanNot), + _ => Err(()), + } } - } } impl FromStr for Builtin { - type Err = (); + type Err = (); - fn from_str(s: &str) -> Result { - 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(()) - }) - } + fn from_str(s: &str) -> Result { + 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(()), + }) + } } diff --git a/schala-lang/language/src/error.rs b/schala-lang/language/src/error.rs index cf24816..1bf28ec 100644 --- a/schala-lang/language/src/error.rs +++ b/schala-lang/language/src/error.rs @@ -2,7 +2,7 @@ use crate::parsing::ParseError; use crate::schala::{SourceReference, Stage}; use crate::tokenizing::{Location, Token, TokenKind}; use crate::symbol_table::SymbolError; -use crate::typechecking::TypeError; +use crate::type_inference::TypeError; pub struct SchalaError { errors: Vec, @@ -19,6 +19,7 @@ impl SchalaError { } } + #[allow(dead_code)] pub(crate) fn from_type_error(err: TypeError) -> Self { Self { formatted_parse_error: None, diff --git a/schala-lang/language/src/lib.rs b/schala-lang/language/src/lib.rs index dcd4fa1..c5675d7 100644 --- a/schala-lang/language/src/lib.rs +++ b/schala-lang/language/src/lib.rs @@ -13,8 +13,9 @@ extern crate derivative; #[macro_use] mod util; + #[macro_use] -mod typechecking; +mod type_inference; mod ast; mod parsing; diff --git a/schala-lang/language/src/reduced_ir/types.rs b/schala-lang/language/src/reduced_ir/types.rs index 2a85521..807b10c 100644 --- a/schala-lang/language/src/reduced_ir/types.rs +++ b/schala-lang/language/src/reduced_ir/types.rs @@ -4,7 +4,7 @@ use std::convert::From; use crate::builtin::Builtin; use crate::symbol_table::{DefId, SymbolTable}; -use crate::typechecking::TypeId; +use crate::type_inference::TypeId; //TODO most of these Clone impls only exist to support function application, because the //tree-walking evaluator moves the reduced IR members. diff --git a/schala-lang/language/src/schala.rs b/schala-lang/language/src/schala.rs index 7255c2c..8001c8e 100644 --- a/schala-lang/language/src/schala.rs +++ b/schala-lang/language/src/schala.rs @@ -5,7 +5,7 @@ use schala_repl::{ use stopwatch::Stopwatch; use crate::{ - error::SchalaError, parsing, reduced_ir, symbol_table, tokenizing, tree_walk_eval, typechecking, + error::SchalaError, parsing, reduced_ir, symbol_table, tokenizing, tree_walk_eval, type_inference, }; /// All the state necessary to parse and execute a Schala program are stored in this struct. @@ -17,7 +17,7 @@ pub struct Schala<'a> { /// Keeps track of symbols and scopes symbol_table: symbol_table::SymbolTable, /// Contains information for type-checking - type_context: typechecking::TypeContext<'static>, + type_context: type_inference::TypeContext, /// Schala Parser active_parser: parsing::Parser, @@ -44,8 +44,7 @@ impl<'a> Schala<'a> { Schala { source_reference: SourceReference::new(), symbol_table: symbol_table::SymbolTable::new(), - //state: eval::State::new(), - type_context: typechecking::TypeContext::new(), + type_context: type_inference::TypeContext::new(), active_parser: parsing::Parser::new(), eval_state: tree_walk_eval::State::new(), } @@ -88,7 +87,7 @@ impl<'a> Schala<'a> { // Typechecking // TODO typechecking not working - let _overall_type = self.type_context.typecheck(&ast).map_err(SchalaError::from_type_error); + //let _overall_type = self.type_context.typecheck(&ast).map_err(SchalaError::from_type_error); let reduced_ir = reduced_ir::reduce(&ast, &self.symbol_table); diff --git a/schala-lang/language/src/symbol_table/mod.rs b/schala-lang/language/src/symbol_table/mod.rs index 0ff2089..ea89514 100644 --- a/schala-lang/language/src/symbol_table/mod.rs +++ b/schala-lang/language/src/symbol_table/mod.rs @@ -8,7 +8,7 @@ use crate::ast::{ Variant, VariantKind, }; use crate::tokenizing::Location; -use crate::typechecking::TypeId; +use crate::type_inference::TypeId; mod resolver; mod symbol_trie; diff --git a/schala-lang/language/src/tree_walk_eval/mod.rs b/schala-lang/language/src/tree_walk_eval/mod.rs index 5923c54..9e0189d 100644 --- a/schala-lang/language/src/tree_walk_eval/mod.rs +++ b/schala-lang/language/src/tree_walk_eval/mod.rs @@ -6,7 +6,7 @@ use crate::{ Alternative, Callable, Expression, FunctionDefinition, Literal, Lookup, Pattern, ReducedIR, Statement, }, symbol_table::DefId, - typechecking::TypeId, + type_inference::TypeId, util::ScopeStack, }; diff --git a/schala-lang/language/src/type_inference/mod.rs b/schala-lang/language/src/type_inference/mod.rs new file mode 100644 index 0000000..4bfdf82 --- /dev/null +++ b/schala-lang/language/src/type_inference/mod.rs @@ -0,0 +1,73 @@ +use std::{fmt, rc::Rc}; + +//TODO need to hook this into the actual typechecking system somehow +#[derive(Debug, Clone)] +pub struct TypeId { + local_name: Rc, +} + +impl fmt::Display for TypeId { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "TypeId:{}", self.local_name()) + } +} + +impl TypeId { + //TODO this is definitely incomplete + pub fn lookup_name(name: &str) -> TypeId { + TypeId { local_name: Rc::new(name.to_string()) } + } + + pub fn local_name(&self) -> &str { + self.local_name.as_ref() + } +} + +pub struct TypeContext; + +impl TypeContext { + pub fn new() -> Self { + Self + } +} + +#[derive(Debug, Clone)] +pub struct TypeError { + pub msg: String, +} + +#[allow(dead_code)] +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum TypeConst { + Unit, + Nat, + Int, + Float, + StringT, + Bool, + Ordering, +} + +#[allow(dead_code)] +#[derive(Debug, Clone, PartialEq)] +pub enum Type { + Const(TypeConst), + //Var(TypeVar), + Arrow { params: Vec, ret: Box }, + Compound { ty_name: String, args: Vec }, +} + +macro_rules! ty { + ($type_name:ident) => { + Type::Const(crate::type_inference::TypeConst::$type_name) + }; + ($t1:ident -> $t2:ident) => { + Type::Arrow { params: vec![ty!($t1)], ret: box ty!($t2) } + }; + ($t1:ident -> $t2:ident -> $t3:ident) => { + Type::Arrow { params: vec![ty!($t1), ty!($t2)], ret: box ty!($t3) } + }; + ($type_list:ident, $ret_type:ident) => { + Type::Arrow { params: $type_list, ret: box $ret_type } + }; +} diff --git a/schala-lang/language/src/util.rs b/schala-lang/language/src/util.rs index 87bd4bf..4856f7d 100644 --- a/schala-lang/language/src/util.rs +++ b/schala-lang/language/src/util.rs @@ -1,8 +1,4 @@ -use std::{cmp::Eq, collections::HashMap, hash::Hash, ops::Deref}; - -pub fn deref_optional_box(x: &Option>) -> Option<&T> { - x.as_ref().map(Deref::deref) -} +use std::{cmp::Eq, collections::HashMap, hash::Hash}; #[derive(Default, Debug)] pub struct ScopeStack<'a, T: 'a, V: 'a, N = String>