class Nydp::InterpretedFunction

Constants

NIL

Attributes

arg_names[RW]
body[RW]
context_builder[RW]

Public Class Methods

build(arg_list, body, bindings, ns) click to toggle source
# File lib/nydp/interpreted_function.rb, line 99
def self.build arg_list, body, bindings, ns
  my_params = { }
  index_parameters arg_list, my_params
  body = compile_body body, cons(my_params, bindings), [], ns
  reach = body.map { |b| b.lexical_reach(-1)  }.max

  ifn_klass     = reach >= 0 ? InterpretedFunctionWithClosure : InterpretedFunctionWithoutClosure
  ifn           = ifn_klass.new
  ifn.arg_names = arg_list
  ifn.body      = body

  ifn.extend Nydp::LexicalContextBuilder.select arg_list
  ifn
end
compile_body(body_forms, bindings, instructions, ns) click to toggle source
# File lib/nydp/interpreted_function.rb, line 114
def self.compile_body body_forms, bindings, instructions, ns
  instructions << Nydp::Compiler.compile(body_forms.car, bindings, ns)

  rest = body_forms.cdr
  if !rest
    return Pair.from_list(instructions)
  else
    # PopArg is necessary because each expression pushes an arg onto the arg stack.
    # we only need to keep the arg pushed by the last expression in a function
    # so we need the following line in order to remove unwanted args from the stack.
    # Each expression at some executes vm.push_arg(thing)
    # TODO find a more intelligent way to do this, eg change the meaning of vm or of push_arg in the expression vm.push_arg(thing)
    # instructions << PopArg
    compile_body rest, bindings, instructions, ns
  end
end
index_parameters(arg_list, hsh) click to toggle source
# File lib/nydp/interpreted_function.rb, line 131
def self.index_parameters arg_list, hsh
  if pair? arg_list
    index_parameters arg_list.car, hsh
    index_parameters arg_list.cdr, hsh
  elsif NIL != arg_list
    hsh[arg_list] = hsh.size
  end
end

Public Instance Methods

can_do?() click to toggle source
# File lib/nydp/interpreted_function.rb, line 46
def can_do?
  arg_names == nil
end
compile_do_expr_to_ruby(indent, srcs) click to toggle source
# File lib/nydp/interpreted_function.rb, line 50
def compile_do_expr_to_ruby indent, srcs
  body.
    map { |expr| expr.compile_to_ruby("  ", srcs, cando: true) }.
    to_a.
    join("\n").
    split(/\n/). # need join-split to separate out embedded newlines (TODO worry about newlines within literal strings?)
    map { |e| "#{indent}  #{e}" }.
    join("\n")
end
compile_to_ruby(indent, srcs, opts={}) click to toggle source
# File lib/nydp/interpreted_function.rb, line 60
def compile_to_ruby indent, srcs, opts={}
  an        = arg_names
  rubyargs  = []
  src_index = srcs.length

  srcs << to_s

  while (pair? an)
    rubyargs << "_arg_#{an.car.to_s._nydp_name_to_rb_name}=nil"
    an = an.cdr
  end

  if an
    rest_arg = "_arg_#{an.to_s._nydp_name_to_rb_name}"
    rubyargs << "*#{rest_arg}"
  end

  if rubyargs == []
    rubyargs = ""
  else
    rubyargs = "|#{rubyargs.join ","}|"
    # rubyargs = "(#{rubyargs.join ","})"
  end

  # code = "#{indent}(Nydp::Fn.new(@@src_#{src_index}) {#{rubyargs}\n"
  code = "#{indent}##> (fn #{arg_names._nydp_inspect} #{body.to_a.map(&:_nydp_inspect).join(" ").gsub(/\n/, '\n')})\n"
  code << "#{indent}(Nydp::Fn.new {#{rubyargs}\n"
  # code << "#{indent}(Proc.new {#{rubyargs}\n"
  # code = "(->#{rubyargs} {\n"
  if rest_arg
    code << "#{indent}  #{rest_arg} = #{rest_arg}._nydp_wrapper\n"
  end
  bodycode = body.map { |expr| expr.compile_to_ruby("  ", srcs, cando: true) }.to_a

  bodycode.push "#{bodycode.pop}._nydp_wrapper"
  code << bodycode.join("\n").split(/\n/).map { |e| "#{indent}  #{e}" }.join("\n")
  code << "\n#{indent}})"
end
inspect() click to toggle source
# File lib/nydp/interpreted_function.rb, line 141
def inspect   ; to_s ; end
lexical_reach(n) click to toggle source
# File lib/nydp/interpreted_function.rb, line 42
def lexical_reach n
  body.map { |b| b.lexical_reach(n - 1)  }.max
end
nydp_type() click to toggle source
# File lib/nydp/interpreted_function.rb, line 140
def nydp_type ; "fn" ; end
run_body(vm) click to toggle source
# File lib/nydp/interpreted_function.rb, line 146
def run_body vm
  res = nil
  self.body.each { |x| res = x.execute(vm) }
  res
end
to_s() click to toggle source
# File lib/nydp/interpreted_function.rb, line 142
def to_s
  "(fn #{arg_names._nydp_inspect} #{body.map { |b| b._nydp_inspect}.join('\n')})"
end