MODULE************************************************************************* 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. *************************************************************************; M3LDepends
IMPORT M3AST_AS; IMPORT M3AST_AS_F, M3AST_SM_F, M3AST_PL_F; IMPORT SeqM3AST_AS_Used_interface_id; IMPORT SeqM3AST_AS_Module, SeqM3AST_AS_Module_id; IMPORT M3CUnit; IMPORT M3Context;Debug IMPORT M3CId, Wr, Stdio, Fmt; Debug
CONST (* states of computation *) Needed = 0; InProgress = 1; Done = 2; NoGenerics = M3CUnit.TypeSet{M3CUnit.Type.Interface, M3CUnit.Type.Interface_gen_ins, M3CUnit.Type.Module, M3CUnit.Type.Module_gen_ins}; TYPE ContextClosure = M3Context.Closure OBJECT dependsClosure: Closure; END; REVEAL Closure = Closure_public BRANDED OBJECT END;PUBLIC
PROCEDURESet (c: M3Context.T; cl: Closure) RAISES {}= <*FATAL ANY*> BEGIN Clear(c); M3Context.ApplyToSet(c, NEW(M3Context.Closure, callback := SetExportedBy), NoGenerics); M3Context.ApplyToSet(c, NEW(ContextClosure, dependsClosure := cl, callback := SetSimpleDependsOn), NoGenerics); M3Context.ApplyToSet(c, NEW(ContextClosure, dependsClosure := cl, callback := CloseDependsOn), NoGenerics);
Debug M3Context.Apply(c, NEW(M3Context.Closure, callback := Debug)); Debug
END Set;PUBLIC
PROCEDUREDebug PROCEDURE Debug( cl: M3Context.Closure; ut: M3CUnit.Type; name: TEXT; cu: M3AST_AS.Compilation_Unit) RAISES {}= VAR iter: SeqM3AST_AS_Module.Iter; m, tm: M3AST_AS.Module; BEGIN cu := M3CUnit.ToGenIns(cu, ut); TYPECASE cu.as_root OFClear (c: M3Context.T) RAISES {}= <*FATAL ANY*> BEGIN M3Context.ApplyToSet(c, NEW(M3Context.Closure, callback := ClearUnit), NoGenerics); END Clear; PROCEDUREClearUnit ( <*UNUSED*> cl: M3Context.Closure; ut: M3CUnit.Type; <*UNUSED*> name: TEXT; cu: M3AST_AS.Compilation_Unit) RAISES {}= BEGIN cu := M3CUnit.ToGenIns(cu, ut); TYPECASE cu.as_root OF <*NOWARN*> | M3AST_AS.Module(m) => m.pl_tmp_dep_status := Needed; m.pl_dependson_s := NIL; | M3AST_AS.Interface(i) => VAR id: M3AST_AS.Interface_id := i.as_id; BEGIN id.pl_isexportedby_s := SeqM3AST_AS_Module_id.Null; END; END; (* if *) END ClearUnit;
M3AST_AS.Module(m) =>Put(
\nDependsOn list for %s\n -
, m, NIL);
iter := SeqM3AST_AS_Module.NewIter(m.pl_dependson_s);
WHILE SeqM3AST_AS_Module.Next(iter, tm) DO
Put(%s
, tm, NIL);
END;
ELSE
END;
END Debug;
Debug
PRIVATE
PROCEDUREPRIVATESetExportedBy ( <*UNUSED*> cl: M3Context.Closure; ut: M3CUnit.Type; <*UNUSED*> name: TEXT; cu: M3AST_AS.Compilation_Unit) RAISES {}= VAR iter: SeqM3AST_AS_Used_interface_id.Iter; used_intf_id: M3AST_AS.Used_interface_id; BEGIN cu := M3CUnit.ToGenIns(cu, ut); TYPECASE cu.as_root OF | M3AST_AS.Module(m) => m.pl_tmp_dep_status := Needed; (* add myself to exportedby list of all interfaces *) iter := SeqM3AST_AS_Used_interface_id.NewIter(m.sm_export_s); WHILE SeqM3AST_AS_Used_interface_id.Next(iter, used_intf_id) DO (* be graceful about unresolved names *) IF used_intf_id.sm_def # NIL THEN SeqM3AST_AS_Module_id.AddFront( NARROW(used_intf_id.sm_def, M3AST_AS.Interface_id).pl_isexportedby_s, m.as_id); END; (* if *) END; (* while *) ELSE END; (* typecase *) END SetExportedBy;
PROCEDUREPRIVATESetSimpleDependsOn ( cl: ContextClosure; ut: M3CUnit.Type; <*UNUSED*> name: TEXT; cu: M3AST_AS.Compilation_Unit) RAISES {}= VAR i: M3AST_AS.Interface; iter: SeqM3AST_AS_Used_interface_id.Iter; used_intf_id: M3AST_AS.Used_interface_id; BEGIN cu := M3CUnit.ToGenIns(cu, ut); TYPECASE cu.as_root OF | M3AST_AS.Module(m) => iter := SeqM3AST_AS_Used_interface_id.NewIter(m.sm_import_s); WHILE SeqM3AST_AS_Used_interface_id.Next(iter, used_intf_id) DO i := InterfaceFromUsedId(used_intf_id); IF (i # NIL) AND cl.dependsClosure.callback(m, i) THEN (* finally! *) AddExporters(m, i); END; (* if *) END; (* while *) ELSE END; END SetSimpleDependsOn;
PROCEDUREPRIVATECloseDependsOn ( cl: ContextClosure; ut: M3CUnit.Type; <*UNUSED*> name: TEXT; cu: M3AST_AS.Compilation_Unit) RAISES {}= BEGIN cu := M3CUnit.ToGenIns(cu, ut); TYPECASE cu.as_root OF | M3AST_AS.Module => DoCloseDependsOn(cu.as_root, cl); ELSE END; END CloseDependsOn;
PROCEDUREPRIVATEDoCloseDependsOn (m: M3AST_AS.Module; cl: ContextClosure) RAISES {}= VAR iter, iter2: SeqM3AST_AS_Module.Iter; tm, ttm: M3AST_AS.Module; depends, ndepends: SeqM3AST_AS_Module.T; secondary := FALSE; BEGIN (*Debug Put("DoCloseDependsOn m= %s - ", m); Debug*) IF m.pl_tmp_dep_status = Done THEN (*Debug Put("Done\n"); Debug*) RETURN ELSIF m.pl_tmp_dep_status = InProgress THEN (*Debug Put("InProgress\n"); Cycle(m); Debug*) RETURN ELSE (*Debug Put("Starting\n"); Debug*) m.pl_tmp_dep_status := InProgress; depends := m.pl_dependson_s; REPEAT ndepends := NIL; iter := SeqM3AST_AS_Module.NewIter(depends); WHILE SeqM3AST_AS_Module.Next(iter, tm) DO IF tm.pl_tmp_dep_status = Needed THEN DoCloseDependsOn(tm, cl); END; iter2 := SeqM3AST_AS_Module.NewIter(tm.pl_dependson_s); WHILE SeqM3AST_AS_Module.Next(iter2, ttm) DO IF AddModule(m, ttm) THEN IF secondary THEN Trap() END; SeqM3AST_AS_Module.AddFront(ndepends, ttm); END; END; END; (* while *) depends := ndepends; secondary := TRUE; UNTIL SeqM3AST_AS_Module.Empty(depends); m.pl_tmp_dep_status := Done; (*Debug Put("DoCloseDependsOn m= %s - ", m); Put("Finished (%s)\n", m); Debug*) END; END DoCloseDependsOn;
PROCEDUREPRIVATETrap ()= BEGIN END Trap;
PROCEDUREPRIVATEInterfaceFromUsedId (used_intf_id: M3AST_AS.Used_interface_id ): M3AST_AS.Interface RAISES {}= BEGIN (* be graceful about unresolved names *) IF used_intf_id.sm_def = NIL THEN RETURN NIL ELSE RETURN NARROW(used_intf_id.sm_def, M3AST_AS.Interface_id).sm_spec; END; END InterfaceFromUsedId;
PROCEDUREPRIVATEAddModule (m, dm: M3AST_AS.Module): BOOLEAN RAISES {}= VAR xm: M3AST_AS.Module; iter: SeqM3AST_AS_Module.Iter; BEGIN (* No dependency on self *) IF m = dm THEN RETURN FALSE ELSE (* Have we already seen this *) iter := SeqM3AST_AS_Module.NewIter(m.pl_dependson_s); WHILE SeqM3AST_AS_Module.Next(iter, xm) DO IF xm = dm THEN RETURN FALSE END; END; (* while *) (*Debug Put("Adding %s to dependson list of %s\n", dm, m); Debug*) SeqM3AST_AS_Module.AddFront(m.pl_dependson_s, dm); RETURN TRUE; END; END AddModule;
PROCEDUREDebug PROCEDURE Put(t: TEXT; u1, u2: M3AST_AS.UNIT := NIL) RAISES {}= VAR t1, t2: TEXT := NIL; BEGIN IF u1 # NIL THEN t1 := M3CId.ToText(u1.as_id.lx_symrep); END; IF u2 # NIL THEN t2 := M3CId.ToText(u2.as_id.lx_symrep) END; Wr.PutText(Stdio.stdout, Fmt.F(t, t1, t2)); END Put; DebugAddExporters ( m: M3AST_AS.Module; i: M3AST_AS.Interface) RAISES {}= VAR iter := SeqM3AST_AS_Module_id.NewIter( NARROW(i.as_id, M3AST_AS.Interface_id).pl_isexportedby_s); mod_id: M3AST_AS.Module_id; BEGIN (* Add all the exporters of 'i' to the depends-on list of 'm' *) (*Debug Put("AddExporters of %s to %s\n", i, m); Debug*) WHILE SeqM3AST_AS_Module_id.Next(iter, mod_id) DO EVAL AddModule(m, mod_id.sm_spec); END; (* while *) END AddExporters;
PUBLIC
PROCEDUREPRIVATEDefault (): Closure RAISES {}= BEGIN RETURN NEW(Closure, callback := DefaultUses); END Default;
PROCEDURE**************************************************** (*PRIVATEDefaultUses ( <*UNUSED*> cl: Closure_public; <*UNUSED*> m: M3AST_AS.Module; <*UNUSED*> i: M3AST_AS.Interface): BOOLEAN RAISES {}= BEGIN (* 'm' depends on 'i' if 'i' is on the sm_import_s list of 'm'. *) RETURN TRUE; END DefaultUses;
PROCEDURE Cycle(<*UNUSED*> m: M3AST_AS.Module) RAISES {}= BEGIN END Cycle; ***************************************************) BEGIN END M3LDepends.