Skip to content

Yadriggy C Examples

chibash edited this page Jul 13, 2018 · 2 revisions

The source code of the following examples are under yadriggy/examples.

Free variable

When the DSL code refers to a variable out of the DSL code, the value of the variable is copied during the translation into C code. For example,

require 'yadriggy/c'

include Yadriggy::C::CType

def fib(n) ! Integer
  typedecl n: Integer
  if n > 1
    return fib(n - 1) + fib(n - 2)
  else
    return n
  end
end

n = 32
puts Yadriggy::C.run { return fib(n) }

The argument to fib is take from the variable n that exists outside of the block. n is passed to the compiled block by copying. It is not passed by reference. Thus, when a new value is assigned to n within the compiled block, it is not visible from the Ruby code. The variable n in the Ruby code keeps the old value.

Ahead of time compilation

A compiled method can be repeatedly invoked. To do so, first define a subclass of Yadriggy::C::Program:

require 'yadriggy/c'

class Fib < Yadriggy::C::Program
  def fib(n) ! Integer
    typedecl n: Integer
    if n > 1
      return fib(n - 1) + fib(n - 2)
    else
      return n
    end
  end
end

Then compile all the public methods in Fib:

m = Fib.compile

The compile method returns a module that contains a stub method invoking the compiled fib method. To invoke it, simply do:

puts m.fib(32)
puts m.fib(30)

It is also possible to generate a Ruby script to load the generated binary later. For example,

m = Fib.compile('FastFib')

This generates yadriggy_tmp/fastfib.rb. It loads the FastFib module with the compiled method fib.

require 'yadriggy_tmp/fastfib'
puts FastFib.fib(31)

Array

Passing an array to a compiled method is supported. The type of array is either arrayof(Int) or arrayof(Float). The length of array has to be also passed.

require 'yadriggy/c'

class ArrayToC < Yadriggy::C::Program
  def inc(a, b, n) ! Void
    typedecl a: arrayof(Int), b: arrayof(Int), n: Int
    for i in 0...n
      b[i] = a[i] + 1
    end
  end
end

To call inc, first, special array objects are created; they are instances of Yadriggy::C::CType::IntArray or FloatArray and they are accessible from both the Ruby code and the offloaded inc method. Regular Ruby arrays are not available in the method.

include Yadriggy::C::CType

a_in = IntArray.new(5)    # an array object that can be passed to C code.
a_in.set_values {|i| i }  # a_in[i] = i
a_in[0] = 7
a_out = IntArray.new(5)
ArrayToC.compile.inc(a_in, a_out, a_in.size)  # compile and run
puts a_out.to_a           # convert a_out into a Ruby array and print it.

In the compiled method written in the DSL, control structures such as for and if are available. Moreover, the times method is available on an integer. The inc method above can be rewritten as follows:

def inc(a, b, n) ! Void
  typedecl a: arrayof(Int), b: arrayof(Int), n: Int
  n.times do |i|
    b[i] = a[i] + 1
  end
end

The block parameter i is a loop counter. Note that a block argument is only available for times in the DSL. times in the DSL is not a method but a special syntax form provided for Ruby-like programming experience. Currently, IntArray or FloatArray does not accept times.

Clone this wiki locally