anmonteiro / lumo

Fast, cross-platform, standalone ClojureScript environment
Eclipse Public License 1.0
1.88k stars 85 forks source link

Use GeneratorFunction in lumo REPL #345

Open arichiardi opened 6 years ago

arichiardi commented 6 years ago

I was wondering if I could use js/GeneratorFunction in lumo, just for the fun of it (not true, I am trying js.csp :smile:).

The following does not work though:

cljs.user=> (new js/GeneratorFunction "test1" "test2")
GeneratorFunction is not defined
     (evalmachine.<anonymous>:1:1)
     ContextifyScript.Script.runInThisContext (vm.cljs:50:33)
     Object.runInThisContext (vm.cljs:152:38)
     (Object._t)
     (Object.lumo.repl.caching_node_eval)
     (NO_SOURCE_FILE <embedded>:5837:273)
     E (NO_SOURCE_FILE <embedded>:5838:269)
     Object.cljs.js.eval_str_STAR_ (NO_SOURCE_FILE <embedded>:5839:373)
     Function.cljs.js.eval_str.cljs$core$IFn$_invoke$arity$5 (NO_SOURCE_FILE <embedded>:5842:508)
     Object.lumo.repl.execute_text (NO_SOURCE_FILE <embedded>:6621:475)

The GCC flags say that they accept ES6 in there, so I was wondering what needs to happen in order to specify the :language-in in lumo.

Will dig of course, any hint is very welcome!

anmonteiro commented 6 years ago

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/GeneratorFunction

Note that GeneratorFunction is not a global object. It could be obtained by evaluating the following code.

Object.getPrototypeOf(function*(){}).constructor
arichiardi commented 6 years ago

I tried that too, maybe with the wrong syntax though:

cljs.user=> (.getPrototypeOf js/Object (js* "function*(){}"))
Evaluating (.getPrototypeOf js/Object (js* "function*(){}"))
Object.getPrototypeOf(function*(){})
Function.prototype.toString requires that 'this' be a Function
     GeneratorFunction.toString (NO_SOURCE_FILE <anonymous>)
     Function.cljs.core.str.cljs$core$IFn$_invoke$arity$1 (NO_SOURCE_FILE <embedded>:738:77)
     Object.cljs.core.pr_writer_impl (NO_SOURCE_FILE <embedded>:1800:289)
     Object.cljs.core.pr_writer (NO_SOURCE_FILE <embedded>:1801:405)
     Object.cljs.core.pr_seq_writer (NO_SOURCE_FILE <embedded>:1802:51)
     Object.cljs.core.pr_sb_with_opts (NO_SOURCE_FILE <embedded>:1803:156)
     Object.cljs.core.pr_str_with_opts (NO_SOURCE_FILE <embedded>:1803:362)
     Function.cljs.core.pr_str.cljs$core$IFn$_invoke$arity$variadic (NO_SOURCE_FILE <embedded>:1807:84)
     (NO_SOURCE_FILE <embedded>:6349:98)
     lumo.pprint.data.LumoPrinter.fipp$visit$IVisitor$visit_unknown$arity$2 (NO_SOURCE_FILE <embedded>:6349:236)
arichiardi commented 6 years ago

This works!

cljs.user=> (.constructor (.getPrototypeOf js/Object (js* "function*(){}")))
Evaluating (.constructor (.getPrototypeOf js/Object (js* "function*(){}")))
Object.getPrototypeOf(function*(){}).constructor()
#object[anonymous]
anmonteiro commented 6 years ago

you want .-constructor

arichiardi commented 6 years ago

:+1:

Can live with this:

cljs.user=> (.-constructor (.getPrototypeOf js/Object (js* "function*(){}")))
Evaluating (.-constructor (.getPrototypeOf js/Object (js* "function*(){}")))
Object.getPrototypeOf(function*(){}).constructor
#object[GeneratorFunction]

Probably it can be documented somewhere, will keep it open.

arichiardi commented 6 years ago

So it turns out that:

functionBody A string containing the JavaScript statements comprising the function definition.

So this makes my task a bit harder than expected. I need to pause playing with it for now.

arichiardi commented 6 years ago

So we can eval to string for sure, do we want to be super cutting edge and provide a simple macro that creates a generator in lumo.core? Haven't had time to work on it yet (prefer to finish outstanding PRs), but it would be nice to have.