From 9c68b2e77d3a1a8314b16158719aefdf24b24185 Mon Sep 17 00:00:00 2001 From: PuqiAR Date: Thu, 5 Feb 2026 22:20:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=9D=E8=AF=95UTF32String?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ast/Expressions/FunctionCall.hpp | 25 +- src/Ast/Expressions/FunctionLiteralExpr.hpp | 17 +- src/Ast/Expressions/InitExpr.hpp | 9 +- src/Ast/Expressions/PostfixExprs.hpp | 18 +- src/Ast/Expressions/VarExpr.hpp | 16 +- src/Ast/Statements/ErrorFlow.hpp | 25 +- src/Ast/Statements/FunctionDefSt.hpp | 14 +- src/Ast/Statements/IfSt.hpp | 41 +- src/Ast/Statements/ImplementSt.hpp | 19 +- src/Ast/Statements/ImportSt.hpp | 17 +- src/Ast/Statements/InterfaceDefSt.hpp | 28 +- src/Ast/Statements/StructDefSt.hpp | 22 +- src/Ast/Statements/VarDef.hpp | 9 +- src/Ast/astBase.hpp | 78 +- src/Ast/functionParameters.hpp | 30 +- src/Bytecode/Chunk.hpp | 12 +- src/Bytecode/CompileError.hpp | 8 +- src/Bytecode/CompiledFunction.hpp | 9 +- src/Bytecode/vm_test_main.cpp | 18 +- src/Core/CharUtils.hpp | 312 +++ src/Core/String.cpp | 12 + src/Core/String.hpp | 2227 ++++++++++------- src/Core/{fig_string.hpp => __fig_string.hpp} | 121 +- ...{utf8_iterator.hpp => __utf8_iterator.hpp} | 0 src/Core/core.hpp | 3 +- src/Core/warning.cpp | 6 +- src/Core/warning.hpp | 39 +- src/Error/error.hpp | 96 +- src/Error/errorLog.hpp | 71 +- src/Evaluator/Context/context.hpp | 71 +- src/Evaluator/Core/Eval.cpp | 24 +- src/Evaluator/Core/EvalBinary.cpp | 48 +- src/Evaluator/Core/EvalFunctionCall.cpp | 51 +- src/Evaluator/Core/EvalInitExpr.cpp | 48 +- src/Evaluator/Core/EvalLvObject.cpp | 26 +- src/Evaluator/Core/EvalStatement.cpp | 159 +- src/Evaluator/Core/EvalTernary.cpp | 2 +- src/Evaluator/Core/EvalUnary.cpp | 2 +- src/Evaluator/Core/ExprResult.hpp | 2 +- src/Evaluator/Core/ResolveModulePath.cpp | 32 +- src/Evaluator/Core/StatementResult.hpp | 2 +- src/Evaluator/Value/IntPool.hpp | 2 +- src/Evaluator/Value/LvObject.hpp | 65 +- src/Evaluator/Value/Type.hpp | 14 +- src/Evaluator/Value/VariableSlot.hpp | 7 +- src/Evaluator/Value/function.hpp | 11 +- src/Evaluator/Value/module.hpp | 17 +- src/Evaluator/Value/structType.hpp | 39 +- src/Evaluator/Value/value.cpp | 38 +- src/Evaluator/Value/value.hpp | 241 +- src/Evaluator/Value/valueError.hpp | 11 +- src/Evaluator/evaluator.cpp | 40 +- src/Evaluator/evaluator.hpp | 54 +- src/Evaluator/evaluator_error.hpp | 36 +- src/IR/IR.hpp | 8 +- src/Lexer/lexer.cpp | 452 ++-- src/Lexer/lexer.hpp | 62 +- src/Module/builtins.cpp | 246 +- src/Module/builtins.hpp | 20 +- src/Parser/parser.cpp | 169 +- src/Parser/parser.hpp | 70 +- src/Repl/Repl.cpp | 8 +- src/Repl/Repl.hpp | 4 +- src/Token/token.hpp | 50 +- src/Utils/AstPrinter.hpp | 52 +- src/Utils/utils.hpp | 91 +- src/VirtualMachine/VirtualMachine.cpp | 38 +- src/main.cpp | 68 +- xmake.lua | 1 + 69 files changed, 3078 insertions(+), 2605 deletions(-) create mode 100644 src/Core/CharUtils.hpp create mode 100644 src/Core/String.cpp rename src/Core/{fig_string.hpp => __fig_string.hpp} (52%) rename src/Core/{utf8_iterator.hpp => __utf8_iterator.hpp} (100%) diff --git a/src/Ast/Expressions/FunctionCall.hpp b/src/Ast/Expressions/FunctionCall.hpp index fb260a8..c9e3fc6 100644 --- a/src/Ast/Expressions/FunctionCall.hpp +++ b/src/Ast/Expressions/FunctionCall.hpp @@ -12,7 +12,7 @@ namespace Fig::Ast size_t getLength() const { return argv.size(); } }; - struct FunctionCallArgs final + struct FunctionCallArgs final { std::vector argv; size_t getLength() const { return argv.size(); } @@ -24,31 +24,26 @@ namespace Fig::Ast Expression callee; FunctionArguments arg; - FunctionCallExpr() + FunctionCallExpr() { type = AstType::FunctionCall; } + + FunctionCallExpr(Expression _callee, FunctionArguments _arg) : callee(std::move(_callee)), arg(std::move(_arg)) { type = AstType::FunctionCall; } - FunctionCallExpr(Expression _callee, FunctionArguments _arg) : - callee(std::move(_callee)), arg(std::move(_arg)) + virtual String toString() override { - type = AstType::FunctionCall; - } - - virtual FString toString() override - { - FString s = callee->toString(); - s += u8"("; + String s = callee->toString(); + s += U"("; for (size_t i = 0; i < arg.argv.size(); ++i) { s += arg.argv[i]->toString(); - if (i + 1 < arg.argv.size()) - s += u8", "; + if (i + 1 < arg.argv.size()) s += U","; } - s += u8")"; + s += U")"; return s; } }; using FunctionCall = std::shared_ptr; -}; // namespace Fig +}; // namespace Fig::Ast diff --git a/src/Ast/Expressions/FunctionLiteralExpr.hpp b/src/Ast/Expressions/FunctionLiteralExpr.hpp index 6742ee5..655c791 100644 --- a/src/Ast/Expressions/FunctionLiteralExpr.hpp +++ b/src/Ast/Expressions/FunctionLiteralExpr.hpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include namespace Fig::Ast @@ -25,20 +25,11 @@ namespace Fig::Ast type = AstType::FunctionLiteralExpr; } - bool isExprMode() const - { - return std::holds_alternative(body); - } + bool isExprMode() const { return std::holds_alternative(body); } - BlockStatement &getBlockBody() - { - return std::get(body); - } + BlockStatement &getBlockBody() { return std::get(body); } - Expression &getExprBody() - { - return std::get(body); - } + Expression &getExprBody() { return std::get(body); } ~FunctionLiteralExprAst() = default; }; diff --git a/src/Ast/Expressions/InitExpr.hpp b/src/Ast/Expressions/InitExpr.hpp index a81ae86..cae1b41 100644 --- a/src/Ast/Expressions/InitExpr.hpp +++ b/src/Ast/Expressions/InitExpr.hpp @@ -9,7 +9,7 @@ namespace Fig::Ast public: Expression structe; - std::vector> args; + std::vector> args; enum class InitMode { @@ -25,12 +25,9 @@ namespace Fig::Ast .3 Person {name, age, sex}; */ - InitExprAst() - { - type = AstType::InitExpr; - } + InitExprAst() { type = AstType::InitExpr; } - InitExprAst(Expression _structe, std::vector> _args, InitMode _initMode) : + InitExprAst(Expression _structe, std::vector> _args, InitMode _initMode) : structe(std::move(_structe)), args(std::move(_args)), initMode(_initMode) { type = AstType::InitExpr; diff --git a/src/Ast/Expressions/PostfixExprs.hpp b/src/Ast/Expressions/PostfixExprs.hpp index 6edcecc..7643f70 100644 --- a/src/Ast/Expressions/PostfixExprs.hpp +++ b/src/Ast/Expressions/PostfixExprs.hpp @@ -11,15 +11,11 @@ namespace Fig::Ast { public: Expression base; - FString member; + String member; - MemberExprAst() - { - type = AstType::MemberExpr; - } + MemberExprAst() { type = AstType::MemberExpr; } - MemberExprAst(Expression _base, FString _member) : - base(std::move(_base)), member(std::move(_member)) + MemberExprAst(Expression _base, String _member) : base(std::move(_base)), member(std::move(_member)) { type = AstType::MemberExpr; } @@ -33,13 +29,9 @@ namespace Fig::Ast Expression base; Expression index; - IndexExprAst() - { - type = AstType::IndexExpr; - } + IndexExprAst() { type = AstType::IndexExpr; } - IndexExprAst(Expression _base, Expression _index) : - base(std::move(_base)), index(std::move(_index)) + IndexExprAst(Expression _base, Expression _index) : base(std::move(_base)), index(std::move(_index)) { type = AstType::IndexExpr; } diff --git a/src/Ast/Expressions/VarExpr.hpp b/src/Ast/Expressions/VarExpr.hpp index ce7fb9b..023f469 100644 --- a/src/Ast/Expressions/VarExpr.hpp +++ b/src/Ast/Expressions/VarExpr.hpp @@ -7,18 +7,10 @@ namespace Fig::Ast class VarExprAst final : public ExpressionAst { public: - const FString name; - VarExprAst() : - name(u8"") - { - type = AstType::VarExpr; - } - VarExprAst(FString _name) : - name(std::move(_name)) - { - type = AstType::VarExpr; - } + const String name; + VarExprAst() : name(U"") { type = AstType::VarExpr; } + VarExprAst(String _name) : name(std::move(_name)) { type = AstType::VarExpr; } }; using VarExpr = std::shared_ptr; -}; // namespace Fig \ No newline at end of file +}; // namespace Fig::Ast \ No newline at end of file diff --git a/src/Ast/Statements/ErrorFlow.hpp b/src/Ast/Statements/ErrorFlow.hpp index cc7cadc..e6c4a8a 100644 --- a/src/Ast/Statements/ErrorFlow.hpp +++ b/src/Ast/Statements/ErrorFlow.hpp @@ -9,34 +9,26 @@ namespace Fig::Ast public: Expression value; - ThrowSt() - { - type = AstType::ThrowSt; - } + ThrowSt() { type = AstType::ThrowSt; } - ThrowSt(Expression _value) : - value(std::move(_value)) - { - type = AstType::ThrowSt; - } + ThrowSt(Expression _value) : value(std::move(_value)) { type = AstType::ThrowSt; } }; using Throw = std::shared_ptr; struct Catch { - FString errVarName; + String errVarName; bool hasType = false; - FString errVarType; + String errVarType; BlockStatement body; 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)) { hasType = true; } - Catch(FString _errVarName, BlockStatement _body) : - errVarName(std::move(_errVarName)), body(std::move(_body)) + Catch(String _errVarName, BlockStatement _body) : errVarName(std::move(_errVarName)), body(std::move(_body)) { hasType = false; } @@ -49,10 +41,7 @@ namespace Fig::Ast std::vector catches; BlockStatement finallyBlock = nullptr; - TrySt() - { - type = AstType::TrySt; - } + TrySt() { type = AstType::TrySt; } TrySt(BlockStatement _body, std::vector _catches, BlockStatement _finallyBlock) : body(std::move(_body)), catches(std::move(_catches)), finallyBlock(std::move(_finallyBlock)) { diff --git a/src/Ast/Statements/FunctionDefSt.hpp b/src/Ast/Statements/FunctionDefSt.hpp index b7f1426..03ddc92 100644 --- a/src/Ast/Statements/FunctionDefSt.hpp +++ b/src/Ast/Statements/FunctionDefSt.hpp @@ -20,17 +20,15 @@ namespace Fig::Ast class FunctionDefSt final : public StatementAst // for definition { public: - FString name; + String name; FunctionParameters paras; bool isPublic; - Expression retType; + Expression retType; BlockStatement body; - FunctionDefSt() - { - type = AstType::FunctionDefSt; - } - FunctionDefSt(FString _name, FunctionParameters _paras, bool _isPublic, Expression _retType, BlockStatement _body) + FunctionDefSt() { type = AstType::FunctionDefSt; } + FunctionDefSt( + String _name, FunctionParameters _paras, bool _isPublic, Expression _retType, BlockStatement _body) { type = AstType::FunctionDefSt; @@ -42,4 +40,4 @@ namespace Fig::Ast } }; using FunctionDef = std::shared_ptr; -}; // namespace Fig \ No newline at end of file +}; // namespace Fig::Ast \ No newline at end of file diff --git a/src/Ast/Statements/IfSt.hpp b/src/Ast/Statements/IfSt.hpp index 7643abd..be54ac9 100644 --- a/src/Ast/Statements/IfSt.hpp +++ b/src/Ast/Statements/IfSt.hpp @@ -8,19 +8,9 @@ namespace Fig::Ast { public: BlockStatement body; - ElseSt() - { - type = AstType::ElseSt; - } - ElseSt(BlockStatement _body) : - body(_body) - { - type = AstType::ElseSt; - } - virtual FString toString() override - { - return FString(std::format("", aai.line, aai.column)); - } + ElseSt() { type = AstType::ElseSt; } + ElseSt(BlockStatement _body) : body(_body) { type = AstType::ElseSt; } + virtual String toString() override { return String(std::format("", aai.line, aai.column)); } }; using Else = std::shared_ptr; class ElseIfSt final : public StatementAst @@ -28,19 +18,14 @@ namespace Fig::Ast public: Expression condition; BlockStatement body; - ElseIfSt() + ElseIfSt() { type = AstType::ElseIfSt; } + ElseIfSt(Expression _condition, BlockStatement _body) : condition(_condition), body(_body) { type = AstType::ElseIfSt; } - ElseIfSt(Expression _condition, - BlockStatement _body) : - condition(_condition), body(_body) + virtual String toString() override { - type = AstType::ElseIfSt; - } - virtual FString toString() override - { - return FString(std::format("", aai.line, aai.column)); + return String(std::format("", aai.line, aai.column)); } }; using ElseIf = std::shared_ptr; @@ -51,18 +36,12 @@ namespace Fig::Ast BlockStatement body; std::vector elifs; Else els; - IfSt() - { - type = AstType::IfSt; - } - IfSt(Expression _condition, - BlockStatement _body, - std::vector _elifs, - Else _els) : + IfSt() { type = AstType::IfSt; } + IfSt(Expression _condition, BlockStatement _body, std::vector _elifs, Else _els) : condition(_condition), body(_body), elifs(_elifs), els(_els) { type = AstType::IfSt; } }; using If = std::shared_ptr; -}; // namespace Fig \ No newline at end of file +}; // namespace Fig::Ast \ No newline at end of file diff --git a/src/Ast/Statements/ImplementSt.hpp b/src/Ast/Statements/ImplementSt.hpp index 4d021b1..8a082af 100644 --- a/src/Ast/Statements/ImplementSt.hpp +++ b/src/Ast/Statements/ImplementSt.hpp @@ -6,18 +6,18 @@ namespace Fig::Ast { /* - + impl Readable for File { read() -> String { ... } - + */ struct ImplementMethod { - FString name; + String name; FunctionParameters paras; BlockStatement body; }; @@ -25,17 +25,14 @@ namespace Fig::Ast class ImplementAst final : public StatementAst { public: - FString interfaceName; - FString structName; + String interfaceName; + String structName; std::vector methods; - ImplementAst() - { - type = AstType::ImplementSt; - } + ImplementAst() { type = AstType::ImplementSt; } - ImplementAst(FString _interfaceName, FString _structName, std::vector _methods) : + ImplementAst(String _interfaceName, String _structName, std::vector _methods) : interfaceName(std::move(_interfaceName)), structName(std::move(_structName)), methods(std::move(_methods)) { type = AstType::ImplementSt; @@ -43,4 +40,4 @@ namespace Fig::Ast }; using Implement = std::shared_ptr; -}; \ No newline at end of file +}; // namespace Fig::Ast \ No newline at end of file diff --git a/src/Ast/Statements/ImportSt.hpp b/src/Ast/Statements/ImportSt.hpp index 57338f7..7f33a56 100644 --- a/src/Ast/Statements/ImportSt.hpp +++ b/src/Ast/Statements/ImportSt.hpp @@ -14,17 +14,14 @@ namespace Fig::Ast class ImportSt final : public StatementAst { public: - std::vector path; - std::vector names; + std::vector path; + std::vector names; - FString rename; - - ImportSt() - { - type = AstType::ImportSt; - } + String rename; - ImportSt(std::vector _path, std::vector _names, const FString &_rename) : + ImportSt() { type = AstType::ImportSt; } + + ImportSt(std::vector _path, std::vector _names, const String &_rename) : path(std::move(_path)), names(std::move(_names)), rename(_rename) { type = AstType::ImportSt; @@ -32,4 +29,4 @@ namespace Fig::Ast }; using Import = std::shared_ptr; -}; \ No newline at end of file +}; // namespace Fig::Ast \ No newline at end of file diff --git a/src/Ast/Statements/InterfaceDefSt.hpp b/src/Ast/Statements/InterfaceDefSt.hpp index e0fb141..aafce32 100644 --- a/src/Ast/Statements/InterfaceDefSt.hpp +++ b/src/Ast/Statements/InterfaceDefSt.hpp @@ -3,52 +3,44 @@ #include #include - namespace Fig::Ast { /* - + interface Readable { read() -> String { // default } - + flush() -> Null; // non-default } - - */ + */ struct InterfaceMethod { - FString name; + String name; FunctionParameters paras; Expression returnType; BlockStatement defaultBody = nullptr; // nullptr is non-default func - bool hasDefaultBody() const - { - return defaultBody != nullptr; - } + bool hasDefaultBody() const { return defaultBody != nullptr; } }; class InterfaceDefAst final : public StatementAst { public: - FString name; + String name; std::vector methods; - std::vector parents; // Feature, NOT NOW + std::vector parents; // Feature, NOT NOW bool isPublic; - InterfaceDefAst() - { - type = AstType::InterfaceDefSt; - } + InterfaceDefAst() { type = AstType::InterfaceDefSt; } - InterfaceDefAst(FString _name, std::vector _methods, bool _isPublic) : + InterfaceDefAst(String _name, std::vector _methods, bool _isPublic) : name(std::move(_name)), methods(std::move(_methods)), isPublic(_isPublic) { type = AstType::InterfaceDefSt; @@ -56,4 +48,4 @@ namespace Fig::Ast }; using InterfaceDef = std::shared_ptr; -}; \ No newline at end of file +}; // namespace Fig::Ast \ No newline at end of file diff --git a/src/Ast/Statements/StructDefSt.hpp b/src/Ast/Statements/StructDefSt.hpp index d04d467..0442e1a 100644 --- a/src/Ast/Statements/StructDefSt.hpp +++ b/src/Ast/Statements/StructDefSt.hpp @@ -11,13 +11,16 @@ namespace Fig::Ast struct StructDefField { AccessModifier am; - FString fieldName; - Expression declaredType; + String fieldName; + Expression declaredType; Expression defaultValueExpr; StructDefField() {} - StructDefField(AccessModifier _am, FString _fieldName, Expression _declaredType, Expression _defaultValueExpr) : - am(std::move(_am)), fieldName(std::move(_fieldName)), declaredType(std::move(_declaredType)), defaultValueExpr(std::move(_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)) { } }; @@ -25,15 +28,12 @@ namespace Fig::Ast { public: bool isPublic; - const FString name; + const String name; const std::vector fields; // field name (:type name = default value expression) // name / name: String / name: String = "Fig" const BlockStatement body; - StructDefSt() - { - type = AstType::StructSt; - } - StructDefSt(bool _isPublic, FString _name, std::vector _fields, BlockStatement _body) : + StructDefSt() { type = AstType::StructSt; } + StructDefSt(bool _isPublic, String _name, std::vector _fields, BlockStatement _body) : isPublic(std::move(_isPublic)), name(std::move(_name)), fields(std::move(_fields)), body(std::move(_body)) { type = AstType::StructSt; @@ -41,4 +41,4 @@ namespace Fig::Ast }; using StructDef = std::shared_ptr; -}; // namespace Fig \ No newline at end of file +}; // namespace Fig::Ast \ No newline at end of file diff --git a/src/Ast/Statements/VarDef.hpp b/src/Ast/Statements/VarDef.hpp index d0f0280..0419867 100644 --- a/src/Ast/Statements/VarDef.hpp +++ b/src/Ast/Statements/VarDef.hpp @@ -10,8 +10,8 @@ namespace Fig::Ast public: bool isPublic; bool isConst; - FString name; - // FString typeName; + String name; + // String typeName; Expression declaredType; Expression expr; @@ -24,7 +24,8 @@ namespace Fig::Ast expr = nullptr; 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; isPublic = _isPublic; @@ -37,4 +38,4 @@ namespace Fig::Ast }; using VarDef = std::shared_ptr; -} // namespace Fig \ No newline at end of file +} // namespace Fig::Ast \ No newline at end of file diff --git a/src/Ast/astBase.hpp b/src/Ast/astBase.hpp index 99e2fd9..c32f4f1 100644 --- a/src/Ast/astBase.hpp +++ b/src/Ast/astBase.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include @@ -66,43 +66,43 @@ namespace Fig::Ast ThrowSt, }; - // static const std::unordered_map astTypeToString{ + // static const std::unordered_map astTypeToString{ // /* Base Class */ - // {AstType::_AstBase, FString(u8"Ast")}, - // {AstType::StatementBase, FString(u8"Statement")}, - // {AstType::ExpressionBase, FString(u8"Expression")}, + // {AstType::_AstBase, String(U"Ast")}, + // {AstType::StatementBase, String(U"Statement")}, + // {AstType::ExpressionBase, String(U"Expression")}, // /* Expression */ - // {AstType::ValueExpr, FString(u8"ValueExpr")}, - // {AstType::LambdaExpr, FString(u8"LambdaExpr")}, - // {AstType::UnaryExpr, FString(u8"UnaryExpr")}, - // {AstType::BinaryExpr, FString(u8"BinaryExpr")}, - // {AstType::TernaryExpr, FString(u8"TernaryExpr")}, + // {AstType::ValueExpr, String(U"ValueExpr")}, + // {AstType::LambdaExpr, String(U"LambdaExpr")}, + // {AstType::UnaryExpr, String(U"UnaryExpr")}, + // {AstType::BinaryExpr, String(U"BinaryExpr")}, + // {AstType::TernaryExpr, String(U"TernaryExpr")}, - // {AstType::InitExpr, FString(u8"InitExpr")}, + // {AstType::InitExpr, String(U"InitExpr")}, // /* Statement */ - // {AstType::BlockStatement, FString(u8"BlockStatement")}, + // {AstType::BlockStatement, String(U"BlockStatement")}, - // {AstType::VarDefSt, FString(u8"VarSt")}, - // {AstType::FunctionDefSt, FString(u8"FunctionDefSt")}, - // {AstType::StructSt, FString(u8"StructSt")}, - // {AstType::ImplementSt, FString(u8"ImplementSt")}, + // {AstType::VarDefSt, String(U"VarSt")}, + // {AstType::FunctionDefSt, String(U"FunctionDefSt")}, + // {AstType::StructSt, String(U"StructSt")}, + // {AstType::ImplementSt, String(U"ImplementSt")}, - // {AstType::IfSt, FString(u8"IfSt")}, - // {AstType::ElseSt, FString(u8"ElseSt")}, - // {AstType::ElseIfSt, FString(u8"ElseIfSt")}, - // {AstType::VarAssignSt, FString(u8"VarAssignSt")}, - // {AstType::WhileSt, FString(u8"WhileSt")}, - // {AstType::ReturnSt, FString(u8"ReturnSt")}, - // {AstType::BreakSt, FString(u8"BreakSt")}, - // {AstType::ContinueSt, FString(u8"ContinueSt")}, + // {AstType::IfSt, String(U"IfSt")}, + // {AstType::ElseSt, String(U"ElseSt")}, + // {AstType::ElseIfSt, String(U"ElseIfSt")}, + // {AstType::VarAssignSt, String(U"VarAssignSt")}, + // {AstType::WhileSt, String(U"WhileSt")}, + // {AstType::ReturnSt, String(U"ReturnSt")}, + // {AstType::BreakSt, String(U"BreakSt")}, + // {AstType::ContinueSt, String(U"ContinueSt")}, // }; struct AstAddressInfo { size_t line, column; - std::shared_ptr sourcePath; - std::shared_ptr> sourceLines; + std::shared_ptr sourcePath; + std::shared_ptr> sourceLines; }; class _AstBase @@ -122,14 +122,14 @@ namespace Fig::Ast void setAAI(AstAddressInfo _aai) { aai = std::move(_aai); } - virtual FString typeName() + virtual String typeName() { 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("", typeName().toBasicString(), aai.line, aai.column)); + return String(std::format("", typeName().toBasicString(), aai.line, aai.column)); } AstAddressInfo getAAI() { return aai; } @@ -144,9 +144,9 @@ namespace Fig::Ast using _AstBase::operator=; StatementAst() { type = AstType::StatementBase; } - virtual FString toString() override + virtual String toString() override { - return FString(std::format("", typeName().toBasicString(), aai.line, aai.column)); + return String(std::format("", typeName().toBasicString(), aai.line, aai.column)); } }; @@ -155,9 +155,9 @@ namespace Fig::Ast public: EofStmt() { type = AstType::StatementBase; } - virtual FString toString() override + virtual String toString() override { - return FString(std::format("", aai.line, aai.column)); + return String(std::format("", aai.line, aai.column)); } }; @@ -168,9 +168,9 @@ namespace Fig::Ast using _AstBase::operator=; ExpressionAst() { type = AstType::ExpressionBase; } - virtual FString toString() override + virtual String toString() override { - return FString(std::format("", typeName().toBasicString(), aai.line, aai.column)); + return String(std::format("", typeName().toBasicString(), aai.line, aai.column)); } }; enum class Operator : uint8_t @@ -326,10 +326,10 @@ namespace Fig::Ast std::vector stmts; BlockStatementAst() { type = AstType::BlockStatement; } BlockStatementAst(std::vector _stmts) : stmts(std::move(_stmts)) { type = AstType::BlockStatement; } - virtual FString typeName() override { return FString(u8"BlockStatement"); } - virtual FString toString() override + virtual String typeName() override { return String(U"BlockStatement"); } + virtual String toString() override { - return FString(std::format("", typeName().toBasicString(), aai.line, aai.column)); + return String(std::format("", typeName().toBasicString(), aai.line, aai.column)); } virtual ~BlockStatementAst() = default; }; diff --git a/src/Ast/functionParameters.hpp b/src/Ast/functionParameters.hpp index 18299cf..43d3eee 100644 --- a/src/Ast/functionParameters.hpp +++ b/src/Ast/functionParameters.hpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include @@ -17,15 +17,15 @@ namespace Fig::Ast func test2(dp1 = 10, dp2:String = "default parameter 2") */ - using PosParasType = std::vector>; + using PosParasType = std::vector>; // name type exp - using DefParasType = std::vector>>; + using DefParasType = std::vector>>; // name type exp default value PosParasType posParas; DefParasType defParas; // default parameters - FString variadicPara; + String variadicPara; bool variadic = false; FunctionParameters() @@ -36,7 +36,7 @@ namespace Fig::Ast posParas = std::move(_posParas); defParas = std::move(_defParas); } - FunctionParameters(FString _variadicPara) + FunctionParameters(String _variadicPara) { variadicPara = std::move(_variadicPara); variadic = true; @@ -52,46 +52,46 @@ namespace Fig::Ast return posParas == other.posParas && defParas == other.defParas && variadicPara == other.variadicPara && variadic == other.variadic; } - FString toString() const + String toString() const { if (variadic) { - return FString(variadicPara + u8"..."); + return String(variadicPara + U"..."); } const auto posParasToString = [this]() { - FString out; + String out; for (auto &p : posParas) { out += p.first; if (p.second != nullptr) { - out += FString(u8":" + p.second->toString()); + out += String(String(U":") + p.second->toString()); } - out += u8","; + out += U","; } out.pop_back(); return out; }; const auto defParasToString = [this]() { - FString out; + String out; for (auto &p : defParas) { out += p.first; 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) { - out += u8"="; + out += U"="; out += p.second.second->toString(); } - out += u8","; + out += U","; } out.pop_back(); return out; }; - return FString(std::format("{},{}", posParasToString().toBasicString(), defParasToString().toBasicString())); + return String(std::format("{},{}", posParasToString().toBasicString(), defParasToString().toBasicString())); } }; } // namespace Fig::Ast \ No newline at end of file diff --git a/src/Bytecode/Chunk.hpp b/src/Bytecode/Chunk.hpp index b85b317..ca7c612 100644 --- a/src/Bytecode/Chunk.hpp +++ b/src/Bytecode/Chunk.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -10,16 +10,16 @@ namespace Fig { struct ChunkAddressInfo { - FString sourcePath; - std::vector sourceLines; + String sourcePath; + std::vector sourceLines; }; struct Chunk { - Instructions ins; // vector + Instructions ins; // vector std::vector constants; // 常量池 std::vector instructions_addr; // 下标和ins对齐,表示每个Instruction对应的地址 - ChunkAddressInfo addr; // 代码块独立Addr + ChunkAddressInfo addr; // 代码块独立Addr }; -}; \ No newline at end of file +}; // namespace Fig \ No newline at end of file diff --git a/src/Bytecode/CompileError.hpp b/src/Bytecode/CompileError.hpp index 42dd218..8918315 100644 --- a/src/Bytecode/CompileError.hpp +++ b/src/Bytecode/CompileError.hpp @@ -8,15 +8,15 @@ namespace Fig { using AddressableError::AddressableError; - virtual FString toString() const override + virtual String toString() const override { std::string msg = std::format("[CompileError] {} in [{}] {}", this->message.toBasicString(), this->src_loc.file_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"); } }; -}; \ No newline at end of file +}; // namespace Fig \ No newline at end of file diff --git a/src/Bytecode/CompiledFunction.hpp b/src/Bytecode/CompiledFunction.hpp index 1ec9125..c1ad2fc 100644 --- a/src/Bytecode/CompiledFunction.hpp +++ b/src/Bytecode/CompiledFunction.hpp @@ -7,15 +7,14 @@ namespace Fig { struct CompiledFunction { - Chunk chunk; // 函数代码块 - FString name; // 函数名 + String name; // 函数名 uint64_t posArgCount; // 位置参数数量 uint64_t defArgCount; // 默认参数数量 bool variadicPara; // 可变参数(是:最后为可变,否:不可变) - uint64_t localCount; // 局部变量数量(不包括参数) - uint64_t slotCount; // = 总参数数量 + 局部变量数量 + uint64_t localCount; // 局部变量数量(不包括参数) + uint64_t slotCount; // = 总参数数量 + 局部变量数量 }; -}; \ No newline at end of file +}; // namespace Fig \ No newline at end of file diff --git a/src/Bytecode/vm_test_main.cpp b/src/Bytecode/vm_test_main.cpp index 7fff430..70edb10 100644 --- a/src/Bytecode/vm_test_main.cpp +++ b/src/Bytecode/vm_test_main.cpp @@ -24,9 +24,9 @@ int main() // ---------------- fib ---------------- Instructions fib_ins{ - /* 0 */ {OpCode::LOAD_LOCAL, 0}, // x - /* 1 */ {OpCode::LOAD_CONST, 0}, // 1 - /* 2 */ {OpCode::LTET}, // x <= 1 + /* 0 */ {OpCode::LOAD_LOCAL, 0}, // x + /* 1 */ {OpCode::LOAD_CONST, 0}, // 1 + /* 2 */ {OpCode::LTET}, // x <= 1 /* 3 */ {OpCode::JUMP_IF_FALSE, 2}, // false -> jump to 6 /* 4 */ {OpCode::LOAD_LOCAL, 0}, // return x @@ -34,13 +34,13 @@ int main() /* 6 */ {OpCode::LOAD_LOCAL, 0}, // x /* 7 */ {OpCode::LOAD_CONST, 0}, // 1 - /* 8 */ {OpCode::SUB}, // x - 1 + /* 8 */ {OpCode::SUB}, // x - 1 /* 9 */ {OpCode::LOAD_CONST, 2}, // fib /* 10 */ {OpCode::CALL, 1}, // fib(x-1) /* 11 */ {OpCode::LOAD_LOCAL, 0}, // x /* 12 */ {OpCode::LOAD_CONST, 1}, // 2 - /* 13 */ {OpCode::SUB}, // x - 2 + /* 13 */ {OpCode::SUB}, // x - 2 /* 14 */ {OpCode::LOAD_CONST, 2}, // fib /* 15 */ {OpCode::CALL, 1}, // fib(x-2) @@ -56,7 +56,7 @@ int main() CompiledFunction fib_fn{ {}, - u8"fib", + U"\1", 1, // posArgCount 0, false, @@ -81,13 +81,13 @@ int main() }; std::vector main_consts{ - Object((int64_t)251), // 0 - Object(Function(&fib_fn)), // 1 + Object((int64_t) 251), // 0 + Object(Function(&fib_fn)), // 1 }; 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}; diff --git a/src/Core/CharUtils.hpp b/src/Core/CharUtils.hpp new file mode 100644 index 0000000..02fd2e5 --- /dev/null +++ b/src/Core/CharUtils.hpp @@ -0,0 +1,312 @@ +#pragma once + +#include +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 + } +}; \ No newline at end of file diff --git a/src/Core/String.cpp b/src/Core/String.cpp new file mode 100644 index 0000000..02da3a6 --- /dev/null +++ b/src/Core/String.cpp @@ -0,0 +1,12 @@ +#include + +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]; + } +}; \ No newline at end of file diff --git a/src/Core/String.hpp b/src/Core/String.hpp index bc9f314..f14a28d 100644 --- a/src/Core/String.hpp +++ b/src/Core/String.hpp @@ -6,868 +6,908 @@ #include #include -namespace Fig::StringClass::SizeFixed -{ - class String - { - private: - static constexpr uint8_t SSO_SIZE = 32; - static constexpr uint8_t SSO_MAX_ASCII_LEN = SSO_SIZE; - static constexpr uint8_t SSO_MAX_UTF32_LEN = SSO_SIZE / 4; - - bool is_heap; - bool is_ascii; - uint64_t _length; - - union - { - struct - { - union - { - unsigned char ascii[SSO_MAX_ASCII_LEN]; // 1 * 32 byte - char32_t utf32[SSO_MAX_UTF32_LEN]; // 4 * 8 byte - }; - } sso; - - struct - { - union - { - unsigned char *ascii; - char32_t *utf32; - }; - } heap; - }; - - void destroy() - { - _length = 0; - - if (is_heap) - { - if (is_ascii) { delete[] heap.ascii; } - else - { - delete[] heap.utf32; - } - } - // sso, pass - } - - void alloc_heap(bool ascii, uint64_t size) - { - if (ascii) { heap.ascii = new unsigned char[size]; } - else - { - heap.utf32 = new char32_t[size]; - } - } - - void realloc_heap(bool ascii, uint64_t size) - { - destroy(); - - if (ascii) { heap.ascii = new unsigned char[size]; } - else - { - heap.utf32 = new char32_t[size]; - } - } - - void copy(const String &other) - { - if (other.is_heap) - { - if (!is_heap) - { - destroy(); - is_heap = other.is_heap; - } - if (_length != other._length) - { - realloc_heap(other.is_ascii, other._length); - _length = other._length; - } - is_ascii = other.is_ascii; - if (is_ascii) - { - for (uint64_t i = 0; i < _length; ++i) { heap.ascii[i] = other.heap.ascii[i]; } - } - else - { - for (uint64_t i = 0; i < _length; ++i) { heap.utf32[i] = other.heap.utf32[i]; } - } - } - else - { - // other is sso - if (is_heap) - { - destroy(); - is_heap = other.is_heap; - } - is_ascii = other.is_ascii; - _length = other._length; - - if (is_ascii) - { - for (uint64_t i = 0; i < _length; ++i) { sso.ascii[i] = other.sso.ascii[i]; } - } - else - { - for (uint64_t i = 0; i < _length; ++i) { sso.utf32[i] = other.sso.utf32[i]; } - } - } - } - - void init(const char *cstr) - { - is_ascii = isPureASCII(cstr); - - if (is_ascii) - { - uint64_t len = strlen(cstr); - _length = len; - if (len <= SSO_MAX_ASCII_LEN) - { - memcpy(sso.ascii, cstr, len); - is_heap = false; - } - else - { - realloc_heap(true, len); - memcpy(heap.ascii, cstr, len); - is_heap = true; - } - } - else - { - uint64_t len = fixed_strlen(cstr); - _length = 0; - if (len <= SSO_MAX_UTF32_LEN) - { - for (size_t i = 0; cstr[i] != '\0';) - { - unsigned char c = static_cast(cstr[i]); - if (c <= 0x7F) - { - sso.utf32[_length++] = static_cast(c); - ++i; - } - else if ((c & 0xE0) == 0xC0) - { - char32_t result = ((c & 0x1F) << 6) | (cstr[i + 1] & 0x3F); - sso.utf32[_length++] = result; - i += 2; - } - else if ((c & 0xF0) == 0xE0) - { - char32_t result = ((c & 0x1F) << 12) | ((cstr[i + 1] & 0x3F) << 6) | ((cstr[i + 2] & 0x3F)); - sso.utf32[_length++] = result; - i += 3; - } - else if ((c & 0xF8) == 0xF0) - { - char32_t result = ((c & 0x07) << 18) | ((cstr[i + 1] & 0x3F) << 12) - | ((cstr[i + 2] & 0x3F) << 6) | (cstr[i + 3] & 0x3F); - sso.utf32[_length++] = result; - i += 4; - } - else - { - assert(false && "bad utf8 string"); - } - } - is_heap = false; - } - else - { - realloc_heap(false, len); - _length = 0; - for (size_t i = 0; cstr[i] != '\0';) - { - unsigned char c = static_cast(cstr[i]); - if (c <= 0x7F) - { - heap.utf32[_length++] = static_cast(c); - ++i; - } - else if ((c & 0xE0) == 0xC0) - { - char32_t result = ((c & 0x1F) << 6) | (cstr[i + 1] & 0x3F); - heap.utf32[_length++] = result; - i += 2; - } - else if ((c & 0xF0) == 0xE0) - { - char32_t result = ((c & 0x1F) << 12) | ((cstr[i + 1] & 0x3F) << 6) | ((cstr[i + 2] & 0x3F)); - heap.utf32[_length++] = result; - i += 3; - } - else if ((c & 0xF8) == 0xF0) - { - char32_t result = ((c & 0x07) << 18) | ((cstr[i + 1] & 0x3F) << 12) - | ((cstr[i + 2] & 0x3F) << 6) | (cstr[i + 3] & 0x3F); - heap.utf32[_length++] = result; - i += 4; - } - else - { - assert(false && "bad utf8 string"); - } - } - is_heap = true; - } - } - } - - void init(const char32_t *str) - { - assert(str); - - uint64_t len = 0; - bool ascii = true; - - for (const char32_t *p = str; *p != U'\0'; ++p) - { - if (*p > 0x7F) ascii = false; - ++len; - } - - _length = len; - is_ascii = ascii; - - if (ascii) - { - if (len <= SSO_MAX_ASCII_LEN) - { - is_heap = false; - for (uint64_t i = 0; i < len; ++i) sso.ascii[i] = static_cast(str[i]); - } - else - { - is_heap = true; - realloc_heap(true, len); - for (uint64_t i = 0; i < len; ++i) heap.ascii[i] = static_cast(str[i]); - } - } - else - { - if (len <= SSO_MAX_UTF32_LEN) - { - is_heap = false; - for (uint64_t i = 0; i < len; ++i) sso.utf32[i] = str[i]; - } - else - { - is_heap = true; - realloc_heap(false, len); - for (uint64_t i = 0; i < len; ++i) heap.utf32[i] = str[i]; - } - } - } - - void init(const std::string &str) { init(str.c_str()); } - - void promote_sso_to_heap(uint64_t len) - { - if (is_heap) return; - - is_heap = true; - - if (is_ascii) - { - heap.ascii = new unsigned char[len]; - memcpy(heap.ascii, sso.ascii, _length); - } - else - { - heap.utf32 = new char32_t[len]; - memcpy(heap.utf32, sso.utf32, sizeof(char32_t) * _length); - } - _length = len; - } - - void move_sso_ascii_to_sso_utf() - { - // current: sso, ascii - // after: sso, utf32 - - assert(is_ascii); - assert(!is_heap); - - is_ascii = false; - - for (uint8_t i = 0; i < _length; ++i) { sso.utf32[i] = static_cast(sso.ascii[i]); } - } - - void move_heap_ascii_to_heap_utf() - { - // current: heap, ascii - // after: heap, utf32 - - assert(is_heap); - assert(is_ascii); - - is_ascii = false; - - unsigned char *buf = new unsigned char[_length]; - memcpy(buf, heap.ascii, _length); - - realloc_heap(false, _length); // destroy + alloc - - for (uint64_t i = 0; i < _length; ++i) { heap.utf32[i] = static_cast(buf[i]); } - } - - void move_sso_ascii_to_heap_utf() - { - // current: sso, ascii - // after: heap, utf32 - - assert(!is_heap); - assert(is_ascii); - - is_heap = true; - is_ascii = false; - - heap.utf32 = new char32_t[_length]; - - for (uint64_t i = 0; i < _length; ++i) { heap.utf32[i] = static_cast(sso.ascii[i]); } - } - - public: - static bool isPureASCII(const char *cstr) - { - for (size_t i = 0; cstr[i] != '\0'; ++i) - { - // 最高位是否为0 - // 0b10000000 - if (static_cast(cstr[i]) & 0x80) { return false; } - } - return true; - } - - static uint64_t fixed_strlen(const char *cstr) // must pass a correct utf format str - { - // 0b1000 0000 --> 1 - // 0b1100 0000 --> 2 - // 0b1110 0000 --> 3 - // 0b1111 0000 --> 4 - uint64_t cnt = 0; - for (size_t i = 0; cstr[i] != '\0'; ++i) - { - unsigned char c = static_cast(cstr[i]); - if ((c & 0xC0) != 0x80) { ++cnt; } - } - return cnt; - } - - static char *decodeUTF32String(const char32_t *str, uint64_t len) - { - if (!str) return nullptr; - - size_t utf8_len = 0; - for (uint64_t i = 0; i < len; ++i) - { - char32_t c = str[i]; - if (c <= 0x7F) - utf8_len += 1; - else if (c <= 0x7FF) - utf8_len += 2; - else if (c <= 0xFFFF) - utf8_len += 3; - else if (c <= 0x10FFFF) - utf8_len += 4; - else - assert(false && "invalid UTF-32 code point"); - } - - char *result = new char[utf8_len + 1]; - char *dest = result; - - for (uint64_t i = 0; i < len; ++i) - { - char32_t c = str[i]; - if (c <= 0x7F) { *dest++ = static_cast(c); } - else if (c <= 0x7FF) - { - *dest++ = static_cast(0xC0 | ((c >> 6) & 0x1F)); - *dest++ = static_cast(0x80 | (c & 0x3F)); - } - else if (c <= 0xFFFF) - { - *dest++ = static_cast(0xE0 | ((c >> 12) & 0x0F)); - *dest++ = static_cast(0x80 | ((c >> 6) & 0x3F)); - *dest++ = static_cast(0x80 | (c & 0x3F)); - } - else - { - *dest++ = static_cast(0xF0 | ((c >> 18) & 0x07)); - *dest++ = static_cast(0x80 | ((c >> 12) & 0x3F)); - *dest++ = static_cast(0x80 | ((c >> 6) & 0x3F)); - *dest++ = static_cast(0x80 | (c & 0x3F)); - } - } - - *dest = '\0'; - return result; - } - - static char32_t UTF8BytesToUTF32CodePoint(const char *str, uint64_t len) - { - // unsafe, str must be valid, otherwise Access Violation Memory - if (!str) return char32_t(); - - assert(len <= 4); - - unsigned char c = str[0]; - if (len == 1) { return static_cast(c); } - - if (len == 2) { return ((c & 0x1F) << 6) | (str[1] & 0x3F); } - if (len == 3) { return ((c & 0x1F) << 12) | ((str[1] & 0x3F) << 6) | ((str[2] & 0x3F)); } - if (len == 4) - { - return ((c & 0x07) << 18) | ((str[1] & 0x3F) << 12) | ((str[2] & 0x3F) << 6) | (str[3] & 0x3F); - } - assert(false && "invalid len"); - } - - const char *toCString() const - { - char *buf = new char[_length + 1]; - - if (is_ascii) - { - if (is_heap) - memcpy(buf, heap.ascii, _length); - else - memcpy(buf, sso.ascii, _length); - } - else - { - char *tmp = is_heap ? decodeUTF32String(heap.utf32, _length) : decodeUTF32String(sso.utf32, _length); - - memcpy(buf, tmp, strlen(tmp)); - delete[] tmp; - } - - buf[_length] = '\0'; - return buf; - } - - char *toCString() - { - char *n_c = new char[_length + 1]; - - if (is_ascii) - { - if (is_heap) - memcpy(n_c, heap.ascii, _length); - else - memcpy(n_c, sso.ascii, _length); - - n_c[_length] = '\0'; - return n_c; - } - - else - { - if (is_heap) { return decodeUTF32String(heap.utf32, _length); } - else - { - return decodeUTF32String(sso.utf32, _length); - } - } - } - - std::string toBasicString() const - { - if (is_ascii) return std::string(toCString()); - - char *tmp = is_heap ? decodeUTF32String(heap.utf32, _length) : decodeUTF32String(sso.utf32, _length); - - std::string s(tmp); - delete[] tmp; - return s; - } - - bool empty() const noexcept { return _length == 0; } - uint64_t size() const noexcept { return _length; } // c++ api - uint64_t length() const noexcept { return _length; } - bool isAscii() const noexcept { return is_ascii; } - bool isOnHeap() const noexcept { return is_heap; } - - void clear() noexcept { _length = 0; } - - bool operator==(const String &other) const - { - if (this == &other) return true; - if (_length != other._length) return false; - - // ASCII == ASCII - if (is_ascii && other.is_ascii) - { - if (is_heap && other.is_heap) return std::memcmp(heap.ascii, other.heap.ascii, _length) == 0; - if (!is_heap && !other.is_heap) return std::memcmp(sso.ascii, other.sso.ascii, _length) == 0; - - const unsigned char *l = is_heap ? heap.ascii : sso.ascii; - const unsigned char *r = other.is_heap ? other.heap.ascii : other.sso.ascii; - return std::memcmp(l, r, _length) == 0; - } - - // codepoint <--> codepoint - for (uint64_t i = 0; i < _length; ++i) - { - if ((*this)[i] != other[i]) return false; - } - - return true; - } - - char32_t operator[](uint64_t idx) const - { - if (is_ascii) - { - if (is_heap) { return static_cast(heap.ascii[idx]); } - else - { - return static_cast(sso.ascii[idx]); - } - } - else - { - if (is_heap) { return heap.utf32[idx]; } - else - { - return sso.utf32[idx]; - } - } - } - - char32_t at(uint64_t idx) const - { - if (idx >= _length) { throw std::runtime_error("index out of string range"); } - return operator[](idx); - } - - void set(uint64_t idx, char32_t codepoint) - { - if (idx >= _length) throw std::runtime_error("index out of string range"); - - if (is_ascii) - { - if (codepoint <= 0x7F) - { - unsigned char *dest = is_heap ? heap.ascii : sso.ascii; - dest[idx] = static_cast(codepoint); - return; - } - - // ASCII -> UTF32 (Heap) - if (is_heap) { move_heap_ascii_to_heap_utf(); } - else - { - move_sso_ascii_to_heap_utf(); - } - - heap.utf32[idx] = codepoint; - } - else - { - char32_t *dest = is_heap ? heap.utf32 : sso.utf32; - dest[idx] = codepoint; - } - } - - String operator+(const String &other) const - { - /* - ASCII + ASCII --> ASCII (SSO/HEAP) - UTF32 + UTF32 --> UTF32 (HEAP) - - ASCII + UTF32 --> UTF32 (HEAP) - UTF32 + ASCII ⬆ - */ - uint64_t nlen = _length + other._length; - if (nlen == _length) return *this; // other._length = 0 - - if (is_ascii && other.is_ascii) - { - const unsigned char *ld = is_heap ? heap.ascii : sso.ascii; - const unsigned char *rd = other.is_heap ? other.heap.ascii : other.sso.ascii; - - String result; - if (nlen <= SSO_MAX_ASCII_LEN) - { - memcpy(result.sso.ascii, ld, _length); - memcpy(result.sso.ascii + _length, rd, other._length); - - result.is_ascii = true; - result.is_heap = false; - result._length = nlen; - } - else - { - result.heap.ascii = new unsigned char[nlen]; - memcpy(result.heap.ascii, ld, _length); - memcpy(result.heap.ascii + _length, rd, other._length); - - result.is_ascii = true; - result.is_heap = true; - result._length = nlen; - } - return result; - } - if (!is_ascii && !other.is_ascii) - { - // both utf32 mode - const char32_t *ld = (is_heap ? heap.utf32 : sso.utf32); - const char32_t *rd = (other.is_heap ? other.heap.utf32 : other.sso.utf32); - - String result; // UTF32 concatenation always uses heap - - result.heap.utf32 = new char32_t[nlen]; - - result.is_heap = true; - result.is_ascii = false; - result._length = nlen; - - memcpy(result.heap.utf32, ld, sizeof(char32_t) * _length); - memcpy(result.heap.utf32 + _length, rd, sizeof(char32_t) * other._length); - return result; - } - - String result; - result.heap.utf32 = new char32_t[nlen]; // UTF32 concatenation always uses heap - - result.is_ascii = false; - result.is_heap = true; - result._length = nlen; - - if (is_ascii) - { - // other is utf32 mode - const unsigned char *ld = (is_heap ? heap.ascii : sso.ascii); - - for (uint64_t i = 0; i < _length; ++i) { result.heap.utf32[i] = static_cast(ld[i]); } - - const char32_t *rd = (other.is_heap ? other.heap.utf32 : other.sso.utf32); - memcpy(result.heap.utf32 + _length, rd, sizeof(char32_t) * other._length); - } - else - { - // other is ascii mode - // (this) is utf32 mode - - const char32_t *ld = (is_heap ? heap.utf32 : sso.utf32); - - memcpy(result.heap.utf32, ld, sizeof(char32_t) * _length); - const unsigned char *rd = (other.is_heap ? other.heap.ascii : other.sso.ascii); - for (uint64_t i = 0; i < other._length; ++i) - { - result.heap.utf32[_length + i] = static_cast(rd[i]); - } - } - return result; - } - - String &operator+=(const String &other) - { - if (other._length == 0) return *this; - - if (is_ascii && other.is_ascii) - { - uint64_t nlen = _length + other._length; - - const unsigned char *rd = other.is_heap ? other.heap.ascii : other.sso.ascii; - - if (!is_heap && nlen <= SSO_MAX_ASCII_LEN) - { - // SSO - memcpy(sso.ascii + _length, rd, other._length); - } - else - { - // heap - unsigned char *old = is_heap ? heap.ascii : nullptr; - - unsigned char *buf = new unsigned char[nlen]; - - if (is_heap) - memcpy(buf, old, _length); - else - memcpy(buf, sso.ascii, _length); - - memcpy(buf + _length, rd, other._length); - - if (is_heap) delete[] old; - - heap.ascii = buf; - is_heap = true; - } - - _length = nlen; - return *this; - } - - // UTF32 + UTF32 / ASCII + UTF32 / UTF32 + ASCII - uint64_t nlen = _length + other._length; - - char32_t *buf = new char32_t[nlen]; - - // copy lhs - if (is_ascii) - { - const unsigned char *ld = is_heap ? heap.ascii : sso.ascii; - for (uint64_t i = 0; i < _length; ++i) buf[i] = static_cast(ld[i]); - } - else - { - const char32_t *ld = is_heap ? heap.utf32 : sso.utf32; - memcpy(buf, ld, sizeof(char32_t) * _length); - } - - // copy rhs - if (other.is_ascii) - { - const unsigned char *rd = other.is_heap ? other.heap.ascii : other.sso.ascii; - for (uint64_t i = 0; i < other._length; ++i) buf[_length + i] = static_cast(rd[i]); - } - else - { - const char32_t *rd = other.is_heap ? other.heap.utf32 : other.sso.utf32; - memcpy(buf + _length, rd, sizeof(char32_t) * other._length); - } - - // destroy old storage - destroy(); - - heap.utf32 = buf; - is_ascii = false; - is_heap = true; - _length = nlen; - - return *this; - } - - String(String &&other) noexcept - { - is_ascii = other.is_ascii; - is_heap = other.is_heap; - _length = other._length; - - if (other.is_heap) - { - if (other.is_ascii) - { - heap.ascii = other.heap.ascii; - other.heap.ascii = nullptr; - } - else - { - heap.utf32 = other.heap.utf32; - other.heap.utf32 = nullptr; - } - } - else - { - if (other.is_ascii) - { - // SSO - memcpy(sso.ascii, other.sso.ascii, _length); - } - else - { - memcpy(sso.utf32, other.sso.utf32, sizeof(char32_t) * _length); - } - } - - other._length = 0; - other.is_heap = false; - other.is_ascii = true; // set to default mode - } - - String &operator=(const String &other) - { - copy(other); - return *this; - } - - String &operator=(String &&other) noexcept - { - if (this == &other) return *this; - - destroy(); // cleanup current - - is_ascii = other.is_ascii; - is_heap = other.is_heap; - _length = other._length; - - if (other.is_heap) - { - if (other.is_ascii) - { - heap.ascii = other.heap.ascii; - other.heap.ascii = nullptr; - } - else - { - heap.utf32 = other.heap.utf32; - other.heap.utf32 = nullptr; - } - } - else - { - if (other.is_ascii) - { - // SSO - memcpy(sso.ascii, other.sso.ascii, _length); - } - else - { - memcpy(sso.utf32, other.sso.utf32, sizeof(char32_t) * _length); - } - } - - other._length = 0; - other.is_heap = false; - other.is_ascii = true; // set to default mode - - return *this; - } - - String() - { - is_heap = false; - is_ascii = true; - } - - String(const String &str) { copy(str); } - - String(const char *cstr) { init(cstr); } - - String(const std::string &str) { init(str); } - - String(const char32_t *u32str) { init(u32str); } - - String(char32_t codepoint) - { - char32_t *str = new char32_t[2]; - str[0] = codepoint; - str[1] = U'\0'; - init(str); - delete[] str; - } - - ~String() { destroy(); } - }; -}; // namespace Fig::StringClass::SizeFixed +// namespace Fig::StringClass::SizeFixed +// { + +// class String +// { +// private: +// static constexpr uint8_t SSO_SIZE = 32; +// static constexpr uint8_t SSO_MAX_ASCII_LEN = SSO_SIZE; +// static constexpr uint8_t SSO_MAX_UTF32_LEN = SSO_SIZE / 4; + +// bool is_heap; +// bool is_ascii; +// uint64_t _length; + +// union +// { +// struct +// { +// union +// { +// unsigned char ascii[SSO_MAX_ASCII_LEN]; // 1 * 32 byte +// char32_t utf32[SSO_MAX_UTF32_LEN]; // 4 * 8 byte +// }; +// } sso; + +// struct +// { +// union +// { +// unsigned char *ascii; +// char32_t *utf32; +// }; +// } heap; +// }; + +// void destroy() +// { +// _length = 0; + +// if (is_heap) +// { +// if (is_ascii) { delete[] heap.ascii; } +// else +// { +// delete[] heap.utf32; +// } +// } +// // sso, pass +// } + +// void alloc_heap(bool ascii, uint64_t size) +// { +// if (ascii) { heap.ascii = new unsigned char[size]; } +// else +// { +// heap.utf32 = new char32_t[size]; +// } +// } + +// void realloc_heap(bool ascii, uint64_t size) +// { +// destroy(); + +// if (ascii) { heap.ascii = new unsigned char[size]; } +// else +// { +// heap.utf32 = new char32_t[size]; +// } +// } + +// void copy(const String &other) +// { +// if (other.is_heap) +// { +// if (!is_heap) +// { +// destroy(); +// is_heap = other.is_heap; +// } +// if (_length != other._length) +// { +// realloc_heap(other.is_ascii, other._length); +// _length = other._length; +// } +// is_ascii = other.is_ascii; +// if (is_ascii) +// { +// for (uint64_t i = 0; i < _length; ++i) { heap.ascii[i] = other.heap.ascii[i]; } +// } +// else +// { +// for (uint64_t i = 0; i < _length; ++i) { heap.utf32[i] = other.heap.utf32[i]; } +// } +// } +// else +// { +// // other is sso +// if (is_heap) +// { +// destroy(); +// is_heap = other.is_heap; +// } +// is_ascii = other.is_ascii; +// _length = other._length; + +// if (is_ascii) +// { +// for (uint64_t i = 0; i < _length; ++i) { sso.ascii[i] = other.sso.ascii[i]; } +// } +// else +// { +// for (uint64_t i = 0; i < _length; ++i) { sso.utf32[i] = other.sso.utf32[i]; } +// } +// } +// } + +// void init(const char *cstr) +// { +// is_ascii = isPureASCII(cstr); + +// if (is_ascii) +// { +// uint64_t len = strlen(cstr); +// _length = len; +// if (len <= SSO_MAX_ASCII_LEN) +// { +// memcpy(sso.ascii, cstr, len); +// is_heap = false; +// } +// else +// { +// realloc_heap(true, len); +// memcpy(heap.ascii, cstr, len); +// is_heap = true; +// } +// } +// else +// { +// uint64_t len = fixed_strlen(cstr); +// _length = 0; +// if (len <= SSO_MAX_UTF32_LEN) +// { +// for (size_t i = 0; cstr[i] != '\0';) +// { +// unsigned char c = static_cast(cstr[i]); +// if (c <= 0x7F) +// { +// sso.utf32[_length++] = static_cast(c); +// ++i; +// } +// else if ((c & 0xE0) == 0xC0) +// { +// char32_t result = ((c & 0x1F) << 6) | (cstr[i + 1] & 0x3F); +// sso.utf32[_length++] = result; +// i += 2; +// } +// else if ((c & 0xF0) == 0xE0) +// { +// char32_t result = ((c & 0x1F) << 12) | ((cstr[i + 1] & 0x3F) << 6) | ((cstr[i + 2] & 0x3F)); +// sso.utf32[_length++] = result; +// i += 3; +// } +// else if ((c & 0xF8) == 0xF0) +// { +// char32_t result = ((c & 0x07) << 18) | ((cstr[i + 1] & 0x3F) << 12) +// | ((cstr[i + 2] & 0x3F) << 6) | (cstr[i + 3] & 0x3F); +// sso.utf32[_length++] = result; +// i += 4; +// } +// else +// { +// assert(false && "bad utf8 string"); +// } +// } +// is_heap = false; +// } +// else +// { +// realloc_heap(false, len); +// _length = 0; +// for (size_t i = 0; cstr[i] != '\0';) +// { +// unsigned char c = static_cast(cstr[i]); +// if (c <= 0x7F) +// { +// heap.utf32[_length++] = static_cast(c); +// ++i; +// } +// else if ((c & 0xE0) == 0xC0) +// { +// char32_t result = ((c & 0x1F) << 6) | (cstr[i + 1] & 0x3F); +// heap.utf32[_length++] = result; +// i += 2; +// } +// else if ((c & 0xF0) == 0xE0) +// { +// char32_t result = ((c & 0x1F) << 12) | ((cstr[i + 1] & 0x3F) << 6) | ((cstr[i + 2] & 0x3F)); +// heap.utf32[_length++] = result; +// i += 3; +// } +// else if ((c & 0xF8) == 0xF0) +// { +// char32_t result = ((c & 0x07) << 18) | ((cstr[i + 1] & 0x3F) << 12) +// | ((cstr[i + 2] & 0x3F) << 6) | (cstr[i + 3] & 0x3F); +// heap.utf32[_length++] = result; +// i += 4; +// } +// else +// { +// assert(false && "bad utf8 string"); +// } +// } +// is_heap = true; +// } +// } +// } + +// void init(const char32_t *str) +// { +// assert(str); + +// uint64_t len = 0; +// bool ascii = true; + +// for (const char32_t *p = str; *p != U'\0'; ++p) +// { +// if (*p > 0x7F) ascii = false; +// ++len; +// } + +// _length = len; +// is_ascii = ascii; + +// if (ascii) +// { +// if (len <= SSO_MAX_ASCII_LEN) +// { +// is_heap = false; +// for (uint64_t i = 0; i < len; ++i) sso.ascii[i] = static_cast(str[i]); +// } +// else +// { +// is_heap = true; +// realloc_heap(true, len); +// for (uint64_t i = 0; i < len; ++i) heap.ascii[i] = static_cast(str[i]); +// } +// } +// else +// { +// if (len <= SSO_MAX_UTF32_LEN) +// { +// is_heap = false; +// for (uint64_t i = 0; i < len; ++i) sso.utf32[i] = str[i]; +// } +// else +// { +// is_heap = true; +// realloc_heap(false, len); +// for (uint64_t i = 0; i < len; ++i) heap.utf32[i] = str[i]; +// } +// } +// } + +// void init(const std::string &str) { init(str.c_str()); } + +// void promote_sso_to_heap(uint64_t len) +// { +// if (is_heap) return; + +// is_heap = true; + +// if (is_ascii) +// { +// heap.ascii = new unsigned char[len]; +// memcpy(heap.ascii, sso.ascii, _length); +// } +// else +// { +// heap.utf32 = new char32_t[len]; +// memcpy(heap.utf32, sso.utf32, sizeof(char32_t) * _length); +// } +// _length = len; +// } + +// void move_sso_ascii_to_sso_utf() +// { +// // current: sso, ascii +// // after: sso, utf32 + +// assert(is_ascii); +// assert(!is_heap); + +// is_ascii = false; + +// for (uint8_t i = 0; i < _length; ++i) { sso.utf32[i] = static_cast(sso.ascii[i]); } +// } + +// void move_heap_ascii_to_heap_utf() +// { +// // current: heap, ascii +// // after: heap, utf32 + +// assert(is_heap); +// assert(is_ascii); + +// is_ascii = false; + +// unsigned char *buf = new unsigned char[_length]; +// memcpy(buf, heap.ascii, _length); + +// realloc_heap(false, _length); // destroy + alloc + +// for (uint64_t i = 0; i < _length; ++i) { heap.utf32[i] = static_cast(buf[i]); } +// } + +// void move_sso_ascii_to_heap_utf() +// { +// // current: sso, ascii +// // after: heap, utf32 + +// assert(!is_heap); +// assert(is_ascii); + +// is_heap = true; +// is_ascii = false; + +// heap.utf32 = new char32_t[_length]; + +// for (uint64_t i = 0; i < _length; ++i) { heap.utf32[i] = static_cast(sso.ascii[i]); } +// } + +// public: +// static bool isPureASCII(const char *cstr) +// { +// for (size_t i = 0; cstr[i] != '\0'; ++i) +// { +// // 最高位是否为0 +// // 0b10000000 +// if (static_cast(cstr[i]) & 0x80) { return false; } +// } +// return true; +// } + +// static uint64_t fixed_strlen(const char *cstr) // must pass a correct utf format str +// { +// // 0b1000 0000 --> 1 +// // 0b1100 0000 --> 2 +// // 0b1110 0000 --> 3 +// // 0b1111 0000 --> 4 +// uint64_t cnt = 0; +// for (size_t i = 0; cstr[i] != '\0'; ++i) +// { +// unsigned char c = static_cast(cstr[i]); +// if ((c & 0xC0) != 0x80) { ++cnt; } +// } +// return cnt; +// } + +// static char *decodeUTF32String(const char32_t *str, uint64_t len) +// { +// if (!str) return nullptr; + +// size_t utf8_len = 0; +// for (uint64_t i = 0; i < len; ++i) +// { +// char32_t c = str[i]; +// if (c <= 0x7F) +// utf8_len += 1; +// else if (c <= 0x7FF) +// utf8_len += 2; +// else if (c <= 0xFFFF) +// utf8_len += 3; +// else if (c <= 0x10FFFF) +// utf8_len += 4; +// else +// assert(false && "invalid UTF-32 code point"); +// } + +// char *result = new char[utf8_len + 1]; +// char *dest = result; + +// for (uint64_t i = 0; i < len; ++i) +// { +// char32_t c = str[i]; +// if (c <= 0x7F) { *dest++ = static_cast(c); } +// else if (c <= 0x7FF) +// { +// *dest++ = static_cast(0xC0 | ((c >> 6) & 0x1F)); +// *dest++ = static_cast(0x80 | (c & 0x3F)); +// } +// else if (c <= 0xFFFF) +// { +// *dest++ = static_cast(0xE0 | ((c >> 12) & 0x0F)); +// *dest++ = static_cast(0x80 | ((c >> 6) & 0x3F)); +// *dest++ = static_cast(0x80 | (c & 0x3F)); +// } +// else +// { +// *dest++ = static_cast(0xF0 | ((c >> 18) & 0x07)); +// *dest++ = static_cast(0x80 | ((c >> 12) & 0x3F)); +// *dest++ = static_cast(0x80 | ((c >> 6) & 0x3F)); +// *dest++ = static_cast(0x80 | (c & 0x3F)); +// } +// } + +// *dest = '\0'; +// return result; +// } + +// static char32_t UTF8BytesToUTF32CodePoint(const char *str, uint64_t len) +// { +// // unsafe, str must be valid, otherwise Access Violation Memory +// if (!str) return char32_t(); + +// assert(len <= 4); + +// unsigned char c = str[0]; +// if (len == 1) { return static_cast(c); } + +// if (len == 2) { return ((c & 0x1F) << 6) | (str[1] & 0x3F); } +// if (len == 3) { return ((c & 0x1F) << 12) | ((str[1] & 0x3F) << 6) | ((str[2] & 0x3F)); } +// if (len == 4) +// { +// return ((c & 0x07) << 18) | ((str[1] & 0x3F) << 12) | ((str[2] & 0x3F) << 6) | (str[3] & 0x3F); +// } +// assert(false && "invalid len"); +// } + +// const char *toCString() const +// { +// char *buf = new char[_length + 1]; + +// if (is_ascii) +// { +// if (is_heap) +// memcpy(buf, heap.ascii, _length); +// else +// memcpy(buf, sso.ascii, _length); +// } +// else +// { +// char *tmp = is_heap ? decodeUTF32String(heap.utf32, _length) : decodeUTF32String(sso.utf32, _length); + +// memcpy(buf, tmp, strlen(tmp)); +// delete[] tmp; +// } + +// buf[_length] = '\0'; +// return buf; +// } + +// char *toCString() +// { +// char *n_c = new char[_length + 1]; + +// if (is_ascii) +// { +// if (is_heap) +// memcpy(n_c, heap.ascii, _length); +// else +// memcpy(n_c, sso.ascii, _length); + +// n_c[_length] = '\0'; +// return n_c; +// } + +// else +// { +// if (is_heap) { return decodeUTF32String(heap.utf32, _length); } +// else +// { +// return decodeUTF32String(sso.utf32, _length); +// } +// } +// } + +// std::string toBasicString() const +// { +// if (is_ascii) return std::string(toCString()); + +// char *tmp = is_heap ? decodeUTF32String(heap.utf32, _length) : decodeUTF32String(sso.utf32, _length); + +// std::string s(tmp); +// delete[] tmp; +// return s; +// } + +// bool empty() const noexcept { return _length == 0; } +// uint64_t size() const noexcept { return _length; } // c++ api +// uint64_t length() const noexcept { return _length; } +// bool isAscii() const noexcept { return is_ascii; } +// bool isOnHeap() const noexcept { return is_heap; } + +// void clear() noexcept { _length = 0; } + +// bool operator==(const String &other) const +// { +// if (this == &other) return true; +// if (_length != other._length) return false; + +// // ASCII == ASCII +// if (is_ascii && other.is_ascii) +// { +// if (is_heap && other.is_heap) return std::memcmp(heap.ascii, other.heap.ascii, _length) == 0; +// if (!is_heap && !other.is_heap) return std::memcmp(sso.ascii, other.sso.ascii, _length) == 0; + +// const unsigned char *l = is_heap ? heap.ascii : sso.ascii; +// const unsigned char *r = other.is_heap ? other.heap.ascii : other.sso.ascii; +// return std::memcmp(l, r, _length) == 0; +// } + +// // codepoint <--> codepoint +// for (uint64_t i = 0; i < _length; ++i) +// { +// if ((*this)[i] != other[i]) return false; +// } + +// return true; +// } + +// char32_t operator[](uint64_t idx) const +// { +// if (is_ascii) +// { +// if (is_heap) { return static_cast(heap.ascii[idx]); } +// else +// { +// return static_cast(sso.ascii[idx]); +// } +// } +// else +// { +// if (is_heap) { return heap.utf32[idx]; } +// else +// { +// return sso.utf32[idx]; +// } +// } +// } + +// char32_t at(uint64_t idx) const +// { +// if (idx >= _length) { throw std::runtime_error("index out of string range"); } +// return operator[](idx); +// } + +// void set(uint64_t idx, char32_t codepoint) +// { +// if (idx >= _length) throw std::runtime_error("index out of string range"); + +// if (is_ascii) +// { +// if (codepoint <= 0x7F) +// { +// unsigned char *dest = is_heap ? heap.ascii : sso.ascii; +// dest[idx] = static_cast(codepoint); +// return; +// } + +// // ASCII -> UTF32 (Heap) +// if (is_heap) { move_heap_ascii_to_heap_utf(); } +// else +// { +// move_sso_ascii_to_heap_utf(); +// } + +// heap.utf32[idx] = codepoint; +// } +// else +// { +// char32_t *dest = is_heap ? heap.utf32 : sso.utf32; +// dest[idx] = codepoint; +// } +// } + +// String operator+(const String &other) const +// { +// /* +// ASCII + ASCII --> ASCII (SSO/HEAP) +// UTF32 + UTF32 --> UTF32 (HEAP) + +// ASCII + UTF32 --> UTF32 (HEAP) +// UTF32 + ASCII ⬆ +// */ +// uint64_t nlen = _length + other._length; +// if (nlen == _length) return *this; // other._length = 0 + +// if (is_ascii && other.is_ascii) +// { +// const unsigned char *ld = is_heap ? heap.ascii : sso.ascii; +// const unsigned char *rd = other.is_heap ? other.heap.ascii : other.sso.ascii; + +// String result; +// if (nlen <= SSO_MAX_ASCII_LEN) +// { +// memcpy(result.sso.ascii, ld, _length); +// memcpy(result.sso.ascii + _length, rd, other._length); + +// result.is_ascii = true; +// result.is_heap = false; +// result._length = nlen; +// } +// else +// { +// result.heap.ascii = new unsigned char[nlen]; +// memcpy(result.heap.ascii, ld, _length); +// memcpy(result.heap.ascii + _length, rd, other._length); + +// result.is_ascii = true; +// result.is_heap = true; +// result._length = nlen; +// } +// return result; +// } +// if (!is_ascii && !other.is_ascii) +// { +// // both utf32 mode +// const char32_t *ld = (is_heap ? heap.utf32 : sso.utf32); +// const char32_t *rd = (other.is_heap ? other.heap.utf32 : other.sso.utf32); + +// String result; // UTF32 concatenation always uses heap + +// result.heap.utf32 = new char32_t[nlen]; + +// result.is_heap = true; +// result.is_ascii = false; +// result._length = nlen; + +// memcpy(result.heap.utf32, ld, sizeof(char32_t) * _length); +// memcpy(result.heap.utf32 + _length, rd, sizeof(char32_t) * other._length); +// return result; +// } + +// String result; +// result.heap.utf32 = new char32_t[nlen]; // UTF32 concatenation always uses heap + +// result.is_ascii = false; +// result.is_heap = true; +// result._length = nlen; + +// if (is_ascii) +// { +// // other is utf32 mode +// const unsigned char *ld = (is_heap ? heap.ascii : sso.ascii); + +// for (uint64_t i = 0; i < _length; ++i) { result.heap.utf32[i] = static_cast(ld[i]); } + +// const char32_t *rd = (other.is_heap ? other.heap.utf32 : other.sso.utf32); +// memcpy(result.heap.utf32 + _length, rd, sizeof(char32_t) * other._length); +// } +// else +// { +// // other is ascii mode +// // (this) is utf32 mode + +// const char32_t *ld = (is_heap ? heap.utf32 : sso.utf32); + +// memcpy(result.heap.utf32, ld, sizeof(char32_t) * _length); +// const unsigned char *rd = (other.is_heap ? other.heap.ascii : other.sso.ascii); +// for (uint64_t i = 0; i < other._length; ++i) +// { +// result.heap.utf32[_length + i] = static_cast(rd[i]); +// } +// } +// return result; +// } + +// String &operator+=(const String &other) +// { +// if (other._length == 0) return *this; + +// if (is_ascii && other.is_ascii) +// { +// uint64_t nlen = _length + other._length; + +// const unsigned char *rd = other.is_heap ? other.heap.ascii : other.sso.ascii; + +// if (!is_heap && nlen <= SSO_MAX_ASCII_LEN) +// { +// // SSO +// memcpy(sso.ascii + _length, rd, other._length); +// } +// else +// { +// // heap +// unsigned char *old = is_heap ? heap.ascii : nullptr; + +// unsigned char *buf = new unsigned char[nlen]; + +// if (is_heap) +// memcpy(buf, old, _length); +// else +// memcpy(buf, sso.ascii, _length); + +// memcpy(buf + _length, rd, other._length); + +// if (is_heap) delete[] old; + +// heap.ascii = buf; +// is_heap = true; +// } + +// _length = nlen; +// return *this; +// } + +// // UTF32 + UTF32 / ASCII + UTF32 / UTF32 + ASCII +// uint64_t nlen = _length + other._length; + +// char32_t *buf = new char32_t[nlen]; + +// // copy lhs +// if (is_ascii) +// { +// const unsigned char *ld = is_heap ? heap.ascii : sso.ascii; +// for (uint64_t i = 0; i < _length; ++i) buf[i] = static_cast(ld[i]); +// } +// else +// { +// const char32_t *ld = is_heap ? heap.utf32 : sso.utf32; +// memcpy(buf, ld, sizeof(char32_t) * _length); +// } + +// // copy rhs +// if (other.is_ascii) +// { +// const unsigned char *rd = other.is_heap ? other.heap.ascii : other.sso.ascii; +// for (uint64_t i = 0; i < other._length; ++i) buf[_length + i] = static_cast(rd[i]); +// } +// else +// { +// const char32_t *rd = other.is_heap ? other.heap.utf32 : other.sso.utf32; +// memcpy(buf + _length, rd, sizeof(char32_t) * other._length); +// } + +// // destroy old storage +// destroy(); + +// heap.utf32 = buf; +// is_ascii = false; +// is_heap = true; +// _length = nlen; + +// return *this; +// } + +// String(String &&other) noexcept +// { +// is_ascii = other.is_ascii; +// is_heap = other.is_heap; +// _length = other._length; + +// if (other.is_heap) +// { +// if (other.is_ascii) +// { +// heap.ascii = other.heap.ascii; +// other.heap.ascii = nullptr; +// } +// else +// { +// heap.utf32 = other.heap.utf32; +// other.heap.utf32 = nullptr; +// } +// } +// else +// { +// if (other.is_ascii) +// { +// // SSO +// memcpy(sso.ascii, other.sso.ascii, _length); +// } +// else +// { +// memcpy(sso.utf32, other.sso.utf32, sizeof(char32_t) * _length); +// } +// } + +// other._length = 0; +// other.is_heap = false; +// other.is_ascii = true; // set to default mode +// } + +// String &operator=(const String &other) +// { +// copy(other); +// return *this; +// } + +// String &operator=(String &&other) noexcept +// { +// if (this == &other) return *this; + +// destroy(); // cleanup current + +// is_ascii = other.is_ascii; +// is_heap = other.is_heap; +// _length = other._length; + +// if (other.is_heap) +// { +// if (other.is_ascii) +// { +// heap.ascii = other.heap.ascii; +// other.heap.ascii = nullptr; +// } +// else +// { +// heap.utf32 = other.heap.utf32; +// other.heap.utf32 = nullptr; +// } +// } +// else +// { +// if (other.is_ascii) +// { +// // SSO +// memcpy(sso.ascii, other.sso.ascii, _length); +// } +// else +// { +// memcpy(sso.utf32, other.sso.utf32, sizeof(char32_t) * _length); +// } +// } + +// other._length = 0; +// other.is_heap = false; +// other.is_ascii = true; // set to default mode + +// return *this; +// } + +// String() +// { +// is_heap = false; +// is_ascii = true; +// } + +// String(const String &str) { copy(str); } + +// String(const char *cstr) { init(cstr); } + +// String(const std::string &str) { init(str); } + +// String(const char32_t *u32str) { init(u32str); } + +// String(char32_t codepoint) +// { +// char32_t *str = new char32_t[2]; +// str[0] = codepoint; +// str[1] = U'\0'; +// init(str); +// delete[] str; +// } + +// ~String() { destroy(); } +// }; +// }; // namespace Fig::StringClass::SizeFixed namespace Fig::StringClass::DynamicCapacity { + class String; + + struct Iterator + { + private: + const String *str; + uint64_t index; + + public: + using value_type = char32_t; + using difference_type = std::ptrdiff_t; + using pointer = const char32_t *; + using reference = char32_t; + using iterator_category = std::forward_iterator_tag; + + Iterator(const String *s, uint64_t idx) : str(s), index(idx) {} + + char32_t operator*() const; + + Iterator &operator++() + { + ++index; + return *this; + } + Iterator operator++(int) + { + Iterator tmp = *this; + ++index; + return tmp; + } + + bool operator==(const Iterator &other) const { return str == other.str && index == other.index; } + bool operator!=(const Iterator &other) const { return !(*this == other); } + }; + class String { + friend struct Iterator; + friend struct std::hash; + + using __Iterator = Iterator; private: static constexpr uint8_t SSO_SIZE = 32; static constexpr uint8_t SSO_MAX_ASCII_LEN = SSO_SIZE; @@ -902,8 +942,9 @@ namespace Fig::StringClass::DynamicCapacity { if (this != &other) { - delete[] ascii; - delete[] utf32; + if (ascii) delete[] ascii; + if (utf32) delete[] utf32; + ascii = other.ascii; utf32 = other.utf32; other.ascii = nullptr; @@ -937,16 +978,12 @@ namespace Fig::StringClass::DynamicCapacity { if (is_heap) { - if (is_ascii) - delete[] heap.ascii; - else - delete[] heap.utf32; + heap.~HeapBuffer(); } } void destroy() { - destroy_heap_memory(); _length = 0; _capacity = 0; is_heap = false; @@ -1040,7 +1077,6 @@ namespace Fig::StringClass::DynamicCapacity void move_from(String &&other) noexcept { - destroy(); is_ascii = other.is_ascii; _length = other._length; is_heap = other.is_heap; @@ -1205,7 +1241,9 @@ namespace Fig::StringClass::DynamicCapacity String() : is_heap(false), is_ascii(true), _length(0), _capacity(0) {} String(const std::string &str) { init_from_cstr(str.c_str()); } String(const char *cstr) { init_from_cstr(cstr); } - String(const String &other) { copy_from(other); } + String(const String &other) { + copy_from(other); + } String(String &&other) noexcept { move_from(std::move(other)); } String(const char32_t *utf32str) { init_from_u32_str(utf32str); } String(char32_t codepoint) @@ -1244,6 +1282,235 @@ namespace Fig::StringClass::DynamicCapacity return is_heap ? heap.utf32[idx] : sso.utf32[idx]; } + void push_back(char32_t c) + { + if (is_ascii) + { + if (c <= 0x7F) + { + // ASCII mode + ensure_capacity(_length + 1); + if (is_heap) + heap.ascii[_length] = static_cast(c); + else + sso.ascii[_length] = static_cast(c); + ++_length; + } + else + { + // promote to UTF-32 + convert_to_utf32_mode(); + ensure_capacity(_length + 1); + if (is_heap) + heap.utf32[_length] = c; + else + sso.utf32[_length] = c; + ++_length; + } + } + else + { + // UTF-32 + ensure_capacity(_length + 1); + if (is_heap) + heap.utf32[_length] = c; + else + sso.utf32[_length] = c; + ++_length; + } + } + + void pop_back() + { + if (_length == 0) return; + --_length; + + if (is_heap) + { + if (is_ascii && _length <= SSO_MAX_ASCII_LEN) + { + // back to SSO + unsigned char tmp[SSO_MAX_ASCII_LEN]; + std::memcpy(tmp, heap.ascii, _length); + delete[] heap.ascii; + std::memcpy(sso.ascii, tmp, _length); + is_heap = false; + _capacity = 0; + } + else if (!is_ascii && _length <= SSO_MAX_UTF32_LEN) + { + char32_t tmp[SSO_MAX_UTF32_LEN]; + std::memcpy(tmp, heap.utf32, _length * sizeof(char32_t)); + delete[] heap.utf32; + std::memcpy(sso.utf32, tmp, _length * sizeof(char32_t)); + is_heap = false; + _capacity = 0; + } + } + } + + // [pos, pos + count - 1] + void erase(uint64_t pos, uint64_t count = 1) + { + if (pos >= _length || count == 0) return; + if (pos + count > _length) count = _length - pos; + + if (is_ascii) + { + if (is_heap) + std::memmove(heap.ascii + pos, heap.ascii + pos + count, _length - pos - count); + else + std::memmove(sso.ascii + pos, sso.ascii + pos + count, _length - pos - count); + } + else + { + if (is_heap) + std::memmove( + heap.utf32 + pos, heap.utf32 + pos + count, (_length - pos - count) * sizeof(char32_t)); + else + std::memmove(sso.utf32 + pos, sso.utf32 + pos + count, (_length - pos - count) * sizeof(char32_t)); + } + + _length -= count; + shrink_to_fit(); + } + + void insert(uint64_t pos, char32_t c) + { + if (pos > _length) pos = _length; + + push_back(0); + + // 向后移动 + if (is_ascii) + { + if (is_heap) + std::memmove(heap.ascii + pos + 1, heap.ascii + pos, _length - pos - 1); + else + std::memmove(sso.ascii + pos + 1, sso.ascii + pos, _length - pos - 1); + } + else + { + if (is_heap) + std::memmove(heap.utf32 + pos + 1, heap.utf32 + pos, (_length - pos - 1) * sizeof(char32_t)); + else + std::memmove(sso.utf32 + pos + 1, sso.utf32 + pos, (_length - pos - 1) * sizeof(char32_t)); + } + + // 写入 c + if (is_ascii && c <= 0x7F) + { + if (is_heap) + heap.ascii[pos] = static_cast(c); + else + sso.ascii[pos] = static_cast(c); + } + else + { + if (is_ascii) convert_to_utf32_mode(); + if (is_heap) + heap.utf32[pos] = c; + else + sso.utf32[pos] = c; + } + } + + void insert(uint64_t pos, const String &other) + { + if (other._length == 0) return; + if (pos > _length) pos = _length; + + uint64_t new_length = _length + other._length; + + // ASCII/UTF-32 + if (is_ascii && !other.is_ascii) convert_to_utf32_mode(); + + ensure_capacity(new_length); // 扩容 + + // 向后移动 + if (is_ascii) + { + unsigned char *buf = is_heap ? heap.ascii : sso.ascii; + std::memmove(buf + pos + other._length, buf + pos, _length - pos); + } + else + { + char32_t *buf = is_heap ? heap.utf32 : sso.utf32; + std::memmove(buf + pos + other._length, buf + pos, (_length - pos) * sizeof(char32_t)); + } + + if (is_ascii && other.is_ascii) + { + const unsigned char *src = other.is_heap ? other.heap.ascii : other.sso.ascii; + if (is_heap) + std::memcpy(heap.ascii + pos, src, other._length); + else + std::memcpy(sso.ascii + pos, src, other._length); + } + else + { + // 转换到 UTF-32 + if (other.is_ascii) + { + const unsigned char *src = other.is_heap ? other.heap.ascii : other.sso.ascii; + char32_t *buf = is_heap ? heap.utf32 : sso.utf32; + for (uint64_t i = 0; i < other._length; ++i) buf[pos + i] = src[i]; + } + else + { + const char32_t *src = other.is_heap ? other.heap.utf32 : other.sso.utf32; + char32_t *buf = is_heap ? heap.utf32 : sso.utf32; + std::memcpy(buf + pos, src, other._length * sizeof(char32_t)); + } + } + + _length = new_length; + } + + void replace(uint64_t pos, uint64_t count, char32_t new_char) + { + if (pos >= _length) return; + if (pos + count > _length) count = _length - pos; + + // ASCII -> UTF32 + if (is_ascii && new_char > 0x7F) convert_to_utf32_mode(); + + if (is_ascii) + { + if (is_heap) + { + for (uint64_t i = 0; i < count; ++i) heap.ascii[pos + i] = static_cast(new_char); + } + else + { + for (uint64_t i = 0; i < count; ++i) sso.ascii[pos + i] = static_cast(new_char); + } + } + else + { + if (is_heap) + { + for (uint64_t i = 0; i < count; ++i) heap.utf32[pos + i] = new_char; + } + else + { + for (uint64_t i = 0; i < count; ++i) sso.utf32[pos + i] = new_char; + } + } + } + + void replace(uint64_t pos, uint64_t count, const String &other) + { + if (pos >= _length) return; + if (pos + count > _length) count = _length - pos; + + // 删除原有内容 + erase(pos, count); + + // 在 pos 位置插入 new String + insert(pos, other); + } + void set(uint64_t idx, char32_t c) { assert(idx < _length && "Index out of bounds"); @@ -1336,6 +1603,38 @@ namespace Fig::StringClass::DynamicCapacity res += other; return res; } + + String &operator+=(const char32_t *utf32str) + { + if (!utf32str) return *this; + + uint64_t add_len = 0; + while (utf32str[add_len] != U'\0') ++add_len; + if (add_len == 0) return *this; + + uint64_t new_length = _length + add_len; + + // 升级 ASCII -> UTF-32 + if (is_ascii) { convert_to_utf32_mode(); } + + ensure_capacity(new_length); // 扩容 + + if (is_heap) { std::memcpy(heap.utf32 + _length, utf32str, add_len * sizeof(char32_t)); } + else + { + std::memcpy(sso.utf32 + _length, utf32str, add_len * sizeof(char32_t)); + } + + _length = new_length; + return *this; + } + + String operator+(const char32_t *utf32str) const + { + String res = *this; + res += utf32str; + return res; + } // Conversion char *toCString() const @@ -1436,6 +1735,174 @@ namespace Fig::StringClass::DynamicCapacity bool operator!=(const String &other) const { return !(*this == other); } + bool operator<(const String &other) const + { + uint64_t min_len = _length < other._length ? _length : other._length; + + for (uint64_t i = 0; i < min_len; ++i) + { + char32_t c1 = + is_ascii ? (is_heap ? heap.ascii[i] : sso.ascii[i]) : (is_heap ? heap.utf32[i] : sso.utf32[i]); + char32_t c2 = other.is_ascii ? (other.is_heap ? other.heap.ascii[i] : other.sso.ascii[i]) : + (other.is_heap ? other.heap.utf32[i] : other.sso.utf32[i]); + + if (c1 < c2) return true; + if (c1 > c2) return false; + } + + // 如果前 min_len 个字符相等,则长度短的更小 + return _length < other._length; + } + + bool operator>(const String &other) const + { + uint64_t min_len = _length < other._length ? _length : other._length; + + for (uint64_t i = 0; i < min_len; ++i) + { + char32_t c1 = + is_ascii ? (is_heap ? heap.ascii[i] : sso.ascii[i]) : (is_heap ? heap.utf32[i] : sso.utf32[i]); + char32_t c2 = other.is_ascii ? (other.is_heap ? other.heap.ascii[i] : other.sso.ascii[i]) : + (other.is_heap ? other.heap.utf32[i] : other.sso.utf32[i]); + + if (c1 > c2) return true; + if (c1 < c2) return false; + } + + // 如果前 min_len 个字符相等,则长度长的更大 + return _length > other._length; + } + + static constexpr int64_t npos = -1; + + int64_t find(const String &needle) const + { + if (needle._length == 0) return 0; // empty needle + if (needle._length > _length) return -1; // too long + + auto get_char = [this](uint64_t idx) -> char32_t { + return is_ascii ? (is_heap ? heap.ascii[idx] : sso.ascii[idx]) : + (is_heap ? heap.utf32[idx] : sso.utf32[idx]); + }; + + auto get_needle_char = [&needle](uint64_t idx) -> char32_t { + return needle.is_ascii ? (needle.is_heap ? needle.heap.ascii[idx] : needle.sso.ascii[idx]) : + (needle.is_heap ? needle.heap.utf32[idx] : needle.sso.utf32[idx]); + }; + + for (uint64_t i = 0; i <= _length - needle._length; ++i) + { + bool matched = true; + for (uint64_t j = 0; j < needle._length; ++j) + { + if (get_char(i + j) != get_needle_char(j)) + { + matched = false; + break; + } + } + if (matched) return static_cast(i); + } + + return npos; // not found + } + + int64_t find(char32_t c) const + { + if (_length == 0) return -1; + + if (is_ascii && c <= 0x7F) + { + // ASCII dispatch + const unsigned char *buf = is_heap ? heap.ascii : sso.ascii; + for (uint64_t i = 0; i < _length; ++i) + { + if (buf[i] == static_cast(c)) return static_cast(i); + } + } + else + { + // UTF-32 / Mixed + for (uint64_t i = 0; i < _length; ++i) + { + char32_t current = + is_ascii ? (is_heap ? heap.ascii[i] : sso.ascii[i]) : (is_heap ? heap.utf32[i] : sso.utf32[i]); + if (current == c) return static_cast(i); + } + } + + return npos; // not found + } + + bool contains(char32_t c) const + { + return find(c) != npos; + } + + bool starts_with(const String &prefix) const + { + if (prefix._length == 0) return true; // empty + if (prefix._length > _length) return false; // too long! + + auto get_char = [this](uint64_t idx) -> char32_t { + return is_ascii ? (is_heap ? heap.ascii[idx] : sso.ascii[idx]) : + (is_heap ? heap.utf32[idx] : sso.utf32[idx]); + }; + + auto get_pre_char = [&prefix](uint64_t idx) -> char32_t { + return prefix.is_ascii ? (prefix.is_heap ? prefix.heap.ascii[idx] : prefix.sso.ascii[idx]) : + (prefix.is_heap ? prefix.heap.utf32[idx] : prefix.sso.utf32[idx]); + }; + + for (uint64_t i = 0; i < prefix._length; ++i) + { + if (get_char(i) != get_pre_char(i)) return false; + } + + return true; + } + + bool starts_with(char32_t c) const + { + if (_length == 0) return false; + + char32_t first_char = + is_ascii ? (is_heap ? heap.ascii[0] : sso.ascii[0]) : (is_heap ? heap.utf32[0] : sso.utf32[0]); + return first_char == c; + } + + bool ends_with(const String &suffix) const + { + if (suffix._length == 0) return true; // empty + if (suffix._length > _length) return false; // too long + auto get_char = [this](uint64_t idx) -> char32_t { + return is_ascii ? (is_heap ? heap.ascii[idx] : sso.ascii[idx]) : + (is_heap ? heap.utf32[idx] : sso.utf32[idx]); + }; + + auto get_suf_char = [&suffix](uint64_t idx) -> char32_t { + return suffix.is_ascii ? (suffix.is_heap ? suffix.heap.ascii[idx] : suffix.sso.ascii[idx]) : + (suffix.is_heap ? suffix.heap.utf32[idx] : suffix.sso.utf32[idx]); + }; + + uint64_t offset = _length - suffix._length; + for (uint64_t i = 0; i < suffix._length; ++i) + { + if (get_char(offset + i) != get_suf_char(i)) return false; + } + + return true; + } + + bool ends_with(char32_t c) const + { + if (_length == 0) return false; + + char32_t last_char = is_ascii ? (is_heap ? heap.ascii[_length - 1] : sso.ascii[_length - 1]) : + (is_heap ? heap.utf32[_length - 1] : sso.utf32[_length - 1]); + return last_char == c; + } + void clear() { destroy(); @@ -1529,8 +1996,15 @@ namespace Fig::StringClass::DynamicCapacity } } - friend struct std::hash; + __Iterator begin() const { return Iterator(this, 0); } + __Iterator end() const { return Iterator(this, _length); } }; + inline String operator+(const char32_t *lhs, const String &rhs) + { + String res(lhs); + res += rhs; + return res; + } }; // namespace Fig::StringClass::DynamicCapacity namespace Fig @@ -1556,21 +2030,13 @@ namespace std const uint64_t FNV_PRIME = 1099511628211ull; uint64_t hash = FNV_OFFSET_BASIS; - if (s.isAscii()) + + for (uint64_t i = 0; i < s.length(); ++i) { - const unsigned char *data = s.isOnHeap() ? s.heap.ascii : s.sso.ascii; - for (uint64_t i = 0; i < s.length(); ++i) + char32_t c = s[i]; + if (s.isAscii()) { hash ^= static_cast(static_cast(c)); } + else { - hash ^= static_cast(data[i]); - hash *= FNV_PRIME; - } - } - else - { - const char32_t *data = s.isOnHeap() ? s.heap.utf32 : s.sso.utf32; - for (uint64_t i = 0; i < s.length(); ++i) - { - uint32_t c = data[i]; // 将 char32_t -> 4 bytes for (int shift = 0; shift < 32; shift += 8) { @@ -1578,6 +2044,7 @@ namespace std hash *= FNV_PRIME; } } + hash *= FNV_PRIME; } return static_cast(hash); } diff --git a/src/Core/fig_string.hpp b/src/Core/__fig_string.hpp similarity index 52% rename from src/Core/fig_string.hpp rename to src/Core/__fig_string.hpp index 07fc1d1..63d0892 100644 --- a/src/Core/fig_string.hpp +++ b/src/Core/__fig_string.hpp @@ -18,15 +18,9 @@ namespace Fig return FStringView(reinterpret_cast(sv.data())); } - explicit FStringView(std::string_view sv) - { - *this = fromBasicStringView(sv); - } + explicit FStringView(std::string_view sv) { *this = fromBasicStringView(sv); } - explicit FStringView() - { - *this = fromBasicStringView(std::string_view("")); - } + explicit FStringView() { *this = fromBasicStringView(std::string_view("")); } std::string_view toBasicStringView() const { @@ -34,56 +28,26 @@ namespace Fig } }; - class FString : public std::u8string + class String : public std::u8string { public: using std::u8string::u8string; using std::u8string::operator=; - FString operator+(const FString &x) - { - return FString(toBasicString() + x.toBasicString()); - } - FString operator+(const char8_t *c) - { - return FString(*this + std::u8string(c)); - } + String operator+(const String &x) { return String(toBasicString() + x.toBasicString()); } + String operator+(const char8_t *c) { return String(*this + std::u8string(c)); } - explicit FString(const std::u8string &str) - { - *this = fromU8String(str); - } - explicit FString(std::string str) - { - *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()); - } + explicit String(const std::u8string &str) { *this = fromU8String(str); } + explicit String(std::string str) { *this = fromBasicString(str); } + explicit String(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) - { - return FString(str.begin(), str.end()); - } + static String fromBasicString(const std::string &str) { return String(str.begin(), str.end()); } - static FString fromStringView(FStringView sv) - { - return FString(reinterpret_cast(sv.data())); - } + static String fromStringView(FStringView sv) { return String(reinterpret_cast(sv.data())); } - static FString fromU8String(const std::u8string &str) - { - return FString(str.begin(), str.end()); - } + static String fromU8String(const std::u8string &str) { return String(str.begin(), str.end()); } size_t length() const { @@ -91,17 +55,14 @@ namespace Fig size_t len = 0; for (auto it = this->begin(); it != this->end(); ++it) { - if ((*it & 0xC0) != 0x80) - { - ++len; - } + if ((*it & 0xC0) != 0x80) { ++len; } } return len; } - FString getRealChar(size_t index) + String getRealChar(size_t index) { - FString ch; + String ch; size_t cnt = 0; for (size_t i = 0; i < size();) { @@ -112,13 +73,9 @@ namespace Fig cplen = 3; else if ((at(i) & 0xe0) == 0xc0) cplen = 2; - if (i + cplen > size()) - cplen = 1; + if (i + cplen > size()) cplen = 1; - if (cnt == index) - { - ch += substr(i, cplen); - } + if (cnt == index) { ch += substr(i, cplen); } i += cplen; ++cnt; @@ -127,7 +84,7 @@ namespace Fig return ch; } - void realReplace(size_t index, const FString &src) + void realReplace(size_t index, const String &src) { size_t cnt = 0; for (size_t i = 0; i < size();) @@ -139,13 +96,9 @@ namespace Fig cplen = 3; else if ((at(i) & 0xe0) == 0xc0) cplen = 2; - if (i + cplen > size()) - cplen = 1; + if (i + cplen > size()) cplen = 1; - if (cnt == index) - { - *this = FString(substr(0, i)) + src + FString(substr(i + cplen)); - } + if (cnt == index) { *this = String(substr(0, i)) + src + String(substr(i + cplen)); } i += cplen; ++cnt; @@ -165,32 +118,22 @@ namespace Fig cplen = 3; else if ((at(i) & 0xe0) == 0xc0) cplen = 2; - if (i + cplen > size()) - cplen = 1; + if (i + cplen > size()) cplen = 1; i += cplen; ++cnt; - if (cnt == index) - { - eraseStart = i; - } - if (cnt < index + n) - { - eraseCplens += cplen; - } + if (cnt == index) { eraseStart = i; } + if (cnt < index + n) { eraseCplens += cplen; } } erase(eraseStart, eraseCplens); } - void realInsert(size_t index, const FString &src) + void realInsert(size_t index, const String &src) { if (index == length()) { - for (auto &c : src) - { - push_back(c); - } + for (auto &c : src) { push_back(c); } return; } size_t cnt = 0; @@ -203,13 +146,9 @@ namespace Fig cplen = 3; else if ((at(i) & 0xe0) == 0xc0) cplen = 2; - if (i + cplen > size()) - cplen = 1; + if (i + cplen > size()) cplen = 1; - if (cnt == index) - { - insert(i, src); - } + if (cnt == index) { insert(i, src); } i += cplen; ++cnt; @@ -222,9 +161,9 @@ namespace Fig namespace std { template <> - struct hash + struct hash { - std::size_t operator()(const Fig::FString &s) const + std::size_t operator()(const Fig::String &s) const { return std::hash{}(static_cast(s)); } diff --git a/src/Core/utf8_iterator.hpp b/src/Core/__utf8_iterator.hpp similarity index 100% rename from src/Core/utf8_iterator.hpp rename to src/Core/__utf8_iterator.hpp diff --git a/src/Core/core.hpp b/src/Core/core.hpp index 2e07843..bcfa5e3 100644 --- a/src/Core/core.hpp +++ b/src/Core/core.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -54,6 +54,5 @@ namespace Fig inline constexpr std::string_view COMPILER = __FCORE_COMPILER; inline constexpr std::string_view COMPILE_TIME = __FCORE_COMPILE_TIME; inline constexpr std::string_view ARCH = __FCORE_ARCH; - inline constexpr FString MAIN_FUNCTION = u8"main"; }; // namespace Core }; // namespace Fig \ No newline at end of file diff --git a/src/Core/warning.cpp b/src/Core/warning.cpp index b1fa626..da5dae5 100644 --- a/src/Core/warning.cpp +++ b/src/Core/warning.cpp @@ -2,8 +2,8 @@ namespace Fig { - const std::unordered_map Warning::standardWarnings = { - {1, FString(u8"Identifier is too similar to a keyword or a primitive type")}, - {2, FString(u8"The identifier is too abstract")} + const std::unordered_map Warning::standardWarnings = { + {1, String(U"Identifier is too similar to a keyword or a primitive type")}, + {2, String(U"The identifier is too abstract")} }; }; \ No newline at end of file diff --git a/src/Core/warning.hpp b/src/Core/warning.hpp index bf63520..ab76710 100644 --- a/src/Core/warning.hpp +++ b/src/Core/warning.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -11,16 +11,17 @@ namespace Fig { private: size_t id; // the id (standard) of warning - FString msg; + String msg; size_t line, column; + public: - static const std::unordered_map standardWarnings; - Warning(size_t _id, FString _msg) + static const std::unordered_map standardWarnings; + Warning(size_t _id, String _msg) { id = _id; 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; msg = std::move(_msg); @@ -28,28 +29,12 @@ namespace Fig column = _column; } - auto getIDName() - { - return standardWarnings.at(id); - } - - auto getID() - { - return id; - } - auto getMsg() - { - return msg; - } - auto getLine() - { - return line; - } - auto getColumn() - { - return column; - } + auto getIDName() { return standardWarnings.at(id); } + auto getID() { return id; } + auto getMsg() { return msg; } + auto getLine() { return line; } + auto getColumn() { return column; } }; -}; \ No newline at end of file +}; // namespace Fig \ No newline at end of file diff --git a/src/Error/error.hpp b/src/Error/error.hpp index 5a9755d..6b89fab 100644 --- a/src/Error/error.hpp +++ b/src/Error/error.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -14,20 +14,29 @@ namespace Fig { public: explicit AddressableError() {} - explicit AddressableError(FString _msg, + explicit AddressableError(String _msg, size_t _line, size_t _column, - FString _sourcePath, - std::vector _sourceLines, + String _sourcePath, + std::vector _sourceLines, 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; } - 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()); - return FString(msg); + std::string msg = std::format("[AddressableError] {} at {}:{}, in [{}] {}", + 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 { @@ -38,37 +47,36 @@ namespace Fig virtual size_t getLine() const { return line; } virtual size_t getColumn() const { return column; } - FString getMessage() const { return message; } - FString getSourcePath() const { return sourcePath; } - std::vector getSourceLines() const { return sourceLines; } + String getMessage() const { return message; } + String getSourcePath() const { return sourcePath; } + std::vector getSourceLines() const { return sourceLines; } - virtual FString getErrorType() const - { - return FString(u8"AddressableError"); - } + virtual String getErrorType() const { return String(U"\1"); } protected: size_t line, column; - FString message; + String message; - FString sourcePath; - std::vector sourceLines; + String sourcePath; + std::vector sourceLines; }; class UnaddressableError : public std::exception { public: explicit UnaddressableError() {} - explicit UnaddressableError(FString _msg, - std::source_location loc = std::source_location::current()) : + explicit UnaddressableError(String _msg, std::source_location loc = std::source_location::current()) : src_loc(loc) { 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()); - return FString(msg); + std::string msg = std::format("[UnaddressableError] {} in [{}] {}", + this->message.toBasicString(), + this->src_loc.file_name(), + this->src_loc.function_name()); + return String(msg); } const char *what() const noexcept override { @@ -76,15 +84,12 @@ namespace Fig return msg.c_str(); } std::source_location src_loc; - FString getMessage() const { return message; } + String getMessage() const { return message; } - virtual FString getErrorType() const - { - return FString(u8"UnaddressableError"); - } + virtual String getErrorType() const { return String(U"\1"); } protected: - FString message; + String message; }; class SyntaxError : public AddressableError @@ -92,37 +97,36 @@ namespace Fig public: 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()); - return FString(msg); + std::string msg = std::format("[SyntaxError] {} in [{}] {}", + this->message.toBasicString(), + this->src_loc.file_name(), + this->src_loc.function_name()); + return String(msg); } - virtual FString getErrorType() const override - { - return FString(u8"SyntaxError"); - } + virtual String getErrorType() const override { return String(U"\1"); } }; class RuntimeError final : public UnaddressableError { public: using UnaddressableError::UnaddressableError; - explicit RuntimeError(FString _msg, - std::source_location loc = std::source_location::current()) : + explicit RuntimeError(String _msg, std::source_location loc = std::source_location::current()) : 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()); - return FString(msg); + std::string msg = std::format("[RuntimeError] {} in [{}] {}", + this->message.toBasicString(), + this->src_loc.file_name(), + this->src_loc.function_name()); + return String(msg); } - virtual FString getErrorType() const override - { - return FString(u8"RuntimeError"); - } + virtual String getErrorType() const override { return String(U"\1"); } }; - + } // namespace Fig \ No newline at end of file diff --git a/src/Error/errorLog.hpp b/src/Error/errorLog.hpp index 918d2d5..ba3d526 100644 --- a/src/Error/errorLog.hpp +++ b/src/Error/errorLog.hpp @@ -6,7 +6,6 @@ #include #include - namespace Fig { namespace ErrorLog @@ -87,7 +86,7 @@ namespace Fig constexpr const char *OnGray = "\033[48;2;128;128;128m"; }; // 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); } @@ -97,34 +96,44 @@ namespace Fig 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; - coloredPrint(TC::LightWhite, "Uncaught Fig exception:\n"); - coloredPrint(TC::LightRed, "✖ "); + coloredPrint(TC::LightWhite, U"Uncaught Fig exception:\n"); + coloredPrint(TC::LightRed, U"✖ "); coloredPrint(TC::Red, errorClass.toBasicString() + ": "); coloredPrint(TC::Red, errorMessage.toBasicString() + "\n"); } inline void logAddressableError(const AddressableError &err) { - const FString &fileName = err.getSourcePath(); - const std::vector &sourceLines = err.getSourceLines(); + const String &fileName = err.getSourcePath(); + const std::vector &sourceLines = err.getSourceLines(); std::print("\n"); namespace TC = TerminalColors; - coloredPrint(TC::LightWhite, "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::LightRed, "✖ "); - coloredPrint(TC::LightRed, std::format("{}: {}\n", err.getErrorType().toBasicString(), FString(err.getMessage()).toBasicString())); - coloredPrint(TC::White, std::format(" at {}:{} in file '{}'\n", err.getLine(), err.getColumn(), fileName.toBasicString())); + 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::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; - FString pointerLine; + String lineContent; + String pointerLine; - if (fileName != u8"") + if (fileName != U"\1") { - lineContent = ((int64_t(err.getLine()) - int64_t(1)) >= 0 ? sourceLines[err.getLine() - 1] : u8""); + lineContent = ((int64_t(err.getLine()) - int64_t(1)) >= 0 ? sourceLines[err.getLine() - 1] : U"\1"); for (size_t i = 1; i < err.getColumn(); ++i) { if (lineContent[i - 1] == U'\t') { pointerLine += U'\t'; } @@ -135,7 +144,7 @@ namespace Fig } pointerLine += U'^'; } - else + else { lineContent = fileName; } @@ -143,18 +152,34 @@ namespace Fig coloredPrint(TC::LightBlue, std::format(" {}\n", lineContent.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) { std::print("\n"); namespace TC = TerminalColors; - coloredPrint(TC::LightWhite, "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::DarkRed, "✖"); - coloredPrint(TC::Red, std::format("{}: {}\n", err.getErrorType().toBasicString(), FString(err.getMessage()).toBasicString())); - coloredPrint(TC::DarkGray, std::format("🔧 in function '{}' ({}:{})", err.src_loc.function_name(), err.src_loc.file_name(), err.src_loc.line())); + 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::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 Fig \ No newline at end of file diff --git a/src/Evaluator/Context/context.hpp b/src/Evaluator/Context/context.hpp index ac4762a..2fdd16d 100644 --- a/src/Evaluator/Context/context.hpp +++ b/src/Evaluator/Context/context.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -26,7 +26,7 @@ namespace Fig TypeInfo interfaceType; TypeInfo structType; - std::unordered_map implMethods; + std::unordered_map implMethods; }; struct OperationRecord @@ -49,11 +49,11 @@ namespace Fig class Context : public std::enable_shared_from_this { private: - FString scopeName; - std::unordered_map> variables; + String scopeName; + std::unordered_map> variables; // std::unordered_map functions; - // std::unordered_map functionNames; + // std::unordered_map functionNames; // implRegistry std::unordered_map, TypeInfoHash> implRegistry; @@ -63,13 +63,13 @@ namespace Fig ContextPtr parent; Context(const Context &) = default; - Context(const FString &name, ContextPtr p = nullptr) : scopeName(name), parent(p) {} + Context(const String &name, ContextPtr p = nullptr) : scopeName(name), parent(p) {} void setParent(ContextPtr _parent) { parent = _parent; } - void setScopeName(FString _name) { scopeName = std::move(_name); } + void setScopeName(String _name) { scopeName = std::move(_name); } - FString getScopeName() const { return scopeName; } + String getScopeName() const { return scopeName; } void merge(const Context &c) { @@ -94,58 +94,58 @@ namespace Fig return result; } - std::shared_ptr get(const FString &name) + std::shared_ptr get(const String &name) { auto it = variables.find(name); if (it != variables.end()) return it->second; if (parent) return parent->get(name); - throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString()))); + throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString()))); } - AccessModifier getAccessModifier(const FString &name) + AccessModifier getAccessModifier(const String &name) { if (variables.contains(name)) { return variables[name]->am; } else if (parent != nullptr) { return parent->getAccessModifier(name); } else { - throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString()))); + throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString()))); } } - bool isVariableMutable(const FString &name) + bool isVariableMutable(const String &name) { AccessModifier am = getAccessModifier(name); // may throw return !isAccessConst(am); } - bool isVariablePublic(const FString &name) + bool isVariablePublic(const String &name) { AccessModifier am = getAccessModifier(name); // may throw return isAccessPublic(am); } - void set(const FString &name, ObjectPtr value) + void set(const String &name, ObjectPtr value) { if (variables.contains(name)) { if (!isVariableMutable(name)) { - throw RuntimeError(FString(std::format("Variable '{}' is immutable", name.toBasicString()))); + throw RuntimeError(String(std::format("Variable '{}' is immutable", name.toBasicString()))); } variables[name]->value = value; } else if (parent != nullptr) { parent->set(name, value); } else { - throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString()))); + throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString()))); } } - void _update(const FString &name, ObjectPtr value) + void _update(const String &name, ObjectPtr value) { if (variables.contains(name)) { variables[name]->value = value; } else if (parent != nullptr) { parent->_update(name, value); } else { - throw RuntimeError(FString(std::format("Variable '{}' not defined", name.toBasicString()))); + throw RuntimeError(String(std::format("Variable '{}' not defined", name.toBasicString()))); } } - void def(const FString &name, + void def(const String &name, const TypeInfo &ti, AccessModifier am, const ObjectPtr &value = Object::getNullInstance()) @@ -153,7 +153,7 @@ namespace Fig if (containsInThisScope(name)) { throw RuntimeError( - FString(std::format("Variable '{}' already defined in this scope", name.toBasicString()))); + String(std::format("Variable '{}' already defined in this scope", name.toBasicString()))); } variables[name] = std::make_shared(name, value, ti, am); // if (ti == ValueType::StructType) @@ -163,17 +163,17 @@ namespace Fig // } } void - defReference(const FString &name, const TypeInfo &ti, AccessModifier am, std::shared_ptr target) + defReference(const String &name, const TypeInfo &ti, AccessModifier am, std::shared_ptr target) { if (containsInThisScope(name)) { throw RuntimeError( - FString(std::format("Variable '{}' already defined in this scope", name.toBasicString()))); + String(std::format("Variable '{}' already defined in this scope", name.toBasicString()))); } variables[name] = std::make_shared(name, target->value, ti, am, true, target); } - std::optional getFunctionName(std::size_t id) + std::optional getFunctionName(std::size_t id) { for (auto &[name, slot] : variables) { @@ -185,7 +185,7 @@ namespace Fig } return std::nullopt; } - // std::optional getStructName(std::size_t id) + // std::optional getStructName(std::size_t id) // { // auto it = structTypeNames.find(id); // if (it != structTypeNames.end()) @@ -201,21 +201,21 @@ namespace Fig // return std::nullopt; // } // } - bool contains(const FString &name) + bool contains(const String &name) { if (variables.contains(name)) { return true; } else if (parent != nullptr) { return parent->contains(name); } return false; } - bool containsInThisScope(const FString &name) const { return variables.contains(name); } + bool containsInThisScope(const String &name) const { return variables.contains(name); } - TypeInfo getTypeInfo(const FString &name) { return get(name)->declaredType; } + TypeInfo getTypeInfo(const String &name) { return get(name)->declaredType; } bool isInFunctionContext() { ContextPtr ctx = shared_from_this(); while (ctx) { - if (ctx->getScopeName().find(u8"getScopeName().find(U"\1") == 0) { return true; } ctx = ctx->parent; } return false; @@ -225,10 +225,7 @@ namespace Fig ContextPtr ctx = shared_from_this(); while (ctx) { - if (ctx->getScopeName().find(u8"getScopeName().find(u8"getScopeName().find(U"\1") == 0 or ctx->getScopeName().find(U"\1") == 0) { return true; } ctx = ctx->parent; } return false; @@ -282,7 +279,7 @@ namespace Fig list.push_back(record); // order is the level } - bool hasMethodImplemented(const TypeInfo &structType, const FString &functionName) const + bool hasMethodImplemented(const TypeInfo &structType, const String &functionName) const { auto it = implRegistry.find(structType); if (it != implRegistry.end()) @@ -296,7 +293,7 @@ namespace Fig return parent && parent->hasMethodImplemented(structType, functionName); } - bool hasDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName) const + bool hasDefaultImplementedMethod(const TypeInfo &structType, const String &functionName) const { auto it = implRegistry.find(structType); if (it == implRegistry.end()) return false; @@ -325,7 +322,7 @@ namespace Fig return false; } - Ast::InterfaceMethod getDefaultImplementedMethod(const TypeInfo &structType, const FString &functionName) + Ast::InterfaceMethod getDefaultImplementedMethod(const TypeInfo &structType, const String &functionName) { // O(N²) // SLOW @@ -366,7 +363,7 @@ namespace Fig assert(false); } - const Function &getImplementedMethod(const TypeInfo &structType, const FString &functionName) const + const Function &getImplementedMethod(const TypeInfo &structType, const String &functionName) const { auto it = implRegistry.find(structType); if (it != implRegistry.end()) diff --git a/src/Evaluator/Core/Eval.cpp b/src/Evaluator/Core/Eval.cpp index 1e5f823..1406af8 100644 --- a/src/Evaluator/Core/Eval.cpp +++ b/src/Evaluator/Core/Eval.cpp @@ -12,7 +12,7 @@ namespace Fig { case AstType::ValueExpr: { auto val = std::static_pointer_cast(exp); - + return val->val; } case AstType::VarExpr: { @@ -22,17 +22,17 @@ namespace Fig } case AstType::BinaryExpr: { auto bin = std::static_pointer_cast(exp); - + return evalBinary(bin, ctx); } case AstType::UnaryExpr: { auto un = std::static_pointer_cast(exp); - + return evalUnary(un, ctx); } case AstType::TernaryExpr: { auto te = std::static_pointer_cast(exp); - + return evalTernary(te, ctx); } case AstType::MemberExpr: @@ -44,13 +44,11 @@ namespace Fig } case AstType::FunctionLiteralExpr: { auto fnLiteral = std::static_pointer_cast(exp); - Ast::BlockStatement body = nullptr; if (fnLiteral->isExprMode()) { Ast::Expression exprBody = fnLiteral->getExprBody(); - const Ast::AstAddressInfo &aai = exprBody->getAAI(); Ast::Return st = std::make_shared(exprBody); @@ -63,9 +61,8 @@ namespace Fig else { body = fnLiteral->getBlockBody(); - } - Function fn(FString(std::format("")),fnLiteral->paras, ValueType::Any, body, ctx + Function fn(String(std::format("")), fnLiteral->paras, ValueType::Any, body, ctx /* pass the ctx(fnLiteral eval context) as closure context */ @@ -74,13 +71,12 @@ namespace Fig } case AstType::InitExpr: { auto initExpr = std::static_pointer_cast(exp); - + return evalInitExpr(initExpr, ctx); } case AstType::ListExpr: { auto lstExpr = std::static_pointer_cast(exp); - List list; for (auto &exp : lstExpr->val) { list.push_back(check_unwrap(eval(exp, ctx))); } @@ -89,19 +85,19 @@ namespace Fig case AstType::MapExpr: { auto mapExpr = std::static_pointer_cast(exp); - Map map; - for (auto &[key, value] : mapExpr->val) { + for (auto &[key, value] : mapExpr->val) + { map[check_unwrap(eval(key, ctx))] = check_unwrap(eval(value, ctx)); } return std::make_shared(std::move(map)); } default: { - throw RuntimeError(FString(std::format("err type of expr: {}", magic_enum::enum_name(type)))); + throw RuntimeError(String(std::format("err type of expr: {}", magic_enum::enum_name(type)))); } } return Object::getNullInstance(); // ignore warning } -}; \ No newline at end of file +}; // namespace Fig \ No newline at end of file diff --git a/src/Evaluator/Core/EvalBinary.cpp b/src/Evaluator/Core/EvalBinary.cpp index 544d245..89650ec 100644 --- a/src/Evaluator/Core/EvalBinary.cpp +++ b/src/Evaluator/Core/EvalBinary.cpp @@ -86,7 +86,7 @@ namespace Fig { ValueType::IntClass lv = lhs->as(); ValueType::IntClass rv = rhs->as(); - if (rv == 0) { throw ValueError(FString(std::format("Modulo by zero: {} % {}", lv, rv))); } + if (rv == 0) { throw ValueError(String(std::format("Modulo by zero: {} % {}", lv, rv))); } ValueType::IntClass result = lv / rv; ValueType::IntClass r = lv % rv; if (r != 0 && ((lv < 0) != (rv < 0))) { result -= 1; } @@ -139,7 +139,7 @@ namespace Fig return Object::getFalseInstance(); } - throw EvaluatorError(u8"TypeError", + throw EvaluatorError(U"TypeError", std::format("Unsupported operator `is` for '{}' && '{}'", prettyType(lhs).toBasicString(), prettyType(rhs).toBasicString()), @@ -155,7 +155,7 @@ namespace Fig if (!rhs->is()) { throw EvaluatorError( - u8"OperatorError", + U"OperatorError", std::format("Operator `as` requires right hand side operand a struct type, but got '{}'", prettyType(rhs).toBasicString()), bin->rexp); @@ -183,7 +183,7 @@ namespace Fig } else if (sourceType == ValueType::String) { - const FString &str = lhs->as(); + const String &str = lhs->as(); if (targetType == ValueType::Int) { try @@ -194,10 +194,10 @@ namespace Fig catch (std::exception &e) { return ExprResult::error( - genTypeError(FString(std::format("Cannot cast type `{}` to `{}`, bad int string {}", - prettyType(lhs).toBasicString(), - prettyType(rhs).toBasicString(), - str.toBasicString())), + genTypeError(String(std::format("Cannot cast type `{}` to `{}`, bad int string {}", + prettyType(lhs).toBasicString(), + prettyType(rhs).toBasicString(), + str.toBasicString())), bin->rexp, ctx)); } @@ -211,22 +211,22 @@ namespace Fig catch (std::exception &e) { return ExprResult::error(genTypeError( - FString(std::format("Cannot cast type `{}` to `{}`, bad double string {}", - prettyType(lhs).toBasicString(), - prettyType(rhs).toBasicString(), - str.toBasicString())), + String(std::format("Cannot cast type `{}` to `{}`, bad double string {}", + prettyType(lhs).toBasicString(), + prettyType(rhs).toBasicString(), + str.toBasicString())), bin->rexp, ctx)); } } if (targetType == ValueType::Bool) { - if (str == u8"true") { return Object::getTrueInstance(); } - else if (str == u8"false") { return Object::getFalseInstance(); } + if (str == U"true") { return Object::getTrueInstance(); } + else if (str == U"false") { return Object::getFalseInstance(); } return ExprResult::error( - genTypeError(FString(std::format("Cannot cast type `{}` to `{}`, bad bool string {}", - prettyType(lhs).toBasicString(), - prettyType(rhs).toBasicString(), + genTypeError(String(std::format("Cannot cast type `{}` to `{}`, bad bool string {}", + prettyType(lhs).toBasicString(), + prettyType(rhs).toBasicString(), str.toBasicString())), bin->rexp, ctx)); @@ -236,17 +236,19 @@ namespace Fig { if (targetType == ValueType::Int) { - return IntPool::getInstance().createInt(static_cast(lhs->as())); + return IntPool::getInstance().createInt( + static_cast(lhs->as())); } if (targetType == ValueType::Double) { - return std::make_shared(static_cast(lhs->as())); + return std::make_shared( + static_cast(lhs->as())); } } - return ExprResult::error(genTypeError(FString(std::format("Cannot cast type `{}` to `{}`", - prettyType(lhs).toBasicString(), - prettyType(rhs).toBasicString())), + return ExprResult::error(genTypeError(String(std::format("Cannot cast type `{}` to `{}`", + prettyType(lhs).toBasicString(), + prettyType(rhs).toBasicString())), bin->rexp, ctx)); }); @@ -429,7 +431,7 @@ namespace Fig } default: - throw EvaluatorError(u8"UnsupportedOp", + throw EvaluatorError(U"UnsupportedOp", std::format("Unsupport operator '{}' for binary", magic_enum::enum_name(op)), bin); } diff --git a/src/Evaluator/Core/EvalFunctionCall.cpp b/src/Evaluator/Core/EvalFunctionCall.cpp index c52ae7d..7fba2b0 100644 --- a/src/Evaluator/Core/EvalFunctionCall.cpp +++ b/src/Evaluator/Core/EvalFunctionCall.cpp @@ -9,11 +9,11 @@ namespace Fig { - ExprResult Evaluator::executeFunction(const Function &fn, - const Ast::FunctionCallArgs &args, - ContextPtr fnCtx) // new context for fn, already filled paras + ExprResult Evaluator::executeFunction(const Function &fn, + const Ast::FunctionCallArgs &args, + ContextPtr fnCtx) // new context for fn, already filled paras { - // const FString &fnName = fn.name; + // const String &fnName = fn.name; if (fn.type == Function::Builtin || fn.type == Function::MemberType) { if (fn.type == Function::Builtin) { return fn.builtin(args.argv); } @@ -27,14 +27,8 @@ namespace Fig for (const auto &stmt : fn.body->stmts) { StatementResult sr = evalStatement(stmt, fnCtx); - if (sr.isError()) - { - handle_error(sr, stmt, fnCtx); - } - if (!sr.isNormal()) - { - return sr.result; - } + if (sr.isError()) { handle_error(sr, stmt, fnCtx); } + if (!sr.isNormal()) { return sr.result; } } return Object::getNullInstance(); } @@ -43,14 +37,14 @@ namespace Fig RvObject fnObj = check_unwrap(eval(call->callee, ctx)); if (fnObj->getTypeInfo() != ValueType::Function) { - throw EvaluatorError(u8"ObjectNotCallable", + throw EvaluatorError(U"ObjectNotCallable", std::format("Object `{}` isn't callable", fnObj->toString().toBasicString()), call->callee); } const Function &fn = fnObj->as(); - const FString &fnName = fn.name; + const String &fnName = fn.name; const Ast::FunctionArguments &fnArgs = call->arg; Ast::FunctionCallArgs evaluatedArgs; @@ -59,7 +53,7 @@ namespace Fig for (const auto &argExpr : fnArgs.argv) { evaluatedArgs.argv.push_back(check_unwrap(eval(argExpr, ctx))); } if (fn.builtinParamCount != -1 && fn.builtinParamCount != evaluatedArgs.getLength()) { - throw EvaluatorError(u8"BuiltinArgumentMismatchError", + throw EvaluatorError(U"BuiltinArgumentMismatchError", std::format("Builtin function '{}' expects {} arguments, but {} were provided", fnName.toBasicString(), fn.builtinParamCount, @@ -73,7 +67,7 @@ namespace Fig Ast::FunctionParameters fnParas = fn.paras; // create new context for function call - auto newContext = std::make_shared(FString(std::format("", fnName.toBasicString())), + auto newContext = std::make_shared(String(std::format("", fnName.toBasicString())), fn.closureContext); if (fnParas.variadic) @@ -84,24 +78,25 @@ namespace Fig NormalFilling: { if (fnArgs.getLength() < fnParas.posParas.size() || fnArgs.getLength() > fnParas.size()) { - throw RuntimeError(FString(std::format("Function '{}' expects {} to {} arguments, but {} were provided", - fnName.toBasicString(), - fnParas.posParas.size(), - fnParas.size(), - fnArgs.getLength()))); + throw RuntimeError(String(std::format("Function '{}' expects {} to {} arguments, but {} were provided", + fnName.toBasicString(), + fnParas.posParas.size(), + fnParas.size(), + fnArgs.getLength()))); } // positional parameters type check size_t i; for (i = 0; i < fnParas.posParas.size(); i++) { - const TypeInfo &expectedType = actualType(check_unwrap(eval(fnParas.posParas[i].second, fn.closureContext))); // look up type info, if exists a type - // with the name, use it, else throw + const TypeInfo &expectedType = actualType(check_unwrap( + eval(fnParas.posParas[i].second, fn.closureContext))); // look up type info, if exists a type + // with the name, use it, else throw ObjectPtr argVal = check_unwrap(eval(fnArgs.argv[i], ctx)); TypeInfo actualType = argVal->getTypeInfo(); if (!isTypeMatch(expectedType, argVal, fn.closureContext)) { - throw EvaluatorError(u8"ArgumentTypeMismatchError", + throw EvaluatorError(U"ArgumentTypeMismatchError", std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'", fnName.toBasicString(), fnParas.posParas[i].first.toBasicString(), @@ -122,7 +117,7 @@ namespace Fig if (!isTypeMatch(expectedType, defaultVal, fn.closureContext)) { throw EvaluatorError( - u8"DefaultParameterTypeError", + U"DefaultParameterTypeError", std::format( "In function '{}', default parameter '{}' has type '{}', which does not match the expected type '{}'", fnName.toBasicString(), @@ -136,7 +131,7 @@ namespace Fig TypeInfo actualType = argVal->getTypeInfo(); if (!isTypeMatch(expectedType, argVal, fn.closureContext)) { - throw EvaluatorError(u8"ArgumentTypeMismatchError", + throw EvaluatorError(U"ArgumentTypeMismatchError", std::format("In function '{}', argument '{}' expects type '{}', but got type '{}'", fnName.toBasicString(), fnParas.defParas[defParamIndex].first.toBasicString(), @@ -157,7 +152,7 @@ namespace Fig // define parameters in new context for (size_t j = 0; j < fnParas.size(); j++) { - FString paramName; + String paramName; TypeInfo paramType; if (j < fnParas.posParas.size()) { @@ -193,7 +188,7 @@ namespace Fig if (!isTypeMatch(fn.retType, retVal, ctx)) { - throw EvaluatorError(u8"ReturnTypeMismatchError", + throw EvaluatorError(U"ReturnTypeMismatchError", std::format("Function '{}' expects return type '{}', but got type '{}'", fnName.toBasicString(), fn.retType.toString().toBasicString(), diff --git a/src/Evaluator/Core/EvalInitExpr.cpp b/src/Evaluator/Core/EvalInitExpr.cpp index f6acc51..9f8ee48 100644 --- a/src/Evaluator/Core/EvalInitExpr.cpp +++ b/src/Evaluator/Core/EvalInitExpr.cpp @@ -10,10 +10,10 @@ namespace Fig { LvObject structeLv = check_unwrap_lv(evalLv(initExpr->structe, ctx)); ObjectPtr structTypeVal = structeLv.get(); - const FString &structName = structeLv.name(); + const String &structName = structeLv.name(); if (!structTypeVal->is()) { - throw EvaluatorError(u8"NotAStructTypeError", + throw EvaluatorError(U"NotAStructTypeError", std::format("'{}' is not a structure type", structName.toBasicString()), initExpr); } @@ -27,7 +27,7 @@ namespace Fig if (argSize > 1) { - throw EvaluatorError(u8"StructInitArgumentMismatchError", + throw EvaluatorError(U"StructInitArgumentMismatchError", std::format("Builtin class `{}` expects 0 or 1 argument, but {} were provided", type.toString().toBasicString(), argSize), @@ -40,7 +40,7 @@ namespace Fig if (type == ValueType::Any || type == ValueType::Null || type == ValueType::Function) { throw EvaluatorError( - u8"BuiltinNotConstructibleError", + U"BuiltinNotConstructibleError", std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()), initExpr); } @@ -50,7 +50,7 @@ namespace Fig ObjectPtr val = check_unwrap(eval(args[0].second, ctx)); auto err = [&](const char *msg) { - throw EvaluatorError(u8"BuiltinInitTypeMismatchError", + throw EvaluatorError(U"BuiltinInitTypeMismatchError", std::format("Builtin `{}` constructor {}", type.toString().toBasicString(), msg), initExpr); }; @@ -121,7 +121,7 @@ namespace Fig } throw EvaluatorError( - u8"BuiltinNotConstructibleError", + U"BuiltinNotConstructibleError", std::format("Builtin type `{}` cannot be constructed", type.toString().toBasicString()), initExpr); } @@ -140,7 +140,7 @@ namespace Fig size_t got = initExpr->args.size(); if (got > maxArgs || got < minArgs) { - throw EvaluatorError(u8"StructInitArgumentMismatchError", + throw EvaluatorError(U"StructInitArgumentMismatchError", std::format("Structure '{}' expects {} to {} fields, but {} were provided", structName.toBasicString(), minArgs, @@ -149,9 +149,9 @@ namespace Fig initExpr); } - std::vector> evaluatedArgs; + std::vector> evaluatedArgs; - auto evalArguments = [&evaluatedArgs, initExpr, ctx, this](){ + auto evalArguments = [&evaluatedArgs, initExpr, ctx, this]() { for (const auto &[argName, argExpr] : initExpr->args) { evaluatedArgs.push_back({argName, check_unwrap(eval(argExpr, ctx))}); @@ -159,8 +159,8 @@ namespace Fig return ExprResult::normal(Object::getNullInstance()); }; - ContextPtr instanceCtx = - std::make_shared(FString(std::format("", structName.toBasicString())), defContext); + ContextPtr instanceCtx = std::make_shared( + String(std::format("", structName.toBasicString())), defContext); /* 3 ways of calling constructor .1 Person {"Fig", 1, "IDK"}; @@ -176,7 +176,7 @@ namespace Fig for (size_t i = 0; i < maxArgs; ++i) { const Field &field = structT.fields[i]; - const FString &fieldName = field.name; + const String &fieldName = field.name; const TypeInfo &expectedType = field.type; if (i >= evaluatedArgs.size()) { @@ -191,7 +191,7 @@ namespace Fig if (!isTypeMatch(expectedType, defaultVal, ctx)) { throw EvaluatorError( - u8"StructFieldTypeMismatchError", + U"StructFieldTypeMismatchError", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", structName.toBasicString(), fieldName.toBasicString(), @@ -208,7 +208,7 @@ namespace Fig if (!isTypeMatch(expectedType, argVal, ctx)) { throw EvaluatorError( - u8"StructFieldTypeMismatchError", + U"StructFieldTypeMismatchError", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", structName.toBasicString(), fieldName.toBasicString(), @@ -227,10 +227,10 @@ namespace Fig for (size_t i = 0; i < maxArgs; ++i) { const Field &field = structT.fields[i]; - const FString &fieldName = (field.name.empty() ? evaluatedArgs[i].first : field.name); + const String &fieldName = (field.name.empty() ? evaluatedArgs[i].first : field.name); if (instanceCtx->containsInThisScope(fieldName)) { - throw EvaluatorError(u8"StructFieldRedeclarationError", + throw EvaluatorError(U"StructFieldRedeclarationError", std::format("Field '{}' already initialized in structure '{}'", fieldName.toBasicString(), structName.toBasicString()), @@ -248,7 +248,7 @@ namespace Fig if (!isTypeMatch(expectedType, defaultVal, ctx)) { throw EvaluatorError( - u8"StructFieldTypeMismatchError", + U"StructFieldTypeMismatchError", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", structName.toBasicString(), fieldName.toBasicString(), @@ -264,7 +264,7 @@ namespace Fig if (!isTypeMatch(field.type, argVal, ctx)) { throw EvaluatorError( - u8"StructFieldTypeMismatchError", + U"StructFieldTypeMismatchError", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", structName.toBasicString(), fieldName.toBasicString(), @@ -291,7 +291,7 @@ namespace Fig [&argName](const Field &f) { return f.name == argName; }); if (fieldIt == structT.fields.end()) { - // throw EvaluatorError(u8"StructFieldNotFoundError", + // throw EvaluatorError(U"StructFieldNotFoundError", // std::format("Field '{}' not found in structure '{}'", // argName.toBasicString(), // structName.toBasicString()), @@ -303,7 +303,7 @@ namespace Fig if (!isTypeMatch(field.type, argVal, ctx)) { throw EvaluatorError( - u8"StructFieldTypeMismatchError", + U"StructFieldTypeMismatchError", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", structName.toBasicString(), field.name.toBasicString(), @@ -332,7 +332,7 @@ namespace Fig if (!isTypeMatch(field.type, defaultVal, ctx)) { throw EvaluatorError( - u8"StructFieldTypeMismatchError", + U"StructFieldTypeMismatchError", std::format("In structure '{}', field '{}' expects type '{}', but got type '{}'", structName.toBasicString(), field.name.toBasicString(), @@ -350,9 +350,9 @@ namespace Fig // load struct method for (auto &[id, fn] : stDefCtx->getFunctions()) { - const FString &funcName = fn.name; + const String &funcName = fn.name; const auto &funcSlot = stDefCtx->get(funcName); - + instanceCtx->def(funcName, ValueType::Function, funcSlot->am, @@ -361,4 +361,4 @@ namespace Fig return std::make_shared(StructInstance(structT.type, instanceCtx)); } -}; \ No newline at end of file +}; // namespace Fig \ No newline at end of file diff --git a/src/Evaluator/Core/EvalLvObject.cpp b/src/Evaluator/Core/EvalLvObject.cpp index 5e3ad6a..6df3edf 100644 --- a/src/Evaluator/Core/EvalLvObject.cpp +++ b/src/Evaluator/Core/EvalLvObject.cpp @@ -8,7 +8,7 @@ namespace Fig { ExprResult Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx) { - const FString &name = var->name; + const String &name = var->name; // 调试信息 // std::cerr << "=== DEBUG evalVarExpr ===" << std::endl; @@ -38,14 +38,14 @@ namespace Fig // } // end - if (!ctx->contains(name)) { throw EvaluatorError(u8"UndeclaredIdentifierError", name, var); } + if (!ctx->contains(name)) { throw EvaluatorError(U"UndeclaredIdentifierError", name, var); } return LvObject(ctx->get(name), ctx); } ExprResult Evaluator::evalMemberExpr(Ast::MemberExpr me, ContextPtr ctx) { // LvObject base = evalLv(me->base, ctx); RvObject baseVal = check_unwrap(eval(me->base, ctx)); - const FString &member = me->member; + const String &member = me->member; if (baseVal->getTypeInfo() == ValueType::Module) { // std::cerr << "=== DEBUG evalMemberExpr (Module) ===" << std::endl; @@ -74,7 +74,7 @@ namespace Fig } else { - throw EvaluatorError(u8"VariableNotFoundError", + throw EvaluatorError(U"VariableNotFoundError", std::format("`{}` has not variable '{}', check if it is public", baseVal->toString().toBasicString(), member.toBasicString()), @@ -118,7 +118,7 @@ namespace Fig if (baseVal->getTypeInfo() != ValueType::StructInstance) // and not member function found { throw EvaluatorError( - u8"NoAttributeError", + U"NoAttributeError", std::format("`{}` has not attribute '{}'", baseVal->toString().toBasicString(), member.toBasicString()), me->base); } @@ -153,7 +153,7 @@ namespace Fig } else { - throw EvaluatorError(u8"NoAttributeError", + throw EvaluatorError(U"NoAttributeError", std::format("`{}` has not attribute '{}' and no interfaces have been implemented it", baseVal->toString().toBasicString(), member.toBasicString()), @@ -172,7 +172,7 @@ namespace Fig if (index->getTypeInfo() != ValueType::Int) { throw EvaluatorError( - u8"TypeError", + U"TypeError", std::format("Type `List` indices must be `Int`, got '{}'", prettyType(index).toBasicString()), ie->index); } @@ -181,7 +181,7 @@ namespace Fig if (indexVal >= list.size()) { throw EvaluatorError( - u8"IndexOutOfRangeError", + U"IndexOutOfRangeError", std::format("Index {} out of list `{}` range", indexVal, base->toString().toBasicString()), ie->index); } @@ -193,16 +193,16 @@ namespace Fig if (index->getTypeInfo() != ValueType::Int) { throw EvaluatorError( - u8"TypeError", + U"TypeError", std::format("Type `String` indices must be `Int`, got '{}'", prettyType(index).toBasicString()), ie->index); } - FString &string = base->as(); + String &string = base->as(); ValueType::IntClass indexVal = index->as(); if (indexVal >= string.length()) { throw EvaluatorError( - u8"IndexOutOfRangeError", + U"IndexOutOfRangeError", std::format("Index {} out of string `{}` range", indexVal, base->toString().toBasicString()), ie->index); } @@ -211,7 +211,7 @@ namespace Fig else { throw EvaluatorError( - u8"NoSubscriptableError", + U"NoSubscriptableError", std::format("`{}` object is not subscriptable", base->getTypeInfo().toString().toBasicString()), ie->base); } @@ -239,7 +239,7 @@ namespace Fig } default: { throw EvaluatorError( - u8"TypeError", + U"TypeError", std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()), exp); } diff --git a/src/Evaluator/Core/EvalStatement.cpp b/src/Evaluator/Core/EvalStatement.cpp index 629b2be..b34f467 100644 --- a/src/Evaluator/Core/EvalStatement.cpp +++ b/src/Evaluator/Core/EvalStatement.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -32,7 +32,7 @@ namespace Fig if (ctx->containsInThisScope(varDef->name)) { throw EvaluatorError( - u8"RedeclarationError", + U"RedeclarationError", std::format("Variable `{}` already declared in this scope", varDef->name.toBasicString()), varDef); } @@ -51,7 +51,7 @@ namespace Fig if (value != nullptr && !isTypeMatch(declaredType, value, ctx)) { - throw EvaluatorError(u8"TypeError", + throw EvaluatorError(U"TypeError", std::format("Variable `{}` expects init-value type `{}`, but got '{}'", varDef->name.toBasicString(), prettyType(declaredTypeValue).toBasicString(), @@ -73,11 +73,11 @@ namespace Fig case FunctionDefSt: { auto fnDef = std::static_pointer_cast(stmt); - const FString &fnName = fnDef->name; + const String &fnName = fnDef->name; if (ctx->containsInThisScope(fnName)) { throw EvaluatorError( - u8"RedeclarationError", + U"RedeclarationError", std::format("Function `{}` already declared in this scope", fnName.toBasicString()), fnDef); } @@ -102,16 +102,16 @@ namespace Fig if (ctx->containsInThisScope(stDef->name)) { throw EvaluatorError( - u8"RedeclarationError", + U"RedeclarationError", std::format("Structure '{}' already defined in this scope", stDef->name.toBasicString()), stDef); } TypeInfo type(stDef->name, true); // register type name - ContextPtr defContext = std::make_shared(FString(std::format("", - stDef->name.toBasicString(), - stDef->getAAI().line, - stDef->getAAI().column)), + ContextPtr defContext = std::make_shared(String(std::format("", + stDef->name.toBasicString(), + stDef->getAAI().line, + stDef->getAAI().column)), ctx); ObjectPtr structTypeObj = std::make_shared(StructType(type, defContext, {})); @@ -124,12 +124,12 @@ namespace Fig structTypeObj); // predef to itself, always const std::vector fields; - std::vector _fieldNames; + std::vector _fieldNames; for (Ast::StructDefField field : stDef->fields) { if (Utils::vectorContains(field.fieldName, _fieldNames)) { - throw EvaluatorError(u8"RedeclarationError", + throw EvaluatorError(U"RedeclarationError", std::format("Field '{}' already defined in structure '{}'", field.fieldName.toBasicString(), stDef->name.toBasicString()), @@ -151,7 +151,7 @@ namespace Fig { if (st->getType() != Ast::AstType::FunctionDefSt) { - throw EvaluatorError(u8"UnexpectedStatementInStructError", + throw EvaluatorError(U"UnexpectedStatementInStructError", std::format("Unexpected statement `{}` in struct declaration", st->toString().toBasicString()), st); @@ -164,12 +164,12 @@ namespace Fig case InterfaceDefSt: { auto ifd = std::static_pointer_cast(stmt); - const FString &interfaceName = ifd->name; + const String &interfaceName = ifd->name; if (ctx->containsInThisScope(interfaceName)) { throw EvaluatorError( - u8"RedeclarationError", + U"RedeclarationError", std::format("Interface `{}` already declared in this scope", interfaceName.toBasicString()), ifd); } @@ -188,7 +188,7 @@ namespace Fig TypeInfo interfaceType(ip->interfaceName); if (ctx->hasImplRegisted(structType, interfaceType)) { - throw EvaluatorError(u8"DuplicateImplError", + throw EvaluatorError(U"DuplicateImplError", std::format("Duplicate implement `{}` for `{}`", interfaceType.toString().toBasicString(), structType.toString().toBasicString()), @@ -196,13 +196,13 @@ namespace Fig } if (!ctx->contains(ip->interfaceName)) { - throw EvaluatorError(u8"InterfaceNotFoundError", + throw EvaluatorError(U"InterfaceNotFoundError", std::format("Interface '{}' not found", ip->interfaceName.toBasicString()), ip); } if (!ctx->contains(ip->structName)) { - throw EvaluatorError(u8"StructNotFoundError", + throw EvaluatorError(U"StructNotFoundError", std::format("Struct '{}' not found", ip->structName.toBasicString()), ip); } @@ -218,21 +218,21 @@ namespace Fig if (!interfaceObj->is()) { throw EvaluatorError( - u8"NotAInterfaceError", + U"NotAInterfaceError", std::format("Variable `{}` is not a interface", ip->interfaceName.toBasicString()), ip); } if (!structTypeObj->is()) { throw EvaluatorError( - u8"NotAStructType", + U"NotAStructType", std::format("Variable `{}` is not a struct type", ip->structName.toBasicString()), ip); } auto &implementMethods = ip->methods; - if (ip->interfaceName == u8"Operation") + if (ip->interfaceName == U"Operation") { // 运算符重载 /* @@ -243,52 +243,52 @@ namespace Fig */ if (ValueType::isTypeBuiltin(structType)) { - throw EvaluatorError(u8"BadUserError", + throw EvaluatorError(U"BadUserError", std::format("Don't overload built-in type operators plz! `{}`", prettyType(structTypeObj).toBasicString()), ip); } using enum Ast::Operator; - static const std::unordered_map> magic_name_to_op = { + static const std::unordered_map> magic_name_to_op = { // 算术 - {u8"Add", {Ast::Operator::Add, 2}}, - {u8"Sub", {Ast::Operator::Subtract, 2}}, - {u8"Mul", {Ast::Operator::Multiply, 2}}, - {u8"Div", {Ast::Operator::Divide, 2}}, - {u8"Mod", {Ast::Operator::Modulo, 2}}, - {u8"Pow", {Ast::Operator::Power, 2}}, + {U"Add", {Ast::Operator::Add, 2}}, + {U"Sub", {Ast::Operator::Subtract, 2}}, + {U"Mul", {Ast::Operator::Multiply, 2}}, + {U"Div", {Ast::Operator::Divide, 2}}, + {U"Mod", {Ast::Operator::Modulo, 2}}, + {U"Pow", {Ast::Operator::Power, 2}}, // 逻辑(一元) - {u8"Neg", {Ast::Operator::Subtract, 1}}, // 一元负号 - {u8"Not", {Ast::Operator::Not, 1}}, + {U"Neg", {Ast::Operator::Subtract, 1}}, // 一元负号 + {U"Not", {Ast::Operator::Not, 1}}, // 逻辑(二元) - {u8"And", {Ast::Operator::And, 2}}, - {u8"Or", {Ast::Operator::Or, 2}}, + {U"And", {Ast::Operator::And, 2}}, + {U"Or", {Ast::Operator::Or, 2}}, // 比较 - {u8"Equal", {Ast::Operator::Equal, 2}}, - {u8"NotEqual", {Ast::Operator::NotEqual, 2}}, - {u8"LessThan", {Ast::Operator::Less, 2}}, - {u8"LessEqual", {Ast::Operator::LessEqual, 2}}, - {u8"GreaterThan", {Ast::Operator::Greater, 2}}, - {u8"GreaterEqual", {Ast::Operator::GreaterEqual, 2}}, - {u8"Is", {Ast::Operator::Is, 2}}, + {U"Equal", {Ast::Operator::Equal, 2}}, + {U"NotEqual", {Ast::Operator::NotEqual, 2}}, + {U"LessThan", {Ast::Operator::Less, 2}}, + {U"LessEqual", {Ast::Operator::LessEqual, 2}}, + {U"GreaterThan", {Ast::Operator::Greater, 2}}, + {U"GreaterEqual", {Ast::Operator::GreaterEqual, 2}}, + {U"Is", {Ast::Operator::Is, 2}}, // 位运算(一元) - {u8"BitNot", {Ast::Operator::BitNot, 1}}, + {U"BitNot", {Ast::Operator::BitNot, 1}}, // 位运算(二元) - {u8"BitAnd", {Ast::Operator::BitAnd, 2}}, - {u8"BitOr", {Ast::Operator::BitOr, 2}}, - {u8"BitXor", {Ast::Operator::BitXor, 2}}, - {u8"ShiftLeft", {Ast::Operator::ShiftLeft, 2}}, - {u8"ShiftRight", {Ast::Operator::ShiftRight, 2}}, + {U"BitAnd", {Ast::Operator::BitAnd, 2}}, + {U"BitOr", {Ast::Operator::BitOr, 2}}, + {U"BitXor", {Ast::Operator::BitXor, 2}}, + {U"ShiftLeft", {Ast::Operator::ShiftLeft, 2}}, + {U"ShiftRight", {Ast::Operator::ShiftRight, 2}}, }; for (auto &implMethod : implementMethods) { - const FString &opName = implMethod.name; + const String &opName = implMethod.name; if (!magic_name_to_op.contains(opName)) { // ... 现在忽略 @@ -303,7 +303,7 @@ namespace Fig if (ctx->hasOperatorImplemented(structType, op, (expectArgCnt == 1 ? true : false))) { throw EvaluatorError( - u8"DuplicateImplementError", + U"DuplicateImplementError", std::format("{} has already implement by another interface", opName.toBasicString()), ip); } @@ -312,7 +312,7 @@ namespace Fig if (paraCnt != expectArgCnt || implMethod.paras.size() != expectArgCnt) { // 特化报错,更详细易读 - throw EvaluatorError(u8"InterfaceSignatureMismatch", + throw EvaluatorError(U"InterfaceSignatureMismatch", std::format("Operator {} for {} arg count must be {}, got {}", opName.toBasicString(), structLv.name().toBasicString(), @@ -321,10 +321,10 @@ namespace Fig ip); } - FString opFnName(u8"Operation." + prettyType(structTypeObj) + u8"." + opName); + String opFnName(U"Operation." + prettyType(structTypeObj) + U"." + opName); ContextPtr fnCtx = std::make_shared( - FString(std::format("", opFnName.toBasicString())), ctx); + String(std::format("", opFnName.toBasicString())), ctx); const auto &fillOpFnParas = [this, structType, implMethod, opFnName, fnCtx, ctx, paraCnt]( const std::vector &args) { @@ -336,7 +336,7 @@ namespace Fig if (paraType != ValueType::Any && paraType != structType) { throw EvaluatorError( - u8"ParameterTypeError", + U"ParameterTypeError", std::format("Invalid op fn parameter type '{}' of `{}`, must be `{}`", paraType.toString().toBasicString(), paras.posParas[i].first.toBasicString(), @@ -385,12 +385,12 @@ namespace Fig // ===== interface implementation validation ===== ImplRecord record{interfaceType, structType, {}}; - std::unordered_map ifaceMethods; + std::unordered_map ifaceMethods; for (auto &m : interface.methods) { if (ifaceMethods.contains(m.name)) { - throw EvaluatorError(u8"InterfaceDuplicateMethodError", + throw EvaluatorError(U"InterfaceDuplicateMethodError", std::format("Interface '{}' has duplicate method '{}'", interfaceType.toString().toBasicString(), m.name.toBasicString()), @@ -399,16 +399,16 @@ namespace Fig ifaceMethods[m.name] = m; } - std::unordered_set implemented; + std::unordered_set implemented; for (auto &implMethod : implementMethods) { - const FString &name = implMethod.name; + const String &name = implMethod.name; // ---- redundant impl ---- if (!ifaceMethods.contains(name)) { - throw EvaluatorError(u8"RedundantImplementationError", + throw EvaluatorError(U"RedundantImplementationError", std::format("Struct '{}' implements extra method '{}' " "which is not required by interface '{}'", structType.toString().toBasicString(), @@ -419,7 +419,7 @@ namespace Fig if (implemented.contains(name)) { - throw EvaluatorError(u8"DuplicateImplementMethodError", + throw EvaluatorError(U"DuplicateImplementMethodError", std::format("Duplicate implement method '{}'", name.toBasicString()), ip); } @@ -429,7 +429,7 @@ namespace Fig // ---- signature check ---- if (!isInterfaceSignatureMatch(implMethod, ifMethod)) { - throw EvaluatorError(u8"InterfaceSignatureMismatch", + throw EvaluatorError(U"InterfaceSignatureMismatch", std::format("Interface method '{}({})' signature mismatch with " "implementation '{}({})'", ifMethod.name.toBasicString(), @@ -441,7 +441,7 @@ namespace Fig if (ctx->hasMethodImplemented(structType, name)) { - throw EvaluatorError(u8"DuplicateImplementMethodError", + throw EvaluatorError(U"DuplicateImplementMethodError", std::format("Method '{}' already implemented by another interface " "for struct '{}'", name.toBasicString(), @@ -463,7 +463,7 @@ namespace Fig if (m.hasDefaultBody()) continue; - throw EvaluatorError(u8"MissingImplementationError", + throw EvaluatorError(U"MissingImplementationError", std::format("Struct '{}' does not implement required interface method '{}' " "and interface '{}' provides no default implementation", structType.toString().toBasicString(), @@ -482,7 +482,7 @@ namespace Fig if (condVal->getTypeInfo() != ValueType::Bool) { throw EvaluatorError( - u8"TypeError", + U"TypeError", std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()), ifSt->condition); } @@ -494,7 +494,7 @@ namespace Fig if (elifCondVal->getTypeInfo() != ValueType::Bool) { throw EvaluatorError( - u8"TypeError", + U"TypeError", std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()), ifSt->condition); } @@ -511,13 +511,13 @@ namespace Fig if (condVal->getTypeInfo() != ValueType::Bool) { throw EvaluatorError( - u8"TypeError", + U"TypeError", std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()), whileSt->condition); } if (!condVal->as()) { break; } ContextPtr loopContext = std::make_shared( - FString(std::format("", whileSt->getAAI().line, whileSt->getAAI().column)), + String(std::format("", whileSt->getAAI().line, whileSt->getAAI().column)), ctx); // every loop has its own context StatementResult sr = evalBlockStatement(whileSt->body, loopContext); if (sr.shouldReturn()) { return sr; } @@ -529,7 +529,7 @@ namespace Fig case ForSt: { auto forSt = std::static_pointer_cast(stmt); ContextPtr loopContext = std::make_shared( - FString(std::format("", forSt->getAAI().line, forSt->getAAI().column)), + String(std::format("", forSt->getAAI().line, forSt->getAAI().column)), ctx); // for loop has its own context evalStatement(forSt->initSt, @@ -543,14 +543,14 @@ namespace Fig if (condVal->getTypeInfo() != ValueType::Bool) { throw EvaluatorError( - u8"TypeError", + U"TypeError", std::format("Condition must be boolean, but got '{}'", prettyType(condVal).toBasicString()), forSt->condition); } if (!condVal->as()) { break; } iteration++; ContextPtr iterationContext = std::make_shared( - FString(std::format( + String(std::format( "", forSt->getAAI().line, forSt->getAAI().column, iteration)), loopContext); // every loop has its own context StatementResult sr = evalBlockStatement(forSt->body, iterationContext); @@ -571,7 +571,7 @@ namespace Fig auto tryst = std::static_pointer_cast(stmt); ContextPtr tryCtx = std::make_shared( - FString(std::format("", tryst->getAAI().line, tryst->getAAI().column)), ctx); + String(std::format("", tryst->getAAI().line, tryst->getAAI().column)), ctx); StatementResult sr = StatementResult::normal(); bool crashed = false; for (auto &stmt : tryst->body->stmts) @@ -586,13 +586,12 @@ namespace Fig bool catched = false; for (auto &cat : tryst->catches) { - const FString &errVarName = cat.errVarName; + const String &errVarName = cat.errVarName; TypeInfo errVarType = (cat.hasType ? TypeInfo(cat.errVarType) : ValueType::Any); if (isTypeMatch(errVarType, sr.result, ctx)) { ContextPtr catchCtx = std::make_shared( - FString( - std::format("", cat.body->getAAI().line, cat.body->getAAI().column)), + String(std::format("", cat.body->getAAI().line, cat.body->getAAI().column)), ctx); catchCtx->def(errVarName, errVarType, AccessModifier::Normal, sr.result); sr = evalBlockStatement(cat.body, catchCtx); @@ -602,7 +601,7 @@ namespace Fig } if (!catched && crashed) { - throw EvaluatorError(u8"UncaughtExceptionError", + throw EvaluatorError(U"UncaughtExceptionError", std::format("Uncaught exception: {}", sr.result->toString().toBasicString()), tryst); } @@ -616,7 +615,7 @@ namespace Fig ObjectPtr value = check_unwrap_stres(eval(ts->value, ctx)); if (value->is()) { - throw EvaluatorError(u8"TypeError", u8"Why did you throw a null?", ts); + throw EvaluatorError(U"TypeError", U"Why did you throw a null?", ts); } return StatementResult::errorFlow(value); } @@ -632,11 +631,11 @@ namespace Fig case BreakSt: { if (!ctx->parent) { - throw EvaluatorError(u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt); + throw EvaluatorError(U"BreakOutsideLoopError", U"`break` statement outside loop", stmt); } if (!ctx->isInLoopContext()) { - throw EvaluatorError(u8"BreakOutsideLoopError", u8"`break` statement outside loop", stmt); + throw EvaluatorError(U"BreakOutsideLoopError", U"`break` statement outside loop", stmt); } return StatementResult::breakFlow(); } @@ -644,11 +643,11 @@ namespace Fig case ContinueSt: { if (!ctx->parent) { - throw EvaluatorError(u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt); + throw EvaluatorError(U"ContinueOutsideLoopError", U"`continue` statement outside loop", stmt); } if (!ctx->isInLoopContext()) { - throw EvaluatorError(u8"ContinueOutsideLoopError", u8"`continue` statement outside loop", stmt); + throw EvaluatorError(U"ContinueOutsideLoopError", U"`continue` statement outside loop", stmt); } return StatementResult::continueFlow(); } @@ -662,13 +661,13 @@ namespace Fig auto block = std::static_pointer_cast(stmt); ContextPtr blockCtx = std::make_shared( - FString(std::format("", block->getAAI().line, block->getAAI().column)), ctx); + String(std::format("", block->getAAI().line, block->getAAI().column)), ctx); return evalBlockStatement(block, blockCtx); } default: throw RuntimeError( - FString(std::format("Feature stmt {} unsupported yet", magic_enum::enum_name(stmt->getType())))); + String(std::format("Feature stmt {} unsupported yet", magic_enum::enum_name(stmt->getType())))); } } }; // namespace Fig \ No newline at end of file diff --git a/src/Evaluator/Core/EvalTernary.cpp b/src/Evaluator/Core/EvalTernary.cpp index 732a485..b03935b 100644 --- a/src/Evaluator/Core/EvalTernary.cpp +++ b/src/Evaluator/Core/EvalTernary.cpp @@ -11,7 +11,7 @@ namespace Fig if (condVal->getTypeInfo() != ValueType::Bool) { throw EvaluatorError( - u8"TypeError", + U"TypeError", std::format("Condition must be boolean, got '{}'", prettyType(condVal).toBasicString()), te->condition); } diff --git a/src/Evaluator/Core/EvalUnary.cpp b/src/Evaluator/Core/EvalUnary.cpp index e5f8574..33622fa 100644 --- a/src/Evaluator/Core/EvalUnary.cpp +++ b/src/Evaluator/Core/EvalUnary.cpp @@ -39,7 +39,7 @@ namespace Fig return tryInvokeOverloadFn(value, [value]() { return std::make_shared(bit_not(*value)); }); } default: { - throw EvaluatorError(u8"UnsupportedOpError", + throw EvaluatorError(U"UnsupportedOpError", std::format("Unsupported op '{}' for unary expression", magic_enum::enum_name(op)), un); } diff --git a/src/Evaluator/Core/ExprResult.hpp b/src/Evaluator/Core/ExprResult.hpp index dbcc3d1..c8e9872 100644 --- a/src/Evaluator/Core/ExprResult.hpp +++ b/src/Evaluator/Core/ExprResult.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/src/Evaluator/Core/ResolveModulePath.cpp b/src/Evaluator/Core/ResolveModulePath.cpp index 12c460d..b62b691 100644 --- a/src/Evaluator/Core/ResolveModulePath.cpp +++ b/src/Evaluator/Core/ResolveModulePath.cpp @@ -6,7 +6,7 @@ namespace Fig { - std::filesystem::path Evaluator::resolveModulePath(const std::vector &pathVec) + std::filesystem::path Evaluator::resolveModulePath(const std::vector &pathVec) { namespace fs = std::filesystem; @@ -32,13 +32,13 @@ namespace Fig import comp.config; */ - const FString &modPathStrTop = pathVec.at(0); + const String &modPathStrTop = pathVec.at(0); fs::path modPath; bool found = false; for (auto &parentFolder : pathToFind) { - modPath = parentFolder / FString(modPathStrTop + u8".fig").toBasicString(); + modPath = parentFolder / String(modPathStrTop + U".fig").toBasicString(); if (fs::exists(modPath)) { path = modPath; @@ -50,16 +50,16 @@ namespace Fig modPath = parentFolder / modPathStrTop.toBasicString(); if (fs::is_directory(modPath)) // comp is a directory { - modPath = modPath / FString(modPathStrTop + u8".fig").toBasicString(); + modPath = modPath / String(modPathStrTop + U".fig").toBasicString(); /* if module name is a directory, we require [module name].fig at the directory */ if (!fs::exists(modPath)) { - throw RuntimeError(FString(std::format("requires module file, {}\\{}", - modPathStrTop.toBasicString(), - FString(modPathStrTop + u8".fig").toBasicString()))); + throw RuntimeError(String(std::format("requires module file, {}\\{}", + modPathStrTop.toBasicString(), + String(modPathStrTop + U".fig").toBasicString()))); } found = true; path = modPath; @@ -69,19 +69,19 @@ namespace Fig } if (!found) - throw RuntimeError(FString(std::format("Could not find module `{}`", modPathStrTop.toBasicString()))); + throw RuntimeError(String(std::format("Could not find module `{}`", modPathStrTop.toBasicString()))); bool found2 = false; for (size_t i = 1; i < pathVec.size(); ++i) // has next module { - const FString &next = pathVec.at(i); + const String &next = pathVec.at(i); modPath = modPath.parent_path(); // get the folder - modPath = modPath / FString(next + u8".fig").toBasicString(); + modPath = modPath / String(next + U".fig").toBasicString(); if (fs::exists(modPath)) { if (i != pathVec.size() - 1) - throw RuntimeError(FString(std::format( + throw RuntimeError(String(std::format( "expects {} as parent directory and find next module, but got a file", next.toBasicString()))); // it's the last module found2 = true; @@ -91,14 +91,14 @@ namespace Fig // `next` is a folder modPath = modPath.parent_path() / next.toBasicString(); if (!fs::exists(modPath)) - throw RuntimeError(FString(std::format("Could not find module `{}`", next.toBasicString()))); + throw RuntimeError(String(std::format("Could not find module `{}`", next.toBasicString()))); if (i == pathVec.size() - 1) { // `next` is the last module - modPath = modPath / FString(next + u8".fig").toBasicString(); + modPath = modPath / String(next + U".fig").toBasicString(); if (!fs::exists(modPath)) { - throw RuntimeError(FString(std::format( + throw RuntimeError(String(std::format( "expects {} as parent directory and find next module, but got a file", next.toBasicString()))); } found2 = true; @@ -107,8 +107,8 @@ namespace Fig } if (!found2 && !fs::exists(modPath)) - throw RuntimeError(FString(std::format("Could not find module `{}`", pathVec.end()->toBasicString()))); + throw RuntimeError(String(std::format("Could not find module `{}`", pathVec.end()->toBasicString()))); return path; } -}; \ No newline at end of file +}; // namespace Fig \ No newline at end of file diff --git a/src/Evaluator/Core/StatementResult.hpp b/src/Evaluator/Core/StatementResult.hpp index f94374f..e0ac983 100644 --- a/src/Evaluator/Core/StatementResult.hpp +++ b/src/Evaluator/Core/StatementResult.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include namespace Fig diff --git a/src/Evaluator/Value/IntPool.hpp b/src/Evaluator/Value/IntPool.hpp index 55f5fe4..7a4aef5 100644 --- a/src/Evaluator/Value/IntPool.hpp +++ b/src/Evaluator/Value/IntPool.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include diff --git a/src/Evaluator/Value/LvObject.hpp b/src/Evaluator/Value/LvObject.hpp index 002a4e6..e148da5 100644 --- a/src/Evaluator/Value/LvObject.hpp +++ b/src/Evaluator/Value/LvObject.hpp @@ -24,18 +24,15 @@ namespace Fig ContextPtr ctx; - LvObject(std::shared_ptr _slot, ContextPtr _ctx) : - slot(std::move(_slot)), ctx(_ctx) + LvObject(std::shared_ptr _slot, ContextPtr _ctx) : slot(std::move(_slot)), ctx(_ctx) { kind = Kind::Variable; } - LvObject(ObjectPtr _v, size_t _index, Kind _kind, ContextPtr _ctx) : - value(_v), numIndex(_index), ctx(_ctx) + LvObject(ObjectPtr _v, size_t _index, Kind _kind, ContextPtr _ctx) : value(_v), numIndex(_index), ctx(_ctx) { kind = _kind; } - LvObject(ObjectPtr _v, ObjectPtr _index, Kind _kind, ContextPtr _ctx) : - value(_v), mapIndex(_index), ctx(_ctx) + LvObject(ObjectPtr _v, ObjectPtr _index, Kind _kind, ContextPtr _ctx) : value(_v), mapIndex(_index), ctx(_ctx) { kind = _kind; } @@ -51,27 +48,26 @@ namespace Fig { List &list = value->as(); if (numIndex >= list.size()) - throw RuntimeError(FString( - std::format("Index {} out of range {}", numIndex, value->toString().toBasicString()))); + throw RuntimeError( + String(std::format("Index {} out of range {}", numIndex, value->toString().toBasicString()))); return list.at(numIndex).value; } else if (kind == Kind::MapElement) // map { Map &map = value->as(); if (!map.contains(mapIndex)) - throw RuntimeError(FString( - std::format("Key {} not found", mapIndex->toString().toBasicString()))); + throw RuntimeError(String(std::format("Key {} not found", mapIndex->toString().toBasicString()))); return map.at(mapIndex); } else { // string - FString &string = value->as(); + String &string = value->as(); if (numIndex >= string.length()) - throw RuntimeError(FString( - std::format("Index {} out of range {}", numIndex, value->toString().toBasicString()))); + throw RuntimeError( + String(std::format("Index {} out of range {}", numIndex, value->toString().toBasicString()))); - return std::make_shared(string.getRealChar(numIndex)); + return std::make_shared(String(string[numIndex])); } } @@ -82,26 +78,21 @@ namespace Fig auto s = resolve(slot); if (!isTypeMatch(s->declaredType, v, ctx)) { - throw RuntimeError( - FString( - std::format("Variable `{}` expects type `{}`, but got '{}'", - s->name.toBasicString(), - s->declaredType.toString().toBasicString(), - prettyType(v).toBasicString()))); + throw RuntimeError(String(std::format("Variable `{}` expects type `{}`, but got '{}'", + s->name.toBasicString(), + s->declaredType.toString().toBasicString(), + prettyType(v).toBasicString()))); } if (isAccessConst(s->am)) { - throw RuntimeError(FString( - std::format("Variable `{}` is immutable", s->name.toBasicString()))); + throw RuntimeError(String(std::format("Variable `{}` is immutable", s->name.toBasicString()))); } s->value = v; } else if (kind == Kind::ListElement) { List &list = value->as(); - if (numIndex >= list.size()) - throw RuntimeError(FString( - std::format("Index {} out of range", numIndex))); + if (numIndex >= list.size()) throw RuntimeError(String(std::format("Index {} out of range", numIndex))); list[numIndex] = v; } else if (kind == Kind::MapElement) // map @@ -111,25 +102,23 @@ namespace Fig } else if (kind == Kind::StringElement) { - FString &string = value->as(); + String &string = value->as(); if (numIndex >= string.length()) - throw RuntimeError(FString( - std::format("Index {} out of range {}", numIndex, value->toString().toBasicString()))); - + throw RuntimeError( + String(std::format("Index {} out of range {}", numIndex, value->toString().toBasicString()))); + if (v->getTypeInfo() != ValueType::String) - throw RuntimeError(FString( - std::format("Could not assign {} to sub string", v->toString().toBasicString()) - )); - const FString &strReplace = v->as(); + throw RuntimeError( + String(std::format("Could not assign {} to sub string", v->toString().toBasicString()))); + const String &strReplace = v->as(); if (strReplace.length() > 1) - throw RuntimeError(FString( - std::format("Could not assign {} to sub string, expects length 1", v->toString().toBasicString()) - )); - string.realReplace(numIndex, strReplace); + throw RuntimeError(String(std::format("Could not assign {} to sub string, expects length 1", + v->toString().toBasicString()))); + string.replace(numIndex, strReplace.length(), strReplace); } } - FString name() const { return resolve(slot)->name; } + String name() const { return resolve(slot)->name; } TypeInfo declaredType() const { return resolve(slot)->declaredType; } AccessModifier access() const { return resolve(slot)->am; } diff --git a/src/Evaluator/Value/Type.hpp b/src/Evaluator/Value/Type.hpp index ded549a..e11678c 100644 --- a/src/Evaluator/Value/Type.hpp +++ b/src/Evaluator/Value/Type.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -14,23 +14,23 @@ namespace Fig private: size_t id; - std::map &getTypeMap() + std::map &getTypeMap() { - static std::map typeMap; + static std::map typeMap; return typeMap; } public: friend class TypeInfoHash; - FString name; + String name; - FString toString() const { return name; } + String toString() const { return name; } size_t getInstanceID() const { return id; } TypeInfo(); - explicit TypeInfo(const FString &_name, bool reg = false); + explicit TypeInfo(const String &_name, bool reg = false); TypeInfo(const TypeInfo &other) = default; bool operator==(const TypeInfo &other) const { return id == other.id; } @@ -63,7 +63,7 @@ namespace Fig using DoubleClass = double; using BoolClass = bool; using NullClass = std::monostate; - using StringClass = FString; + using StringClass = Fig::String; inline bool isTypeBuiltin(const TypeInfo &type) { diff --git a/src/Evaluator/Value/VariableSlot.hpp b/src/Evaluator/Value/VariableSlot.hpp index f2080a6..a0043f9 100644 --- a/src/Evaluator/Value/VariableSlot.hpp +++ b/src/Evaluator/Value/VariableSlot.hpp @@ -1,8 +1,7 @@ #pragma once - #include -#include +#include #include #include @@ -12,7 +11,7 @@ namespace Fig struct VariableSlot { - FString name; + String name; ObjectPtr value; TypeInfo declaredType; AccessModifier am; @@ -20,4 +19,4 @@ namespace Fig bool isRef = false; std::shared_ptr refTarget; }; -} \ No newline at end of file +} // namespace Fig \ No newline at end of file diff --git a/src/Evaluator/Value/function.hpp b/src/Evaluator/Value/function.hpp index a2ff208..cd1983a 100644 --- a/src/Evaluator/Value/function.hpp +++ b/src/Evaluator/Value/function.hpp @@ -16,7 +16,7 @@ namespace Fig { public: std::size_t id; - FString name; + String name; enum FnType { @@ -53,7 +53,7 @@ namespace Fig new (&body) Ast::BlockStatement(); } - Function(const FString &_name, + Function(const String &_name, Ast::FunctionParameters _paras, TypeInfo _retType, Ast::BlockStatement _body, @@ -68,13 +68,16 @@ namespace Fig type = Normal; } - Function(const FString &_name, std::function(const std::vector> &)> fn, int argc) : + Function(const String &_name, + std::function(const std::vector> &)> fn, + int argc) : id(nextId()), name(_name), type(Builtin), builtin(fn), builtinParamCount(argc) { type = Builtin; } - Function(const FString &_name, std::function(std::shared_ptr, + Function(const String &_name, + std::function(std::shared_ptr, const std::vector> &)> fn, int argc) : id(nextId()), name(_name), type(MemberType), mtFn(fn), builtinParamCount(argc) diff --git a/src/Evaluator/Value/module.hpp b/src/Evaluator/Value/module.hpp index 5720add..824c5af 100644 --- a/src/Evaluator/Value/module.hpp +++ b/src/Evaluator/Value/module.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include @@ -8,20 +8,13 @@ namespace Fig { struct Module { - FString name; + String name; ContextPtr ctx; Module() = default; - Module(FString n, ContextPtr c) : - name(std::move(n)), - ctx(std::move(c)) - { - } + Module(String n, ContextPtr c) : name(std::move(n)), ctx(std::move(c)) {} - bool operator==(const Module &o) const noexcept - { - return name == o.name; - } + bool operator==(const Module &o) const noexcept { return name == o.name; } }; -}; \ No newline at end of file +}; // namespace Fig \ No newline at end of file diff --git a/src/Evaluator/Value/structType.hpp b/src/Evaluator/Value/structType.hpp index 35ec7eb..6729d3f 100644 --- a/src/Evaluator/Value/structType.hpp +++ b/src/Evaluator/Value/structType.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -14,21 +14,17 @@ namespace Fig struct Field { AccessModifier am; - FString name; + String name; TypeInfo type; Ast::Expression defaultValue; - Field(AccessModifier _am, FString _name, TypeInfo _type, Ast::Expression _defaultValue) : - am(_am), name(std::move(_name)), type(std::move(_type)), defaultValue(std::move(_defaultValue)) {} + Field(AccessModifier _am, String _name, TypeInfo _type, Ast::Expression _defaultValue) : + am(_am), name(std::move(_name)), type(std::move(_type)), defaultValue(std::move(_defaultValue)) + { + } - bool isPublic() const - { - return am == AccessModifier::Public || am == AccessModifier::PublicConst; - } - bool isConst() const - { - return am == AccessModifier::Const || am == AccessModifier::PublicConst; - } + bool isPublic() const { return am == AccessModifier::Public || am == AccessModifier::PublicConst; } + bool isConst() const { return am == AccessModifier::Const || am == AccessModifier::PublicConst; } }; struct StructType @@ -41,7 +37,9 @@ namespace Fig // ===== Constructors ===== StructType(TypeInfo _type, ContextPtr _defContext, std::vector _fields, bool _builtin = false) : - type(std::move(_type)), defContext(std::move(_defContext)), fields(std::move(_fields)), builtin(_builtin) {} + type(std::move(_type)), defContext(std::move(_defContext)), fields(std::move(_fields)), builtin(_builtin) + { + } StructType(const StructType &other) = default; StructType(StructType &&) noexcept = default; @@ -49,14 +47,8 @@ namespace Fig StructType &operator=(StructType &&) noexcept = default; // ===== Comparison ===== - bool operator==(const StructType &other) const noexcept - { - return type == other.type; - } - bool operator!=(const StructType &other) const noexcept - { - return !(*this == other); - } + bool operator==(const StructType &other) const noexcept { return type == other.type; } + bool operator!=(const StructType &other) const noexcept { return !(*this == other); } private: static std::size_t nextId() @@ -72,9 +64,6 @@ namespace std template <> struct hash { - size_t operator()(const Fig::Field &f) - { - return std::hash{}(f.name); - } + size_t operator()(const Fig::Field &f) { return std::hash{}(f.name); } }; }; // namespace std \ No newline at end of file diff --git a/src/Evaluator/Value/value.cpp b/src/Evaluator/Value/value.cpp index 71ef674..728144d 100644 --- a/src/Evaluator/Value/value.cpp +++ b/src/Evaluator/Value/value.cpp @@ -11,10 +11,10 @@ namespace Fig { TypeInfo::TypeInfo() : // only allow use in evaluate time !! <---- dynamic type system requirement - id(1), name(FString(u8"Any")) + id(1), name(String(U"Any")) { } - TypeInfo::TypeInfo(const FString &_name, bool reg) + TypeInfo::TypeInfo(const String &_name, bool reg) { static size_t id_count = 0; name = _name; @@ -28,7 +28,7 @@ namespace Fig { if (!getTypeMap().contains(_name)) { - throw RuntimeError(FString(std::format("No type named '{}'", _name.toBasicString()))); + throw RuntimeError(String(std::format("No type named '{}'", _name.toBasicString()))); // *this = ValueType::String; } id = getTypeMap().at(name); // may throw @@ -93,25 +93,29 @@ namespace Fig if (t == ValueType::StructInstance) return obj->as().parentType; return t; } - FString prettyType(std::shared_ptr obj) + String prettyType(std::shared_ptr obj) { return actualType(obj).toString(); } - const TypeInfo ValueType::Any(FString(u8"Any"), true); // id: 1 - const TypeInfo ValueType::Null(FString(u8"Null"), true); // id: 2 - const TypeInfo ValueType::Int(FString(u8"Int"), true); // id: 3 - const TypeInfo ValueType::String(FString(u8"String"), true); // id: 4 - const TypeInfo ValueType::Bool(FString(u8"Bool"), true); // id: 5 - const TypeInfo ValueType::Double(FString(u8"Double"), true); // id: 6 - const TypeInfo ValueType::Function(FString(u8"Function"), true); // id: 7 - const TypeInfo ValueType::StructType(FString(u8"StructType"), true); // id: 8 - const TypeInfo ValueType::StructInstance(FString(u8"StructInstance"), true); // id: 9 - const TypeInfo ValueType::List(FString(u8"List"), true); // id: 10 - const TypeInfo ValueType::Map(FString(u8"Map"), true); // id: 11 - const TypeInfo ValueType::Module(FString(u8"Module"), true); // id: 12 - const TypeInfo ValueType::InterfaceType(FString(u8"InterfaceType"), true); // id: 13 + const TypeInfo ValueType::Any(U"Any", true); // id: 1 + const TypeInfo ValueType::Null(U"Null", true); // id: 2 + const TypeInfo ValueType::Int(U"Int", true); // id: 3 + const TypeInfo ValueType::String(U"String", true); // id: 4 + const TypeInfo ValueType::Bool(U"Bool", true); // id: 5 + const TypeInfo ValueType::Double(U"Double", true); // id: 6 + const TypeInfo ValueType::Function(U"Function", true); // id: 7 + const TypeInfo ValueType::StructType(U"StructType", true); // id: 8 + const TypeInfo ValueType::StructInstance(U"StructInstance", true); // id: 9 + const TypeInfo ValueType::List(U"List", true); // id: 10 + const TypeInfo ValueType::Map(U"Map", true); // id: 11 + const TypeInfo ValueType::Module(U"Module", true); // id: 12 + const TypeInfo ValueType::InterfaceType(U"InterfaceType", true); // id: 13 + namespace ValueType + { + + }; bool implements(const TypeInfo &structType, const TypeInfo &interfaceType, ContextPtr ctx) { return ctx->hasImplRegisted(structType, interfaceType); diff --git a/src/Evaluator/Value/value.hpp b/src/Evaluator/Value/value.hpp index 0258d7b..ccf1d57 100644 --- a/src/Evaluator/Value/value.hpp +++ b/src/Evaluator/Value/value.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include #include @@ -43,7 +43,7 @@ namespace Fig } TypeInfo actualType(std::shared_ptr obj); - FString prettyType(std::shared_ptr obj); + String prettyType(std::shared_ptr obj); bool operator==(const Object &, const Object &); @@ -93,89 +93,92 @@ namespace Fig Module, InterfaceType>; - static std::unordered_map, TypeInfoHash> + static std::unordered_map, TypeInfoHash> getMemberTypeFunctions() { - static const std::unordered_map, TypeInfoHash> + static const std::unordered_map, TypeInfoHash> memberTypeFunctions{ {ValueType::Null, {}}, {ValueType::Int, {}}, {ValueType::Double, {}}, {ValueType::String, { - {u8"length", + {U"length", [](ObjectPtr object, std::vector args) -> ObjectPtr { if (args.size() != 0) throw RuntimeError( - FString(std::format("`length` expects 0 arguments, {} got", args.size()))); - const FString &str = object->as(); + String(std::format("`length` expects 0 arguments, {} got", args.size()))); + const String &str = object->as(); return std::make_shared(static_cast(str.length())); }}, - {u8"replace", + {U"replace", [](ObjectPtr object, std::vector args) -> ObjectPtr { if (args.size() != 2) throw RuntimeError( - FString(std::format("`replace` expects 2 arguments, {} got", args.size()))); - FString &str = object->as(); + String(std::format("`replace` expects 2 arguments, {} got", args.size()))); + String &str = object->as(); ObjectPtr arg1 = args[0]; ObjectPtr arg2 = args[1]; if (!arg1->is()) { - throw RuntimeError(FString("`replace` arg 1 expects type Int")); + throw RuntimeError(String("`replace` arg 1 expects type Int")); } if (!arg2->is()) { - throw RuntimeError(FString("`replace` arg 2 expects type String")); + throw RuntimeError(String("`replace` arg 2 expects type String")); } - str.realReplace(arg1->as(), arg2->as()); + const String &target = arg2->as(); + str.replace(arg1->as(), target.length(), target); return Object::getNullInstance(); }}, - {u8"erase", + {U"erase", [](ObjectPtr object, std::vector args) -> ObjectPtr { if (args.size() != 2) throw RuntimeError( - FString(std::format("`erase` expects 2 arguments, {} got", args.size()))); - FString &str = object->as(); + String(std::format("`erase` expects 2 arguments, {} got", args.size()))); + String &str = object->as(); ObjectPtr arg1 = args[0]; ObjectPtr arg2 = args[1]; if (!arg1->is()) { - throw RuntimeError(FString("`erase` arg 1 expects type Int")); + throw RuntimeError(String("`erase` arg 1 expects type Int")); } if (!arg2->is()) { - 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 n = arg2->as(); if (index < 0 || n < 0) { - throw RuntimeError(FString("`erase`: index and n must greater or equal to 0")); + throw RuntimeError(String("`erase`: index and n must greater or equal to 0")); } if (index + n > str.length()) { - throw RuntimeError(FString("`erase`: length is not long enough to erase")); + throw RuntimeError(String("`erase`: length is not long enough to erase")); } - str.realErase(arg1->as(), arg2->as()); + str.erase(arg1->as(), arg2->as()); return Object::getNullInstance(); }}, - {u8"insert", + {U"insert", [](ObjectPtr object, std::vector args) -> ObjectPtr { if (args.size() != 2) throw RuntimeError( - FString(std::format("`insert` expects 2 arguments, {} got", args.size()))); - FString &str = object->as(); + String(std::format("`insert` expects 2 arguments, {} got", args.size()))); + String &str = object->as(); ObjectPtr arg1 = args[0]; ObjectPtr arg2 = args[1]; if (!arg1->is()) { - throw RuntimeError(FString("`insert` arg 1 expects type Int")); + throw RuntimeError(String("`insert` arg 1 expects type Int")); } if (!arg2->is()) { - throw RuntimeError(FString("`insert` arg 2 expects type String")); + throw RuntimeError(String("`insert` arg 2 expects type String")); } - str.realInsert(arg1->as(), arg2->as()); + ValueType::IntClass dest = arg1->as(); + const String &src = arg2->as(); + str.insert(dest, src); return Object::getNullInstance(); }}, }}, @@ -184,34 +187,34 @@ namespace Fig {ValueType::StructInstance, {}}, {ValueType::List, { - {u8"length", + {U"length", [](ObjectPtr object, std::vector args) -> ObjectPtr { if (args.size() != 0) throw RuntimeError( - FString(std::format("`length` expects 0 arguments, {} got", args.size()))); + String(std::format("`length` expects 0 arguments, {} got", args.size()))); const List &list = object->as(); return std::make_shared(static_cast(list.size())); }}, - {u8"get", + {U"get", [](ObjectPtr object, std::vector args) -> ObjectPtr { if (args.size() != 1) throw RuntimeError( - FString(std::format("`get` expects 1 arguments, {} got", args.size()))); + String(std::format("`get` expects 1 arguments, {} got", args.size()))); ObjectPtr arg = args[0]; if (arg->getTypeInfo() != ValueType::Int) throw RuntimeError( - FString(std::format("`get` argument 1 expects Int, {} got", - arg->getTypeInfo().toString().toBasicString()))); + String(std::format("`get` argument 1 expects Int, {} got", + arg->getTypeInfo().toString().toBasicString()))); ValueType::IntClass i = arg->as(); const List &list = object->as(); if (i >= list.size()) return Object::getNullInstance(); return list[i].value; }}, - {u8"push", + {U"push", [](ObjectPtr object, std::vector args) -> ObjectPtr { if (args.size() != 1) throw RuntimeError( - FString(std::format("`push` expects 1 arguments, {} got", args.size()))); + String(std::format("`push` expects 1 arguments, {} got", args.size()))); ObjectPtr arg = args[0]; List &list = object->as(); list.push_back(arg); @@ -220,21 +223,21 @@ namespace Fig }}, {ValueType::Map, { - {u8"get", + {U"get", [](ObjectPtr object, std::vector args) -> ObjectPtr { if (args.size() != 1) throw RuntimeError( - FString(std::format("`get` expects 1 arguments, {} got", args.size()))); + String(std::format("`get` expects 1 arguments, {} got", args.size()))); ObjectPtr index = args[0]; const Map &map = object->as(); if (!map.contains(index)) return Object::getNullInstance(); return map.at(index); }}, - {u8"contains", + {U"contains", [](ObjectPtr object, std::vector args) -> ObjectPtr { if (args.size() != 1) throw RuntimeError( - FString(std::format("`contains` expects 1 arguments, {} got", args.size()))); + String(std::format("`contains` expects 1 arguments, {} got", args.size()))); ObjectPtr index = args[0]; const Map &map = object->as(); return std::make_shared(map.contains(index)); @@ -246,29 +249,28 @@ namespace Fig return memberTypeFunctions; } - static std::unordered_map, TypeInfoHash> - getMemberTypeFunctionsParas() + static std::unordered_map, TypeInfoHash> getMemberTypeFunctionsParas() { - static const std::unordered_map, TypeInfoHash> + static const std::unordered_map, TypeInfoHash> memberTypeFunctionsParas{ {ValueType::Null, {}}, {ValueType::Int, {}}, {ValueType::Double, {}}, {ValueType::String, { - {u8"length", 0}, - {u8"replace", 2}, - {u8"erase", 2}, - {u8"insert", 2}, + {U"length", 0}, + {U"replace", 2}, + {U"erase", 2}, + {U"insert", 2}, }}, {ValueType::Function, {}}, {ValueType::StructType, {}}, {ValueType::StructInstance, {}}, - {ValueType::List, {{u8"length", 0}, {u8"get", 1}, {u8"push", 1}}}, + {ValueType::List, {{U"length", 0}, {U"get", 1}, {U"push", 1}}}, {ValueType::Map, { - {u8"get", 1}, - {u8"contains", 1}, + {U"get", 1}, + {U"contains", 1}, }}, {ValueType::Module, {}}, {ValueType::InterfaceType, {}}, @@ -276,15 +278,15 @@ namespace Fig return memberTypeFunctionsParas; } - bool hasMemberFunction(const FString &name) const + bool hasMemberFunction(const String &name) const { return getMemberTypeFunctions().at(getTypeInfo()).contains(name); } - BuiltinTypeMemberFn getMemberFunction(const FString &name) const + BuiltinTypeMemberFn getMemberFunction(const String &name) const { return getMemberTypeFunctions().at(getTypeInfo()).at(name); } - int getMemberFunctionParaCount(const FString &name) const + int getMemberFunctionParaCount(const String &name) const { return getMemberTypeFunctionsParas().at(getTypeInfo()).at(name); } @@ -317,7 +319,7 @@ namespace Fig else if (ti == ValueType::Double) return Object(ValueType::DoubleClass(0.0)); else if (ti == ValueType::String) - return Object(ValueType::StringClass(u8"")); + return Object(ValueType::StringClass(U"")); else if (ti == ValueType::Bool) return Object(ValueType::BoolClass(false)); else if (ti == ValueType::List) @@ -420,83 +422,83 @@ namespace Fig else if (is()) return as(); 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()) return as(); return toString(); } - FString toString(std::unordered_set &visited) const + String toString(std::unordered_set &visited) const { - if (is()) return FString(u8"null"); - if (is()) return FString(std::to_string(as())); - if (is()) return FString(std::format("{}", as())); - if (is()) return FString(u8"\"" + as() + u8"\""); - if (is()) return as() ? FString(u8"true") : FString(u8"false"); + if (is()) return String(U"null"); + if (is()) return String(std::to_string(as())); + if (is()) return String(std::format("{}", as())); + if (is()) return String(String(U"\"") + as() + String(U"\"")); + if (is()) return as() ? String(U"true") : String(U"false"); if (is()) - return FString(std::format( + return String(std::format( "", as().id, static_cast(&as()))); if (is()) - return FString(std::format("", - as().type.toString().toBasicString(), - static_cast(&as()))); + return String(std::format("", + as().type.toString().toBasicString(), + static_cast(&as()))); if (is()) - return FString(std::format("", - as().parentType.toString().toBasicString(), - static_cast(&as()))); + return String(std::format("", + as().parentType.toString().toBasicString(), + static_cast(&as()))); if (is()) { - if (visited.contains(this)) { return u8"[...]"; } + if (visited.contains(this)) { return U"[...]"; } visited.insert(this); - FString output(u8"["); + String output(U"["); const List &list = as(); bool first_flag = true; for (auto &ele : list) { - if (!first_flag) output += u8", "; + if (!first_flag) output += U", "; output += ele.value->toString(visited); first_flag = false; } - output += u8"]"; + output += U"]"; return output; } if (is()) { - if (visited.contains(this)) { return u8"{...}"; } + if (visited.contains(this)) { return U"{...}"; } visited.insert(this); - FString output(u8"{"); + String output(U"{"); const Map &map = as(); bool first_flag = true; for (auto &[key, value] : map) { - if (!first_flag) output += u8", "; - output += key.value->toString(visited) + FString(u8" : ") + value->toString(visited); + if (!first_flag) output += U", "; + output += key.value->toString(visited) + String(U" : ") + value->toString(visited); first_flag = false; } - output += u8"}"; + output += U"}"; return output; } if (is()) { - return FString(std::format("", - as().name.toBasicString(), - static_cast(&as()))); + return String(std::format("", + as().name.toBasicString(), + static_cast(&as()))); } if (is()) { - return FString(std::format("", - as().type.toString().toBasicString(), - static_cast(&as()))); + return String(std::format("", + as().type.toString().toBasicString(), + static_cast(&as()))); } - return FString(u8""); + return String(U""); } - FString toString() const + String toString() const { std::unordered_set visited{}; return toString(visited); @@ -516,7 +518,7 @@ namespace Fig friend Object operator+(const Object &lhs, const Object &rhs) { if (lhs.isNull() || rhs.isNull()) - throw ValueError(FString(makeTypeErrorMessage("Cannot add", "+", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Cannot add", "+", lhs, rhs))); if (lhs.isNumeric() && rhs.isNumeric()) { bool bothInt = lhs.is() && rhs.is(); @@ -525,14 +527,14 @@ namespace Fig return Object(result); } if (lhs.is() && rhs.is()) - return Object(FString(lhs.as() + rhs.as())); - throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "+", lhs, rhs))); + return Object(String(lhs.as() + rhs.as())); + throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "+", lhs, rhs))); } friend Object operator-(const Object &lhs, const Object &rhs) { if (lhs.isNull() || rhs.isNull()) - throw ValueError(FString(makeTypeErrorMessage("Cannot subtract", "-", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Cannot subtract", "-", lhs, rhs))); if (lhs.isNumeric() && rhs.isNumeric()) { bool bothInt = lhs.is() && rhs.is(); @@ -540,13 +542,13 @@ namespace Fig if (bothInt) return Object(static_cast(result)); return Object(result); } - throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "-", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "-", lhs, rhs))); } friend Object operator*(const Object &lhs, const Object &rhs) { if (lhs.isNull() || rhs.isNull()) - throw ValueError(FString(makeTypeErrorMessage("Cannot multiply", "*", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Cannot multiply", "*", lhs, rhs))); if (lhs.isNumeric() && rhs.isNumeric()) { bool bothInt = lhs.is() && rhs.is(); @@ -556,22 +558,22 @@ namespace Fig } if (lhs.is() && rhs.is()) { - FString result; - const FString &l = lhs.as(); + String result; + const String &l = lhs.as(); for (size_t i = 0; i < rhs.getNumericValue(); ++i) { result += l; } return Object(result); } - throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "*", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "*", lhs, rhs))); } friend Object operator/(const Object &lhs, const Object &rhs) { if (lhs.isNull() || rhs.isNull()) - throw ValueError(FString(makeTypeErrorMessage("Cannot divide", "/", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Cannot divide", "/", lhs, rhs))); if (lhs.isNumeric() && rhs.isNumeric()) { auto rnv = rhs.getNumericValue(); - if (rnv == 0) throw ValueError(FString(makeTypeErrorMessage("Division by zero", "/", lhs, rhs))); + if (rnv == 0) throw ValueError(String(makeTypeErrorMessage("Division by zero", "/", lhs, rhs))); // bool bothInt = lhs.is() && rhs.is(); auto result = lhs.getNumericValue() / rnv; // if (bothInt) @@ -581,18 +583,18 @@ namespace Fig // DO NOT convert it to INT return Object(result); } - throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "/", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "/", lhs, rhs))); } friend Object operator%(const Object &lhs, const Object &rhs) { if (lhs.isNull() || rhs.isNull()) - throw ValueError(FString(makeTypeErrorMessage("Cannot modulo", "%", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Cannot modulo", "%", lhs, rhs))); if (lhs.is() && rhs.is()) { ValueType::IntClass lv = lhs.as(); ValueType::IntClass rv = lhs.as(); - if (rv == 0) throw ValueError(FString(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs))); + if (rv == 0) throw ValueError(String(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs))); ValueType::IntClass q = lv / rv; ValueType::IntClass r = lv % rv; @@ -603,25 +605,25 @@ namespace Fig if (lhs.isNumeric() && rhs.isNumeric()) { auto rnv = rhs.getNumericValue(); - if (rnv == 0) throw ValueError(FString(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs))); + if (rnv == 0) throw ValueError(String(makeTypeErrorMessage("Modulo by zero", "/", lhs, rhs))); auto result = std::fmod(lhs.getNumericValue(), rnv); return Object(result); } - throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "%", lhs, rhs))); } // logic friend Object operator&&(const Object &lhs, const Object &rhs) { if (!lhs.is() || !rhs.is()) - throw ValueError(FString(makeTypeErrorMessage("Logical AND requires bool", "&&", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Logical AND requires bool", "&&", lhs, rhs))); return Object(lhs.as() && rhs.as()); } friend Object operator||(const Object &lhs, const Object &rhs) { if (!lhs.is() || !rhs.is()) - throw ValueError(FString(makeTypeErrorMessage("Logical OR requires bool", "||", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Logical OR requires bool", "||", lhs, rhs))); return Object(lhs.as() || rhs.as()); } @@ -629,34 +631,35 @@ namespace Fig { if (!v.is()) 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()); } 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()) return Object(-v.as()); if (v.is()) return Object(-v.as()); throw ValueError( - FString(std::format("Unary minus requires int or double: '{}'", v.getTypeInfo().name.toBasicString()))); + String(std::format("Unary minus requires int or double: '{}'", v.getTypeInfo().name.toBasicString()))); } friend Object operator~(const Object &v) { if (!v.is()) 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()); } // comparison - friend bool operator==(const Object &lhs, const Object &rhs) { + friend bool operator==(const Object &lhs, const Object &rhs) + { if (lhs.isNumeric() && rhs.isNumeric()) { return nearlyEqual(lhs.getNumericValue(), rhs.getNumericValue()); } - return lhs.data == rhs.data; + return lhs.data == rhs.data; } friend bool operator!=(const Object &lhs, const Object &rhs) { return !(lhs == rhs); } friend bool operator<(const Object &lhs, const Object &rhs) @@ -664,7 +667,7 @@ namespace Fig if (lhs.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() < rhs.getNumericValue(); if (lhs.is() && rhs.is()) return lhs.as() < rhs.as(); - throw ValueError(FString(makeTypeErrorMessage("Unsupported comparison", "<", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Unsupported comparison", "<", lhs, rhs))); } friend bool operator<=(const Object &lhs, const Object &rhs) { return lhs == rhs || lhs < rhs; } friend bool operator>(const Object &lhs, const Object &rhs) @@ -672,7 +675,7 @@ namespace Fig if (lhs.isNumeric() && rhs.isNumeric()) return lhs.getNumericValue() > rhs.getNumericValue(); if (lhs.is() && rhs.is()) return lhs.as() > rhs.as(); - throw ValueError(FString(makeTypeErrorMessage("Unsupported comparison", ">", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Unsupported comparison", ">", lhs, rhs))); } friend bool operator>=(const Object &lhs, const Object &rhs) { return lhs == rhs || lhs > rhs; } @@ -680,21 +683,21 @@ namespace Fig friend Object bit_and(const Object &lhs, const Object &rhs) { if (!lhs.is() || !rhs.is()) - throw ValueError(FString(makeTypeErrorMessage("Bitwise AND requires int", "&", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Bitwise AND requires int", "&", lhs, rhs))); return Object(lhs.as() & rhs.as()); } friend Object bit_or(const Object &lhs, const Object &rhs) { if (!lhs.is() || !rhs.is()) - throw ValueError(FString(makeTypeErrorMessage("Bitwise OR requires int", "|", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Bitwise OR requires int", "|", lhs, rhs))); return Object(lhs.as() | rhs.as()); } friend Object bit_xor(const Object &lhs, const Object &rhs) { if (!lhs.is() || !rhs.is()) - throw ValueError(FString(makeTypeErrorMessage("Bitwise XOR requires int", "^", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Bitwise XOR requires int", "^", lhs, rhs))); return Object(lhs.as() ^ rhs.as()); } @@ -702,28 +705,28 @@ namespace Fig { if (!v.is()) 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()); } friend Object shift_left(const Object &lhs, const Object &rhs) { if (!lhs.is() || !rhs.is()) - throw ValueError(FString(makeTypeErrorMessage("Shift left requires int", "<<", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Shift left requires int", "<<", lhs, rhs))); return Object(lhs.as() << rhs.as()); } friend Object shift_right(const Object &lhs, const Object &rhs) { if (!lhs.is() || !rhs.is()) - throw ValueError(FString(makeTypeErrorMessage("Shift right requires int", ">>", lhs, rhs))); + throw ValueError(String(makeTypeErrorMessage("Shift right requires int", ">>", lhs, rhs))); return Object(lhs.as() >> rhs.as()); } friend Object power(const Object &base, const Object &exp) { if (base.isNull() || exp.isNull()) - throw ValueError(FString(makeTypeErrorMessage("Cannot exponentiate", "**", base, exp))); + throw ValueError(String(makeTypeErrorMessage("Cannot exponentiate", "**", base, exp))); if (base.isNumeric() && exp.isNumeric()) { bool bothInt = base.is() && exp.is(); @@ -731,7 +734,7 @@ namespace Fig if (bothInt) return Object(static_cast(result)); return Object(result); } - throw ValueError(FString(makeTypeErrorMessage("Unsupported operation", "**", base, exp))); + throw ValueError(String(makeTypeErrorMessage("Unsupported operation", "**", base, exp))); } }; diff --git a/src/Evaluator/Value/valueError.hpp b/src/Evaluator/Value/valueError.hpp index ccbba06..4788123 100644 --- a/src/Evaluator/Value/valueError.hpp +++ b/src/Evaluator/Value/valueError.hpp @@ -8,10 +8,13 @@ namespace Fig { public: using UnaddressableError::UnaddressableError; - virtual FString toString() const override + virtual String toString() const override { - std::string msg = std::format("[ValueError] {} in [{}] {}", std::string(this->message.begin(), this->message.end()), this->src_loc.file_name(), this->src_loc.function_name()); - return FString(msg); + std::string msg = std::format("[ValueError] {} in [{}] {}", + std::string(this->message.begin(), this->message.end()), + this->src_loc.file_name(), + this->src_loc.function_name()); + return String(msg); } }; -}; \ No newline at end of file +}; // namespace Fig \ No newline at end of file diff --git a/src/Evaluator/evaluator.cpp b/src/Evaluator/evaluator.cpp index 9e4f2b9..d3344a9 100644 --- a/src/Evaluator/evaluator.cpp +++ b/src/Evaluator/evaluator.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include @@ -50,16 +50,16 @@ namespace Fig ContextPtr Evaluator::loadModule(const std::filesystem::path &path) { - static std::unordered_map, std::vector>> mod_ast_cache{}; + static std::unordered_map, std::vector>> mod_ast_cache{}; - FString modSourcePath(path.string()); + String modSourcePath(path.string()); std::ifstream file(path); assert(file.is_open()); std::vector asts; - std::vector modSourceLines; + std::vector modSourceLines; if (mod_ast_cache.contains(modSourcePath)) { @@ -72,9 +72,9 @@ namespace Fig std::string source((std::istreambuf_iterator(file)), std::istreambuf_iterator()); file.close(); - modSourceLines = Utils::splitSource(FString(source)); + modSourceLines = Utils::splitSource(String(source)); - Lexer lexer((FString(source)), modSourcePath, modSourceLines); + Lexer lexer((String(source)), modSourcePath, modSourceLines); Parser parser(lexer, modSourcePath, modSourceLines); asts = parser.parseAll(); @@ -85,7 +85,7 @@ namespace Fig evaluator.SetSourcePath(modSourcePath); evaluator.SetSourceLines(modSourceLines); - ContextPtr modctx = std::make_shared(FString(std::format("", path.string())), nullptr); + ContextPtr modctx = std::make_shared(String(std::format("", path.string())), nullptr); evaluator.SetGlobalContext(modctx); evaluator.RegisterBuiltinsValue(); @@ -96,10 +96,10 @@ namespace Fig StatementResult Evaluator::evalImportSt(Ast::Import i, ContextPtr ctx) { - const std::vector &pathVec = i->path; + const std::vector &pathVec = i->path; - FString modName = pathVec.back(); // pathVec at least has 1 element - if (modName == u8"_builtins") + String modName = pathVec.back(); // pathVec at least has 1 element + if (modName == U"\1") { RegisterBuiltins(); return StatementResult::normal(); @@ -109,8 +109,7 @@ namespace Fig if (ctx->containsInThisScope(modName)) { - throw EvaluatorError( - u8"RedeclarationError", std::format("{} has already been declared.", modName.toBasicString()), i); + throw EvaluatorError(U"\1", std::format("{} has already been declared.", modName.toBasicString()), i); } auto path = resolveModulePath(pathVec); @@ -124,7 +123,7 @@ namespace Fig if (ctx->getOpRegistry().contains(type)) { throw EvaluatorError( - u8"DuplicateOperationOverload", + U"\1", std::format("Module `{}` and current context `{}` have conflict operation overload for `{}` object", modCtx->getScopeName().toBasicString(), ctx->getScopeName().toBasicString(), @@ -135,7 +134,7 @@ namespace Fig } if (!i->names.empty()) { - for (const FString &symName : i->names) + for (const String &symName : i->names) { LvObject tmp(modCtx->get(symName), modCtx); const ObjectPtr &value = tmp.get(); @@ -183,13 +182,13 @@ namespace Fig */ const StructInstance &resInst = result->as(); - Function getErrorClassFn = ctx->getImplementedMethod(resultType, u8"getErrorClass"); + Function getErrorClassFn = ctx->getImplementedMethod(resultType, U"\1"); getErrorClassFn = Function(getErrorClassFn.name, getErrorClassFn.paras, getErrorClassFn.retType, getErrorClassFn.body, resInst.localContext); - Function getErrorMessageFn = ctx->getImplementedMethod(resultType, u8"getErrorMessage"); + Function getErrorMessageFn = ctx->getImplementedMethod(resultType, U"\1"); getErrorMessageFn = Function(getErrorMessageFn.name, getErrorMessageFn.paras, getErrorMessageFn.retType, @@ -210,17 +209,16 @@ namespace Fig // std::cerr << errorClassRes.unwrap()->toString().toBasicString() << "\n"; // std::cerr << errorMessageRes.unwrap()->toString().toBasicString() << "\n"; - const FString &errorClass = errorClassRes.unwrap()->as(); - const FString &errorMessage = errorMessageRes.unwrap()->as(); + const String &errorClass = errorClassRes.unwrap()->as(); + const String &errorMessage = errorMessageRes.unwrap()->as(); ErrorLog::logFigErrorInterface(errorClass, errorMessage); std::exit(1); } else { - throw EvaluatorError(u8"UncaughtExceptionError", - std::format("Uncaught exception: {}", sr.result->toString().toBasicString()), - stmt); + throw EvaluatorError( + U"\1", std::format("Uncaught exception: {}", sr.result->toString().toBasicString()), stmt); } } diff --git a/src/Evaluator/evaluator.hpp b/src/Evaluator/evaluator.hpp index c141aa9..e4c6e28 100644 --- a/src/Evaluator/evaluator.hpp +++ b/src/Evaluator/evaluator.hpp @@ -34,12 +34,12 @@ namespace Fig ContextPtr global; public: - FString sourcePath; - std::vector sourceLines; + String sourcePath; + std::vector sourceLines; - void SetSourcePath(const FString &sp) { sourcePath = sp; } + void SetSourcePath(const String &sp) { sourcePath = sp; } - void SetSourceLines(const std::vector &sl) { sourceLines = sl; } + void SetSourceLines(const std::vector &sl) { sourceLines = sl; } void SetGlobalContext(ContextPtr ctx) { @@ -47,7 +47,7 @@ namespace Fig global = ctx; } - void CreateGlobalContext() { global = std::make_shared(FString(u8"")); } + void CreateGlobalContext() { global = std::make_shared(String(U"\1")); } void RegisterBuiltins() // only function { @@ -67,33 +67,31 @@ namespace Fig .interfaceType = Builtins::getErrorInterfaceTypeInfo(), .structType = Builtins::getTypeErrorStructTypeInfo(), .implMethods = { - {u8"toString", - Function( - u8"toString", - Ast::FunctionParameters{}, - ValueType::String, - std::make_shared(std::vector( - {std::make_shared(std::make_shared( - std::make_shared(std::make_shared(u8"TypeError: ")), - Ast::Operator::Add, - std::make_shared( - std::make_shared(u8"getErrorMessage"), - Ast::FunctionArguments{})))})), - nullptr)}, - {u8"getErrorClass", - Function(u8"getErrorClass", + {U"\1", + Function(U"\1", + Ast::FunctionParameters{}, + ValueType::String, + std::make_shared(std::vector( + {std::make_shared(std::make_shared( + std::make_shared(std::make_shared(U"\1")), + Ast::Operator::Add, + std::make_shared( + std::make_shared(U"\1"), Ast::FunctionArguments{})))})), + nullptr)}, + {U"\1", + Function(U"\1", Ast::FunctionParameters{}, ValueType::String, std::make_shared(std::vector( {std::make_shared(std::make_shared( - std::make_shared(FString(u8"TypeError"))))})), + std::make_shared(String(U"\1"))))})), nullptr)}, - {u8"getErrorMessage", - Function(u8"getErrorMessage", + {U"\1", + Function(U"\1", Ast::FunctionParameters{}, ValueType::String, std::make_shared(std::vector( - {std::make_shared(std::make_shared(u8"msg"))})), + {std::make_shared(std::make_shared(U"\1"))})), nullptr)}, }}); } @@ -110,13 +108,13 @@ namespace Fig bool isInterfaceSignatureMatch(const Ast::ImplementMethod &, const Ast::InterfaceMethod &); - ObjectPtr genTypeError(const FString &_msg, + ObjectPtr genTypeError(const String &_msg, const Ast::AstBase &_ast, ContextPtr ctx, std::source_location loc = std::source_location::current()) { - ContextPtr stCtx = std::make_shared(u8""); - stCtx->def(u8"msg", ValueType::String, AccessModifier::Const, std::make_shared(_msg)); + ContextPtr stCtx = std::make_shared(U"\1"); + stCtx->def(U"\1", ValueType::String, AccessModifier::Const, std::make_shared(_msg)); return std::make_shared(StructInstance(Builtins::getTypeErrorStructTypeInfo(), stCtx)); } @@ -143,7 +141,7 @@ namespace Fig StatementResult evalBlockStatement(Ast::BlockStatement, ContextPtr); // block StatementResult evalStatement(Ast::Statement, ContextPtr); // statement - std::filesystem::path resolveModulePath(const std::vector &); + std::filesystem::path resolveModulePath(const std::vector &); ContextPtr loadModule(const std::filesystem::path &); StatementResult evalImportSt(Ast::Import, ContextPtr); diff --git a/src/Evaluator/evaluator_error.hpp b/src/Evaluator/evaluator_error.hpp index 11163b6..3e491ab 100644 --- a/src/Evaluator/evaluator_error.hpp +++ b/src/Evaluator/evaluator_error.hpp @@ -8,16 +8,15 @@ namespace Fig class EvaluatorError final : public AddressableError { public: - FString typeName; + String typeName; using AddressableError::AddressableError; - EvaluatorError(FString _typeName, - FString msg, + EvaluatorError(String _typeName, + String msg, Ast::AstBase ast, std::source_location loc = std::source_location::current()) { message = msg; - src_loc = std::move(loc); typeName = std::move(_typeName); @@ -29,25 +28,24 @@ namespace Fig sourcePath = *ast->getAAI().sourcePath; sourceLines = *ast->getAAI().sourceLines; } - } - EvaluatorError(FString _typeName, - std::string_view msg, - Ast::AstBase ast, - std::source_location loc = std::source_location::current()) - { - message = FString::fromBasicString(std::string(msg.data())); - line = ast->getAAI().line; - column = ast->getAAI().column; + // EvaluatorError(String _typeName, + // std::string_view msg, + // Ast::AstBase ast, + // std::source_location loc = std::source_location::current()) + // { + // message = String(std::string(msg.data())); + // line = ast->getAAI().line; + // column = ast->getAAI().column; - src_loc = std::move(loc); + // src_loc = std::move(loc); - typeName = std::move(_typeName); + // typeName = std::move(_typeName); - sourcePath = *ast->getAAI().sourcePath; - sourceLines = *ast->getAAI().sourceLines; - } + // sourcePath = *ast->getAAI().sourcePath; + // sourceLines = *ast->getAAI().sourceLines; + // } - virtual FString getErrorType() const override { return typeName; } + virtual String getErrorType() const override { return typeName; } }; }; // namespace Fig \ No newline at end of file diff --git a/src/IR/IR.hpp b/src/IR/IR.hpp index c0bc9f4..adbd329 100644 --- a/src/IR/IR.hpp +++ b/src/IR/IR.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -51,12 +51,12 @@ namespace Fig::IR struct Function { - FString name; + String name; uint16_t paramCount; uint16_t localCount; // 不含参数 - uint16_t regCount; // param + locals + temps + uint16_t regCount; // param + locals + temps std::vector code; }; -}; \ No newline at end of file +}; // namespace Fig::IR \ No newline at end of file diff --git a/src/Lexer/lexer.cpp b/src/Lexer/lexer.cpp index 0b95eab..55fa652 100644 --- a/src/Lexer/lexer.cpp +++ b/src/Lexer/lexer.cpp @@ -1,9 +1,9 @@ -#include #include #include #include -#include +#include +#include #include #if 0 @@ -17,113 +17,110 @@ namespace Fig { - const std::unordered_map Lexer::symbol_map{ + const std::unordered_map Lexer::symbol_map{ // 三字符 - {FString(u8"..."), TokenType::TripleDot}, + {String(U"..."), TokenType::TripleDot}, // 双字符 - {FString(u8"=="), TokenType::Equal}, - {FString(u8"!="), TokenType::NotEqual}, - {FString(u8"<="), TokenType::LessEqual}, - {FString(u8">="), TokenType::GreaterEqual}, - {FString(u8"<<"), TokenType::ShiftLeft}, - {FString(u8">>"), TokenType::ShiftRight}, - {FString(u8"+="), TokenType::PlusEqual}, - {FString(u8"-="), TokenType::MinusEqual}, - {FString(u8"*="), TokenType::AsteriskEqual}, - {FString(u8"/="), TokenType::SlashEqual}, - {FString(u8"%="), TokenType::PercentEqual}, - {FString(u8"^="), TokenType::CaretEqual}, - {FString(u8"++"), TokenType::DoublePlus}, - {FString(u8"--"), TokenType::DoubleMinus}, - {FString(u8"&&"), TokenType::DoubleAmpersand}, - {FString(u8"||"), TokenType::DoublePipe}, - {FString(u8":="), TokenType::Walrus}, - {FString(u8"**"), TokenType::Power}, - {FString(u8"->"), TokenType::RightArrow}, - {FString(u8"=>"), TokenType::DoubleArrow}, + {String(U"=="), TokenType::Equal}, + {String(U"!="), TokenType::NotEqual}, + {String(U"<="), TokenType::LessEqual}, + {String(U">="), TokenType::GreaterEqual}, + {String(U"<<"), TokenType::ShiftLeft}, + {String(U">>"), TokenType::ShiftRight}, + {String(U"+="), TokenType::PlusEqual}, + {String(U"-="), TokenType::MinusEqual}, + {String(U"*="), TokenType::AsteriskEqual}, + {String(U"/="), TokenType::SlashEqual}, + {String(U"%="), TokenType::PercentEqual}, + {String(U"^="), TokenType::CaretEqual}, + {String(U"++"), TokenType::DoublePlus}, + {String(U"--"), TokenType::DoubleMinus}, + {String(U"&&"), TokenType::DoubleAmpersand}, + {String(U"||"), TokenType::DoublePipe}, + {String(U":="), TokenType::Walrus}, + {String(U"**"), TokenType::Power}, + {String(U"->"), TokenType::RightArrow}, + {String(U"=>"), TokenType::DoubleArrow}, // 单字符 - {FString(u8"+"), TokenType::Plus}, - {FString(u8"-"), TokenType::Minus}, - {FString(u8"*"), TokenType::Asterisk}, - {FString(u8"/"), TokenType::Slash}, - {FString(u8"%"), TokenType::Percent}, - {FString(u8"^"), TokenType::Caret}, - {FString(u8"&"), TokenType::Ampersand}, - {FString(u8"|"), TokenType::Pipe}, - {FString(u8"~"), TokenType::Tilde}, - {FString(u8"="), TokenType::Assign}, - {FString(u8"<"), TokenType::Less}, - {FString(u8">"), TokenType::Greater}, - {FString(u8"."), TokenType::Dot}, - {FString(u8","), TokenType::Comma}, - {FString(u8":"), TokenType::Colon}, - {FString(u8";"), TokenType::Semicolon}, - {FString(u8"'"), TokenType::SingleQuote}, - {FString(u8"\""), TokenType::DoubleQuote}, - {FString(u8"("), TokenType::LeftParen}, - {FString(u8")"), TokenType::RightParen}, - {FString(u8"["), TokenType::LeftBracket}, - {FString(u8"]"), TokenType::RightBracket}, - {FString(u8"{"), TokenType::LeftBrace}, - {FString(u8"}"), TokenType::RightBrace}, - {FString(u8"?"), TokenType::Question}, - {FString(u8"!"), TokenType::Not}, + {String(U"+"), TokenType::Plus}, + {String(U"-"), TokenType::Minus}, + {String(U"*"), TokenType::Asterisk}, + {String(U"/"), TokenType::Slash}, + {String(U"%"), TokenType::Percent}, + {String(U"^"), TokenType::Caret}, + {String(U"&"), TokenType::Ampersand}, + {String(U"|"), TokenType::Pipe}, + {String(U"~"), TokenType::Tilde}, + {String(U"="), TokenType::Assign}, + {String(U"<"), TokenType::Less}, + {String(U">"), TokenType::Greater}, + {String(U"."), TokenType::Dot}, + {String(U","), TokenType::Comma}, + {String(U":"), TokenType::Colon}, + {String(U";"), TokenType::Semicolon}, + {String(U"'"), TokenType::SingleQuote}, + {String(U"\""), TokenType::DoubleQuote}, + {String(U"("), TokenType::LeftParen}, + {String(U")"), TokenType::RightParen}, + {String(U"["), TokenType::LeftBracket}, + {String(U"]"), TokenType::RightBracket}, + {String(U"{"), TokenType::LeftBrace}, + {String(U"}"), TokenType::RightBrace}, + {String(U"?"), TokenType::Question}, + {String(U"!"), TokenType::Not}, }; - const std::unordered_map Lexer::keyword_map{ - {FString(u8"and"), TokenType::And}, - {FString(u8"or"), TokenType::Or}, - {FString(u8"not"), TokenType::Not}, - {FString(u8"import"), TokenType::Import}, - {FString(u8"func"), TokenType::Function}, - {FString(u8"var"), TokenType::Variable}, - {FString(u8"const"), TokenType::Const}, - // {FString(u8"final"), TokenType::Final}, - {FString(u8"while"), TokenType::While}, - {FString(u8"for"), TokenType::For}, - {FString(u8"if"), TokenType::If}, - {FString(u8"else"), TokenType::Else}, - {FString(u8"new"), TokenType::New}, - {FString(u8"struct"), TokenType::Struct}, - {FString(u8"interface"), TokenType::Interface}, - {FString(u8"impl"), TokenType::Implement}, - {FString(u8"is"), TokenType::Is}, - {FString(u8"public"), TokenType::Public}, - {FString(u8"return"), TokenType::Return}, - {FString(u8"break"), TokenType::Break}, - {FString(u8"continue"), TokenType::Continue}, - {FString(u8"try"), TokenType::Try}, - {FString(u8"catch"), TokenType::Catch}, - {FString(u8"throw"), TokenType::Throw}, - {FString(u8"Finally"), TokenType::Finally}, - {FString(u8"as"), TokenType::As}, + const std::unordered_map Lexer::keyword_map{ + {String(U"and"), TokenType::And}, + {String(U"or"), TokenType::Or}, + {String(U"not"), TokenType::Not}, + {String(U"import"), TokenType::Import}, + {String(U"func"), TokenType::Function}, + {String(U"var"), TokenType::Variable}, + {String(U"const"), TokenType::Const}, + // {String(U"final"), TokenType::Final}, + {String(U"while"), TokenType::While}, + {String(U"for"), TokenType::For}, + {String(U"if"), TokenType::If}, + {String(U"else"), TokenType::Else}, + {String(U"new"), TokenType::New}, + {String(U"struct"), TokenType::Struct}, + {String(U"interface"), TokenType::Interface}, + {String(U"impl"), TokenType::Implement}, + {String(U"is"), TokenType::Is}, + {String(U"public"), TokenType::Public}, + {String(U"return"), TokenType::Return}, + {String(U"break"), TokenType::Break}, + {String(U"continue"), TokenType::Continue}, + {String(U"try"), TokenType::Try}, + {String(U"catch"), TokenType::Catch}, + {String(U"throw"), TokenType::Throw}, + {String(U"Finally"), TokenType::Finally}, + {String(U"as"), TokenType::As}, - // {FString(u8"Null"), TokenType::TypeNull}, - // {FString(u8"Int"), TokenType::TypeInt}, - // {FString(u8"String"), TokenType::TypeString}, - // {FString(u8"Bool"), TokenType::TypeBool}, - // {FString(u8"Double"), TokenType::TypeDouble}, + // {String(U"Null"), TokenType::TypeNull}, + // {String(U"Int"), TokenType::TypeInt}, + // {String(U"String"), TokenType::TypeString}, + // {String(U"Bool"), TokenType::TypeBool}, + // {String(U"Double"), TokenType::TypeDouble}, }; void Lexer::skipLine() { - while (*it != U'\n' and hasNext()) - { - next(); - } + while (current() != U'\n' and hasNext()) { next(); } next(); // skip '\n' ++line; } Token Lexer::scanIdentifier() { - FString identifier; + String identifier; while (hasNext()) { - UTF8Char c = *it; - if (c.isAlnum() || c == U'_') + char32_t c = current(); + if (CharUtils::isAlnum(c) || c == U'_') { - identifier += c.getString(); + identifier += c; next(); } else @@ -131,23 +128,27 @@ namespace Fig break; } } - if (this->keyword_map.contains(identifier)) - { - return Token(identifier, this->keyword_map.at(identifier)); - } - else if (identifier == u8"true" || identifier == u8"false") - { - return Token(identifier, TokenType::LiteralBool); - } - else if (identifier == u8"null") + 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); } + else if (identifier == U"\1") { // null instance return Token(identifier, TokenType::LiteralNull); } - if (keyword_map.contains(Utils::toLower(identifier))) - { - pushWarning(1, identifier); // Identifier is too similar to a keyword or a primitive type - } + // const auto &toLower = [](const String &str) -> String + // { + // 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) { pushWarning(2, identifier); // The identifier is too abstract @@ -156,12 +157,12 @@ namespace Fig } Token Lexer::scanString() { - FString str; + String str; bool unterminated = true; - size_t str_start_col = it.column() - 1; + size_t str_start_col = column - 1; while (hasNext()) { - UTF8Char c = *it; + char32_t c = current(); if (c == U'"' || c == U'\n') { next(); @@ -170,74 +171,74 @@ namespace Fig } 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; } next(); - UTF8Char ec = *it; + char32_t ec = current(); if (ec == U'n') { next(); - str += u8"\n"; + str += U"\1"; } else if (ec == U't') { next(); - str += u8"\t"; + str += U"\1"; } else if (ec == U'v') { next(); - str += u8"\v"; + str += U"\1"; } else if (ec == U'b') { next(); - str += u8"\b"; + str += U"\1"; } else if (ec == U'"') { next(); - str += u8"\""; + str += U"\1"; } else if (ec == U'\'') { next(); - str += u8"'"; + str += U"\1"; } else { - error = SyntaxError(FString(std::format("Unsupported escape character: {}", - FString(ec.getString()).toBasicString())), - this->line, - it.column(), - SourceInfo(this)); + error = + SyntaxError(String(std::format("Unsupported escape character: {}", String(ec).toBasicString())), + this->line, + column, + SourceInfo(this)); return IllegalTok; } } else { - str += c.getString(); + str += c; next(); } } 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 Token(str, TokenType::LiteralString); } Token Lexer::scanRawString() { - FString str; + String str; bool unterminated = true; - size_t str_start_col = it.column() - 1; + size_t str_start_col = column - 1; while (hasNext()) { - UTF8Char c = *it; + char32_t c = current(); if (c == U'"' || c == U'\n') { next(); @@ -246,27 +247,27 @@ namespace Fig } else { - str += c.getString(); + str += c; next(); } } 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 Token(str, TokenType::LiteralString); } Token Lexer::scanMultilineString() { - FString str; + String str; bool unterminated = true; uint8_t end = 0; - size_t str_start_col = it.column() - 1; + size_t str_start_col = column - 1; while (hasNext()) { - UTF8Char c = *it; + char32_t c = current(); if (c == U'"') { if (end == 3) @@ -281,99 +282,99 @@ namespace Fig } 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; } next(); - UTF8Char ec = *it; + char32_t ec = current(); if (ec == U'n') { next(); - str += u8"\n"; + str += U"\n"; } else if (ec == U't') { next(); - str += u8"\t"; + str += U"\t"; } else if (ec == U'v') { next(); - str += u8"\v"; + str += U"\v"; } else if (ec == U'b') { next(); - str += u8"\b"; + str += U"\b"; } else if (ec == U'"') { next(); - str += u8"\""; + str += U"\""; } else if (ec == U'\'') { next(); - str += u8"'"; + str += U"\'"; } else if (ec == U'\\') { next(); - str += u8"\\"; + str += U"\\"; } else { - error = SyntaxError(FString(std::format("Unsupported escape character: {}", - FString(ec.getString()).toBasicString())), - this->line, - it.column(), - SourceInfo(this)); + error = SyntaxError( + String(std::format("Unsupported escape character: {}", String(ec).toBasicString())), + this->line, + column, + SourceInfo(this)); return IllegalTok; } } else { - str += c.getString(); + str += c; } end = 0; } 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 Token(str, TokenType::LiteralString); } Token Lexer::scanNumber() { - FString numStr; + String numStr; bool hasPoint = false; 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(); } else if (ch == U'-' && !numStr.empty() && (numStr.ends_with(U'e') || numStr.ends_with(U'E'))) { - numStr += ch.getString(); + numStr += ch; next(); } else if (ch == U'+' && !numStr.empty() && (numStr.ends_with(U'e') || numStr.ends_with(U'E'))) { - numStr += ch.getString(); + numStr += ch; next(); } else if (ch == U'.' && !hasPoint) { hasPoint = true; - numStr += ch.getString(); + numStr += ch; next(); } else @@ -385,9 +386,9 @@ namespace Fig 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, - it.column(), + column, SourceInfo(this)); return IllegalTok; } @@ -395,7 +396,7 @@ namespace Fig bool hasDigit = false; for (auto it = numStr.begin(); it != numStr.end(); ++it) { - if (isdigit(*it)) + if (CharUtils::isDigit(*it)) { hasDigit = true; break; @@ -404,55 +405,55 @@ namespace Fig if (!hasDigit) { - error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), + error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, - it.column(), + column, SourceInfo(this)); return IllegalTok; } size_t ePos = numStr.find(U'e'); - if (ePos != FString::npos) + if (ePos != String::npos) { 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, - it.column(), + column, SourceInfo(this)); return IllegalTok; } 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, - it.column(), + column, SourceInfo(this)); return IllegalTok; } bool hasDigitAfterE = false; 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 (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, - it.column(), + column, SourceInfo(this)); return IllegalTok; } continue; } - if (c.isDigit()) { hasDigitAfterE = true; } + if (CharUtils::isDigit(c)) { hasDigitAfterE = true; } else { - error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), + error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, - it.column(), + column, SourceInfo(this)); return IllegalTok; } @@ -460,9 +461,9 @@ namespace Fig if (!hasDigitAfterE) { - error = SyntaxError(FString(std::format("Illegal number literal: {}", numStr.toBasicString())), + error = SyntaxError(String(std::format("Illegal number literal: {}", numStr.toBasicString())), this->line, - it.column(), + column, SourceInfo(this)); return IllegalTok; } @@ -472,25 +473,24 @@ namespace Fig } Token Lexer::scanSymbol() { - FString sym; - UTF8Char ch = *it; - sym += ch.getString(); + String sym; + char32_t ch = current(); + sym += ch; - auto startsWith = [&](const FString &prefix) -> bool { + auto startsWith = [&](const String &prefix) -> bool { for (const auto &p : symbol_map) { - const FString &op = p.first; - if (op.starts_with(prefix)) - return true; + const String &op = p.first; + if (op.starts_with(prefix)) return true; } return false; }; 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, - it.column(), + column, SourceInfo(this)); next(); return IllegalTok; @@ -498,11 +498,10 @@ namespace Fig while (hasNext()) { - UTF8Char peek = it.peek(); - if (!peek.isPunct()) - break; + char32_t peek_ch = peek(); + if (!CharUtils::isPunct(peek_ch)) break; - FString candidate = sym + FString(peek.getString()); + String candidate = sym + peek_ch; if (startsWith(candidate)) { @@ -517,9 +516,9 @@ namespace Fig 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, - it.column(), + column, SourceInfo(this)); next(); return IllegalTok; @@ -533,37 +532,34 @@ namespace Fig { // entry: when iterator current char is '/' and peek is '/' or '*' // 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 second '/' - UTF8Char c = *it; + char32_t c = current(); while (c != U'\n' and hasNext()) { - comment += c.getString(); + comment += c; next(); - c = *it; + c = current(); } - if (hasNext() && c == U'\n') - { - next(); - } + if (hasNext() && c == U'\n') { next(); } } else // multi-line comment { next(); // skip '/' next(); // skip '*' - UTF8Char c = *it; + char32_t c = current(); bool terminated = false; while (hasNext()) { - if (c == U'*' and hasNext() and it.peek() == U'/') + if (c == U'*' and hasNext() and peek() == U'/') { next(); // skip '*' next(); // skip '/' @@ -572,16 +568,15 @@ namespace Fig } else { - comment += c.getString(); + comment += c; next(); - c = *it; + c = current(); } } if (!terminated) { - error = - SyntaxError(FString(u8"Unterminated multiline comment"), this->line, it.column(), SourceInfo(this)); + error = SyntaxError(String(U"\1"), this->line, column, SourceInfo(this)); next(); return IllegalTok; } @@ -591,76 +586,61 @@ namespace Fig } Token Lexer::nextToken() { - if (!hasNext()) + if (!hasNext()) { return EOFTok.setPos(getCurrentLine(), getCurrentColumn()); } + char32_t ch = current(); + while (hasNext()) { - return EOFTok; - } - UTF8Char ch = *it; - while (ch.isSpace()) - { - next(); - ch = *it; - if (!hasNext()) + ch = current(); + if (!CharUtils::isSpace(ch)) { - return EOFTok.setPos(getCurrentLine(), getCurrentColumn()); + break; } + next(); } last_line = getCurrentLine(); last_column = getCurrentColumn(); if (ch == U'/') { - UTF8Char c{u8""}; + char32_t c; if (!hasNext()) { 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'*') { 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); return nextToken(); // 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"" - // raw FString + // raw String next(); next(); return scanRawString().setPos(last_line, last_column); } - if (ch.isAlpha() || ch == U'_') - { - return scanIdentifier().setPos(last_line, last_column); - } + if (CharUtils::isAlpha(ch) || ch == U'_') { return scanIdentifier().setPos(last_line, last_column); } else if (ch == U'"') { next(); return scanString().setPos(last_line, last_column); } - else if (ch.isDigit()) - { - return scanNumber().setPos(last_line, last_column); - } - else if (ch.isPunct()) - { - return scanSymbol().setPos(last_line, last_column); - } + else if (CharUtils::isDigit(ch)) { return scanNumber().setPos(last_line, last_column); } + else if (CharUtils::isPunct(ch)) { return scanSymbol().setPos(last_line, last_column); } else { error = - SyntaxError(FString(std::format("Cannot tokenize char: '{}'", FString(ch.getString()).toBasicString())), + SyntaxError(String(std::format("Cannot tokenize char: '{}'", String(ch).toBasicString())), this->line, - it.column(), + column, SourceInfo(this)); - if (hasNext()) - { - next(); - } + if (hasNext()) { next(); } return IllegalTok.setPos(last_line, last_column); } } diff --git a/src/Lexer/lexer.hpp b/src/Lexer/lexer.hpp index 196749e..c238d6e 100644 --- a/src/Lexer/lexer.hpp +++ b/src/Lexer/lexer.hpp @@ -8,8 +8,7 @@ #include #include -#include -#include +#include #include namespace Fig @@ -19,26 +18,33 @@ namespace Fig { private: size_t line; - const FString source; + const String source; SyntaxError error; - UTF8Iterator it; - - FString sourcePath; - std::vector sourceLines; + String sourcePath; + std::vector sourceLines; std::vector warnings; + int64_t idx = 0; + size_t last_line, last_column, column = 1; - bool hasNext() - { - return !this->it.isEnd(); + char32_t current() const { return source[idx]; } + + char32_t peek() const { + if (idx + 1 >= source.length()) + { + return U'\0'; + } + return source[idx + 1]; } + bool hasNext() { return idx < source.length(); } + void skipLine(); inline void next() { - if (*it == U'\n') + if (current() == U'\n') { ++this->line; this->column = 1; @@ -47,43 +53,31 @@ namespace Fig { ++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())); } - 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)); } public: - static const std::unordered_map symbol_map; - static const std::unordered_map keyword_map; + static const std::unordered_map symbol_map; + static const std::unordered_map keyword_map; - inline Lexer(const FString &_source, const FString &_sourcePath, const std::vector &_sourceLines) : - source(_source), it(source), sourcePath(_sourcePath), sourceLines(_sourceLines) + inline Lexer(const String &_source, const String &_sourcePath, const std::vector &_sourceLines) : + source(_source), sourcePath(_sourcePath), sourceLines(_sourceLines) { line = 1; } - inline size_t getCurrentLine() - { - return line; - } - inline size_t getCurrentColumn() - { - return column; - } - SyntaxError getError() const - { - return error; - } - std::vector getWarnings() const - { - return warnings; - } + inline size_t getCurrentLine() { return line; } + inline size_t getCurrentColumn() { return column; } + SyntaxError getError() const { return error; } + std::vector getWarnings() const { return warnings; } Token nextToken(); Token scanNumber(); diff --git a/src/Module/builtins.cpp b/src/Module/builtins.cpp index 6e6dbb6..6c7c367 100644 --- a/src/Module/builtins.cpp +++ b/src/Module/builtins.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -24,60 +24,60 @@ namespace Fig::Builtins { const TypeInfo &getErrorInterfaceTypeInfo() { - static const TypeInfo ErrorInterfaceTypeInfo(u8"Error", true); + static const TypeInfo ErrorInterfaceTypeInfo(U"Error", true); return ErrorInterfaceTypeInfo; } const TypeInfo &getTypeErrorStructTypeInfo() { - static const TypeInfo TypeErrorStructTypeInfo(u8"TypeError", true); + static const TypeInfo TypeErrorStructTypeInfo(U"TypeError", true); return TypeErrorStructTypeInfo; } const TypeInfo &getOperationInterfaceTypeInfo() { - static const TypeInfo OperationInterfaceTypeInfo(u8"Operation", true); + static const TypeInfo OperationInterfaceTypeInfo(U"Operation", true); return OperationInterfaceTypeInfo; } - const std::unordered_map &getBuiltinValues() + const std::unordered_map &getBuiltinValues() { - static const std::unordered_map builtinValues = { - {u8"null", Object::getNullInstance()}, - {u8"true", Object::getTrueInstance()}, - {u8"false", Object::getFalseInstance()}, - {u8"Error", + static const std::unordered_map builtinValues = { + {U"null", Object::getNullInstance()}, + {U"true", Object::getTrueInstance()}, + {U"false", Object::getFalseInstance()}, + {U"Error", std::make_shared(InterfaceType(getErrorInterfaceTypeInfo(), - {Ast::InterfaceMethod(u8"toString", + {Ast::InterfaceMethod(U"toString", Ast::FunctionParameters({}, {}), - std::make_shared(u8"String"), + std::make_shared(U"String"), nullptr), - Ast::InterfaceMethod(u8"getErrorClass", + Ast::InterfaceMethod(U"getErrorClass", Ast::FunctionParameters({}, {}), - std::make_shared(u8"String"), + std::make_shared(U"String"), nullptr), - Ast::InterfaceMethod(u8"getErrorMessage", + Ast::InterfaceMethod(U"getErrorMessage", Ast::FunctionParameters({}, {}), - std::make_shared(u8"String"), + std::make_shared(U"String"), nullptr)}))}, - {u8"TypeError", std::make_shared(StructType( + {U"TypeError", std::make_shared(StructType( getTypeErrorStructTypeInfo(), - std::make_shared(u8""), - {Field(AccessModifier::Public, u8"msg", ValueType::String, nullptr)} + std::make_shared(U""), + {Field(AccessModifier::Public, U"msg", ValueType::String, nullptr)} ))}, - {u8"Operation", std::make_shared(InterfaceType(getOperationInterfaceTypeInfo(), {}))}, + {U"Operation", std::make_shared(InterfaceType(getOperationInterfaceTypeInfo(), {}))}, - {u8"Any", std::make_shared(StructType(ValueType::Any, nullptr, {}, true))}, - {u8"Int", std::make_shared(StructType(ValueType::Int, nullptr, {}, true))}, - {u8"Null", std::make_shared(StructType(ValueType::Null, nullptr, {}, true))}, - {u8"String", std::make_shared(StructType(ValueType::String, nullptr, {}, true))}, - {u8"Bool", std::make_shared(StructType(ValueType::Bool, nullptr, {}, true))}, - {u8"Double", std::make_shared(StructType(ValueType::Double, nullptr, {}, true))}, - {u8"Function", std::make_shared(StructType(ValueType::Function, nullptr, {}, true))}, - {u8"List", std::make_shared(StructType(ValueType::List, nullptr, {}, true))}, - {u8"Map", std::make_shared(StructType(ValueType::Map, nullptr, {}, true))}, + {U"Any", std::make_shared(StructType(ValueType::Any, nullptr, {}, true))}, + {U"Int", std::make_shared(StructType(ValueType::Int, nullptr, {}, true))}, + {U"Null", std::make_shared(StructType(ValueType::Null, nullptr, {}, true))}, + {U"String", std::make_shared(StructType(ValueType::String, nullptr, {}, true))}, + {U"Bool", std::make_shared(StructType(ValueType::Bool, nullptr, {}, true))}, + {U"Double", std::make_shared(StructType(ValueType::Double, nullptr, {}, true))}, + {U"Function", std::make_shared(StructType(ValueType::Function, nullptr, {}, true))}, + {U"List", std::make_shared(StructType(ValueType::List, nullptr, {}, true))}, + {U"Map", std::make_shared(StructType(ValueType::Map, nullptr, {}, true))}, // Type `StructType` `StructInstance` `Module` `InterfaceType` // Not allowed to call constructor! - {u8"type", std::make_shared(Function( - u8"type", + {U"type", std::make_shared(Function( + U"type", [](const std::vector &_args) -> ObjectPtr { const ObjectPtr &arg = _args[0]; @@ -88,86 +88,86 @@ namespace Fig::Builtins }; return builtinValues; } - const std::unordered_map &getBuiltinFunctionArgCounts() + const std::unordered_map &getBuiltinFunctionArgCounts() { - static const std::unordered_map builtinFunctionArgCounts = { - {u8"__fstdout_print", -1}, // variadic - {u8"__fstdout_println", -1}, // variadic - {u8"__fstdin_read", 0}, - {u8"__fstdin_readln", 0}, - {u8"__fvalue_type", 1}, - {u8"__fvalue_int_parse", 1}, - {u8"__fvalue_int_from", 1}, - {u8"__fvalue_double_parse", 1}, - {u8"__fvalue_double_from", 1}, - {u8"__fvalue_string_from", 1}, - {u8"__ftime_now_ns", 0}, + static const std::unordered_map builtinFunctionArgCounts = { + {U"__fstdout_print", -1}, // variadic + {U"__fstdout_println", -1}, // variadic + {U"__fstdin_read", 0}, + {U"__fstdin_readln", 0}, + {U"__fvalue_type", 1}, + {U"__fvalue_int_parse", 1}, + {U"__fvalue_int_from", 1}, + {U"__fvalue_double_parse", 1}, + {U"__fvalue_double_from", 1}, + {U"__fvalue_string_from", 1}, + {U"__ftime_now_ns", 0}, /* math start */ - {u8"__fmath_acos", 1}, - {u8"__fmath_acosh", 1}, - {u8"__fmath_asin", 1}, - {u8"__fmath_asinh", 1}, - {u8"__fmath_atan", 1}, - {u8"__fmath_atan2", 2}, - {u8"__fmath_atanh", 1}, - {u8"__fmath_ceil", 1}, - {u8"__fmath_cos", 1}, - {u8"__fmath_cosh", 1}, - {u8"__fmath_exp", 1}, - {u8"__fmath_expm1", 1}, - {u8"__fmath_fabs", 1}, - {u8"__fmath_floor", 1}, - {u8"__fmath_fmod", 2}, - {u8"__fmath_frexp", 1}, - {u8"__fmath_gcd", 2}, - {u8"__fmath_hypot", 2}, - {u8"__fmath_isequal", 2}, - {u8"__fmath_log", 1}, - {u8"__fmath_log10", 1}, - {u8"__fmath_log1p", 1}, - {u8"__fmath_log2", 1}, - {u8"__fmath_sin", 1}, - {u8"__fmath_sinh", 1}, - {u8"__fmath_sqrt", 1}, - {u8"__fmath_tan", 1}, - {u8"__fmath_tanh", 1}, - {u8"__fmath_trunc", 1}, + {U"__fmath_acos", 1}, + {U"__fmath_acosh", 1}, + {U"__fmath_asin", 1}, + {U"__fmath_asinh", 1}, + {U"__fmath_atan", 1}, + {U"__fmath_atan2", 2}, + {U"__fmath_atanh", 1}, + {U"__fmath_ceil", 1}, + {U"__fmath_cos", 1}, + {U"__fmath_cosh", 1}, + {U"__fmath_exp", 1}, + {U"__fmath_expm1", 1}, + {U"__fmath_fabs", 1}, + {U"__fmath_floor", 1}, + {U"__fmath_fmod", 2}, + {U"__fmath_frexp", 1}, + {U"__fmath_gcd", 2}, + {U"__fmath_hypot", 2}, + {U"__fmath_isequal", 2}, + {U"__fmath_log", 1}, + {U"__fmath_log10", 1}, + {U"__fmath_log1p", 1}, + {U"__fmath_log2", 1}, + {U"__fmath_sin", 1}, + {U"__fmath_sinh", 1}, + {U"__fmath_sqrt", 1}, + {U"__fmath_tan", 1}, + {U"__fmath_tanh", 1}, + {U"__fmath_trunc", 1}, }; return builtinFunctionArgCounts; } - const std::unordered_map &getBuiltinFunctions() + const std::unordered_map &getBuiltinFunctions() { - static const std::unordered_map builtinFunctions{ - {u8"__fstdout_print", + static const std::unordered_map builtinFunctions{ + {U"__fstdout_print", [](const std::vector &args) -> ObjectPtr { for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); } return std::make_shared(ValueType::IntClass(args.size())); }}, - {u8"__fstdout_println", + {U"__fstdout_println", [](const std::vector &args) -> ObjectPtr { for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); } std::print("\n"); return std::make_shared(ValueType::IntClass(args.size())); }}, - {u8"__fstdin_read", + {U"__fstdin_read", [](const std::vector &args) -> ObjectPtr { std::string input; std::cin >> input; - return std::make_shared(FString::fromBasicString(input)); + return std::make_shared(String(input)); }}, - {u8"__fstdin_readln", + {U"__fstdin_readln", [](const std::vector &args) -> ObjectPtr { std::string line; std::getline(std::cin, line); - return std::make_shared(FString::fromBasicString(line)); + return std::make_shared(String(line)); }}, - {u8"__fvalue_type", + {U"__fvalue_type", [](const std::vector &args) -> ObjectPtr { return std::make_shared(args[0]->getTypeInfo().toString()); }}, - {u8"__fvalue_int_parse", + {U"__fvalue_int_parse", [](const std::vector &args) -> ObjectPtr { - FString str = args[0]->as(); + String str = args[0]->as(); try { ValueType::IntClass val = std::stoi(str.toBasicString()); @@ -175,10 +175,10 @@ namespace Fig::Builtins } 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 &args) -> ObjectPtr { ObjectPtr val = args[0]; if (val->is()) @@ -193,13 +193,13 @@ namespace Fig::Builtins } 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()))); } }}, - {u8"__fvalue_double_parse", + {U"__fvalue_double_parse", [](const std::vector &args) -> ObjectPtr { - FString str = args[0]->as(); + String str = args[0]->as(); try { ValueType::DoubleClass val = std::stod(str.toBasicString()); @@ -207,10 +207,10 @@ namespace Fig::Builtins } 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 &args) -> ObjectPtr { ObjectPtr val = args[0]; if (val->is()) @@ -225,16 +225,16 @@ namespace Fig::Builtins } 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()))); } }}, - {u8"__fvalue_string_from", + {U"__fvalue_string_from", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; return std::make_shared(val->toStringIO()); }}, - {u8"__ftime_now_ns", + {U"__ftime_now_ns", [](const std::vector &args) -> ObjectPtr { // returns nanoseconds using namespace Fig::Time; @@ -244,97 +244,97 @@ namespace Fig::Builtins }}, /* math start */ - {u8"__fmath_acos", + {U"__fmath_acos", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(acos(d)); }}, - {u8"__fmath_acosh", + {U"__fmath_acosh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(acosh(d)); }}, - {u8"__fmath_asin", + {U"__fmath_asin", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(asin(d)); }}, - {u8"__fmath_asinh", + {U"__fmath_asinh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(asinh(d)); }}, - {u8"__fmath_atan", + {U"__fmath_atan", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(atan(d)); }}, - {u8"__fmath_atan2", + {U"__fmath_atan2", [](const std::vector &args) -> ObjectPtr { ValueType::DoubleClass y = args[0]->getNumericValue(); ValueType::DoubleClass x = args[1]->getNumericValue(); return std::make_shared(atan2(y, x)); }}, - {u8"__fmath_atanh", + {U"__fmath_atanh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(atanh(d)); }}, - {u8"__fmath_ceil", + {U"__fmath_ceil", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(ceil(d)); }}, - {u8"__fmath_cos", + {U"__fmath_cos", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(cos(d)); }}, - {u8"__fmath_cosh", + {U"__fmath_cosh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(cosh(d)); }}, - {u8"__fmath_exp", + {U"__fmath_exp", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(exp(d)); }}, - {u8"__fmath_expm1", + {U"__fmath_expm1", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(expm1(d)); }}, - {u8"__fmath_fabs", + {U"__fmath_fabs", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(fabs(d)); }}, - {u8"__fmath_floor", + {U"__fmath_floor", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(floor(d)); }}, - {u8"__fmath_fmod", + {U"__fmath_fmod", [](const std::vector &args) -> ObjectPtr { ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue(); return std::make_shared(fmod(x, y)); }}, - {u8"__fmath_frexp", + {U"__fmath_frexp", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); @@ -342,80 +342,80 @@ namespace Fig::Builtins return std::make_shared(List({std::make_shared(frexp(d, &e)), std::make_shared(static_cast(e))})); }}, - {u8"__fmath_gcd", + {U"__fmath_gcd", [](const std::vector &args) -> ObjectPtr { ValueType::IntClass x = args[0]->as(); ValueType::IntClass y = args[1]->as(); return std::make_shared(std::gcd(x, y)); }}, - {u8"__fmath_hypot", + {U"__fmath_hypot", [](const std::vector &args) -> ObjectPtr { ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue(); return std::make_shared(hypot(x, y)); }}, - {u8"__fmath_isequal", + {U"__fmath_isequal", [](const std::vector &args) -> ObjectPtr { ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue(); static const double epsilon = 1e-9; return std::make_shared(fabs(x - y) < epsilon); }}, - {u8"__fmath_log", + {U"__fmath_log", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(log(d)); }}, - {u8"__fmath_log10", + {U"__fmath_log10", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(log10(d)); }}, - {u8"__fmath_log1p", + {U"__fmath_log1p", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(log1p(d)); }}, - {u8"__fmath_log2", + {U"__fmath_log2", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(log2(d)); }}, - {u8"__fmath_sin", + {U"__fmath_sin", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(sin(d)); }}, - {u8"__fmath_sinh", + {U"__fmath_sinh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(sinh(d)); }}, - {u8"__fmath_sqrt", + {U"__fmath_sqrt", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(sqrt(d)); }}, - {u8"__fmath_tan", + {U"__fmath_tan", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(tan(d)); }}, - {u8"__fmath_tanh", + {U"__fmath_tanh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(tanh(d)); }}, - {u8"__fmath_trunc", + {U"__fmath_trunc", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); diff --git a/src/Module/builtins.hpp b/src/Module/builtins.hpp index 86b3d26..8e2c6bf 100644 --- a/src/Module/builtins.hpp +++ b/src/Module/builtins.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include @@ -34,39 +34,39 @@ namespace Fig { add(..., ...) -> ...; } - + */ const TypeInfo &getOperationInterfaceTypeInfo(); - const std::unordered_map &getBuiltinValues(); + const std::unordered_map &getBuiltinValues(); using BuiltinFunction = std::function &)>; - const std::unordered_map &getBuiltinFunctionArgCounts(); - const std::unordered_map &getBuiltinFunctions(); + const std::unordered_map &getBuiltinFunctionArgCounts(); + const std::unordered_map &getBuiltinFunctions(); - inline bool isBuiltinFunction(const FString &name) + inline bool isBuiltinFunction(const String &name) { return getBuiltinFunctions().find(name) != getBuiltinFunctions().end(); } - inline BuiltinFunction getBuiltinFunction(const FString &name) + inline BuiltinFunction getBuiltinFunction(const String &name) { auto it = getBuiltinFunctions().find(name); 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; } - inline int getBuiltinFunctionParamCount(const FString &name) + inline int getBuiltinFunctionParamCount(const String &name) { auto it = getBuiltinFunctionArgCounts().find(name); 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; } diff --git a/src/Parser/parser.cpp b/src/Parser/parser.cpp index a750b21..83a8da8 100644 --- a/src/Parser/parser.cpp +++ b/src/Parser/parser.cpp @@ -87,7 +87,7 @@ namespace Fig bool isConst = (currentToken().getType() == TokenType::Const ? true : false); next(); expect(TokenType::Identifier); - FString name = currentToken().getValue(); + String name = currentToken().getValue(); next(); Ast::Expression declaredType = nullptr; bool hasSpecificType = false; @@ -102,12 +102,12 @@ namespace Fig next(); // consume `;`, no using expectConsume here cause we don't need to check again return makeAst(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; if (isThis(TokenType::Walrus)) { - if (hasSpecificType) throwAddressableError(FString(u8"")); + if (hasSpecificType) throwAddressableError(String(U"\1")); followupType = true; } next(); @@ -118,7 +118,7 @@ namespace Fig ObjectPtr Parser::__parseValue() { - FString _val = currentToken().getValue(); + String _val = currentToken().getValue(); if (currentToken().getType() == TokenType::LiteralNumber) { if (_val.contains(u8'.') || _val.contains(u8'e')) @@ -131,7 +131,7 @@ namespace Fig } catch (...) { - throwAddressableError(FString(u8"Illegal number literal")); + throwAddressableError(String(U"\1")); } return std::make_shared(d); } @@ -145,7 +145,7 @@ namespace Fig } catch (...) { - throwAddressableError(FString(u8"Illegal number literal")); + throwAddressableError(String(U"\1")); } return std::make_shared(i); } @@ -153,7 +153,7 @@ namespace Fig else if (currentToken().getType() == TokenType::LiteralString) { return std::make_shared(_val); } else if (currentToken().getType() == TokenType::LiteralBool) { - return std::make_shared((_val == u8"true" ? true : false)); + return std::make_shared((_val == U"\1" ? true : false)); } else if (currentToken().getType() == TokenType::LiteralNull) { return Object::getNullInstance(); } else @@ -176,7 +176,7 @@ namespace Fig Ast::FunctionParameters::PosParasType pp; Ast::FunctionParameters::DefParasType dp; - FString variaPara; + String variaPara; while (true) { if (isThis(TokenType::RightParen)) @@ -184,13 +184,13 @@ namespace Fig next(); return Ast::FunctionParameters(pp, dp); } - expect(TokenType::Identifier, FString(u8"Identifier or `)`")); // check current - FString pname = currentToken().getValue(); + expect(TokenType::Identifier, String(U"\1")); // check current + String pname = currentToken().getValue(); next(); // skip pname if (isThis(TokenType::Assign)) // = { next(); - dp.push_back({pname, {makeAst(u8"Any"), parseExpression(0, TokenType::Comma)}}); + dp.push_back({pname, {makeAst(U"\1"), parseExpression(0, TokenType::Comma)}}); if (isThis(TokenType::Comma)) { next(); // only skip `,` when it's there @@ -224,16 +224,13 @@ namespace Fig variaPara = pname; next(); // skip `...` if (!isThis(TokenType::RightParen)) - throwAddressableError( - u8"Expects right paren, variable parameter function can only have one parameter", - currentAAI.line, - currentAAI.column); + throwAddressableError(U"\1", currentAAI.line, currentAAI.column); next(); // skip `)` return Ast::FunctionParameters(variaPara); } else { - pp.push_back({pname, makeAst(u8"Any")}); + pp.push_back({pname, makeAst(U"\1")}); if (isThis(TokenType::Comma)) { next(); // only skip `,` when it's there @@ -243,7 +240,7 @@ namespace Fig } Ast::FunctionDef Parser::__parseFunctionDef(bool isPublic) { - FString funcName = currentToken().getValue(); + String funcName = currentToken().getValue(); next(); expect(TokenType::LeftParen); Ast::FunctionParameters params = __parseFunctionParameters(); @@ -262,9 +259,9 @@ namespace Fig Ast::StructDef Parser::__parseStructDef(bool isPublic) { // entry: current is struct name - FString structName = currentToken().getValue(); + String structName = currentToken().getValue(); next(); - expect(TokenType::LeftBrace, u8"struct body"); + expect(TokenType::LeftBrace, U"\1"); next(); bool braceClosed = false; @@ -281,7 +278,7 @@ namespace Fig auto __parseStructField = [this](bool isPublic) -> Ast::StructDefField { AccessModifier am = AccessModifier::Normal; - FString fieldName; + String fieldName; if (isThis(TokenType::Identifier)) { fieldName = currentToken().getValue(); @@ -291,13 +288,13 @@ namespace Fig else if (isThis(TokenType::Const)) { next(); - expect(TokenType::Identifier, u8"field name"); + expect(TokenType::Identifier, U"\1"); fieldName = currentToken().getValue(); am = (isPublic ? AccessModifier::PublicConst : AccessModifier::Const); } else { - throwAddressableError(FString(std::format("expect field name or field attribute"))); + throwAddressableError(String(std::format("expect field name or field attribute"))); } Ast::Expression fieldType = nullptr; if (isThis(TokenType::Colon)) @@ -309,7 +306,7 @@ namespace Fig if (isThis(TokenType::Assign)) { next(); - if (isEOF()) throwAddressableError(FString(u8"expect an expression")); + if (isEOF()) throwAddressableError(String(U"\1")); initExpr = parseExpression(0); } expectSemicolon(); @@ -353,7 +350,7 @@ namespace Fig } else { - throwAddressableError(FString("Invalid syntax")); + throwAddressableError(String("Invalid syntax")); } } else if (isThis(TokenType::Function)) @@ -370,21 +367,21 @@ namespace Fig else if (isThis(TokenType::Variable)) { throwAddressableError( - FString("Variables are not allowed to be defined within a structure.")); + String("Variables are not allowed to be defined within a structure.")); } else { - throwAddressableError(FString("Invalid syntax")); + throwAddressableError(String("Invalid syntax")); } } - if (!braceClosed) { throwAddressableError(FString("braces are not closed")); } + if (!braceClosed) { throwAddressableError(String("braces are not closed")); } return makeAst(isPublic, structName, fields, makeAst(stmts)); } Ast::InterfaceDef Parser::__parseInterfaceDef(bool isPublic) { // entry: current is interface name - FString interfaceName = currentToken().getValue(); + String interfaceName = currentToken().getValue(); next(); // consume name expect(TokenType::LeftBrace); // `{ next(); // consume `{` @@ -400,7 +397,7 @@ namespace Fig } if (isThis(TokenType::Identifier)) { - FString funcName = currentToken().getValue(); + String funcName = currentToken().getValue(); next(); // consume func name expect(TokenType::LeftParen); @@ -424,7 +421,7 @@ namespace Fig } else { - throwAddressableError(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column); + throwAddressableError(String(U"\1"), currentAAI.line, currentAAI.column); } } return makeAst(interfaceName, methods, isPublic); @@ -434,15 +431,15 @@ namespace Fig { // entry: current is `impl` next(); // consume `impl` - expect(TokenType::Identifier, u8"interface name"); - FString interfaceName = currentToken().getValue(); + expect(TokenType::Identifier, U"\1"); + String interfaceName = currentToken().getValue(); next(); // consume interface name expect(TokenType::For); next(); // consume `for` - expect(TokenType::Identifier, u8"struct name"); - FString structName = currentToken().getValue(); + expect(TokenType::Identifier, U"\1"); + String structName = currentToken().getValue(); next(); // consume name expect(TokenType::LeftBrace); // { next(); // consume `{` @@ -458,7 +455,7 @@ namespace Fig } if (isThis(TokenType::Identifier)) { - FString funcName = currentToken().getValue(); + String funcName = currentToken().getValue(); next(); // consume func name expect(TokenType::LeftParen); Ast::FunctionParameters paras = __parseFunctionParameters(); @@ -468,7 +465,7 @@ namespace Fig } else { - throwAddressableError(FString(u8"Invalid syntax"), currentAAI.line, currentAAI.column); + throwAddressableError(String(U"\1"), currentAAI.line, currentAAI.column); } } @@ -513,16 +510,16 @@ namespace Fig next(); // consume `catch` expect(TokenType::LeftParen); next(); // consume `(` - expect(TokenType::Identifier, u8"error receive var name"); - FString errVarName = currentToken().getValue(); + expect(TokenType::Identifier, U"\1"); + String errVarName = currentToken().getValue(); next(); // consume name bool hasType = false; - FString errVarType; + String errVarType; if (isThis(TokenType::Colon)) // : { next(); - expect(TokenType::Identifier, u8"error type"); + expect(TokenType::Identifier, U"\1"); errVarType = currentToken().getValue(); next(); // consume var type hasType = true; @@ -542,8 +539,7 @@ namespace Fig { if (finallyBlock != nullptr) { - throwAddressableError( - u8"Duplicate try finally-block", currentAAI.line, currentAAI.column); + throwAddressableError(U"\1", currentAAI.line, currentAAI.column); } next(); // consume `finally` expect(TokenType::LeftBrace); @@ -579,8 +575,7 @@ namespace Fig else if (isThis(TokenType::Interface)) { stmt = __parseInterfaceDef(true); } else { - throwAddressableError( - FString(u8"Expected `var`, `const`, `function`, `struct` or `interface` after `public`")); + throwAddressableError(String(U"\1")); } } else if (isThis(TokenType::Variable) || isThis(TokenType::Const)) { stmt = __parseVarDef(false); } @@ -591,22 +586,19 @@ namespace Fig } else if (isThis(TokenType::Struct)) { - expectPeek(TokenType::Identifier, u8"struct name"); + expectPeek(TokenType::Identifier, U"\1"); next(); stmt = __parseStructDef(false); } else if (isThis(TokenType::Interface)) { - expectPeek(TokenType::Identifier, u8"interface name"); + expectPeek(TokenType::Identifier, U"\1"); next(); stmt = __parseInterfaceDef(false); } else if (isThis(TokenType::Implement)) { stmt = __parseImplement(); } else if (isThis(TokenType::If)) { stmt = __parseIf(); } - else if (isThis(TokenType::Else)) - { - throwAddressableError(FString(u8"`else` without matching `if`")); - } + else if (isThis(TokenType::Else)) { throwAddressableError(String(U"\1")); } else if (isThis(TokenType::LeftBrace)) { stmt = __parseBlockStatement(); } else if (isThis(TokenType::While)) { stmt = __parseWhile(); } else if (isThis(TokenType::For)) { stmt = __parseFor(); } @@ -624,7 +616,7 @@ namespace Fig } else { - throwAddressableError(u8"invalid syntax", currentAAI.line, currentAAI.column); + throwAddressableError(U"\1", currentAAI.line, currentAAI.column); } return stmt; } @@ -724,15 +716,12 @@ namespace Fig // 2. expression stmt:i++, foo() // ❌ not allowed:if/while/for/block stmt - if (isThis(TokenType::LeftBrace)) - { - throwAddressableError(u8"BlockStatement cannot be used as for loop increment"); - } + if (isThis(TokenType::LeftBrace)) { throwAddressableError(U"\1"); } if (isThis(TokenType::If) || isThis(TokenType::While) || isThis(TokenType::For) || isThis(TokenType::Return) || isThis(TokenType::Break) || isThis(TokenType::Continue)) { - throwAddressableError(u8"Control flow statements cannot be used as for loop increment"); + throwAddressableError(U"\1"); } Ast::Expression exp = parseExpression(0, TokenType::LeftBrace); @@ -786,7 +775,7 @@ namespace Fig return makeAst(); } - Ast::VarExpr Parser::__parseVarExpr(FString name) + Ast::VarExpr Parser::__parseVarExpr(String name) { return makeAst(name); } @@ -869,7 +858,7 @@ namespace Fig { // entry: current is `{` next(); // consume `{` - std::vector> args; + std::vector> args; /* 3 ways of calling constructor .1 Person {"Fig", 1, "IDK"}; @@ -893,13 +882,13 @@ namespace Fig { // 1 Person {"Fig", 1, "IDK"}; 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) { // 2 Person {name: "Fig", age: 1, sex: "IDK"}; expect(TokenType::Identifier); - FString fieldName = currentToken().getValue(); + String fieldName = currentToken().getValue(); next(); // consume identifier expect(TokenType::Colon); next(); // consume colon @@ -913,28 +902,22 @@ namespace Fig else if (!isThis(TokenType::RightBrace)) { throwAddressableError( - FString(std::format("Expect `,` or `}}` in struct initialization expression, got {}", - currentToken().toString().toBasicString()))); + String(std::format("Expect `,` or `}}` in struct initialization expression, got {}", + currentToken().toString().toBasicString()))); } } bool shorthand = true; if (mode == 1) { - for (auto &[name, exp] : args) + for (auto &[name, exp] : args) { - if (!name.empty()) - { - shorthand = false; - } - if (exp->getType() != Ast::AstType::VarExpr) - { - shorthand = false; - } + if (!name.empty()) { 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 - std::vector> nargs; + std::vector> nargs; for (auto &[name, exp] : args) { const Ast::VarExpr var = std::static_pointer_cast(exp); @@ -987,7 +970,7 @@ namespace Fig } else { - throwAddressableError(FString(u8"Expect ')' or ',' after expression in parentheses")); + throwAddressableError(String(U"\1")); } return nullptr; // to suppress compiler warning } @@ -1015,12 +998,12 @@ namespace Fig Ast::Import Parser::__parseImport() { next(); // consume `import` - std::vector path; - std::vector names; - FString rename; + std::vector path; + std::vector names; + String rename; while (true) { - expect(TokenType::Identifier, u8"package name"); + expect(TokenType::Identifier, U"\1"); path.push_back(currentToken().getValue()); next(); // consume package name if (isThis(TokenType::Semicolon)) { break; } @@ -1032,13 +1015,13 @@ namespace Fig else if (isThis(TokenType::LeftBrace)) { break; } else { - throwAddressableError(u8"invalid syntax"); + throwAddressableError(U"\1"); } } if (isThis(TokenType::As)) { next(); // consume `as` - expect(TokenType::Identifier, u8"new name"); + expect(TokenType::Identifier, U"\1"); rename = currentToken().getValue(); next(); // consume name } @@ -1056,7 +1039,7 @@ namespace Fig { next(); // consume `,` } - expect(TokenType::Identifier, u8"symbol name"); + expect(TokenType::Identifier, U"\1"); names.push_back(currentToken().getValue()); next(); } @@ -1071,10 +1054,10 @@ namespace Fig Ast::Operator op; Token tok = currentToken(); - if (tok == EOFTok) throwAddressableError(FString(u8"Unexpected end of expression")); + if (tok == EOFTok) throwAddressableError(String(U"\1")); if (tok.getType() == stop || tok.getType() == stop2 || tok.getType() == stop3) { - if (lhs == nullptr) throwAddressableError(FString(u8"Expected expression")); + if (lhs == nullptr) throwAddressableError(String(U"\1")); return lhs; } if (tok.getType() == TokenType::LeftBracket) @@ -1095,7 +1078,7 @@ namespace Fig if (currentToken().getType() == TokenType::Identifier) { // err - throwAddressableError(FString(u8"Function literal should not have a name")); + throwAddressableError(String(U"\1")); } expect(TokenType::LeftParen); lhs = __parseFunctionLiteralExpr(); @@ -1107,7 +1090,7 @@ namespace Fig } else if (tok.isIdentifier()) { - FString id = tok.getValue(); + String id = tok.getValue(); next(); lhs = __parseVarExpr(id); } @@ -1127,7 +1110,7 @@ namespace Fig } else { - throwAddressableError(FString(u8"Unexpected token in expression:") + tok.toString()); + throwAddressableError(String(U"\1") + tok.toString()); } // infix / (postfix) ? @@ -1138,11 +1121,7 @@ namespace Fig /* Postfix */ - if (tok.getType() == TokenType::LeftBrace) - { - throwAddressableError( - FString(u8"Since Fig v0.4.2, please use new struct{} to avoid syntax ambiguity")); - } + if (tok.getType() == TokenType::LeftBrace) { throwAddressableError(String(U"\1")); } if (tok.getType() == TokenType::LeftParen) { @@ -1165,10 +1144,9 @@ namespace Fig { next(); // consume '.' Token idTok = currentToken(); - if (!idTok.isIdentifier()) - throwAddressableError(FString(u8"Expected identifier after '.'")); + if (!idTok.isIdentifier()) throwAddressableError(String(U"\1")); - FString member = idTok.getValue(); + String member = idTok.getValue(); next(); // consume identifier lhs = makeAst(lhs, member); @@ -1224,8 +1202,7 @@ namespace Fig auto stmt = __parseStatement(); if (!output.empty() && stmt->getType() == Ast::AstType::PackageSt) { - throwAddressableError( - u8"Package must be at the beginning of the file", currentAAI.line, currentAAI.column); + throwAddressableError(U"\1", currentAAI.line, currentAAI.column); } pushNode(stmt); } diff --git a/src/Parser/parser.hpp b/src/Parser/parser.hpp index e5c981e..fda14dd 100644 --- a/src/Parser/parser.hpp +++ b/src/Parser/parser.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include @@ -23,8 +23,8 @@ namespace Fig std::vector output; std::vector previousTokens; - std::shared_ptr sourcePathPtr; - std::shared_ptr> sourceLinesPtr; + std::shared_ptr sourcePathPtr; + std::shared_ptr> sourceLinesPtr; size_t tokenPruduced = 0; size_t currentTokenIndex = 0; @@ -76,16 +76,16 @@ namespace Fig static const std::unordered_map> opPrecedence; static const std::unordered_map unaryOpPrecedence; - Parser(const Lexer &_lexer, FString _sourcePath, std::vector _sourceLines) : lexer(_lexer) + Parser(const Lexer &_lexer, String _sourcePath, std::vector _sourceLines) : lexer(_lexer) { - sourcePathPtr = std::make_shared(_sourcePath); - sourceLinesPtr = std::make_shared>(_sourceLines); + sourcePathPtr = std::make_shared(_sourcePath); + sourceLinesPtr = std::make_shared>(_sourceLines); } AddressableError *getError() const { return error.get(); } template - void throwAddressableError(FString msg, + void throwAddressableError(String msg, size_t line, size_t column, std::source_location loc = std::source_location::current()) @@ -96,7 +96,7 @@ namespace Fig throw spError; } template - 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, "_ErrT must derive from AddressableError"); // line, column provide by `currentAAI` @@ -106,7 +106,7 @@ namespace Fig } template - 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, "_ErrT must derive from AddressableError"); _ErrT spError(msg, loc); @@ -202,9 +202,9 @@ namespace Fig { if (peekToken().getType() != type) { - throwAddressableError(FString(std::format("Expected `{}`, but got `{}`", - magic_enum::enum_name(type), - magic_enum::enum_name(peekToken().getType()))), + throwAddressableError(String(std::format("Expected `{}`, but got `{}`", + magic_enum::enum_name(type), + magic_enum::enum_name(peekToken().getType()))), loc); } } @@ -213,34 +213,32 @@ namespace Fig { if (currentToken().getType() != type) { - throwAddressableError( - FString(std::format("Expected `{}`, but got `{}`", - magic_enum::enum_name(type), - 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(FString(std::format("Expected `{}`, but got `{}`", - expected.toBasicString(), - magic_enum::enum_name(peekToken().getType()))), + throwAddressableError(String(std::format("Expected `{}`, but got `{}`", + magic_enum::enum_name(type), + magic_enum::enum_name(currentToken().getType()))), 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(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) { - throwAddressableError( - FString(std::format("Expected `{}`, but got `{}`", - expected.toBasicString(), - magic_enum::enum_name(currentToken().getType()))), - loc); + throwAddressableError(String(std::format("Expected `{}`, but got `{}`", + expected.toBasicString(), + magic_enum::enum_name(currentToken().getType()))), + loc); } } @@ -264,7 +262,7 @@ namespace Fig 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); next(); @@ -279,8 +277,6 @@ namespace Fig bool isNext(TokenType type) { return peekToken().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) ObjectPtr __parseValue(); Ast::ValueExpr __parseValueExpr(); @@ -294,7 +290,7 @@ namespace Fig Ast::Break __parseBreak(); // entry: current is Token::Break 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::StructDef __parseStructDef(bool); // entry: current is Token::Identifier (struct name) arg(isPublic: bool) Ast::InterfaceDef diff --git a/src/Repl/Repl.cpp b/src/Repl/Repl.cpp index 2957773..fc84d36 100644 --- a/src/Repl/Repl.cpp +++ b/src/Repl/Repl.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include @@ -11,8 +11,8 @@ namespace Fig { ostream << getPrompt() << "\n"; - const FString &sourcePath = u8""; - const std::vector &sourceLines{}; + const String &sourcePath = U""; + const std::vector &sourceLines{}; Evaluator evaluator; @@ -24,7 +24,7 @@ namespace Fig while (true) { ostream << "\r\n>>"; - const FString &line = readline(); + const String &line = readline(); if (line.empty()) { diff --git a/src/Repl/Repl.hpp b/src/Repl/Repl.hpp index c1d9f71..83dc04d 100644 --- a/src/Repl/Repl.hpp +++ b/src/Repl/Repl.hpp @@ -28,12 +28,12 @@ namespace Fig { } - FString readline() const + String readline() const { std::string buf; std::getline(istream, buf); - return FString(buf); + return String(buf); } static std::string getPrompt() diff --git a/src/Token/token.hpp b/src/Token/token.hpp index acd690e..1cf3412 100644 --- a/src/Token/token.hpp +++ b/src/Token/token.hpp @@ -4,7 +4,7 @@ #include #include -#include +#include namespace Fig { @@ -54,7 +54,7 @@ namespace Fig /* Literal Types (not keyword)*/ LiteralNumber, // number (int,float...) - LiteralString, // FString + LiteralString, // String LiteralBool, // bool (true/false) LiteralNull, // null (Null unique instance) @@ -121,56 +121,40 @@ namespace Fig friend bool operator==(const Token &l, const Token &r); private: - FString value; + String value; TokenType type; public: size_t line, column; inline Token() {}; - inline Token(const FString &_value, TokenType _type) : - value(_value), type(_type) {} - inline Token(const FString &_value, TokenType _type, size_t _line, size_t _column) : - value(_value), type(_type) + inline Token(const String &_value, TokenType _type) : value(_value), type(_type) {} + inline Token(const String &_value, TokenType _type, size_t _line, size_t _column) : value(_value), type(_type) { line = _line; column = _column; } - const Token& setPos(size_t _line, size_t _column) + const Token &setPos(size_t _line, size_t _column) { line = _line; column = _column; return *this; } - size_t getLength() + size_t getLength() { return value.length(); } + const String &getValue() const { return value; } + inline String toString() const { - return value.length(); - } - const FString& getValue() const - { - return value; - } - inline FString toString() const - { - return FString(std::format( - "Token('{}',{})", - this->value.toBasicString(), - magic_enum::enum_name(type))); + return String(std::format("Token('{}',{})", this->value.toBasicString(), magic_enum::enum_name(type))); } - bool isIdentifier() - { - return type == TokenType::Identifier; - } + bool isIdentifier() { return type == TokenType::Identifier; } bool isLiteral() { - return type == TokenType::LiteralNull || type == TokenType::LiteralBool || type == TokenType::LiteralNumber || type == TokenType::LiteralString; - } - - TokenType getType() const - { - return type; + return type == TokenType::LiteralNull || type == TokenType::LiteralBool || type == TokenType::LiteralNumber + || type == TokenType::LiteralString; } + + TokenType getType() const { return type; } }; 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; } - static Token IllegalTok(u8"ILLEGAL", TokenType::Illegal); - static Token EOFTok(u8"EOF", TokenType::EndOfFile); + static Token IllegalTok(U"ILLEGAL", TokenType::Illegal); + static Token EOFTok(U"EOF", TokenType::EndOfFile); } // namespace Fig \ No newline at end of file diff --git a/src/Utils/AstPrinter.hpp b/src/Utils/AstPrinter.hpp index ccf024f..1c16c55 100644 --- a/src/Utils/AstPrinter.hpp +++ b/src/Utils/AstPrinter.hpp @@ -15,53 +15,32 @@ public: if (!node) return; switch (node->getType()) { - case AstType::BinaryExpr: - printBinaryExpr(std::static_pointer_cast(node), indent); - break; - case AstType::UnaryExpr: - printUnaryExpr(std::static_pointer_cast(node), indent); - break; - case AstType::ValueExpr: - printValueExpr(std::static_pointer_cast(node), indent); - break; - case AstType::VarDefSt: - printVarDef(std::static_pointer_cast(node), indent); - break; - case AstType::VarExpr: - printVarExpr(std::static_pointer_cast(node), indent); - break; + case AstType::BinaryExpr: printBinaryExpr(std::static_pointer_cast(node), indent); break; + case AstType::UnaryExpr: printUnaryExpr(std::static_pointer_cast(node), indent); break; + case AstType::ValueExpr: printValueExpr(std::static_pointer_cast(node), indent); break; + case AstType::VarDefSt: printVarDef(std::static_pointer_cast(node), indent); break; + case AstType::VarExpr: printVarExpr(std::static_pointer_cast(node), indent); break; case AstType::BlockStatement: printBlockStatement(std::static_pointer_cast(node), indent); break; case AstType::FunctionCall: printFunctionCall(std::static_pointer_cast(node), indent); break; - case AstType::FunctionDefSt: - printFunctionSt(std::static_pointer_cast(node), indent); - break; - case AstType::IfSt: - printIfSt(std::static_pointer_cast(node), indent); - break; - case AstType::TernaryExpr: - printTernaryExpr(std::static_pointer_cast(node), indent); - break; - default: - printIndent(indent); - std::cout << "Unknown AST Node\n"; + case AstType::FunctionDefSt: printFunctionSt(std::static_pointer_cast(node), indent); break; + case AstType::IfSt: printIfSt(std::static_pointer_cast(node), indent); break; + case AstType::TernaryExpr: printTernaryExpr(std::static_pointer_cast(node), indent); break; + default: printIndent(indent); std::cout << "Unknown AST Node\n"; } } private: - void printIndent(int indent) - { - std::cout << std::string(indent, ' '); - } + void printIndent(int indent) { std::cout << std::string(indent, ' '); } - void printFString(const Fig::FString &fstr, int indent) + void printFString(const Fig::String &fstr, int indent) { printIndent(indent); - std::cout << "FString: \""; - std::cout.write(reinterpret_cast(fstr.data()), fstr.size()); + std::cout << "String: \""; + std::cout << fstr; std::cout << "\"\n"; } @@ -133,10 +112,7 @@ private: { printIndent(indent); std::cout << "BlockStatement\n"; - for (const auto &stmt : node->stmts) - { - print(stmt, indent + 2); - } + for (const auto &stmt : node->stmts) { print(stmt, indent + 2); } } void printFunctionCall(const std::shared_ptr &node, int indent) diff --git a/src/Utils/utils.hpp b/src/Utils/utils.hpp index fd0d521..cb7cd0f 100644 --- a/src/Utils/utils.hpp +++ b/src/Utils/utils.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -11,36 +11,33 @@ namespace Fig::Utils { - inline std::vector splitSource(FString source) + inline std::vector splitSource(const String &source) { - UTF8Iterator it(source); - std::vector lines; - FString currentLine; - while (!it.isEnd()) + + std::vector lines; + String currentLine; + + for (char32_t c : source) { - UTF8Char c = *it; if (c == U'\n') { lines.push_back(currentLine); - currentLine = FString(u8""); + currentLine = String(U"\1"); } else { - currentLine += c.getString(); + currentLine += c; } - ++it; - } - if (!currentLine.empty()) - { - lines.push_back(currentLine); } + + if (!currentLine.empty()) { lines.push_back(currentLine); } return lines; } - inline std::u32string utf8ToUtf32(const FString &s) + inline std::u32string utf8ToUtf32(const String &s) { std::u32string result; size_t i = 0; - while (i < s.size()) + while (i < s.length()) { char32_t codepoint = 0; unsigned char c = static_cast(s[i]); @@ -57,12 +54,15 @@ namespace Fig::Utils } else if ((c >> 4) == 0xE) { - codepoint = ((c & 0x0F) << 12) | ((static_cast(s[i + 1]) & 0x3F) << 6) | (static_cast(s[i + 2]) & 0x3F); + codepoint = ((c & 0x0F) << 12) | ((static_cast(s[i + 1]) & 0x3F) << 6) + | (static_cast(s[i + 2]) & 0x3F); i += 3; } else if ((c >> 3) == 0x1E) { - codepoint = ((c & 0x07) << 18) | ((static_cast(s[i + 1]) & 0x3F) << 12) | ((static_cast(s[i + 2]) & 0x3F) << 6) | (static_cast(s[i + 3]) & 0x3F); + codepoint = ((c & 0x07) << 18) | ((static_cast(s[i + 1]) & 0x3F) << 12) + | ((static_cast(s[i + 2]) & 0x3F) << 6) + | (static_cast(s[i + 3]) & 0x3F); i += 4; } else @@ -74,60 +74,7 @@ namespace Fig::Utils } return result; } - - inline FString utf32ToUtf8(const std::u32string &s) - { - FString result; - for (char32_t cp : s) - { - if (cp < 0x80) - { - result.push_back(static_cast(cp)); - } - else if (cp < 0x800) - { - result.push_back(static_cast((cp >> 6) | 0xC0)); - result.push_back(static_cast((cp & 0x3F) | 0x80)); - } - else if (cp < 0x10000) - { - result.push_back(static_cast((cp >> 12) | 0xE0)); - result.push_back(static_cast(((cp >> 6) & 0x3F) | 0x80)); - result.push_back(static_cast((cp & 0x3F) | 0x80)); - } - else - { - result.push_back(static_cast((cp >> 18) | 0xF0)); - result.push_back(static_cast(((cp >> 12) & 0x3F) | 0x80)); - result.push_back(static_cast(((cp >> 6) & 0x3F) | 0x80)); - result.push_back(static_cast((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 bool vectorContains(const T &t, const std::vector v) { diff --git a/src/VirtualMachine/VirtualMachine.cpp b/src/VirtualMachine/VirtualMachine.cpp index 6e12a1a..733866f 100644 --- a/src/VirtualMachine/VirtualMachine.cpp +++ b/src/VirtualMachine/VirtualMachine.cpp @@ -24,10 +24,7 @@ namespace Fig uint64_t base = currentFrame->base; popFrame(); - if (frames.empty()) - { - return ret; - } + if (frames.empty()) { return ret; } stack.resize(base); // 清除函数的临时值 push(ret); @@ -147,7 +144,8 @@ namespace Fig if (lhs.is() && rhs.is()) { - ValueType::DoubleClass result = (double)lhs.as() / (double)rhs.as(); + ValueType::DoubleClass result = + (double) lhs.as() / (double) rhs.as(); push(Object(result)); break; } @@ -166,12 +164,7 @@ namespace Fig case OpCode::JUMP_IF_FALSE: { const Object &cond = pop(); - if (!cond.is()) - { - throw RuntimeError( - FString(u8"Condition must be boolean!") - ); - } + if (!cond.is()) { throw RuntimeError(String(U"\1")); } if (!cond.as()) { // cond is falsity @@ -181,19 +174,18 @@ namespace Fig break; } - case OpCode::CALL: - { + case OpCode::CALL: { uint16_t argCount = static_cast(ins.operand); // number of max arg is UINT16_MAX - + const Object &obj = stack.back(); if (!obj.is()) { - 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(); // assert(fn_obj.isCompiled && "function must be compiled"); - + CompiledFunction fn; assert(stack.size() >= argCount && "stack does not have enough arguments"); @@ -203,17 +195,11 @@ namespace Fig pop(); // pop function - for (int64_t i = 0; i < fn.slotCount - argCount; ++i) - { - push(*Object::getNullInstance()); - } + for (int64_t i = 0; i < fn.slotCount - argCount; ++i) { push(*Object::getNullInstance()); } - CallFrame newFrame - { - 0, - base, // 参数已经加载到stack, base为第一个参数 - fn - }; + CallFrame newFrame{0, + base, // 参数已经加载到stack, base为第一个参数 + fn}; addFrame(newFrame); break; diff --git a/src/main.cpp b/src/main.cpp index 2253d0a..24154b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,26 +1,37 @@ /* - ███████████ █████ █████ ██████████ ███████████ █████ █████████ █████ █████████ ██████ █████ █████████ █████ █████ █████████ █████████ ██████████ -░█░░░███░░░█░░███ ░░███ ░░███░░░░░█ ░░███░░░░░░█░░███ ███░░░░░███ ░░███ ███░░░░░███ ░░██████ ░░███ ███░░░░░███░░███ ░░███ ███░░░░░███ ███░░░░░███░░███░░░░░█ -░ ░███ ░ ░███ ░███ ░███ █ ░ ░███ █ ░ ░███ ███ ░░░ ░███ ░███ ░███ ░███░███ ░███ ███ ░░░ ░███ ░███ ░███ ░███ ███ ░░░ ░███ █ ░ - ░███ ░███████████ ░██████ ░███████ ░███ ░███ ░███ ░███████████ ░███░░███░███ ░███ ░███ ░███ ░███████████ ░███ ░██████ - ░███ ░███░░░░░███ ░███░░█ ░███░░░█ ░███ ░███ █████ ░███ ░███░░░░░███ ░███ ░░██████ ░███ █████ ░███ ░███ ░███░░░░░███ ░███ █████ ░███░░█ - ░███ ░███ ░███ ░███ ░ █ ░███ ░ ░███ ░░███ ░░███ ░███ █ ░███ ░███ ░███ ░░█████ ░░███ ░░███ ░███ ░███ ░███ ░███ ░░███ ░░███ ░███ ░ █ - █████ █████ █████ ██████████ █████ █████ ░░█████████ ███████████ █████ █████ █████ ░░█████ ░░█████████ ░░████████ █████ █████ ░░█████████ ██████████ - ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░ + ███████████ █████ █████ ██████████ ███████████ █████ █████████ █████ █████████ ██████ █████ +█████████ █████ █████ █████████ █████████ ██████████ ░█░░░███░░░█░░███ ░░███ ░░███░░░░░█ ░░███░░░░░░█░░███ +███░░░░░███ ░░███ ███░░░░░███ ░░██████ ░░███ ███░░░░░███░░███ ░░███ ███░░░░░███ ███░░░░░███░░███░░░░░█ +░ ░███ ░ ░███ ░███ ░███ █ ░ ░███ █ ░ ░███ ███ ░░░ ░███ ░███ ░███ ░███░███ ░███ ███ +░░░ ░███ ░███ ░███ ░███ ███ ░░░ ░███ █ ░ ░███ ░███████████ ░██████ ░███████ ░███ ░███ ░███ +░███████████ ░███░░███░███ ░███ ░███ ░███ ░███████████ ░███ ░██████ ░███ ░███░░░░░███ ░███░░█ +░███░░░█ ░███ ░███ █████ ░███ ░███░░░░░███ ░███ ░░██████ ░███ █████ ░███ ░███ ░███░░░░░███ ░███ +█████ ░███░░█ ░███ ░███ ░███ ░███ ░ █ ░███ ░ ░███ ░░███ ░░███ ░███ █ ░███ ░███ ░███ +░░█████ ░░███ ░░███ ░███ ░███ ░███ ░███ ░░███ ░░███ ░███ ░ █ █████ █████ █████ ██████████ █████ +█████ ░░█████████ ███████████ █████ █████ █████ ░░█████ ░░█████████ ░░████████ █████ █████ ░░█████████ +██████████ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ +░░░░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░░░░░░ .---. - . __.....__ .--. | | _..._ __.....__ - .'| .-'' '. _.._ |__| .--./) | | .' '. .--./) .--./) .-'' '. - .| < | / .-''"'-. `. .' .._|.--. /.''\\ | | . .-. . /.''\\ /.''\\ / .-''"'-. `. - .' |_ | | / /________\ \ | ' | || | | | | | __ | ' ' || | | | __ | | | |/ /________\ \ - .' || | .'''-. | | __| |__ | | \`-' / | | .:--.'. | | | | \`-' / _ _ .:--.'. \`-' / | | -'--. .-'| |/.'''. \\ .-------------' |__ __| | | /("'` | |/ | \ | | | | | /("'` | ' / | / | \ | /("'` \ .-------------' - | | | / | | \ '-.____...---. | | | | \ '---. | |`" __ | | | | | | \ '---. .' | .' | `" __ | | \ '---. \ '-.____...---. - | | | | | | `. .' | | |__| /'""'.\ | | .'.''| | | | | | /'""'.\ / | / | .'.''| | /'""'.\ `. .' - | '.'| | | | `''-...... -' | | || || '---'/ / | |_| | | | || ||| `'. | / / | |_|| || `''-...... -' - | / | '. | '. | | \'. __// \ \._,\ '/| | | | \'. __// ' .'| '/\ \._,\ '/\'. __// - `'-' '---' '---' |_| `'---' `--' `" '--' '--' `'---' `-' `--' `--' `" `'---' + . __.....__ .--. | | _..._ __.....__ + .'| .-'' '. _.._ |__| .--./) | | .' '. .--./) +.--./) .-'' '. + .| < | / .-''"'-. `. .' .._|.--. /.''\\ | | . .-. . /.''\\ +/.''\\ / .-''"'-. `. + .' |_ | | / /________\ \ | ' | || | | | | | __ | ' ' || | | | +__ | | | |/ /________\ \ + .' || | .'''-. | | __| |__ | | \`-' / | | .:--.'. | | | | \`-' / _ +_ .:--.'. \`-' / | | +'--. .-'| |/.'''. \\ .-------------' |__ __| | | /("'` | |/ | \ | | | | | /("'` | ' +/ | / | \ | /("'` \ .-------------' | | | / | | \ '-.____...---. | | | | \ '---. | |`" +__ | | | | | | \ '---. .' | .' | `" __ | | \ '---. \ '-.____...---. | | | | | | `. .' | | +|__| /'""'.\ | | .'.''| | | | | | /'""'.\ / | / | .'.''| | /'""'.\ `. .' | '.'| | | +| `''-...... -' | | || || '---'/ / | |_| | | | || ||| `'. | / / | +|_|| || `''-...... -' | / | '. | '. | | \'. __// \ \._,\ '/| | | | +\'. __// ' .'| '/\ \._,\ '/\'. __// + `'-' '---' '---' |_| `'---' `--' `" '--' '--' `'---' +`-' `--' `--' `" `'---' 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 unaddressableErrorCount = 0; - int main(int argc, char **argv) { Time::init(); // init, set start_time (std::chrono::time_point) - argparse::ArgumentParser program("Fig Interpreter", Fig::Core::VERSION.data()); - program.add_argument("source") - .help("source file to be interpreted") - .default_value(std::string("")); - program.add_argument("-r", "--repl") - .help("start repl") - .default_value(false) - .implicit_value(true); + program.add_argument("source").help("source file to be interpreted").default_value(std::string("")); + program.add_argument("-r", "--repl").help("start repl").default_value(false).implicit_value(true); // program.add_argument("-v", "--version") // .help("get the version of Fig Interpreter") // .default_value(false) @@ -87,7 +91,7 @@ int main(int argc, char **argv) exit(0); } - Fig::FString sourcePath(program.get("source")); + Fig::String sourcePath(program.get("source")); if (sourcePath.empty()) { std::cerr << "No source file provided.\n"; @@ -102,9 +106,9 @@ int main(int argc, char **argv) std::string source((std::istreambuf_iterator(file)), std::istreambuf_iterator()); file.close(); - std::vector sourceLines = Fig::Utils::splitSource(Fig::FString(source)); + std::vector 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; // while ((tok = lexer.nextToken()).getType() != TokenType::EndOfFile) @@ -149,7 +153,7 @@ int main(int argc, char **argv) evaluator.SetSourcePath(sourcePath); evaluator.SetSourceLines(sourceLines); evaluator.CreateGlobalContext(); - evaluator.RegisterBuiltinsValue(); + evaluator.RegisterBuiltinsValue(); try { diff --git a/xmake.lua b/xmake.lua index f7db62d..cd41544 100644 --- a/xmake.lua +++ b/xmake.lua @@ -27,6 +27,7 @@ end add_files("src/Core/warning.cpp") add_files("src/Core/runtimeTime.cpp") +add_files("src/Core/String.cpp") add_files("src/Lexer/lexer.cpp") add_files("src/Parser/parser.cpp")