Skip to content

Commit

Permalink
Merge pull request #179 from faultyserver/nativelib/type_conversions
Browse files Browse the repository at this point in the history
Closes #174. Implement various type conversions for primitive values
  • Loading branch information
faultyserver authored Apr 1, 2018
2 parents fd26570 + 3169f1f commit b799d89
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 13 deletions.
52 changes: 52 additions & 0 deletions spec/myst/float_spec.mt
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,58 @@ describe("Float#%") do
end


describe("Float#to_i") do
it("returns a new Integer representing the Float") do
assert(1.0.to_i).equals(1)
assert(100.0.to_i).equals(100)
end

it("truncates decimals to create the Integer") do
assert(1.4.to_i).equals(1)
assert(123.456.to_i).equals(123)
end

it("does not perform rounding when truncating") do
assert(1.7.to_i).equals(1)
assert(10.5.to_i).equals(10)
end

it("raises an error if the Float cannot fit into an Integer value") do
# This number is larger than the maximum storable in a 64-bit integer.
assert{ 9_223_372_036_854_775_810.0.to_i }.raises
end
end


describe("Float#round") do
it("returns a new Integer representing the Float") do
assert(1.0.round).equals(1)
assert(100.0.round).equals(100)
end

it("rounds to the nearest Integer") do
assert(1.4.round).equals(1)
assert(123.789.round).equals(124)
end

it("rounds .5 decimals to the higher nearest Integer") do
assert(1.5.round).equals(2)
assert(214.5.round).equals(215)
end

it("accurately rounds decimals around *.5") do
assert(100.49999.round).equals(100)
assert(100.50000.round).equals(101)
assert(100.50001.round).equals(101)
end

it("raises an error if the Float cannot fit into an Integer value") do
# This number is larger than the maximum storable in a 64-bit integer.
assert{ 9_223_372_036_854_775_810.0.round }.raises
end
end


describe("Float#to_s") do
it("returns the string representation of the number") do
assert(1.0.to_s).equals("1.0")
Expand Down
8 changes: 8 additions & 0 deletions spec/myst/integer_spec.mt
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,14 @@ describe("Integer#times") do
end


describe("Integer#to_f") do
it("returns a new Float representing the Integer") do
assert(1.to_f).equals(1.0)
assert(100.to_f).equals(100.0)
end
end


describe("Integer#to_s") do
it("returns the string representation of the integer") do
assert(1.to_s).equals("1")
Expand Down
84 changes: 84 additions & 0 deletions spec/myst/string_spec.mt
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,88 @@ describe("String#empty?") do
end


describe("String#to_i") do
it("returns the Integer represented in the String") do
assert("100".to_i).equals(100)
end

it("defaults to parsing in base 10") do
assert("1234567890".to_i).equals(1234567890)
end

it("allows whitespace on either side of the integer") do
assert(" 100 ".to_i).equals(100)
assert("100 \t ".to_i).equals(100)
assert(" \t 100".to_i).equals(100)
assert("\n\n100\n\n".to_i).equals(100)
end

it("allows underscores in the integer value") do
assert("1_00_0".to_i).equals(1000)
assert("1_000".to_i).equals(1000)
end

it("allows prefixes to change the base") do
assert("0b10".to_i).equals(2)
assert("010".to_i).equals(8)
assert("0x10".to_i).equals(16)
end

it("raises an error if the string does not represent an integer") do
assert{ "hello".to_i }.raises
end

it("raises an error if the string contains a float value") do
assert{ "1.0".to_i }.raises
end

it("raises an error if the String contains extraneous characters after the integer") do
assert{ "100abc".to_i }.raises
end

describe("with a base argument") do
it("interprets the integer in the given base") do
assert("111".to_i(2)).equals(7)
assert("777".to_i(8)).equals(511)
end

it("expects the argument to be an Integer") do
assert{ "1".to_i(:f) }.raises
end
end
end


describe("String#to_f") do
it("returns the Float represented in the String") do
assert("100.123".to_f).equals(100.123)
end

it("defaults to parsing in base 10") do
assert("123450.6789".to_f).equals(123450.6789)
end

it("allows whitespace on either side of the Float") do
assert(" 1.2 ".to_f).equals(1.2)
assert("1.2 \t ".to_f).equals(1.2)
assert(" \t 1.2".to_f).equals(1.2)
assert("\n\n1.2\n".to_f).equals(1.2)
end

it("can parse an integer value into a Float") do
assert("100".to_f).equals(100.0)
end

it("raises an error if the string does not represent an integer") do
assert{ "hello".to_f }.raises
end

it("raises an error if the String contains extraneous characters after the integer") do
assert{ "100abc".to_f }.raises
end
end


describe("String#to_s") do
it("returns itself") do
assert("".to_s).equals("")
Expand All @@ -146,13 +228,15 @@ describe("String#to_s") do
end
end


describe("String#chars") do
it("Returns a List with chars in a string") do
assert("abc".chars).equals(["a", "b", "c"])
assert("yay".chars).equals(["y", "a", "y"])
end
end


