[ruby-core:98592] [Ruby master Feature#16924] instance_eval equivalent for RubyVM::InstructionSequence
From:
nunuu@...
Date:
2020-05-30 15:49:49 UTC
List:
ruby-core #98592
Issue #16924 has been reported by Wuerfel21 (Ada Gottenstr=E4ter). ---------------------------------------- Feature #16924: instance_eval equivalent for RubyVM::InstructionSequence https://bugs.ruby-lang.org/issues/16924 * Author: Wuerfel21 (Ada Gottenstr=E4ter) * Status: Open * Priority: Normal ---------------------------------------- # Abstract Proposal to expose the ability to evaluate precompiled ISEQs in non-topleve= l contexts. # Background A common pattern used for certain kinds of DSL is to instance_eval entire f= iles, like this: ```ruby ___dsl_object.instance_eval(File.read(___path),___path,0) ``` This has certain advantages and disadvantages over other methods of executi= ng DSL code (mainly that the global namespace is not being polluted by eith= er the DSL itself or the code running in the DSL). I find it very useful. Ruby exposes the RubyVM::InstructionSequence API, allowing caching of parsi= ng/compilation steps to speed up execution. However, the resulting code can= only be evaluated at the top level, disallowing it's use with DSLs designe= d to be instance_eval'd. # Proposal Add a `RubyVM::InstructionSequence#eval_in_instance` method that could be u= sed to replace ```ruby ___dsl_object.instance_eval(File.read(___path),___path,0) ``` with ```ruby iseq =3D RubyVM::InstructionSequence.compile_file(___path) # iseq could be cached here iseq.eval_in_instance(___dsl_object) ``` Note that while instance_eval makes local variables available if the evalua= ted argument is a string, this new method would not (as the local variables= can't be known at compile time). This discrepancy already exists between = RubyVM::InstructionSequence#eval and all other standard library functions n= amed eval, so I assume it's okay. This new method could also replace some use cases of Kernal#eval (any where= the passing of local variables is not required). # Implementation From a cursory glance at the relevant code, this seems like a fairly simple= feature to implement. Maybe an additional parameter to `#compile` is neede= d to change the ISEQ type, I'm not sure. If no one who is more experienced = at working with Ruby internals wants to step up to implement this feature, = I will try it myself. # Discussion There is a rejected feature #12093 about evaluating ISEQs with a binding (w= hich is not possible since the compiler needs to know the local variables o= f a binding to compile for it, thus the request got rejected). There was so= me talk about evaling inside an instance in the comments, but I assume that= was forgotten about due to the ticket being closed. Therefore I think open= ing this new ticket is justified. -- = https://bugs.ruby-lang.org/ Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=3Dunsubscribe> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>