-- MobConnectionMXCode.mesa
DIRECTORY Atom, MobConnection, Rope, Scheme;
MobConnectionMXCode: CEDAR PROGRAM
IMPORTS Atom, MobConnection, Scheme
= BEGIN OPEN Scheme;
SymbolFromRope: PROC [rope: Rope.ROPE] RETURNS [Symbol] ~ {RETURN[Atom.MakeAtom[rope]]};
RopeFromSymbol: PROC [Symbol] RETURNS [Rope.ROPE] ~ Atom.GetPName;
TheSymbol: PROC [a: Any] RETURNS [Scheme.Symbol] = {
WITH a SELECT FROM
a: Scheme.Symbol => RETURN [a];
ENDCASE => Complain[a, "not a Scheme.Symbol"];
};
SymbolForFilterItem: REF ARRAY MobConnection.FilterItem OF Symbol = InitSymbolForFilterItem[];
InitSymbolForFilterItem: PROC RETURNS [a: REF ARRAY MobConnection.FilterItem OF Symbol] = {
a ← NEW[ARRAY MobConnection.FilterItem OF Symbol];
a[versions] ← $versions;
a[directory] ← $directory;
a[using] ← $using;
a[imports] ← $imports;
a[importedItems] ← Atom.MakeAtom["imported-items"];
a[exports] ← $exports;
a[typeExports] ← Atom.MakeAtom["type-exports"];
a[exportedItems] ← Atom.MakeAtom["exported-items"];
a[modules] ← $modules;
a[configurations] ← $configurations;
};
TheFilterItem: PROC [a: Any] RETURNS [MobConnection.FilterItem] = {
FOR k: MobConnection.FilterItem IN MobConnection.FilterItem DO
IF a=SymbolForFilterItem[k] THEN RETURN [k];
ENDLOOP;
ERROR Complain[a, "is not a MobConnection.FilterItem"];
};
MobConnectionPrim: PROC [SELF: Primitive, ARG1,ARG2,ARG3: Any, REST: ProperList] RETURNS [result: Any ← unspecified] = {
INNER: PROC = {
POP: PROC RETURNS [a: Any ← undefined] = {
IF REST#NIL THEN {a ← REST.car; REST ← NARROW[REST.cdr]}};
DATA: Pair ~ NARROW[SELF.data];
env: Environment ~ NARROW[DATA.cdr];
SELECT NAT[NARROW[DATA.car, REF INT]↑] FROM
0 => {
filename: Any ← ARG1;
filter: Any ← ARG2;
stack: LIST OF Appender ← NIL;
Begin: PROC [id: Symbol] = {
head: Pair = Cons[id, NIL];
stack ← CONS[[head, head], stack];
};
End: PROC = {
a: Any ← stack.first.head;
stack ← stack.rest;
IF stack = NIL THEN result ← a ELSE Put[a];
};
Put: PROC [a: Any] = {
stack.first.last ← stack.first.last.cdr ← Cons[a, NIL]
};
PutATOM: PROC [a: Symbol] = {Put[a]};
PutROPE: PROC [a: Rope.ROPE] = {Put[StringFromRope[a]]};
PutINT: PROC [a: INT] = {Put[MakeFixnum[a]]};
PutBOOL: PROC [a: BOOL] = {Put[IF a THEN true ELSE false]};
PutModuleID: PROC [a: MobConnection.ModuleID] = {
Begin[$id]; PutATOM[a.identifier]; PutATOM[a.version]; End[]
};
f: MobConnection.Filter ← ALL[FALSE];
IF filter = undefined
THEN f ← ALL[TRUE]
ELSE {
FOR tail: Any ← filter, Cdr[tail] UNTIL tail = NIL DO
f[TheFilterItem[Car[tail]]] ← TRUE;
ENDLOOP;
};
MobConnection.DecodeMob[fileName: RopeFromString[TheString[filename]], begin: Begin, end: End, putATOM: PutATOM, putROPE: PutROPE, putINT: PutINT, putBOOL: PutBOOL, putModuleID: PutModuleID, filter: f];
IF stack # NIL THEN ERROR;
};
ENDCASE => ERROR
}; INNER[!
MobConnection.Error => Complain[culprit, msg];
];
};
MobConnectionInit: PROC [env: Environment] = {
DefinePrimitive[name: "decode-mob", nArgs: 2, proc: MobConnectionPrim, doc: "(filename [ filter ]) Extract useful information from a mob file", env: env, optional: 1, dotted: FALSE, data: Cons[MakeFixnum[0], env]];
};
Appender: TYPE = RECORD [head, last: Pair];
RegisterInit[MobConnectionInit];
END.