Move minimal typechecking code into directory-style module

This commit is contained in:
Greg Shuflin 2021-10-27 01:11:46 -07:00
parent 4dd39fe085
commit 08590430e4
9 changed files with 191 additions and 119 deletions

View File

@ -1,128 +1,130 @@
use std::str::FromStr; use std::{convert::TryFrom, str::FromStr};
use std::convert::TryFrom;
use crate::typechecking::{TypeConst, Type}; use crate::{
use crate::ast::{BinOp, PrefixOp}; ast::{BinOp, PrefixOp},
type_inference::Type,
};
/// "Builtin" computational operations with some kind of semantics, mostly mathematical operations. /// "Builtin" computational operations with some kind of semantics, mostly mathematical operations.
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum Builtin { pub enum Builtin {
Add, Add,
Increment, Increment,
Subtract, Subtract,
Negate, Negate,
Multiply, Multiply,
Divide, Divide,
Quotient, Quotient,
Modulo, Modulo,
Exponentiation, Exponentiation,
BitwiseAnd, BitwiseAnd,
BitwiseOr, BitwiseOr,
BooleanAnd, BooleanAnd,
BooleanOr, BooleanOr,
BooleanNot, BooleanNot,
Equality, Equality,
LessThan, LessThan,
LessThanOrEqual, LessThanOrEqual,
GreaterThan, GreaterThan,
GreaterThanOrEqual, GreaterThanOrEqual,
Comparison, Comparison,
FieldAccess, FieldAccess,
IOPrint, IOPrint,
IOPrintLn, IOPrintLn,
IOGetLine, IOGetLine,
Assignment, Assignment,
Concatenate, Concatenate,
} }
impl Builtin { impl Builtin {
pub fn get_type(&self) -> Type { #[allow(dead_code)]
use Builtin::*; pub fn get_type(&self) -> Type {
match self { use Builtin::*;
Add => ty!(Nat -> Nat -> Nat), match self {
Subtract => ty!(Nat -> Nat -> Nat), Add => ty!(Nat -> Nat -> Nat),
Multiply => ty!(Nat -> Nat -> Nat), Subtract => ty!(Nat -> Nat -> Nat),
Divide => ty!(Nat -> Nat -> Float), Multiply => ty!(Nat -> Nat -> Nat),
Quotient => ty!(Nat -> Nat -> Nat), Divide => ty!(Nat -> Nat -> Float),
Modulo => ty!(Nat -> Nat -> Nat), Quotient => ty!(Nat -> Nat -> Nat),
Exponentiation => ty!(Nat -> Nat -> Nat), Modulo => ty!(Nat -> Nat -> Nat),
BitwiseAnd => ty!(Nat -> Nat -> Nat), Exponentiation => ty!(Nat -> Nat -> Nat),
BitwiseOr => ty!(Nat -> Nat -> Nat), BitwiseAnd => ty!(Nat -> Nat -> Nat),
BooleanAnd => ty!(Bool -> Bool -> Bool), BitwiseOr => ty!(Nat -> Nat -> Nat),
BooleanOr => ty!(Bool -> Bool -> Bool), BooleanAnd => ty!(Bool -> Bool -> Bool),
BooleanNot => ty!(Bool -> Bool), BooleanOr => ty!(Bool -> Bool -> Bool),
Equality => ty!(Nat -> Nat -> Bool), BooleanNot => ty!(Bool -> Bool),
LessThan => ty!(Nat -> Nat -> Bool), Equality => ty!(Nat -> Nat -> Bool),
LessThanOrEqual => ty!(Nat -> Nat -> Bool), LessThan => ty!(Nat -> Nat -> Bool),
GreaterThan => ty!(Nat -> Nat -> Bool), LessThanOrEqual => ty!(Nat -> Nat -> Bool),
GreaterThanOrEqual => ty!(Nat -> Nat -> Bool), GreaterThan => ty!(Nat -> Nat -> Bool),
Comparison => ty!(Nat -> Nat -> Ordering), GreaterThanOrEqual => ty!(Nat -> Nat -> Bool),
FieldAccess => ty!(Unit), Comparison => ty!(Nat -> Nat -> Ordering),
IOPrint => ty!(Unit), FieldAccess => ty!(Unit),
IOPrintLn => ty!(Unit) , IOPrint => ty!(Unit),
IOGetLine => ty!(StringT), IOPrintLn => ty!(Unit),
Assignment => ty!(Unit), IOGetLine => ty!(StringT),
Concatenate => ty!(StringT -> StringT -> StringT), Assignment => ty!(Unit),
Increment => ty!(Nat -> Int), Concatenate => ty!(StringT -> StringT -> StringT),
Negate => ty!(Nat -> Int) Increment => ty!(Nat -> Int),
Negate => ty!(Nat -> Int),
}
} }
}
} }
impl TryFrom<&BinOp> for Builtin { impl TryFrom<&BinOp> for Builtin {
type Error = (); type Error = ();
fn try_from(binop: &BinOp) -> Result<Self, Self::Error> { fn try_from(binop: &BinOp) -> Result<Self, Self::Error> {
FromStr::from_str(binop.sigil()) FromStr::from_str(binop.sigil())
} }
} }
impl TryFrom<&PrefixOp> for Builtin { impl TryFrom<&PrefixOp> for Builtin {
type Error = (); type Error = ();
fn try_from(prefix_op: &PrefixOp) -> Result<Self, Self::Error> { fn try_from(prefix_op: &PrefixOp) -> Result<Self, Self::Error> {
use Builtin::*; use Builtin::*;
match prefix_op.sigil() { match prefix_op.sigil() {
"+" => Ok(Increment), "+" => Ok(Increment),
"-" => Ok(Negate), "-" => Ok(Negate),
"!" => Ok(BooleanNot), "!" => Ok(BooleanNot),
_ => Err(()) _ => Err(()),
}
} }
}
} }
impl FromStr for Builtin { impl FromStr for Builtin {
type Err = (); type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
use Builtin::*; use Builtin::*;
Ok(match s { Ok(match s {
"+" => Add, "+" => Add,
"-" => Subtract, "-" => Subtract,
"*" => Multiply, "*" => Multiply,
"/" => Divide, "/" => Divide,
"quot" => Quotient, "quot" => Quotient,
"%" => Modulo, "%" => Modulo,
"++" => Concatenate, "++" => Concatenate,
"^" => Exponentiation, "^" => Exponentiation,
"&" => BitwiseAnd, "&" => BitwiseAnd,
"&&" => BooleanAnd, "&&" => BooleanAnd,
"|" => BitwiseOr, "|" => BitwiseOr,
"||" => BooleanOr, "||" => BooleanOr,
"!" => BooleanNot, "!" => BooleanNot,
">" => GreaterThan, ">" => GreaterThan,
">=" => GreaterThanOrEqual, ">=" => GreaterThanOrEqual,
"<" => LessThan, "<" => LessThan,
"<=" => LessThanOrEqual, "<=" => LessThanOrEqual,
"==" => Equality, "==" => Equality,
"=" => Assignment, "=" => Assignment,
"<=>" => Comparison, "<=>" => Comparison,
"." => FieldAccess, "." => FieldAccess,
"print" => IOPrint, "print" => IOPrint,
"println" => IOPrintLn, "println" => IOPrintLn,
"getline" => IOGetLine, "getline" => IOGetLine,
_ => return Err(()) _ => return Err(()),
}) })
} }
} }

