mirror of
https://github.com/SpaceManiac/SpacemanDMM.git
synced 2025-12-23 05:36:47 +00:00
Factor flags of VarType into VarTypeFlags bitfield
This commit is contained in:
parent
4cbccb4819
commit
3f7c793162
9 changed files with 134 additions and 89 deletions
|
|
@ -359,12 +359,12 @@ fn main2() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let block = DocBlock::parse(&var.value.docs.text(), Some(broken_link_callback));
|
||||
// `type` is pulled from the parent if necessary
|
||||
let type_ = ty.get_var_declaration(name).map(|decl| VarType {
|
||||
is_static: decl.var_type.is_static,
|
||||
is_const: decl.var_type.is_const,
|
||||
is_tmp: decl.var_type.is_tmp,
|
||||
is_final: decl.var_type.is_final,
|
||||
is_private: decl.var_type.is_private,
|
||||
is_protected: decl.var_type.is_protected,
|
||||
is_static: decl.var_type.flags.is_static(),
|
||||
is_const: decl.var_type.flags.is_const(),
|
||||
is_tmp: decl.var_type.flags.is_tmp(),
|
||||
is_final: decl.var_type.flags.is_final(),
|
||||
is_private: decl.var_type.flags.is_private(),
|
||||
is_protected: decl.var_type.flags.is_protected(),
|
||||
path: &decl.var_type.type_path,
|
||||
});
|
||||
parsed_type.vars.insert(name, Var {
|
||||
|
|
|
|||
|
|
@ -940,14 +940,14 @@ pub fn check_var_defs(objtree: &ObjectTree, context: &Context) {
|
|||
.register(context);
|
||||
}
|
||||
|
||||
if decl.var_type.is_final {
|
||||
if decl.var_type.flags.is_final() {
|
||||
DMError::new(typevar.value.location, format!("{} overrides final var {:?}", path, varname))
|
||||
.with_errortype("final_var")
|
||||
.with_note(decl.location, format!("declared final on {} here", parent.path))
|
||||
.register(context);
|
||||
}
|
||||
|
||||
if decl.var_type.is_private {
|
||||
if decl.var_type.flags.is_private() {
|
||||
DMError::new(typevar.value.location, format!("{} overrides private var {:?}", path, varname))
|
||||
.with_errortype("private_var")
|
||||
.with_note(decl.location, format!("declared private on {} here", parent.path))
|
||||
|
|
@ -1812,13 +1812,13 @@ impl<'o, 's> AnalyzeProc<'o, 's> {
|
|||
Follow::Field(kind, name) => {
|
||||
if let Some(ty) = lhs.static_ty.basic_type() {
|
||||
if let Some(decl) = ty.get_var_declaration(name) {
|
||||
if ty != self.ty && decl.var_type.is_private {
|
||||
if ty != self.ty && decl.var_type.flags.is_private() {
|
||||
error(location, format!("field {:?} on {} is declared as private", name, ty))
|
||||
.with_errortype("private_var")
|
||||
.set_severity(Severity::Warning)
|
||||
.with_note(decl.location, "definition is here")
|
||||
.register(self.context);
|
||||
} else if !self.ty.is_subtype_of(ty.get()) && decl.var_type.is_protected {
|
||||
} else if !self.ty.is_subtype_of(ty.get()) && decl.var_type.flags.is_protected() {
|
||||
error(location, format!("field {:?} on {} is declared as protected", name, ty))
|
||||
.with_errortype("protected_var")
|
||||
.set_severity(Severity::Warning)
|
||||
|
|
|
|||
|
|
@ -815,27 +815,117 @@ type_table! {
|
|||
"color", COLOR, 1 << 17;
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Default)]
|
||||
pub struct VarTypeFlags: u8 {
|
||||
// DM flags
|
||||
const STATIC = 1 << 0;
|
||||
const CONST = 1 << 2;
|
||||
const TMP = 1 << 3;
|
||||
// SpacemanDMM flags
|
||||
const FINAL = 1 << 4;
|
||||
const PRIVATE = 1 << 5;
|
||||
const PROTECTED = 1 << 6;
|
||||
}
|
||||
}
|
||||
|
||||
impl VarTypeFlags {
|
||||
pub fn from_name(name: &str) -> Option<VarTypeFlags> {
|
||||
match name {
|
||||
// DM flags
|
||||
"global" | "static" => Some(VarTypeFlags::STATIC),
|
||||
"const" => Some(VarTypeFlags::CONST),
|
||||
"tmp" => Some(VarTypeFlags::TMP),
|
||||
// SpacemanDMM flags
|
||||
"SpacemanDMM_final" => Some(VarTypeFlags::FINAL),
|
||||
"SpacemanDMM_private" => Some(VarTypeFlags::PRIVATE),
|
||||
"SpacemanDMM_protected" => Some(VarTypeFlags::PROTECTED),
|
||||
// Fallback
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_static(&self) -> bool {
|
||||
self.contains(VarTypeFlags::STATIC)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_const(&self) -> bool {
|
||||
self.contains(VarTypeFlags::CONST)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_tmp(&self) -> bool {
|
||||
self.contains(VarTypeFlags::TMP)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_final(&self) -> bool {
|
||||
self.contains(VarTypeFlags::FINAL)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_private(&self) -> bool {
|
||||
self.contains(VarTypeFlags::PRIVATE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_protected(&self) -> bool {
|
||||
self.contains(VarTypeFlags::PROTECTED)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_const_evaluable(&self) -> bool {
|
||||
self.contains(VarTypeFlags::CONST) || !self.intersects(VarTypeFlags::STATIC | VarTypeFlags::PROTECTED)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_normal(&self) -> bool {
|
||||
!self.intersects(VarTypeFlags::CONST | VarTypeFlags::STATIC | VarTypeFlags::PROTECTED)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for VarTypeFlags {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.is_static() {
|
||||
fmt.write_str("static/")?;
|
||||
}
|
||||
if self.is_const() {
|
||||
fmt.write_str("const/")?;
|
||||
}
|
||||
if self.is_tmp() {
|
||||
fmt.write_str("tmp/")?;
|
||||
}
|
||||
if self.is_final() {
|
||||
fmt.write_str("SpacemanDMM_final/")?;
|
||||
}
|
||||
if self.is_private() {
|
||||
fmt.write_str("SpacemanDMM_private/")?;
|
||||
}
|
||||
if self.is_protected() {
|
||||
fmt.write_str("SpacemanDMM_protected/")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A type which may be ascribed to a `var`.
|
||||
#[derive(Debug, Clone, PartialEq, Default)]
|
||||
pub struct VarType {
|
||||
pub is_static: bool,
|
||||
pub is_const: bool,
|
||||
pub is_tmp: bool,
|
||||
pub is_final: bool,
|
||||
pub is_private: bool,
|
||||
pub is_protected: bool,
|
||||
pub flags: VarTypeFlags,
|
||||
pub type_path: TreePath,
|
||||
}
|
||||
|
||||
impl VarType {
|
||||
#[inline]
|
||||
pub fn is_const_evaluable(&self) -> bool {
|
||||
self.is_const || (!self.is_static && !self.is_tmp)
|
||||
self.flags.is_const_evaluable()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_normal(&self) -> bool {
|
||||
!(self.is_static || self.is_const || self.is_tmp)
|
||||
self.flags.is_normal()
|
||||
}
|
||||
|
||||
pub fn suffix(&mut self, suffix: &VarSuffix) {
|
||||
|
|
@ -847,39 +937,19 @@ impl VarType {
|
|||
|
||||
impl FromIterator<String> for VarType {
|
||||
fn from_iter<T: IntoIterator<Item=String>>(iter: T) -> Self {
|
||||
let (mut is_static, mut is_const, mut is_tmp, mut is_final, mut is_private, mut is_protected) = (false, false, false, false, false, false);
|
||||
let mut flags = VarTypeFlags::default();
|
||||
let type_path = iter
|
||||
.into_iter()
|
||||
.skip_while(|p| {
|
||||
if p == "global" || p == "static" {
|
||||
is_static = true;
|
||||
true
|
||||
} else if p == "SpacemanDMM_final" {
|
||||
is_final = true;
|
||||
true
|
||||
} else if p == "SpacemanDMM_private" {
|
||||
is_private = true;
|
||||
true
|
||||
} else if p == "SpacemanDMM_protected" {
|
||||
is_protected = true;
|
||||
true
|
||||
} else if p == "const" {
|
||||
is_const = true;
|
||||
true
|
||||
} else if p == "tmp" {
|
||||
is_tmp = true;
|
||||
if let Some(flag) = VarTypeFlags::from_name(p) {
|
||||
flags |= flag;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}).collect();
|
||||
VarType {
|
||||
is_static,
|
||||
is_const,
|
||||
is_tmp,
|
||||
is_final,
|
||||
is_private,
|
||||
is_protected,
|
||||
flags,
|
||||
type_path,
|
||||
}
|
||||
}
|
||||
|
|
@ -887,24 +957,7 @@ impl FromIterator<String> for VarType {
|
|||
|
||||
impl fmt::Display for VarType {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.is_static {
|
||||
fmt.write_str("static/")?;
|
||||
}
|
||||
if self.is_const {
|
||||
fmt.write_str("const/")?;
|
||||
}
|
||||
if self.is_tmp {
|
||||
fmt.write_str("tmp/")?;
|
||||
}
|
||||
if self.is_final {
|
||||
fmt.write_str("SpacemanDMM_final/")?;
|
||||
}
|
||||
if self.is_private {
|
||||
fmt.write_str("SpacemanDMM_private/")?;
|
||||
}
|
||||
if self.is_protected {
|
||||
fmt.write_str("SpacemanDMM_protected/")?;
|
||||
}
|
||||
self.flags.fmt(fmt)?;
|
||||
for bit in self.type_path.iter() {
|
||||
fmt.write_str(bit)?;
|
||||
fmt.write_str("/")?;
|
||||
|
|
|
|||
|
|
@ -434,7 +434,7 @@ pub(crate) fn evaluate_all(context: &Context, tree: &mut ObjectTree) {
|
|||
if !tree[ty]
|
||||
.get_var_declaration(&key, tree)
|
||||
.map_or(true, |x| {
|
||||
x.var_type.is_const_evaluable() && (x.var_type.is_const || ty != NodeIndex::new(0))
|
||||
x.var_type.is_const_evaluable() && (x.var_type.flags.is_const() || ty != NodeIndex::new(0))
|
||||
})
|
||||
{
|
||||
continue; // skip non-constant-evaluable vars
|
||||
|
|
@ -497,7 +497,7 @@ fn constant_ident_lookup(
|
|||
var.value.location,
|
||||
format!("non-const-evaluable variable: {}", ident),
|
||||
));
|
||||
} else if !decl.var_type.is_const && must_be_const {
|
||||
} else if !decl.var_type.flags.is_const() && must_be_const {
|
||||
return Err(DMError::new(
|
||||
var.value.location,
|
||||
format!("non-const variable: {}", ident),
|
||||
|
|
|
|||
|
|
@ -919,7 +919,9 @@ impl ObjectTree {
|
|||
where
|
||||
I: Iterator<Item=&'a str>,
|
||||
{
|
||||
let (mut is_declaration, mut is_static, mut is_const, mut is_tmp, mut is_final, mut is_private, mut is_protected) = (false, false, false, false, false, false, false);
|
||||
use super::ast::VarTypeFlags;
|
||||
let mut is_declaration = false;
|
||||
let mut flags = VarTypeFlags::default();
|
||||
|
||||
if is_var_decl(prev) {
|
||||
is_declaration = true;
|
||||
|
|
@ -927,14 +929,9 @@ impl ObjectTree {
|
|||
Some(name) => name,
|
||||
None => return Ok(None), // var{} block, children will be real vars
|
||||
};
|
||||
while prev == "global" || prev == "static" || prev == "tmp" || prev == "const" || prev == "SpacemanDMM_final" || prev == "SpacemanDMM_private" || prev == "SpacemanDMM_protected" {
|
||||
while let Some(flag) = VarTypeFlags::from_name(prev) {
|
||||
if let Some(name) = rest.next() {
|
||||
is_static |= prev == "global" || prev == "static";
|
||||
is_const |= prev == "const";
|
||||
is_tmp |= prev == "tmp";
|
||||
is_final |= prev == "SpacemanDMM_final";
|
||||
is_private |= prev == "SpacemanDMM_private";
|
||||
is_protected |= prev == "SpacemanDMM_protected";
|
||||
flags |= flag;
|
||||
prev = name;
|
||||
} else {
|
||||
return Ok(None); // var/const{} block, children will be real vars
|
||||
|
|
@ -950,12 +947,7 @@ impl ObjectTree {
|
|||
prev = each;
|
||||
}
|
||||
let mut var_type = VarType {
|
||||
is_static,
|
||||
is_const,
|
||||
is_tmp,
|
||||
is_final,
|
||||
is_private,
|
||||
is_protected,
|
||||
flags,
|
||||
type_path,
|
||||
};
|
||||
var_type.suffix(&suffix);
|
||||
|
|
|
|||
|
|
@ -986,7 +986,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> {
|
|||
.register(self.context);
|
||||
}
|
||||
let mut var_type: VarType = path.into_iter().collect();
|
||||
if var_type.is_static {
|
||||
if var_type.flags.is_static() {
|
||||
DMError::new(leading_loc, "'static/' has no effect here")
|
||||
.set_severity(Severity::Warning)
|
||||
.with_errortype("static_in_proc_parameter")
|
||||
|
|
@ -1460,25 +1460,25 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> {
|
|||
};
|
||||
|
||||
let mut var_type = tree_path.into_iter().collect::<VarType>();
|
||||
if var_type.is_tmp {
|
||||
if var_type.flags.is_tmp() {
|
||||
DMError::new(type_path_start, "var/tmp has no effect here")
|
||||
.set_severity(Severity::Warning)
|
||||
.with_errortype("tmp_no_effect")
|
||||
.register(self.context);
|
||||
}
|
||||
if var_type.is_final {
|
||||
if var_type.flags.is_final() {
|
||||
DMError::new(type_path_start, "var/final has no effect here")
|
||||
.set_severity(Severity::Warning)
|
||||
.with_errortype("final_no_effect")
|
||||
.register(self.context);
|
||||
}
|
||||
if var_type.is_private {
|
||||
if var_type.flags.is_private() {
|
||||
DMError::new(type_path_start, "var/SpacemanDMM_private has no effect here")
|
||||
.with_errortype("private_var")
|
||||
.set_severity(Severity::Warning)
|
||||
.register(self.context);
|
||||
}
|
||||
if var_type.is_protected {
|
||||
if var_type.flags.is_protected() {
|
||||
DMError::new(type_path_start, "var/SpacemanDMM_protected has no effect here")
|
||||
.with_errortype("protected_var")
|
||||
.set_severity(Severity::Warning)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use crate::symbol_search::contains;
|
|||
pub fn item_var(ty: TypeRef, name: &str, var: &TypeVar) -> CompletionItem {
|
||||
let mut detail = ty.pretty_path().to_owned();
|
||||
if let Some(ref decl) = var.declaration {
|
||||
if decl.var_type.is_const {
|
||||
if decl.var_type.flags.is_const() {
|
||||
if let Some(ref constant) = var.value.constant {
|
||||
if ty.is_root() {
|
||||
detail = constant.to_string();
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ impl<'o> WalkProc<'o> {
|
|||
|
||||
fn visit_var(&mut self, _location: Location, var_type: &VarType, name: &str, _value: Option<&'o Expression>) {
|
||||
// static and const vars do not exist in the stack frame
|
||||
if !var_type.is_static && !var_type.is_const {
|
||||
if !var_type.flags.is_static() && !var_type.flags.is_const() {
|
||||
self.local_vars.push(name.to_owned());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1102,22 +1102,22 @@ handle_method_call! {
|
|||
if let Some(ref decl) = var.declaration {
|
||||
let mut declaration = String::new();
|
||||
declaration.push_str("var");
|
||||
if decl.var_type.is_static {
|
||||
if decl.var_type.flags.is_static() {
|
||||
declaration.push_str("/static");
|
||||
}
|
||||
if decl.var_type.is_const {
|
||||
if decl.var_type.flags.is_const() {
|
||||
declaration.push_str("/const");
|
||||
}
|
||||
if decl.var_type.is_tmp {
|
||||
if decl.var_type.flags.is_tmp() {
|
||||
declaration.push_str("/tmp");
|
||||
}
|
||||
if decl.var_type.is_final {
|
||||
if decl.var_type.flags.is_final() {
|
||||
declaration.push_str("/SpacemanDMM_final");
|
||||
}
|
||||
if decl.var_type.is_private {
|
||||
if decl.var_type.flags.is_private() {
|
||||
declaration.push_str("/SpacemanDMM_private");
|
||||
}
|
||||
if decl.var_type.is_protected {
|
||||
if decl.var_type.flags.is_protected() {
|
||||
declaration.push_str("/SpacemanDMM_protected");
|
||||
}
|
||||
for bit in decl.var_type.type_path.iter() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue