Strict types

This commit is contained in:
Aoran Zeng 2025-07-16 15:47:21 +08:00
parent 286843b40b
commit 8032921182
No known key found for this signature in database
GPG Key ID: 8F8BA8488E10ED98

View File

@ -13,10 +13,10 @@
unit module Parser; unit module Parser;
#| Bool Boolean #| Bool Boolean
my enum ConfigItem's-ValueType <String Mode Boolean>; my enum ConfigItem's-ValueType < RS4C-Nil RS4C-String RS4C-Mode RS4C-Bool>;
#| #|
my class ConfigItem's-Value { class ConfigItem's-Value {
has ConfigItem's-ValueType $.type; has ConfigItem's-ValueType $.type;
has Str $.raw-value; has Str $.raw-value;
has Any $.parsed-value; has Any $.parsed-value;
@ -28,17 +28,24 @@ my class ConfigItem's-Value {
given $raw-text { given $raw-text {
when /^ ':' (.+) $/ { when /^ ':' (.+) $/ {
# 模式值 :mode # 模式值 :mode
$type = Mode; $type = RS4C-Mode;
$parsed = ~$0; $parsed = ~$0;
} }
when /^ ('true'|'false'|'yes'|'no') $/ { when /^ ('true'|'false'|'yes'|'no') $/ {
# 特殊字面量 - true/false/yes/no 都是 literal # 特殊字面量 - true/false/yes/no 都是 literal
$type = Boolean; $type = RS4C-Bool;
$parsed = ~$0 ~~ /^('true'|'yes')$/ ?? True !! False; $parsed = ~$0 ~~ /^('true'|'yes')$/ ?? True !! False;
} }
# 明确区分空字符串和无值情况
# 这种情况不可能是用户写的(并没有nil这个字面量),只由内部实现时刻意传 Nil 出现
when Nil {
$type = RS4C-Nil;
$parsed = Nil;
}
# 输入为空时被当做是字符串类型
default { default {
# 普通字符串 # 普通字符串
$type = String; $type = RS4C-String;
$parsed = $raw-text; $parsed = $raw-text;
} }
} }
@ -46,30 +53,41 @@ my class ConfigItem's-Value {
self.bless(:$type, :raw-value($raw-text), :parsed-value($parsed)); self.bless(:$type, :raw-value($raw-text), :parsed-value($parsed));
} }
method as-string() { # 获得适合调用者接受的值
return $.parsed-value.Str; method value() {
}
method as-bool() {
given $.type { given $.type {
when Boolean { return $.parsed-value; } when RS4C-Nil | RS4C-String | RS4C-Bool | RS4C-Mode { return $.parsed-value; }
when String { default { die "Unknown config value type: {$.type}"; }
# 尝试将字符串解析为布尔值
return $.parsed-value ~~ /^('true'|'yes')$/;
}
default { return False; }
} }
} }
# 获取模式值(去掉冒号前缀) # 这些函数防止开发者写错类型
method as-mode() { method nil-value() {
return $.type == Mode ?? $.parsed-value !! $.raw-value; return self.value if $.type == RS4C-Nil;
die "The config value type is not RS4C-Nil, but: {$.type}";
} }
method string-value() {
return self.value if $.type == RS4C-String;
die "The config value type is not RS4C-String, but: {$.type}";
}
method bool-value() {
return self.value if $.type == RS4C-Bool;
die "The config value type is not RS4C-Bool, but: {$.type}";
}
method mode-value() {
return self.value if $.type == RS4C-Mode;
die "The config value type is not RS4C-Mode, but: {$.type}";
}
# 类型检查方法 # 类型检查方法
method is-mode() { return $.type == Mode; } method is-nil() { return $.type == RS4C-Nil; }
method is-bool() { return $.type == Boolean; } method is-mode() { return $.type == RS4C-Mode; }
method is-string() { return $.type == String; } method is-bool() { return $.type == RS4C-Bool; }
method is-string() { return $.type == RS4C-String; }
} }
@ -85,8 +103,8 @@ my class ConfigBlock {
%!items{$k} = ConfigItem's-Value.new($raw-value); %!items{$k} = ConfigItem's-Value.new($raw-value);
} }
method get($k, $default = Nil) { method get($k) {
return %!items{$k} // ($default ?? ConfigItem's-Value.new($default) !! ConfigItem's-Value.new('')); return %!items{$k};
} }
method exist($k) { method exist($k) {
@ -102,7 +120,7 @@ my class ConfigBlock {
#| section #| section
my class Section { class Section {
has Str $.title; has Str $.title;
has Int $.level; has Int $.level;