comparison cbackend.js @ 329:eef8a5cea812

Use a smarter algorithm for calculating module init order and break some circular module dependencies in the standard library
author Michael Pavone <pavone@retrodev.com>
date Sat, 28 Mar 2015 13:26:03 -0700
parents 4a79311dbd29
children 61f5b794d939
comparison
equal deleted inserted replaced
328:c1fad3d93861 329:eef8a5cea812
1006 return this.ast.toCModuleInstance(); 1006 return this.ast.toCModuleInstance();
1007 }; 1007 };
1008 1008
1009 function processUsedToplevel(toplevel) 1009 function processUsedToplevel(toplevel)
1010 { 1010 {
1011 var alwaysused = ['list', 'true', 'false']; 1011 var alwaysused = ['true', 'false', 'list'];
1012 var ret = ''; 1012 var ret = '';
1013 var modulenum = 0; 1013 var modulenum = 0;
1014 var visited = {}; 1014 var visited = {};
1015 var newused = []; 1015 var newused = alwaysused;//Object.keys(toplevel.used);
1016 for (var i in alwaysused) {
1017 delete toplevel.used[alwaysused[i]];
1018 visited[alwaysused[i]] = true;
1019 }
1020 var addedAlways = false;
1021 var newused = Object.keys(toplevel.used);
1022 var allused = newused; 1016 var allused = newused;
1017 print('//newused = ' + newused.join(', '));
1023 while (newused.length) { 1018 while (newused.length) {
1024 for (var i in newused) { 1019 for (var i in newused) {
1025 debugprint('//---module', newused[i], '--- populate symbols'); 1020 debugprint('//---module', newused[i], '--- populate symbols');
1026 forwarddec += 'object * ' + toplevel.moduleVar(newused[i]) + ';\n'; 1021 forwarddec += 'object * ' + toplevel.moduleVar(newused[i]) + ';\n';
1027 toplevel.names[newused[i]].populateSymbols(toplevel); 1022 toplevel.names[newused[i]].populateSymbols(toplevel);
1033 debugprint('//found new usage of module', symbol); 1028 debugprint('//found new usage of module', symbol);
1034 newused.push(symbol); 1029 newused.push(symbol);
1035 allused.push(symbol); 1030 allused.push(symbol);
1036 } 1031 }
1037 } 1032 }
1038 if (!newused.length && !addedAlways) { 1033 }
1039 addedAlways = true; 1034 var compiled = {};
1040 for (var i in alwaysused) { 1035 //true and false depend on each other, but not at module init time
1041 toplevel.used[alwaysused[i]] = true; 1036 //force them to have no dependencies
1042 newused.push(alwaysused[i]); 1037 toplevel.names['true'].dependencies = {};
1043 allused.push(alwaysused[i]); 1038 toplevel.names['false'].dependencies = {};
1044 } 1039 //string and object can be a problem as well and is safe to init them before other things
1045 } 1040 toplevel.names['string'].dependencies = {};
1046 } 1041 toplevel.names['object'].dependencies = {};
1047 1042
1048 for (var i = allused.length-1; i >= 0; i--) { 1043 while (allused.length) {
1049 var symbol = allused[i]; 1044 var nextused = [];
1050 debugprint('//---module', symbol, '(' + i +')--- compile'); 1045 var minUnmet = allused.length;
1051 assignNames.push(symbol); 1046 var minUnmetIdx = -1;
1052 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n'; 1047 for (var i = 0; i < allused.length; i++) {
1053 assignNames.pop(); 1048 var symbol = allused[i];
1049 var module = toplevel.names[symbol];
1050 var unmet = 0;
1051 for (var dependency in module.dependencies) {
1052 if (!(dependency in compiled) && dependency != symbol) {
1053 unmet++;
1054 }
1055 }
1056 if (unmet) {
1057 nextused.push(symbol);
1058 if (unmet < minUnmet) {
1059 minUnmet = unmet;
1060 minUnmetIdx = i;
1061 }
1062 } else {
1063 debugprint('//---module', symbol, '(' + i +')--- compile');
1064 debugprint('// dependencies: ' + Object.keys(toplevel.names[symbol].dependencies).join(', '));
1065 assignNames.push(symbol);
1066 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n';
1067 assignNames.pop();
1068 compiled[symbol] = true;
1069 }
1070 }
1071 if (nextused.length == allused.length) {
1072 var symbol = nextused[minUnmetIdx];
1073 print('//WARNING: circular module dependency detected, compiling ' + symbol + ' with dependencies ' + Object.keys(toplevel.names[symbol].dependencies).join(', '));
1074 print('// but only these dependencies are met: ' + Object.keys(compiled).join(', '));
1075 debugprint('//---module', symbol, '(' + i +')--- compile');
1076 assignNames.push(symbol);
1077 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n';
1078 assignNames.pop();
1079 compiled[symbol] = true;
1080 nextused[minUnmetIdx] = nextused[nextused.length-1];
1081 nextused.pop();
1082 }
1083 allused = nextused;
1054 } 1084 }
1055 return ret; 1085 return ret;
1056 } 1086 }
1057 1087
1058 function makeCProg(obj) 1088 function makeCProg(obj)