尝试UTF32String
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
#include <Evaluator/Value/interface.hpp>
|
||||
#include <Evaluator/Value/Type.hpp>
|
||||
#include <Evaluator/Context/context_forward.hpp>
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Core/String.hpp>
|
||||
#include <Evaluator/Value/value.hpp>
|
||||
#include <Evaluator/Value/VariableSlot.hpp>
|
||||
#include <Evaluator/Core/ExprResult.hpp>
|
||||
@@ -26,7 +26,7 @@ namespace Fig
|
||||
TypeInfo interfaceType;
|
||||
TypeInfo structType;
|
||||
|
||||
std::unordered_map<FString, Function> implMethods;
|
||||
std::unordered_map<String, Function> implMethods;
|
||||
};
|
||||
|
||||
struct OperationRecord
|
||||
@@ -49,11 +49,11 @@ namespace Fig
|
||||
class Context : public std::enable_shared_from_this<Context>
|
||||
{
|
||||
private:
|
||||
FString scopeName;
|
||||
std::unordered_map<FString, std::shared_ptr<VariableSlot>> variables;
|
||||
String scopeName;
|
||||
std::unordered_map<String, std::shared_ptr<VariableSlot>> variables;
|
||||
|
||||
// std::unordered_map<std::size_t, Function> functions;
|
||||
// std::unordered_map<std::size_t, FString> functionNames;
|
||||
// std::unordered_map<std::size_t, String> functionNames;
|
||||
|
||||
// implRegistry <Struct, ordered list of ImplRecord>
|
||||
std::unordered_map<TypeInfo, std::vector<ImplRecord>, TypeInfoHash> implRegistry;
|
||||
@@ -63,13 +63,13 @@ namespace Fig
|
||||
ContextPtr parent;
|
||||
|
||||
Context(const Context &) = default;
|
||||
Context(const FString &name, ContextPtr p = nullptr) : scopeName(name), parent(p) {}
|
||||
Context(const String &name, ContextPtr p = nullptr) : scopeName(name), parent(p) {}
|
||||
|
||||
void setParent(ContextPtr _parent) { parent = _parent; }
|
||||
|
||||
void setScopeName(FString _name) { scopeName = std::move(_name); }
|
||||
void setScopeName(String _name) { scopeName = std::move(_name); }
|
||||
|
||||
FString getScopeName() const { return scopeName; }
|
||||
String getScopeName() const { return scopeName; }
|
||||
|
||||
void merge(const Context &c)
|
||||
{
|
||||
@@ -94,58 +94,58 @@ namespace Fig
|
||||
return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<VariableSlot> get(const FString &name)
|
||||
std::shared_ptr<VariableSlot> get(const String &name)
|
||||
{
|
||||
auto it = variables.find(name);
|
||||
if (it != variables.end()) return it->second;
|
||||
if (parent) return parent->get(name);
|
||||
throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
}
|
||||
AccessModifier getAccessModifier(const FString &name)
|
||||
AccessModifier getAccessModifier(const String &name)
|
||||
{
|
||||
if (variables.contains(name)) { return variables[name]->am; }
|
||||
else if (parent != nullptr) { return parent->getAccessModifier(name); }
|
||||
else
|
||||
{
|
||||
throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
}
|
||||
}
|
||||
bool isVariableMutable(const FString &name)
|
||||
bool isVariableMutable(const String &name)
|
||||
{
|
||||
AccessModifier am = getAccessModifier(name); // may throw
|
||||
return !isAccessConst(am);
|
||||
}
|
||||
bool isVariablePublic(const FString &name)
|
||||
bool isVariablePublic(const String &name)
|
||||
{
|
||||
AccessModifier am = getAccessModifier(name); // may throw
|
||||
return isAccessPublic(am);
|
||||
}
|
||||
void set(const FString &name, ObjectPtr value)
|
||||
void set(const String &name, ObjectPtr value)
|
||||
{
|
||||
if (variables.contains(name))
|
||||
{
|
||||
if (!isVariableMutable(name))
|
||||
{
|
||||
throw RuntimeError(FString(std::format("Variable '{}' is immutable", name.toBasicString())));
|
||||
throw RuntimeError(String(std::format("Variable '{}' is immutable", name.toBasicString())));
|
||||
}
|
||||
variables[name]->value = value;
|
||||
}
|
||||
else if (parent != nullptr) { parent->set(name, value); }
|
||||
else
|
||||
{
|
||||
throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
}
|
||||
}
|
||||
void _update(const FString &name, ObjectPtr value)
|
||||
void _update(const String &name, ObjectPtr value)
|
||||
{
|
||||
if (variables.contains(name)) { variables[name]->value = value; }
|
||||
else if (parent != nullptr) { parent->_update(name, value); }
|
||||
else
|
||||
{
|
||||
throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString())));
|
||||
}
|
||||
}
|
||||
void def(const FString &name,
|
||||
void def(const String &name,
|
||||
const TypeInfo &ti,
|
||||
AccessModifier am,
|
||||
const ObjectPtr &value = Object::getNullInstance())
|
||||
@@ -153,7 +153,7 @@ namespace Fig
|
||||
if (containsInThisScope(name))
|
||||
{
|
||||
throw RuntimeError(
|
||||
FString(std::format("Variable '{}' already defined in this scope", name.toBasicString())));
|
||||
String(std::format("Variable '{}' already defined in this scope", name.toBasicString())));
|
||||
}
|
||||
variables[name] = std::make_shared<VariableSlot>(name, value, ti, am);
|
||||
// if (ti == ValueType::StructType)
|
||||
@@ -163,17 +163,17 @@ namespace Fig
|
||||
// }
|
||||
}
|
||||
void
|
||||
defReference(const FString &name, const TypeInfo &ti, AccessModifier am, std::shared_ptr<VariableSlot> target)
|
||||
defReference(const String &name, const TypeInfo &ti, AccessModifier am, std::shared_ptr<VariableSlot> target)
|
||||
{
|
||||
if (containsInThisScope(name))
|
||||
{
|
||||
throw RuntimeError(
|
||||
FString(std::format("Variable '{}' already defined in this scope", name.toBasicString())));
|
||||
String(std::format("Variable '{}' already defined in this scope", name.toBasicString())));
|
||||
}
|
||||
variables[name] = std::make_shared<VariableSlot>(name, target->value, ti, am, true, target);
|
||||
}
|
||||
|
||||
std::optional<FString> getFunctionName(std::size_t id)
|
||||
std::optional<String> getFunctionName(std::size_t id)
|
||||
{
|
||||
for (auto &[name, slot] : variables)
|
||||
{
|
||||
@@ -185,7 +185,7 @@ namespace Fig
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
// std::optional<FString> getStructName(std::size_t id)
|
||||
// std::optional<String> getStructName(std::size_t id)
|
||||
// {
|
||||
// auto it = structTypeNames.find(id);
|
||||
// if (it != structTypeNames.end())
|
||||
@@ -201,21 +201,21 @@ namespace Fig
|
||||
// return std::nullopt;
|
||||
// }
|
||||
// }
|
||||
bool contains(const FString &name)
|
||||
bool contains(const String &name)
|
||||
{
|
||||
if (variables.contains(name)) { return true; }
|
||||
else if (parent != nullptr) { return parent->contains(name); }
|
||||
return false;
|
||||
}
|
||||
bool containsInThisScope(const FString &name) const { return variables.contains(name); }
|
||||
bool containsInThisScope(const String &name) const { return variables.contains(name); }
|
||||
|
||||
TypeInfo getTypeInfo(const FString &name) { return get(name)->declaredType; }
|
||||
TypeInfo getTypeInfo(const String &name) { return get(name)->declaredType; }
|
||||
bool isInFunctionContext()
|
||||
{
|
||||
ContextPtr ctx = shared_from_this();
|
||||
while (ctx)
|
||||
{
|
||||
if (ctx->getScopeName().find(u8"<Function ") == 0) { return true; }
|
||||
if (ctx->getScopeName().find(U"\1") == 0) { return true; }
|
||||
ctx = ctx->parent;
|
||||
}
|
||||
return false;
|
||||
@@ -225,10 +225,7 @@ namespace Fig
|
||||
ContextPtr ctx = shared_from_this();
|
||||
while (ctx)
|
||||
{
|
||||
if (ctx->getScopeName().find(u8"<While ") == 0 or ctx->getScopeName().find(u8"<For ") == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (ctx->getScopeName().find(U"\1") == 0 or ctx->getScopeName().find(U"\1") == 0) { return true; }
|
||||
ctx = ctx->parent;
|
||||
}
|
||||
return false;
|
||||
@@ -282,7 +279,7 @@ namespace Fig
|
||||
list.push_back(record); // order is the level
|
||||
}
|
||||
|
||||
bool hasMethodImplemented(const TypeInfo &structType, const FString &functionName) const
|
||||
bool hasMethodImplemented(const TypeInfo &structType, const String &functionName) const
|
||||
{
|
||||
auto it = implRegistry.find(structType);
|
||||
if (it != implRegistry.end())
|
||||
@@ -296,7 +293,7 @@ namespace Fig
|
||||
return parent && parent->hasMethodImplemented(structType, functionName);
|
||||
}
|
||||
|
||||
bool hasDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName) const
|
||||
bool hasDefaultImplementedMethod(const TypeInfo &structType, const String &functionName) const
|
||||
{
|
||||
auto it = implRegistry.find(structType);
|
||||
if (it == implRegistry.end()) return false;
|
||||
@@ -325,7 +322,7 @@ namespace Fig
|
||||
return false;
|
||||
}
|
||||
|
||||
Ast::InterfaceMethod getDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName)
|
||||
Ast::InterfaceMethod getDefaultImplementedMethod(const TypeInfo &structType, const String &functionName)
|
||||
{
|
||||
// O(N²)
|
||||
// SLOW
|
||||
@@ -366,7 +363,7 @@ namespace Fig
|
||||
assert(false);
|
||||
}
|
||||
|
||||
const Function &getImplementedMethod(const TypeInfo &structType, const FString &functionName) const
|
||||
const Function &getImplementedMethod(const TypeInfo &structType, const String &functionName) const
|
||||
{
|
||||
auto it = implRegistry.find(structType);
|
||||
if (it != implRegistry.end())
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Fig
|
||||
{
|
||||
case AstType::ValueExpr: {
|
||||
auto val = std::static_pointer_cast<Ast::ValueExprAst>(exp);
|
||||
|
||||
|
||||
return val->val;
|
||||
}
|
||||
case AstType::VarExpr: {
|
||||
@@ -22,17 +22,17 @@ namespace Fig
|
||||
}
|
||||
case AstType::BinaryExpr: {
|
||||
auto bin = std::static_pointer_cast<Ast::BinaryExprAst>(exp);
|
||||
|
||||
|
||||
return evalBinary(bin, ctx);
|
||||
}
|
||||
case AstType::UnaryExpr: {
|
||||
auto un = std::static_pointer_cast<Ast::UnaryExprAst>(exp);
|
||||
|
||||
|
||||
return evalUnary(un, ctx);
|
||||
}
|
||||
case AstType::TernaryExpr: {
|
||||
auto te = std::static_pointer_cast<Ast::TernaryExprAst>(exp);
|
||||
|
||||
|
||||
return evalTernary(te, ctx);
|
||||
}
|
||||
case AstType::MemberExpr:
|
||||
@@ -44,13 +44,11 @@ namespace Fig
|
||||
}
|
||||
case AstType::FunctionLiteralExpr: {
|
||||
auto fnLiteral = std::static_pointer_cast<Ast::FunctionLiteralExprAst>(exp);
|
||||
|
||||
|
||||
Ast::BlockStatement body = nullptr;
|
||||
if (fnLiteral->isExprMode())
|
||||
{
|
||||
Ast::Expression exprBody = fnLiteral->getExprBody();
|
||||
|
||||
|
||||
const Ast::AstAddressInfo &aai = exprBody->getAAI();
|
||||
Ast::Return st = std::make_shared<Ast::ReturnSt>(exprBody);
|
||||
@@ -63,9 +61,8 @@ namespace Fig
|
||||
else
|
||||
{
|
||||
body = fnLiteral->getBlockBody();
|
||||
|
||||
}
|
||||
Function fn(FString(std::format("<LambdaFn>")),fnLiteral->paras, ValueType::Any, body, ctx
|
||||
Function fn(String(std::format("<LambdaFn>")), fnLiteral->paras, ValueType::Any, body, ctx
|
||||
/*
|
||||
pass the ctx(fnLiteral eval context) as closure context
|
||||
*/
|
||||
@@ -74,13 +71,12 @@ namespace Fig
|
||||
}
|
||||
case AstType::InitExpr: {
|
||||
auto initExpr = std::static_pointer_cast<Ast::InitExprAst>(exp);
|
||||
|
||||
|
||||
return evalInitExpr(initExpr, ctx);
|
||||
}
|
||||
|
||||
case AstType::ListExpr: {
|
||||
auto lstExpr = std::static_pointer_cast<Ast::ListExprAst>(exp);
|
||||
|
||||
|
||||
List list;
|
||||
for (auto &exp : lstExpr->val) { list.push_back(check_unwrap(eval(exp, ctx))); }
|
||||
@@ -89,19 +85,19 @@ namespace Fig
|
||||
|
||||
case AstType::MapExpr: {
|
||||
auto mapExpr = std::static_pointer_cast<Ast::MapExprAst>(exp);
|
||||
|
||||
|
||||
Map map;
|
||||
for (auto &[key, value] : mapExpr->val) {
|
||||
for (auto &[key, value] : mapExpr->val)
|
||||
{
|
||||
map[check_unwrap(eval(key, ctx))] = check_unwrap(eval(value, ctx));
|
||||
}
|
||||
return std::make_shared<Object>(std::move(map));
|
||||
}
|
||||
|
||||
default: {
|
||||
throw RuntimeError(FString(std::format("err type of expr: {}", magic_enum::enum_name(type))));
|
||||
throw RuntimeError(String(std::format("err type of expr: {}", magic_enum::enum_name(type))));
|
||||
}
|
||||
}
|
||||
return Object::getNullInstance(); // ignore warning
|
||||
}
|
||||
};
|
||||
}; // namespace Fig
|
||||
@@ -86,7 +86,7 @@ namespace Fig
|
||||
{
|
||||
ValueType::IntClass lv = lhs->as<ValueType::IntClass>();
|
||||
ValueType::IntClass rv = rhs->as<ValueType::IntClass>();
|
||||
if (rv == 0) { throw ValueError(FString(std::format("Modulo by zero: {} % {}", lv, rv))); }
|
||||
if (rv == 0) { throw ValueError(String(std::format("Modulo by zero: {} % {}", lv, rv))); }
|
||||
ValueType::IntClass result = lv / rv;
|
||||
ValueType::IntClass r = lv % rv;
|
||||
if (r != 0 && ((lv < 0) != (rv < 0))) { result -= 1; }
|
||||
@@ -139,7 +139,7 @@ namespace Fig
|
||||
return Object::getFalseInstance();
|
||||
}
|
||||
|
||||
throw EvaluatorError(u8"TypeError",
|
||||
throw EvaluatorError(U"TypeError",
|
||||
std::format("Unsupported operator `is` for '{}' && '{}'",
|
||||
prettyType(lhs).toBasicString(),
|
||||
prettyType(rhs).toBasicString()),
|
||||
@@ -155,7 +155,7 @@ namespace Fig
|
||||
if (!rhs->is<StructType>())
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"OperatorError",
|
||||
U"OperatorError",
|
||||
std::format("Operator `as` requires right hand side operand a struct type, but got '{}'",
|
||||
prettyType(rhs).toBasicString()),
|
||||
bin->rexp);
|
||||
@@ -183,7 +183,7 @@ namespace Fig
|
||||
}
|
||||
else if (sourceType == ValueType::String)
|
||||
{
|
||||
const FString &str = lhs->as<ValueType::StringClass>();
|
||||
const String &str = lhs->as<ValueType::StringClass>();
|
||||
if (targetType == ValueType::Int)
|
||||
{
|
||||
try
|
||||
@@ -194,10 +194,10 @@ namespace Fig
|
||||
catch (std::exception &e)
|
||||
{
|
||||
return ExprResult::error(
|
||||
genTypeError(FString(std::format("Cannot cast type `{}` to `{}`, bad int string {}",
|
||||
prettyType(lhs).toBasicString(),
|
||||
prettyType(rhs).toBasicString(),
|
||||
str.toBasicString())),
|
||||
genTypeError(String(std::format("Cannot cast type `{}` to `{}`, bad int string {}",
|
||||
prettyType(lhs).toBasicString(),
|
||||
prettyType(rhs).toBasicString(),
|
||||
str.toBasicString())),
|
||||
bin->rexp,
|
||||
ctx));
|
||||
}
|
||||
@@ -211,22 +211,22 @@ namespace Fig
|
||||
catch (std::exception &e)
|
||||
{
|
||||
return ExprResult::error(genTypeError(
|
||||
FString(std::format("Cannot cast type `{}` to `{}`, bad double string {}",
|
||||
prettyType(lhs).toBasicString(),
|
||||
prettyType(rhs).toBasicString(),
|
||||
str.toBasicString())),
|
||||
String(std::format("Cannot cast type `{}` to `{}`, bad double string {}",
|
||||
prettyType(lhs).toBasicString(),
|
||||
prettyType(rhs).toBasicString(),
|
||||
str.toBasicString())),
|
||||
bin->rexp,
|
||||
ctx));
|
||||
}
|
||||
}
|
||||
if (targetType == ValueType::Bool)
|
||||
{
|
||||
if (str == u8"true") { return Object::getTrueInstance(); }
|
||||
else if (str == u8"false") { return Object::getFalseInstance(); }
|
||||
if (str == U"true") { return Object::getTrueInstance(); }
|
||||
else if (str == U"false") { return Object::getFalseInstance(); }
|
||||
return ExprResult::error(
|
||||
genTypeError(FString(std::format("Cannot cast type `{}` to `{}`, bad bool string {}",
|
||||
prettyType(lhs).toBasicString(),
|
||||
prettyType(rhs).toBasicString(),
|
||||
genTypeError(String(std::format("Cannot cast type `{}` to `{}`, bad bool string {}",
|
||||
prettyType(lhs).toBasicString(),
|
||||
prettyType(rhs).toBasicString(),
|
||||
str.toBasicString())),
|
||||
bin->rexp,
|
||||
ctx));
|
||||
@@ -236,17 +236,19 @@ namespace Fig
|
||||
{
|
||||
if (targetType == ValueType::Int)
|
||||
{
|
||||
return IntPool::getInstance().createInt(static_cast<ValueType::IntClass>(lhs->as<ValueType::BoolClass>()));
|
||||
return IntPool::getInstance().createInt(
|
||||
static_cast<ValueType::IntClass>(lhs->as<ValueType::BoolClass>()));
|
||||
}
|
||||
if (targetType == ValueType::Double)
|
||||
{
|
||||
return std::make_shared<Object>(static_cast<ValueType::DoubleClass>(lhs->as<ValueType::BoolClass>()));
|
||||
return std::make_shared<Object>(
|
||||
static_cast<ValueType::DoubleClass>(lhs->as<ValueType::BoolClass>()));
|
||||
}
|
||||
}
|
||||
|
||||
return ExprResult::error(genTypeError(FString(std::format("Cannot cast type `{}` to `{}`",
|
||||
prettyType(lhs).toBasicString(),
|
||||
prettyType(rhs).toBasicString())),
|
||||
return ExprResult::error(genTypeError(String(std::format("Cannot cast type `{}` to `{}`",
|
||||
prettyType(lhs).toBasicString(),
|
||||
prettyType(rhs).toBasicString())),
|
||||
bin->rexp,
|
||||
ctx));
|
||||
});
|
||||
@@ -429,7 +431,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
default:
|
||||
throw EvaluatorError(u8"UnsupportedOp",
|
||||
throw EvaluatorError(U"UnsupportedOp",
|
||||
std::format("Unsupport operator '{}' for binary", magic_enum::enum_name(op)),
|
||||
bin);
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
ExprResult Evaluator::executeFunction(const Function &fn,
|
||||
const Ast::FunctionCallArgs &args,
|
||||
ContextPtr fnCtx) // new context for fn, already filled paras
|
||||
ExprResult Evaluator::executeFunction(const Function &fn,
|
||||
const Ast::FunctionCallArgs &args,
|
||||
ContextPtr fnCtx) // new context for fn, already filled paras
|
||||
{
|
||||
// const FString &fnName = fn.name;
|
||||
// const String &fnName = fn.name;
|
||||
if (fn.type == Function::Builtin || fn.type == Function::MemberType)
|
||||
{
|
||||
if (fn.type == Function::Builtin) { return fn.builtin(args.argv); }
|
||||
@@ -27,14 +27,8 @@ namespace Fig
|
||||
for (const auto &stmt : fn.body->stmts)
|
||||
{
|
||||
StatementResult sr = evalStatement(stmt, fnCtx);
|
||||
if (sr.isError())
|
||||
{
|
||||
handle_error(sr, stmt, fnCtx);
|
||||
}
|
||||
if (!sr.isNormal())
|
||||
{
|
||||
return sr.result;
|
||||
}
|
||||
if (sr.isError()) { handle_error(sr, stmt, fnCtx); }
|
||||
if (!sr.isNormal()) { return sr.result; }
|
||||
}
|
||||
return Object::getNullInstance();
|
||||
}
|
||||
@@ -43,14 +37,14 @@ namespace Fig
|
||||
RvObject fnObj = check_unwrap(eval(call->callee, ctx));
|
||||
if (fnObj->getTypeInfo() != ValueType::Function)
|
||||
{
|
||||
throw EvaluatorError(u8"ObjectNotCallable",
|
||||
throw EvaluatorError(U"ObjectNotCallable",
|
||||
std::format("Object `{}` isn't callable", fnObj->toString().toBasicString()),
|
||||
call->callee);
|
||||
}
|
||||
|
||||
const Function &fn = fnObj->as<Function>();
|
||||
|
||||
const FString &fnName = fn.name;
|
||||
const String &fnName = fn.name;
|
||||
const Ast::FunctionArguments &fnArgs = call->arg;
|
||||
|
||||
Ast::FunctionCallArgs evaluatedArgs;
|
||||
@@ -59,7 +53,7 @@ namespace Fig
|
||||
for (const auto &argExpr : fnArgs.argv) { evaluatedArgs.argv.push_back(check_unwrap(eval(argExpr, ctx))); }
|
||||
if (fn.builtinParamCount != -1 && fn.builtinParamCount != evaluatedArgs.getLength())
|
||||
{
|
||||
throw EvaluatorError(u8"BuiltinArgumentMismatchError",
|
||||
throw EvaluatorError(U"BuiltinArgumentMismatchError",
|
||||
std::format("Builtin function '{}' expects {} arguments, but {} were provided",
|
||||
fnName.toBasicString(),
|
||||
fn.builtinParamCount,
|
||||
@@ -73,7 +67,7 @@ namespace Fig
|
||||
Ast::FunctionParameters fnParas = fn.paras;
|
||||
|
||||
// create new context for function call
|
||||
auto newContext = std::make_shared<Context>(FString(std::format("<Function {}()>", fnName.toBasicString())),
|
||||
auto newContext = std::make_shared<Context>(String(std::format("<Function {}()>", fnName.toBasicString())),
|
||||
fn.closureContext);
|
||||
|
||||
if (fnParas.variadic)
|
||||
@@ -84,24 +78,25 @@ namespace Fig
|
||||
NormalFilling: {
|
||||
if (fnArgs.getLength() < fnParas.posParas.size() || fnArgs.getLength() > fnParas.size())
|
||||
{
|
||||
throw RuntimeError(FString(std::format("Function '{}' expects {} to {} arguments, but {} were provided",
|
||||
fnName.toBasicString(),
|
||||
fnParas.posParas.size(),
|
||||
fnParas.size(),
|
||||
fnArgs.getLength())));
|
||||
throw RuntimeError(String(std::format("Function '{}' expects {} to {} arguments, but {} were provided",
|
||||
fnName.toBasicString(),
|
||||
fnParas.posParas.size(),
|
||||
fnParas.size(),
|
||||
fnArgs.getLength())));
|
||||
}
|
||||
|
||||
// positional parameters type check
|
||||
size_t i;
|
||||
for (i = 0; i < fnParas.posParas.size(); i++)
|
||||
{
|
||||
const TypeInfo &expectedType = actualType(check_unwrap(eval(fnParas.posParas[i].second, fn.closureContext))); // look up type info, if exists a type
|
||||
// with the name, use it, else throw
|
||||
const TypeInfo &expectedType = actualType(check_unwrap(
|
||||
eval(fnParas.posParas[i].second, fn.closureContext))); // look up type info, if exists a type
|
||||
// with the name, use it, else throw
|
||||
ObjectPtr argVal = check_unwrap(eval(fnArgs.argv[i], ctx));
|
||||
TypeInfo actualType = argVal->getTypeInfo();
|
||||
if (!isTypeMatch(expectedType, argVal, fn.closureContext))
|
||||
{
|
||||
throw EvaluatorError(u8"ArgumentTypeMismatchError",
|
||||
throw EvaluatorError(U"ArgumentTypeMismatchError",
|
||||
std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'",
|
||||
fnName.toBasicString(),
|
||||
fnParas.posParas[i].first.toBasicString(),
|
||||
@@ -122,7 +117,7 @@ namespace Fig
|
||||
if (!isTypeMatch(expectedType, defaultVal, fn.closureContext))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"DefaultParameterTypeError",
|
||||
U"DefaultParameterTypeError",
|
||||
std::format(
|
||||
"In function '{}', default parameter '{}' has type '{}', which does not match the expected type '{}'",
|
||||
fnName.toBasicString(),
|
||||
@@ -136,7 +131,7 @@ namespace Fig
|
||||
TypeInfo actualType = argVal->getTypeInfo();
|
||||
if (!isTypeMatch(expectedType, argVal, fn.closureContext))
|
||||
{
|
||||
throw EvaluatorError(u8"ArgumentTypeMismatchError",
|
||||
throw EvaluatorError(U"ArgumentTypeMismatchError",
|
||||
std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'",
|
||||
fnName.toBasicString(),
|
||||
fnParas.defParas[defParamIndex].first.toBasicString(),
|
||||
@@ -157,7 +152,7 @@ namespace Fig
|
||||
// define parameters in new context
|
||||
for (size_t j = 0; j < fnParas.size(); j++)
|
||||
{
|
||||
FString paramName;
|
||||
String paramName;
|
||||
TypeInfo paramType;
|
||||
if (j < fnParas.posParas.size())
|
||||
{
|
||||
@@ -193,7 +188,7 @@ namespace Fig
|
||||
|
||||
if (!isTypeMatch(fn.retType, retVal, ctx))
|
||||
{
|
||||
throw EvaluatorError(u8"ReturnTypeMismatchError",
|
||||
throw EvaluatorError(U"ReturnTypeMismatchError",
|
||||
std::format("Function '{}' expects return type '{}', but got type '{}'",
|
||||
fnName.toBasicString(),
|
||||
fn.retType.toString().toBasicString(),
|
||||
|
||||
@@ -10,10 +10,10 @@ namespace Fig
|
||||
{
|
||||
LvObject structeLv = check_unwrap_lv(evalLv(initExpr->structe, ctx));
|
||||
ObjectPtr structTypeVal = structeLv.get();
|
||||
const FString &structName = structeLv.name();
|
||||
const String &structName = structeLv.name();
|
||||
if (!structTypeVal->is<StructType>())
|
||||
{
|
||||
throw EvaluatorError(u8"NotAStructTypeError",
|
||||
throw EvaluatorError(U"NotAStructTypeError",
|
||||
std::format("'{}' is not a structure type", structName.toBasicString()),
|
||||
initExpr);
|
||||
}
|
||||
@@ -27,7 +27,7 @@ namespace Fig
|
||||
|
||||
if (argSize > 1)
|
||||
{
|
||||
throw EvaluatorError(u8"StructInitArgumentMismatchError",
|
||||
throw EvaluatorError(U"StructInitArgumentMismatchError",
|
||||
std::format("Builtin class `{}` expects 0 or 1 argument, but {} were provided",
|
||||
type.toString().toBasicString(),
|
||||
argSize),
|
||||
@@ -40,7 +40,7 @@ namespace Fig
|
||||
if (type == ValueType::Any || type == ValueType::Null || type == ValueType::Function)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"BuiltinNotConstructibleError",
|
||||
U"BuiltinNotConstructibleError",
|
||||
std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()),
|
||||
initExpr);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ namespace Fig
|
||||
ObjectPtr val = check_unwrap(eval(args[0].second, ctx));
|
||||
|
||||
auto err = [&](const char *msg) {
|
||||
throw EvaluatorError(u8"BuiltinInitTypeMismatchError",
|
||||
throw EvaluatorError(U"BuiltinInitTypeMismatchError",
|
||||
std::format("Builtin `{}` constructor {}", type.toString().toBasicString(), msg),
|
||||
initExpr);
|
||||
};
|
||||
@@ -121,7 +121,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
throw EvaluatorError(
|
||||
u8"BuiltinNotConstructibleError",
|
||||
U"BuiltinNotConstructibleError",
|
||||
std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()),
|
||||
initExpr);
|
||||
}
|
||||
@@ -140,7 +140,7 @@ namespace Fig
|
||||
size_t got = initExpr->args.size();
|
||||
if (got > maxArgs || got < minArgs)
|
||||
{
|
||||
throw EvaluatorError(u8"StructInitArgumentMismatchError",
|
||||
throw EvaluatorError(U"StructInitArgumentMismatchError",
|
||||
std::format("Structure '{}' expects {} to {} fields, but {} were provided",
|
||||
structName.toBasicString(),
|
||||
minArgs,
|
||||
@@ -149,9 +149,9 @@ namespace Fig
|
||||
initExpr);
|
||||
}
|
||||
|
||||
std::vector<std::pair<FString, ObjectPtr>> evaluatedArgs;
|
||||
std::vector<std::pair<String, ObjectPtr>> evaluatedArgs;
|
||||
|
||||
auto evalArguments = [&evaluatedArgs, initExpr, ctx, this](){
|
||||
auto evalArguments = [&evaluatedArgs, initExpr, ctx, this]() {
|
||||
for (const auto &[argName, argExpr] : initExpr->args)
|
||||
{
|
||||
evaluatedArgs.push_back({argName, check_unwrap(eval(argExpr, ctx))});
|
||||
@@ -159,8 +159,8 @@ namespace Fig
|
||||
return ExprResult::normal(Object::getNullInstance());
|
||||
};
|
||||
|
||||
ContextPtr instanceCtx =
|
||||
std::make_shared<Context>(FString(std::format("<StructInstance {}>", structName.toBasicString())), defContext);
|
||||
ContextPtr instanceCtx = std::make_shared<Context>(
|
||||
String(std::format("<StructInstance {}>", structName.toBasicString())), defContext);
|
||||
/*
|
||||
3 ways of calling constructor
|
||||
.1 Person {"Fig", 1, "IDK"};
|
||||
@@ -176,7 +176,7 @@ namespace Fig
|
||||
for (size_t i = 0; i < maxArgs; ++i)
|
||||
{
|
||||
const Field &field = structT.fields[i];
|
||||
const FString &fieldName = field.name;
|
||||
const String &fieldName = field.name;
|
||||
const TypeInfo &expectedType = field.type;
|
||||
if (i >= evaluatedArgs.size())
|
||||
{
|
||||
@@ -191,7 +191,7 @@ namespace Fig
|
||||
if (!isTypeMatch(expectedType, defaultVal, ctx))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"StructFieldTypeMismatchError",
|
||||
U"StructFieldTypeMismatchError",
|
||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||
structName.toBasicString(),
|
||||
fieldName.toBasicString(),
|
||||
@@ -208,7 +208,7 @@ namespace Fig
|
||||
if (!isTypeMatch(expectedType, argVal, ctx))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"StructFieldTypeMismatchError",
|
||||
U"StructFieldTypeMismatchError",
|
||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||
structName.toBasicString(),
|
||||
fieldName.toBasicString(),
|
||||
@@ -227,10 +227,10 @@ namespace Fig
|
||||
for (size_t i = 0; i < maxArgs; ++i)
|
||||
{
|
||||
const Field &field = structT.fields[i];
|
||||
const FString &fieldName = (field.name.empty() ? evaluatedArgs[i].first : field.name);
|
||||
const String &fieldName = (field.name.empty() ? evaluatedArgs[i].first : field.name);
|
||||
if (instanceCtx->containsInThisScope(fieldName))
|
||||
{
|
||||
throw EvaluatorError(u8"StructFieldRedeclarationError",
|
||||
throw EvaluatorError(U"StructFieldRedeclarationError",
|
||||
std::format("Field '{}' already initialized in structure '{}'",
|
||||
fieldName.toBasicString(),
|
||||
structName.toBasicString()),
|
||||
@@ -248,7 +248,7 @@ namespace Fig
|
||||
if (!isTypeMatch(expectedType, defaultVal, ctx))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"StructFieldTypeMismatchError",
|
||||
U"StructFieldTypeMismatchError",
|
||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||
structName.toBasicString(),
|
||||
fieldName.toBasicString(),
|
||||
@@ -264,7 +264,7 @@ namespace Fig
|
||||
if (!isTypeMatch(field.type, argVal, ctx))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"StructFieldTypeMismatchError",
|
||||
U"StructFieldTypeMismatchError",
|
||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||
structName.toBasicString(),
|
||||
fieldName.toBasicString(),
|
||||
@@ -291,7 +291,7 @@ namespace Fig
|
||||
[&argName](const Field &f) { return f.name == argName; });
|
||||
if (fieldIt == structT.fields.end())
|
||||
{
|
||||
// throw EvaluatorError(u8"StructFieldNotFoundError",
|
||||
// throw EvaluatorError(U"StructFieldNotFoundError",
|
||||
// std::format("Field '{}' not found in structure '{}'",
|
||||
// argName.toBasicString(),
|
||||
// structName.toBasicString()),
|
||||
@@ -303,7 +303,7 @@ namespace Fig
|
||||
if (!isTypeMatch(field.type, argVal, ctx))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"StructFieldTypeMismatchError",
|
||||
U"StructFieldTypeMismatchError",
|
||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||
structName.toBasicString(),
|
||||
field.name.toBasicString(),
|
||||
@@ -332,7 +332,7 @@ namespace Fig
|
||||
if (!isTypeMatch(field.type, defaultVal, ctx))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"StructFieldTypeMismatchError",
|
||||
U"StructFieldTypeMismatchError",
|
||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||
structName.toBasicString(),
|
||||
field.name.toBasicString(),
|
||||
@@ -350,9 +350,9 @@ namespace Fig
|
||||
// load struct method
|
||||
for (auto &[id, fn] : stDefCtx->getFunctions())
|
||||
{
|
||||
const FString &funcName = fn.name;
|
||||
const String &funcName = fn.name;
|
||||
const auto &funcSlot = stDefCtx->get(funcName);
|
||||
|
||||
|
||||
instanceCtx->def(funcName,
|
||||
ValueType::Function,
|
||||
funcSlot->am,
|
||||
@@ -361,4 +361,4 @@ namespace Fig
|
||||
|
||||
return std::make_shared<Object>(StructInstance(structT.type, instanceCtx));
|
||||
}
|
||||
};
|
||||
}; // namespace Fig
|
||||
@@ -8,7 +8,7 @@ namespace Fig
|
||||
{
|
||||
ExprResult Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx)
|
||||
{
|
||||
const FString &name = var->name;
|
||||
const String &name = var->name;
|
||||
|
||||
// 调试信息
|
||||
// std::cerr << "=== DEBUG evalVarExpr ===" << std::endl;
|
||||
@@ -38,14 +38,14 @@ namespace Fig
|
||||
// }
|
||||
// end
|
||||
|
||||
if (!ctx->contains(name)) { throw EvaluatorError(u8"UndeclaredIdentifierError", name, var); }
|
||||
if (!ctx->contains(name)) { throw EvaluatorError(U"UndeclaredIdentifierError", name, var); }
|
||||
return LvObject(ctx->get(name), ctx);
|
||||
}
|
||||
ExprResult Evaluator::evalMemberExpr(Ast::MemberExpr me, ContextPtr ctx)
|
||||
{
|
||||
// LvObject base = evalLv(me->base, ctx);
|
||||
RvObject baseVal = check_unwrap(eval(me->base, ctx));
|
||||
const FString &member = me->member;
|
||||
const String &member = me->member;
|
||||
if (baseVal->getTypeInfo() == ValueType::Module)
|
||||
{
|
||||
// std::cerr << "=== DEBUG evalMemberExpr (Module) ===" << std::endl;
|
||||
@@ -74,7 +74,7 @@ namespace Fig
|
||||
}
|
||||
else
|
||||
{
|
||||
throw EvaluatorError(u8"VariableNotFoundError",
|
||||
throw EvaluatorError(U"VariableNotFoundError",
|
||||
std::format("`{}` has not variable '{}', check if it is public",
|
||||
baseVal->toString().toBasicString(),
|
||||
member.toBasicString()),
|
||||
@@ -118,7 +118,7 @@ namespace Fig
|
||||
if (baseVal->getTypeInfo() != ValueType::StructInstance) // and not member function found
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"NoAttributeError",
|
||||
U"NoAttributeError",
|
||||
std::format("`{}` has not attribute '{}'", baseVal->toString().toBasicString(), member.toBasicString()),
|
||||
me->base);
|
||||
}
|
||||
@@ -153,7 +153,7 @@ namespace Fig
|
||||
}
|
||||
else
|
||||
{
|
||||
throw EvaluatorError(u8"NoAttributeError",
|
||||
throw EvaluatorError(U"NoAttributeError",
|
||||
std::format("`{}` has not attribute '{}' and no interfaces have been implemented it",
|
||||
baseVal->toString().toBasicString(),
|
||||
member.toBasicString()),
|
||||
@@ -172,7 +172,7 @@ namespace Fig
|
||||
if (index->getTypeInfo() != ValueType::Int)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"TypeError",
|
||||
U"TypeError",
|
||||
std::format("Type `List` indices must be `Int`, got '{}'", prettyType(index).toBasicString()),
|
||||
ie->index);
|
||||
}
|
||||
@@ -181,7 +181,7 @@ namespace Fig
|
||||
if (indexVal >= list.size())
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"IndexOutOfRangeError",
|
||||
U"IndexOutOfRangeError",
|
||||
std::format("Index {} out of list `{}` range", indexVal, base->toString().toBasicString()),
|
||||
ie->index);
|
||||
}
|
||||
@@ -193,16 +193,16 @@ namespace Fig
|
||||
if (index->getTypeInfo() != ValueType::Int)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"TypeError",
|
||||
U"TypeError",
|
||||
std::format("Type `String` indices must be `Int`, got '{}'", prettyType(index).toBasicString()),
|
||||
ie->index);
|
||||
}
|
||||
FString &string = base->as<ValueType::StringClass>();
|
||||
String &string = base->as<ValueType::StringClass>();
|
||||
ValueType::IntClass indexVal = index->as<ValueType::IntClass>();
|
||||
if (indexVal >= string.length())
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"IndexOutOfRangeError",
|
||||
U"IndexOutOfRangeError",
|
||||
std::format("Index {} out of string `{}` range", indexVal, base->toString().toBasicString()),
|
||||
ie->index);
|
||||
}
|
||||
@@ -211,7 +211,7 @@ namespace Fig
|
||||
else
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"NoSubscriptableError",
|
||||
U"NoSubscriptableError",
|
||||
std::format("`{}` object is not subscriptable", base->getTypeInfo().toString().toBasicString()),
|
||||
ie->base);
|
||||
}
|
||||
@@ -239,7 +239,7 @@ namespace Fig
|
||||
}
|
||||
default: {
|
||||
throw EvaluatorError(
|
||||
u8"TypeError",
|
||||
U"TypeError",
|
||||
std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()),
|
||||
exp);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <Ast/Expressions/FunctionCall.hpp>
|
||||
#include <Ast/astBase.hpp>
|
||||
#include <Ast/functionParameters.hpp>
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Core/String.hpp>
|
||||
#include <Evaluator/Core/StatementResult.hpp>
|
||||
#include <Evaluator/Value/Type.hpp>
|
||||
#include <Evaluator/Value/structType.hpp>
|
||||
@@ -32,7 +32,7 @@ namespace Fig
|
||||
if (ctx->containsInThisScope(varDef->name))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"RedeclarationError",
|
||||
U"RedeclarationError",
|
||||
std::format("Variable `{}` already declared in this scope", varDef->name.toBasicString()),
|
||||
varDef);
|
||||
}
|
||||
@@ -51,7 +51,7 @@ namespace Fig
|
||||
|
||||
if (value != nullptr && !isTypeMatch(declaredType, value, ctx))
|
||||
{
|
||||
throw EvaluatorError(u8"TypeError",
|
||||
throw EvaluatorError(U"TypeError",
|
||||
std::format("Variable `{}` expects init-value type `{}`, but got '{}'",
|
||||
varDef->name.toBasicString(),
|
||||
prettyType(declaredTypeValue).toBasicString(),
|
||||
@@ -73,11 +73,11 @@ namespace Fig
|
||||
case FunctionDefSt: {
|
||||
auto fnDef = std::static_pointer_cast<Ast::FunctionDefSt>(stmt);
|
||||
|
||||
const FString &fnName = fnDef->name;
|
||||
const String &fnName = fnDef->name;
|
||||
if (ctx->containsInThisScope(fnName))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"RedeclarationError",
|
||||
U"RedeclarationError",
|
||||
std::format("Function `{}` already declared in this scope", fnName.toBasicString()),
|
||||
fnDef);
|
||||
}
|
||||
@@ -102,16 +102,16 @@ namespace Fig
|
||||
if (ctx->containsInThisScope(stDef->name))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"RedeclarationError",
|
||||
U"RedeclarationError",
|
||||
std::format("Structure '{}' already defined in this scope", stDef->name.toBasicString()),
|
||||
stDef);
|
||||
}
|
||||
|
||||
TypeInfo type(stDef->name, true); // register type name
|
||||
ContextPtr defContext = std::make_shared<Context>(FString(std::format("<Struct {} at {}:{}>",
|
||||
stDef->name.toBasicString(),
|
||||
stDef->getAAI().line,
|
||||
stDef->getAAI().column)),
|
||||
ContextPtr defContext = std::make_shared<Context>(String(std::format("<Struct {} at {}:{}>",
|
||||
stDef->name.toBasicString(),
|
||||
stDef->getAAI().line,
|
||||
stDef->getAAI().column)),
|
||||
ctx);
|
||||
ObjectPtr structTypeObj = std::make_shared<Object>(StructType(type, defContext, {}));
|
||||
|
||||
@@ -124,12 +124,12 @@ namespace Fig
|
||||
structTypeObj); // predef to itself, always const
|
||||
|
||||
std::vector<Field> fields;
|
||||
std::vector<FString> _fieldNames;
|
||||
std::vector<String> _fieldNames;
|
||||
for (Ast::StructDefField field : stDef->fields)
|
||||
{
|
||||
if (Utils::vectorContains(field.fieldName, _fieldNames))
|
||||
{
|
||||
throw EvaluatorError(u8"RedeclarationError",
|
||||
throw EvaluatorError(U"RedeclarationError",
|
||||
std::format("Field '{}' already defined in structure '{}'",
|
||||
field.fieldName.toBasicString(),
|
||||
stDef->name.toBasicString()),
|
||||
@@ -151,7 +151,7 @@ namespace Fig
|
||||
{
|
||||
if (st->getType() != Ast::AstType::FunctionDefSt)
|
||||
{
|
||||
throw EvaluatorError(u8"UnexpectedStatementInStructError",
|
||||
throw EvaluatorError(U"UnexpectedStatementInStructError",
|
||||
std::format("Unexpected statement `{}` in struct declaration",
|
||||
st->toString().toBasicString()),
|
||||
st);
|
||||
@@ -164,12 +164,12 @@ namespace Fig
|
||||
case InterfaceDefSt: {
|
||||
auto ifd = std::static_pointer_cast<Ast::InterfaceDefAst>(stmt);
|
||||
|
||||
const FString &interfaceName = ifd->name;
|
||||
const String &interfaceName = ifd->name;
|
||||
|
||||
if (ctx->containsInThisScope(interfaceName))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"RedeclarationError",
|
||||
U"RedeclarationError",
|
||||
std::format("Interface `{}` already declared in this scope", interfaceName.toBasicString()),
|
||||
ifd);
|
||||
}
|
||||
@@ -188,7 +188,7 @@ namespace Fig
|
||||
TypeInfo interfaceType(ip->interfaceName);
|
||||
if (ctx->hasImplRegisted(structType, interfaceType))
|
||||
{
|
||||
throw EvaluatorError(u8"DuplicateImplError",
|
||||
throw EvaluatorError(U"DuplicateImplError",
|
||||
std::format("Duplicate implement `{}` for `{}`",
|
||||
interfaceType.toString().toBasicString(),
|
||||
structType.toString().toBasicString()),
|
||||
@@ -196,13 +196,13 @@ namespace Fig
|
||||
}
|
||||
if (!ctx->contains(ip->interfaceName))
|
||||
{
|
||||
throw EvaluatorError(u8"InterfaceNotFoundError",
|
||||
throw EvaluatorError(U"InterfaceNotFoundError",
|
||||
std::format("Interface '{}' not found", ip->interfaceName.toBasicString()),
|
||||
ip);
|
||||
}
|
||||
if (!ctx->contains(ip->structName))
|
||||
{
|
||||
throw EvaluatorError(u8"StructNotFoundError",
|
||||
throw EvaluatorError(U"StructNotFoundError",
|
||||
std::format("Struct '{}' not found", ip->structName.toBasicString()),
|
||||
ip);
|
||||
}
|
||||
@@ -218,21 +218,21 @@ namespace Fig
|
||||
if (!interfaceObj->is<InterfaceType>())
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"NotAInterfaceError",
|
||||
U"NotAInterfaceError",
|
||||
std::format("Variable `{}` is not a interface", ip->interfaceName.toBasicString()),
|
||||
ip);
|
||||
}
|
||||
if (!structTypeObj->is<StructType>())
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"NotAStructType",
|
||||
U"NotAStructType",
|
||||
std::format("Variable `{}` is not a struct type", ip->structName.toBasicString()),
|
||||
ip);
|
||||
}
|
||||
|
||||
auto &implementMethods = ip->methods;
|
||||
|
||||
if (ip->interfaceName == u8"Operation")
|
||||
if (ip->interfaceName == U"Operation")
|
||||
{
|
||||
// 运算符重载
|
||||
/*
|
||||
@@ -243,52 +243,52 @@ namespace Fig
|
||||
*/
|
||||
if (ValueType::isTypeBuiltin(structType))
|
||||
{
|
||||
throw EvaluatorError(u8"BadUserError",
|
||||
throw EvaluatorError(U"BadUserError",
|
||||
std::format("Don't overload built-in type operators plz! `{}`",
|
||||
prettyType(structTypeObj).toBasicString()),
|
||||
ip);
|
||||
}
|
||||
|
||||
using enum Ast::Operator;
|
||||
static const std::unordered_map<FString, std::pair<Ast::Operator, size_t>> magic_name_to_op = {
|
||||
static const std::unordered_map<String, std::pair<Ast::Operator, size_t>> magic_name_to_op = {
|
||||
// 算术
|
||||
{u8"Add", {Ast::Operator::Add, 2}},
|
||||
{u8"Sub", {Ast::Operator::Subtract, 2}},
|
||||
{u8"Mul", {Ast::Operator::Multiply, 2}},
|
||||
{u8"Div", {Ast::Operator::Divide, 2}},
|
||||
{u8"Mod", {Ast::Operator::Modulo, 2}},
|
||||
{u8"Pow", {Ast::Operator::Power, 2}},
|
||||
{U"Add", {Ast::Operator::Add, 2}},
|
||||
{U"Sub", {Ast::Operator::Subtract, 2}},
|
||||
{U"Mul", {Ast::Operator::Multiply, 2}},
|
||||
{U"Div", {Ast::Operator::Divide, 2}},
|
||||
{U"Mod", {Ast::Operator::Modulo, 2}},
|
||||
{U"Pow", {Ast::Operator::Power, 2}},
|
||||
|
||||
// 逻辑(一元)
|
||||
{u8"Neg", {Ast::Operator::Subtract, 1}}, // 一元负号
|
||||
{u8"Not", {Ast::Operator::Not, 1}},
|
||||
{U"Neg", {Ast::Operator::Subtract, 1}}, // 一元负号
|
||||
{U"Not", {Ast::Operator::Not, 1}},
|
||||
|
||||
// 逻辑(二元)
|
||||
{u8"And", {Ast::Operator::And, 2}},
|
||||
{u8"Or", {Ast::Operator::Or, 2}},
|
||||
{U"And", {Ast::Operator::And, 2}},
|
||||
{U"Or", {Ast::Operator::Or, 2}},
|
||||
|
||||
// 比较
|
||||
{u8"Equal", {Ast::Operator::Equal, 2}},
|
||||
{u8"NotEqual", {Ast::Operator::NotEqual, 2}},
|
||||
{u8"LessThan", {Ast::Operator::Less, 2}},
|
||||
{u8"LessEqual", {Ast::Operator::LessEqual, 2}},
|
||||
{u8"GreaterThan", {Ast::Operator::Greater, 2}},
|
||||
{u8"GreaterEqual", {Ast::Operator::GreaterEqual, 2}},
|
||||
{u8"Is", {Ast::Operator::Is, 2}},
|
||||
{U"Equal", {Ast::Operator::Equal, 2}},
|
||||
{U"NotEqual", {Ast::Operator::NotEqual, 2}},
|
||||
{U"LessThan", {Ast::Operator::Less, 2}},
|
||||
{U"LessEqual", {Ast::Operator::LessEqual, 2}},
|
||||
{U"GreaterThan", {Ast::Operator::Greater, 2}},
|
||||
{U"GreaterEqual", {Ast::Operator::GreaterEqual, 2}},
|
||||
{U"Is", {Ast::Operator::Is, 2}},
|
||||
|
||||
// 位运算(一元)
|
||||
{u8"BitNot", {Ast::Operator::BitNot, 1}},
|
||||
{U"BitNot", {Ast::Operator::BitNot, 1}},
|
||||
|
||||
// 位运算(二元)
|
||||
{u8"BitAnd", {Ast::Operator::BitAnd, 2}},
|
||||
{u8"BitOr", {Ast::Operator::BitOr, 2}},
|
||||
{u8"BitXor", {Ast::Operator::BitXor, 2}},
|
||||
{u8"ShiftLeft", {Ast::Operator::ShiftLeft, 2}},
|
||||
{u8"ShiftRight", {Ast::Operator::ShiftRight, 2}},
|
||||
{U"BitAnd", {Ast::Operator::BitAnd, 2}},
|
||||
{U"BitOr", {Ast::Operator::BitOr, 2}},
|
||||
{U"BitXor", {Ast::Operator::BitXor, 2}},
|
||||
{U"ShiftLeft", {Ast::Operator::ShiftLeft, 2}},
|
||||
{U"ShiftRight", {Ast::Operator::ShiftRight, 2}},
|
||||
};
|
||||
for (auto &implMethod : implementMethods)
|
||||
{
|
||||
const FString &opName = implMethod.name;
|
||||
const String &opName = implMethod.name;
|
||||
if (!magic_name_to_op.contains(opName))
|
||||
{
|
||||
// ... 现在忽略
|
||||
@@ -303,7 +303,7 @@ namespace Fig
|
||||
if (ctx->hasOperatorImplemented(structType, op, (expectArgCnt == 1 ? true : false)))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"DuplicateImplementError",
|
||||
U"DuplicateImplementError",
|
||||
std::format("{} has already implement by another interface", opName.toBasicString()),
|
||||
ip);
|
||||
}
|
||||
@@ -312,7 +312,7 @@ namespace Fig
|
||||
if (paraCnt != expectArgCnt || implMethod.paras.size() != expectArgCnt)
|
||||
{
|
||||
// 特化报错,更详细易读
|
||||
throw EvaluatorError(u8"InterfaceSignatureMismatch",
|
||||
throw EvaluatorError(U"InterfaceSignatureMismatch",
|
||||
std::format("Operator {} for {} arg count must be {}, got {}",
|
||||
opName.toBasicString(),
|
||||
structLv.name().toBasicString(),
|
||||
@@ -321,10 +321,10 @@ namespace Fig
|
||||
ip);
|
||||
}
|
||||
|
||||
FString opFnName(u8"Operation." + prettyType(structTypeObj) + u8"." + opName);
|
||||
String opFnName(U"Operation." + prettyType(structTypeObj) + U"." + opName);
|
||||
|
||||
ContextPtr fnCtx = std::make_shared<Context>(
|
||||
FString(std::format("<Function {}>", opFnName.toBasicString())), ctx);
|
||||
String(std::format("<Function {}>", opFnName.toBasicString())), ctx);
|
||||
|
||||
const auto &fillOpFnParas = [this, structType, implMethod, opFnName, fnCtx, ctx, paraCnt](
|
||||
const std::vector<ObjectPtr> &args) {
|
||||
@@ -336,7 +336,7 @@ namespace Fig
|
||||
if (paraType != ValueType::Any && paraType != structType)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"ParameterTypeError",
|
||||
U"ParameterTypeError",
|
||||
std::format("Invalid op fn parameter type '{}' of `{}`, must be `{}`",
|
||||
paraType.toString().toBasicString(),
|
||||
paras.posParas[i].first.toBasicString(),
|
||||
@@ -385,12 +385,12 @@ namespace Fig
|
||||
// ===== interface implementation validation =====
|
||||
ImplRecord record{interfaceType, structType, {}};
|
||||
|
||||
std::unordered_map<FString, Ast::InterfaceMethod> ifaceMethods;
|
||||
std::unordered_map<String, Ast::InterfaceMethod> ifaceMethods;
|
||||
for (auto &m : interface.methods)
|
||||
{
|
||||
if (ifaceMethods.contains(m.name))
|
||||
{
|
||||
throw EvaluatorError(u8"InterfaceDuplicateMethodError",
|
||||
throw EvaluatorError(U"InterfaceDuplicateMethodError",
|
||||
std::format("Interface '{}' has duplicate method '{}'",
|
||||
interfaceType.toString().toBasicString(),
|
||||
m.name.toBasicString()),
|
||||
@@ -399,16 +399,16 @@ namespace Fig
|
||||
ifaceMethods[m.name] = m;
|
||||
}
|
||||
|
||||
std::unordered_set<FString> implemented;
|
||||
std::unordered_set<String> implemented;
|
||||
|
||||
for (auto &implMethod : implementMethods)
|
||||
{
|
||||
const FString &name = implMethod.name;
|
||||
const String &name = implMethod.name;
|
||||
|
||||
// ---- redundant impl ----
|
||||
if (!ifaceMethods.contains(name))
|
||||
{
|
||||
throw EvaluatorError(u8"RedundantImplementationError",
|
||||
throw EvaluatorError(U"RedundantImplementationError",
|
||||
std::format("Struct '{}' implements extra method '{}' "
|
||||
"which is not required by interface '{}'",
|
||||
structType.toString().toBasicString(),
|
||||
@@ -419,7 +419,7 @@ namespace Fig
|
||||
|
||||
if (implemented.contains(name))
|
||||
{
|
||||
throw EvaluatorError(u8"DuplicateImplementMethodError",
|
||||
throw EvaluatorError(U"DuplicateImplementMethodError",
|
||||
std::format("Duplicate implement method '{}'", name.toBasicString()),
|
||||
ip);
|
||||
}
|
||||
@@ -429,7 +429,7 @@ namespace Fig
|
||||
// ---- signature check ----
|
||||
if (!isInterfaceSignatureMatch(implMethod, ifMethod))
|
||||
{
|
||||
throw EvaluatorError(u8"InterfaceSignatureMismatch",
|
||||
throw EvaluatorError(U"InterfaceSignatureMismatch",
|
||||
std::format("Interface method '{}({})' signature mismatch with "
|
||||
"implementation '{}({})'",
|
||||
ifMethod.name.toBasicString(),
|
||||
@@ -441,7 +441,7 @@ namespace Fig
|
||||
|
||||
if (ctx->hasMethodImplemented(structType, name))
|
||||
{
|
||||
throw EvaluatorError(u8"DuplicateImplementMethodError",
|
||||
throw EvaluatorError(U"DuplicateImplementMethodError",
|
||||
std::format("Method '{}' already implemented by another interface "
|
||||
"for struct '{}'",
|
||||
name.toBasicString(),
|
||||
@@ -463,7 +463,7 @@ namespace Fig
|
||||
|
||||
if (m.hasDefaultBody()) continue;
|
||||
|
||||
throw EvaluatorError(u8"MissingImplementationError",
|
||||
throw EvaluatorError(U"MissingImplementationError",
|
||||
std::format("Struct '{}' does not implement required interface method '{}' "
|
||||
"and interface '{}' provides no default implementation",
|
||||
structType.toString().toBasicString(),
|
||||
@@ -482,7 +482,7 @@ namespace Fig
|
||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"TypeError",
|
||||
U"TypeError",
|
||||
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
||||
ifSt->condition);
|
||||
}
|
||||
@@ -494,7 +494,7 @@ namespace Fig
|
||||
if (elifCondVal->getTypeInfo() != ValueType::Bool)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"TypeError",
|
||||
U"TypeError",
|
||||
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
||||
ifSt->condition);
|
||||
}
|
||||
@@ -511,13 +511,13 @@ namespace Fig
|
||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"TypeError",
|
||||
U"TypeError",
|
||||
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
||||
whileSt->condition);
|
||||
}
|
||||
if (!condVal->as<ValueType::BoolClass>()) { break; }
|
||||
ContextPtr loopContext = std::make_shared<Context>(
|
||||
FString(std::format("<While {}:{}>", whileSt->getAAI().line, whileSt->getAAI().column)),
|
||||
String(std::format("<While {}:{}>", whileSt->getAAI().line, whileSt->getAAI().column)),
|
||||
ctx); // every loop has its own context
|
||||
StatementResult sr = evalBlockStatement(whileSt->body, loopContext);
|
||||
if (sr.shouldReturn()) { return sr; }
|
||||
@@ -529,7 +529,7 @@ namespace Fig
|
||||
case ForSt: {
|
||||
auto forSt = std::static_pointer_cast<Ast::ForSt>(stmt);
|
||||
ContextPtr loopContext = std::make_shared<Context>(
|
||||
FString(std::format("<For {}:{}>", forSt->getAAI().line, forSt->getAAI().column)),
|
||||
String(std::format("<For {}:{}>", forSt->getAAI().line, forSt->getAAI().column)),
|
||||
ctx); // for loop has its own context
|
||||
|
||||
evalStatement(forSt->initSt,
|
||||
@@ -543,14 +543,14 @@ namespace Fig
|
||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"TypeError",
|
||||
U"TypeError",
|
||||
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
||||
forSt->condition);
|
||||
}
|
||||
if (!condVal->as<ValueType::BoolClass>()) { break; }
|
||||
iteration++;
|
||||
ContextPtr iterationContext = std::make_shared<Context>(
|
||||
FString(std::format(
|
||||
String(std::format(
|
||||
"<For {}:{}, Iteration {}>", forSt->getAAI().line, forSt->getAAI().column, iteration)),
|
||||
loopContext); // every loop has its own context
|
||||
StatementResult sr = evalBlockStatement(forSt->body, iterationContext);
|
||||
@@ -571,7 +571,7 @@ namespace Fig
|
||||
auto tryst = std::static_pointer_cast<Ast::TrySt>(stmt);
|
||||
|
||||
ContextPtr tryCtx = std::make_shared<Context>(
|
||||
FString(std::format("<Try at {}:{}>", tryst->getAAI().line, tryst->getAAI().column)), ctx);
|
||||
String(std::format("<Try at {}:{}>", tryst->getAAI().line, tryst->getAAI().column)), ctx);
|
||||
StatementResult sr = StatementResult::normal();
|
||||
bool crashed = false;
|
||||
for (auto &stmt : tryst->body->stmts)
|
||||
@@ -586,13 +586,12 @@ namespace Fig
|
||||
bool catched = false;
|
||||
for (auto &cat : tryst->catches)
|
||||
{
|
||||
const FString &errVarName = cat.errVarName;
|
||||
const String &errVarName = cat.errVarName;
|
||||
TypeInfo errVarType = (cat.hasType ? TypeInfo(cat.errVarType) : ValueType::Any);
|
||||
if (isTypeMatch(errVarType, sr.result, ctx))
|
||||
{
|
||||
ContextPtr catchCtx = std::make_shared<Context>(
|
||||
FString(
|
||||
std::format("<Catch at {}:{}>", cat.body->getAAI().line, cat.body->getAAI().column)),
|
||||
String(std::format("<Catch at {}:{}>", cat.body->getAAI().line, cat.body->getAAI().column)),
|
||||
ctx);
|
||||
catchCtx->def(errVarName, errVarType, AccessModifier::Normal, sr.result);
|
||||
sr = evalBlockStatement(cat.body, catchCtx);
|
||||
@@ -602,7 +601,7 @@ namespace Fig
|
||||
}
|
||||
if (!catched && crashed)
|
||||
{
|
||||
throw EvaluatorError(u8"UncaughtExceptionError",
|
||||
throw EvaluatorError(U"UncaughtExceptionError",
|
||||
std::format("Uncaught exception: {}", sr.result->toString().toBasicString()),
|
||||
tryst);
|
||||
}
|
||||
@@ -616,7 +615,7 @@ namespace Fig
|
||||
ObjectPtr value = check_unwrap_stres(eval(ts->value, ctx));
|
||||
if (value->is<ValueType::NullClass>())
|
||||
{
|
||||
throw EvaluatorError(u8"TypeError", u8"Why did you throw a null?", ts);
|
||||
throw EvaluatorError(U"TypeError", U"Why did you throw a null?", ts);
|
||||
}
|
||||
return StatementResult::errorFlow(value);
|
||||
}
|
||||
@@ -632,11 +631,11 @@ namespace Fig
|
||||
case BreakSt: {
|
||||
if (!ctx->parent)
|
||||
{
|
||||
throw EvaluatorError(u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt);
|
||||
throw EvaluatorError(U"BreakOutsideLoopError", U"`break` statement outside loop", stmt);
|
||||
}
|
||||
if (!ctx->isInLoopContext())
|
||||
{
|
||||
throw EvaluatorError(u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt);
|
||||
throw EvaluatorError(U"BreakOutsideLoopError", U"`break` statement outside loop", stmt);
|
||||
}
|
||||
return StatementResult::breakFlow();
|
||||
}
|
||||
@@ -644,11 +643,11 @@ namespace Fig
|
||||
case ContinueSt: {
|
||||
if (!ctx->parent)
|
||||
{
|
||||
throw EvaluatorError(u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt);
|
||||
throw EvaluatorError(U"ContinueOutsideLoopError", U"`continue` statement outside loop", stmt);
|
||||
}
|
||||
if (!ctx->isInLoopContext())
|
||||
{
|
||||
throw EvaluatorError(u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt);
|
||||
throw EvaluatorError(U"ContinueOutsideLoopError", U"`continue` statement outside loop", stmt);
|
||||
}
|
||||
return StatementResult::continueFlow();
|
||||
}
|
||||
@@ -662,13 +661,13 @@ namespace Fig
|
||||
auto block = std::static_pointer_cast<Ast::BlockStatementAst>(stmt);
|
||||
|
||||
ContextPtr blockCtx = std::make_shared<Context>(
|
||||
FString(std::format("<Block at {}:{}>", block->getAAI().line, block->getAAI().column)), ctx);
|
||||
String(std::format("<Block at {}:{}>", block->getAAI().line, block->getAAI().column)), ctx);
|
||||
return evalBlockStatement(block, blockCtx);
|
||||
}
|
||||
|
||||
default:
|
||||
throw RuntimeError(
|
||||
FString(std::format("Feature stmt {} unsupported yet", magic_enum::enum_name(stmt->getType()))));
|
||||
String(std::format("Feature stmt {} unsupported yet", magic_enum::enum_name(stmt->getType()))));
|
||||
}
|
||||
}
|
||||
}; // namespace Fig
|
||||
@@ -11,7 +11,7 @@ namespace Fig
|
||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"TypeError",
|
||||
U"TypeError",
|
||||
std::format("Condition must be boolean, got '{}'", prettyType(condVal).toBasicString()),
|
||||
te->condition);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Fig
|
||||
return tryInvokeOverloadFn(value, [value]() { return std::make_shared<Object>(bit_not(*value)); });
|
||||
}
|
||||
default: {
|
||||
throw EvaluatorError(u8"UnsupportedOpError",
|
||||
throw EvaluatorError(U"UnsupportedOpError",
|
||||
std::format("Unsupported op '{}' for unary expression", magic_enum::enum_name(op)),
|
||||
un);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Core/String.hpp>
|
||||
#include <Evaluator/Value/value_forward.hpp>
|
||||
#include <Evaluator/Value/LvObject.hpp>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
namespace Fig
|
||||
{
|
||||
|
||||
std::filesystem::path Evaluator::resolveModulePath(const std::vector<FString> &pathVec)
|
||||
std::filesystem::path Evaluator::resolveModulePath(const std::vector<String> &pathVec)
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -32,13 +32,13 @@ namespace Fig
|
||||
import comp.config;
|
||||
*/
|
||||
|
||||
const FString &modPathStrTop = pathVec.at(0);
|
||||
const String &modPathStrTop = pathVec.at(0);
|
||||
fs::path modPath;
|
||||
|
||||
bool found = false;
|
||||
for (auto &parentFolder : pathToFind)
|
||||
{
|
||||
modPath = parentFolder / FString(modPathStrTop + u8".fig").toBasicString();
|
||||
modPath = parentFolder / String(modPathStrTop + U".fig").toBasicString();
|
||||
if (fs::exists(modPath))
|
||||
{
|
||||
path = modPath;
|
||||
@@ -50,16 +50,16 @@ namespace Fig
|
||||
modPath = parentFolder / modPathStrTop.toBasicString();
|
||||
if (fs::is_directory(modPath)) // comp is a directory
|
||||
{
|
||||
modPath = modPath / FString(modPathStrTop + u8".fig").toBasicString();
|
||||
modPath = modPath / String(modPathStrTop + U".fig").toBasicString();
|
||||
/*
|
||||
if module name is a directory, we require [module
|
||||
name].fig at the directory
|
||||
*/
|
||||
if (!fs::exists(modPath))
|
||||
{
|
||||
throw RuntimeError(FString(std::format("requires module file, {}\\{}",
|
||||
modPathStrTop.toBasicString(),
|
||||
FString(modPathStrTop + u8".fig").toBasicString())));
|
||||
throw RuntimeError(String(std::format("requires module file, {}\\{}",
|
||||
modPathStrTop.toBasicString(),
|
||||
String(modPathStrTop + U".fig").toBasicString())));
|
||||
}
|
||||
found = true;
|
||||
path = modPath;
|
||||
@@ -69,19 +69,19 @@ namespace Fig
|
||||
}
|
||||
|
||||
if (!found)
|
||||
throw RuntimeError(FString(std::format("Could not find module `{}`", modPathStrTop.toBasicString())));
|
||||
throw RuntimeError(String(std::format("Could not find module `{}`", modPathStrTop.toBasicString())));
|
||||
|
||||
bool found2 = false;
|
||||
|
||||
for (size_t i = 1; i < pathVec.size(); ++i) // has next module
|
||||
{
|
||||
const FString &next = pathVec.at(i);
|
||||
const String &next = pathVec.at(i);
|
||||
modPath = modPath.parent_path(); // get the folder
|
||||
modPath = modPath / FString(next + u8".fig").toBasicString();
|
||||
modPath = modPath / String(next + U".fig").toBasicString();
|
||||
if (fs::exists(modPath))
|
||||
{
|
||||
if (i != pathVec.size() - 1)
|
||||
throw RuntimeError(FString(std::format(
|
||||
throw RuntimeError(String(std::format(
|
||||
"expects {} as parent directory and find next module, but got a file", next.toBasicString())));
|
||||
// it's the last module
|
||||
found2 = true;
|
||||
@@ -91,14 +91,14 @@ namespace Fig
|
||||
// `next` is a folder
|
||||
modPath = modPath.parent_path() / next.toBasicString();
|
||||
if (!fs::exists(modPath))
|
||||
throw RuntimeError(FString(std::format("Could not find module `{}`", next.toBasicString())));
|
||||
throw RuntimeError(String(std::format("Could not find module `{}`", next.toBasicString())));
|
||||
if (i == pathVec.size() - 1)
|
||||
{
|
||||
// `next` is the last module
|
||||
modPath = modPath / FString(next + u8".fig").toBasicString();
|
||||
modPath = modPath / String(next + U".fig").toBasicString();
|
||||
if (!fs::exists(modPath))
|
||||
{
|
||||
throw RuntimeError(FString(std::format(
|
||||
throw RuntimeError(String(std::format(
|
||||
"expects {} as parent directory and find next module, but got a file", next.toBasicString())));
|
||||
}
|
||||
found2 = true;
|
||||
@@ -107,8 +107,8 @@ namespace Fig
|
||||
}
|
||||
|
||||
if (!found2 && !fs::exists(modPath))
|
||||
throw RuntimeError(FString(std::format("Could not find module `{}`", pathVec.end()->toBasicString())));
|
||||
throw RuntimeError(String(std::format("Could not find module `{}`", pathVec.end()->toBasicString())));
|
||||
|
||||
return path;
|
||||
}
|
||||
};
|
||||
}; // namespace Fig
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Core/String.hpp>
|
||||
#include <Evaluator/Value/value.hpp>
|
||||
|
||||
namespace Fig
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Evaluator/Value/value.hpp>
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Core/String.hpp>
|
||||
#include <Evaluator/Value/value_forward.hpp>
|
||||
#include <Evaluator/Value/Type.hpp>
|
||||
#include <array>
|
||||
|
||||
@@ -24,18 +24,15 @@ namespace Fig
|
||||
|
||||
ContextPtr ctx;
|
||||
|
||||
LvObject(std::shared_ptr<VariableSlot> _slot, ContextPtr _ctx) :
|
||||
slot(std::move(_slot)), ctx(_ctx)
|
||||
LvObject(std::shared_ptr<VariableSlot> _slot, ContextPtr _ctx) : slot(std::move(_slot)), ctx(_ctx)
|
||||
{
|
||||
kind = Kind::Variable;
|
||||
}
|
||||
LvObject(ObjectPtr _v, size_t _index, Kind _kind, ContextPtr _ctx) :
|
||||
value(_v), numIndex(_index), ctx(_ctx)
|
||||
LvObject(ObjectPtr _v, size_t _index, Kind _kind, ContextPtr _ctx) : value(_v), numIndex(_index), ctx(_ctx)
|
||||
{
|
||||
kind = _kind;
|
||||
}
|
||||
LvObject(ObjectPtr _v, ObjectPtr _index, Kind _kind, ContextPtr _ctx) :
|
||||
value(_v), mapIndex(_index), ctx(_ctx)
|
||||
LvObject(ObjectPtr _v, ObjectPtr _index, Kind _kind, ContextPtr _ctx) : value(_v), mapIndex(_index), ctx(_ctx)
|
||||
{
|
||||
kind = _kind;
|
||||
}
|
||||
@@ -51,27 +48,26 @@ namespace Fig
|
||||
{
|
||||
List &list = value->as<List>();
|
||||
if (numIndex >= list.size())
|
||||
throw RuntimeError(FString(
|
||||
std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
||||
throw RuntimeError(
|
||||
String(std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
||||
return list.at(numIndex).value;
|
||||
}
|
||||
else if (kind == Kind::MapElement) // map
|
||||
{
|
||||
Map &map = value->as<Map>();
|
||||
if (!map.contains(mapIndex))
|
||||
throw RuntimeError(FString(
|
||||
std::format("Key {} not found", mapIndex->toString().toBasicString())));
|
||||
throw RuntimeError(String(std::format("Key {} not found", mapIndex->toString().toBasicString())));
|
||||
return map.at(mapIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// string
|
||||
FString &string = value->as<ValueType::StringClass>();
|
||||
String &string = value->as<ValueType::StringClass>();
|
||||
if (numIndex >= string.length())
|
||||
throw RuntimeError(FString(
|
||||
std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
||||
throw RuntimeError(
|
||||
String(std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
||||
|
||||
return std::make_shared<Object>(string.getRealChar(numIndex));
|
||||
return std::make_shared<Object>(String(string[numIndex]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,26 +78,21 @@ namespace Fig
|
||||
auto s = resolve(slot);
|
||||
if (!isTypeMatch(s->declaredType, v, ctx))
|
||||
{
|
||||
throw RuntimeError(
|
||||
FString(
|
||||
std::format("Variable `{}` expects type `{}`, but got '{}'",
|
||||
s->name.toBasicString(),
|
||||
s->declaredType.toString().toBasicString(),
|
||||
prettyType(v).toBasicString())));
|
||||
throw RuntimeError(String(std::format("Variable `{}` expects type `{}`, but got '{}'",
|
||||
s->name.toBasicString(),
|
||||
s->declaredType.toString().toBasicString(),
|
||||
prettyType(v).toBasicString())));
|
||||
}
|
||||
if (isAccessConst(s->am))
|
||||
{
|
||||
throw RuntimeError(FString(
|
||||
std::format("Variable `{}` is immutable", s->name.toBasicString())));
|
||||
throw RuntimeError(String(std::format("Variable `{}` is immutable", s->name.toBasicString())));
|
||||
}
|
||||
s->value = v;
|
||||
}
|
||||
else if (kind == Kind::ListElement)
|
||||
{
|
||||
List &list = value->as<List>();
|
||||
if (numIndex >= list.size())
|
||||
throw RuntimeError(FString(
|
||||
std::format("Index {} out of range", numIndex)));
|
||||
if (numIndex >= list.size()) throw RuntimeError(String(std::format("Index {} out of range", numIndex)));
|
||||
list[numIndex] = v;
|
||||
}
|
||||
else if (kind == Kind::MapElement) // map
|
||||
@@ -111,25 +102,23 @@ namespace Fig
|
||||
}
|
||||
else if (kind == Kind::StringElement)
|
||||
{
|
||||
FString &string = value->as<ValueType::StringClass>();
|
||||
String &string = value->as<ValueType::StringClass>();
|
||||
if (numIndex >= string.length())
|
||||
throw RuntimeError(FString(
|
||||
std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
||||
|
||||
throw RuntimeError(
|
||||
String(std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
||||
|
||||
if (v->getTypeInfo() != ValueType::String)
|
||||
throw RuntimeError(FString(
|
||||
std::format("Could not assign {} to sub string", v->toString().toBasicString())
|
||||
));
|
||||
const FString &strReplace = v->as<ValueType::StringClass>();
|
||||
throw RuntimeError(
|
||||
String(std::format("Could not assign {} to sub string", v->toString().toBasicString())));
|
||||
const String &strReplace = v->as<ValueType::StringClass>();
|
||||
if (strReplace.length() > 1)
|
||||
throw RuntimeError(FString(
|
||||
std::format("Could not assign {} to sub string, expects length 1", v->toString().toBasicString())
|
||||
));
|
||||
string.realReplace(numIndex, strReplace);
|
||||
throw RuntimeError(String(std::format("Could not assign {} to sub string, expects length 1",
|
||||
v->toString().toBasicString())));
|
||||
string.replace(numIndex, strReplace.length(), strReplace);
|
||||
}
|
||||
}
|
||||
|
||||
FString name() const { return resolve(slot)->name; }
|
||||
String name() const { return resolve(slot)->name; }
|
||||
TypeInfo declaredType() const { return resolve(slot)->declaredType; }
|
||||
AccessModifier access() const { return resolve(slot)->am; }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Core/String.hpp>
|
||||
|
||||
#include <unordered_set>
|
||||
#include <variant>
|
||||
@@ -14,23 +14,23 @@ namespace Fig
|
||||
private:
|
||||
size_t id;
|
||||
|
||||
std::map<FString, size_t> &getTypeMap()
|
||||
std::map<String, size_t> &getTypeMap()
|
||||
{
|
||||
static std::map<FString, size_t> typeMap;
|
||||
static std::map<String, size_t> typeMap;
|
||||
return typeMap;
|
||||
}
|
||||
|
||||
public:
|
||||
friend class TypeInfoHash;
|
||||
|
||||
FString name;
|
||||
String name;
|
||||
|
||||
FString toString() const { return name; }
|
||||
String toString() const { return name; }
|
||||
|
||||
size_t getInstanceID() const { return id; }
|
||||
|
||||
TypeInfo();
|
||||
explicit TypeInfo(const FString &_name, bool reg = false);
|
||||
explicit TypeInfo(const String &_name, bool reg = false);
|
||||
TypeInfo(const TypeInfo &other) = default;
|
||||
|
||||
bool operator==(const TypeInfo &other) const { return id == other.id; }
|
||||
@@ -63,7 +63,7 @@ namespace Fig
|
||||
using DoubleClass = double;
|
||||
using BoolClass = bool;
|
||||
using NullClass = std::monostate;
|
||||
using StringClass = FString;
|
||||
using StringClass = Fig::String;
|
||||
|
||||
inline bool isTypeBuiltin(const TypeInfo &type)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <Ast/AccessModifier.hpp>
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Core/String.hpp>
|
||||
#include <Evaluator/Value/Type.hpp>
|
||||
#include <Evaluator/Value/value_forward.hpp>
|
||||
|
||||
@@ -12,7 +11,7 @@ namespace Fig
|
||||
|
||||
struct VariableSlot
|
||||
{
|
||||
FString name;
|
||||
String name;
|
||||
ObjectPtr value;
|
||||
TypeInfo declaredType;
|
||||
AccessModifier am;
|
||||
@@ -20,4 +19,4 @@ namespace Fig
|
||||
bool isRef = false;
|
||||
std::shared_ptr<VariableSlot> refTarget;
|
||||
};
|
||||
}
|
||||
} // namespace Fig
|
||||
@@ -16,7 +16,7 @@ namespace Fig
|
||||
{
|
||||
public:
|
||||
std::size_t id;
|
||||
FString name;
|
||||
String name;
|
||||
|
||||
enum FnType
|
||||
{
|
||||
@@ -53,7 +53,7 @@ namespace Fig
|
||||
new (&body) Ast::BlockStatement();
|
||||
}
|
||||
|
||||
Function(const FString &_name,
|
||||
Function(const String &_name,
|
||||
Ast::FunctionParameters _paras,
|
||||
TypeInfo _retType,
|
||||
Ast::BlockStatement _body,
|
||||
@@ -68,13 +68,16 @@ namespace Fig
|
||||
type = Normal;
|
||||
}
|
||||
|
||||
Function(const FString &_name, std::function<std::shared_ptr<Object>(const std::vector<std::shared_ptr<Object>> &)> fn, int argc) :
|
||||
Function(const String &_name,
|
||||
std::function<std::shared_ptr<Object>(const std::vector<std::shared_ptr<Object>> &)> fn,
|
||||
int argc) :
|
||||
id(nextId()), name(_name), type(Builtin), builtin(fn), builtinParamCount(argc)
|
||||
{
|
||||
type = Builtin;
|
||||
}
|
||||
|
||||
Function(const FString &_name, std::function<std::shared_ptr<Object>(std::shared_ptr<Object>,
|
||||
Function(const String &_name,
|
||||
std::function<std::shared_ptr<Object>(std::shared_ptr<Object>,
|
||||
const std::vector<std::shared_ptr<Object>> &)> fn,
|
||||
int argc) :
|
||||
id(nextId()), name(_name), type(MemberType), mtFn(fn), builtinParamCount(argc)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Core/String.hpp>
|
||||
|
||||
#include <Evaluator/Context/context_forward.hpp>
|
||||
|
||||
@@ -8,20 +8,13 @@ namespace Fig
|
||||
{
|
||||
struct Module
|
||||
{
|
||||
FString name;
|
||||
String name;
|
||||
ContextPtr ctx;
|
||||
|
||||
Module() = default;
|
||||
|
||||
Module(FString n, ContextPtr c) :
|
||||
name(std::move(n)),
|
||||
ctx(std::move(c))
|
||||
{
|
||||
}
|
||||
Module(String n, ContextPtr c) : name(std::move(n)), ctx(std::move(c)) {}
|
||||
|
||||
bool operator==(const Module &o) const noexcept
|
||||
{
|
||||
return name == o.name;
|
||||
}
|
||||
bool operator==(const Module &o) const noexcept { return name == o.name; }
|
||||
};
|
||||
};
|
||||
}; // namespace Fig
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Core/String.hpp>
|
||||
#include <Ast/Statements/StructDefSt.hpp>
|
||||
|
||||
#include <Evaluator/Value/Type.hpp>
|
||||
@@ -14,21 +14,17 @@ namespace Fig
|
||||
struct Field
|
||||
{
|
||||
AccessModifier am;
|
||||
FString name;
|
||||
String name;
|
||||
TypeInfo type;
|
||||
Ast::Expression defaultValue;
|
||||
|
||||
Field(AccessModifier _am, FString _name, TypeInfo _type, Ast::Expression _defaultValue) :
|
||||
am(_am), name(std::move(_name)), type(std::move(_type)), defaultValue(std::move(_defaultValue)) {}
|
||||
Field(AccessModifier _am, String _name, TypeInfo _type, Ast::Expression _defaultValue) :
|
||||
am(_am), name(std::move(_name)), type(std::move(_type)), defaultValue(std::move(_defaultValue))
|
||||
{
|
||||
}
|
||||
|
||||
bool isPublic() const
|
||||
{
|
||||
return am == AccessModifier::Public || am == AccessModifier::PublicConst;
|
||||
}
|
||||
bool isConst() const
|
||||
{
|
||||
return am == AccessModifier::Const || am == AccessModifier::PublicConst;
|
||||
}
|
||||
bool isPublic() const { return am == AccessModifier::Public || am == AccessModifier::PublicConst; }
|
||||
bool isConst() const { return am == AccessModifier::Const || am == AccessModifier::PublicConst; }
|
||||
};
|
||||
|
||||
struct StructType
|
||||
@@ -41,7 +37,9 @@ namespace Fig
|
||||
|
||||
// ===== Constructors =====
|
||||
StructType(TypeInfo _type, ContextPtr _defContext, std::vector<Field> _fields, bool _builtin = false) :
|
||||
type(std::move(_type)), defContext(std::move(_defContext)), fields(std::move(_fields)), builtin(_builtin) {}
|
||||
type(std::move(_type)), defContext(std::move(_defContext)), fields(std::move(_fields)), builtin(_builtin)
|
||||
{
|
||||
}
|
||||
|
||||
StructType(const StructType &other) = default;
|
||||
StructType(StructType &&) noexcept = default;
|
||||
@@ -49,14 +47,8 @@ namespace Fig
|
||||
StructType &operator=(StructType &&) noexcept = default;
|
||||
|
||||
// ===== Comparison =====
|
||||
bool operator==(const StructType &other) const noexcept
|
||||
{
|
||||
return type == other.type;
|
||||
}
|
||||
bool operator!=(const StructType &other) const noexcept
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
bool operator==(const StructType &other) const noexcept { return type == other.type; }
|
||||
bool operator!=(const StructType &other) const noexcept { return !(*this == other); }
|
||||
|
||||
private:
|
||||
static std::size_t nextId()
|
||||
@@ -72,9 +64,6 @@ namespace std
|
||||
template <>
|
||||
struct hash<Fig::Field>
|
||||
{
|
||||
size_t operator()(const Fig::Field &f)
|
||||
{
|
||||
return std::hash<Fig::FString>{}(f.name);
|
||||
}
|
||||
size_t operator()(const Fig::Field &f) { return std::hash<Fig::String>{}(f.name); }
|
||||
};
|
||||
}; // namespace std
|
||||
@@ -11,10 +11,10 @@ namespace Fig
|
||||
{
|
||||
|
||||
TypeInfo::TypeInfo() : // only allow use in evaluate time !! <---- dynamic type system requirement
|
||||
id(1), name(FString(u8"Any"))
|
||||
id(1), name(String(U"Any"))
|
||||
{
|
||||
}
|
||||
TypeInfo::TypeInfo(const FString &_name, bool reg)
|
||||
TypeInfo::TypeInfo(const String &_name, bool reg)
|
||||
{
|
||||
static size_t id_count = 0;
|
||||
name = _name;
|
||||
@@ -28,7 +28,7 @@ namespace Fig
|
||||
{
|
||||
if (!getTypeMap().contains(_name))
|
||||
{
|
||||
throw RuntimeError(FString(std::format("No type named '{}'", _name.toBasicString())));
|
||||
throw RuntimeError(String(std::format("No type named '{}'", _name.toBasicString())));
|
||||
// *this = ValueType::String;
|
||||
}
|
||||
id = getTypeMap().at(name); // may throw
|
||||
@@ -93,25 +93,29 @@ namespace Fig
|
||||
if (t == ValueType::StructInstance) return obj->as<StructInstance>().parentType;
|
||||
return t;
|
||||
}
|
||||
FString prettyType(std::shared_ptr<const Object> obj)
|
||||
String prettyType(std::shared_ptr<const Object> obj)
|
||||
{
|
||||
return actualType(obj).toString();
|
||||
}
|
||||
|
||||
const TypeInfo ValueType::Any(FString(u8"Any"), true); // id: 1
|
||||
const TypeInfo ValueType::Null(FString(u8"Null"), true); // id: 2
|
||||
const TypeInfo ValueType::Int(FString(u8"Int"), true); // id: 3
|
||||
const TypeInfo ValueType::String(FString(u8"String"), true); // id: 4
|
||||
const TypeInfo ValueType::Bool(FString(u8"Bool"), true); // id: 5
|
||||
const TypeInfo ValueType::Double(FString(u8"Double"), true); // id: 6
|
||||
const TypeInfo ValueType::Function(FString(u8"Function"), true); // id: 7
|
||||
const TypeInfo ValueType::StructType(FString(u8"StructType"), true); // id: 8
|
||||
const TypeInfo ValueType::StructInstance(FString(u8"StructInstance"), true); // id: 9
|
||||
const TypeInfo ValueType::List(FString(u8"List"), true); // id: 10
|
||||
const TypeInfo ValueType::Map(FString(u8"Map"), true); // id: 11
|
||||
const TypeInfo ValueType::Module(FString(u8"Module"), true); // id: 12
|
||||
const TypeInfo ValueType::InterfaceType(FString(u8"InterfaceType"), true); // id: 13
|
||||
const TypeInfo ValueType::Any(U"Any", true); // id: 1
|
||||
const TypeInfo ValueType::Null(U"Null", true); // id: 2
|
||||
const TypeInfo ValueType::Int(U"Int", true); // id: 3
|
||||
const TypeInfo ValueType::String(U"String", true); // id: 4
|
||||
const TypeInfo ValueType::Bool(U"Bool", true); // id: 5
|
||||
const TypeInfo ValueType::Double(U"Double", true); // id: 6
|
||||
const TypeInfo ValueType::Function(U"Function", true); // id: 7
|
||||
const TypeInfo ValueType::StructType(U"StructType", true); // id: 8
|
||||
const TypeInfo ValueType::StructInstance(U"StructInstance", true); // id: 9
|
||||
const TypeInfo ValueType::List(U"List", true); // id: 10
|
||||
const TypeInfo ValueType::Map(U"Map", true); // id: 11
|
||||
const TypeInfo ValueType::Module(U"Module", true); // id: 12
|
||||
const TypeInfo ValueType::InterfaceType(U"InterfaceType", true); // id: 13
|
||||
|
||||
namespace ValueType
|
||||
{
|
||||
|
||||
};
|
||||
bool implements(const TypeInfo &structType, const TypeInfo &interfaceType, ContextPtr ctx)
|
||||
{
|
||||
return ctx->hasImplRegisted(structType, interfaceType);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Core/String.hpp>
|
||||
#include <Evaluator/Value/function.hpp>
|
||||
#include <Evaluator/Value/interface.hpp>
|
||||
#include <Evaluator/Value/structType.hpp>
|
||||
@@ -43,7 +43,7 @@ namespace Fig
|
||||
}
|
||||
|
||||
TypeInfo actualType(std::shared_ptr<const Object> obj);
|
||||
FString prettyType(std::shared_ptr<const Object> obj);
|
||||
String prettyType(std::shared_ptr<const Object> obj);
|
||||
|
||||
bool operator==(const Object &, const Object &);
|
||||
|
||||
@@ -93,89 +93,92 @@ namespace Fig
|
||||
Module,
|
||||
InterfaceType>;
|
||||
|
||||
static std::unordered_map<TypeInfo, std::unordered_map<FString, BuiltinTypeMemberFn>, TypeInfoHash>
|
||||
static std::unordered_map<TypeInfo, std::unordered_map<String, BuiltinTypeMemberFn>, TypeInfoHash>
|
||||
getMemberTypeFunctions()
|
||||
{
|
||||
static const std::unordered_map<TypeInfo, std::unordered_map<FString, BuiltinTypeMemberFn>, TypeInfoHash>
|
||||
static const std::unordered_map<TypeInfo, std::unordered_map<String, BuiltinTypeMemberFn>, TypeInfoHash>
|
||||
memberTypeFunctions{
|
||||
{ValueType::Null, {}},
|
||||
{ValueType::Int, {}},
|
||||
{ValueType::Double, {}},
|
||||
{ValueType::String,
|
||||
{
|
||||
{u8"length",
|
||||
{U"length",
|
||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||
if (args.size() != 0)
|
||||
throw RuntimeError(
|
||||
FString(std::format("`length` expects 0 arguments, {} got", args.size())));
|
||||
const FString &str = object->as<ValueType::StringClass>();
|
||||
String(std::format("`length` expects 0 arguments, {} got", args.size())));
|
||||
const String &str = object->as<ValueType::StringClass>();
|
||||
return std::make_shared<Object>(static_cast<ValueType::IntClass>(str.length()));
|
||||
}},
|
||||
{u8"replace",
|
||||
{U"replace",
|
||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||
if (args.size() != 2)
|
||||
throw RuntimeError(
|
||||
FString(std::format("`replace` expects 2 arguments, {} got", args.size())));
|
||||
FString &str = object->as<ValueType::StringClass>();
|
||||
String(std::format("`replace` expects 2 arguments, {} got", args.size())));
|
||||
String &str = object->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"));
|
||||
throw RuntimeError(String("`replace` arg 1 expects type Int"));
|
||||
}
|
||||
if (!arg2->is<ValueType::StringClass>())
|
||||
{
|
||||
throw RuntimeError(FString("`replace` arg 2 expects type String"));
|
||||
throw RuntimeError(String("`replace` arg 2 expects type String"));
|
||||
}
|
||||
str.realReplace(arg1->as<ValueType::IntClass>(), arg2->as<ValueType::StringClass>());
|
||||
const String &target = arg2->as<ValueType::StringClass>();
|
||||
str.replace(arg1->as<ValueType::IntClass>(), target.length(), target);
|
||||
return Object::getNullInstance();
|
||||
}},
|
||||
{u8"erase",
|
||||
{U"erase",
|
||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||
if (args.size() != 2)
|
||||
throw RuntimeError(
|
||||
FString(std::format("`erase` expects 2 arguments, {} got", args.size())));
|
||||
FString &str = object->as<ValueType::StringClass>();
|
||||
String(std::format("`erase` expects 2 arguments, {} got", args.size())));
|
||||
String &str = object->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"));
|
||||
throw RuntimeError(String("`erase` arg 1 expects type Int"));
|
||||
}
|
||||
if (!arg2->is<ValueType::IntClass>())
|
||||
{
|
||||
throw RuntimeError(FString("`erase` arg 2 expects type Int"));
|
||||
throw RuntimeError(String("`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"));
|
||||
throw RuntimeError(String("`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"));
|
||||
throw RuntimeError(String("`erase`: length is not long enough to erase"));
|
||||
}
|
||||
str.realErase(arg1->as<ValueType::IntClass>(), arg2->as<ValueType::IntClass>());
|
||||
str.erase(arg1->as<ValueType::IntClass>(), arg2->as<ValueType::IntClass>());
|
||||
return Object::getNullInstance();
|
||||
}},
|
||||
{u8"insert",
|
||||
{U"insert",
|
||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||
if (args.size() != 2)
|
||||
throw RuntimeError(
|
||||
FString(std::format("`insert` expects 2 arguments, {} got", args.size())));
|
||||
FString &str = object->as<ValueType::StringClass>();
|
||||
String(std::format("`insert` expects 2 arguments, {} got", args.size())));
|
||||
String &str = object->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"));
|
||||
throw RuntimeError(String("`insert` arg 1 expects type Int"));
|
||||
}
|
||||
if (!arg2->is<ValueType::StringClass>())
|
||||
{
|
||||
throw RuntimeError(FString("`insert` arg 2 expects type String"));
|
||||
throw RuntimeError(String("`insert` arg 2 expects type String"));
|
||||
}
|
||||
str.realInsert(arg1->as<ValueType::IntClass>(), arg2->as<ValueType::StringClass>());
|
||||
ValueType::IntClass dest = arg1->as<ValueType::IntClass>();
|
||||
const String &src = arg2->as<ValueType::StringClass>();
|
||||
str.insert(dest, src);
|
||||
return Object::getNullInstance();
|
||||
}},
|
||||
}},
|
||||
@@ -184,34 +187,34 @@ namespace Fig
|
||||
{ValueType::StructInstance, {}},
|
||||
{ValueType::List,
|
||||
{
|
||||
{u8"length",
|
||||
{U"length",
|
||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||
if (args.size() != 0)
|
||||
throw RuntimeError(
|
||||
FString(std::format("`length` expects 0 arguments, {} got", args.size())));
|
||||
String(std::format("`length` expects 0 arguments, {} got", args.size())));
|
||||
const List &list = object->as<List>();
|
||||
return std::make_shared<Object>(static_cast<ValueType::IntClass>(list.size()));
|
||||
}},
|
||||
{u8"get",
|
||||
{U"get",
|
||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||
if (args.size() != 1)
|
||||
throw RuntimeError(
|
||||
FString(std::format("`get` expects 1 arguments, {} got", args.size())));
|
||||
String(std::format("`get` expects 1 arguments, {} got", args.size())));
|
||||
ObjectPtr arg = args[0];
|
||||
if (arg->getTypeInfo() != ValueType::Int)
|
||||
throw RuntimeError(
|
||||
FString(std::format("`get` argument 1 expects Int, {} got",
|
||||
arg->getTypeInfo().toString().toBasicString())));
|
||||
String(std::format("`get` argument 1 expects Int, {} got",
|
||||
arg->getTypeInfo().toString().toBasicString())));
|
||||
ValueType::IntClass i = arg->as<ValueType::IntClass>();
|
||||
const List &list = object->as<List>();
|
||||
if (i >= list.size()) return Object::getNullInstance();
|
||||
return list[i].value;
|
||||
}},
|
||||
{u8"push",
|
||||
{U"push",
|
||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||
if (args.size() != 1)
|
||||
throw RuntimeError(
|
||||
FString(std::format("`push` expects 1 arguments, {} got", args.size())));
|
||||
String(std::format("`push` expects 1 arguments, {} got", args.size())));
|
||||
ObjectPtr arg = args[0];
|
||||
List &list = object->as<List>();
|
||||
list.push_back(arg);
|
||||
@@ -220,21 +223,21 @@ namespace Fig
|
||||
}},
|
||||
{ValueType::Map,
|
||||
{
|
||||
{u8"get",
|
||||
{U"get",
|
||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||
if (args.size() != 1)
|
||||
throw RuntimeError(
|
||||
FString(std::format("`get` expects 1 arguments, {} got", args.size())));
|
||||
String(std::format("`get` expects 1 arguments, {} got", args.size())));
|
||||
ObjectPtr index = args[0];
|
||||
const Map &map = object->as<Map>();
|
||||
if (!map.contains(index)) return Object::getNullInstance();
|
||||
return map.at(index);
|
||||
}},
|
||||
{u8"contains",
|
||||
{U"contains",
|
||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||
if (args.size() != 1)
|
||||
throw RuntimeError(
|
||||
FString(std::format("`contains` expects 1 arguments, {} got", args.size())));
|
||||
String(std::format("`contains` expects 1 arguments, {} got", args.size())));
|
||||
ObjectPtr index = args[0];
|
||||
const Map &map = object->as<Map>();
|
||||
return std::make_shared<Object>(map.contains(index));
|
||||
@@ -246,29 +249,28 @@ namespace Fig
|
||||
return memberTypeFunctions;
|
||||
}
|
||||
|
||||
static std::unordered_map<TypeInfo, std::unordered_map<FString, int>, TypeInfoHash>
|
||||
getMemberTypeFunctionsParas()
|
||||
static std::unordered_map<TypeInfo, std::unordered_map<String, int>, TypeInfoHash> getMemberTypeFunctionsParas()
|
||||
{
|
||||
static const std::unordered_map<TypeInfo, std::unordered_map<FString, int>, TypeInfoHash>
|
||||
static const std::unordered_map<TypeInfo, std::unordered_map<String, int>, TypeInfoHash>
|
||||
memberTypeFunctionsParas{
|
||||
{ValueType::Null, {}},
|
||||
{ValueType::Int, {}},
|
||||
{ValueType::Double, {}},
|
||||
{ValueType::String,
|
||||
{
|
||||
{u8"length", 0},
|
||||
{u8"replace", 2},
|
||||
{u8"erase", 2},
|
||||
{u8"insert", 2},
|
||||
{U"length", 0},
|
||||
{U"replace", 2},
|
||||
{U"erase", 2},
|
||||
{U"insert", 2},
|
||||
}},
|
||||
{ValueType::Function, {}},
|
||||
{ValueType::StructType, {}},
|
||||
{ValueType::StructInstance, {}},
|
||||
{ValueType::List, {{u8"length", 0}, {u8"get", 1}, {u8"push", 1}}},
|
||||
{ValueType::List, {{U"length", 0}, {U"get", 1}, {U"push", 1}}},
|
||||
{ValueType::Map,
|
||||
{
|
||||
{u8"get", 1},
|
||||
{u8"contains", 1},
|
||||
{U"get", 1},
|
||||
{U"contains", 1},
|
||||
}},
|
||||
{ValueType::Module, {}},
|
||||
{ValueType::InterfaceType, {}},
|
||||
@@ -276,15 +278,15 @@ namespace Fig
|
||||
return memberTypeFunctionsParas;
|
||||
}
|
||||
|
||||
bool hasMemberFunction(const FString &name) const
|
||||
bool hasMemberFunction(const String &name) const
|
||||
{
|
||||
return getMemberTypeFunctions().at(getTypeInfo()).contains(name);
|
||||
}
|
||||
BuiltinTypeMemberFn getMemberFunction(const FString &name) const
|
||||
BuiltinTypeMemberFn getMemberFunction(const String &name) const
|
||||
{
|
||||
return getMemberTypeFunctions().at(getTypeInfo()).at(name);
|
||||
}
|
||||
int getMemberFunctionParaCount(const FString &name) const
|
||||
int getMemberFunctionParaCount(const String &name) const
|
||||
{
|
||||
return getMemberTypeFunctionsParas().at(getTypeInfo()).at(name);
|
||||
}
|
||||
@@ -317,7 +319,7 @@ namespace Fig
|
||||
else if (ti == ValueType::Double)
|
||||
return Object(ValueType::DoubleClass(0.0));
|
||||
else if (ti == ValueType::String)
|
||||
return Object(ValueType::StringClass(u8""));
|
||||
return Object(ValueType::StringClass(U""));
|
||||
else if (ti == ValueType::Bool)
|
||||
return Object(ValueType::BoolClass(false));
|
||||
else if (ti == ValueType::List)
|
||||
@@ -420,83 +422,83 @@ namespace Fig
|
||||
else if (is<ValueType::DoubleClass>())
|
||||
return as<ValueType::DoubleClass>();
|
||||
else
|
||||
throw RuntimeError(u8"getNumericValue: Not a numeric value");
|
||||
throw RuntimeError(U"getNumericValue: Not a numeric value");
|
||||
}
|
||||
|
||||
FString toStringIO() const
|
||||
String toStringIO() const
|
||||
{
|
||||
if (is<ValueType::StringClass>()) return as<ValueType::StringClass>();
|
||||
return toString();
|
||||
}
|
||||
|
||||
FString toString(std::unordered_set<const Object *> &visited) const
|
||||
String toString(std::unordered_set<const Object *> &visited) const
|
||||
{
|
||||
if (is<ValueType::NullClass>()) return FString(u8"null");
|
||||
if (is<ValueType::IntClass>()) return FString(std::to_string(as<ValueType::IntClass>()));
|
||||
if (is<ValueType::DoubleClass>()) return FString(std::format("{}", as<ValueType::DoubleClass>()));
|
||||
if (is<ValueType::StringClass>()) return FString(u8"\"" + as<ValueType::StringClass>() + u8"\"");
|
||||
if (is<ValueType::BoolClass>()) return as<ValueType::BoolClass>() ? FString(u8"true") : FString(u8"false");
|
||||
if (is<ValueType::NullClass>()) return String(U"null");
|
||||
if (is<ValueType::IntClass>()) return String(std::to_string(as<ValueType::IntClass>()));
|
||||
if (is<ValueType::DoubleClass>()) return String(std::format("{}", as<ValueType::DoubleClass>()));
|
||||
if (is<ValueType::StringClass>()) return String(String(U"\"") + as<ValueType::StringClass>() + String(U"\""));
|
||||
if (is<ValueType::BoolClass>()) return as<ValueType::BoolClass>() ? String(U"true") : String(U"false");
|
||||
if (is<Function>())
|
||||
return FString(std::format(
|
||||
return String(std::format(
|
||||
"<Function '{}' at {:p}>", as<Function>().id, static_cast<const void *>(&as<Function>())));
|
||||
if (is<StructType>())
|
||||
return FString(std::format("<StructType '{}' at {:p}>",
|
||||
as<StructType>().type.toString().toBasicString(),
|
||||
static_cast<const void *>(&as<StructType>())));
|
||||
return String(std::format("<StructType '{}' at {:p}>",
|
||||
as<StructType>().type.toString().toBasicString(),
|
||||
static_cast<const void *>(&as<StructType>())));
|
||||
if (is<StructInstance>())
|
||||
return FString(std::format("<StructInstance '{}' at {:p}>",
|
||||
as<StructInstance>().parentType.toString().toBasicString(),
|
||||
static_cast<const void *>(&as<StructInstance>())));
|
||||
return String(std::format("<StructInstance '{}' at {:p}>",
|
||||
as<StructInstance>().parentType.toString().toBasicString(),
|
||||
static_cast<const void *>(&as<StructInstance>())));
|
||||
if (is<List>())
|
||||
{
|
||||
if (visited.contains(this)) { return u8"[...]"; }
|
||||
if (visited.contains(this)) { return U"[...]"; }
|
||||
visited.insert(this);
|
||||
|
||||
FString output(u8"[");
|
||||
String output(U"[");
|
||||
const List &list = as<List>();
|
||||
bool first_flag = true;
|
||||
for (auto &ele : list)
|
||||
{
|
||||
if (!first_flag) output += u8", ";
|
||||
if (!first_flag) output += U", ";
|
||||
output += ele.value->toString(visited);
|
||||
first_flag = false;
|
||||
}
|
||||
output += u8"]";
|
||||
output += U"]";
|
||||
return output;
|
||||
}
|
||||
if (is<Map>())
|
||||
{
|
||||
if (visited.contains(this)) { return u8"{...}"; }
|
||||
if (visited.contains(this)) { return U"{...}"; }
|
||||
visited.insert(this);
|
||||
|
||||
FString output(u8"{");
|
||||
String output(U"{");
|
||||
const Map &map = as<Map>();
|
||||
bool first_flag = true;
|
||||
for (auto &[key, value] : map)
|
||||
{
|
||||
if (!first_flag) output += u8", ";
|
||||
output += key.value->toString(visited) + FString(u8" : ") + value->toString(visited);
|
||||
if (!first_flag) output += U", ";
|
||||
output += key.value->toString(visited) + String(U" : ") + value->toString(visited);
|
||||
first_flag = false;
|
||||
}
|
||||
output += u8"}";
|
||||
output += U"}";
|
||||
return output;
|
||||
}
|
||||
if (is<Module>())
|
||||
{
|
||||
return FString(std::format("<Module '{}' at {:p}>",
|
||||
as<Module>().name.toBasicString(),
|
||||
static_cast<const void *>(&as<Module>())));
|
||||
return String(std::format("<Module '{}' at {:p}>",
|
||||
as<Module>().name.toBasicString(),
|
||||
static_cast<const void *>(&as<Module>())));
|
||||
}
|
||||
if (is<InterfaceType>())
|
||||
{
|
||||
return FString(std::format("<InterfaceType '{}' at {:p}>",
|
||||
as<InterfaceType>().type.toString().toBasicString(),
|
||||
static_cast<const void *>(&as<InterfaceType>())));
|
||||
return String(std::format("<InterfaceType '{}' at {:p}>",
|
||||
as<InterfaceType>().type.toString().toBasicString(),
|
||||
static_cast<const void *>(&as<InterfaceType>())));
|
||||
}
|
||||
return FString(u8"<error>");
|
||||
return String(U"<error>");
|
||||
}
|
||||
|
||||
FString toString() const
|
||||
String toString() const
|
||||
{
|
||||
std::unordered_set<const Object *> visited{};
|
||||
return toString(visited);
|
||||
@@ -516,7 +518,7 @@ namespace Fig
|
||||
friend Object operator+(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (lhs.isNull() || rhs.isNull())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Cannot add", "+", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Cannot add", "+", lhs, rhs)));
|
||||
if (lhs.isNumeric() && rhs.isNumeric())
|
||||
{
|
||||
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
||||
@@ -525,14 +527,14 @@ namespace Fig
|
||||
return Object(result);
|
||||
}
|
||||
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
|
||||
return Object(FString(lhs.as<ValueType::StringClass>() + rhs.as<ValueType::StringClass>()));
|
||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "+", lhs, rhs)));
|
||||
return Object(String(lhs.as<ValueType::StringClass>() + rhs.as<ValueType::StringClass>()));
|
||||
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "+", lhs, rhs)));
|
||||
}
|
||||
|
||||
friend Object operator-(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (lhs.isNull() || rhs.isNull())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Cannot subtract", "-", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Cannot subtract", "-", lhs, rhs)));
|
||||
if (lhs.isNumeric() && rhs.isNumeric())
|
||||
{
|
||||
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
||||
@@ -540,13 +542,13 @@ namespace Fig
|
||||
if (bothInt) return Object(static_cast<ValueType::IntClass>(result));
|
||||
return Object(result);
|
||||
}
|
||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "-", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "-", lhs, rhs)));
|
||||
}
|
||||
|
||||
friend Object operator*(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (lhs.isNull() || rhs.isNull())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Cannot multiply", "*", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Cannot multiply", "*", lhs, rhs)));
|
||||
if (lhs.isNumeric() && rhs.isNumeric())
|
||||
{
|
||||
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
||||
@@ -556,22 +558,22 @@ namespace Fig
|
||||
}
|
||||
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::IntClass>())
|
||||
{
|
||||
FString result;
|
||||
const FString &l = lhs.as<ValueType::StringClass>();
|
||||
String result;
|
||||
const String &l = lhs.as<ValueType::StringClass>();
|
||||
for (size_t i = 0; i < rhs.getNumericValue(); ++i) { result += l; }
|
||||
return Object(result);
|
||||
}
|
||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "*", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "*", lhs, rhs)));
|
||||
}
|
||||
|
||||
friend Object operator/(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (lhs.isNull() || rhs.isNull())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Cannot divide", "/", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Cannot divide", "/", lhs, rhs)));
|
||||
if (lhs.isNumeric() && rhs.isNumeric())
|
||||
{
|
||||
auto rnv = rhs.getNumericValue();
|
||||
if (rnv == 0) throw ValueError(FString(makeTypeErrorMessage("Division by zero", "/", lhs, rhs)));
|
||||
if (rnv == 0) throw ValueError(String(makeTypeErrorMessage("Division by zero", "/", lhs, rhs)));
|
||||
// bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
||||
auto result = lhs.getNumericValue() / rnv;
|
||||
// if (bothInt)
|
||||
@@ -581,18 +583,18 @@ namespace Fig
|
||||
// DO NOT convert it to INT
|
||||
return Object(result);
|
||||
}
|
||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "/", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "/", lhs, rhs)));
|
||||
}
|
||||
|
||||
friend Object operator%(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (lhs.isNull() || rhs.isNull())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Cannot modulo", "%", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Cannot modulo", "%", lhs, rhs)));
|
||||
if (lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>())
|
||||
{
|
||||
ValueType::IntClass lv = lhs.as<ValueType::IntClass>();
|
||||
ValueType::IntClass rv = lhs.as<ValueType::IntClass>();
|
||||
if (rv == 0) throw ValueError(FString(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs)));
|
||||
if (rv == 0) throw ValueError(String(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs)));
|
||||
|
||||
ValueType::IntClass q = lv / rv;
|
||||
ValueType::IntClass r = lv % rv;
|
||||
@@ -603,25 +605,25 @@ namespace Fig
|
||||
if (lhs.isNumeric() && rhs.isNumeric())
|
||||
{
|
||||
auto rnv = rhs.getNumericValue();
|
||||
if (rnv == 0) throw ValueError(FString(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs)));
|
||||
if (rnv == 0) throw ValueError(String(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs)));
|
||||
auto result = std::fmod(lhs.getNumericValue(), rnv);
|
||||
return Object(result);
|
||||
}
|
||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs)));
|
||||
}
|
||||
|
||||
// logic
|
||||
friend Object operator&&(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (!lhs.is<ValueType::BoolClass>() || !rhs.is<ValueType::BoolClass>())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Logical AND requires bool", "&&", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Logical AND requires bool", "&&", lhs, rhs)));
|
||||
return Object(lhs.as<ValueType::BoolClass>() && rhs.as<ValueType::BoolClass>());
|
||||
}
|
||||
|
||||
friend Object operator||(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (!lhs.is<ValueType::BoolClass>() || !rhs.is<ValueType::BoolClass>())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Logical OR requires bool", "||", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Logical OR requires bool", "||", lhs, rhs)));
|
||||
return Object(lhs.as<ValueType::BoolClass>() || rhs.as<ValueType::BoolClass>());
|
||||
}
|
||||
|
||||
@@ -629,34 +631,35 @@ namespace Fig
|
||||
{
|
||||
if (!v.is<ValueType::BoolClass>())
|
||||
throw ValueError(
|
||||
FString(std::format("Logical NOT requires bool: '{}'", v.getTypeInfo().name.toBasicString())));
|
||||
String(std::format("Logical NOT requires bool: '{}'", v.getTypeInfo().name.toBasicString())));
|
||||
return Object(!v.as<ValueType::BoolClass>());
|
||||
}
|
||||
|
||||
friend Object operator-(const Object &v)
|
||||
{
|
||||
if (v.isNull()) throw ValueError(FString(u8"Unary minus cannot be applied to null"));
|
||||
if (v.isNull()) throw ValueError(String(U"Unary minus cannot be applied to null"));
|
||||
if (v.is<ValueType::IntClass>()) return Object(-v.as<ValueType::IntClass>());
|
||||
if (v.is<ValueType::DoubleClass>()) return Object(-v.as<ValueType::DoubleClass>());
|
||||
throw ValueError(
|
||||
FString(std::format("Unary minus requires int or double: '{}'", v.getTypeInfo().name.toBasicString())));
|
||||
String(std::format("Unary minus requires int or double: '{}'", v.getTypeInfo().name.toBasicString())));
|
||||
}
|
||||
|
||||
friend Object operator~(const Object &v)
|
||||
{
|
||||
if (!v.is<ValueType::IntClass>())
|
||||
throw ValueError(
|
||||
FString(std::format("Bitwise NOT requires int: '{}'", v.getTypeInfo().name.toBasicString())));
|
||||
String(std::format("Bitwise NOT requires int: '{}'", v.getTypeInfo().name.toBasicString())));
|
||||
return Object(~v.as<ValueType::IntClass>());
|
||||
}
|
||||
|
||||
// comparison
|
||||
friend bool operator==(const Object &lhs, const Object &rhs) {
|
||||
friend bool operator==(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (lhs.isNumeric() && rhs.isNumeric())
|
||||
{
|
||||
return nearlyEqual(lhs.getNumericValue(), rhs.getNumericValue());
|
||||
}
|
||||
return lhs.data == rhs.data;
|
||||
return lhs.data == rhs.data;
|
||||
}
|
||||
friend bool operator!=(const Object &lhs, const Object &rhs) { return !(lhs == rhs); }
|
||||
friend bool operator<(const Object &lhs, const Object &rhs)
|
||||
@@ -664,7 +667,7 @@ namespace Fig
|
||||
if (lhs.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() < rhs.getNumericValue();
|
||||
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
|
||||
return lhs.as<ValueType::StringClass>() < rhs.as<ValueType::StringClass>();
|
||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported comparison", "<", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Unsupported comparison", "<", lhs, rhs)));
|
||||
}
|
||||
friend bool operator<=(const Object &lhs, const Object &rhs) { return lhs == rhs || lhs < rhs; }
|
||||
friend bool operator>(const Object &lhs, const Object &rhs)
|
||||
@@ -672,7 +675,7 @@ namespace Fig
|
||||
if (lhs.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() > rhs.getNumericValue();
|
||||
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
|
||||
return lhs.as<ValueType::StringClass>() > rhs.as<ValueType::StringClass>();
|
||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported comparison", ">", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Unsupported comparison", ">", lhs, rhs)));
|
||||
}
|
||||
friend bool operator>=(const Object &lhs, const Object &rhs) { return lhs == rhs || lhs > rhs; }
|
||||
|
||||
@@ -680,21 +683,21 @@ namespace Fig
|
||||
friend Object bit_and(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Bitwise AND requires int", "&", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Bitwise AND requires int", "&", lhs, rhs)));
|
||||
return Object(lhs.as<ValueType::IntClass>() & rhs.as<ValueType::IntClass>());
|
||||
}
|
||||
|
||||
friend Object bit_or(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Bitwise OR requires int", "|", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Bitwise OR requires int", "|", lhs, rhs)));
|
||||
return Object(lhs.as<ValueType::IntClass>() | rhs.as<ValueType::IntClass>());
|
||||
}
|
||||
|
||||
friend Object bit_xor(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Bitwise XOR requires int", "^", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Bitwise XOR requires int", "^", lhs, rhs)));
|
||||
return Object(lhs.as<ValueType::IntClass>() ^ rhs.as<ValueType::IntClass>());
|
||||
}
|
||||
|
||||
@@ -702,28 +705,28 @@ namespace Fig
|
||||
{
|
||||
if (!v.is<ValueType::IntClass>())
|
||||
throw ValueError(
|
||||
FString(std::format("Bitwise NOT requires int: '{}'", v.getTypeInfo().name.toBasicString())));
|
||||
String(std::format("Bitwise NOT requires int: '{}'", v.getTypeInfo().name.toBasicString())));
|
||||
return Object(~v.as<ValueType::IntClass>());
|
||||
}
|
||||
|
||||
friend Object shift_left(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Shift left requires int", "<<", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Shift left requires int", "<<", lhs, rhs)));
|
||||
return Object(lhs.as<ValueType::IntClass>() << rhs.as<ValueType::IntClass>());
|
||||
}
|
||||
|
||||
friend Object shift_right(const Object &lhs, const Object &rhs)
|
||||
{
|
||||
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Shift right requires int", ">>", lhs, rhs)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Shift right requires int", ">>", lhs, rhs)));
|
||||
return Object(lhs.as<ValueType::IntClass>() >> rhs.as<ValueType::IntClass>());
|
||||
}
|
||||
|
||||
friend Object power(const Object &base, const Object &exp)
|
||||
{
|
||||
if (base.isNull() || exp.isNull())
|
||||
throw ValueError(FString(makeTypeErrorMessage("Cannot exponentiate", "**", base, exp)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Cannot exponentiate", "**", base, exp)));
|
||||
if (base.isNumeric() && exp.isNumeric())
|
||||
{
|
||||
bool bothInt = base.is<ValueType::IntClass>() && exp.is<ValueType::IntClass>();
|
||||
@@ -731,7 +734,7 @@ namespace Fig
|
||||
if (bothInt) return Object(static_cast<ValueType::IntClass>(result));
|
||||
return Object(result);
|
||||
}
|
||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "**", base, exp)));
|
||||
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "**", base, exp)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -8,10 +8,13 @@ namespace Fig
|
||||
{
|
||||
public:
|
||||
using UnaddressableError::UnaddressableError;
|
||||
virtual FString toString() const override
|
||||
virtual String toString() const override
|
||||
{
|
||||
std::string msg = std::format("[ValueError] {} in [{}] {}", std::string(this->message.begin(), this->message.end()), this->src_loc.file_name(), this->src_loc.function_name());
|
||||
return FString(msg);
|
||||
std::string msg = std::format("[ValueError] {} in [{}] {}",
|
||||
std::string(this->message.begin(), this->message.end()),
|
||||
this->src_loc.file_name(),
|
||||
this->src_loc.function_name());
|
||||
return String(msg);
|
||||
}
|
||||
};
|
||||
};
|
||||
}; // namespace Fig
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <Evaluator/Value/Type.hpp>
|
||||
#include <Evaluator/Value/structInstance.hpp>
|
||||
#include <Ast/astBase.hpp>
|
||||
#include <Core/fig_string.hpp>
|
||||
#include <Core/String.hpp>
|
||||
#include <Evaluator/Core/StatementResult.hpp>
|
||||
#include <Evaluator/Value/value.hpp>
|
||||
#include <Error/errorLog.hpp>
|
||||
@@ -50,16 +50,16 @@ namespace Fig
|
||||
|
||||
ContextPtr Evaluator::loadModule(const std::filesystem::path &path)
|
||||
{
|
||||
static std::unordered_map<FString, std::pair<std::vector<FString>, std::vector<Ast::AstBase>>> mod_ast_cache{};
|
||||
static std::unordered_map<String, std::pair<std::vector<String>, std::vector<Ast::AstBase>>> mod_ast_cache{};
|
||||
|
||||
FString modSourcePath(path.string());
|
||||
String modSourcePath(path.string());
|
||||
|
||||
std::ifstream file(path);
|
||||
assert(file.is_open());
|
||||
|
||||
std::vector<Ast::AstBase> asts;
|
||||
|
||||
std::vector<FString> modSourceLines;
|
||||
std::vector<String> modSourceLines;
|
||||
|
||||
if (mod_ast_cache.contains(modSourcePath))
|
||||
{
|
||||
@@ -72,9 +72,9 @@ namespace Fig
|
||||
std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||
file.close();
|
||||
|
||||
modSourceLines = Utils::splitSource(FString(source));
|
||||
modSourceLines = Utils::splitSource(String(source));
|
||||
|
||||
Lexer lexer((FString(source)), modSourcePath, modSourceLines);
|
||||
Lexer lexer((String(source)), modSourcePath, modSourceLines);
|
||||
Parser parser(lexer, modSourcePath, modSourceLines);
|
||||
|
||||
asts = parser.parseAll();
|
||||
@@ -85,7 +85,7 @@ namespace Fig
|
||||
evaluator.SetSourcePath(modSourcePath);
|
||||
evaluator.SetSourceLines(modSourceLines);
|
||||
|
||||
ContextPtr modctx = std::make_shared<Context>(FString(std::format("<Module at {}>", path.string())), nullptr);
|
||||
ContextPtr modctx = std::make_shared<Context>(String(std::format("<Module at {}>", path.string())), nullptr);
|
||||
|
||||
evaluator.SetGlobalContext(modctx);
|
||||
evaluator.RegisterBuiltinsValue();
|
||||
@@ -96,10 +96,10 @@ namespace Fig
|
||||
|
||||
StatementResult Evaluator::evalImportSt(Ast::Import i, ContextPtr ctx)
|
||||
{
|
||||
const std::vector<FString> &pathVec = i->path;
|
||||
const std::vector<String> &pathVec = i->path;
|
||||
|
||||
FString modName = pathVec.back(); // pathVec at least has 1 element
|
||||
if (modName == u8"_builtins")
|
||||
String modName = pathVec.back(); // pathVec at least has 1 element
|
||||
if (modName == U"\1")
|
||||
{
|
||||
RegisterBuiltins();
|
||||
return StatementResult::normal();
|
||||
@@ -109,8 +109,7 @@ namespace Fig
|
||||
|
||||
if (ctx->containsInThisScope(modName))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"RedeclarationError", std::format("{} has already been declared.", modName.toBasicString()), i);
|
||||
throw EvaluatorError(U"\1", std::format("{} has already been declared.", modName.toBasicString()), i);
|
||||
}
|
||||
|
||||
auto path = resolveModulePath(pathVec);
|
||||
@@ -124,7 +123,7 @@ namespace Fig
|
||||
if (ctx->getOpRegistry().contains(type))
|
||||
{
|
||||
throw EvaluatorError(
|
||||
u8"DuplicateOperationOverload",
|
||||
U"\1",
|
||||
std::format("Module `{}` and current context `{}` have conflict operation overload for `{}` object",
|
||||
modCtx->getScopeName().toBasicString(),
|
||||
ctx->getScopeName().toBasicString(),
|
||||
@@ -135,7 +134,7 @@ namespace Fig
|
||||
}
|
||||
if (!i->names.empty())
|
||||
{
|
||||
for (const FString &symName : i->names)
|
||||
for (const String &symName : i->names)
|
||||
{
|
||||
LvObject tmp(modCtx->get(symName), modCtx);
|
||||
const ObjectPtr &value = tmp.get();
|
||||
@@ -183,13 +182,13 @@ namespace Fig
|
||||
*/
|
||||
const StructInstance &resInst = result->as<StructInstance>();
|
||||
|
||||
Function getErrorClassFn = ctx->getImplementedMethod(resultType, u8"getErrorClass");
|
||||
Function getErrorClassFn = ctx->getImplementedMethod(resultType, U"\1");
|
||||
getErrorClassFn = Function(getErrorClassFn.name,
|
||||
getErrorClassFn.paras,
|
||||
getErrorClassFn.retType,
|
||||
getErrorClassFn.body,
|
||||
resInst.localContext);
|
||||
Function getErrorMessageFn = ctx->getImplementedMethod(resultType, u8"getErrorMessage");
|
||||
Function getErrorMessageFn = ctx->getImplementedMethod(resultType, U"\1");
|
||||
getErrorMessageFn = Function(getErrorMessageFn.name,
|
||||
getErrorMessageFn.paras,
|
||||
getErrorMessageFn.retType,
|
||||
@@ -210,17 +209,16 @@ namespace Fig
|
||||
// std::cerr << errorClassRes.unwrap()->toString().toBasicString() << "\n";
|
||||
// std::cerr << errorMessageRes.unwrap()->toString().toBasicString() << "\n";
|
||||
|
||||
const FString &errorClass = errorClassRes.unwrap()->as<ValueType::StringClass>();
|
||||
const FString &errorMessage = errorMessageRes.unwrap()->as<ValueType::StringClass>();
|
||||
const String &errorClass = errorClassRes.unwrap()->as<ValueType::StringClass>();
|
||||
const String &errorMessage = errorMessageRes.unwrap()->as<ValueType::StringClass>();
|
||||
|
||||
ErrorLog::logFigErrorInterface(errorClass, errorMessage);
|
||||
std::exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw EvaluatorError(u8"UncaughtExceptionError",
|
||||
std::format("Uncaught exception: {}", sr.result->toString().toBasicString()),
|
||||
stmt);
|
||||
throw EvaluatorError(
|
||||
U"\1", std::format("Uncaught exception: {}", sr.result->toString().toBasicString()), stmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,12 +34,12 @@ namespace Fig
|
||||
ContextPtr global;
|
||||
|
||||
public:
|
||||
FString sourcePath;
|
||||
std::vector<FString> sourceLines;
|
||||
String sourcePath;
|
||||
std::vector<String> sourceLines;
|
||||
|
||||
void SetSourcePath(const FString &sp) { sourcePath = sp; }
|
||||
void SetSourcePath(const String &sp) { sourcePath = sp; }
|
||||
|
||||
void SetSourceLines(const std::vector<FString> &sl) { sourceLines = sl; }
|
||||
void SetSourceLines(const std::vector<String> &sl) { sourceLines = sl; }
|
||||
|
||||
void SetGlobalContext(ContextPtr ctx)
|
||||
{
|
||||
@@ -47,7 +47,7 @@ namespace Fig
|
||||
global = ctx;
|
||||
}
|
||||
|
||||
void CreateGlobalContext() { global = std::make_shared<Context>(FString(u8"<Global>")); }
|
||||
void CreateGlobalContext() { global = std::make_shared<Context>(String(U"\1")); }
|
||||
|
||||
void RegisterBuiltins() // only function
|
||||
{
|
||||
@@ -67,33 +67,31 @@ namespace Fig
|
||||
.interfaceType = Builtins::getErrorInterfaceTypeInfo(),
|
||||
.structType = Builtins::getTypeErrorStructTypeInfo(),
|
||||
.implMethods = {
|
||||
{u8"toString",
|
||||
Function(
|
||||
u8"toString",
|
||||
Ast::FunctionParameters{},
|
||||
ValueType::String,
|
||||
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
|
||||
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::BinaryExprAst>(
|
||||
std::make_shared<Ast::ValueExprAst>(std::make_shared<Object>(u8"TypeError: ")),
|
||||
Ast::Operator::Add,
|
||||
std::make_shared<Ast::FunctionCallExpr>(
|
||||
std::make_shared<Ast::VarExprAst>(u8"getErrorMessage"),
|
||||
Ast::FunctionArguments{})))})),
|
||||
nullptr)},
|
||||
{u8"getErrorClass",
|
||||
Function(u8"getErrorClass",
|
||||
{U"\1",
|
||||
Function(U"\1",
|
||||
Ast::FunctionParameters{},
|
||||
ValueType::String,
|
||||
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
|
||||
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::BinaryExprAst>(
|
||||
std::make_shared<Ast::ValueExprAst>(std::make_shared<Object>(U"\1")),
|
||||
Ast::Operator::Add,
|
||||
std::make_shared<Ast::FunctionCallExpr>(
|
||||
std::make_shared<Ast::VarExprAst>(U"\1"), Ast::FunctionArguments{})))})),
|
||||
nullptr)},
|
||||
{U"\1",
|
||||
Function(U"\1",
|
||||
Ast::FunctionParameters{},
|
||||
ValueType::String,
|
||||
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
|
||||
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::ValueExprAst>(
|
||||
std::make_shared<Object>(FString(u8"TypeError"))))})),
|
||||
std::make_shared<Object>(String(U"\1"))))})),
|
||||
nullptr)},
|
||||
{u8"getErrorMessage",
|
||||
Function(u8"getErrorMessage",
|
||||
{U"\1",
|
||||
Function(U"\1",
|
||||
Ast::FunctionParameters{},
|
||||
ValueType::String,
|
||||
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
|
||||
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::VarExprAst>(u8"msg"))})),
|
||||
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::VarExprAst>(U"\1"))})),
|
||||
nullptr)},
|
||||
}});
|
||||
}
|
||||
@@ -110,13 +108,13 @@ namespace Fig
|
||||
|
||||
bool isInterfaceSignatureMatch(const Ast::ImplementMethod &, const Ast::InterfaceMethod &);
|
||||
|
||||
ObjectPtr genTypeError(const FString &_msg,
|
||||
ObjectPtr genTypeError(const String &_msg,
|
||||
const Ast::AstBase &_ast,
|
||||
ContextPtr ctx,
|
||||
std::source_location loc = std::source_location::current())
|
||||
{
|
||||
ContextPtr stCtx = std::make_shared<Context>(u8"<TypeError Instance>");
|
||||
stCtx->def(u8"msg", ValueType::String, AccessModifier::Const, std::make_shared<Object>(_msg));
|
||||
ContextPtr stCtx = std::make_shared<Context>(U"\1");
|
||||
stCtx->def(U"\1", ValueType::String, AccessModifier::Const, std::make_shared<Object>(_msg));
|
||||
return std::make_shared<Object>(StructInstance(Builtins::getTypeErrorStructTypeInfo(), stCtx));
|
||||
}
|
||||
|
||||
@@ -143,7 +141,7 @@ namespace Fig
|
||||
StatementResult evalBlockStatement(Ast::BlockStatement, ContextPtr); // block
|
||||
StatementResult evalStatement(Ast::Statement, ContextPtr); // statement
|
||||
|
||||
std::filesystem::path resolveModulePath(const std::vector<FString> &);
|
||||
std::filesystem::path resolveModulePath(const std::vector<String> &);
|
||||
ContextPtr loadModule(const std::filesystem::path &);
|
||||
|
||||
StatementResult evalImportSt(Ast::Import, ContextPtr);
|
||||
|
||||
@@ -8,16 +8,15 @@ namespace Fig
|
||||
class EvaluatorError final : public AddressableError
|
||||
{
|
||||
public:
|
||||
FString typeName;
|
||||
String typeName;
|
||||
using AddressableError::AddressableError;
|
||||
EvaluatorError(FString _typeName,
|
||||
FString msg,
|
||||
EvaluatorError(String _typeName,
|
||||
String msg,
|
||||
Ast::AstBase ast,
|
||||
std::source_location loc = std::source_location::current())
|
||||
{
|
||||
message = msg;
|
||||
|
||||
|
||||
src_loc = std::move(loc);
|
||||
|
||||
typeName = std::move(_typeName);
|
||||
@@ -29,25 +28,24 @@ namespace Fig
|
||||
sourcePath = *ast->getAAI().sourcePath;
|
||||
sourceLines = *ast->getAAI().sourceLines;
|
||||
}
|
||||
|
||||
}
|
||||
EvaluatorError(FString _typeName,
|
||||
std::string_view msg,
|
||||
Ast::AstBase ast,
|
||||
std::source_location loc = std::source_location::current())
|
||||
{
|
||||
message = FString::fromBasicString(std::string(msg.data()));
|
||||
line = ast->getAAI().line;
|
||||
column = ast->getAAI().column;
|
||||
// EvaluatorError(String _typeName,
|
||||
// std::string_view msg,
|
||||
// Ast::AstBase ast,
|
||||
// std::source_location loc = std::source_location::current())
|
||||
// {
|
||||
// message = String(std::string(msg.data()));
|
||||
// line = ast->getAAI().line;
|
||||
// column = ast->getAAI().column;
|
||||
|
||||
src_loc = std::move(loc);
|
||||
// src_loc = std::move(loc);
|
||||
|
||||
typeName = std::move(_typeName);
|
||||
// typeName = std::move(_typeName);
|
||||
|
||||
sourcePath = *ast->getAAI().sourcePath;
|
||||
sourceLines = *ast->getAAI().sourceLines;
|
||||
}
|
||||
// sourcePath = *ast->getAAI().sourcePath;
|
||||
// sourceLines = *ast->getAAI().sourceLines;
|
||||
// }
|
||||
|
||||
virtual FString getErrorType() const override { return typeName; }
|
||||
virtual String getErrorType() const override { return typeName; }
|
||||
};
|
||||
}; // namespace Fig
|
||||
Reference in New Issue
Block a user