Mercurial > repos > tabletprog
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) |