SciRuby / rubex

rubex - A Ruby-like language for writing Ruby C extensions.
BSD 2-Clause "Simplified" License
451 stars 21 forks source link

cannnot call C functions #5

Closed kojix2 closed 7 years ago

kojix2 commented 7 years ago

Hello. I tried the sample code. https://github.com/v0dro/rubex/pull/4#issuecomment-322530853

lib "<math.h>" # Yes, "do" is obsolete.
  double cos(double)
end

class A
   def math
      return cos(4.5)
   end
end

However, the following error occured on my computer.

/path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/expression.rb:694:in `code_for_ruby_method_call': undefined method `c_code' for nil:NilClass (NoMethodError)
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/expression.rb:646:in `c_code'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/expression.rb:777:in `generate_evaluation_code'
    from /path/2.3.4/lib/ruby/2.3.0/forwardable.rb:204:in `generate_evaluation_code'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/statement.rb:361:in `generate_code'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:213:in `block in generate_statements'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:212:in `each'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:212:in `generate_statements'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:202:in `generate_function_definition'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:180:in `block in generate_code'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/code_writer.rb:127:in `block'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:179:in `generate_code'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:261:in `generate_code'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:333:in `block in generate_code'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:332:in `each'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:332:in `generate_code'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/node.rb:189:in `block in generate_code'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/node.rb:188:in `each'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/node.rb:188:in `generate_code'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/ast/node.rb:17:in `process_statements'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/compiler.rb:50:in `generate_code'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/lib/rubex/compiler.rb:9:in `compile'
    from /path/2.3.4/lib/ruby/gems/2.3.0/gems/rubex-0.0.1/bin/rubex:10:in `<top (required)>'
    from /path/2.3.4/bin/rubex:22:in `load'
    from /path/2.3.4/bin/rubex:22:in `<main>'

The following code can be executed without error. But it shows me a bit strange behavior.

lib "<math.h>"
  double cos(double)
end

def stray_cos
  return cos(4.5)
end

class A
  def cos
    return cos(4.5)
  end
end
irb(main):001:0> require './r5.so'
=> true
irb(main):002:0> stray_cos
=> -0.2107957994307797
irb(main):003:0> A.new.cos
=> 4.5 # ??
irb(main):004:0> A.new.stray_cos
=> -0.2107957994307797

This is C file.

/* C extension for r5.
This file in generated by Rubex::Compiler. Do not change!
File generation time: ***.*/

#include <ruby.h>
#include <stdint.h>
#include <stdbool.h>
#include <math.h>

#define __rubex_INT2BOOL(arg) (arg ? Qtrue : Qfalse)

VALUE rb_cObject;
VALUE __rubex_rb_cls_A;
static VALUE __rubex_rb_f_Object_stray_cos (int argc,VALUE* argv,VALUE __rubex_arg_self);
static VALUE __rubex_rb_f_A_cos (int argc,VALUE* argv,VALUE __rubex_arg_self);

VALUE __rubex_char2rubystr(char ch);
VALUE __rubex_char2rubystr(char ch)
{
  char s[2];
  s[0] = ch;
  s[1] = '\0';
  return rb_str_new2(s);
}

static VALUE __rubex_rb_f_Object_stray_cos (int argc,VALUE* argv,VALUE __rubex_arg_self)
{
  if (argc < 0)
  {
    rb_raise(rb_eArgError, "Need 0 args, not %d", argc);
  }

  /* Rubex file location: /home/kojix2/Ruby/rubex/r5.rubex:6 */
  return rb_float_new(cos(4.5));
}

static VALUE __rubex_rb_f_A_cos (int argc,VALUE* argv,VALUE __rubex_arg_self)
{
  VALUE __rubex_rb_f_A_cos_actual_args[0];
  if (argc < 0)
  {
    rb_raise(rb_eArgError, "Need 0 args, not %d", argc);
  }

  /* Rubex file location: /home/kojix2/Ruby/rubex/r5.rubex:11 */
  return __rubex_rb_f_A_cos_actual_args[0] = rb_float_new(4.5);
  __rubex_rb_f_A_cos(1, __rubex_rb_f_A_cos_actual_args,__rubex_arg_self);
}

