class Lisp::PrimIo

Public Class Methods

close_port_impl(args, env) click to toggle source
# File lib/rubylisp/prim_io.rb, line 56
def self.close_port_impl(args, env)
  p = args.car
  return Lisp::Debug.process_error("'close-port' requires a port argument.", env) unless p.port?
  p.value.close
  Lisp::String.with_value("OK")
end
eof_objectp_impl(args, env) click to toggle source
# File lib/rubylisp/prim_io.rb, line 128
def self.eof_objectp_impl(args, env)
  Boolean.with_value(args.car.eof_object?)
end
format_impl(args, env) click to toggle source
# File lib/rubylisp/prim_io.rb, line 133
def self.format_impl(args, env)
  destination = args.car
  return Lisp::Debug.process_error("'format' requires a port or boolean as it's first argument.", env) unless destination.port? || destination.boolean?

  control_string_obj = args.cadr
  return Lisp::Debug.process_error("'format' requires a string as it's second argument.", env) unless control_string_obj.string?
  control_string = control_string_obj.value

  arguments = args.cddr

  number_of_substitutions = control_string.count('~')
  parts = []
  start = 0
  i = 0
  numeric_arg = 0
  at_modifier = false
  
  while i < control_string.length
    numeric_arg = 0
    at_modifier = false

    if control_string[i] == '~'
      parts << control_string[start...i]
      i += 1
      start = i
      i += 1 while '0123456789'.include?(control_string[i])
      if i == start
        if control_string[i] == '#'
          numeric_arg = arguments.length
          i += 1
        elsif 'vV'.include?(control_string[i])
          if arguments.car.number?
            numeric_arg = arguments.car.value
            arguments = arguments.cdr
          else
            return Lisp::Debug.process_error("'format' encountered a size argument mismatch at index #{i}.", env)
          end
          i += 1
        else
          numeric_arg = 0
        end
      else
        numeric_arg = control_string[start...i].to_i
      end
      if control_string[i] == '@'
        at_modifier = true
        i += 1
      end

      case control_string[i]
      when 'A', 'a', 'S', 's'
        substitution = ('Aa'.include?(control_string[i])) ? arguments.car.print_string : arguments.car.to_s
        padding = substitution.length < numeric_arg ? (" " * (numeric_arg - substitution.length)) : ""
        parts << padding if at_modifier
        parts << substitution
        parts << padding unless at_modifier
        arguments = arguments.cdr
        start = i + 1
      when '%'
        parts << ((numeric_arg > 0) ? ("\n" * numeric_arg) : "\n")
        start = i + 1
      when '~'
        parts << ((numeric_arg > 0) ? ("~" * numeric_arg) : "~")
        start = i + 1
      when "\n"
        while control_string[i] =~ /[[:space:]]/
          i += 1
        end
        parts << "\n" if at_modifier
        start = i
        i -= 1
      else
        return Lisp::Debug.process_error("'format' encountered an unsupported substitution at index #{i}.", env)
      end
    end
    i += 1
  end
  parts << control_string[start..i] if start < control_string.length
  return Lisp::Debug.process_error("'format' found a mismatch in the number of substitutions and arguments.", env) if i < control_string.length || !arguments.nil?

  combined_string = parts.join

  if destination.port?
    destination.value.write(combined_string)
    Lisp::String.with_value("OK")
  elsif destination.value
    self.output_to_stdout(combined_string)
    Lisp::String.with_value("OK")
  else
    return Lisp::String.with_value(combined_string)
  end

end
list_directory_impl(args, env) click to toggle source
# File lib/rubylisp/prim_io.rb, line 119
def self.list_directory_impl(args, env)
  return Lisp::Debug.process_error("'list-directory' requires a string as it's first argument.", env) unless args.car.string?
  dir = args.car.value
  fpart = (args.length == 2) ? args.cadr.value : "*"
  filenames = Dir.glob(File.join(dir, fpart))
  Lisp::ConsCell.array_to_list(filenames.map {|f| Lisp::String.with_value(f)})
end
load_impl(args, env) click to toggle source
# File lib/rubylisp/prim_io.rb, line 30
def self.load_impl(args, env)
  fname = args.car
  return Lisp::Debug.process_error("'load' requires a string argument.", env) unless fname.string?
  filename = fname.value.end_with?(".lsp") ? fname.value : "#{fname.value}.lsp"
  Lisp::Parser.new.process_file(filename)
  Lisp::String.with_value("OK")
