[WIP] start to implement types as Objects
This commit is contained in:
parent
148366914e
commit
c89c832b96
2 changed files with 232 additions and 0 deletions
184
lib/rpl/types.rb
Normal file
184
lib/rpl/types.rb
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# :boolean
|
||||||
|
class RplBoolean
|
||||||
|
attr_accessor :value
|
||||||
|
|
||||||
|
def initialize( value )
|
||||||
|
raise RplTypeError unless self.class.can_parse?( value )
|
||||||
|
|
||||||
|
@value = if value.is_a?( String )
|
||||||
|
value.downcase == 'true'
|
||||||
|
else
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
@value.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_parse?( value )
|
||||||
|
return %w[true false].include?( value.downcase ) if value.is_a?( String )
|
||||||
|
|
||||||
|
%w[TrueClass FalseClass].include?( value.class.to_s )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :list
|
||||||
|
class RplList
|
||||||
|
attr_accessor :value
|
||||||
|
|
||||||
|
def initialize( value )
|
||||||
|
raise RplTypeError unless self.class.can_parse?( value )
|
||||||
|
|
||||||
|
# we systematicalyl trim enclosing { }
|
||||||
|
@value = value[2..-3] # TODO: parse each element
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"{ #{@value.map(&:to_s).join(' ')} }"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_parse?( value )
|
||||||
|
value[0] == '{' && value[-1] == '}'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :name
|
||||||
|
class RplName
|
||||||
|
attr_accessor :value
|
||||||
|
|
||||||
|
def initialize( value )
|
||||||
|
raise RplTypeError unless self.class.can_parse?( value )
|
||||||
|
|
||||||
|
# we systematicalyl trim enclosing '
|
||||||
|
@value = value[1..-2]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"'#{@value}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_parse?( value )
|
||||||
|
value[0] == "'" && value[-1] == "'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :numeric
|
||||||
|
class RplNumeric
|
||||||
|
attr_accessor :value
|
||||||
|
|
||||||
|
def initialize( value, base = 10 )
|
||||||
|
raise RplTypeError unless self.class.can_parse?( value )
|
||||||
|
|
||||||
|
@base = base
|
||||||
|
@value = value
|
||||||
|
|
||||||
|
underscore_position = @value.index('_')
|
||||||
|
|
||||||
|
if @value[0] == '0' && ( %w[b o x].include?( @value[1] ) || !underscore_position.nil? )
|
||||||
|
if @value[1] == 'x'
|
||||||
|
@base = 16
|
||||||
|
elsif @value[1] == 'b'
|
||||||
|
@base = 2
|
||||||
|
elsif @value[1] == 'o'
|
||||||
|
@base = 8
|
||||||
|
@value = @value[2..-1]
|
||||||
|
elsif !underscore_position.nil?
|
||||||
|
@base = @value[1..(underscore_position - 1)].to_i
|
||||||
|
@value = @value[(underscore_position + 1)..-1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@value = @value.to_i( @base ) unless @base == 10
|
||||||
|
@value = BigDecimal( @value, @precision ) # FIXME: how to get @precision?
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
prefix = case @base
|
||||||
|
when 2
|
||||||
|
'0b'
|
||||||
|
when 8
|
||||||
|
'0o'
|
||||||
|
when 10
|
||||||
|
''
|
||||||
|
when 16
|
||||||
|
'0x'
|
||||||
|
else
|
||||||
|
"0#{@base}_"
|
||||||
|
end
|
||||||
|
|
||||||
|
if @value.infinite?
|
||||||
|
suffix = @value.infinite?.positive? ? '∞' : '-∞'
|
||||||
|
elsif @value.nan?
|
||||||
|
suffix = '<NaN>'
|
||||||
|
else
|
||||||
|
suffix = if @value.to_i == @value
|
||||||
|
@value.to_i
|
||||||
|
else
|
||||||
|
@value.to_s('F')
|
||||||
|
end
|
||||||
|
suffix = @value.to_s( @base ) unless @base == 10
|
||||||
|
end
|
||||||
|
|
||||||
|
"#{prefix}#{suffix}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_parse?( value )
|
||||||
|
# FIXME
|
||||||
|
!Float( value ).nil?
|
||||||
|
rescue ArgumentError
|
||||||
|
begin
|
||||||
|
!Integer( value ).nil?
|
||||||
|
rescue ArgumentError
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.infer_resulting_base( numerics )
|
||||||
|
10 if numerics.length.zero?
|
||||||
|
|
||||||
|
numerics.last.base
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :string
|
||||||
|
class RplString
|
||||||
|
attr_accessor :value
|
||||||
|
|
||||||
|
def initialize( value )
|
||||||
|
raise RplTypeError unless self.class.can_parse?( value )
|
||||||
|
|
||||||
|
# we systematicalyl trim enclosing "
|
||||||
|
@value = value[1..-2]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"\"#{@value}\""
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_parse?( value )
|
||||||
|
value[0] == '"' && value[-1] == '"'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :program
|
||||||
|
class RplProgram
|
||||||
|
attr_accessor :value
|
||||||
|
|
||||||
|
def initialize( value )
|
||||||
|
raise RplTypeError unless self.class.can_parse?( value )
|
||||||
|
|
||||||
|
# we systematicalyl trim enclosing « »
|
||||||
|
@value = value[2..-3]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"« #{@value} »"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.can_parse?( value )
|
||||||
|
value[0] == '«' && value[-1] == '»'
|
||||||
|
end
|
||||||
|
end
|
48
spec/types_spec.rb
Normal file
48
spec/types_spec.rb
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# coding: utf-8
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'minitest/autorun'
|
||||||
|
|
||||||
|
require 'rpl/types'
|
||||||
|
|
||||||
|
class TestTypes < MiniTest::Test
|
||||||
|
def test_boolean
|
||||||
|
assert_equal true, RplBoolean.can_parse?( true )
|
||||||
|
assert_equal true, RplBoolean.can_parse?( false )
|
||||||
|
assert_equal true, RplBoolean.can_parse?( 'true' )
|
||||||
|
assert_equal true, RplBoolean.can_parse?( 'false' )
|
||||||
|
assert_equal true, RplBoolean.can_parse?( 'TRUE' )
|
||||||
|
assert_equal true, RplBoolean.can_parse?( 'FALSE' )
|
||||||
|
assert_equal false, RplBoolean.can_parse?( 'prout' )
|
||||||
|
assert_equal false, RplBoolean.can_parse?( 1 )
|
||||||
|
|
||||||
|
assert_equal RplBoolean, RplBoolean.new( true ).class
|
||||||
|
assert_equal RplBoolean, RplBoolean.new( false ).class
|
||||||
|
assert_equal RplBoolean, RplBoolean.new( 'true' ).class
|
||||||
|
assert_equal RplBoolean, RplBoolean.new( 'false' ).class
|
||||||
|
assert_equal RplBoolean, RplBoolean.new( 'TRUE' ).class
|
||||||
|
assert_equal RplBoolean, RplBoolean.new( 'FALSE' ).class
|
||||||
|
|
||||||
|
assert_equal true, RplBoolean.new( true ).value
|
||||||
|
assert_equal false, RplBoolean.new( false ).value
|
||||||
|
assert_equal true, RplBoolean.new( 'true' ).value
|
||||||
|
assert_equal false, RplBoolean.new( 'false' ).value
|
||||||
|
assert_equal true, RplBoolean.new( 'TRUE' ).value
|
||||||
|
assert_equal false, RplBoolean.new( 'FALSE' ).value
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_string
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_program
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_numeric
|
||||||
|
end
|
||||||
|
end
|
Loading…
Add table
Reference in a new issue