@sap/cds-compiler
Version:
CDS (Core Data Services) compiler and backends
76 lines (66 loc) • 2.02 kB
JavaScript
// Module handling, layers and packages
;
const detectCycles = require('./cycle-detector');
const { setLink } = require('./utils');
function setLayers( sources ) {
// set dependencies
for (const name in sources) {
const ast = sources[name];
ast.realname = name;
setLink( ast, '_deps', [] );
for (const d of ast.dependencies || []) {
const art = sources[d.realname];
if (art)
ast._deps.push( { art } );
}
}
let layerNumber = 0;
let layerRepresentative;
detectCycles( sources, null, setExtends );
// It is ensured that the representative is called last in SCC and that
// dependent SCCs are called first
function setExtends( node, representative, sccDeps = Object.create( null ) ) {
setLink( node, '_layerRepresentative', representative );
if (layerRepresentative !== representative) {
layerRepresentative = representative;
++layerNumber;
}
node.$layerNumber = layerNumber; // for sorting
for (const dep of node._deps) {
if (dep.art._scc.lowlink !== node._scc.lowlink) { // not in same SCC
const depRepr = dep.art._layerRepresentative;
sccDeps[depRepr.realname] = depRepr;
}
}
if (node === representative) {
const exts = Object.keys( sccDeps ).map( name => sccDeps[name]._layerExtends );
Object.assign( sccDeps, ...exts );
setLink( representative, '_layerExtends', sccDeps );
// console.log ('SCC:', node.realname)
}
return sccDeps;
}
}
function layer( art ) {
while (art && art.kind !== 'source')
art = art._block;
return art && art._layerRepresentative;
}
function realname( art ) {
while (art && art.kind !== 'source')
art = art._block;
return art && art.realname || '';
}
function compareLayer( a, b ) {
while (a && a.kind !== 'source')
a = a._block;
while (b && b.kind !== 'source')
b = b._block;
return a.$layerNumber - b.$layerNumber;
}
module.exports = {
setLayers,
layer,
realname,
compareLayer,
};