尝试UTF32String

This commit is contained in:
2026-02-05 22:20:21 +08:00
parent d897f41c57
commit 9c68b2e77d
69 changed files with 3078 additions and 2605 deletions

View File

@@ -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())

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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(),

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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>

View File

@@ -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

View File

@@ -1,6 +1,6 @@
#pragma once
#include <Core/fig_string.hpp>
#include <Core/String.hpp>
#include <Evaluator/Value/value.hpp>
namespace Fig

View File

@@ -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>

View File

@@ -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; }

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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)));
}
};

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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