Move minimal typechecking code into directory-style module
This commit is contained in:
parent
4dd39fe085
commit
08590430e4
@ -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 {
|
||||||
@ -64,7 +66,7 @@ impl Builtin {
|
|||||||
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(()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
73
schala-lang/language/src/type_inference/mod.rs
Normal file
73
schala-lang/language/src/type_inference/mod.rs
Normal 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 }
|
||||||
|
};
|
||||||
|
}
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user