Class: Haskell

Inherits:
Object
  • Object
show all
Defined in:
lib/rubiskell.rb

Defined Under Namespace

Classes: Signeture

Constant Summary collapse

TYPE_TABLE =
[
  ["Int", Integer],
  ["String", String],
]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(code, option = {}) ⇒ Haskell

Returns a new instance of Haskell.



13
14
15
16
17
18
# File 'lib/rubiskell.rb', line 13

def initialize(code, option={})
  @interpreter = option[:interpreter] || "runghc"
  @signetures = parse_signetures(code)
  @code = code
  @k = 0
end

Class Method Details

.load(fname) ⇒ Object



4
5
6
# File 'lib/rubiskell.rb', line 4

def self.load(fname)
  new(File.read(fname))
end

.tuple_form(args) ⇒ Object



8
9
10
11
# File 'lib/rubiskell.rb', line 8

def self.tuple_form(args)
  a = args.join(",") 
  return args.size == 1 ? a : "(#{a})"
end

Instance Method Details

#call(sig, *args) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rubiskell.rb', line 20

def call(sig, *args)
  if String === sig 
    sig = @signetures.find{|sig| sig.name == sig}
    raise ArgumentError, "unknown method" if sig.nil?
  end

  src = make_src(@code, sig)
  path = make_tempfile(src)
  cmd = make_cmd(path, args)
  convert_result(`#{cmd}`.chomp, sig.ret)
end

#convert_result(result, type) ⇒ Object



43
44
45
46
47
48
49
50
51
52
# File 'lib/rubiskell.rb', line 43

def convert_result(result, type)
  case type.to_s
  when "Integer"
    result.to_i
  when "String"
    result[1..-2] #cut \"
  else
    raise "unknown type: #{type}"
  end
end

#make_cmd(path, args) ⇒ Object



37
38
39
40
41
# File 'lib/rubiskell.rb', line 37

def make_cmd(path, args)
  arg_list = Haskell.tuple_form(args.map{|x| x.inspect})
  arg_list.gsub!(/"/, '\\"')
  %Q<#{@interpreter} "#{path}" "#{arg_list}">
end

#make_src(code, sig) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/rubiskell.rb', line 94

def make_src(code, sig)
  src = "import System\n"
  src << code
  src << "\n"
  src << "main = do args <- getArgs\n"
  src << "          print $ apply #{sig.name} $ _read $ head args\n"
  src << "  where\n"
  src << "    _read :: String -> #{sig.tuple_form}\n"
  src << "    _read = read\n"
  src << "    apply f #{sig.tuple_vars} = f #{sig.list_vars}\n"
end

#make_tempfile(src) ⇒ Object



106
107
108
109
110
111
112
113
# File 'lib/rubiskell.rb', line 106

def make_tempfile(src)
  while File.exist?(fname = "rubiskell.#{Process.pid}.#{@k}.hs")
    @k += 1
  end
  open(fname, "w"){|f| f.write src }
  at_exit{ File.unlink(fname) }
  fname
end

#parse_signetures(code) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/rubiskell.rb', line 82

def parse_signetures(code)
  code.scan(/^(\w+)\s*::\s*(\w+(\s*->\s*\w+)*)\s*$/).map do |sig|
    name = $1.strip
    args = $2.split(/->/).map{|x| 
      pair = TYPE_TABLE.assoc(x.strip)
      pair ? pair[1] : (raise ArgumentError, "unknown Haskell type #{x.strip}")
    }
    ret = args.pop
    Signeture.new(name, args, ret)
  end
end

#run(*args) ⇒ Object Also known as: []



32
33
34
# File 'lib/rubiskell.rb', line 32

def run(*args)
  call(@signetures[0], *args)
end