Beginnings of type analysis.
This commit is contained in:
parent
8d73a8ea73
commit
734a00ea92
@ -135,6 +135,7 @@ fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use crate::name_analysis::symbol::*;
|
||||
use crate::type_analysis::kinds::*;
|
||||
|
||||
#(#types)*
|
||||
};
|
||||
|
||||
@ -30,6 +30,81 @@ pub mod node {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
pub fn analyzed_kind(&self) -> Kind {
|
||||
match self {
|
||||
Expression::Ternary(ternary_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Or(or_expression) => {todo!()}
|
||||
Expression::And(and_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Comparison(comparison_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Shift(shift_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Additive(additive_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Multiplicative(multiplicative_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Prefix(prefix_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Suffix(suffix_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Literal(literal) => {
|
||||
literal.analyzed_kind()
|
||||
}
|
||||
Expression::Identifier(identifier) => {
|
||||
identifier.analyzed_kind().expect("IdentifierExpression's analyzed_kind not set.").clone()
|
||||
}
|
||||
Expression::Fqn(fqn) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Closure(closure) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::List(list_expression) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Literal {
|
||||
pub fn analyzed_kind(&self) -> Kind {
|
||||
match self {
|
||||
Literal::IntLiteral(_) => {
|
||||
Kind::Primitive(PrimitiveKind::Int.into())
|
||||
}
|
||||
Literal::LongLiteral(_) => {
|
||||
Kind::Primitive(PrimitiveKind::Long.into())
|
||||
}
|
||||
Literal::DoubleLiteral(_) => {
|
||||
Kind::Primitive(PrimitiveKind::Double.into())
|
||||
}
|
||||
Literal::SingleQuoteString(_) => {
|
||||
Kind::Primitive(PrimitiveKind::String.into())
|
||||
}
|
||||
Literal::DString(_) => {
|
||||
todo!()
|
||||
}
|
||||
Literal::BacktickString(_) => {
|
||||
todo!()
|
||||
}
|
||||
Literal::BooleanLiteral(_) => {
|
||||
Kind::Primitive(PrimitiveKind::Boolean.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Parameters {
|
||||
fn default() -> Self {
|
||||
|
||||
@ -3,13 +3,19 @@ use deimos::asm::assemble_ir::assemble_ir_function;
|
||||
use deimos::ast::node::CompilationUnit;
|
||||
use deimos::ir::lower_ast::lower_compilation_unit;
|
||||
use deimos::ir::Ir;
|
||||
use deimos::util::indent_writer::IndentWriter;
|
||||
use deimos::type_analysis::analyze_types;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn compile_to_ir(
|
||||
paths: &[PathBuf],
|
||||
) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> {
|
||||
let compilation_units = name_analysis(&paths)?;
|
||||
let mut compilation_units = name_analysis(&paths)?;
|
||||
|
||||
let type_diagnostics = analyze_types(&mut compilation_units);
|
||||
|
||||
if !type_diagnostics.is_empty() {
|
||||
eprintln!("There were type diagnostics")
|
||||
}
|
||||
|
||||
for compilation_unit in &compilation_units {
|
||||
let cu_irs = lower_compilation_unit(compilation_unit);
|
||||
|
||||
@ -11,6 +11,7 @@ use crate::name_analysis::symbol::{ClassSymbol, ParameterSymbol, PrimitiveTypeSy
|
||||
use std::cell::RefCell;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use crate::type_analysis::kinds::Kind;
|
||||
|
||||
struct CuContext {
|
||||
irs: Vec<Ir>,
|
||||
@ -437,5 +438,6 @@ fn call_to_ir_expression(
|
||||
receiver: &Expression,
|
||||
fn_context: &mut FnContext,
|
||||
) -> IrExpression {
|
||||
todo!()
|
||||
let function_kind = receiver.analyzed_kind().expect_function();
|
||||
todo!("Rework AST nodes so that Call and children have a better api")
|
||||
}
|
||||
|
||||
@ -13,5 +13,6 @@ pub mod name_analysis;
|
||||
pub mod object_file;
|
||||
pub mod parser;
|
||||
pub mod std_core;
|
||||
pub mod type_analysis;
|
||||
pub mod util;
|
||||
pub mod vm;
|
||||
|
||||
@ -2,12 +2,13 @@ use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||
use crate::name_analysis::symbol::Symbol;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
use crate::type_analysis::kinds::Kind;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VariableSymbol {
|
||||
declared_name: Rc<str>,
|
||||
is_mutable: bool,
|
||||
source_definition: Option<SourceDefinition>,
|
||||
analyzed_kind: Option<Kind>,
|
||||
}
|
||||
|
||||
impl VariableSymbol {
|
||||
@ -20,6 +21,7 @@ impl VariableSymbol {
|
||||
declared_name: Rc::from(declared_name),
|
||||
is_mutable,
|
||||
source_definition,
|
||||
analyzed_kind: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,6 +36,14 @@ impl VariableSymbol {
|
||||
pub fn is_mutable(&self) -> bool {
|
||||
self.is_mutable
|
||||
}
|
||||
|
||||
pub fn set_analyzed_kind(&mut self, analyzed_kind: Kind) {
|
||||
self.analyzed_kind = Some(analyzed_kind);
|
||||
}
|
||||
|
||||
pub fn analyzed_kind(&self) -> Option<&Kind> {
|
||||
self.analyzed_kind.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Symbol for VariableSymbol {
|
||||
|
||||
@ -1224,6 +1224,8 @@ IdentifierExpression:
|
||||
fields:
|
||||
- expressible_symbol:
|
||||
kind: ExpressibleSymbol
|
||||
- analyzed_kind:
|
||||
kind: Kind
|
||||
ListExpression:
|
||||
struct:
|
||||
children:
|
||||
|
||||
27
src/type_analysis/kinds/class_kind.rs
Normal file
27
src/type_analysis/kinds/class_kind.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use std::fmt::Display;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub struct ClassKind {
|
||||
fqn: Rc<str>
|
||||
}
|
||||
|
||||
impl ClassKind {
|
||||
pub fn new(fqn: &str) -> Self {
|
||||
Self { fqn: fqn.into() }
|
||||
}
|
||||
|
||||
pub fn fqn(&self) -> &str {
|
||||
&self.fqn
|
||||
}
|
||||
|
||||
pub fn fqn_owned(&self) -> Rc<str> {
|
||||
self.fqn.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ClassKind {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
write!(f, "{}", self.fqn)
|
||||
}
|
||||
}
|
||||
27
src/type_analysis/kinds/function_kind.rs
Normal file
27
src/type_analysis/kinds/function_kind.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub struct FunctionKind {
|
||||
fqn: Rc<str>,
|
||||
}
|
||||
|
||||
impl FunctionKind {
|
||||
pub fn new(fqn: &str) -> Self {
|
||||
Self { fqn: fqn.into() }
|
||||
}
|
||||
|
||||
pub fn fqn(&self) -> &str {
|
||||
&self.fqn
|
||||
}
|
||||
|
||||
pub fn fqn_owned(&self) -> Rc<str> {
|
||||
self.fqn.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FunctionKind {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.fqn)
|
||||
}
|
||||
}
|
||||
40
src/type_analysis/kinds/mod.rs
Normal file
40
src/type_analysis/kinds/mod.rs
Normal file
@ -0,0 +1,40 @@
|
||||
pub use crate::type_analysis::kinds::class_kind::ClassKind;
|
||||
pub use crate::type_analysis::kinds::function_kind::FunctionKind;
|
||||
pub use crate::type_analysis::kinds::primitive_kind::PrimitiveKind;
|
||||
use std::fmt::Display;
|
||||
|
||||
pub mod class_kind;
|
||||
pub mod function_kind;
|
||||
pub mod primitive_kind;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub enum Kind {
|
||||
Primitive(Box<PrimitiveKind>),
|
||||
Class(Box<ClassKind>),
|
||||
Function(Box<FunctionKind>),
|
||||
}
|
||||
|
||||
impl Kind {
|
||||
pub fn expect_function(&self) -> &FunctionKind {
|
||||
match self {
|
||||
Kind::Function(function_kind) => function_kind,
|
||||
_ => panic!("Expected FunctionKind, found {:?}", self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Kind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Kind::Primitive(primitive_kind) => {
|
||||
write!(f, "{}", primitive_kind)
|
||||
}
|
||||
Kind::Class(class_kind) => {
|
||||
write!(f, "{}", class_kind)
|
||||
}
|
||||
Kind::Function(function_kind) => {
|
||||
write!(f, "{}", function_kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/type_analysis/kinds/primitive_kind.rs
Normal file
24
src/type_analysis/kinds/primitive_kind.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use std::fmt::Display;
|
||||
use crate::type_analysis::kinds::Kind;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub enum PrimitiveKind {
|
||||
Byte,
|
||||
Char,
|
||||
Short,
|
||||
Int,
|
||||
Long,
|
||||
Float,
|
||||
Double,
|
||||
Boolean,
|
||||
String,
|
||||
Array { inner_type: Kind },
|
||||
Any,
|
||||
Void,
|
||||
}
|
||||
|
||||
impl Display for PrimitiveKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
232
src/type_analysis/mod.rs
Normal file
232
src/type_analysis/mod.rs
Normal file
@ -0,0 +1,232 @@
|
||||
pub mod kinds;
|
||||
|
||||
use crate::ast::node::{
|
||||
AdditiveExpression, CompilationUnit, Expression, ExpressionStatement, Function,
|
||||
FunctionBlockBody, FunctionBody, IdentifierExpression, ModuleLevelDeclaration, Statement,
|
||||
VariableDeclaration,
|
||||
};
|
||||
use crate::diagnostic::DmDiagnostic;
|
||||
use crate::name_analysis::symbol::ExpressibleSymbol;
|
||||
use crate::type_analysis::kinds::class_kind::ClassKind;
|
||||
use crate::type_analysis::kinds::function_kind::FunctionKind;
|
||||
use crate::type_analysis::kinds::Kind;
|
||||
use codespan_reporting::files::Files;
|
||||
|
||||
pub fn analyze_types(compilation_units: &mut [CompilationUnit]) -> Vec<DmDiagnostic> {
|
||||
let mut diagnostics: Vec<DmDiagnostic> = vec![];
|
||||
for compilation_unit in compilation_units {
|
||||
ta_compilation_unit(compilation_unit, &mut diagnostics);
|
||||
}
|
||||
diagnostics
|
||||
}
|
||||
|
||||
fn ta_compilation_unit(
|
||||
compilation_unit: &mut CompilationUnit,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
for module_level_declaration in compilation_unit.module_level_declarations_mut() {
|
||||
ta_module_level_declaration(module_level_declaration, diagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
fn ta_module_level_declaration(
|
||||
module_level_declaration: &mut ModuleLevelDeclaration,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
match module_level_declaration {
|
||||
ModuleLevelDeclaration::Module(module) => {
|
||||
todo!()
|
||||
}
|
||||
ModuleLevelDeclaration::Interface(interface) => {
|
||||
todo!()
|
||||
}
|
||||
ModuleLevelDeclaration::Class(class) => {
|
||||
todo!()
|
||||
}
|
||||
ModuleLevelDeclaration::Function(function) => {
|
||||
ta_function(function, diagnostics);
|
||||
}
|
||||
ModuleLevelDeclaration::PlatformFunction(platform_function) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ta_function(function: &mut Function, diagnostics: &mut Vec<DmDiagnostic>) {
|
||||
ta_function_body(function.function_body_mut(), diagnostics);
|
||||
}
|
||||
|
||||
fn ta_function_body(function_body: &mut FunctionBody, diagnostics: &mut Vec<DmDiagnostic>) {
|
||||
match function_body {
|
||||
FunctionBody::FunctionAliasBody(function_alias_body) => {
|
||||
todo!()
|
||||
}
|
||||
FunctionBody::FunctionEqualsBody(function_equals_body) => {
|
||||
todo!()
|
||||
}
|
||||
FunctionBody::FunctionBlockBody(function_block_body) => {
|
||||
ta_function_block_body(function_block_body, diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ta_function_block_body(
|
||||
function_block_body: &mut FunctionBlockBody,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
for statement in function_block_body.statements_mut() {
|
||||
ta_statement(statement, diagnostics);
|
||||
}
|
||||
}
|
||||
|
||||
fn ta_statement(statement: &mut Statement, diagnostics: &mut Vec<DmDiagnostic>) {
|
||||
match statement {
|
||||
Statement::VariableDeclaration(variable_declaration) => {
|
||||
ta_variable_declaration(variable_declaration, diagnostics);
|
||||
}
|
||||
Statement::AssignmentStatement(assignment_statement) => {
|
||||
todo!()
|
||||
}
|
||||
Statement::ExpressionStatement(expression_statement) => {
|
||||
ta_expression_statement(expression_statement, diagnostics);
|
||||
}
|
||||
Statement::UseStatement(use_statement) => {
|
||||
todo!()
|
||||
}
|
||||
Statement::IfStatement(if_statement) => {
|
||||
todo!()
|
||||
}
|
||||
Statement::WhileStatement(while_statement) => {
|
||||
todo!()
|
||||
}
|
||||
Statement::ForStatement(for_statement) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ta_variable_declaration(
|
||||
variable_declaration: &mut VariableDeclaration,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
// compute type of initializer
|
||||
ta_expression(variable_declaration.expression_mut(), diagnostics);
|
||||
// get type of initializer, and check against to declared type (if present)
|
||||
// todo
|
||||
|
||||
// set type of variable's symbol to analyzed type (initializer type or declared type)
|
||||
let variable_kind = if let Some(declared_type) = variable_declaration.type_use() {
|
||||
todo!("declared types on variable declarations")
|
||||
} else {
|
||||
variable_declaration.expression().analyzed_kind().clone()
|
||||
};
|
||||
|
||||
variable_declaration
|
||||
.variable_symbol_mut()
|
||||
.expect("VariableDeclaration's variable_symbol not set.")
|
||||
.borrow_mut()
|
||||
.set_analyzed_kind(variable_kind)
|
||||
}
|
||||
|
||||
fn ta_expression_statement(
|
||||
expression_statement: &mut ExpressionStatement,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
ta_expression(expression_statement.expression_mut(), diagnostics);
|
||||
}
|
||||
|
||||
fn ta_expression(expression: &mut Expression, diagnostics: &mut Vec<DmDiagnostic>) {
|
||||
match expression {
|
||||
Expression::Ternary(ternary_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Or(or_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::And(and_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Comparison(comparison_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Shift(shift_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Additive(additive_expression) => {
|
||||
ta_additive_expression(additive_expression, diagnostics);
|
||||
}
|
||||
Expression::Multiplicative(multiplicative_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Prefix(prefix_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Suffix(suffix_expression) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Literal(literal) => {
|
||||
// no-op
|
||||
}
|
||||
Expression::Identifier(identifier_expression) => {
|
||||
ta_identifier_expression(identifier_expression);
|
||||
}
|
||||
Expression::Fqn(fqn) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::Closure(closure) => {
|
||||
todo!()
|
||||
}
|
||||
Expression::List(list_expression) => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ta_additive_expression(
|
||||
additive_expression: &mut AdditiveExpression,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
ta_expression(additive_expression.left_mut(), diagnostics);
|
||||
ta_expression(additive_expression.rhs_mut().expression_mut(), diagnostics);
|
||||
|
||||
let left_kind = additive_expression.left().analyzed_kind();
|
||||
let right_kind = additive_expression.rhs().expression().analyzed_kind();
|
||||
|
||||
if left_kind != right_kind {
|
||||
diagnostics.push(DmDiagnostic::error().with_message(&format!(
|
||||
"Incompatible types for additive expression: {} vs. {}",
|
||||
left_kind, right_kind
|
||||
)));
|
||||
todo!("Error file_id and range; set Error type on additive expression")
|
||||
} else {
|
||||
todo!("set analyzed type for additive expression")
|
||||
}
|
||||
}
|
||||
|
||||
fn ta_identifier_expression(identifier_expression: &mut IdentifierExpression) {
|
||||
let expressible_symbol = identifier_expression
|
||||
.expressible_symbol()
|
||||
.expect("IdentifierExpression's expressible_symbol must be set before type analysis.");
|
||||
let kind = match expressible_symbol {
|
||||
ExpressibleSymbol::Class(class_symbol) => {
|
||||
let class_kind = ClassKind::new(&class_symbol.borrow().fqn_formatted());
|
||||
Kind::Class(class_kind.into())
|
||||
}
|
||||
ExpressibleSymbol::Function(function_symbol) => {
|
||||
let function_kind = FunctionKind::new(&function_symbol.borrow().fqn_formatted());
|
||||
Kind::Function(function_kind.into())
|
||||
}
|
||||
ExpressibleSymbol::ClassMember(class_member_symbol) => {
|
||||
todo!()
|
||||
}
|
||||
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
||||
todo!()
|
||||
}
|
||||
ExpressibleSymbol::Variable(variable_symbol) => variable_symbol
|
||||
.borrow()
|
||||
.analyzed_kind()
|
||||
.expect("VariableSymbol's analyzed_kind not set.")
|
||||
.clone(),
|
||||
};
|
||||
identifier_expression.set_analyzed_kind(kind);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user