Editing Topic: RCR234 Project: RCR | RCRchive home

RCR 234: Uniform meta-access while parsing Ruby code (replaces RCR 228)

submitted by itsme213 on Thu Apr 08 2004 10:53:25 AM -0700

Status: pending


Abstract

Ruby exposes self within a class body, and also calls certain methods (e.g. Module#included) to signal certain parsing events (e.g. including of a module). These are powerful extensibility feature, allowing new methods to be written at the meta-level (e.g. Class) and easily invoked at many places within Ruby code. This RCR provides both extensibility mechanisms uniformaly throughout the source code, with access to many other syntactic elements (methods, parameters, constants, ...).

Problem

Facilities such as attr rely on methods on Class being invoked within the text of a class fdefinition with self = current_class. I can write new methods on Class and explicitly invoke them directly from anywhere within a class that self is bound.

Similarly, methods such as Module#included and Class#inherited are always invoked by the Ruby intepreter on certain events like module inclusion or class inheritance. I can override these methods for my own module or class and they are automatically invoked when those events take place with my module or class.

However, these two facilities are limited. I cannot define new methods on Method (or UnboundMethod, or whatever the underlying meta-level class will be called) and explicitly invoke them (similar to today's common attr invocation) at appropriate points (if any) in a method definition. I cannot write new methods on Parameter ... etc.

Similarly, I cannot override methods on Method, Parameter, etc. and have them automatically invoked by Ruby at key sentinel points in the code e.g. Method#started, ParamList#finished

This makes it more awkward than necessary to extend the meta-level e.g. I may want to create and attach information to explicit "Attribute" and "Method" objects to represent various meta-data information

This facility could be extremely useful if more uniformly available. Classes representing the entire Ruby Abstract Syntax Tree should be published (Method, Parameter, Constant, ...), self should be bound to instances of these AST classes during parsing, and a rich set of events should be defined that call methods on those AST objects (Class#started, Class#finished, Module#included, Class#inherited, ParamList#started, ParamList#finished, etc.) just as SAX parsers raise events when procesing an XML stream).

Proposal

The examples below are meant only to illustrate the idea. I do not have detailed enough knowledge of the Ruby grammar to know which points in the code would be reasonable choices for definition of new methods or explicit invocation of methods, or if some syntax change may be involved . I have annotatated the code with [1][2]... as points in the code that I cross-reference subsequently.

class Method [1]
 def started [2]; p "New Method"; end
 def explicit [3]; p "Method#explicit"; end
end

class [4] A [5]
 def [6] foo [7] explicit [8] (a [9] ...)[10]
   # body
 end [11]  def self.wrapped [12] (...) # used like self.included in a class
         end [13]
 [14]
end [15]
> Explanation of above code refers to [1], [2], etc.

Analysis

With this scheme:

Implementation

If I knew more of how the Ruby grammar was being implemented I could probably suggest something. However, most of this seems to require a generalization of facilities currently available: self binding during parsing, and automatic invocation of pre-defined methods at key events during parsing.



Back to RCRchive.


RCR Submission page and RCRchive powered by Ruby, Apache, RuWiki (modified), and RubLog