MODULE M3CDuplicate; (***************************************************************************) (* Copyright (C) Olivetti 1989 *) (* All Rights reserved *) (* *) (* Use and copy of this software and preparation of derivative works based *) (* upon this software are permitted to any person, provided this same *) (* copyright notice and the following Olivetti warranty disclaimer are *) (* included in any copy of the software or any modification thereof or *) (* derivative work therefrom made by any person. *) (* *) (* This software is made available AS IS and Olivetti disclaims all *) (* warranties with respect to this software, whether expressed or implied *) (* under any law, including all implied warranties of merchantibility and *) (* fitness for any purpose. In no event shall Olivetti be liable for any *) (* damages whatsoever resulting from loss of use, data or profits or *) (* otherwise arising out of or in connection with the use or performance *) (* of this software. *) (***************************************************************************) IMPORT M3AST_AS, M3AST_SM; IMPORT M3AST_AS_F, M3AST_SM_F; IMPORT M3Error, M3ASTNext, M3CBackEnd, M3COrdinal; TYPE Tree = OBJECT left, right: Tree := NIL; count: INTEGER; low, high: M3AST_SM.Exp_value; END; PROCEDURE NewLeaf( count: INTEGER; low, high: M3AST_SM.Exp_value) : Tree RAISES {}= BEGIN RETURN NEW(Tree, count := count, low := low, high := high); END NewLeaf; PROCEDURE AddRange( low, high: M3AST_SM.Exp_value; count: INTEGER; VAR tree: Tree) : BOOLEAN RAISES {}= BEGIN IF tree = NIL THEN tree := NewLeaf(count, low, high); RETURN TRUE; ELSIF M3CBackEnd.Compare(low, tree.high) > 0 THEN RETURN AddRange(low, high, count, tree.right); ELSIF M3CBackEnd.Compare(high, tree.low) < 0 THEN RETURN AddRange(low, high, count, tree.left); ELSE IF M3CBackEnd.Compare(low, tree.low) < 0 THEN tree.low := low END; IF M3CBackEnd.Compare(high, tree.high) > 0 THEN tree.high := high END; WITH result = count = tree.count DO tree.count := count; RETURN result; END; END; (* if *) END AddRange; PROCEDURE CheckExp( exp: M3AST_AS.EXP; VAR val: M3AST_SM.Exp_value) : BOOLEAN RAISES {}= VAR type := exp.sm_exp_type_spec; baseType: M3AST_SM.TYPE_SPEC_UNSET; BEGIN IF M3COrdinal.Is(type, baseType) AND (type # NIL) AND (exp.sm_exp_value # NIL) THEN val := exp.sm_exp_value; RETURN TRUE; ELSE RETURN FALSE; END; (* if *) END CheckExp; PROCEDURE CaseLabels(caseSt: M3AST_AS.Case_st) RAISES {}= VAR tree: Tree := NIL; iter := M3ASTNext.NewIterCaseLabel(caseSt.as_case_s); count := 0; oldCase, case: M3AST_AS.Case := NIL; label: M3AST_AS.RANGE_EXP; val1, val2: M3AST_SM.Exp_value; BEGIN WHILE M3ASTNext.CaseLabel(iter, case, label) DO IF case # oldCase THEN INC(count); oldCase := case END; TYPECASE label OF | M3AST_AS.Range(range) => IF CheckExp(range.as_exp1, val1) AND CheckExp(range.as_exp2, val2) THEN IF M3CBackEnd.Compare(val1, val2) <= 0 THEN IF NOT AddRange(val1, val2, count, tree) THEN M3Error.Report(range.as_exp1, "duplicated case label"); END; (* if *) END; (* if *) END; (* if *) | M3AST_AS.Range_EXP(rangeExp) => IF CheckExp(rangeExp.as_exp, val1) AND (NOT AddRange(val1, val1, count, tree)) THEN M3Error.Report(label, "duplicated case label"); END; (* if *) END; (* if *) END; (* while *) END CaseLabels; TYPE List = RECORD number: INTEGER; ids: ARRAY [0..31] OF RECORD id: M3AST_AS.DEF_ID; count: INTEGER END; next: REF List; END; PROCEDURE AddId( id: M3AST_AS.DEF_ID; count: INTEGER; VAR list: List) : BOOLEAN RAISES {}= BEGIN FOR i := 0 TO list.number - 1 DO WITH compare = list.ids[i] DO IF id = compare.id THEN IF compare.count = count THEN RETURN TRUE; ELSE compare.count := count; RETURN FALSE; END; END; END; END; IF list.number = NUMBER(list.ids) AND list.next = NIL THEN list.next := NEW(REF List, number := 0, next := NIL); END; IF list.next # NIL THEN RETURN AddId(id, count, list.next^); ELSE WITH add = list.ids[list.number] DO add.id := id; add.count := count; END; INC(list.number); RETURN TRUE END; END AddId; PROCEDURE HandlerExceptions(except: M3AST_AS.Try_except) RAISES {}= VAR list: List; iter := M3ASTNext.NewIterHandlerLabel(except.as_handler_s); count := 0; oldHandler, handler: M3AST_AS.Handler; qId: M3AST_AS.Qual_used_id; defId: M3AST_AS.DEF_ID; BEGIN list.number := 0; list.next := NIL; oldHandler := NIL; WHILE M3ASTNext.HandlerLabel(iter, handler, qId) DO IF handler # oldHandler THEN INC(count); oldHandler := handler END; defId := qId.as_id.sm_def; IF defId # NIL AND NOT AddId(defId, count, list) THEN M3Error.ReportWithId(qId, "duplicate exception handler label \'%s\'", defId.lx_symrep); END; (* if *) END; (* while *) END HandlerExceptions; BEGIN END M3CDuplicate.