View File

@ -2,7 +2,7 @@ use crate::parsing::ParseError;
use crate::schala::{SourceReference, Stage}; use crate::schala::{SourceReference, Stage};
use crate::tokenizing::{Location, Token, TokenKind}; use crate::tokenizing::{Location, Token, TokenKind};
use crate::symbol_table::SymbolError; use crate::symbol_table::SymbolError;
use crate::typechecking::TypeError; use crate::type_inference::TypeError;
pub struct SchalaError { pub struct SchalaError {
errors: Vec<Error>, errors: Vec<Error>,
@ -19,6 +19,7 @@ impl SchalaError {
} }
} }
#[allow(dead_code)]
pub(crate) fn from_type_error(err: TypeError) -> Self { pub(crate) fn from_type_error(err: TypeError) -> Self {
Self { Self {
formatted_parse_error: None, formatted_parse_error: None,

View File

@ -13,8 +13,9 @@ extern crate derivative;
#[macro_use] #[macro_use]
mod util; mod util;
#[macro_use] #[macro_use]
mod typechecking; mod type_inference;
mod ast; mod ast;
mod parsing; mod parsing;

View File

@ -4,7 +4,7 @@ use std::convert::From;
use crate::builtin::Builtin; use crate::builtin::Builtin;
use crate::symbol_table::{DefId, SymbolTable}; 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 //TODO most of these Clone impls only exist to support function application, because the
//tree-walking evaluator moves the reduced IR members. //tree-walking evaluator moves the reduced IR members.

View File

@ -5,7 +5,7 @@ use schala_repl::{
use stopwatch::Stopwatch; use stopwatch::Stopwatch;
use crate::{ 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. /// 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 /// Keeps track of symbols and scopes
symbol_table: symbol_table::SymbolTable, symbol_table: symbol_table::SymbolTable,
/// Contains information for type-checking /// Contains information for type-checking
type_context: typechecking::TypeContext<'static>, type_context: type_inference::TypeContext,
/// Schala Parser /// Schala Parser
active_parser: parsing::Parser, active_parser: parsing::Parser,
@ -44,8 +44,7 @@ impl<'a> Schala<'a> {
Schala { Schala {
source_reference: SourceReference::new(), source_reference: SourceReference::new(),
symbol_table: symbol_table::SymbolTable::new(), symbol_table: symbol_table::SymbolTable::new(),
//state: eval::State::new(), type_context: type_inference::TypeContext::new(),
type_context: typechecking::TypeContext::new(),
active_parser: parsing::Parser::new(), active_parser: parsing::Parser::new(),
eval_state: tree_walk_eval::State::new(), eval_state: tree_walk_eval::State::new(),
} }
@ -88,7 +87,7 @@ impl<'a> Schala<'a> {
// Typechecking // Typechecking
// TODO typechecking not working // 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); let reduced_ir = reduced_ir::reduce(&ast, &self.symbol_table);

View File

@ -8,7 +8,7 @@ use crate::ast::{
Variant, VariantKind, Variant, VariantKind,
}; };
use crate::tokenizing::Location; use crate::tokenizing::Location;
use crate::typechecking::TypeId; use crate::type_inference::TypeId;
mod resolver; mod resolver;
mod symbol_trie; mod symbol_trie;

View File

@ -6,7 +6,7 @@ use crate::{
Alternative, Callable, Expression, FunctionDefinition, Literal, Lookup, Pattern, ReducedIR, Statement, Alternative, Callable, Expression, FunctionDefinition, Literal, Lookup, Pattern, ReducedIR, Statement,
}, },
symbol_table::DefId, symbol_table::DefId,
typechecking::TypeId, type_inference::TypeId,
util::ScopeStack, util::ScopeStack,
}; };

View File

@ -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<String>,
}
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<Type>, ret: Box<Type> },
Compound { ty_name: String, args: Vec<Type> },
}
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 }
};
}

View File

@ -1,8 +1,4 @@
use std::{cmp::Eq, collections::HashMap, hash::Hash, ops::Deref}; use std::{cmp::Eq, collections::HashMap, hash::Hash};
pub fn deref_optional_box<T>(x: &Option<Box<T>>) -> Option<&T> {
x.as_ref().map(Deref::deref)
}
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct ScopeStack<'a, T: 'a, V: 'a, N = String> pub struct ScopeStack<'a, T: 'a, V: 'a, N = String>