[Feat] 实现 std.formater库,增加 std.io.printf函数

[Fix] 修复 evaluator中处理else if condVal类型错误的低级问题
[Feat] 为 String类型增加 insert, replace, erase函数
This commit is contained in:
2025-12-29 18:27:39 +08:00
parent cd106fc513
commit 2a455a0487
6 changed files with 335 additions and 14 deletions

View File

@@ -115,7 +115,7 @@ namespace Fig
} }
i += cplen; i += cplen;
++ cnt; ++cnt;
} }
return ch; return ch;
@@ -138,8 +138,71 @@ namespace Fig
if (cnt == index) if (cnt == index)
{ {
*this = FString(substr(0, i)) + src + *this = FString(substr(0, i)) + src + FString(substr(i + cplen));
FString(substr(i + cplen)); }
i += cplen;
++cnt;
}
}
void realErase(size_t index, size_t n)
{
size_t cnt = 0;
size_t eraseStart = 0;
size_t eraseCplens = 0;
for (size_t i = 0; i < size();)
{
uint8_t cplen = 1;
if ((at(i) & 0xf8) == 0xf0)
cplen = 4;
else if ((at(i) & 0xf0) == 0xe0)
cplen = 3;
else if ((at(i) & 0xe0) == 0xc0)
cplen = 2;
if (i + cplen > size())
cplen = 1;
i += cplen;
++cnt;
if (cnt == index)
{
eraseStart = i;
}
if (cnt < index + n)
{
eraseCplens += cplen;
}
}
erase(eraseStart, eraseCplens);
}
void realInsert(size_t index, const FString &src)
{
if (index == length())
{
for (auto &c : src)
{
push_back(c);
}
return;
}
size_t cnt = 0;
for (size_t i = 0; i < size();)
{
uint8_t cplen = 1;
if ((at(i) & 0xf8) == 0xf0)
cplen = 4;
else if ((at(i) & 0xf0) == 0xe0)
cplen = 3;
else if ((at(i) & 0xe0) == 0xc0)
cplen = 2;
if (i + cplen > size())
cplen = 1;
if (cnt == index)
{
insert(i, src);
} }
i += cplen; i += cplen;

View File

@@ -1037,12 +1037,15 @@ namespace Fig
for (const auto &elif : ifSt->elifs) for (const auto &elif : ifSt->elifs)
{ {
ObjectPtr elifCondVal = eval(elif->condition, ctx); ObjectPtr elifCondVal = eval(elif->condition, ctx);
throw EvaluatorError( if (elifCondVal->getTypeInfo() != ValueType::Bool)
u8"TypeError", {
std::format( throw EvaluatorError(
"Condition must be boolean, but got '{}'", u8"TypeError",
condVal->getTypeInfo().toString().toBasicString()), std::format(
ifSt->condition); "Condition must be boolean, but got '{}'",
condVal->getTypeInfo().toString().toBasicString()),
ifSt->condition);
}
if (elifCondVal->as<ValueType::BoolClass>()) if (elifCondVal->as<ValueType::BoolClass>())
{ {
return evalBlockStatement(elif->body, ctx); return evalBlockStatement(elif->body, ctx);

View File

@@ -0,0 +1,178 @@
/*
Official Module `std.formater`
Library/std/formater/formater.fig
*/
import std.value; // `type` function and string_from
public func format(objects ...) -> Any
{
if objects.length() < 1
{
return null;
}
var fmt := objects[0];
if value.type(fmt) != "String"
{
return null;
}
var result := "";
var argIndex := 1;
var i := 0;
var length := fmt.length();
while (i < length)
{
var char := fmt[i];
if char == "{"
{
if (i + 1 >= length)
{
return null;
}
var nextChar = fmt[i + 1];
if nextChar == "{"
{
result += "{";
i += 2;
continue;
}
var endIndex := -1;
for var j = i + 1; j < length; j += 1
{
if fmt[j] == "}"
{
endIndex = j;
break;
}
}
if endIndex == -1
{
return null;
}
if argIndex >= objects.length()
{
return null;
}
result += value.string_from(objects[argIndex]);
argIndex += 1;
i = endIndex + 1;
}
else if char == "}"
{
if i + 1 < length && fmt[i + 1] == "}"
{
result += "}";
i += 2;
continue;
}
return null;
}
else
{
result += char;
i += 1;
}
}
return result;
}
public func formatByListArgs(objects) -> Any
{
if value.type(objects) != "List"
{
return null;
}
if objects.length() < 1
{
return null;
}
var fmt := objects[0];
if value.type(fmt) != "String"
{
return null;
}
var result := "";
var argIndex := 1;
var i := 0;
var length := fmt.length();
while (i < length)
{
var char := fmt[i];
if char == "{"
{
if (i + 1 >= length)
{
return null;
}
var nextChar = fmt[i + 1];
if nextChar == "{"
{
result += "{";
i += 2;
continue;
}
var endIndex := -1;
for var j = i + 1; j < length; j += 1
{
if fmt[j] == "}"
{
endIndex = j;
break;
}
}
if endIndex == -1
{
return null;
}
if argIndex >= objects.length()
{
return null;
}
result += value.string_from(objects[argIndex]);
argIndex += 1;
i = endIndex + 1;
}
else if char == "}"
{
if i + 1 < length && fmt[i + 1] == "}"
{
result += "}";
i += 2;
continue;
}
return null;
}
else
{
result += char;
i += 1;
}
}
return result;
}

View File

@@ -6,6 +6,8 @@
import _builtins; import _builtins;
import noSpace; // sub module `no space print` import noSpace; // sub module `no space print`
import std.formater; // format
// outputs // outputs
public func print(objects...) -> Int public func print(objects...) -> Int
@@ -37,6 +39,11 @@ public func println(objects...) -> Int
return length + 1; return length + 1;
} }
public func printf(objects...) -> Any
{
__fstdout_print(formater.formatByListArgs(objects));
}
// inputs // inputs
public func read() -> String public func read() -> String

View File

@@ -151,7 +151,7 @@ namespace Fig
}}, }},
{u8"__fvalue_string_from", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fvalue_string_from", [](const std::vector<ObjectPtr> &args) -> ObjectPtr {
ObjectPtr val = args[0]; ObjectPtr val = args[0];
return std::make_shared<Object>(val->toString()); return std::make_shared<Object>(val->toStringIO());
}}, }},
/* math start */ /* math start */
{u8"__fmath_acos", [](const std::vector<ObjectPtr> &args) -> ObjectPtr { {u8"__fmath_acos", [](const std::vector<ObjectPtr> &args) -> ObjectPtr {

View File

@@ -78,7 +78,76 @@ namespace Fig
const FString &str = as<ValueType::StringClass>(); const FString &str = as<ValueType::StringClass>();
return std::make_shared<Object>(static_cast<ValueType::IntClass>(str.length())); return std::make_shared<Object>(static_cast<ValueType::IntClass>(str.length()));
}}, }},
{u8"replace", [this](std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 2)
throw RuntimeError(FString(
std::format("`replace` expects 2 arguments, {} got", args.size())));
FString &str = as<ValueType::StringClass>();
ObjectPtr arg1 = args[0];
ObjectPtr arg2 = args[1];
if (!arg1->is<ValueType::IntClass>())
{
throw RuntimeError(FString(
"`replace` arg 1 expects type Int"));
}
if (!arg2->is<ValueType::StringClass>())
{
throw RuntimeError(FString(
"`replace` arg 2 expects type String"));
}
str.realReplace(arg1->as<ValueType::IntClass>(), arg2->as<ValueType::StringClass>());
return Object::getNullInstance();
}},
{u8"erase", [this](std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 2)
throw RuntimeError(FString(
std::format("`erase` expects 2 arguments, {} got", args.size())));
FString &str = as<ValueType::StringClass>();
ObjectPtr arg1 = args[0];
ObjectPtr arg2 = args[1];
if (!arg1->is<ValueType::IntClass>())
{
throw RuntimeError(FString(
"`erase` arg 1 expects type Int"));
}
if (!arg2->is<ValueType::IntClass>())
{
throw RuntimeError(FString(
"`erase` arg 2 expects type Int"));
}
ValueType::IntClass index = arg1->as<ValueType::IntClass>();
ValueType::IntClass n = arg2->as<ValueType::IntClass>();
if (index < 0 || n < 0)
{
throw RuntimeError(FString("`erase`: index and n must greater or equal to 0"));
}
if (index + n > str.length())
{
throw RuntimeError(FString("`erase`: length is not long enough to erase"));
}
str.realErase(arg1->as<ValueType::IntClass>(), arg2->as<ValueType::IntClass>());
return Object::getNullInstance();
}},
{u8"insert", [this](std::vector<ObjectPtr> args) -> ObjectPtr {
if (args.size() != 2)
throw RuntimeError(FString(
std::format("`insert` expects 2 arguments, {} got", args.size())));
FString &str = as<ValueType::StringClass>();
ObjectPtr arg1 = args[0];
ObjectPtr arg2 = args[1];
if (!arg1->is<ValueType::IntClass>())
{
throw RuntimeError(FString(
"`insert` arg 1 expects type Int"));
}
if (!arg2->is<ValueType::StringClass>())
{
throw RuntimeError(FString(
"`insert` arg 2 expects type String"));
}
str.realInsert(arg1->as<ValueType::IntClass>(), arg2->as<ValueType::StringClass>());
return Object::getNullInstance();
}},
}}, }},
{ValueType::Function, {}}, {ValueType::Function, {}},
{ValueType::StructType, {}}, {ValueType::StructType, {}},
@@ -136,15 +205,16 @@ namespace Fig
map.contains(index)); map.contains(index));
}}, }},
}}, }},
{ValueType::Module, {}} {ValueType::Module, {}}};
};
std::unordered_map<TypeInfo, std::unordered_map<FString, int>, TypeInfoHash> memberTypeFunctionsParas{ std::unordered_map<TypeInfo, std::unordered_map<FString, int>, TypeInfoHash> memberTypeFunctionsParas{
{ValueType::Null, {}}, {ValueType::Null, {}},
{ValueType::Int, {}}, {ValueType::Int, {}},
{ValueType::Double, {}}, {ValueType::Double, {}},
{ValueType::String, { {ValueType::String, {
{u8"length", 0}, {u8"length", 0},
{u8"replace", 2},
{u8"erase", 2},
{u8"insert", 2},
}}, }},
{ValueType::Function, {}}, {ValueType::Function, {}},
{ValueType::StructType, {}}, {ValueType::StructType, {}},