Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9c68b2e77d |
@@ -12,7 +12,7 @@ namespace Fig::Ast
|
|||||||
size_t getLength() const { return argv.size(); }
|
size_t getLength() const { return argv.size(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FunctionCallArgs final
|
struct FunctionCallArgs final
|
||||||
{
|
{
|
||||||
std::vector<ObjectPtr> argv;
|
std::vector<ObjectPtr> argv;
|
||||||
size_t getLength() const { return argv.size(); }
|
size_t getLength() const { return argv.size(); }
|
||||||
@@ -24,31 +24,26 @@ namespace Fig::Ast
|
|||||||
Expression callee;
|
Expression callee;
|
||||||
FunctionArguments arg;
|
FunctionArguments arg;
|
||||||
|
|
||||||
FunctionCallExpr()
|
FunctionCallExpr() { type = AstType::FunctionCall; }
|
||||||
|
|
||||||
|
FunctionCallExpr(Expression _callee, FunctionArguments _arg) : callee(std::move(_callee)), arg(std::move(_arg))
|
||||||
{
|
{
|
||||||
type = AstType::FunctionCall;
|
type = AstType::FunctionCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionCallExpr(Expression _callee, FunctionArguments _arg) :
|
virtual String toString() override
|
||||||
callee(std::move(_callee)), arg(std::move(_arg))
|
|
||||||
{
|
{
|
||||||
type = AstType::FunctionCall;
|
String s = callee->toString();
|
||||||
}
|
s += U"(";
|
||||||
|
|
||||||
virtual FString toString() override
|
|
||||||
{
|
|
||||||
FString s = callee->toString();
|
|
||||||
s += u8"(";
|
|
||||||
for (size_t i = 0; i < arg.argv.size(); ++i)
|
for (size_t i = 0; i < arg.argv.size(); ++i)
|
||||||
{
|
{
|
||||||
s += arg.argv[i]->toString();
|
s += arg.argv[i]->toString();
|
||||||
if (i + 1 < arg.argv.size())
|
if (i + 1 < arg.argv.size()) s += U",";
|
||||||
s += u8", ";
|
|
||||||
}
|
}
|
||||||
s += u8")";
|
s += U")";
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using FunctionCall = std::shared_ptr<FunctionCallExpr>;
|
using FunctionCall = std::shared_ptr<FunctionCallExpr>;
|
||||||
}; // namespace Fig
|
}; // namespace Fig::Ast
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <Ast/astBase.hpp>
|
#include <Ast/astBase.hpp>
|
||||||
#include <Ast/functionParameters.hpp>
|
#include <Ast/functionParameters.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
namespace Fig::Ast
|
namespace Fig::Ast
|
||||||
@@ -25,20 +25,11 @@ namespace Fig::Ast
|
|||||||
type = AstType::FunctionLiteralExpr;
|
type = AstType::FunctionLiteralExpr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isExprMode() const
|
bool isExprMode() const { return std::holds_alternative<Expression>(body); }
|
||||||
{
|
|
||||||
return std::holds_alternative<Expression>(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockStatement &getBlockBody()
|
BlockStatement &getBlockBody() { return std::get<BlockStatement>(body); }
|
||||||
{
|
|
||||||
return std::get<BlockStatement>(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
Expression &getExprBody()
|
Expression &getExprBody() { return std::get<Expression>(body); }
|
||||||
{
|
|
||||||
return std::get<Expression>(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
~FunctionLiteralExprAst() = default;
|
~FunctionLiteralExprAst() = default;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Fig::Ast
|
|||||||
public:
|
public:
|
||||||
Expression structe;
|
Expression structe;
|
||||||
|
|
||||||
std::vector<std::pair<FString, Expression>> args;
|
std::vector<std::pair<String, Expression>> args;
|
||||||
|
|
||||||
enum class InitMode
|
enum class InitMode
|
||||||
{
|
{
|
||||||
@@ -25,12 +25,9 @@ namespace Fig::Ast
|
|||||||
.3 Person {name, age, sex};
|
.3 Person {name, age, sex};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
InitExprAst()
|
InitExprAst() { type = AstType::InitExpr; }
|
||||||
{
|
|
||||||
type = AstType::InitExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
InitExprAst(Expression _structe, std::vector<std::pair<FString, Expression>> _args, InitMode _initMode) :
|
InitExprAst(Expression _structe, std::vector<std::pair<String, Expression>> _args, InitMode _initMode) :
|
||||||
structe(std::move(_structe)), args(std::move(_args)), initMode(_initMode)
|
structe(std::move(_structe)), args(std::move(_args)), initMode(_initMode)
|
||||||
{
|
{
|
||||||
type = AstType::InitExpr;
|
type = AstType::InitExpr;
|
||||||
|
|||||||
@@ -11,15 +11,11 @@ namespace Fig::Ast
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Expression base;
|
Expression base;
|
||||||
FString member;
|
String member;
|
||||||
|
|
||||||
MemberExprAst()
|
MemberExprAst() { type = AstType::MemberExpr; }
|
||||||
{
|
|
||||||
type = AstType::MemberExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemberExprAst(Expression _base, FString _member) :
|
MemberExprAst(Expression _base, String _member) : base(std::move(_base)), member(std::move(_member))
|
||||||
base(std::move(_base)), member(std::move(_member))
|
|
||||||
{
|
{
|
||||||
type = AstType::MemberExpr;
|
type = AstType::MemberExpr;
|
||||||
}
|
}
|
||||||
@@ -33,13 +29,9 @@ namespace Fig::Ast
|
|||||||
Expression base;
|
Expression base;
|
||||||
Expression index;
|
Expression index;
|
||||||
|
|
||||||
IndexExprAst()
|
IndexExprAst() { type = AstType::IndexExpr; }
|
||||||
{
|
|
||||||
type = AstType::IndexExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
IndexExprAst(Expression _base, Expression _index) :
|
IndexExprAst(Expression _base, Expression _index) : base(std::move(_base)), index(std::move(_index))
|
||||||
base(std::move(_base)), index(std::move(_index))
|
|
||||||
{
|
{
|
||||||
type = AstType::IndexExpr;
|
type = AstType::IndexExpr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,18 +7,10 @@ namespace Fig::Ast
|
|||||||
class VarExprAst final : public ExpressionAst
|
class VarExprAst final : public ExpressionAst
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const FString name;
|
const String name;
|
||||||
VarExprAst() :
|
VarExprAst() : name(U"") { type = AstType::VarExpr; }
|
||||||
name(u8"")
|
VarExprAst(String _name) : name(std::move(_name)) { type = AstType::VarExpr; }
|
||||||
{
|
|
||||||
type = AstType::VarExpr;
|
|
||||||
}
|
|
||||||
VarExprAst(FString _name) :
|
|
||||||
name(std::move(_name))
|
|
||||||
{
|
|
||||||
type = AstType::VarExpr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using VarExpr = std::shared_ptr<VarExprAst>;
|
using VarExpr = std::shared_ptr<VarExprAst>;
|
||||||
}; // namespace Fig
|
}; // namespace Fig::Ast
|
||||||
@@ -9,34 +9,26 @@ namespace Fig::Ast
|
|||||||
public:
|
public:
|
||||||
Expression value;
|
Expression value;
|
||||||
|
|
||||||
ThrowSt()
|
ThrowSt() { type = AstType::ThrowSt; }
|
||||||
{
|
|
||||||
type = AstType::ThrowSt;
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowSt(Expression _value) :
|
ThrowSt(Expression _value) : value(std::move(_value)) { type = AstType::ThrowSt; }
|
||||||
value(std::move(_value))
|
|
||||||
{
|
|
||||||
type = AstType::ThrowSt;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
using Throw = std::shared_ptr<ThrowSt>;
|
using Throw = std::shared_ptr<ThrowSt>;
|
||||||
|
|
||||||
struct Catch
|
struct Catch
|
||||||
{
|
{
|
||||||
FString errVarName;
|
String errVarName;
|
||||||
bool hasType = false;
|
bool hasType = false;
|
||||||
FString errVarType;
|
String errVarType;
|
||||||
BlockStatement body;
|
BlockStatement body;
|
||||||
|
|
||||||
Catch() {}
|
Catch() {}
|
||||||
Catch(FString _errVarName, FString _errVarType, BlockStatement _body) :
|
Catch(String _errVarName, String _errVarType, BlockStatement _body) :
|
||||||
errVarName(std::move(_errVarName)), errVarType(std::move(_errVarType)), body(std::move(_body))
|
errVarName(std::move(_errVarName)), errVarType(std::move(_errVarType)), body(std::move(_body))
|
||||||
{
|
{
|
||||||
hasType = true;
|
hasType = true;
|
||||||
}
|
}
|
||||||
Catch(FString _errVarName, BlockStatement _body) :
|
Catch(String _errVarName, BlockStatement _body) : errVarName(std::move(_errVarName)), body(std::move(_body))
|
||||||
errVarName(std::move(_errVarName)), body(std::move(_body))
|
|
||||||
{
|
{
|
||||||
hasType = false;
|
hasType = false;
|
||||||
}
|
}
|
||||||
@@ -49,10 +41,7 @@ namespace Fig::Ast
|
|||||||
std::vector<Catch> catches;
|
std::vector<Catch> catches;
|
||||||
BlockStatement finallyBlock = nullptr;
|
BlockStatement finallyBlock = nullptr;
|
||||||
|
|
||||||
TrySt()
|
TrySt() { type = AstType::TrySt; }
|
||||||
{
|
|
||||||
type = AstType::TrySt;
|
|
||||||
}
|
|
||||||
TrySt(BlockStatement _body, std::vector<Catch> _catches, BlockStatement _finallyBlock) :
|
TrySt(BlockStatement _body, std::vector<Catch> _catches, BlockStatement _finallyBlock) :
|
||||||
body(std::move(_body)), catches(std::move(_catches)), finallyBlock(std::move(_finallyBlock))
|
body(std::move(_body)), catches(std::move(_catches)), finallyBlock(std::move(_finallyBlock))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,17 +20,15 @@ namespace Fig::Ast
|
|||||||
class FunctionDefSt final : public StatementAst // for definition
|
class FunctionDefSt final : public StatementAst // for definition
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FString name;
|
String name;
|
||||||
FunctionParameters paras;
|
FunctionParameters paras;
|
||||||
bool isPublic;
|
bool isPublic;
|
||||||
Expression retType;
|
Expression retType;
|
||||||
BlockStatement body;
|
BlockStatement body;
|
||||||
|
|
||||||
FunctionDefSt()
|
FunctionDefSt() { type = AstType::FunctionDefSt; }
|
||||||
{
|
FunctionDefSt(
|
||||||
type = AstType::FunctionDefSt;
|
String _name, FunctionParameters _paras, bool _isPublic, Expression _retType, BlockStatement _body)
|
||||||
}
|
|
||||||
FunctionDefSt(FString _name, FunctionParameters _paras, bool _isPublic, Expression _retType, BlockStatement _body)
|
|
||||||
{
|
{
|
||||||
type = AstType::FunctionDefSt;
|
type = AstType::FunctionDefSt;
|
||||||
|
|
||||||
@@ -42,4 +40,4 @@ namespace Fig::Ast
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
using FunctionDef = std::shared_ptr<FunctionDefSt>;
|
using FunctionDef = std::shared_ptr<FunctionDefSt>;
|
||||||
}; // namespace Fig
|
}; // namespace Fig::Ast
|
||||||
@@ -8,19 +8,9 @@ namespace Fig::Ast
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BlockStatement body;
|
BlockStatement body;
|
||||||
ElseSt()
|
ElseSt() { type = AstType::ElseSt; }
|
||||||
{
|
ElseSt(BlockStatement _body) : body(_body) { type = AstType::ElseSt; }
|
||||||
type = AstType::ElseSt;
|
virtual String toString() override { return String(std::format("<Else Ast at {}:{}>", aai.line, aai.column)); }
|
||||||
}
|
|
||||||
ElseSt(BlockStatement _body) :
|
|
||||||
body(_body)
|
|
||||||
{
|
|
||||||
type = AstType::ElseSt;
|
|
||||||
}
|
|
||||||
virtual FString toString() override
|
|
||||||
{
|
|
||||||
return FString(std::format("<Else Ast at {}:{}>", aai.line, aai.column));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
using Else = std::shared_ptr<ElseSt>;
|
using Else = std::shared_ptr<ElseSt>;
|
||||||
class ElseIfSt final : public StatementAst
|
class ElseIfSt final : public StatementAst
|
||||||
@@ -28,19 +18,14 @@ namespace Fig::Ast
|
|||||||
public:
|
public:
|
||||||
Expression condition;
|
Expression condition;
|
||||||
BlockStatement body;
|
BlockStatement body;
|
||||||
ElseIfSt()
|
ElseIfSt() { type = AstType::ElseIfSt; }
|
||||||
|
ElseIfSt(Expression _condition, BlockStatement _body) : condition(_condition), body(_body)
|
||||||
{
|
{
|
||||||
type = AstType::ElseIfSt;
|
type = AstType::ElseIfSt;
|
||||||
}
|
}
|
||||||
ElseIfSt(Expression _condition,
|
virtual String toString() override
|
||||||
BlockStatement _body) :
|
|
||||||
condition(_condition), body(_body)
|
|
||||||
{
|
{
|
||||||
type = AstType::ElseIfSt;
|
return String(std::format("<ElseIf Ast at {}:{}>", aai.line, aai.column));
|
||||||
}
|
|
||||||
virtual FString toString() override
|
|
||||||
{
|
|
||||||
return FString(std::format("<ElseIf Ast at {}:{}>", aai.line, aai.column));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
using ElseIf = std::shared_ptr<ElseIfSt>;
|
using ElseIf = std::shared_ptr<ElseIfSt>;
|
||||||
@@ -51,18 +36,12 @@ namespace Fig::Ast
|
|||||||
BlockStatement body;
|
BlockStatement body;
|
||||||
std::vector<ElseIf> elifs;
|
std::vector<ElseIf> elifs;
|
||||||
Else els;
|
Else els;
|
||||||
IfSt()
|
IfSt() { type = AstType::IfSt; }
|
||||||
{
|
IfSt(Expression _condition, BlockStatement _body, std::vector<ElseIf> _elifs, Else _els) :
|
||||||
type = AstType::IfSt;
|
|
||||||
}
|
|
||||||
IfSt(Expression _condition,
|
|
||||||
BlockStatement _body,
|
|
||||||
std::vector<ElseIf> _elifs,
|
|
||||||
Else _els) :
|
|
||||||
condition(_condition), body(_body), elifs(_elifs), els(_els)
|
condition(_condition), body(_body), elifs(_elifs), els(_els)
|
||||||
{
|
{
|
||||||
type = AstType::IfSt;
|
type = AstType::IfSt;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
using If = std::shared_ptr<IfSt>;
|
using If = std::shared_ptr<IfSt>;
|
||||||
}; // namespace Fig
|
}; // namespace Fig::Ast
|
||||||
@@ -6,18 +6,18 @@
|
|||||||
namespace Fig::Ast
|
namespace Fig::Ast
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
||||||
impl Readable for File
|
impl Readable for File
|
||||||
{
|
{
|
||||||
read() -> String
|
read() -> String
|
||||||
{
|
{
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
struct ImplementMethod
|
struct ImplementMethod
|
||||||
{
|
{
|
||||||
FString name;
|
String name;
|
||||||
FunctionParameters paras;
|
FunctionParameters paras;
|
||||||
BlockStatement body;
|
BlockStatement body;
|
||||||
};
|
};
|
||||||
@@ -25,17 +25,14 @@ namespace Fig::Ast
|
|||||||
class ImplementAst final : public StatementAst
|
class ImplementAst final : public StatementAst
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FString interfaceName;
|
String interfaceName;
|
||||||
FString structName;
|
String structName;
|
||||||
|
|
||||||
std::vector<ImplementMethod> methods;
|
std::vector<ImplementMethod> methods;
|
||||||
|
|
||||||
ImplementAst()
|
ImplementAst() { type = AstType::ImplementSt; }
|
||||||
{
|
|
||||||
type = AstType::ImplementSt;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImplementAst(FString _interfaceName, FString _structName, std::vector<ImplementMethod> _methods) :
|
ImplementAst(String _interfaceName, String _structName, std::vector<ImplementMethod> _methods) :
|
||||||
interfaceName(std::move(_interfaceName)), structName(std::move(_structName)), methods(std::move(_methods))
|
interfaceName(std::move(_interfaceName)), structName(std::move(_structName)), methods(std::move(_methods))
|
||||||
{
|
{
|
||||||
type = AstType::ImplementSt;
|
type = AstType::ImplementSt;
|
||||||
@@ -43,4 +40,4 @@ namespace Fig::Ast
|
|||||||
};
|
};
|
||||||
|
|
||||||
using Implement = std::shared_ptr<ImplementAst>;
|
using Implement = std::shared_ptr<ImplementAst>;
|
||||||
};
|
}; // namespace Fig::Ast
|
||||||
@@ -14,17 +14,14 @@ namespace Fig::Ast
|
|||||||
class ImportSt final : public StatementAst
|
class ImportSt final : public StatementAst
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::vector<FString> path;
|
std::vector<String> path;
|
||||||
std::vector<FString> names;
|
std::vector<String> names;
|
||||||
|
|
||||||
FString rename;
|
String rename;
|
||||||
|
|
||||||
ImportSt()
|
|
||||||
{
|
|
||||||
type = AstType::ImportSt;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImportSt(std::vector<FString> _path, std::vector<FString> _names, const FString &_rename) :
|
ImportSt() { type = AstType::ImportSt; }
|
||||||
|
|
||||||
|
ImportSt(std::vector<String> _path, std::vector<String> _names, const String &_rename) :
|
||||||
path(std::move(_path)), names(std::move(_names)), rename(_rename)
|
path(std::move(_path)), names(std::move(_names)), rename(_rename)
|
||||||
{
|
{
|
||||||
type = AstType::ImportSt;
|
type = AstType::ImportSt;
|
||||||
@@ -32,4 +29,4 @@ namespace Fig::Ast
|
|||||||
};
|
};
|
||||||
|
|
||||||
using Import = std::shared_ptr<ImportSt>;
|
using Import = std::shared_ptr<ImportSt>;
|
||||||
};
|
}; // namespace Fig::Ast
|
||||||
@@ -3,52 +3,44 @@
|
|||||||
#include <Ast/functionParameters.hpp>
|
#include <Ast/functionParameters.hpp>
|
||||||
#include <Ast/astBase.hpp>
|
#include <Ast/astBase.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace Fig::Ast
|
namespace Fig::Ast
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
||||||
interface Readable
|
interface Readable
|
||||||
{
|
{
|
||||||
read() -> String
|
read() -> String
|
||||||
{
|
{
|
||||||
// default
|
// default
|
||||||
}
|
}
|
||||||
|
|
||||||
flush() -> Null; // non-default
|
flush() -> Null; // non-default
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
struct InterfaceMethod
|
struct InterfaceMethod
|
||||||
{
|
{
|
||||||
FString name;
|
String name;
|
||||||
FunctionParameters paras;
|
FunctionParameters paras;
|
||||||
Expression returnType;
|
Expression returnType;
|
||||||
|
|
||||||
BlockStatement defaultBody = nullptr; // nullptr is non-default func
|
BlockStatement defaultBody = nullptr; // nullptr is non-default func
|
||||||
|
|
||||||
bool hasDefaultBody() const
|
bool hasDefaultBody() const { return defaultBody != nullptr; }
|
||||||
{
|
|
||||||
return defaultBody != nullptr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class InterfaceDefAst final : public StatementAst
|
class InterfaceDefAst final : public StatementAst
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FString name;
|
String name;
|
||||||
std::vector<InterfaceMethod> methods;
|
std::vector<InterfaceMethod> methods;
|
||||||
std::vector<FString> parents; // Feature, NOT NOW
|
std::vector<String> parents; // Feature, NOT NOW
|
||||||
bool isPublic;
|
bool isPublic;
|
||||||
|
|
||||||
InterfaceDefAst()
|
InterfaceDefAst() { type = AstType::InterfaceDefSt; }
|
||||||
{
|
|
||||||
type = AstType::InterfaceDefSt;
|
|
||||||
}
|
|
||||||
|
|
||||||
InterfaceDefAst(FString _name, std::vector<InterfaceMethod> _methods, bool _isPublic) :
|
InterfaceDefAst(String _name, std::vector<InterfaceMethod> _methods, bool _isPublic) :
|
||||||
name(std::move(_name)), methods(std::move(_methods)), isPublic(_isPublic)
|
name(std::move(_name)), methods(std::move(_methods)), isPublic(_isPublic)
|
||||||
{
|
{
|
||||||
type = AstType::InterfaceDefSt;
|
type = AstType::InterfaceDefSt;
|
||||||
@@ -56,4 +48,4 @@ namespace Fig::Ast
|
|||||||
};
|
};
|
||||||
|
|
||||||
using InterfaceDef = std::shared_ptr<InterfaceDefAst>;
|
using InterfaceDef = std::shared_ptr<InterfaceDefAst>;
|
||||||
};
|
}; // namespace Fig::Ast
|
||||||
@@ -11,13 +11,16 @@ namespace Fig::Ast
|
|||||||
struct StructDefField
|
struct StructDefField
|
||||||
{
|
{
|
||||||
AccessModifier am;
|
AccessModifier am;
|
||||||
FString fieldName;
|
String fieldName;
|
||||||
Expression declaredType;
|
Expression declaredType;
|
||||||
Expression defaultValueExpr;
|
Expression defaultValueExpr;
|
||||||
|
|
||||||
StructDefField() {}
|
StructDefField() {}
|
||||||
StructDefField(AccessModifier _am, FString _fieldName, Expression _declaredType, Expression _defaultValueExpr) :
|
StructDefField(AccessModifier _am, String _fieldName, Expression _declaredType, Expression _defaultValueExpr) :
|
||||||
am(std::move(_am)), fieldName(std::move(_fieldName)), declaredType(std::move(_declaredType)), defaultValueExpr(std::move(_defaultValueExpr))
|
am(std::move(_am)),
|
||||||
|
fieldName(std::move(_fieldName)),
|
||||||
|
declaredType(std::move(_declaredType)),
|
||||||
|
defaultValueExpr(std::move(_defaultValueExpr))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -25,15 +28,12 @@ namespace Fig::Ast
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool isPublic;
|
bool isPublic;
|
||||||
const FString name;
|
const String name;
|
||||||
const std::vector<StructDefField> fields; // field name (:type name = default value expression)
|
const std::vector<StructDefField> fields; // field name (:type name = default value expression)
|
||||||
// name / name: String / name: String = "Fig"
|
// name / name: String / name: String = "Fig"
|
||||||
const BlockStatement body;
|
const BlockStatement body;
|
||||||
StructDefSt()
|
StructDefSt() { type = AstType::StructSt; }
|
||||||
{
|
StructDefSt(bool _isPublic, String _name, std::vector<StructDefField> _fields, BlockStatement _body) :
|
||||||
type = AstType::StructSt;
|
|
||||||
}
|
|
||||||
StructDefSt(bool _isPublic, FString _name, std::vector<StructDefField> _fields, BlockStatement _body) :
|
|
||||||
isPublic(std::move(_isPublic)), name(std::move(_name)), fields(std::move(_fields)), body(std::move(_body))
|
isPublic(std::move(_isPublic)), name(std::move(_name)), fields(std::move(_fields)), body(std::move(_body))
|
||||||
{
|
{
|
||||||
type = AstType::StructSt;
|
type = AstType::StructSt;
|
||||||
@@ -41,4 +41,4 @@ namespace Fig::Ast
|
|||||||
};
|
};
|
||||||
|
|
||||||
using StructDef = std::shared_ptr<StructDefSt>;
|
using StructDef = std::shared_ptr<StructDefSt>;
|
||||||
}; // namespace Fig
|
}; // namespace Fig::Ast
|
||||||
@@ -10,8 +10,8 @@ namespace Fig::Ast
|
|||||||
public:
|
public:
|
||||||
bool isPublic;
|
bool isPublic;
|
||||||
bool isConst;
|
bool isConst;
|
||||||
FString name;
|
String name;
|
||||||
// FString typeName;
|
// String typeName;
|
||||||
Expression declaredType;
|
Expression declaredType;
|
||||||
Expression expr;
|
Expression expr;
|
||||||
|
|
||||||
@@ -24,7 +24,8 @@ namespace Fig::Ast
|
|||||||
expr = nullptr;
|
expr = nullptr;
|
||||||
followupType = false;
|
followupType = false;
|
||||||
}
|
}
|
||||||
VarDefAst(bool _isPublic, bool _isConst, FString _name, Expression _declaredType, Expression _expr, bool _followupType)
|
VarDefAst(
|
||||||
|
bool _isPublic, bool _isConst, String _name, Expression _declaredType, Expression _expr, bool _followupType)
|
||||||
{
|
{
|
||||||
type = AstType::VarDefSt;
|
type = AstType::VarDefSt;
|
||||||
isPublic = _isPublic;
|
isPublic = _isPublic;
|
||||||
@@ -37,4 +38,4 @@ namespace Fig::Ast
|
|||||||
};
|
};
|
||||||
|
|
||||||
using VarDef = std::shared_ptr<VarDefAst>;
|
using VarDef = std::shared_ptr<VarDefAst>;
|
||||||
} // namespace Fig
|
} // namespace Fig::Ast
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Token/token.hpp>
|
#include <Token/token.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
|
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -66,43 +66,43 @@ namespace Fig::Ast
|
|||||||
ThrowSt,
|
ThrowSt,
|
||||||
};
|
};
|
||||||
|
|
||||||
// static const std::unordered_map<AstType, FString> astTypeToString{
|
// static const std::unordered_map<AstType, String> astTypeToString{
|
||||||
// /* Base Class */
|
// /* Base Class */
|
||||||
// {AstType::_AstBase, FString(u8"Ast")},
|
// {AstType::_AstBase, String(U"Ast")},
|
||||||
// {AstType::StatementBase, FString(u8"Statement")},
|
// {AstType::StatementBase, String(U"Statement")},
|
||||||
// {AstType::ExpressionBase, FString(u8"Expression")},
|
// {AstType::ExpressionBase, String(U"Expression")},
|
||||||
// /* Expression */
|
// /* Expression */
|
||||||
// {AstType::ValueExpr, FString(u8"ValueExpr")},
|
// {AstType::ValueExpr, String(U"ValueExpr")},
|
||||||
// {AstType::LambdaExpr, FString(u8"LambdaExpr")},
|
// {AstType::LambdaExpr, String(U"LambdaExpr")},
|
||||||
// {AstType::UnaryExpr, FString(u8"UnaryExpr")},
|
// {AstType::UnaryExpr, String(U"UnaryExpr")},
|
||||||
// {AstType::BinaryExpr, FString(u8"BinaryExpr")},
|
// {AstType::BinaryExpr, String(U"BinaryExpr")},
|
||||||
// {AstType::TernaryExpr, FString(u8"TernaryExpr")},
|
// {AstType::TernaryExpr, String(U"TernaryExpr")},
|
||||||
|
|
||||||
// {AstType::InitExpr, FString(u8"InitExpr")},
|
// {AstType::InitExpr, String(U"InitExpr")},
|
||||||
|
|
||||||
// /* Statement */
|
// /* Statement */
|
||||||
// {AstType::BlockStatement, FString(u8"BlockStatement")},
|
// {AstType::BlockStatement, String(U"BlockStatement")},
|
||||||
|
|
||||||
// {AstType::VarDefSt, FString(u8"VarSt")},
|
// {AstType::VarDefSt, String(U"VarSt")},
|
||||||
// {AstType::FunctionDefSt, FString(u8"FunctionDefSt")},
|
// {AstType::FunctionDefSt, String(U"FunctionDefSt")},
|
||||||
// {AstType::StructSt, FString(u8"StructSt")},
|
// {AstType::StructSt, String(U"StructSt")},
|
||||||
// {AstType::ImplementSt, FString(u8"ImplementSt")},
|
// {AstType::ImplementSt, String(U"ImplementSt")},
|
||||||
|
|
||||||
// {AstType::IfSt, FString(u8"IfSt")},
|
// {AstType::IfSt, String(U"IfSt")},
|
||||||
// {AstType::ElseSt, FString(u8"ElseSt")},
|
// {AstType::ElseSt, String(U"ElseSt")},
|
||||||
// {AstType::ElseIfSt, FString(u8"ElseIfSt")},
|
// {AstType::ElseIfSt, String(U"ElseIfSt")},
|
||||||
// {AstType::VarAssignSt, FString(u8"VarAssignSt")},
|
// {AstType::VarAssignSt, String(U"VarAssignSt")},
|
||||||
// {AstType::WhileSt, FString(u8"WhileSt")},
|
// {AstType::WhileSt, String(U"WhileSt")},
|
||||||
// {AstType::ReturnSt, FString(u8"ReturnSt")},
|
// {AstType::ReturnSt, String(U"ReturnSt")},
|
||||||
// {AstType::BreakSt, FString(u8"BreakSt")},
|
// {AstType::BreakSt, String(U"BreakSt")},
|
||||||
// {AstType::ContinueSt, FString(u8"ContinueSt")},
|
// {AstType::ContinueSt, String(U"ContinueSt")},
|
||||||
// };
|
// };
|
||||||
|
|
||||||
struct AstAddressInfo
|
struct AstAddressInfo
|
||||||
{
|
{
|
||||||
size_t line, column;
|
size_t line, column;
|
||||||
std::shared_ptr<FString> sourcePath;
|
std::shared_ptr<String> sourcePath;
|
||||||
std::shared_ptr<std::vector<FString>> sourceLines;
|
std::shared_ptr<std::vector<String>> sourceLines;
|
||||||
};
|
};
|
||||||
|
|
||||||
class _AstBase
|
class _AstBase
|
||||||
@@ -122,14 +122,14 @@ namespace Fig::Ast
|
|||||||
|
|
||||||
void setAAI(AstAddressInfo _aai) { aai = std::move(_aai); }
|
void setAAI(AstAddressInfo _aai) { aai = std::move(_aai); }
|
||||||
|
|
||||||
virtual FString typeName()
|
virtual String typeName()
|
||||||
{
|
{
|
||||||
const auto &name = magic_enum::enum_name(type);
|
const auto &name = magic_enum::enum_name(type);
|
||||||
return FString::fromBasicString(std::string(name.data(), name.length()));
|
return String(std::string(name.data(), name.length()));
|
||||||
}
|
}
|
||||||
virtual FString toString()
|
virtual String toString()
|
||||||
{
|
{
|
||||||
return FString(std::format("<Base Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
|
return String(std::format("<Base Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
|
||||||
}
|
}
|
||||||
|
|
||||||
AstAddressInfo getAAI() { return aai; }
|
AstAddressInfo getAAI() { return aai; }
|
||||||
@@ -144,9 +144,9 @@ namespace Fig::Ast
|
|||||||
using _AstBase::operator=;
|
using _AstBase::operator=;
|
||||||
StatementAst() { type = AstType::StatementBase; }
|
StatementAst() { type = AstType::StatementBase; }
|
||||||
|
|
||||||
virtual FString toString() override
|
virtual String toString() override
|
||||||
{
|
{
|
||||||
return FString(std::format("<Stmt Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
|
return String(std::format("<Stmt Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -155,9 +155,9 @@ namespace Fig::Ast
|
|||||||
public:
|
public:
|
||||||
EofStmt() { type = AstType::StatementBase; }
|
EofStmt() { type = AstType::StatementBase; }
|
||||||
|
|
||||||
virtual FString toString() override
|
virtual String toString() override
|
||||||
{
|
{
|
||||||
return FString(std::format("<EOF Stmt at {}:{}>", aai.line, aai.column));
|
return String(std::format("<EOF Stmt at {}:{}>", aai.line, aai.column));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -168,9 +168,9 @@ namespace Fig::Ast
|
|||||||
using _AstBase::operator=;
|
using _AstBase::operator=;
|
||||||
ExpressionAst() { type = AstType::ExpressionBase; }
|
ExpressionAst() { type = AstType::ExpressionBase; }
|
||||||
|
|
||||||
virtual FString toString() override
|
virtual String toString() override
|
||||||
{
|
{
|
||||||
return FString(std::format("<Expr Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
|
return String(std::format("<Expr Ast '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
enum class Operator : uint8_t
|
enum class Operator : uint8_t
|
||||||
@@ -326,10 +326,10 @@ namespace Fig::Ast
|
|||||||
std::vector<Statement> stmts;
|
std::vector<Statement> stmts;
|
||||||
BlockStatementAst() { type = AstType::BlockStatement; }
|
BlockStatementAst() { type = AstType::BlockStatement; }
|
||||||
BlockStatementAst(std::vector<Statement> _stmts) : stmts(std::move(_stmts)) { type = AstType::BlockStatement; }
|
BlockStatementAst(std::vector<Statement> _stmts) : stmts(std::move(_stmts)) { type = AstType::BlockStatement; }
|
||||||
virtual FString typeName() override { return FString(u8"BlockStatement"); }
|
virtual String typeName() override { return String(U"BlockStatement"); }
|
||||||
virtual FString toString() override
|
virtual String toString() override
|
||||||
{
|
{
|
||||||
return FString(std::format("<StmtAst '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
|
return String(std::format("<StmtAst '{}' at {}:{}>", typeName().toBasicString(), aai.line, aai.column));
|
||||||
}
|
}
|
||||||
virtual ~BlockStatementAst() = default;
|
virtual ~BlockStatementAst() = default;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <Ast/astBase.hpp>
|
#include <Ast/astBase.hpp>
|
||||||
#include <Evaluator/Value/Type.hpp>
|
#include <Evaluator/Value/Type.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
|
|
||||||
#include <format>
|
#include <format>
|
||||||
|
|
||||||
@@ -17,15 +17,15 @@ namespace Fig::Ast
|
|||||||
func test2(dp1 = 10, dp2:String = "default parameter 2")
|
func test2(dp1 = 10, dp2:String = "default parameter 2")
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using PosParasType = std::vector<std::pair<FString, Expression>>;
|
using PosParasType = std::vector<std::pair<String, Expression>>;
|
||||||
// name type exp
|
// name type exp
|
||||||
using DefParasType = std::vector<std::pair<FString, std::pair<Expression, Expression>>>;
|
using DefParasType = std::vector<std::pair<String, std::pair<Expression, Expression>>>;
|
||||||
// name type exp default value
|
// name type exp default value
|
||||||
|
|
||||||
PosParasType posParas;
|
PosParasType posParas;
|
||||||
DefParasType defParas; // default parameters
|
DefParasType defParas; // default parameters
|
||||||
|
|
||||||
FString variadicPara;
|
String variadicPara;
|
||||||
bool variadic = false;
|
bool variadic = false;
|
||||||
|
|
||||||
FunctionParameters()
|
FunctionParameters()
|
||||||
@@ -36,7 +36,7 @@ namespace Fig::Ast
|
|||||||
posParas = std::move(_posParas);
|
posParas = std::move(_posParas);
|
||||||
defParas = std::move(_defParas);
|
defParas = std::move(_defParas);
|
||||||
}
|
}
|
||||||
FunctionParameters(FString _variadicPara)
|
FunctionParameters(String _variadicPara)
|
||||||
{
|
{
|
||||||
variadicPara = std::move(_variadicPara);
|
variadicPara = std::move(_variadicPara);
|
||||||
variadic = true;
|
variadic = true;
|
||||||
@@ -52,46 +52,46 @@ namespace Fig::Ast
|
|||||||
return posParas == other.posParas && defParas == other.defParas && variadicPara == other.variadicPara && variadic == other.variadic;
|
return posParas == other.posParas && defParas == other.defParas && variadicPara == other.variadicPara && variadic == other.variadic;
|
||||||
}
|
}
|
||||||
|
|
||||||
FString toString() const
|
String toString() const
|
||||||
{
|
{
|
||||||
if (variadic)
|
if (variadic)
|
||||||
{
|
{
|
||||||
return FString(variadicPara + u8"...");
|
return String(variadicPara + U"...");
|
||||||
}
|
}
|
||||||
const auto posParasToString = [this]() {
|
const auto posParasToString = [this]() {
|
||||||
FString out;
|
String out;
|
||||||
for (auto &p : posParas)
|
for (auto &p : posParas)
|
||||||
{
|
{
|
||||||
out += p.first;
|
out += p.first;
|
||||||
if (p.second != nullptr)
|
if (p.second != nullptr)
|
||||||
{
|
{
|
||||||
out += FString(u8":" + p.second->toString());
|
out += String(String(U":") + p.second->toString());
|
||||||
}
|
}
|
||||||
out += u8",";
|
out += U",";
|
||||||
}
|
}
|
||||||
out.pop_back();
|
out.pop_back();
|
||||||
return out;
|
return out;
|
||||||
};
|
};
|
||||||
const auto defParasToString = [this]() {
|
const auto defParasToString = [this]() {
|
||||||
FString out;
|
String out;
|
||||||
for (auto &p : defParas)
|
for (auto &p : defParas)
|
||||||
{
|
{
|
||||||
out += p.first;
|
out += p.first;
|
||||||
if (p.second.first != nullptr)
|
if (p.second.first != nullptr)
|
||||||
{
|
{
|
||||||
out += FString(u8":" + p.second.first->toString());
|
out += String(String(U":") + p.second.first->toString());
|
||||||
}
|
}
|
||||||
if (p.second.second != nullptr)
|
if (p.second.second != nullptr)
|
||||||
{
|
{
|
||||||
out += u8"=";
|
out += U"=";
|
||||||
out += p.second.second->toString();
|
out += p.second.second->toString();
|
||||||
}
|
}
|
||||||
out += u8",";
|
out += U",";
|
||||||
}
|
}
|
||||||
out.pop_back();
|
out.pop_back();
|
||||||
return out;
|
return out;
|
||||||
};
|
};
|
||||||
return FString(std::format("{},{}", posParasToString().toBasicString(), defParasToString().toBasicString()));
|
return String(std::format("{},{}", posParasToString().toBasicString(), defParasToString().toBasicString()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace Fig::Ast
|
} // namespace Fig::Ast
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Bytecode/Instruction.hpp>
|
#include <Bytecode/Instruction.hpp>
|
||||||
#include <Evaluator/Value/value.hpp>
|
#include <Evaluator/Value/value.hpp>
|
||||||
|
|
||||||
@@ -10,16 +10,16 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
struct ChunkAddressInfo
|
struct ChunkAddressInfo
|
||||||
{
|
{
|
||||||
FString sourcePath;
|
String sourcePath;
|
||||||
std::vector<FString> sourceLines;
|
std::vector<String> sourceLines;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Chunk
|
struct Chunk
|
||||||
{
|
{
|
||||||
Instructions ins; // vector<Instruction>
|
Instructions ins; // vector<Instruction>
|
||||||
std::vector<Object> constants; // 常量池
|
std::vector<Object> constants; // 常量池
|
||||||
|
|
||||||
std::vector<InstructionAddressInfo> instructions_addr; // 下标和ins对齐,表示每个Instruction对应的地址
|
std::vector<InstructionAddressInfo> instructions_addr; // 下标和ins对齐,表示每个Instruction对应的地址
|
||||||
ChunkAddressInfo addr; // 代码块独立Addr
|
ChunkAddressInfo addr; // 代码块独立Addr
|
||||||
};
|
};
|
||||||
};
|
}; // namespace Fig
|
||||||
@@ -8,15 +8,15 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
using AddressableError::AddressableError;
|
using AddressableError::AddressableError;
|
||||||
|
|
||||||
virtual FString toString() const override
|
virtual String toString() const override
|
||||||
{
|
{
|
||||||
std::string msg = std::format("[CompileError] {} in [{}] {}",
|
std::string msg = std::format("[CompileError] {} in [{}] {}",
|
||||||
this->message.toBasicString(),
|
this->message.toBasicString(),
|
||||||
this->src_loc.file_name(),
|
this->src_loc.file_name(),
|
||||||
this->src_loc.function_name());
|
this->src_loc.function_name());
|
||||||
return FString(msg);
|
return String(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual FString getErrorType() const override { return FString(u8"CompileError"); }
|
virtual String getErrorType() const override { return String(U"\1"); }
|
||||||
};
|
};
|
||||||
};
|
}; // namespace Fig
|
||||||
@@ -7,15 +7,14 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
struct CompiledFunction
|
struct CompiledFunction
|
||||||
{
|
{
|
||||||
|
|
||||||
Chunk chunk; // 函数代码块
|
Chunk chunk; // 函数代码块
|
||||||
|
|
||||||
FString name; // 函数名
|
String name; // 函数名
|
||||||
uint64_t posArgCount; // 位置参数数量
|
uint64_t posArgCount; // 位置参数数量
|
||||||
uint64_t defArgCount; // 默认参数数量
|
uint64_t defArgCount; // 默认参数数量
|
||||||
bool variadicPara; // 可变参数(是:最后为可变,否:不可变)
|
bool variadicPara; // 可变参数(是:最后为可变,否:不可变)
|
||||||
|
|
||||||
uint64_t localCount; // 局部变量数量(不包括参数)
|
uint64_t localCount; // 局部变量数量(不包括参数)
|
||||||
uint64_t slotCount; // = 总参数数量 + 局部变量数量
|
uint64_t slotCount; // = 总参数数量 + 局部变量数量
|
||||||
};
|
};
|
||||||
};
|
}; // namespace Fig
|
||||||
@@ -24,9 +24,9 @@ int main()
|
|||||||
// ---------------- fib ----------------
|
// ---------------- fib ----------------
|
||||||
|
|
||||||
Instructions fib_ins{
|
Instructions fib_ins{
|
||||||
/* 0 */ {OpCode::LOAD_LOCAL, 0}, // x
|
/* 0 */ {OpCode::LOAD_LOCAL, 0}, // x
|
||||||
/* 1 */ {OpCode::LOAD_CONST, 0}, // 1
|
/* 1 */ {OpCode::LOAD_CONST, 0}, // 1
|
||||||
/* 2 */ {OpCode::LTET}, // x <= 1
|
/* 2 */ {OpCode::LTET}, // x <= 1
|
||||||
/* 3 */ {OpCode::JUMP_IF_FALSE, 2}, // false -> jump to 6
|
/* 3 */ {OpCode::JUMP_IF_FALSE, 2}, // false -> jump to 6
|
||||||
|
|
||||||
/* 4 */ {OpCode::LOAD_LOCAL, 0}, // return x
|
/* 4 */ {OpCode::LOAD_LOCAL, 0}, // return x
|
||||||
@@ -34,13 +34,13 @@ int main()
|
|||||||
|
|
||||||
/* 6 */ {OpCode::LOAD_LOCAL, 0}, // x
|
/* 6 */ {OpCode::LOAD_LOCAL, 0}, // x
|
||||||
/* 7 */ {OpCode::LOAD_CONST, 0}, // 1
|
/* 7 */ {OpCode::LOAD_CONST, 0}, // 1
|
||||||
/* 8 */ {OpCode::SUB}, // x - 1
|
/* 8 */ {OpCode::SUB}, // x - 1
|
||||||
/* 9 */ {OpCode::LOAD_CONST, 2}, // fib
|
/* 9 */ {OpCode::LOAD_CONST, 2}, // fib
|
||||||
/* 10 */ {OpCode::CALL, 1}, // fib(x-1)
|
/* 10 */ {OpCode::CALL, 1}, // fib(x-1)
|
||||||
|
|
||||||
/* 11 */ {OpCode::LOAD_LOCAL, 0}, // x
|
/* 11 */ {OpCode::LOAD_LOCAL, 0}, // x
|
||||||
/* 12 */ {OpCode::LOAD_CONST, 1}, // 2
|
/* 12 */ {OpCode::LOAD_CONST, 1}, // 2
|
||||||
/* 13 */ {OpCode::SUB}, // x - 2
|
/* 13 */ {OpCode::SUB}, // x - 2
|
||||||
/* 14 */ {OpCode::LOAD_CONST, 2}, // fib
|
/* 14 */ {OpCode::LOAD_CONST, 2}, // fib
|
||||||
/* 15 */ {OpCode::CALL, 1}, // fib(x-2)
|
/* 15 */ {OpCode::CALL, 1}, // fib(x-2)
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ int main()
|
|||||||
|
|
||||||
CompiledFunction fib_fn{
|
CompiledFunction fib_fn{
|
||||||
{},
|
{},
|
||||||
u8"fib",
|
U"\1",
|
||||||
1, // posArgCount
|
1, // posArgCount
|
||||||
0,
|
0,
|
||||||
false,
|
false,
|
||||||
@@ -81,13 +81,13 @@ int main()
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Object> main_consts{
|
std::vector<Object> main_consts{
|
||||||
Object((int64_t)251), // 0
|
Object((int64_t) 251), // 0
|
||||||
Object(Function(&fib_fn)), // 1
|
Object(Function(&fib_fn)), // 1
|
||||||
};
|
};
|
||||||
|
|
||||||
Chunk main_chunk{main_ins, main_consts, {}, ChunkAddressInfo{}};
|
Chunk main_chunk{main_ins, main_consts, {}, ChunkAddressInfo{}};
|
||||||
|
|
||||||
CompiledFunction main_fn{main_chunk, u8"main", 0, 0, false, 0, 0};
|
CompiledFunction main_fn{main_chunk, U"\1", 0, 0, false, 0, 0};
|
||||||
|
|
||||||
CallFrame entry{.ip = 0, .base = 0, .fn = main_fn};
|
CallFrame entry{.ip = 0, .base = 0, .fn = main_fn};
|
||||||
|
|
||||||
|
|||||||
312
src/Core/CharUtils.hpp
Normal file
312
src/Core/CharUtils.hpp
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
class CharUtils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool isDigit(char32_t c) { return c >= U'0' && c <= U'9'; }
|
||||||
|
|
||||||
|
static bool isAlpha(char32_t c)
|
||||||
|
{
|
||||||
|
// ASCII字母
|
||||||
|
if ((c >= U'A' && c <= U'Z') || (c >= U'a' && c <= U'z')) return true;
|
||||||
|
|
||||||
|
// Unicode字母检查
|
||||||
|
// Ll - 小写字母
|
||||||
|
// Lu - 大写字母
|
||||||
|
// Lt - 标题字母
|
||||||
|
// Lm - 修饰字母
|
||||||
|
// Lo - 其他字母
|
||||||
|
|
||||||
|
// 基本拉丁字母
|
||||||
|
if ((c >= 0x00C0 && c <= 0x00D6) || // Latin-1 Supplement
|
||||||
|
(c >= 0x00D8 && c <= 0x00F6) || // Latin-1 Supplement
|
||||||
|
(c >= 0x00F8 && c <= 0x02AF) || // Latin Extended
|
||||||
|
(c >= 0x0370 && c <= 0x052F) || // Greek, Cyrillic
|
||||||
|
(c >= 0x0591 && c <= 0x05F4) || // Hebrew
|
||||||
|
(c >= 0x0600 && c <= 0x06FF) || // Arabic
|
||||||
|
(c >= 0x0700 && c <= 0x0D7F) || // Syriac, Thaana, Devanagari, etc.
|
||||||
|
(c >= 0x0E00 && c <= 0x0E7F) || // Thai
|
||||||
|
(c >= 0x0F00 && c <= 0x0FFF) || // Tibetan
|
||||||
|
(c >= 0x1000 && c <= 0x109F) || // Myanmar
|
||||||
|
(c >= 0x10A0 && c <= 0x10FF) || // Georgian
|
||||||
|
(c >= 0x1100 && c <= 0x11FF) || // Hangul Jamo
|
||||||
|
(c >= 0x1200 && c <= 0x137F) || // Ethiopic
|
||||||
|
(c >= 0x13A0 && c <= 0x13FF) || // Cherokee
|
||||||
|
(c >= 0x1400 && c <= 0x167F) || // Unified Canadian Aboriginal Syllabics
|
||||||
|
(c >= 0x1680 && c <= 0x169F) || // Ogham
|
||||||
|
(c >= 0x16A0 && c <= 0x16FF) || // Runic
|
||||||
|
(c >= 0x1700 && c <= 0x171F) || // Tagalog
|
||||||
|
(c >= 0x1720 && c <= 0x173F) || // Hanunoo
|
||||||
|
(c >= 0x1740 && c <= 0x175F) || // Buhid
|
||||||
|
(c >= 0x1760 && c <= 0x177F) || // Tagbanwa
|
||||||
|
(c >= 0x1780 && c <= 0x17FF) || // Khmer
|
||||||
|
(c >= 0x1800 && c <= 0x18AF) || // Mongolian
|
||||||
|
(c >= 0x1900 && c <= 0x194F) || // Limbu
|
||||||
|
(c >= 0x1950 && c <= 0x197F) || // Tai Le
|
||||||
|
(c >= 0x19E0 && c <= 0x19FF) || // Khmer Symbols
|
||||||
|
(c >= 0x1D00 && c <= 0x1D7F) || // Phonetic Extensions
|
||||||
|
(c >= 0x1E00 && c <= 0x1EFF) || // Latin Extended Additional
|
||||||
|
(c >= 0x1F00 && c <= 0x1FFF) || // Greek Extended
|
||||||
|
(c >= 0x2C00 && c <= 0x2C5F) || // Glagolitic
|
||||||
|
(c >= 0x2C60 && c <= 0x2C7F) || // Latin Extended-C
|
||||||
|
(c >= 0x2C80 && c <= 0x2CFF) || // Coptic
|
||||||
|
(c >= 0x2D00 && c <= 0x2D2F) || // Georgian Supplement
|
||||||
|
(c >= 0x2D30 && c <= 0x2D7F) || // Tifinagh
|
||||||
|
(c >= 0x2D80 && c <= 0x2DDF) || // Ethiopic Extended
|
||||||
|
(c >= 0x2DE0 && c <= 0x2DFF) || // Cyrillic Extended-A
|
||||||
|
(c >= 0x2E00 && c <= 0x2E7F) || // Supplemental Punctuation
|
||||||
|
(c >= 0xA640 && c <= 0xA69F) || // Cyrillic Extended-B
|
||||||
|
(c >= 0xA720 && c <= 0xA7FF) || // Latin Extended-D
|
||||||
|
(c >= 0xA800 && c <= 0xA82F) || // Syloti Nagri
|
||||||
|
(c >= 0xA840 && c <= 0xA87F) || // Phags-pa
|
||||||
|
(c >= 0xAC00 && c <= 0xD7AF) || // Hangul Syllables
|
||||||
|
(c >= 0xF900 && c <= 0xFAFF) || // CJK Compatibility Ideographs
|
||||||
|
(c >= 0xFB00 && c <= 0xFB4F) || // Alphabetic Presentation Forms
|
||||||
|
(c >= 0xFE20 && c <= 0xFE2F) || // Combining Half Marks
|
||||||
|
(c >= 0xFE70 && c <= 0xFEFF) || // Arabic Presentation Forms-B
|
||||||
|
(c >= 0xFF00 && c <= 0xFFEF) || // Halfwidth and Fullwidth Forms
|
||||||
|
(c >= 0x10000 && c <= 0x100FF) || // Linear B Syllabary
|
||||||
|
(c >= 0x10140 && c <= 0x1018F) || // Ancient Greek Numbers
|
||||||
|
(c >= 0x10300 && c <= 0x1032F) || // Old Italic
|
||||||
|
(c >= 0x10330 && c <= 0x1034F) || // Gothic
|
||||||
|
(c >= 0x10380 && c <= 0x1039F) || // Ugaritic
|
||||||
|
(c >= 0x103A0 && c <= 0x103DF) || // Old Persian
|
||||||
|
(c >= 0x10400 && c <= 0x1044F) || // Deseret
|
||||||
|
(c >= 0x10450 && c <= 0x1047F) || // Shavian
|
||||||
|
(c >= 0x10480 && c <= 0x104AF) || // Osmanya
|
||||||
|
(c >= 0x10800 && c <= 0x1083F) || // Cypriot Syllabary
|
||||||
|
(c >= 0x10900 && c <= 0x1091F) || // Phoenician
|
||||||
|
(c >= 0x10A00 && c <= 0x10A5F) || // Kharoshthi
|
||||||
|
(c >= 0x12000 && c <= 0x123FF) || // Cuneiform
|
||||||
|
(c >= 0x1D400 && c <= 0x1D7FF) || // Mathematical Alphanumeric Symbols
|
||||||
|
(c >= 0x1F130 && c <= 0x1F1FF) || // Enclosed Alphanumeric Supplement
|
||||||
|
(c >= 0x20000 && c <= 0x2A6DF) || // CJK Unified Ideographs Extension B
|
||||||
|
(c >= 0x2A700 && c <= 0x2B73F) || // CJK Unified Ideographs Extension C
|
||||||
|
(c >= 0x2B740 && c <= 0x2B81F) || // CJK Unified Ideographs Extension D
|
||||||
|
(c >= 0x2F800 && c <= 0x2FA1F)) // CJK Compatibility Ideographs Supplement
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CJK统一表意文字 (中文、日文、韩文)
|
||||||
|
if ((c >= 0x4E00 && c <= 0x9FFF) || // CJK Unified Ideographs
|
||||||
|
(c >= 0x3400 && c <= 0x4DBF) || // CJK Unified Ideographs Extension A
|
||||||
|
(c >= 0x2E80 && c <= 0x2EFF) || // CJK Radicals Supplement
|
||||||
|
(c >= 0x2F00 && c <= 0x2FDF) || // Kangxi Radicals
|
||||||
|
(c >= 0x2FF0 && c <= 0x2FFF) || // Ideographic Description Characters
|
||||||
|
(c >= 0x3000 && c <= 0x303F) || // CJK Symbols and Punctuation
|
||||||
|
(c >= 0x31C0 && c <= 0x31EF) || // CJK Strokes
|
||||||
|
(c >= 0x3200 && c <= 0x32FF) || // Enclosed CJK Letters and Months
|
||||||
|
(c >= 0x3300 && c <= 0x33FF) || // CJK Compatibility
|
||||||
|
(c >= 0xF900 && c <= 0xFAFF) || // CJK Compatibility Ideographs
|
||||||
|
(c >= 0xFE30 && c <= 0xFE4F) || // CJK Compatibility Forms
|
||||||
|
(c >= 0x1F200 && c <= 0x1F2FF)) // Enclosed Ideographic Supplement
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isUpper(char32_t c)
|
||||||
|
{
|
||||||
|
// ASCII大写字母
|
||||||
|
if (c >= U'A' && c <= U'Z') return true;
|
||||||
|
|
||||||
|
// Unicode大写字母检查
|
||||||
|
if ((c >= 0x00C0 && c <= 0x00D6) || // Latin-1 Supplement
|
||||||
|
(c >= 0x00D8 && c <= 0x00DE) || // Latin-1 Supplement
|
||||||
|
(c >= 0x0100 && c <= 0x012E) || // Latin Extended-A
|
||||||
|
(c >= 0x0132 && c <= 0x0136) || (c >= 0x0139 && c <= 0x0147) || (c >= 0x014A && c <= 0x0178)
|
||||||
|
|| (c >= 0x0179 && c <= 0x017D) || (c >= 0x0181 && c <= 0x0182) || c == 0x0186 || c == 0x0189 || c == 0x018A
|
||||||
|
|| c == 0x018E || c == 0x018F || c == 0x0190 || c == 0x0191 || c == 0x0193 || c == 0x0194 || c == 0x0196
|
||||||
|
|| c == 0x0197 || c == 0x0198 || c == 0x019C || c == 0x019D || c == 0x019F || c == 0x01A0 || c == 0x01A2
|
||||||
|
|| c == 0x01A4 || c == 0x01A7 || c == 0x01A9 || c == 0x01AC || c == 0x01AE || c == 0x01AF
|
||||||
|
|| (c >= 0x01B1 && c <= 0x01B3) || c == 0x01B5 || c == 0x01B7 || c == 0x01B8 || c == 0x01BC || c == 0x01C4
|
||||||
|
|| c == 0x01C7 || c == 0x01CA || c == 0x01CD || c == 0x01CF || c == 0x01D1 || c == 0x01D3 || c == 0x01D5
|
||||||
|
|| c == 0x01D7 || c == 0x01D9 || c == 0x01DB || c == 0x01DE || c == 0x01E0 || c == 0x01E2 || c == 0x01E4
|
||||||
|
|| c == 0x01E6 || c == 0x01E8 || c == 0x01EA || c == 0x01EC || c == 0x01EE || c == 0x01F4 || c == 0x01FA
|
||||||
|
|| (c >= 0x01FC && c <= 0x01FF) || (c >= 0x0200 && c <= 0x0220) || (c >= 0x0222 && c <= 0x0232)
|
||||||
|
|| (c >= 0x0370 && c <= 0x0373) || (c >= 0x0376 && c <= 0x0377) || (c >= 0x03D8 && c <= 0x03EF)
|
||||||
|
|| (c >= 0x03F4 && c <= 0x03F7) || (c >= 0x03F9 && c <= 0x03FA) || (c >= 0x03FD && c <= 0x042F)
|
||||||
|
|| (c >= 0x0460 && c <= 0x0480) || (c >= 0x048A && c <= 0x04C0) || (c >= 0x04C1 && c <= 0x04CD)
|
||||||
|
|| (c >= 0x04D0 && c <= 0x0528) || (c >= 0x0531 && c <= 0x0556) || (c >= 0x10A0 && c <= 0x10C5)
|
||||||
|
|| (c >= 0x1E00 && c <= 0x1E94) || (c >= 0x1EA0 && c <= 0x1EFE) || (c >= 0x2C00 && c <= 0x2C2E)
|
||||||
|
|| (c >= 0x2C60 && c <= 0x2C62) || (c >= 0xA640 && c <= 0xA66C) || (c >= 0xA680 && c <= 0xA69A)
|
||||||
|
|| (c >= 0xA722 && c <= 0xA72E) || (c >= 0xA732 && c <= 0xA76E) || (c >= 0xA779 && c <= 0xA77D)
|
||||||
|
|| (c >= 0xA77E && c <= 0xA786) || (c >= 0xA78B && c <= 0xA78D) || (c >= 0xA790 && c <= 0xA792)
|
||||||
|
|| (c >= 0xA796 && c <= 0xA7A8) || (c >= 0xA7AA && c <= 0xA7AE) || (c >= 0xA7B0 && c <= 0xA7B4)
|
||||||
|
|| (c >= 0xA7B6 && c <= 0xA7BE) || (c >= 0xFF21 && c <= 0xFF3A) || // 全角大写字母
|
||||||
|
(c >= 0x10400 && c <= 0x10427) || // Deseret
|
||||||
|
(c >= 0x104B0 && c <= 0x104D3) || // Osage
|
||||||
|
(c >= 0x10C80 && c <= 0x10CB2) || // Old Hungarian
|
||||||
|
(c >= 0x118A0 && c <= 0x118DF) || // Warang Citi
|
||||||
|
(c >= 0x1D400 && c <= 0x1D419) || // Mathematical bold capital
|
||||||
|
(c >= 0x1D434 && c <= 0x1D44D) || // Mathematical italic capital
|
||||||
|
(c >= 0x1D468 && c <= 0x1D481) || // Mathematical bold italic capital
|
||||||
|
(c >= 0x1D49C && c <= 0x1D4B5) || // Mathematical script capital
|
||||||
|
(c >= 0x1D4D0 && c <= 0x1D4E9) || // Mathematical bold script capital
|
||||||
|
(c >= 0x1D504 && c <= 0x1D51C) || // Mathematical fraktur capital
|
||||||
|
(c >= 0x1D538 && c <= 0x1D550) || // Mathematical double-struck capital
|
||||||
|
(c >= 0x1D56C && c <= 0x1D585) || // Mathematical bold fraktur capital
|
||||||
|
(c >= 0x1D5A0 && c <= 0x1D5B9) || // Mathematical sans-serif capital
|
||||||
|
(c >= 0x1D5D4 && c <= 0x1D5ED) || // Mathematical sans-serif bold capital
|
||||||
|
(c >= 0x1D608 && c <= 0x1D621) || // Mathematical sans-serif italic capital
|
||||||
|
(c >= 0x1D63C && c <= 0x1D655) || // Mathematical sans-serif bold italic capital
|
||||||
|
(c >= 0x1D670 && c <= 0x1D689) || // Mathematical monospace capital
|
||||||
|
(c >= 0x1D6A8 && c <= 0x1D6C0) || // Mathematical bold capital Greek
|
||||||
|
(c >= 0x1D6E2 && c <= 0x1D6FA) || // Mathematical italic capital Greek
|
||||||
|
(c >= 0x1D71C && c <= 0x1D734) || // Mathematical bold italic capital Greek
|
||||||
|
(c >= 0x1D756 && c <= 0x1D76E) || // Mathematical sans-serif bold capital Greek
|
||||||
|
(c >= 0x1D790 && c <= 0x1D7A8)) // Mathematical sans-serif bold italic capital Greek
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isLower(char32_t c)
|
||||||
|
{
|
||||||
|
// ASCII小写字母
|
||||||
|
if (c >= U'a' && c <= U'z') return true;
|
||||||
|
|
||||||
|
// Unicode小写字母检查
|
||||||
|
if ((c >= 0x00DF && c <= 0x00F6) || // Latin-1 Supplement
|
||||||
|
(c >= 0x00F8 && c <= 0x00FF) || // Latin-1 Supplement
|
||||||
|
(c >= 0x0101 && c <= 0x012F) || // Latin Extended-A
|
||||||
|
(c >= 0x0133 && c <= 0x0137) || (c >= 0x013A && c <= 0x0148) || (c >= 0x014B && c <= 0x0177)
|
||||||
|
|| (c >= 0x017A && c <= 0x017E) || (c >= 0x0183 && c <= 0x0185) || c == 0x0188 || c == 0x018C || c == 0x0192
|
||||||
|
|| c == 0x0195 || c == 0x0199 || c == 0x019A || c == 0x019E || c == 0x01A1 || c == 0x01A3 || c == 0x01A5
|
||||||
|
|| c == 0x01A8 || c == 0x01AA || c == 0x01AB || c == 0x01AD || c == 0x01B0 || c == 0x01B4 || c == 0x01B6
|
||||||
|
|| c == 0x01B9 || c == 0x01BA || c == 0x01BD || c == 0x01C6 || c == 0x01C9 || c == 0x01CC || c == 0x01CE
|
||||||
|
|| c == 0x01D0 || c == 0x01D2 || c == 0x01D4 || c == 0x01D6 || c == 0x01D8 || c == 0x01DA || c == 0x01DC
|
||||||
|
|| c == 0x01DD || c == 0x01DF || c == 0x01E1 || c == 0x01E3 || c == 0x01E5 || c == 0x01E7 || c == 0x01E9
|
||||||
|
|| c == 0x01EB || c == 0x01ED || c == 0x01F3 || c == 0x01F5 || c == 0x01FB || (c >= 0x0201 && c <= 0x0217)
|
||||||
|
|| (c >= 0x0250 && c <= 0x02A8) || (c >= 0x03B1 && c <= 0x03C1) || (c >= 0x03C3 && c <= 0x03CE)
|
||||||
|
|| (c >= 0x0430 && c <= 0x044F) || (c >= 0x0451 && c <= 0x045C) || (c >= 0x045E && c <= 0x0481)
|
||||||
|
|| (c >= 0x0491 && c <= 0x04BF) || (c >= 0x04C2 && c <= 0x04CE) || (c >= 0x04D1 && c <= 0x0527)
|
||||||
|
|| (c >= 0x0561 && c <= 0x0587) || (c >= 0x1D00 && c <= 0x1D2B) || (c >= 0x1D62 && c <= 0x1D77)
|
||||||
|
|| (c >= 0x1D79 && c <= 0x1D9A) || (c >= 0x1E01 && c <= 0x1E95) || (c >= 0x1EA1 && c <= 0x1EFF)
|
||||||
|
|| (c >= 0x2C30 && c <= 0x2C5E) || (c >= 0x2C61 && c <= 0x2C65) || (c >= 0x2C66 && c <= 0x2C6C)
|
||||||
|
|| (c >= 0x2C73 && c <= 0x2C74) || (c >= 0x2C76 && c <= 0x2C7B) || (c >= 0xA641 && c <= 0xA66D)
|
||||||
|
|| (c >= 0xA681 && c <= 0xA69B) || (c >= 0xA723 && c <= 0xA72F) || (c >= 0xA733 && c <= 0xA76F)
|
||||||
|
|| (c >= 0xA77A && c <= 0xA77C) || (c >= 0xA77F && c <= 0xA787) || (c >= 0xA78C && c <= 0xA78E)
|
||||||
|
|| (c >= 0xA791 && c <= 0xA793) || (c >= 0xA797 && c <= 0xA7A9) || (c >= 0xA7AB && c <= 0xA7AE)
|
||||||
|
|| (c >= 0xA7B1 && c <= 0xA7B5) || (c >= 0xA7B7 && c <= 0xA7BF) || (c >= 0xAB30 && c <= 0xAB5A)
|
||||||
|
|| (c >= 0xAB60 && c <= 0xAB65) || (c >= 0xAB70 && c <= 0xABBF) || (c >= 0xFB00 && c <= 0xFB06)
|
||||||
|
|| (c >= 0xFB13 && c <= 0xFB17) || (c >= 0xFF41 && c <= 0xFF5A) || // 全角小写字母
|
||||||
|
(c >= 0x10428 && c <= 0x1044F) || // Deseret lowercase
|
||||||
|
(c >= 0x104D8 && c <= 0x104FB) || // Osage lowercase
|
||||||
|
(c >= 0x10CC0 && c <= 0x10CF2) || // Old Hungarian lowercase
|
||||||
|
(c >= 0x118C0 && c <= 0x118E0) || // Warang Citi lowercase
|
||||||
|
(c >= 0x1D41A && c <= 0x1D433) || // Mathematical bold lowercase
|
||||||
|
(c >= 0x1D44E && c <= 0x1D467) || // Mathematical italic lowercase
|
||||||
|
(c >= 0x1D482 && c <= 0x1D49B) || // Mathematical bold italic lowercase
|
||||||
|
(c >= 0x1D4B6 && c <= 0x1D4CF) || // Mathematical script lowercase
|
||||||
|
(c >= 0x1D4EA && c <= 0x1D503) || // Mathematical bold script lowercase
|
||||||
|
(c >= 0x1D51E && c <= 0x1D537) || // Mathematical fraktur lowercase
|
||||||
|
(c >= 0x1D552 && c <= 0x1D56B) || // Mathematical double-struck lowercase
|
||||||
|
(c >= 0x1D586 && c <= 0x1D59F) || // Mathematical bold fraktur lowercase
|
||||||
|
(c >= 0x1D5BA && c <= 0x1D5D3) || // Mathematical sans-serif lowercase
|
||||||
|
(c >= 0x1D5EE && c <= 0x1D607) || // Mathematical sans-serif bold lowercase
|
||||||
|
(c >= 0x1D622 && c <= 0x1D63B) || // Mathematical sans-serif italic lowercase
|
||||||
|
(c >= 0x1D656 && c <= 0x1D66F) || // Mathematical sans-serif bold italic lowercase
|
||||||
|
(c >= 0x1D68A && c <= 0x1D6A5) || // Mathematical monospace lowercase
|
||||||
|
(c >= 0x1D6C1 && c <= 0x1D6DA) || // Mathematical bold lowercase Greek
|
||||||
|
(c >= 0x1D6FB && c <= 0x1D714) || // Mathematical italic lowercase Greek
|
||||||
|
(c >= 0x1D735 && c <= 0x1D74E) || // Mathematical bold italic lowercase Greek
|
||||||
|
(c >= 0x1D76F && c <= 0x1D788) || // Mathematical sans-serif bold lowercase Greek
|
||||||
|
(c >= 0x1D7A9 && c <= 0x1D7C2)) // Mathematical sans-serif bold italic lowercase Greek
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isAlnum(char32_t c) { return isAlpha(c) || isDigit(c); }
|
||||||
|
|
||||||
|
static bool isXdigit(char32_t c)
|
||||||
|
{
|
||||||
|
return isDigit(c) || (c >= U'a' && c <= U'f') || (c >= U'A' && c <= U'F') || (c >= 0xFF10 && c <= 0xFF19)
|
||||||
|
|| // 全角数字
|
||||||
|
(c >= 0xFF21 && c <= 0xFF26) || // 全角大写A-F
|
||||||
|
(c >= 0xFF41 && c <= 0xFF46); // 全角小写a-f
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isSpace(char32_t c)
|
||||||
|
{
|
||||||
|
return c == U' ' || c == U'\t' || c == U'\n' || c == U'\r' || c == U'\f' || c == U'\v' || c == 0x00A0
|
||||||
|
|| c == 0x1680 || c == 0x2000 || c == 0x2001 || c == 0x2002 || c == 0x2003 || c == 0x2004 || c == 0x2005
|
||||||
|
|| c == 0x2006 || c == 0x2007 || c == 0x2008 || c == 0x2009 || c == 0x200A || c == 0x202F || c == 0x205F
|
||||||
|
|| c == 0x3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isCntrl(char32_t c) { return (c <= 0x1F) || (c >= 0x7F && c <= 0x9F) || c == 0x2028 || c == 0x2029; }
|
||||||
|
|
||||||
|
static bool isGraph(char32_t c) { return !isSpace(c) && !isCntrl(c) && c != 0x00AD && c != 0x180E; }
|
||||||
|
|
||||||
|
static bool isPrint(char32_t c) { return isGraph(c) || isSpace(c); }
|
||||||
|
|
||||||
|
static bool isPunct(char32_t c) { return isGraph(c) && !isAlnum(c); }
|
||||||
|
|
||||||
|
// 大小写转换
|
||||||
|
static char32_t toLower(char32_t c)
|
||||||
|
{
|
||||||
|
if (isLower(c)) return c;
|
||||||
|
if (c >= U'A' && c <= U'Z') return c + 32;
|
||||||
|
if (c >= 0xC0 && c <= 0xD6 && c != 0xD7) return c + 32;
|
||||||
|
if (c >= 0xD8 && c <= 0xDE) return c + 32;
|
||||||
|
|
||||||
|
assert(false && "Unsupported yet");
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char32_t toUpper(char32_t c)
|
||||||
|
{
|
||||||
|
if (isUpper(c)) return c;
|
||||||
|
if (c >= U'a' && c <= U'z') return c - 32;
|
||||||
|
if (c >= 0xE0 && c <= 0xF6 && c != 0xF7) return c - 32;
|
||||||
|
if (c >= 0xF8 && c <= 0xFE) return c - 32;
|
||||||
|
|
||||||
|
assert(false && "Unsupported yet");
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否是空白字符
|
||||||
|
static bool isWhitespace(char32_t c)
|
||||||
|
{
|
||||||
|
return c == U' ' || c == U'\t' || c == U'\n' || c == U'\r' || c == U'\f' || c == U'\v' || c == 0x00A0
|
||||||
|
|| c == 0x1680 || c == 0x2000 || c == 0x2001 || c == 0x2002 || c == 0x2003 || c == 0x2004 || c == 0x2005
|
||||||
|
|| c == 0x2006 || c == 0x2007 || c == 0x2008 || c == 0x2009 || c == 0x200A || c == 0x2028 || c == 0x2029
|
||||||
|
|| c == 0x202F || c == 0x205F || c == 0x3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否是标点符号
|
||||||
|
static bool isPunctuation(char32_t c)
|
||||||
|
{
|
||||||
|
return (c >= 0x21 && c <= 0x2F) || (c >= 0x3A && c <= 0x40) || (c >= 0x5B && c <= 0x60)
|
||||||
|
|| (c >= 0x7B && c <= 0x7E) || (c >= 0x2000 && c <= 0x206F) || (c >= 0x2E00 && c <= 0x2E7F)
|
||||||
|
|| (c >= 0x3000 && c <= 0x303F) || (c >= 0xFE10 && c <= 0xFE1F) || (c >= 0xFE30 && c <= 0xFE4F)
|
||||||
|
|| (c >= 0xFF00 && c <= 0xFF0F) || (c >= 0xFF1A && c <= 0xFF20) || (c >= 0xFF3B && c <= 0xFF40)
|
||||||
|
|| (c >= 0xFF5B && c <= 0xFF65);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否是表情符号
|
||||||
|
static bool isEmoji(char32_t c)
|
||||||
|
{
|
||||||
|
return (c >= 0x1F600 && c <= 0x1F64F) || // Emoticons
|
||||||
|
(c >= 0x1F300 && c <= 0x1F5FF) || // Miscellaneous Symbols and Pictographs
|
||||||
|
(c >= 0x1F680 && c <= 0x1F6FF) || // Transport and Map Symbols
|
||||||
|
(c >= 0x1F900 && c <= 0x1F9FF) || // Supplemental Symbols and Pictographs
|
||||||
|
(c >= 0x2600 && c <= 0x26FF) || // Miscellaneous Symbols
|
||||||
|
(c >= 0x2700 && c <= 0x27BF) || // Dingbats
|
||||||
|
(c >= 0xFE00 && c <= 0xFE0F) || // Variation Selectors
|
||||||
|
(c >= 0x1F1E6 && c <= 0x1F1FF) || // Regional Indicator Symbols
|
||||||
|
(c >= 0xE0020 && c <= 0xE007F); // Tags
|
||||||
|
}
|
||||||
|
};
|
||||||
12
src/Core/String.cpp
Normal file
12
src/Core/String.cpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#include <Core/String.hpp>
|
||||||
|
|
||||||
|
namespace Fig::StringClass::DynamicCapacity
|
||||||
|
{
|
||||||
|
char32_t Iterator::operator*() const
|
||||||
|
{
|
||||||
|
if (str->is_ascii)
|
||||||
|
return str->is_heap ? str->heap.ascii[index] : str->sso.ascii[index];
|
||||||
|
else
|
||||||
|
return str->is_heap ? str->heap.utf32[index] : str->sso.utf32[index];
|
||||||
|
}
|
||||||
|
};
|
||||||
2227
src/Core/String.hpp
2227
src/Core/String.hpp
File diff suppressed because it is too large
Load Diff
@@ -18,15 +18,9 @@ namespace Fig
|
|||||||
return FStringView(reinterpret_cast<const char8_t *>(sv.data()));
|
return FStringView(reinterpret_cast<const char8_t *>(sv.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit FStringView(std::string_view sv)
|
explicit FStringView(std::string_view sv) { *this = fromBasicStringView(sv); }
|
||||||
{
|
|
||||||
*this = fromBasicStringView(sv);
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit FStringView()
|
explicit FStringView() { *this = fromBasicStringView(std::string_view("")); }
|
||||||
{
|
|
||||||
*this = fromBasicStringView(std::string_view(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view toBasicStringView() const
|
std::string_view toBasicStringView() const
|
||||||
{
|
{
|
||||||
@@ -34,56 +28,26 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FString : public std::u8string
|
class String : public std::u8string
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using std::u8string::u8string;
|
using std::u8string::u8string;
|
||||||
using std::u8string::operator=;
|
using std::u8string::operator=;
|
||||||
|
|
||||||
FString operator+(const FString &x)
|
String operator+(const String &x) { return String(toBasicString() + x.toBasicString()); }
|
||||||
{
|
String operator+(const char8_t *c) { return String(*this + std::u8string(c)); }
|
||||||
return FString(toBasicString() + x.toBasicString());
|
|
||||||
}
|
|
||||||
FString operator+(const char8_t *c)
|
|
||||||
{
|
|
||||||
return FString(*this + std::u8string(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit FString(const std::u8string &str)
|
explicit String(const std::u8string &str) { *this = fromU8String(str); }
|
||||||
{
|
explicit String(std::string str) { *this = fromBasicString(str); }
|
||||||
*this = fromU8String(str);
|
explicit String(FStringView sv) { *this = fromStringView(sv); }
|
||||||
}
|
std::string toBasicString() const { return std::string(this->begin(), this->end()); }
|
||||||
explicit FString(std::string str)
|
FStringView toStringView() const { return FStringView(this->data(), this->size()); }
|
||||||
{
|
|
||||||
*this = fromBasicString(str);
|
|
||||||
}
|
|
||||||
explicit FString(FStringView sv)
|
|
||||||
{
|
|
||||||
*this = fromStringView(sv);
|
|
||||||
}
|
|
||||||
std::string toBasicString() const
|
|
||||||
{
|
|
||||||
return std::string(this->begin(), this->end());
|
|
||||||
}
|
|
||||||
FStringView toStringView() const
|
|
||||||
{
|
|
||||||
return FStringView(this->data(), this->size());
|
|
||||||
}
|
|
||||||
|
|
||||||
static FString fromBasicString(const std::string &str)
|
static String fromBasicString(const std::string &str) { return String(str.begin(), str.end()); }
|
||||||
{
|
|
||||||
return FString(str.begin(), str.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
static FString fromStringView(FStringView sv)
|
static String fromStringView(FStringView sv) { return String(reinterpret_cast<const char *>(sv.data())); }
|
||||||
{
|
|
||||||
return FString(reinterpret_cast<const char *>(sv.data()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static FString fromU8String(const std::u8string &str)
|
static String fromU8String(const std::u8string &str) { return String(str.begin(), str.end()); }
|
||||||
{
|
|
||||||
return FString(str.begin(), str.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t length() const
|
size_t length() const
|
||||||
{
|
{
|
||||||
@@ -91,17 +55,14 @@ namespace Fig
|
|||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
for (auto it = this->begin(); it != this->end(); ++it)
|
for (auto it = this->begin(); it != this->end(); ++it)
|
||||||
{
|
{
|
||||||
if ((*it & 0xC0) != 0x80)
|
if ((*it & 0xC0) != 0x80) { ++len; }
|
||||||
{
|
|
||||||
++len;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
FString getRealChar(size_t index)
|
String getRealChar(size_t index)
|
||||||
{
|
{
|
||||||
FString ch;
|
String ch;
|
||||||
size_t cnt = 0;
|
size_t cnt = 0;
|
||||||
for (size_t i = 0; i < size();)
|
for (size_t i = 0; i < size();)
|
||||||
{
|
{
|
||||||
@@ -112,13 +73,9 @@ namespace Fig
|
|||||||
cplen = 3;
|
cplen = 3;
|
||||||
else if ((at(i) & 0xe0) == 0xc0)
|
else if ((at(i) & 0xe0) == 0xc0)
|
||||||
cplen = 2;
|
cplen = 2;
|
||||||
if (i + cplen > size())
|
if (i + cplen > size()) cplen = 1;
|
||||||
cplen = 1;
|
|
||||||
|
|
||||||
if (cnt == index)
|
if (cnt == index) { ch += substr(i, cplen); }
|
||||||
{
|
|
||||||
ch += substr(i, cplen);
|
|
||||||
}
|
|
||||||
|
|
||||||
i += cplen;
|
i += cplen;
|
||||||
++cnt;
|
++cnt;
|
||||||
@@ -127,7 +84,7 @@ namespace Fig
|
|||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void realReplace(size_t index, const FString &src)
|
void realReplace(size_t index, const String &src)
|
||||||
{
|
{
|
||||||
size_t cnt = 0;
|
size_t cnt = 0;
|
||||||
for (size_t i = 0; i < size();)
|
for (size_t i = 0; i < size();)
|
||||||
@@ -139,13 +96,9 @@ namespace Fig
|
|||||||
cplen = 3;
|
cplen = 3;
|
||||||
else if ((at(i) & 0xe0) == 0xc0)
|
else if ((at(i) & 0xe0) == 0xc0)
|
||||||
cplen = 2;
|
cplen = 2;
|
||||||
if (i + cplen > size())
|
if (i + cplen > size()) cplen = 1;
|
||||||
cplen = 1;
|
|
||||||
|
|
||||||
if (cnt == index)
|
if (cnt == index) { *this = String(substr(0, i)) + src + String(substr(i + cplen)); }
|
||||||
{
|
|
||||||
*this = FString(substr(0, i)) + src + FString(substr(i + cplen));
|
|
||||||
}
|
|
||||||
|
|
||||||
i += cplen;
|
i += cplen;
|
||||||
++cnt;
|
++cnt;
|
||||||
@@ -165,32 +118,22 @@ namespace Fig
|
|||||||
cplen = 3;
|
cplen = 3;
|
||||||
else if ((at(i) & 0xe0) == 0xc0)
|
else if ((at(i) & 0xe0) == 0xc0)
|
||||||
cplen = 2;
|
cplen = 2;
|
||||||
if (i + cplen > size())
|
if (i + cplen > size()) cplen = 1;
|
||||||
cplen = 1;
|
|
||||||
|
|
||||||
i += cplen;
|
i += cplen;
|
||||||
++cnt;
|
++cnt;
|
||||||
|
|
||||||
if (cnt == index)
|
if (cnt == index) { eraseStart = i; }
|
||||||
{
|
if (cnt < index + n) { eraseCplens += cplen; }
|
||||||
eraseStart = i;
|
|
||||||
}
|
|
||||||
if (cnt < index + n)
|
|
||||||
{
|
|
||||||
eraseCplens += cplen;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
erase(eraseStart, eraseCplens);
|
erase(eraseStart, eraseCplens);
|
||||||
}
|
}
|
||||||
|
|
||||||
void realInsert(size_t index, const FString &src)
|
void realInsert(size_t index, const String &src)
|
||||||
{
|
{
|
||||||
if (index == length())
|
if (index == length())
|
||||||
{
|
{
|
||||||
for (auto &c : src)
|
for (auto &c : src) { push_back(c); }
|
||||||
{
|
|
||||||
push_back(c);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t cnt = 0;
|
size_t cnt = 0;
|
||||||
@@ -203,13 +146,9 @@ namespace Fig
|
|||||||
cplen = 3;
|
cplen = 3;
|
||||||
else if ((at(i) & 0xe0) == 0xc0)
|
else if ((at(i) & 0xe0) == 0xc0)
|
||||||
cplen = 2;
|
cplen = 2;
|
||||||
if (i + cplen > size())
|
if (i + cplen > size()) cplen = 1;
|
||||||
cplen = 1;
|
|
||||||
|
|
||||||
if (cnt == index)
|
if (cnt == index) { insert(i, src); }
|
||||||
{
|
|
||||||
insert(i, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
i += cplen;
|
i += cplen;
|
||||||
++cnt;
|
++cnt;
|
||||||
@@ -222,9 +161,9 @@ namespace Fig
|
|||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
template <>
|
template <>
|
||||||
struct hash<Fig::FString>
|
struct hash<Fig::String>
|
||||||
{
|
{
|
||||||
std::size_t operator()(const Fig::FString &s) const
|
std::size_t operator()(const Fig::String &s) const
|
||||||
{
|
{
|
||||||
return std::hash<std::u8string>{}(static_cast<const std::u8string &>(s));
|
return std::hash<std::u8string>{}(static_cast<const std::u8string &>(s));
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
@@ -54,6 +54,5 @@ namespace Fig
|
|||||||
inline constexpr std::string_view COMPILER = __FCORE_COMPILER;
|
inline constexpr std::string_view COMPILER = __FCORE_COMPILER;
|
||||||
inline constexpr std::string_view COMPILE_TIME = __FCORE_COMPILE_TIME;
|
inline constexpr std::string_view COMPILE_TIME = __FCORE_COMPILE_TIME;
|
||||||
inline constexpr std::string_view ARCH = __FCORE_ARCH;
|
inline constexpr std::string_view ARCH = __FCORE_ARCH;
|
||||||
inline constexpr FString MAIN_FUNCTION = u8"main";
|
|
||||||
}; // namespace Core
|
}; // namespace Core
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
const std::unordered_map<std::size_t, FString> Warning::standardWarnings = {
|
const std::unordered_map<std::size_t, String> Warning::standardWarnings = {
|
||||||
{1, FString(u8"Identifier is too similar to a keyword or a primitive type")},
|
{1, String(U"Identifier is too similar to a keyword or a primitive type")},
|
||||||
{2, FString(u8"The identifier is too abstract")}
|
{2, String(U"The identifier is too abstract")}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
|
|
||||||
#include <Utils/magic_enum/magic_enum.hpp>
|
#include <Utils/magic_enum/magic_enum.hpp>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -11,16 +11,17 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
size_t id; // the id (standard) of warning
|
size_t id; // the id (standard) of warning
|
||||||
FString msg;
|
String msg;
|
||||||
size_t line, column;
|
size_t line, column;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const std::unordered_map<size_t, FString> standardWarnings;
|
static const std::unordered_map<size_t, String> standardWarnings;
|
||||||
Warning(size_t _id, FString _msg)
|
Warning(size_t _id, String _msg)
|
||||||
{
|
{
|
||||||
id = _id;
|
id = _id;
|
||||||
msg = std::move(_msg);
|
msg = std::move(_msg);
|
||||||
}
|
}
|
||||||
Warning(size_t _id, FString _msg, size_t _line, size_t _column)
|
Warning(size_t _id, String _msg, size_t _line, size_t _column)
|
||||||
{
|
{
|
||||||
id = _id;
|
id = _id;
|
||||||
msg = std::move(_msg);
|
msg = std::move(_msg);
|
||||||
@@ -28,28 +29,12 @@ namespace Fig
|
|||||||
column = _column;
|
column = _column;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto getIDName()
|
auto getIDName() { return standardWarnings.at(id); }
|
||||||
{
|
|
||||||
return standardWarnings.at(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto getID()
|
|
||||||
{
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
auto getMsg()
|
|
||||||
{
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
auto getLine()
|
|
||||||
{
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
auto getColumn()
|
|
||||||
{
|
|
||||||
return column;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
auto getID() { return id; }
|
||||||
|
auto getMsg() { return msg; }
|
||||||
|
auto getLine() { return line; }
|
||||||
|
auto getColumn() { return column; }
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
}; // namespace Fig
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <format>
|
#include <format>
|
||||||
@@ -14,20 +14,29 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit AddressableError() {}
|
explicit AddressableError() {}
|
||||||
explicit AddressableError(FString _msg,
|
explicit AddressableError(String _msg,
|
||||||
size_t _line,
|
size_t _line,
|
||||||
size_t _column,
|
size_t _column,
|
||||||
FString _sourcePath,
|
String _sourcePath,
|
||||||
std::vector<FString> _sourceLines,
|
std::vector<String> _sourceLines,
|
||||||
std::source_location loc = std::source_location::current()) :
|
std::source_location loc = std::source_location::current()) :
|
||||||
src_loc(loc), line(_line), column(_column), sourcePath(std::move(_sourcePath)), sourceLines(std::move(_sourceLines))
|
src_loc(loc),
|
||||||
|
line(_line),
|
||||||
|
column(_column),
|
||||||
|
sourcePath(std::move(_sourcePath)),
|
||||||
|
sourceLines(std::move(_sourceLines))
|
||||||
{
|
{
|
||||||
message = _msg;
|
message = _msg;
|
||||||
}
|
}
|
||||||
virtual FString toString() const
|
virtual String toString() const
|
||||||
{
|
{
|
||||||
std::string msg = std::format("[AddressableError] {} at {}:{}, in [{}] {}", std::string(this->message.begin(), this->message.end()), this->line, this->column, this->src_loc.file_name(), this->src_loc.function_name());
|
std::string msg = std::format("[AddressableError] {} at {}:{}, in [{}] {}",
|
||||||
return FString(msg);
|
this->message.toBasicString(),
|
||||||
|
this->line,
|
||||||
|
this->column,
|
||||||
|
this->src_loc.file_name(),
|
||||||
|
this->src_loc.function_name());
|
||||||
|
return String(msg);
|
||||||
}
|
}
|
||||||
const char *what() const noexcept override
|
const char *what() const noexcept override
|
||||||
{
|
{
|
||||||
@@ -38,37 +47,36 @@ namespace Fig
|
|||||||
|
|
||||||
virtual size_t getLine() const { return line; }
|
virtual size_t getLine() const { return line; }
|
||||||
virtual size_t getColumn() const { return column; }
|
virtual size_t getColumn() const { return column; }
|
||||||
FString getMessage() const { return message; }
|
String getMessage() const { return message; }
|
||||||
FString getSourcePath() const { return sourcePath; }
|
String getSourcePath() const { return sourcePath; }
|
||||||
std::vector<FString> getSourceLines() const { return sourceLines; }
|
std::vector<String> getSourceLines() const { return sourceLines; }
|
||||||
|
|
||||||
virtual FString getErrorType() const
|
virtual String getErrorType() const { return String(U"\1"); }
|
||||||
{
|
|
||||||
return FString(u8"AddressableError");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t line, column;
|
size_t line, column;
|
||||||
FString message;
|
String message;
|
||||||
|
|
||||||
FString sourcePath;
|
String sourcePath;
|
||||||
std::vector<FString> sourceLines;
|
std::vector<String> sourceLines;
|
||||||
};
|
};
|
||||||
|
|
||||||
class UnaddressableError : public std::exception
|
class UnaddressableError : public std::exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit UnaddressableError() {}
|
explicit UnaddressableError() {}
|
||||||
explicit UnaddressableError(FString _msg,
|
explicit UnaddressableError(String _msg, std::source_location loc = std::source_location::current()) :
|
||||||
std::source_location loc = std::source_location::current()) :
|
|
||||||
src_loc(loc)
|
src_loc(loc)
|
||||||
{
|
{
|
||||||
message = _msg;
|
message = _msg;
|
||||||
}
|
}
|
||||||
virtual FString toString() const
|
virtual String toString() const
|
||||||
{
|
{
|
||||||
std::string msg = std::format("[UnaddressableError] {} in [{}] {}", this->message.toBasicString(), this->src_loc.file_name(), this->src_loc.function_name());
|
std::string msg = std::format("[UnaddressableError] {} in [{}] {}",
|
||||||
return FString(msg);
|
this->message.toBasicString(),
|
||||||
|
this->src_loc.file_name(),
|
||||||
|
this->src_loc.function_name());
|
||||||
|
return String(msg);
|
||||||
}
|
}
|
||||||
const char *what() const noexcept override
|
const char *what() const noexcept override
|
||||||
{
|
{
|
||||||
@@ -76,15 +84,12 @@ namespace Fig
|
|||||||
return msg.c_str();
|
return msg.c_str();
|
||||||
}
|
}
|
||||||
std::source_location src_loc;
|
std::source_location src_loc;
|
||||||
FString getMessage() const { return message; }
|
String getMessage() const { return message; }
|
||||||
|
|
||||||
virtual FString getErrorType() const
|
virtual String getErrorType() const { return String(U"\1"); }
|
||||||
{
|
|
||||||
return FString(u8"UnaddressableError");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FString message;
|
String message;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SyntaxError : public AddressableError
|
class SyntaxError : public AddressableError
|
||||||
@@ -92,37 +97,36 @@ namespace Fig
|
|||||||
public:
|
public:
|
||||||
using AddressableError::AddressableError;
|
using AddressableError::AddressableError;
|
||||||
|
|
||||||
virtual FString toString() const override
|
virtual String toString() const override
|
||||||
{
|
{
|
||||||
std::string msg = std::format("[SyntaxError] {} in [{}] {}", this->message.toBasicString(), this->src_loc.file_name(), this->src_loc.function_name());
|
std::string msg = std::format("[SyntaxError] {} in [{}] {}",
|
||||||
return FString(msg);
|
this->message.toBasicString(),
|
||||||
|
this->src_loc.file_name(),
|
||||||
|
this->src_loc.function_name());
|
||||||
|
return String(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual FString getErrorType() const override
|
virtual String getErrorType() const override { return String(U"\1"); }
|
||||||
{
|
|
||||||
return FString(u8"SyntaxError");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RuntimeError final : public UnaddressableError
|
class RuntimeError final : public UnaddressableError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using UnaddressableError::UnaddressableError;
|
using UnaddressableError::UnaddressableError;
|
||||||
explicit RuntimeError(FString _msg,
|
explicit RuntimeError(String _msg, std::source_location loc = std::source_location::current()) :
|
||||||
std::source_location loc = std::source_location::current()) :
|
|
||||||
UnaddressableError(_msg, loc)
|
UnaddressableError(_msg, loc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual FString toString() const override
|
virtual String toString() const override
|
||||||
{
|
{
|
||||||
std::string msg = std::format("[RuntimeError] {} in [{}] {}", this->message.toBasicString(), this->src_loc.file_name(), this->src_loc.function_name());
|
std::string msg = std::format("[RuntimeError] {} in [{}] {}",
|
||||||
return FString(msg);
|
this->message.toBasicString(),
|
||||||
|
this->src_loc.file_name(),
|
||||||
|
this->src_loc.function_name());
|
||||||
|
return String(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual FString getErrorType() const override
|
virtual String getErrorType() const override { return String(U"\1"); }
|
||||||
{
|
|
||||||
return FString(u8"RuntimeError");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Fig
|
} // namespace Fig
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
#include <print>
|
#include <print>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
namespace ErrorLog
|
namespace ErrorLog
|
||||||
@@ -87,7 +86,7 @@ namespace Fig
|
|||||||
constexpr const char *OnGray = "\033[48;2;128;128;128m";
|
constexpr const char *OnGray = "\033[48;2;128;128;128m";
|
||||||
}; // namespace TerminalColors
|
}; // namespace TerminalColors
|
||||||
|
|
||||||
inline void coloredPrint(const char *colorCode, FString msg)
|
inline void coloredPrint(const char *colorCode, String msg)
|
||||||
{
|
{
|
||||||
std::print("{}{}{}", colorCode, msg.toBasicString(), TerminalColors::Reset);
|
std::print("{}{}{}", colorCode, msg.toBasicString(), TerminalColors::Reset);
|
||||||
}
|
}
|
||||||
@@ -97,34 +96,44 @@ namespace Fig
|
|||||||
std::print("{}{}{}", colorCode, msg, TerminalColors::Reset);
|
std::print("{}{}{}", colorCode, msg, TerminalColors::Reset);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void logFigErrorInterface(const FString &errorClass, const FString &errorMessage)
|
inline void logFigErrorInterface(const String &errorClass, const String &errorMessage)
|
||||||
{
|
{
|
||||||
namespace TC = TerminalColors;
|
namespace TC = TerminalColors;
|
||||||
coloredPrint(TC::LightWhite, "Uncaught Fig exception:\n");
|
coloredPrint(TC::LightWhite, U"Uncaught Fig exception:\n");
|
||||||
coloredPrint(TC::LightRed, "✖ ");
|
coloredPrint(TC::LightRed, U"✖ ");
|
||||||
coloredPrint(TC::Red, errorClass.toBasicString() + ": ");
|
coloredPrint(TC::Red, errorClass.toBasicString() + ": ");
|
||||||
coloredPrint(TC::Red, errorMessage.toBasicString() + "\n");
|
coloredPrint(TC::Red, errorMessage.toBasicString() + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void logAddressableError(const AddressableError &err)
|
inline void logAddressableError(const AddressableError &err)
|
||||||
{
|
{
|
||||||
const FString &fileName = err.getSourcePath();
|
const String &fileName = err.getSourcePath();
|
||||||
const std::vector<FString> &sourceLines = err.getSourceLines();
|
const std::vector<String> &sourceLines = err.getSourceLines();
|
||||||
|
|
||||||
std::print("\n");
|
std::print("\n");
|
||||||
namespace TC = TerminalColors;
|
namespace TC = TerminalColors;
|
||||||
coloredPrint(TC::LightWhite, "An error occurred! ");
|
coloredPrint(TC::LightWhite, U"An error occurred! ");
|
||||||
coloredPrint(TC::White, std::format("Fig {} ({})[{} {} bit on `{}`]\n",Core::VERSION, Core::COMPILE_TIME, Core::COMPILER, Core::ARCH, Core::PLATFORM));
|
coloredPrint(TC::White,
|
||||||
coloredPrint(TC::LightRed, "✖ ");
|
std::format("Fig {} ({})[{} {} bit on `{}`]\n",
|
||||||
coloredPrint(TC::LightRed, std::format("{}: {}\n", err.getErrorType().toBasicString(), FString(err.getMessage()).toBasicString()));
|
Core::VERSION,
|
||||||
coloredPrint(TC::White, std::format(" at {}:{} in file '{}'\n", err.getLine(), err.getColumn(), fileName.toBasicString()));
|
Core::COMPILE_TIME,
|
||||||
|
Core::COMPILER,
|
||||||
|
Core::ARCH,
|
||||||
|
Core::PLATFORM));
|
||||||
|
coloredPrint(TC::LightRed, U"✖ ");
|
||||||
|
coloredPrint(
|
||||||
|
TC::LightRed,
|
||||||
|
std::format("{}: {}\n", err.getErrorType().toBasicString(), String(err.getMessage()).toBasicString()));
|
||||||
|
coloredPrint(
|
||||||
|
TC::White,
|
||||||
|
std::format(" at {}:{} in file '{}'\n", err.getLine(), err.getColumn(), fileName.toBasicString()));
|
||||||
|
|
||||||
FString lineContent;
|
String lineContent;
|
||||||
FString pointerLine;
|
String pointerLine;
|
||||||
|
|
||||||
if (fileName != u8"<stdin>")
|
if (fileName != U"\1")
|
||||||
{
|
{
|
||||||
lineContent = ((int64_t(err.getLine()) - int64_t(1)) >= 0 ? sourceLines[err.getLine() - 1] : u8"<No Source>");
|
lineContent = ((int64_t(err.getLine()) - int64_t(1)) >= 0 ? sourceLines[err.getLine() - 1] : U"\1");
|
||||||
for (size_t i = 1; i < err.getColumn(); ++i)
|
for (size_t i = 1; i < err.getColumn(); ++i)
|
||||||
{
|
{
|
||||||
if (lineContent[i - 1] == U'\t') { pointerLine += U'\t'; }
|
if (lineContent[i - 1] == U'\t') { pointerLine += U'\t'; }
|
||||||
@@ -135,7 +144,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
pointerLine += U'^';
|
pointerLine += U'^';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lineContent = fileName;
|
lineContent = fileName;
|
||||||
}
|
}
|
||||||
@@ -143,18 +152,34 @@ namespace Fig
|
|||||||
coloredPrint(TC::LightBlue, std::format(" {}\n", lineContent.toBasicString()));
|
coloredPrint(TC::LightBlue, std::format(" {}\n", lineContent.toBasicString()));
|
||||||
|
|
||||||
coloredPrint(TC::LightGreen, std::format(" {}\n", pointerLine.toBasicString()));
|
coloredPrint(TC::LightGreen, std::format(" {}\n", pointerLine.toBasicString()));
|
||||||
coloredPrint(TC::DarkGray, std::format("🔧 in function '{}' ({}:{})\n", err.src_loc.function_name(), err.src_loc.file_name(), err.src_loc.line()));
|
coloredPrint(TC::DarkGray,
|
||||||
|
std::format("🔧 in function '{}' ({}:{})\n",
|
||||||
|
err.src_loc.function_name(),
|
||||||
|
err.src_loc.file_name(),
|
||||||
|
err.src_loc.line()));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void logUnaddressableError(const UnaddressableError &err)
|
inline void logUnaddressableError(const UnaddressableError &err)
|
||||||
{
|
{
|
||||||
std::print("\n");
|
std::print("\n");
|
||||||
namespace TC = TerminalColors;
|
namespace TC = TerminalColors;
|
||||||
coloredPrint(TC::LightWhite, "An error occurred! ");
|
coloredPrint(TC::LightWhite, U"An error occurred! ");
|
||||||
coloredPrint(TC::White, std::format("Fig {} ({})[{} {} bit on `{}`]\n", Core::VERSION, Core::COMPILE_TIME, Core::COMPILER, Core::ARCH, Core::PLATFORM));
|
coloredPrint(TC::White,
|
||||||
coloredPrint(TC::DarkRed, "✖");
|
std::format("Fig {} ({})[{} {} bit on `{}`]\n",
|
||||||
coloredPrint(TC::Red, std::format("{}: {}\n", err.getErrorType().toBasicString(), FString(err.getMessage()).toBasicString()));
|
Core::VERSION,
|
||||||
coloredPrint(TC::DarkGray, std::format("🔧 in function '{}' ({}:{})", err.src_loc.function_name(), err.src_loc.file_name(), err.src_loc.line()));
|
Core::COMPILE_TIME,
|
||||||
|
Core::COMPILER,
|
||||||
|
Core::ARCH,
|
||||||
|
Core::PLATFORM));
|
||||||
|
coloredPrint(TC::DarkRed, U"✖");
|
||||||
|
coloredPrint(
|
||||||
|
TC::Red,
|
||||||
|
std::format("{}: {}\n", err.getErrorType().toBasicString(), String(err.getMessage()).toBasicString()));
|
||||||
|
coloredPrint(TC::DarkGray,
|
||||||
|
std::format("🔧 in function '{}' ({}:{})",
|
||||||
|
err.src_loc.function_name(),
|
||||||
|
err.src_loc.file_name(),
|
||||||
|
err.src_loc.line()));
|
||||||
}
|
}
|
||||||
}; // namespace ErrorLog
|
}; // namespace ErrorLog
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <Evaluator/Value/interface.hpp>
|
#include <Evaluator/Value/interface.hpp>
|
||||||
#include <Evaluator/Value/Type.hpp>
|
#include <Evaluator/Value/Type.hpp>
|
||||||
#include <Evaluator/Context/context_forward.hpp>
|
#include <Evaluator/Context/context_forward.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Evaluator/Value/value.hpp>
|
#include <Evaluator/Value/value.hpp>
|
||||||
#include <Evaluator/Value/VariableSlot.hpp>
|
#include <Evaluator/Value/VariableSlot.hpp>
|
||||||
#include <Evaluator/Core/ExprResult.hpp>
|
#include <Evaluator/Core/ExprResult.hpp>
|
||||||
@@ -26,7 +26,7 @@ namespace Fig
|
|||||||
TypeInfo interfaceType;
|
TypeInfo interfaceType;
|
||||||
TypeInfo structType;
|
TypeInfo structType;
|
||||||
|
|
||||||
std::unordered_map<FString, Function> implMethods;
|
std::unordered_map<String, Function> implMethods;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OperationRecord
|
struct OperationRecord
|
||||||
@@ -49,11 +49,11 @@ namespace Fig
|
|||||||
class Context : public std::enable_shared_from_this<Context>
|
class Context : public std::enable_shared_from_this<Context>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
FString scopeName;
|
String scopeName;
|
||||||
std::unordered_map<FString, std::shared_ptr<VariableSlot>> variables;
|
std::unordered_map<String, std::shared_ptr<VariableSlot>> variables;
|
||||||
|
|
||||||
// std::unordered_map<std::size_t, Function> functions;
|
// 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>
|
// implRegistry <Struct, ordered list of ImplRecord>
|
||||||
std::unordered_map<TypeInfo, std::vector<ImplRecord>, TypeInfoHash> implRegistry;
|
std::unordered_map<TypeInfo, std::vector<ImplRecord>, TypeInfoHash> implRegistry;
|
||||||
@@ -63,13 +63,13 @@ namespace Fig
|
|||||||
ContextPtr parent;
|
ContextPtr parent;
|
||||||
|
|
||||||
Context(const Context &) = default;
|
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 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)
|
void merge(const Context &c)
|
||||||
{
|
{
|
||||||
@@ -94,58 +94,58 @@ namespace Fig
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VariableSlot> get(const FString &name)
|
std::shared_ptr<VariableSlot> get(const String &name)
|
||||||
{
|
{
|
||||||
auto it = variables.find(name);
|
auto it = variables.find(name);
|
||||||
if (it != variables.end()) return it->second;
|
if (it != variables.end()) return it->second;
|
||||||
if (parent) return parent->get(name);
|
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; }
|
if (variables.contains(name)) { return variables[name]->am; }
|
||||||
else if (parent != nullptr) { return parent->getAccessModifier(name); }
|
else if (parent != nullptr) { return parent->getAccessModifier(name); }
|
||||||
else
|
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
|
AccessModifier am = getAccessModifier(name); // may throw
|
||||||
return !isAccessConst(am);
|
return !isAccessConst(am);
|
||||||
}
|
}
|
||||||
bool isVariablePublic(const FString &name)
|
bool isVariablePublic(const String &name)
|
||||||
{
|
{
|
||||||
AccessModifier am = getAccessModifier(name); // may throw
|
AccessModifier am = getAccessModifier(name); // may throw
|
||||||
return isAccessPublic(am);
|
return isAccessPublic(am);
|
||||||
}
|
}
|
||||||
void set(const FString &name, ObjectPtr value)
|
void set(const String &name, ObjectPtr value)
|
||||||
{
|
{
|
||||||
if (variables.contains(name))
|
if (variables.contains(name))
|
||||||
{
|
{
|
||||||
if (!isVariableMutable(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;
|
variables[name]->value = value;
|
||||||
}
|
}
|
||||||
else if (parent != nullptr) { parent->set(name, value); }
|
else if (parent != nullptr) { parent->set(name, value); }
|
||||||
else
|
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; }
|
if (variables.contains(name)) { variables[name]->value = value; }
|
||||||
else if (parent != nullptr) { parent->_update(name, value); }
|
else if (parent != nullptr) { parent->_update(name, value); }
|
||||||
else
|
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,
|
const TypeInfo &ti,
|
||||||
AccessModifier am,
|
AccessModifier am,
|
||||||
const ObjectPtr &value = Object::getNullInstance())
|
const ObjectPtr &value = Object::getNullInstance())
|
||||||
@@ -153,7 +153,7 @@ namespace Fig
|
|||||||
if (containsInThisScope(name))
|
if (containsInThisScope(name))
|
||||||
{
|
{
|
||||||
throw RuntimeError(
|
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);
|
variables[name] = std::make_shared<VariableSlot>(name, value, ti, am);
|
||||||
// if (ti == ValueType::StructType)
|
// if (ti == ValueType::StructType)
|
||||||
@@ -163,17 +163,17 @@ namespace Fig
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
void
|
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))
|
if (containsInThisScope(name))
|
||||||
{
|
{
|
||||||
throw RuntimeError(
|
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);
|
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)
|
for (auto &[name, slot] : variables)
|
||||||
{
|
{
|
||||||
@@ -185,7 +185,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
// std::optional<FString> getStructName(std::size_t id)
|
// std::optional<String> getStructName(std::size_t id)
|
||||||
// {
|
// {
|
||||||
// auto it = structTypeNames.find(id);
|
// auto it = structTypeNames.find(id);
|
||||||
// if (it != structTypeNames.end())
|
// if (it != structTypeNames.end())
|
||||||
@@ -201,21 +201,21 @@ namespace Fig
|
|||||||
// return std::nullopt;
|
// return std::nullopt;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
bool contains(const FString &name)
|
bool contains(const String &name)
|
||||||
{
|
{
|
||||||
if (variables.contains(name)) { return true; }
|
if (variables.contains(name)) { return true; }
|
||||||
else if (parent != nullptr) { return parent->contains(name); }
|
else if (parent != nullptr) { return parent->contains(name); }
|
||||||
return false;
|
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()
|
bool isInFunctionContext()
|
||||||
{
|
{
|
||||||
ContextPtr ctx = shared_from_this();
|
ContextPtr ctx = shared_from_this();
|
||||||
while (ctx)
|
while (ctx)
|
||||||
{
|
{
|
||||||
if (ctx->getScopeName().find(u8"<Function ") == 0) { return true; }
|
if (ctx->getScopeName().find(U"\1") == 0) { return true; }
|
||||||
ctx = ctx->parent;
|
ctx = ctx->parent;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -225,10 +225,7 @@ namespace Fig
|
|||||||
ContextPtr ctx = shared_from_this();
|
ContextPtr ctx = shared_from_this();
|
||||||
while (ctx)
|
while (ctx)
|
||||||
{
|
{
|
||||||
if (ctx->getScopeName().find(u8"<While ") == 0 or ctx->getScopeName().find(u8"<For ") == 0)
|
if (ctx->getScopeName().find(U"\1") == 0 or ctx->getScopeName().find(U"\1") == 0) { return true; }
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
ctx = ctx->parent;
|
ctx = ctx->parent;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -282,7 +279,7 @@ namespace Fig
|
|||||||
list.push_back(record); // order is the level
|
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);
|
auto it = implRegistry.find(structType);
|
||||||
if (it != implRegistry.end())
|
if (it != implRegistry.end())
|
||||||
@@ -296,7 +293,7 @@ namespace Fig
|
|||||||
return parent && parent->hasMethodImplemented(structType, functionName);
|
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);
|
auto it = implRegistry.find(structType);
|
||||||
if (it == implRegistry.end()) return false;
|
if (it == implRegistry.end()) return false;
|
||||||
@@ -325,7 +322,7 @@ namespace Fig
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast::InterfaceMethod getDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName)
|
Ast::InterfaceMethod getDefaultImplementedMethod(const TypeInfo &structType, const String &functionName)
|
||||||
{
|
{
|
||||||
// O(N²)
|
// O(N²)
|
||||||
// SLOW
|
// SLOW
|
||||||
@@ -366,7 +363,7 @@ namespace Fig
|
|||||||
assert(false);
|
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);
|
auto it = implRegistry.find(structType);
|
||||||
if (it != implRegistry.end())
|
if (it != implRegistry.end())
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
case AstType::ValueExpr: {
|
case AstType::ValueExpr: {
|
||||||
auto val = std::static_pointer_cast<Ast::ValueExprAst>(exp);
|
auto val = std::static_pointer_cast<Ast::ValueExprAst>(exp);
|
||||||
|
|
||||||
return val->val;
|
return val->val;
|
||||||
}
|
}
|
||||||
case AstType::VarExpr: {
|
case AstType::VarExpr: {
|
||||||
@@ -22,17 +22,17 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
case AstType::BinaryExpr: {
|
case AstType::BinaryExpr: {
|
||||||
auto bin = std::static_pointer_cast<Ast::BinaryExprAst>(exp);
|
auto bin = std::static_pointer_cast<Ast::BinaryExprAst>(exp);
|
||||||
|
|
||||||
return evalBinary(bin, ctx);
|
return evalBinary(bin, ctx);
|
||||||
}
|
}
|
||||||
case AstType::UnaryExpr: {
|
case AstType::UnaryExpr: {
|
||||||
auto un = std::static_pointer_cast<Ast::UnaryExprAst>(exp);
|
auto un = std::static_pointer_cast<Ast::UnaryExprAst>(exp);
|
||||||
|
|
||||||
return evalUnary(un, ctx);
|
return evalUnary(un, ctx);
|
||||||
}
|
}
|
||||||
case AstType::TernaryExpr: {
|
case AstType::TernaryExpr: {
|
||||||
auto te = std::static_pointer_cast<Ast::TernaryExprAst>(exp);
|
auto te = std::static_pointer_cast<Ast::TernaryExprAst>(exp);
|
||||||
|
|
||||||
return evalTernary(te, ctx);
|
return evalTernary(te, ctx);
|
||||||
}
|
}
|
||||||
case AstType::MemberExpr:
|
case AstType::MemberExpr:
|
||||||
@@ -44,13 +44,11 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
case AstType::FunctionLiteralExpr: {
|
case AstType::FunctionLiteralExpr: {
|
||||||
auto fnLiteral = std::static_pointer_cast<Ast::FunctionLiteralExprAst>(exp);
|
auto fnLiteral = std::static_pointer_cast<Ast::FunctionLiteralExprAst>(exp);
|
||||||
|
|
||||||
|
|
||||||
Ast::BlockStatement body = nullptr;
|
Ast::BlockStatement body = nullptr;
|
||||||
if (fnLiteral->isExprMode())
|
if (fnLiteral->isExprMode())
|
||||||
{
|
{
|
||||||
Ast::Expression exprBody = fnLiteral->getExprBody();
|
Ast::Expression exprBody = fnLiteral->getExprBody();
|
||||||
|
|
||||||
|
|
||||||
const Ast::AstAddressInfo &aai = exprBody->getAAI();
|
const Ast::AstAddressInfo &aai = exprBody->getAAI();
|
||||||
Ast::Return st = std::make_shared<Ast::ReturnSt>(exprBody);
|
Ast::Return st = std::make_shared<Ast::ReturnSt>(exprBody);
|
||||||
@@ -63,9 +61,8 @@ namespace Fig
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
body = fnLiteral->getBlockBody();
|
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
|
pass the ctx(fnLiteral eval context) as closure context
|
||||||
*/
|
*/
|
||||||
@@ -74,13 +71,12 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
case AstType::InitExpr: {
|
case AstType::InitExpr: {
|
||||||
auto initExpr = std::static_pointer_cast<Ast::InitExprAst>(exp);
|
auto initExpr = std::static_pointer_cast<Ast::InitExprAst>(exp);
|
||||||
|
|
||||||
return evalInitExpr(initExpr, ctx);
|
return evalInitExpr(initExpr, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
case AstType::ListExpr: {
|
case AstType::ListExpr: {
|
||||||
auto lstExpr = std::static_pointer_cast<Ast::ListExprAst>(exp);
|
auto lstExpr = std::static_pointer_cast<Ast::ListExprAst>(exp);
|
||||||
|
|
||||||
|
|
||||||
List list;
|
List list;
|
||||||
for (auto &exp : lstExpr->val) { list.push_back(check_unwrap(eval(exp, ctx))); }
|
for (auto &exp : lstExpr->val) { list.push_back(check_unwrap(eval(exp, ctx))); }
|
||||||
@@ -89,19 +85,19 @@ namespace Fig
|
|||||||
|
|
||||||
case AstType::MapExpr: {
|
case AstType::MapExpr: {
|
||||||
auto mapExpr = std::static_pointer_cast<Ast::MapExprAst>(exp);
|
auto mapExpr = std::static_pointer_cast<Ast::MapExprAst>(exp);
|
||||||
|
|
||||||
|
|
||||||
Map map;
|
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));
|
map[check_unwrap(eval(key, ctx))] = check_unwrap(eval(value, ctx));
|
||||||
}
|
}
|
||||||
return std::make_shared<Object>(std::move(map));
|
return std::make_shared<Object>(std::move(map));
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
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
|
return Object::getNullInstance(); // ignore warning
|
||||||
}
|
}
|
||||||
};
|
}; // namespace Fig
|
||||||
@@ -86,7 +86,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
ValueType::IntClass lv = lhs->as<ValueType::IntClass>();
|
ValueType::IntClass lv = lhs->as<ValueType::IntClass>();
|
||||||
ValueType::IntClass rv = rhs->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 result = lv / rv;
|
||||||
ValueType::IntClass r = lv % rv;
|
ValueType::IntClass r = lv % rv;
|
||||||
if (r != 0 && ((lv < 0) != (rv < 0))) { result -= 1; }
|
if (r != 0 && ((lv < 0) != (rv < 0))) { result -= 1; }
|
||||||
@@ -139,7 +139,7 @@ namespace Fig
|
|||||||
return Object::getFalseInstance();
|
return Object::getFalseInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw EvaluatorError(u8"TypeError",
|
throw EvaluatorError(U"TypeError",
|
||||||
std::format("Unsupported operator `is` for '{}' && '{}'",
|
std::format("Unsupported operator `is` for '{}' && '{}'",
|
||||||
prettyType(lhs).toBasicString(),
|
prettyType(lhs).toBasicString(),
|
||||||
prettyType(rhs).toBasicString()),
|
prettyType(rhs).toBasicString()),
|
||||||
@@ -155,7 +155,7 @@ namespace Fig
|
|||||||
if (!rhs->is<StructType>())
|
if (!rhs->is<StructType>())
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"OperatorError",
|
U"OperatorError",
|
||||||
std::format("Operator `as` requires right hand side operand a struct type, but got '{}'",
|
std::format("Operator `as` requires right hand side operand a struct type, but got '{}'",
|
||||||
prettyType(rhs).toBasicString()),
|
prettyType(rhs).toBasicString()),
|
||||||
bin->rexp);
|
bin->rexp);
|
||||||
@@ -183,7 +183,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else if (sourceType == ValueType::String)
|
else if (sourceType == ValueType::String)
|
||||||
{
|
{
|
||||||
const FString &str = lhs->as<ValueType::StringClass>();
|
const String &str = lhs->as<ValueType::StringClass>();
|
||||||
if (targetType == ValueType::Int)
|
if (targetType == ValueType::Int)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -194,10 +194,10 @@ namespace Fig
|
|||||||
catch (std::exception &e)
|
catch (std::exception &e)
|
||||||
{
|
{
|
||||||
return ExprResult::error(
|
return ExprResult::error(
|
||||||
genTypeError(FString(std::format("Cannot cast type `{}` to `{}`, bad int string {}",
|
genTypeError(String(std::format("Cannot cast type `{}` to `{}`, bad int string {}",
|
||||||
prettyType(lhs).toBasicString(),
|
prettyType(lhs).toBasicString(),
|
||||||
prettyType(rhs).toBasicString(),
|
prettyType(rhs).toBasicString(),
|
||||||
str.toBasicString())),
|
str.toBasicString())),
|
||||||
bin->rexp,
|
bin->rexp,
|
||||||
ctx));
|
ctx));
|
||||||
}
|
}
|
||||||
@@ -211,22 +211,22 @@ namespace Fig
|
|||||||
catch (std::exception &e)
|
catch (std::exception &e)
|
||||||
{
|
{
|
||||||
return ExprResult::error(genTypeError(
|
return ExprResult::error(genTypeError(
|
||||||
FString(std::format("Cannot cast type `{}` to `{}`, bad double string {}",
|
String(std::format("Cannot cast type `{}` to `{}`, bad double string {}",
|
||||||
prettyType(lhs).toBasicString(),
|
prettyType(lhs).toBasicString(),
|
||||||
prettyType(rhs).toBasicString(),
|
prettyType(rhs).toBasicString(),
|
||||||
str.toBasicString())),
|
str.toBasicString())),
|
||||||
bin->rexp,
|
bin->rexp,
|
||||||
ctx));
|
ctx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (targetType == ValueType::Bool)
|
if (targetType == ValueType::Bool)
|
||||||
{
|
{
|
||||||
if (str == u8"true") { return Object::getTrueInstance(); }
|
if (str == U"true") { return Object::getTrueInstance(); }
|
||||||
else if (str == u8"false") { return Object::getFalseInstance(); }
|
else if (str == U"false") { return Object::getFalseInstance(); }
|
||||||
return ExprResult::error(
|
return ExprResult::error(
|
||||||
genTypeError(FString(std::format("Cannot cast type `{}` to `{}`, bad bool string {}",
|
genTypeError(String(std::format("Cannot cast type `{}` to `{}`, bad bool string {}",
|
||||||
prettyType(lhs).toBasicString(),
|
prettyType(lhs).toBasicString(),
|
||||||
prettyType(rhs).toBasicString(),
|
prettyType(rhs).toBasicString(),
|
||||||
str.toBasicString())),
|
str.toBasicString())),
|
||||||
bin->rexp,
|
bin->rexp,
|
||||||
ctx));
|
ctx));
|
||||||
@@ -236,17 +236,19 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
if (targetType == ValueType::Int)
|
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)
|
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 `{}`",
|
return ExprResult::error(genTypeError(String(std::format("Cannot cast type `{}` to `{}`",
|
||||||
prettyType(lhs).toBasicString(),
|
prettyType(lhs).toBasicString(),
|
||||||
prettyType(rhs).toBasicString())),
|
prettyType(rhs).toBasicString())),
|
||||||
bin->rexp,
|
bin->rexp,
|
||||||
ctx));
|
ctx));
|
||||||
});
|
});
|
||||||
@@ -429,7 +431,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw EvaluatorError(u8"UnsupportedOp",
|
throw EvaluatorError(U"UnsupportedOp",
|
||||||
std::format("Unsupport operator '{}' for binary", magic_enum::enum_name(op)),
|
std::format("Unsupport operator '{}' for binary", magic_enum::enum_name(op)),
|
||||||
bin);
|
bin);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,11 @@
|
|||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
ExprResult Evaluator::executeFunction(const Function &fn,
|
ExprResult Evaluator::executeFunction(const Function &fn,
|
||||||
const Ast::FunctionCallArgs &args,
|
const Ast::FunctionCallArgs &args,
|
||||||
ContextPtr fnCtx) // new context for fn, already filled paras
|
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 || fn.type == Function::MemberType)
|
||||||
{
|
{
|
||||||
if (fn.type == Function::Builtin) { return fn.builtin(args.argv); }
|
if (fn.type == Function::Builtin) { return fn.builtin(args.argv); }
|
||||||
@@ -27,14 +27,8 @@ namespace Fig
|
|||||||
for (const auto &stmt : fn.body->stmts)
|
for (const auto &stmt : fn.body->stmts)
|
||||||
{
|
{
|
||||||
StatementResult sr = evalStatement(stmt, fnCtx);
|
StatementResult sr = evalStatement(stmt, fnCtx);
|
||||||
if (sr.isError())
|
if (sr.isError()) { handle_error(sr, stmt, fnCtx); }
|
||||||
{
|
if (!sr.isNormal()) { return sr.result; }
|
||||||
handle_error(sr, stmt, fnCtx);
|
|
||||||
}
|
|
||||||
if (!sr.isNormal())
|
|
||||||
{
|
|
||||||
return sr.result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Object::getNullInstance();
|
return Object::getNullInstance();
|
||||||
}
|
}
|
||||||
@@ -43,14 +37,14 @@ namespace Fig
|
|||||||
RvObject fnObj = check_unwrap(eval(call->callee, ctx));
|
RvObject fnObj = check_unwrap(eval(call->callee, ctx));
|
||||||
if (fnObj->getTypeInfo() != ValueType::Function)
|
if (fnObj->getTypeInfo() != ValueType::Function)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"ObjectNotCallable",
|
throw EvaluatorError(U"ObjectNotCallable",
|
||||||
std::format("Object `{}` isn't callable", fnObj->toString().toBasicString()),
|
std::format("Object `{}` isn't callable", fnObj->toString().toBasicString()),
|
||||||
call->callee);
|
call->callee);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Function &fn = fnObj->as<Function>();
|
const Function &fn = fnObj->as<Function>();
|
||||||
|
|
||||||
const FString &fnName = fn.name;
|
const String &fnName = fn.name;
|
||||||
const Ast::FunctionArguments &fnArgs = call->arg;
|
const Ast::FunctionArguments &fnArgs = call->arg;
|
||||||
|
|
||||||
Ast::FunctionCallArgs evaluatedArgs;
|
Ast::FunctionCallArgs evaluatedArgs;
|
||||||
@@ -59,7 +53,7 @@ namespace Fig
|
|||||||
for (const auto &argExpr : fnArgs.argv) { evaluatedArgs.argv.push_back(check_unwrap(eval(argExpr, ctx))); }
|
for (const auto &argExpr : fnArgs.argv) { evaluatedArgs.argv.push_back(check_unwrap(eval(argExpr, ctx))); }
|
||||||
if (fn.builtinParamCount != -1 && fn.builtinParamCount != evaluatedArgs.getLength())
|
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",
|
std::format("Builtin function '{}' expects {} arguments, but {} were provided",
|
||||||
fnName.toBasicString(),
|
fnName.toBasicString(),
|
||||||
fn.builtinParamCount,
|
fn.builtinParamCount,
|
||||||
@@ -73,7 +67,7 @@ namespace Fig
|
|||||||
Ast::FunctionParameters fnParas = fn.paras;
|
Ast::FunctionParameters fnParas = fn.paras;
|
||||||
|
|
||||||
// create new context for function call
|
// 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);
|
fn.closureContext);
|
||||||
|
|
||||||
if (fnParas.variadic)
|
if (fnParas.variadic)
|
||||||
@@ -84,24 +78,25 @@ namespace Fig
|
|||||||
NormalFilling: {
|
NormalFilling: {
|
||||||
if (fnArgs.getLength() < fnParas.posParas.size() || fnArgs.getLength() > fnParas.size())
|
if (fnArgs.getLength() < fnParas.posParas.size() || fnArgs.getLength() > fnParas.size())
|
||||||
{
|
{
|
||||||
throw RuntimeError(FString(std::format("Function '{}' expects {} to {} arguments, but {} were provided",
|
throw RuntimeError(String(std::format("Function '{}' expects {} to {} arguments, but {} were provided",
|
||||||
fnName.toBasicString(),
|
fnName.toBasicString(),
|
||||||
fnParas.posParas.size(),
|
fnParas.posParas.size(),
|
||||||
fnParas.size(),
|
fnParas.size(),
|
||||||
fnArgs.getLength())));
|
fnArgs.getLength())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// positional parameters type check
|
// positional parameters type check
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < fnParas.posParas.size(); 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
|
const TypeInfo &expectedType = actualType(check_unwrap(
|
||||||
// with the name, use it, else throw
|
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));
|
ObjectPtr argVal = check_unwrap(eval(fnArgs.argv[i], ctx));
|
||||||
TypeInfo actualType = argVal->getTypeInfo();
|
TypeInfo actualType = argVal->getTypeInfo();
|
||||||
if (!isTypeMatch(expectedType, argVal, fn.closureContext))
|
if (!isTypeMatch(expectedType, argVal, fn.closureContext))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"ArgumentTypeMismatchError",
|
throw EvaluatorError(U"ArgumentTypeMismatchError",
|
||||||
std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'",
|
std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'",
|
||||||
fnName.toBasicString(),
|
fnName.toBasicString(),
|
||||||
fnParas.posParas[i].first.toBasicString(),
|
fnParas.posParas[i].first.toBasicString(),
|
||||||
@@ -122,7 +117,7 @@ namespace Fig
|
|||||||
if (!isTypeMatch(expectedType, defaultVal, fn.closureContext))
|
if (!isTypeMatch(expectedType, defaultVal, fn.closureContext))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"DefaultParameterTypeError",
|
U"DefaultParameterTypeError",
|
||||||
std::format(
|
std::format(
|
||||||
"In function '{}', default parameter '{}' has type '{}', which does not match the expected type '{}'",
|
"In function '{}', default parameter '{}' has type '{}', which does not match the expected type '{}'",
|
||||||
fnName.toBasicString(),
|
fnName.toBasicString(),
|
||||||
@@ -136,7 +131,7 @@ namespace Fig
|
|||||||
TypeInfo actualType = argVal->getTypeInfo();
|
TypeInfo actualType = argVal->getTypeInfo();
|
||||||
if (!isTypeMatch(expectedType, argVal, fn.closureContext))
|
if (!isTypeMatch(expectedType, argVal, fn.closureContext))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"ArgumentTypeMismatchError",
|
throw EvaluatorError(U"ArgumentTypeMismatchError",
|
||||||
std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'",
|
std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'",
|
||||||
fnName.toBasicString(),
|
fnName.toBasicString(),
|
||||||
fnParas.defParas[defParamIndex].first.toBasicString(),
|
fnParas.defParas[defParamIndex].first.toBasicString(),
|
||||||
@@ -157,7 +152,7 @@ namespace Fig
|
|||||||
// define parameters in new context
|
// define parameters in new context
|
||||||
for (size_t j = 0; j < fnParas.size(); j++)
|
for (size_t j = 0; j < fnParas.size(); j++)
|
||||||
{
|
{
|
||||||
FString paramName;
|
String paramName;
|
||||||
TypeInfo paramType;
|
TypeInfo paramType;
|
||||||
if (j < fnParas.posParas.size())
|
if (j < fnParas.posParas.size())
|
||||||
{
|
{
|
||||||
@@ -193,7 +188,7 @@ namespace Fig
|
|||||||
|
|
||||||
if (!isTypeMatch(fn.retType, retVal, ctx))
|
if (!isTypeMatch(fn.retType, retVal, ctx))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"ReturnTypeMismatchError",
|
throw EvaluatorError(U"ReturnTypeMismatchError",
|
||||||
std::format("Function '{}' expects return type '{}', but got type '{}'",
|
std::format("Function '{}' expects return type '{}', but got type '{}'",
|
||||||
fnName.toBasicString(),
|
fnName.toBasicString(),
|
||||||
fn.retType.toString().toBasicString(),
|
fn.retType.toString().toBasicString(),
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
LvObject structeLv = check_unwrap_lv(evalLv(initExpr->structe, ctx));
|
LvObject structeLv = check_unwrap_lv(evalLv(initExpr->structe, ctx));
|
||||||
ObjectPtr structTypeVal = structeLv.get();
|
ObjectPtr structTypeVal = structeLv.get();
|
||||||
const FString &structName = structeLv.name();
|
const String &structName = structeLv.name();
|
||||||
if (!structTypeVal->is<StructType>())
|
if (!structTypeVal->is<StructType>())
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"NotAStructTypeError",
|
throw EvaluatorError(U"NotAStructTypeError",
|
||||||
std::format("'{}' is not a structure type", structName.toBasicString()),
|
std::format("'{}' is not a structure type", structName.toBasicString()),
|
||||||
initExpr);
|
initExpr);
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ namespace Fig
|
|||||||
|
|
||||||
if (argSize > 1)
|
if (argSize > 1)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"StructInitArgumentMismatchError",
|
throw EvaluatorError(U"StructInitArgumentMismatchError",
|
||||||
std::format("Builtin class `{}` expects 0 or 1 argument, but {} were provided",
|
std::format("Builtin class `{}` expects 0 or 1 argument, but {} were provided",
|
||||||
type.toString().toBasicString(),
|
type.toString().toBasicString(),
|
||||||
argSize),
|
argSize),
|
||||||
@@ -40,7 +40,7 @@ namespace Fig
|
|||||||
if (type == ValueType::Any || type == ValueType::Null || type == ValueType::Function)
|
if (type == ValueType::Any || type == ValueType::Null || type == ValueType::Function)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"BuiltinNotConstructibleError",
|
U"BuiltinNotConstructibleError",
|
||||||
std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()),
|
std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()),
|
||||||
initExpr);
|
initExpr);
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ namespace Fig
|
|||||||
ObjectPtr val = check_unwrap(eval(args[0].second, ctx));
|
ObjectPtr val = check_unwrap(eval(args[0].second, ctx));
|
||||||
|
|
||||||
auto err = [&](const char *msg) {
|
auto err = [&](const char *msg) {
|
||||||
throw EvaluatorError(u8"BuiltinInitTypeMismatchError",
|
throw EvaluatorError(U"BuiltinInitTypeMismatchError",
|
||||||
std::format("Builtin `{}` constructor {}", type.toString().toBasicString(), msg),
|
std::format("Builtin `{}` constructor {}", type.toString().toBasicString(), msg),
|
||||||
initExpr);
|
initExpr);
|
||||||
};
|
};
|
||||||
@@ -121,7 +121,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"BuiltinNotConstructibleError",
|
U"BuiltinNotConstructibleError",
|
||||||
std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()),
|
std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()),
|
||||||
initExpr);
|
initExpr);
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ namespace Fig
|
|||||||
size_t got = initExpr->args.size();
|
size_t got = initExpr->args.size();
|
||||||
if (got > maxArgs || got < minArgs)
|
if (got > maxArgs || got < minArgs)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"StructInitArgumentMismatchError",
|
throw EvaluatorError(U"StructInitArgumentMismatchError",
|
||||||
std::format("Structure '{}' expects {} to {} fields, but {} were provided",
|
std::format("Structure '{}' expects {} to {} fields, but {} were provided",
|
||||||
structName.toBasicString(),
|
structName.toBasicString(),
|
||||||
minArgs,
|
minArgs,
|
||||||
@@ -149,9 +149,9 @@ namespace Fig
|
|||||||
initExpr);
|
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)
|
for (const auto &[argName, argExpr] : initExpr->args)
|
||||||
{
|
{
|
||||||
evaluatedArgs.push_back({argName, check_unwrap(eval(argExpr, ctx))});
|
evaluatedArgs.push_back({argName, check_unwrap(eval(argExpr, ctx))});
|
||||||
@@ -159,8 +159,8 @@ namespace Fig
|
|||||||
return ExprResult::normal(Object::getNullInstance());
|
return ExprResult::normal(Object::getNullInstance());
|
||||||
};
|
};
|
||||||
|
|
||||||
ContextPtr instanceCtx =
|
ContextPtr instanceCtx = std::make_shared<Context>(
|
||||||
std::make_shared<Context>(FString(std::format("<StructInstance {}>", structName.toBasicString())), defContext);
|
String(std::format("<StructInstance {}>", structName.toBasicString())), defContext);
|
||||||
/*
|
/*
|
||||||
3 ways of calling constructor
|
3 ways of calling constructor
|
||||||
.1 Person {"Fig", 1, "IDK"};
|
.1 Person {"Fig", 1, "IDK"};
|
||||||
@@ -176,7 +176,7 @@ namespace Fig
|
|||||||
for (size_t i = 0; i < maxArgs; ++i)
|
for (size_t i = 0; i < maxArgs; ++i)
|
||||||
{
|
{
|
||||||
const Field &field = structT.fields[i];
|
const Field &field = structT.fields[i];
|
||||||
const FString &fieldName = field.name;
|
const String &fieldName = field.name;
|
||||||
const TypeInfo &expectedType = field.type;
|
const TypeInfo &expectedType = field.type;
|
||||||
if (i >= evaluatedArgs.size())
|
if (i >= evaluatedArgs.size())
|
||||||
{
|
{
|
||||||
@@ -191,7 +191,7 @@ namespace Fig
|
|||||||
if (!isTypeMatch(expectedType, defaultVal, ctx))
|
if (!isTypeMatch(expectedType, defaultVal, ctx))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"StructFieldTypeMismatchError",
|
U"StructFieldTypeMismatchError",
|
||||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||||
structName.toBasicString(),
|
structName.toBasicString(),
|
||||||
fieldName.toBasicString(),
|
fieldName.toBasicString(),
|
||||||
@@ -208,7 +208,7 @@ namespace Fig
|
|||||||
if (!isTypeMatch(expectedType, argVal, ctx))
|
if (!isTypeMatch(expectedType, argVal, ctx))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"StructFieldTypeMismatchError",
|
U"StructFieldTypeMismatchError",
|
||||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||||
structName.toBasicString(),
|
structName.toBasicString(),
|
||||||
fieldName.toBasicString(),
|
fieldName.toBasicString(),
|
||||||
@@ -227,10 +227,10 @@ namespace Fig
|
|||||||
for (size_t i = 0; i < maxArgs; ++i)
|
for (size_t i = 0; i < maxArgs; ++i)
|
||||||
{
|
{
|
||||||
const Field &field = structT.fields[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))
|
if (instanceCtx->containsInThisScope(fieldName))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"StructFieldRedeclarationError",
|
throw EvaluatorError(U"StructFieldRedeclarationError",
|
||||||
std::format("Field '{}' already initialized in structure '{}'",
|
std::format("Field '{}' already initialized in structure '{}'",
|
||||||
fieldName.toBasicString(),
|
fieldName.toBasicString(),
|
||||||
structName.toBasicString()),
|
structName.toBasicString()),
|
||||||
@@ -248,7 +248,7 @@ namespace Fig
|
|||||||
if (!isTypeMatch(expectedType, defaultVal, ctx))
|
if (!isTypeMatch(expectedType, defaultVal, ctx))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"StructFieldTypeMismatchError",
|
U"StructFieldTypeMismatchError",
|
||||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||||
structName.toBasicString(),
|
structName.toBasicString(),
|
||||||
fieldName.toBasicString(),
|
fieldName.toBasicString(),
|
||||||
@@ -264,7 +264,7 @@ namespace Fig
|
|||||||
if (!isTypeMatch(field.type, argVal, ctx))
|
if (!isTypeMatch(field.type, argVal, ctx))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"StructFieldTypeMismatchError",
|
U"StructFieldTypeMismatchError",
|
||||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||||
structName.toBasicString(),
|
structName.toBasicString(),
|
||||||
fieldName.toBasicString(),
|
fieldName.toBasicString(),
|
||||||
@@ -291,7 +291,7 @@ namespace Fig
|
|||||||
[&argName](const Field &f) { return f.name == argName; });
|
[&argName](const Field &f) { return f.name == argName; });
|
||||||
if (fieldIt == structT.fields.end())
|
if (fieldIt == structT.fields.end())
|
||||||
{
|
{
|
||||||
// throw EvaluatorError(u8"StructFieldNotFoundError",
|
// throw EvaluatorError(U"StructFieldNotFoundError",
|
||||||
// std::format("Field '{}' not found in structure '{}'",
|
// std::format("Field '{}' not found in structure '{}'",
|
||||||
// argName.toBasicString(),
|
// argName.toBasicString(),
|
||||||
// structName.toBasicString()),
|
// structName.toBasicString()),
|
||||||
@@ -303,7 +303,7 @@ namespace Fig
|
|||||||
if (!isTypeMatch(field.type, argVal, ctx))
|
if (!isTypeMatch(field.type, argVal, ctx))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"StructFieldTypeMismatchError",
|
U"StructFieldTypeMismatchError",
|
||||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||||
structName.toBasicString(),
|
structName.toBasicString(),
|
||||||
field.name.toBasicString(),
|
field.name.toBasicString(),
|
||||||
@@ -332,7 +332,7 @@ namespace Fig
|
|||||||
if (!isTypeMatch(field.type, defaultVal, ctx))
|
if (!isTypeMatch(field.type, defaultVal, ctx))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"StructFieldTypeMismatchError",
|
U"StructFieldTypeMismatchError",
|
||||||
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'",
|
||||||
structName.toBasicString(),
|
structName.toBasicString(),
|
||||||
field.name.toBasicString(),
|
field.name.toBasicString(),
|
||||||
@@ -350,9 +350,9 @@ namespace Fig
|
|||||||
// load struct method
|
// load struct method
|
||||||
for (auto &[id, fn] : stDefCtx->getFunctions())
|
for (auto &[id, fn] : stDefCtx->getFunctions())
|
||||||
{
|
{
|
||||||
const FString &funcName = fn.name;
|
const String &funcName = fn.name;
|
||||||
const auto &funcSlot = stDefCtx->get(funcName);
|
const auto &funcSlot = stDefCtx->get(funcName);
|
||||||
|
|
||||||
instanceCtx->def(funcName,
|
instanceCtx->def(funcName,
|
||||||
ValueType::Function,
|
ValueType::Function,
|
||||||
funcSlot->am,
|
funcSlot->am,
|
||||||
@@ -361,4 +361,4 @@ namespace Fig
|
|||||||
|
|
||||||
return std::make_shared<Object>(StructInstance(structT.type, instanceCtx));
|
return std::make_shared<Object>(StructInstance(structT.type, instanceCtx));
|
||||||
}
|
}
|
||||||
};
|
}; // namespace Fig
|
||||||
@@ -8,7 +8,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
ExprResult Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx)
|
ExprResult Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx)
|
||||||
{
|
{
|
||||||
const FString &name = var->name;
|
const String &name = var->name;
|
||||||
|
|
||||||
// 调试信息
|
// 调试信息
|
||||||
// std::cerr << "=== DEBUG evalVarExpr ===" << std::endl;
|
// std::cerr << "=== DEBUG evalVarExpr ===" << std::endl;
|
||||||
@@ -38,14 +38,14 @@ namespace Fig
|
|||||||
// }
|
// }
|
||||||
// end
|
// 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);
|
return LvObject(ctx->get(name), ctx);
|
||||||
}
|
}
|
||||||
ExprResult Evaluator::evalMemberExpr(Ast::MemberExpr me, ContextPtr ctx)
|
ExprResult Evaluator::evalMemberExpr(Ast::MemberExpr me, ContextPtr ctx)
|
||||||
{
|
{
|
||||||
// LvObject base = evalLv(me->base, ctx);
|
// LvObject base = evalLv(me->base, ctx);
|
||||||
RvObject baseVal = check_unwrap(eval(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)
|
if (baseVal->getTypeInfo() == ValueType::Module)
|
||||||
{
|
{
|
||||||
// std::cerr << "=== DEBUG evalMemberExpr (Module) ===" << std::endl;
|
// std::cerr << "=== DEBUG evalMemberExpr (Module) ===" << std::endl;
|
||||||
@@ -74,7 +74,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"VariableNotFoundError",
|
throw EvaluatorError(U"VariableNotFoundError",
|
||||||
std::format("`{}` has not variable '{}', check if it is public",
|
std::format("`{}` has not variable '{}', check if it is public",
|
||||||
baseVal->toString().toBasicString(),
|
baseVal->toString().toBasicString(),
|
||||||
member.toBasicString()),
|
member.toBasicString()),
|
||||||
@@ -118,7 +118,7 @@ namespace Fig
|
|||||||
if (baseVal->getTypeInfo() != ValueType::StructInstance) // and not member function found
|
if (baseVal->getTypeInfo() != ValueType::StructInstance) // and not member function found
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"NoAttributeError",
|
U"NoAttributeError",
|
||||||
std::format("`{}` has not attribute '{}'", baseVal->toString().toBasicString(), member.toBasicString()),
|
std::format("`{}` has not attribute '{}'", baseVal->toString().toBasicString(), member.toBasicString()),
|
||||||
me->base);
|
me->base);
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"NoAttributeError",
|
throw EvaluatorError(U"NoAttributeError",
|
||||||
std::format("`{}` has not attribute '{}' and no interfaces have been implemented it",
|
std::format("`{}` has not attribute '{}' and no interfaces have been implemented it",
|
||||||
baseVal->toString().toBasicString(),
|
baseVal->toString().toBasicString(),
|
||||||
member.toBasicString()),
|
member.toBasicString()),
|
||||||
@@ -172,7 +172,7 @@ namespace Fig
|
|||||||
if (index->getTypeInfo() != ValueType::Int)
|
if (index->getTypeInfo() != ValueType::Int)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"TypeError",
|
U"TypeError",
|
||||||
std::format("Type `List` indices must be `Int`, got '{}'", prettyType(index).toBasicString()),
|
std::format("Type `List` indices must be `Int`, got '{}'", prettyType(index).toBasicString()),
|
||||||
ie->index);
|
ie->index);
|
||||||
}
|
}
|
||||||
@@ -181,7 +181,7 @@ namespace Fig
|
|||||||
if (indexVal >= list.size())
|
if (indexVal >= list.size())
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"IndexOutOfRangeError",
|
U"IndexOutOfRangeError",
|
||||||
std::format("Index {} out of list `{}` range", indexVal, base->toString().toBasicString()),
|
std::format("Index {} out of list `{}` range", indexVal, base->toString().toBasicString()),
|
||||||
ie->index);
|
ie->index);
|
||||||
}
|
}
|
||||||
@@ -193,16 +193,16 @@ namespace Fig
|
|||||||
if (index->getTypeInfo() != ValueType::Int)
|
if (index->getTypeInfo() != ValueType::Int)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"TypeError",
|
U"TypeError",
|
||||||
std::format("Type `String` indices must be `Int`, got '{}'", prettyType(index).toBasicString()),
|
std::format("Type `String` indices must be `Int`, got '{}'", prettyType(index).toBasicString()),
|
||||||
ie->index);
|
ie->index);
|
||||||
}
|
}
|
||||||
FString &string = base->as<ValueType::StringClass>();
|
String &string = base->as<ValueType::StringClass>();
|
||||||
ValueType::IntClass indexVal = index->as<ValueType::IntClass>();
|
ValueType::IntClass indexVal = index->as<ValueType::IntClass>();
|
||||||
if (indexVal >= string.length())
|
if (indexVal >= string.length())
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"IndexOutOfRangeError",
|
U"IndexOutOfRangeError",
|
||||||
std::format("Index {} out of string `{}` range", indexVal, base->toString().toBasicString()),
|
std::format("Index {} out of string `{}` range", indexVal, base->toString().toBasicString()),
|
||||||
ie->index);
|
ie->index);
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,7 @@ namespace Fig
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"NoSubscriptableError",
|
U"NoSubscriptableError",
|
||||||
std::format("`{}` object is not subscriptable", base->getTypeInfo().toString().toBasicString()),
|
std::format("`{}` object is not subscriptable", base->getTypeInfo().toString().toBasicString()),
|
||||||
ie->base);
|
ie->base);
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"TypeError",
|
U"TypeError",
|
||||||
std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()),
|
std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()),
|
||||||
exp);
|
exp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <Ast/Expressions/FunctionCall.hpp>
|
#include <Ast/Expressions/FunctionCall.hpp>
|
||||||
#include <Ast/astBase.hpp>
|
#include <Ast/astBase.hpp>
|
||||||
#include <Ast/functionParameters.hpp>
|
#include <Ast/functionParameters.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Evaluator/Core/StatementResult.hpp>
|
#include <Evaluator/Core/StatementResult.hpp>
|
||||||
#include <Evaluator/Value/Type.hpp>
|
#include <Evaluator/Value/Type.hpp>
|
||||||
#include <Evaluator/Value/structType.hpp>
|
#include <Evaluator/Value/structType.hpp>
|
||||||
@@ -32,7 +32,7 @@ namespace Fig
|
|||||||
if (ctx->containsInThisScope(varDef->name))
|
if (ctx->containsInThisScope(varDef->name))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"RedeclarationError",
|
U"RedeclarationError",
|
||||||
std::format("Variable `{}` already declared in this scope", varDef->name.toBasicString()),
|
std::format("Variable `{}` already declared in this scope", varDef->name.toBasicString()),
|
||||||
varDef);
|
varDef);
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ namespace Fig
|
|||||||
|
|
||||||
if (value != nullptr && !isTypeMatch(declaredType, value, ctx))
|
if (value != nullptr && !isTypeMatch(declaredType, value, ctx))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"TypeError",
|
throw EvaluatorError(U"TypeError",
|
||||||
std::format("Variable `{}` expects init-value type `{}`, but got '{}'",
|
std::format("Variable `{}` expects init-value type `{}`, but got '{}'",
|
||||||
varDef->name.toBasicString(),
|
varDef->name.toBasicString(),
|
||||||
prettyType(declaredTypeValue).toBasicString(),
|
prettyType(declaredTypeValue).toBasicString(),
|
||||||
@@ -73,11 +73,11 @@ namespace Fig
|
|||||||
case FunctionDefSt: {
|
case FunctionDefSt: {
|
||||||
auto fnDef = std::static_pointer_cast<Ast::FunctionDefSt>(stmt);
|
auto fnDef = std::static_pointer_cast<Ast::FunctionDefSt>(stmt);
|
||||||
|
|
||||||
const FString &fnName = fnDef->name;
|
const String &fnName = fnDef->name;
|
||||||
if (ctx->containsInThisScope(fnName))
|
if (ctx->containsInThisScope(fnName))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"RedeclarationError",
|
U"RedeclarationError",
|
||||||
std::format("Function `{}` already declared in this scope", fnName.toBasicString()),
|
std::format("Function `{}` already declared in this scope", fnName.toBasicString()),
|
||||||
fnDef);
|
fnDef);
|
||||||
}
|
}
|
||||||
@@ -102,16 +102,16 @@ namespace Fig
|
|||||||
if (ctx->containsInThisScope(stDef->name))
|
if (ctx->containsInThisScope(stDef->name))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"RedeclarationError",
|
U"RedeclarationError",
|
||||||
std::format("Structure '{}' already defined in this scope", stDef->name.toBasicString()),
|
std::format("Structure '{}' already defined in this scope", stDef->name.toBasicString()),
|
||||||
stDef);
|
stDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeInfo type(stDef->name, true); // register type name
|
TypeInfo type(stDef->name, true); // register type name
|
||||||
ContextPtr defContext = std::make_shared<Context>(FString(std::format("<Struct {} at {}:{}>",
|
ContextPtr defContext = std::make_shared<Context>(String(std::format("<Struct {} at {}:{}>",
|
||||||
stDef->name.toBasicString(),
|
stDef->name.toBasicString(),
|
||||||
stDef->getAAI().line,
|
stDef->getAAI().line,
|
||||||
stDef->getAAI().column)),
|
stDef->getAAI().column)),
|
||||||
ctx);
|
ctx);
|
||||||
ObjectPtr structTypeObj = std::make_shared<Object>(StructType(type, defContext, {}));
|
ObjectPtr structTypeObj = std::make_shared<Object>(StructType(type, defContext, {}));
|
||||||
|
|
||||||
@@ -124,12 +124,12 @@ namespace Fig
|
|||||||
structTypeObj); // predef to itself, always const
|
structTypeObj); // predef to itself, always const
|
||||||
|
|
||||||
std::vector<Field> fields;
|
std::vector<Field> fields;
|
||||||
std::vector<FString> _fieldNames;
|
std::vector<String> _fieldNames;
|
||||||
for (Ast::StructDefField field : stDef->fields)
|
for (Ast::StructDefField field : stDef->fields)
|
||||||
{
|
{
|
||||||
if (Utils::vectorContains(field.fieldName, _fieldNames))
|
if (Utils::vectorContains(field.fieldName, _fieldNames))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"RedeclarationError",
|
throw EvaluatorError(U"RedeclarationError",
|
||||||
std::format("Field '{}' already defined in structure '{}'",
|
std::format("Field '{}' already defined in structure '{}'",
|
||||||
field.fieldName.toBasicString(),
|
field.fieldName.toBasicString(),
|
||||||
stDef->name.toBasicString()),
|
stDef->name.toBasicString()),
|
||||||
@@ -151,7 +151,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
if (st->getType() != Ast::AstType::FunctionDefSt)
|
if (st->getType() != Ast::AstType::FunctionDefSt)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"UnexpectedStatementInStructError",
|
throw EvaluatorError(U"UnexpectedStatementInStructError",
|
||||||
std::format("Unexpected statement `{}` in struct declaration",
|
std::format("Unexpected statement `{}` in struct declaration",
|
||||||
st->toString().toBasicString()),
|
st->toString().toBasicString()),
|
||||||
st);
|
st);
|
||||||
@@ -164,12 +164,12 @@ namespace Fig
|
|||||||
case InterfaceDefSt: {
|
case InterfaceDefSt: {
|
||||||
auto ifd = std::static_pointer_cast<Ast::InterfaceDefAst>(stmt);
|
auto ifd = std::static_pointer_cast<Ast::InterfaceDefAst>(stmt);
|
||||||
|
|
||||||
const FString &interfaceName = ifd->name;
|
const String &interfaceName = ifd->name;
|
||||||
|
|
||||||
if (ctx->containsInThisScope(interfaceName))
|
if (ctx->containsInThisScope(interfaceName))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"RedeclarationError",
|
U"RedeclarationError",
|
||||||
std::format("Interface `{}` already declared in this scope", interfaceName.toBasicString()),
|
std::format("Interface `{}` already declared in this scope", interfaceName.toBasicString()),
|
||||||
ifd);
|
ifd);
|
||||||
}
|
}
|
||||||
@@ -188,7 +188,7 @@ namespace Fig
|
|||||||
TypeInfo interfaceType(ip->interfaceName);
|
TypeInfo interfaceType(ip->interfaceName);
|
||||||
if (ctx->hasImplRegisted(structType, interfaceType))
|
if (ctx->hasImplRegisted(structType, interfaceType))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"DuplicateImplError",
|
throw EvaluatorError(U"DuplicateImplError",
|
||||||
std::format("Duplicate implement `{}` for `{}`",
|
std::format("Duplicate implement `{}` for `{}`",
|
||||||
interfaceType.toString().toBasicString(),
|
interfaceType.toString().toBasicString(),
|
||||||
structType.toString().toBasicString()),
|
structType.toString().toBasicString()),
|
||||||
@@ -196,13 +196,13 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
if (!ctx->contains(ip->interfaceName))
|
if (!ctx->contains(ip->interfaceName))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"InterfaceNotFoundError",
|
throw EvaluatorError(U"InterfaceNotFoundError",
|
||||||
std::format("Interface '{}' not found", ip->interfaceName.toBasicString()),
|
std::format("Interface '{}' not found", ip->interfaceName.toBasicString()),
|
||||||
ip);
|
ip);
|
||||||
}
|
}
|
||||||
if (!ctx->contains(ip->structName))
|
if (!ctx->contains(ip->structName))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"StructNotFoundError",
|
throw EvaluatorError(U"StructNotFoundError",
|
||||||
std::format("Struct '{}' not found", ip->structName.toBasicString()),
|
std::format("Struct '{}' not found", ip->structName.toBasicString()),
|
||||||
ip);
|
ip);
|
||||||
}
|
}
|
||||||
@@ -218,21 +218,21 @@ namespace Fig
|
|||||||
if (!interfaceObj->is<InterfaceType>())
|
if (!interfaceObj->is<InterfaceType>())
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"NotAInterfaceError",
|
U"NotAInterfaceError",
|
||||||
std::format("Variable `{}` is not a interface", ip->interfaceName.toBasicString()),
|
std::format("Variable `{}` is not a interface", ip->interfaceName.toBasicString()),
|
||||||
ip);
|
ip);
|
||||||
}
|
}
|
||||||
if (!structTypeObj->is<StructType>())
|
if (!structTypeObj->is<StructType>())
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"NotAStructType",
|
U"NotAStructType",
|
||||||
std::format("Variable `{}` is not a struct type", ip->structName.toBasicString()),
|
std::format("Variable `{}` is not a struct type", ip->structName.toBasicString()),
|
||||||
ip);
|
ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &implementMethods = ip->methods;
|
auto &implementMethods = ip->methods;
|
||||||
|
|
||||||
if (ip->interfaceName == u8"Operation")
|
if (ip->interfaceName == U"Operation")
|
||||||
{
|
{
|
||||||
// 运算符重载
|
// 运算符重载
|
||||||
/*
|
/*
|
||||||
@@ -243,52 +243,52 @@ namespace Fig
|
|||||||
*/
|
*/
|
||||||
if (ValueType::isTypeBuiltin(structType))
|
if (ValueType::isTypeBuiltin(structType))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"BadUserError",
|
throw EvaluatorError(U"BadUserError",
|
||||||
std::format("Don't overload built-in type operators plz! `{}`",
|
std::format("Don't overload built-in type operators plz! `{}`",
|
||||||
prettyType(structTypeObj).toBasicString()),
|
prettyType(structTypeObj).toBasicString()),
|
||||||
ip);
|
ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
using enum Ast::Operator;
|
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}},
|
{U"Add", {Ast::Operator::Add, 2}},
|
||||||
{u8"Sub", {Ast::Operator::Subtract, 2}},
|
{U"Sub", {Ast::Operator::Subtract, 2}},
|
||||||
{u8"Mul", {Ast::Operator::Multiply, 2}},
|
{U"Mul", {Ast::Operator::Multiply, 2}},
|
||||||
{u8"Div", {Ast::Operator::Divide, 2}},
|
{U"Div", {Ast::Operator::Divide, 2}},
|
||||||
{u8"Mod", {Ast::Operator::Modulo, 2}},
|
{U"Mod", {Ast::Operator::Modulo, 2}},
|
||||||
{u8"Pow", {Ast::Operator::Power, 2}},
|
{U"Pow", {Ast::Operator::Power, 2}},
|
||||||
|
|
||||||
// 逻辑(一元)
|
// 逻辑(一元)
|
||||||
{u8"Neg", {Ast::Operator::Subtract, 1}}, // 一元负号
|
{U"Neg", {Ast::Operator::Subtract, 1}}, // 一元负号
|
||||||
{u8"Not", {Ast::Operator::Not, 1}},
|
{U"Not", {Ast::Operator::Not, 1}},
|
||||||
|
|
||||||
// 逻辑(二元)
|
// 逻辑(二元)
|
||||||
{u8"And", {Ast::Operator::And, 2}},
|
{U"And", {Ast::Operator::And, 2}},
|
||||||
{u8"Or", {Ast::Operator::Or, 2}},
|
{U"Or", {Ast::Operator::Or, 2}},
|
||||||
|
|
||||||
// 比较
|
// 比较
|
||||||
{u8"Equal", {Ast::Operator::Equal, 2}},
|
{U"Equal", {Ast::Operator::Equal, 2}},
|
||||||
{u8"NotEqual", {Ast::Operator::NotEqual, 2}},
|
{U"NotEqual", {Ast::Operator::NotEqual, 2}},
|
||||||
{u8"LessThan", {Ast::Operator::Less, 2}},
|
{U"LessThan", {Ast::Operator::Less, 2}},
|
||||||
{u8"LessEqual", {Ast::Operator::LessEqual, 2}},
|
{U"LessEqual", {Ast::Operator::LessEqual, 2}},
|
||||||
{u8"GreaterThan", {Ast::Operator::Greater, 2}},
|
{U"GreaterThan", {Ast::Operator::Greater, 2}},
|
||||||
{u8"GreaterEqual", {Ast::Operator::GreaterEqual, 2}},
|
{U"GreaterEqual", {Ast::Operator::GreaterEqual, 2}},
|
||||||
{u8"Is", {Ast::Operator::Is, 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}},
|
{U"BitAnd", {Ast::Operator::BitAnd, 2}},
|
||||||
{u8"BitOr", {Ast::Operator::BitOr, 2}},
|
{U"BitOr", {Ast::Operator::BitOr, 2}},
|
||||||
{u8"BitXor", {Ast::Operator::BitXor, 2}},
|
{U"BitXor", {Ast::Operator::BitXor, 2}},
|
||||||
{u8"ShiftLeft", {Ast::Operator::ShiftLeft, 2}},
|
{U"ShiftLeft", {Ast::Operator::ShiftLeft, 2}},
|
||||||
{u8"ShiftRight", {Ast::Operator::ShiftRight, 2}},
|
{U"ShiftRight", {Ast::Operator::ShiftRight, 2}},
|
||||||
};
|
};
|
||||||
for (auto &implMethod : implementMethods)
|
for (auto &implMethod : implementMethods)
|
||||||
{
|
{
|
||||||
const FString &opName = implMethod.name;
|
const String &opName = implMethod.name;
|
||||||
if (!magic_name_to_op.contains(opName))
|
if (!magic_name_to_op.contains(opName))
|
||||||
{
|
{
|
||||||
// ... 现在忽略
|
// ... 现在忽略
|
||||||
@@ -303,7 +303,7 @@ namespace Fig
|
|||||||
if (ctx->hasOperatorImplemented(structType, op, (expectArgCnt == 1 ? true : false)))
|
if (ctx->hasOperatorImplemented(structType, op, (expectArgCnt == 1 ? true : false)))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"DuplicateImplementError",
|
U"DuplicateImplementError",
|
||||||
std::format("{} has already implement by another interface", opName.toBasicString()),
|
std::format("{} has already implement by another interface", opName.toBasicString()),
|
||||||
ip);
|
ip);
|
||||||
}
|
}
|
||||||
@@ -312,7 +312,7 @@ namespace Fig
|
|||||||
if (paraCnt != expectArgCnt || implMethod.paras.size() != expectArgCnt)
|
if (paraCnt != expectArgCnt || implMethod.paras.size() != expectArgCnt)
|
||||||
{
|
{
|
||||||
// 特化报错,更详细易读
|
// 特化报错,更详细易读
|
||||||
throw EvaluatorError(u8"InterfaceSignatureMismatch",
|
throw EvaluatorError(U"InterfaceSignatureMismatch",
|
||||||
std::format("Operator {} for {} arg count must be {}, got {}",
|
std::format("Operator {} for {} arg count must be {}, got {}",
|
||||||
opName.toBasicString(),
|
opName.toBasicString(),
|
||||||
structLv.name().toBasicString(),
|
structLv.name().toBasicString(),
|
||||||
@@ -321,10 +321,10 @@ namespace Fig
|
|||||||
ip);
|
ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
FString opFnName(u8"Operation." + prettyType(structTypeObj) + u8"." + opName);
|
String opFnName(U"Operation." + prettyType(structTypeObj) + U"." + opName);
|
||||||
|
|
||||||
ContextPtr fnCtx = std::make_shared<Context>(
|
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 auto &fillOpFnParas = [this, structType, implMethod, opFnName, fnCtx, ctx, paraCnt](
|
||||||
const std::vector<ObjectPtr> &args) {
|
const std::vector<ObjectPtr> &args) {
|
||||||
@@ -336,7 +336,7 @@ namespace Fig
|
|||||||
if (paraType != ValueType::Any && paraType != structType)
|
if (paraType != ValueType::Any && paraType != structType)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"ParameterTypeError",
|
U"ParameterTypeError",
|
||||||
std::format("Invalid op fn parameter type '{}' of `{}`, must be `{}`",
|
std::format("Invalid op fn parameter type '{}' of `{}`, must be `{}`",
|
||||||
paraType.toString().toBasicString(),
|
paraType.toString().toBasicString(),
|
||||||
paras.posParas[i].first.toBasicString(),
|
paras.posParas[i].first.toBasicString(),
|
||||||
@@ -385,12 +385,12 @@ namespace Fig
|
|||||||
// ===== interface implementation validation =====
|
// ===== interface implementation validation =====
|
||||||
ImplRecord record{interfaceType, structType, {}};
|
ImplRecord record{interfaceType, structType, {}};
|
||||||
|
|
||||||
std::unordered_map<FString, Ast::InterfaceMethod> ifaceMethods;
|
std::unordered_map<String, Ast::InterfaceMethod> ifaceMethods;
|
||||||
for (auto &m : interface.methods)
|
for (auto &m : interface.methods)
|
||||||
{
|
{
|
||||||
if (ifaceMethods.contains(m.name))
|
if (ifaceMethods.contains(m.name))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"InterfaceDuplicateMethodError",
|
throw EvaluatorError(U"InterfaceDuplicateMethodError",
|
||||||
std::format("Interface '{}' has duplicate method '{}'",
|
std::format("Interface '{}' has duplicate method '{}'",
|
||||||
interfaceType.toString().toBasicString(),
|
interfaceType.toString().toBasicString(),
|
||||||
m.name.toBasicString()),
|
m.name.toBasicString()),
|
||||||
@@ -399,16 +399,16 @@ namespace Fig
|
|||||||
ifaceMethods[m.name] = m;
|
ifaceMethods[m.name] = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_set<FString> implemented;
|
std::unordered_set<String> implemented;
|
||||||
|
|
||||||
for (auto &implMethod : implementMethods)
|
for (auto &implMethod : implementMethods)
|
||||||
{
|
{
|
||||||
const FString &name = implMethod.name;
|
const String &name = implMethod.name;
|
||||||
|
|
||||||
// ---- redundant impl ----
|
// ---- redundant impl ----
|
||||||
if (!ifaceMethods.contains(name))
|
if (!ifaceMethods.contains(name))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"RedundantImplementationError",
|
throw EvaluatorError(U"RedundantImplementationError",
|
||||||
std::format("Struct '{}' implements extra method '{}' "
|
std::format("Struct '{}' implements extra method '{}' "
|
||||||
"which is not required by interface '{}'",
|
"which is not required by interface '{}'",
|
||||||
structType.toString().toBasicString(),
|
structType.toString().toBasicString(),
|
||||||
@@ -419,7 +419,7 @@ namespace Fig
|
|||||||
|
|
||||||
if (implemented.contains(name))
|
if (implemented.contains(name))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"DuplicateImplementMethodError",
|
throw EvaluatorError(U"DuplicateImplementMethodError",
|
||||||
std::format("Duplicate implement method '{}'", name.toBasicString()),
|
std::format("Duplicate implement method '{}'", name.toBasicString()),
|
||||||
ip);
|
ip);
|
||||||
}
|
}
|
||||||
@@ -429,7 +429,7 @@ namespace Fig
|
|||||||
// ---- signature check ----
|
// ---- signature check ----
|
||||||
if (!isInterfaceSignatureMatch(implMethod, ifMethod))
|
if (!isInterfaceSignatureMatch(implMethod, ifMethod))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"InterfaceSignatureMismatch",
|
throw EvaluatorError(U"InterfaceSignatureMismatch",
|
||||||
std::format("Interface method '{}({})' signature mismatch with "
|
std::format("Interface method '{}({})' signature mismatch with "
|
||||||
"implementation '{}({})'",
|
"implementation '{}({})'",
|
||||||
ifMethod.name.toBasicString(),
|
ifMethod.name.toBasicString(),
|
||||||
@@ -441,7 +441,7 @@ namespace Fig
|
|||||||
|
|
||||||
if (ctx->hasMethodImplemented(structType, name))
|
if (ctx->hasMethodImplemented(structType, name))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"DuplicateImplementMethodError",
|
throw EvaluatorError(U"DuplicateImplementMethodError",
|
||||||
std::format("Method '{}' already implemented by another interface "
|
std::format("Method '{}' already implemented by another interface "
|
||||||
"for struct '{}'",
|
"for struct '{}'",
|
||||||
name.toBasicString(),
|
name.toBasicString(),
|
||||||
@@ -463,7 +463,7 @@ namespace Fig
|
|||||||
|
|
||||||
if (m.hasDefaultBody()) continue;
|
if (m.hasDefaultBody()) continue;
|
||||||
|
|
||||||
throw EvaluatorError(u8"MissingImplementationError",
|
throw EvaluatorError(U"MissingImplementationError",
|
||||||
std::format("Struct '{}' does not implement required interface method '{}' "
|
std::format("Struct '{}' does not implement required interface method '{}' "
|
||||||
"and interface '{}' provides no default implementation",
|
"and interface '{}' provides no default implementation",
|
||||||
structType.toString().toBasicString(),
|
structType.toString().toBasicString(),
|
||||||
@@ -482,7 +482,7 @@ namespace Fig
|
|||||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"TypeError",
|
U"TypeError",
|
||||||
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
||||||
ifSt->condition);
|
ifSt->condition);
|
||||||
}
|
}
|
||||||
@@ -494,7 +494,7 @@ namespace Fig
|
|||||||
if (elifCondVal->getTypeInfo() != ValueType::Bool)
|
if (elifCondVal->getTypeInfo() != ValueType::Bool)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"TypeError",
|
U"TypeError",
|
||||||
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
||||||
ifSt->condition);
|
ifSt->condition);
|
||||||
}
|
}
|
||||||
@@ -511,13 +511,13 @@ namespace Fig
|
|||||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"TypeError",
|
U"TypeError",
|
||||||
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
||||||
whileSt->condition);
|
whileSt->condition);
|
||||||
}
|
}
|
||||||
if (!condVal->as<ValueType::BoolClass>()) { break; }
|
if (!condVal->as<ValueType::BoolClass>()) { break; }
|
||||||
ContextPtr loopContext = std::make_shared<Context>(
|
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
|
ctx); // every loop has its own context
|
||||||
StatementResult sr = evalBlockStatement(whileSt->body, loopContext);
|
StatementResult sr = evalBlockStatement(whileSt->body, loopContext);
|
||||||
if (sr.shouldReturn()) { return sr; }
|
if (sr.shouldReturn()) { return sr; }
|
||||||
@@ -529,7 +529,7 @@ namespace Fig
|
|||||||
case ForSt: {
|
case ForSt: {
|
||||||
auto forSt = std::static_pointer_cast<Ast::ForSt>(stmt);
|
auto forSt = std::static_pointer_cast<Ast::ForSt>(stmt);
|
||||||
ContextPtr loopContext = std::make_shared<Context>(
|
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
|
ctx); // for loop has its own context
|
||||||
|
|
||||||
evalStatement(forSt->initSt,
|
evalStatement(forSt->initSt,
|
||||||
@@ -543,14 +543,14 @@ namespace Fig
|
|||||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"TypeError",
|
U"TypeError",
|
||||||
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()),
|
||||||
forSt->condition);
|
forSt->condition);
|
||||||
}
|
}
|
||||||
if (!condVal->as<ValueType::BoolClass>()) { break; }
|
if (!condVal->as<ValueType::BoolClass>()) { break; }
|
||||||
iteration++;
|
iteration++;
|
||||||
ContextPtr iterationContext = std::make_shared<Context>(
|
ContextPtr iterationContext = std::make_shared<Context>(
|
||||||
FString(std::format(
|
String(std::format(
|
||||||
"<For {}:{}, Iteration {}>", forSt->getAAI().line, forSt->getAAI().column, iteration)),
|
"<For {}:{}, Iteration {}>", forSt->getAAI().line, forSt->getAAI().column, iteration)),
|
||||||
loopContext); // every loop has its own context
|
loopContext); // every loop has its own context
|
||||||
StatementResult sr = evalBlockStatement(forSt->body, iterationContext);
|
StatementResult sr = evalBlockStatement(forSt->body, iterationContext);
|
||||||
@@ -571,7 +571,7 @@ namespace Fig
|
|||||||
auto tryst = std::static_pointer_cast<Ast::TrySt>(stmt);
|
auto tryst = std::static_pointer_cast<Ast::TrySt>(stmt);
|
||||||
|
|
||||||
ContextPtr tryCtx = std::make_shared<Context>(
|
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();
|
StatementResult sr = StatementResult::normal();
|
||||||
bool crashed = false;
|
bool crashed = false;
|
||||||
for (auto &stmt : tryst->body->stmts)
|
for (auto &stmt : tryst->body->stmts)
|
||||||
@@ -586,13 +586,12 @@ namespace Fig
|
|||||||
bool catched = false;
|
bool catched = false;
|
||||||
for (auto &cat : tryst->catches)
|
for (auto &cat : tryst->catches)
|
||||||
{
|
{
|
||||||
const FString &errVarName = cat.errVarName;
|
const String &errVarName = cat.errVarName;
|
||||||
TypeInfo errVarType = (cat.hasType ? TypeInfo(cat.errVarType) : ValueType::Any);
|
TypeInfo errVarType = (cat.hasType ? TypeInfo(cat.errVarType) : ValueType::Any);
|
||||||
if (isTypeMatch(errVarType, sr.result, ctx))
|
if (isTypeMatch(errVarType, sr.result, ctx))
|
||||||
{
|
{
|
||||||
ContextPtr catchCtx = std::make_shared<Context>(
|
ContextPtr catchCtx = std::make_shared<Context>(
|
||||||
FString(
|
String(std::format("<Catch at {}:{}>", cat.body->getAAI().line, cat.body->getAAI().column)),
|
||||||
std::format("<Catch at {}:{}>", cat.body->getAAI().line, cat.body->getAAI().column)),
|
|
||||||
ctx);
|
ctx);
|
||||||
catchCtx->def(errVarName, errVarType, AccessModifier::Normal, sr.result);
|
catchCtx->def(errVarName, errVarType, AccessModifier::Normal, sr.result);
|
||||||
sr = evalBlockStatement(cat.body, catchCtx);
|
sr = evalBlockStatement(cat.body, catchCtx);
|
||||||
@@ -602,7 +601,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
if (!catched && crashed)
|
if (!catched && crashed)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"UncaughtExceptionError",
|
throw EvaluatorError(U"UncaughtExceptionError",
|
||||||
std::format("Uncaught exception: {}", sr.result->toString().toBasicString()),
|
std::format("Uncaught exception: {}", sr.result->toString().toBasicString()),
|
||||||
tryst);
|
tryst);
|
||||||
}
|
}
|
||||||
@@ -616,7 +615,7 @@ namespace Fig
|
|||||||
ObjectPtr value = check_unwrap_stres(eval(ts->value, ctx));
|
ObjectPtr value = check_unwrap_stres(eval(ts->value, ctx));
|
||||||
if (value->is<ValueType::NullClass>())
|
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);
|
return StatementResult::errorFlow(value);
|
||||||
}
|
}
|
||||||
@@ -632,11 +631,11 @@ namespace Fig
|
|||||||
case BreakSt: {
|
case BreakSt: {
|
||||||
if (!ctx->parent)
|
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())
|
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();
|
return StatementResult::breakFlow();
|
||||||
}
|
}
|
||||||
@@ -644,11 +643,11 @@ namespace Fig
|
|||||||
case ContinueSt: {
|
case ContinueSt: {
|
||||||
if (!ctx->parent)
|
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())
|
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();
|
return StatementResult::continueFlow();
|
||||||
}
|
}
|
||||||
@@ -662,13 +661,13 @@ namespace Fig
|
|||||||
auto block = std::static_pointer_cast<Ast::BlockStatementAst>(stmt);
|
auto block = std::static_pointer_cast<Ast::BlockStatementAst>(stmt);
|
||||||
|
|
||||||
ContextPtr blockCtx = std::make_shared<Context>(
|
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);
|
return evalBlockStatement(block, blockCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw RuntimeError(
|
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
|
}; // namespace Fig
|
||||||
@@ -11,7 +11,7 @@ namespace Fig
|
|||||||
if (condVal->getTypeInfo() != ValueType::Bool)
|
if (condVal->getTypeInfo() != ValueType::Bool)
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"TypeError",
|
U"TypeError",
|
||||||
std::format("Condition must be boolean, got '{}'", prettyType(condVal).toBasicString()),
|
std::format("Condition must be boolean, got '{}'", prettyType(condVal).toBasicString()),
|
||||||
te->condition);
|
te->condition);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace Fig
|
|||||||
return tryInvokeOverloadFn(value, [value]() { return std::make_shared<Object>(bit_not(*value)); });
|
return tryInvokeOverloadFn(value, [value]() { return std::make_shared<Object>(bit_not(*value)); });
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw EvaluatorError(u8"UnsupportedOpError",
|
throw EvaluatorError(U"UnsupportedOpError",
|
||||||
std::format("Unsupported op '{}' for unary expression", magic_enum::enum_name(op)),
|
std::format("Unsupported op '{}' for unary expression", magic_enum::enum_name(op)),
|
||||||
un);
|
un);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Evaluator/Value/value_forward.hpp>
|
#include <Evaluator/Value/value_forward.hpp>
|
||||||
#include <Evaluator/Value/LvObject.hpp>
|
#include <Evaluator/Value/LvObject.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
namespace Fig
|
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;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
@@ -32,13 +32,13 @@ namespace Fig
|
|||||||
import comp.config;
|
import comp.config;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const FString &modPathStrTop = pathVec.at(0);
|
const String &modPathStrTop = pathVec.at(0);
|
||||||
fs::path modPath;
|
fs::path modPath;
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto &parentFolder : pathToFind)
|
for (auto &parentFolder : pathToFind)
|
||||||
{
|
{
|
||||||
modPath = parentFolder / FString(modPathStrTop + u8".fig").toBasicString();
|
modPath = parentFolder / String(modPathStrTop + U".fig").toBasicString();
|
||||||
if (fs::exists(modPath))
|
if (fs::exists(modPath))
|
||||||
{
|
{
|
||||||
path = modPath;
|
path = modPath;
|
||||||
@@ -50,16 +50,16 @@ namespace Fig
|
|||||||
modPath = parentFolder / modPathStrTop.toBasicString();
|
modPath = parentFolder / modPathStrTop.toBasicString();
|
||||||
if (fs::is_directory(modPath)) // comp is a directory
|
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
|
if module name is a directory, we require [module
|
||||||
name].fig at the directory
|
name].fig at the directory
|
||||||
*/
|
*/
|
||||||
if (!fs::exists(modPath))
|
if (!fs::exists(modPath))
|
||||||
{
|
{
|
||||||
throw RuntimeError(FString(std::format("requires module file, {}\\{}",
|
throw RuntimeError(String(std::format("requires module file, {}\\{}",
|
||||||
modPathStrTop.toBasicString(),
|
modPathStrTop.toBasicString(),
|
||||||
FString(modPathStrTop + u8".fig").toBasicString())));
|
String(modPathStrTop + U".fig").toBasicString())));
|
||||||
}
|
}
|
||||||
found = true;
|
found = true;
|
||||||
path = modPath;
|
path = modPath;
|
||||||
@@ -69,19 +69,19 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
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;
|
bool found2 = false;
|
||||||
|
|
||||||
for (size_t i = 1; i < pathVec.size(); ++i) // has next module
|
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.parent_path(); // get the folder
|
||||||
modPath = modPath / FString(next + u8".fig").toBasicString();
|
modPath = modPath / String(next + U".fig").toBasicString();
|
||||||
if (fs::exists(modPath))
|
if (fs::exists(modPath))
|
||||||
{
|
{
|
||||||
if (i != pathVec.size() - 1)
|
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())));
|
"expects {} as parent directory and find next module, but got a file", next.toBasicString())));
|
||||||
// it's the last module
|
// it's the last module
|
||||||
found2 = true;
|
found2 = true;
|
||||||
@@ -91,14 +91,14 @@ namespace Fig
|
|||||||
// `next` is a folder
|
// `next` is a folder
|
||||||
modPath = modPath.parent_path() / next.toBasicString();
|
modPath = modPath.parent_path() / next.toBasicString();
|
||||||
if (!fs::exists(modPath))
|
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)
|
if (i == pathVec.size() - 1)
|
||||||
{
|
{
|
||||||
// `next` is the last module
|
// `next` is the last module
|
||||||
modPath = modPath / FString(next + u8".fig").toBasicString();
|
modPath = modPath / String(next + U".fig").toBasicString();
|
||||||
if (!fs::exists(modPath))
|
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())));
|
"expects {} as parent directory and find next module, but got a file", next.toBasicString())));
|
||||||
}
|
}
|
||||||
found2 = true;
|
found2 = true;
|
||||||
@@ -107,8 +107,8 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found2 && !fs::exists(modPath))
|
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;
|
return path;
|
||||||
}
|
}
|
||||||
};
|
}; // namespace Fig
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Evaluator/Value/value.hpp>
|
#include <Evaluator/Value/value.hpp>
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Evaluator/Value/value.hpp>
|
#include <Evaluator/Value/value.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Evaluator/Value/value_forward.hpp>
|
#include <Evaluator/Value/value_forward.hpp>
|
||||||
#include <Evaluator/Value/Type.hpp>
|
#include <Evaluator/Value/Type.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|||||||
@@ -24,18 +24,15 @@ namespace Fig
|
|||||||
|
|
||||||
ContextPtr ctx;
|
ContextPtr ctx;
|
||||||
|
|
||||||
LvObject(std::shared_ptr<VariableSlot> _slot, ContextPtr _ctx) :
|
LvObject(std::shared_ptr<VariableSlot> _slot, ContextPtr _ctx) : slot(std::move(_slot)), ctx(_ctx)
|
||||||
slot(std::move(_slot)), ctx(_ctx)
|
|
||||||
{
|
{
|
||||||
kind = Kind::Variable;
|
kind = Kind::Variable;
|
||||||
}
|
}
|
||||||
LvObject(ObjectPtr _v, size_t _index, Kind _kind, ContextPtr _ctx) :
|
LvObject(ObjectPtr _v, size_t _index, Kind _kind, ContextPtr _ctx) : value(_v), numIndex(_index), ctx(_ctx)
|
||||||
value(_v), numIndex(_index), ctx(_ctx)
|
|
||||||
{
|
{
|
||||||
kind = _kind;
|
kind = _kind;
|
||||||
}
|
}
|
||||||
LvObject(ObjectPtr _v, ObjectPtr _index, Kind _kind, ContextPtr _ctx) :
|
LvObject(ObjectPtr _v, ObjectPtr _index, Kind _kind, ContextPtr _ctx) : value(_v), mapIndex(_index), ctx(_ctx)
|
||||||
value(_v), mapIndex(_index), ctx(_ctx)
|
|
||||||
{
|
{
|
||||||
kind = _kind;
|
kind = _kind;
|
||||||
}
|
}
|
||||||
@@ -51,27 +48,26 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
List &list = value->as<List>();
|
List &list = value->as<List>();
|
||||||
if (numIndex >= list.size())
|
if (numIndex >= list.size())
|
||||||
throw RuntimeError(FString(
|
throw RuntimeError(
|
||||||
std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
String(std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
||||||
return list.at(numIndex).value;
|
return list.at(numIndex).value;
|
||||||
}
|
}
|
||||||
else if (kind == Kind::MapElement) // map
|
else if (kind == Kind::MapElement) // map
|
||||||
{
|
{
|
||||||
Map &map = value->as<Map>();
|
Map &map = value->as<Map>();
|
||||||
if (!map.contains(mapIndex))
|
if (!map.contains(mapIndex))
|
||||||
throw RuntimeError(FString(
|
throw RuntimeError(String(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
|
else
|
||||||
{
|
{
|
||||||
// string
|
// string
|
||||||
FString &string = value->as<ValueType::StringClass>();
|
String &string = value->as<ValueType::StringClass>();
|
||||||
if (numIndex >= string.length())
|
if (numIndex >= string.length())
|
||||||
throw RuntimeError(FString(
|
throw RuntimeError(
|
||||||
std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
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);
|
auto s = resolve(slot);
|
||||||
if (!isTypeMatch(s->declaredType, v, ctx))
|
if (!isTypeMatch(s->declaredType, v, ctx))
|
||||||
{
|
{
|
||||||
throw RuntimeError(
|
throw RuntimeError(String(std::format("Variable `{}` expects type `{}`, but got '{}'",
|
||||||
FString(
|
s->name.toBasicString(),
|
||||||
std::format("Variable `{}` expects type `{}`, but got '{}'",
|
s->declaredType.toString().toBasicString(),
|
||||||
s->name.toBasicString(),
|
prettyType(v).toBasicString())));
|
||||||
s->declaredType.toString().toBasicString(),
|
|
||||||
prettyType(v).toBasicString())));
|
|
||||||
}
|
}
|
||||||
if (isAccessConst(s->am))
|
if (isAccessConst(s->am))
|
||||||
{
|
{
|
||||||
throw RuntimeError(FString(
|
throw RuntimeError(String(std::format("Variable `{}` is immutable", s->name.toBasicString())));
|
||||||
std::format("Variable `{}` is immutable", s->name.toBasicString())));
|
|
||||||
}
|
}
|
||||||
s->value = v;
|
s->value = v;
|
||||||
}
|
}
|
||||||
else if (kind == Kind::ListElement)
|
else if (kind == Kind::ListElement)
|
||||||
{
|
{
|
||||||
List &list = value->as<List>();
|
List &list = value->as<List>();
|
||||||
if (numIndex >= list.size())
|
if (numIndex >= list.size()) throw RuntimeError(String(std::format("Index {} out of range", numIndex)));
|
||||||
throw RuntimeError(FString(
|
|
||||||
std::format("Index {} out of range", numIndex)));
|
|
||||||
list[numIndex] = v;
|
list[numIndex] = v;
|
||||||
}
|
}
|
||||||
else if (kind == Kind::MapElement) // map
|
else if (kind == Kind::MapElement) // map
|
||||||
@@ -111,25 +102,23 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else if (kind == Kind::StringElement)
|
else if (kind == Kind::StringElement)
|
||||||
{
|
{
|
||||||
FString &string = value->as<ValueType::StringClass>();
|
String &string = value->as<ValueType::StringClass>();
|
||||||
if (numIndex >= string.length())
|
if (numIndex >= string.length())
|
||||||
throw RuntimeError(FString(
|
throw RuntimeError(
|
||||||
std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
String(std::format("Index {} out of range {}", numIndex, value->toString().toBasicString())));
|
||||||
|
|
||||||
if (v->getTypeInfo() != ValueType::String)
|
if (v->getTypeInfo() != ValueType::String)
|
||||||
throw RuntimeError(FString(
|
throw RuntimeError(
|
||||||
std::format("Could not assign {} to sub string", v->toString().toBasicString())
|
String(std::format("Could not assign {} to sub string", v->toString().toBasicString())));
|
||||||
));
|
const String &strReplace = v->as<ValueType::StringClass>();
|
||||||
const FString &strReplace = v->as<ValueType::StringClass>();
|
|
||||||
if (strReplace.length() > 1)
|
if (strReplace.length() > 1)
|
||||||
throw RuntimeError(FString(
|
throw RuntimeError(String(std::format("Could not assign {} to sub string, expects length 1",
|
||||||
std::format("Could not assign {} to sub string, expects length 1", v->toString().toBasicString())
|
v->toString().toBasicString())));
|
||||||
));
|
string.replace(numIndex, strReplace.length(), strReplace);
|
||||||
string.realReplace(numIndex, strReplace);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FString name() const { return resolve(slot)->name; }
|
String name() const { return resolve(slot)->name; }
|
||||||
TypeInfo declaredType() const { return resolve(slot)->declaredType; }
|
TypeInfo declaredType() const { return resolve(slot)->declaredType; }
|
||||||
AccessModifier access() const { return resolve(slot)->am; }
|
AccessModifier access() const { return resolve(slot)->am; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
@@ -14,23 +14,23 @@ namespace Fig
|
|||||||
private:
|
private:
|
||||||
size_t id;
|
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;
|
return typeMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
friend class TypeInfoHash;
|
friend class TypeInfoHash;
|
||||||
|
|
||||||
FString name;
|
String name;
|
||||||
|
|
||||||
FString toString() const { return name; }
|
String toString() const { return name; }
|
||||||
|
|
||||||
size_t getInstanceID() const { return id; }
|
size_t getInstanceID() const { return id; }
|
||||||
|
|
||||||
TypeInfo();
|
TypeInfo();
|
||||||
explicit TypeInfo(const FString &_name, bool reg = false);
|
explicit TypeInfo(const String &_name, bool reg = false);
|
||||||
TypeInfo(const TypeInfo &other) = default;
|
TypeInfo(const TypeInfo &other) = default;
|
||||||
|
|
||||||
bool operator==(const TypeInfo &other) const { return id == other.id; }
|
bool operator==(const TypeInfo &other) const { return id == other.id; }
|
||||||
@@ -63,7 +63,7 @@ namespace Fig
|
|||||||
using DoubleClass = double;
|
using DoubleClass = double;
|
||||||
using BoolClass = bool;
|
using BoolClass = bool;
|
||||||
using NullClass = std::monostate;
|
using NullClass = std::monostate;
|
||||||
using StringClass = FString;
|
using StringClass = Fig::String;
|
||||||
|
|
||||||
inline bool isTypeBuiltin(const TypeInfo &type)
|
inline bool isTypeBuiltin(const TypeInfo &type)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
#include <Ast/AccessModifier.hpp>
|
#include <Ast/AccessModifier.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Evaluator/Value/Type.hpp>
|
#include <Evaluator/Value/Type.hpp>
|
||||||
#include <Evaluator/Value/value_forward.hpp>
|
#include <Evaluator/Value/value_forward.hpp>
|
||||||
|
|
||||||
@@ -12,7 +11,7 @@ namespace Fig
|
|||||||
|
|
||||||
struct VariableSlot
|
struct VariableSlot
|
||||||
{
|
{
|
||||||
FString name;
|
String name;
|
||||||
ObjectPtr value;
|
ObjectPtr value;
|
||||||
TypeInfo declaredType;
|
TypeInfo declaredType;
|
||||||
AccessModifier am;
|
AccessModifier am;
|
||||||
@@ -20,4 +19,4 @@ namespace Fig
|
|||||||
bool isRef = false;
|
bool isRef = false;
|
||||||
std::shared_ptr<VariableSlot> refTarget;
|
std::shared_ptr<VariableSlot> refTarget;
|
||||||
};
|
};
|
||||||
}
|
} // namespace Fig
|
||||||
@@ -16,7 +16,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::size_t id;
|
std::size_t id;
|
||||||
FString name;
|
String name;
|
||||||
|
|
||||||
enum FnType
|
enum FnType
|
||||||
{
|
{
|
||||||
@@ -53,7 +53,7 @@ namespace Fig
|
|||||||
new (&body) Ast::BlockStatement();
|
new (&body) Ast::BlockStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
Function(const FString &_name,
|
Function(const String &_name,
|
||||||
Ast::FunctionParameters _paras,
|
Ast::FunctionParameters _paras,
|
||||||
TypeInfo _retType,
|
TypeInfo _retType,
|
||||||
Ast::BlockStatement _body,
|
Ast::BlockStatement _body,
|
||||||
@@ -68,13 +68,16 @@ namespace Fig
|
|||||||
type = Normal;
|
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)
|
id(nextId()), name(_name), type(Builtin), builtin(fn), builtinParamCount(argc)
|
||||||
{
|
{
|
||||||
type = Builtin;
|
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,
|
const std::vector<std::shared_ptr<Object>> &)> fn,
|
||||||
int argc) :
|
int argc) :
|
||||||
id(nextId()), name(_name), type(MemberType), mtFn(fn), builtinParamCount(argc)
|
id(nextId()), name(_name), type(MemberType), mtFn(fn), builtinParamCount(argc)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
|
|
||||||
#include <Evaluator/Context/context_forward.hpp>
|
#include <Evaluator/Context/context_forward.hpp>
|
||||||
|
|
||||||
@@ -8,20 +8,13 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
struct Module
|
struct Module
|
||||||
{
|
{
|
||||||
FString name;
|
String name;
|
||||||
ContextPtr ctx;
|
ContextPtr ctx;
|
||||||
|
|
||||||
Module() = default;
|
Module() = default;
|
||||||
|
|
||||||
Module(FString n, ContextPtr c) :
|
Module(String n, ContextPtr c) : name(std::move(n)), ctx(std::move(c)) {}
|
||||||
name(std::move(n)),
|
|
||||||
ctx(std::move(c))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const Module &o) const noexcept
|
bool operator==(const Module &o) const noexcept { return name == o.name; }
|
||||||
{
|
|
||||||
return name == o.name;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
}; // namespace Fig
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Ast/Statements/StructDefSt.hpp>
|
#include <Ast/Statements/StructDefSt.hpp>
|
||||||
|
|
||||||
#include <Evaluator/Value/Type.hpp>
|
#include <Evaluator/Value/Type.hpp>
|
||||||
@@ -14,21 +14,17 @@ namespace Fig
|
|||||||
struct Field
|
struct Field
|
||||||
{
|
{
|
||||||
AccessModifier am;
|
AccessModifier am;
|
||||||
FString name;
|
String name;
|
||||||
TypeInfo type;
|
TypeInfo type;
|
||||||
Ast::Expression defaultValue;
|
Ast::Expression defaultValue;
|
||||||
|
|
||||||
Field(AccessModifier _am, FString _name, TypeInfo _type, Ast::Expression _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)) {}
|
am(_am), name(std::move(_name)), type(std::move(_type)), defaultValue(std::move(_defaultValue))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool isPublic() const
|
bool isPublic() const { return am == AccessModifier::Public || am == AccessModifier::PublicConst; }
|
||||||
{
|
bool isConst() const { return am == AccessModifier::Const || am == AccessModifier::PublicConst; }
|
||||||
return am == AccessModifier::Public || am == AccessModifier::PublicConst;
|
|
||||||
}
|
|
||||||
bool isConst() const
|
|
||||||
{
|
|
||||||
return am == AccessModifier::Const || am == AccessModifier::PublicConst;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StructType
|
struct StructType
|
||||||
@@ -41,7 +37,9 @@ namespace Fig
|
|||||||
|
|
||||||
// ===== Constructors =====
|
// ===== Constructors =====
|
||||||
StructType(TypeInfo _type, ContextPtr _defContext, std::vector<Field> _fields, bool _builtin = false) :
|
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(const StructType &other) = default;
|
||||||
StructType(StructType &&) noexcept = default;
|
StructType(StructType &&) noexcept = default;
|
||||||
@@ -49,14 +47,8 @@ namespace Fig
|
|||||||
StructType &operator=(StructType &&) noexcept = default;
|
StructType &operator=(StructType &&) noexcept = default;
|
||||||
|
|
||||||
// ===== Comparison =====
|
// ===== Comparison =====
|
||||||
bool operator==(const StructType &other) const noexcept
|
bool operator==(const StructType &other) const noexcept { return type == other.type; }
|
||||||
{
|
bool operator!=(const StructType &other) const noexcept { return !(*this == other); }
|
||||||
return type == other.type;
|
|
||||||
}
|
|
||||||
bool operator!=(const StructType &other) const noexcept
|
|
||||||
{
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::size_t nextId()
|
static std::size_t nextId()
|
||||||
@@ -72,9 +64,6 @@ namespace std
|
|||||||
template <>
|
template <>
|
||||||
struct hash<Fig::Field>
|
struct hash<Fig::Field>
|
||||||
{
|
{
|
||||||
size_t operator()(const Fig::Field &f)
|
size_t operator()(const Fig::Field &f) { return std::hash<Fig::String>{}(f.name); }
|
||||||
{
|
|
||||||
return std::hash<Fig::FString>{}(f.name);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}; // namespace std
|
}; // namespace std
|
||||||
@@ -11,10 +11,10 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
|
|
||||||
TypeInfo::TypeInfo() : // only allow use in evaluate time !! <---- dynamic type system requirement
|
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;
|
static size_t id_count = 0;
|
||||||
name = _name;
|
name = _name;
|
||||||
@@ -28,7 +28,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
if (!getTypeMap().contains(_name))
|
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;
|
// *this = ValueType::String;
|
||||||
}
|
}
|
||||||
id = getTypeMap().at(name); // may throw
|
id = getTypeMap().at(name); // may throw
|
||||||
@@ -93,25 +93,29 @@ namespace Fig
|
|||||||
if (t == ValueType::StructInstance) return obj->as<StructInstance>().parentType;
|
if (t == ValueType::StructInstance) return obj->as<StructInstance>().parentType;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
FString prettyType(std::shared_ptr<const Object> obj)
|
String prettyType(std::shared_ptr<const Object> obj)
|
||||||
{
|
{
|
||||||
return actualType(obj).toString();
|
return actualType(obj).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeInfo ValueType::Any(FString(u8"Any"), true); // id: 1
|
const TypeInfo ValueType::Any(U"Any", true); // id: 1
|
||||||
const TypeInfo ValueType::Null(FString(u8"Null"), true); // id: 2
|
const TypeInfo ValueType::Null(U"Null", true); // id: 2
|
||||||
const TypeInfo ValueType::Int(FString(u8"Int"), true); // id: 3
|
const TypeInfo ValueType::Int(U"Int", true); // id: 3
|
||||||
const TypeInfo ValueType::String(FString(u8"String"), true); // id: 4
|
const TypeInfo ValueType::String(U"String", true); // id: 4
|
||||||
const TypeInfo ValueType::Bool(FString(u8"Bool"), true); // id: 5
|
const TypeInfo ValueType::Bool(U"Bool", true); // id: 5
|
||||||
const TypeInfo ValueType::Double(FString(u8"Double"), true); // id: 6
|
const TypeInfo ValueType::Double(U"Double", true); // id: 6
|
||||||
const TypeInfo ValueType::Function(FString(u8"Function"), true); // id: 7
|
const TypeInfo ValueType::Function(U"Function", true); // id: 7
|
||||||
const TypeInfo ValueType::StructType(FString(u8"StructType"), true); // id: 8
|
const TypeInfo ValueType::StructType(U"StructType", true); // id: 8
|
||||||
const TypeInfo ValueType::StructInstance(FString(u8"StructInstance"), true); // id: 9
|
const TypeInfo ValueType::StructInstance(U"StructInstance", true); // id: 9
|
||||||
const TypeInfo ValueType::List(FString(u8"List"), true); // id: 10
|
const TypeInfo ValueType::List(U"List", true); // id: 10
|
||||||
const TypeInfo ValueType::Map(FString(u8"Map"), true); // id: 11
|
const TypeInfo ValueType::Map(U"Map", true); // id: 11
|
||||||
const TypeInfo ValueType::Module(FString(u8"Module"), true); // id: 12
|
const TypeInfo ValueType::Module(U"Module", true); // id: 12
|
||||||
const TypeInfo ValueType::InterfaceType(FString(u8"InterfaceType"), true); // id: 13
|
const TypeInfo ValueType::InterfaceType(U"InterfaceType", true); // id: 13
|
||||||
|
|
||||||
|
namespace ValueType
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
bool implements(const TypeInfo &structType, const TypeInfo &interfaceType, ContextPtr ctx)
|
bool implements(const TypeInfo &structType, const TypeInfo &interfaceType, ContextPtr ctx)
|
||||||
{
|
{
|
||||||
return ctx->hasImplRegisted(structType, interfaceType);
|
return ctx->hasImplRegisted(structType, interfaceType);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Evaluator/Value/function.hpp>
|
#include <Evaluator/Value/function.hpp>
|
||||||
#include <Evaluator/Value/interface.hpp>
|
#include <Evaluator/Value/interface.hpp>
|
||||||
#include <Evaluator/Value/structType.hpp>
|
#include <Evaluator/Value/structType.hpp>
|
||||||
@@ -43,7 +43,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
TypeInfo actualType(std::shared_ptr<const Object> obj);
|
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 &);
|
bool operator==(const Object &, const Object &);
|
||||||
|
|
||||||
@@ -93,89 +93,92 @@ namespace Fig
|
|||||||
Module,
|
Module,
|
||||||
InterfaceType>;
|
InterfaceType>;
|
||||||
|
|
||||||
static std::unordered_map<TypeInfo, std::unordered_map<FString, BuiltinTypeMemberFn>, TypeInfoHash>
|
static std::unordered_map<TypeInfo, std::unordered_map<String, BuiltinTypeMemberFn>, TypeInfoHash>
|
||||||
getMemberTypeFunctions()
|
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{
|
memberTypeFunctions{
|
||||||
{ValueType::Null, {}},
|
{ValueType::Null, {}},
|
||||||
{ValueType::Int, {}},
|
{ValueType::Int, {}},
|
||||||
{ValueType::Double, {}},
|
{ValueType::Double, {}},
|
||||||
{ValueType::String,
|
{ValueType::String,
|
||||||
{
|
{
|
||||||
{u8"length",
|
{U"length",
|
||||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||||
if (args.size() != 0)
|
if (args.size() != 0)
|
||||||
throw RuntimeError(
|
throw RuntimeError(
|
||||||
FString(std::format("`length` expects 0 arguments, {} got", args.size())));
|
String(std::format("`length` expects 0 arguments, {} got", args.size())));
|
||||||
const FString &str = object->as<ValueType::StringClass>();
|
const String &str = object->as<ValueType::StringClass>();
|
||||||
return std::make_shared<Object>(static_cast<ValueType::IntClass>(str.length()));
|
return std::make_shared<Object>(static_cast<ValueType::IntClass>(str.length()));
|
||||||
}},
|
}},
|
||||||
{u8"replace",
|
{U"replace",
|
||||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2)
|
||||||
throw RuntimeError(
|
throw RuntimeError(
|
||||||
FString(std::format("`replace` expects 2 arguments, {} got", args.size())));
|
String(std::format("`replace` expects 2 arguments, {} got", args.size())));
|
||||||
FString &str = object->as<ValueType::StringClass>();
|
String &str = object->as<ValueType::StringClass>();
|
||||||
ObjectPtr arg1 = args[0];
|
ObjectPtr arg1 = args[0];
|
||||||
ObjectPtr arg2 = args[1];
|
ObjectPtr arg2 = args[1];
|
||||||
if (!arg1->is<ValueType::IntClass>())
|
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>())
|
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();
|
return Object::getNullInstance();
|
||||||
}},
|
}},
|
||||||
{u8"erase",
|
{U"erase",
|
||||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2)
|
||||||
throw RuntimeError(
|
throw RuntimeError(
|
||||||
FString(std::format("`erase` expects 2 arguments, {} got", args.size())));
|
String(std::format("`erase` expects 2 arguments, {} got", args.size())));
|
||||||
FString &str = object->as<ValueType::StringClass>();
|
String &str = object->as<ValueType::StringClass>();
|
||||||
ObjectPtr arg1 = args[0];
|
ObjectPtr arg1 = args[0];
|
||||||
ObjectPtr arg2 = args[1];
|
ObjectPtr arg2 = args[1];
|
||||||
if (!arg1->is<ValueType::IntClass>())
|
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>())
|
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 index = arg1->as<ValueType::IntClass>();
|
||||||
ValueType::IntClass n = arg2->as<ValueType::IntClass>();
|
ValueType::IntClass n = arg2->as<ValueType::IntClass>();
|
||||||
if (index < 0 || n < 0)
|
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())
|
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();
|
return Object::getNullInstance();
|
||||||
}},
|
}},
|
||||||
{u8"insert",
|
{U"insert",
|
||||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||||
if (args.size() != 2)
|
if (args.size() != 2)
|
||||||
throw RuntimeError(
|
throw RuntimeError(
|
||||||
FString(std::format("`insert` expects 2 arguments, {} got", args.size())));
|
String(std::format("`insert` expects 2 arguments, {} got", args.size())));
|
||||||
FString &str = object->as<ValueType::StringClass>();
|
String &str = object->as<ValueType::StringClass>();
|
||||||
ObjectPtr arg1 = args[0];
|
ObjectPtr arg1 = args[0];
|
||||||
ObjectPtr arg2 = args[1];
|
ObjectPtr arg2 = args[1];
|
||||||
if (!arg1->is<ValueType::IntClass>())
|
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>())
|
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();
|
return Object::getNullInstance();
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
@@ -184,34 +187,34 @@ namespace Fig
|
|||||||
{ValueType::StructInstance, {}},
|
{ValueType::StructInstance, {}},
|
||||||
{ValueType::List,
|
{ValueType::List,
|
||||||
{
|
{
|
||||||
{u8"length",
|
{U"length",
|
||||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||||
if (args.size() != 0)
|
if (args.size() != 0)
|
||||||
throw RuntimeError(
|
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>();
|
const List &list = object->as<List>();
|
||||||
return std::make_shared<Object>(static_cast<ValueType::IntClass>(list.size()));
|
return std::make_shared<Object>(static_cast<ValueType::IntClass>(list.size()));
|
||||||
}},
|
}},
|
||||||
{u8"get",
|
{U"get",
|
||||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
throw RuntimeError(
|
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];
|
ObjectPtr arg = args[0];
|
||||||
if (arg->getTypeInfo() != ValueType::Int)
|
if (arg->getTypeInfo() != ValueType::Int)
|
||||||
throw RuntimeError(
|
throw RuntimeError(
|
||||||
FString(std::format("`get` argument 1 expects Int, {} got",
|
String(std::format("`get` argument 1 expects Int, {} got",
|
||||||
arg->getTypeInfo().toString().toBasicString())));
|
arg->getTypeInfo().toString().toBasicString())));
|
||||||
ValueType::IntClass i = arg->as<ValueType::IntClass>();
|
ValueType::IntClass i = arg->as<ValueType::IntClass>();
|
||||||
const List &list = object->as<List>();
|
const List &list = object->as<List>();
|
||||||
if (i >= list.size()) return Object::getNullInstance();
|
if (i >= list.size()) return Object::getNullInstance();
|
||||||
return list[i].value;
|
return list[i].value;
|
||||||
}},
|
}},
|
||||||
{u8"push",
|
{U"push",
|
||||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
throw RuntimeError(
|
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];
|
ObjectPtr arg = args[0];
|
||||||
List &list = object->as<List>();
|
List &list = object->as<List>();
|
||||||
list.push_back(arg);
|
list.push_back(arg);
|
||||||
@@ -220,21 +223,21 @@ namespace Fig
|
|||||||
}},
|
}},
|
||||||
{ValueType::Map,
|
{ValueType::Map,
|
||||||
{
|
{
|
||||||
{u8"get",
|
{U"get",
|
||||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
throw RuntimeError(
|
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];
|
ObjectPtr index = args[0];
|
||||||
const Map &map = object->as<Map>();
|
const Map &map = object->as<Map>();
|
||||||
if (!map.contains(index)) return Object::getNullInstance();
|
if (!map.contains(index)) return Object::getNullInstance();
|
||||||
return map.at(index);
|
return map.at(index);
|
||||||
}},
|
}},
|
||||||
{u8"contains",
|
{U"contains",
|
||||||
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
[](ObjectPtr object, std::vector<ObjectPtr> args) -> ObjectPtr {
|
||||||
if (args.size() != 1)
|
if (args.size() != 1)
|
||||||
throw RuntimeError(
|
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];
|
ObjectPtr index = args[0];
|
||||||
const Map &map = object->as<Map>();
|
const Map &map = object->as<Map>();
|
||||||
return std::make_shared<Object>(map.contains(index));
|
return std::make_shared<Object>(map.contains(index));
|
||||||
@@ -246,29 +249,28 @@ namespace Fig
|
|||||||
return memberTypeFunctions;
|
return memberTypeFunctions;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::unordered_map<TypeInfo, std::unordered_map<FString, int>, TypeInfoHash>
|
static std::unordered_map<TypeInfo, std::unordered_map<String, int>, TypeInfoHash> getMemberTypeFunctionsParas()
|
||||||
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{
|
memberTypeFunctionsParas{
|
||||||
{ValueType::Null, {}},
|
{ValueType::Null, {}},
|
||||||
{ValueType::Int, {}},
|
{ValueType::Int, {}},
|
||||||
{ValueType::Double, {}},
|
{ValueType::Double, {}},
|
||||||
{ValueType::String,
|
{ValueType::String,
|
||||||
{
|
{
|
||||||
{u8"length", 0},
|
{U"length", 0},
|
||||||
{u8"replace", 2},
|
{U"replace", 2},
|
||||||
{u8"erase", 2},
|
{U"erase", 2},
|
||||||
{u8"insert", 2},
|
{U"insert", 2},
|
||||||
}},
|
}},
|
||||||
{ValueType::Function, {}},
|
{ValueType::Function, {}},
|
||||||
{ValueType::StructType, {}},
|
{ValueType::StructType, {}},
|
||||||
{ValueType::StructInstance, {}},
|
{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,
|
{ValueType::Map,
|
||||||
{
|
{
|
||||||
{u8"get", 1},
|
{U"get", 1},
|
||||||
{u8"contains", 1},
|
{U"contains", 1},
|
||||||
}},
|
}},
|
||||||
{ValueType::Module, {}},
|
{ValueType::Module, {}},
|
||||||
{ValueType::InterfaceType, {}},
|
{ValueType::InterfaceType, {}},
|
||||||
@@ -276,15 +278,15 @@ namespace Fig
|
|||||||
return memberTypeFunctionsParas;
|
return memberTypeFunctionsParas;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasMemberFunction(const FString &name) const
|
bool hasMemberFunction(const String &name) const
|
||||||
{
|
{
|
||||||
return getMemberTypeFunctions().at(getTypeInfo()).contains(name);
|
return getMemberTypeFunctions().at(getTypeInfo()).contains(name);
|
||||||
}
|
}
|
||||||
BuiltinTypeMemberFn getMemberFunction(const FString &name) const
|
BuiltinTypeMemberFn getMemberFunction(const String &name) const
|
||||||
{
|
{
|
||||||
return getMemberTypeFunctions().at(getTypeInfo()).at(name);
|
return getMemberTypeFunctions().at(getTypeInfo()).at(name);
|
||||||
}
|
}
|
||||||
int getMemberFunctionParaCount(const FString &name) const
|
int getMemberFunctionParaCount(const String &name) const
|
||||||
{
|
{
|
||||||
return getMemberTypeFunctionsParas().at(getTypeInfo()).at(name);
|
return getMemberTypeFunctionsParas().at(getTypeInfo()).at(name);
|
||||||
}
|
}
|
||||||
@@ -317,7 +319,7 @@ namespace Fig
|
|||||||
else if (ti == ValueType::Double)
|
else if (ti == ValueType::Double)
|
||||||
return Object(ValueType::DoubleClass(0.0));
|
return Object(ValueType::DoubleClass(0.0));
|
||||||
else if (ti == ValueType::String)
|
else if (ti == ValueType::String)
|
||||||
return Object(ValueType::StringClass(u8""));
|
return Object(ValueType::StringClass(U""));
|
||||||
else if (ti == ValueType::Bool)
|
else if (ti == ValueType::Bool)
|
||||||
return Object(ValueType::BoolClass(false));
|
return Object(ValueType::BoolClass(false));
|
||||||
else if (ti == ValueType::List)
|
else if (ti == ValueType::List)
|
||||||
@@ -420,83 +422,83 @@ namespace Fig
|
|||||||
else if (is<ValueType::DoubleClass>())
|
else if (is<ValueType::DoubleClass>())
|
||||||
return as<ValueType::DoubleClass>();
|
return as<ValueType::DoubleClass>();
|
||||||
else
|
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>();
|
if (is<ValueType::StringClass>()) return as<ValueType::StringClass>();
|
||||||
return toString();
|
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::NullClass>()) return String(U"null");
|
||||||
if (is<ValueType::IntClass>()) return FString(std::to_string(as<ValueType::IntClass>()));
|
if (is<ValueType::IntClass>()) return String(std::to_string(as<ValueType::IntClass>()));
|
||||||
if (is<ValueType::DoubleClass>()) return FString(std::format("{}", as<ValueType::DoubleClass>()));
|
if (is<ValueType::DoubleClass>()) return String(std::format("{}", as<ValueType::DoubleClass>()));
|
||||||
if (is<ValueType::StringClass>()) return FString(u8"\"" + as<ValueType::StringClass>() + u8"\"");
|
if (is<ValueType::StringClass>()) return String(String(U"\"") + as<ValueType::StringClass>() + String(U"\""));
|
||||||
if (is<ValueType::BoolClass>()) return as<ValueType::BoolClass>() ? FString(u8"true") : FString(u8"false");
|
if (is<ValueType::BoolClass>()) return as<ValueType::BoolClass>() ? String(U"true") : String(U"false");
|
||||||
if (is<Function>())
|
if (is<Function>())
|
||||||
return FString(std::format(
|
return String(std::format(
|
||||||
"<Function '{}' at {:p}>", as<Function>().id, static_cast<const void *>(&as<Function>())));
|
"<Function '{}' at {:p}>", as<Function>().id, static_cast<const void *>(&as<Function>())));
|
||||||
if (is<StructType>())
|
if (is<StructType>())
|
||||||
return FString(std::format("<StructType '{}' at {:p}>",
|
return String(std::format("<StructType '{}' at {:p}>",
|
||||||
as<StructType>().type.toString().toBasicString(),
|
as<StructType>().type.toString().toBasicString(),
|
||||||
static_cast<const void *>(&as<StructType>())));
|
static_cast<const void *>(&as<StructType>())));
|
||||||
if (is<StructInstance>())
|
if (is<StructInstance>())
|
||||||
return FString(std::format("<StructInstance '{}' at {:p}>",
|
return String(std::format("<StructInstance '{}' at {:p}>",
|
||||||
as<StructInstance>().parentType.toString().toBasicString(),
|
as<StructInstance>().parentType.toString().toBasicString(),
|
||||||
static_cast<const void *>(&as<StructInstance>())));
|
static_cast<const void *>(&as<StructInstance>())));
|
||||||
if (is<List>())
|
if (is<List>())
|
||||||
{
|
{
|
||||||
if (visited.contains(this)) { return u8"[...]"; }
|
if (visited.contains(this)) { return U"[...]"; }
|
||||||
visited.insert(this);
|
visited.insert(this);
|
||||||
|
|
||||||
FString output(u8"[");
|
String output(U"[");
|
||||||
const List &list = as<List>();
|
const List &list = as<List>();
|
||||||
bool first_flag = true;
|
bool first_flag = true;
|
||||||
for (auto &ele : list)
|
for (auto &ele : list)
|
||||||
{
|
{
|
||||||
if (!first_flag) output += u8", ";
|
if (!first_flag) output += U", ";
|
||||||
output += ele.value->toString(visited);
|
output += ele.value->toString(visited);
|
||||||
first_flag = false;
|
first_flag = false;
|
||||||
}
|
}
|
||||||
output += u8"]";
|
output += U"]";
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
if (is<Map>())
|
if (is<Map>())
|
||||||
{
|
{
|
||||||
if (visited.contains(this)) { return u8"{...}"; }
|
if (visited.contains(this)) { return U"{...}"; }
|
||||||
visited.insert(this);
|
visited.insert(this);
|
||||||
|
|
||||||
FString output(u8"{");
|
String output(U"{");
|
||||||
const Map &map = as<Map>();
|
const Map &map = as<Map>();
|
||||||
bool first_flag = true;
|
bool first_flag = true;
|
||||||
for (auto &[key, value] : map)
|
for (auto &[key, value] : map)
|
||||||
{
|
{
|
||||||
if (!first_flag) output += u8", ";
|
if (!first_flag) output += U", ";
|
||||||
output += key.value->toString(visited) + FString(u8" : ") + value->toString(visited);
|
output += key.value->toString(visited) + String(U" : ") + value->toString(visited);
|
||||||
first_flag = false;
|
first_flag = false;
|
||||||
}
|
}
|
||||||
output += u8"}";
|
output += U"}";
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
if (is<Module>())
|
if (is<Module>())
|
||||||
{
|
{
|
||||||
return FString(std::format("<Module '{}' at {:p}>",
|
return String(std::format("<Module '{}' at {:p}>",
|
||||||
as<Module>().name.toBasicString(),
|
as<Module>().name.toBasicString(),
|
||||||
static_cast<const void *>(&as<Module>())));
|
static_cast<const void *>(&as<Module>())));
|
||||||
}
|
}
|
||||||
if (is<InterfaceType>())
|
if (is<InterfaceType>())
|
||||||
{
|
{
|
||||||
return FString(std::format("<InterfaceType '{}' at {:p}>",
|
return String(std::format("<InterfaceType '{}' at {:p}>",
|
||||||
as<InterfaceType>().type.toString().toBasicString(),
|
as<InterfaceType>().type.toString().toBasicString(),
|
||||||
static_cast<const void *>(&as<InterfaceType>())));
|
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{};
|
std::unordered_set<const Object *> visited{};
|
||||||
return toString(visited);
|
return toString(visited);
|
||||||
@@ -516,7 +518,7 @@ namespace Fig
|
|||||||
friend Object operator+(const Object &lhs, const Object &rhs)
|
friend Object operator+(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (lhs.isNull() || rhs.isNull())
|
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())
|
if (lhs.isNumeric() && rhs.isNumeric())
|
||||||
{
|
{
|
||||||
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
||||||
@@ -525,14 +527,14 @@ namespace Fig
|
|||||||
return Object(result);
|
return Object(result);
|
||||||
}
|
}
|
||||||
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
|
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
|
||||||
return Object(FString(lhs.as<ValueType::StringClass>() + rhs.as<ValueType::StringClass>()));
|
return Object(String(lhs.as<ValueType::StringClass>() + rhs.as<ValueType::StringClass>()));
|
||||||
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)
|
friend Object operator-(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (lhs.isNull() || rhs.isNull())
|
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())
|
if (lhs.isNumeric() && rhs.isNumeric())
|
||||||
{
|
{
|
||||||
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
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));
|
if (bothInt) return Object(static_cast<ValueType::IntClass>(result));
|
||||||
return Object(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)
|
friend Object operator*(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (lhs.isNull() || rhs.isNull())
|
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())
|
if (lhs.isNumeric() && rhs.isNumeric())
|
||||||
{
|
{
|
||||||
bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
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>())
|
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::IntClass>())
|
||||||
{
|
{
|
||||||
FString result;
|
String result;
|
||||||
const FString &l = lhs.as<ValueType::StringClass>();
|
const String &l = lhs.as<ValueType::StringClass>();
|
||||||
for (size_t i = 0; i < rhs.getNumericValue(); ++i) { result += l; }
|
for (size_t i = 0; i < rhs.getNumericValue(); ++i) { result += l; }
|
||||||
return Object(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)
|
friend Object operator/(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (lhs.isNull() || rhs.isNull())
|
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())
|
if (lhs.isNumeric() && rhs.isNumeric())
|
||||||
{
|
{
|
||||||
auto rnv = rhs.getNumericValue();
|
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>();
|
// bool bothInt = lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>();
|
||||||
auto result = lhs.getNumericValue() / rnv;
|
auto result = lhs.getNumericValue() / rnv;
|
||||||
// if (bothInt)
|
// if (bothInt)
|
||||||
@@ -581,18 +583,18 @@ namespace Fig
|
|||||||
// DO NOT convert it to INT
|
// DO NOT convert it to INT
|
||||||
return Object(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)
|
friend Object operator%(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (lhs.isNull() || rhs.isNull())
|
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>())
|
if (lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>())
|
||||||
{
|
{
|
||||||
ValueType::IntClass lv = lhs.as<ValueType::IntClass>();
|
ValueType::IntClass lv = lhs.as<ValueType::IntClass>();
|
||||||
ValueType::IntClass rv = 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 q = lv / rv;
|
||||||
ValueType::IntClass r = lv % rv;
|
ValueType::IntClass r = lv % rv;
|
||||||
@@ -603,25 +605,25 @@ namespace Fig
|
|||||||
if (lhs.isNumeric() && rhs.isNumeric())
|
if (lhs.isNumeric() && rhs.isNumeric())
|
||||||
{
|
{
|
||||||
auto rnv = rhs.getNumericValue();
|
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);
|
auto result = std::fmod(lhs.getNumericValue(), rnv);
|
||||||
return Object(result);
|
return Object(result);
|
||||||
}
|
}
|
||||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs)));
|
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// logic
|
// logic
|
||||||
friend Object operator&&(const Object &lhs, const Object &rhs)
|
friend Object operator&&(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (!lhs.is<ValueType::BoolClass>() || !rhs.is<ValueType::BoolClass>())
|
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>());
|
return Object(lhs.as<ValueType::BoolClass>() && rhs.as<ValueType::BoolClass>());
|
||||||
}
|
}
|
||||||
|
|
||||||
friend Object operator||(const Object &lhs, const Object &rhs)
|
friend Object operator||(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (!lhs.is<ValueType::BoolClass>() || !rhs.is<ValueType::BoolClass>())
|
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>());
|
return Object(lhs.as<ValueType::BoolClass>() || rhs.as<ValueType::BoolClass>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,34 +631,35 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
if (!v.is<ValueType::BoolClass>())
|
if (!v.is<ValueType::BoolClass>())
|
||||||
throw ValueError(
|
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>());
|
return Object(!v.as<ValueType::BoolClass>());
|
||||||
}
|
}
|
||||||
|
|
||||||
friend Object operator-(const Object &v)
|
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::IntClass>()) return Object(-v.as<ValueType::IntClass>());
|
||||||
if (v.is<ValueType::DoubleClass>()) return Object(-v.as<ValueType::DoubleClass>());
|
if (v.is<ValueType::DoubleClass>()) return Object(-v.as<ValueType::DoubleClass>());
|
||||||
throw ValueError(
|
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)
|
friend Object operator~(const Object &v)
|
||||||
{
|
{
|
||||||
if (!v.is<ValueType::IntClass>())
|
if (!v.is<ValueType::IntClass>())
|
||||||
throw ValueError(
|
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>());
|
return Object(~v.as<ValueType::IntClass>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// comparison
|
// comparison
|
||||||
friend bool operator==(const Object &lhs, const Object &rhs) {
|
friend bool operator==(const Object &lhs, const Object &rhs)
|
||||||
|
{
|
||||||
if (lhs.isNumeric() && rhs.isNumeric())
|
if (lhs.isNumeric() && rhs.isNumeric())
|
||||||
{
|
{
|
||||||
return nearlyEqual(lhs.getNumericValue(), rhs.getNumericValue());
|
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) { return !(lhs == rhs); }
|
||||||
friend bool operator<(const Object &lhs, const Object &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.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() < rhs.getNumericValue();
|
||||||
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
|
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
|
||||||
return lhs.as<ValueType::StringClass>() < rhs.as<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) { return lhs == rhs || lhs < rhs; }
|
||||||
friend bool operator>(const Object &lhs, const Object &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.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() > rhs.getNumericValue();
|
||||||
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
|
if (lhs.is<ValueType::StringClass>() && rhs.is<ValueType::StringClass>())
|
||||||
return lhs.as<ValueType::StringClass>() > rhs.as<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) { return lhs == rhs || lhs > rhs; }
|
||||||
|
|
||||||
@@ -680,21 +683,21 @@ namespace Fig
|
|||||||
friend Object bit_and(const Object &lhs, const Object &rhs)
|
friend Object bit_and(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
|
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>());
|
return Object(lhs.as<ValueType::IntClass>() & rhs.as<ValueType::IntClass>());
|
||||||
}
|
}
|
||||||
|
|
||||||
friend Object bit_or(const Object &lhs, const Object &rhs)
|
friend Object bit_or(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
|
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>());
|
return Object(lhs.as<ValueType::IntClass>() | rhs.as<ValueType::IntClass>());
|
||||||
}
|
}
|
||||||
|
|
||||||
friend Object bit_xor(const Object &lhs, const Object &rhs)
|
friend Object bit_xor(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
|
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>());
|
return Object(lhs.as<ValueType::IntClass>() ^ rhs.as<ValueType::IntClass>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,28 +705,28 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
if (!v.is<ValueType::IntClass>())
|
if (!v.is<ValueType::IntClass>())
|
||||||
throw ValueError(
|
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>());
|
return Object(~v.as<ValueType::IntClass>());
|
||||||
}
|
}
|
||||||
|
|
||||||
friend Object shift_left(const Object &lhs, const Object &rhs)
|
friend Object shift_left(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
|
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>());
|
return Object(lhs.as<ValueType::IntClass>() << rhs.as<ValueType::IntClass>());
|
||||||
}
|
}
|
||||||
|
|
||||||
friend Object shift_right(const Object &lhs, const Object &rhs)
|
friend Object shift_right(const Object &lhs, const Object &rhs)
|
||||||
{
|
{
|
||||||
if (!lhs.is<ValueType::IntClass>() || !rhs.is<ValueType::IntClass>())
|
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>());
|
return Object(lhs.as<ValueType::IntClass>() >> rhs.as<ValueType::IntClass>());
|
||||||
}
|
}
|
||||||
|
|
||||||
friend Object power(const Object &base, const Object &exp)
|
friend Object power(const Object &base, const Object &exp)
|
||||||
{
|
{
|
||||||
if (base.isNull() || exp.isNull())
|
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())
|
if (base.isNumeric() && exp.isNumeric())
|
||||||
{
|
{
|
||||||
bool bothInt = base.is<ValueType::IntClass>() && exp.is<ValueType::IntClass>();
|
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));
|
if (bothInt) return Object(static_cast<ValueType::IntClass>(result));
|
||||||
return Object(result);
|
return Object(result);
|
||||||
}
|
}
|
||||||
throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "**", base, exp)));
|
throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "**", base, exp)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,13 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using UnaddressableError::UnaddressableError;
|
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());
|
std::string msg = std::format("[ValueError] {} in [{}] {}",
|
||||||
return FString(msg);
|
std::string(this->message.begin(), this->message.end()),
|
||||||
|
this->src_loc.file_name(),
|
||||||
|
this->src_loc.function_name());
|
||||||
|
return String(msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
}; // namespace Fig
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <Evaluator/Value/Type.hpp>
|
#include <Evaluator/Value/Type.hpp>
|
||||||
#include <Evaluator/Value/structInstance.hpp>
|
#include <Evaluator/Value/structInstance.hpp>
|
||||||
#include <Ast/astBase.hpp>
|
#include <Ast/astBase.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Evaluator/Core/StatementResult.hpp>
|
#include <Evaluator/Core/StatementResult.hpp>
|
||||||
#include <Evaluator/Value/value.hpp>
|
#include <Evaluator/Value/value.hpp>
|
||||||
#include <Error/errorLog.hpp>
|
#include <Error/errorLog.hpp>
|
||||||
@@ -50,16 +50,16 @@ namespace Fig
|
|||||||
|
|
||||||
ContextPtr Evaluator::loadModule(const std::filesystem::path &path)
|
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);
|
std::ifstream file(path);
|
||||||
assert(file.is_open());
|
assert(file.is_open());
|
||||||
|
|
||||||
std::vector<Ast::AstBase> asts;
|
std::vector<Ast::AstBase> asts;
|
||||||
|
|
||||||
std::vector<FString> modSourceLines;
|
std::vector<String> modSourceLines;
|
||||||
|
|
||||||
if (mod_ast_cache.contains(modSourcePath))
|
if (mod_ast_cache.contains(modSourcePath))
|
||||||
{
|
{
|
||||||
@@ -72,9 +72,9 @@ namespace Fig
|
|||||||
std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
file.close();
|
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);
|
Parser parser(lexer, modSourcePath, modSourceLines);
|
||||||
|
|
||||||
asts = parser.parseAll();
|
asts = parser.parseAll();
|
||||||
@@ -85,7 +85,7 @@ namespace Fig
|
|||||||
evaluator.SetSourcePath(modSourcePath);
|
evaluator.SetSourcePath(modSourcePath);
|
||||||
evaluator.SetSourceLines(modSourceLines);
|
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.SetGlobalContext(modctx);
|
||||||
evaluator.RegisterBuiltinsValue();
|
evaluator.RegisterBuiltinsValue();
|
||||||
@@ -96,10 +96,10 @@ namespace Fig
|
|||||||
|
|
||||||
StatementResult Evaluator::evalImportSt(Ast::Import i, ContextPtr ctx)
|
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
|
String modName = pathVec.back(); // pathVec at least has 1 element
|
||||||
if (modName == u8"_builtins")
|
if (modName == U"\1")
|
||||||
{
|
{
|
||||||
RegisterBuiltins();
|
RegisterBuiltins();
|
||||||
return StatementResult::normal();
|
return StatementResult::normal();
|
||||||
@@ -109,8 +109,7 @@ namespace Fig
|
|||||||
|
|
||||||
if (ctx->containsInThisScope(modName))
|
if (ctx->containsInThisScope(modName))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(U"\1", std::format("{} has already been declared.", modName.toBasicString()), i);
|
||||||
u8"RedeclarationError", std::format("{} has already been declared.", modName.toBasicString()), i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto path = resolveModulePath(pathVec);
|
auto path = resolveModulePath(pathVec);
|
||||||
@@ -124,7 +123,7 @@ namespace Fig
|
|||||||
if (ctx->getOpRegistry().contains(type))
|
if (ctx->getOpRegistry().contains(type))
|
||||||
{
|
{
|
||||||
throw EvaluatorError(
|
throw EvaluatorError(
|
||||||
u8"DuplicateOperationOverload",
|
U"\1",
|
||||||
std::format("Module `{}` and current context `{}` have conflict operation overload for `{}` object",
|
std::format("Module `{}` and current context `{}` have conflict operation overload for `{}` object",
|
||||||
modCtx->getScopeName().toBasicString(),
|
modCtx->getScopeName().toBasicString(),
|
||||||
ctx->getScopeName().toBasicString(),
|
ctx->getScopeName().toBasicString(),
|
||||||
@@ -135,7 +134,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
if (!i->names.empty())
|
if (!i->names.empty())
|
||||||
{
|
{
|
||||||
for (const FString &symName : i->names)
|
for (const String &symName : i->names)
|
||||||
{
|
{
|
||||||
LvObject tmp(modCtx->get(symName), modCtx);
|
LvObject tmp(modCtx->get(symName), modCtx);
|
||||||
const ObjectPtr &value = tmp.get();
|
const ObjectPtr &value = tmp.get();
|
||||||
@@ -183,13 +182,13 @@ namespace Fig
|
|||||||
*/
|
*/
|
||||||
const StructInstance &resInst = result->as<StructInstance>();
|
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 = Function(getErrorClassFn.name,
|
||||||
getErrorClassFn.paras,
|
getErrorClassFn.paras,
|
||||||
getErrorClassFn.retType,
|
getErrorClassFn.retType,
|
||||||
getErrorClassFn.body,
|
getErrorClassFn.body,
|
||||||
resInst.localContext);
|
resInst.localContext);
|
||||||
Function getErrorMessageFn = ctx->getImplementedMethod(resultType, u8"getErrorMessage");
|
Function getErrorMessageFn = ctx->getImplementedMethod(resultType, U"\1");
|
||||||
getErrorMessageFn = Function(getErrorMessageFn.name,
|
getErrorMessageFn = Function(getErrorMessageFn.name,
|
||||||
getErrorMessageFn.paras,
|
getErrorMessageFn.paras,
|
||||||
getErrorMessageFn.retType,
|
getErrorMessageFn.retType,
|
||||||
@@ -210,17 +209,16 @@ namespace Fig
|
|||||||
// std::cerr << errorClassRes.unwrap()->toString().toBasicString() << "\n";
|
// std::cerr << errorClassRes.unwrap()->toString().toBasicString() << "\n";
|
||||||
// std::cerr << errorMessageRes.unwrap()->toString().toBasicString() << "\n";
|
// std::cerr << errorMessageRes.unwrap()->toString().toBasicString() << "\n";
|
||||||
|
|
||||||
const FString &errorClass = errorClassRes.unwrap()->as<ValueType::StringClass>();
|
const String &errorClass = errorClassRes.unwrap()->as<ValueType::StringClass>();
|
||||||
const FString &errorMessage = errorMessageRes.unwrap()->as<ValueType::StringClass>();
|
const String &errorMessage = errorMessageRes.unwrap()->as<ValueType::StringClass>();
|
||||||
|
|
||||||
ErrorLog::logFigErrorInterface(errorClass, errorMessage);
|
ErrorLog::logFigErrorInterface(errorClass, errorMessage);
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw EvaluatorError(u8"UncaughtExceptionError",
|
throw EvaluatorError(
|
||||||
std::format("Uncaught exception: {}", sr.result->toString().toBasicString()),
|
U"\1", std::format("Uncaught exception: {}", sr.result->toString().toBasicString()), stmt);
|
||||||
stmt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,12 +34,12 @@ namespace Fig
|
|||||||
ContextPtr global;
|
ContextPtr global;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FString sourcePath;
|
String sourcePath;
|
||||||
std::vector<FString> sourceLines;
|
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)
|
void SetGlobalContext(ContextPtr ctx)
|
||||||
{
|
{
|
||||||
@@ -47,7 +47,7 @@ namespace Fig
|
|||||||
global = ctx;
|
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
|
void RegisterBuiltins() // only function
|
||||||
{
|
{
|
||||||
@@ -67,33 +67,31 @@ namespace Fig
|
|||||||
.interfaceType = Builtins::getErrorInterfaceTypeInfo(),
|
.interfaceType = Builtins::getErrorInterfaceTypeInfo(),
|
||||||
.structType = Builtins::getTypeErrorStructTypeInfo(),
|
.structType = Builtins::getTypeErrorStructTypeInfo(),
|
||||||
.implMethods = {
|
.implMethods = {
|
||||||
{u8"toString",
|
{U"\1",
|
||||||
Function(
|
Function(U"\1",
|
||||||
u8"toString",
|
Ast::FunctionParameters{},
|
||||||
Ast::FunctionParameters{},
|
ValueType::String,
|
||||||
ValueType::String,
|
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
|
||||||
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
|
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::BinaryExprAst>(
|
||||||
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::BinaryExprAst>(
|
std::make_shared<Ast::ValueExprAst>(std::make_shared<Object>(U"\1")),
|
||||||
std::make_shared<Ast::ValueExprAst>(std::make_shared<Object>(u8"TypeError: ")),
|
Ast::Operator::Add,
|
||||||
Ast::Operator::Add,
|
std::make_shared<Ast::FunctionCallExpr>(
|
||||||
std::make_shared<Ast::FunctionCallExpr>(
|
std::make_shared<Ast::VarExprAst>(U"\1"), Ast::FunctionArguments{})))})),
|
||||||
std::make_shared<Ast::VarExprAst>(u8"getErrorMessage"),
|
nullptr)},
|
||||||
Ast::FunctionArguments{})))})),
|
{U"\1",
|
||||||
nullptr)},
|
Function(U"\1",
|
||||||
{u8"getErrorClass",
|
|
||||||
Function(u8"getErrorClass",
|
|
||||||
Ast::FunctionParameters{},
|
Ast::FunctionParameters{},
|
||||||
ValueType::String,
|
ValueType::String,
|
||||||
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
|
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
|
||||||
{std::make_shared<Ast::ReturnSt>(std::make_shared<Ast::ValueExprAst>(
|
{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)},
|
nullptr)},
|
||||||
{u8"getErrorMessage",
|
{U"\1",
|
||||||
Function(u8"getErrorMessage",
|
Function(U"\1",
|
||||||
Ast::FunctionParameters{},
|
Ast::FunctionParameters{},
|
||||||
ValueType::String,
|
ValueType::String,
|
||||||
std::make_shared<Ast::BlockStatementAst>(std::vector<Ast::Statement>(
|
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)},
|
nullptr)},
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
@@ -110,13 +108,13 @@ namespace Fig
|
|||||||
|
|
||||||
bool isInterfaceSignatureMatch(const Ast::ImplementMethod &, const Ast::InterfaceMethod &);
|
bool isInterfaceSignatureMatch(const Ast::ImplementMethod &, const Ast::InterfaceMethod &);
|
||||||
|
|
||||||
ObjectPtr genTypeError(const FString &_msg,
|
ObjectPtr genTypeError(const String &_msg,
|
||||||
const Ast::AstBase &_ast,
|
const Ast::AstBase &_ast,
|
||||||
ContextPtr ctx,
|
ContextPtr ctx,
|
||||||
std::source_location loc = std::source_location::current())
|
std::source_location loc = std::source_location::current())
|
||||||
{
|
{
|
||||||
ContextPtr stCtx = std::make_shared<Context>(u8"<TypeError Instance>");
|
ContextPtr stCtx = std::make_shared<Context>(U"\1");
|
||||||
stCtx->def(u8"msg", ValueType::String, AccessModifier::Const, std::make_shared<Object>(_msg));
|
stCtx->def(U"\1", ValueType::String, AccessModifier::Const, std::make_shared<Object>(_msg));
|
||||||
return std::make_shared<Object>(StructInstance(Builtins::getTypeErrorStructTypeInfo(), stCtx));
|
return std::make_shared<Object>(StructInstance(Builtins::getTypeErrorStructTypeInfo(), stCtx));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +141,7 @@ 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> &);
|
std::filesystem::path resolveModulePath(const std::vector<String> &);
|
||||||
ContextPtr loadModule(const std::filesystem::path &);
|
ContextPtr loadModule(const std::filesystem::path &);
|
||||||
|
|
||||||
StatementResult evalImportSt(Ast::Import, ContextPtr);
|
StatementResult evalImportSt(Ast::Import, ContextPtr);
|
||||||
|
|||||||
@@ -8,16 +8,15 @@ namespace Fig
|
|||||||
class EvaluatorError final : public AddressableError
|
class EvaluatorError final : public AddressableError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FString typeName;
|
String typeName;
|
||||||
using AddressableError::AddressableError;
|
using AddressableError::AddressableError;
|
||||||
EvaluatorError(FString _typeName,
|
EvaluatorError(String _typeName,
|
||||||
FString msg,
|
String msg,
|
||||||
Ast::AstBase ast,
|
Ast::AstBase ast,
|
||||||
std::source_location loc = std::source_location::current())
|
std::source_location loc = std::source_location::current())
|
||||||
{
|
{
|
||||||
message = msg;
|
message = msg;
|
||||||
|
|
||||||
|
|
||||||
src_loc = std::move(loc);
|
src_loc = std::move(loc);
|
||||||
|
|
||||||
typeName = std::move(_typeName);
|
typeName = std::move(_typeName);
|
||||||
@@ -29,25 +28,24 @@ namespace Fig
|
|||||||
sourcePath = *ast->getAAI().sourcePath;
|
sourcePath = *ast->getAAI().sourcePath;
|
||||||
sourceLines = *ast->getAAI().sourceLines;
|
sourceLines = *ast->getAAI().sourceLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
EvaluatorError(FString _typeName,
|
// EvaluatorError(String _typeName,
|
||||||
std::string_view msg,
|
// std::string_view msg,
|
||||||
Ast::AstBase ast,
|
// Ast::AstBase ast,
|
||||||
std::source_location loc = std::source_location::current())
|
// std::source_location loc = std::source_location::current())
|
||||||
{
|
// {
|
||||||
message = FString::fromBasicString(std::string(msg.data()));
|
// message = String(std::string(msg.data()));
|
||||||
line = ast->getAAI().line;
|
// line = ast->getAAI().line;
|
||||||
column = ast->getAAI().column;
|
// 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;
|
// sourcePath = *ast->getAAI().sourcePath;
|
||||||
sourceLines = *ast->getAAI().sourceLines;
|
// sourceLines = *ast->getAAI().sourceLines;
|
||||||
}
|
// }
|
||||||
|
|
||||||
virtual FString getErrorType() const override { return typeName; }
|
virtual String getErrorType() const override { return typeName; }
|
||||||
};
|
};
|
||||||
}; // namespace Fig
|
}; // namespace Fig
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -51,12 +51,12 @@ namespace Fig::IR
|
|||||||
|
|
||||||
struct Function
|
struct Function
|
||||||
{
|
{
|
||||||
FString name;
|
String name;
|
||||||
|
|
||||||
uint16_t paramCount;
|
uint16_t paramCount;
|
||||||
uint16_t localCount; // 不含参数
|
uint16_t localCount; // 不含参数
|
||||||
uint16_t regCount; // param + locals + temps
|
uint16_t regCount; // param + locals + temps
|
||||||
|
|
||||||
std::vector<Inst> code;
|
std::vector<Inst> code;
|
||||||
};
|
};
|
||||||
};
|
}; // namespace Fig::IR
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
#include <Core/fig_string.hpp>
|
|
||||||
#include <Error/error.hpp>
|
#include <Error/error.hpp>
|
||||||
#include <Token/token.hpp>
|
#include <Token/token.hpp>
|
||||||
#include <Lexer/lexer.hpp>
|
#include <Lexer/lexer.hpp>
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
|
#include <Core/CharUtils.hpp>
|
||||||
#include <Utils/utils.hpp>
|
#include <Utils/utils.hpp>
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@@ -17,113 +17,110 @@
|
|||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
|
|
||||||
const std::unordered_map<FString, TokenType> Lexer::symbol_map{
|
const std::unordered_map<String, TokenType> Lexer::symbol_map{
|
||||||
// 三字符
|
// 三字符
|
||||||
{FString(u8"..."), TokenType::TripleDot},
|
{String(U"..."), TokenType::TripleDot},
|
||||||
// 双字符
|
// 双字符
|
||||||
{FString(u8"=="), TokenType::Equal},
|
{String(U"=="), TokenType::Equal},
|
||||||
{FString(u8"!="), TokenType::NotEqual},
|
{String(U"!="), TokenType::NotEqual},
|
||||||
{FString(u8"<="), TokenType::LessEqual},
|
{String(U"<="), TokenType::LessEqual},
|
||||||
{FString(u8">="), TokenType::GreaterEqual},
|
{String(U">="), TokenType::GreaterEqual},
|
||||||
{FString(u8"<<"), TokenType::ShiftLeft},
|
{String(U"<<"), TokenType::ShiftLeft},
|
||||||
{FString(u8">>"), TokenType::ShiftRight},
|
{String(U">>"), TokenType::ShiftRight},
|
||||||
{FString(u8"+="), TokenType::PlusEqual},
|
{String(U"+="), TokenType::PlusEqual},
|
||||||
{FString(u8"-="), TokenType::MinusEqual},
|
{String(U"-="), TokenType::MinusEqual},
|
||||||
{FString(u8"*="), TokenType::AsteriskEqual},
|
{String(U"*="), TokenType::AsteriskEqual},
|
||||||
{FString(u8"/="), TokenType::SlashEqual},
|
{String(U"/="), TokenType::SlashEqual},
|
||||||
{FString(u8"%="), TokenType::PercentEqual},
|
{String(U"%="), TokenType::PercentEqual},
|
||||||
{FString(u8"^="), TokenType::CaretEqual},
|
{String(U"^="), TokenType::CaretEqual},
|
||||||
{FString(u8"++"), TokenType::DoublePlus},
|
{String(U"++"), TokenType::DoublePlus},
|
||||||
{FString(u8"--"), TokenType::DoubleMinus},
|
{String(U"--"), TokenType::DoubleMinus},
|
||||||
{FString(u8"&&"), TokenType::DoubleAmpersand},
|
{String(U"&&"), TokenType::DoubleAmpersand},
|
||||||
{FString(u8"||"), TokenType::DoublePipe},
|
{String(U"||"), TokenType::DoublePipe},
|
||||||
{FString(u8":="), TokenType::Walrus},
|
{String(U":="), TokenType::Walrus},
|
||||||
{FString(u8"**"), TokenType::Power},
|
{String(U"**"), TokenType::Power},
|
||||||
{FString(u8"->"), TokenType::RightArrow},
|
{String(U"->"), TokenType::RightArrow},
|
||||||
{FString(u8"=>"), TokenType::DoubleArrow},
|
{String(U"=>"), TokenType::DoubleArrow},
|
||||||
|
|
||||||
// 单字符
|
// 单字符
|
||||||
{FString(u8"+"), TokenType::Plus},
|
{String(U"+"), TokenType::Plus},
|
||||||
{FString(u8"-"), TokenType::Minus},
|
{String(U"-"), TokenType::Minus},
|
||||||
{FString(u8"*"), TokenType::Asterisk},
|
{String(U"*"), TokenType::Asterisk},
|
||||||
{FString(u8"/"), TokenType::Slash},
|
{String(U"/"), TokenType::Slash},
|
||||||
{FString(u8"%"), TokenType::Percent},
|
{String(U"%"), TokenType::Percent},
|
||||||
{FString(u8"^"), TokenType::Caret},
|
{String(U"^"), TokenType::Caret},
|
||||||
{FString(u8"&"), TokenType::Ampersand},
|
{String(U"&"), TokenType::Ampersand},
|
||||||
{FString(u8"|"), TokenType::Pipe},
|
{String(U"|"), TokenType::Pipe},
|
||||||
{FString(u8"~"), TokenType::Tilde},
|
{String(U"~"), TokenType::Tilde},
|
||||||
{FString(u8"="), TokenType::Assign},
|
{String(U"="), TokenType::Assign},
|
||||||
{FString(u8"<"), TokenType::Less},
|
{String(U"<"), TokenType::Less},
|
||||||
{FString(u8">"), TokenType::Greater},
|
{String(U">"), TokenType::Greater},
|
||||||
{FString(u8"."), TokenType::Dot},
|
{String(U"."), TokenType::Dot},
|
||||||
{FString(u8","), TokenType::Comma},
|
{String(U","), TokenType::Comma},
|
||||||
{FString(u8":"), TokenType::Colon},
|
{String(U":"), TokenType::Colon},
|
||||||
{FString(u8";"), TokenType::Semicolon},
|
{String(U";"), TokenType::Semicolon},
|
||||||
{FString(u8"'"), TokenType::SingleQuote},
|
{String(U"'"), TokenType::SingleQuote},
|
||||||
{FString(u8"\""), TokenType::DoubleQuote},
|
{String(U"\""), TokenType::DoubleQuote},
|
||||||
{FString(u8"("), TokenType::LeftParen},
|
{String(U"("), TokenType::LeftParen},
|
||||||
{FString(u8")"), TokenType::RightParen},
|
{String(U")"), TokenType::RightParen},
|
||||||
{FString(u8"["), TokenType::LeftBracket},
|
{String(U"["), TokenType::LeftBracket},
|
||||||
{FString(u8"]"), TokenType::RightBracket},
|
{String(U"]"), TokenType::RightBracket},
|
||||||
{FString(u8"{"), TokenType::LeftBrace},
|
{String(U"{"), TokenType::LeftBrace},
|
||||||
{FString(u8"}"), TokenType::RightBrace},
|
{String(U"}"), TokenType::RightBrace},
|
||||||
{FString(u8"?"), TokenType::Question},
|
{String(U"?"), TokenType::Question},
|
||||||
{FString(u8"!"), TokenType::Not},
|
{String(U"!"), TokenType::Not},
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::unordered_map<FString, TokenType> Lexer::keyword_map{
|
const std::unordered_map<String, TokenType> Lexer::keyword_map{
|
||||||
{FString(u8"and"), TokenType::And},
|
{String(U"and"), TokenType::And},
|
||||||
{FString(u8"or"), TokenType::Or},
|
{String(U"or"), TokenType::Or},
|
||||||
{FString(u8"not"), TokenType::Not},
|
{String(U"not"), TokenType::Not},
|
||||||
{FString(u8"import"), TokenType::Import},
|
{String(U"import"), TokenType::Import},
|
||||||
{FString(u8"func"), TokenType::Function},
|
{String(U"func"), TokenType::Function},
|
||||||
{FString(u8"var"), TokenType::Variable},
|
{String(U"var"), TokenType::Variable},
|
||||||
{FString(u8"const"), TokenType::Const},
|
{String(U"const"), TokenType::Const},
|
||||||
// {FString(u8"final"), TokenType::Final},
|
// {String(U"final"), TokenType::Final},
|
||||||
{FString(u8"while"), TokenType::While},
|
{String(U"while"), TokenType::While},
|
||||||
{FString(u8"for"), TokenType::For},
|
{String(U"for"), TokenType::For},
|
||||||
{FString(u8"if"), TokenType::If},
|
{String(U"if"), TokenType::If},
|
||||||
{FString(u8"else"), TokenType::Else},
|
{String(U"else"), TokenType::Else},
|
||||||
{FString(u8"new"), TokenType::New},
|
{String(U"new"), TokenType::New},
|
||||||
{FString(u8"struct"), TokenType::Struct},
|
{String(U"struct"), TokenType::Struct},
|
||||||
{FString(u8"interface"), TokenType::Interface},
|
{String(U"interface"), TokenType::Interface},
|
||||||
{FString(u8"impl"), TokenType::Implement},
|
{String(U"impl"), TokenType::Implement},
|
||||||
{FString(u8"is"), TokenType::Is},
|
{String(U"is"), TokenType::Is},
|
||||||
{FString(u8"public"), TokenType::Public},
|
{String(U"public"), TokenType::Public},
|
||||||
{FString(u8"return"), TokenType::Return},
|
{String(U"return"), TokenType::Return},
|
||||||
{FString(u8"break"), TokenType::Break},
|
{String(U"break"), TokenType::Break},
|
||||||
{FString(u8"continue"), TokenType::Continue},
|
{String(U"continue"), TokenType::Continue},
|
||||||
{FString(u8"try"), TokenType::Try},
|
{String(U"try"), TokenType::Try},
|
||||||
{FString(u8"catch"), TokenType::Catch},
|
{String(U"catch"), TokenType::Catch},
|
||||||
{FString(u8"throw"), TokenType::Throw},
|
{String(U"throw"), TokenType::Throw},
|
||||||
{FString(u8"Finally"), TokenType::Finally},
|
{String(U"Finally"), TokenType::Finally},
|
||||||
{FString(u8"as"), TokenType::As},
|
{String(U"as"), TokenType::As},
|
||||||
|
|
||||||
// {FString(u8"Null"), TokenType::TypeNull},
|
// {String(U"Null"), TokenType::TypeNull},
|
||||||
// {FString(u8"Int"), TokenType::TypeInt},
|
// {String(U"Int"), TokenType::TypeInt},
|
||||||
// {FString(u8"String"), TokenType::TypeString},
|
// {String(U"String"), TokenType::TypeString},
|
||||||
// {FString(u8"Bool"), TokenType::TypeBool},
|
// {String(U"Bool"), TokenType::TypeBool},
|
||||||
// {FString(u8"Double"), TokenType::TypeDouble},
|
// {String(U"Double"), TokenType::TypeDouble},
|
||||||
};
|
};
|
||||||
void Lexer::skipLine()
|
void Lexer::skipLine()
|
||||||
{
|
{
|
||||||
while (*it != U'\n' and hasNext())
|
while (current() != U'\n' and hasNext()) { next(); }
|
||||||
{
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
next(); // skip '\n'
|
next(); // skip '\n'
|
||||||
++line;
|
++line;
|
||||||
}
|
}
|
||||||
Token Lexer::scanIdentifier()
|
Token Lexer::scanIdentifier()
|
||||||
{
|
{
|
||||||
FString identifier;
|
String identifier;
|
||||||
|
|
||||||
while (hasNext())
|
while (hasNext())
|
||||||
{
|
{
|
||||||
UTF8Char c = *it;
|
char32_t c = current();
|
||||||
if (c.isAlnum() || c == U'_')
|
if (CharUtils::isAlnum(c) || c == U'_')
|
||||||
{
|
{
|
||||||
identifier += c.getString();
|
identifier += c;
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -131,23 +128,27 @@ namespace Fig
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this->keyword_map.contains(identifier))
|
if (this->keyword_map.contains(identifier)) { return Token(identifier, this->keyword_map.at(identifier)); }
|
||||||
{
|
else if (identifier == U"\1" || identifier == U"\1") { return Token(identifier, TokenType::LiteralBool); }
|
||||||
return Token(identifier, this->keyword_map.at(identifier));
|
else if (identifier == U"\1")
|
||||||
}
|
|
||||||
else if (identifier == u8"true" || identifier == u8"false")
|
|
||||||
{
|
|
||||||
return Token(identifier, TokenType::LiteralBool);
|
|
||||||
}
|
|
||||||
else if (identifier == u8"null")
|
|
||||||
{
|
{
|
||||||
// null instance
|
// null instance
|
||||||
return Token(identifier, TokenType::LiteralNull);
|
return Token(identifier, TokenType::LiteralNull);
|
||||||
}
|
}
|
||||||
if (keyword_map.contains(Utils::toLower(identifier)))
|
// const auto &toLower = [](const String &str) -> String
|
||||||
{
|
// {
|
||||||
pushWarning(1, identifier); // Identifier is too similar to a keyword or a primitive type
|
// String res;
|
||||||
}
|
// for (auto c : str)
|
||||||
|
// {
|
||||||
|
// res += CharUtils::toLower(c);
|
||||||
|
// }
|
||||||
|
// return res;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// if (keyword_map.contains(toLower(identifier)))
|
||||||
|
// {
|
||||||
|
// pushWarning(1, identifier); // Identifier is too similar to a keyword or a primitive type
|
||||||
|
// }
|
||||||
if (identifier.length() <= 1)
|
if (identifier.length() <= 1)
|
||||||
{
|
{
|
||||||
pushWarning(2, identifier); // The identifier is too abstract
|
pushWarning(2, identifier); // The identifier is too abstract
|
||||||
@@ -156,12 +157,12 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
Token Lexer::scanString()
|
Token Lexer::scanString()
|
||||||
{
|
{
|
||||||
FString str;
|
String str;
|
||||||
bool unterminated = true;
|
bool unterminated = true;
|
||||||
size_t str_start_col = it.column() - 1;
|
size_t str_start_col = column - 1;
|
||||||
while (hasNext())
|
while (hasNext())
|
||||||
{
|
{
|
||||||
UTF8Char c = *it;
|
char32_t c = current();
|
||||||
if (c == U'"' || c == U'\n')
|
if (c == U'"' || c == U'\n')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
@@ -170,74 +171,74 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else if (c == U'\\') // c is '\'
|
else if (c == U'\\') // c is '\'
|
||||||
{
|
{
|
||||||
if (it.isEnd())
|
if (!hasNext())
|
||||||
{
|
{
|
||||||
error = SyntaxError(u8"Unterminated FString", this->line, it.column(), SourceInfo(this));
|
error = SyntaxError(U"\1", this->line, column, SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
UTF8Char ec = *it;
|
char32_t ec = current();
|
||||||
if (ec == U'n')
|
if (ec == U'n')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"\n";
|
str += U"\1";
|
||||||
}
|
}
|
||||||
else if (ec == U't')
|
else if (ec == U't')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"\t";
|
str += U"\1";
|
||||||
}
|
}
|
||||||
else if (ec == U'v')
|
else if (ec == U'v')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"\v";
|
str += U"\1";
|
||||||
}
|
}
|
||||||
else if (ec == U'b')
|
else if (ec == U'b')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"\b";
|
str += U"\1";
|
||||||
}
|
}
|
||||||
else if (ec == U'"')
|
else if (ec == U'"')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"\"";
|
str += U"\1";
|
||||||
}
|
}
|
||||||
else if (ec == U'\'')
|
else if (ec == U'\'')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"'";
|
str += U"\1";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error = SyntaxError(FString(std::format("Unsupported escape character: {}",
|
error =
|
||||||
FString(ec.getString()).toBasicString())),
|
SyntaxError(String(std::format("Unsupported escape character: {}", String(ec).toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
str += c.getString();
|
str += c;
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unterminated)
|
if (unterminated)
|
||||||
{
|
{
|
||||||
error = SyntaxError(u8"Unterminated FString", this->line, str_start_col, SourceInfo(this));
|
error = SyntaxError(U"Unterminated FString", this->line, str_start_col, SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
return Token(str, TokenType::LiteralString);
|
return Token(str, TokenType::LiteralString);
|
||||||
}
|
}
|
||||||
Token Lexer::scanRawString()
|
Token Lexer::scanRawString()
|
||||||
{
|
{
|
||||||
FString str;
|
String str;
|
||||||
bool unterminated = true;
|
bool unterminated = true;
|
||||||
size_t str_start_col = it.column() - 1;
|
size_t str_start_col = column - 1;
|
||||||
while (hasNext())
|
while (hasNext())
|
||||||
{
|
{
|
||||||
UTF8Char c = *it;
|
char32_t c = current();
|
||||||
if (c == U'"' || c == U'\n')
|
if (c == U'"' || c == U'\n')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
@@ -246,27 +247,27 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
str += c.getString();
|
str += c;
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unterminated)
|
if (unterminated)
|
||||||
{
|
{
|
||||||
error = SyntaxError(u8"Unterminated FString", this->line, str_start_col, SourceInfo(this));
|
error = SyntaxError(U"Unterminated FString", this->line, str_start_col, SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
return Token(str, TokenType::LiteralString);
|
return Token(str, TokenType::LiteralString);
|
||||||
}
|
}
|
||||||
Token Lexer::scanMultilineString()
|
Token Lexer::scanMultilineString()
|
||||||
{
|
{
|
||||||
FString str;
|
String str;
|
||||||
bool unterminated = true;
|
bool unterminated = true;
|
||||||
|
|
||||||
uint8_t end = 0;
|
uint8_t end = 0;
|
||||||
size_t str_start_col = it.column() - 1;
|
size_t str_start_col = column - 1;
|
||||||
while (hasNext())
|
while (hasNext())
|
||||||
{
|
{
|
||||||
UTF8Char c = *it;
|
char32_t c = current();
|
||||||
if (c == U'"')
|
if (c == U'"')
|
||||||
{
|
{
|
||||||
if (end == 3)
|
if (end == 3)
|
||||||
@@ -281,99 +282,99 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else if (c == U'\\') // c is '\'
|
else if (c == U'\\') // c is '\'
|
||||||
{
|
{
|
||||||
if (it.isEnd())
|
if (!hasNext())
|
||||||
{
|
{
|
||||||
error = SyntaxError(u8"Unterminated FString", this->line, it.column(), SourceInfo(this));
|
error = SyntaxError(U"Unterminated FString", this->line, column, SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
UTF8Char ec = *it;
|
char32_t ec = current();
|
||||||
if (ec == U'n')
|
if (ec == U'n')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"\n";
|
str += U"\n";
|
||||||
}
|
}
|
||||||
else if (ec == U't')
|
else if (ec == U't')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"\t";
|
str += U"\t";
|
||||||
}
|
}
|
||||||
else if (ec == U'v')
|
else if (ec == U'v')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"\v";
|
str += U"\v";
|
||||||
}
|
}
|
||||||
else if (ec == U'b')
|
else if (ec == U'b')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"\b";
|
str += U"\b";
|
||||||
}
|
}
|
||||||
else if (ec == U'"')
|
else if (ec == U'"')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"\"";
|
str += U"\"";
|
||||||
}
|
}
|
||||||
else if (ec == U'\'')
|
else if (ec == U'\'')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"'";
|
str += U"\'";
|
||||||
}
|
}
|
||||||
else if (ec == U'\\')
|
else if (ec == U'\\')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
str += u8"\\";
|
str += U"\\";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error = SyntaxError(FString(std::format("Unsupported escape character: {}",
|
error = SyntaxError(
|
||||||
FString(ec.getString()).toBasicString())),
|
String(std::format("Unsupported escape character: {}", String(ec).toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
str += c.getString();
|
str += c;
|
||||||
}
|
}
|
||||||
end = 0;
|
end = 0;
|
||||||
}
|
}
|
||||||
if (unterminated)
|
if (unterminated)
|
||||||
{
|
{
|
||||||
error = SyntaxError(u8"Unterminated FString", this->line, str_start_col, SourceInfo(this));
|
error = SyntaxError(U"\1", this->line, str_start_col, SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
return Token(str, TokenType::LiteralString);
|
return Token(str, TokenType::LiteralString);
|
||||||
}
|
}
|
||||||
Token Lexer::scanNumber()
|
Token Lexer::scanNumber()
|
||||||
{
|
{
|
||||||
FString numStr;
|
String numStr;
|
||||||
bool hasPoint = false;
|
bool hasPoint = false;
|
||||||
|
|
||||||
while (hasNext())
|
while (hasNext())
|
||||||
{
|
{
|
||||||
UTF8Char ch = *it;
|
char32_t ch = current();
|
||||||
|
|
||||||
if (ch.isDigit() || ch == U'e')
|
if (CharUtils::isDigit(ch) || ch == U'e')
|
||||||
{
|
{
|
||||||
numStr += ch.getString();
|
numStr += ch;
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
else if (ch == U'-' && !numStr.empty() && (numStr.ends_with(U'e') || numStr.ends_with(U'E')))
|
else if (ch == U'-' && !numStr.empty() && (numStr.ends_with(U'e') || numStr.ends_with(U'E')))
|
||||||
{
|
{
|
||||||
numStr += ch.getString();
|
numStr += ch;
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
else if (ch == U'+' && !numStr.empty() && (numStr.ends_with(U'e') || numStr.ends_with(U'E')))
|
else if (ch == U'+' && !numStr.empty() && (numStr.ends_with(U'e') || numStr.ends_with(U'E')))
|
||||||
{
|
{
|
||||||
numStr += ch.getString();
|
numStr += ch;
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
else if (ch == U'.' && !hasPoint)
|
else if (ch == U'.' && !hasPoint)
|
||||||
{
|
{
|
||||||
hasPoint = true;
|
hasPoint = true;
|
||||||
numStr += ch.getString();
|
numStr += ch;
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -385,9 +386,9 @@ namespace Fig
|
|||||||
|
|
||||||
if (numStr.ends_with(U'e'))
|
if (numStr.ends_with(U'e'))
|
||||||
{
|
{
|
||||||
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
@@ -395,7 +396,7 @@ namespace Fig
|
|||||||
bool hasDigit = false;
|
bool hasDigit = false;
|
||||||
for (auto it = numStr.begin(); it != numStr.end(); ++it)
|
for (auto it = numStr.begin(); it != numStr.end(); ++it)
|
||||||
{
|
{
|
||||||
if (isdigit(*it))
|
if (CharUtils::isDigit(*it))
|
||||||
{
|
{
|
||||||
hasDigit = true;
|
hasDigit = true;
|
||||||
break;
|
break;
|
||||||
@@ -404,55 +405,55 @@ namespace Fig
|
|||||||
|
|
||||||
if (!hasDigit)
|
if (!hasDigit)
|
||||||
{
|
{
|
||||||
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ePos = numStr.find(U'e');
|
size_t ePos = numStr.find(U'e');
|
||||||
if (ePos != FString::npos)
|
if (ePos != String::npos)
|
||||||
{
|
{
|
||||||
if (ePos == 0)
|
if (ePos == 0)
|
||||||
{
|
{
|
||||||
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
if (ePos + 1 >= numStr.length())
|
if (ePos + 1 >= numStr.length())
|
||||||
{
|
{
|
||||||
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
bool hasDigitAfterE = false;
|
bool hasDigitAfterE = false;
|
||||||
for (size_t i = ePos + 1; i < numStr.length(); ++i)
|
for (size_t i = ePos + 1; i < numStr.length(); ++i)
|
||||||
{
|
{
|
||||||
UTF8Char c = std::u8string(1,numStr[i]);
|
char32_t c = numStr[i];
|
||||||
if (c == U'+' || c == U'-')
|
if (c == U'+' || c == U'-')
|
||||||
{
|
{
|
||||||
if (i != ePos + 1)
|
if (i != ePos + 1)
|
||||||
{
|
{
|
||||||
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.isDigit()) { hasDigitAfterE = true; }
|
if (CharUtils::isDigit(c)) { hasDigitAfterE = true; }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
@@ -460,9 +461,9 @@ namespace Fig
|
|||||||
|
|
||||||
if (!hasDigitAfterE)
|
if (!hasDigitAfterE)
|
||||||
{
|
{
|
||||||
error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
@@ -472,25 +473,24 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
Token Lexer::scanSymbol()
|
Token Lexer::scanSymbol()
|
||||||
{
|
{
|
||||||
FString sym;
|
String sym;
|
||||||
UTF8Char ch = *it;
|
char32_t ch = current();
|
||||||
sym += ch.getString();
|
sym += ch;
|
||||||
|
|
||||||
auto startsWith = [&](const FString &prefix) -> bool {
|
auto startsWith = [&](const String &prefix) -> bool {
|
||||||
for (const auto &p : symbol_map)
|
for (const auto &p : symbol_map)
|
||||||
{
|
{
|
||||||
const FString &op = p.first;
|
const String &op = p.first;
|
||||||
if (op.starts_with(prefix))
|
if (op.starts_with(prefix)) return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!startsWith(sym))
|
if (!startsWith(sym))
|
||||||
{
|
{
|
||||||
error = SyntaxError(FString(std::format("No such operator: {}", sym.toBasicString())),
|
error = SyntaxError(String(std::format("No such operator: {}", sym.toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
next();
|
next();
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
@@ -498,11 +498,10 @@ namespace Fig
|
|||||||
|
|
||||||
while (hasNext())
|
while (hasNext())
|
||||||
{
|
{
|
||||||
UTF8Char peek = it.peek();
|
char32_t peek_ch = peek();
|
||||||
if (!peek.isPunct())
|
if (!CharUtils::isPunct(peek_ch)) break;
|
||||||
break;
|
|
||||||
|
|
||||||
FString candidate = sym + FString(peek.getString());
|
String candidate = sym + peek_ch;
|
||||||
|
|
||||||
if (startsWith(candidate))
|
if (startsWith(candidate))
|
||||||
{
|
{
|
||||||
@@ -517,9 +516,9 @@ namespace Fig
|
|||||||
|
|
||||||
if (!symbol_map.contains(sym))
|
if (!symbol_map.contains(sym))
|
||||||
{
|
{
|
||||||
error = SyntaxError(FString(std::format("No such operator: {}", sym.toBasicString())),
|
error = SyntaxError(String(std::format("No such operator: {}", sym.toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
next();
|
next();
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
@@ -533,37 +532,34 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
// entry: when iterator current char is '/' and peek is '/' or '*'
|
// entry: when iterator current char is '/' and peek is '/' or '*'
|
||||||
// current char is '/'
|
// current char is '/'
|
||||||
FString comment;
|
String comment;
|
||||||
|
|
||||||
if (it.peek() == U'/') // single-line comment
|
if (peek() == U'/') // single-line comment
|
||||||
{
|
{
|
||||||
next(); // skip first '/'
|
next(); // skip first '/'
|
||||||
next(); // skip second '/'
|
next(); // skip second '/'
|
||||||
|
|
||||||
UTF8Char c = *it;
|
char32_t c = current();
|
||||||
while (c != U'\n' and hasNext())
|
while (c != U'\n' and hasNext())
|
||||||
{
|
{
|
||||||
comment += c.getString();
|
comment += c;
|
||||||
next();
|
next();
|
||||||
c = *it;
|
c = current();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasNext() && c == U'\n')
|
if (hasNext() && c == U'\n') { next(); }
|
||||||
{
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else // multi-line comment
|
else // multi-line comment
|
||||||
{
|
{
|
||||||
next(); // skip '/'
|
next(); // skip '/'
|
||||||
next(); // skip '*'
|
next(); // skip '*'
|
||||||
|
|
||||||
UTF8Char c = *it;
|
char32_t c = current();
|
||||||
bool terminated = false;
|
bool terminated = false;
|
||||||
|
|
||||||
while (hasNext())
|
while (hasNext())
|
||||||
{
|
{
|
||||||
if (c == U'*' and hasNext() and it.peek() == U'/')
|
if (c == U'*' and hasNext() and peek() == U'/')
|
||||||
{
|
{
|
||||||
next(); // skip '*'
|
next(); // skip '*'
|
||||||
next(); // skip '/'
|
next(); // skip '/'
|
||||||
@@ -572,16 +568,15 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
comment += c.getString();
|
comment += c;
|
||||||
next();
|
next();
|
||||||
c = *it;
|
c = current();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!terminated)
|
if (!terminated)
|
||||||
{
|
{
|
||||||
error =
|
error = SyntaxError(String(U"\1"), this->line, column, SourceInfo(this));
|
||||||
SyntaxError(FString(u8"Unterminated multiline comment"), this->line, it.column(), SourceInfo(this));
|
|
||||||
next();
|
next();
|
||||||
return IllegalTok;
|
return IllegalTok;
|
||||||
}
|
}
|
||||||
@@ -591,76 +586,61 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
Token Lexer::nextToken()
|
Token Lexer::nextToken()
|
||||||
{
|
{
|
||||||
if (!hasNext())
|
if (!hasNext()) { return EOFTok.setPos(getCurrentLine(), getCurrentColumn()); }
|
||||||
|
char32_t ch = current();
|
||||||
|
while (hasNext())
|
||||||
{
|
{
|
||||||
return EOFTok;
|
ch = current();
|
||||||
}
|
if (!CharUtils::isSpace(ch))
|
||||||
UTF8Char ch = *it;
|
|
||||||
while (ch.isSpace())
|
|
||||||
{
|
|
||||||
next();
|
|
||||||
ch = *it;
|
|
||||||
if (!hasNext())
|
|
||||||
{
|
{
|
||||||
return EOFTok.setPos(getCurrentLine(), getCurrentColumn());
|
break;
|
||||||
}
|
}
|
||||||
|
next();
|
||||||
}
|
}
|
||||||
last_line = getCurrentLine();
|
last_line = getCurrentLine();
|
||||||
last_column = getCurrentColumn();
|
last_column = getCurrentColumn();
|
||||||
if (ch == U'/')
|
if (ch == U'/')
|
||||||
{
|
{
|
||||||
UTF8Char c{u8""};
|
char32_t c;
|
||||||
if (!hasNext())
|
if (!hasNext())
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
return Token(u8"/", this->symbol_map.at(u8"/")).setPos(last_line, last_column);
|
return Token(U"\1", this->symbol_map.at(U"\1")).setPos(last_line, last_column);
|
||||||
}
|
}
|
||||||
c = it.peek();
|
c = peek();
|
||||||
if (c != U'/' and c != U'*')
|
if (c != U'/' and c != U'*')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
return Token(u8"/", this->symbol_map.at(u8"/")).setPos(last_line, last_column);
|
return Token(U"\1", this->symbol_map.at(U"\1")).setPos(last_line, last_column);
|
||||||
}
|
}
|
||||||
scanComments().setPos(last_line, last_column);
|
scanComments().setPos(last_line, last_column);
|
||||||
return nextToken();
|
return nextToken();
|
||||||
// now we ignore comments to avoid some stupid bugs
|
// now we ignore comments to avoid some stupid bugs
|
||||||
}
|
}
|
||||||
if (ch == U'r' and hasNext() and it.peek() == U'"')
|
if (ch == U'r' and hasNext() and peek() == U'"')
|
||||||
{
|
{
|
||||||
// r""
|
// r""
|
||||||
// raw FString
|
// raw String
|
||||||
next();
|
next();
|
||||||
next();
|
next();
|
||||||
return scanRawString().setPos(last_line, last_column);
|
return scanRawString().setPos(last_line, last_column);
|
||||||
}
|
}
|
||||||
if (ch.isAlpha() || ch == U'_')
|
if (CharUtils::isAlpha(ch) || ch == U'_') { return scanIdentifier().setPos(last_line, last_column); }
|
||||||
{
|
|
||||||
return scanIdentifier().setPos(last_line, last_column);
|
|
||||||
}
|
|
||||||
else if (ch == U'"')
|
else if (ch == U'"')
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
return scanString().setPos(last_line, last_column);
|
return scanString().setPos(last_line, last_column);
|
||||||
}
|
}
|
||||||
else if (ch.isDigit())
|
else if (CharUtils::isDigit(ch)) { return scanNumber().setPos(last_line, last_column); }
|
||||||
{
|
else if (CharUtils::isPunct(ch)) { return scanSymbol().setPos(last_line, last_column); }
|
||||||
return scanNumber().setPos(last_line, last_column);
|
|
||||||
}
|
|
||||||
else if (ch.isPunct())
|
|
||||||
{
|
|
||||||
return scanSymbol().setPos(last_line, last_column);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error =
|
error =
|
||||||
SyntaxError(FString(std::format("Cannot tokenize char: '{}'", FString(ch.getString()).toBasicString())),
|
SyntaxError(String(std::format("Cannot tokenize char: '{}'", String(ch).toBasicString())),
|
||||||
this->line,
|
this->line,
|
||||||
it.column(),
|
column,
|
||||||
SourceInfo(this));
|
SourceInfo(this));
|
||||||
if (hasNext())
|
if (hasNext()) { next(); }
|
||||||
{
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
return IllegalTok.setPos(last_line, last_column);
|
return IllegalTok.setPos(last_line, last_column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,7 @@
|
|||||||
|
|
||||||
#include <Token/token.hpp>
|
#include <Token/token.hpp>
|
||||||
#include <Error/error.hpp>
|
#include <Error/error.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Core/utf8_iterator.hpp>
|
|
||||||
#include <Core/warning.hpp>
|
#include <Core/warning.hpp>
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
@@ -19,26 +18,33 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
size_t line;
|
size_t line;
|
||||||
const FString source;
|
const String source;
|
||||||
SyntaxError error;
|
SyntaxError error;
|
||||||
UTF8Iterator it;
|
|
||||||
|
|
||||||
FString sourcePath;
|
|
||||||
std::vector<FString> sourceLines;
|
|
||||||
|
|
||||||
|
String sourcePath;
|
||||||
|
std::vector<String> sourceLines;
|
||||||
std::vector<Warning> warnings;
|
std::vector<Warning> warnings;
|
||||||
|
|
||||||
|
int64_t idx = 0;
|
||||||
|
|
||||||
size_t last_line, last_column, column = 1;
|
size_t last_line, last_column, column = 1;
|
||||||
|
|
||||||
bool hasNext()
|
char32_t current() const { return source[idx]; }
|
||||||
{
|
|
||||||
return !this->it.isEnd();
|
char32_t peek() const {
|
||||||
|
if (idx + 1 >= source.length())
|
||||||
|
{
|
||||||
|
return U'\0';
|
||||||
|
}
|
||||||
|
return source[idx + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasNext() { return idx < source.length(); }
|
||||||
|
|
||||||
void skipLine();
|
void skipLine();
|
||||||
inline void next()
|
inline void next()
|
||||||
{
|
{
|
||||||
if (*it == U'\n')
|
if (current() == U'\n')
|
||||||
{
|
{
|
||||||
++this->line;
|
++this->line;
|
||||||
this->column = 1;
|
this->column = 1;
|
||||||
@@ -47,43 +53,31 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
++this->column;
|
++this->column;
|
||||||
}
|
}
|
||||||
++it;
|
++idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pushWarning(size_t id, FString msg)
|
void pushWarning(size_t id, String msg)
|
||||||
{
|
{
|
||||||
warnings.push_back(Warning(id, std::move(msg), getCurrentLine(), getCurrentColumn()));
|
warnings.push_back(Warning(id, std::move(msg), getCurrentLine(), getCurrentColumn()));
|
||||||
}
|
}
|
||||||
void pushWarning(size_t id, FString msg, size_t line, size_t column)
|
void pushWarning(size_t id, String msg, size_t line, size_t column)
|
||||||
{
|
{
|
||||||
warnings.push_back(Warning(id, std::move(msg), line, column));
|
warnings.push_back(Warning(id, std::move(msg), line, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const std::unordered_map<FString, TokenType> symbol_map;
|
static const std::unordered_map<String, TokenType> symbol_map;
|
||||||
static const std::unordered_map<FString, TokenType> keyword_map;
|
static const std::unordered_map<String, TokenType> keyword_map;
|
||||||
|
|
||||||
inline Lexer(const FString &_source, const FString &_sourcePath, const std::vector<FString> &_sourceLines) :
|
inline Lexer(const String &_source, const String &_sourcePath, const std::vector<String> &_sourceLines) :
|
||||||
source(_source), it(source), sourcePath(_sourcePath), sourceLines(_sourceLines)
|
source(_source), sourcePath(_sourcePath), sourceLines(_sourceLines)
|
||||||
{
|
{
|
||||||
line = 1;
|
line = 1;
|
||||||
}
|
}
|
||||||
inline size_t getCurrentLine()
|
inline size_t getCurrentLine() { return line; }
|
||||||
{
|
inline size_t getCurrentColumn() { return column; }
|
||||||
return line;
|
SyntaxError getError() const { return error; }
|
||||||
}
|
std::vector<Warning> getWarnings() const { return warnings; }
|
||||||
inline size_t getCurrentColumn()
|
|
||||||
{
|
|
||||||
return column;
|
|
||||||
}
|
|
||||||
SyntaxError getError() const
|
|
||||||
{
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
std::vector<Warning> getWarnings() const
|
|
||||||
{
|
|
||||||
return warnings;
|
|
||||||
}
|
|
||||||
Token nextToken();
|
Token nextToken();
|
||||||
|
|
||||||
Token scanNumber();
|
Token scanNumber();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <Ast/astBase.hpp>
|
#include <Ast/astBase.hpp>
|
||||||
#include <Ast/functionParameters.hpp>
|
#include <Ast/functionParameters.hpp>
|
||||||
#include <Evaluator/Context/context.hpp>
|
#include <Evaluator/Context/context.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Ast/AccessModifier.hpp>
|
#include <Ast/AccessModifier.hpp>
|
||||||
#include <Evaluator/Value/structType.hpp>
|
#include <Evaluator/Value/structType.hpp>
|
||||||
#include <Evaluator/Value/value.hpp>
|
#include <Evaluator/Value/value.hpp>
|
||||||
@@ -24,60 +24,60 @@ namespace Fig::Builtins
|
|||||||
{
|
{
|
||||||
const TypeInfo &getErrorInterfaceTypeInfo()
|
const TypeInfo &getErrorInterfaceTypeInfo()
|
||||||
{
|
{
|
||||||
static const TypeInfo ErrorInterfaceTypeInfo(u8"Error", true);
|
static const TypeInfo ErrorInterfaceTypeInfo(U"Error", true);
|
||||||
return ErrorInterfaceTypeInfo;
|
return ErrorInterfaceTypeInfo;
|
||||||
}
|
}
|
||||||
const TypeInfo &getTypeErrorStructTypeInfo()
|
const TypeInfo &getTypeErrorStructTypeInfo()
|
||||||
{
|
{
|
||||||
static const TypeInfo TypeErrorStructTypeInfo(u8"TypeError", true);
|
static const TypeInfo TypeErrorStructTypeInfo(U"TypeError", true);
|
||||||
return TypeErrorStructTypeInfo;
|
return TypeErrorStructTypeInfo;
|
||||||
}
|
}
|
||||||
const TypeInfo &getOperationInterfaceTypeInfo()
|
const TypeInfo &getOperationInterfaceTypeInfo()
|
||||||
{
|
{
|
||||||
static const TypeInfo OperationInterfaceTypeInfo(u8"Operation", true);
|
static const TypeInfo OperationInterfaceTypeInfo(U"Operation", true);
|
||||||
return OperationInterfaceTypeInfo;
|
return OperationInterfaceTypeInfo;
|
||||||
}
|
}
|
||||||
const std::unordered_map<FString, ObjectPtr> &getBuiltinValues()
|
const std::unordered_map<String, ObjectPtr> &getBuiltinValues()
|
||||||
{
|
{
|
||||||
static const std::unordered_map<FString, ObjectPtr> builtinValues = {
|
static const std::unordered_map<String, ObjectPtr> builtinValues = {
|
||||||
{u8"null", Object::getNullInstance()},
|
{U"null", Object::getNullInstance()},
|
||||||
{u8"true", Object::getTrueInstance()},
|
{U"true", Object::getTrueInstance()},
|
||||||
{u8"false", Object::getFalseInstance()},
|
{U"false", Object::getFalseInstance()},
|
||||||
{u8"Error",
|
{U"Error",
|
||||||
std::make_shared<Object>(InterfaceType(getErrorInterfaceTypeInfo(),
|
std::make_shared<Object>(InterfaceType(getErrorInterfaceTypeInfo(),
|
||||||
{Ast::InterfaceMethod(u8"toString",
|
{Ast::InterfaceMethod(U"toString",
|
||||||
Ast::FunctionParameters({}, {}),
|
Ast::FunctionParameters({}, {}),
|
||||||
std::make_shared<Ast::VarExprAst>(u8"String"),
|
std::make_shared<Ast::VarExprAst>(U"String"),
|
||||||
nullptr),
|
nullptr),
|
||||||
Ast::InterfaceMethod(u8"getErrorClass",
|
Ast::InterfaceMethod(U"getErrorClass",
|
||||||
Ast::FunctionParameters({}, {}),
|
Ast::FunctionParameters({}, {}),
|
||||||
std::make_shared<Ast::VarExprAst>(u8"String"),
|
std::make_shared<Ast::VarExprAst>(U"String"),
|
||||||
nullptr),
|
nullptr),
|
||||||
Ast::InterfaceMethod(u8"getErrorMessage",
|
Ast::InterfaceMethod(U"getErrorMessage",
|
||||||
Ast::FunctionParameters({}, {}),
|
Ast::FunctionParameters({}, {}),
|
||||||
std::make_shared<Ast::VarExprAst>(u8"String"),
|
std::make_shared<Ast::VarExprAst>(U"String"),
|
||||||
nullptr)}))},
|
nullptr)}))},
|
||||||
{u8"TypeError", std::make_shared<Object>(StructType(
|
{U"TypeError", std::make_shared<Object>(StructType(
|
||||||
getTypeErrorStructTypeInfo(),
|
getTypeErrorStructTypeInfo(),
|
||||||
std::make_shared<Context>(u8"<Built-in `TypeError`>"),
|
std::make_shared<Context>(U"<Built-in `TypeError`>"),
|
||||||
{Field(AccessModifier::Public, u8"msg", ValueType::String, nullptr)}
|
{Field(AccessModifier::Public, U"msg", ValueType::String, nullptr)}
|
||||||
))},
|
))},
|
||||||
{u8"Operation", std::make_shared<Object>(InterfaceType(getOperationInterfaceTypeInfo(), {}))},
|
{U"Operation", std::make_shared<Object>(InterfaceType(getOperationInterfaceTypeInfo(), {}))},
|
||||||
|
|
||||||
{u8"Any", std::make_shared<Object>(StructType(ValueType::Any, nullptr, {}, true))},
|
{U"Any", std::make_shared<Object>(StructType(ValueType::Any, nullptr, {}, true))},
|
||||||
{u8"Int", std::make_shared<Object>(StructType(ValueType::Int, nullptr, {}, true))},
|
{U"Int", std::make_shared<Object>(StructType(ValueType::Int, nullptr, {}, true))},
|
||||||
{u8"Null", std::make_shared<Object>(StructType(ValueType::Null, nullptr, {}, true))},
|
{U"Null", std::make_shared<Object>(StructType(ValueType::Null, nullptr, {}, true))},
|
||||||
{u8"String", std::make_shared<Object>(StructType(ValueType::String, nullptr, {}, true))},
|
{U"String", std::make_shared<Object>(StructType(ValueType::String, nullptr, {}, true))},
|
||||||
{u8"Bool", std::make_shared<Object>(StructType(ValueType::Bool, nullptr, {}, true))},
|
{U"Bool", std::make_shared<Object>(StructType(ValueType::Bool, nullptr, {}, true))},
|
||||||
{u8"Double", std::make_shared<Object>(StructType(ValueType::Double, nullptr, {}, true))},
|
{U"Double", std::make_shared<Object>(StructType(ValueType::Double, nullptr, {}, true))},
|
||||||
{u8"Function", std::make_shared<Object>(StructType(ValueType::Function, nullptr, {}, true))},
|
{U"Function", std::make_shared<Object>(StructType(ValueType::Function, nullptr, {}, true))},
|
||||||
{u8"List", std::make_shared<Object>(StructType(ValueType::List, nullptr, {}, true))},
|
{U"List", std::make_shared<Object>(StructType(ValueType::List, nullptr, {}, true))},
|
||||||
{u8"Map", std::make_shared<Object>(StructType(ValueType::Map, nullptr, {}, true))},
|
{U"Map", std::make_shared<Object>(StructType(ValueType::Map, nullptr, {}, true))},
|
||||||
// Type `StructType` `StructInstance` `Module` `InterfaceType`
|
// Type `StructType` `StructInstance` `Module` `InterfaceType`
|
||||||
// Not allowed to call constructor!
|
// Not allowed to call constructor!
|
||||||
|
|
||||||
{u8"type", std::make_shared<Object>(Function(
|
{U"type", std::make_shared<Object>(Function(
|
||||||
u8"type",
|
U"type",
|
||||||
[](const std::vector<ObjectPtr> &_args) -> ObjectPtr
|
[](const std::vector<ObjectPtr> &_args) -> ObjectPtr
|
||||||
{
|
{
|
||||||
const ObjectPtr &arg = _args[0];
|
const ObjectPtr &arg = _args[0];
|
||||||
@@ -88,86 +88,86 @@ namespace Fig::Builtins
|
|||||||
};
|
};
|
||||||
return builtinValues;
|
return builtinValues;
|
||||||
}
|
}
|
||||||
const std::unordered_map<FString, int> &getBuiltinFunctionArgCounts()
|
const std::unordered_map<String, int> &getBuiltinFunctionArgCounts()
|
||||||
{
|
{
|
||||||
static const std::unordered_map<FString, int> builtinFunctionArgCounts = {
|
static const std::unordered_map<String, int> builtinFunctionArgCounts = {
|
||||||
{u8"__fstdout_print", -1}, // variadic
|
{U"__fstdout_print", -1}, // variadic
|
||||||
{u8"__fstdout_println", -1}, // variadic
|
{U"__fstdout_println", -1}, // variadic
|
||||||
{u8"__fstdin_read", 0},
|
{U"__fstdin_read", 0},
|
||||||
{u8"__fstdin_readln", 0},
|
{U"__fstdin_readln", 0},
|
||||||
{u8"__fvalue_type", 1},
|
{U"__fvalue_type", 1},
|
||||||
{u8"__fvalue_int_parse", 1},
|
{U"__fvalue_int_parse", 1},
|
||||||
{u8"__fvalue_int_from", 1},
|
{U"__fvalue_int_from", 1},
|
||||||
{u8"__fvalue_double_parse", 1},
|
{U"__fvalue_double_parse", 1},
|
||||||
{u8"__fvalue_double_from", 1},
|
{U"__fvalue_double_from", 1},
|
||||||
{u8"__fvalue_string_from", 1},
|
{U"__fvalue_string_from", 1},
|
||||||
{u8"__ftime_now_ns", 0},
|
{U"__ftime_now_ns", 0},
|
||||||
/* math start */
|
/* math start */
|
||||||
{u8"__fmath_acos", 1},
|
{U"__fmath_acos", 1},
|
||||||
{u8"__fmath_acosh", 1},
|
{U"__fmath_acosh", 1},
|
||||||
{u8"__fmath_asin", 1},
|
{U"__fmath_asin", 1},
|
||||||
{u8"__fmath_asinh", 1},
|
{U"__fmath_asinh", 1},
|
||||||
{u8"__fmath_atan", 1},
|
{U"__fmath_atan", 1},
|
||||||
{u8"__fmath_atan2", 2},
|
{U"__fmath_atan2", 2},
|
||||||
{u8"__fmath_atanh", 1},
|
{U"__fmath_atanh", 1},
|
||||||
{u8"__fmath_ceil", 1},
|
{U"__fmath_ceil", 1},
|
||||||
{u8"__fmath_cos", 1},
|
{U"__fmath_cos", 1},
|
||||||
{u8"__fmath_cosh", 1},
|
{U"__fmath_cosh", 1},
|
||||||
{u8"__fmath_exp", 1},
|
{U"__fmath_exp", 1},
|
||||||
{u8"__fmath_expm1", 1},
|
{U"__fmath_expm1", 1},
|
||||||
{u8"__fmath_fabs", 1},
|
{U"__fmath_fabs", 1},
|
||||||
{u8"__fmath_floor", 1},
|
{U"__fmath_floor", 1},
|
||||||
{u8"__fmath_fmod", 2},
|
{U"__fmath_fmod", 2},
|
||||||
{u8"__fmath_frexp", 1},
|
{U"__fmath_frexp", 1},
|
||||||
{u8"__fmath_gcd", 2},
|
{U"__fmath_gcd", 2},
|
||||||
{u8"__fmath_hypot", 2},
|
{U"__fmath_hypot", 2},
|
||||||
{u8"__fmath_isequal", 2},
|
{U"__fmath_isequal", 2},
|
||||||
{u8"__fmath_log", 1},
|
{U"__fmath_log", 1},
|
||||||
{u8"__fmath_log10", 1},
|
{U"__fmath_log10", 1},
|
||||||
{u8"__fmath_log1p", 1},
|
{U"__fmath_log1p", 1},
|
||||||
{u8"__fmath_log2", 1},
|
{U"__fmath_log2", 1},
|
||||||
{u8"__fmath_sin", 1},
|
{U"__fmath_sin", 1},
|
||||||
{u8"__fmath_sinh", 1},
|
{U"__fmath_sinh", 1},
|
||||||
{u8"__fmath_sqrt", 1},
|
{U"__fmath_sqrt", 1},
|
||||||
{u8"__fmath_tan", 1},
|
{U"__fmath_tan", 1},
|
||||||
{u8"__fmath_tanh", 1},
|
{U"__fmath_tanh", 1},
|
||||||
{u8"__fmath_trunc", 1},
|
{U"__fmath_trunc", 1},
|
||||||
};
|
};
|
||||||
return builtinFunctionArgCounts;
|
return builtinFunctionArgCounts;
|
||||||
}
|
}
|
||||||
const std::unordered_map<FString, BuiltinFunction> &getBuiltinFunctions()
|
const std::unordered_map<String, BuiltinFunction> &getBuiltinFunctions()
|
||||||
{
|
{
|
||||||
static const std::unordered_map<FString, BuiltinFunction> builtinFunctions{
|
static const std::unordered_map<String, BuiltinFunction> builtinFunctions{
|
||||||
{u8"__fstdout_print",
|
{U"__fstdout_print",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); }
|
for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); }
|
||||||
return std::make_shared<Object>(ValueType::IntClass(args.size()));
|
return std::make_shared<Object>(ValueType::IntClass(args.size()));
|
||||||
}},
|
}},
|
||||||
{u8"__fstdout_println",
|
{U"__fstdout_println",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); }
|
for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); }
|
||||||
std::print("\n");
|
std::print("\n");
|
||||||
return std::make_shared<Object>(ValueType::IntClass(args.size()));
|
return std::make_shared<Object>(ValueType::IntClass(args.size()));
|
||||||
}},
|
}},
|
||||||
{u8"__fstdin_read",
|
{U"__fstdin_read",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
std::string input;
|
std::string input;
|
||||||
std::cin >> input;
|
std::cin >> input;
|
||||||
return std::make_shared<Object>(FString::fromBasicString(input));
|
return std::make_shared<Object>(String(input));
|
||||||
}},
|
}},
|
||||||
{u8"__fstdin_readln",
|
{U"__fstdin_readln",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
std::string line;
|
std::string line;
|
||||||
std::getline(std::cin, line);
|
std::getline(std::cin, line);
|
||||||
return std::make_shared<Object>(FString::fromBasicString(line));
|
return std::make_shared<Object>(String(line));
|
||||||
}},
|
}},
|
||||||
{u8"__fvalue_type",
|
{U"__fvalue_type",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
return std::make_shared<Object>(args[0]->getTypeInfo().toString());
|
return std::make_shared<Object>(args[0]->getTypeInfo().toString());
|
||||||
}},
|
}},
|
||||||
{u8"__fvalue_int_parse",
|
{U"__fvalue_int_parse",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
FString str = args[0]->as<ValueType::StringClass>();
|
String str = args[0]->as<ValueType::StringClass>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ValueType::IntClass val = std::stoi(str.toBasicString());
|
ValueType::IntClass val = std::stoi(str.toBasicString());
|
||||||
@@ -175,10 +175,10 @@ namespace Fig::Builtins
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
throw RuntimeError(FString(std::format("Invalid int string for parsing", str.toBasicString())));
|
throw RuntimeError(String(std::format("Invalid int string for parsing", str.toBasicString())));
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
{u8"__fvalue_int_from",
|
{U"__fvalue_int_from",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
if (val->is<ValueType::DoubleClass>())
|
if (val->is<ValueType::DoubleClass>())
|
||||||
@@ -193,13 +193,13 @@ namespace Fig::Builtins
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw RuntimeError(FString(std::format("Type '{}' cannot be converted to int",
|
throw RuntimeError(String(std::format("Type '{}' cannot be converted to int",
|
||||||
val->getTypeInfo().toString().toBasicString())));
|
val->getTypeInfo().toString().toBasicString())));
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
{u8"__fvalue_double_parse",
|
{U"__fvalue_double_parse",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
FString str = args[0]->as<ValueType::StringClass>();
|
String str = args[0]->as<ValueType::StringClass>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ValueType::DoubleClass val = std::stod(str.toBasicString());
|
ValueType::DoubleClass val = std::stod(str.toBasicString());
|
||||||
@@ -207,10 +207,10 @@ namespace Fig::Builtins
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
throw RuntimeError(FString(std::format("Invalid double string for parsing", str.toBasicString())));
|
throw RuntimeError(String(std::format("Invalid double string for parsing", str.toBasicString())));
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
{u8"__fvalue_double_from",
|
{U"__fvalue_double_from",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
if (val->is<ValueType::IntClass>())
|
if (val->is<ValueType::IntClass>())
|
||||||
@@ -225,16 +225,16 @@ namespace Fig::Builtins
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw RuntimeError(FString(std::format("Type '{}' cannot be converted to double",
|
throw RuntimeError(String(std::format("Type '{}' cannot be converted to double",
|
||||||
val->getTypeInfo().toString().toBasicString())));
|
val->getTypeInfo().toString().toBasicString())));
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
{u8"__fvalue_string_from",
|
{U"__fvalue_string_from",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
return std::make_shared<Object>(val->toStringIO());
|
return std::make_shared<Object>(val->toStringIO());
|
||||||
}},
|
}},
|
||||||
{u8"__ftime_now_ns",
|
{U"__ftime_now_ns",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
// returns nanoseconds
|
// returns nanoseconds
|
||||||
using namespace Fig::Time;
|
using namespace Fig::Time;
|
||||||
@@ -244,97 +244,97 @@ namespace Fig::Builtins
|
|||||||
}},
|
}},
|
||||||
|
|
||||||
/* math start */
|
/* math start */
|
||||||
{u8"__fmath_acos",
|
{U"__fmath_acos",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(acos(d));
|
return std::make_shared<Object>(acos(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_acosh",
|
{U"__fmath_acosh",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(acosh(d));
|
return std::make_shared<Object>(acosh(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_asin",
|
{U"__fmath_asin",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(asin(d));
|
return std::make_shared<Object>(asin(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_asinh",
|
{U"__fmath_asinh",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(asinh(d));
|
return std::make_shared<Object>(asinh(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_atan",
|
{U"__fmath_atan",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(atan(d));
|
return std::make_shared<Object>(atan(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_atan2",
|
{U"__fmath_atan2",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ValueType::DoubleClass y = args[0]->getNumericValue();
|
ValueType::DoubleClass y = args[0]->getNumericValue();
|
||||||
ValueType::DoubleClass x = args[1]->getNumericValue();
|
ValueType::DoubleClass x = args[1]->getNumericValue();
|
||||||
return std::make_shared<Object>(atan2(y, x));
|
return std::make_shared<Object>(atan2(y, x));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_atanh",
|
{U"__fmath_atanh",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(atanh(d));
|
return std::make_shared<Object>(atanh(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_ceil",
|
{U"__fmath_ceil",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(ceil(d));
|
return std::make_shared<Object>(ceil(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_cos",
|
{U"__fmath_cos",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(cos(d));
|
return std::make_shared<Object>(cos(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_cosh",
|
{U"__fmath_cosh",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(cosh(d));
|
return std::make_shared<Object>(cosh(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_exp",
|
{U"__fmath_exp",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(exp(d));
|
return std::make_shared<Object>(exp(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_expm1",
|
{U"__fmath_expm1",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(expm1(d));
|
return std::make_shared<Object>(expm1(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_fabs",
|
{U"__fmath_fabs",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(fabs(d));
|
return std::make_shared<Object>(fabs(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_floor",
|
{U"__fmath_floor",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(floor(d));
|
return std::make_shared<Object>(floor(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_fmod",
|
{U"__fmath_fmod",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ValueType::DoubleClass x = args[0]->getNumericValue();
|
ValueType::DoubleClass x = args[0]->getNumericValue();
|
||||||
ValueType::DoubleClass y = args[1]->getNumericValue();
|
ValueType::DoubleClass y = args[1]->getNumericValue();
|
||||||
return std::make_shared<Object>(fmod(x, y));
|
return std::make_shared<Object>(fmod(x, y));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_frexp",
|
{U"__fmath_frexp",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
@@ -342,80 +342,80 @@ namespace Fig::Builtins
|
|||||||
return std::make_shared<Object>(List({std::make_shared<Object>(frexp(d, &e)),
|
return std::make_shared<Object>(List({std::make_shared<Object>(frexp(d, &e)),
|
||||||
std::make_shared<Object>(static_cast<ValueType::IntClass>(e))}));
|
std::make_shared<Object>(static_cast<ValueType::IntClass>(e))}));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_gcd",
|
{U"__fmath_gcd",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ValueType::IntClass x = args[0]->as<ValueType::IntClass>();
|
ValueType::IntClass x = args[0]->as<ValueType::IntClass>();
|
||||||
ValueType::IntClass y = args[1]->as<ValueType::IntClass>();
|
ValueType::IntClass y = args[1]->as<ValueType::IntClass>();
|
||||||
return std::make_shared<Object>(std::gcd(x, y));
|
return std::make_shared<Object>(std::gcd(x, y));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_hypot",
|
{U"__fmath_hypot",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ValueType::DoubleClass x = args[0]->getNumericValue();
|
ValueType::DoubleClass x = args[0]->getNumericValue();
|
||||||
ValueType::DoubleClass y = args[1]->getNumericValue();
|
ValueType::DoubleClass y = args[1]->getNumericValue();
|
||||||
return std::make_shared<Object>(hypot(x, y));
|
return std::make_shared<Object>(hypot(x, y));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_isequal",
|
{U"__fmath_isequal",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ValueType::DoubleClass x = args[0]->getNumericValue();
|
ValueType::DoubleClass x = args[0]->getNumericValue();
|
||||||
ValueType::DoubleClass y = args[1]->getNumericValue();
|
ValueType::DoubleClass y = args[1]->getNumericValue();
|
||||||
static const double epsilon = 1e-9;
|
static const double epsilon = 1e-9;
|
||||||
return std::make_shared<Object>(fabs(x - y) < epsilon);
|
return std::make_shared<Object>(fabs(x - y) < epsilon);
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_log",
|
{U"__fmath_log",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(log(d));
|
return std::make_shared<Object>(log(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_log10",
|
{U"__fmath_log10",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(log10(d));
|
return std::make_shared<Object>(log10(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_log1p",
|
{U"__fmath_log1p",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(log1p(d));
|
return std::make_shared<Object>(log1p(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_log2",
|
{U"__fmath_log2",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(log2(d));
|
return std::make_shared<Object>(log2(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_sin",
|
{U"__fmath_sin",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(sin(d));
|
return std::make_shared<Object>(sin(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_sinh",
|
{U"__fmath_sinh",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(sinh(d));
|
return std::make_shared<Object>(sinh(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_sqrt",
|
{U"__fmath_sqrt",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(sqrt(d));
|
return std::make_shared<Object>(sqrt(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_tan",
|
{U"__fmath_tan",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(tan(d));
|
return std::make_shared<Object>(tan(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_tanh",
|
{U"__fmath_tanh",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
return std::make_shared<Object>(tanh(d));
|
return std::make_shared<Object>(tanh(d));
|
||||||
}},
|
}},
|
||||||
{u8"__fmath_trunc",
|
{U"__fmath_trunc",
|
||||||
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
[](const std::vector<ObjectPtr> &args) -> ObjectPtr {
|
||||||
ObjectPtr val = args[0];
|
ObjectPtr val = args[0];
|
||||||
ValueType::DoubleClass d = val->getNumericValue();
|
ValueType::DoubleClass d = val->getNumericValue();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <Ast/Expressions/VarExpr.hpp>
|
#include <Ast/Expressions/VarExpr.hpp>
|
||||||
|
|
||||||
#include <Ast/functionParameters.hpp>
|
#include <Ast/functionParameters.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Evaluator/Value/value.hpp>
|
#include <Evaluator/Value/value.hpp>
|
||||||
#include <Core/runtimeTime.hpp>
|
#include <Core/runtimeTime.hpp>
|
||||||
|
|
||||||
@@ -34,39 +34,39 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
add(..., ...) -> ...;
|
add(..., ...) -> ...;
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const TypeInfo &getOperationInterfaceTypeInfo();
|
const TypeInfo &getOperationInterfaceTypeInfo();
|
||||||
|
|
||||||
const std::unordered_map<FString, ObjectPtr> &getBuiltinValues();
|
const std::unordered_map<String, ObjectPtr> &getBuiltinValues();
|
||||||
|
|
||||||
using BuiltinFunction = std::function<ObjectPtr(const std::vector<ObjectPtr> &)>;
|
using BuiltinFunction = std::function<ObjectPtr(const std::vector<ObjectPtr> &)>;
|
||||||
|
|
||||||
const std::unordered_map<FString, int> &getBuiltinFunctionArgCounts();
|
const std::unordered_map<String, int> &getBuiltinFunctionArgCounts();
|
||||||
const std::unordered_map<FString, BuiltinFunction> &getBuiltinFunctions();
|
const std::unordered_map<String, BuiltinFunction> &getBuiltinFunctions();
|
||||||
|
|
||||||
inline bool isBuiltinFunction(const FString &name)
|
inline bool isBuiltinFunction(const String &name)
|
||||||
{
|
{
|
||||||
return getBuiltinFunctions().find(name) != getBuiltinFunctions().end();
|
return getBuiltinFunctions().find(name) != getBuiltinFunctions().end();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline BuiltinFunction getBuiltinFunction(const FString &name)
|
inline BuiltinFunction getBuiltinFunction(const String &name)
|
||||||
{
|
{
|
||||||
auto it = getBuiltinFunctions().find(name);
|
auto it = getBuiltinFunctions().find(name);
|
||||||
if (it == getBuiltinFunctions().end())
|
if (it == getBuiltinFunctions().end())
|
||||||
{
|
{
|
||||||
throw RuntimeError(FString(std::format("Builtin function '{}' not found", name.toBasicString())));
|
throw RuntimeError(String(std::format("Builtin function '{}' not found", name.toBasicString())));
|
||||||
}
|
}
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int getBuiltinFunctionParamCount(const FString &name)
|
inline int getBuiltinFunctionParamCount(const String &name)
|
||||||
{
|
{
|
||||||
auto it = getBuiltinFunctionArgCounts().find(name);
|
auto it = getBuiltinFunctionArgCounts().find(name);
|
||||||
if (it == getBuiltinFunctionArgCounts().end())
|
if (it == getBuiltinFunctionArgCounts().end())
|
||||||
{
|
{
|
||||||
throw RuntimeError(FString(std::format("Builtin function '{}' not found", name.toBasicString())));
|
throw RuntimeError(String(std::format("Builtin function '{}' not found", name.toBasicString())));
|
||||||
}
|
}
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ namespace Fig
|
|||||||
bool isConst = (currentToken().getType() == TokenType::Const ? true : false);
|
bool isConst = (currentToken().getType() == TokenType::Const ? true : false);
|
||||||
next();
|
next();
|
||||||
expect(TokenType::Identifier);
|
expect(TokenType::Identifier);
|
||||||
FString name = currentToken().getValue();
|
String name = currentToken().getValue();
|
||||||
next();
|
next();
|
||||||
Ast::Expression declaredType = nullptr;
|
Ast::Expression declaredType = nullptr;
|
||||||
bool hasSpecificType = false;
|
bool hasSpecificType = false;
|
||||||
@@ -102,12 +102,12 @@ namespace Fig
|
|||||||
next(); // consume `;`, no using expectConsume here cause we don't need to check again
|
next(); // consume `;`, no using expectConsume here cause we don't need to check again
|
||||||
return makeAst<Ast::VarDefAst>(isPublic, isConst, name, declaredType, nullptr, false);
|
return makeAst<Ast::VarDefAst>(isPublic, isConst, name, declaredType, nullptr, false);
|
||||||
}
|
}
|
||||||
if (!isThis(TokenType::Assign) and !isThis(TokenType::Walrus)) expect(TokenType::Assign, u8"assign or walrus");
|
if (!isThis(TokenType::Assign) and !isThis(TokenType::Walrus)) expect(TokenType::Assign, U"\1");
|
||||||
bool followupType = false;
|
bool followupType = false;
|
||||||
|
|
||||||
if (isThis(TokenType::Walrus))
|
if (isThis(TokenType::Walrus))
|
||||||
{
|
{
|
||||||
if (hasSpecificType) throwAddressableError<SyntaxError>(FString(u8""));
|
if (hasSpecificType) throwAddressableError<SyntaxError>(String(U"\1"));
|
||||||
followupType = true;
|
followupType = true;
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
@@ -118,7 +118,7 @@ namespace Fig
|
|||||||
|
|
||||||
ObjectPtr Parser::__parseValue()
|
ObjectPtr Parser::__parseValue()
|
||||||
{
|
{
|
||||||
FString _val = currentToken().getValue();
|
String _val = currentToken().getValue();
|
||||||
if (currentToken().getType() == TokenType::LiteralNumber)
|
if (currentToken().getType() == TokenType::LiteralNumber)
|
||||||
{
|
{
|
||||||
if (_val.contains(u8'.') || _val.contains(u8'e'))
|
if (_val.contains(u8'.') || _val.contains(u8'e'))
|
||||||
@@ -131,7 +131,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(FString(u8"Illegal number literal"));
|
throwAddressableError<SyntaxError>(String(U"\1"));
|
||||||
}
|
}
|
||||||
return std::make_shared<Object>(d);
|
return std::make_shared<Object>(d);
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(FString(u8"Illegal number literal"));
|
throwAddressableError<SyntaxError>(String(U"\1"));
|
||||||
}
|
}
|
||||||
return std::make_shared<Object>(i);
|
return std::make_shared<Object>(i);
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ namespace Fig
|
|||||||
else if (currentToken().getType() == TokenType::LiteralString) { return std::make_shared<Object>(_val); }
|
else if (currentToken().getType() == TokenType::LiteralString) { return std::make_shared<Object>(_val); }
|
||||||
else if (currentToken().getType() == TokenType::LiteralBool)
|
else if (currentToken().getType() == TokenType::LiteralBool)
|
||||||
{
|
{
|
||||||
return std::make_shared<Object>((_val == u8"true" ? true : false));
|
return std::make_shared<Object>((_val == U"\1" ? true : false));
|
||||||
}
|
}
|
||||||
else if (currentToken().getType() == TokenType::LiteralNull) { return Object::getNullInstance(); }
|
else if (currentToken().getType() == TokenType::LiteralNull) { return Object::getNullInstance(); }
|
||||||
else
|
else
|
||||||
@@ -176,7 +176,7 @@ namespace Fig
|
|||||||
|
|
||||||
Ast::FunctionParameters::PosParasType pp;
|
Ast::FunctionParameters::PosParasType pp;
|
||||||
Ast::FunctionParameters::DefParasType dp;
|
Ast::FunctionParameters::DefParasType dp;
|
||||||
FString variaPara;
|
String variaPara;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (isThis(TokenType::RightParen))
|
if (isThis(TokenType::RightParen))
|
||||||
@@ -184,13 +184,13 @@ namespace Fig
|
|||||||
next();
|
next();
|
||||||
return Ast::FunctionParameters(pp, dp);
|
return Ast::FunctionParameters(pp, dp);
|
||||||
}
|
}
|
||||||
expect(TokenType::Identifier, FString(u8"Identifier or `)`")); // check current
|
expect(TokenType::Identifier, String(U"\1")); // check current
|
||||||
FString pname = currentToken().getValue();
|
String pname = currentToken().getValue();
|
||||||
next(); // skip pname
|
next(); // skip pname
|
||||||
if (isThis(TokenType::Assign)) // =
|
if (isThis(TokenType::Assign)) // =
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
dp.push_back({pname, {makeAst<Ast::VarExprAst>(u8"Any"), parseExpression(0, TokenType::Comma)}});
|
dp.push_back({pname, {makeAst<Ast::VarExprAst>(U"\1"), parseExpression(0, TokenType::Comma)}});
|
||||||
if (isThis(TokenType::Comma))
|
if (isThis(TokenType::Comma))
|
||||||
{
|
{
|
||||||
next(); // only skip `,` when it's there
|
next(); // only skip `,` when it's there
|
||||||
@@ -224,16 +224,13 @@ namespace Fig
|
|||||||
variaPara = pname;
|
variaPara = pname;
|
||||||
next(); // skip `...`
|
next(); // skip `...`
|
||||||
if (!isThis(TokenType::RightParen))
|
if (!isThis(TokenType::RightParen))
|
||||||
throwAddressableError<SyntaxError>(
|
throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
|
||||||
u8"Expects right paren, variable parameter function can only have one parameter",
|
|
||||||
currentAAI.line,
|
|
||||||
currentAAI.column);
|
|
||||||
next(); // skip `)`
|
next(); // skip `)`
|
||||||
return Ast::FunctionParameters(variaPara);
|
return Ast::FunctionParameters(variaPara);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pp.push_back({pname, makeAst<Ast::VarExprAst>(u8"Any")});
|
pp.push_back({pname, makeAst<Ast::VarExprAst>(U"\1")});
|
||||||
if (isThis(TokenType::Comma))
|
if (isThis(TokenType::Comma))
|
||||||
{
|
{
|
||||||
next(); // only skip `,` when it's there
|
next(); // only skip `,` when it's there
|
||||||
@@ -243,7 +240,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
Ast::FunctionDef Parser::__parseFunctionDef(bool isPublic)
|
Ast::FunctionDef Parser::__parseFunctionDef(bool isPublic)
|
||||||
{
|
{
|
||||||
FString funcName = currentToken().getValue();
|
String funcName = currentToken().getValue();
|
||||||
next();
|
next();
|
||||||
expect(TokenType::LeftParen);
|
expect(TokenType::LeftParen);
|
||||||
Ast::FunctionParameters params = __parseFunctionParameters();
|
Ast::FunctionParameters params = __parseFunctionParameters();
|
||||||
@@ -262,9 +259,9 @@ namespace Fig
|
|||||||
Ast::StructDef Parser::__parseStructDef(bool isPublic)
|
Ast::StructDef Parser::__parseStructDef(bool isPublic)
|
||||||
{
|
{
|
||||||
// entry: current is struct name
|
// entry: current is struct name
|
||||||
FString structName = currentToken().getValue();
|
String structName = currentToken().getValue();
|
||||||
next();
|
next();
|
||||||
expect(TokenType::LeftBrace, u8"struct body");
|
expect(TokenType::LeftBrace, U"\1");
|
||||||
next();
|
next();
|
||||||
bool braceClosed = false;
|
bool braceClosed = false;
|
||||||
|
|
||||||
@@ -281,7 +278,7 @@ namespace Fig
|
|||||||
|
|
||||||
auto __parseStructField = [this](bool isPublic) -> Ast::StructDefField {
|
auto __parseStructField = [this](bool isPublic) -> Ast::StructDefField {
|
||||||
AccessModifier am = AccessModifier::Normal;
|
AccessModifier am = AccessModifier::Normal;
|
||||||
FString fieldName;
|
String fieldName;
|
||||||
if (isThis(TokenType::Identifier))
|
if (isThis(TokenType::Identifier))
|
||||||
{
|
{
|
||||||
fieldName = currentToken().getValue();
|
fieldName = currentToken().getValue();
|
||||||
@@ -291,13 +288,13 @@ namespace Fig
|
|||||||
else if (isThis(TokenType::Const))
|
else if (isThis(TokenType::Const))
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
expect(TokenType::Identifier, u8"field name");
|
expect(TokenType::Identifier, U"\1");
|
||||||
fieldName = currentToken().getValue();
|
fieldName = currentToken().getValue();
|
||||||
am = (isPublic ? AccessModifier::PublicConst : AccessModifier::Const);
|
am = (isPublic ? AccessModifier::PublicConst : AccessModifier::Const);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(FString(std::format("expect field name or field attribute")));
|
throwAddressableError<SyntaxError>(String(std::format("expect field name or field attribute")));
|
||||||
}
|
}
|
||||||
Ast::Expression fieldType = nullptr;
|
Ast::Expression fieldType = nullptr;
|
||||||
if (isThis(TokenType::Colon))
|
if (isThis(TokenType::Colon))
|
||||||
@@ -309,7 +306,7 @@ namespace Fig
|
|||||||
if (isThis(TokenType::Assign))
|
if (isThis(TokenType::Assign))
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
if (isEOF()) throwAddressableError<SyntaxError>(FString(u8"expect an expression"));
|
if (isEOF()) throwAddressableError<SyntaxError>(String(U"\1"));
|
||||||
initExpr = parseExpression(0);
|
initExpr = parseExpression(0);
|
||||||
}
|
}
|
||||||
expectSemicolon();
|
expectSemicolon();
|
||||||
@@ -353,7 +350,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(FString("Invalid syntax"));
|
throwAddressableError<SyntaxError>(String("Invalid syntax"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isThis(TokenType::Function))
|
else if (isThis(TokenType::Function))
|
||||||
@@ -370,21 +367,21 @@ namespace Fig
|
|||||||
else if (isThis(TokenType::Variable))
|
else if (isThis(TokenType::Variable))
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(
|
throwAddressableError<SyntaxError>(
|
||||||
FString("Variables are not allowed to be defined within a structure."));
|
String("Variables are not allowed to be defined within a structure."));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(FString("Invalid syntax"));
|
throwAddressableError<SyntaxError>(String("Invalid syntax"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!braceClosed) { throwAddressableError<SyntaxError>(FString("braces are not closed")); }
|
if (!braceClosed) { throwAddressableError<SyntaxError>(String("braces are not closed")); }
|
||||||
return makeAst<Ast::StructDefSt>(isPublic, structName, fields, makeAst<Ast::BlockStatementAst>(stmts));
|
return makeAst<Ast::StructDefSt>(isPublic, structName, fields, makeAst<Ast::BlockStatementAst>(stmts));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast::InterfaceDef Parser::__parseInterfaceDef(bool isPublic)
|
Ast::InterfaceDef Parser::__parseInterfaceDef(bool isPublic)
|
||||||
{
|
{
|
||||||
// entry: current is interface name
|
// entry: current is interface name
|
||||||
FString interfaceName = currentToken().getValue();
|
String interfaceName = currentToken().getValue();
|
||||||
next(); // consume name
|
next(); // consume name
|
||||||
expect(TokenType::LeftBrace); // `{
|
expect(TokenType::LeftBrace); // `{
|
||||||
next(); // consume `{`
|
next(); // consume `{`
|
||||||
@@ -400,7 +397,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
if (isThis(TokenType::Identifier))
|
if (isThis(TokenType::Identifier))
|
||||||
{
|
{
|
||||||
FString funcName = currentToken().getValue();
|
String funcName = currentToken().getValue();
|
||||||
next(); // consume func name
|
next(); // consume func name
|
||||||
|
|
||||||
expect(TokenType::LeftParen);
|
expect(TokenType::LeftParen);
|
||||||
@@ -424,7 +421,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column);
|
throwAddressableError<SyntaxError>(String(U"\1"), currentAAI.line, currentAAI.column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return makeAst<Ast::InterfaceDefAst>(interfaceName, methods, isPublic);
|
return makeAst<Ast::InterfaceDefAst>(interfaceName, methods, isPublic);
|
||||||
@@ -434,15 +431,15 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
// entry: current is `impl`
|
// entry: current is `impl`
|
||||||
next(); // consume `impl`
|
next(); // consume `impl`
|
||||||
expect(TokenType::Identifier, u8"interface name");
|
expect(TokenType::Identifier, U"\1");
|
||||||
FString interfaceName = currentToken().getValue();
|
String interfaceName = currentToken().getValue();
|
||||||
next(); // consume interface name
|
next(); // consume interface name
|
||||||
|
|
||||||
expect(TokenType::For);
|
expect(TokenType::For);
|
||||||
next(); // consume `for`
|
next(); // consume `for`
|
||||||
|
|
||||||
expect(TokenType::Identifier, u8"struct name");
|
expect(TokenType::Identifier, U"\1");
|
||||||
FString structName = currentToken().getValue();
|
String structName = currentToken().getValue();
|
||||||
next(); // consume name
|
next(); // consume name
|
||||||
expect(TokenType::LeftBrace); // {
|
expect(TokenType::LeftBrace); // {
|
||||||
next(); // consume `{`
|
next(); // consume `{`
|
||||||
@@ -458,7 +455,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
if (isThis(TokenType::Identifier))
|
if (isThis(TokenType::Identifier))
|
||||||
{
|
{
|
||||||
FString funcName = currentToken().getValue();
|
String funcName = currentToken().getValue();
|
||||||
next(); // consume func name
|
next(); // consume func name
|
||||||
expect(TokenType::LeftParen);
|
expect(TokenType::LeftParen);
|
||||||
Ast::FunctionParameters paras = __parseFunctionParameters();
|
Ast::FunctionParameters paras = __parseFunctionParameters();
|
||||||
@@ -468,7 +465,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column);
|
throwAddressableError<SyntaxError>(String(U"\1"), currentAAI.line, currentAAI.column);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,16 +510,16 @@ namespace Fig
|
|||||||
next(); // consume `catch`
|
next(); // consume `catch`
|
||||||
expect(TokenType::LeftParen);
|
expect(TokenType::LeftParen);
|
||||||
next(); // consume `(`
|
next(); // consume `(`
|
||||||
expect(TokenType::Identifier, u8"error receive var name");
|
expect(TokenType::Identifier, U"\1");
|
||||||
FString errVarName = currentToken().getValue();
|
String errVarName = currentToken().getValue();
|
||||||
next(); // consume name
|
next(); // consume name
|
||||||
|
|
||||||
bool hasType = false;
|
bool hasType = false;
|
||||||
FString errVarType;
|
String errVarType;
|
||||||
if (isThis(TokenType::Colon)) // :
|
if (isThis(TokenType::Colon)) // :
|
||||||
{
|
{
|
||||||
next();
|
next();
|
||||||
expect(TokenType::Identifier, u8"error type");
|
expect(TokenType::Identifier, U"\1");
|
||||||
errVarType = currentToken().getValue();
|
errVarType = currentToken().getValue();
|
||||||
next(); // consume var type
|
next(); // consume var type
|
||||||
hasType = true;
|
hasType = true;
|
||||||
@@ -542,8 +539,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
if (finallyBlock != nullptr)
|
if (finallyBlock != nullptr)
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(
|
throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
|
||||||
u8"Duplicate try finally-block", currentAAI.line, currentAAI.column);
|
|
||||||
}
|
}
|
||||||
next(); // consume `finally`
|
next(); // consume `finally`
|
||||||
expect(TokenType::LeftBrace);
|
expect(TokenType::LeftBrace);
|
||||||
@@ -579,8 +575,7 @@ namespace Fig
|
|||||||
else if (isThis(TokenType::Interface)) { stmt = __parseInterfaceDef(true); }
|
else if (isThis(TokenType::Interface)) { stmt = __parseInterfaceDef(true); }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(
|
throwAddressableError<SyntaxError>(String(U"\1"));
|
||||||
FString(u8"Expected `var`, `const`, `function`, `struct` or `interface` after `public`"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isThis(TokenType::Variable) || isThis(TokenType::Const)) { stmt = __parseVarDef(false); }
|
else if (isThis(TokenType::Variable) || isThis(TokenType::Const)) { stmt = __parseVarDef(false); }
|
||||||
@@ -591,22 +586,19 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else if (isThis(TokenType::Struct))
|
else if (isThis(TokenType::Struct))
|
||||||
{
|
{
|
||||||
expectPeek(TokenType::Identifier, u8"struct name");
|
expectPeek(TokenType::Identifier, U"\1");
|
||||||
next();
|
next();
|
||||||
stmt = __parseStructDef(false);
|
stmt = __parseStructDef(false);
|
||||||
}
|
}
|
||||||
else if (isThis(TokenType::Interface))
|
else if (isThis(TokenType::Interface))
|
||||||
{
|
{
|
||||||
expectPeek(TokenType::Identifier, u8"interface name");
|
expectPeek(TokenType::Identifier, U"\1");
|
||||||
next();
|
next();
|
||||||
stmt = __parseInterfaceDef(false);
|
stmt = __parseInterfaceDef(false);
|
||||||
}
|
}
|
||||||
else if (isThis(TokenType::Implement)) { stmt = __parseImplement(); }
|
else if (isThis(TokenType::Implement)) { stmt = __parseImplement(); }
|
||||||
else if (isThis(TokenType::If)) { stmt = __parseIf(); }
|
else if (isThis(TokenType::If)) { stmt = __parseIf(); }
|
||||||
else if (isThis(TokenType::Else))
|
else if (isThis(TokenType::Else)) { throwAddressableError<SyntaxError>(String(U"\1")); }
|
||||||
{
|
|
||||||
throwAddressableError<SyntaxError>(FString(u8"`else` without matching `if`"));
|
|
||||||
}
|
|
||||||
else if (isThis(TokenType::LeftBrace)) { stmt = __parseBlockStatement(); }
|
else if (isThis(TokenType::LeftBrace)) { stmt = __parseBlockStatement(); }
|
||||||
else if (isThis(TokenType::While)) { stmt = __parseWhile(); }
|
else if (isThis(TokenType::While)) { stmt = __parseWhile(); }
|
||||||
else if (isThis(TokenType::For)) { stmt = __parseFor(); }
|
else if (isThis(TokenType::For)) { stmt = __parseFor(); }
|
||||||
@@ -624,7 +616,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(u8"invalid syntax", currentAAI.line, currentAAI.column);
|
throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
|
||||||
}
|
}
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@@ -724,15 +716,12 @@ namespace Fig
|
|||||||
// 2. expression stmt:i++, foo()
|
// 2. expression stmt:i++, foo()
|
||||||
// ❌ not allowed:if/while/for/block stmt
|
// ❌ not allowed:if/while/for/block stmt
|
||||||
|
|
||||||
if (isThis(TokenType::LeftBrace))
|
if (isThis(TokenType::LeftBrace)) { throwAddressableError<SyntaxError>(U"\1"); }
|
||||||
{
|
|
||||||
throwAddressableError<SyntaxError>(u8"BlockStatement cannot be used as for loop increment");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isThis(TokenType::If) || isThis(TokenType::While) || isThis(TokenType::For) || isThis(TokenType::Return)
|
if (isThis(TokenType::If) || isThis(TokenType::While) || isThis(TokenType::For) || isThis(TokenType::Return)
|
||||||
|| isThis(TokenType::Break) || isThis(TokenType::Continue))
|
|| isThis(TokenType::Break) || isThis(TokenType::Continue))
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(u8"Control flow statements cannot be used as for loop increment");
|
throwAddressableError<SyntaxError>(U"\1");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast::Expression exp = parseExpression(0, TokenType::LeftBrace);
|
Ast::Expression exp = parseExpression(0, TokenType::LeftBrace);
|
||||||
@@ -786,7 +775,7 @@ namespace Fig
|
|||||||
return makeAst<Ast::BreakSt>();
|
return makeAst<Ast::BreakSt>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast::VarExpr Parser::__parseVarExpr(FString name)
|
Ast::VarExpr Parser::__parseVarExpr(String name)
|
||||||
{
|
{
|
||||||
return makeAst<Ast::VarExprAst>(name);
|
return makeAst<Ast::VarExprAst>(name);
|
||||||
}
|
}
|
||||||
@@ -869,7 +858,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
// entry: current is `{`
|
// entry: current is `{`
|
||||||
next(); // consume `{`
|
next(); // consume `{`
|
||||||
std::vector<std::pair<FString, Ast::Expression>> args;
|
std::vector<std::pair<String, Ast::Expression>> args;
|
||||||
/*
|
/*
|
||||||
3 ways of calling constructor
|
3 ways of calling constructor
|
||||||
.1 Person {"Fig", 1, "IDK"};
|
.1 Person {"Fig", 1, "IDK"};
|
||||||
@@ -893,13 +882,13 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
// 1 Person {"Fig", 1, "IDK"};
|
// 1 Person {"Fig", 1, "IDK"};
|
||||||
Ast::Expression expr = parseExpression(0, TokenType::Comma, TokenType::RightBrace);
|
Ast::Expression expr = parseExpression(0, TokenType::Comma, TokenType::RightBrace);
|
||||||
args.push_back({FString(), std::move(expr)});
|
args.push_back({String(), std::move(expr)});
|
||||||
}
|
}
|
||||||
else if (mode == 2)
|
else if (mode == 2)
|
||||||
{
|
{
|
||||||
// 2 Person {name: "Fig", age: 1, sex: "IDK"};
|
// 2 Person {name: "Fig", age: 1, sex: "IDK"};
|
||||||
expect(TokenType::Identifier);
|
expect(TokenType::Identifier);
|
||||||
FString fieldName = currentToken().getValue();
|
String fieldName = currentToken().getValue();
|
||||||
next(); // consume identifier
|
next(); // consume identifier
|
||||||
expect(TokenType::Colon);
|
expect(TokenType::Colon);
|
||||||
next(); // consume colon
|
next(); // consume colon
|
||||||
@@ -913,28 +902,22 @@ namespace Fig
|
|||||||
else if (!isThis(TokenType::RightBrace))
|
else if (!isThis(TokenType::RightBrace))
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(
|
throwAddressableError<SyntaxError>(
|
||||||
FString(std::format("Expect `,` or `}}` in struct initialization expression, got {}",
|
String(std::format("Expect `,` or `}}` in struct initialization expression, got {}",
|
||||||
currentToken().toString().toBasicString())));
|
currentToken().toString().toBasicString())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool shorthand = true;
|
bool shorthand = true;
|
||||||
if (mode == 1)
|
if (mode == 1)
|
||||||
{
|
{
|
||||||
for (auto &[name, exp] : args)
|
for (auto &[name, exp] : args)
|
||||||
{
|
{
|
||||||
if (!name.empty())
|
if (!name.empty()) { shorthand = false; }
|
||||||
{
|
if (exp->getType() != Ast::AstType::VarExpr) { shorthand = false; }
|
||||||
shorthand = false;
|
|
||||||
}
|
|
||||||
if (exp->getType() != Ast::AstType::VarExpr)
|
|
||||||
{
|
|
||||||
shorthand = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (shorthand)
|
if (shorthand)
|
||||||
{
|
{
|
||||||
mode = 3; // all are identifiers, so it's shorthand mode, not positional
|
mode = 3; // all are identifiers, so it's shorthand mode, not positional
|
||||||
std::vector<std::pair<FString, Ast::Expression>> nargs;
|
std::vector<std::pair<String, Ast::Expression>> nargs;
|
||||||
for (auto &[name, exp] : args)
|
for (auto &[name, exp] : args)
|
||||||
{
|
{
|
||||||
const Ast::VarExpr var = std::static_pointer_cast<Ast::VarExprAst>(exp);
|
const Ast::VarExpr var = std::static_pointer_cast<Ast::VarExprAst>(exp);
|
||||||
@@ -987,7 +970,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(FString(u8"Expect ')' or ',' after expression in parentheses"));
|
throwAddressableError<SyntaxError>(String(U"\1"));
|
||||||
}
|
}
|
||||||
return nullptr; // to suppress compiler warning
|
return nullptr; // to suppress compiler warning
|
||||||
}
|
}
|
||||||
@@ -1015,12 +998,12 @@ namespace Fig
|
|||||||
Ast::Import Parser::__parseImport()
|
Ast::Import Parser::__parseImport()
|
||||||
{
|
{
|
||||||
next(); // consume `import`
|
next(); // consume `import`
|
||||||
std::vector<FString> path;
|
std::vector<String> path;
|
||||||
std::vector<FString> names;
|
std::vector<String> names;
|
||||||
FString rename;
|
String rename;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
expect(TokenType::Identifier, u8"package name");
|
expect(TokenType::Identifier, U"\1");
|
||||||
path.push_back(currentToken().getValue());
|
path.push_back(currentToken().getValue());
|
||||||
next(); // consume package name
|
next(); // consume package name
|
||||||
if (isThis(TokenType::Semicolon)) { break; }
|
if (isThis(TokenType::Semicolon)) { break; }
|
||||||
@@ -1032,13 +1015,13 @@ namespace Fig
|
|||||||
else if (isThis(TokenType::LeftBrace)) { break; }
|
else if (isThis(TokenType::LeftBrace)) { break; }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(u8"invalid syntax");
|
throwAddressableError<SyntaxError>(U"\1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isThis(TokenType::As))
|
if (isThis(TokenType::As))
|
||||||
{
|
{
|
||||||
next(); // consume `as`
|
next(); // consume `as`
|
||||||
expect(TokenType::Identifier, u8"new name");
|
expect(TokenType::Identifier, U"\1");
|
||||||
rename = currentToken().getValue();
|
rename = currentToken().getValue();
|
||||||
next(); // consume name
|
next(); // consume name
|
||||||
}
|
}
|
||||||
@@ -1056,7 +1039,7 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
next(); // consume `,`
|
next(); // consume `,`
|
||||||
}
|
}
|
||||||
expect(TokenType::Identifier, u8"symbol name");
|
expect(TokenType::Identifier, U"\1");
|
||||||
names.push_back(currentToken().getValue());
|
names.push_back(currentToken().getValue());
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
@@ -1071,10 +1054,10 @@ namespace Fig
|
|||||||
Ast::Operator op;
|
Ast::Operator op;
|
||||||
|
|
||||||
Token tok = currentToken();
|
Token tok = currentToken();
|
||||||
if (tok == EOFTok) throwAddressableError<SyntaxError>(FString(u8"Unexpected end of expression"));
|
if (tok == EOFTok) throwAddressableError<SyntaxError>(String(U"\1"));
|
||||||
if (tok.getType() == stop || tok.getType() == stop2 || tok.getType() == stop3)
|
if (tok.getType() == stop || tok.getType() == stop2 || tok.getType() == stop3)
|
||||||
{
|
{
|
||||||
if (lhs == nullptr) throwAddressableError<SyntaxError>(FString(u8"Expected expression"));
|
if (lhs == nullptr) throwAddressableError<SyntaxError>(String(U"\1"));
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
if (tok.getType() == TokenType::LeftBracket)
|
if (tok.getType() == TokenType::LeftBracket)
|
||||||
@@ -1095,7 +1078,7 @@ namespace Fig
|
|||||||
if (currentToken().getType() == TokenType::Identifier)
|
if (currentToken().getType() == TokenType::Identifier)
|
||||||
{
|
{
|
||||||
// err
|
// err
|
||||||
throwAddressableError<SyntaxError>(FString(u8"Function literal should not have a name"));
|
throwAddressableError<SyntaxError>(String(U"\1"));
|
||||||
}
|
}
|
||||||
expect(TokenType::LeftParen);
|
expect(TokenType::LeftParen);
|
||||||
lhs = __parseFunctionLiteralExpr();
|
lhs = __parseFunctionLiteralExpr();
|
||||||
@@ -1107,7 +1090,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else if (tok.isIdentifier())
|
else if (tok.isIdentifier())
|
||||||
{
|
{
|
||||||
FString id = tok.getValue();
|
String id = tok.getValue();
|
||||||
next();
|
next();
|
||||||
lhs = __parseVarExpr(id);
|
lhs = __parseVarExpr(id);
|
||||||
}
|
}
|
||||||
@@ -1127,7 +1110,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(FString(u8"Unexpected token in expression:") + tok.toString());
|
throwAddressableError<SyntaxError>(String(U"\1") + tok.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// infix / (postfix) ?
|
// infix / (postfix) ?
|
||||||
@@ -1138,11 +1121,7 @@ namespace Fig
|
|||||||
|
|
||||||
/* Postfix */
|
/* Postfix */
|
||||||
|
|
||||||
if (tok.getType() == TokenType::LeftBrace)
|
if (tok.getType() == TokenType::LeftBrace) { throwAddressableError<SyntaxError>(String(U"\1")); }
|
||||||
{
|
|
||||||
throwAddressableError<SyntaxError>(
|
|
||||||
FString(u8"Since Fig v0.4.2, please use new struct{} to avoid syntax ambiguity"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tok.getType() == TokenType::LeftParen)
|
if (tok.getType() == TokenType::LeftParen)
|
||||||
{
|
{
|
||||||
@@ -1165,10 +1144,9 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
next(); // consume '.'
|
next(); // consume '.'
|
||||||
Token idTok = currentToken();
|
Token idTok = currentToken();
|
||||||
if (!idTok.isIdentifier())
|
if (!idTok.isIdentifier()) throwAddressableError<SyntaxError>(String(U"\1"));
|
||||||
throwAddressableError<SyntaxError>(FString(u8"Expected identifier after '.'"));
|
|
||||||
|
|
||||||
FString member = idTok.getValue();
|
String member = idTok.getValue();
|
||||||
next(); // consume identifier
|
next(); // consume identifier
|
||||||
|
|
||||||
lhs = makeAst<Ast::MemberExprAst>(lhs, member);
|
lhs = makeAst<Ast::MemberExprAst>(lhs, member);
|
||||||
@@ -1224,8 +1202,7 @@ namespace Fig
|
|||||||
auto stmt = __parseStatement();
|
auto stmt = __parseStatement();
|
||||||
if (!output.empty() && stmt->getType() == Ast::AstType::PackageSt)
|
if (!output.empty() && stmt->getType() == Ast::AstType::PackageSt)
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(
|
throwAddressableError<SyntaxError>(U"\1", currentAAI.line, currentAAI.column);
|
||||||
u8"Package must be at the beginning of the file", currentAAI.line, currentAAI.column);
|
|
||||||
}
|
}
|
||||||
pushNode(stmt);
|
pushNode(stmt);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <Ast/astBase.hpp>
|
#include <Ast/astBase.hpp>
|
||||||
#include <Ast/ast.hpp>
|
#include <Ast/ast.hpp>
|
||||||
#include <Lexer/lexer.hpp>
|
#include <Lexer/lexer.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Error/error.hpp>
|
#include <Error/error.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -23,8 +23,8 @@ namespace Fig
|
|||||||
std::vector<Ast::AstBase> output;
|
std::vector<Ast::AstBase> output;
|
||||||
std::vector<Token> previousTokens;
|
std::vector<Token> previousTokens;
|
||||||
|
|
||||||
std::shared_ptr<FString> sourcePathPtr;
|
std::shared_ptr<String> sourcePathPtr;
|
||||||
std::shared_ptr<std::vector<FString>> sourceLinesPtr;
|
std::shared_ptr<std::vector<String>> sourceLinesPtr;
|
||||||
|
|
||||||
size_t tokenPruduced = 0;
|
size_t tokenPruduced = 0;
|
||||||
size_t currentTokenIndex = 0;
|
size_t currentTokenIndex = 0;
|
||||||
@@ -76,16 +76,16 @@ namespace Fig
|
|||||||
static const std::unordered_map<Ast::Operator, std::pair<Precedence, Precedence>> opPrecedence;
|
static const std::unordered_map<Ast::Operator, std::pair<Precedence, Precedence>> opPrecedence;
|
||||||
static const std::unordered_map<Ast::Operator, Precedence> unaryOpPrecedence;
|
static const std::unordered_map<Ast::Operator, Precedence> unaryOpPrecedence;
|
||||||
|
|
||||||
Parser(const Lexer &_lexer, FString _sourcePath, std::vector<FString> _sourceLines) : lexer(_lexer)
|
Parser(const Lexer &_lexer, String _sourcePath, std::vector<String> _sourceLines) : lexer(_lexer)
|
||||||
{
|
{
|
||||||
sourcePathPtr = std::make_shared<FString>(_sourcePath);
|
sourcePathPtr = std::make_shared<String>(_sourcePath);
|
||||||
sourceLinesPtr = std::make_shared<std::vector<FString>>(_sourceLines);
|
sourceLinesPtr = std::make_shared<std::vector<String>>(_sourceLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressableError *getError() const { return error.get(); }
|
AddressableError *getError() const { return error.get(); }
|
||||||
|
|
||||||
template <class _ErrT, typename = AddressableError>
|
template <class _ErrT, typename = AddressableError>
|
||||||
void throwAddressableError(FString msg,
|
void throwAddressableError(String msg,
|
||||||
size_t line,
|
size_t line,
|
||||||
size_t column,
|
size_t column,
|
||||||
std::source_location loc = std::source_location::current())
|
std::source_location loc = std::source_location::current())
|
||||||
@@ -96,7 +96,7 @@ namespace Fig
|
|||||||
throw spError;
|
throw spError;
|
||||||
}
|
}
|
||||||
template <class _ErrT, typename = AddressableError>
|
template <class _ErrT, typename = AddressableError>
|
||||||
void throwAddressableError(FString msg, std::source_location loc = std::source_location::current())
|
void throwAddressableError(String msg, std::source_location loc = std::source_location::current())
|
||||||
{
|
{
|
||||||
static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError");
|
static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError");
|
||||||
// line, column provide by `currentAAI`
|
// line, column provide by `currentAAI`
|
||||||
@@ -106,7 +106,7 @@ namespace Fig
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class _ErrT, typename = UnaddressableError>
|
template <class _ErrT, typename = UnaddressableError>
|
||||||
void throwUnaddressableError(FString msg, std::source_location loc = std::source_location::current())
|
void throwUnaddressableError(String msg, std::source_location loc = std::source_location::current())
|
||||||
{
|
{
|
||||||
static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError");
|
static_assert(std::is_base_of_v<AddressableError, _ErrT>, "_ErrT must derive from AddressableError");
|
||||||
_ErrT spError(msg, loc);
|
_ErrT spError(msg, loc);
|
||||||
@@ -202,9 +202,9 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
if (peekToken().getType() != type)
|
if (peekToken().getType() != type)
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
|
throwAddressableError<SyntaxError>(String(std::format("Expected `{}`, but got `{}`",
|
||||||
magic_enum::enum_name(type),
|
magic_enum::enum_name(type),
|
||||||
magic_enum::enum_name(peekToken().getType()))),
|
magic_enum::enum_name(peekToken().getType()))),
|
||||||
loc);
|
loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,34 +213,32 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
if (currentToken().getType() != type)
|
if (currentToken().getType() != type)
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(
|
throwAddressableError<SyntaxError>(String(std::format("Expected `{}`, but got `{}`",
|
||||||
FString(std::format("Expected `{}`, but got `{}`",
|
magic_enum::enum_name(type),
|
||||||
magic_enum::enum_name(type),
|
magic_enum::enum_name(currentToken().getType()))),
|
||||||
magic_enum::enum_name(currentToken().getType()))),
|
|
||||||
loc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void expectPeek(TokenType type, FString expected, std::source_location loc = std::source_location::current())
|
|
||||||
{
|
|
||||||
if (peekToken().getType() != type)
|
|
||||||
{
|
|
||||||
throwAddressableError<SyntaxError>(FString(std::format("Expected `{}`, but got `{}`",
|
|
||||||
expected.toBasicString(),
|
|
||||||
magic_enum::enum_name(peekToken().getType()))),
|
|
||||||
loc);
|
loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void expect(TokenType type, FString expected, std::source_location loc = std::source_location::current())
|
void expectPeek(TokenType type, String expected, std::source_location loc = std::source_location::current())
|
||||||
|
{
|
||||||
|
if (peekToken().getType() != type)
|
||||||
|
{
|
||||||
|
throwAddressableError<SyntaxError>(String(std::format("Expected `{}`, but got `{}`",
|
||||||
|
expected.toBasicString(),
|
||||||
|
magic_enum::enum_name(peekToken().getType()))),
|
||||||
|
loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void expect(TokenType type, String expected, std::source_location loc = std::source_location::current())
|
||||||
{
|
{
|
||||||
if (currentToken().getType() != type)
|
if (currentToken().getType() != type)
|
||||||
{
|
{
|
||||||
throwAddressableError<SyntaxError>(
|
throwAddressableError<SyntaxError>(String(std::format("Expected `{}`, but got `{}`",
|
||||||
FString(std::format("Expected `{}`, but got `{}`",
|
expected.toBasicString(),
|
||||||
expected.toBasicString(),
|
magic_enum::enum_name(currentToken().getType()))),
|
||||||
magic_enum::enum_name(currentToken().getType()))),
|
loc);
|
||||||
loc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +262,7 @@ namespace Fig
|
|||||||
expectConsume(TokenType::Semicolon, loc);
|
expectConsume(TokenType::Semicolon, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void expectConsume(TokenType type, FString expected, std::source_location loc = std::source_location::current())
|
void expectConsume(TokenType type, String expected, std::source_location loc = std::source_location::current())
|
||||||
{
|
{
|
||||||
expect(type, expected, loc);
|
expect(type, expected, loc);
|
||||||
next();
|
next();
|
||||||
@@ -279,8 +277,6 @@ namespace Fig
|
|||||||
bool isNext(TokenType type) { return peekToken().getType() == type; }
|
bool isNext(TokenType type) { return peekToken().getType() == type; }
|
||||||
bool isThis(TokenType type) { return currentToken().getType() == type; }
|
bool isThis(TokenType type) { return currentToken().getType() == type; }
|
||||||
|
|
||||||
static constexpr FString varDefTypeFollowed = u8"(Followed)";
|
|
||||||
|
|
||||||
Ast::VarDef __parseVarDef(bool); // entry: current is keyword `var` or `const` (isConst: Bool)
|
Ast::VarDef __parseVarDef(bool); // entry: current is keyword `var` or `const` (isConst: Bool)
|
||||||
ObjectPtr __parseValue();
|
ObjectPtr __parseValue();
|
||||||
Ast::ValueExpr __parseValueExpr();
|
Ast::ValueExpr __parseValueExpr();
|
||||||
@@ -294,7 +290,7 @@ namespace Fig
|
|||||||
Ast::Break __parseBreak(); // entry: current is Token::Break
|
Ast::Break __parseBreak(); // entry: current is Token::Break
|
||||||
Ast::Continue __parseContinue(); // entry: current is Token::Continue
|
Ast::Continue __parseContinue(); // entry: current is Token::Continue
|
||||||
|
|
||||||
Ast::VarExpr __parseVarExpr(FString);
|
Ast::VarExpr __parseVarExpr(String);
|
||||||
Ast::FunctionDef __parseFunctionDef(bool); // entry: current is Token::Identifier (isPublic: Bool)
|
Ast::FunctionDef __parseFunctionDef(bool); // entry: current is Token::Identifier (isPublic: Bool)
|
||||||
Ast::StructDef __parseStructDef(bool); // entry: current is Token::Identifier (struct name) arg(isPublic: bool)
|
Ast::StructDef __parseStructDef(bool); // entry: current is Token::Identifier (struct name) arg(isPublic: bool)
|
||||||
Ast::InterfaceDef
|
Ast::InterfaceDef
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <Ast/astBase.hpp>
|
#include <Ast/astBase.hpp>
|
||||||
#include <Error/error.hpp>
|
#include <Error/error.hpp>
|
||||||
#include <Error/errorLog.hpp>
|
#include <Error/errorLog.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <Repl/Repl.hpp>
|
#include <Repl/Repl.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -11,8 +11,8 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
ostream << getPrompt() << "\n";
|
ostream << getPrompt() << "\n";
|
||||||
|
|
||||||
const FString &sourcePath = u8"<stdin>";
|
const String &sourcePath = U"<stdin>";
|
||||||
const std::vector<FString> &sourceLines{};
|
const std::vector<String> &sourceLines{};
|
||||||
|
|
||||||
Evaluator evaluator;
|
Evaluator evaluator;
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ namespace Fig
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
ostream << "\r\n>>";
|
ostream << "\r\n>>";
|
||||||
const FString &line = readline();
|
const String &line = readline();
|
||||||
|
|
||||||
if (line.empty())
|
if (line.empty())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ namespace Fig
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FString readline() const
|
String readline() const
|
||||||
{
|
{
|
||||||
std::string buf;
|
std::string buf;
|
||||||
std::getline(istream, buf);
|
std::getline(istream, buf);
|
||||||
|
|
||||||
return FString(buf);
|
return String(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getPrompt()
|
static std::string getPrompt()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <format>
|
#include <format>
|
||||||
#include <Utils/magic_enum/magic_enum.hpp>
|
#include <Utils/magic_enum/magic_enum.hpp>
|
||||||
|
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
|
|
||||||
namespace Fig
|
namespace Fig
|
||||||
{
|
{
|
||||||
@@ -54,7 +54,7 @@ namespace Fig
|
|||||||
|
|
||||||
/* Literal Types (not keyword)*/
|
/* Literal Types (not keyword)*/
|
||||||
LiteralNumber, // number (int,float...)
|
LiteralNumber, // number (int,float...)
|
||||||
LiteralString, // FString
|
LiteralString, // String
|
||||||
LiteralBool, // bool (true/false)
|
LiteralBool, // bool (true/false)
|
||||||
LiteralNull, // null (Null unique instance)
|
LiteralNull, // null (Null unique instance)
|
||||||
|
|
||||||
@@ -121,56 +121,40 @@ namespace Fig
|
|||||||
friend bool operator==(const Token &l, const Token &r);
|
friend bool operator==(const Token &l, const Token &r);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FString value;
|
String value;
|
||||||
TokenType type;
|
TokenType type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
size_t line, column;
|
size_t line, column;
|
||||||
|
|
||||||
inline Token() {};
|
inline Token() {};
|
||||||
inline Token(const FString &_value, TokenType _type) :
|
inline Token(const String &_value, TokenType _type) : value(_value), type(_type) {}
|
||||||
value(_value), type(_type) {}
|
inline Token(const String &_value, TokenType _type, size_t _line, size_t _column) : value(_value), type(_type)
|
||||||
inline Token(const FString &_value, TokenType _type, size_t _line, size_t _column) :
|
|
||||||
value(_value), type(_type)
|
|
||||||
{
|
{
|
||||||
line = _line;
|
line = _line;
|
||||||
column = _column;
|
column = _column;
|
||||||
}
|
}
|
||||||
const Token& setPos(size_t _line, size_t _column)
|
const Token &setPos(size_t _line, size_t _column)
|
||||||
{
|
{
|
||||||
line = _line;
|
line = _line;
|
||||||
column = _column;
|
column = _column;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
size_t getLength()
|
size_t getLength() { return value.length(); }
|
||||||
|
const String &getValue() const { return value; }
|
||||||
|
inline String toString() const
|
||||||
{
|
{
|
||||||
return value.length();
|
return String(std::format("Token('{}',{})", this->value.toBasicString(), magic_enum::enum_name(type)));
|
||||||
}
|
|
||||||
const FString& getValue() const
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
inline FString toString() const
|
|
||||||
{
|
|
||||||
return FString(std::format(
|
|
||||||
"Token('{}',{})",
|
|
||||||
this->value.toBasicString(),
|
|
||||||
magic_enum::enum_name(type)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isIdentifier()
|
bool isIdentifier() { return type == TokenType::Identifier; }
|
||||||
{
|
|
||||||
return type == TokenType::Identifier;
|
|
||||||
}
|
|
||||||
bool isLiteral()
|
bool isLiteral()
|
||||||
{
|
{
|
||||||
return type == TokenType::LiteralNull || type == TokenType::LiteralBool || type == TokenType::LiteralNumber || type == TokenType::LiteralString;
|
return type == TokenType::LiteralNull || type == TokenType::LiteralBool || type == TokenType::LiteralNumber
|
||||||
}
|
|| type == TokenType::LiteralString;
|
||||||
|
|
||||||
TokenType getType() const
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TokenType getType() const { return type; }
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(const Token &l, const Token &r)
|
inline bool operator==(const Token &l, const Token &r)
|
||||||
@@ -178,6 +162,6 @@ namespace Fig
|
|||||||
return l.type == r.type and l.value == r.value;
|
return l.type == r.type and l.value == r.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Token IllegalTok(u8"ILLEGAL", TokenType::Illegal);
|
static Token IllegalTok(U"ILLEGAL", TokenType::Illegal);
|
||||||
static Token EOFTok(u8"EOF", TokenType::EndOfFile);
|
static Token EOFTok(U"EOF", TokenType::EndOfFile);
|
||||||
} // namespace Fig
|
} // namespace Fig
|
||||||
@@ -15,53 +15,32 @@ public:
|
|||||||
if (!node) return;
|
if (!node) return;
|
||||||
switch (node->getType())
|
switch (node->getType())
|
||||||
{
|
{
|
||||||
case AstType::BinaryExpr:
|
case AstType::BinaryExpr: printBinaryExpr(std::static_pointer_cast<BinaryExprAst>(node), indent); break;
|
||||||
printBinaryExpr(std::static_pointer_cast<BinaryExprAst>(node), indent);
|
case AstType::UnaryExpr: printUnaryExpr(std::static_pointer_cast<UnaryExprAst>(node), indent); break;
|
||||||
break;
|
case AstType::ValueExpr: printValueExpr(std::static_pointer_cast<ValueExprAst>(node), indent); break;
|
||||||
case AstType::UnaryExpr:
|
case AstType::VarDefSt: printVarDef(std::static_pointer_cast<VarDefAst>(node), indent); break;
|
||||||
printUnaryExpr(std::static_pointer_cast<UnaryExprAst>(node), indent);
|
case AstType::VarExpr: printVarExpr(std::static_pointer_cast<VarExprAst>(node), indent); break;
|
||||||
break;
|
|
||||||
case AstType::ValueExpr:
|
|
||||||
printValueExpr(std::static_pointer_cast<ValueExprAst>(node), indent);
|
|
||||||
break;
|
|
||||||
case AstType::VarDefSt:
|
|
||||||
printVarDef(std::static_pointer_cast<VarDefAst>(node), indent);
|
|
||||||
break;
|
|
||||||
case AstType::VarExpr:
|
|
||||||
printVarExpr(std::static_pointer_cast<VarExprAst>(node), indent);
|
|
||||||
break;
|
|
||||||
case AstType::BlockStatement:
|
case AstType::BlockStatement:
|
||||||
printBlockStatement(std::static_pointer_cast<BlockStatementAst>(node), indent);
|
printBlockStatement(std::static_pointer_cast<BlockStatementAst>(node), indent);
|
||||||
break;
|
break;
|
||||||
case AstType::FunctionCall:
|
case AstType::FunctionCall:
|
||||||
printFunctionCall(std::static_pointer_cast<FunctionCallExpr>(node), indent);
|
printFunctionCall(std::static_pointer_cast<FunctionCallExpr>(node), indent);
|
||||||
break;
|
break;
|
||||||
case AstType::FunctionDefSt:
|
case AstType::FunctionDefSt: printFunctionSt(std::static_pointer_cast<FunctionDefSt>(node), indent); break;
|
||||||
printFunctionSt(std::static_pointer_cast<FunctionDefSt>(node), indent);
|
case AstType::IfSt: printIfSt(std::static_pointer_cast<IfSt>(node), indent); break;
|
||||||
break;
|
case AstType::TernaryExpr: printTernaryExpr(std::static_pointer_cast<TernaryExprAst>(node), indent); break;
|
||||||
case AstType::IfSt:
|
default: printIndent(indent); std::cout << "Unknown AST Node\n";
|
||||||
printIfSt(std::static_pointer_cast<IfSt>(node), indent);
|
|
||||||
break;
|
|
||||||
case AstType::TernaryExpr:
|
|
||||||
printTernaryExpr(std::static_pointer_cast<TernaryExprAst>(node), indent);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printIndent(indent);
|
|
||||||
std::cout << "Unknown AST Node\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void printIndent(int indent)
|
void printIndent(int indent) { std::cout << std::string(indent, ' '); }
|
||||||
{
|
|
||||||
std::cout << std::string(indent, ' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
void printFString(const Fig::FString &fstr, int indent)
|
void printFString(const Fig::String &fstr, int indent)
|
||||||
{
|
{
|
||||||
printIndent(indent);
|
printIndent(indent);
|
||||||
std::cout << "FString: \"";
|
std::cout << "String: \"";
|
||||||
std::cout.write(reinterpret_cast<const char *>(fstr.data()), fstr.size());
|
std::cout << fstr;
|
||||||
std::cout << "\"\n";
|
std::cout << "\"\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,10 +112,7 @@ private:
|
|||||||
{
|
{
|
||||||
printIndent(indent);
|
printIndent(indent);
|
||||||
std::cout << "BlockStatement\n";
|
std::cout << "BlockStatement\n";
|
||||||
for (const auto &stmt : node->stmts)
|
for (const auto &stmt : node->stmts) { print(stmt, indent + 2); }
|
||||||
{
|
|
||||||
print(stmt, indent + 2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void printFunctionCall(const std::shared_ptr<FunctionCallExpr> &node, int indent)
|
void printFunctionCall(const std::shared_ptr<FunctionCallExpr> &node, int indent)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Lexer/lexer.hpp>
|
#include <Lexer/lexer.hpp>
|
||||||
#include <Core/fig_string.hpp>
|
#include <Core/String.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <cwctype>
|
#include <cwctype>
|
||||||
@@ -11,36 +11,33 @@
|
|||||||
namespace Fig::Utils
|
namespace Fig::Utils
|
||||||
{
|
{
|
||||||
|
|
||||||
inline std::vector<FString> splitSource(FString source)
|
inline std::vector<String> splitSource(const String &source)
|
||||||
{
|
{
|
||||||
UTF8Iterator it(source);
|
|
||||||
std::vector<FString> lines;
|
std::vector<String> lines;
|
||||||
FString currentLine;
|
String currentLine;
|
||||||
while (!it.isEnd())
|
|
||||||
|
for (char32_t c : source)
|
||||||
{
|
{
|
||||||
UTF8Char c = *it;
|
|
||||||
if (c == U'\n')
|
if (c == U'\n')
|
||||||
{
|
{
|
||||||
lines.push_back(currentLine);
|
lines.push_back(currentLine);
|
||||||
currentLine = FString(u8"");
|
currentLine = String(U"\1");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentLine += c.getString();
|
currentLine += c;
|
||||||
}
|
}
|
||||||
++it;
|
|
||||||
}
|
|
||||||
if (!currentLine.empty())
|
|
||||||
{
|
|
||||||
lines.push_back(currentLine);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!currentLine.empty()) { lines.push_back(currentLine); }
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
inline std::u32string utf8ToUtf32(const FString &s)
|
inline std::u32string utf8ToUtf32(const String &s)
|
||||||
{
|
{
|
||||||
std::u32string result;
|
std::u32string result;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (i < s.size())
|
while (i < s.length())
|
||||||
{
|
{
|
||||||
char32_t codepoint = 0;
|
char32_t codepoint = 0;
|
||||||
unsigned char c = static_cast<unsigned char>(s[i]);
|
unsigned char c = static_cast<unsigned char>(s[i]);
|
||||||
@@ -57,12 +54,15 @@ namespace Fig::Utils
|
|||||||
}
|
}
|
||||||
else if ((c >> 4) == 0xE)
|
else if ((c >> 4) == 0xE)
|
||||||
{
|
{
|
||||||
codepoint = ((c & 0x0F) << 12) | ((static_cast<unsigned char>(s[i + 1]) & 0x3F) << 6) | (static_cast<unsigned char>(s[i + 2]) & 0x3F);
|
codepoint = ((c & 0x0F) << 12) | ((static_cast<unsigned char>(s[i + 1]) & 0x3F) << 6)
|
||||||
|
| (static_cast<unsigned char>(s[i + 2]) & 0x3F);
|
||||||
i += 3;
|
i += 3;
|
||||||
}
|
}
|
||||||
else if ((c >> 3) == 0x1E)
|
else if ((c >> 3) == 0x1E)
|
||||||
{
|
{
|
||||||
codepoint = ((c & 0x07) << 18) | ((static_cast<unsigned char>(s[i + 1]) & 0x3F) << 12) | ((static_cast<unsigned char>(s[i + 2]) & 0x3F) << 6) | (static_cast<unsigned char>(s[i + 3]) & 0x3F);
|
codepoint = ((c & 0x07) << 18) | ((static_cast<unsigned char>(s[i + 1]) & 0x3F) << 12)
|
||||||
|
| ((static_cast<unsigned char>(s[i + 2]) & 0x3F) << 6)
|
||||||
|
| (static_cast<unsigned char>(s[i + 3]) & 0x3F);
|
||||||
i += 4;
|
i += 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -74,60 +74,7 @@ namespace Fig::Utils
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline FString utf32ToUtf8(const std::u32string &s)
|
|
||||||
{
|
|
||||||
FString result;
|
|
||||||
for (char32_t cp : s)
|
|
||||||
{
|
|
||||||
if (cp < 0x80)
|
|
||||||
{
|
|
||||||
result.push_back(static_cast<char8_t>(cp));
|
|
||||||
}
|
|
||||||
else if (cp < 0x800)
|
|
||||||
{
|
|
||||||
result.push_back(static_cast<char8_t>((cp >> 6) | 0xC0));
|
|
||||||
result.push_back(static_cast<char8_t>((cp & 0x3F) | 0x80));
|
|
||||||
}
|
|
||||||
else if (cp < 0x10000)
|
|
||||||
{
|
|
||||||
result.push_back(static_cast<char8_t>((cp >> 12) | 0xE0));
|
|
||||||
result.push_back(static_cast<char8_t>(((cp >> 6) & 0x3F) | 0x80));
|
|
||||||
result.push_back(static_cast<char8_t>((cp & 0x3F) | 0x80));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.push_back(static_cast<char8_t>((cp >> 18) | 0xF0));
|
|
||||||
result.push_back(static_cast<char8_t>(((cp >> 12) & 0x3F) | 0x80));
|
|
||||||
result.push_back(static_cast<char8_t>(((cp >> 6) & 0x3F) | 0x80));
|
|
||||||
result.push_back(static_cast<char8_t>((cp & 0x3F) | 0x80));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FString toLower(const FString &s)
|
|
||||||
{
|
|
||||||
std::u32string u32 = utf8ToUtf32(s);
|
|
||||||
std::locale loc("");
|
|
||||||
for (auto &ch : u32)
|
|
||||||
{
|
|
||||||
ch = std::towlower(ch);
|
|
||||||
}
|
|
||||||
return utf32ToUtf8(u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FString toUpper(const FString &s)
|
|
||||||
{
|
|
||||||
std::u32string u32 = utf8ToUtf32(s);
|
|
||||||
std::locale loc("");
|
|
||||||
for (auto &ch : u32)
|
|
||||||
{
|
|
||||||
ch = std::towupper(ch);
|
|
||||||
}
|
|
||||||
return utf32ToUtf8(u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
bool vectorContains(const T &t, const std::vector<T> v)
|
bool vectorContains(const T &t, const std::vector<T> v)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,10 +24,7 @@ namespace Fig
|
|||||||
uint64_t base = currentFrame->base;
|
uint64_t base = currentFrame->base;
|
||||||
popFrame();
|
popFrame();
|
||||||
|
|
||||||
if (frames.empty())
|
if (frames.empty()) { return ret; }
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
stack.resize(base); // 清除函数的临时值
|
stack.resize(base); // 清除函数的临时值
|
||||||
push(ret);
|
push(ret);
|
||||||
@@ -147,7 +144,8 @@ namespace Fig
|
|||||||
|
|
||||||
if (lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>())
|
if (lhs.is<ValueType::IntClass>() && rhs.is<ValueType::IntClass>())
|
||||||
{
|
{
|
||||||
ValueType::DoubleClass result = (double)lhs.as<ValueType::IntClass>() / (double)rhs.as<ValueType::IntClass>();
|
ValueType::DoubleClass result =
|
||||||
|
(double) lhs.as<ValueType::IntClass>() / (double) rhs.as<ValueType::IntClass>();
|
||||||
push(Object(result));
|
push(Object(result));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -166,12 +164,7 @@ namespace Fig
|
|||||||
case OpCode::JUMP_IF_FALSE: {
|
case OpCode::JUMP_IF_FALSE: {
|
||||||
const Object &cond = pop();
|
const Object &cond = pop();
|
||||||
|
|
||||||
if (!cond.is<bool>())
|
if (!cond.is<bool>()) { throw RuntimeError(String(U"\1")); }
|
||||||
{
|
|
||||||
throw RuntimeError(
|
|
||||||
FString(u8"Condition must be boolean!")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!cond.as<bool>())
|
if (!cond.as<bool>())
|
||||||
{
|
{
|
||||||
// cond is falsity
|
// cond is falsity
|
||||||
@@ -181,19 +174,18 @@ namespace Fig
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpCode::CALL:
|
case OpCode::CALL: {
|
||||||
{
|
|
||||||
uint16_t argCount = static_cast<uint16_t>(ins.operand); // number of max arg is UINT16_MAX
|
uint16_t argCount = static_cast<uint16_t>(ins.operand); // number of max arg is UINT16_MAX
|
||||||
|
|
||||||
const Object &obj = stack.back();
|
const Object &obj = stack.back();
|
||||||
if (!obj.is<Function>())
|
if (!obj.is<Function>())
|
||||||
{
|
{
|
||||||
throw RuntimeError(FString(std::format("{} is not callable", obj.toString().toBasicString())));
|
throw RuntimeError(String(std::format("{} is not callable", obj.toString().toBasicString())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// const Function &fn_obj = obj.as<Function>();
|
// const Function &fn_obj = obj.as<Function>();
|
||||||
// assert(fn_obj.isCompiled && "function must be compiled");
|
// assert(fn_obj.isCompiled && "function must be compiled");
|
||||||
|
|
||||||
CompiledFunction fn;
|
CompiledFunction fn;
|
||||||
|
|
||||||
assert(stack.size() >= argCount && "stack does not have enough arguments");
|
assert(stack.size() >= argCount && "stack does not have enough arguments");
|
||||||
@@ -203,17 +195,11 @@ namespace Fig
|
|||||||
|
|
||||||
pop(); // pop function
|
pop(); // pop function
|
||||||
|
|
||||||
for (int64_t i = 0; i < fn.slotCount - argCount; ++i)
|
for (int64_t i = 0; i < fn.slotCount - argCount; ++i) { push(*Object::getNullInstance()); }
|
||||||
{
|
|
||||||
push(*Object::getNullInstance());
|
|
||||||
}
|
|
||||||
|
|
||||||
CallFrame newFrame
|
CallFrame newFrame{0,
|
||||||
{
|
base, // 参数已经加载到stack, base为第一个参数
|
||||||
0,
|
fn};
|
||||||
base, // 参数已经加载到stack, base为第一个参数
|
|
||||||
fn
|
|
||||||
};
|
|
||||||
|
|
||||||
addFrame(newFrame);
|
addFrame(newFrame);
|
||||||
break;
|
break;
|
||||||
|
|||||||
68
src/main.cpp
68
src/main.cpp
@@ -1,26 +1,37 @@
|
|||||||
/*
|
/*
|
||||||
███████████ █████ █████ ██████████ ███████████ █████ █████████ █████ █████████ ██████ █████ █████████ █████ █████ █████████ █████████ ██████████
|
███████████ █████ █████ ██████████ ███████████ █████ █████████ █████ █████████ ██████ █████
|
||||||
░█░░░███░░░█░░███ ░░███ ░░███░░░░░█ ░░███░░░░░░█░░███ ███░░░░░███ ░░███ ███░░░░░███ ░░██████ ░░███ ███░░░░░███░░███ ░░███ ███░░░░░███ ███░░░░░███░░███░░░░░█
|
█████████ █████ █████ █████████ █████████ ██████████ ░█░░░███░░░█░░███ ░░███ ░░███░░░░░█ ░░███░░░░░░█░░███
|
||||||
░ ░███ ░ ░███ ░███ ░███ █ ░ ░███ █ ░ ░███ ███ ░░░ ░███ ░███ ░███ ░███░███ ░███ ███ ░░░ ░███ ░███ ░███ ░███ ███ ░░░ ░███ █ ░
|
███░░░░░███ ░░███ ███░░░░░███ ░░██████ ░░███ ███░░░░░███░░███ ░░███ ███░░░░░███ ███░░░░░███░░███░░░░░█
|
||||||
░███ ░███████████ ░██████ ░███████ ░███ ░███ ░███ ░███████████ ░███░░███░███ ░███ ░███ ░███ ░███████████ ░███ ░██████
|
░ ░███ ░ ░███ ░███ ░███ █ ░ ░███ █ ░ ░███ ███ ░░░ ░███ ░███ ░███ ░███░███ ░███ ███
|
||||||
░███ ░███░░░░░███ ░███░░█ ░███░░░█ ░███ ░███ █████ ░███ ░███░░░░░███ ░███ ░░██████ ░███ █████ ░███ ░███ ░███░░░░░███ ░███ █████ ░███░░█
|
░░░ ░███ ░███ ░███ ░███ ███ ░░░ ░███ █ ░ ░███ ░███████████ ░██████ ░███████ ░███ ░███ ░███
|
||||||
░███ ░███ ░███ ░███ ░ █ ░███ ░ ░███ ░░███ ░░███ ░███ █ ░███ ░███ ░███ ░░█████ ░░███ ░░███ ░███ ░███ ░███ ░███ ░░███ ░░███ ░███ ░ █
|
░███████████ ░███░░███░███ ░███ ░███ ░███ ░███████████ ░███ ░██████ ░███ ░███░░░░░███ ░███░░█
|
||||||
█████ █████ █████ ██████████ █████ █████ ░░█████████ ███████████ █████ █████ █████ ░░█████ ░░█████████ ░░████████ █████ █████ ░░█████████ ██████████
|
░███░░░█ ░███ ░███ █████ ░███ ░███░░░░░███ ░███ ░░██████ ░███ █████ ░███ ░███ ░███░░░░░███ ░███
|
||||||
░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░
|
█████ ░███░░█ ░███ ░███ ░███ ░███ ░ █ ░███ ░ ░███ ░░███ ░░███ ░███ █ ░███ ░███ ░███
|
||||||
|
░░█████ ░░███ ░░███ ░███ ░███ ░███ ░███ ░░███ ░░███ ░███ ░ █ █████ █████ █████ ██████████ █████
|
||||||
|
█████ ░░█████████ ███████████ █████ █████ █████ ░░█████ ░░█████████ ░░████████ █████ █████ ░░█████████
|
||||||
|
██████████ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░
|
||||||
|
░░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░
|
||||||
|
|
||||||
|
|
||||||
.---.
|
.---.
|
||||||
. __.....__ .--. | | _..._ __.....__
|
. __.....__ .--. | | _..._ __.....__
|
||||||
.'| .-'' '. _.._ |__| .--./) | | .' '. .--./) .--./) .-'' '.
|
.'| .-'' '. _.._ |__| .--./) | | .' '. .--./)
|
||||||
.| < | / .-''"'-. `. .' .._|.--. /.''\\ | | . .-. . /.''\\ /.''\\ / .-''"'-. `.
|
.--./) .-'' '.
|
||||||
.' |_ | | / /________\ \ | ' | || | | | | | __ | ' ' || | | | __ | | | |/ /________\ \
|
.| < | / .-''"'-. `. .' .._|.--. /.''\\ | | . .-. . /.''\\
|
||||||
.' || | .'''-. | | __| |__ | | \`-' / | | .:--.'. | | | | \`-' / _ _ .:--.'. \`-' / | |
|
/.''\\ / .-''"'-. `.
|
||||||
'--. .-'| |/.'''. \\ .-------------' |__ __| | | /("'` | |/ | \ | | | | | /("'` | ' / | / | \ | /("'` \ .-------------'
|
.' |_ | | / /________\ \ | ' | || | | | | | __ | ' ' || | | |
|
||||||
| | | / | | \ '-.____...---. | | | | \ '---. | |`" __ | | | | | | \ '---. .' | .' | `" __ | | \ '---. \ '-.____...---.
|
__ | | | |/ /________\ \
|
||||||
| | | | | | `. .' | | |__| /'""'.\ | | .'.''| | | | | | /'""'.\ / | / | .'.''| | /'""'.\ `. .'
|
.' || | .'''-. | | __| |__ | | \`-' / | | .:--.'. | | | | \`-' / _
|
||||||
| '.'| | | | `''-...... -' | | || || '---'/ / | |_| | | | || ||| `'. | / / | |_|| || `''-...... -'
|
_ .:--.'. \`-' / | |
|
||||||
| / | '. | '. | | \'. __// \ \._,\ '/| | | | \'. __// ' .'| '/\ \._,\ '/\'. __//
|
'--. .-'| |/.'''. \\ .-------------' |__ __| | | /("'` | |/ | \ | | | | | /("'` | '
|
||||||
`'-' '---' '---' |_| `'---' `--' `" '--' '--' `'---' `-' `--' `--' `" `'---'
|
/ | / | \ | /("'` \ .-------------' | | | / | | \ '-.____...---. | | | | \ '---. | |`"
|
||||||
|
__ | | | | | | \ '---. .' | .' | `" __ | | \ '---. \ '-.____...---. | | | | | | `. .' | |
|
||||||
|
|__| /'""'.\ | | .'.''| | | | | | /'""'.\ / | / | .'.''| | /'""'.\ `. .' | '.'| | |
|
||||||
|
| `''-...... -' | | || || '---'/ / | |_| | | | || ||| `'. | / / |
|
||||||
|
|_|| || `''-...... -' | / | '. | '. | | \'. __// \ \._,\ '/| | | |
|
||||||
|
\'. __// ' .'| '/\ \._,\ '/\'. __//
|
||||||
|
`'-' '---' '---' |_| `'---' `--' `" '--' '--' `'---'
|
||||||
|
`-' `--' `--' `" `'---'
|
||||||
|
|
||||||
Copyright (C) 2020-2026 PuqiAR
|
Copyright (C) 2020-2026 PuqiAR
|
||||||
|
|
||||||
@@ -44,21 +55,14 @@ This software is licensed under the MIT License. See LICENSE.txt for details.
|
|||||||
static size_t addressableErrorCount = 0;
|
static size_t addressableErrorCount = 0;
|
||||||
static size_t unaddressableErrorCount = 0;
|
static size_t unaddressableErrorCount = 0;
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
Time::init();
|
Time::init();
|
||||||
// init, set start_time (std::chrono::time_point)
|
// init, set start_time (std::chrono::time_point)
|
||||||
|
|
||||||
|
|
||||||
argparse::ArgumentParser program("Fig Interpreter", Fig::Core::VERSION.data());
|
argparse::ArgumentParser program("Fig Interpreter", Fig::Core::VERSION.data());
|
||||||
program.add_argument("source")
|
program.add_argument("source").help("source file to be interpreted").default_value(std::string(""));
|
||||||
.help("source file to be interpreted")
|
program.add_argument("-r", "--repl").help("start repl").default_value(false).implicit_value(true);
|
||||||
.default_value(std::string(""));
|
|
||||||
program.add_argument("-r", "--repl")
|
|
||||||
.help("start repl")
|
|
||||||
.default_value(false)
|
|
||||||
.implicit_value(true);
|
|
||||||
// program.add_argument("-v", "--version")
|
// program.add_argument("-v", "--version")
|
||||||
// .help("get the version of Fig Interpreter")
|
// .help("get the version of Fig Interpreter")
|
||||||
// .default_value(false)
|
// .default_value(false)
|
||||||
@@ -87,7 +91,7 @@ int main(int argc, char **argv)
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fig::FString sourcePath(program.get<std::string>("source"));
|
Fig::String sourcePath(program.get<std::string>("source"));
|
||||||
if (sourcePath.empty())
|
if (sourcePath.empty())
|
||||||
{
|
{
|
||||||
std::cerr << "No source file provided.\n";
|
std::cerr << "No source file provided.\n";
|
||||||
@@ -102,9 +106,9 @@ int main(int argc, char **argv)
|
|||||||
std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
std::string source((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
std::vector<FString> sourceLines = Fig::Utils::splitSource(Fig::FString(source));
|
std::vector<String> sourceLines = Fig::Utils::splitSource(Fig::String(source));
|
||||||
|
|
||||||
Fig::Lexer lexer((Fig::FString(source)), sourcePath, sourceLines);
|
Fig::Lexer lexer((Fig::String(source)), sourcePath, sourceLines);
|
||||||
|
|
||||||
// Token tok;
|
// Token tok;
|
||||||
// while ((tok = lexer.nextToken()).getType() != TokenType::EndOfFile)
|
// while ((tok = lexer.nextToken()).getType() != TokenType::EndOfFile)
|
||||||
@@ -149,7 +153,7 @@ int main(int argc, char **argv)
|
|||||||
evaluator.SetSourcePath(sourcePath);
|
evaluator.SetSourcePath(sourcePath);
|
||||||
evaluator.SetSourceLines(sourceLines);
|
evaluator.SetSourceLines(sourceLines);
|
||||||
evaluator.CreateGlobalContext();
|
evaluator.CreateGlobalContext();
|
||||||
evaluator.RegisterBuiltinsValue();
|
evaluator.RegisterBuiltinsValue();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ end
|
|||||||
|
|
||||||
add_files("src/Core/warning.cpp")
|
add_files("src/Core/warning.cpp")
|
||||||
add_files("src/Core/runtimeTime.cpp")
|
add_files("src/Core/runtimeTime.cpp")
|
||||||
|
add_files("src/Core/String.cpp")
|
||||||
|
|
||||||
add_files("src/Lexer/lexer.cpp")
|
add_files("src/Lexer/lexer.cpp")
|
||||||
add_files("src/Parser/parser.cpp")
|
add_files("src/Parser/parser.cpp")
|
||||||
|
|||||||
Reference in New Issue
Block a user