end
newline_impl(args, env) click to toggle source
# File lib/rubylisp/prim_io.rb, line 80
def self.newline_impl(args, env)
  if args.length == 1
    p = args.car
    return Lisp::Debug.process_error("'newline' requires a port as it's argument.", env) unless p.port?
    port = p.value
    port.write("\n")
  else
    self.output_to_stdout("\n")
  end
  Lisp::String.with_value("OK")
end
open_input_file_impl(args, env) click to toggle source
# File lib/rubylisp/prim_io.rb, line 39
def self.open_input_file_impl(args, env)
  fname = args.car
  return Lisp::Debug.process_error("'open-input-file' requires a string argument.", env) unless fname.string?
  f = File.open(fname.value, "r")
  f ? Lisp::Port.with_value(f) : nil
end
open_output_file_impl(args, env) click to toggle source
# File lib/rubylisp/prim_io.rb, line 47
def self.open_output_file_impl(args, env)
  fname = args.car
  return Lisp::Debug.process_error("'load' requires a string argument.", env) unless fname.string?
  mode = (args.length == 2 && args.cadr.true?) ? "a" : "w"
  f = File.open(fname.value, mode)
  f ? Lisp::Port.with_value(f) : nil
end
output_to_stdout(to_output) click to toggle source
# File lib/rubylisp/prim_io.rb, line 25
def self.output_to_stdout(to_output)
  $stdout.write(to_output)
end
read_impl(args, env) click to toggle source
# File lib/rubylisp/prim_io.rb, line 106
def self.read_impl(args, env)
  if args.length == 1
    p = args.car
    return Lisp::Debug.process_error("'read' requires a port as it's argument.", env) unless p.port?
    port = p.value
  else
    port = $stdin
  end

  Lisp::Parser.new.parse_object_from_file(port)
end
register() click to toggle source
# File lib/rubylisp/prim_io.rb, line 5
 def self.register
   Primitive.register("load", "1")         {|args, env| Lisp::PrimIo::load_impl(args, env) }
   Primitive.register("open-input-file", "1") {|args, env| Lisp::PrimIo::open_input_file_impl(args, env) }
   Primitive.register("open-output-file", "1|2") {|args, env| Lisp::PrimIo::open_output_file_impl(args, env) }
   Primitive.register("close-port", "1") {|args, env| Lisp::PrimIo::close_port_impl(args, env) }
   Primitive.register("write-string", "1|2") {|args, env| Lisp::PrimIo::write_string_impl(args, env) }
   Primitive.register("newline", "0|1") {|args, env| Lisp::PrimIo::newline_impl(args, env) }
   Primitive.register("write", "1|2") {|args, env| Lisp::PrimIo::write_impl(args, env) }
   Primitive.register("read", "0|1") {|args, env| Lisp::PrimIo::read_impl(args, env) }
   Primitive.register("list-directory", "1|2") {|args, env| Lisp::PrimIo::list_directory_impl(args, env) }
   Primitive.register("eof-object?", "1") {|args, env| Lisp::PrimIo::eof_objectp_impl(args, env) }
   Primitive.register("format", ">=2") {|args, env| Lisp::PrimIo::format_impl(args, env) }
   # Primitive.register("load-library", "1") {|args, env| Lisp::PrimIo::load_library_impl(args, env) }
   # Primitive.register("load-project", "1") {|args, env| Lisp::PrimIo::load_project_impl(args, env) }
   Primitive.register("trace", "*")        {|args, env| puts "Trace: #{(args.to_a.map {|a| a.value.to_s}).join(' ')}"; nil} 
   Primitive.register("error", "*")        {|args, env| App.alert((args.to_a.map {|a| a.value.to_s}).join(' '))}
   Primitive.register("alert", "*")        {|args, env| App.alert((args.to_a.map {|a| a.value.to_s}).join(' '))}
end
write_impl(args, env) click to toggle source
# File lib/rubylisp/prim_io.rb, line 93
def self.write_impl(args, env)
  if args.length == 2
    p = args.cadr
    return Lisp::Debug.process_error("'write' requires a port as it's second argument.", env) unless p.port?
    port = p.value
    port.write(args.car.print_string)
  else
    self.output_to_stdout(args.car.print_string)
  end
  Lisp::String.with_value("OK")
end
write_string_impl(args, env) click to toggle source
# File lib/rubylisp/prim_io.rb, line 64
def self.write_string_impl(args, env)
  s = args.car
  return Lisp::Debug.process_error("'write-string' requires a string first argument.", env) unless s.string?

  if args.length == 2
    p = args.cadr
    return Lisp::Debug.process_error("'write-string' requires a port as it's second argument.", env) unless p.port?
    port = p.value
    port.write(s.value)
  else
    self.output_to_stdout(s.value)
  end
  Lisp::String.with_value("OK")
end