Temporary tag for this failure. Updated CI spec coming.
[rbx.git] / kernel / core / kernel.rb
blob84b43e3e2b5504cc6e9d431f38c871700769ccc1
1 # depends on: module.rb kernel.rb
3 module Type
5   ##
6   # Returns an object of given class. If given object already is one, it is
7   # returned. Otherwise tries obj.meth and returns the result if it is of the
8   # right kind. TypeErrors are raised if the conversion method fails or the
9   # conversion result is wrong.
10   #
11   # Uses Type.obj_kind_of to bypass type check overrides.
13   def self.coerce_to(obj, cls, meth)
14     return obj if self.obj_kind_of?(obj, cls)
16     begin
17       ret = obj.__send__(meth)
18     rescue Exception => e
19       raise TypeError, "Coercion error: #{obj.inspect}.#{meth} => #{cls} failed:\n" \
20                        "(#{e.message})"
21     end
23     return ret if self.obj_kind_of?(ret, cls)
25     raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})"
26   end
27 end
29 module Kernel
31   def Float(obj)
32     raise TypeError, "can't convert nil into Float" if obj.nil?
34     if obj.is_a?(String)
35       if obj !~ /^(\+|\-)?\d+$/ && obj !~ /^(\+|\-)?(\d_?)*\.(\d_?)+$/ && obj !~ /^[-+]?\d*\.?\d*e[-+]\d*\.?\d*/
36         raise ArgumentError, "invalid value for Float(): #{obj.inspect}"
37       end
38     end
40     Type.coerce_to(obj, Float, :to_f)
41   end
42   module_function :Float
44   def Integer(obj)
45     return obj.to_inum(0, true) if obj.is_a?(String)
46     method = obj.respond_to?(:to_int) ? :to_int : :to_i
47     Type.coerce_to(obj, Integer, method)
48   end
49   module_function :Integer
51   def Array(obj)
52     if obj.respond_to?(:to_ary)
53       Type.coerce_to(obj, Array, :to_ary)
54     elsif obj.respond_to?(:to_a)
55       Type.coerce_to(obj, Array, :to_a)
56     else
57       [obj]
58     end
59   end
60   module_function :Array
62   def String(obj)
63     Type.coerce_to(obj, String, :to_s)
64   end
65   module_function :String
67   ##
68   # MRI uses a macro named StringValue which has essentially the same
69   # semantics as obj.coerce_to(String, :to_str), but rather than using that
70   # long construction everywhere, we define a private method similar to
71   # String().
72   #
73   # Another possibility would be to change String() as follows:
74   #
75   #   String(obj, sym=:to_s)
76   #
77   # and use String(obj, :to_str) instead of StringValue(obj)
79   def StringValue(obj)
80     Type.coerce_to(obj, String, :to_str)
81   end
82   private :StringValue
84   ##
85   # MRI uses a macro named NUM2DBL which has essentially the same semantics as
86   # Float(), with the difference that it raises a TypeError and not a
87   # ArgumentError. It is only used in a few places (in MRI and Rubinius).
88   #--
89   # If we can, we should probably get rid of this.
91   def FloatValue(obj)
92     begin
93       Float(obj)
94     rescue
95       raise TypeError, 'no implicit conversion to float'
96     end
97   end
98   private :FloatValue
100   ##
101   #--
102   # HACK :: added due to broken constant lookup rules
103   #++
105   def raise(exc=Undefined, msg=nil, trace=nil)
106     skip = false
107     if exc.equal? Undefined
108       exc = $!
109       if exc
110         skip = true
111       else
112         exc = RuntimeError.new("No current exception")
113       end
114     elsif exc.respond_to? :exception
115       exc = exc.exception msg
116       raise ::TypeError, 'exception class/object expected' unless exc.kind_of?(::Exception)
117       exc.set_backtrace trace if trace
118     elsif exc.kind_of? String or !exc
119       exc = ::RuntimeError.exception exc
120     else
121       raise ::TypeError, 'exception class/object expected'
122     end
124     if $DEBUG and $VERBOSE != nil
125       sender = MethodContext.current.sender
126       STDERR.puts "Exception: `#{exc.class}' #{sender.location} - #{exc.message}"
127     end
129     unless skip
130       exc.set_backtrace MethodContext.current.sender unless exc.context
131     end
132     Rubinius.asm(exc) { |e| e.bytecode(self); raise_exc }
133   end
134   module_function :raise
136   alias_method :fail, :raise
137   module_function :fail
139   def warn(warning)
140     if $VERBOSE
141       $stderr.write MethodContext.current.sender.location
142       $stderr.write ": warning: "
143       $stderr.write warning
144       $stderr.write "\n"
145     end
146     nil
147   end
148   module_function :warn
150   def exit(code=0)
151     code = 0 if code.equal? true
152     raise SystemExit.new(code)
153   end
154   module_function :exit
156   def exit!(code=0)
157     Process.exit(code)
158   end
159   module_function :exit!
161   def abort(msg=nil)
162     Process.abort(msg)
163   end
164   module_function :abort
166   def printf(target, *args)
167     if target.kind_of? IO
168       target.printf(*args)
169     elsif target.kind_of? String
170       $stdout << Sprintf.new(target, *args).parse
171     else
172       raise TypeError, "The first arg to printf should be an IO or a String"
173     end
174     nil
175   end
176   module_function :printf
178   def sprintf(str, *args)
179     Sprintf.new(str, *args).parse
180   end
181   alias_method :format, :sprintf
182   module_function :sprintf
183   module_function :format
184   module_function :abort
186   def puts(*a)
187     $stdout.puts(*a)
188     return nil
189   end
190   module_function :puts
192   # For each object given, prints obj.inspect followed by the
193   # system record separator to standard output (thus, separator
194   # cannot be overridden.) Prints nothing if no objects given.
195   def p(*a)
196     return nil if a.empty?
197     a.each { |obj| $stdout.puts obj.inspect }
198     nil
199   end
200   module_function :p
202   def print(*args)
203     args.each do |obj|
204       $stdout.write obj.to_s
205     end
206     nil
207   end
208   module_function :print
210   def open(path, *rest, &block)
211     path = StringValue(path)
213     if path.kind_of? String and path.prefix? '|'
214       return IO.popen(path[1..-1], *rest, &block)
215     end
217     File.open(path, *rest, &block)
218   end
219   module_function :open
221   #--
222   # NOTE: This isn't quite MRI compatible.
223   # We don't seed the RNG by default with a combination of time, pid and
224   # sequence number
225   #++
227   def srand(seed)
228     cur = Kernel.current_srand
229     Platform::POSIX.srand(seed.to_i)
230     Kernel.current_srand = seed.to_i
231     return cur
232   end
233   module_function :srand
235   @current_seed = 0
236   def self.current_srand
237     @current_seed
238   end
240   def self.current_srand=(val)
241     @current_seed = val
242   end
244   def rand(max=nil)
245     max = max.to_i.abs
246     x = Platform::POSIX.rand
247     # scale result of rand to a domain between 0 and max
248     if max.zero?
249       x / 0x7fffffff.to_f
250     else
251       if max < 0x7fffffff
252         x / (0x7fffffff / max)
253       else
254          x * (max / 0x7fffffff)
255       end
256     end
257   end
258   module_function :rand
260   def endian?(order)
261     order == Rubinius::ENDIAN
262   end
263   module_function :endian?
265   def block_given?
266     if MethodContext.current.sender.block
267       return true
268     end
270     return false
271   end
272   module_function :block_given?
274   alias_method :iterator?, :block_given?
275   module_function :iterator?
277   def lambda
278     block = block_given?
279     raise ArgumentError, "block required" if block.nil?
281     block.disable_long_return!
283     return Proc::Function.from_environment(block)
284   end
285   alias_method :proc, :lambda
286   module_function :lambda
287   module_function :proc
289   def caller(start=1)
290     return MethodContext.current.sender.calling_hierarchy(start)
291   end
292   module_function :caller
294   def global_variables
295     Globals.variables.map { |i| i.to_s }
296   end
297   module_function :global_variables
299   def loop
300     raise LocalJumpError, "no block given" unless block_given?
302     while true
303       yield
304     end
305   end
306   module_function :loop
308   ##
309   # Sleeps the current thread for +duration+ seconds.
311   def sleep(duration = Undefined)
312     start = Time.now
313     chan = Channel.new
314     # No duration means we sleep forever. By not registering anything with
315     # Scheduler, the receive call will effectively block until someone
316     # explicitely wakes this thread.
317     unless duration.equal?(Undefined)
318       raise TypeError, 'time interval must be a numeric value' unless duration.kind_of?(Numeric)
319       duration = Time.at duration
320       Scheduler.send_in_seconds(chan, duration.to_f, nil)
321     end
322     chan.receive
323     return (Time.now - start).round
324   end
325   module_function :sleep
327   def at_exit(&block)
328     Rubinius::AtExit.unshift(block)
329   end
330   module_function :at_exit
332   def test(cmd, file1, file2=nil)
333     case cmd
334     when ?d
335       File.directory? file1
336     when ?e
337       File.exist? file1
338     when ?f
339       File.file? file1
340     else
341       false
342     end
343   end
344   module_function :test
346   def trap(sig, prc=nil, &block)
347     Signal.trap(sig, prc, &block)
348   end
349   module_function :trap
351   def initialize_copy(other)
352     return self
353   end
354   private :initialize_copy
356   alias_method :__id__, :object_id
358   alias_method :==,   :equal?
360   # The "sorta" operator, also known as the case equality operator.
361   # Generally while #eql? and #== are stricter, #=== is often used
362   # to denote an acceptable match or inclusion. It returns true if
363   # the match is considered to be valid and false otherwise. It has
364   # one special purpose: it is the operator used by the case expression.
365   # So in this expression:
366   #
367   #   case obj
368   #   when /Foo/
369   #     ...
370   #   when "Hi"
371   #     ...
372   #   end
373   #
374   # What really happens is that `/Foo/ === obj` is attempted and so
375   # on down until a match is found or the expression ends. The use
376   # by Regexp is very illustrative: while obj may satisfy the pattern,
377   # it may not be the only option.
378   #
379   # The default #=== operator checks if the other object is #equal?
380   # to this one (i.e., is the same object) or if #== returns true.
381   # If neither is true, false is returned instead. Many classes opt
382   # to override this behaviour to take advantage of its use in a
383   # case expression and to implement more relaxed matching semantics.
384   # Notably, the above Regexp as well as String, Module and many others.
385   def ===(other)
386     equal?(other) || self == other
387   end
389   ##
390   # Regexp matching fails by default but may be overridden by subclasses,
391   # notably Regexp and String.
393   def =~(other)
394     false
395   end
397   def class_variable_get(sym)
398     self.class.class_variable_get sym
399   end
401   def class_variable_set(sym, value)
402     self.class.class_variable_set sym, value
403   end
405   def class_variables(symbols = false)
406     self.class.class_variables(symbols)
407   end
409   ##
410   # \_\_const_set__ is emitted by the compiler for const assignment
411   # in userland.
412   #
413   # This is the catch-all version for unwanted values
415   def __const_set__(name, obj)
416     raise TypeError, "#{self} is not a class/module"
417   end
419   ##
420   # Activates the singleton Debugger instance, and sets a breakpoint
421   # immediately after the call site to this method.
422   #--
423   # TODO: Have method take an options hash to configure debugger behavior,
424   # and perhaps a block containing debugger commands to be executed when the
425   # breakpoint is hit.
427   def debugger
428     require 'debugger/debugger'
429     dbg = Debugger.instance
431     unless dbg.interface
432       # Default to command-line interface if nothing registered
433       require 'debugger/interface'
434       Debugger::CmdLineInterface.new
435     end
437     ctxt = MethodContext.current.sender
438     cm = ctxt.method
439     ip = ctxt.ip
440     bp = dbg.get_breakpoint(cm, ip)
441     if bp
442       bp.enable unless bp.enabled?
443     else
444       bp = dbg.set_breakpoint(cm, ip)
445     end
447     # Modify send site not to call this method again
448     bc = ctxt.method.bytecodes
449     
450     Breakpoint.encoder.replace_instruction(bc, ip-4, [:noop])
451     Breakpoint.encoder.replace_instruction(bc, ip-2, [:noop])
453     ctxt.reload_method
454   end
456   alias_method :breakpoint, :debugger
458   alias_method :eql?, :equal?
460   def extend(*modules)
461     modules.reverse_each do |mod|
462       mod.extend_object(self)
463       mod.send(:extended, self)
464     end
465     self
466   end
468   def inspect(prefix=nil, vars=nil)
469     return "..." if RecursionGuard.inspecting?(self)
471     iv = __ivars__()
473     return self.to_s unless iv
475     if (iv.is_a?(Hash) or iv.is_a?(Tuple)) and iv.empty?
476       return self.to_s
477     end
479     prefix = "#{self.class}:0x#{self.object_id.to_s(16)}" unless prefix
480     parts = []
482     RecursionGuard.inspect(self) do
484       if iv.is_a?(Hash)
485         iv.each do |k,v|
486           next if vars and !vars.include?(k)
487           parts << "#{k}=#{v.inspect}"
488         end
489       else
490         0.step(iv.size - 1, 2) do |i|
491           if k = iv[i]
492             next if vars and !vars.include?(k)
493             v = iv[i+1]
494             parts << "#{k}=#{v.inspect}"
495           end
496         end
497       end
499     end
501     if parts.empty?
502       "#<#{prefix}>"
503     else
504       "#<#{prefix} #{parts.join(' ')}>"
505     end
506   end
508   ##
509   # :call-seq:
510   #   obj.instance_exec(arg, ...) { |var,...| block }  => obj
511   #
512   # Executes the given block within the context of the receiver +obj+. In
513   # order to set the context, the variable +self+ is set to +obj+ while the
514   # code is executing, giving the code access to +obj+'s instance variables.
515   #
516   # Arguments are passed as block parameters.
517   #
518   #   class Klass
519   #     def initialize
520   #       @secret = 99
521   #     end
522   #   end
523   #   
524   #   k = Klass.new
525   #   k.instance_exec(5) {|x| @secret+x }   #=> 104
527   def instance_exec(*args, &prc)
528     raise ArgumentError, "Missing block" unless block_given?
529     env = prc.block.redirect_to self
530     env.method.staticscope = StaticScope.new(metaclass, env.method.staticscope)
531     env.call(*args)
532   end
534   ##
535   # Returns true if this object is an instance of the given class, otherwise
536   # false. Raises a TypeError if a non-Class object given.
537   #
538   # Module objects can also be given for MRI compatibility but the result is
539   # always false.
541   def instance_of?(cls)
542     if cls.class != Class and cls.class != Module
543       # We can obviously compare against Modules but result is always false
544       raise TypeError, "instance_of? requires a Class argument"
545     end
547     self.class == cls
548   end
550   def instance_variable_get(sym)
551     sym = instance_variable_validate(sym)
552     get_instance_variable(sym)
553   end
555   def instance_variable_set(sym, value)
556     sym = instance_variable_validate(sym)
557     set_instance_variable(sym, value)
558   end
560   def remove_instance_variable(sym)
561     # HACK
562     instance_variable_set(sym, nil)
563   end
564   private :remove_instance_variable
566   def instance_variables
567     vars = get_instance_variables
568     return [] if vars.nil?
570     # CSM awareness
571     if vars.kind_of? Tuple
572       out = []
573       0.step(vars.size - 1, 2) do |i|
574         k = vars[i]
575         if k
576           k = k.to_s
577           out << k
578         else
579           return out
580         end
581       end
582       return out
583     end
584     return vars.keys.collect { |v| v.to_s }
585   end
587   def instance_variable_defined?(name)
588     vars = get_instance_variables
589     return false unless vars
591     name = name.to_sym unless name.kind_of? Symbol
592     
593     # CSM awareness
594     if vars.kind_of? Tuple
595       out = []
596       0.step(vars.size - 1, 2) do |i|
597         k = vars[i]
598         return true if k == name
599       end
601       return false
602     end
604     return vars.key?(name)
605   end
607   # Both of these are for defined? when used inside a proxy obj that
608   # may undef the regular method. The compiler generates __ calls.
609   alias_method :__instance_variable_defined_eh__, :instance_variable_defined?
610   alias_method :__respond_to_eh__, :respond_to?
612   def singleton_method_added(name)
613   end
614   private :singleton_method_added
616   def singleton_method_removed(name)
617   end
618   private :singleton_method_removed
620   def singleton_method_undefined(name)
621   end
622   private :singleton_method_undefined
624   alias_method :is_a?, :kind_of?
626   def method(name)
627     cm = __find_method__(name)
629     if cm
630       return Method.new(self, cm[1], cm[0])
631     else
632       raise NameError, "undefined method `#{name}' for #{self.inspect}"
633     end
634   end
636   def nil?
637     false
638   end
640   def method_missing_cv(meth, *args)
641     # Exclude method_missing from the backtrace since it only confuses
642     # people.
643     myself = MethodContext.current
644     ctx = myself.sender
646     if myself.send_private?
647       raise NameError, "undefined local variable or method `#{meth}' for #{inspect}"
648     elsif self.kind_of? Class or self.kind_of? Module
649       raise NoMethodError.new("No method '#{meth}' on #{self} (#{self.class})", ctx, args)
650     else
651       raise NoMethodError.new("No method '#{meth}' on an instance of #{self.class}.", ctx, args)
652     end
653   end
655   private :method_missing_cv
657   def methods(all=true)
658     names = singleton_methods(all)
659     names |= self.class.instance_methods(true) if all
660     return names
661   end
663   def private_methods(all=true)
664     names = private_singleton_methods
665     names |= self.class.private_instance_methods(all)
666     return names
667   end
669   def private_singleton_methods
670     metaclass.method_table.private_names.map { |meth| meth.to_s }
671   end
673   def protected_methods(all=true)
674     names = protected_singleton_methods
675     names |= self.class.protected_instance_methods(all)
676     return names
677   end
679   def protected_singleton_methods
680     metaclass.method_table.protected_names.map { |meth| meth.to_s }
681   end
683   def public_methods(all=true)
684     names = singleton_methods(all)
685     names |= self.class.public_instance_methods(all)
686     return names
687   end
689   def singleton_methods(all=true)
690     mt = metaclass.method_table
691     if all
692       return mt.keys.map { |m| m.to_s }
693     else
694       (mt.public_names + mt.protected_names).map { |m| m.to_s }
695     end
696   end
698   alias_method :send, :__send__
700   def to_a
701     if self.kind_of? Array
702       self
703     else
704       [self]
705     end
706   end
708   def to_s
709     "#<#{self.class}:0x#{self.object_id.to_s(16)}>"
710   end
712   def autoload(name, file)
713     Object.autoload(name, file)
714   end
715   private :autoload
717   def autoload?(name)
718     Object.autoload?(name)
719   end
720   private :autoload?
722   def set_trace_func(*args)
723     raise NotImplementedError
724   end
725   module_function :set_trace_func
726   
727   def syscall(*args)
728     raise NotImplementedError
729   end
730   module_function :syscall
732   def trace_var(*args)
733     raise NotImplementedError
734   end
735   module_function :trace_var
737   def untrace_var(*args)
738     raise NotImplementedError
739   end
740   module_function :untrace_var
742   # Perlisms.
744   def chomp(string=$/)
745     $_ = $_.chomp(string)
746   end
747   module_function :chomp
748   
749   def chomp!(string=$/)
750     $_.chomp!(string)
751   end
752   module_function :chomp!
754   def chop(string=$/)
755     $_ = $_.chop(string)
756   end
757   module_function :chop
758   
759   def chop!(string=$/)
760     $_.chop!(string)
761   end
762   module_function :chop!
764   def getc
765     $stdin.getc
766   end
767   module_function :getc
769   def putc(int)
770     $stdin.putc(int)
771   end
772   module_function :putc
774   def gets(sep=$/)
775     # HACK. Needs to use ARGF first.
776     $stdin.gets(sep)
777   end
778   module_function :gets
780   def readline(sep)
781     $stdin.readline(sep)
782   end
783   module_function :readline
784   
785   def readlines(sep)
786     $stdin.readlines(sep)
787   end
788   module_function :readlines
790   def gsub(pattern, rep=nil, &block)
791     $_ = $_.gsub(pattern, rep, &block)
792   end
793   module_function :gsub
794   
795   def gsub!(pattern, rep=nil, &block)
796     $_.gsub!(pattern, rep, &block)
797   end
798   module_function :gsub!
800   def sub(pattern, rep=nil, &block)
801     $_ = $_.sub(pattern, rep, &block)
802   end
803   module_function :sub
804   
805   def sub!(pattern, rep=nil, &block)
806     $_.sub!(pattern, rep, &block)
807   end
808   module_function :sub!
810   def scan(pattern, &block)
811     $_.scan(pattern, &block)
812   end
813   module_function :scan
815   def select(*args)
816     IO.select(*args)
817   end
818   module_function :select
820   def split(*args)
821     $_.split(*args)
822   end
823   module_function :split
825   # From bootstrap
826   private :get_instance_variable
827   private :get_instance_variables
828   private :set_instance_variable
830   def self.after_loaded
831     alias_method :method_missing, :method_missing_cv
833     # Add in $! in as a hook, to just do $!. This is for accesses to $!
834     # that the compiler can't see.
835     get = proc { $! }
836     Globals.set_hook(:$!, get, nil)
838     # Same as $!, for any accesses we might miss.
839     # HACK. I doubt this is correct, because of how it will be called.
840     get = proc { Regex.last_match }
841     Globals.set_hook(:$~, get, nil)
843     get = proc { ARGV }
844     Globals.set_hook(:$*, get, nil)
846     get = proc { $! ? $!.backtrace : nil }
847     Globals.set_hook(:$@, get, nil)
849     get = proc { Process.pid }
850     Globals.set_hook(:$$, get, nil)
851   end
855 class SystemExit < Exception
856   def initialize(status)
857     @status = status
858   end
860   attr_reader :status
862   def message
863     "System is exiting with code '#{status}'"
864   end