class Lrb

Constants

KEYWORD

Attributes

debug[RW]
parser[RW]

Public Class Methods

new() click to toggle source
# File lib/lrb.rb, line 9
def initialize
  @_dbg = false
  @_indent = 0
  @_stack = Array.new
  @_parser = Bracer.new
  @_parser.ruby_keyword_literals = true
  readline_autocompletion
end

Public Instance Methods

eval_file(path) click to toggle source
# File lib/lrb.rb, line 39
def eval_file path
  source = File.read path
  eval_source source, mode = :compile
end
eval_list(list) click to toggle source
# File lib/lrb.rb, line 69
def eval_list list
  eval list_to_ruby(list)
end
eval_source(source, mode = :repl) click to toggle source
# File lib/lrb.rb, line 44
def eval_source source, mode = :repl
  begin
    e = to_ruby source
    evaluated = eval e
  rescue Exception => ex
    if @_dbg
      puts ex.backtrace.join("\n").red
      binding.pry 
    end
    puts ex.message.red
  end
  if @_dbg
    if mode == :compile
      puts "[LRB]:".light_yellow
      puts source.light_yellow
    end  
    puts e.light_green
    if mode == :compile
      puts "\n[evaluated]:".light_yellow
      puts "#{evaluated}".blue
    end
  end
  evaluated
end
list_to_ruby(ast) click to toggle source
# File lib/lrb.rb, line 73
def list_to_ruby ast
  ast = ast.map do |sexp|
    result = transform sexp
    puts result if @_dbg
    result
  end
  ast.join "\n\n"
end
parse(source) click to toggle source
# File lib/lrb.rb, line 18
def parse source
  @_parser.parse_string source 
end
repl() click to toggle source
# File lib/lrb.rb, line 22
def repl
  begin
    while line = readline_with_hist_management
      @_stack << line
      if balanced?
        e = eval_source @_stack.join " "
        puts e.to_s.blue
        @_stack.clear
        @_indent = 0
      end
    end
  rescue Interrupt => e
    puts "\nGoodbye !".light_yellow
    exit
  end
end
to_ruby(source) click to toggle source
# File lib/lrb.rb, line 82
def to_ruby source
  ast = parse source 
  puts "parsed: #{ast}".green if @_dbg
  list_to_ruby ast
end
transform(sexp) click to toggle source
# File lib/lrb.rb, line 88
def transform sexp
  puts line if @_dbg
  if sexp.class == Array
    fun = sexp.first
    args = wrap_string sexp.drop(1)
    result = ""
    if @_dbg
      puts "function: #{fun}".yellow
      puts "args: #{args}".yellow
      puts line 
    end
    
    if KEYWORD.include? fun
      result = self.instance_exec *args, &KEYWORD[fun]
    elsif class_method? fun
      puts "[ERROR] dot operator only take 1 arg.".red if args.length > 1
      result = class_method_append fun, args.first
    else
      # function call
      result = compose_function fun, args
    end

    if @_dbg
      puts result.light_green
      puts line
    end
    indent + result
  else
    puts "#{sexp}".yellow if @_dbg
    sexp
  end
end

Private Instance Methods

balanced?() click to toggle source
# File lib/lrb.rb, line 122
def balanced?
  source = @_stack.join " "
  @left = source.count "["
  @right = source.count "]"
  @_indent = @left - @right if (@left - @right) > 0
  @left == @right
end
class_method?(function) click to toggle source
# File lib/lrb.rb, line 148
def class_method? function
  function[0] == "."
end
class_method_append(fun, args) click to toggle source
# File lib/lrb.rb, line 152
def class_method_append fun, args
  "(#{transform args})#{fun}"
end
compose_function(fun, args) click to toggle source
# File lib/lrb.rb, line 194
def compose_function fun, args
  args = transform_exp args
  "#{fun} #{args.join ', '}"
end
conditional_block(keyword, cond, true_block, false_block) click to toggle source
# File lib/lrb.rb, line 223
def conditional_block keyword, cond, true_block, false_block
  op = cond.first
  cond = cond.drop(1).join " #{op} "
  true_block = transform true_block
  false_block = transform false_block
  ["#{keyword} #{cond}",
    "    #{true_block}",
    "  else",
    "    #{false_block}",
    "  end"
  ].join("\n")
end
indent() click to toggle source
# File lib/lrb.rb, line 199
def indent
  "  " * @_indent
end
line() click to toggle source
# File lib/lrb.rb, line 203
def line
  "-" * 80
end
operator(op, args) click to toggle source
# File lib/lrb.rb, line 207
def operator op, args
  args = args.map do |arg|
    transform arg
  end
  e = args.join " #{op.to_s} "
  "(#{e})"
end
readline_autocompletion() click to toggle source
# File lib/lrb.rb, line 130
def readline_autocompletion
  @dict = KEYWORD.keys.sort

  comp = proc { |s| @dict.grep( /^#{Regexp.escape(s)}/ ) }

  Readline.completion_append_character = " "
  Readline.completion_proc = comp
end
readline_with_hist_management() click to toggle source
# File lib/lrb.rb, line 139
def readline_with_hist_management
  line = Readline.readline('> ' + indent, true)
  return nil if line.nil?
  if line =~ /^\s*$/ or Readline::HISTORY.to_a[-2] == line
    Readline::HISTORY.pop
  end
  line
end
replace_parenthese(arg) click to toggle source
# File lib/lrb.rb, line 166
def replace_parenthese arg
  if arg.kind_of? Array
    arg = arg.map{ |element|
      replace_parenthese element
    }
    arg
  else
    if arg.to_s["("] && arg.to_s[")"]
      old = arg
      arg = arg.to_s.gsub(/\((.*)\)/, '[\1]').to_sym
      puts "arg: #{old} => #{arg}".light_yellow if @_dbg
      arg
    else
      arg
    end
  end
end
single_block(keyword, block) click to toggle source
# File lib/lrb.rb, line 236
def single_block keyword, block
  block = transform_body block
  ["#{keyword}",
    "  #{block}",
    "end"
  ].join("\n")
end
transform_body(block) click to toggle source
# File lib/lrb.rb, line 215
def transform_body block
  if block.first.class == Array
    block.map{|body| transform body}.join "\n  "
  else
    transform block
  end
end
transform_exp(exps) click to toggle source
# File lib/lrb.rb, line 184
def transform_exp exps
  exps.map do |arg|
    unless arg.class == String
      transform arg 
    else
      arg
    end
  end
end
wrap_string(args) click to toggle source
# File lib/lrb.rb, line 156
def wrap_string args
  args.map do |arg| 
    if arg.class == String 
      "\"#{arg}\""
    else
      replace_parenthese arg
    end
  end
end