diff --git a/src/analysis/ast_analysis.rs b/src/analysis/ast_analysis.rs index 3b2052e..52c36a3 100644 --- a/src/analysis/ast_analysis.rs +++ b/src/analysis/ast_analysis.rs @@ -34,7 +34,7 @@ use syntax::ast::*; use analysis::sem_rep::*; use analysis::trav_monad::*; use analysis::def_table::*; -use analysis::decl_analysis::{analyseTypeDecl, analyseTypeDef, StorageSpec, StaticSpec, ExternSpec, analyseVarDecl_q, VarDeclInfo}; +use analysis::decl_analysis::{analyseTypeDecl, StorageSpec, StaticSpec, ExternSpec, analyseVarDecl_q, VarDeclInfo}; use data::node::NodeInfo; use data::ident::Ident; use analysis::type_utils::*; diff --git a/src/analysis/builtins.rs b/src/analysis/builtins.rs index 109e2dc..bf0a5af 100644 --- a/src/analysis/builtins.rs +++ b/src/analysis/builtins.rs @@ -1,213 +1,209 @@ // Original file: "Builtins.hs" // File auto-generated using Corollary. -#[macro_use] -use corollary_support::*; - -// NOTE: These imports are advisory. You probably need to change them to support Rust. -// use Language::C::Analysis::DefTable; -// use Language::C::Analysis::SemRep; -// use Language::C::Analysis::TypeUtils; -// use Language::C::Data::Ident; -// use Language::C::Data::Node; - +use data::ident::*; +use data::node::*; use analysis::sem_rep::*; use analysis::type_utils::*; +use analysis::def_table::DefTable; pub fn builtins() -> DefTable { + let mut tbl = DefTable::new(); - let doTypeDef = |d| snd(defineTypeDef((identOfTypeDef(d)), d)); - - let doIdent = |d| snd(defineGlobalIdent((declIdent(d)), d)); - - let dName = |s| VarName((builtinIdent(s)), None); + let dName = |s| VarName(Ident::builtin(s), None); let param = |ty| { - ParamDecl((VarDecl(NoName, - (DeclAttrs(noFunctionAttrs, (Auto(false)), vec![])), - ty)), - undefNode) + ParamDecl(VarDecl(NoName, DeclAttrs(noFunctionAttrs(), (Auto(false)), vec![]), ty), NodeInfo::undef()) }; - let fnAttrs = DeclAttrs(noFunctionAttrs, (FunLinkage(ExternalLinkage)), vec![]); + let fnAttrs = DeclAttrs(noFunctionAttrs(), FunLinkage(ExternalLinkage), vec![]); - let varAttrs = DeclAttrs(noFunctionAttrs, (Static(InternalLinkage, false)), vec![]); + let varAttrs = DeclAttrs(noFunctionAttrs(), Static(InternalLinkage, false), vec![]); - let fnType = |r, __as| FunctionType((FunType(r, (__map!(param, __as)), false)), noAttributes); + let fnType = |r, args: Vec| { + FunctionType(box FunType(r, args.into_iter().map(¶m).collect(), false), noAttributes()) + }; - let fnType_q = |r, __as| FunctionType((FunType(r, (__map!(param, __as)), true)), noAttributes); + let fnType_q = |r, args: Vec| { + FunctionType(box FunType(r, args.into_iter().map(¶m).collect(), true), noAttributes()) + }; - let func = |n, r, __as| { - Declaration((Decl((VarDecl((dName(n)), fnAttrs, (fnType(r, __as)))), undefNode))) + let func = |n, r, args| { + Declaration(Decl(VarDecl(dName(n), fnAttrs.clone(), fnType(r, args)), NodeInfo::undef())) }; - let func_q = |n, r, __as| { - Declaration((Decl((VarDecl((dName(n)), fnAttrs, (fnType_q(r, __as)))), - undefNode))) + let func_q = |n, r, args| { + Declaration(Decl(VarDecl(dName(n), fnAttrs.clone(), fnType_q(r, args)), NodeInfo::undef())) }; - let var = |n, t| Declaration((Decl((VarDecl((dName(n)), varAttrs, t)), undefNode))); + let var = |n, t| Declaration(Decl(VarDecl(dName(n), varAttrs.clone(), t), NodeInfo::undef())); - let typedef = |n, t| TypeDef((builtinIdent(n)), t, vec![], undefNode); + let typedef = |n, t| TypeDef(Ident::builtin(n), t, vec![], NodeInfo::undef()); - let typedefs = vec![typedef("__builtin_va_list".to_string(), valistType)]; + let typedefs = vec![typedef("__builtin_va_list".to_string(), valistType())]; let idents = vec![func("__builtin_expect".to_string(), (integral(TyLong)), vec![integral(TyLong), integral(TyLong)]), func("__builtin_bswap16".to_string(), - uint16_tType, - vec![uint16_tType]), + uint16_tType(), + vec![uint16_tType()]), func("__builtin_bswap32".to_string(), - uint32_tType, - vec![uint32_tType]), + uint32_tType(), + vec![uint32_tType()]), func("__builtin_bswap64".to_string(), - uint64_tType, - vec![uint64_tType]), + uint64_tType(), + vec![uint64_tType()]), func("__builtin_fabs".to_string(), - (floating(TyDouble)), + floating(TyDouble), vec![floating(TyDouble)]), func("__builtin_fabsf".to_string(), - (floating(TyFloat)), + floating(TyFloat), vec![floating(TyFloat)]), func("__builtin_fabsl".to_string(), - (floating(TyLDouble)), + floating(TyLDouble), vec![floating(TyLDouble)]), - func("__builtin_inf".to_string(), (floating(TyDouble)), vec![]), - func("__builtin_inff".to_string(), (floating(TyFloat)), vec![]), - func("__builtin_infl".to_string(), (floating(TyLDouble)), vec![]), + func("__builtin_inf".to_string(), floating(TyDouble), vec![]), + func("__builtin_inff".to_string(), floating(TyFloat), vec![]), + func("__builtin_infl".to_string(), floating(TyLDouble), vec![]), func("__builtin_huge_val".to_string(), - (floating(TyDouble)), + floating(TyDouble), vec![]), func("__builtin_huge_valf".to_string(), - (floating(TyFloat)), + floating(TyFloat), vec![]), func("__builtin_huge_vall".to_string(), - (floating(TyLDouble)), + floating(TyLDouble), vec![]), func("__builtin_copysign".to_string(), - (floating(TyDouble)), + floating(TyDouble), vec![floating(TyDouble), floating(TyDouble)]), func("__builtin_va_start".to_string(), - voidType, - vec![valistType, voidPtr]), - func("__builtin_va_end".to_string(), voidType, vec![valistType]), + voidType(), + vec![valistType(), voidPtr()]), + func("__builtin_va_end".to_string(), voidType(), vec![valistType()]), func("__builtin_va_copy".to_string(), - voidType, - vec![valistType, valistType]), + voidType(), + vec![valistType(), valistType()]), func("__builtin_va_arg_pack".to_string(), - (integral(TyInt)), + integral(TyInt), vec![]), func("__builtin_va_arg_pack_len".to_string(), - (integral(TyInt)), + integral(TyInt), vec![]), - func("__builtin_alloca".to_string(), voidPtr, vec![size_tType]), + func("__builtin_alloca".to_string(), voidPtr(), vec![size_tType()]), func("__builtin_memcpy".to_string(), - voidPtr, - vec![voidPtr, constVoidPtr, size_tType]), + voidPtr(), + vec![voidPtr(), constVoidPtr(), size_tType()]), func("__builtin_strspn".to_string(), - size_tType, - vec![constCharPtr, constCharPtr]), + size_tType(), + vec![constCharPtr(), constCharPtr()]), func("__builtin_strcspn".to_string(), - size_tType, - vec![constCharPtr, constCharPtr]), + size_tType(), + vec![constCharPtr(), constCharPtr()]), func("__builtin_strchr".to_string(), - charPtr, - vec![constCharPtr, integral(TyInt)]), + charPtr(), + vec![constCharPtr(), integral(TyInt)]), func("__builtin_strncpy".to_string(), - charPtr, - vec![constCharPtr, constCharPtr, size_tType]), + charPtr(), + vec![constCharPtr(), constCharPtr(), size_tType()]), func("__builtin_strncat".to_string(), - charPtr, - vec![constCharPtr, constCharPtr, size_tType]), + charPtr(), + vec![constCharPtr(), constCharPtr(), size_tType()]), func("__builtin_strcmp".to_string(), - (integral(TyInt)), - vec![constCharPtr, constCharPtr]), + integral(TyInt), + vec![constCharPtr(), constCharPtr()]), func("__builtin_strpbrk".to_string(), - charPtr, - vec![constCharPtr, constCharPtr]), + charPtr(), + vec![constCharPtr(), constCharPtr()]), func("__builtin_bzero".to_string(), - voidType, - vec![voidPtr, size_tType]), + voidType(), + vec![voidPtr(), size_tType()]), func("__builtin_clz".to_string(), - (integral(TyInt)), + integral(TyInt), vec![integral(TyUInt)]), func("__builtin_constant_p".to_string(), - (integral(TyInt)), - vec![DirectType((TyBuiltin(TyAny)), noTypeQuals, noAttributes)]), + integral(TyInt), + vec![DirectType(TyBuiltin(TyAny), noTypeQuals(), noAttributes())]), func("__builtin_extract_return_addr".to_string(), - voidPtr, - vec![voidPtr]), + voidPtr(), + vec![voidPtr()]), func("__builtin_return_address".to_string(), - voidPtr, + voidPtr(), vec![integral(TyUInt)]), func("__builtin_frame_address".to_string(), - voidPtr, + voidPtr(), vec![integral(TyUInt)]), func("__builtin_expect".to_string(), - (integral(TyLong)), + integral(TyLong), vec![integral(TyLong), integral(TyLong)]), func("__builtin_prefetch".to_string(), - voidType, - vec![constVoidPtr]), - var("__func__".to_string(), stringType), - var("__PRETTY_FUNCTION__".to_string(), stringType), - var("__FUNCTION__".to_string(), stringType), + voidType(), + vec![constVoidPtr()]), + var("__func__".to_string(), stringType()), + var("__PRETTY_FUNCTION__".to_string(), stringType()), + var("__FUNCTION__".to_string(), stringType()), func("__builtin_object_size".to_string(), - size_tType, - vec![voidPtr, integral(TyInt)]), + size_tType(), + vec![voidPtr(), integral(TyInt)]), func("__builtin___memcpy_chk".to_string(), - voidPtr, - vec![voidPtr, constVoidPtr, size_tType, size_tType]), + voidPtr(), + vec![voidPtr(), constVoidPtr(), size_tType(), size_tType()]), func("__builtin___mempcpy_chk".to_string(), - voidPtr, - vec![voidPtr, constVoidPtr, size_tType, size_tType]), + voidPtr(), + vec![voidPtr(), constVoidPtr(), size_tType(), size_tType()]), func("__builtin___memmove_chk".to_string(), - voidPtr, - vec![voidPtr, constVoidPtr, size_tType, size_tType]), + voidPtr(), + vec![voidPtr(), constVoidPtr(), size_tType(), size_tType()]), func("__builtin___memset_chk".to_string(), - voidPtr, - vec![voidPtr, integral(TyInt), size_tType, size_tType]), + voidPtr(), + vec![voidPtr(), integral(TyInt), size_tType(), size_tType()]), func("__builtin___strcpy_chk".to_string(), - charPtr, - vec![constCharPtr, constCharPtr, size_tType]), + charPtr(), + vec![constCharPtr(), constCharPtr(), size_tType()]), func("__builtin___stpcpy_chk".to_string(), - charPtr, - vec![constCharPtr, constCharPtr, size_tType]), + charPtr(), + vec![constCharPtr(), constCharPtr(), size_tType()]), func("__builtin___strncpy_chk".to_string(), - charPtr, - vec![constCharPtr, constCharPtr, size_tType, size_tType]), + charPtr(), + vec![constCharPtr(), constCharPtr(), size_tType(), size_tType()]), func("__builtin___strcat_chk".to_string(), - charPtr, - vec![constCharPtr, constCharPtr, size_tType]), + charPtr(), + vec![constCharPtr(), constCharPtr(), size_tType()]), func("__builtin___strncat_chk".to_string(), - charPtr, - vec![constCharPtr, constCharPtr, size_tType, size_tType]), + charPtr(), + vec![constCharPtr(), constCharPtr(), size_tType(), size_tType()]), func_q("__builtin___sprintf_chk".to_string(), (integral(TyInt)), - vec![charPtr, integral(TyInt), size_tType, constCharPtr]), + vec![charPtr(), integral(TyInt), size_tType(), constCharPtr()]), func_q("__builtin___snprintf_chk".to_string(), (integral(TyInt)), - vec![charPtr, - size_tType, + vec![charPtr(), + size_tType(), integral(TyInt), - size_tType, - constCharPtr]), + size_tType(), + constCharPtr()]), func("__builtin___vsprintf_chk".to_string(), (integral(TyInt)), - vec![charPtr, + vec![charPtr(), integral(TyInt), - size_tType, - constCharPtr, - valistType]), + size_tType(), + constCharPtr(), + valistType()]), func("__builtin___vsnprintf_chk".to_string(), (integral(TyInt)), - vec![charPtr, - size_tType, + vec![charPtr(), + size_tType(), integral(TyInt), - size_tType, - constCharPtr, - valistType])]; - - foldr(doIdent, (foldr(doTypeDef, emptyDefTable, typedefs)), idents) + size_tType(), + constCharPtr(), + valistType()])]; + + for typedef in typedefs { + tbl.defineTypeDef(identOfTypeDef(&typedef), typedef); + } + for ident in idents { + tbl.defineGlobalIdent(declIdent(&ident), ident); + } + tbl } diff --git a/src/analysis/decl_analysis.rs b/src/analysis/decl_analysis.rs index 471b72f..fe59a62 100644 --- a/src/analysis/decl_analysis.rs +++ b/src/analysis/decl_analysis.rs @@ -30,7 +30,7 @@ use syntax::ast::*; use analysis::trav_monad::*; use analysis::sem_rep::*; use data::node::*; -use analysis::sem_error::*; +use analysis::sem_error::*; use data::ident::*; pub fn tParamDecl(_0: CDecl) -> m { @@ -502,10 +502,10 @@ pub fn tArraySize(_0: CArrSize) -> m { pub fn tTypeQuals() -> m<(TypeQuals, Attributes)> { let go = |_0, _1| match (_0, _1) { - (CConstQual(_), (tq, attrs)) => (__assign!(tq, TODO { constant: true }), attrs), - (CVolatQual(_), (tq, attrs)) => (__assign!(tq, TODO { volatile: true }), attrs), - (CRestrQual(_), (tq, attrs)) => (__assign!(tq, TODO { restrict: true }), attrs), - (CAtomicQual(_), (tq, attrs)) => (__assign!(tq, TODO { atomic: true }), attrs), + (CConstQual(_), (tq, attrs)) => (__assign!(tq, /*TODO*/ { constant: true }), attrs), + (CVolatQual(_), (tq, attrs)) => (__assign!(tq, /*TODO*/ { volatile: true }), attrs), + (CRestrQual(_), (tq, attrs)) => (__assign!(tq, /*TODO*/ { restrict: true }), attrs), + (CAtomicQual(_), (tq, attrs)) => (__assign!(tq, /*TODO*/ { atomic: true }), attrs), (CAttrQual(attr), (tq, attrs)) => { liftM((|attr_q| (tq, __op_concat(attr_q, attrs))), (tAttr(attr))) } diff --git a/src/analysis/def_table.rs b/src/analysis/def_table.rs index c8efa3b..08737b4 100644 --- a/src/analysis/def_table.rs +++ b/src/analysis/def_table.rs @@ -1,37 +1,59 @@ // Original file: "DefTable.hs" // File auto-generated using Corollary. -#[macro_use] -use corollary_support::*; - -// NOTE: These imports are advisory. You probably need to change them to support Rust. -// use Language::C::Data; -// use Language::C::Analysis::NameSpaceMap; -// use Language::C::Analysis::SemRep; -// use Data::Map; -// use Data::IntMap; -// use IntMap; -// use Data::IntMap; -// use Data::Generics; +use std::collections::HashMap; +use std::collections::BTreeMap; +use std::hash::Hash; +use either::Either; +use either::Either::*; -use analysis::sem_rep::*; use data::ident::Ident; -use analysis::name_space_map::mergeNameSpace; -use data::name::Name; +use data::name::*; use data::ident::*; +use data::node::*; +use analysis::name_space_map::*; +use analysis::sem_rep::*; pub type IdentEntry = Either; -pub fn identOfTyDecl() -> Ident { - either(identOfTypeDef, declIdent) +pub fn identOfTyDecl(entry: &IdentEntry) -> Ident { + entry.as_ref().either(identOfTypeDef, declIdent) } +// TODO: use a similar dedicated data structure? +type NameMap = HashMap; + +#[derive(Clone)] pub enum TagFwdDecl { CompDecl(CompTypeRef), EnumDecl(EnumTypeRef), } pub use self::TagFwdDecl::*; +impl HasSUERef for TagFwdDecl { + fn sueRef(&self) -> SUERef { + match *self { + CompDecl(ref ctr) => ctr.sueRef(), + EnumDecl(ref etr) => etr.sueRef(), + } + } +} + +impl CNode for TagFwdDecl { + fn node_info(&self) -> &NodeInfo { + match *self { + CompDecl(ref ctr) => ctr.node_info(), + EnumDecl(ref etr) => etr.node_info(), + } + } + fn into_node_info(self) -> NodeInfo { + match self { + CompDecl(ctr) => ctr.into_node_info(), + EnumDecl(etr) => etr.into_node_info(), + } + } +} + pub type TagEntry = Either; pub struct DefTable { @@ -39,308 +61,294 @@ pub struct DefTable { tagDecls: NameSpaceMap, labelDefs: NameSpaceMap, memberDecls: NameSpaceMap, - refTable: IntMap, - typeTable: IntMap, -} -fn identDecls(a: DefTable) -> NameSpaceMap { - a.identDecls -} -fn tagDecls(a: DefTable) -> NameSpaceMap { - a.tagDecls -} -fn labelDefs(a: DefTable) -> NameSpaceMap { - a.labelDefs -} -fn memberDecls(a: DefTable) -> NameSpaceMap { - a.memberDecls -} -fn refTable(a: DefTable) -> IntMap { - a.refTable -} -fn typeTable(a: DefTable) -> IntMap { - a.typeTable -} - -pub fn emptyDefTable() -> DefTable { - DefTable(nameSpaceMap, - nameSpaceMap, - nameSpaceMap, - nameSpaceMap, - IntMap::empty, - IntMap::empty) -} - -pub fn globalDefs(deftbl: DefTable) -> GlobalDecls { - - let e = Map::empty; - - let insertDecl = |_0, _1, _2| match (_0, _1, _2) { - (ident, Left(tydef), ds) => ds { gTypeDefs: Map::insert(ident, tydef, (gTypeDefs(ds))) }, - (ident, Right(obj), ds) => ds { gObjs: Map::insert(ident, obj, (gObjs(ds))) }, - }; - - Map::foldWithKey(insertDecl, - (GlobalDecls(e, gtags, e)), - (globalNames(identDecls(deftbl)))) -} - -pub fn inFileScope(dt: DefTable) -> bool { - not(((hasLocalNames((identDecls(dt))) || hasLocalNames((labelDefs(dt)))))) -} - -pub fn leaveScope_() -> NameSpaceMap { - fst(leaveScope) -} - -pub fn enterLocalScope(deftbl: DefTable) -> DefTable { - deftbl { - identDecls: enterNewScope((identDecls(deftbl))), - tagDecls: enterNewScope((tagDecls(deftbl))), + pub refTable: NameMap, //TODO + typeTable: NameMap, +} + +impl DefTable { + pub fn new() -> DefTable { + DefTable { identDecls: NameSpaceMap::new(), + tagDecls: NameSpaceMap::new(), + labelDefs: NameSpaceMap::new(), + memberDecls: NameSpaceMap::new(), + refTable: NameMap::default(), + typeTable: NameMap::default() } } -} -pub fn leaveLocalScope(deftbl: DefTable) -> DefTable { - deftbl { - identDecls: leaveScope_((identDecls(deftbl))), - tagDecls: leaveScope_((tagDecls(deftbl))), + pub fn lookupIdent(&self, ident: &Ident) -> Option<&IdentEntry> { + self.identDecls.lookupName(ident) } -} -pub fn enterFunctionScope(deftbl: DefTable) -> DefTable { - enterLocalScope(deftbl { labelDefs: enterNewScope((labelDefs(deftbl))) }) -} + pub fn lookupTag(&self, sue_ref: &SUERef) -> Option<&TagEntry> { + self.tagDecls.lookupName(sue_ref) + } -pub fn leaveFunctionScope(deftbl: DefTable) -> DefTable { - leaveLocalScope(deftbl { labelDefs: leaveScope_((labelDefs(deftbl))) }) -} + pub fn lookupLabel(&self, ident: &Ident) -> Option<&Ident> { + self.labelDefs.lookupName(ident) + } -pub fn enterBlockScope(deftbl: DefTable) -> DefTable { - enterLocalScope(deftbl { labelDefs: enterNewScope((labelDefs(deftbl))) }) -} + pub fn lookupIdentInner(&self, ident: &Ident) -> Option<&IdentEntry> { + self.identDecls.lookupInnermostScope(ident) + } -pub fn leaveBlockScope(deftbl: DefTable) -> DefTable { - leaveLocalScope(deftbl { labelDefs: leaveScope_((labelDefs(deftbl))) }) -} + pub fn lookupTagInner(&self, sue_ref: &SUERef) -> Option<&TagEntry> { + self.tagDecls.lookupInnermostScope(sue_ref) + } -pub fn enterMemberDecl(deftbl: DefTable) -> DefTable { - deftbl { memberDecls: enterNewScope((memberDecls(deftbl))) } -} + pub fn insertType(&mut self, n: Name, t: Type) { + self.typeTable.insert(n, t); + } -pub fn leaveMemberDecl(deftbl: DefTable) -> (Vec, DefTable) { - { - let (decls_q, members) = leaveScope((memberDecls(deftbl))); + pub fn lookupType(&self, n: Name) -> Option<&Type> { + self.typeTable.get(&n) + } - __op_tuple2((), - (__map!(snd, members))((deftbl { memberDecls: decls_q }))) + pub fn defineScopedIdent(&mut self, ident: Ident, def: IdentDecl) -> DeclarationStatus { + self.defineScopedIdentWhen(|_| true, ident, def) } -} -#[derive(Clone, Debug)] -pub enum DeclarationStatus { - NewDecl, - Redeclared(t), - KeepDef(t), - Shadowed(t), - KindMismatch(t), -} -pub use self::DeclarationStatus::*; + pub fn globalDefs(&self) -> GlobalDecls { + let gtags = self.tagDecls.globalNames().iter().filter_map(|(k, v)| { + match *v { + Left(_) => None, + Right(ref y) => Some((k.clone(), y.clone())) + } + }).collect(); + let mut decls = GlobalDecls { + gObjs: BTreeMap::new(), + gTags: gtags, + gTypeDefs: BTreeMap::new(), + }; + let global_names = self.identDecls.globalNames(); + for (ident, what) in global_names { + match *what { + Left(ref tydef) => { decls.gTypeDefs.insert(ident.clone(), tydef.clone()); } + Right(ref obj) => { decls.gObjs.insert(ident.clone(), obj.clone()); } + } + } + decls + } -pub fn declStatusDescr(_0: DeclarationStatus) -> String { - match (_0) { - NewDecl => "new".to_string(), - Redeclared(_) => "redeclared".to_string(), - KeepDef(_) => "keep old".to_string(), - Shadowed(_) => "shadowed".to_string(), - KindMismatch(_) => "kind mismatch".to_string(), + pub fn inFileScope(&self) -> bool { + !(self.identDecls.hasLocalNames() || self.labelDefs.hasLocalNames()) } -} -pub fn compatIdentEntry(_0: IdentEntry) -> bool { - match (_0) { - Left(_tydef) => either((__TODO_const(true)), (__TODO_const(false))), - Right(def) => { - either((__TODO_const(false)), |other_def| match (def, other_def) { - (EnumeratorDef(_), EnumeratorDef(_)) => true, - (EnumeratorDef(_), _) => true, - (_, EnumeratorDef(_)) => true, - (_, _) => true, - }) + pub fn declareTag(&mut self, sueref: SUERef, decl: TagFwdDecl) -> DeclarationStatus { + match self.lookupTag(&sueref) { + None => (), + Some(old_def) if tagKind(old_def) == tagKind(&Left(decl)) => + return KeepDef(old_def.clone()), + Some(old_def) => + return KindMismatch(old_def.clone()), } + self.tagDecls.defLocal(sueref, Left(decl)); + NewDecl } -} -#[derive(Eq, Ord)] -pub enum TagEntryKind { - CompKind(CompTyKind), - EnumKind, -} -pub use self::TagEntryKind::*; + pub fn defineScopedIdentWhen(&mut self, override_def: F, ident: Ident, def: IdentDecl) + -> DeclarationStatus + where F: Fn(&IdentDecl) -> bool + { -pub fn tagKind(_0: TagEntry) -> TagEntryKind { - match (_0) { - Left(CompDecl(cd)) => CompKind((compTag(cd))), - Left(EnumDecl(_)) => EnumKind, - Right(CompDef(cd)) => CompKind((compTag(cd))), - Right(EnumDef(_)) => EnumKind, - } -} + let new_def = Right(def); -pub fn compatTagEntry(te1: TagEntry, te2: TagEntry) -> bool { - (tagKind(te1) == tagKind(te2)) -} + let old_decls = self.identDecls.clone(); + let old_decl_opt = old_decls.lookupInnermostScope(&ident).cloned(); -pub fn defRedeclStatus(sameKind: fn(t) -> fn(t) -> bool, - def: t, - oldDecl: Option) - -> DeclarationStatus { - match oldDecl { - Some(def_q) if sameKind(def, def_q) => Redeclared(def_q), - Some(def_q) => KindMismatch(def_q), - None => NewDecl, - } -} + let doOverride = |def: &IdentEntry| match *def { + Left(_) => false, + Right(ref old_def) => override_def(old_def), + }; -pub fn defRedeclStatusLocal(sameKind: fn(t) -> fn(t) -> bool, - ident: k, - def: t, - oldDecl: Option, - nsm: NameSpaceMap) - -> DeclarationStatus { - match defRedeclStatus(sameKind, def, oldDecl) { - NewDecl => { - match lookupName(nsm, ident) { - Some(shadowed) => Shadowed(shadowed), - None => NewDecl, - } + self.identDecls.defLocal(ident.clone(), new_def.clone()); + + if old_decl_opt.as_ref().map_or(false, |old_decl| !compatIdentEntry(old_decl, &new_def)) { + KindMismatch(old_decl_opt.unwrap()) + } else if old_decl_opt.as_ref().map_or(true, doOverride) { + defRedeclStatusLocal(compatIdentEntry, &ident, new_def, + old_decl_opt, &self.identDecls) + } else { + self.identDecls = old_decls; + old_decl_opt.map_or(NewDecl, KeepDef) } - redecl => redecl, } -} -pub fn defineTypeDef(ident: Ident, - tydef: TypeDef, - deftbl: DefTable) - -> (DeclarationStatus, DefTable) { + pub fn defineTypeDef(&mut self, ident: Ident, tydef: TypeDef) -> DeclarationStatus { + let old_decl = self.identDecls.defLocal(ident, Left(tydef.clone())); + defRedeclStatus(compatIdentEntry, Left(tydef), old_decl) + } - (defRedeclStatus(compatIdentEntry, (Left(tydef)), oldDecl), deftbl { identDecls: decls_q }) -} + pub fn defineGlobalIdent(&mut self, ident: Ident, def: IdentDecl) -> DeclarationStatus { + let old_decl = self.identDecls.defGlobal(ident, Right(def.clone())); + defRedeclStatus(compatIdentEntry, Right(def), old_decl) + } -pub fn defineGlobalIdent(ident: Ident, - def: IdentDecl, - deftbl: DefTable) - -> (DeclarationStatus, DefTable) { + pub fn defineTag(&mut self, sueref: SUERef, def: TagDef) -> DeclarationStatus { + let old_decl = self.tagDecls.defLocal(sueref.clone(), Right(def.clone())); - (defRedeclStatus(compatIdentEntry, (Right(def)), oldDecl), deftbl { identDecls: decls_q }) -} + let redeclStatus = match old_decl { + Some(fwd_decl @ Left(_)) => { + if tagKind(&fwd_decl) == tagKind(&Right(def)) { + NewDecl + } else { + KindMismatch(fwd_decl) + } + } + _ => { + defRedeclStatusLocal(compatTagEntry, + &sueref, + Right(def), + old_decl, + &self.tagDecls) + } + }; -pub fn defineScopedIdent() -> (DeclarationStatus, DefTable) { - defineScopedIdentWhen((__TODO_const(true))) -} + redeclStatus + } -pub fn defineScopedIdentWhen(override_def: fn(IdentDecl) -> bool, - ident: Ident, - def: IdentDecl, - deftbl: DefTable) - -> (DeclarationStatus, DefTable) { + pub fn defineLabel(&mut self, ident: Ident) -> DeclarationStatus { + let old_label = self.labelDefs.defLocal(ident.clone(), ident); + old_label.map_or(NewDecl, Redeclared) + } - let new_def = Right(def); + pub fn enterLocalScope(&mut self) { + self.identDecls.enterNewScope(); + self.tagDecls.enterNewScope(); + } - let old_decls = identDecls(deftbl); + pub fn leaveLocalScope(&mut self) { + self.identDecls.leaveScope(); + self.tagDecls.leaveScope(); + } - let old_decl_opt = lookupInnermostScope(old_decls, ident); + pub fn enterFunctionScope(&mut self) { + self.labelDefs.enterNewScope(); + self.enterLocalScope(); + } - let new_decls = fst((defLocal(old_decls, ident, new_def))); + pub fn leaveFunctionScope(&mut self) { + self.labelDefs.leaveScope(); + self.leaveLocalScope(); + } - let doOverride = |_0| match (_0) { - Left(_) => false, - Right(old_def) => override_def(old_def), - }; + pub fn enterBlockScope(&mut self) { + self.labelDefs.enterNewScope(); + self.enterLocalScope(); + } - let redeclStatus_q = |overriden_decl| { - defRedeclStatusLocal(compatIdentEntry, ident, new_def, overriden_decl, old_decls) - }; + pub fn leaveBlockScope(&mut self) { + self.labelDefs.leaveScope(); + self.leaveLocalScope(); + } - (redecl_status, deftbl { identDecls: decls_q }) -} + pub fn enterMemberDecl(&mut self) { + self.memberDecls.enterNewScope(); + } -pub fn declareTag(sueref: SUERef, - decl: TagFwdDecl, - deftbl: DefTable) - -> (DeclarationStatus, DefTable) { - match lookupTag(sueref, deftbl) { - None => { - (NewDecl, deftbl { tagDecls: fst(defLocal((tagDecls(deftbl)), sueref, (Left(decl)))) }) - } - Some(old_def) if (tagKind(old_def) == tagKind((Left(decl)))) => (KeepDef(old_def), deftbl), - Some(old_def) => (KindMismatch(old_def), deftbl), + pub fn leaveMemberDecl(&mut self) -> Vec { + self.memberDecls.leaveScope().into_iter().map(|kv| kv.1).collect() } } -pub fn defineTag(sueref: SUERef, - def: TagDef, - deftbl: DefTable) - -> (DeclarationStatus, DefTable) { - - let redeclStatus = match olddecl { - Some(fwd_decl, __OP__, Left(_)) if (tagKind(fwd_decl) == tagKind((Right(def)))) => NewDecl, - Some(fwd_decl, __OP__, Left(_)) => KindMismatch(fwd_decl), - _ => { - defRedeclStatusLocal(compatTagEntry, - sueref, - (Right(def)), - olddecl, - (tagDecls(deftbl))) - } - }; - - (redeclStatus, deftbl { tagDecls: decls_q }) +#[derive(Clone, Debug)] +pub enum DeclarationStatus { + NewDecl, + Redeclared(T), + KeepDef(T), + Shadowed(T), + KindMismatch(T), } +pub use self::DeclarationStatus::*; -pub fn defineLabel(ident: Ident, deftbl: DefTable) -> (DeclarationStatus, DefTable) { - { - let (labels_q, old_label) = defLocal((labelDefs(deftbl)), ident, ident); - - (maybe(NewDecl, Redeclared, old_label), deftbl { labelDefs: labels_q }) +pub fn declStatusDescr(decl: DeclarationStatus) -> &'static str { + match decl { + NewDecl => "new", + Redeclared(_) => "redeclared", + KeepDef(_) => "keep old", + Shadowed(_) => "shadowed", + KindMismatch(_) => "kind mismatch", } } -pub fn lookupIdent(ident: Ident, deftbl: DefTable) -> Option { - lookupName((identDecls(deftbl)), ident) +pub fn compatIdentEntry(entry: &IdentEntry, other: &IdentEntry) -> bool { + match (entry, other) { + (&Left(_), &Left(_)) => true, + (&Left(_), &Right(_)) | (&Right(_), &Left(_)) => false, + (&Right(ref def), &Right(ref other_def)) => match (def, other_def) { + // TODO: all true?! + (&EnumeratorDef(_), &EnumeratorDef(_)) => true, + (&EnumeratorDef(_), _) => true, + (_, &EnumeratorDef(_)) => true, + (_, _) => true, + }, + } } -pub fn lookupTag(sue_ref: SUERef, deftbl: DefTable) -> Option { - lookupName((tagDecls(deftbl)), sue_ref) +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum TagEntryKind { + CompKind(CompTyKind), + EnumKind, } +pub use self::TagEntryKind::*; -pub fn lookupLabel(ident: Ident, deftbl: DefTable) -> Option { - lookupName((labelDefs(deftbl)), ident) +pub fn tagKind(tag: &TagEntry) -> TagEntryKind { + match *tag { + Left(CompDecl(ref cd)) => CompKind(cd.compTag()), + Left(EnumDecl(_)) => EnumKind, + Right(CompDef(ref cd)) => CompKind(cd.compTag()), + Right(EnumDef(_)) => EnumKind, + } } -pub fn lookupIdentInner(ident: Ident, deftbl: DefTable) -> Option { - lookupInnermostScope((identDecls(deftbl)), ident) +pub fn compatTagEntry(te1: &TagEntry, te2: &TagEntry) -> bool { + tagKind(te1) == tagKind(te2) } -pub fn lookupTagInner(sue_ref: SUERef, deftbl: DefTable) -> Option { - lookupInnermostScope((tagDecls(deftbl)), sue_ref) +pub fn defRedeclStatus(sameKind: F, def: V, old_decl: Option) -> DeclarationStatus + where F: Fn(&V, &V) -> bool +{ + match old_decl { + None => NewDecl, + Some(def_q) => { + if sameKind(&def, &def_q) { + Redeclared(def_q) + } else { + KindMismatch(def_q) + } + } + } } -pub fn insertType(dt: DefTable, n: Name, t: Type) -> DefTable { - __assign!(dt, TODO { typeTable: IntMap::insert((nameId(n)), t, (typeTable(dt))) }) +pub fn defRedeclStatusLocal(sameKind: F, ident: &K, def: V, + old_decl: Option, nsm: &NameSpaceMap) + -> DeclarationStatus + where F: Fn(&V, &V) -> bool +{ + match defRedeclStatus(sameKind, def, old_decl) { + NewDecl => { + match nsm.lookupName(ident) { + Some(shadowed) => Shadowed(shadowed.clone()), + None => NewDecl, + } + } + redecl => redecl, + } } -pub fn lookupType(dt: DefTable, n: Name) -> Option { - IntMap::lookup((nameId(n)), (typeTable(dt))) +fn mergeHashMap(mut h1: HashMap, h2: HashMap) -> HashMap { + for (k, v) in h2 { + h1.insert(k, v); + } + h1 } -pub fn mergeDefTable(DefTable(i1, t1, l1, m1, r1, tt1): DefTable, - DefTable(i2, t2, l2, m2, r2, tt2): DefTable) - -> DefTable { +pub fn mergeDefTable(dt1: DefTable, dt2: DefTable) -> DefTable { DefTable { - identDecls: mergeNameSpace(i1, i2), - tagDecls: mergeNameSpace(t1, t2), - labelDefs: mergeNameSpace(l1, l2), - memberDecls: mergeNameSpace(m1, m2), - refTable: union(r1, r2), - typeTable: union(tt1, tt2), + identDecls: mergeNameSpace(dt1.identDecls, dt2.identDecls), + tagDecls: mergeNameSpace(dt1.tagDecls, dt2.tagDecls), + labelDefs: mergeNameSpace(dt1.labelDefs, dt2.labelDefs), + memberDecls: mergeNameSpace(dt1.memberDecls, dt2.memberDecls), + refTable: mergeHashMap(dt1.refTable, dt2.refTable), + typeTable: mergeHashMap(dt1.typeTable, dt2.typeTable), } } diff --git a/src/analysis/mod.rs b/src/analysis/mod.rs index 31ef71d..e8b6347 100644 --- a/src/analysis/mod.rs +++ b/src/analysis/mod.rs @@ -1,28 +1,19 @@ // Original file: "Analysis.hs" // File auto-generated using Corollary. -#[macro_use] -use corollary_support::*; +// uses HughesPJ prettyprinter API +// pub mod debug; -// NOTE: These imports are advisory. You probably need to change them to support Rust. -// use Language::C::Analysis::SemError; -// use Language::C::Analysis::SemRep; -// use Language::C::Analysis::TravMonad; -// use Language::C::Analysis::AstAnalysis; -// use Language::C::Analysis::DeclAnalysis; -// use Language::C::Analysis::Debug; - -pub mod ast_analysis; +// pub mod ast_analysis; pub mod builtins; -pub mod const_eval; -pub mod debug; -pub mod decl_analysis; +// pub mod const_eval; +// pub mod decl_analysis; pub mod def_table; -pub mod export; +// pub mod export; pub mod name_space_map; pub mod sem_error; pub mod sem_rep; pub mod trav_monad; -pub mod type_check; -pub mod type_conversions; +// pub mod type_check; +// pub mod type_conversions; pub mod type_utils; diff --git a/src/analysis/name_space_map.rs b/src/analysis/name_space_map.rs index 64d28c6..925e4c3 100644 --- a/src/analysis/name_space_map.rs +++ b/src/analysis/name_space_map.rs @@ -1,121 +1,110 @@ // Original file: "NameSpaceMap.hs" // File auto-generated using Corollary. -#[macro_use] -use corollary_support::*; +use std::collections::BTreeMap; -// NOTE: These imports are advisory. You probably need to change them to support Rust. -// use Prelude; -// use Prelude; -// use Data::Map; -// use Data::List; -// use Data::Map; -// use Map; - -pub struct NsMap(Map, Vec>); - -pub type NameSpaceMap = NsMap; +#[derive(Clone, Debug)] +pub struct NameSpaceMap { + gs: BTreeMap, + ls: Vec>, +} +impl NameSpaceMap { -pub fn globalNames(NsMap(g, _): NameSpaceMap) -> Map { - g -} + pub fn new() -> NameSpaceMap { + NameSpaceMap { gs: BTreeMap::new(), ls: vec![] } + } -pub fn hasLocalNames(NsMap(_, l): NameSpaceMap) -> bool { - not((null(l))) -} + pub fn globalNames(&self) -> &BTreeMap { + &self.gs + } -pub fn localNames(NsMap(_, l): NameSpaceMap) -> Vec> { - l -} + pub fn hasLocalNames(&self) -> bool { + !self.ls.is_empty() + } -pub fn nameSpaceMap() -> NameSpaceMap { - NsMap(Map::empty(), vec![]) -} + pub fn localNames(&self) -> &[Vec<(K, V)>] { + &self.ls + } -pub fn defGlobal(NsMap(gs, lss): NameSpaceMap, - ident: k, - def: a) - -> (NameSpaceMap, Option) { - (NsMap((Map::insert(ident, def, gs)), lss), Map::lookup(ident, gs)) -} + pub fn defGlobal(&mut self, ident: K, def: V) -> Option { + let prev = self.gs.get(&ident).cloned(); + self.gs.insert(ident, def); + prev + } -pub fn enterNewScope(NsMap(gs, lss): NameSpaceMap) -> NameSpaceMap { - NsMap(gs, (__op_concat(vec![], lss))) -} + pub fn enterNewScope(&mut self) { + self.ls.push(vec![]); + } -pub fn leaveScope(_0: NameSpaceMap) -> (NameSpaceMap, Vec<(k, a)>) { - match (_0) { - NsMap(_, []) => panic!("NsMaps.leaveScope: No local scope!"), - NsMap(gs, [ls, lss]) => (NsMap(gs, lss), ls), + pub fn leaveScope(&mut self) -> Vec<(K, V)> { + match self.ls.pop() { + None => panic!("NsMaps.leaveScope: No local scope!"), + Some(v) => v + } } -} -pub fn defLocal(_0: NameSpaceMap, - _1: k, - _2: a, - _3: (NameSpaceMap, Option)) - -> (NameSpaceMap, Option) { - match (_0, _1, _2, _3, _4) { - (ns, __OP__, NsMap(_, []), ident, def) => defGlobal(ns, ident, def), - (NsMap(gs, [ls, lss]), ident, def) => { - (NsMap(gs, (__op_concat((__op_concat((ident, def), ls)), lss))), - Prelude::lookup(ident, ls)) + pub fn defLocal(&mut self, ident: K, def: V) -> Option { + if self.ls.len() == 0 { // XXX: would match last_mut() with nonlexical borrows + return self.defGlobal(ident, def); } + let scope = self.ls.last_mut().unwrap(); + let prev = None; // TODO lookup ident in Vec + scope.push((ident, def)); + prev } -} -pub fn lookupName(ns: NameSpaceMap, - __OP__: k, - NsMap(_, localDefs): Option) - -> Option { - - let lookupLocal = |_0| match (_0) { - [] => None, - [ls, lss] => { - match Prelude::lookup(ident, ls) { - None => lookupLocal(lss), - Some(def) => Some(def), + pub fn lookupName(&self, ident: &K) -> Option<&V> { + for _scope in self.ls.iter().rev() { + if /* TODO lookup */ false { + return None; // Some(def) } } - }; - - match lookupLocal(localDefs) { - None => lookupGlobal(ns, ident), - Some(def) => Some(def), + self.lookupGlobal(ident) } -} -pub fn lookupGlobal(NsMap(gs, _): NameSpaceMap, ident: k) -> Option { - Map::lookup(ident, gs) -} + pub fn lookupGlobal(&self, ident: &K) -> Option<&V> { + self.gs.get(ident) + } -pub fn lookupInnermostScope(nsm: NameSpaceMap, - __OP__: k, - NsMap(_gs, localDefs): Option) - -> Option { - match localDefs { - [ls, _lss] => Prelude::lookup(ident, ls), - [] => lookupGlobal(nsm, ident), + pub fn lookupInnermostScope(&self, ident: &K) -> Option<&V> { + if let Some(_scope) = self.ls.last() { + if /* TODO lookup */ false { + return None; // Some(def) + } + } + self.lookupGlobal(ident) } -} -pub fn nsMapToList(NsMap(gs, lss): NameSpaceMap) -> Vec<(k, a)> { - __op_addadd(concat(lss), Map::toList(gs)) + pub fn toList(self) -> Vec<(K, V)> { + let NameSpaceMap { gs, ls } = self; + ls.into_iter().flat_map(|v| v).chain(gs.into_iter()).collect() + } } -pub fn mergeNameSpace(NsMap(global1, local1): NameSpaceMap, - NsMap(global2, local2): NameSpaceMap) - -> NameSpaceMap { - - let localUnion = |_0, _1| match (_0, _1) { - ([l1, ls1], [l2, ls2]) => { - __op_concat(List::unionBy((|p1, p2| (fst(p1) == fst(p2))), l1, l2), - localUnion(ls1, ls2)) +pub fn mergeNameSpace(map1: NameSpaceMap, map2: NameSpaceMap) + -> NameSpaceMap { + let NameSpaceMap { gs: mut global1, ls: mut local1 } = map1; + let NameSpaceMap { gs: mut global2, ls: mut local2 } = map2; + global1.append(&mut global2); + + let mut localUnion = Vec::new(); + // TODO use zip_longest from Itertools instead + loop { + match (local1.pop(), local2.pop()) { + (Some(mut l1), Some(mut l2)) => { + // TODO naive algorithm + l2.retain(|l2el| !l1.iter().any(|l1el| l1el.0 == l2el.0)); + l1.append(&mut l2); + localUnion.push(l1); + } + (Some(l), _) | (_, Some(l)) => { + localUnion.push(l); + } + _ => break, } - ([], ls2) => ls2, - (ls1, []) => ls1, - }; + } - NsMap((Map::union(global1, global2)), (localUnion(local1, local2))) + localUnion.reverse(); + NameSpaceMap { gs: global1, ls: localUnion } } diff --git a/src/analysis/sem_error.rs b/src/analysis/sem_error.rs index dcc907a..9fa3625 100644 --- a/src/analysis/sem_error.rs +++ b/src/analysis/sem_error.rs @@ -1,34 +1,46 @@ // Original file: "SemError.hs" // File auto-generated using Corollary. -#[macro_use] -use corollary_support::*; - -// NOTE: These imports are advisory. You probably need to change them to support Rust. -// use Data::Typeable; -// use Language::C::Analysis::SemRep; -// use Language::C::Data::Error; -// use Language::C::Data::Node; - use data::node::*; -use analysis::sem_rep::*; use data::error::*; +use data::position::Pos; +use analysis::sem_rep::*; #[derive(Debug)] pub struct InvalidASTError(pub ErrorInfo); +impl Error for InvalidASTError { + fn errorInfo(&self) -> ErrorInfo { self.0.clone() } +} + #[derive(Debug)] pub struct BadSpecifierError(pub ErrorInfo); +impl Error for BadSpecifierError { + fn errorInfo(&self) -> ErrorInfo { self.0.clone() } +} + #[derive(Debug)] pub struct RedefError(pub ErrorLevel, pub RedefInfo); +impl Error for RedefError { + fn errorInfo(&self) -> ErrorInfo { + let msgs = vec![ + self.1.redefErrReason(), + format!("The previous declaration was here: {}", + ((self.1).3).pos()), + ]; + ErrorInfo(self.0, ((self.1).2).pos().clone(), msgs) + } +} + +#[derive(Debug)] pub struct RedefInfo(pub String, pub RedefKind, pub NodeInfo, pub NodeInfo); - +#[derive(Clone, Copy, Debug)] pub enum RedefKind { DuplicateDef, DiffKindRedecl, @@ -38,62 +50,56 @@ pub enum RedefKind { } pub use self::RedefKind::*; -#[derive(Debug)] -pub struct TypeMismatch(pub String, pub (NodeInfo, Type), pub (NodeInfo, Type)); - +impl RedefInfo { + fn redefErrReason(&self) -> String { + match *self { + RedefInfo(ref ident, DuplicateDef, _, _) => { + format!("duplicate definition of {}", ident) + } + RedefInfo(ref ident, ShadowedDef, _, _) => { + format!("this declaration of {} shadows a previous one", ident) + } + RedefInfo(ref ident, DiffKindRedecl, _, _) => { + format!("{} previously declared as a different kind of symbol", ident) + } + RedefInfo(ref ident, DisagreeLinkage, _, _) => { + format!("{} previously declared with different linkage", ident) + } + RedefInfo(ref ident, NoLinkageOld, _, _) => { + format!("{} previously declared without linkage", ident) + } + } + } -pub fn invalidAST(node_info: NodeInfo, msg: String) -> InvalidASTError { - InvalidAST((mkErrorInfo(LevelError, msg, node_info))) + fn redefErrLabel(&self) -> String { + format!("{} redefined", self.0) + } } -pub fn badSpecifierError(node_info: NodeInfo, msg: String) -> BadSpecifierError { - BadSpecifierError((mkErrorInfo(LevelError, msg, node_info))) -} +#[derive(Debug)] +pub struct TypeMismatch(pub String, pub (NodeInfo, Type), pub (NodeInfo, Type)); -pub fn typeMismatch() -> TypeMismatch { - TypeMismatch +impl Error for TypeMismatch { + fn errorInfo(&self) -> ErrorInfo { + ErrorInfo(LevelError, ((self.1).0).pos().clone(), vec![self.0.clone()]) + } } -pub fn typeMismatchInfo(TypeMismatch(reason, (node1, _ty2), _t2): TypeMismatch) -> ErrorInfo { - ErrorInfo(LevelError, (posOfNode(node1)), vec![reason]) -} -pub fn redefErrLabel(RedefInfo(ident, _, _, _): RedefInfo) -> String { - __op_addadd(ident, " redefined".to_string()) +pub fn invalidAST(node_info: NodeInfo, msg: String) -> InvalidASTError { + InvalidASTError(mkErrorInfo(LevelError, msg, node_info)) } -pub fn redefErrorInfo(lvl: ErrorLevel, info: RedefInfo, __OP__: ErrorInfo) -> ErrorInfo { - ErrorInfo(lvl, - (posOfNode(node)), - (__op_addadd(vec![redefErrReason(info)], prevDeclMsg(old_node)))) +pub fn badSpecifierError(node_info: NodeInfo, msg: String) -> BadSpecifierError { + BadSpecifierError(mkErrorInfo(LevelError, msg, node_info)) } -pub fn redefErrReason(_0: RedefInfo) -> String { - match (_0) { - RedefInfo(ident, DuplicateDef, _, _) => { - __op_addadd("duplicate definition of ".to_string(), ident) - } - RedefInfo(ident, ShadowedDef, _, _) => { - __op_addadd("this declaration of ".to_string(), - __op_addadd(ident, " shadows a previous one".to_string())) - } - RedefInfo(ident, DiffKindRedecl, _, _) => { - __op_addadd(ident, - " previously declared as a different kind of symbol".to_string()) - } - RedefInfo(ident, DisagreeLinkage, _, _) => { - __op_addadd(ident, - " previously declared with different linkage".to_string()) - } - RedefInfo(ident, NoLinkageOld, _, _) => { - __op_addadd(ident, " previously declared without linkage".to_string()) - } - } +pub fn typeMismatch(s: String, t: (NodeInfo, Type), u: (NodeInfo, Type)) -> TypeMismatch { + TypeMismatch(s, t, u) } -pub fn prevDeclMsg(old_node: NodeInfo) -> Vec { - vec!["The previous declaration was here: ".to_string(), - show((posOfNode(old_node)))] +pub fn typeMismatchInfo(TypeMismatch(reason, (node1, _ty2), _t2): TypeMismatch) -> ErrorInfo { + ErrorInfo(LevelError, node1.into_pos(), vec![reason]) } pub fn redefinition(lvl: ErrorLevel, diff --git a/src/analysis/sem_rep.rs b/src/analysis/sem_rep.rs index fe10393..ab9af41 100644 --- a/src/analysis/sem_rep.rs +++ b/src/analysis/sem_rep.rs @@ -1,22 +1,24 @@ // Original file: "SemRep.hs" // File auto-generated using Corollary. -#[macro_use] -use corollary_support::*; - -// NOTE: These imports are advisory. You probably need to change them to support Rust. -// use Language::C::Data; -// use Language::C::Syntax; -// use Data::Map; -// use Map; -// use Data::Map; -// use Data::Maybe; -// use Data::Generics; +use std::collections::BTreeMap; use data::ident::*; use data::node::*; use syntax::ast::*; +pub trait HasCompTyKind { + fn compTag(&self) -> CompTyKind; +} + +pub trait HasSUERef { + fn sueRef(&self) -> SUERef; +} + +pub trait Declaration { + fn getVarDecl(&self) -> VarDecl; +} + #[derive(Clone, Debug)] pub enum TagDef { CompDef(CompType), @@ -24,41 +26,42 @@ pub enum TagDef { } pub use self::TagDef::*; -pub fn typeOfTagDef(_0: TagDef) -> TypeName { - match (_0) { +impl HasSUERef for TagDef { + fn sueRef(&self) -> SUERef { + match *self { + CompDef(ref ct) => ct.sueRef(), + EnumDef(ref et) => et.sueRef(), + } + } +} + +pub fn typeOfTagDef(def: TagDef) -> TypeName { + match def { CompDef(comptype) => typeOfCompDef(comptype), EnumDef(enumtype) => typeOfEnumDef(enumtype), } } -pub fn declOfDef(def: n) -> Decl { - { - let vd = getVarDecl(def); +pub fn declOfDef(def: &N) -> Decl { + let vd = def.getVarDecl(); - Decl(vd, (nodeInfo(def))) - } + Decl(vd, def.clone().into_node_info()) } -pub fn declIdent() -> Ident { - identOfVarName(declName) +pub fn declIdent(def: &N) -> Ident { + identOfVarName(declName(def)) } -pub fn declName() -> VarName { - (|VarDecl(n, _, _)| { - n - }(getVarDecl)) +pub fn declName(def: &N) -> VarName { + def.getVarDecl().0 } -pub fn declType() -> Type { - (|VarDecl(_, _, ty)| { - ty - }(getVarDecl)) +pub fn declType(def: &N) -> Type { + def.getVarDecl().2 } -pub fn declAttrs() -> DeclAttrs { - (|VarDecl(_, specs, _)| { - specs - }(getVarDecl)) +pub fn declAttrs(def: &N) -> DeclAttrs { + def.getVarDecl().1 } #[derive(Clone, Debug)] @@ -70,72 +73,83 @@ pub enum IdentDecl { } pub use self::IdentDecl::*; -pub fn objKindDescr(_0: IdentDecl) -> String { - match (_0) { - Declaration(_) => "declaration".to_string(), - ObjectDef(_) => "object definition".to_string(), - FunctionDef(_) => "function definition".to_string(), - EnumeratorDef(_) => "enumerator definition".to_string(), +impl Declaration for IdentDecl { + fn getVarDecl(&self) -> VarDecl { + match *self { + Declaration(ref decl) => decl.getVarDecl(), + ObjectDef(ref def) => def.getVarDecl(), + FunctionDef(ref def) => def.getVarDecl(), + EnumeratorDef(ref def) => def.getVarDecl(), + } } } -pub fn splitIdentDecls - (include_all: bool) - -> (Map, (Map, Map, Map)) { - - let deal = |ident, entry, (decls, defs)| { - (Map::insert(ident, (declOfDef(entry)), decls), addDef(ident, entry, defs)) - }; - - let deal_q = |_0, _1, _2| match (_0, _1, _2) { - (ident, Declaration(d), (decls, defs)) => (Map::insert(ident, d, decls), defs), - (ident, def, (decls, defs)) => (decls, addDef(ident, def, defs)), - }; +pub fn objKindDescr(decl: &IdentDecl) -> String { + match *decl { + Declaration(_) => "declaration", + ObjectDef(_) => "object definition", + FunctionDef(_) => "function definition", + EnumeratorDef(_) => "enumerator definition", + }.into() +} - let addDef = |ident, entry, (es, os, fs)| match entry { - Declaration(_) => (es, os, fs), - EnumeratorDef(e) => (Map::insert(ident, e, es), os, fs), - ObjectDef(o) => (es, Map::insert(ident, o, os), fs), - FunctionDef(f) => (es, os, Map::insert(ident, f, fs)), - }; +pub fn splitIdentDecls(include_all: bool, all: BTreeMap) + -> (BTreeMap, + (BTreeMap, BTreeMap, BTreeMap)) +{ + let mut decls = BTreeMap::new(); + let mut enums = BTreeMap::new(); + let mut objs = BTreeMap::new(); + let mut funcs = BTreeMap::new(); - Map::foldWithKey((if include_all { deal } else { deal_q }), - (Map::empty, (Map::empty, Map::empty, Map::empty))) + { + let mut addDef = |ident, entry| match entry { + Declaration(_) => {} + EnumeratorDef(e) => { enums.insert(ident, e); } + ObjectDef(o) => { objs.insert(ident, o); } + FunctionDef(f) => { funcs.insert(ident, f); } + }; + + for (ident, entry) in all { + if include_all { + decls.insert(ident.clone(), declOfDef(&entry)); + addDef(ident, entry); + } else { + match entry { + Declaration(d) => { decls.insert(ident, d); } + other => { addDef(ident, other); } + } + } + } + } + (decls, (enums, objs, funcs)) } pub struct GlobalDecls { - gObjs: Map, - gTags: Map, - gTypeDefs: Map, -} -fn gObjs(a: GlobalDecls) -> Map { - a.gObjs -} -fn gTags(a: GlobalDecls) -> Map { - a.gTags -} -fn gTypeDefs(a: GlobalDecls) -> Map { - a.gTypeDefs + pub gObjs: BTreeMap, + pub gTags: BTreeMap, + pub gTypeDefs: BTreeMap, } pub fn emptyGlobalDecls() -> GlobalDecls { - GlobalDecls(Map::empty, Map::empty, Map::empty) + GlobalDecls { gObjs: BTreeMap::new(), gTags: BTreeMap::new(), gTypeDefs: BTreeMap::new() } } -pub fn filterGlobalDecls(decl_filter: fn(DeclEvent) -> bool, gmap: GlobalDecls) -> GlobalDecls { +pub fn filterGlobalDecls(decl_filter: F, gmap: GlobalDecls) -> GlobalDecls + where F: Fn(DeclEvent) -> bool +{ GlobalDecls { - gObjs: Map::filter((decl_filter(DeclEvent)), (gObjs(gmap))), - gTags: Map::filter((decl_filter(TagEvent)), (gTags(gmap))), - gTypeDefs: Map::filter((decl_filter(TypeDefEvent)), (gTypeDefs(gmap))), + gObjs: gmap.gObjs.into_iter().filter(|&(_, ref v)| decl_filter(DeclEvent(v.clone()))).collect(), + gTags: gmap.gTags.into_iter().filter(|&(_, ref v)| decl_filter(TagEvent(v.clone()))).collect(), + gTypeDefs: gmap.gTypeDefs.into_iter().filter(|&(_, ref v)| decl_filter(TypeDefEvent(v.clone()))).collect(), } } -pub fn mergeGlobalDecls(gmap1: GlobalDecls, gmap2: GlobalDecls) -> GlobalDecls { - GlobalDecls { - gObjs: Map::union((gObjs(gmap1)), (gObjs(gmap2))), - gTags: Map::union((gTags(gmap1)), (gTags(gmap2))), - gTypeDefs: Map::union((gTypeDefs(gmap1)), (gTypeDefs(gmap2))), - } +pub fn mergeGlobalDecls(mut gmap1: GlobalDecls, mut gmap2: GlobalDecls) -> GlobalDecls { + gmap1.gObjs.append(&mut gmap2.gObjs); + gmap1.gTags.append(&mut gmap2.gTags); + gmap1.gTypeDefs.append(&mut gmap2.gTypeDefs); + gmap1 } pub enum DeclEvent { @@ -151,14 +165,38 @@ pub use self::DeclEvent::*; #[derive(Clone, Debug)] pub struct Decl(pub VarDecl, pub NodeInfo); +impl Declaration for Decl { + fn getVarDecl(&self) -> VarDecl { + self.0.clone() + } +} + #[derive(Clone, Debug)] pub struct ObjDef(pub VarDecl, pub Option, pub NodeInfo); +impl Declaration for ObjDef { + fn getVarDecl(&self) -> VarDecl { + self.0.clone() + } +} + +impl ObjDef { + pub fn isTentative(&self) -> bool { + if isExtDecl(&self.0) { self.1.is_none() } else { false } + } +} + #[derive(Clone, Debug)] pub struct FunDef(pub VarDecl, pub Stmt, pub NodeInfo); +impl Declaration for FunDef { + fn getVarDecl(&self) -> VarDecl { + self.0.clone() + } +} + #[derive(Clone, Debug)] pub enum ParamDecl { @@ -167,6 +205,15 @@ pub enum ParamDecl { } pub use self::ParamDecl::*; +impl Declaration for ParamDecl { + fn getVarDecl(&self) -> VarDecl { + match *self { + ParamDecl(ref vd, _) => vd.clone(), + AbstractParamDecl(ref vd, _) => vd.clone(), + } + } +} + #[derive(Clone, Debug)] pub enum MemberDecl { MemberDecl(VarDecl, Option, NodeInfo), @@ -174,49 +221,58 @@ pub enum MemberDecl { } pub use self::MemberDecl::*; +impl Declaration for MemberDecl { + fn getVarDecl(&self) -> VarDecl { + match *self { + MemberDecl(ref vd, ..) => vd.clone(), + AnonBitField(ref ty, ..) => VarDecl( + VarName::NoName, + DeclAttrs(noFunctionAttrs(), NoStorage, noAttributes()), + ty.clone()) + } + } +} + + #[derive(Clone, Debug)] pub struct TypeDef(pub Ident, pub Type, pub Attributes, pub NodeInfo); -pub fn identOfTypeDef(TypeDef(ide, _, _, _): TypeDef) -> Ident { - ide +pub fn identOfTypeDef(&TypeDef(ref ide, _, _, _): &TypeDef) -> Ident { + ide.clone() } #[derive(Clone, Debug)] -pub struct VarDecl(); +pub struct VarDecl(pub VarName, pub DeclAttrs, pub Type); + +impl Declaration for VarDecl { + fn getVarDecl(&self) -> VarDecl { + self.clone() + } +} -pub fn isExtDecl() -> bool { - hasLinkage(declStorage) +pub fn isExtDecl(decl: &D) -> bool { + declStorage(decl).hasLinkage() } #[derive(Clone, Debug)] pub struct DeclAttrs(pub FunctionAttrs, pub Storage, pub Attributes); -pub fn declStorage(d: d) -> Storage { - match declAttrs(d) { - DeclAttrs(_, st, _) => st, - } +pub fn declStorage(d: &D) -> Storage { + declAttrs(d).1 } -pub fn functionAttrs(d: d) -> FunctionAttrs { - match declAttrs(d) { - DeclAttrs(fa, _, _) => fa, - } +pub fn functionAttrs(d: &D) -> FunctionAttrs { + declAttrs(d).0 } -#[derive(Clone, Debug, Eq, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct FunctionAttrs { isInline: bool, isNoreturn: bool, } -fn isInline(a: FunctionAttrs) -> bool { - a.isInline -} -fn isNoreturn(a: FunctionAttrs) -> bool { - a.isNoreturn -} pub fn noFunctionAttrs() -> FunctionAttrs { FunctionAttrs { @@ -225,20 +281,11 @@ pub fn noFunctionAttrs() -> FunctionAttrs { } } -#[derive(Clone, Debug, Eq, Ord)] -pub enum Storage { - NoStorage, - Auto(Register), - Static(Linkage, ThreadLocal), - FunLinkage(Linkage), -} -pub use self::Storage::*; - pub type ThreadLocal = bool; pub type Register = bool; -#[derive(Clone, Debug, Eq, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Linkage { NoLinkage, InternalLinkage, @@ -246,17 +293,28 @@ pub enum Linkage { } pub use self::Linkage::*; -pub fn hasLinkage(_0: Storage) -> bool { - match (_0) { - Auto(_) => false, - Static(NoLinkage, _) => false, - _ => true, +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Storage { + NoStorage, + Auto(Register), + Static(Linkage, ThreadLocal), + FunLinkage(Linkage), +} +pub use self::Storage::*; + +impl Storage { + pub fn hasLinkage(self) -> bool { + match self { + Auto(_) => false, + Static(NoLinkage, _) => false, + _ => true, + } } } -pub fn declLinkage(decl: d) -> Linkage { +pub fn declLinkage(decl: &D) -> Linkage { match declStorage(decl) { - NoStorage => undefined, + NoStorage => panic!("undefined"), Auto(_) => NoLinkage, Static(linkage, _) => linkage, FunLinkage(linkage) => linkage, @@ -266,10 +324,10 @@ pub fn declLinkage(decl: d) -> Linkage { #[derive(Clone, Debug)] pub enum Type { DirectType(TypeName, TypeQuals, Attributes), - PtrType(Type, TypeQuals, Attributes), - ArrayType(Type, ArraySize, TypeQuals, Attributes), - FunctionType(FunType, Attributes), - TypeDefType(TypeDefRef, TypeQuals, Attributes), + PtrType(Box, TypeQuals, Attributes), + ArrayType(Box, ArraySize, TypeQuals, Attributes), + FunctionType(Box, Attributes), + TypeDefType(Box, TypeQuals, Attributes), } pub use self::Type::*; @@ -299,7 +357,7 @@ pub enum TypeName { } pub use self::TypeName::*; -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub enum BuiltinType { TyVaList, TyAny, @@ -310,7 +368,7 @@ pub use self::BuiltinType::*; pub struct TypeDefRef(pub Ident, pub Type, pub NodeInfo); -#[derive(Clone, Debug, Eq, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum IntType { TyBool, TyChar, @@ -329,7 +387,7 @@ pub enum IntType { } pub use self::IntType::*; -#[derive(Clone, Debug, Eq, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum FloatType { TyFloat, TyDouble, @@ -340,79 +398,106 @@ pub use self::FloatType::*; #[derive(Clone, Debug)] pub struct CompTypeRef(pub SUERef, pub CompTyKind, pub NodeInfo); +impl HasCompTyKind for CompTypeRef { + fn compTag(&self) -> CompTyKind { + self.1 + } +} + +impl HasSUERef for CompTypeRef { + fn sueRef(&self) -> SUERef { + self.0.clone() + } +} + #[derive(Clone, Debug)] pub struct EnumTypeRef(pub SUERef, pub NodeInfo); +impl HasSUERef for EnumTypeRef { + fn sueRef(&self) -> SUERef { + self.0.clone() + } +} + #[derive(Clone, Debug)] pub struct CompType(pub SUERef, pub CompTyKind, pub Vec, pub Attributes, pub NodeInfo); +impl HasCompTyKind for CompType { + fn compTag(&self) -> CompTyKind { + self.1 + } +} -pub fn typeOfCompDef(CompType(__ref, tag, _, _, _): CompType) -> TypeName { - TyComp((CompTypeRef(__ref, tag, undefNode))) +impl HasSUERef for CompType { + fn sueRef(&self) -> SUERef { + self.0.clone() + } +} + + +pub fn typeOfCompDef(CompType(ref_, tag, _, _, _): CompType) -> TypeName { + TyComp(CompTypeRef(ref_, tag, NodeInfo::undef())) } -#[derive(Clone, Debug, Eq, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum CompTyKind { StructTag, UnionTag, } pub use self::CompTyKind::*; + #[derive(Clone, Debug)] pub struct EnumType(pub SUERef, pub Vec, pub Attributes, pub NodeInfo); +impl HasSUERef for EnumType { + fn sueRef(&self) -> SUERef { + self.0.clone() + } +} -pub fn typeOfEnumDef(EnumType(__ref, _, _, _): EnumType) -> TypeName { - TyEnum((EnumTypeRef(__ref, undefNode))) + +pub fn typeOfEnumDef(EnumType(ref_, _, _, _): EnumType) -> TypeName { + TyEnum(EnumTypeRef(ref_, NodeInfo::undef())) } #[derive(Clone, Debug)] pub struct Enumerator(pub Ident, pub Expr, pub EnumType, pub NodeInfo); +impl Declaration for Enumerator { + fn getVarDecl(&self) -> VarDecl { + VarDecl(VarName::VarName(self.0.clone(), None), + DeclAttrs(noFunctionAttrs(), NoStorage, noAttributes()), + DirectType(typeOfEnumDef(self.2.clone()), noTypeQuals(), noAttributes())) + } +} + -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct TypeQuals { - constant: bool, - volatile: bool, - restrict: bool, - atomic: bool, - nullable: bool, - nonnull: bool, -} -fn constant(a: TypeQuals) -> bool { - a.constant -} -fn volatile(a: TypeQuals) -> bool { - a.volatile -} -fn restrict(a: TypeQuals) -> bool { - a.restrict -} -fn atomic(a: TypeQuals) -> bool { - a.atomic -} -fn nullable(a: TypeQuals) -> bool { - a.nullable -} -fn nonnull(a: TypeQuals) -> bool { - a.nonnull + pub constant: bool, + pub volatile: bool, + pub restrict: bool, + pub atomic: bool, + pub nullable: bool, + pub nonnull: bool, } pub fn noTypeQuals() -> TypeQuals { - TypeQuals(false, false, false, false, false, false) + TypeQuals::default() } -pub fn mergeTypeQuals(TypeQuals(c1, v1, r1, a1, n1, nn1): TypeQuals, - TypeQuals(c2, v2, r2, a2, n2, nn2): TypeQuals) - -> TypeQuals { - TypeQuals(((c1 && c2)), - ((v1 && v2)), - ((r1 && r2)), - ((a1 && a2)), - ((n1 && n2)), - ((nn1 && nn2))) +pub fn mergeTypeQuals(t1: TypeQuals, t2: TypeQuals) -> TypeQuals { + TypeQuals { + constant: t1.constant && t2.constant, + volatile: t1.volatile && t2.volatile, + restrict: t1.restrict && t2.restrict, + atomic: t1.atomic && t2.atomic, + nullable: t1.nullable && t2.nullable, + nonnull: t1.nonnull && t2.nonnull, + } } pub type Initializer = CInit; @@ -424,15 +509,15 @@ pub enum VarName { } pub use self::VarName::*; -pub fn identOfVarName(_0: VarName) -> Ident { - match (_0) { +pub fn identOfVarName(name: VarName) -> Ident { + match name { NoName => panic!("identOfVarName: NoName"), VarName(ident, _) => ident, } } -pub fn isNoName(_0: VarName) -> bool { - match (_0) { +pub fn isNoName(name: VarName) -> bool { + match name { NoName => true, _ => false, } @@ -452,10 +537,57 @@ pub fn noAttributes() -> Attributes { vec![] } -pub fn mergeAttributes() -> Attributes { - (__op_addadd) +pub fn mergeAttributes(mut a1: Attributes, mut a2: Attributes) -> Attributes { + a1.append(&mut a2); + a1 } pub type Stmt = CStat; pub type Expr = CExpr; + + +macro_rules! implement_cnode_pos { + (struct $ty:ident) => { + impl CNode for $ty { + fn node_info(&self) -> &NodeInfo { + let $ty(.., ref ni) = *self; ni + } + fn into_node_info(self) -> NodeInfo { + let $ty(.., ni) = self; ni + } + } + }; + (enum $ty:ident, $($variant:ident),+) => { + impl CNode for $ty { + fn node_info(&self) -> &NodeInfo { + match *self { + $( $variant(.., ref obj) => obj.node_info() ),* + } + } + fn into_node_info(self) -> NodeInfo { + match self { + $( $variant(.., obj) => obj.into_node_info() ),* + } + } + } + }; +} + +implement_cnode_pos!(enum TagDef, CompDef, EnumDef); +implement_cnode_pos!(enum IdentDecl, Declaration, ObjectDef, FunctionDef, EnumeratorDef); +implement_cnode_pos!(enum DeclEvent, TagEvent, DeclEvent, ParamEvent, LocalEvent, + TypeDefEvent, AsmEvent); +implement_cnode_pos!(struct Decl); +implement_cnode_pos!(struct ObjDef); +implement_cnode_pos!(struct FunDef); +implement_cnode_pos!(enum ParamDecl, ParamDecl, AbstractParamDecl); +implement_cnode_pos!(enum MemberDecl, MemberDecl, AnonBitField); +implement_cnode_pos!(struct TypeDef); +implement_cnode_pos!(struct TypeDefRef); +implement_cnode_pos!(struct CompTypeRef); +implement_cnode_pos!(struct EnumTypeRef); +implement_cnode_pos!(struct CompType); +implement_cnode_pos!(struct EnumType); +implement_cnode_pos!(struct Enumerator); +implement_cnode_pos!(struct Attr); diff --git a/src/analysis/trav_monad.rs b/src/analysis/trav_monad.rs index b7fe8f5..f92712c 100644 --- a/src/analysis/trav_monad.rs +++ b/src/analysis/trav_monad.rs @@ -1,528 +1,426 @@ // Original file: "TravMonad.hs" // File auto-generated using Corollary. -#[macro_use] -use corollary_support::*; - -// NOTE: These imports are advisory. You probably need to change them to support Rust. -// use Language::C::Data; -// use Language::C::Data::RList; -// use Language::C::Analysis::Builtins; -// use Language::C::Analysis::SemError; -// use Language::C::Analysis::SemRep; -// use Language::C::Analysis::TypeUtils; -// use sameType; -// use Language::C::Analysis::DefTable; -// use Language::C::Analysis::DefTable; -// use Data::IntMap; -// use insert; -// use Data::Maybe; -// use Control::Applicative; -// use Applicative; -// use Control::Monad; -// use liftM; -// use Prelude; - -use data::name::newNameSupply; +use std::mem; +use either::Either::*; + +use data::error::Error; +use data::node::*; +use data::name::*; use analysis::def_table::*; use analysis::sem_rep::*; use analysis::sem_error::*; +use analysis::builtins::*; +use analysis::type_utils::*; use data::ident::*; use data::error::*; -pub fn checkRedef(subject: String, new_decl: t, redecl_status: DeclarationStatus) -> m<()> { - match redecl_status { - NewDecl => (), - Redeclared(old_def) => { - throwTravError(redefinition(LevelError, - subject, - DuplicateDef, - (nodeInfo(new_decl)), - (nodeInfo(old_def)))) - } - KindMismatch(old_def) => { - throwTravError(redefinition(LevelError, - subject, - DiffKindRedecl, - (nodeInfo(new_decl)), - (nodeInfo(old_def)))) - } - Shadowed(_old_def) => (), - KeepDef(_old_def) => (), - } -} - -pub fn handleTagDecl(decl: TagFwdDecl) -> m<()> { - /*do*/ - { - let redecl = withDefTable(declareTag((sueRef(decl)), decl)); - checkRedef((sueRefToString(sueRef(decl))), decl, redecl) +pub fn isDeclaration(decl: &IdentDecl) -> bool { + match *decl { + Declaration(_) => true, + _ => false, } } -pub fn handleTagDef(def: TagDef) -> m<()> { - /*do*/ - { - let redecl = withDefTable(defineTag((sueRef(def)), def)); - - checkRedef((sueRefToString(sueRef(def))), def, redecl); - handleDecl((TagEvent(def))) - } +pub fn mismatchErr(ctx: &str, expect: &str, found: &str) -> String { + format!("{}: Expected {}, but found: {}", ctx, expect, found) } -pub fn handleEnumeratorDef(enumerator: Enumerator) -> m<()> { - /*do*/ - { - let ident = declIdent(enumerator); - - let redecl = withDefTable(defineScopedIdent(ident, (EnumeratorDef(enumerator)))); - - checkRedef((identToString(ident)), ident, redecl); - () - } +pub fn hadHardErrors(errors: &[CError]) -> bool { + errors.iter().any(isHardError) } -pub fn handleTypeDef(typeDef: TypeDef, __OP__: m<()>) -> m<()> { - /*do*/ - { - let redecl = withDefTable(defineTypeDef(ident, typeDef)); - - match redecl { - Redeclared(Left(TypeDef(_, t2, _, _))) if sameType(t1, t2) => (), - _ => checkRedef((identToString(ident)), typeDef, redecl), - }; - handleDecl((TypeDefEvent(typeDef))); - () - } +pub fn travErrors(a: &mut TravState) -> Vec { + let mut errors = mem::replace(&mut a.rerrors, vec![]); + errors.reverse(); + errors } -pub fn handleAsmBlock(asm: AsmBlock) -> m<()> { - handleDecl((AsmEvent(asm))) +pub fn checkCompatibleTypes(_: Type, _: Type) -> Result<(), TypeMismatch> { + // TODO: is that all? + Ok(()) } -pub fn redefErr(name: Ident, lvl: ErrorLevel, new: new, old: old, kind: RedefKind) -> m<()> { - throwTravError(redefinition(lvl, - (identToString(name)), - kind, - (nodeInfo(new)), - (nodeInfo(old)))) +fn redefErr(name: Ident, lvl: ErrorLevel, new: N, old: O, + kind: RedefKind) -> TravResult<()> { + Err(redefinition(lvl, + name.to_string(), + kind, + new.into_node_info(), + old.into_node_info()).toError()) } -pub fn _checkIdentTyRedef(_0: IdentEntry, _1: DeclarationStatus) -> m<()> { - match (_0, _1) { - (Right(decl), status) => checkVarRedef(decl, status), - (Left(tydef), KindMismatch(old_def)) => { - redefErr((identOfTypeDef(tydef)), - LevelError, - tydef, - old_def, - DiffKindRedecl) - } - (Left(tydef), Redeclared(old_def)) => { - redefErr((identOfTypeDef(tydef)), - LevelError, - tydef, - old_def, - DuplicateDef) - } - (Left(_tydef), _) => (), - } +fn linkageErr(new_def: IdentDecl, old_def: IdentDecl) -> TravResult<()> { + let kind = match (declLinkage(&new_def), declLinkage(&old_def)) { + (NoLinkage, _) => NoLinkageOld, + _ => DisagreeLinkage, + }; + redefErr(declIdent(&new_def), LevelError, new_def, old_def, kind) } -pub fn checkVarRedef(def: IdentDecl, redecl: DeclarationStatus) -> m<()> { - let redefVarErr = |old_def, kind| redefErr((declIdent(def)), LevelError, def, old_def, kind); +#[derive(Clone, Copy)] +pub enum CLanguage { + C89, + C99, + GNU89, + GNU99, +} - let linkageErr = |new_def, old_def| match (declLinkage(new_def), declLinkage(old_def)) { - (NoLinkage, _) => { - redefErr((declIdent(new_def)), - LevelError, - new_def, - old_def, - NoLinkageOld) - } - _ => { - redefErr((declIdent(new_def)), - LevelError, - new_def, - old_def, - DisagreeLinkage) - } - }; +pub struct TravOptions { + language: CLanguage, +} - let new_ty = declType(def); +type ExtDeclHandler = Fn(&mut TravState, DeclEvent); - let canBeOverwritten = |_0| match (_0) { - Declaration(_) => true, - ObjectDef(od) => isTentative(od), - _ => false, - }; +pub struct TravState { + symbolTable: DefTable, + rerrors: Vec, + nameGenerator: Box>, + userState: S, + options: TravOptions, +} - match redecl { - KindMismatch(old_def) => redefVarErr(old_def, DiffKindRedecl), - KeepDef(Right(old_def)) if not((agreeOnLinkage(def, old_def))) => linkageErr(def, old_def), - KeepDef(Right(old_def)) => throwOnLeft(checkCompatibleTypes(new_ty, (declType(old_def)))), - Redeclared(Right(old_def)) if not((agreeOnLinkage(def, old_def))) => { - linkageErr(def, old_def) +impl TravState { + fn new(userst: S) -> TravState { + TravState { + symbolTable: DefTable::new(), + rerrors: Vec::new(), + nameGenerator: new_name_supply(), + userState: userst, + options: TravOptions { language: CLanguage::C99 }, } - Redeclared(Right(old_def)) if not((canBeOverwritten(old_def))) => { - redefVarErr(old_def, DuplicateDef) - } - Redeclared(Right(old_def)) => { - throwOnLeft(checkCompatibleTypes(new_ty, (declType(old_def)))) - } - _ => (), } } -pub fn handleVarDecl(is_local: bool, decl: Decl) -> m<()> { - /*do*/ - { - let def = enterDecl(decl, (__TODO_const(false))); +pub struct Trav { + state: TravState, + doHandleExtDecl: Box>, +} - handleDecl(((if is_local { LocalEvent } else { DeclEvent })(def))) +pub fn runTrav(state: S, mut do_traversal: F) -> Result<(T, TravState), Vec> + where F: FnMut(&mut Trav) -> TravResult +{ + let mut trav = Trav { state: TravState::new(state), doHandleExtDecl: Box::new(|_, _| ()) }; + trav.state.symbolTable = builtins(); + match do_traversal(&mut trav) { + Err(trav_err) => Err(vec![trav_err]), + Ok(_) if hadHardErrors(&trav.state.rerrors) => Err(travErrors(&mut trav.state)), + Ok(v) => Ok((v, trav.state)), } } -pub fn handleParamDecl(_0: ParamDecl) -> m<()> { - match _0 { - pd @ AbstractParamDecl(_, _) => handleDecl((ParamEvent(pd))), - pd @ ParamDecl(vardecl, node) => { - /*do*/ - { - let def = ObjectDef((ObjDef(vardecl, None, node))); - - let redecl = withDefTable(defineScopedIdent((declIdent(def)), def)); - - checkVarRedef(def, redecl); - handleDecl((ParamEvent(pd))) +pub fn runTrav_(mut do_traversal: F) -> Result<(T, Vec), Vec> + where F: FnMut(&mut Trav<()>) -> TravResult +{ + runTrav((), |trav| { + let v = do_traversal(trav)?; + Ok((v, travErrors(&mut trav.state))) + }).map(|x| x.0) +} + +pub type TravResult = Result; + +impl Trav { + pub fn checkRedef(&mut self, subject: String, new_decl: T, + redecl_status: DeclarationStatus) -> TravResult<()> { + match redecl_status { + NewDecl => Ok(()), + Redeclared(old_def) => { + Err(redefinition(LevelError, + subject, + DuplicateDef, + new_decl.into_node_info(), + old_def.into_node_info()).toError()) + } + KindMismatch(old_def) => { + Err(redefinition(LevelError, + subject, + DiffKindRedecl, + new_decl.into_node_info(), + old_def.into_node_info()).toError()) } + Shadowed(_old_def) => Ok(()), + KeepDef(_old_def) => Ok(()), } } -} - -pub fn enterDecl(decl: Decl, cond: fn(IdentDecl) -> bool) -> m { - /*do*/ - { - let def = Declaration(decl); - - let redecl = withDefTable(defineScopedIdentWhen(cond, (declIdent(def)), def)); - checkVarRedef(def, redecl); - def + pub fn handleDecl(&mut self, decl: DeclEvent) -> TravResult<()> { + (self.doHandleExtDecl)(&mut self.state, decl); + Ok(()) } -} - -pub fn handleFunDef(ident: Ident, fun_def: FunDef) -> m<()> { - /*do*/ - { - let def = FunctionDef(fun_def); - - let redecl = withDefTable(defineScopedIdentWhen(isDeclaration, ident, def)); - checkVarRedef(def, redecl); - handleDecl((DeclEvent(def))) + pub fn handleTagDecl(&mut self, decl: TagFwdDecl) -> TravResult<()> { + let redecl = self.state.symbolTable.declareTag(decl.sueRef(), decl.clone()); + self.checkRedef(decl.sueRef().to_string(), decl, redecl) } -} -pub fn isDeclaration(_0: IdentDecl) -> bool { - match (_0) { - Declaration(_) => true, - _ => false, + pub fn handleTagDef(&mut self, def: TagDef) -> TravResult<()> { + let redecl = self.state.symbolTable.defineTag(def.sueRef(), def.clone()); + self.checkRedef(def.sueRef().to_string(), def.clone(), redecl)?; + self.handleDecl(TagEvent(def)) } -} - -pub fn checkCompatibleTypes(_: Type, _: Type) -> Result<(), TypeMismatch> { - Ok(()) -} -pub fn handleObjectDef(local: bool, ident: Ident, obj_def: ObjDef) -> m<()> { - - let isTentativeDef = |_0| match (_0) { - ObjectDef(object_def) => isTentative(object_def), - _ => false, - }; - - /*do*/ - { - let def = ObjectDef(obj_def); - - let redecl = withDefTable(defineScopedIdentWhen((shouldOverride(def)), ident, def)); - - checkVarRedef(def, redecl); - handleDecl(((if local { LocalEvent } else { DeclEvent })(def))) + pub fn handleEnumeratorDef(&mut self, enumerator: Enumerator) -> TravResult<()> { + let ident = declIdent(&enumerator); + let redecl = self.state.symbolTable.defineScopedIdent(ident.clone(), EnumeratorDef(enumerator)); + self.checkRedef(ident.clone().to_string(), ident, redecl) } -} -pub fn updDefTable(f: fn(DefTable) -> DefTable) -> m<()> { - withDefTable((|st| ((), f(st)))) -} + pub fn handleTypeDef(&mut self, typeDef: TypeDef) -> TravResult<()> { + match typeDef.clone() { + TypeDef(ident, t1, ..) => { + let redecl = self.state.symbolTable.defineTypeDef(ident.clone(), typeDef.clone()); -pub fn enterPrototypeScope() -> m<()> { - updDefTable(ST::enterBlockScope()) -} - -pub fn leavePrototypeScope() -> m<()> { - updDefTable(ST::leaveBlockScope()) -} - -pub fn enterFunctionScope() -> m<()> { - updDefTable(ST::enterFunctionScope()) -} - -pub fn leaveFunctionScope() -> m<()> { - updDefTable(ST::leaveFunctionScope()) -} - -pub fn enterBlockScope() -> m<()> { - updDefTable(ST::enterBlockScope()) -} + match redecl { + Redeclared(Left(TypeDef(_, ref t2, _, _))) if sameType(t1, t2.clone()) => (), + _ => self.checkRedef(ident.to_string(), typeDef.clone(), redecl)?, + }; + self.handleDecl(TypeDefEvent(typeDef)) + } + } + } -pub fn leaveBlockScope() -> m<()> { - updDefTable(ST::leaveBlockScope()) -} + pub fn handleAsmBlock(&mut self, asm: AsmBlock) -> TravResult<()> { + self.handleDecl(AsmEvent(asm)) + } -pub fn lookupTypeDef(ident: Ident) -> m { + pub fn _checkIdentTyRedef(&mut self, _0: IdentEntry, _1: DeclarationStatus) -> TravResult<()> { + match (_0, _1) { + (Right(decl), status) => self.checkVarRedef(decl, status), + (Left(tydef), KindMismatch(old_def)) => { + redefErr(identOfTypeDef(&tydef), LevelError, tydef, old_def, DiffKindRedecl) + } + (Left(tydef), Redeclared(old_def)) => { + redefErr(identOfTypeDef(&tydef), LevelError, tydef, old_def, DuplicateDef) + } + (Left(_tydef), _) => Ok(()), + } + } - let wrongKindErrMsg = |d| { - __op_addadd("wrong kind of object: expected typedef but found ".to_string(), - __op_addadd((objKindDescr(d)), - __op_addadd(" (for identifier `".to_string(), - __op_addadd(identToString(ident), "\')".to_string())))) - }; + pub fn checkVarRedef(&mut self, def: IdentDecl, redecl: DeclarationStatus) -> TravResult<()> { + let new_ty = declType(&def); - __op_bind(getDefTable, |symt| match lookupIdent(ident, symt) { - None => { - astError((nodeInfo(ident)), - __op_addadd("unbound typeDef: ".to_string(), identToString(ident))) + fn canBeOverwritten(def: &IdentDecl) -> bool { + match *def { + Declaration(_) => true, + ObjectDef(ref od) => od.isTentative(), + _ => false, + } } - Some(Left(TypeDef(def_ident, ty, _, _))) => __op_rshift(addRef(ident, def_ident), ty), - Some(Right(d)) => astError((nodeInfo(ident)), (wrongKindErrMsg(d))), - }) -} -pub fn lookupObject(ident: Ident) -> m> { - /*do*/ - { - let old_decl = liftM((lookupIdent(ident)), getDefTable); - - mapMaybeM(old_decl, |obj| match obj { - Right(objdef) => __op_rshift(addRef(ident, objdef), objdef), - Left(_tydef) => { - astError((nodeInfo(ident)), - (mismatchErr("lookupObject".to_string(), - "an object".to_string(), - "a typeDef".to_string()))) + fn agreeOnLinkage(new_def: &IdentDecl, old_def: &IdentDecl) -> bool { + if declStorage(old_def) == FunLinkage(InternalLinkage) { + true + } else if !declStorage(new_def).hasLinkage() || !declStorage(old_def).hasLinkage() { + false + } else if declLinkage(new_def) != declLinkage(old_def) { + false + } else { + true } - }) - } -} - -pub fn addRef(__use: u, def: d) -> m<()> { - match (nodeInfo(__use), nodeInfo(def)) { - (NodeInfo(_, _, useName), NodeInfo(_, _, defName)) => { - withDefTable((|dt| { - ((), - dt { refTable: insert((nameId(useName)), defName, (refTable(dt))) }) - })) } - (_, _) => (), - } -} -pub fn mismatchErr(ctx: String, expect: String, found: String) -> String { - __op_addadd(ctx, - __op_addadd(": Expected ".to_string(), - __op_addadd(expect, __op_addadd(", but found: ".to_string(), found)))) -} - -pub fn createSUERef(_0: NodeInfo, _1: Option) -> m { - match (_0, _1) { - (_node_info, Some(ident)) => NamedRef(ident), - (node_info, None) => { - /* Expr::Error */ - Error + match redecl { + KindMismatch(old_def) => { + redefErr(declIdent(&def), LevelError, def, old_def, DiffKindRedecl) + } + KeepDef(Right(old_def)) => { + if !agreeOnLinkage(&def, &old_def) { + linkageErr(def, old_def) + } else { + checkCompatibleTypes(new_ty, declType(&old_def)).map_err(Error::toError) + } + } + Redeclared(Right(old_def)) => { + if !agreeOnLinkage(&def, &old_def) { + linkageErr(def, old_def) + } else if !canBeOverwritten(&old_def) { + redefErr(declIdent(&def), LevelError, def, old_def, DuplicateDef) + } else { + checkCompatibleTypes(new_ty, declType(&old_def)).map_err(Error::toError) + } + } + _ => Ok(()), } } -} -pub fn handleTravError(a: m) -> m> { - catchTravError(liftM(Some, a), (|e| __op_rshift(recordError(e), None))) -} + pub fn handleVarDecl(&mut self, is_local: bool, decl: Decl) -> TravResult<()> { + let def = self.enterDecl(decl, |_| false)?; + self.handleDecl(if is_local { LocalEvent(def) } else { DeclEvent(def) }) + } -pub fn hadHardErrors() -> bool { - any(isHardError) -} + pub fn handleParamDecl(&mut self, decl: ParamDecl) -> TravResult<()> { + match decl.clone() { + AbstractParamDecl(_, _) => self.handleDecl(ParamEvent(decl)), + ParamDecl(vardecl, node) => { + let def = ObjectDef(ObjDef(vardecl, None, node)); -pub fn astError(node: NodeInfo, msg: String) -> m { - throwTravError(invalidAST(node, msg)) -} + let redecl = self.state.symbolTable.defineScopedIdent(declIdent(&def), def.clone()); -pub fn throwOnLeft(_0: Result) -> m { - match (_0) { - Err(err) => throwTravError(err), - Ok(v) => v, + self.checkVarRedef(def, redecl)?; + self.handleDecl(ParamEvent(decl)) + } + } } -} -pub fn warn(err: e) -> m<()> { - recordError((changeErrorLevel(err, LevelWarn))) -} - -pub struct Trav { - unTrav: fn(TravState) -> Result<(a, TravState), CError>, -} -fn unTrav(a: Trav) -> fn(TravState) -> Result<(a, TravState), CError> { - a.unTrav -} + pub fn enterDecl(&mut self, decl: Decl, cond: F) -> TravResult + where F: Fn(&IdentDecl) -> bool + { + let def = Declaration(decl); + let redecl = self.state.symbolTable.defineScopedIdentWhen(cond, declIdent(&def), def.clone()); + self.checkVarRedef(def.clone(), redecl)?; + Ok(def) + } -pub fn modify(f: fn(TravState) -> TravState) -> Trav { - Trav((|s| Right(((), f(s))))) -} + pub fn handleFunDef(&mut self, ident: Ident, fun_def: FunDef) -> TravResult<()> { + let def = FunctionDef(fun_def); -pub fn gets(f: fn(TravState) -> a) -> Trav { - Trav((|s| Right((f(s), s)))) -} + let redecl = self.state.symbolTable.defineScopedIdentWhen(isDeclaration, ident, def.clone()); -pub fn get() -> Trav> { - Trav((|s| Right((s, s)))) -} + self.checkVarRedef(def.clone(), redecl)?; + self.handleDecl(DeclEvent(def)) + } -pub fn put(s: TravState) -> Trav { - Trav((|_| Right(((), s)))) -} + pub fn handleObjectDef(&mut self, local: bool, ident: Ident, obj_def: ObjDef) -> TravResult<()> { + fn isTentativeDef(def: &IdentDecl) -> bool { + match *def { + ObjectDef(ref object_def) => object_def.isTentative(), + _ => false, + } + } -pub fn runTrav(state: s, traversal: Trav) -> Result<(a, TravState), Vec> { + let def = ObjectDef(obj_def); - let action = /*do*/ { - withDefTable((__TODO_const(((), builtins)))); - traversal + let redecl = { + let shouldOverride = |old: &IdentDecl| { + isDeclaration(old) || !isTentativeDef(&def) || isTentativeDef(old) + }; + self.state.symbolTable.defineScopedIdentWhen(shouldOverride, ident, def.clone()) }; - match unTrav(action, (initTravState(state))) { - Err(trav_err) => Err(vec![trav_err]), - Ok((v, ts)) if hadHardErrors((travErrors(ts))) => Err((travErrors(ts))), - Ok((v, ts)) => Ok((v, ts)), + self.checkVarRedef(def.clone(), redecl)?; + self.handleDecl(if local { LocalEvent(def) } else { DeclEvent(def) }) } -} -pub fn runTrav_(t: Trav<(), a>) -> Result<(a, Vec), Vec> { - fmap(fst, - runTrav((), - /*do*/ - { - let r = t; + pub fn enterPrototypeScope(&mut self) { + self.state.symbolTable.enterBlockScope(); + } - let es = getErrors; + pub fn leavePrototypeScope(&mut self) { + self.state.symbolTable.leaveBlockScope(); + } - (r, es) - })) -} + pub fn enterFunctionScope(&mut self) { + self.state.symbolTable.enterFunctionScope(); + } -pub fn withExtDeclHandler(action: Trav, - handler: fn(DeclEvent) -> Trav) - -> Trav { - /*do*/ - { - modify(|st| st { doHandleExtDecl: handler }); - action + pub fn leaveFunctionScope(&mut self) { + self.state.symbolTable.leaveFunctionScope(); } -} -pub enum CLanguage { - C89, - C99, - GNU89, - GNU99, -} -pub use self::CLanguage::*; + pub fn enterBlockScope(&mut self) { + self.state.symbolTable.enterBlockScope(); + } -pub struct TravOptions { - language: CLanguage, -} -fn language(a: TravOptions) -> CLanguage { - a.language -} + pub fn leaveBlockScope(&mut self) { + self.state.symbolTable.leaveBlockScope(); + } -pub struct TravState { - symbolTable: DefTable, - rerrors: RList, - nameGenerator: Vec, - doHandleExtDecl: fn(DeclEvent) -> Trav, - userState: s, - options: TravOptions, -} -fn symbolTable(a: TravState) -> DefTable { - a.symbolTable -} -fn rerrors(a: TravState) -> RList { - a.rerrors -} -fn nameGenerator(a: TravState) -> Vec { - a.nameGenerator -} -fn doHandleExtDecl(a: TravState) -> fn(DeclEvent) -> Trav { - a.doHandleExtDecl -} -fn userState(a: TravState) -> s { - a.userState -} -fn options(a: TravState) -> TravOptions { - a.options -} + pub fn lookupTypeDef(&mut self, ident: Ident) -> TravResult { + match self.state.symbolTable.lookupIdent(&ident).cloned() { + None => { + Err(invalidAST(ident.node_info().clone(), + format!("unbound typeDef: {}", ident.to_string())).toError()) + } + Some(Right(d)) => { + Err(invalidAST(ident.node_info().clone(), + format!("wrong kind of object: expected typedef but found {} \ + (for identifier `{}')", + objKindDescr(&d), ident.to_string())).toError()) + } + Some(Left(TypeDef(def_ident, ty, _, _))) => { + self.addRef(ident, def_ident); + Ok(ty) + } + } + } -pub fn travErrors() -> Vec { - RList::reverse(rerrors) -} + pub fn lookupObject(&mut self, ident: Ident) -> TravResult> { + match self.state.symbolTable.lookupIdent(&ident).cloned() { + None => Ok(None), + Some(Right(objdef)) => { + self.addRef(ident, objdef.clone()); + Ok(Some(objdef)) + } + Some(Left(_)) => { + Err(invalidAST(ident.node_info().clone(), + mismatchErr("lookupObject", "an object", "a typeDef")).toError()) + } + } + } -pub fn initTravState(userst: s) -> TravState { - TravState { - symbolTable: emptyDefTable, - rerrors: RList::empty, - nameGenerator: newNameSupply, - doHandleExtDecl: __TODO_const((())), - userState: userst, - options: TravOptions { language: C99 }, + pub fn addRef(&mut self, use_: U, def: D) { + match (use_.into_node_info(), def.into_node_info()) { + (NodeInfo(_, _, useName), NodeInfo(_, _, defName)) => { + self.state.symbolTable.refTable.insert(useName, defName); + } + _ => {} + } } -} -pub fn modifyUserState(f: fn(s) -> s) -> Trav { - modify(|ts| ts { userState: f((userState(ts))) }) -} + pub fn createSUERef(&mut self, node_info: NodeInfo, ident: Option) -> TravResult { + match ident { + Some(ident) => Ok(NamedRef(ident)), + None => if let Some(name) = node_info.clone().name() { + Ok(AnonymousRef(name)) + } else { + Err(invalidAST(node_info, "struct/union/enum definition without unique name".into()).toError()) + } + } + } -pub fn getUserState() -> Trav { - liftM(userState, get) -} + pub fn recordError(&mut self, err: E) { + self.state.rerrors.push(err.toError()); + } -pub fn modifyOptions(f: fn(TravOptions) -> TravOptions) -> Trav { - modify(|ts| ts { options: f((options(ts))) }) -} + pub fn handleTravError(&mut self, v: TravResult) -> TravResult> { + match v { + Ok(v) => Ok(Some(v)), + Err(e) => { + self.recordError(e); + Ok(None) + } + } + } -pub fn generateName() -> Trav { - __op_bind(get, |ts| { - /*do*/ - { - let [new_name, gen_q] = nameGenerator(ts); + pub fn warn(&mut self, err: E) { + self.recordError(err.changeErrorLevel(LevelWarn)) + } - put(ts { nameGenerator: gen_q }); - new_name - } - }) -} + pub fn withExtDeclHandler(&mut self, handler: Box>) { + // TODO: should this be scoped (take closure)? + self.doHandleExtDecl = handler; + } -pub fn mapMaybeM(m: Option, f: fn(a) -> m) -> m> { - maybe((None), (liftM(Some, f)), m) -} + pub fn modifyUserState(&mut self, mut f: F) + where F: FnMut(&mut S) + { + f(&mut self.state.userState) + } -pub fn maybeM(m: Option, f: fn(a) -> m<()>) -> m<()> { - maybe((()), f, m) -} + pub fn getUserState(&self) -> &S { + &self.state.userState + } -pub fn mapSndM(f: fn(b) -> m, (a, b): (a, b)) -> m<(a, c)> { - liftM((__op_tuple2(a)), (f(b))) -} + pub fn modifyOptions(&mut self, mut f: F) + where F: FnMut(&mut TravOptions) + { + f(&mut self.state.options) + } -pub fn concatMapM(f: fn(a) -> m>) -> m> { - liftM(concat, mapM(f)) + pub fn generateName(&mut self) -> Name { + self.state.nameGenerator.next().unwrap() + } } diff --git a/src/analysis/type_utils.rs b/src/analysis/type_utils.rs index 892bb39..0fb6f29 100644 --- a/src/analysis/type_utils.rs +++ b/src/analysis/type_utils.rs @@ -1,33 +1,24 @@ // Original file: "TypeUtils.hs" // File auto-generated using Corollary. -#[macro_use] -use corollary_support::*; - -// NOTE: These imports are advisory. You probably need to change them to support Rust. -// use Language::C::Analysis::SemRep; -// use Language::C::Data::Node; -// use CNode; -// use Language::C::Syntax::AST; -// use CExpression; -// use Language::C::Syntax::Constants; - +use data::node::CNode; +use syntax::ast::{CConstant, CExpression}; use analysis::sem_rep::*; pub fn integral(ty: IntType) -> Type { - DirectType((TyIntegral(ty)), noTypeQuals, noAttributes) + DirectType(TyIntegral(ty), noTypeQuals(), noAttributes()) } pub fn floating(ty: FloatType) -> Type { - DirectType((TyFloating(ty)), noTypeQuals, noAttributes) + DirectType(TyFloating(ty), noTypeQuals(), noAttributes()) } -pub fn simplePtr(t: Type) -> Type { - PtrType(t, noTypeQuals, vec![]) +pub fn simplePtr(ty: Type) -> Type { + PtrType(Box::new(ty), noTypeQuals(), noAttributes()) } -pub fn constPtr(t: Type) -> Type { - PtrType(t, (noTypeQuals { constant: true }), vec![]) +pub fn constPtr(ty: Type) -> Type { + PtrType(Box::new(ty), TypeQuals { constant: true, .. Default::default() }, noAttributes()) } pub fn uint16_tType() -> Type { @@ -55,207 +46,215 @@ pub fn boolType() -> Type { } pub fn voidType() -> Type { - DirectType(TyVoid, noTypeQuals, noAttributes) + DirectType(TyVoid, noTypeQuals(), noAttributes()) } pub fn voidPtr() -> Type { - simplePtr(voidType) + simplePtr(voidType()) } pub fn constVoidPtr() -> Type { - constPtr(voidType) + constPtr(voidType()) } pub fn charPtr() -> Type { - simplePtr((integral(TyChar))) + simplePtr(integral(TyChar)) } pub fn constCharPtr() -> Type { - constPtr((integral(TyChar))) + constPtr(integral(TyChar)) } pub fn stringType() -> Type { - ArrayType((DirectType((TyIntegral(TyChar)), - (noTypeQuals { constant: true }), - noAttributes)), - (UnknownArraySize(false)), - noTypeQuals, - vec![]) + ArrayType(Box::new(DirectType(TyIntegral(TyChar), + TypeQuals { constant: true, .. Default::default() }, + noAttributes())), + UnknownArraySize(false), + noTypeQuals(), + noAttributes()) } pub fn valistType() -> Type { - DirectType((TyBuiltin(TyVaList)), noTypeQuals, noAttributes) + DirectType(TyBuiltin(TyVaList), noTypeQuals(), noAttributes()) } -pub fn isIntegralType(_0: Type) -> bool { - match (_0) { - DirectType(TyIntegral(_), _, _) => true, - DirectType(TyEnum(_), _, _) => true, +pub fn isIntegralType(ty: &Type) -> bool { + match *ty { + DirectType(TyIntegral(_), ..) => true, + DirectType(TyEnum(_), ..) => true, _ => false, } } -pub fn isFloatingType(_0: Type) -> bool { - match (_0) { - DirectType(TyFloating(_), _, _) => true, +pub fn isFloatingType(ty: &Type) -> bool { + match *ty { + DirectType(TyFloating(_), ..) => true, _ => false, } } -pub fn isPointerType(_0: Type) -> bool { - match (_0) { - PtrType(_, _, _) => true, - ArrayType(_, _, _, _) => true, +pub fn isPointerType(ty: &Type) -> bool { + match *ty { + PtrType(..) => true, + ArrayType(..) => true, _ => false, } } -pub fn isScalarType(t: Type) -> bool { - (isIntegralType(t) || (isPointerType(t) || isFloatingType(t))) +pub fn isScalarType(ty: &Type) -> bool { + isIntegralType(ty) || isPointerType(ty) || isFloatingType(ty) } -pub fn isFunctionType(ty: Type) -> bool { - match ty { - TypeDefType(TypeDefRef(_, actual_ty, _), _, _) => isFunctionType(actual_ty), - FunctionType(_, _) => true, +pub fn isFunctionType(ty: &Type) -> bool { + match *ty { + TypeDefType(box TypeDefRef(_, ref actual_ty, _), ..) => isFunctionType(actual_ty), + FunctionType(..) => true, _ => false, } } -pub fn typeQuals(_0: Type) -> TypeQuals { - match (_0) { +pub fn typeQuals(ty: Type) -> TypeQuals { + match ty { DirectType(_, q, _) => q, PtrType(_, q, _) => q, ArrayType(_, _, q, _) => q, - FunctionType(_, _) => noTypeQuals, - TypeDefType(TypeDefRef(_, t, _), q, _) => mergeTypeQuals(q, (typeQuals(t))), + FunctionType(_, _) => noTypeQuals(), + TypeDefType(box TypeDefRef(_, t, _), q, _) => mergeTypeQuals(q, typeQuals(t)), } } -pub fn typeQualsUpd(f: fn(TypeQuals) -> TypeQuals, ty: Type) -> Type { +pub fn typeQualsUpd(f: F, ty: Type) -> Type + where F: FnOnce(TypeQuals) -> TypeQuals +{ match ty { - DirectType(ty_name, ty_quals, ty_attrs) => DirectType(ty_name, (f(ty_quals)), ty_attrs), - PtrType(ty_inner, ty_quals, ty_attrs) => PtrType(ty_inner, (f(ty_quals)), ty_attrs), + DirectType(ty_name, ty_quals, ty_attrs) => DirectType(ty_name, f(ty_quals), ty_attrs), + PtrType(ty_inner, ty_quals, ty_attrs) => PtrType(ty_inner, f(ty_quals), ty_attrs), ArrayType(ty_inner, sz, ty_quals, ty_attrs) => { - ArrayType(ty_inner, sz, (f(ty_quals)), ty_attrs) + ArrayType(ty_inner, sz, f(ty_quals), ty_attrs) } FunctionType(ty_inner, ty_attrs) => FunctionType(ty_inner, ty_attrs), - TypeDefType(ty_ref, ty_quals, ty_attrs) => TypeDefType(ty_ref, (f(ty_quals)), ty_attrs), + TypeDefType(ty_ref, ty_quals, ty_attrs) => TypeDefType(ty_ref, f(ty_quals), ty_attrs), } } -pub fn typeAttrs(_0: Type) -> Attributes { - match (_0) { +pub fn typeAttrs(ty: Type) -> Attributes { + match ty { DirectType(_, _, a) => a, PtrType(_, _, a) => a, ArrayType(_, _, _, a) => a, FunctionType(_, a) => a, - TypeDefType(TypeDefRef(_, t, _), _, a) => mergeAttributes(a, (typeAttrs(t))), + TypeDefType(box TypeDefRef(_, t, _), _, a) => mergeAttributes(a, typeAttrs(t)), } } -pub fn typeAttrsUpd(f: fn(Attributes) -> Attributes, ty: Type) -> Type { +pub fn typeAttrsUpd(f: F, ty: Type) -> Type + where F: FnOnce(Attributes) -> Attributes +{ match ty { - DirectType(ty_name, ty_quals, ty_attrs) => DirectType(ty_name, ty_quals, (f(ty_attrs))), - PtrType(ty_inner, ty_quals, ty_attrs) => PtrType(ty_inner, ty_quals, (f(ty_attrs))), + DirectType(ty_name, ty_quals, ty_attrs) => DirectType(ty_name, ty_quals, f(ty_attrs)), + PtrType(ty_inner, ty_quals, ty_attrs) => PtrType(ty_inner, ty_quals, f(ty_attrs)), ArrayType(ty_inner, sz, ty_quals, ty_attrs) => { - ArrayType(ty_inner, sz, ty_quals, (f(ty_attrs))) + ArrayType(ty_inner, sz, ty_quals, f(ty_attrs)) } - FunctionType(ty_inner, ty_attrs) => FunctionType(ty_inner, (f(ty_attrs))), - TypeDefType(ty_ref, ty_quals, ty_attrs) => TypeDefType(ty_ref, ty_quals, (f(ty_attrs))), + FunctionType(ty_inner, ty_attrs) => FunctionType(ty_inner, f(ty_attrs)), + TypeDefType(ty_ref, ty_quals, ty_attrs) => TypeDefType(ty_ref, ty_quals, f(ty_attrs)), } } -pub fn baseType(_0: Type) -> Type { - match (_0) { - PtrType(t, _, _) => t, - ArrayType(t, _, _, _) => t, +pub fn baseType(ty: Type) -> Type { + match ty { + PtrType(t, _, _) => *t, + ArrayType(t, _, _, _) => *t, _ => panic!("base of non-pointer type"), } } -pub fn derefTypeDef(_0: Type) -> Type { - match (_0) { - TypeDefType(TypeDefRef(_, t, _), q, a) => { - (typeAttrsUpd((mergeAttributes(a)), - typeQualsUpd((mergeTypeQuals(q)))))((derefTypeDef(t))) +pub fn derefTypeDef(ty: Type) -> Type { + match ty { + TypeDefType(box TypeDefRef(_, t, _), q, a) => { + typeAttrsUpd(|b| mergeAttributes(a, b), + typeQualsUpd(|b| mergeTypeQuals(q, b), derefTypeDef(t))) } ty => ty, } } -pub fn deepDerefTypeDef(_0: Type) -> Type { - match (_0) { - PtrType(t, quals, attrs) => PtrType((deepDerefTypeDef(t)), quals, attrs), - ArrayType(t, size, quals, attrs) => ArrayType((deepDerefTypeDef(t)), size, quals, attrs), - FunctionType(FunType(rt, params, varargs), attrs) => { - FunctionType((FunType((deepDerefTypeDef(rt)), params, varargs)), attrs) - } - FunctionType(FunTypeIncomplete(rt), attrs) => { - FunctionType((FunTypeIncomplete((deepDerefTypeDef(rt)))), attrs) +pub fn deepDerefTypeDef(ty: Type) -> Type { + match ty { + PtrType(t, quals, attrs) => PtrType(box deepDerefTypeDef(*t), quals, attrs), + ArrayType(t, size, quals, attrs) => ArrayType(box deepDerefTypeDef(*t), size, quals, attrs), + FunctionType(funtype, attrs) => { + // XXX I can't match on *funtype directly for some reason? + let unboxed = *funtype; + match unboxed { + FunType(rt, params, varargs) => + FunctionType(box FunType(deepDerefTypeDef(rt), params, varargs), attrs), + FunTypeIncomplete(rt) => + FunctionType(box FunTypeIncomplete(deepDerefTypeDef(rt)), attrs) + } } - TypeDefType(TypeDefRef(_, t, _), q, a) => { - (typeAttrsUpd((mergeAttributes(a)), - typeQualsUpd((mergeTypeQuals(q)))))((deepDerefTypeDef(t))) + TypeDefType(box TypeDefRef(_, t, _), q, a) => { + typeAttrsUpd(|b| mergeAttributes(a, b), + typeQualsUpd(|b| mergeTypeQuals(q, b), deepDerefTypeDef(t))) } t => t, } } -pub fn isVariablyModifiedType(t: Type) -> bool { +pub fn isVariablyModifiedType(ty: Type) -> bool { - pub fn isVariableArraySize(_0: ArraySize) -> bool { - match (_0) { + pub fn isVariableArraySize(sz: &ArraySize) -> bool { + match *sz { UnknownArraySize(isStarred) => isStarred, - ArraySize(isStatic, e) => (isStatic || isConstantSize(e)), + ArraySize(isStatic, ref e) => isStatic || isConstantSize(e), } } - pub fn isConstantSize(_0: Expr) -> bool { - match (_0) { - CConst(CIntConst {}) => true, + pub fn isConstantSize(expr: &Expr) -> bool { + match *expr { + CExpression::CConst(CConstant::CIntConst { .. }) => true, _ => false, } } - match derefTypeDef(t) { - TypeDefType {} => panic!("impossible: derefTypeDef t returned a TypeDefType"), - DirectType {} => false, - PtrType(ptr_ty, _, _) => isVariablyModifiedType(ptr_ty), - ArrayType(_, sz, _, _) => isVariableArraySize(sz), - FunctionType {} => false, + match derefTypeDef(ty) { + TypeDefType { .. } => panic!("impossible: derefTypeDef returned a TypeDefType"), + DirectType { .. } => false, + PtrType(ptr_ty, _, _) => isVariablyModifiedType(*ptr_ty), + ArrayType(_, sz, _, _) => isVariableArraySize(&sz), + FunctionType { .. } => false, } } pub fn sameType(t1: Type, t2: Type) -> bool { - let sameType_q = match (derefTypeDef(t1), derefTypeDef(t2)) { - (TypeDefType {}, _) => { + let sameType_q = match (derefTypeDef(t1.clone()), derefTypeDef(t2.clone())) { + (TypeDefType { .. }, _) => { panic!("impossible: derefTypeDef t1 returned a TypeDefType") } - (_, TypeDefType {}) => { + (_, TypeDefType { .. }) => { panic!("impossible: derefTypeDef t2 returned a TypeDefType") } (DirectType(tn1, q1, _a1), DirectType(tn2, q2, _a2)) => { - (sameTypeName(tn1, tn2) && sameQuals(q1, q2)) + sameTypeName(tn1, tn2) && sameQuals(q1, q2) } - (PtrType(pt1, q1, _a1), PtrType(pt2, q2, _a2)) => (sameType(pt1, pt2) && sameQuals(q1, q2)), + (PtrType(pt1, q1, _a1), PtrType(pt2, q2, _a2)) => sameType(*pt1, *pt2) && sameQuals(q1, q2), (ArrayType(at1, sz1, q1, _a1), ArrayType(at2, sz2, q2, _a2)) => { - (sameType(at1, at2) && (sameArraySize(sz1, sz2) && sameQuals(q1, q2))) + sameType(*at1, *at2) && sameArraySize(sz1, sz2) && sameQuals(q1, q2) } - (FunctionType(ft1, _a1), FunctionType(ft2, _a2)) => sameFunType(ft1, ft2), + (FunctionType(ft1, _a1), FunctionType(ft2, _a2)) => sameFunType(*ft1, *ft2), _ => false, }; - (not(((isVariablyModifiedType(t1) || isVariablyModifiedType(t2)))) && sameType_q) + !(isVariablyModifiedType(t1) || isVariablyModifiedType(t2)) && sameType_q } pub fn sameTypeName(t1: TypeName, t2: TypeName) -> bool { match (t1, t2) { (TyVoid, TyVoid) => true, - (TyIntegral(i1), TyIntegral(i2)) => (i1 == i2), - (TyFloating(f1), TyFloating(f2)) => (f1 == f2), - (TyComplex(f1), TyComplex(f2)) => (f1 == f2), + (TyIntegral(i1), TyIntegral(i2)) => i1 == i2, + (TyFloating(f1), TyFloating(f2)) => f1 == f2, + (TyComplex(f1), TyComplex(f2)) => f1 == f2, (TyComp(ctr1), TyComp(ctr2)) => sameCompTypeRef(ctr1, ctr2), (TyEnum(etr1), TyEnum(etr2)) => sameEnumTypeRef(etr1, etr2), (TyBuiltin(b1), TyBuiltin(b2)) => sameBuiltinType(b1, b2), @@ -274,19 +273,24 @@ pub fn sameBuiltinType(_0: BuiltinType, _1: BuiltinType) -> bool { pub fn sameCompTypeRef(CompTypeRef(sue1, kind1, _): CompTypeRef, CompTypeRef(sue2, kind2, _): CompTypeRef) -> bool { - (sue1 == (sue2 && (kind1 == kind2))) + sue1 == sue2 && kind1 == kind2 } pub fn sameEnumTypeRef(EnumTypeRef(sue1, _): EnumTypeRef, EnumTypeRef(sue2, _): EnumTypeRef) -> bool { - (sue1 == sue2) + sue1 == sue2 } pub fn sameFunType(_0: FunType, _1: FunType) -> bool { + fn sameParamDecls(pl1: &[ParamDecl], pl2: &[ParamDecl]) -> bool { + pl1.len() == pl2.len() && + pl1.iter().zip(pl2).all(|(x, y)| sameType(declType(x), declType(y))) + } + match (_0, _1) { (FunType(rt1, params1, isVar1), FunType(rt2, params2, isVar2)) => { - (sameType(rt1, rt2) && (sameParamDecls(params1, params2) && (isVar1 == isVar2))) + sameType(rt1, rt2) && sameParamDecls(¶ms1, ¶ms2) && isVar1 == isVar2 } (FunTypeIncomplete(rt1), FunTypeIncomplete(rt2)) => sameType(rt1, rt2), (_, _) => false, @@ -294,24 +298,29 @@ pub fn sameFunType(_0: FunType, _1: FunType) -> bool { } pub fn sameArraySize(_0: ArraySize, _1: ArraySize) -> bool { + fn sizeEqual(a: Expr, b: Expr) -> bool { + match (a, b) { + (CExpression::CConst(CConstant::CIntConst(i1, _)), + CExpression::CConst(CConstant::CIntConst(i2, _))) => i1 == i2, + (oe1, oe2) => oe1.node_info() == oe2.node_info() + } + } + match (_0, _1) { - (UnknownArraySize(isStar1), UnknownArraySize(isStar2)) => (isStar1 == isStar2), - (ArraySize(s1, e1), ArraySize(s2, e2)) => (s1 == (s2 && sizeEqual(e1, e2))), + (UnknownArraySize(isStar1), UnknownArraySize(isStar2)) => isStar1 == isStar2, + (ArraySize(s1, e1), ArraySize(s2, e2)) => s1 == s2 && sizeEqual(e1, e2), (_, _) => false, } } -pub fn sameQuals(TypeQuals {}: TypeQuals, TypeQuals {}: TypeQuals) -> bool { - (c1 == (c2 && (v1 == (v2 && (r1 == r2))))) +pub fn sameQuals(TypeQuals { constant: c1, volatile: v1, restrict: r1, .. }: TypeQuals, + TypeQuals { constant: c2, volatile: v2, restrict: r2, .. }: TypeQuals) -> bool { + c1 == c2 && v1 == v2 && r1 == r2 } -pub fn canonicalType(t: Type) -> Type { - match deepDerefTypeDef(t) { - FunctionType(ft, attrs) => simplePtr((FunctionType(ft, attrs))), - t_q => t_q, +pub fn canonicalType(ty: Type) -> Type { + match deepDerefTypeDef(ty) { + FunctionType(ft, attrs) => simplePtr(FunctionType(ft, attrs)), + ty => ty, } } - -pub fn testFlags(flags: Vec, fi: Flags) -> bool { - all((testFlag(fi)), flags) -} diff --git a/src/data/error.rs b/src/data/error.rs index 1806730..e86fde2 100644 --- a/src/data/error.rs +++ b/src/data/error.rs @@ -6,7 +6,7 @@ use std::fmt::Write; use data::node::NodeInfo; use data::position::{Position, Pos}; -#[derive(Eq, Ord, PartialEq, PartialOrd, Debug)] +#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Debug)] pub enum ErrorLevel { LevelWarn, LevelError, @@ -20,11 +20,11 @@ impl ::std::fmt::Display for ErrorLevel { } } -pub fn isHardError(e: E) -> bool { +pub fn isHardError(e: &E) -> bool { errorLevel(e) > LevelWarn } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct ErrorInfo(pub ErrorLevel, pub Position, pub Vec); @@ -42,16 +42,20 @@ pub trait Error where Self: Debug { // obtain source location etc. of an error - fn errorInfo(self) -> ErrorInfo; + fn errorInfo(&self) -> ErrorInfo; // wrap error in 'CError' - fn toError(self) -> CError; + fn toError(self) -> CError where Self: Sized + 'static { + CError(Box::new(self)) + } // try to cast a generic 'CError' to the specific error type - fn fromError(c: CError) -> Option> where Self: Sized; + fn fromError(_c: CError) -> Option> where Self: Sized { + unimplemented!("unused in source anyway") + } // modify the error level fn changeErrorLevel(self, lvl: ErrorLevel) -> Self where Self: Sized + Clone { - if errorLevel(self.clone()) == lvl { + if errorLevel(&self.clone()) == lvl { // TODO self } else { panic!("changeErrorLevel: not possible for {:?}", self); @@ -63,10 +67,8 @@ pub trait Error // instance Show CError where // show (CError e) = show e impl Error for CError { - fn errorInfo(self) -> ErrorInfo { - // TODO - unreachable!() - // self.0.errorInfo() + fn errorInfo(&self) -> ErrorInfo { + self.0.errorInfo() } fn toError(self) -> CError { @@ -84,19 +86,16 @@ impl Error for CError { } } -pub fn errorPos(e: E) -> Position { - let ErrorInfo(_, pos, _) = e.errorInfo(); - pos +pub fn errorLevel(e: &E) -> ErrorLevel { + e.errorInfo().0 } -pub fn errorLevel(e: E) -> ErrorLevel { - let ErrorInfo(lvl, _, _) = e.errorInfo(); - lvl +pub fn errorPos(e: &E) -> Position { + e.errorInfo().1 } -pub fn errorMsg(e: E) -> Vec { - let ErrorInfo(_, _, msgs) = e.errorInfo(); - msgs +pub fn errorMsg(e: &E) -> Vec { + e.errorInfo().2 } #[derive(Debug)] diff --git a/src/data/ident.rs b/src/data/ident.rs index c39b94c..017fc70 100644 --- a/src/data/ident.rs +++ b/src/data/ident.rs @@ -7,7 +7,7 @@ use data::position::{Position, Pos}; use data::node::{NodeInfo, CNode}; use data::name::Name; -#[derive(Clone, Debug, PartialEq, PartialOrd, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum SUERef { AnonymousRef(Name), NamedRef(Ident), @@ -30,7 +30,8 @@ impl SUERef { } } -#[derive(Clone, Debug, PartialOrd, Eq)] +// TODO: use NodeInfo for Ord or not? +#[derive(Clone, Debug, PartialOrd, Ord, Eq)] pub struct Ident(pub String, pub NodeInfo); // required because we keep Idents in a HashSet and don't want the set to diff --git a/src/data/node.rs b/src/data/node.rs index 12aed30..3ef3e80 100644 --- a/src/data/node.rs +++ b/src/data/node.rs @@ -3,6 +3,7 @@ use std::fmt; use std::rc::Rc; +use either::Either; use data::name::Name; use data::position::{Pos, Position, PosLength}; @@ -22,6 +23,21 @@ impl CNode for NodeInfo { } } +impl CNode for Either { + fn node_info(&self) -> &NodeInfo { + match *self { + Either::Left(ref x) => x.node_info(), + Either::Right(ref x) => x.node_info() + } + } + fn into_node_info(self) -> NodeInfo { + match self { + Either::Left(x) => x.into_node_info(), + Either::Right(x) => x.into_node_info() + } + } +} + impl Pos for T { fn pos(&self) -> &Position { NodeInfo::pos(self.node_info()) diff --git a/src/lib.rs b/src/lib.rs index 6f26672..4d77455 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,12 +36,12 @@ extern crate tempdir; #[macro_use] extern crate bitflags; #[macro_use] extern crate parser_c_macro; -// pub mod analysis; pub mod data; pub mod parser; pub mod system; pub mod syntax; pub mod pretty; +pub mod analysis; use std::path::{Path, PathBuf};