diff --git a/core/flags/doc.odin b/core/flags/doc.odin index 183b86f41..e17cff21b 100644 --- a/core/flags/doc.odin +++ b/core/flags/doc.odin @@ -11,13 +11,21 @@ Command-Line Syntax: Arguments are treated differently depending on how they're formatted. The format is similar to the Odin binary's way of handling compiler flags. - type handling - ------------ ------------------------ - depends on struct layout - - set a bool true - - set flag to option - - set flag to option, alternative syntax - -:= set map[key] to value + type handling + ------------ ------------------------ + depends on struct layout + - set a bool true + - set flag to option + - set flag to option, alternative syntax + - set bit_set flag to one or more options + - set bit_set flag to one or more options, alternative syntax + -:= set map[key] to value + +Underscores (`_`) in a flag will be replaced with dashes (`-`). + +Bit sets may be set with a strictly comma-separated list of options. + +Bit sets may also be set with a binary string of 0s and 1s, and will be parsed from left to right, from least significant bit to most significant bit. Underscores are allowed and will be ignored. However, starting with an underscore is disallowed. Unhandled Arguments: diff --git a/core/flags/example/example.odin b/core/flags/example/example.odin index 6ace3d852..204fca8e9 100644 --- a/core/flags/example/example.odin +++ b/core/flags/example/example.odin @@ -20,6 +20,14 @@ Optimization_Level :: enum { Ludicrous_Speed, } +Vet_Flag :: enum { + Unused, + Unused_Variables, + Unused_Imports, + Shadowing, + Using_Stmt, +} + // It's simple but powerful. my_custom_type_setter :: proc( data: rawptr, @@ -83,6 +91,8 @@ main :: proc() { schedule: datetime.DateTime `usage:"Launch tasks at this time."`, opt: Optimization_Level `usage:"Optimization level."`, + vet_flags: bit_set[Vet_Flag] `usage:"Vet flags. Example usage: + -vet-flags:Unused,Shadowing"`, todo: [dynamic]string `usage:"Todo items."`, accuracy: Fixed_Point1_1 `args:"required" usage:"Lenience in FLOP calculations."`, diff --git a/core/flags/internal_rtti.odin b/core/flags/internal_rtti.odin index 1d86f4bce..8a79f75a8 100644 --- a/core/flags/internal_rtti.odin +++ b/core/flags/internal_rtti.odin @@ -110,7 +110,7 @@ parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: case f32be: (^f32be)(ptr)^ = cast(f32be) value case f64be: (^f64be)(ptr)^ = cast(f64be) value } - + case runtime.Type_Info_Complex: value := strconv.parse_complex128(str) or_return switch type_info.id { @@ -118,7 +118,7 @@ parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: case complex64: (^complex64) (ptr)^ = (complex64)(value) case complex128: (^complex128)(ptr)^ = value } - + case runtime.Type_Info_Quaternion: value := strconv.parse_quaternion256(str) or_return switch type_info.id { @@ -152,15 +152,16 @@ parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: } case runtime.Type_Info_Bit_Set: - // Parse a string of 1's and 0's, from left to right, + // Parse a string of 1s and 0s, from left to right, // least significant bit to most significant bit. value: u128 // NOTE: `upper` is inclusive, i.e: `0..=31` - max_bit_index := u128(1 + specific_type_info.upper - specific_type_info.lower) + underscores := u128(strings.count(str, "_")) + bit_index_limit := u128(1 + specific_type_info.upper - specific_type_info.lower) + underscores bit_index := u128(0) #no_bounds_check for string_index in 0.. 0 + args := [?]string { + "-a:Option_A,Option_D", + } + result := flags.parse(&r, args[:]) + testing.expect_value(t, result, nil) + testing.expect_value(t, r.a, bit_set[E2]{E2.Option_A, E2.Option_D}) + } + { + args := [?]string { "-a:Option_Non_Existent" } + result := flags.parse(&r, args[:]) + err, ok := result.(flags.Parse_Error) + testing.expectf(t, ok, "unexpected result: %v", result) + if ok { + testing.expect_value(t, err.reason, flags.Parse_Error_Reason.Bad_Value) + } + } + { + // Value names list must be strictly comma-separated. + args := [?]string { "-a:Option_A, Option_B" } + result := flags.parse(&r, args[:]) + err, ok := result.(flags.Parse_Error) + testing.expectf(t, ok, "unexpected result: %v", result) + if ok { + testing.expect_value(t, err.reason, flags.Parse_Error_Reason.Bad_Value) + } + } + { + // Value names list must not end with a comma. + args := [?]string { "-a:Option_A,Option_B," } + result := flags.parse(&r, args[:]) + err, ok := result.(flags.Parse_Error) + testing.expectf(t, ok, "unexpected result: %v", result) + if ok { + testing.expect_value(t, err.reason, flags.Parse_Error_Reason.Bad_Value) + } + } } @(test) @@ -1288,13 +1347,11 @@ test_distinct_types :: proc(t: ^testing.T) { unmodified_i: I, } s: S - { args := [?]string {"-base-i:1"} result := flags.parse(&s, args[:]) testing.expect_value(t, result, nil) } - { args := [?]string {"-unmodified-i:1"} result := flags.parse(&s, args[:])