ruby / ruby/rdoc

Needs a parse tree for C files

Open
#1,168 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Ruby
Stars
930
Forks
465
Avg merge
3d 10h
Merged PRs (30d)
27

Description

In the current version of RDoc, when searching for class definition APIs such as rb_define_class and rb_define_method in a C file, if a match is found in that file, it seems to only accept the class and method definitions in that file.
This means that no matter how the method is defined in other C files, it will be ignored.

A mechanism will needed that to first gather elements from the C file and determine whether they are properly defined as classes. In this case, the parse tree would be desirable.
rb_xYYY variables used as object entities are basically the global variables, so they must be declared as extern when defining classes at the C level. However, this way does not work in outer method definitions (#pack/#unpack, etc.) because these "global variables" are not defined as classes.

In C, global variables must be initialized. A popular solution is to do the initialization in a single C file.

// global.h
#ifdef GLOBAL_VARIABLE_DEFINE
#define GLOBAL
#define GLOBAL_VAL(v) = (v)
#else
#define GLOBAL extern
#define GLOBAL_VAL(v)
#endif

This allows you to initialize variables as needed.

#define GLOBAL_VARIABLE_DEFINE // without extern
#include "global.h"

In Ruby, C's global variables are definitions, which means they have a different meaning than initialization.
Now below, definition in single file, RDoc is well parse here:

/*
 * call-seq:
 *   bar -> nil
 *
 * It is a test.
 */
static VALUE
foo_bar(VALUE self)
{
	return Qnil;
}

void
Init_foo()
{
	rb_cFoo = rb_define_class("Foo", rb_cObject);

	rb_define_method(rb_cFoo, "bar", foo_bar, 0);
}

However, a library that could become a small framework (such as image processing) is unlikely to be a single C file.
That is, it needs to be improved.

Below is a typical way I write it, and it is an example of an extension library that uses Professor Oura's FFT in Ruby.
The compiler passes it, but RDoc doesn't.

// ---(ruby/ext_extern.h)
#ifndef RUBY_EXT_EXTERN_H_INCLUDED
#define RUBY_EXT_EXTERN_H_INCLUDED

#if defined(__cplusplus)
extern "C" {
#endif

#ifdef     USE_GLOBAL_VARIABLE
# define   RUBY_EXT_EXTERN
#else
# define   RUBY_EXT_EXTERN    extern
#endif

#if defined(__cplusplus)
}
#endif

#endif /* RUBY_EXT_EXTERN_H_INCLUDED */
// ---

// ---(ruby/ooura_fft/globals.h)
#ifndef RUBY_OOURAFFT_GLOBALS_H_INCLUDED
#define RUBY_OOURAFFT_GLOBALS_H_INCLUDED

#include <ruby/internal/value.h> // VALUE
#include "ruby/ext_extern.h"

RUBY_EXT_EXTERN VALUE rb_mOouraFFT;

#endif /* RUBY_OOURAFFT_GLOBALS_H_INCLUDED */
// ---

// --- (ooura_fft.c)
#include <ruby.h>
#define  USE_GLOBAL_VARIABLE
#include "ruby/ooura_fft/globals.h"

void
Init_ooura_fft(void)
{
	rb_mOouraFFT = rb_define_module("OouraFFT");
	
	InitVM(FFT);
}
// ---

// --- (fft.c)
#include <ruby.h>
#include "ruby/ooura_fft/globals.h"

// :
// :

static void InitVM_FFTMain(void);
void
InitVM_FFT(void)
{
	InitVM(FFTMain);
}

// :
// :

static void
InitVM_FFTMain(void)
{
	rb_define_module_function(rb_mOouraFFT, "cdft", fft_cdft, -1);
	rb_define_module_function(rb_mOouraFFT, "rdft", fft_rdft, -1);
	rb_define_module_function(rb_mOouraFFT, "ddct", fft_ddct, -1);
	rb_define_module_function(rb_mOouraFFT, "ddst", fft_ddst, -1);
	rb_define_module_function(rb_mOouraFFT, "dfct", fft_dfct, -1);
	rb_define_module_function(rb_mOouraFFT, "dfst", fft_dfst, -1);
	rb_define_const(rb_mOouraFFT, "USING_THREAD", rb_str_new_cstr((const char *)USING_THREAD));
}
// ---

It is expected that more extension libraries with this syntax will be available in the future. You may want to reconsider RDoc as well.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing RDoc's handling of rb_define_class, rb_define_method, and rb_define_module_function against the cross-file examples in globals.h, ooura_fft.c, and fft.c. Done means RDoc recognizes classes or modules initialized in one C file and used through extern declarations in another, including the documented methods.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, ruby
Domain
documentation, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.