Class: Lisp::FfiSend

Inherits:
Atom show all
Defined in:
lib/rubylisp/ffi_send.rb

Direct Known Subclasses

FfiStatic

Instance Attribute Summary

Attributes inherited from Atom

#value

Instance Method Summary collapse

Methods inherited from Atom

#all?, #car, #cdr, #character?, #class?, #copy, #doc, #environment?, #eof_object?, #eq?, #equal?, #eqv?, #evaluate, #false?, #frame?, #function?, #length, #lisp_object?, #list?, #macro?, #negative?, #number?, #object?, #pair?, #port?, #positive?, #print_string, #quoted, #set!, #set_location, #special?, #string?, #symbol?, #true?, #vector?, #zero?

Constructor Details

#initialize(name) ⇒ FfiSend

Returns a new instance of FfiSend.



5
6
7
# File 'lib/rubylisp/ffi_send.rb', line 5

def initialize(name)
  @value = name.to_sym
end

Instance Method Details

#apply_to(args, env) ⇒ Object



9
10
11
# File 'lib/rubylisp/ffi_send.rb', line 9

def apply_to(args, env)
  apply_to_without_evaluating(Lisp::ConsCell.array_to_list(args.to_a.map {|a| a.evaluate(env)}), env)
end

#apply_to_without_evaluating(args, env) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/rubylisp/ffi_send.rb', line 55

def apply_to_without_evaluating(args, env)
  target = args.car
  return Lisp::Debug.process_error("Send target of '#{@value}' evaluated to nil.", env) if target.nil?
  return Lisp::Debug.process_error("Target of an FFI send of '#{@value}' must be a wrapped ObjC object, was #{target}", env) unless target.object?

  # puts "Sending #{@value} to #{target.to_s} with raw args #{args}"

  arguments = args.cdr.nil? ? [] : args.cdr.to_a.map {|a| process_arg(a, env)}      
  result = nil
  
  begin
    result = if arguments[-1].instance_of?(Proc)
               target.value.send(@value, *(arguments[0..-2]), &arguments[-1])
             else
               # puts "Sending #{@value} to #{target} with processed args #{arguments}"
               target.value.send(@value, *arguments)
             end
  rescue Exception => e
    return Lisp::Debug.process_error("Exception sending #{@value} - #{e.name}", env)
  end

  convert_value(result)
end

#convert_value(value) ⇒ Object

convert a rubymotion arg to a lisp arg



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/rubylisp/ffi_send.rb', line 14

def convert_value(value)
  #puts "convert_value(#{value.to_s})\n"
  case value.class.name
  when "Fixnum", "Float"
    Lisp::Number.with_value(value)
  when "TrueClass"
    Lisp::Boolean.TRUE
  when "FalseClass"
    Lisp::Boolean.FALSE
  when "String"
    Lisp::String.with_value(value)
  when "Symbol"
    Lisp::Symbol.named(value)
  when "Array"
    Lisp::ConsCell.array_to_list(value.map {|a| convert_value(a)})
  else
    Lisp::NativeObject.with_value(value)
  end
end

#primitive?Boolean

Returns:



83
84
85
# File 'lib/rubylisp/ffi_send.rb', line 83

def primitive?
  true
end

#process_arg(a, env) ⇒ Object

convert a lisp arg to a rubymotion arg



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/rubylisp/ffi_send.rb', line 36

def process_arg(a, env)
  #puts "process_arg(#{a.to_s})"
  if a.function?
    #puts "function arg"
    proc do #|*args|
      #puts "Proc argument invoked"
      # arg_list = args.empty? ? nil : Lisp::ConsCell.array_to_list(args.collect {|arg| convert_value(arg) })
      # puts "Applying #{@a.to_s} to #{arg_list}"
     
      a.apply_to(nil, env)
    end
  elsif a.list?
    a.to_a.map {|i| process_arg(i, env)}
  else
    a.value
  end
end

#to_sObject



79
80
81
# File 'lib/rubylisp/ffi_send.rb', line 79

def to_s
  ".#{@value}"
end

#typeObject



87
88
89
# File 'lib/rubylisp/ffi_send.rb', line 87

def type
  :primitive
end