# encoding: utf-8 # frozen_string_literal: true module Carbon module Core module Integer # Defines a set of miscellaneous functions. These functions are various # functions that don't fit in any of the other category. These functions # include: # # - `.next(self): self` # - `.succ(self): self` # - `.abs(self): self` # - `.prev(self): self` # - `.pred(self): self` # - `.to-bool(self): self` # - `.size(): Carbon::UInt32` # - `.size(self): Carbon::UInt32` # # These functions are defined on all of the integer types except boolean. # However, `.size` is also defined on boolean. # # @api private module Misc # Defines the "to boolean" function for the given integer type. This # just returns the result of comparison of the number to zero (returns # 0 if the number is zero, 1 otherwise). # # @param int [Core::Int] The (receiver) value. # @return [void] def define_bool_function(int) function_name = int.name.call("to-bool", [int.name]) Core.define(function: function_name) do |function| function[:return] = int.name function[:definition].add("entry").build do |b| this = function[:definition].params[0] this.name = "self" b.ret(b.icmp(:ne, this, 0)) end end end # Define the next functions for the given integer type. These # functions just return the given number incremented by one. This is # implemented without any calls. This function defines both the # `.next` and `.succ` functions. # # @param int [Core::Int] The (receiver) value. # @return [void] def define_next_function(int) %w(next succ).each do |name| function_name = int.name.call(name, [int.name]) Core.define(function: function_name) do |function| function[:return] = int.name define_next_definition(function[:definition]) end end end # Define the previous functions for the given integer type. These # functions just return the given number decremented by one. This is # implemented without any calls. This function defines both the # `.prev` and `.pred` functions. # # @param int [Core::Int] The (receiver) value. # @return [void] def define_prev_function(int) %w(prev pred).each do |name| function_name = int.name.call(name, [int.name]) Core.define(function: function_name) do |function| function[:return] = int.name define_prev_definition(function[:definition]) end end end # Define the absolute value function. For signed integers, it returns # the absolute (positive) value of an integer; for unsigned integers, # it returns itself. # # @param int [Core::Int] The (receiver) value. # @return [void] def define_iabs_function(int) function_name = int.name.call("abs", [int.name]) Core.define(function: function_name) do |function| function[:return] = int.name define_iabs_definition(int, function[:definition]) end end # Defines the size function. This returns the size of the integer, in # bits. # # @param int [Core::Int] The (receiver) integer type. # @return [void] def define_size_function(int) [[], [int.name]].each do |args| function_name = int.name.call("size", args) Core.define(function: function_name) do |function| function[:return] = Carbon::Type("Carbon::UInt32") define_size_definition(int, function[:definition]) end end end private def define_next_definition(definition) entry = definition.add("entry").build this = definition.params[0] this.name = "self" entry.ret(entry.add(this, 1)) end def define_prev_definition(definition) entry = definition.add("entry").build this = definition.params[0] this.name = "self" entry.ret(entry.sub(this, 1)) end def define_iabs_definition(int, definition) entry = definition.add("entry").build this = definition.params[0] this.name = "self" if int.sign == :unsigned entry.ret(this) else y = entry.ashr(this, int.size - 1) entry.ret(entry.sub(entry.xor(this, y), y)) end end def define_size_definition(int, definition) entry = definition.add("entry").build entry.ret(int.size) end end end end end