Closed IngwiePhoenix closed 8 years ago
require
occurs at runtime. That's too late for several of the existing compiler optimizations (inline const, inline enum, squeezing, etc). You could add support to parse require
into the compiler, but that means making the compiler aware of Node's implementation of require, and the compiler would need to know when a module was suppose to be handled at runtime vs. at ojc time.
In general, there are optimizations that the compiler can do when it knows about all classes and methods in a compilation unit. The compiler may not do those optimizations yet, but I'd prefer to not exclude them in the future (hence the reason why the current supported path has always been "compile your .oj files as one unit" with multiple compilation units being experimental/undocumented).
Note: actual compilation speed, even if you compile all your sources each time, is really fast. The bottleneck is using JSHint/linters/babel/typechecking.
Well what I was thinking about was to redo my current app to use OJ instead of plain JS. So my idea was this:
app.js
require.extensions[".oj"] = function(module, filename) {
// Get file from filename, compile it and run
// module._compile to finalize the require call
}
// Run actual app
require("./main/main.oj");
main.oj:
#include "myfile.oj"
#include "lib.oj"
@implementation MyApp {}
// ...
-(http) {
var app = require("express")();
app.get("/", function(req, res, next) {
[self handleRequest:req to:res withCallback:next];
});
}
@end
I dont know if you remember my connect-oj
project. It has a tiny pre-processor that it can use to include files into this .oj file. So the compiler would get the entire source.
Another mock up I have had was
request_handler.oj
@implementation RequestHandler {
var app;
}
+(id)init:(Express)_app {
app = _app;
// Assign routes etc
}
@end
module.exports = function(app) {
return [[RequestHandler alloc] init:app];
}
And the very last mock up
db_models.oj
@implementation Model {
var con;
}
+(id)create:(string)name {
// ...
}
@end
module.exports = Model;
my_model.oj:
require("db_model.oj");
// or: var Model = require(...);
@implementation ChatMessages : Model {}
// ...
@end
Of course, these are only mock-ups. So I will probably have to do what other apps do and create an npm script that re-compiles my app, or re-build the app whenever it launches.
Anyway, I'd recommend you to think about it - anything that would work, would be very interesting! :) I just love using OJ in my project and want to extend its use beyond the browser.
I just played and toyed around with the runtime functions, and came across something that got me baffled:
var oj = require("ojc/src/runtime");
@implementation Foo
+(id)greet { console.log("Hi"); }
@end
var vname = [Foo class].displayName;
var obj = {f: oj._cls[vname] };
[obj.f greet]; // <-- And that works!
Maybe I figure it out somehow, but It made me think of an expression. If you ever intended to implement CommonJS patterns or NodeJS support in general, consider a code transformation like this:
@export Foo;
// => module.exports.Foo = $oj_oj._cls[ [Foo class].displayName ];
In another file:
var Foo = require("other.oj").Foo;
@implementation Baz : Foo
// ...
@end
I dont have any idea how to properly create a @import
statement. It would probably require an enhanced @export
statement.
But I just thought I'd drop it here, because I found this really cool! :)
Let's just say I got a bit bored while waiting for my food to be done... https://github.com/IngwiePhoenix/oj-node :) Should try it, it's kinda nice.
So there actually is a way to extend NodeJS' require:
And I even found this: http://stackoverflow.com/questions/17294275/is-there-a-way-to-register-new-coffeescript-extensions-for-require (The ticked answer is where I found the resources)
Honestly, it would be pretty awesome to be able to use
.oj
files seamlessly together. For example:I haven't looked into the compiler/runtime again in a while to see if classes are registered into the global $oj_oj object or not ^^; But it certainly would be very nice to do use this!