Giter Site home page Giter Site logo

rubex's Introduction

SciRuby meta gem Build Status

Tools for Scientific Computing in Ruby

Description

This gem acts as a meta gem which collects and provides multiple scientific gems, including numeric and visualization libraries.

Getting started

Installation:

gem install sciruby
gem install sciruby-full

If you want to have a full-blown installation, install sciruby-full.

Start a notebook server:

iruby notebook

Enter commands:

require 'sciruby'
# Scientific gems are auto loaded, you can use them directly!
plot = Nyaplot::Plot.new
sc = plot.add(:scatter, [0,1,2,3,4], [-1,2,-3,4,-5])

Take a look at gems.yml or the list of gems for interesting gems which are included in sciruby-full.

License

Copyright (c) 2010 onward, The Ruby Science Foundation.

All rights reserved.

SciRuby is licensed under the BSD 3-clause license. See LICENSE for details.

Donations

Support a SciRuby Fellow via Pledgie.

rubex's People

Contributors

arjunmenon avatar codetriage-readme-bot avatar kojix2 avatar ledsun avatar shaunakpp avatar tessi avatar v0dro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rubex's Issues

Fix expression generation in loop expressions

This goes wrong. Which it should not.

class String
  def blank?(str string)
    char *s = string
    int i = 0
    
    while i < string.size do
      return false if s[i] != ' '
      i += 1
    end

    return true
  end
end

Ability to release the GIL

Design a special syntax that allows a C function to run without GIL. This might also need some sort of a threading API for spawning native threads (if that is possible).

How can I refer to self?

Tutorial sample fast_blank is

class String
  def blank?(string)
    char *s = string
    int i = 0
    int a = string.size

    while i < a do
      return false if s[i] != ' '
      i += 1
    end

    return true
  end
end

This code define String#blank?(string) method.
But I think the fast_blank evaluates value of self, not argument.
I tried below:

class String
  def blank?
    char *s = self
  end
end

I got error below:

~ rubex fast_blank.rubex

PARSE ERROR:
Line:     char *s = self
Location: fast_blank.rubex:3
Error:

parse error on value "self" (kSELF)
Traceback (most recent call last):
	7: from /Users/shigerunakajima/rubex/bin/rubex:7:in `<main>'
	6: from /usr/local/lib/ruby/gems/2.5.0/gems/thor-0.20.0/lib/thor/base.rb:466:in `start'
	5: from /usr/local/lib/ruby/gems/2.5.0/gems/thor-0.20.0/lib/thor.rb:387:in `dispatch'
	4: from /usr/local/lib/ruby/gems/2.5.0/gems/thor-0.20.0/lib/thor/invocation.rb:126:in `invoke_command'
	3: from /usr/local/lib/ruby/gems/2.5.0/gems/thor-0.20.0/lib/thor/command.rb:27:in `run'
	2: from /Users/shigerunakajima/rubex/lib/rubex/cli.rb:21:in `generate'
	1: from /Users/shigerunakajima/rubex/lib/rubex/compiler.rb:48:in `compile'
/Users/shigerunakajima/rubex/lib/rubex/compiler.rb:105:in `generate_code': Must be a Rubex::AST::Node::MainNode, not NilClass (RuntimeError)

Tried version is 'bf5ee9365e1b93ae58c97827c1a6ef6c04cb5f33' of the mater branch.

Error in C compilation when rubex method is recursive

Consider a simple example of printing sum of n Fibonacci numbers.

# fibonacci.rubex
class Fibonacci
  def compute(int n)
    if n == 0 || n == 1
      return n
    end
    return compute(n - 1) + compute(n - 2)
  end
end

running rubex fibonacci.rubex successfully generates the extconf.rb, Makefile and fibonacci.c files.
But, on running make, I got the following errors:

compiling fibonacci.c
fibonacci.c:30:9: error: redefinition of '__rubex_rb_f_Fibonacci_compute_actual_args'
  VALUE __rubex_rb_f_Fibonacci_compute_actual_args[1];
        ^
