-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create simple values for runtime checking
- Loading branch information
0 parents
commit 6e45d74
Showing
4 changed files
with
351 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
elliotchance/reflect | ||
==================== | ||
|
||
Runtime reflection for [V](https://vlang.io). | ||
|
||
V does not carry runtime information about types. Although compile-time | ||
reflection is more performant it can be limiting in some cases that can't be | ||
avoided. | ||
|
||
Values | ||
------ | ||
|
||
A `Value` can be created from any literal or simple value, for example: | ||
|
||
```v | ||
v := reflect.value_of(1.23) | ||
println(v.kind) // "f64" | ||
println(v.get_f64()) // 1.23 | ||
println(v.get_int()) // V panic: value must be int but is f64 | ||
``` | ||
|
||
This becomes especially useful when dealing with arrays of mixed types: | ||
|
||
```v | ||
// Only sum numbers. | ||
fn sum(items []reflect.Value) f64 { | ||
mut total := 0.0 | ||
for item in items { | ||
match item.kind { | ||
.is_f64 { total += item.get_f64() } | ||
.is_int { total += item.get_int() } | ||
else { /* ignore */ } | ||
} | ||
} | ||
return total | ||
} | ||
fn main() { | ||
v := [ | ||
reflect.value_of(1.23), | ||
reflect.value_of("hello"), | ||
reflect.value_of(7), | ||
] | ||
println(sum(v)) // 8.23 | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
module reflect | ||
|
||
pub enum Kind { | ||
is_bool | ||
is_string | ||
is_i8 | ||
is_i16 | ||
is_int | ||
is_i64 | ||
is_byte | ||
is_u16 | ||
is_u32 | ||
is_u64 | ||
is_rune | ||
is_f32 | ||
is_f64 | ||
} | ||
|
||
pub fn (k Kind) str() string { | ||
return match k { | ||
.is_bool { 'bool' } | ||
.is_string { 'string' } | ||
.is_i8 { 'i8' } | ||
.is_i16 { 'i16' } | ||
.is_int { 'int' } | ||
.is_i64 { 'i64' } | ||
.is_byte { 'byte' } | ||
.is_u16 { 'u16' } | ||
.is_u32 { 'u32' } | ||
.is_u64 { 'u64' } | ||
.is_rune { 'rune' } | ||
.is_f32 { 'f32' } | ||
.is_f64 { 'f64' } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
module reflect | ||
|
||
pub struct Value { | ||
// TODO(elliot): I know this is extremely wasteful. We'll come up with | ||
// something more sane later. | ||
value_bool bool | ||
value_string string | ||
value_i8 i8 | ||
value_i16 i16 | ||
value_int int | ||
value_i64 i64 | ||
value_byte byte | ||
value_u16 u16 | ||
value_u32 u32 | ||
value_u64 u64 | ||
value_rune rune | ||
value_f32 f32 | ||
value_f64 f64 | ||
pub: | ||
kind Kind | ||
} | ||
|
||
// value_of is used to create a Value | ||
pub fn value_of<T>(x T) Value { | ||
$if T is bool { | ||
return { | ||
kind: Kind.is_bool | ||
value_bool: x | ||
} | ||
} | ||
|
||
$if T is string { | ||
return { | ||
kind: Kind.is_string | ||
value_string: x | ||
} | ||
} | ||
|
||
$if T is i8 { | ||
return { | ||
kind: Kind.is_i8 | ||
value_i8: x | ||
} | ||
} | ||
|
||
$if T is i16 { | ||
return { | ||
kind: Kind.is_i16 | ||
value_i16: x | ||
} | ||
} | ||
|
||
$if T is int { | ||
return { | ||
kind: Kind.is_int | ||
value_int: x | ||
} | ||
} | ||
|
||
$if T is i64 { | ||
return { | ||
kind: Kind.is_i64 | ||
value_i64: x | ||
} | ||
} | ||
|
||
$if T is byte { | ||
return { | ||
kind: Kind.is_byte | ||
value_byte: x | ||
} | ||
} | ||
|
||
$if T is u16 { | ||
return { | ||
kind: Kind.is_u16 | ||
value_u16: x | ||
} | ||
} | ||
|
||
$if T is u32 { | ||
return { | ||
kind: Kind.is_u32 | ||
value_u32: x | ||
} | ||
} | ||
|
||
$if T is u64 { | ||
return { | ||
kind: Kind.is_u64 | ||
value_u64: x | ||
} | ||
} | ||
|
||
$if T is rune { | ||
return { | ||
kind: Kind.is_rune | ||
value_rune: x | ||
} | ||
} | ||
|
||
$if T is f32 { | ||
return { | ||
kind: Kind.is_f32 | ||
value_f32: x | ||
} | ||
} | ||
|
||
$if T is f64 { | ||
return { | ||
kind: Kind.is_f64 | ||
value_f64: x | ||
} | ||
} | ||
|
||
panic('unsupported value $x') | ||
} | ||
|
||
fn (v Value) must_be(k Kind) { | ||
if v.kind != k { | ||
panic('value must be $k but is $v.kind') | ||
} | ||
} | ||
|
||
pub fn (v Value) get_bool() bool { | ||
v.must_be(Kind.is_bool) | ||
return v.value_bool | ||
} | ||
|
||
pub fn (v Value) get_string() string { | ||
v.must_be(Kind.is_string) | ||
return v.value_string | ||
} | ||
|
||
pub fn (v Value) get_i8() i8 { | ||
v.must_be(Kind.is_i8) | ||
return v.value_i8 | ||
} | ||
|
||
pub fn (v Value) get_i16() i16 { | ||
v.must_be(Kind.is_i16) | ||
return v.value_i16 | ||
} | ||
|
||
pub fn (v Value) get_int() int { | ||
v.must_be(Kind.is_int) | ||
return v.value_int | ||
} | ||
|
||
pub fn (v Value) get_i64() i64 { | ||
v.must_be(Kind.is_i64) | ||
return v.value_i64 | ||
} | ||
|
||
pub fn (v Value) get_byte() byte { | ||
v.must_be(Kind.is_byte) | ||
return v.value_byte | ||
} | ||
|
||
pub fn (v Value) get_u16() u16 { | ||
v.must_be(Kind.is_u16) | ||
return v.value_u16 | ||
} | ||
|
||
pub fn (v Value) get_u32() u32 { | ||
v.must_be(Kind.is_u32) | ||
return v.value_u32 | ||
} | ||
|
||
pub fn (v Value) get_u64() u64 { | ||
v.must_be(Kind.is_u64) | ||
return v.value_u64 | ||
} | ||
|
||
pub fn (v Value) get_rune() rune { | ||
v.must_be(Kind.is_rune) | ||
return v.value_rune | ||
} | ||
|
||
pub fn (v Value) get_f32() f32 { | ||
v.must_be(Kind.is_f32) | ||
return v.value_f32 | ||
} | ||
|
||
pub fn (v Value) get_f64() f64 { | ||
v.must_be(Kind.is_f64) | ||
return v.value_f64 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
module reflect | ||
|
||
fn test_value_of_bool() { | ||
v := value_of(true) | ||
assert v.kind == Kind.is_bool | ||
assert v.get_bool() == true | ||
} | ||
|
||
fn test_value_of_string() { | ||
v := value_of('hello') | ||
assert v.kind == Kind.is_string | ||
assert v.get_string() == 'hello' | ||
} | ||
|
||
fn test_value_of_i8() { | ||
v := value_of(i8(57)) | ||
assert v.kind == Kind.is_i8 | ||
assert v.get_i8() == 57 | ||
} | ||
|
||
fn test_value_of_i16() { | ||
v := value_of(i16(43)) | ||
assert v.kind == Kind.is_i16 | ||
assert v.get_i16() == 43 | ||
} | ||
|
||
fn test_value_of_int() { | ||
v := value_of(123) | ||
assert v.kind == Kind.is_int | ||
assert v.get_int() == 123 | ||
} | ||
|
||
fn test_value_of_i64() { | ||
v := value_of(i64(123456)) | ||
assert v.kind == Kind.is_i64 | ||
assert v.get_i64() == 123456 | ||
} | ||
|
||
fn test_value_of_byte() { | ||
v := value_of(byte(45)) | ||
assert v.kind == Kind.is_byte | ||
assert v.get_byte() == 45 | ||
} | ||
|
||
fn test_value_of_u16() { | ||
v := value_of(u16(34)) | ||
assert v.kind == Kind.is_u16 | ||
assert v.get_u16() == 34 | ||
} | ||
|
||
fn test_value_of_u32() { | ||
v := value_of(u32(4567)) | ||
assert v.kind == Kind.is_u32 | ||
assert v.get_u32() == 4567 | ||
} | ||
|
||
fn test_value_of_u64() { | ||
v := value_of(u64(56789)) | ||
assert v.kind == Kind.is_u64 | ||
assert v.get_u64() == 56789 | ||
} | ||
|
||
fn test_value_of_rune() { | ||
v := value_of(`😃`) | ||
assert v.kind == Kind.is_rune | ||
assert v.get_rune() == `😃` | ||
} | ||
|
||
fn test_value_of_f32() { | ||
v := value_of(f32(1.23)) | ||
assert v.kind == Kind.is_f32 | ||
assert v.get_f32() == f32(1.23) | ||
} | ||
|
||
fn test_value_of_f64() { | ||
v := value_of(4.56) | ||
assert v.kind == Kind.is_f64 | ||
assert v.get_f64() == 4.56 | ||
} |