describe("String#downcase") do
it("returns a lowercased version of itself") do
assert("HELLO".downcase).equals("hello")
Expand Down
36 changes: 23 additions & 13 deletions src/myst/interpreter/native_lib/float.cr
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ module Myst
end
end

NativeLib.method :float_to_i, Float64 do
this.to_i64
end

NativeLib.method :float_round, Float64 do
this.round
end

NativeLib.method :float_to_s, Float64 do
this.to_s
end
Expand Down Expand Up @@ -103,19 +111,21 @@ module Myst
float_type = TType.new("Float", kernel.scope)
float_type.instance_scope["type"] = float_type

NativeLib.def_instance_method(float_type, :+, :float_add)
NativeLib.def_instance_method(float_type, :-, :float_subtract)
NativeLib.def_instance_method(float_type, :*, :float_multiply)
NativeLib.def_instance_method(float_type, :/, :float_divide)
NativeLib.def_instance_method(float_type, :%, :float_modulo)
NativeLib.def_instance_method(float_type, :==, :float_eq)
NativeLib.def_instance_method(float_type, :!=, :float_not_eq)
NativeLib.def_instance_method(float_type, :to_s, :float_to_s)
NativeLib.def_instance_method(float_type, :negate,:float_negate)
NativeLib.def_instance_method(float_type, :<, :float_lt)
NativeLib.def_instance_method(float_type, :<=, :float_lte)
NativeLib.def_instance_method(float_type, :>, :float_gt)
NativeLib.def_instance_method(float_type, :>=, :float_gte)
NativeLib.def_instance_method(float_type, :+, :float_add)
NativeLib.def_instance_method(float_type, :-, :float_subtract)
NativeLib.def_instance_method(float_type, :*, :float_multiply)
NativeLib.def_instance_method(float_type, :/, :float_divide)
NativeLib.def_instance_method(float_type, :%, :float_modulo)
NativeLib.def_instance_method(float_type, :==, :float_eq)
NativeLib.def_instance_method(float_type, :!=, :float_not_eq)
NativeLib.def_instance_method(float_type, :to_i, :float_to_i)
NativeLib.def_instance_method(float_type, :round, :float_round)
NativeLib.def_instance_method(float_type, :to_s, :float_to_s)
NativeLib.def_instance_method(float_type, :negate, :float_negate)
NativeLib.def_instance_method(float_type, :<, :float_lt)
NativeLib.def_instance_method(float_type, :<=, :float_lte)
NativeLib.def_instance_method(float_type, :>, :float_gt)
NativeLib.def_instance_method(float_type, :>=, :float_gte)

float_type
end
Expand Down
5 changes: 5 additions & 0 deletions src/myst/interpreter/native_lib/integer.cr
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ module Myst
end
end

NativeLib.method :int_to_f, Int64 do
this.to_f64
end

NativeLib.method :int_to_s, Int64 do
this.to_s
end
Expand Down Expand Up @@ -113,6 +117,7 @@ module Myst
NativeLib.def_instance_method(integer_type, :%, :int_modulo)
NativeLib.def_instance_method(integer_type, :==, :int_eq)
NativeLib.def_instance_method(integer_type, :!=, :int_not_eq)
NativeLib.def_instance_method(integer_type, :to_f, :int_to_f)
NativeLib.def_instance_method(integer_type, :to_s, :int_to_s)
NativeLib.def_instance_method(integer_type, :negate,:int_negate)
NativeLib.def_instance_method(integer_type, :<, :int_lt)
Expand Down
19 changes: 19 additions & 0 deletions src/myst/interpreter/native_lib/string.cr
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ module Myst
end
end

NativeLib.method :string_to_i, String, base : Int64? do
begin
base = 10 if base.nil?
this.to_i64(base: base, whitespace: true, underscore: true, prefix: true, strict: true)
rescue ex : ArgumentError
__raise_runtime_error(ex.message.not_nil!)
end
end

NativeLib.method :string_to_f, String, base : Int64? do
begin
this.to_f64(whitespace: true, strict: true)
rescue ex : ArgumentError
__raise_runtime_error(ex.message.not_nil!)
end
end

NativeLib.method :string_to_s, String do
this
end
Expand Down Expand Up @@ -117,6 +134,8 @@ module Myst
NativeLib.def_instance_method(string_type, :==, :string_eq)
NativeLib.def_instance_method(string_type, :!=, :string_not_eq)
NativeLib.def_instance_method(string_type, :[], :string_at)
NativeLib.def_instance_method(string_type, :to_i, :string_to_i)
NativeLib.def_instance_method(string_type, :to_f, :string_to_f)
NativeLib.def_instance_method(string_type, :to_s, :string_to_s)
NativeLib.def_instance_method(string_type, :size, :string_size)
NativeLib.def_instance_method(string_type, :split, :string_split)
Expand Down

0 comments on commit b799d89

Please sign in to comment.