From 2423faa8c6e8cd50ffde5792fa8e64fbb7cde8db Mon Sep 17 00:00:00 2001 From: Tom Robinson Date: Sun, 19 Jul 2009 02:45:27 -0700 Subject: [PATCH] Major improvments to Objective-J Narwhal support. * Added objj_eval, objj_import_sync, objj_preprocess_sync, etc * Refactored REPL. * Added Objective-J plugin for load system, using new Narwhal plugin system. * Refactored objj and objjc into single module. --- External/Rakefile | 1 + External/narwhal | 2 +- Objective-J/Tools/objj/bin/objj | 2 +- Objective-J/Tools/objj/bin/objjc | 6 +- Objective-J/Tools/objj/lib-js/objj/loader.js | 23 +++ Objective-J/Tools/objj/lib-js/objj/objj.js | 157 +++++++++++++----- Objective-J/Tools/objj/lib-js/objj/objjc.js | 21 --- Objective-J/Tools/objj/lib/objj/objj.js | 78 --------- Objective-J/Tools/objj/lib/objj/objjc.js | 19 --- .../Tools/objj/lib/objj/regexp-rhino-patch.js | 73 -------- Objective-J/Tools/objj/package.json | 3 +- 11 files changed, 143 insertions(+), 242 deletions(-) create mode 100644 Objective-J/Tools/objj/lib-js/objj/loader.js delete mode 100644 Objective-J/Tools/objj/lib-js/objj/objjc.js delete mode 100644 Objective-J/Tools/objj/lib/objj/objj.js delete mode 100644 Objective-J/Tools/objj/lib/objj/objjc.js delete mode 100644 Objective-J/Tools/objj/lib/objj/regexp-rhino-patch.js diff --git a/External/Rakefile b/External/Rakefile index b0d4a6fd4..b51625b9f 100644 --- a/External/Rakefile +++ b/External/Rakefile @@ -29,6 +29,7 @@ task :build => [:update_submodules, $ENVIRONMENT_DIR] do cp_r('narwhal', $ENVIRONMENT_NARWHAL_PRODUCT) cp_r('browserjs', $ENVIRONMENT_BROWSERJS_PRODUCT) cp_r('jack', $ENVIRONMENT_JACK_PRODUCT) + symlink_executable(File.join($ENVIRONMENT_JACK_PRODUCT, "bin", "jackup")) end CLOBBER.include($ENVIRONMENT_NARWHAL_PRODUCT) diff --git a/External/narwhal b/External/narwhal index 64a6c684c..9f71966ff 160000 --- a/External/narwhal +++ b/External/narwhal @@ -1 +1 @@ -Subproject commit 64a6c684c5cc8a16dbfa07c45b57f849cd02d3a9 +Subproject commit 9f71966ffb5528df36a0791c2ae622f7573fa3fd diff --git a/Objective-J/Tools/objj/bin/objj b/Objective-J/Tools/objj/bin/objj index 208bcce8b..3c52d2a54 100755 --- a/Objective-J/Tools/objj/bin/objj +++ b/Objective-J/Tools/objj/bin/objj @@ -1,3 +1,3 @@ #!/usr/bin/env narwhal -require("objj/objj"); +require("objj/objj").run(system.args); diff --git a/Objective-J/Tools/objj/bin/objjc b/Objective-J/Tools/objj/bin/objjc index 5b266522c..d72c12ac6 100755 --- a/Objective-J/Tools/objj/bin/objjc +++ b/Objective-J/Tools/objj/bin/objjc @@ -1,9 +1,11 @@ #!/usr/bin/env narwhal -var objjc = require("objj/objjc"), +var objj = require("objj/objj"), File = require("file"); -with (objjc) +require("objj/regexp-rhino-patch"); + +with (objj) { importPackage(java.lang); diff --git a/Objective-J/Tools/objj/lib-js/objj/loader.js b/Objective-J/Tools/objj/lib-js/objj/loader.js new file mode 100644 index 000000000..2077a23fb --- /dev/null +++ b/Objective-J/Tools/objj/lib-js/objj/loader.js @@ -0,0 +1,23 @@ +var objj = null; + +function ObjectiveJLoader() { + var loader = {}; + var factories = {}; + + loader.reload = function(topId, path) { + if (!objj) objj = require("objj/objj"); + + //print("loading objective-j: " + topId + " (" + path + ")"); + factories[topId] = objj.make_narwhal_factory(system.fs.read(path)/*, topId, path*/); + } + + loader.load = function(topId, path) { + if (!factories.hasOwnProperty(topId)) + loader.reload(topId, path); + return factories[topId]; + } + + return loader; +}; + +require.loader.loaders.unshift([".j", ObjectiveJLoader()]); diff --git a/Objective-J/Tools/objj/lib-js/objj/objj.js b/Objective-J/Tools/objj/lib-js/objj/objj.js index ad90dd13c..3d17a562a 100644 --- a/Objective-J/Tools/objj/lib-js/objj/objj.js +++ b/Objective-J/Tools/objj/lib-js/objj/objj.js @@ -1,33 +1,60 @@ var File = require("file"); var window = require("browser/window"); -var OBJJ_HOME = File.resolve(module.path, "..", ".."), - FRAMEWORKS = File.resolve(OBJJ_HOME, "lib/", "Frameworks/"), - OBJECTIVEJ = File.resolve(FRAMEWORKS, "Objective-J/", "rhino.platform/", "Objective-J.js"); +// variables to be exported from the module, for use in objjc, etc +var exported = [ + "objj_preprocess", + "FRAGMENT_FILE", "FRAGMENT_LOCAL", + "MARKER_CODE", "MARKER_IMPORT_STD", "MARKER_IMPORT_LOCAL", + "OBJJ_PREPROCESSOR_DEBUG_SYMBOLS" +]; -window.OBJJ_INCLUDE_PATHS = [FRAMEWORKS]; +// setup OBJJ_HOME, OBJJ_INCLUDE_PATHS, etc +var OBJJ_HOME = exports.OBJJ_HOME = File.resolve(module.path, "..", ".."), + frameworksPath = File.resolve(OBJJ_HOME, "lib/", "Frameworks/"), + objectivejPath = File.resolve(frameworksPath, "Objective-J/", "rhino.platform/", "Objective-J.js"); + +window.OBJJ_INCLUDE_PATHS = [frameworksPath]; if (system.env["OBJJ_INCLUDE_PATHS"]) window.OBJJ_INCLUDE_PATHS = system.env["OBJJ_INCLUDE_PATHS"].split(":").concat(window.OBJJ_INCLUDE_PATHS); - -//if (system.args.length > 0) -// window.OBJJ_MAIN_FILE = File.canonical(args.shift()); - -window.args = system.args; - -// FIXME: ARGS -system.args.shift(); +// bring the "window" object into scope. +// TODO: somehow make window object the top scope? with (window) { - eval(File.read(OBJECTIVEJ, { charset:"UTF-8" })); + // read and eval Objective-J.js with the module's scope + eval(File.read(objectivejPath, { charset:"UTF-8" })); + + // export desired variables. must eval variable name to obtain a reference + for (var i = 0; i < exported.length; i++) + exports[exported[i]] = eval(exported[i]); - if (system.args.length > 0) +/* + objj_set_evaluator(function(code) { + return function(OBJJ_CURRENT_BUNDLE) { + with (window) { + return eval("function(OBJJ_CURRENT_BUNDLE){"+code+"}"); + } + } + }); +*/ + +// runs the objj repl or file provided in args +exports.run = function(args) +{ + args = args || []; + window.args = args; + + // FIXME: ARGS + args.shift(); + + if (args.length > 0) { - while (system.args.length && system.args[0].indexOf('-I') === 0) - OBJJ_INCLUDE_PATHS = system.args.shift().substr(2).split(':').concat(OBJJ_INCLUDE_PATHS); - + while (args.length && args[0].indexOf('-I') === 0) + OBJJ_INCLUDE_PATHS = args.shift().substr(2).split(':').concat(OBJJ_INCLUDE_PATHS); + var mainFilePath = File.canonical(args.shift()); - + objj_import(mainFilePath, YES, function() { if (typeof main === "function") main.apply(main, args); @@ -41,38 +68,76 @@ with (window) system.stdout.write("objj> ").flush(); var input = system.stdin.readLine(), - fragments = objj_preprocess(input, new objj_bundle(), new objj_file(), OBJJ_PREPROCESSOR_DEBUG_SYMBOLS), - count = fragments.length, - ctx = (new objj_context); - - if (count == 1 && (fragments[0].type & FRAGMENT_CODE)) - { - var fragment = fragments[0]; - var result = eval(fragment.info); - if (result != undefined) - print(result); - } - else if (count > 0) - { - while (count--) - { - var fragment = fragments[count]; - - if (fragment.type & FRAGMENT_FILE) - objj_request_file(fragment.info, (fragment.type & FRAGMENT_LOCAL), NULL); - - ctx.pushFragment(fragment); - } - - ctx.schedule(); - } - - require("browser/timeout").serviceTimeouts(); + result = objj_eval(input); + + if (result !== undefined) + print(result); + } catch (e) { print(e); } + + require("browser/timeout").serviceTimeouts(); } } - + require("browser/timeout").serviceTimeouts(); } + +// synchronously evals Objective-J code +var objj_eval = exports.objj_eval = function(code) +{ + var result = eval(objj_preprocess_sync(code)); + + //require("browser/timeout").serviceTimeouts(); + + return result; +} + +// prepocesses Objective-J code into JavaScript, which will perform imports synchronously when eval'd +var objj_preprocess_sync = function(code) +{ + var fragments = objj_preprocess(code, new objj_bundle(), new objj_file(), OBJJ_PREPROCESSOR_DEBUG_SYMBOLS) + + var preprocessed = []; + + fragments.forEach(function(fragment) { + if (fragment.type & FRAGMENT_CODE) + preprocessed.push(fragment.info); + else if (fragment.type & FRAGMENT_LOCAL) + preprocessed.push("objj_import_sync('"+fragment.info+"',YES);"); + else + preprocessed.push("objj_import_sync('"+fragment.info+"',NO);"); + }); + + return preprocessed.join("\n"); +} + +// synchronously perform an import +var objj_import_sync = function(pathOrPaths, isLocal) +{ + var context = new objj_context(); + context.pushFragment(fragment_create_file(pathOrPaths, new objj_bundle(), isLocal, NULL)); + context.evaluate(); + + // HACK: need a real synchronous require + // FIXME: this is bad. not really synchronous. shouldn't have to call serviceTimeouts. + require("browser/timeout").serviceTimeouts(); +} + +// creates a narwhal factory function in the objj module scope +exports.make_narwhal_factory = function(code) { + // TODO: integrate better with objj load system so relative paths work + var OBJJ_CURRENT_BUNDLE = new objj_bundle(); + + return eval( + "(function(require,exports,module,system,print){" + + objj_preprocess_sync(code) + + "/**/\n})" + ); +} + +} // end "with" + +if (require.main == module.id) + exports.run(system.args); diff --git a/Objective-J/Tools/objj/lib-js/objj/objjc.js b/Objective-J/Tools/objj/lib-js/objj/objjc.js deleted file mode 100644 index 2e35dea1b..000000000 --- a/Objective-J/Tools/objj/lib-js/objj/objjc.js +++ /dev/null @@ -1,21 +0,0 @@ -var File = require("file"); -var window = require("browser/window"); - -require("./regexp-rhino-patch"); - -var exported = ["OBJJ_HOME", "objj_preprocess", - "FRAGMENT_FILE", "FRAGMENT_LOCAL", - "MARKER_CODE", "MARKER_IMPORT_STD", "MARKER_IMPORT_LOCAL", - "OBJJ_PREPROCESSOR_DEBUG_SYMBOLS"]; - -var OBJJ_HOME = File.resolve(module.path, "..", ".."), - FRAMEWORKS = File.resolve(OBJJ_HOME, "lib/", "Frameworks/"), - OBJECTIVEJ = File.resolve(FRAMEWORKS, "Objective-J/", "rhino.platform/", "Objective-J.js"); - -with (window) -{ - eval(File.read(OBJECTIVEJ, { charset:"UTF-8" }).toString()); - - for (var i = 0; i < exported.length; i++) - exports[exported[i]] = eval(exported[i]); -} diff --git a/Objective-J/Tools/objj/lib/objj/objj.js b/Objective-J/Tools/objj/lib/objj/objj.js deleted file mode 100644 index e17a54d9f..000000000 --- a/Objective-J/Tools/objj/lib/objj/objj.js +++ /dev/null @@ -1,78 +0,0 @@ -var File = require("file"); -var window = require("browser/window"); - -var OBJJ_HOME = system.prefix + "/.."; - -window.OBJJ_INCLUDE_PATHS = [OBJJ_HOME+"/lib/Frameworks/"]; -if (system.env["OBJJ_INCLUDE_PATHS"]) - window.OBJJ_INCLUDE_PATHS = system.env["OBJJ_INCLUDE_PATHS"].split(":").concat(window.OBJJ_INCLUDE_PATHS); - -//if (system.args.length > 0) -// window.OBJJ_MAIN_FILE = String((new Packages.java.io.File(args.shift())).getAbsolutePath()); - -window.args = system.args; - -// FIXME: ARGS -system.args.shift(); - -with (window) -{ - eval(File.read(OBJJ_HOME + "/lib/Frameworks/Objective-J/rhino.platform/Objective-J.js", { charset:"UTF-8" })); - - if (system.args.length > 0) - { - while (system.args.length && system.args[0].indexOf('-I') === 0) - OBJJ_INCLUDE_PATHS = system.args.shift().substr(2).split(':').concat(OBJJ_INCLUDE_PATHS); - - var mainFilePath = String((new Packages.java.io.File(args.shift())).getAbsolutePath()); - - objj_import(mainFilePath, YES, function() { - if (typeof main === "function") - main.apply(main, args); - }); - } - else - { - var br = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(Packages.java.lang.System["in"], "UTF-8")); - - while (true) - { - try { - Packages.java.lang.System.out.print("objj> "); - - var input = String(br.readLine()), - fragments = objj_preprocess(input, new objj_bundle(), new objj_file(), OBJJ_PREPROCESSOR_DEBUG_SYMBOLS), - count = fragments.length, - ctx = (new objj_context); - - if (count == 1 && (fragments[0].type & FRAGMENT_CODE)) - { - var fragment = fragments[0]; - var result = eval(fragment.info); - if (result != undefined) - print(result); - } - else if (count > 0) - { - while (count--) - { - var fragment = fragments[count]; - - if (fragment.type & FRAGMENT_FILE) - objj_request_file(fragment.info, (fragment.type & FRAGMENT_LOCAL), NULL); - - ctx.pushFragment(fragment); - } - - ctx.schedule(); - } - - require("browser/timeout").serviceTimeouts(); - } catch (e) { - print(e); - } - } - } - - require("browser/timeout").serviceTimeouts(); -} diff --git a/Objective-J/Tools/objj/lib/objj/objjc.js b/Objective-J/Tools/objj/lib/objj/objjc.js deleted file mode 100644 index 9d9357f1c..000000000 --- a/Objective-J/Tools/objj/lib/objj/objjc.js +++ /dev/null @@ -1,19 +0,0 @@ -var File = require("file"); -var window = require("browser/window"); - -require("./regexp-rhino-patch"); - -var exported = ["OBJJ_HOME", "objj_preprocess", - "FRAGMENT_FILE", "FRAGMENT_LOCAL", - "MARKER_CODE", "MARKER_IMPORT_STD", "MARKER_IMPORT_LOCAL", - "OBJJ_PREPROCESSOR_DEBUG_SYMBOLS"]; - -var OBJJ_HOME = system.prefix + "/.."; - -with (window) -{ - eval(File.read(OBJJ_HOME + "/lib/Frameworks/Objective-J/rhino.platform/Objective-J.js", { charset:"UTF-8" }).toString()); - - for (var i = 0; i < exported.length; i++) - exports[exported[i]] = eval(exported[i]); -} diff --git a/Objective-J/Tools/objj/lib/objj/regexp-rhino-patch.js b/Objective-J/Tools/objj/lib/objj/regexp-rhino-patch.js deleted file mode 100644 index c8bf0d6f3..000000000 --- a/Objective-J/Tools/objj/lib/objj/regexp-rhino-patch.js +++ /dev/null @@ -1,73 +0,0 @@ -var CachedRegexData = []; - -function regexDataFromRegex(aRegex) -{ - var source = "", - flags = ""; - - if (typeof aRegex == "string") - { - if (CachedRegexData[aRegex]) - return CachedRegexData[aRegex]; - - string = aRegex; - source = aRegex; - } - else - { - string = aRegex.toString(); - - if (CachedRegexData[string]) - return CachedRegexData[string]; - - var index = string.lastIndexOf('/'); - - source = string.substr(0, index); - flags = string.substr(index + 1); - } - - source = source.replace("\\[\\^\\\\\\d\\]", ".", "g"); - source = source.replace("\\[([^\\]]*)\\\\b([^\\]]*)\\]", "[$1\\\\cH$2]", "g") // [...\b...] -> [...\cH...] - source = source.replace("(?