Merge pull request #8 from mist-go/improved-type-checking
Improved type checking
This commit is contained in:
+4
-4
@@ -1,7 +1,7 @@
|
|||||||
use std::{collections::HashMap, sync::Arc};
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
scope::Refrence,
|
scope::Reference,
|
||||||
top_level::{FunctionSymbol, StructSymbol, TopLevelSymbolScope, TypeSymbol, VarSymbol},
|
top_level::{FunctionSymbol, StructSymbol, TopLevelSymbolScope, TypeSymbol, VarSymbol},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -162,11 +162,11 @@ impl TopLevelHirScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_refrence(&self, name: &String) -> Option<Refrence> {
|
pub fn get_reference(&self, name: &String) -> Option<Reference> {
|
||||||
if let Some(r) = self.functions.get(name) {
|
if let Some(r) = self.functions.get(name) {
|
||||||
Some(Refrence::Func(r.clone()))
|
Some(Reference::Func(r.clone()))
|
||||||
} else if let Some(r) = self.types.get(name) {
|
} else if let Some(r) = self.types.get(name) {
|
||||||
Some(Refrence::Type(r.clone()))
|
Some(Reference::Type(r.clone()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
+59
-16
@@ -11,7 +11,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Refrence {
|
pub enum Reference {
|
||||||
Type(Arc<TypeRef>),
|
Type(Arc<TypeRef>),
|
||||||
Var(Arc<VarRef>),
|
Var(Arc<VarRef>),
|
||||||
Func(Arc<FunctionRef>),
|
Func(Arc<FunctionRef>),
|
||||||
@@ -29,16 +29,10 @@ impl Scope {
|
|||||||
Arc::new(Self::TopLevel(TopLevelHirScope::from_tlss(&tl)))
|
Arc::new(Self::TopLevel(TopLevelHirScope::from_tlss(&tl)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_refrence(&self, name: &String) -> Option<Refrence> {
|
pub fn get_reference(&self, name: &String) -> Option<Reference> {
|
||||||
match self {
|
match self {
|
||||||
Scope::TopLevel(tl) => tl.get_refrence(name),
|
Scope::TopLevel(tl) => tl.get_reference(name),
|
||||||
Scope::Local(l) => l
|
Scope::Local(l) => l.get_reference(name),
|
||||||
.variables
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.get(name)
|
|
||||||
.cloned()
|
|
||||||
.map(Refrence::Var),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,17 +51,29 @@ impl LocalScope {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_reference(&self, name: &String) -> Option<Reference> {
|
||||||
|
self.variables
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.get(name)
|
||||||
|
.cloned()
|
||||||
|
.map(Reference::Var)
|
||||||
|
.or_else(|| self.parent.get_reference(name))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_block(self: &Arc<Self>, block: &mut parser::ast::Block) {
|
pub fn with_block(self: &Arc<Self>, block: &mut parser::ast::Block) {
|
||||||
for statement in &mut block.0 {
|
for statement in &mut block.0 {
|
||||||
match statement {
|
match statement {
|
||||||
Statement::Block(b) => self.clone().with_block(b),
|
Statement::Block(b) => self.clone().with_block(b),
|
||||||
Statement::VarDecl { kind, name, init } => {
|
Statement::VarDecl { name, init, .. } => {
|
||||||
if let Some(init) = init {
|
if let Some(init) = init {
|
||||||
|
let var_type = self.get_type_from_expr(init).unwrap();
|
||||||
|
|
||||||
self.variables.lock().unwrap().insert(
|
self.variables.lock().unwrap().insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
Arc::new(VarRef {
|
Arc::new(VarRef {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
var_type: self.get_type_from_expr(init).unwrap(),
|
var_type,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -80,14 +86,51 @@ impl LocalScope {
|
|||||||
pub fn get_type_from_expr(self: &Arc<Self>, expr: &ast::Expression) -> Option<Arc<TypeRef>> {
|
pub fn get_type_from_expr(self: &Arc<Self>, expr: &ast::Expression) -> Option<Arc<TypeRef>> {
|
||||||
match expr {
|
match expr {
|
||||||
ast::Expression::IntLiteral(_) => {
|
ast::Expression::IntLiteral(_) => {
|
||||||
self.parent.get_refrence(&"int".to_string()).map(|r| {
|
self.parent.get_reference(&"int".to_string()).map(|r| {
|
||||||
if let Refrence::Type(tr) = &r {
|
if let Reference::Type(tr) = &r {
|
||||||
tr.clone()
|
tr.clone()
|
||||||
} else {
|
} else {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ast::Expression::FloatLiteral(_) => {
|
||||||
|
self.parent.get_reference(&"float".to_string()).map(|r| {
|
||||||
|
if let Reference::Type(tr) = &r {
|
||||||
|
tr.clone()
|
||||||
|
} else {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::Expression::BoolLiteral(_) => {
|
||||||
|
self.parent.get_reference(&"bool".to_string()).map(|r| {
|
||||||
|
if let Reference::Type(tr) = &r {
|
||||||
|
tr.clone()
|
||||||
|
} else {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::Expression::StringLiteral(_) => {
|
||||||
|
self.parent.get_reference(&"string".to_string()).map(|r| {
|
||||||
|
if let Reference::Type(tr) = &r {
|
||||||
|
tr.clone()
|
||||||
|
} else {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::Expression::Identifier(id) => match self.get_reference(id) {
|
||||||
|
Some(Reference::Var(var_ref)) => Some(var_ref.var_type.clone()),
|
||||||
|
Some(Reference::Func(func_ref)) => func_ref.return_type.clone(),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,8 +138,8 @@ impl LocalScope {
|
|||||||
pub fn with_params(self: &Arc<Self>, param_list: &ParamList) {
|
pub fn with_params(self: &Arc<Self>, param_list: &ParamList) {
|
||||||
for (param_name, type_expr) in ¶m_list.0 {
|
for (param_name, type_expr) in ¶m_list.0 {
|
||||||
match type_expr {
|
match type_expr {
|
||||||
parser::ast::TypeExpr::Identifier(id) => match self.parent.get_refrence(id) {
|
parser::ast::TypeExpr::Identifier(id) => match self.parent.get_reference(id) {
|
||||||
Some(Refrence::Type(type_ref)) => {
|
Some(Reference::Type(type_ref)) => {
|
||||||
self.variables.lock().unwrap().insert(
|
self.variables.lock().unwrap().insert(
|
||||||
param_name.clone(),
|
param_name.clone(),
|
||||||
Arc::new(VarRef {
|
Arc::new(VarRef {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
function add(a: int, b: int) {
|
function add(a: int, b: int) {
|
||||||
let myVar = 10;
|
let myVar = 10;
|
||||||
|
|
||||||
|
let test = myVar;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user