#include "Ast/Statements/ImplementSt.hpp" #include "Ast/Statements/InterfaceDefSt.hpp" #include "Value/Type.hpp" #include #include #include #include #include #include namespace Fig { struct StatementResult { ObjectPtr result; enum class Flow { Normal, Return, Break, Continue, Error } flow; StatementResult(ObjectPtr val, Flow f = Flow::Normal) : result(val), flow(f) { } static StatementResult normal(ObjectPtr val = Object::getNullInstance()) { return StatementResult(val, Flow::Normal); } static StatementResult returnFlow(ObjectPtr val) { return StatementResult(val, Flow::Return); } static StatementResult breakFlow() { return StatementResult(Object::getNullInstance(), Flow::Break); } static StatementResult continueFlow() { return StatementResult(Object::getNullInstance(), Flow::Continue); } static StatementResult errorFlow(ObjectPtr val) { return StatementResult(val, Flow::Error); } bool isNormal() const { return flow == Flow::Normal; } bool shouldReturn() const { return flow == Flow::Return; } bool shouldBreak() const { return flow == Flow::Break; } bool shouldContinue() const { return flow == Flow::Continue; } bool isError() const { return flow == Flow::Error; } }; class Evaluator { private: ContextPtr global; public: FString sourcePath; void SetSourcePath(const FString &sp) { sourcePath = sp; } void SetGlobalContext(ContextPtr ctx) { assert(ctx != nullptr); global = ctx; } void CreateGlobalContext() { global = std::make_shared( FString(u8"")); } void RegisterBuiltins() // only function { assert(global != nullptr); for (auto &[name, fn] : Builtins::builtinFunctions) { int argc = Builtins::getBuiltinFunctionParamCount(name); Function f(fn, argc); global->def( name, ValueType::Function, AccessModifier::Const, std::make_shared(f)); } } void RegisterBuiltinsValue() { assert(global != nullptr); for (auto &[name, val] : Builtins::builtinValues) { global->def( name, val->getTypeInfo(), AccessModifier::Const, val); } } bool isInterfaceSignatureMatch(const Ast::ImplementMethod &, const Ast::InterfaceMethod &); /* Left-value eval*/ LvObject evalVarExpr(Ast::VarExpr, ContextPtr); LvObject evalMemberExpr(Ast::MemberExpr, ContextPtr); // a.b LvObject evalIndexExpr(Ast::IndexExpr, ContextPtr); // a[b] LvObject evalLv(Ast::Expression, ContextPtr); // for access: a.b / index a[b] /* Right-value eval*/ RvObject evalBinary(Ast::BinaryExpr, ContextPtr); // normal binary expr: +, -, *.... RvObject evalUnary(Ast::UnaryExpr, ContextPtr); // unary expr RvObject evalTernary(Ast::TernaryExpr, ContextPtr); // ternary expr RvObject evalFunctionCall(const Function &, const Ast::FunctionArguments &, const FString &, ContextPtr); // function call RvObject eval(Ast::Expression, ContextPtr); StatementResult evalBlockStatement(Ast::BlockStatement, ContextPtr); // block StatementResult evalStatement(Ast::Statement, ContextPtr); // statement std::filesystem::path resolveModulePath(const std::vector &); ContextPtr loadModule(const std::filesystem::path &); StatementResult evalImportSt(Ast::Import, ContextPtr); StatementResult Run(std::vector); // Entry void printStackTrace(); }; }; // namespace Fig