Skip to content

Commit

Permalink
Re-add check for duplicate names in enumeration
Browse files Browse the repository at this point in the history
git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@23265 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
sjoelund committed Nov 7, 2014
1 parent 522c324 commit 4e9730e
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 2 deletions.
10 changes: 8 additions & 2 deletions Compiler/FrontEnd/Inst.mo
Expand Up @@ -1101,6 +1101,9 @@ algorithm
(c as SCode.CLASS(name = n,restriction = SCode.R_ENUMERATION(),classDef =
SCode.PARTS(elementLst = els),info = info)),_,inst_dims,impl,callscope,graph,_,_)
equation
names = SCode.componentNames(c);
Types.checkEnumDuplicateLiterals(names, info);

tys = instBasicTypeAttributes(cache, env, mods,
DAE.T_ENUMERATION_DEFAULT, getEnumAttributeType, pre);
/* uncomment this and see how checkAllModelsRecursive(Modelica.Electrical.Digital) looks like
Expand All @@ -1122,8 +1125,7 @@ algorithm

(cache,fq_class) = makeFullyQualified(cache,env_2, Absyn.IDENT(n));
eqConstraint = InstUtil.equalityConstraint(env_2, els, info);
_ = DAEUtil.addComponentType(dae1, fq_class);
names = SCode.componentNames(c);
// DAEUtil.addComponentType(dae1, fq_class);
ty2 = DAE.T_ENUMERATION(NONE(), fq_class, names, tys1, tys, DAE.emptyTypeSource);
bc = arrayBasictypeBaseclass(inst_dims, ty2);
bc = if Util.isSome(bc) then bc else SOME(ty2);
Expand All @@ -1141,6 +1143,10 @@ algorithm
equation
ErrorExt.setCheckpoint("instClassParts");
false = InstUtil.isBuiltInClass(n) "If failed above, no need to try again";
_ = match r
case SCode.R_ENUMERATION() then fail();
else ();
end match;
// fprint(Flags.INSTTR, "ICLASS [");
// _ = if_(impl, "impl] ", "expl] ");
// fprint(Flags.INSTTR, implstr);
Expand Down
1 change: 1 addition & 0 deletions Compiler/FrontEnd/Lookup.mo
Expand Up @@ -216,6 +216,7 @@ algorithm
ConnectionGraph.EMPTY, Connect.emptySet, NONE());
// build names
(_,names) = SCode.getClassComponents(c);
Types.checkEnumDuplicateLiterals(names, c.info);
// generate the enumeration type
path = FGraph.getGraphName(env_3);
ts = Types.mkTypeSource(SOME(path));
Expand Down
14 changes: 14 additions & 0 deletions Compiler/FrontEnd/Types.mo
Expand Up @@ -8374,5 +8374,19 @@ algorithm
index := List.positionOnTrue(name, vars, DAEUtil.typeVarIdentEqual);
end lookupIndexInMetaRecord;

function checkEnumDuplicateLiterals
input list<String> names;
input Absyn.Info info;
protected
list<String> sortedNames;
algorithm
// Sort+uniq = O(n*log(n)); naive way to check duplicates is O(n*n) but might be faster...
sortedNames := List.sort(names,Util.strcmpBool);
if not List.sortedListAllUnique(sortedNames, stringEq) then
Error.addSourceMessage(Error.ENUM_DUPLICATES, {stringDelimitList(List.sortedUniqueOnlyDuplicates(sortedNames, stringEq), ","), stringDelimitList(names, ",")}, info);
fail();
end if;
end checkEnumDuplicateLiterals;

annotation(__OpenModelica_Interface="frontend");
end Types;
2 changes: 2 additions & 0 deletions Compiler/Util/Error.mo
Expand Up @@ -669,6 +669,8 @@ public constant Message TCOMPLEX_MULTIPLE_NAMES = MESSAGE(251, TRANSLATION(), NO
Util.gettext("Non-tuple complex type specifiers need to have exactly one type name: %s."));
public constant Message TCOMPLEX_TUPLE_ONE_NAME = MESSAGE(252, TRANSLATION(), NOTIFICATION(),
Util.gettext("Tuple complex type specifiers need to have more than one type name: %s."));
public constant Message ENUM_DUPLICATES = MESSAGE(253, TRANSLATION(), ERROR(),
Util.gettext("Enumeration has duplicate names: %s in list of names %s."));

public constant Message UNBOUND_PARAMETER_WITH_START_VALUE_WARNING = MESSAGE(499, TRANSLATION(), WARNING(),
Util.gettext("Parameter %s has no value, and is fixed during initialization (fixed=true), using available start value (start=%s) as default value."));
Expand Down
59 changes: 59 additions & 0 deletions Compiler/Util/List.mo
Expand Up @@ -704,6 +704,38 @@ algorithm
outDuplicates := listReverseInPlace(outDuplicates);
end sortedDuplicates;

public function sortedListAllUnique<T>
"The input is a sorted list. The functions checks if all elements are unique."
input list<T> lst;
input CompareFunc compare;
output Boolean allUnique := false;

partial function CompareFunc
input T inElement1;
input T inElement2;
output Boolean outEqual;
end CompareFunc;
protected
T e;
list<T> rest := lst;
algorithm
while not listEmpty(rest) loop
rest := match rest
local
T e1,e2;
case {} then {};
case {_} then {};
case e1::(rest as e2::_)
algorithm
if compare(e1,e2) then
return;
end if;
then rest;
end match;
end while;
allUnique := true;
end sortedListAllUnique;

public function sortedUnique<T>
"Returns a list of unique elements in a sorted list, using the given
comparison function to check for equality."
Expand Down Expand Up @@ -762,6 +794,33 @@ algorithm
outDuplicateElements := listReverseInPlace(outDuplicateElements);
end sortedUniqueAndDuplicates;

public function sortedUniqueOnlyDuplicates<T>
"Returns a list with all duplicate elements removed, as well as a list of the
removed elements, using the given comparison function to check for equality."
input list<T> inList;
input CompareFunc inCompFunc;
output list<T> outDuplicateElements := {};

partial function CompareFunc
input T inElement1;
input T inElement2;
output Boolean outEqual;
end CompareFunc;
protected
T e;
list<T> rest := inList;
algorithm
while not listEmpty(rest) loop
e :: rest := rest;

if not listEmpty(rest) and inCompFunc(e, listHead(rest)) then
outDuplicateElements := e :: outDuplicateElements;
end if;
end while;

outDuplicateElements := listReverseInPlace(outDuplicateElements);
end sortedUniqueOnlyDuplicates;

protected function merge<T>
"Helper function to sort, merges two sorted lists."
input list<T> inLeft;
Expand Down

0 comments on commit 4e9730e

Please sign in to comment.