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,8 +1,9 @@
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)]
@ -36,6 +37,7 @@ pub enum Builtin {
} }
impl Builtin { impl Builtin {
#[allow(dead_code)]
pub fn get_type(&self) -> Type { pub fn get_type(&self) -> Type {
use Builtin::*; use Builtin::*;
match self { match self {
@ -59,12 +61,12 @@ impl Builtin {
Comparison => ty!(Nat -> Nat -> Ordering), Comparison => ty!(Nat -> Nat -> Ordering),
FieldAccess => ty!(Unit), FieldAccess => ty!(Unit),
IOPrint => ty!(Unit), IOPrint => ty!(Unit),
IOPrintLn => ty!(Unit) , IOPrintLn => ty!(Unit),
IOGetLine => ty!(StringT), IOGetLine => ty!(StringT),
Assignment => ty!(Unit), Assignment => ty!(Unit),
Concatenate => ty!(StringT -> StringT -> StringT), Concatenate => ty!(StringT -> StringT -> StringT),
Increment => ty!(Nat -> Int), Increment => ty!(Nat -> Int),
Negate => ty!(Nat -> Int) Negate => ty!(Nat -> Int),
} }
} }
} }
@ -87,7 +89,7 @@ impl TryFrom<&PrefixOp> for Builtin {
"+" => Ok(Increment), "+" => Ok(Increment),
"-" => Ok(Negate), "-" => Ok(Negate),
"!" => Ok(BooleanNot), "!" => Ok(BooleanNot),
_ => Err(()) _ => Err(()),
} }
} }
} }
@ -122,7 +124,7 @@ impl FromStr for Builtin {
"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>