Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions xsc-core/src/static/info/fn_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,36 @@ use crate::r#static::info::src_loc::SrcLoc;
#[allow(dead_code)]
pub struct FnInfo {
pub identifiers: HashMap<Identifier, IdInfo>,
pub active_loop_params: HashMap<Identifier, SrcLoc>,
pub src_loc: SrcLoc
}

impl FnInfo {
pub fn new(src_loc: SrcLoc) -> Self {
Self { identifiers: HashMap::new(), src_loc }
Self { identifiers: HashMap::new(), active_loop_params: HashMap::new(), src_loc }
}

pub fn get_mut(&mut self, id: &Identifier) -> Option<&mut IdInfo> {
self.identifiers.get_mut(id)
}

pub fn get(&self, id: &Identifier) -> Option<&IdInfo> {
self.identifiers.get(id)
}

pub fn set(&mut self, id: Identifier, info: IdInfo) {
self.identifiers.insert(id, info);
}
}

pub fn get_active_loop_param(&self, id: &Identifier) -> Option<&SrcLoc> {
self.active_loop_params.get(id)
}

pub fn set_active_loop_param(&mut self, id: Identifier, src_loc: SrcLoc) {
self.active_loop_params.insert(id, src_loc);
}

pub fn unset_active_loop_param(&mut self, id: &Identifier) {
self.active_loop_params.remove(id);
}
}
25 changes: 23 additions & 2 deletions xsc-core/src/static/info/type_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::parsing::ast::{Identifier};
use crate::parsing::span::{contains, Span};
use crate::r#static::info::fn_info::FnInfo;
use crate::r#static::info::id_info::IdInfo;
use crate::r#static::info::src_loc::SrcLoc;
use crate::r#static::info::xs_error::XsError;

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -85,6 +86,12 @@ impl TypeEnv {
.or_else(|| self.identifiers.get(id))
.map(|val| val.clone())
}

pub fn get_active_loop_param(&self, id: &Identifier) -> Option<SrcLoc> {
self.current_fnv_env.as_ref()
.and_then(|env| env.get_active_loop_param(id))
.cloned()
}

pub fn set(&mut self, id: &Identifier, info: IdInfo) {
match &mut self.current_fnv_env {
Expand All @@ -102,7 +109,7 @@ impl TypeEnv {
.and_then(|env| env.get(&Identifier::new("return")))
.map(|val| val.clone())
}

pub fn add_group(&mut self, group: &String) {
self.groups.insert(group.clone());
}
Expand Down Expand Up @@ -162,6 +169,20 @@ impl TypeEnv {
self.current_doc.take()
}

pub fn set_active_loop_param(&mut self, id: &Identifier, src_loc: SrcLoc) {
let Some(env) = self.current_fnv_env.as_mut() else {
return;
};
env.set_active_loop_param(id.clone(), src_loc);
}

pub fn unset_active_loop_param(&mut self, id: &Identifier) {
let Some(env) = self.current_fnv_env.as_mut() else {
return;
};
env.unset_active_loop_param(id);
}

pub fn local_ids(&self, path: &PathBuf, span: &Span) -> Option<&HashMap<Identifier, IdInfo>> {
self.fn_envs
.values()
Expand All @@ -171,4 +192,4 @@ impl TypeEnv {
loc.file_path == *path && contains(&loc.span, span)
}).map(|env| &env.identifiers).next()
}
}
}
2 changes: 2 additions & 0 deletions xsc-core/src/static/type_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@ mod expression;
mod util;
mod statement;
mod statements;
#[cfg(test)]
mod tests;