fibonacci.c:29:9: note: previous definition is here
  VALUE __rubex_rb_f_Fibonacci_compute_actual_args[1];
        ^
fibonacci.c:47:101: error: expected ')'
  return ( rb_funcall(__rubex_rb_f_Fibonacci_compute_actual_args[0] = INT2NUM(( __rubex_arg_n - 1 ));
                                                                                                    ^
fibonacci.c:47:22: note: to match this '('
  return ( rb_funcall(__rubex_rb_f_Fibonacci_compute_actual_args[0] = INT2NUM(( __rubex_arg_n - 1 ));
                     ^
fibonacci.c:48:116: warning: expression result unused [-Wunused-value]
  __rubex_rb_f_Fibonacci_compute(1, __rubex_rb_f_Fibonacci_compute_actual_args,__rubex_arg_self), rb_intern("+") , 1, __rubex_rb_f_Fibonacci_compute_actual_args[0] = INT2N...
                                                                                                                   ^
fibonacci.c:49:97: error: expected ';' after expression
  __rubex_rb_f_Fibonacci_compute(1, __rubex_rb_f_Fibonacci_compute_actual_args,__rubex_arg_self)) );
                                                                                                ^
                                                                                                ;
fibonacci.c:49:97: error: expected expression
1 warning and 4 errors generated.
make: *** [fibonacci.o] Error 1

It would be awesome if recursion is supported in rubex, as recursion often helps in writing concise programs.

Support for blocks

Blocks are an integral part of Ruby and users should be allowed to supply blocks to any Ruby method just like normal Ruby.

Identify 'code smell' and refactor.

Rubex was written in a bit of hurry, so parts of the code base are quite messy. Identify these smelly parts and refactor them with better design. Refer to Martin Fowler's Refactoring Ruby book for reference. Here's a rough list based on basic parameters like a method/class doing too many things or being too long. Feel free to add your own.

  • Statement::Alias#analyse_statement.
    This method is using an if-else approach for detecting function pointers. Ideally we should use a new class for denoting function pointers for arguments (like this commit: ff00ff8)

  • Expression::MethodCall#analyse_statement

Method is too long and does too many things in 30 lines of code :O

  • Expression::Name#analyse_statement

Too long and does too many things.

  • analyse_statement in Expression classes

    The analyse_statement method should only analyse statements and make sense of their types
    and generate symbol table entries etc. Currently methods of this name exist in Expression
    classes as well. This should go so that there is a clear demarcation between statements and
    expressions. Don't just rechristen to analyse_expression. Let there be some value to it.

  • Separate classes into their own files as per ruby-style-guide.

  • Expression::CommandCall#generate_evaluation_code
    Method is too long and does too many things. Too many conditionals.

  • ElementRef#analyse_statement

  • ElementRef#generate_evaluation_code

  • Expression::StringLit class
    Class trying to be both a Ruby string and C string. Segregate.

  • Refactor temp allocation mechanism. Current mechanism requires too much work on part of programmer.

  • Refactor code generation. Current mechanism relies on the c_code construct which does not convey meaning properly and does too many things in one method in many cases.

  • Unify Statement::ArgumentList and Expression::ArgList. There should be only one class for dealing with argument lists.

Create additional rake tasks for building and shipping

Currently the rake tasks inside rubex/rake_task are only meant for compiling a Rubex file inside a gem.

There should be additional rake tasks that help build Rubex files inside Rails apps (or any other framework) and even for standalone Rubex scripts.

Specs failing on macOS Sierra and High Sierra

On a typical macOS machine, whenever we run make after running ruby extconf.rb, .bundle and .o files are created. .bundle is the macOS equivalent of .so files. So, requiring them in our ruby programs should expect the standard behaviour.

But, when I run the basic_ruby_method.spec,which runs basic_ruby_method.rubex, requiring the .bundle file created after running make doesn't work and gives the following error:

TypeError: wrong argument type false (expected Class)

Here is the C file generated by rubex:

/* C extension for basic_ruby_method.
This file in generated by Rubex::Compiler. Do not change!
File generation time: 2017-10-03 17:26:38 +0530.*/

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

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


VALUE rb_cObject;
static VALUE __rubex_rb_f_Object_addition (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_addition (int argc,VALUE* argv,VALUE __rubex_arg_self)
{
  int32_t __rubex_arg_a;
  int32_t __rubex_arg_b;
  VALUE __rubex_v_t;
  VALUE __rubex_temp_1;
  if (argc < 2)
  {
    rb_raise(rb_eArgError, "Need 2 args, not %d", argc);
  }

  __rubex_arg_a=(int32_t)NUM2INT(argv[0]);
  __rubex_arg_b=(int32_t)NUM2INT(argv[1]);

  /* Rubex file location: /path/to/rubex/file:2 */
  __rubex_temp_1 = rb_str_new2("aaa");
  __rubex_v_t = __rubex_temp_1;
  __rubex_temp_1 = 0;
  __rubex_temp_1 = 0;

  /* Rubex file location: /path/to/rubex/file:3 */
  rb_funcall(__rubex_v_t, rb_intern("nil?"), 0, NULL);

  /* Rubex file location: /path/to/rubex/file:4 */
  return INT2NUM(( __rubex_arg_a + __rubex_arg_b ));
}


void Init_basic_ruby_method ();
void Init_basic_ruby_method ()
{


  rb_define_method(rb_cObject ,"addition", __rubex_rb_f_Object_addition, -1);
}

Environment:
os: macOS Sierra
ruby: 2.4.1 running on rvm
running gcc --version gives the following output:

Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.37)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

As a side note:

I tried the simple example of creating Ruby extensions in 5 minutes and it works perfectly.

Linking external C library

Hey
I am trying to understand correct way to create bindings to any external C libs.

C lib - https://github.com/wooorm/levenshtein.c

rubex file

lib "<levenshtein.h>"
	unsigned int levenshtein(char *a, char *b)
end

class Lev
	def self.distance(a, b)
		return levenshtein(a, b)
	end
end

Error

>:~/Desktop/c/levenshtein.c$ rubex lev.rubex 
creating Makefile

>:~/Desktop/c/levenshtein.c$ cd lev/

>:~/Desktop/c/levenshtein.c/lev$ ruby extconf.rb // added all lib files
creating Makefile

>:~/Desktop/c/levenshtein.c/lev$ make
compiling lev.c
compiling __rubex__common_utils_.c
linking shared-object /home/arjun/Desktop/c/levenshtein.c/lev/lev.so

>:~/Desktop/c/levenshtein.c/lev$ ruby rb_lev.rb 
#<Lev:0x0055a47eb7f868>
ruby: symbol lookup error: /home/arjun/Desktop/c/levenshtein.c/lev/lev.so: undefined symbol: levenshtein

>:~/Desktop/c/levenshtein.c/lev$ ls
extconf.rb  levenshtein.c  lev.h  lev.so    rb_lev.rb                 __rubex__common_utils_.h
lev.c       levenshtein.h  lev.o  Makefile  __rubex__common_utils_.c  __rubex__common_utils_.o

Why am I getting this error?

Rubex - 0.1.2
Ruby 2.3.3

Better error reporting

Various methods for catching errors exist in compilers. Document best approaches for doing so in this issue and tackle the following problems in error reporting:

  • Print location of statement before outputting any statement.
  • Print location of line number where a compile error happened to STDOUT.
  • Research and setup various error classes that can arise out of a badly written program and how they should be reported.

Errors to handle:

  • Proper declaration of required functions in attached classes.
  • Error if attached classes are being used and rubex/ruby is not required using lib.

rubex typed memoryviews

cython uses typed memoryviews for direct access to underlying c objects that implement a buffer protocol. Add something similar so that we can declare memoryviews on numo::narray , narray, and other objects and have direct pointer views of these objects

Setup Travis, Gitter and other services.

General checklist of things to setup:

  • Travis CI for linux and macOS

  • Gitter

  • Rubygems version

  • Code Climate

  • Add mention of #sciruby IRC channel on freenode.

  • SimpleCov

Support for ? : operator

Rubex should support single line if-else with ? : operator and it should directly compile into C ? :.

Specify types of Ruby objects for faster method calls and C level optimizations

The C API provides several features for optimizing method calls and things like directly accessing the length of a string via macro RSTRING_LEN() instead of going through the overhead of a Ruby method lookup.

Therefore, if the user can specify the type of a Ruby object using data types str, array and hsh. These Ruby objects will then be of that type only and assigning them to another type of Ruby object should raise an error (via calls to TYPE() etc.)

Sample code:

def foo
  str a = "hello world"
  return a.size
end

Since the compiler knows that a is a String, it can directly call RSTRING_LEN() to generate code like so:

// header code....
static VALUE foo(...)
{
  VALUE a = rb_str_new2("hello world");
   return INT2FIX(RSTRING_LEN(a));
}
// footer code....

Various such examples exist for each data type, all of which should be implemented.

Error with struct example from tutorial

lib "rubex/ruby"; end

struct mp3info
  int id
  char* title
end

class Music attach mp3info
  def initialize(id, title)
    mp3info* mp3 = data$.mp3info

    mp3.id = id
    mp3.title = title
  end

  def id
    return data$.id
  end

  def title
    return data$.title
  end

  cfunc void deallocate
    xfree(data$.mp3info)
  end
end

Output when compiling:

/home/jacob/.rvm/gems/ruby-2.4.1/gems/rubex-0.0.1/lib/rubex/ast/expression.rb:810:in 
`analyse_command_type': Entry #<Rubex::AST::Expression::CommandCall:0x00000001592df0> does 
not exist in #<Rubex::AST::Expression::ElementRef:0x000000018ff470>. (RuntimeError)
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/expression.rb:749:in `analyse_statement'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/statement.rb:341:in `analyse_statement'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:171:in `block in analyse_statement'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:170:in `each'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:170:in `analyse_statement'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:253:in `analyse_statement'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:437:in `block in analyse_statement'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:433:in `each'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/top_statement.rb:433:in `analyse_statement'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/node.rb:147:in `block in analyse_statement'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/node.rb:146:in `each'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/node.rb:146:in `analyse_statement'
  from [..]/gems/rubex-0.0.1/lib/rubex/ast/node.rb:14:in `process_statements'
  from [..]/gems/rubex-0.0.1/lib/rubex/compiler.rb:50:in `generate_code'
  from [..]/gems/rubex-0.0.1/lib/rubex/compiler.rb:9:in `compile'
  from [..]/gems/rubex-0.0.1/bin/rubex:10:in `<top (required)>'
  from [..]/bin/rubex:23:in `load'
  from [..]/bin/rubex:23:in `<main>'

It compiles if I remove the #id and #title methods.

Command line option to overwrite dirs

I request some command line option that can overwrite existing directories.
For example,

rubex cat.rubex
vi cat.rubex # make some changes..
rubex -f cat.rubex # overwrite cat directory

cannnot call C functions

Hello.
I tried the sample code. #4 (comment)

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.

LoadError: Can't find oedipus_lex

How to correct this issue.

~/Desktop/ruby/rubex$ bundle install
Fetching gem metadata from https://rubygems.org/
Fetching version metadata from https://rubygems.org/
Resolving dependencies....
Using rake 11.3.0
Installing awesome_print 1.8.0
Installing benchmark-ips 2.7.2
Using byebug 9.1.0
Installing coderay 1.1.2
Using debug_inspector 0.0.3
Installing diff-lcs 1.3
Using method_source 0.8.2
Installing oedipus_lex 2.5.0      <--------- Rake issue
Using slop 3.6.0
Installing racc 1.4.14 with native extensions
Installing rspec-support 3.6.0
Using ruby-prof 0.16.2
Using bundler 1.12.5
Installing rake-compiler 1.0.4
Installing pretty_backtrace 0.1.3
Using pry 0.10.4
Installing rspec-core 3.6.0
Installing rspec-expectations 3.6.0
Installing rspec-mocks 3.6.0
Using rubex 0.1 from source at `.`
Installing pry-byebug 3.5.0
Installing rspec 3.6.0
Bundle complete! 9 Gemfile dependencies, 23 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.

~/Desktop/ruby/rubex$ rake install
rake aborted!
LoadError: Can't find oedipus_lex
/home/arjun/Desktop/ruby/rubex/Rakefile:6:in `<top (required)>'
(See full trace by running task with --trace)

~/Desktop/ruby/rubex$ rake install --trace
rake aborted!
LoadError: Can't find oedipus_lex
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rake-12.0.0/lib/rake/application.rb:652:in `rake_require'
/home/arjun/Desktop/ruby/rubex/Rakefile:6:in `<top (required)>'
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rake-12.0.0/lib/rake/rake_module.rb:28:in `load'
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rake-12.0.0/lib/rake/rake_module.rb:28:in `load_rakefile'
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rake-12.0.0/lib/rake/application.rb:687:in `raw_load_rakefile'
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rake-12.0.0/lib/rake/application.rb:96:in `block in load_rakefile'
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rake-12.0.0/lib/rake/application.rb:178:in `standard_exception_handling'
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rake-12.0.0/lib/rake/application.rb:95:in `load_rakefile'
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rake-12.0.0/lib/rake/application.rb:79:in `block in run'
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rake-12.0.0/lib/rake/application.rb:178:in `standard_exception_handling'
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rake-12.0.0/lib/rake/application.rb:77:in `run'
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/rake-12.0.0/exe/rake:27:in `<top (required)>'
/home/arjun/.rbenv/versions/2.2.3/bin/rake:23:in `load'
/home/arjun/.rbenv/versions/2.2.3/bin/rake:23:in `<main>'

You can see that gem is installed.

~/Desktop/ruby/rubex$ gem which oedipus_lex
/home/arjun/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/oedipus_lex-2.5.0/lib/oedipus_lex.rb

Handle unicode strings

Due to the nature of a C char data type, Rubex cannot support unicode strings out of the box. A possible approach to supporting unicode can involve defining a new data type and making sure that Ruby strings can implicitly convert into that type without user intervention (something that is supported for char* currently).

Allow multiple file Rubex scripts

Currently Rubex files can only exist inside one single file. This is quite detrimental to effective
management of code. Support multiple files.

A new function called require_rubex can be used for this purpose. This function will be a compiler construct similar to #include in C and will include that file into the compilation phase.

Attach class : make fails

Hello.
#5 has been resolved. Thank you.

Now I'd like to try an attached class.
After yesterday's update, rubex can compile attach class. That is great! However make fails. This is the error message of the c_struct_interface example.

I am sorry if the attach class is under development and the message is not a problem.

rubex rubex c_struct_interface.rubex
cd c_struct_interface
ruby extconf.rb
make

Error message

compiling c_struct_interface.c
c_struct_interface.c:63:9: error: passing '__rubex_t_Music_Music_data_struct'
      (aka 'struct Music_data_struct') to parameter of incompatible type
      'void *'
  xfree(__rubex_ptr_data[0]);
        ^~~~~~~~~~~~~~~~~~~
/path/2.4.1/include/ruby-2.4.0/ruby/defines.h:201:17: note: 
      passing argument to parameter here
void xfree(void*);
                ^
c_struct_interface.c:77:37: warning: incompatible pointer types initializing
      'size_t (*)(const void *)' (aka 'unsigned long (*)(const void *)') with an
      expression of type 'size_t (void *)' (aka 'unsigned long (void *)')
      [-Wincompatible-pointer-types]
  {0, __rubex_c_f_Music_deallocate, __rubex_c_f_Music_memcount,
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning and 1 error generated.
make: *** [c_struct_interface.o] Error 1

This is the generated C file.

/* C extension for c_struct_interface.
This file in generated by Rubex::Compiler. Do not change!
File generation time: 2017-08-28 09:22:59 +0900.*/

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

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

typedef struct mp3info
{
  char* __rubex_ptr_artist;
  char* __rubex_ptr_title;
  int __rubex_v_id;
} __rubex_t_Object_mp3info;


typedef struct Music_data_struct
{
  __rubex_t_Object_mp3info* __rubex_ptr_mp3info;
} __rubex_t_Music_Music_data_struct;



VALUE rb_cObject;
VALUE __rubex_rb_cls_Music;
static VALUE __rubex_rb_f_Music_initialize (int argc,VALUE* argv,VALUE __rubex_arg_self);
static VALUE __rubex_rb_f_Music_artist (int argc,VALUE* argv,VALUE __rubex_arg_self);
static VALUE __rubex_rb_f_Music_title (int argc,VALUE* argv,VALUE __rubex_arg_self);
static VALUE __rubex_rb_f_Music_id (int argc,VALUE* argv,VALUE __rubex_arg_self);
static void __rubex_c_f_Music_deallocate (void* __rubex_arg_raw_data);
static VALUE __rubex_c_f_Music_allocate (VALUE __rubex_arg_self);
static size_t __rubex_c_f_Music_memcount (void* __rubex_arg_raw_data);
static __rubex_t_Music_Music_data_struct* __rubex_c_f_Music_get_struct (VALUE __rubex_arg_obj);

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 void __rubex_c_f_Music_deallocate (void* __rubex_arg_raw_data)
{
  __rubex_t_Music_Music_data_struct* __rubex_ptr_data;
  __rubex_ptr_data = (__rubex_t_Music_Music_data_struct*)__rubex_arg_raw_data;

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:37 */
  xfree(__rubex_ptr_data[0].__rubex_ptr_mp3info->__rubex_ptr_artist);

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:38 */
  xfree(__rubex_ptr_data[0].__rubex_ptr_mp3info->__rubex_ptr_title);

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:39 */
  xfree(__rubex_ptr_data[0].__rubex_ptr_mp3info);

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:40 */
  xfree(__rubex_ptr_data[0]);

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:54 */
  xfree(__rubex_ptr_data);
}

static size_t __rubex_c_f_Music_memcount (void* __rubex_arg_raw_data)
{
  return sizeof(__rubex_arg_raw_data);

}

static const rb_data_type_t __rubex_attach_rb_cls_Music_data_type_t = {
  "Music",
  {0, __rubex_c_f_Music_deallocate, __rubex_c_f_Music_memcount,
  0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};

static __rubex_t_Music_Music_data_struct* __rubex_c_f_Music_get_struct (VALUE __rubex_arg_obj)
{
  __rubex_t_Music_Music_data_struct *data;
  
  TypedData_Get_Struct(__rubex_arg_obj, __rubex_t_Music_Music_data_struct, &__rubex_attach_rb_cls_Music_data_type_t, data);
  return data;
}

static VALUE __rubex_c_f_Music_allocate (VALUE __rubex_arg_self)
{
  __rubex_t_Music_Music_data_struct *data;
  
  data = (__rubex_t_Music_Music_data_struct*)xmalloc(sizeof(__rubex_t_Music_Music_data_struct));
  data->__rubex_ptr_mp3info = (__rubex_t_Object_mp3info*)xmalloc(sizeof(__rubex_t_Object_mp3info));
  return TypedData_Wrap_Struct(__rubex_arg_self,&__rubex_attach_rb_cls_Music_data_type_t, data);
}

static VALUE __rubex_rb_f_Music_initialize (int argc,VALUE* argv,VALUE __rubex_arg_self)
{
  VALUE __rubex_arg_artist;
  VALUE __rubex_arg_title;
  VALUE __rubex_arg_id;
  __rubex_t_Music_Music_data_struct* __rubex_ptr_data;
  __rubex_t_Object_mp3info* __rubex_ptr_mp3;
  int __rubex_v_a_size;
  int __rubex_v_t_size;
  if (argc < 3)
  {
    rb_raise(rb_eArgError, "Need 3 args, not %d", argc);
  }

  __rubex_arg_artist=argv[0];
  __rubex_arg_title=argv[1];
  __rubex_arg_id=argv[2];
  __rubex_ptr_data = __rubex_c_f_Music_get_struct(__rubex_arg_self);
  __rubex_ptr_mp3 = __rubex_ptr_data[0].__rubex_ptr_mp3info;
  __rubex_v_a_size = NUM2INT(rb_funcall(__rubex_arg_artist, rb_intern("size"), 0, NULL));
  __rubex_v_t_size = NUM2INT(rb_funcall(__rubex_arg_title, rb_intern("size"), 0, NULL));

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:23 */
  __rubex_ptr_mp3->__rubex_ptr_artist = (char*)xmalloc(( sizeof(char) * __rubex_v_a_size ));

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:24 */
  __rubex_ptr_mp3->__rubex_ptr_artist = StringValueCStr(__rubex_arg_artist);

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:26 */
  __rubex_ptr_mp3->__rubex_ptr_title = (char*)xmalloc(( sizeof(char) * __rubex_v_t_size ));

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:27 */
  __rubex_ptr_mp3->__rubex_ptr_title = StringValueCStr(__rubex_arg_title);

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:29 */
  __rubex_ptr_mp3->__rubex_v_id = NUM2INT(__rubex_arg_id);
}

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

  __rubex_ptr_data = __rubex_c_f_Music_get_struct(__rubex_arg_self);

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:44 */
  return rb_str_new2(__rubex_ptr_data[0].__rubex_ptr_mp3info->__rubex_ptr_artist);
}

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

  __rubex_ptr_data = __rubex_c_f_Music_get_struct(__rubex_arg_self);

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:48 */
  return rb_str_new2(__rubex_ptr_data[0].__rubex_ptr_mp3info->__rubex_ptr_title);
}

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

  __rubex_ptr_data = __rubex_c_f_Music_get_struct(__rubex_arg_self);

  /* Rubex file location: /path//rubex/examples/c_struct_interface/c_struct_interface.rubex:52 */
  return INT2NUM(__rubex_ptr_data[0].__rubex_ptr_mp3info->__rubex_v_id);
}


void Init_c_struct_interface ();
void Init_c_struct_interface ()
{
  VALUE __rubex_rb_cls_Music;

  __rubex_rb_cls_Music = rb_define_class("Music", rb_cObject);
  rb_define_alloc_func(__rubex_rb_cls_Music, __rubex_c_f_Music_allocate);

  rb_define_method(__rubex_rb_cls_Music ,"initialize", __rubex_rb_f_Music_initialize, -1);
  rb_define_method(__rubex_rb_cls_Music ,"artist", __rubex_rb_f_Music_artist, -1);
  rb_define_method(__rubex_rb_cls_Music ,"title", __rubex_rb_f_Music_title, -1);
  rb_define_method(__rubex_rb_cls_Music ,"id", __rubex_rb_f_Music_id, -1);
}

FR - Infer type without declaration

Hey
Just wanted to mention if it is feasible to modify the AST to infer variable type from the value it is set?

Currently, in C specific examples I was exploring, variables are declared.
Recently was looking into Mirah and their that is not required even if calling Java methods. It is more ruby like. It properly compiles to classes, without any penalty.

Optimize output code to minimize gcc warnings

Currently, gcc gives many compiler warnings for most non-trivial Rubex programs. Rubex code should be ideally optimized to minimize these warnings so as to produce optimal C code.

Allow inheritance of attached classes

If attached classes can be inherited, it will allow accessing two or more structs that the hierarchy of classes is attached to. The syntax should be like normal inheritance:

class B attach CSB

end

class A attach CSA < B
  # .... 
end

Allow inline C code.

A new directive called C_INLINE should allow the user to directly write C code inside a Rubex file which will be directly copied into the resulting C code as-is. The opening and closing of this section will be demarcated on similar lines as flex's %{ ... %} directive for demarcating code sections.

The code inside this section will not be parsed with the Rubex compiler. Syntax correctness is the programmer's responsibility.

Code sample:

def meth
  int a = 4
  C_INLINE<<
    float b = 5;
    printf("%d", b);
  <<C_INLINE
end

Regexp

How would one approach regular expressions in Rubex?

Like how would the RubexClass.execute_pattern be defined in Rubex?

def my_method(pattern)
  RubexClass.match(pattern)
  RubexClass.match?(pattern)
end

Check for return statement

Since Rubex does not return the last value of the method like in Ruby, it is important to check whether a return statement has been used in the program.

error in samples on windows

I tried the samples and I keep getting errors like this:

c_struct_interface.rb:1:in require_relative': no super class for Music' (ArgumentError)
from c_struct_interface.rb:1:in `

'

I get the same kind of error for all the samples

c:\Dominic\programming\repos\git\rubex\examples\c_struct_interface>ruby --version
ruby 2.4.1p111 (2017-03-22 revision 58053) [x64-mingw32]

Documentation

Most new features in Rubex are not well documented yet. Here's list:

  • CLI interface (being looked at by @shaunakpp).
  • Releasing the GIL.
  • Constant scoping.
  • Differences between Ruby and Rubex like using brackets for functions call arguments.
  • Multi-file Rubex programs. #48
  • Rubex APIs for C libraries. #19

Ability to create C APIs for gems

This will be similar to a C header file that will allow other gems using Rubex to easily access C API-level functions using Rubex.

The file should (probably) have extension .rubexh (for rubex header). And should store publicly available functions from the Rubex extension of a gem for use in other gems. This will make it easy for gems to make use of C level APIs of a particular gem.

Print not working correctly in irb

Using the Fibonnaci code in the README

lokeshh:~/workspace/rubex/fib $ irb
2.3.0 :001 > require_relative 'fib.so'
 => true 
2.3.0 :002 > Fibonnaci.new.compute(10)
 => false 
2.3.0 :003 > quit
1"\n"1"\n"2"\n"3"\n"5"\n"8"\n"13"\n"21"\n"34"\n"55"\n"89"\n"lokeshh:~/workspace/rubex/fib $ 

So, its printing the all the output when I quit irb.

Error if type of special function for attached class is not what it should be

For example, the deallocate function for attached classes must not take in arguments and must be of return type void. Similar constraints exist for the others as well. These must be adhered to.

  • deallocate function.
  • allocate function.
  • memcount function.
  • get_struct function.

Also, if the user fails to write a deallocate function the compiler must raise an error and state so.

JIT for Rubex?

Rubex complements Ruby. Is there a reason why it can't replace Ruby? Because wouldn't it be great if we can make it act like JIT (just in time) compile. This way we can retain advantage of interpreter and performance of compiler at same time.

Error when using rubex from command line

There is a runtime error if using Rubex from the command line after installation.

Here's the error:

โžœ  ~ git:(master) rubex no_gil.rubex 
/home/sameer/.rvm/gems/ruby-2.3.3/gems/rubex-0.1.1/lib/rubex/constants.rb:19:in `<module:Rubex>': uninitialized constant Rubex::DataType::Char (NameError)
	from /home/sameer/.rvm/gems/ruby-2.3.3/gems/rubex-0.1.1/lib/rubex/constants.rb:1:in `<top (required)>'
	from /home/sameer/.rvm/rubies/ruby-2.3.3/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	from /home/sameer/.rvm/rubies/ruby-2.3.3/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	from /home/sameer/.rvm/gems/ruby-2.3.3/gems/rubex-0.1.1/lib/rubex.rb:3:in `<top (required)>'
	from /home/sameer/.rvm/rubies/ruby-2.3.3/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	from /home/sameer/.rvm/rubies/ruby-2.3.3/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	from /home/sameer/.rvm/gems/ruby-2.3.3/gems/rubex-0.1.1/bin/rubex:3:in `<top (required)>'
	from /home/sameer/.rvm/gems/ruby-2.3.3/bin/rubex:23:in `load'
	from /home/sameer/.rvm/gems/ruby-2.3.3/bin/rubex:23:in `<main>'
	from /home/sameer/.rvm/gems/ruby-2.3.3/bin/ruby_executable_hooks:15:in `eval'
	from /home/sameer/.rvm/gems/ruby-2.3.3/bin/ruby_executable_hooks:15:in `<main>'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.