void Init_r5 ();
void Init_r5 ()
{
  VALUE __rubex_rb_cls_A;

  __rubex_rb_cls_A = rb_define_class("A", rb_cObject);

  rb_define_method(rb_cObject ,"stray_cos", __rubex_rb_f_Object_stray_cos, -1);
  rb_define_method(__rubex_rb_cls_A ,"cos", __rubex_rb_f_A_cos, -1);
}

Perhaps the setting and the execution environment are not sufficient, and that may be the reason it does not work. However, as it may be useful for something, I will report it as it is. Thank you.

v0dro commented 7 years ago

Thank you for your report. The first example is working on my computer. Can you use the current master and see if it still works? Also can you write the commands that you used over here?

As for the second example:

lib "<math.h>"
  double cos(double)
end

def stray_cos
  return cos(4.5)
end

class A
  def cos
    return cos(4.5)
  end
end

The A.new.cos is not working because Rubex is assuming that cos is a C method. Since C methods are not namespaced, it is currently not possible to use the same name as the C method for the Ruby method. So if you write code like this:

lib "<math.h>"
  double cos(double)
end

def stray_cos
  return cos(4.5)
end

class A
  def ruby_cos
    return cos(4.5)
  end
end

It will work with A.new.ruby_cos. I will write the namespacing feature in the future work soon.

kojix2 commented 7 years ago

A.new.ruby_cos works good!
The first example still not work. I will think about it for a while. Thank you.

v0dro commented 7 years ago

If there are any updates please post in this thread. Closing for now.

kojix2 commented 7 years ago

I tried experiment

m1.rubex

lib "<math.h>"
  double sin(doublue)
end

def top_sin(x)
  sin(x)
end

class RMath
  def ruby_sin(x)
    sin(x)
  end
end

m2.rubex

lib "<math.h>"
  double sin(doublue)
end

class RMath
  def ruby_sin(x)
    sin(x)
  end
end

change rubex-0.0.1/lib/rubex/symbol_table/scope.rb

172     private
173       def recursive_find name, scope
174         if scope
175           require 'rainbow'
176           if scope.has_entry?(name)
177             puts Rainbow("+" << name.to_s << " in " << scope.name.to_s).green
178             return scope[name]
179           else
180             puts Rainbow("- " << name.to_s << " in " << scope.name.to_s).red
181             return recursive_find(name, scope.outer_scope)
182           end
183         end
184 
185         return nil
186       end
rubex m1.rubex
+ Object in Object
+ Object in Object
+ top_sin in Object
+ x in top_sin
- sin in top_sin
+ sin in Object
- sin in top_sin
+ sin in Object
- sin in top_sin
+ sin in Object
- top_sin in top_sin
+ top_sin in Object
+ RMath in Object
+ ruby_sin in RMath
+ x in ruby_sin
- sin in ruby_sin
- sin in RMath
+ sin in Object
- sin in ruby_sin
- sin in RMath
+ sin in Object
- sin in ruby_sin
- sin in RMath
+ sin in Object
- ruby_sin in ruby_sin
+ ruby_sin in RMath
- sin in top_sin
+ sin in Object
- sin in ruby_sin
- sin in RMath
+ sin in Object
+ RMath in Object
+ Object in Object
+ Object in Object
+ RMath in Object

Succeeded

rubex m2.rubex
- Object in Object
+ RMath in Object
+ ruby_sin in RMath
+ x in ruby_sin
- sin in ruby_sin
- sin in RMath
- sin in Object
- sin in ruby_sin
- sin in RMath
- sin in Object
+ sin in ruby_sin
- ruby_sin in ruby_sin
+ ruby_sin in RMath
+ sin in ruby_sin
+ sin in ruby_sin

error

2.4.0/gems/rubex-0.0.1/lib/rubex/ast/expression.rb:694:in `code_for_ruby_method_call': undefined method `c_code' for nil:NilClass (NoMethodError)

Well. I do not know whether it is correct or wrong. Mr. v0dro, do you understand something?

v0dro commented 7 years ago

Investigating.

v0dro commented 7 years ago

Has been fixed in https://github.com/v0dro/rubex/commit/c9793b605855521c724d11de50ca09d4cc3020bb

Thank you for your report! Do send more :)