pub use statements::{xs_tc};
121 changes: 92 additions & 29 deletions xsc-core/src/static/type_check/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,45 +632,108 @@ match stmt {
let (AstNode::VarAssign { name: (name, name_span), value }, _span) = var.as_ref()
else { unreachable!("XSC Internal Error while type checking For at {}", var.as_ref().1) };

/* Redefinitions are allowed for for loop variables */

// match type_env.get(name) {
// Some(IdInfo { src_loc: og_src_loc, .. }) => {
// type_env.add_err(path, XSError::redefined_name(
// name,
// name_span,
// &og_src_loc,
// None,
// ));
// return Ok(());
// }
// _ => {}
// };

if let Some(value_type) = xs_tc_expr(path, value, type_env) {
type_env.add_errs(path, type_cmp(&Type::Int, &value_type, &value.1, false, false));
}

type_env.set(name, IdInfo::new(Type::Int, SrcLoc::from(path, name_span), doc));
if let Some(type_) = xs_tc_expr(path, condition, type_env) {
if type_ != Type::Bool {
type_env.add_err(path, XsError::type_mismatch(
&type_.to_string(),
"bool",
&condition.1,
None,
let mut can_activate_loop_param = true;
let mut chk_loop_var_usage = true;
let mut loop_var_type = Type::Int;
let is_new_loop_param = match type_env.get(name) {
Some(IdInfo { type_, modifiers, .. }) if modifiers.is_const() => {
type_env.add_err(path, XsError::syntax(
span,
"Cannot re-assign a value to a {0} variable",
vec!["const"],
));
can_activate_loop_param = false;
chk_loop_var_usage = false;
loop_var_type = type_;
false
}
Some(IdInfo { type_, .. }) => {
loop_var_type = type_.clone();
match type_ {
Type::Int | Type::Float => {}
_ => {
type_env.add_err(path, XsError::type_mismatch(
&type_.to_string(),
"int | float",
name_span,
None,
));
can_activate_loop_param = false;
chk_loop_var_usage = false;
}
}
false
}
None => {
type_env.set(name, IdInfo::new(Type::Int, SrcLoc::from(path, name_span), doc.clone()));
true
}
};

if let Some(og_src_loc) = type_env.get_active_loop_param(name) {
type_env.add_err(path, XsError::redefined_name(
name,
name_span,
&og_src_loc,
Some("Nested loops cannot reuse the same loop parameter"),
));
can_activate_loop_param = false;
}

let value_type = xs_tc_expr(path, value, type_env);
if chk_loop_var_usage {
if let Some(value_type) = value_type {
let expected_type = if is_new_loop_param { &Type::Int } else { &loop_var_type };
type_env.add_errs(path, type_cmp(expected_type, &value_type, &value.1, false, false));
}
}

combine_results(body.0.iter()
if chk_loop_var_usage {
if let Some(type_) = xs_tc_expr(path, condition, type_env) {
if type_ != Type::Bool {
type_env.add_err(path, XsError::type_mismatch(
&type_.to_string(),
"bool",
&condition.1,
None,
));
}
}
} else {
let Some(spanned_expr) = (match &condition.0 {
Expr::Lt(_lhs, rhs) | Expr::Le(_lhs, rhs) | Expr::Gt(_lhs, rhs) | Expr::Ge(_lhs, rhs) => {
Some(rhs.as_ref())
}
_ => None,
}) else {
unreachable!("XSC Internal Error while type checking For condition at {}", condition.1);
};
xs_tc_expr(path, spanned_expr, type_env);
}

if can_activate_loop_param {
let loop_src_loc = if is_new_loop_param {
SrcLoc::from(path, name_span)
} else {
SrcLoc::from(path, span)
};
type_env.set_active_loop_param(name, loop_src_loc);
}

let result = combine_results(body.0.iter()
.map(|spanned_stmt| {
xs_tc_stmt(
path, spanned_stmt, type_env, ast_cache, src_cache, comments, comment_pos,
false, true, true,
)
})
)
);

if can_activate_loop_param {
type_env.unset_active_loop_param(name);
}

result
},
AstNode::Switch { clause, cases } => {
if is_top_level {
Expand Down
Loading