forked from PuqiAR/Fig-TreeWalker
[Feat] 模块系统支持,使用 import x.x.x导入
[Fix] Context内部辅助函数修改, getStructName .... [Feat] 增加字符串下标获取操作,和修改字符操作,实现使用了第四点的函数 [Impl] FString添加新方法 getRealChar, realReplace [Fun] 在utf8_iterator中辱骂了C++
This commit is contained in:
27
src/Ast/Statements/ImportSt.hpp
Normal file
27
src/Ast/Statements/ImportSt.hpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Ast/astBase.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Fig::Ast
|
||||||
|
{
|
||||||
|
class ImportSt final : public StatementAst
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<FString> path;
|
||||||
|
|
||||||
|
ImportSt()
|
||||||
|
{
|
||||||
|
type = AstType::ImportSt;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportSt(std::vector<FString> _path) :
|
||||||
|
path(std::move(_path))
|
||||||
|
{
|
||||||
|
type = AstType::ImportSt;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Import = std::shared_ptr<ImportSt>;
|
||||||
|
};
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <Ast/Statements/StructDefSt.hpp>
|
#include <Ast/Statements/StructDefSt.hpp>
|
||||||
#include <Ast/Statements/IfSt.hpp>
|
#include <Ast/Statements/IfSt.hpp>
|
||||||
#include <Ast/Statements/ImplementSt.hpp>
|
#include <Ast/Statements/ImplementSt.hpp>
|
||||||
|
#include <Ast/Statements/ImportSt.hpp>
|
||||||
#include <Ast/Statements/FunctionDefSt.hpp>
|
#include <Ast/Statements/FunctionDefSt.hpp>
|
||||||
#include <Ast/Statements/ControlSt.hpp>
|
#include <Ast/Statements/ControlSt.hpp>
|
||||||
#include <Ast/Statements/ExpressionStmt.hpp>
|
#include <Ast/Statements/ExpressionStmt.hpp>
|
||||||
|
|||||||
@@ -50,12 +50,15 @@ namespace Fig::Ast
|
|||||||
ElseSt,
|
ElseSt,
|
||||||
ElseIfSt,
|
ElseIfSt,
|
||||||
|
|
||||||
VarAssignSt,
|
// VarAssignSt,
|
||||||
WhileSt,
|
WhileSt,
|
||||||
ForSt,
|
ForSt,
|
||||||
ReturnSt,
|
ReturnSt,
|
||||||
BreakSt,
|
BreakSt,
|
||||||
ContinueSt,
|
ContinueSt,
|
||||||
|
|
||||||
|
PackageSt,
|
||||||
|
ImportSt,
|
||||||
};
|
};
|
||||||
|
|
||||||
// static const std::unordered_map<AstType, FString> astTypeToString{
|
// static const std::unordered_map<AstType, FString> astTypeToString{
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ namespace Fig
|
|||||||
Context(const Context &) = default;
|
Context(const Context &) = default;
|
||||||
Context(const FString &name, ContextPtr p = nullptr) :
|
Context(const FString &name, ContextPtr p = nullptr) :
|
||||||
scopeName(name), parent(p) {}
|
scopeName(name), parent(p) {}
|
||||||
Context(const FString &name, std::unordered_map<FString, TypeInfo> types, std::unordered_map<FString, std::shared_ptr<VariableSlot>> vars, std::unordered_map<FString, AccessModifier> _ams) :
|
|
||||||
scopeName(std::move(name)), variables(std::move(vars)) {}
|
|
||||||
|
|
||||||
void setParent(ContextPtr _parent)
|
void setParent(ContextPtr _parent)
|
||||||
{
|
{
|
||||||
@@ -120,7 +118,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else if (parent != nullptr)
|
else if (parent != nullptr)
|
||||||
{
|
{
|
||||||
parent->set(name, value);
|
parent->_update(name, value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -191,7 +189,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else if (parent)
|
else if (parent)
|
||||||
{
|
{
|
||||||
return parent->getFunctionName(id);
|
return parent->getStructName(id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
// using String = std::u8string;
|
// using String = std::u8string;
|
||||||
@@ -93,6 +92,60 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FString getRealChar(size_t index)
|
||||||
|
{
|
||||||
|
FString ch;
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (size_t i = 0; i < size();)
|
||||||
|
{
|
||||||
|
uint8_t cplen = 1;
|
||||||
|
if ((at(i) & 0xf8) == 0xf0)
|
||||||
|
cplen = 4;
|
||||||
|
else if ((at(i) & 0xf0) == 0xe0)
|
||||||
|
cplen = 3;
|
||||||
|
else if ((at(i) & 0xe0) == 0xc0)
|
||||||
|
cplen = 2;
|
||||||
|
if (i + cplen > size())
|
||||||
|
cplen = 1;
|
||||||
|
|
||||||
|
if (cnt == index)
|
||||||
|
{
|
||||||
|
ch += substr(i, cplen);
|
||||||
|
}
|
||||||
|
|
||||||
|
i += cplen;
|
||||||
|
++ cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void realReplace(size_t index, const FString &src)
|
||||||
|
{
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (size_t i = 0; i < size();)
|
||||||
|
{
|
||||||
|
uint8_t cplen = 1;
|
||||||
|
if ((at(i) & 0xf8) == 0xf0)
|
||||||
|
cplen = 4;
|
||||||
|
else if ((at(i) & 0xf0) == 0xe0)
|
||||||
|
cplen = 3;
|
||||||
|
else if ((at(i) & 0xe0) == 0xc0)
|
||||||
|
cplen = 2;
|
||||||
|
if (i + cplen > size())
|
||||||
|
cplen = 1;
|
||||||
|
|
||||||
|
if (cnt == index)
|
||||||
|
{
|
||||||
|
*this = FString(substr(0, i)) + src +
|
||||||
|
FString(substr(i + cplen));
|
||||||
|
}
|
||||||
|
|
||||||
|
i += cplen;
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
@@ -107,4 +160,4 @@ namespace std
|
|||||||
return std::hash<std::u8string>{}(static_cast<const std::u8string &>(s));
|
return std::hash<std::u8string>{}(static_cast<const std::u8string &>(s));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace std
|
||||||
@@ -8,6 +8,22 @@
|
|||||||
// fuck
|
// fuck
|
||||||
// generate by Qwen3-Coder:
|
// generate by Qwen3-Coder:
|
||||||
|
|
||||||
|
// 2025-12-26
|
||||||
|
/*
|
||||||
|
again: C++ fuck you
|
||||||
|
fuck you
|
||||||
|
fuck you!
|
||||||
|
|
||||||
|
fuck
|
||||||
|
|
||||||
|
C++ IS A PIECE OF SHIT
|
||||||
|
STOP USING C++
|
||||||
|
|
||||||
|
unicodeString = "some unicode points";
|
||||||
|
unicodeString[0] ---> ?????
|
||||||
|
FUCK YOU C++
|
||||||
|
*/
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
class UTF8Char
|
class UTF8Char
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
|
#include <Error/errorLog.hpp>
|
||||||
#include <Evaluator/evaluator.hpp>
|
#include <Evaluator/evaluator.hpp>
|
||||||
#include <Evaluator/evaluator_error.hpp>
|
#include <Evaluator/evaluator_error.hpp>
|
||||||
#include <Module/builtins.hpp>
|
#include <Module/builtins.hpp>
|
||||||
#include <Context/context.hpp>
|
#include <Context/context.hpp>
|
||||||
#include <Utils/utils.hpp>
|
#include <Utils/utils.hpp>
|
||||||
|
|
||||||
#include <Parser/parser.hpp>
|
#include <Parser/parser.hpp>
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
LvObject Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx)
|
LvObject Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx)
|
||||||
@@ -22,6 +25,25 @@ namespace Fig
|
|||||||
LvObject base = evalLv(me->base, ctx);
|
LvObject base = evalLv(me->base, ctx);
|
||||||
RvObject baseVal = base.get();
|
RvObject baseVal = base.get();
|
||||||
const FString &member = me->member;
|
const FString &member = me->member;
|
||||||
|
if (baseVal->getTypeInfo() == ValueType::Module)
|
||||||
|
{
|
||||||
|
const Module &mod = baseVal->as<Module>();
|
||||||
|
if (mod.ctx->contains(member) && mod.ctx->isVariablePublic(member))
|
||||||
|
{
|
||||||
|
return LvObject(
|
||||||
|
mod.ctx->get(member)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw EvaluatorError(
|
||||||
|
u8"VariableNotFoundError",
|
||||||
|
std::format(
|
||||||
|
"`{}` has not variable '{}', check if it is public",
|
||||||
|
baseVal->toString().toBasicString(),
|
||||||
|
member.toBasicString()),
|
||||||
|
me->base);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (baseVal->hasMemberFunction(member))
|
if (baseVal->hasMemberFunction(member))
|
||||||
{
|
{
|
||||||
return LvObject(std::make_shared<VariableSlot>(
|
return LvObject(std::make_shared<VariableSlot>(
|
||||||
@@ -71,10 +93,8 @@ namespace Fig
|
|||||||
u8"TypeError",
|
u8"TypeError",
|
||||||
std::format(
|
std::format(
|
||||||
"Type `List` indices must be `Int`, got '{}'",
|
"Type `List` indices must be `Int`, got '{}'",
|
||||||
index->getTypeInfo().toString().toBasicString()
|
index->getTypeInfo().toString().toBasicString()),
|
||||||
),
|
ie->index);
|
||||||
ie->index
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
List &list = base.get()->as<List>();
|
List &list = base.get()->as<List>();
|
||||||
ValueType::IntClass indexVal = index->as<ValueType::IntClass>();
|
ValueType::IntClass indexVal = index->as<ValueType::IntClass>();
|
||||||
@@ -85,21 +105,48 @@ namespace Fig
|
|||||||
std::format(
|
std::format(
|
||||||
"Index {} out of list `{}` range",
|
"Index {} out of list `{}` range",
|
||||||
indexVal,
|
indexVal,
|
||||||
base.get()->toString().toBasicString()
|
base.get()->toString().toBasicString()),
|
||||||
),
|
ie->index);
|
||||||
ie->index
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return LvObject(
|
return LvObject(
|
||||||
base.get(),
|
base.get(),
|
||||||
indexVal
|
indexVal,
|
||||||
);
|
LvObject::Kind::ListElement);
|
||||||
}
|
}
|
||||||
else if (type == ValueType::Map)
|
else if (type == ValueType::Map)
|
||||||
{
|
{
|
||||||
return LvObject(
|
return LvObject(
|
||||||
base.get(),
|
base.get(),
|
||||||
index
|
index,
|
||||||
|
LvObject::Kind::MapElement);
|
||||||
|
}
|
||||||
|
else if (type == ValueType::String)
|
||||||
|
{
|
||||||
|
if (index->getTypeInfo() != ValueType::Int)
|
||||||
|
{
|
||||||
|
throw EvaluatorError(
|
||||||
|
u8"TypeError",
|
||||||
|
std::format(
|
||||||
|
"Type `String` indices must be `Int`, got '{}'",
|
||||||
|
index->getTypeInfo().toString().toBasicString()),
|
||||||
|
ie->index);
|
||||||
|
}
|
||||||
|
FString &string = base.get()->as<ValueType::StringClass>();
|
||||||
|
ValueType::IntClass indexVal = index->as<ValueType::IntClass>();
|
||||||
|
if (indexVal >= string.length())
|
||||||
|
{
|
||||||
|
throw EvaluatorError(
|
||||||
|
u8"IndexOutOfRangeError",
|
||||||
|
std::format(
|
||||||
|
"Index {} out of string `{}` range",
|
||||||
|
indexVal,
|
||||||
|
base.get()->toString().toBasicString()),
|
||||||
|
ie->index);
|
||||||
|
}
|
||||||
|
return LvObject(
|
||||||
|
base.get(),
|
||||||
|
indexVal,
|
||||||
|
LvObject::Kind::StringElement
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -111,7 +158,6 @@ namespace Fig
|
|||||||
base.declaredType().toString().toBasicString()),
|
base.declaredType().toString().toBasicString()),
|
||||||
ie->base);
|
ie->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
LvObject Evaluator::evalLv(Ast::Expression exp, ContextPtr ctx)
|
LvObject Evaluator::evalLv(Ast::Expression exp, ContextPtr ctx)
|
||||||
{
|
{
|
||||||
@@ -322,9 +368,13 @@ namespace Fig
|
|||||||
Ast::FunctionParameters fnParas = fnStruct.paras;
|
Ast::FunctionParameters fnParas = fnStruct.paras;
|
||||||
if (fnArgs.getLength() < fnParas.posParas.size() || fnArgs.getLength() > fnParas.size())
|
if (fnArgs.getLength() < fnParas.posParas.size() || fnArgs.getLength() > fnParas.size())
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw RuntimeError(FString(
|
||||||
u8"ArgumentMismatchError",
|
std::format(
|
||||||
std::format("Function '{}' expects {} to {} arguments, but {} were provided", fnName.toBasicString(), fnParas.posParas.size(), fnParas.size(), fnArgs.getLength()), fnArgs.argv.back());
|
"Function '{}' expects {} to {} arguments, but {} were provided",
|
||||||
|
fnName.toBasicString(),
|
||||||
|
fnParas.posParas.size(),
|
||||||
|
fnParas.size(),
|
||||||
|
fnArgs.getLength())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// positional parameters type check
|
// positional parameters type check
|
||||||
@@ -484,8 +534,15 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
const Function &fn = fnObj->as<Function>();
|
const Function &fn = fnObj->as<Function>();
|
||||||
size_t fnId = fn.id;
|
size_t fnId = fn.id;
|
||||||
const auto &fnNameOpt = ctx->getFunctionName(fnId);
|
// const auto &fnNameOpt = ctx->getFunctionName(fnId);
|
||||||
|
// const FString &fnName = (fnNameOpt ? *fnNameOpt : u8"<anonymous>");
|
||||||
|
|
||||||
|
auto fnNameOpt = ctx->getFunctionName(fnId);
|
||||||
|
if (!fnNameOpt && fn.closureContext)
|
||||||
|
fnNameOpt = fn.closureContext->getFunctionName(fnId);
|
||||||
|
|
||||||
const FString &fnName = (fnNameOpt ? *fnNameOpt : u8"<anonymous>");
|
const FString &fnName = (fnNameOpt ? *fnNameOpt : u8"<anonymous>");
|
||||||
|
|
||||||
return evalFunctionCall(fn, fnCall->arg, fnName, ctx);
|
return evalFunctionCall(fn, fnCall->arg, fnName, ctx);
|
||||||
}
|
}
|
||||||
case AstType::FunctionLiteralExpr: {
|
case AstType::FunctionLiteralExpr: {
|
||||||
@@ -745,6 +802,11 @@ namespace Fig
|
|||||||
using enum Ast::AstType;
|
using enum Ast::AstType;
|
||||||
switch (stmt->getType())
|
switch (stmt->getType())
|
||||||
{
|
{
|
||||||
|
case ImportSt: {
|
||||||
|
auto i = std::dynamic_pointer_cast<Ast::ImportSt>(stmt);
|
||||||
|
assert(i != nullptr);
|
||||||
|
return evalImportSt(i, ctx);
|
||||||
|
}
|
||||||
case VarDefSt: {
|
case VarDefSt: {
|
||||||
auto varDef = std::dynamic_pointer_cast<Ast::VarDefAst>(stmt);
|
auto varDef = std::dynamic_pointer_cast<Ast::VarDefAst>(stmt);
|
||||||
assert(varDef != nullptr);
|
assert(varDef != nullptr);
|
||||||
@@ -1067,6 +1129,189 @@ namespace Fig
|
|||||||
magic_enum::enum_name(stmt->getType()))));
|
magic_enum::enum_name(stmt->getType()))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::filesystem::path Evaluator::resolveModulePath(const std::vector<FString> &pathVec)
|
||||||
|
{
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
static const std::vector<fs::path> defaultLibraryPath{
|
||||||
|
"Library",
|
||||||
|
"Library/fpm"};
|
||||||
|
|
||||||
|
std::vector<fs::path> pathToFind(defaultLibraryPath);
|
||||||
|
pathToFind.insert(
|
||||||
|
pathToFind.begin(),
|
||||||
|
fs::path(
|
||||||
|
this->sourcePath.toBasicString())
|
||||||
|
.parent_path()); // first search module at the source file path
|
||||||
|
|
||||||
|
fs::path path;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Example:
|
||||||
|
import comp.config;
|
||||||
|
*/
|
||||||
|
|
||||||
|
const FString &modPathStrTop = pathVec.at(0);
|
||||||
|
fs::path modPath;
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (auto &parentFolder : pathToFind)
|
||||||
|
{
|
||||||
|
modPath = parentFolder / FString(modPathStrTop + u8".fig").toBasicString();
|
||||||
|
if (fs::exists(modPath))
|
||||||
|
{
|
||||||
|
path = modPath;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
modPath = parentFolder / modPathStrTop.toBasicString();
|
||||||
|
if (fs::is_directory(modPath)) // comp is a directory
|
||||||
|
{
|
||||||
|
modPath = modPath / FString(modPathStrTop + u8".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())));
|
||||||
|
}
|
||||||
|
found = true;
|
||||||
|
path = modPath;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
throw RuntimeError(
|
||||||
|
FString(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);
|
||||||
|
modPath = modPath.parent_path(); // get the folder
|
||||||
|
modPath = modPath / FString(next + u8".fig").toBasicString();
|
||||||
|
if (fs::exists(modPath))
|
||||||
|
{
|
||||||
|
if (i != pathVec.size() - 1)
|
||||||
|
throw RuntimeError(FString(
|
||||||
|
std::format(
|
||||||
|
"expects {} as parent directory and find next module, but got a file",
|
||||||
|
next.toBasicString())));
|
||||||
|
// it's the last module
|
||||||
|
found2 = true;
|
||||||
|
path = modPath;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// `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())));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found2 && !fs::exists(modPath))
|
||||||
|
throw RuntimeError(FString(
|
||||||
|
std::format("Could not find module `{}`", pathVec.end()->toBasicString())));
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContextPtr Evaluator::loadModule(const std::filesystem::path &path)
|
||||||
|
{
|
||||||
|
std::ifstream file(path);
|
||||||
|
assert(file.is_open());
|
||||||
|
|
||||||
|
std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
Lexer lexer((FString(source)));
|
||||||
|
Parser parser(lexer);
|
||||||
|
std::vector<Ast::AstBase> asts;
|
||||||
|
|
||||||
|
std::vector<FString> sourceLines = Utils::splitSource(FString(source));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
asts = parser.parseAll();
|
||||||
|
}
|
||||||
|
catch (const AddressableError &e)
|
||||||
|
{
|
||||||
|
ErrorLog::logAddressableError(e, sourcePath, sourceLines);
|
||||||
|
}
|
||||||
|
catch (const UnaddressableError &e)
|
||||||
|
{
|
||||||
|
ErrorLog::logUnaddressableError(e);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "uncaught exception of: " << e.what() << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
Evaluator evaluator;
|
||||||
|
evaluator.SetSourcePath(FString(path.string()));
|
||||||
|
|
||||||
|
ContextPtr modctx = std::make_shared<Context>(
|
||||||
|
FString(std::format("<Module at {}>", path.string())),
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
evaluator.SetGlobalContext(modctx);
|
||||||
|
evaluator.RegisterBuiltins();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
evaluator.Run(asts);
|
||||||
|
}
|
||||||
|
catch (std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << "load module failed" << '\n';
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return evaluator.global;
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementResult Evaluator::evalImportSt(Ast::Import i, ContextPtr ctx)
|
||||||
|
{
|
||||||
|
const std::vector<FString> &pathVec = i->path;
|
||||||
|
auto path = resolveModulePath(pathVec);
|
||||||
|
ContextPtr modCtx = loadModule(path);
|
||||||
|
|
||||||
|
const FString &modName = pathVec.at(pathVec.size() - 1);
|
||||||
|
|
||||||
|
// std::cerr << modName.toBasicString() << '\n'; DEBUG
|
||||||
|
|
||||||
|
if (ctx->containsInThisScope(modName))
|
||||||
|
{
|
||||||
|
throw EvaluatorError(
|
||||||
|
u8"RedeclarationError",
|
||||||
|
std::format(
|
||||||
|
"{} has already been declared.",
|
||||||
|
modName.toBasicString()),
|
||||||
|
i);
|
||||||
|
}
|
||||||
|
ctx->def(
|
||||||
|
modName,
|
||||||
|
ValueType::Module,
|
||||||
|
AccessModifier::PublicConst,
|
||||||
|
std::make_shared<Object>(
|
||||||
|
Module(
|
||||||
|
modName,
|
||||||
|
modCtx)));
|
||||||
|
return StatementResult::normal();
|
||||||
|
}
|
||||||
|
|
||||||
StatementResult Evaluator::Run(std::vector<Ast::AstBase> asts)
|
StatementResult Evaluator::Run(std::vector<Ast::AstBase> asts)
|
||||||
{
|
{
|
||||||
using Ast::AstType;
|
using Ast::AstType;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <Error/error.hpp>
|
#include <Error/error.hpp>
|
||||||
#include <Module/builtins.hpp>
|
#include <Module/builtins.hpp>
|
||||||
#include <Value/LvObject.hpp>
|
#include <Value/LvObject.hpp>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
@@ -52,6 +53,12 @@ namespace Fig
|
|||||||
private:
|
private:
|
||||||
ContextPtr global;
|
ContextPtr global;
|
||||||
public:
|
public:
|
||||||
|
FString sourcePath;
|
||||||
|
|
||||||
|
void SetSourcePath(const FString &sp)
|
||||||
|
{
|
||||||
|
sourcePath = sp;
|
||||||
|
}
|
||||||
|
|
||||||
void SetGlobalContext(ContextPtr ctx)
|
void SetGlobalContext(ContextPtr ctx)
|
||||||
{
|
{
|
||||||
@@ -110,6 +117,11 @@ namespace Fig
|
|||||||
StatementResult evalBlockStatement(Ast::BlockStatement, ContextPtr); // block
|
StatementResult evalBlockStatement(Ast::BlockStatement, ContextPtr); // block
|
||||||
StatementResult evalStatement(Ast::Statement, ContextPtr); // statement
|
StatementResult evalStatement(Ast::Statement, ContextPtr); // statement
|
||||||
|
|
||||||
|
std::filesystem::path resolveModulePath(const std::vector<FString> &);
|
||||||
|
ContextPtr loadModule(const std::filesystem::path &);
|
||||||
|
|
||||||
|
StatementResult evalImportSt(Ast::Import, ContextPtr);
|
||||||
|
|
||||||
StatementResult Run(std::vector<Ast::AstBase>); // Entry
|
StatementResult Run(std::vector<Ast::AstBase>); // Entry
|
||||||
|
|
||||||
void printStackTrace();
|
void printStackTrace();
|
||||||
|
|||||||
9
src/Module/Library/std/io/io.fig
Normal file
9
src/Module/Library/std/io/io.fig
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
Official Module `std.io`
|
||||||
|
Library/std/io/io.fig
|
||||||
|
*/
|
||||||
|
|
||||||
|
public func print(value) -> Null
|
||||||
|
{
|
||||||
|
__fstdout_print(value);
|
||||||
|
}
|
||||||
6
src/Module/Library/std/std.fig
Normal file
6
src/Module/Library/std/std.fig
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/*
|
||||||
|
Official Module `std`
|
||||||
|
Library/std/std.fig
|
||||||
|
*/
|
||||||
|
|
||||||
|
import io; // link std io
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
|
||||||
#include <Value/value.hpp>
|
|
||||||
#include <Context/context.hpp>
|
|
||||||
|
|
||||||
namespace Fig
|
|
||||||
{
|
|
||||||
// class Module
|
|
||||||
// {
|
|
||||||
// public:
|
|
||||||
// const FString name;
|
|
||||||
// const FString spec;
|
|
||||||
// const FString path;
|
|
||||||
|
|
||||||
// std::shared_ptr<Context> context; // module-level context
|
|
||||||
|
|
||||||
// /*
|
|
||||||
|
|
||||||
// import module -> automatically create a module context and call function `init` if exists
|
|
||||||
// all global functions, variables, structs, etc will be stored in module context
|
|
||||||
// then module context will be linked to the current context
|
|
||||||
|
|
||||||
// */
|
|
||||||
// Module(const FString &moduleName, const FString &moduleSpec, const FString &modulePath) :
|
|
||||||
// name(moduleName), spec(moduleSpec), path(modulePath)
|
|
||||||
// {
|
|
||||||
// context = std::make_shared<Context>(FString(std::format("<Module {}>", name.toBasicString())), nullptr);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// bool hasSymbol(const FString &symbolName)
|
|
||||||
// {
|
|
||||||
// return context->contains(symbolName);
|
|
||||||
// }
|
|
||||||
// Object getSymbol(const FString &symbolName)
|
|
||||||
// {
|
|
||||||
// auto valOpt = context->get(symbolName);
|
|
||||||
// if (!valOpt.has_value())
|
|
||||||
// {
|
|
||||||
// throw RuntimeError(FStringView(std::format("Symbol '{}' not found in module '{}'", symbolName.toBasicString(), name.toBasicString())));
|
|
||||||
// }
|
|
||||||
// return valOpt.value();
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
};
|
|
||||||
@@ -350,7 +350,11 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
Ast::Statement stmt;
|
Ast::Statement stmt;
|
||||||
if (isThis(TokenType::EndOfFile)) { return makeAst<Ast::EofStmt>(); }
|
if (isThis(TokenType::EndOfFile)) { return makeAst<Ast::EofStmt>(); }
|
||||||
if (isThis(TokenType::Public))
|
else if (isThis(TokenType::Import))
|
||||||
|
{
|
||||||
|
stmt = __parseImport();
|
||||||
|
}
|
||||||
|
else if (isThis(TokenType::Public))
|
||||||
{
|
{
|
||||||
next(); // consume `public`
|
next(); // consume `public`
|
||||||
if (isThis(TokenType::Variable) || isThis(TokenType::Const))
|
if (isThis(TokenType::Variable) || isThis(TokenType::Const))
|
||||||
@@ -708,8 +712,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(FString(
|
throwAddressableError<SyntaxError>(FString(
|
||||||
std::format("Expect `,` or `}}` in struct initialization expression, got {}",
|
std::format("Expect `,` or `}}` in struct initialization expression, got {}",
|
||||||
currentToken().toString().toBasicString())
|
currentToken().toString().toBasicString())));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect(TokenType::RightBrace);
|
expect(TokenType::RightBrace);
|
||||||
@@ -782,6 +785,33 @@ namespace Fig
|
|||||||
return makeAst<Ast::FunctionLiteralExprAst>(params, __parseBlockStatement());
|
return makeAst<Ast::FunctionLiteralExprAst>(params, __parseBlockStatement());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ast::Import Parser::__parseImport()
|
||||||
|
{
|
||||||
|
next(); // consume `import`
|
||||||
|
std::vector<FString> path;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
expect(TokenType::Identifier, u8"package name");
|
||||||
|
path.push_back(currentToken().getValue());
|
||||||
|
next(); // consume package name
|
||||||
|
if (isThis(TokenType::Semicolon))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (isThis(TokenType::Dot))
|
||||||
|
{
|
||||||
|
next(); // consume `.`
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw SyntaxError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(TokenType::Semicolon);
|
||||||
|
next(); // consume `;`
|
||||||
|
return makeAst<Ast::ImportSt>(path);
|
||||||
|
}
|
||||||
|
|
||||||
Ast::Expression Parser::parseExpression(Precedence bp, TokenType stop, TokenType stop2)
|
Ast::Expression Parser::parseExpression(Precedence bp, TokenType stop, TokenType stop2)
|
||||||
{
|
{
|
||||||
Ast::Expression lhs;
|
Ast::Expression lhs;
|
||||||
@@ -921,10 +951,17 @@ namespace Fig
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Package/Module Import Support
|
|
||||||
while (!isEOF())
|
while (!isEOF())
|
||||||
{
|
{
|
||||||
pushNode(__parseStatement());
|
auto stmt = __parseStatement();
|
||||||
|
if (!output.empty() && stmt->getType() == Ast::AstType::PackageSt)
|
||||||
|
{
|
||||||
|
throw SyntaxError(
|
||||||
|
u8"Package must be at the beginning of the file",
|
||||||
|
currentAAI.line,
|
||||||
|
currentAAI.column);
|
||||||
|
}
|
||||||
|
pushNode(stmt);
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -326,6 +326,8 @@ namespace Fig
|
|||||||
|
|
||||||
Ast::FunctionLiteralExpr __parseFunctionLiteralExpr(); // entry: current is Token::LParen after Token::Function
|
Ast::FunctionLiteralExpr __parseFunctionLiteralExpr(); // entry: current is Token::LParen after Token::Function
|
||||||
|
|
||||||
|
Ast::Import __parseImport(); // entry: current is Token::Import
|
||||||
|
|
||||||
Ast::Statement __parseStatement(); // entry: (idk)
|
Ast::Statement __parseStatement(); // entry: (idk)
|
||||||
Ast::Expression parseExpression(Precedence, TokenType = TokenType::Semicolon, TokenType = TokenType::Semicolon);
|
Ast::Expression parseExpression(Precedence, TokenType = TokenType::Semicolon, TokenType = TokenType::Semicolon);
|
||||||
std::vector<Ast::AstBase> parseAll();
|
std::vector<Ast::AstBase> parseAll();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace Fig
|
|||||||
Identifier,
|
Identifier,
|
||||||
|
|
||||||
/* Keywords */
|
/* Keywords */
|
||||||
|
Package, // package
|
||||||
And, // and
|
And, // and
|
||||||
Or, // or
|
Or, // or
|
||||||
Not, // not
|
Not, // not
|
||||||
@@ -48,7 +49,7 @@ namespace Fig
|
|||||||
LiteralNumber, // number (int,float...)
|
LiteralNumber, // number (int,float...)
|
||||||
LiteralString, // FString
|
LiteralString, // FString
|
||||||
LiteralBool, // bool (true/false)
|
LiteralBool, // bool (true/false)
|
||||||
LiteralNull, // null (Null的唯一实例)
|
LiteralNull, // null (Null unique instance)
|
||||||
|
|
||||||
/* Punct */
|
/* Punct */
|
||||||
Plus, // +
|
Plus, // +
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#pragma once
|
|
||||||
|
#include <Lexer/lexer.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/fig_string.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
@@ -9,6 +10,32 @@
|
|||||||
|
|
||||||
namespace Fig::Utils
|
namespace Fig::Utils
|
||||||
{
|
{
|
||||||
|
|
||||||
|
inline std::vector<FString> splitSource(FString source)
|
||||||
|
{
|
||||||
|
UTF8Iterator it(source);
|
||||||
|
std::vector<FString> lines;
|
||||||
|
FString currentLine;
|
||||||
|
while (!it.isEnd())
|
||||||
|
{
|
||||||
|
UTF8Char c = *it;
|
||||||
|
if (c == U'\n')
|
||||||
|
{
|
||||||
|
lines.push_back(currentLine);
|
||||||
|
currentLine = FString(u8"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentLine += c.getString();
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
if (!currentLine.empty())
|
||||||
|
{
|
||||||
|
lines.push_back(currentLine);
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
inline std::u32string utf8ToUtf32(const FString &s)
|
inline std::u32string utf8ToUtf32(const FString &s)
|
||||||
{
|
{
|
||||||
std::u32string result;
|
std::u32string result;
|
||||||
|
|||||||
@@ -12,12 +12,13 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
Variable,
|
Variable,
|
||||||
ListElement,
|
ListElement,
|
||||||
MapElement
|
MapElement,
|
||||||
|
StringElement,
|
||||||
} kind;
|
} kind;
|
||||||
std::shared_ptr<VariableSlot> slot;
|
std::shared_ptr<VariableSlot> slot;
|
||||||
|
|
||||||
ObjectPtr listOrMap = nullptr;
|
ObjectPtr value = nullptr;
|
||||||
size_t listIndex;
|
size_t numIndex;
|
||||||
|
|
||||||
ObjectPtr mapIndex;
|
ObjectPtr mapIndex;
|
||||||
|
|
||||||
@@ -26,20 +27,18 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
kind = Kind::Variable;
|
kind = Kind::Variable;
|
||||||
}
|
}
|
||||||
LvObject(ObjectPtr _v, size_t _index) :
|
LvObject(ObjectPtr _v, size_t _index, Kind _kind) :
|
||||||
listOrMap(_v), listIndex(_index)
|
value(_v), numIndex(_index)
|
||||||
{
|
{
|
||||||
assert(_v->getTypeInfo() == ValueType::List);
|
kind = _kind;
|
||||||
kind = Kind::ListElement;
|
|
||||||
}
|
}
|
||||||
LvObject(ObjectPtr _v, ObjectPtr _index) :
|
LvObject(ObjectPtr _v, ObjectPtr _index, Kind _kind) :
|
||||||
listOrMap(_v), mapIndex(_index)
|
value(_v), mapIndex(_index)
|
||||||
{
|
{
|
||||||
assert(_v->getTypeInfo() == ValueType::Map);
|
kind = _kind;
|
||||||
kind = Kind::MapElement;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ObjectPtr &get() const
|
ObjectPtr get() const
|
||||||
{
|
{
|
||||||
if (kind == Kind::Variable)
|
if (kind == Kind::Variable)
|
||||||
{
|
{
|
||||||
@@ -48,20 +47,30 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else if (kind == Kind::ListElement)
|
else if (kind == Kind::ListElement)
|
||||||
{
|
{
|
||||||
List &list = listOrMap->as<List>();
|
List &list = value->as<List>();
|
||||||
if (listIndex >= list.size())
|
if (numIndex >= list.size())
|
||||||
throw RuntimeError(FString(
|
throw RuntimeError(FString(
|
||||||
std::format("Index {} out of range", listIndex)));
|
std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
||||||
return list.at(listIndex);
|
return list.at(numIndex);
|
||||||
}
|
}
|
||||||
else // map
|
else if (kind == Kind::MapElement) // map
|
||||||
{
|
{
|
||||||
Map &map = listOrMap->as<Map>();
|
Map &map = value->as<Map>();
|
||||||
if (!map.contains(mapIndex))
|
if (!map.contains(mapIndex))
|
||||||
throw RuntimeError(FString(
|
throw RuntimeError(FString(
|
||||||
std::format("Key {} not found", mapIndex->toString().toBasicString())));
|
std::format("Key {} not found", mapIndex->toString().toBasicString())));
|
||||||
return map.at(mapIndex);
|
return map.at(mapIndex);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// string
|
||||||
|
FString &string = value->as<ValueType::StringClass>();
|
||||||
|
if (numIndex >= string.length())
|
||||||
|
throw RuntimeError(FString(
|
||||||
|
std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
||||||
|
|
||||||
|
return std::make_shared<Object>(string.getRealChar(numIndex));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(const ObjectPtr &v)
|
void set(const ObjectPtr &v)
|
||||||
@@ -87,17 +96,35 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else if (kind == Kind::ListElement)
|
else if (kind == Kind::ListElement)
|
||||||
{
|
{
|
||||||
List &list = listOrMap->as<List>();
|
List &list = value->as<List>();
|
||||||
if (listIndex >= list.size())
|
if (numIndex >= list.size())
|
||||||
throw RuntimeError(FString(
|
throw RuntimeError(FString(
|
||||||
std::format("Index {} out of range", listIndex)));
|
std::format("Index {} out of range", numIndex)));
|
||||||
list[listIndex] = v;
|
list[numIndex] = v;
|
||||||
}
|
}
|
||||||
else // map
|
else if (kind == Kind::MapElement) // map
|
||||||
{
|
{
|
||||||
Map &map = listOrMap->as<Map>();
|
Map &map = value->as<Map>();
|
||||||
map[mapIndex] = v;
|
map[mapIndex] = v;
|
||||||
}
|
}
|
||||||
|
else if (kind == Kind::StringElement)
|
||||||
|
{
|
||||||
|
FString &string = value->as<ValueType::StringClass>();
|
||||||
|
if (numIndex >= string.length())
|
||||||
|
throw RuntimeError(FString(
|
||||||
|
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>();
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FString name() const { return resolve(slot)->name; }
|
FString name() const { return resolve(slot)->name; }
|
||||||
@@ -111,4 +138,4 @@ namespace Fig
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace Fig
|
||||||
@@ -67,6 +67,7 @@ namespace Fig
|
|||||||
extern const TypeInfo StructInstance;
|
extern const TypeInfo StructInstance;
|
||||||
extern const TypeInfo List;
|
extern const TypeInfo List;
|
||||||
extern const TypeInfo Map;
|
extern const TypeInfo Map;
|
||||||
|
extern const TypeInfo Module;
|
||||||
// extern const TypeInfo Tuple;
|
// extern const TypeInfo Tuple;
|
||||||
|
|
||||||
using IntClass = int64_t;
|
using IntClass = int64_t;
|
||||||
|
|||||||
27
src/Value/module.hpp
Normal file
27
src/Value/module.hpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Core/fig_string.hpp>
|
||||||
|
|
||||||
|
#include <Context/context_forward.hpp>
|
||||||
|
|
||||||
|
namespace Fig
|
||||||
|
{
|
||||||
|
struct Module
|
||||||
|
{
|
||||||
|
FString name;
|
||||||
|
ContextPtr ctx;
|
||||||
|
|
||||||
|
Module() = default;
|
||||||
|
|
||||||
|
Module(FString n, ContextPtr c) :
|
||||||
|
name(std::move(n)),
|
||||||
|
ctx(std::move(c))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Module &o) const noexcept
|
||||||
|
{
|
||||||
|
return name == o.name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -80,5 +80,5 @@ namespace Fig
|
|||||||
const TypeInfo ValueType::StructInstance(FString(u8"StructInstance"), true); // id: 9
|
const TypeInfo ValueType::StructInstance(FString(u8"StructInstance"), true); // id: 9
|
||||||
const TypeInfo ValueType::List(FString(u8"List"), true); // id: 10
|
const TypeInfo ValueType::List(FString(u8"List"), true); // id: 10
|
||||||
const TypeInfo ValueType::Map(FString(u8"Map"), true); // id: 11
|
const TypeInfo ValueType::Map(FString(u8"Map"), true); // id: 11
|
||||||
// const TypeInfo ValueType::Tuple(FString(u8"Tuple"), true); // id: 12
|
const TypeInfo ValueType::Module(FString(u8"Module"), true); // id: 12
|
||||||
} // namespace Fig
|
} // namespace Fig
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <Value/structInstance.hpp>
|
#include <Value/structInstance.hpp>
|
||||||
#include <Value/Type.hpp>
|
#include <Value/Type.hpp>
|
||||||
#include <Value/valueError.hpp>
|
#include <Value/valueError.hpp>
|
||||||
|
#include <Value/module.hpp>
|
||||||
|
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -58,7 +59,8 @@ namespace Fig
|
|||||||
StructType,
|
StructType,
|
||||||
StructInstance,
|
StructInstance,
|
||||||
List,
|
List,
|
||||||
Map>;
|
Map,
|
||||||
|
Module>;
|
||||||
|
|
||||||
std::unordered_map<TypeInfo,
|
std::unordered_map<TypeInfo,
|
||||||
std::unordered_map<FString,
|
std::unordered_map<FString,
|
||||||
@@ -134,6 +136,7 @@ namespace Fig
|
|||||||
map.contains(index));
|
map.contains(index));
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
|
{ValueType::Module, {}}
|
||||||
};
|
};
|
||||||
std::unordered_map<TypeInfo, std::unordered_map<FString, int>, TypeInfoHash> memberTypeFunctionsParas{
|
std::unordered_map<TypeInfo, std::unordered_map<FString, int>, TypeInfoHash> memberTypeFunctionsParas{
|
||||||
{ValueType::Null, {}},
|
{ValueType::Null, {}},
|
||||||
@@ -151,6 +154,7 @@ namespace Fig
|
|||||||
{u8"get", 1},
|
{u8"get", 1},
|
||||||
{u8"contains", 1},
|
{u8"contains", 1},
|
||||||
}},
|
}},
|
||||||
|
{ValueType::Module, {}}
|
||||||
|
|
||||||
};
|
};
|
||||||
bool hasMemberFunction(const FString &name) const
|
bool hasMemberFunction(const FString &name) const
|
||||||
@@ -190,6 +194,8 @@ namespace Fig
|
|||||||
data(l) {}
|
data(l) {}
|
||||||
Object(const Map &m) :
|
Object(const Map &m) :
|
||||||
data(m) {}
|
data(m) {}
|
||||||
|
Object(const Module &m) :
|
||||||
|
data(m) {}
|
||||||
|
|
||||||
Object(const Object &) = default;
|
Object(const Object &) = default;
|
||||||
Object(Object &&) noexcept = default;
|
Object(Object &&) noexcept = default;
|
||||||
@@ -283,6 +289,9 @@ namespace Fig
|
|||||||
else if constexpr (std::is_same_v<T, Map>)
|
else if constexpr (std::is_same_v<T, Map>)
|
||||||
return ValueType::Map;
|
return ValueType::Map;
|
||||||
|
|
||||||
|
else if constexpr (std::is_same_v<T, Module>)
|
||||||
|
return ValueType::Module;
|
||||||
|
|
||||||
else
|
else
|
||||||
return ValueType::Any;
|
return ValueType::Any;
|
||||||
},
|
},
|
||||||
@@ -357,6 +366,12 @@ namespace Fig
|
|||||||
output += u8"}";
|
output += u8"}";
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
if (is<Module>())
|
||||||
|
{
|
||||||
|
return FString(std::format(
|
||||||
|
"<Module at {:p}>",
|
||||||
|
static_cast<const void *>(&as<Module>())));
|
||||||
|
}
|
||||||
return FString(u8"<error>");
|
return FString(u8"<error>");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,7 +591,6 @@ namespace Fig
|
|||||||
using ObjectPtr = std::shared_ptr<Object>;
|
using ObjectPtr = std::shared_ptr<Object>;
|
||||||
using RvObject = ObjectPtr;
|
using RvObject = ObjectPtr;
|
||||||
|
|
||||||
|
|
||||||
inline bool operator==(const ValueKey &l, const ValueKey &r)
|
inline bool operator==(const ValueKey &l, const ValueKey &r)
|
||||||
{
|
{
|
||||||
return *l.value == *r.value;
|
return *l.value == *r.value;
|
||||||
|
|||||||
31
src/main.cpp
31
src/main.cpp
@@ -36,36 +36,12 @@ This software is licensed under the MIT License. See LICENSE.txt for details.
|
|||||||
#include <Parser/parser.hpp>
|
#include <Parser/parser.hpp>
|
||||||
#include <Evaluator/evaluator.hpp>
|
#include <Evaluator/evaluator.hpp>
|
||||||
#include <Utils/AstPrinter.hpp>
|
#include <Utils/AstPrinter.hpp>
|
||||||
|
#include <Utils/utils.hpp>
|
||||||
#include <Error/errorLog.hpp>
|
#include <Error/errorLog.hpp>
|
||||||
|
|
||||||
static size_t addressableErrorCount = 0;
|
static size_t addressableErrorCount = 0;
|
||||||
static size_t unaddressableErrorCount = 0;
|
static size_t unaddressableErrorCount = 0;
|
||||||
|
|
||||||
std::vector<FString> splitSource(FString source)
|
|
||||||
{
|
|
||||||
UTF8Iterator it(source);
|
|
||||||
std::vector<FString> lines;
|
|
||||||
FString currentLine;
|
|
||||||
while (!it.isEnd())
|
|
||||||
{
|
|
||||||
UTF8Char c = *it;
|
|
||||||
if (c == U'\n')
|
|
||||||
{
|
|
||||||
lines.push_back(currentLine);
|
|
||||||
currentLine = FString(u8"");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
currentLine += c.getString();
|
|
||||||
}
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
if (!currentLine.empty())
|
|
||||||
{
|
|
||||||
lines.push_back(currentLine);
|
|
||||||
}
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -119,7 +95,7 @@ int main(int argc, char **argv)
|
|||||||
Fig::Parser parser(lexer);
|
Fig::Parser parser(lexer);
|
||||||
std::vector<Fig::Ast::AstBase> asts;
|
std::vector<Fig::Ast::AstBase> asts;
|
||||||
|
|
||||||
std::vector<FString> sourceLines = splitSource(Fig::FString(source));
|
std::vector<FString> sourceLines = Fig::Utils::splitSource(Fig::FString(source));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -151,8 +127,11 @@ int main(int argc, char **argv)
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
Fig::Evaluator evaluator;
|
Fig::Evaluator evaluator;
|
||||||
|
|
||||||
|
evaluator.SetSourcePath(sourcePath);
|
||||||
evaluator.CreateGlobalContext();
|
evaluator.CreateGlobalContext();
|
||||||
evaluator.RegisterBuiltins();
|
evaluator.RegisterBuiltins();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
evaluator.Run(asts);
|
evaluator.Run(asts);
|
||||||
|
|||||||
Reference in New Issue
Block a user