nodejs.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. "use strict";
  2. var Class = require("rtl.js").Class;
  3. var Code = require("js/Code.js");
  4. var Errors = require("js/Errors.js");
  5. var ContextHierarchy = require("js/ContextHierarchy.js");
  6. var LanguageContext = require("js/LanguageContext.js");
  7. var oc = require("oc.js");
  8. var makeRTL = require("rtl_code.js").makeRTL;
  9. var fs = require("fs");
  10. var path = require("path");
  11. var ModuleGenerator = Class.extend({
  12. init: function Nodejs$ModuleGenerator(name, imports, importDir){
  13. this.__name = name;
  14. this.__imports = imports;
  15. this.__importDir = importDir;
  16. },
  17. prolog: function(){
  18. var result = "";
  19. var modules = this.__imports;
  20. for(var name in modules){
  21. var alias = modules[name];
  22. var importName = this.__importDir ? this.__importDir + "/" + name
  23. : name;
  24. result += "var " + alias + " = " + (name == "this"
  25. ? "GLOBAL"
  26. : "require(\"" + importName + ".js\")") + ";\n";
  27. }
  28. return result;
  29. },
  30. epilog: function(exports){
  31. var result = "";
  32. for(var access in exports){
  33. var e = exports[access];
  34. var code = Code.genExport(e);
  35. if (code){
  36. var id = Code.exportId(e);
  37. result += "exports." + id + " = " + code + ";\n";
  38. }
  39. }
  40. return result;
  41. }
  42. });
  43. var RtlCodeUsingWatcher = Class.extend({
  44. init: function(){this.__used = false;},
  45. using: function(){this.__used = true;},
  46. used: function(){return this.__used;},
  47. reset: function(){this.__used = false;}
  48. });
  49. function writeCompiledModule(name, code, outDir){
  50. var filePath = path.join(outDir, name + ".js");
  51. fs.writeFileSync(filePath, code);
  52. }
  53. function compile(sources, language, handleErrors, includeDirs, outDir, importDir){
  54. var rtlCodeWatcher = new RtlCodeUsingWatcher();
  55. var rtl = new makeRTL(language.rtl, rtlCodeWatcher.using.bind(rtlCodeWatcher));
  56. var moduleCode = function(name, imports){
  57. return new ModuleGenerator(name, imports, importDir);};
  58. var compiledFilesStack = [];
  59. var failToCompile = {};
  60. return oc.compileModules(
  61. sources,
  62. function(name){
  63. var fileName = name;
  64. if (!path.extname(fileName).length)
  65. fileName += ".ob";
  66. var alreadyFail = failToCompile[fileName];
  67. if (alreadyFail)
  68. throw new Errors.Error("'" + fileName + "': error " + alreadyFail);
  69. compiledFilesStack.push(fileName);
  70. var readPath = fileName;
  71. var i = 0;
  72. while (!fs.existsSync(readPath) && i < includeDirs.length){
  73. readPath = path.join(includeDirs[i], fileName);
  74. ++i;
  75. }
  76. if (!fs.existsSync(readPath))
  77. throw new Error("cannot find file: '" + fileName + "' in " + includeDirs);
  78. return fs.readFileSync(readPath, "utf8");
  79. },
  80. language.grammar,
  81. function(moduleResolver){
  82. return new ContextHierarchy.Root(
  83. { codeTraits: language.makeCodeTraits(language.codeGenerator.make(), rtl),
  84. moduleGenerator: moduleCode,
  85. rtl: rtl,
  86. types: language.types,
  87. stdSymbols: language.stdSymbols,
  88. moduleResolver: moduleResolver
  89. });},
  90. function(e){
  91. var fileName = compiledFilesStack[compiledFilesStack.length - 1];
  92. failToCompile[fileName] = e;
  93. handleErrors("File \"" + fileName + "\", " + e);
  94. },
  95. function(name, code){
  96. if (rtlCodeWatcher.used()){
  97. code = "var " + rtl.name() + " = require(\"" + rtl.module() + "\");\n" + code;
  98. rtlCodeWatcher.reset();
  99. }
  100. writeCompiledModule(name, code, outDir);
  101. compiledFilesStack.pop();
  102. });
  103. }
  104. exports.compile = compile;